summaryrefslogtreecommitdiffstats
path: root/taskcluster/gecko_taskgraph/util/copy_task.py
diff options
context:
space:
mode:
Diffstat (limited to 'taskcluster/gecko_taskgraph/util/copy_task.py')
-rw-r--r--taskcluster/gecko_taskgraph/util/copy_task.py40
1 files changed, 40 insertions, 0 deletions
diff --git a/taskcluster/gecko_taskgraph/util/copy_task.py b/taskcluster/gecko_taskgraph/util/copy_task.py
new file mode 100644
index 0000000000..0aaf43361e
--- /dev/null
+++ b/taskcluster/gecko_taskgraph/util/copy_task.py
@@ -0,0 +1,40 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from mozbuild.util import ReadOnlyDict
+from taskgraph.task import Task
+
+immutable_types = {int, float, bool, str, type(None), ReadOnlyDict}
+
+
+def copy_task(obj):
+ """
+ Perform a deep copy of a task that has a tree-like structure.
+
+ Unlike copy.deepcopy, this does *not* support copying graph-like structure,
+ but it does it more efficiently than deepcopy.
+ """
+ ty = type(obj)
+ if ty in immutable_types:
+ return obj
+ if ty is dict:
+ return {k: copy_task(v) for k, v in obj.items()}
+ if ty is list:
+ return [copy_task(elt) for elt in obj]
+ if ty is Task:
+ task = Task(
+ kind=copy_task(obj.kind),
+ label=copy_task(obj.label),
+ attributes=copy_task(obj.attributes),
+ task=copy_task(obj.task),
+ description=copy_task(obj.description),
+ optimization=copy_task(obj.optimization),
+ dependencies=copy_task(obj.dependencies),
+ soft_dependencies=copy_task(obj.soft_dependencies),
+ if_dependencies=copy_task(obj.if_dependencies),
+ )
+ if obj.task_id:
+ task.task_id = obj.task_id
+ return task
+ raise NotImplementedError(f"copying '{ty}' from '{obj}'")