fork download
  1. #!/usr/bin/env python3
  2.  
  3. # Family people (c) Baltasar 2019 MIT License <baltasarq@gmail.com>
  4.  
  5.  
  6. import csv
  7. import json
  8. import sys
  9. from io import StringIO
  10.  
  11.  
  12. class Person:
  13. def __init__(self, name, surname, parent):
  14. self._name = name
  15. self._surname = surname
  16. self._parent = parent
  17. self._children = People()
  18.  
  19. @property
  20. def name(self):
  21. return self._name
  22.  
  23. @property
  24. def surname(self):
  25. return self._surname
  26.  
  27. @property
  28. def parent(self):
  29. return self._parent
  30.  
  31. @property
  32. def children(self):
  33. return self._children
  34.  
  35. def __str__(self):
  36. toret = self.surname + ", " + self.name + " (" + self.parent + ")";
  37.  
  38. if self.children:
  39. toret += " (" + str(self.children) + ")"
  40.  
  41. return toret
  42.  
  43.  
  44. class JsonPeopleEncoder(json.JSONEncoder):
  45. @staticmethod
  46. def basic_encode_person(p):
  47. return {"name": p.name,
  48. "surname": p.surname,
  49. "kids": len(p.children),
  50. "children": []}
  51.  
  52. @staticmethod
  53. def encode_people(people):
  54. toret = []
  55.  
  56. for p in people:
  57. p_dict = JsonPeopleEncoder.basic_encode_person(p)
  58.  
  59. if p.children:
  60. p_dict["children"].append(
  61. JsonPeopleEncoder.encode_people(p.children))
  62.  
  63. toret += [p_dict]
  64.  
  65. return toret
  66.  
  67. def default(self, obj):
  68. if isinstance(obj, People):
  69. return JsonPeopleEncoder.encode_people(obj)
  70.  
  71. # Let the base class default method raise the TypeError
  72. return json.JSONEncoder.default(self, obj)
  73.  
  74.  
  75. class People:
  76. def __init__(self):
  77. self._persons = []
  78.  
  79. def add(self, p):
  80. self._persons.append(p)
  81.  
  82. def __add__(self, p):
  83. self._persons.append(p)
  84. return self
  85.  
  86. def __true__(self):
  87. return bool(self._persons)
  88.  
  89. def __len__(self):
  90. return len(self._persons)
  91.  
  92. def __getitem__(self, item):
  93. return self._persons[item]
  94.  
  95. def __str__(self):
  96. return str.join("\n", [str(p) for p in self._persons])
  97.  
  98. def _put_children_inside_persons(self):
  99. dict_names = {p.name:p for p in self._persons}
  100. people_to_remove = []
  101.  
  102. for p in self._persons:
  103. if p.parent and p.parent != "null":
  104. parent = dict_names.get(p.parent)
  105.  
  106. if parent:
  107. parent.children.add(p)
  108. people_to_remove += [p]
  109.  
  110. for p in people_to_remove:
  111. self._persons.remove(p)
  112.  
  113. return
  114.  
  115. def as_json(self):
  116. return json.dumps(self, indent=4, cls=JsonPeopleEncoder)
  117.  
  118. @staticmethod
  119. def read(fd):
  120. toret = People()
  121.  
  122. reader = csv.DictReader(fd, delimiter=',')
  123. for row in reader:
  124. toret += Person(
  125. row["name"],
  126. row["surname"],
  127. row["parent"])
  128.  
  129. toret._put_children_inside_persons()
  130. return toret
  131.  
  132.  
  133. if __name__ == "__main__":
  134. with StringIO(sys.stdin.read()) as strf:
  135. ps = People.read(strf)
  136.  
  137. print("People:")
  138. print(ps)
  139. print("\nJSON:")
  140. print(ps.as_json())
  141.  
Success #stdin #stdout 0.02s 10024KB
stdin
name,surname,parent
diane,xxx,null
bob,xxx,diane
brian,xxx,bob
claire,xxx,brian
tom,xxx,brian
jane,xxx,tom
mike,xxx,tom
stdout
People:
xxx, diane (null) (xxx, bob (diane) (xxx, brian (bob) (xxx, claire (brian)
xxx, tom (brian) (xxx, jane (tom)
xxx, mike (tom)))))

JSON:
[
    {
        "name": "diane",
        "surname": "xxx",
        "kids": 1,
        "children": [
            [
                {
                    "name": "bob",
                    "surname": "xxx",
                    "kids": 1,
                    "children": [
                        [
                            {
                                "name": "brian",
                                "surname": "xxx",
                                "kids": 2,
                                "children": [
                                    [
                                        {
                                            "name": "claire",
                                            "surname": "xxx",
                                            "kids": 0,
                                            "children": []
                                        },
                                        {
                                            "name": "tom",
                                            "surname": "xxx",
                                            "kids": 2,
                                            "children": [
                                                [
                                                    {
                                                        "name": "jane",
                                                        "surname": "xxx",
                                                        "kids": 0,
                                                        "children": []
                                                    },
                                                    {
                                                        "name": "mike",
                                                        "surname": "xxx",
                                                        "kids": 0,
                                                        "children": []
                                                    }
                                                ]
                                            ]
                                        }
                                    ]
                                ]
                            }
                        ]
                    ]
                }
            ]
        ]
    }
]