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
No related merge requests found
......@@ -66,8 +66,8 @@ class LegoComponent:
ValueError: If the type of more_properties argument is not a dictionary.
"""
self.uuid: uuid.UUID = uuid.uuid4()
self.parent: None | LegoAssembly = None
self._uuid: uuid.UUID = uuid.uuid4()
self._parent: None | LegoAssembly = None
self.layer: AggregationLayer = AggregationLayer.COMPONENT
self.properties: dict = {}
if label is not None:
......@@ -82,6 +82,14 @@ class LegoComponent:
for key, value in kwargs.items():
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:
"""Return a new instance of LegoComponent identical to the current instance.
......@@ -103,6 +111,23 @@ class LegoComponent:
clone.properties["label"] = new_label
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):
"""Return the top-level assembly in which the component belongs.
......@@ -114,11 +139,11 @@ class LegoComponent:
None | LegoAssembly: The root-level LegoAssembly or None if the component
has no parent.
"""
if self.parent is None:
if self._parent is None:
return None
current_assembly = self.parent
while current_assembly.parent is not None:
current_assembly = current_assembly.parent
current_assembly = self._parent
while current_assembly._parent is not None:
current_assembly = current_assembly._parent
return current_assembly
def to_dict(self) -> dict:
......@@ -131,7 +156,7 @@ class LegoComponent:
dict[str, Any]: A dictionary representation of the object.
"""
dict_ = {
"uuid": self.uuid,
"uuid": self._uuid,
"properties": self.properties,
"layer": self.layer,
}
......@@ -151,7 +176,7 @@ class LegoComponent:
return False
if (
self.uuid == obj.uuid
self._uuid == obj._uuid
and self.layer == obj.layer
and self.properties == obj.properties
):
......@@ -175,8 +200,8 @@ class LegoComponent:
str: A string converted from the LegoComponent instance.
"""
if self.properties.get("label") is None:
return f"LegoComponent [{self.uuid}]"
return f"LegoComponent {self.properties['label']} [{self.uuid}]"
return f"LegoComponent [{self._uuid}]"
return f"LegoComponent {self.properties['label']} [{self._uuid}]"
class LegoAssembly:
......@@ -209,10 +234,10 @@ class LegoAssembly:
properties (dict): Optional properties for the assembly, such as a label.
**kwargs: Optional keyword arguments for additional properties.
"""
self.uuid: uuid.UUID = uuid.uuid4()
self.parent: None | LegoAssembly = None
self._uuid: uuid.UUID = uuid.uuid4()
self._parent: None | LegoAssembly = None
self.properties: dict = {}
self.layer: AggregationLayer = layer
self._layer: AggregationLayer = layer
if label is not None:
self.properties["label"] = label
for prop in properties:
......@@ -222,8 +247,28 @@ class LegoAssembly:
raise ValueError(f"Unexpected argument type: {type(properties)}")
for key, value in kwargs.items():
self.properties[key] = deepcopy(value)
self.components: list[LegoComponent] = []
self.assemblies: list[LegoAssembly] = []
self._components: list[LegoComponent] = []
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:
"""
......@@ -251,14 +296,14 @@ class LegoAssembly:
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(
f"This assembly or a subassembly already contains "
f"the component with ID "
f"{component.uuid}."
f"{component._uuid}."
)
component.parent = self
self.components.append(component)
component._parent = self
self._components.append(component)
def add_assembly(self, assembly: LegoAssembly | list[LegoAssembly]) -> None:
"""
......@@ -286,13 +331,13 @@ class LegoAssembly:
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(
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
self.assemblies.append(assembly)
assembly._parent = self
self._assemblies.append(assembly)
def add(
self, part: LegoAssembly | LegoComponent | list[LegoAssembly | LegoComponent]
......@@ -332,7 +377,7 @@ class LegoAssembly:
A dictionary with two keys - "components" and "assemblies" - and
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]:
"""
......@@ -341,19 +386,36 @@ class LegoAssembly:
Args:
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:
A list of all LegoComponents contained in the current assembly or
its sub-assemblies.
"""
component_list = []
component_list.extend(self.components)
if max_depth > 0 or max_depth < 0:
for assembly in self.assemblies:
component_list.extend(self._components)
if not max_depth == 0:
for assembly in self._assemblies:
component_list.extend(assembly.get_component_list(max_depth - 1))
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:
"""
Returns the root LegoAssembly of the current assembly by recursively
......@@ -363,8 +425,8 @@ class LegoAssembly:
The root LegoAssembly of the current LegoAssembly instance.
"""
current_assembly = self
while current_assembly.parent is not None:
current_assembly = current_assembly.parent
while current_assembly._parent is not None:
current_assembly = current_assembly._parent
return current_assembly
def contains_uuid(self, uuid_: uuid.UUID):
......@@ -380,13 +442,13 @@ class LegoAssembly:
True if the UUID exists in the assembly or any of its sub-assemblies,
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:
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:
return True
for assembly in self.assemblies:
for assembly in self._assemblies:
if assembly.contains_uuid(uuid_):
return True
return False
......@@ -400,12 +462,12 @@ class LegoAssembly:
of its component and sub-assembly children.
"""
dict_ = {
"uuid": self.uuid,
"uuid": self._uuid,
"properties": self.properties,
"layer": self.layer,
"layer": self._layer,
}
dict_["components"] = [component.to_dict() for component in self.components]
dict_["assemblies"] = [assembly.to_dict() for assembly in self.assemblies]
dict_["components"] = [component.to_dict() for component in self._components]
dict_["assemblies"] = [assembly.to_dict() for assembly in self._assemblies]
return {"assembly": dict_}
def clone(self, label: Optional[str] = None) -> LegoAssembly:
......@@ -423,11 +485,11 @@ class LegoAssembly:
"""
if label is None:
label = self.properties["label"]
clone = LegoAssembly(self.layer, None, deepcopy(self.properties))
clone = LegoAssembly(self._layer, None, deepcopy(self.properties))
clone.properties["label"] = label
for component in self.components:
for component in self._components:
clone.add_component(component.clone())
for assembly in self.assemblies:
for assembly in self._assemblies:
clone.add_assembly(assembly.clone())
return clone
......@@ -446,11 +508,11 @@ class LegoAssembly:
return False
if (
self.uuid == obj.uuid
self._uuid == obj._uuid
and self.properties == obj.properties
and self.layer == obj.layer
and self.components == obj.components
and self.assemblies == obj.assemblies
and self._layer == obj._layer
and self._components == obj._components
and self._assemblies == obj._assemblies
):
return True
else:
......@@ -460,7 +522,7 @@ class LegoAssembly:
"""
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:
......@@ -486,12 +548,12 @@ def print_assembly_tree(root: LegoAssembly, levels: list[bool] = None) -> None:
assembly_padding = "├── " if levels[-1] else "└── "
print(f"{connection_padding[:-4]}{assembly_padding}{root}")
""" Recursively print child components. """
for i, assembly in enumerate(root.assemblies):
is_last = i == len(root.assemblies) - 1 and len(root.components) == 0
for i, assembly in enumerate(root._assemblies):
is_last = i == len(root._assemblies) - 1 and len(root._components) == 0
print_assembly_tree(assembly, [*levels, not is_last])
""" Print the components. """
for i, component in enumerate(root.components):
component_padding = "├── " if i < len(root.components) - 1 else "└── "
for i, component in enumerate(root._components):
component_padding = "├── " if i < len(root._components) - 1 else "└── "
print(f"{connection_padding}{component_padding}{component}")
......@@ -516,11 +578,11 @@ def correct_aggregation_hierarchy(root: LegoAssembly, strict: bool = False):
higher_level = operator.le
if strict:
higher_level = operator.lt
for component in root.components:
if not higher_level(root.layer.value, component.layer.value):
for component in root._components:
if not higher_level(root._layer.value, component.layer.value):
return False
for assembly in root.assemblies:
if not higher_level(root.layer.value, assembly.layer.value):
for assembly in root._assemblies:
if not higher_level(root._layer.value, assembly._layer.value):
return False
if not correct_aggregation_hierarchy(assembly, strict):
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