-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbase_data_components.py
More file actions
145 lines (114 loc) · 4.61 KB
/
base_data_components.py
File metadata and controls
145 lines (114 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
from abc import ABC, abstractmethod
# --- Component ---
class DataComponent(ABC):
"""
DataComponent is an abstract base class that serves as the
foundation for all metadata components.
It enforces the implementation of a `get_data` method in
derived classes and provides default
implementations for `add` and `remove` methods,
which raise `NotImplementedError` to indicate
that the component does not support child components.
Methods:
get_data() -> dict:
Abstract method that must be implemented by subclasses to
return the data associated with the component as a dictionary.
add(component: "DataComponent"):
Raises NotImplementedError. Intended to be overridden
by subclasses that support adding child components.
remove(component: "DataComponent"):
Raises NotImplementedError. Intended to be overridden by subclasses that
support removing child components.
"""
@abstractmethod
def get_data(self) -> dict:
pass
def add(self, component: "DataComponent"):
raise NotImplementedError("This component doesn't support children.")
def remove(self, component: "DataComponent"):
raise NotImplementedError("This component doesn't support children.")
# --- Composite ---
class CompositeData(DataComponent):
"""
CompositeData is a class that represents a composite metadata component,
which can hold and manage other DataComponent instances as its children.
Attributes:
name (str): The name of the composite data component.
Defaults to an empty string. children (list[DataComponent]):
A list of child DataComponent instances contained within this composite.
Methods:
add(component: DataComponent):
Adds a child DataComponent to the composite.
remove(component: DataComponent):
Removes a child DataComponent from the composite.
get_data() -> dict:
Aggregates and returns the data from all child components as a dictionary.
If the composite has a name,
the result is nested under the composite's name.
"""
def __init__(self, name: str = ""):
self.name = name
self.children: list[DataComponent] = []
def add(self, component: DataComponent):
"""
Adds a DataComponent to the list of children.
Args:
component (DataComponent):
The data component to be added to the children list.
"""
self.children.append(component)
def remove(self, component: DataComponent):
"""
Removes a specified DataComponent from the list of children.
Args:
component (DataComponent):
The data component to be removed from the children list.
Raises:
ValueError: If the specified component is not found in the children list.
"""
self.children.remove(component)
def get_data(self) -> dict:
"""
Retrieves the data from the current object and
its children in a hierarchical structure.
Returns:
dict: A dictionary containing the data from
the current object and its children.
If the current object has a name,
the data is nested under the name as the key.
Otherwise, the data is returned as a flat dictionary.
"""
result = {}
for child in self.children:
result.update(child.get_data())
return {self.name: result} if self.name else result
# --- Example Usage for a FIT file ---
if __name__ == "__main__":
# Example Data Component
class ExampleData(DataComponent):
"""
Represents a leaf metadata component (key-value pair or similar).
The leaf methods should be the low level fields of the different
files.
"""
def __init__(self, key: str, value: str):
self.key = key
self.value = value
def get_metadata(self) -> dict:
return {self.key: self.value}
# Example usage
# Build metadata structure
fit_metadata = CompositeData("fit_file")
# Header Section
header = CompositeData("header")
header.add(ExampleData("file_type", "FIT"))
header.add(ExampleData("version", "2.0"))
# Body Section
body = CompositeData("body")
# add the training data
body.add(ExampleData("duration", "45 min"))
body.add(ExampleData("distance", "10 km"))
# Add sections to root
fit_metadata.add(header)
fit_metadata.add(body)
print(fit_metadata.get_metadata())