from typing import Set, Union, List, Optional from collections import UserList class Element: def __init__(self, label: str = "text", content: Union[str, int] = ""): self.label: str = label self.content: Union[str, int] = content @property def label(self) -> str: """Return the element level. """ return self._label @label.setter def label(self, label: str) -> None: approved_label: Set[str] = {"text", "space", "image"} if label not in approved_label: raise ValueError(f"{label} is not a valid type: it must be among {approved_label}.") self._label = label @property def content(self) -> Union[str, int]: """Content """ return self._content @content.setter def content(self, content: Union[str, int]) -> None: """Set content. """ self._content = content def __str__(self) -> str: output: List[str] = [f"\nElement label: {self._label}\nElement content: {self._content}\n"] return "".join(output) class Item(UserList): def __init__(self, element: Optional[Element] = None, level: int = 0): super().__init__() self.level: int = level if element: self.data.append(element) @property def level(self) -> int: """Nesting level is relative to the previous item: 0 same level as previous one 1 less nested then previous one -1 more nested then previous one """ return self._level @level.setter def level(self, level_set: int) -> None: """Level is set to: 0, 1 or -1. """ if type(level_set) != int: raise ValueError(f"{level_set} is not a valid level: it must be an integer.") self._level = 1 if level_set > 0 else 0 self._level = -1 if level_set < 0 else self._level def __str__(self) -> str: """Print """ output: List[str] = [f"\nItem level: {self.level}"] output += [elem.__str__() for elem in self.data] return "".join(output) class Nesteditems(UserList): def __init__(self, title: str = ""): super().__init__() self.title: str = title self.data: List[Item] = [] @property def title(self) -> str: """Return the instance title. """ return self._title @title.setter def title(self, title: str) -> None: """Set the instance title. """ self._title = title def append(self, item: Item) -> None: """Overload UserList append method. """ if type(item) is not Item: raise ValueError(f"{item} is not a list") super().append(item) def __str__(self) -> str: """Print Nesteditem """ output: List[str] = [f"\nNesteditem title: {self.title}"] output += [items.__str__() for items in self.data] return "".join(output) if __name__ == "__main__": # Element e1 = Element("text", "Welcome to my house") e2 = Element("space", 10) print("e1: ", e1) print("e2: ", e2) # Item i = Item(e1) i.append(Element("image", "This is my picture")) print("i: ", i) ni = Nesteditems("my nested") print("ni: ", ni) i.append(e2) ni.append(i) print("ni :", ni)