def __call__(self, table: Table, root: Person, x0: int = 0, y0: int = 0 ) -> List[Union[PersonBox, SpouseLink, ParentChildLink]]: # handle single person spouse = table.get_spouse(root) if spouse is None: x = x0 + self.x_margin y = y0 + self.y_margin elements = [self.person_box_class(root, x, y)] return elements # get family members from the table if root.gender == 'M': parents = [root, spouse] else: parents = [spouse, root] children = table.find_children(*parents) children = sorted(children, key=lambda p: (p.birth_order, p.id_)) elements = [] x = x0 # elements for children for child in children: elems = self(table, child, x0=x, y0=y0 + self.unit_h) x = max([e.xmax for e in _get_person_boxes(elems)]) x += self.x_margin elements += elems child_elements = [e for e in _get_person_boxes(elements) if e.person in children] # elements for parents center = (x0 + x) // 2 x = max(x0, center - self.unit_w) x1 = x + self.x_margin x2 = x + self.x_margin + self.unit_w y = y0 + self.y_margin elements.append(self.person_box_class(parents[0], x1, y)) elements.append(self.person_box_class(parents[1], x2, y)) # parent and child link ym = y0 + self.person_box_class.height // 2 for child_elem in child_elements: x1 = x + self.unit_w y1 = ym x2 = (child_elem.xmin + child_elem.xmax) // 2 y2 = child_elem.ymin elements.append(self.parent_child_link_class(x1, y1, x2, y2)) # spouse link elements.append(self.spouse_link_class( x + self.unit_w - self.x_margin, ym, x + self.unit_w + self.x_margin, ym)) return elements
def __call__(self, table: Table, target: Person) -> List[Element]: # a) single # - with parent info -> tree(father) # - no parent info -> tree(target) spouse = table.get_spouse(target) if spouse is None: parents = table.get_parents(target) if parents[0] and parents[1]: return self.tree_layout_func(table, parents[0]) else: return self.tree_layout_func(table, target) if target.gender == 'M': husband = target wife = spouse else: husband = spouse wife = target parents1 = table.get_parents(husband) parents2 = table.get_parents(wife) # b) couple, no parents info -> tree(target) if ((parents1[0] is None or parents1[1] is None) and (parents2[0] is None or parents2[1] is None)): return self.tree_layout_func(table, target) # c) couple, with parents info -> butterfly layout children1 = _get_brothers_and_sisters(table, husband) children2 = _get_brothers_and_sisters(table, wife) elements = [] # layout children x = 0 elements, x = self._layout_children(elements, x, table, children1) elements, x = self._layout_children(elements, x, table, [husband]) elements, x = self._layout_children(elements, x, table, children2) # layout parents x = 0 elements, x = self._layout_parents(elements, x, table, parents1, children1 + [husband]) elements, x = self._layout_parents(elements, x, table, parents2, [wife] + children2) return elements
def test_get_spouse_key_error(self): person = Person(1, "Name", spouse_id=999) table = Table([person]) with pytest.raises(KeyError): table.get_spouse(person)
def test_get_spouse_no_result(self): person = Person(1, "Name") table = Table([person]) assert table.get_spouse(person) == None
def test_get_spouse(self): husband = Person(1, "Husband", spouse_id=2) wife = Person(2, "Wife", spouse_id=1) table = Table([husband, wife]) assert table.get_spouse(husband) == wife assert table.get_spouse(wife) == husband