Skip to content
Snippets Groups Projects
Commit 9a8a9f5d authored by Lamm, Sascha's avatar Lamm, Sascha :cow2:
Browse files

Added getters for some important attributes of LegoComponent and LegoAssembly...

Added getters for some important attributes of LegoComponent and LegoAssembly classes. Added a get_property that also allows getting uuid and aggregation layer
parent 8f295e11
No related branches found
No related tags found
1 merge request!8Unifying PraDDa and GdD Code Style
...@@ -66,8 +66,8 @@ class LegoComponent: ...@@ -66,8 +66,8 @@ class LegoComponent:
ValueError: If the type of more_properties argument is not a dictionary. ValueError: If the type of more_properties argument is not a dictionary.
""" """
self.uuid: uuid.UUID = uuid.uuid4() self._uuid: uuid.UUID = uuid.uuid4()
self.parent: None | LegoAssembly = None self._parent: None | LegoAssembly = None
self.layer: AggregationLayer = AggregationLayer.COMPONENT self.layer: AggregationLayer = AggregationLayer.COMPONENT
self.properties: dict = {} self.properties: dict = {}
if label is not None: if label is not None:
...@@ -82,6 +82,14 @@ class LegoComponent: ...@@ -82,6 +82,14 @@ class LegoComponent:
for key, value in kwargs.items(): for key, value in kwargs.items():
self.properties[key] = deepcopy(value) self.properties[key] = deepcopy(value)
@property
def uuid(self) -> uuid.UUID:
return self._uuid
@property
def parent(self) -> None | LegoAssembly:
return self._parent
def clone(self, new_label: Optional[str] = None) -> LegoComponent: def clone(self, new_label: Optional[str] = None) -> LegoComponent:
"""Return a new instance of LegoComponent identical to the current instance. """Return a new instance of LegoComponent identical to the current instance.
...@@ -103,6 +111,23 @@ class LegoComponent: ...@@ -103,6 +111,23 @@ class LegoComponent:
clone.properties["label"] = new_label clone.properties["label"] = new_label
return clone return clone
def get_property(self, key: str, default: Any = None) -> Any:
"""Get a property from the component.
Args:
key (str): Property name.
default (Any, optional): What to return if key is not available in
properties. Defaults to None.
Returns:
Any: Property value.
"""
if key == "uuid":
return self._uuid
if key == "layer":
return self._layer
return self.properties.get(key, default=default)
def get_root_assembly(self): def get_root_assembly(self):
"""Return the top-level assembly in which the component belongs. """Return the top-level assembly in which the component belongs.
...@@ -114,11 +139,11 @@ class LegoComponent: ...@@ -114,11 +139,11 @@ class LegoComponent:
None | LegoAssembly: The root-level LegoAssembly or None if the component None | LegoAssembly: The root-level LegoAssembly or None if the component
has no parent. has no parent.
""" """
if self.parent is None: if self._parent is None:
return None return None
current_assembly = self.parent current_assembly = self._parent
while current_assembly.parent is not None: while current_assembly._parent is not None:
current_assembly = current_assembly.parent current_assembly = current_assembly._parent
return current_assembly return current_assembly
def to_dict(self) -> dict: def to_dict(self) -> dict:
...@@ -131,7 +156,7 @@ class LegoComponent: ...@@ -131,7 +156,7 @@ class LegoComponent:
dict[str, Any]: A dictionary representation of the object. dict[str, Any]: A dictionary representation of the object.
""" """
dict_ = { dict_ = {
"uuid": self.uuid, "uuid": self._uuid,
"properties": self.properties, "properties": self.properties,
"layer": self.layer, "layer": self.layer,
} }
...@@ -151,7 +176,7 @@ class LegoComponent: ...@@ -151,7 +176,7 @@ class LegoComponent:
return False return False
if ( if (
self.uuid == obj.uuid self._uuid == obj._uuid
and self.layer == obj.layer and self.layer == obj.layer
and self.properties == obj.properties and self.properties == obj.properties
): ):
...@@ -175,8 +200,8 @@ class LegoComponent: ...@@ -175,8 +200,8 @@ class LegoComponent:
str: A string converted from the LegoComponent instance. str: A string converted from the LegoComponent instance.
""" """
if self.properties.get("label") is None: if self.properties.get("label") is None:
return f"LegoComponent [{self.uuid}]" return f"LegoComponent [{self._uuid}]"
return f"LegoComponent {self.properties['label']} [{self.uuid}]" return f"LegoComponent {self.properties['label']} [{self._uuid}]"
class LegoAssembly: class LegoAssembly:
...@@ -209,10 +234,10 @@ class LegoAssembly: ...@@ -209,10 +234,10 @@ class LegoAssembly:
properties (dict): Optional properties for the assembly, such as a label. properties (dict): Optional properties for the assembly, such as a label.
**kwargs: Optional keyword arguments for additional properties. **kwargs: Optional keyword arguments for additional properties.
""" """
self.uuid: uuid.UUID = uuid.uuid4() self._uuid: uuid.UUID = uuid.uuid4()
self.parent: None | LegoAssembly = None self._parent: None | LegoAssembly = None
self.properties: dict = {} self.properties: dict = {}
self.layer: AggregationLayer = layer self._layer: AggregationLayer = layer
if label is not None: if label is not None:
self.properties["label"] = label self.properties["label"] = label
for prop in properties: for prop in properties:
...@@ -222,8 +247,28 @@ class LegoAssembly: ...@@ -222,8 +247,28 @@ class LegoAssembly:
raise ValueError(f"Unexpected argument type: {type(properties)}") raise ValueError(f"Unexpected argument type: {type(properties)}")
for key, value in kwargs.items(): for key, value in kwargs.items():
self.properties[key] = deepcopy(value) self.properties[key] = deepcopy(value)
self.components: list[LegoComponent] = [] self._components: list[LegoComponent] = []
self.assemblies: list[LegoAssembly] = [] self._assemblies: list[LegoAssembly] = []
@property
def uuid(self) -> uuid.UUID:
return self._uuid
@property
def parent(self) -> None | LegoAssembly:
return self._parent
@property
def layer(self) -> AggregationLayer:
return self._layer
@property
def components(self) -> list[LegoComponent]:
return self._components
@property
def assemblies(self) -> list[LegoAssembly]:
return self._assemblies
def add_component(self, component: LegoComponent | list[LegoComponent]) -> None: def add_component(self, component: LegoComponent | list[LegoComponent]) -> None:
""" """
...@@ -251,14 +296,14 @@ class LegoAssembly: ...@@ -251,14 +296,14 @@ class LegoAssembly:
f"got {type(component).__name__} instead." f"got {type(component).__name__} instead."
) )
if self.get_root_assembly().contains_uuid(component.uuid): if self.get_root_assembly().contains_uuid(component._uuid):
raise AssertionError( raise AssertionError(
f"This assembly or a subassembly already contains " f"This assembly or a subassembly already contains "
f"the component with ID " f"the component with ID "
f"{component.uuid}." f"{component._uuid}."
) )
component.parent = self component._parent = self
self.components.append(component) self._components.append(component)
def add_assembly(self, assembly: LegoAssembly | list[LegoAssembly]) -> None: def add_assembly(self, assembly: LegoAssembly | list[LegoAssembly]) -> None:
""" """
...@@ -286,13 +331,13 @@ class LegoAssembly: ...@@ -286,13 +331,13 @@ class LegoAssembly:
f"got {type(assembly).__name__} instead." f"got {type(assembly).__name__} instead."
) )
if self.get_root_assembly().contains_uuid(assembly.uuid): if self.get_root_assembly().contains_uuid(assembly._uuid):
raise AssertionError( raise AssertionError(
f"This assembly or a subassembly already contains " f"This assembly or a subassembly already contains "
f"the assembly with ID {assembly.uuid}." f"the assembly with ID {assembly._uuid}."
) )
assembly.parent = self assembly._parent = self
self.assemblies.append(assembly) self._assemblies.append(assembly)
def add( def add(
self, part: LegoAssembly | LegoComponent | list[LegoAssembly | LegoComponent] self, part: LegoAssembly | LegoComponent | list[LegoAssembly | LegoComponent]
...@@ -332,7 +377,7 @@ class LegoAssembly: ...@@ -332,7 +377,7 @@ class LegoAssembly:
A dictionary with two keys - "components" and "assemblies" - and A dictionary with two keys - "components" and "assemblies" - and
corresponding lists of LegoComponents and LegoAssemblies as values. corresponding lists of LegoComponents and LegoAssemblies as values.
""" """
return {"components": self.components, "assemblies": self.assemblies} return {"components": self._components, "assemblies": self._assemblies}
def get_component_list(self, max_depth: int = -1) -> list[LegoComponent]: def get_component_list(self, max_depth: int = -1) -> list[LegoComponent]:
""" """
...@@ -341,19 +386,36 @@ class LegoAssembly: ...@@ -341,19 +386,36 @@ class LegoAssembly:
Args: Args:
max_depth: An integer indicating the maximum depth of recursion. max_depth: An integer indicating the maximum depth of recursion.
-1 means unlimited depth. 0 returns only direc children. -1 means unlimited depth. 0 returns only direct children.
Returns: Returns:
A list of all LegoComponents contained in the current assembly or A list of all LegoComponents contained in the current assembly or
its sub-assemblies. its sub-assemblies.
""" """
component_list = [] component_list = []
component_list.extend(self.components) component_list.extend(self._components)
if max_depth > 0 or max_depth < 0: if not max_depth == 0:
for assembly in self.assemblies: for assembly in self._assemblies:
component_list.extend(assembly.get_component_list(max_depth - 1)) component_list.extend(assembly.get_component_list(max_depth - 1))
return component_list return component_list
def get_property(self, key: str, default: Any = None) -> Any:
"""Get a property from the assembly.
Args:
key (str): Property name.
default (Any, optional): What to return if key is not available in
properties. Defaults to None.
Returns:
Any: Property value.
"""
if key == "uuid":
return self._uuid
if key == "layer":
return self._layer
return self.properties.get(key, default=default)
def get_root_assembly(self) -> LegoAssembly: def get_root_assembly(self) -> LegoAssembly:
""" """
Returns the root LegoAssembly of the current assembly by recursively Returns the root LegoAssembly of the current assembly by recursively
...@@ -363,8 +425,8 @@ class LegoAssembly: ...@@ -363,8 +425,8 @@ class LegoAssembly:
The root LegoAssembly of the current LegoAssembly instance. The root LegoAssembly of the current LegoAssembly instance.
""" """
current_assembly = self current_assembly = self
while current_assembly.parent is not None: while current_assembly._parent is not None:
current_assembly = current_assembly.parent current_assembly = current_assembly._parent
return current_assembly return current_assembly
def contains_uuid(self, uuid_: uuid.UUID): def contains_uuid(self, uuid_: uuid.UUID):
...@@ -380,13 +442,13 @@ class LegoAssembly: ...@@ -380,13 +442,13 @@ class LegoAssembly:
True if the UUID exists in the assembly or any of its sub-assemblies, True if the UUID exists in the assembly or any of its sub-assemblies,
False otherwise. False otherwise.
""" """
component_ids = list(map(lambda c: c.uuid, self.components)) component_ids = list(map(lambda c: c._uuid, self._components))
if uuid_ in component_ids: if uuid_ in component_ids:
return True return True
assembly_ids = list(map(lambda a: a.uuid, self.assemblies)) assembly_ids = list(map(lambda a: a._uuid, self._assemblies))
if uuid_ in assembly_ids: if uuid_ in assembly_ids:
return True return True
for assembly in self.assemblies: for assembly in self._assemblies:
if assembly.contains_uuid(uuid_): if assembly.contains_uuid(uuid_):
return True return True
return False return False
...@@ -400,12 +462,12 @@ class LegoAssembly: ...@@ -400,12 +462,12 @@ class LegoAssembly:
of its component and sub-assembly children. of its component and sub-assembly children.
""" """
dict_ = { dict_ = {
"uuid": self.uuid, "uuid": self._uuid,
"properties": self.properties, "properties": self.properties,
"layer": self.layer, "layer": self._layer,
} }
dict_["components"] = [component.to_dict() for component in self.components] dict_["components"] = [component.to_dict() for component in self._components]
dict_["assemblies"] = [assembly.to_dict() for assembly in self.assemblies] dict_["assemblies"] = [assembly.to_dict() for assembly in self._assemblies]
return {"assembly": dict_} return {"assembly": dict_}
def clone(self, label: Optional[str] = None) -> LegoAssembly: def clone(self, label: Optional[str] = None) -> LegoAssembly:
...@@ -423,11 +485,11 @@ class LegoAssembly: ...@@ -423,11 +485,11 @@ class LegoAssembly:
""" """
if label is None: if label is None:
label = self.properties["label"] label = self.properties["label"]
clone = LegoAssembly(self.layer, None, deepcopy(self.properties)) clone = LegoAssembly(self._layer, None, deepcopy(self.properties))
clone.properties["label"] = label clone.properties["label"] = label
for component in self.components: for component in self._components:
clone.add_component(component.clone()) clone.add_component(component.clone())
for assembly in self.assemblies: for assembly in self._assemblies:
clone.add_assembly(assembly.clone()) clone.add_assembly(assembly.clone())
return clone return clone
...@@ -446,11 +508,11 @@ class LegoAssembly: ...@@ -446,11 +508,11 @@ class LegoAssembly:
return False return False
if ( if (
self.uuid == obj.uuid self._uuid == obj._uuid
and self.properties == obj.properties and self.properties == obj.properties
and self.layer == obj.layer and self._layer == obj._layer
and self.components == obj.components and self._components == obj._components
and self.assemblies == obj.assemblies and self._assemblies == obj._assemblies
): ):
return True return True
else: else:
...@@ -460,7 +522,7 @@ class LegoAssembly: ...@@ -460,7 +522,7 @@ class LegoAssembly:
""" """
String representation of the object including the component label and UUID. String representation of the object including the component label and UUID.
""" """
return f"LegoAssembly {self.properties['label']} [{self.uuid}]" return f"LegoAssembly {self.properties['label']} [{self._uuid}]"
def print_assembly_tree(root: LegoAssembly, levels: list[bool] = None) -> None: def print_assembly_tree(root: LegoAssembly, levels: list[bool] = None) -> None:
...@@ -486,12 +548,12 @@ def print_assembly_tree(root: LegoAssembly, levels: list[bool] = None) -> None: ...@@ -486,12 +548,12 @@ def print_assembly_tree(root: LegoAssembly, levels: list[bool] = None) -> None:
assembly_padding = "├── " if levels[-1] else "└── " assembly_padding = "├── " if levels[-1] else "└── "
print(f"{connection_padding[:-4]}{assembly_padding}{root}") print(f"{connection_padding[:-4]}{assembly_padding}{root}")
""" Recursively print child components. """ """ Recursively print child components. """
for i, assembly in enumerate(root.assemblies): for i, assembly in enumerate(root._assemblies):
is_last = i == len(root.assemblies) - 1 and len(root.components) == 0 is_last = i == len(root._assemblies) - 1 and len(root._components) == 0
print_assembly_tree(assembly, [*levels, not is_last]) print_assembly_tree(assembly, [*levels, not is_last])
""" Print the components. """ """ Print the components. """
for i, component in enumerate(root.components): for i, component in enumerate(root._components):
component_padding = "├── " if i < len(root.components) - 1 else "└── " component_padding = "├── " if i < len(root._components) - 1 else "└── "
print(f"{connection_padding}{component_padding}{component}") print(f"{connection_padding}{component_padding}{component}")
...@@ -516,11 +578,11 @@ def correct_aggregation_hierarchy(root: LegoAssembly, strict: bool = False): ...@@ -516,11 +578,11 @@ def correct_aggregation_hierarchy(root: LegoAssembly, strict: bool = False):
higher_level = operator.le higher_level = operator.le
if strict: if strict:
higher_level = operator.lt higher_level = operator.lt
for component in root.components: for component in root._components:
if not higher_level(root.layer.value, component.layer.value): if not higher_level(root._layer.value, component.layer.value):
return False return False
for assembly in root.assemblies: for assembly in root._assemblies:
if not higher_level(root.layer.value, assembly.layer.value): if not higher_level(root._layer.value, assembly._layer.value):
return False return False
if not correct_aggregation_hierarchy(assembly, strict): if not correct_aggregation_hierarchy(assembly, strict):
return False return False
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment