summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Schubert <contact@benschubert.me>2020-06-29 13:55:17 +0000
committerBenjamin Schubert <contact@benschubert.me>2020-06-29 13:55:17 +0000
commitcb34c95009f8a77ea28b7390a5abbbcc428aa171 (patch)
treebe460a7bd64fbe400678f37f4c58d8c317f8129d
parent712e6b642e5263a24069f8b2300bd0cd76da1a6f (diff)
downloadbuildstream-bschubert/optimize-mapping-node.tar.gz
-rw-r--r--src/buildstream/_yaml.pyx6
-rw-r--r--src/buildstream/node.pxd2
-rw-r--r--src/buildstream/node.pyx64
3 files changed, 37 insertions, 35 deletions
diff --git a/src/buildstream/_yaml.pyx b/src/buildstream/_yaml.pyx
index 26c728681..c94b78ed6 100644
--- a/src/buildstream/_yaml.pyx
+++ b/src/buildstream/_yaml.pyx
@@ -32,7 +32,7 @@ from ruamel import yaml
from ._exceptions import LoadError
from .exceptions import LoadErrorReason
from . cimport node
-from .node cimport MappingNode, ScalarNode, SequenceNode
+from .node cimport MappingNode, Node, ScalarNode, SequenceNode
# These exceptions are intended to be caught entirely within
@@ -188,7 +188,7 @@ cdef class Representer:
cdef RepresenterState _handle_wait_value_MappingStartEvent(self, object ev):
cdef RepresenterState new_state = self._handle_doc_MappingStartEvent(ev)
key = self.keys.pop()
- (<MappingNode> self.output[-2])._set(key, self.output[-1])
+ (<MappingNode> self.output[-2])._set(key, <Node> self.output[-1])
return new_state
cdef RepresenterState _handle_wait_key_MappingEndEvent(self, object ev):
@@ -206,7 +206,7 @@ cdef class Representer:
cdef RepresenterState _handle_wait_value_SequenceStartEvent(self, object ev):
self.output.append(SequenceNode.__new__(
SequenceNode, self._file_index, ev.start_mark.line, ev.start_mark.column, []))
- (<MappingNode> self.output[-2])._set(self.keys[-1], self.output[-1])
+ (<MappingNode> self.output[-2])._set(self.keys[-1], <Node> self.output[-1])
return RepresenterState.wait_list_item
cdef RepresenterState _handle_wait_list_item_SequenceStartEvent(self, object ev):
diff --git a/src/buildstream/node.pxd b/src/buildstream/node.pxd
index 769de9adf..ca773b422 100644
--- a/src/buildstream/node.pxd
+++ b/src/buildstream/node.pxd
@@ -71,7 +71,7 @@ cdef class MappingNode(Node):
# Private Methods
cdef void __composite(self, MappingNode target, list path) except *
- cdef void _set(self, str key, object value)
+ cdef void _set(self, str key, Node value)
cdef Node _get(self, str key, default, default_constructor)
diff --git a/src/buildstream/node.pyx b/src/buildstream/node.pyx
index 42a0794c8..406bbce1b 100644
--- a/src/buildstream/node.pyx
+++ b/src/buildstream/node.pyx
@@ -504,7 +504,37 @@ cdef class MappingNode(Node):
del self.value[key]
def __setitem__(self, str key, object value):
- self._set(key, value)
+ cdef Node old_value
+ cdef Node node
+
+ if type(value) not in [MappingNode, ScalarNode, SequenceNode]:
+ node = __create_node_recursive(value, self)
+
+ # 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 = <Node> self.value.get(key)
+ if old_value:
+ node.file_index = old_value.file_index
+ node.line = old_value.line
+ node.column = old_value.column
+ else:
+ node = value
+
+ self._set(key, node)
#############################################################
# Public Methods #
@@ -1108,38 +1138,10 @@ cdef class MappingNode(Node):
# key (str): the key for which to set the value
# value (object): the value to set
#
- cdef void _set(self, str key, object value):
+ cdef void _set(self, str key, Node value):
cdef Node old_value
cdef intern_key = sys.intern(key)
-
- if type(value) in [MappingNode, ScalarNode, SequenceNode]:
- self.value[intern_key] = value
- else:
- node = __create_node_recursive(value, self)
-
- # 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(intern_key)
- if old_value:
- node.file_index = old_value.file_index
- node.line = old_value.line
- node.column = old_value.column
-
- self.value[intern_key] = node
+ self.value[intern_key] = value
# _get(key, default, default_constructor)
#