from abc import ( ABCMeta, abstractmethod ) from typing import ( Iterable, Optional, ) class ModifiableObject(metaclass=ABCMeta): """ Modifiable objects track their modification status. including the modification status of potential contained objects. If one of the contained objects is modified, the containing object is considered modified as well. Objects determine their modification-relevant sub-objects by implementing their version of the method "get_modifiable_sub_objects". """ def __init__(self, saved_on: Optional[str] = None): self.saved_on = set() if saved_on: self.saved_on.add(saved_on) def touch(self): self.set_unsaved() def set_saved_on(self, destination: str): self.saved_on.add(destination) def set_unsaved(self): self.saved_on = set() def is_saved_on(self, destination: str) -> bool: """ Check whether the object is saved on the given destination. This check includes whether all modifiable sub-objects are saved on the given destination. """ if destination not in self.saved_on: return False return all( map( lambda element: element.is_saved_on(destination), self.modifiable_sub_objects)) @abstractmethod def modifiable_sub_objects(self) -> Iterable["ModifiableObject"]: raise NotImplementedError