yaml.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import datetime # pylint: disable=unused-import; doctest
  2. import yaml
  3. from yamily import Person
  4. class Loader(yaml.SafeLoader):
  5. # pylint: disable=too-many-ancestors
  6. """
  7. >>> alice_yaml = '''
  8. ... !person
  9. ... identifier: alice
  10. ... name: Alice Test
  11. ... birth_date: 1976-02-01
  12. ... mother: mum
  13. ... father: dad
  14. ... '''
  15. >>> alice = yaml.load(alice_yaml, Loader=Loader)
  16. >>> alice
  17. Person(alice, Alice Test, *1976-02-01)
  18. >>> alice.mother
  19. Person(mum)
  20. >>> alice.father
  21. Person(dad)
  22. >>> alice_yaml = '''
  23. ... !person
  24. ... identifier: alice
  25. ... name: Alice Test
  26. ... birth_date: 1976-02-01
  27. ... mother: !person
  28. ... identifier: mum
  29. ... father: !person
  30. ... identifier: dad
  31. ... name: Dad Test
  32. ... '''
  33. >>> alice = yaml.load(alice_yaml, Loader=Loader)
  34. >>> alice
  35. Person(alice, Alice Test, *1976-02-01)
  36. >>> alice.mother
  37. Person(mum)
  38. >>> alice.father
  39. Person(dad, Dad Test)
  40. """
  41. def __init__(self, stream):
  42. super().__init__(stream)
  43. self.add_constructor("!person", self._construct_person)
  44. @staticmethod
  45. def _construct_person(loader: "Loader", node: yaml.nodes.MappingNode) -> Person:
  46. (person_attrs,) = loader.construct_yaml_map(node)
  47. person = Person(person_attrs["identifier"])
  48. if "name" in person_attrs:
  49. person.name = person_attrs["name"]
  50. if "birth_date" in person_attrs:
  51. person.birth_date = person_attrs["birth_date"]
  52. if "mother" in person_attrs:
  53. if isinstance(person_attrs["mother"], Person):
  54. person.mother = person_attrs["mother"]
  55. else:
  56. person.mother = Person(person_attrs["mother"])
  57. if "father" in person_attrs:
  58. if isinstance(person_attrs["father"], Person):
  59. person.father = person_attrs["father"]
  60. else:
  61. person.father = Person(person_attrs["father"])
  62. return person
  63. class Dumper(yaml.SafeDumper):
  64. """
  65. >>> p = Person('alice')
  66. >>> p.name = 'Alice'
  67. >>> p.birth_date = datetime.date(1976, 2, 1)
  68. >>> print(yaml.dump(p, Dumper=Dumper))
  69. !person
  70. birth_date: 1976-02-01
  71. identifier: alice
  72. name: Alice
  73. <BLANKLINE>
  74. >>> p = Person('bob')
  75. >>> p.mother = Person('bob-mum')
  76. >>> p.father = Person('bob-father')
  77. >>> print(yaml.dump(p, Dumper=Dumper))
  78. !person
  79. father: !person
  80. identifier: bob-father
  81. identifier: bob
  82. mother: !person
  83. identifier: bob-mum
  84. <BLANKLINE>
  85. """
  86. # pylint: disable=too-many-ancestors
  87. def __init__(self, stream, **kwargs):
  88. super().__init__(stream, **kwargs)
  89. self.add_representer(Person, self._represent_person)
  90. @staticmethod
  91. def _represent_person(dumper: "_Dumper", person: Person) -> yaml.nodes.MappingNode:
  92. person_attrs = {"identifier": person.identifier}
  93. if person.name is not None:
  94. person_attrs["name"] = person.name
  95. if person.birth_date is not None:
  96. person_attrs["birth_date"] = person.birth_date
  97. if person.mother is not None:
  98. person_attrs["mother"] = person.mother
  99. if person.father is not None:
  100. person_attrs["father"] = person.father
  101. return dumper.represent_mapping("!person", person_attrs)