Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Q
quality-kpi
Manage
Activity
Members
Labels
Plan
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Stumpe, Marius
quality-kpi
Commits
6d18c70b
Commit
6d18c70b
authored
2 years ago
by
Hock, Martin
Browse files
Options
Downloads
Patches
Plain Diff
Add docstrings, and reformat docstring to black and flake8 with max-line-length of 88.
parent
06b42396
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
functions/classes.py
+261
-8
261 additions, 8 deletions
functions/classes.py
with
261 additions
and
8 deletions
functions/classes.py
+
261
−
8
View file @
6d18c70b
"""
File consists of several classes for the different elements of a device.
File consists of several classes to model elements and assembly
layers of a composed device.
"""
from
__future__
import
annotations
import
uuid
...
...
@@ -10,6 +11,10 @@ from typing import List, Dict, Optional
class
AggregationLayer
(
Enum
):
"""
Describes the levl of aggregation for the objects LegoComponent
and LegoAssembly and provides the 4 applicable layers.
"""
SYSTEM
=
auto
()
ASSEMBLY
=
auto
()
SUBASSEMBLY
=
auto
()
...
...
@@ -17,6 +22,34 @@ class AggregationLayer(Enum):
class
LegoComponent
:
"""
A class for storing information about a single Lego component.
...
Attributes
----------
uuid : UUID
A randomly generated unique identifier for the component.
parent : None | LegoAssembly
The parent of the component. Can be either None or a LegoAssembly object.
layer : AggregationLayer
An enumeration indicating the hierarchy level. For compoennts, this is
COMPONENT by default.
properties : dict
Dictionary that holds all properties of the component that can be saved
in a dictionary format.
Methods
-------
clone(new_label=None)
Returns a new instance of LegoComponent identical to the current instance.
get_root_assembly()
Returns the top-level assembly in which the component belongs.
to_dict()
Returns the current instance represented as a dictionary.
"""
def
__init__
(
self
,
label
:
Optional
[
str
]
=
None
,
...
...
@@ -24,6 +57,25 @@ class LegoComponent:
*
more_properties
:
dict
,
**
kwargs
,
)
->
None
:
"""
Constructs all the necessary attributes for the LegoComponent object.
Parameters
----------
label : str, optional
The name of the component to add.
datasheet : dict, optional
Metadata describing the component, read from datasheet.
more_properties : tuple of dict, dict
Additional dictionaries representing custom properties.
kwargs
Arbitrary keyword arguments representing custom properties.
Raises
------
ValueError
If the type of more_properties argument is not a dictionary.
"""
self
.
uuid
:
uuid
.
UUID
=
uuid
.
uuid4
()
self
.
parent
:
None
|
LegoAssembly
=
None
self
.
layer
:
AggregationLayer
=
AggregationLayer
.
COMPONENT
...
...
@@ -41,6 +93,24 @@ class LegoComponent:
self
.
properties
[
key
]
=
value
def
clone
(
self
,
new_label
:
Optional
[
str
]
=
None
)
->
LegoComponent
:
"""
Returns a new instance of LegoComponent identical to the current instance.
This method creates a new instance of LegoComponent that is identical to the
current instance with an optional different label.
The assigned uuid changes and elements are copied.
Parameters
----------
new_label : str, optional
A new label string to use. Defaults to None.
Returns
-------
LegoComponent
A new instance of LegoComponent that is identical to the current instance.
"""
if
new_label
is
None
:
new_label
=
self
.
properties
[
"
label
"
]
clone
=
LegoComponent
(
None
,
None
,
self
.
properties
)
...
...
@@ -48,6 +118,18 @@ class LegoComponent:
return
clone
def
get_root_assembly
(
self
):
"""
Returns the top-level assembly in which the component belongs.
This method traverses the parent hierarchy of a LegoComponent object until it
finds the root-level LegoAssembly, returning it to the caller. A parent is
assigned when a LegoComponent or LegoItem is added to a LegoAssembly object.
Returns
-------
None | LegoAssembly
The root-level LegoAssembly or None if the component has no parent.
"""
if
self
.
parent
is
None
:
return
None
current_assembly
=
self
.
parent
...
...
@@ -56,6 +138,17 @@ class LegoComponent:
return
current_assembly
def
to_dict
(
self
)
->
Dict
:
"""
Returns the current instance represented as a dictionary.
This method returns a dictionary representation of the LegoComponent object
suitable for serialization as JSON.
Returns
-------
dict
A dictionary representation of the object.
"""
dict_
=
{
"
uuid
"
:
self
.
uuid
,
"
properties
"
:
self
.
properties
,
...
...
@@ -64,13 +157,31 @@ class LegoComponent:
return
{
"
component
"
:
dict_
}
def
__str__
(
self
):
"""
Simple string representation of the object.
"""
return
self
.
__repr__
()
def
__repr__
(
self
):
"""
String representation of the object including the component label and UUID.
"""
return
f
"
LegoComponent
{
self
.
properties
[
'
label
'
]
}
[
{
self
.
uuid
}
]
"
class
LegoAssembly
:
"""
Represents a Lego assembly that can contain Lego Components and subassemblies.
Attributes:
uuid (uuid.UUID): The unique ID of the assembly.
parent (LegoAssembly or None): The parent assembly containing this one, if any.
properties (dict): Optional properties for the assembly, such as a label.
layer (AggregationLayer): The aggregation layer of the assembly.
components (List[LegoComponent]): The list of contained components.
assemblies (List[LegoAssembly]): The list of contained subassemblies.
"""
def
__init__
(
self
,
layer
:
AggregationLayer
,
...
...
@@ -78,6 +189,16 @@ class LegoAssembly:
*
properties
:
dict
,
**
kwargs
,
)
->
None
:
"""
Initializes a new LegoAssembly instance.
Args:
layer (AggregationLayer): The aggregation layer of the assembly.
label (Optional[str], optional): Optional label for the assembly.
Defaults to None.
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
.
properties
:
dict
=
{}
...
...
@@ -95,6 +216,20 @@ class LegoAssembly:
self
.
assemblies
:
List
[
LegoAssembly
]
=
[]
def
add_component
(
self
,
component
:
LegoComponent
|
List
[
LegoComponent
])
->
None
:
"""
Adds a Lego component to the current assembly.
Use add() to handle both components and assemblies.
Args:
component (LegoComponent or List[LegoComponent]):
The component or list of components to add.
Raises:
TypeError: If the argument is not a LegoComponent instance
or a list of LegoComponent instances.
AssertionError: If the component or a component with the same UUID
is already contained in the assembly or any of its child assemblies.
"""
if
isinstance
(
component
,
list
):
for
c
in
component
:
self
.
add_component
(
c
)
...
...
@@ -116,6 +251,20 @@ class LegoAssembly:
self
.
components
.
append
(
component
)
def
add_assembly
(
self
,
assembly
:
LegoAssembly
|
List
[
LegoAssembly
])
->
None
:
"""
Adds a subassembly to the current assembly.
Use add() to handle both components and assemblies.
Args:
assembly (LegoAssembly or List[LegoAssembly]):
The subassembly or list of subassemblies to add.
Raises:
TypeError: If the argument is not a LegoAssembly instance
or a list of LegoAssembly instances.
AssertionError: If the subassembly or a subassembly with the same UUID
is already contained in the assembly or any of its child assemblies.
"""
if
isinstance
(
assembly
,
list
):
for
a
in
assembly
:
self
.
add_assembly
(
a
)
...
...
@@ -138,6 +287,18 @@ class LegoAssembly:
def
add
(
self
,
part
:
LegoAssembly
|
LegoComponent
|
List
[
LegoAssembly
|
LegoComponent
]
)
->
None
:
"""
Adds either a Lego component, a subassembly or a (mixed) list of them to the
current assembly. Uses internal functions add_component() and add_assembly().
Args:
part (LegoAssembly or LegoComponent or List[LegoAssembly or LegoComponent]):
The part or parts to add.
Raises:
TypeError: If the argument is not a LegoAssembly instance or a LegoComponent
instance, or a (mixed) list of them.
"""
if
isinstance
(
part
,
LegoComponent
):
self
.
add_component
(
part
)
elif
isinstance
(
part
,
LegoAssembly
):
...
...
@@ -153,9 +314,29 @@ class LegoAssembly:
)
def
children
(
self
)
->
Dict
[
str
,
List
[
LegoComponent
]
|
List
[
LegoAssembly
]]:
"""
Returns a dictionary of the assembly
'
s children (components and
sub-assemblies), sorted by category.
Returns:
A dictionary with two keys -
"
components
"
and
"
assemblies
"
- and
corresponding lists of LegoComponents and LegoAssemblies as values.
"""
return
{
"
components
"
:
self
.
components
,
"
assemblies
"
:
self
.
assemblies
}
def
get_component_list
(
self
,
max_depth
:
int
=
-
1
)
->
List
[
LegoComponent
]:
"""
Gets a full list of all components contained in the assembly or any of
its sub-assemblies.
Args:
max_depth: An integer indicating the maximum depth of recursion.
-1 means unlimited depth. 0 returns only direc 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
:
...
...
@@ -164,41 +345,78 @@ class LegoAssembly:
return
component_list
def
get_root_assembly
(
self
)
->
LegoAssembly
:
"""
Returns the root LegoAssembly of the current assembly by recursively
searching up the tree until the top-most parent (the root) is found.
Returns:
The root LegoAssembly of the current LegoAssembly instance.
"""
current_assembly
=
self
while
current_assembly
.
parent
is
not
None
:
current_assembly
=
current_assembly
.
parent
return
current_assembly
def
contains_uuid
(
self
,
uuid_
:
uuid
.
UUID
):
# check component ids
"""
Recursively searches through the assembly and component
tree to determine whether the specified UUID exists anywhere
within it.
Args:
uuid_: A UUID object representing the ID to search for.
Returns:
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
))
if
uuid_
in
component_ids
:
return
True
# check assembly ids
assembly_ids
=
list
(
map
(
lambda
a
:
a
.
uuid
,
self
.
assemblies
))
if
uuid_
in
assembly_ids
:
return
True
# recursively check assemblies
for
assembly
in
self
.
assemblies
:
if
assembly
.
contains_uuid
(
uuid_
):
return
True
return
False
def
to_dict
(
self
)
->
Dict
:
"""
Serializes the current LegoAssembly instance and its descendants into a dict.
Returns:
A dictionary representation of the current assembly, including all
of its component and sub-assembly children.
"""
dict_
=
{
"
uuid
"
:
self
.
uuid
,
"
properties
"
:
self
.
properties
,
"
layer
"
:
self
.
layer
,
}
# store components
dict_
[
"
components
"
]
=
[
component
.
to_dict
()
for
component
in
self
.
components
]
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
all of its component and sub-assembly children. The assigned uuid changes.
Optionally a new label can be passed.
Args:
label: The label (name) for the cloned assembly. If none is passed,
uses the same label as the original assembly.
Returns:
The cloned LegoAssembly instance.
"""
if
label
is
None
:
label
=
self
.
properties
[
"
label
"
]
clone
=
LegoAssembly
(
self
.
layer
,
None
,
self
.
properties
)
...
...
@@ -211,12 +429,22 @@ class LegoAssembly:
def
print_assembly_tree
(
root
,
level
=
0
,
is_last
=
False
):
"""
Prints the assembly tree starting from root with a visualization
implemented with text characters.
Args:
root (LegoAssembly): The root of the assembly tree to print.
level (int): The indentation level. Defaults to 0.
is_last (bool): Determines whether the current node is the last in level.
Defaults to False.
"""
if
not
isinstance
(
root
,
LegoAssembly
):
raise
TypeError
(
f
"
Argument should be of type
{
LegoAssembly
.
__name__
}
,
"
f
"
got
{
type
(
root
).
__name__
}
instead.
"
)
# print component
"""
Print the items.
"""
assembly_padding
=
""
if
level
>
0
:
assembly_padding
+=
"
│
"
*
(
level
-
1
)
...
...
@@ -225,11 +453,11 @@ def print_assembly_tree(root, level=0, is_last=False):
else
:
assembly_padding
+=
"
├──
"
print
(
f
"
{
assembly_padding
}{
root
}
"
)
# r
ecursively print child components
"""
R
ecursively print child components
.
"""
for
i
,
assembly
in
enumerate
(
root
.
assemblies
):
is_last_
=
i
==
len
(
root
.
assemblies
)
-
1
and
len
(
root
.
components
)
==
0
print_assembly_tree
(
assembly
,
level
+
1
,
is_last_
)
# print items
"""
Print the components.
"""
for
i
,
item
in
enumerate
(
root
.
components
):
component_padding
=
"
│
"
*
level
if
not
is_last
else
"
"
component_padding
+=
"
├──
"
if
i
<
len
(
root
.
components
)
-
1
else
"
└──
"
...
...
@@ -237,6 +465,18 @@ def print_assembly_tree(root, level=0, is_last=False):
def
correct_aggregation_hierarchy
(
root
:
LegoAssembly
,
strict
:
bool
=
False
):
"""
Recursively checks whether the aggregation hierarchy from `root` is correct.
Args:
root (LegoAssembly): The root of the assembly tree.
strict (bool): If True, the function will return False if any assembly
or component with a layer level equal to root
'
s is found.
Defaults to False.
Returns:
True if the aggregation hierarchy is correct. False otherwise.
"""
if
not
isinstance
(
root
,
LegoAssembly
):
raise
TypeError
(
f
"
Argument should be of type
{
LegoAssembly
.
__name__
}
,
"
...
...
@@ -257,7 +497,20 @@ def correct_aggregation_hierarchy(root: LegoAssembly, strict: bool = False):
class
KPIEncoder
(
json
.
JSONEncoder
):
"""
JSON encoder that handles special class types for KPI serialization.
"""
def
default
(
self
,
o
):
"""
Overrides default method to handle special conversion cases.
Args:
o : Object to be converted.
Returns:
Converted object or super method if no applicable case is found.
"""
if
isinstance
(
o
,
uuid
.
UUID
):
return
"
kpi-
"
+
str
(
o
)
if
isinstance
(
o
,
(
AggregationLayer
)):
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment