From 8f295e1130b1ff7310f9425e17efae5fd0ef7639 Mon Sep 17 00:00:00 2001
From: Sascha Lamm <sascha.lamm@tu-darmstadt.de>
Date: Fri, 6 Sep 2024 08:27:15 +0200
Subject: [PATCH] Added comparison methods to LegoComponent and LegoAssembly.
 Small updates to docstrings in modul level functions

---
 .gitignore           |  1 +
 functions/classes.py | 81 ++++++++++++++++++++++++++++++++++----------
 2 files changed, 65 insertions(+), 17 deletions(-)
 create mode 100644 .gitignore

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ba0430d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+__pycache__/
\ No newline at end of file
diff --git a/functions/classes.py b/functions/classes.py
index cffbabb..7265d93 100644
--- a/functions/classes.py
+++ b/functions/classes.py
@@ -137,15 +137,27 @@ class LegoComponent:
         }
         return {"component": dict_}
 
-    def __str__(self):
-        """Handle the conversion of LegoComponent objects to str objects.
+    def __eq__(self, obj: object):
+        """Check if provided object is equal to this component.
+
+        Args:
+            obj (object): Object to compare to.
 
         Returns:
-            str: A string converted from the LegoComponent instance.
+            bool: True if UUID, properties, and layer match. False otherwise.
         """
-        if self.properties.get("label") is None:
-            return f"LegoComponent [{self.uuid}]"
-        return f"LegoComponent {self.properties['label']} [{self.uuid}]"
+        # in case of mismatching class
+        if not isinstance(obj, LegoComponent):
+            return False
+
+        if (
+            self.uuid == obj.uuid
+            and self.layer == obj.layer
+            and self.properties == obj.properties
+        ):
+            return True
+        else:
+            return False
 
     def __repr__(self):
         """Create a machine-readable representation of the instance.
@@ -153,9 +165,19 @@ class LegoComponent:
         Returns:
             str: A string representing the LegoComponent instance.
         """
-        
+
         return f"LegoComponent({self.properties if self.properties else ""})"
 
+    def __str__(self):
+        """Handle the conversion of LegoComponent objects to str objects.
+
+        Returns:
+            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}]"
+
 
 class LegoAssembly:
     """
@@ -386,12 +408,6 @@ class LegoAssembly:
         dict_["assemblies"] = [assembly.to_dict() for assembly in self.assemblies]
         return {"assembly": dict_}
 
-    def __repr__(self):
-        """
-        String representation of the object including the component label and UUID.
-        """
-        return f"LegoAssembly {self.properties['label']} [{self.uuid}]"
-
     def clone(self, label: Optional[str] = None) -> LegoAssembly:
         """
         Creates a deep clone of the current LegoAssembly instance, including
@@ -415,8 +431,39 @@ class LegoAssembly:
             clone.add_assembly(assembly.clone())
         return clone
 
+    def __eq__(self, obj: object) -> bool:
+        """Check if provided object is equal to this assembly.
+
+        Args:
+            obj (object): Object to compare to.
+
+        Returns:
+            bool: True if UUID, properties, layer, components and assemblies match.
+                False otherwise.
+        """
+        # in case of mismatching class
+        if not isinstance(obj, LegoAssembly):
+            return False
+
+        if (
+            self.uuid == obj.uuid
+            and self.properties == obj.properties
+            and self.layer == obj.layer
+            and self.components == obj.components
+            and self.assemblies == obj.assemblies
+        ):
+            return True
+        else:
+            return False
+
+    def __repr__(self):
+        """
+        String representation of the object including the component label and UUID.
+        """
+        return f"LegoAssembly {self.properties['label']} [{self.uuid}]"
+
 
-def print_assembly_tree(root, levels=None):
+def print_assembly_tree(root: LegoAssembly, levels: list[bool] = None) -> None:
     """
     Prints the assembly tree starting from root with a visualization
     implemented with text characters.
@@ -424,7 +471,7 @@ def print_assembly_tree(root, levels=None):
     Args:
         root (LegoAssembly): The root of the assembly tree to print.
         levels (list[bool]): Internally used by recursion to know where
-            to print vertical connection. Defaults to an empty list.
+            to print vertical connection. Defaults to None.
     """
     if not isinstance(root, LegoAssembly):
         raise TypeError(
@@ -485,12 +532,12 @@ class KPIEncoder(json.JSONEncoder):
     JSON encoder that handles special class types for KPI serialization.
     """
 
-    def default(self, o):
+    def default(self, o: Any):
         """
         Overrides default method to handle special conversion cases.
 
         Args:
-            o : Object to be converted.
+            o (Any): Object to be converted.
 
         Returns:
             Converted object or super method if no applicable case is found.
-- 
GitLab