diff options
author | Benjamin Schubert <contact@benschubert.me> | 2019-06-08 16:40:26 +0100 |
---|---|---|
committer | Benjamin Schubert <ben.c.schubert@gmail.com> | 2019-07-09 16:53:03 +0100 |
commit | 2fbdffc77342633e4e77ec049b2a208468b6888d (patch) | |
tree | 1a2b1589afa128108c18dcb5ea4e08a5551307f5 | |
parent | b37adcb58f2c0fb46f54b329000621dfa4df1c02 (diff) | |
download | buildstream-2fbdffc77342633e4e77ec049b2a208468b6888d.tar.gz |
_yaml: Introduce a 'Sequence' Node
This allows us to represent sequences (lists) more efficiently.
This is the third type that is needed in order to know what kind of
datastructure we are handling in our graph.
-rw-r--r-- | src/buildstream/_yaml.pyx | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/src/buildstream/_yaml.pyx b/src/buildstream/_yaml.pyx index e3601566f..21e78cb59 100644 --- a/src/buildstream/_yaml.pyx +++ b/src/buildstream/_yaml.pyx @@ -88,6 +88,14 @@ cdef class MappingNode(Node): self.column = column +class SequenceNode(Node): + def __init__(self, list value, int file_index, int line, int column): + self.value = value + self.file_index = file_index + self.line = line + self.column = column + + # Metadata container for a yaml toplevel node. # # This class contains metadata around a yaml node in order to be able @@ -331,13 +339,13 @@ cdef class Representer: return RepresenterState.doc cdef RepresenterState _handle_wait_value_SequenceStartEvent(self, object ev): - self.output.append(Node([], self._file_index, ev.start_mark.line, ev.start_mark.column)) + self.output.append(SequenceNode([], self._file_index, ev.start_mark.line, ev.start_mark.column)) (<dict> (<Node> self.output[-2]).value)[self.keys[-1]] = self.output[-1] return RepresenterState.wait_list_item cdef RepresenterState _handle_wait_list_item_SequenceStartEvent(self, object ev): self.keys.append(len((<Node> self.output[-1]).value)) - self.output.append(Node([], self._file_index, ev.start_mark.line, ev.start_mark.column)) + self.output.append(SequenceNode([], self._file_index, ev.start_mark.line, ev.start_mark.column)) (<list> (<Node> self.output[-2]).value).append(self.output[-1]) return RepresenterState.wait_list_item @@ -376,6 +384,8 @@ cdef Node _create_node(object value, int file_index, int line, int column): return ScalarNode(value, file_index, line, column) elif type(value) is dict: return MappingNode(value, file_index, line, column) + elif type(value) is list: + return SequenceNode(value, file_index, line, column) return Node(value, file_index, line, column) @@ -563,11 +573,11 @@ cpdef object node_get(Node node, object expected_type, str key, list indices=Non else: # Implied type check of the element itself # No need to synthesise useful node content as we destructure it immediately - value = Node(node_get(node, list, key), _SYNTHETIC_FILE_INDEX, 0, 0) + value = SequenceNode(node_get(node, list, key), _SYNTHETIC_FILE_INDEX, 0, 0) for index in indices: value = value.value[index] # FIXME: this should always be nodes, we should be able to remove that - if type(value) not in [Node, MappingNode]: + if type(value) not in [Node, MappingNode, SequenceNode]: value = _create_node(value, _SYNTHETIC_FILE_INDEX, 0, 0) # Optionally allow None as a valid value for any type @@ -659,7 +669,7 @@ cpdef void node_set(Node node, object key, object value, list indices=None) exce key = indices.pop() for idx in indices: node = <Node> (<list> node.value)[idx] - if type(value) in [Node, MappingNode]: + if type(value) in [Node, MappingNode, ScalarNode, SequenceNode]: node.value[key] = value else: try: @@ -694,7 +704,7 @@ def node_extend_list(Node node, str key, Py_ssize_t length, object default): cdef Node list_node = <Node> node.value.get(key) if list_node is None: - list_node = node.value[key] = Node([], node.file_index, node.line, next_synthetic_counter()) + list_node = node.value[key] = SequenceNode([], node.file_index, node.line, next_synthetic_counter()) cdef list the_list = list_node.value def_type = type(default) @@ -791,7 +801,7 @@ cpdef void node_del(Node node, str key, bint safe=False) except *: def is_node(maybenode): # It's a programming error to give this a Node which isn't a mapping # so assert that. - assert (type(maybenode) not in [Node, ScalarNode]) + assert (type(maybenode) not in [ScalarNode, SequenceNode]) # Now return the type check return type(maybenode) is MappingNode @@ -870,7 +880,7 @@ cdef Node __new_node_from_list(list inlist): ret.append(__new_node_from_list(v)) else: ret.append(ScalarNode(str(v), _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter())) - return Node(ret, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter()) + return SequenceNode(ret, _SYNTHETIC_FILE_INDEX, 0, next_synthetic_counter()) # _is_composite_list @@ -1096,7 +1106,7 @@ cpdef object node_sanitize(object node, object dict_type=OrderedDict): # If we have an unwrappable node, unwrap it # FIXME: we should only ever have Nodes here - if node_type in [Node, MappingNode]: + if node_type in [MappingNode, SequenceNode]: node = node.value node_type = type(node) @@ -1225,7 +1235,7 @@ cdef Node _list_copy(Node source): else: raise ValueError("Unable to be quick about list_copy of {}".format(item_type)) - return Node(copy, source.file_index, source.line, source.column) + return SequenceNode(copy, source.file_index, source.line, source.column) # node_final_assertions() |