From c9a83f1447862429108ff2943bb1976b66df2b4e Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Tue, 23 Apr 2024 10:44:21 +0200 Subject: Accessing object properties recursively to allow inheritance. --- src/argaze/DataFeatures.py | 57 ++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/src/argaze/DataFeatures.py b/src/argaze/DataFeatures.py index 07f2980..1964093 100644 --- a/src/argaze/DataFeatures.py +++ b/src/argaze/DataFeatures.py @@ -100,21 +100,30 @@ def get_class_path(o: object) -> str: return m + '.' + c.__qualname__ +def get_class_properties(cls: type) -> dict: + """Get class properties dictionary. -def properties(cls) -> list: - """get class properties name.""" + Parameters: + cls: class to consider. + + Returns: + properties: dict of properties stored by names + """ + + # Stop recursion when reaching core objects + if cls is not object and cls is not PipelineStepObject and cls is not SharedObject: - properties = [name for name, item in cls.__dict__.items() if isinstance(item, property)] + object_properties = {name: item for name, item in cls.__dict__.items() if isinstance(item, property)} - for base in cls.__bases__: + for base in cls.__bases__: - for name, item in base.__dict__.items(): + base_properties = get_class_properties(base) - if isinstance(item, property): - properties.append(name) + if base_properties is not None: - return properties + object_properties.update(base_properties) + return object_properties def from_json(filepath: str) -> any: """ @@ -345,7 +354,7 @@ class TimestampedObjectsList(list): ts_objects = [] self.__object_type = ts_object_type - self.__object_properties = properties(self.__object_type) + self.__object_properties_names = list(get_class_properties(self.__object_type).keys()) for ts_object in ts_objects: self.append(ts_object) @@ -438,7 +447,7 @@ class TimestampedObjectsList(list): Timestamps are stored as index column called 'timestamp'. """ - df = pandas.DataFrame(self.tuples(), columns=self.__object_properties) + df = pandas.DataFrame(self.tuples(), columns=self.__object_properties_names) # Exclude columns df.drop(exclude, inplace=True, axis=True) @@ -857,7 +866,7 @@ class PipelineStepObject(): """Define default method to enter into pipeline step object context.""" # Start children pipeline step objects - for child in self.children: + for child in self.children(): child.__enter__() # Start observers @@ -874,7 +883,7 @@ class PipelineStepObject(): observer.__exit__(exception_type, exception_value, exception_traceback) # Stop children pipeline step objects - for child in self.children: + for child in self.children(): child.__exit__(exception_type, exception_value, exception_traceback) def update_attributes(self, object_data: dict): @@ -1002,7 +1011,7 @@ class PipelineStepObject(): for observer in self.__observers: output += f'{tabs}\t - {Fore.GREEN}{Style.BRIGHT}{observer.__class__.__module__}.{observer.__class__.__name__}{Style.RESET_ALL}\n' - for name, value in self.properties: + for name, value in self.properties(): logging.debug('%s.__str__ @property %s (%s)', get_class_path(self), name, type(value).__name__) @@ -1087,29 +1096,17 @@ class PipelineStepObject(): return tabs - @property - def properties(self) -> tuple[name, any]: - """Iterate over pipeline step properties values.""" - - properties = [name for name, item in self.__class__.__dict__.items() if isinstance(item, property)] - - for base in self.__class__.__bases__: - - if base != PipelineStepObject and base != SharedObject: + def properties(self) -> tuple[str, any]: + """Iterate over object properties values.""" - for name, item in base.__dict__.items(): - - if isinstance(item, property) and not name in properties: - properties.append(name) - - for name in properties: + for name in get_class_properties(self.__class__).keys(): + yield name, getattr(self, name) - @property def children(self): """Iterate over children pipeline step objects.""" - for name, value in self.properties: + for name, value in self.properties(): # Pipeline step object attribute if issubclass(type(value), PipelineStepObject) and value != self.parent: -- cgit v1.1