summaryrefslogtreecommitdiff
path: root/src/buildstream
diff options
context:
space:
mode:
authorBenjamin Schubert <contact@benschubert.me>2019-06-10 07:51:57 +0100
committerBenjamin Schubert <contact@benschubert.me>2019-06-25 21:08:50 +0100
commite62347655a5445a621701b6e13c7abd813d954c9 (patch)
treef540b7c280ae29257fa130d61fc87befa0372282 /src/buildstream
parentfe0cdcb252b880995163f24b37a7a076cdf7824a (diff)
downloadbuildstream-e62347655a5445a621701b6e13c7abd813d954c9.tar.gz
_yaml: Add 'as_str()' on ScalarNode and 'get_scalar()' on MappingNode
- 'get_scalar()' allows retrieving a scalar node from a mapping. - 'as_str()' casts a ScalarNode into a string (thus removing the node information). Both together, those replace 'node_get(mapping, key, type=str)' but also allow retrieving the 'Node' itself, which will allow in the future lazier provenance computation.
Diffstat (limited to 'src/buildstream')
-rw-r--r--src/buildstream/_cas/casremote.py10
-rw-r--r--src/buildstream/_context.py10
-rw-r--r--src/buildstream/_frontend/cli.py2
-rw-r--r--src/buildstream/_gitsourcebase.py16
-rw-r--r--src/buildstream/_loader/loader.py10
-rw-r--r--src/buildstream/_loader/types.pyx6
-rw-r--r--src/buildstream/_options/option.py5
-rw-r--r--src/buildstream/_options/optionbool.py2
-rw-r--r--src/buildstream/_options/optionenum.py4
-rw-r--r--src/buildstream/_options/optionpool.py4
-rw-r--r--src/buildstream/_plugincontext.py10
-rw-r--r--src/buildstream/_project.py34
-rw-r--r--src/buildstream/_variables.pyx2
-rw-r--r--src/buildstream/_workspaces.py4
-rw-r--r--src/buildstream/_yaml.pxd6
-rw-r--r--src/buildstream/_yaml.pyx27
-rw-r--r--src/buildstream/element.py6
-rw-r--r--src/buildstream/plugins/elements/junction.py4
-rw-r--r--src/buildstream/plugins/sources/_downloadablefilesource.py8
-rw-r--r--src/buildstream/plugins/sources/bzr.py6
-rw-r--r--src/buildstream/plugins/sources/deb.py2
-rw-r--r--src/buildstream/plugins/sources/pip.py4
-rw-r--r--src/buildstream/plugins/sources/remote.py2
-rw-r--r--src/buildstream/plugins/sources/tar.py3
-rw-r--r--src/buildstream/plugins/sources/zip.py3
25 files changed, 111 insertions, 79 deletions
diff --git a/src/buildstream/_cas/casremote.py b/src/buildstream/_cas/casremote.py
index cd46e9c38..0195e217a 100644
--- a/src/buildstream/_cas/casremote.py
+++ b/src/buildstream/_cas/casremote.py
@@ -32,24 +32,24 @@ class CASRemoteSpec(namedtuple('CASRemoteSpec', 'url push server_cert client_key
@staticmethod
def _new_from_config_node(spec_node, basedir=None):
_yaml.node_validate(spec_node, ['url', 'push', 'server-cert', 'client-key', 'client-cert', 'instance-name'])
- url = _yaml.node_get(spec_node, str, 'url')
+ url = spec_node.get_str('url')
push = _yaml.node_get(spec_node, bool, 'push', default_value=False)
if not url:
provenance = _yaml.node_get_provenance(spec_node, 'url')
raise LoadError(LoadErrorReason.INVALID_DATA,
"{}: empty artifact cache URL".format(provenance))
- instance_name = _yaml.node_get(spec_node, str, 'instance-name', default_value=None)
+ instance_name = spec_node.get_str('instance-name', default=None)
- server_cert = _yaml.node_get(spec_node, str, 'server-cert', default_value=None)
+ server_cert = spec_node.get_str('server-cert', default=None)
if server_cert and basedir:
server_cert = os.path.join(basedir, server_cert)
- client_key = _yaml.node_get(spec_node, str, 'client-key', default_value=None)
+ client_key = spec_node.get_str('client-key', default=None)
if client_key and basedir:
client_key = os.path.join(basedir, client_key)
- client_cert = _yaml.node_get(spec_node, str, 'client-cert', default_value=None)
+ client_cert = spec_node.get_str('client-cert', default=None)
if client_cert and basedir:
client_cert = os.path.join(basedir, client_cert)
diff --git a/src/buildstream/_context.py b/src/buildstream/_context.py
index c44962d7e..e285f6b6a 100644
--- a/src/buildstream/_context.py
+++ b/src/buildstream/_context.py
@@ -222,7 +222,7 @@ class Context():
# Allow the ~ tilde expansion and any environment variables in
# path specification in the config files.
#
- path = _yaml.node_get(defaults, str, directory)
+ path = defaults.get_str(directory)
path = os.path.expanduser(path)
path = os.path.expandvars(path)
path = os.path.normpath(path)
@@ -254,7 +254,7 @@ class Context():
cache = defaults.get_mapping('cache')
_yaml.node_validate(cache, ['quota', 'pull-buildtrees', 'cache-buildtrees'])
- self.config_cache_quota_string = _yaml.node_get(cache, str, 'quota')
+ self.config_cache_quota_string = cache.get_str('quota')
try:
self.config_cache_quota = utils._parse_size(self.config_cache_quota_string,
self.casdir)
@@ -291,8 +291,8 @@ class Context():
self.log_verbose = _yaml.node_get(logging, bool, 'verbose')
self.log_error_lines = _yaml.node_get(logging, int, 'error-lines')
self.log_message_lines = _yaml.node_get(logging, int, 'message-lines')
- self.log_element_format = _yaml.node_get(logging, str, 'element-format')
- self.log_message_format = _yaml.node_get(logging, str, 'message-format')
+ self.log_element_format = logging.get_str('element-format')
+ self.log_message_format = logging.get_str('message-format')
# Load scheduler config
scheduler = defaults.get_mapping('scheduler')
@@ -756,7 +756,7 @@ class Context():
# LoadError, when the value is not of the expected type, or is not found.
#
def _node_get_option_str(node, key, allowed_options):
- result = _yaml.node_get(node, str, key)
+ result = node.get_str(key)
if result not in allowed_options:
provenance = _yaml.node_get_provenance(node, key)
raise LoadError(LoadErrorReason.INVALID_DATA,
diff --git a/src/buildstream/_frontend/cli.py b/src/buildstream/_frontend/cli.py
index 53adb188c..f2f149403 100644
--- a/src/buildstream/_frontend/cli.py
+++ b/src/buildstream/_frontend/cli.py
@@ -100,7 +100,7 @@ def complete_target(args, incomplete):
return []
# The project is not required to have an element-path
- element_directory = _yaml.node_get(project, str, 'element-path', default_value='')
+ element_directory = project.get_str('element-path', default='')
# If a project was loaded, use its element-path to
# adjust our completion's base directory
diff --git a/src/buildstream/_gitsourcebase.py b/src/buildstream/_gitsourcebase.py
index 8c6b54e2d..eefa36b1d 100644
--- a/src/buildstream/_gitsourcebase.py
+++ b/src/buildstream/_gitsourcebase.py
@@ -376,7 +376,7 @@ class _GitSourceBase(Source):
BST_MIRROR_CLASS = _GitMirror
def configure(self, node):
- ref = self.node_get_member(node, str, 'ref', None)
+ ref = node.get_str('ref', None)
config_keys = ['url', 'track', 'ref', 'submodules',
'checkout-submodules', 'ref-format',
@@ -390,11 +390,11 @@ class _GitSourceBase(Source):
tags = self._load_tags(node)
self.track_tags = self.node_get_member(node, bool, 'track-tags', False)
- self.original_url = self.node_get_member(node, str, 'url')
+ self.original_url = node.get_str('url')
self.mirror = self.BST_MIRROR_CLASS(self, '', self.original_url, ref, tags=tags, primary=True)
- self.tracking = self.node_get_member(node, str, 'track', None)
+ self.tracking = node.get_str('track', None)
- self.ref_format = self.node_get_member(node, str, 'ref-format', 'sha1')
+ self.ref_format = node.get_str('ref-format', 'sha1')
if self.ref_format not in ['sha1', 'git-describe']:
provenance = self.node_provenance(node, member_name='ref-format')
raise SourceError("{}: Unexpected value for ref-format: {}".format(provenance, self.ref_format))
@@ -415,7 +415,7 @@ class _GitSourceBase(Source):
modules = node.get_mapping('submodules', {})
for path, _ in self.node_items(modules):
submodule = modules.get_mapping(path)
- url = self.node_get_member(submodule, str, 'url', None)
+ url = submodule.get_str('url', None)
# Make sure to mark all URLs that are specified in the configuration
if url:
@@ -464,7 +464,7 @@ class _GitSourceBase(Source):
return Consistency.INCONSISTENT
def load_ref(self, node):
- self.mirror.ref = self.node_get_member(node, str, 'ref', None)
+ self.mirror.ref = node.get_str('ref', None)
self.mirror.tags = self._load_tags(node)
def get_ref(self):
@@ -665,8 +665,8 @@ class _GitSourceBase(Source):
tags = []
tags_node = self.node_get_member(node, list, 'tags', [])
for tag_node in tags_node:
- tag = self.node_get_member(tag_node, str, 'tag')
- commit_ref = self.node_get_member(tag_node, str, 'commit')
+ tag = tag_node.get_str('tag')
+ commit_ref = tag_node.get_str('commit')
annotated = self.node_get_member(tag_node, bool, 'annotated')
tags.append((tag, commit_ref, annotated))
return tags
diff --git a/src/buildstream/_loader/loader.py b/src/buildstream/_loader/loader.py
index 6036f4f07..4ac598faf 100644
--- a/src/buildstream/_loader/loader.py
+++ b/src/buildstream/_loader/loader.py
@@ -227,7 +227,7 @@ class Loader():
message, detail=detail) from e
else:
raise
- kind = _yaml.node_get(node, str, Symbol.KIND)
+ kind = node.get_str(Symbol.KIND)
if kind == "junction":
self._first_pass_options.process_node(node)
else:
@@ -306,7 +306,7 @@ class Loader():
dep_deps = extract_depends_from_node(dep_element.node)
loader_queue.append((dep_element, list(reversed(dep_deps)), []))
- if _yaml.node_get(dep_element.node, str, Symbol.KIND) == 'junction':
+ if dep_element.node.get_str(Symbol.KIND) == 'junction':
raise LoadError(LoadErrorReason.INVALID_DATA,
"{}: Cannot depend on junction"
.format(dep.provenance))
@@ -467,17 +467,17 @@ class Loader():
meta_sources = []
sources = _yaml.node_get(node, list, Symbol.SOURCES, default_value=[])
- element_kind = _yaml.node_get(node, str, Symbol.KIND)
+ element_kind = node.get_str(Symbol.KIND)
# Safe loop calling into _yaml.node_get() for each element ensures
# we have good error reporting
for i in range(len(sources)):
source = _yaml.node_get(node, dict, Symbol.SOURCES, indices=[i])
- kind = _yaml.node_get(source, str, Symbol.KIND)
+ kind = source.get_str(Symbol.KIND)
_yaml.node_del(source, Symbol.KIND)
# Directory is optional
- directory = _yaml.node_get(source, str, Symbol.DIRECTORY, default_value=None)
+ directory = source.get_str(Symbol.DIRECTORY, default=None)
if directory:
_yaml.node_del(source, Symbol.DIRECTORY)
diff --git a/src/buildstream/_loader/types.pyx b/src/buildstream/_loader/types.pyx
index c100b77b2..a3e49b040 100644
--- a/src/buildstream/_loader/types.pyx
+++ b/src/buildstream/_loader/types.pyx
@@ -85,7 +85,7 @@ cdef class Dependency:
_yaml.node_validate(<_yaml.Node> dep, ['filename', 'type', 'junction'])
# Make type optional, for this we set it to None
- dep_type = <str> _yaml.node_get(<_yaml.Node> dep, str, <str> Symbol.TYPE, None, None)
+ dep_type = (<_yaml.MappingNode> dep).get_str(<str> Symbol.TYPE, None)
if dep_type is None or dep_type == <str> Symbol.ALL:
dep_type = None
elif dep_type not in [Symbol.BUILD, Symbol.RUNTIME]:
@@ -94,9 +94,9 @@ cdef class Dependency:
"{}: Dependency type '{}' is not 'build', 'runtime' or 'all'"
.format(provenance, dep_type))
- self.name = <str> _yaml.node_get(<_yaml.Node> dep, str, <str> Symbol.FILENAME)
+ self.name = (<_yaml.MappingNode> dep).get_str(<str> Symbol.FILENAME)
self.dep_type = dep_type
- self.junction = <str> _yaml.node_get(<_yaml.Node> dep, str, <str> Symbol.JUNCTION, None, None)
+ self.junction = (<_yaml.MappingNode> dep).get_str(<str> Symbol.JUNCTION, None)
else:
raise LoadError(LoadErrorReason.INVALID_DATA,
diff --git a/src/buildstream/_options/option.py b/src/buildstream/_options/option.py
index ffdb4d272..6aa4cdc01 100644
--- a/src/buildstream/_options/option.py
+++ b/src/buildstream/_options/option.py
@@ -60,8 +60,9 @@ class Option():
# node (dict): The loaded YAML dictionary describing
# the option
def load(self, node):
- self.description = _yaml.node_get(node, str, 'description')
- self.variable = _yaml.node_get(node, str, 'variable', default_value=None)
+ self.description = node.get_str('description')
+ variable_node = node.get_str('variable', default=None)
+ self.variable = variable_node
# Assert valid symbol name for variable name
if self.variable is not None:
diff --git a/src/buildstream/_options/optionbool.py b/src/buildstream/_options/optionbool.py
index bdbb1d32a..caeff9711 100644
--- a/src/buildstream/_options/optionbool.py
+++ b/src/buildstream/_options/optionbool.py
@@ -38,7 +38,7 @@ class OptionBool(Option):
def load_value(self, node, *, transform=None):
if transform:
- self.set_value(transform(_yaml.node_get(node, str, self.name)))
+ self.set_value(transform(node.get_str(self.name)))
else:
self.value = _yaml.node_get(node, bool, self.name)
diff --git a/src/buildstream/_options/optionenum.py b/src/buildstream/_options/optionenum.py
index 889db965c..04a19395b 100644
--- a/src/buildstream/_options/optionenum.py
+++ b/src/buildstream/_options/optionenum.py
@@ -56,7 +56,7 @@ class OptionEnum(Option):
self.value = self.load_default_value(node)
def load_value(self, node, *, transform=None):
- self.value = _yaml.node_get(node, str, self.name)
+ self.value = node.get_str(self.name)
if transform:
self.value = transform(self.value)
self.validate(self.value, _yaml.node_get_provenance(node, self.name))
@@ -79,6 +79,6 @@ class OptionEnum(Option):
"Valid values: {}".format(", ".join(self.values)))
def load_default_value(self, node):
- value = _yaml.node_get(node, str, 'default')
+ value = node.get_str('default')
self.validate(value, _yaml.node_get_provenance(node, 'default'))
return value
diff --git a/src/buildstream/_options/optionpool.py b/src/buildstream/_options/optionpool.py
index de3af3e15..25b96fa98 100644
--- a/src/buildstream/_options/optionpool.py
+++ b/src/buildstream/_options/optionpool.py
@@ -71,7 +71,7 @@ class OptionPool():
p = _yaml.node_get_provenance(options, option_name)
_yaml.assert_symbol_name(p, option_name, "option name", allow_dashes=False)
- opt_type_name = _yaml.node_get(option_definition, str, 'type')
+ opt_type_name = option_definition.get_str('type')
try:
opt_type = _OPTION_TYPES[opt_type_name]
except KeyError:
@@ -249,7 +249,7 @@ class OptionPool():
#
def _process_one_node(self, node):
conditions = _yaml.node_get(node, list, '(?)', default_value=None)
- assertion = _yaml.node_get(node, str, '(!)', default_value=None)
+ assertion = node.get_str('(!)', default=None)
# Process assersions first, we want to abort on the first encountered
# assertion in a given dictionary, and not lose an assertion due to
diff --git a/src/buildstream/_plugincontext.py b/src/buildstream/_plugincontext.py
index 7a5407cf6..c6b6526cb 100644
--- a/src/buildstream/_plugincontext.py
+++ b/src/buildstream/_plugincontext.py
@@ -141,16 +141,16 @@ class PluginContext():
if kind not in _yaml.node_get(origin, list, 'plugins'):
continue
- if _yaml.node_get(origin, str, 'origin') == 'local':
- local_path = _yaml.node_get(origin, str, 'path')
+ if origin.get_str('origin') == 'local':
+ local_path = origin.get_str('path')
source = self._get_local_plugin_source(local_path)
- elif _yaml.node_get(origin, str, 'origin') == 'pip':
- package_name = _yaml.node_get(origin, str, 'package-name')
+ elif origin.get_str('origin') == 'pip':
+ package_name = origin.get_str('package-name')
source, defaults = self._get_pip_plugin_source(package_name, kind)
else:
raise PluginError("Failed to load plugin '{}': "
"Unexpected plugin origin '{}'"
- .format(kind, _yaml.node_get(origin, str, 'origin')))
+ .format(kind, origin.get_str('origin')))
loaded_dependency = True
break
diff --git a/src/buildstream/_project.py b/src/buildstream/_project.py
index e23689d99..bb1b06b43 100644
--- a/src/buildstream/_project.py
+++ b/src/buildstream/_project.py
@@ -84,7 +84,7 @@ class ProjectConfig:
self.source_overrides = {} # Source specific configurations
self.mirrors = OrderedDict() # contains dicts of alias-mappings to URIs.
self.default_mirror = None # The name of the preferred mirror.
- self._aliases = {} # Aliases dictionary
+ self._aliases = None # Aliases dictionary
# Project()
@@ -200,7 +200,7 @@ class Project():
if url and utils._ALIAS_SEPARATOR in url:
url_alias, url_body = url.split(utils._ALIAS_SEPARATOR, 1)
- alias_url = _yaml.node_get(config._aliases, str, url_alias, default_value=None)
+ alias_url = config._aliases.get_str(url_alias, default=None)
if alias_url:
url = alias_url + url_body
@@ -264,7 +264,7 @@ class Project():
#
def get_path_from_node(self, node, key, *,
check_is_file=False, check_is_dir=False):
- path_str = _yaml.node_get(node, str, key)
+ path_str = node.get_str(key)
path = Path(path_str)
full_path = self._absolute_directory_path / path
@@ -404,7 +404,7 @@ class Project():
else:
config = self.config
- return _yaml.node_get(config._aliases, str, alias, default_value=None)
+ return config._aliases.get_str(alias, default=None)
# get_alias_uris()
#
@@ -419,7 +419,7 @@ class Project():
else:
config = self.config
- if not alias or alias not in config._aliases:
+ if not alias or alias not in config._aliases: # pylint: disable=unsupported-membership-test
return [None]
mirror_list = []
@@ -429,7 +429,7 @@ class Project():
mirror_list = alias_mapping[alias] + mirror_list
else:
mirror_list += alias_mapping[alias]
- mirror_list.append(_yaml.node_get(config._aliases, str, alias))
+ mirror_list.append(config._aliases.get_str(alias))
return mirror_list
# load_elements()
@@ -585,7 +585,7 @@ class Project():
# The project name, element path and option declarations
# are constant and cannot be overridden by option conditional statements
- self.name = _yaml.node_get(self._project_conf, str, 'name')
+ self.name = self._project_conf.get_str('name')
# Validate that project name is a valid symbol name
_yaml.assert_symbol_name(_yaml.node_get_provenance(pre_config_node, 'name'),
@@ -621,7 +621,7 @@ class Project():
ignore_unknown=True)
# Use separate file for storing source references
- self.ref_storage = _yaml.node_get(pre_config_node, str, 'ref-storage')
+ self.ref_storage = pre_config_node.get_str('ref-storage')
if self.ref_storage not in [ProjectRefStorage.INLINE, ProjectRefStorage.PROJECT_REFS]:
p = _yaml.node_get_provenance(pre_config_node, 'ref-storage')
raise LoadError(LoadErrorReason.INVALID_DATA,
@@ -715,7 +715,7 @@ class Project():
# Perform environment expansion right away
shell_environment = shell_options.get_mapping('environment', default={})
for key in _yaml.node_keys(shell_environment):
- value = _yaml.node_get(shell_environment, str, key)
+ value = shell_environment.get_str(key)
self._shell_environment[key] = os.path.expandvars(value)
# Host files is parsed as a list for convenience
@@ -730,8 +730,8 @@ class Project():
_yaml.node_validate(host_file_desc, ['path', 'host_path', 'optional'])
# Parse the host mount
- path = _yaml.node_get(host_file_desc, str, 'path')
- host_path = _yaml.node_get(host_file_desc, str, 'host_path', default_value=None)
+ path = host_file_desc.get_str('path')
+ host_path = host_file_desc.get_str('host_path', default=None)
optional = _yaml.node_get(host_file_desc, bool, 'optional', default_value=False)
mount = HostMount(path, host_path, optional)
@@ -806,8 +806,8 @@ class Project():
output.options.export_variables(output.base_variables)
# Override default_mirror if not set by command-line
- output.default_mirror = self._default_mirror or _yaml.node_get(overrides, str,
- 'default-mirror', default_value=None)
+ output.default_mirror = self._default_mirror or overrides.get_str(
+ 'default-mirror', default=None)
mirrors = _yaml.node_get(config, list, 'mirrors', default_value=[])
for mirror in mirrors:
@@ -815,7 +815,7 @@ class Project():
'name', 'aliases'
]
_yaml.node_validate(mirror, allowed_mirror_fields)
- mirror_name = _yaml.node_get(mirror, str, 'name')
+ mirror_name = mirror.get_str('name')
alias_mappings = {}
for alias_mapping, uris in _yaml.node_items(mirror.get_mapping('aliases')):
assert isinstance(uris, list)
@@ -880,7 +880,7 @@ class Project():
allowed_origins = ['core', 'local', 'pip']
_yaml.node_validate(origin, allowed_origin_fields)
- origin_value = _yaml.node_get(origin, str, 'origin')
+ origin_value = origin.get_str('origin')
if origin_value not in allowed_origins:
raise LoadError(
LoadErrorReason.INVALID_YAML,
@@ -907,7 +907,7 @@ class Project():
# Store the origins if they're not 'core'.
# core elements are loaded by default, so storing is unnecessary.
- if _yaml.node_get(origin, str, 'origin') != 'core':
+ if origin.get_str('origin') != 'core':
self._store_origin(origin, 'sources', plugin_source_origins)
self._store_origin(origin, 'elements', plugin_element_origins)
@@ -947,7 +947,7 @@ class Project():
if group in origin_node:
_yaml.node_del(origin_node, group)
- if _yaml.node_get(origin_node, str, 'origin') == 'local':
+ if origin_node.get_str('origin') == 'local':
path = self.get_path_from_node(origin, 'path',
check_is_dir=True)
# paths are passed in relative to the project, but must be absolute
diff --git a/src/buildstream/_variables.pyx b/src/buildstream/_variables.pyx
index 9b8b5a902..c41ff5c3f 100644
--- a/src/buildstream/_variables.pyx
+++ b/src/buildstream/_variables.pyx
@@ -128,7 +128,7 @@ cdef class Variables:
cdef str value
for key in _yaml.node_keys(node):
- value = <str> _yaml.node_get(node, str, key)
+ value = node.get_str(key)
ret[sys.intern(key)] = _parse_expstr(value)
return ret
diff --git a/src/buildstream/_workspaces.py b/src/buildstream/_workspaces.py
index 1adc52ac2..a4f7abc76 100644
--- a/src/buildstream/_workspaces.py
+++ b/src/buildstream/_workspaces.py
@@ -631,8 +631,8 @@ class Workspaces():
def _load_workspace(self, node):
dictionary = {
'prepared': _yaml.node_get(node, bool, 'prepared', default_value=False),
- 'path': _yaml.node_get(node, str, 'path'),
- 'last_successful': _yaml.node_get(node, str, 'last_successful', default_value=None),
+ 'path': node.get_str('path'),
+ 'last_successful': node.get_str('last_successful', default=None),
'running_files': _yaml.node_sanitize(
node.get_mapping('running_files', default=None),
dict_type=dict),
diff --git a/src/buildstream/_yaml.pxd b/src/buildstream/_yaml.pxd
index 7d7e87d8d..b2237f075 100644
--- a/src/buildstream/_yaml.pxd
+++ b/src/buildstream/_yaml.pxd
@@ -31,6 +31,12 @@ cdef class Node:
cdef class MappingNode(Node):
cdef Node get(self, str key, default, default_constructor)
cpdef MappingNode get_mapping(self, str key, default=*)
+ cpdef ScalarNode get_scalar(self, str key, default=*)
+ cpdef str get_str(self, str key, object default=*)
+
+
+cdef class ScalarNode(Node):
+ cpdef str as_str(self)
cdef class ProvenanceInformation:
diff --git a/src/buildstream/_yaml.pyx b/src/buildstream/_yaml.pyx
index 9d9a12400..a7779c41e 100644
--- a/src/buildstream/_yaml.pyx
+++ b/src/buildstream/_yaml.pyx
@@ -78,11 +78,19 @@ cdef class Node:
cdef class ScalarNode(Node):
def __init__(self, object value, int file_index, int line, int column):
+ if type(value) is str:
+ value = value.strip()
self.value = value
self.file_index = file_index
self.line = line
self.column = column
+ cpdef str as_str(self):
+ # We keep 'None' as 'None' to simplify the API's usage and allow chaining for users
+ if self.value is None:
+ return None
+ return str(self.value)
+
cdef class MappingNode(Node):
@@ -119,6 +127,25 @@ cdef class MappingNode(Node):
return value
+ cpdef ScalarNode get_scalar(self, str key, object default=_sentinel):
+ value = self.get(key, default, ScalarNode)
+
+ if type(value) is not ScalarNode:
+ if value is None:
+ value = ScalarNode(None, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter())
+ else:
+ provenance = node_get_provenance(value)
+ raise LoadError(LoadErrorReason.INVALID_DATA,
+ "{}: Value of '{}' is not of the expected type 'Scalar'"
+ .format(provenance, key))
+
+ return value
+
+ cpdef str get_str(self, str key, object default=_sentinel):
+ # TODO: don't go through 'get_scalar', we can directly get everything and optimize
+ cdef ScalarNode scalar = self.get_scalar(key, default)
+ return scalar.as_str()
+
class SequenceNode(Node):
def __init__(self, list value, int file_index, int line, int column):
diff --git a/src/buildstream/element.py b/src/buildstream/element.py
index aaf8577a5..05e590823 100644
--- a/src/buildstream/element.py
+++ b/src/buildstream/element.py
@@ -512,7 +512,7 @@ class Element(Plugin):
# variables in the returned string
name = self.node_subst_member(node, 'name')
"""
- value = self.node_get_member(node, str, member_name, default)
+ value = node.get_str(member_name, default)
try:
return self.__variables.subst(value)
except LoadError as e:
@@ -2702,7 +2702,7 @@ class Element(Plugin):
# Sandbox config, unlike others, has fixed members so we should validate them
_yaml.node_validate(sandbox_config, ['build-uid', 'build-gid', 'build-os', 'build-arch'])
- build_arch = _yaml.node_get(sandbox_config, str, 'build-arch', default_value=None)
+ build_arch = sandbox_config.get_str('build-arch', default=None)
if build_arch:
build_arch = Platform.canonicalize_arch(build_arch)
else:
@@ -2711,7 +2711,7 @@ class Element(Plugin):
return SandboxConfig(
_yaml.node_get(sandbox_config, int, 'build-uid'),
_yaml.node_get(sandbox_config, int, 'build-gid'),
- _yaml.node_get(sandbox_config, str, 'build-os', default_value=host_os),
+ sandbox_config.get_str('build-os', default=host_os),
build_arch)
# This makes a special exception for the split rules, which
diff --git a/src/buildstream/plugins/elements/junction.py b/src/buildstream/plugins/elements/junction.py
index 849df72be..d30e34828 100644
--- a/src/buildstream/plugins/elements/junction.py
+++ b/src/buildstream/plugins/elements/junction.py
@@ -175,9 +175,9 @@ class JunctionElement(Element):
BST_FORBID_RDEPENDS = True
def configure(self, node):
- self.path = self.node_get_member(node, str, 'path', default='')
+ self.path = node.get_str('path', default='')
self.options = node.get_mapping('options', default={})
- self.target = self.node_get_member(node, str, 'target', default=None)
+ self.target = node.get_str('target', default=None)
self.target_element = None
self.target_junction = None
diff --git a/src/buildstream/plugins/sources/_downloadablefilesource.py b/src/buildstream/plugins/sources/_downloadablefilesource.py
index b9b15e268..7b1785979 100644
--- a/src/buildstream/plugins/sources/_downloadablefilesource.py
+++ b/src/buildstream/plugins/sources/_downloadablefilesource.py
@@ -77,8 +77,8 @@ class DownloadableFileSource(Source):
__urlopener = None
def configure(self, node):
- self.original_url = self.node_get_member(node, str, 'url')
- self.ref = self.node_get_member(node, str, 'ref', None)
+ self.original_url = node.get_str('url')
+ self.ref = node.get_str('ref', None)
self.url = self.translate_url(self.original_url)
self._warn_deprecated_etag(node)
@@ -99,7 +99,7 @@ class DownloadableFileSource(Source):
return Consistency.RESOLVED
def load_ref(self, node):
- self.ref = self.node_get_member(node, str, 'ref', None)
+ self.ref = node.get_str('ref', None)
self._warn_deprecated_etag(node)
def get_ref(self):
@@ -143,7 +143,7 @@ class DownloadableFileSource(Source):
.format(self.url, sha256, self.ref))
def _warn_deprecated_etag(self, node):
- etag = self.node_get_member(node, str, 'etag', None)
+ etag = node.get_str('etag', None)
if etag:
provenance = self.node_provenance(node, member_name='etag')
self.warn('{} "etag" is deprecated and ignored.'.format(provenance))
diff --git a/src/buildstream/plugins/sources/bzr.py b/src/buildstream/plugins/sources/bzr.py
index e59986da6..082d11dec 100644
--- a/src/buildstream/plugins/sources/bzr.py
+++ b/src/buildstream/plugins/sources/bzr.py
@@ -69,9 +69,9 @@ class BzrSource(Source):
def configure(self, node):
self.node_validate(node, ['url', 'track', 'ref', *Source.COMMON_CONFIG_KEYS])
- self.original_url = self.node_get_member(node, str, 'url')
- self.tracking = self.node_get_member(node, str, 'track')
- self.ref = self.node_get_member(node, str, 'ref', None)
+ self.original_url = node.get_str('url')
+ self.tracking = node.get_str('track')
+ self.ref = node.get_str('ref', None)
self.url = self.translate_url(self.original_url)
def preflight(self):
diff --git a/src/buildstream/plugins/sources/deb.py b/src/buildstream/plugins/sources/deb.py
index e45994951..cc88cf53c 100644
--- a/src/buildstream/plugins/sources/deb.py
+++ b/src/buildstream/plugins/sources/deb.py
@@ -61,7 +61,7 @@ class DebSource(TarSource):
def configure(self, node):
super().configure(node)
- self.base_dir = self.node_get_member(node, str, 'base-dir', None)
+ self.base_dir = node.get_str('base-dir', None)
def preflight(self):
return
diff --git a/src/buildstream/plugins/sources/pip.py b/src/buildstream/plugins/sources/pip.py
index 9d6c40d74..db0537497 100644
--- a/src/buildstream/plugins/sources/pip.py
+++ b/src/buildstream/plugins/sources/pip.py
@@ -111,8 +111,8 @@ class PipSource(Source):
def configure(self, node):
self.node_validate(node, ['url', 'packages', 'ref', 'requirements-files'] +
Source.COMMON_CONFIG_KEYS)
- self.ref = self.node_get_member(node, str, 'ref', None)
- self.original_url = self.node_get_member(node, str, 'url', _PYPI_INDEX_URL)
+ self.ref = node.get_str('ref', None)
+ self.original_url = node.get_str('url', _PYPI_INDEX_URL)
self.index_url = self.translate_url(self.original_url)
self.packages = self.node_get_member(node, list, 'packages', [])
self.requirements_files = self.node_get_member(node, list, 'requirements-files', [])
diff --git a/src/buildstream/plugins/sources/remote.py b/src/buildstream/plugins/sources/remote.py
index 562a8f226..4e9fe4f7d 100644
--- a/src/buildstream/plugins/sources/remote.py
+++ b/src/buildstream/plugins/sources/remote.py
@@ -62,7 +62,7 @@ class RemoteSource(DownloadableFileSource):
def configure(self, node):
super().configure(node)
- self.filename = self.node_get_member(node, str, 'filename', os.path.basename(self.url))
+ self.filename = node.get_str('filename', os.path.basename(self.url))
self.executable = self.node_get_member(node, bool, 'executable', False)
if os.sep in self.filename:
diff --git a/src/buildstream/plugins/sources/tar.py b/src/buildstream/plugins/sources/tar.py
index c90de74ea..ef2ee1d85 100644
--- a/src/buildstream/plugins/sources/tar.py
+++ b/src/buildstream/plugins/sources/tar.py
@@ -72,8 +72,7 @@ class TarSource(DownloadableFileSource):
def configure(self, node):
super().configure(node)
- self.base_dir = self.node_get_member(node, str, 'base-dir', '*')
-
+ self.base_dir = node.get_str('base-dir', '*')
self.node_validate(node, DownloadableFileSource.COMMON_CONFIG_KEYS + ['base-dir'])
def preflight(self):
diff --git a/src/buildstream/plugins/sources/zip.py b/src/buildstream/plugins/sources/zip.py
index 9981f1260..1724f0587 100644
--- a/src/buildstream/plugins/sources/zip.py
+++ b/src/buildstream/plugins/sources/zip.py
@@ -72,8 +72,7 @@ class ZipSource(DownloadableFileSource):
def configure(self, node):
super().configure(node)
- self.base_dir = self.node_get_member(node, str, 'base-dir', '*')
-
+ self.base_dir = node.get_str('base-dir', '*')
self.node_validate(node, DownloadableFileSource.COMMON_CONFIG_KEYS + ['base-dir'])
def get_unique_key(self):