Source code for cosapp.utils.swap_system

# Copyright (C) 2023 twiinIT - All Rights Reserved
# Licensed under the Apache License, Version 2.0

import copy
import logging
from cosapp.utils.helpers import check_arg

logger = logging.getLogger(__name__)


[docs] def swap_system(old_system: "System", new_system: "System", init_values=True): """Replace `old_system` by `new_system`. Parameters ---------- - old_system [System]: System to replace - new_system [System]: Replacement system - init_values [bool, optional]: If `True` (default), original system values are copied into the replacement system. Returns ------- old_system [System]: the original system, devoid of parent. """ from cosapp.base import System from cosapp.ports.port import BasePort check_arg(old_system, "old_system", System) check_arg(new_system, "new_system", System) if new_system.parent is not None: raise ValueError( f"System {new_system.full_name()!r} already belongs to a system tree." ) if old_system.parent is None: raise ValueError( f"Cannot replace top system {old_system.full_name()!r}." ) if new_system.name != old_system.name: logger.info( f"New system {new_system.name!r} renamed into {old_system.name!r} inside {old_system.parent.full_name()!r}" ) new_system.parent = parent = old_system.parent new_system.name = system_name = old_system.name # connections list to_restore = list( filter( lambda c: (c.source.owner is old_system) or (c.sink.owner is old_system), parent.all_connectors(), ) ) # update child in parent execution_idx = list(parent.exec_order).index(system_name) parent.pop_child(system_name) parent.add_child(new_system, execution_index=execution_idx) # restore connections for connector in to_restore: sink = connector.sink source = connector.source if sink.owner is old_system: connector.sink = new_system[sink.name] if source.owner is old_system: connector.source = new_system[source.name] parent.connect(connector.sink, connector.source, connector.mapping) # init values if init_values: not_copied = set() for name, old_variable in old_system.name2variable.items(): if not isinstance(old_variable.mapping, BasePort): continue try: new_variable = new_system.name2variable[name] except KeyError: not_copied.add(old_variable.contextual_name) continue try: new_variable.value = copy.deepcopy(old_variable.value) except: not_copied.add(old_variable.contextual_name) if not_copied: logger.warning( f"Could not copy {sorted(not_copied)} into {new_system.full_name()!r}" ) return old_system