Skip to content

Commit 8149314

Browse files
dsblankclaude
andcommitted
Move get_parent_handles/get_child_handles to DbReadBase; fix proxy traversal.
Move the Python base implementations of get_parent_handles and get_child_handles from DbGeneric up to DbReadBase so that proxy databases (PrivateProxyDb, LivingProxyDb, etc.) inherit them automatically. Previously, calling these methods through a proxy would fall through __getattr__ to the SQL implementation, bypassing proxy filtering. Now proxies use the base Python implementation which calls get_raw_person_data/get_raw_family_data through the proxy's own filtering layer. Also rename test_graph.py to graph_test.py so CI discovers it via the *_test.py pattern, and add proxy tests for get_parent_handles and get_child_handles to cover this path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 65b861e commit 8149314

4 files changed

Lines changed: 81 additions & 41 deletions

File tree

gramps/gen/db/base.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -967,13 +967,40 @@ def get_parent_handles(self, person_handle, first_only=True):
967967
"""
968968
Return handles of all parents of a person across their parent families.
969969
"""
970-
raise NotImplementedError
970+
person = self.get_raw_person_data(person_handle)
971+
if person is None:
972+
return []
973+
families = person.parent_family_list
974+
if first_only and families:
975+
families = [families[0]]
976+
result = []
977+
for fam_handle in families:
978+
family = self.get_raw_family_data(fam_handle)
979+
if family is None:
980+
continue
981+
if family.father_handle:
982+
result.append(family.father_handle)
983+
if family.mother_handle:
984+
result.append(family.mother_handle)
985+
return result
971986

972987
def get_child_handles(self, person_handle, first_only=True):
973988
"""
974989
Return handles of all children of a person across their families.
975990
"""
976-
raise NotImplementedError
991+
person = self.get_raw_person_data(person_handle)
992+
if person is None:
993+
return []
994+
families = person.family_list
995+
if first_only and families:
996+
families = [families[0]]
997+
result = []
998+
for fam_handle in families:
999+
family = self.get_raw_family_data(fam_handle)
1000+
if family is None:
1001+
continue
1002+
result.extend(cr.ref for cr in family.child_ref_list if cr.ref)
1003+
return result
9771004

9781005
def get_raw_place_data(self, handle):
9791006
"""

gramps/gen/db/generic.py

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,45 +1867,6 @@ def get_raw_person_data(self, handle):
18671867
def get_raw_family_data(self, handle):
18681868
return self._get_raw_data(FAMILY_KEY, handle)
18691869

1870-
def get_parent_handles(self, person_handle, first_only=True):
1871-
"""
1872-
Return handles of all parents of a person across their parent families.
1873-
"""
1874-
person = self.get_raw_person_data(person_handle)
1875-
if person is None:
1876-
return []
1877-
families = person.parent_family_list
1878-
if first_only and families:
1879-
families = [families[0]]
1880-
result = []
1881-
for fam_handle in families:
1882-
family = self.get_raw_family_data(fam_handle)
1883-
if family is None:
1884-
continue
1885-
if family.father_handle:
1886-
result.append(family.father_handle)
1887-
if family.mother_handle:
1888-
result.append(family.mother_handle)
1889-
return result
1890-
1891-
def get_child_handles(self, person_handle, first_only=True):
1892-
"""
1893-
Return handles of all children of a person across their families.
1894-
"""
1895-
person = self.get_raw_person_data(person_handle)
1896-
if person is None:
1897-
return []
1898-
families = person.family_list
1899-
if first_only and families:
1900-
families = [families[0]]
1901-
result = []
1902-
for fam_handle in families:
1903-
family = self.get_raw_family_data(fam_handle)
1904-
if family is None:
1905-
continue
1906-
result.extend(cr.ref for cr in family.child_ref_list if cr.ref)
1907-
return result
1908-
19091870
def get_raw_source_data(self, handle):
19101871
return self._get_raw_data(SOURCE_KEY, handle)
19111872

gramps/gen/proxy/test/proxies_test.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,32 @@ def test_person_with_private_data(self):
112112
person = self.db.basedb.get_person_from_handle(handle)
113113
self.assertTrue(len(person.attribute_list) == 3)
114114

115+
def test_get_parent_handles_private_person(self):
116+
# A private person's parents should not be returned through the proxy.
117+
handle = "0GDKQC54XKSWZKEBWW"
118+
parents = self.db.get_parent_handles(handle)
119+
self.assertEqual(parents, [])
120+
121+
def test_get_parent_handles_non_private_person(self):
122+
# A non-private person's parents should match the base db.
123+
handle = "0FWJQCLYEP736P3YZK"
124+
parents = self.db.get_parent_handles(handle)
125+
parents_base = self.db.basedb.get_parent_handles(handle)
126+
self.assertEqual(sorted(parents), sorted(parents_base))
127+
128+
def test_get_child_handles_private_person(self):
129+
# A private person's children should not be returned through the proxy.
130+
handle = "0GDKQC54XKSWZKEBWW"
131+
children = self.db.get_child_handles(handle)
132+
self.assertEqual(children, [])
133+
134+
def test_get_child_handles_non_private_person(self):
135+
# A non-private person's children should match the base db.
136+
handle = "0FWJQCLYEP736P3YZK"
137+
children = self.db.get_child_handles(handle)
138+
children_base = self.db.basedb.get_child_handles(handle)
139+
self.assertEqual(sorted(children), sorted(children_base))
140+
115141

116142
class LivingProxyTest(unittest.TestCase):
117143
"""
@@ -155,6 +181,32 @@ def test_dead_person(self):
155181
person = self.db.get_person_from_handle(handle)
156182
self.assertIs(person, None)
157183

184+
def test_get_parent_handles_dead_person(self):
185+
# A living-excluded person's parents should not be returned.
186+
handle = "66TJQC6CC7ZWL9YZ64"
187+
parents = self.db.get_parent_handles(handle)
188+
self.assertEqual(parents, [])
189+
190+
def test_get_parent_handles_live_person(self):
191+
# A visible person's parents should match the base db.
192+
handle = "004KQCGYT27EEPQHK"
193+
parents = self.db.get_parent_handles(handle)
194+
parents_base = self.db.basedb.get_parent_handles(handle)
195+
self.assertEqual(sorted(parents), sorted(parents_base))
196+
197+
def test_get_child_handles_dead_person(self):
198+
# A living-excluded person's children should not be returned.
199+
handle = "66TJQC6CC7ZWL9YZ64"
200+
children = self.db.get_child_handles(handle)
201+
self.assertEqual(children, [])
202+
203+
def test_get_child_handles_live_person(self):
204+
# A visible person's children should match the base db.
205+
handle = "004KQCGYT27EEPQHK"
206+
children = self.db.get_child_handles(handle)
207+
children_base = self.db.basedb.get_child_handles(handle)
208+
self.assertEqual(sorted(children), sorted(children_base))
209+
158210

159211
class LivingPrivateProxyTest(unittest.TestCase):
160212
"""

0 commit comments

Comments
 (0)