summaryrefslogtreecommitdiff
path: root/src/buildstream/_yaml.pyx
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildstream/_yaml.pyx')
-rw-r--r--src/buildstream/_yaml.pyx90
1 files changed, 27 insertions, 63 deletions
diff --git a/src/buildstream/_yaml.pyx b/src/buildstream/_yaml.pyx
index 4a49a9832..02e7bf205 100644
--- a/src/buildstream/_yaml.pyx
+++ b/src/buildstream/_yaml.pyx
@@ -74,6 +74,9 @@ cdef class Node:
# code which has access to such nodes would do this.
return what in self.value
+ cpdef Node copy(self):
+ raise NotImplementedError()
+
cdef class ScalarNode(Node):
@@ -85,6 +88,9 @@ cdef class ScalarNode(Node):
self.line = line
self.column = column
+ cpdef ScalarNode copy(self):
+ return self
+
cpdef bint is_none(self):
return self.value is None
@@ -129,6 +135,17 @@ cdef class MappingNode(Node):
self.line = line
self.column = column
+ cpdef MappingNode copy(self):
+ cdef dict copy = {}
+ cdef str key
+ cdef Node value
+
+ for key, value in self.value.items():
+ copy[key] = value.copy()
+
+ return MappingNode(copy, self.file_index, self.line, self.column)
+
+
cdef Node get(self, str key, object default, object default_constructor):
value = self.value.get(key, _sentinel)
@@ -223,6 +240,15 @@ cdef class SequenceNode(Node):
self.line = line
self.column = column
+ cpdef SequenceNode copy(self):
+ cdef list copy = []
+ cdef Node entry
+
+ for entry in self.value:
+ copy.append(entry.copy())
+
+ return SequenceNode(copy, self.file_index, self.line, self.column)
+
cpdef MappingNode mapping_at(self, int index):
value = self.value[index]
@@ -650,7 +676,7 @@ cpdef Node load_data(str data, int file_index=_SYNTHETIC_FILE_INDEX, str file_na
)
if copy_tree:
- contents = node_copy(contents)
+ contents = contents.copy()
return contents
@@ -1240,73 +1266,11 @@ cpdef void node_validate(Node node, list valid_keys) except *:
"{}: Unexpected key: {}".format(provenance, key))
-# Node copying
-#
-# Unfortunately we copy nodes a *lot* and `isinstance()` is super-slow when
-# things from collections.abc get involved. The result is the following
-# intricate but substantially faster group of tuples and the use of `in`.
-#
-# If any of the {node,list}_copy routines raise a ValueError
-# then it's likely additional types need adding to these tuples.
-
-
-# These types just have their value copied
-__QUICK_TYPES = (str, bool)
-
# These are the directives used to compose lists, we need this because it's
# slightly faster during the node_final_assertions checks
__NODE_ASSERT_COMPOSITION_DIRECTIVES = ('(>)', '(<)', '(=)')
-# node_copy()
-#
-# Make a deep copy of the given YAML node, preserving provenance.
-#
-# Args:
-# source (Node): The YAML node to copy
-#
-# Returns:
-# (Node): A deep copy of source with provenance preserved.
-#
-cpdef MappingNode node_copy(MappingNode source):
- cdef dict copy = {}
- cdef str key
- cdef Node value
-
- for key, value in source.value.items():
- value_type = type(value.value)
- if value_type is dict:
- copy[key] = node_copy(value)
- elif value_type is list:
- copy[key] = _list_copy(value)
- elif value_type in __QUICK_TYPES:
- copy[key] = value
- else:
- raise ValueError("Unable to be quick about node_copy of {}".format(value_type))
-
- return MappingNode(copy, source.file_index, source.line, source.column)
-
-
-# Internal function to help node_copy() but for lists.
-cdef Node _list_copy(Node source):
- cdef list copy = []
- cdef Node item
-
- for item in source.value:
- item_type = type(item.value)
-
- if item_type is dict:
- copy.append(node_copy(item))
- elif item_type is list:
- copy.append(_list_copy(item))
- elif item_type in __QUICK_TYPES:
- copy.append(item)
- else:
- raise ValueError("Unable to be quick about list_copy of {}".format(item_type))
-
- return SequenceNode(copy, source.file_index, source.line, source.column)
-
-
# node_final_assertions()
#
# This must be called on a fully loaded and composited node,