__init__.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import datetime
  2. import typing
  3. class Person:
  4. def __init__(self, identifier: str):
  5. self.identifier: str = identifier
  6. self.name: typing.Optional[str] = None
  7. self.birth_date: typing.Optional[datetime.date] = None
  8. self.mother: typing.Optional["Person"] = None
  9. self.father: typing.Optional["Person"] = None
  10. def __repr__(self) -> str:
  11. """
  12. >>> p = Person("max-mustermann")
  13. >>> repr(p)
  14. 'Person(max-mustermann)'
  15. >>> p.name = "Hr. Mustermann"
  16. >>> repr(p)
  17. 'Person(max-mustermann, Hr. Mustermann)'
  18. >>> p.name = "Max Mustermann"
  19. >>> repr(p)
  20. 'Person(max-mustermann, Max Mustermann)'
  21. >>> p.birth_date = datetime.date(1976, 2, 1)
  22. >>> repr(p)
  23. 'Person(max-mustermann, Max Mustermann, *1976-02-01)'
  24. """
  25. return "{}({})".format(
  26. type(self).__name__,
  27. ", ".join(
  28. filter(
  29. None,
  30. (
  31. self.identifier,
  32. self.name,
  33. "*" + self.birth_date.isoformat()
  34. if self.birth_date is not None
  35. else None,
  36. ),
  37. )
  38. ),
  39. )
  40. def __str__(self) -> str:
  41. """
  42. >>> p = Person("max-mustermann")
  43. >>> p.name = "Max Mustermann"
  44. >>> str(p)
  45. 'Max Mustermann'
  46. >>> p.birth_date = datetime.date(1976, 2, 1)
  47. >>> str(p)
  48. 'Max Mustermann (*1976-02-01)'
  49. """
  50. return (self.name or "unnamed") + (
  51. " (*{})".format(self.birth_date.isoformat()) if self.birth_date else ""
  52. )
  53. def __eq__(self, other: "Person") -> bool:
  54. """
  55. >>> maxl = Person("max")
  56. >>> maxl.name = "Max Mustermann"
  57. >>> maxl == Person("max")
  58. True
  59. >>> erika = Person("erika")
  60. >>> erika.name = "Max Mustermann"
  61. >>> maxl == erika
  62. False
  63. """
  64. return self.identifier == other.identifier
  65. def merge(self, person: "Person") -> None:
  66. """
  67. >>> p1 = Person("max")
  68. >>> p1.name = "Max Mustermann"
  69. >>> str(p1)
  70. 'Max Mustermann'
  71. >>> p2 = Person("max2")
  72. >>> p2.birth_date = datetime.date(1976, 2, 1)
  73. >>> p2.mother = Person("mother")
  74. >>> p2.father = Person("father")
  75. >>> str(p2)
  76. 'unnamed (*1976-02-01)'
  77. add attributes of p2 to p1:
  78. >>> p1.merge(p2)
  79. >>> str(p1)
  80. 'Max Mustermann (*1976-02-01)'
  81. >>> p1.mother, p1.father
  82. (Person(mother), Person(father))
  83. p2 is unchanged:
  84. >>> str(p2)
  85. 'unnamed (*1976-02-01)'
  86. """
  87. for attr in ["name", "birth_date", "mother", "father"]:
  88. if getattr(person, attr) is not None:
  89. setattr(self, attr, getattr(person, attr))
  90. class PersonCollection:
  91. def __init__(self):
  92. self._persons = {}
  93. self.__it = None
  94. def __getitem__(self, identifier: str) -> Person:
  95. """
  96. >>> c = PersonCollection()
  97. >>> c.add_person(Person("alice"))
  98. Person(alice)
  99. >>> c["alice"]
  100. Person(alice)
  101. """
  102. return self._persons[identifier]
  103. def add_person(self, person: Person) -> Person:
  104. """
  105. >>> c = PersonCollection()
  106. >>> c.add_person(Person("alice"))
  107. Person(alice)
  108. >>> c.add_person(Person("bob"))
  109. Person(bob)
  110. >>> c["bob"]
  111. Person(bob)
  112. >>> bob = Person("bob")
  113. >>> bob.birth_date = datetime.date(2010, 2, 3)
  114. >>> bob.mother = Person("bob-mum")
  115. >>> bob.father = Person("bob-dad")
  116. >>> c.add_person(bob)
  117. Person(bob, *2010-02-03)
  118. >>> list(c)
  119. [Person(alice), Person(bob, *2010-02-03), Person(bob-mum), Person(bob-dad)]
  120. """
  121. if person.mother is not None:
  122. person.mother = self.add_person(person.mother)
  123. if person.father is not None:
  124. person.father = self.add_person(person.father)
  125. if person.identifier not in self._persons:
  126. self._persons[person.identifier] = person
  127. return person
  128. existing_person = self._persons[person.identifier]
  129. existing_person.merge(person)
  130. return existing_person
  131. def __iter__(self) -> "PersonCollection":
  132. """
  133. >>> c = PersonCollection()
  134. >>> for identifier in ['alice', 'bob', 'charlie']:
  135. ... c.add_person(Person(identifier))
  136. Person(alice)
  137. Person(bob)
  138. Person(charlie)
  139. >>> list(c)
  140. [Person(alice), Person(bob), Person(charlie)]
  141. """
  142. self.__it = iter(self._persons.values())
  143. return self
  144. def __next__(self) -> Person:
  145. return next(self.__it)