summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2017-07-05 22:19:28 +0900
committerTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2017-07-05 22:19:28 +0900
commitfcd2c348bb595fc3d3549cc1207afef632f83d80 (patch)
treed365682a103d56d0498ec6dc5a2dfc87498eb53a
parent5ec9ffe3bfd14b6687b188531792c9479afb62d6 (diff)
downloadbuildstream-fcd2c348bb595fc3d3549cc1207afef632f83d80.tar.gz
_yaml.py: Added node_copy() and list_copy()
These are similar to node_chain_copy() and node_list_copy() which are there mostly for optimization reasons, but node_copy() and list_copy() entirely safely separate the nodes from their originals. This is suitable when giving away a node to a plugin via an API call where we want to be sure that no modifications modify the source node. As a side effect it also ensures that ever node has Provenance, in case nodes are given back to the data model where they might be expected later.
-rw-r--r--buildstream/_yaml.py30
1 files changed, 30 insertions, 0 deletions
diff --git a/buildstream/_yaml.py b/buildstream/_yaml.py
index 93fae4903..c8151d501 100644
--- a/buildstream/_yaml.py
+++ b/buildstream/_yaml.py
@@ -602,3 +602,33 @@ def list_chain_copy(source):
copy.append(item)
return copy
+
+
+def node_copy(source):
+ copy = {}
+ for key, value in source.items():
+ if isinstance(value, collections.Mapping):
+ copy[key] = node_copy(value)
+ elif isinstance(value, list):
+ copy[key] = list_copy(value)
+ elif isinstance(value, Provenance):
+ copy[key] = value.clone()
+
+ ensure_provenance(copy)
+
+ return copy
+
+
+def list_copy(source):
+ copy = []
+ for item in source:
+ if isinstance(item, collections.Mapping):
+ copy.append(node_copy(item))
+ elif isinstance(item, list):
+ copy.append(list_copy(item))
+ elif isinstance(item, Provenance):
+ copy.append(item.clone())
+ else:
+ copy.append(item)
+
+ return copy