in chz/data_model.py [0:0]
def beta_to_blueprint_values(obj) -> Any:
"""Return a dict which can be used to recreate the same object via blueprint.
Example:
```
@chz.chz
class Foo:
a: int
b: str
foo = Foo(a=1, b="hello")
assert chz.Blueprint(Foo).apply(chz.beta_to_blueprint_values(foo)).make() == foo
```
See also: asdict
"""
blueprint_values = {}
def join_arg_path(parent: str, child: str) -> str:
if not parent:
return child
if child.startswith("."):
return parent + child
return parent + "." + child
def inner(obj: Any, path: str):
if hasattr(obj, "__chz_fields__"):
for field_name, field_info in obj.__chz_fields__.items():
value = getattr(obj, field_info.x_name)
param_path = join_arg_path(path, field_name)
if field_info.meta_factory is not None and (
type(value)
is not typing.get_origin(field_info.meta_factory.unspecified_factory())
):
# Try to detect when we have used polymorphic construction
blueprint_values[param_path] = type(value)
inner(value, param_path)
elif (
isinstance(obj, dict)
and all(isinstance(k, str) for k in obj.keys())
and any(is_chz(v) for v in obj.values())
):
for k, v in obj.items():
param_path = join_arg_path(path, k)
blueprint_values[param_path] = type(v) # may be overridden if not needed
inner(v, param_path)
elif isinstance(obj, (list, tuple)) and any(is_chz(v) for v in obj):
for i, v in enumerate(obj):
param_path = join_arg_path(path, str(i))
blueprint_values[param_path] = type(v) # may be overridden if not needed
inner(v, param_path)
else:
blueprint_values[path] = obj
inner(obj, "")
return blueprint_values