MCPcopy Create free account
hub / github.com/BUPT-GAMMA/MASFactory / _safe_clone

Function _safe_clone

masfactory/core/node_template.py:169–247  ·  view source on GitHub ↗

Clone a template config value. - Deep-copies built-in containers recursively (dict/list/tuple/set) so per-node configs don't share mutable containers. - For non-container objects, the default is *per-node instance* (prototype): attempt `copy.deepcopy`. If deepcopy fails, ra

(value: Any, memo: dict[int, Any] | None = None)

Source from the content-addressed store, hash-verified

167
168
169def _safe_clone(value: Any, memo: dict[int, Any] | None = None) -> Any:
170 """
171 Clone a template config value.
172
173 - Deep-copies built-in containers recursively (dict/list/tuple/set) so per-node configs don't share mutable
174 containers.
175 - For non-container objects, the default is *per-node instance* (prototype): attempt `copy.deepcopy`.
176 If deepcopy fails, raise with a clear suggestion to use `Shared(...)` or `Factory(...)` explicitly.
177 - Some objects are intended to be singletons/shared services. Such objects can opt-in
178 by setting `__node_template_scope__ = "shared"` on the instance or its class, or by being wrapped in
179 `Shared(...)`.
180
181 This makes NodeTemplate behavior predictable:
182 - Containers are always copied.
183 - Custom objects are copied (factory-like) unless explicitly marked as shared.
184 - Non-copyable objects must be explicitly scoped via Shared/Factory.
185 """
186 if memo is None:
187 memo = {}
188
189 obj_id = id(value)
190 if obj_id in memo:
191 return memo[obj_id]
192
193 if isinstance(value, _IMMUTABLE_SCALARS):
194 memo[obj_id] = value
195 return value
196
197 if isinstance(value, Shared):
198 memo[obj_id] = value.value
199 return value.value
200
201 if isinstance(value, Factory):
202 produced = value.make()
203 memo[obj_id] = produced
204 return produced
205
206 scope = getattr(value, "__node_template_scope__", None)
207 if scope is None:
208 scope = getattr(getattr(value, "__class__", object), "__node_template_scope__", None)
209 if isinstance(scope, str) and scope.lower() in {"shared", "singleton"}:
210 memo[obj_id] = value
211 return value
212
213 if isinstance(value, dict):
214 cloned: dict[Any, Any] = {}
215 memo[obj_id] = cloned
216 for k, v in value.items():
217 cloned[_safe_clone(k, memo)] = _safe_clone(v, memo)
218 return cloned
219
220 if isinstance(value, list):
221 cloned_list: list[Any] = []
222 memo[obj_id] = cloned_list
223 cloned_list.extend(_safe_clone(v, memo) for v in value)
224 return cloned_list
225
226 if isinstance(value, tuple):

Callers 4

__deepcopy__Method · 0.85
render_configMethod · 0.85
_materializeMethod · 0.85
cloneMethod · 0.85

Calls 1

addMethod · 0.45

Tested by

no test coverage detected