diff options
Diffstat (limited to 'src/buildstream/_yaml.pyx')
| -rw-r--r-- | src/buildstream/_yaml.pyx | 100 |
1 files changed, 61 insertions, 39 deletions
diff --git a/src/buildstream/_yaml.pyx b/src/buildstream/_yaml.pyx index ae00924bc..6d5ac9508 100644 --- a/src/buildstream/_yaml.pyx +++ b/src/buildstream/_yaml.pyx @@ -250,6 +250,36 @@ cdef class MappingNode(Node): def __delitem__(self, str key): del self.value[key] + def __setitem__(self, str key, object value): + if type(value) in [MappingNode, ScalarNode, SequenceNode]: + self.value[key] = value + else: + node = _create_node_recursive(value) + + # FIXME: Do we really want to override provenance? + # + # Related to https://gitlab.com/BuildStream/buildstream/issues/1058 + # + # There are only two cases were nodes are set in the code (hence without provenance): + # - When automatic variables are set by the core (e-g: max-jobs) + # - when plugins call Element.set_public_data + # + # The first case should never throw errors, so it is of limited interests. + # + # The second is more important. What should probably be done here is to have 'set_public_data' + # able of creating a fake provenance with the name of the plugin, the project and probably the + # element name. + # + # We would therefore have much better error messages, and would be able to get rid of most synthetic + # nodes. + old_value = self.value.get(key) + if old_value: + node.file_index = old_value.file_index + node.line = old_value.line + node.column = old_value.column + + self.value[key] = node + cdef class SequenceNode(Node): def __init__(self, list value, int file_index, int line, int column): @@ -302,6 +332,21 @@ cdef class SequenceNode(Node): def __reversed__(self): return reversed(self.value) + def __setitem__(self, int key, object value): + if type(value) in [MappingNode, ScalarNode, SequenceNode]: + self.value[key] = value + else: + node = _create_node_recursive(value) + + # FIXME: Do we really want to override provenance? + # See __setitem__ on 'MappingNode' for more context + old_value = self.value[key] + if old_value: + node.file_index = old_value.file_index + node.line = old_value.line + node.column = old_value.column + + self.value[key] = node # Metadata container for a yaml toplevel node. # @@ -599,6 +644,22 @@ cdef Node _create_node(object value, int file_index, int line, int column): "Node values can only be 'list', 'dict', 'bool', 'str', 'int' or None. Not {}".format(type_value)) +cdef Node _create_node_recursive(object value): + cdef value_type = type(value) + + if value_type is list: + node = __new_node_from_list(value) + elif value_type is str: + node = ScalarNode(value, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter()) + elif value_type is dict: + node = new_node_from_dict(value) + else: + raise ValueError( + "Unable to assign a value of type {} to a Node.".format(value_type)) + + return node + + # Loads a dictionary from some YAML # # Args: @@ -739,45 +800,6 @@ cpdef ProvenanceInformation node_get_provenance(Node node, str key=None, list in return ProvenanceInformation(nodeish) -# node_set() -# -# Set an item within the node. If using `indices` be aware that the entry must -# already exist, or else a KeyError will be raised. Use `node_extend_list` to -# create entries before using `node_set` -# -# Args: -# node (Node): The node -# key (str): The key name -# value: The value -# indices: Any indices to index into the list referenced by key, like in -# `node_get` (must be a list of integers) -# -cpdef void node_set(Node node, object key, object value, list indices=None) except *: - cdef int idx - - if type(value) is list: - value = __new_node_from_list(value) - - if indices: - node = <Node> (<dict> node.value)[key] - key = indices.pop() - for idx in indices: - node = <Node> (<list> node.value)[idx] - if type(value) in [Node, MappingNode, ScalarNode, SequenceNode]: - node.value[key] = value - else: - try: - # Need to do this just in case we're modifying a list - old_value = <Node> node.value[key] - except KeyError: - old_value = None - - if old_value is None: - node.value[key] = _create_node(value, node.file_index, node.line, next_synthetic_counter()) - else: - node.value[key] = _create_node(value, old_value.file_index, old_value.line, old_value.column) - - # node_extend_list() # # Extend a list inside a node to a given length, using the passed |
