Skip to content

Commit

Permalink
feat: port util.copy_task from gecko_taskgraph
Browse files Browse the repository at this point in the history
And use it in `util.templates.merge`.

This is a port of the following patch in `gecko_taskgraph`:
https://hg.mozilla.org/mozilla-central/rev/fa2cdac6989ac78d606d8f8adb10d826a6e50429
  • Loading branch information
ahal committed Jun 7, 2024
1 parent 526d0c7 commit e58ebcc
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 2 deletions.
45 changes: 45 additions & 0 deletions src/taskgraph/util/copy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from taskgraph.task import Task
from taskgraph.util.readonlydict import ReadOnlyDict

immutable_types = {int, float, bool, str, type(None), ReadOnlyDict}


def deepcopy(obj):
"""Perform a deep copy of an object with a tree like structure.
This is a re-implementation of Python's `copy.deepcopy` function with a few key differences:
1. Unlike the stdlib, this does *not* support copying graph-like structure,
which allows it to be more efficient than deepcopy on tree-like structures
(such as Tasks).
2. This special cases support for `taskgraph.task.Task` objects.
Args:
obj: The object to deep copy.
Returns:
A deep copy of the object.
"""
ty = type(obj)
if ty in immutable_types:
return obj
if ty is dict:
return {k: deepcopy(v) for k, v in obj.items()}
if ty is list:
return [deepcopy(elt) for elt in obj]
if ty is Task:
task = Task(
kind=deepcopy(obj.kind),
label=deepcopy(obj.label),
attributes=deepcopy(obj.attributes),
task=deepcopy(obj.task),
description=deepcopy(obj.description),
optimization=deepcopy(obj.optimization),
dependencies=deepcopy(obj.dependencies),
soft_dependencies=deepcopy(obj.soft_dependencies),
if_dependencies=deepcopy(obj.if_dependencies),
)
if obj.task_id:
task.task_id = obj.task_id
return task
raise NotImplementedError(f"copying '{ty}' from '{obj}'")
4 changes: 2 additions & 2 deletions src/taskgraph/util/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# 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/.

import copy
from taskgraph.util.copy import deepcopy


def merge_to(source, dest):
Expand Down Expand Up @@ -55,7 +55,7 @@ def merge(*objects):
Returns the result without modifying any arguments.
"""
if len(objects) == 1:
return copy.deepcopy(objects[0])
return deepcopy(objects[0])
return merge_to(objects[-1], merge(*objects[:-1]))


Expand Down
34 changes: 34 additions & 0 deletions test/test_util_copy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import pytest

from taskgraph.task import Task
from taskgraph.util.copy import deepcopy, immutable_types
from taskgraph.util.readonlydict import ReadOnlyDict


@pytest.mark.parametrize(
"input",
(
1,
False,
"foo",
ReadOnlyDict(a=1, b="foo"),
["foo", "bar"],
{
"foo": Task(
label="abc",
kind="kind",
attributes={"bar": "baz"},
dependencies={"dep": "bar"},
task={"payload": {"command": ["echo hello"]}},
)
},
),
)
def test_deepcopy(input):
result = deepcopy(input)
assert result == input

if type(result) in immutable_types:
assert id(result) == id(input)
else:
assert id(result) != id(input)

0 comments on commit e58ebcc

Please sign in to comment.