Skip to content

Instantly share code, notes, and snippets.

@NargiT
Last active July 3, 2019 07:31
Show Gist options
  • Save NargiT/de4555c59e0e9437a3c8c6c22960edc2 to your computer and use it in GitHub Desktop.
Save NargiT/de4555c59e0e9437a3c8c6c22960edc2 to your computer and use it in GitHub Desktop.
Design Pattern - Composite
import abc
from typing import Dict, Optional, Sequence
class Component(metaclass=abc.ABCMeta):
@property
@abc.abstractmethod
def name(self):
pass
@property
@abc.abstractmethod
def parent(self):
pass
@property
def path(self):
return Component._recursive_path(self.parent, self.name)
@staticmethod
def _recursive_path(parent: 'Component', right_part: str):
if parent is None:
return "/" + right_part
else:
return Component._recursive_path(parent.parent, parent.name + "/" + right_part)
class Composite(Component):
_nodes: Dict[str, Component]
_parent: 'Composite'
_name: str
def __init__(self, name: str, parent: Optional['Composite'] = None):
self._name = name
self._nodes = {}
self._parent = parent
@property
def name(self):
return self._name
@property
def parent(self):
return self._parent
def add(self, node: Component):
if self._nodes.get(node.name) is not None:
pass
else:
self._nodes[node.name] = node
node._parent = self
def find(self, name: str) -> Optional[Component]:
return self._nodes.get(name)
@property
def nodes(self) -> Sequence[Component]:
return list(self._nodes.values())
class Leaf(Component):
_name: str
_content: str
_parent: Composite
def __init__(self, name: str, content: str):
self._content = content
self._name = name
@property
def name(self):
return self._name
@property
def parent(self):
return self._parent
class Name:
_value: str
def __init__(self, path: str):
split = path.split("/")
self._value = split[split.__len__() - 1]
@property
def value(self):
return self._value
def test_tree():
folder = Composite('a')
file = Leaf('stuff', 'a file with stuff')
file1 = Leaf('stuff1', 'a file with stuff1')
folder.add(file)
folder.add(file1)
file2 = Leaf('stuff2', 'a file with stuff2')
folder2 = Composite('sub-folder', folder)
folder2.add(file2)
folder.add(folder2)
assert folder.name == 'a'
assert folder.path == '/a'
assert folder.nodes[0].name == 'stuff'
assert folder.nodes[0].path == '/a/stuff'
assert folder.nodes[1].name == 'stuff1'
assert folder.nodes[1].path == '/a/stuff1'
assert folder.nodes[2].name == 'sub-folder'
assert folder.nodes[2].path == '/a/sub-folder'
assert cast(Composite, folder.nodes[2]).nodes[0].name == 'stuff2'
assert cast(Composite, folder.nodes[2]).nodes[0].path == '/a/sub-folder/stuff2'
def test_simple():
folder = Composite('a')
assert folder.path == '/a'
def test_simple_with_file():
folder = Composite('a')
file = Leaf('b', 'stuff')
folder.add(file)
assert folder.path == '/a'
assert file.path == '/a/b'
def test_name():
name = Name('/toto/pat')
assert 'pat' == name.value
def test_simple_name():
name = Name('toto')
assert 'toto' == name.value
def test_simple_name2():
name = Name('')
assert '' == name.value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment