-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Overhaul json parsing approach #76
Comments
I have had a go at implementing this in the lhumph-experimental branch. I ended up with an Assembly def __init__(
self,
materials: Materials | dict | None = None,
geometry: Geometry | dict | None = None,
components: dict[
str, dict[str, Materials | Geometry | dict | None]
] | None = None,
):
self.identifier = self.name
self.materials = materials
self.geometry = geometry
self.components = components
@classmethod
def make_dataclasses(cls, param_dict) -> dict:
"""Recursively search the parameter dictionary for classes with
associated materials & geometry dataclasses and instantiate them within
the dictionary. For parameter dictionaries without materials or
geometry keys, these are added with the value None.
"""
# Convert material parameters for the assembly.
if "materials" not in param_dict:
param_dict["materials"] = None
elif hasattr(cls, "materials_dataclass"):
materials_dict = param_dict["materials"]
param_dict["materials"] = cls.materials_dataclass(**materials_dict)
# Convert geometry parameters for the assembly.
if "geometry" not in param_dict:
param_dict["geometry"] = None
elif hasattr(cls, "geometry_dataclass"):
geometry_dict = param_dict["geometry"]
param_dict["geometry"] = cls.geometry_dataclass(**geometry_dict)
# Recursively convert any components.
for (name, component_param_dict) in param_dict["components"].items():
classname = component_param_dict["class"]
component_subcls = get_subclass_from_classname(classname)
param_dict["components"][name] = component_subcls.make_dataclasses(
component_param_dict
)
return param_dict
@classmethod
def load_nested_jsons(cls, param_dict) -> dict:
"""Recursively search the components section of a parameter dictionary
for references to json files and load them in. Return the full nested
parameter dictionary.
Parameters
----------
param_dict : dict
The assembly's parameter dictionary to resolve.
Returns
-------
param_dict : dict
The resolved parameter dictionary.
"""
if "components" not in param_dict:
return param_dict
for (name, component_param_dict) in param_dict["components"].items():
if isinstance(component_param_dict, str):
component_param_dict = load_json(component_param_dict)
param_dict["components"][name] = cls.load_nested_jsons(
component_param_dict
)
return param_dict
@classmethod
def from_dict(cls, param_dict: dict) -> Self:
"""Instantiate an Assembly subclass by parsing a parameter dictionary.
Parameters
----------
param_dict : dict
Dictionary describing which Assembly subclass to instantiate and
the required materials, geometry, and component parameters.
Returns
-------
assembly : Assembly
An instance of the Assembly subclass described by param_dict.
"""
classname = param_dict["class"]
subcls = get_subclass_from_classname(classname)
param_dict = cls.load_nested_jsons(param_dict)
param_dict = subcls.make_dataclasses(param_dict)
materials = param_dict["materials"]
geometry = param_dict["geometry"]
components = param_dict["components"]
assembly = subcls(materials, geometry, components)
return assembly
@classmethod
def from_json(cls, json_file: str) -> Self:
"""Instantiate an Assembly subclass by parsing a json file.
Parameters
----------
json_file : str
Path to the json file describing which Assembly subclass to
instantiate and the required materials, geometry, and component
parameters.
Returns
-------
assembly : Assembly
An instance of the Assembly subclass described by param_dict.
"""
param_dict = load_json(json_file)
return cls.from_dict(param_dict) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Currently, we maintain a mapping between various classnames and the actual names of the classes they point to. For example,
"pin"
maps to the classPinAssembly
. These mappings are used in various places to determine which class to instantiate.Suggest we replace this functionality with a function which returns the subclass by its actual name (here,
PinAssembly
). This would be much easier to maintain and read, as well as improving extensibility.The function might look something like this:
Note with this change, we would then use the proper class name in the json files
"class": "PinAssembly"
instead of"class": "pin"
. This would be a breaking change, but should lead to a simplier interface in the end.Note that this should also pick up any user-defined subclasses which would also be in scope. See issue #66.
I suggest we only retain the current lower case classnames for use in the identifiers. See issue #75. (We could use the CamelCase classnames without issue, but the consideration for identifiers should be more about how assembly and component names should appear in the resulting exported files.)
The text was updated successfully, but these errors were encountered: