Skip to content

Commit

Permalink
feat(decl): Implement recursive sync
Browse files Browse the repository at this point in the history
  • Loading branch information
huyenngn committed Mar 12, 2024
1 parent 049b8ee commit 97d68a7
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 8 deletions.
13 changes: 9 additions & 4 deletions capellambse/decl.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ def _operate_sync(

for obj in v:
try:
find_args = obj.pop("find")
find_args = obj["find"]
except KeyError:
raise ValueError(
"Expected `find` key in sync object"
Expand All @@ -274,22 +274,27 @@ def _operate_sync(

if candidates:
candidate = candidates[0]
if sync := obj.pop("sync", None):
yield from _operate_sync(promises, candidate, sync)
if mods := obj.pop("set", None):
yield from _operate_modify(promises, candidate, mods)
if ext := obj.pop("add", None):
if ext := obj.pop("extend", None):
yield from _operate_extend(promises, candidate, ext)
promise: str | Promise | None = obj.get("promise_id")
if promise is not None:
if isinstance(promise, str):
promise = Promise(promise)
yield (promise, candidate)
else:
newobj_props = find_args | obj.get("set", {})
newobj_props = (
find_args | obj.pop("set", {}) | obj.pop("extend", {})
)
if "promise_id" in obj:
newobj_props["promise_id"] = obj["promise_id"]
newobj_props["promise_id"] = obj.pop("promise_id")
yield from _create_complex_objects(
promises, parent, attr, [newobj_props]
)
yield from _operate_sync(promises, parent, modifications)

yield from ()

Expand Down
37 changes: 33 additions & 4 deletions tests/test_decl.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ def test_sync_operation_finds_and_modifies_existing_objects_in_the_list(
assert root_function.functions[0].description == new_description

@staticmethod
def test_sync_operation_finds_and_modifies_existing_objects_in_the_list_recurse(
def test_sync_operation_overwrites_iterables(
model: capellambse.MelodyModel,
) -> None:
root_function = model.by_uuid(ROOT_FUNCTION)
Expand Down Expand Up @@ -648,7 +648,7 @@ def test_sync_operation_finds_and_modifies_existing_objects_in_the_list_recurse(
)

@staticmethod
def test_sync_operation_finds_and_extends_existing_objects_in_the_list_recurse(
def test_sync_operation_extends_iterables(
model: capellambse.MelodyModel,
) -> None:
root_function = model.by_uuid(ROOT_FUNCTION)
Expand All @@ -660,7 +660,7 @@ def test_sync_operation_finds_and_extends_existing_objects_in_the_list_recurse(
functions:
- find:
name: {subfunc.name}
add:
extend:
inputs:
- name: {new_input}
"""
Expand All @@ -674,7 +674,7 @@ def test_sync_operation_finds_and_extends_existing_objects_in_the_list_recurse(
functions:
- find:
name: {root_function.functions[0].name}
add:
extend:
inputs:
- name: {input}
"""
Expand All @@ -685,6 +685,30 @@ def test_sync_operation_finds_and_extends_existing_objects_in_the_list_recurse(
and new_input in subfunc.inputs.by_name
)

@staticmethod
def test_sync_operation_recursive(model: capellambse.MelodyModel) -> None:
root_package = model.la.data_package
package_name = "The new package"
subpackage_name = "The new subpackage"
assert package_name not in root_package.packages.by_name
yml = f"""\
- parent: !uuid {root_package.uuid}
sync:
packages:
- find:
name: "{package_name}"
sync:
packages:
- find:
name: {subpackage_name}
"""

decl.apply(model, io.StringIO(yml))
assert package_name in root_package.packages.by_name
package = root_package.packages.by_name(package_name)
assert subpackage_name in package.packages.by_name

@staticmethod
def test_sync_operation_creates_a_new_object_if_it_didnt_find_a_match(
model: capellambse.MelodyModel,
Expand All @@ -693,6 +717,7 @@ def test_sync_operation_creates_a_new_object_if_it_didnt_find_a_match(
new_name = "The new function"
new_description = "This is a new function."
assert new_name not in root_function.functions.by_name
input = "Power port"
yml = f"""\
- parent: !uuid {ROOT_FUNCTION}
sync:
Expand All @@ -701,13 +726,17 @@ def test_sync_operation_creates_a_new_object_if_it_didnt_find_a_match(
name: {new_name}
set:
description: {new_description!r}
extend:
inputs:
- name: {input}
"""

decl.apply(model, io.StringIO(yml))

assert new_name in root_function.functions.by_name
func = root_function.functions.by_name(new_name, single=True)
assert func.description == new_description
assert input in func.inputs.by_name

@staticmethod
def test_sync_operation_resolves_promises_with_newly_created_objects(
Expand Down

0 comments on commit 97d68a7

Please sign in to comment.