From b3488a29e85656f02459dcecdbbd1e9bb350fc54 Mon Sep 17 00:00:00 2001 From: Daniel Viegas Date: Fri, 28 Nov 2025 22:14:03 +0100 Subject: [PATCH] Fix bidirectional family references in demo family generator - Add parentin references for fathers and mothers - Add childof references for children - Regenerate person XMLs with correct family relationships - Fixes import errors about missing bidirectional references --- demo_family.gramps | 842 +++++++++++++++++++++------------------- generate_demo_family.py | 90 ++++- 2 files changed, 526 insertions(+), 406 deletions(-) diff --git a/demo_family.gramps b/demo_family.gramps index 5e9c4ae..12102d2 100644 --- a/demo_family.gramps +++ b/demo_family.gramps @@ -11,284 +11,279 @@ - + Birth - + Birth of Smith, John - + Death - + Death of Smith, John - + Birth - + Birth of Smith, Mary - + Death - + Death of Smith, Mary - + Marriage - + Marriage - + Birth - - Birth of Smith, Steven + + Birth of Smith, Timothy - - Death - - Death of Smith, Steven - - + Birth - - Birth of Smith, Debra + + Birth of Smith, Samantha - + Birth - - Birth of Smith, Jeffrey - - - Death - - Death of Smith, Jeffrey - - - Birth - - Birth of Smith, Patricia - - - Birth - - Birth of Smith, William - - - Death - - Death of Smith, William - - - Birth - - Birth of Smith, Dorothy - - - Birth - - Birth of Smith, William - - - Birth - - Birth of Smith, Brenda - - - Birth - - Birth of Smith, Jason - - - Birth - - Birth of Smith, Amanda - - - Birth - + Birth of Smith, Anthony - + + Death + + Death of Smith, Anthony + + Birth - - Birth of Smith, Susan - - - Birth - - Birth of Smith, Anthony - - - Birth - - Birth of Smith, Rebecca - - - Birth - - Birth of Smith, Michael - - - Marriage - - Marriage - - - Marriage - - Marriage - - - Marriage - - Marriage - - - Marriage - - Marriage - - - Marriage - - Marriage - - - Birth - + Birth of Smith, Christine - + Birth - - Birth of Smith, Jeffrey + + Birth of Smith, Nicholas - + Birth - - Birth of Smith, Deborah + + Birth of Smith, Pamela - + Birth - - Birth of Smith, Eric - - - Birth - - Birth of Smith, Charles - - - Birth - - Birth of Smith, Thomas - - - Birth - - Birth of Smith, Nancy - - - Birth - - Birth of Smith, David - - - Birth - - Birth of Smith, Katherine - - - Birth - - Birth of Smith, Scott - - - Birth - - Birth of Smith, Betty - - - Birth - - Birth of Smith, Robert - - - Birth - - Birth of Smith, Anna - - - Birth - - Birth of Smith, John - - - Birth - - Birth of Smith, Richard - - - Birth - - Birth of Smith, Joshua - - - Birth - - Birth of Smith, Nancy - - - Birth - - Birth of Smith, Jacob - - - Birth - - Birth of Smith, Elizabeth - - - Birth - - Birth of Smith, Ryan - - - Birth - - Birth of Smith, Carol - - - Birth - - Birth of Smith, George - - - Birth - - Birth of Smith, Rebecca - - - Birth - + Birth of Smith, Edward - - Birth - - Birth of Smith, Amanda + + Death + + Death of Smith, Edward - + Birth - - Birth of Smith, Jacob + + Birth of Smith, Shirley + + + Birth + + Birth of Smith, John + + + Birth + + Birth of Smith, Melissa + + + Birth + + Birth of Smith, Stephen + + + Birth + + Birth of Smith, Jennifer + + + Birth + + Birth of Smith, Daniel + + + Birth + + Birth of Smith, Rebecca + + + Birth + + Birth of Smith, Justin + + + Marriage + + Marriage + + + Marriage + + Marriage + + + Marriage + + Marriage + + + Marriage + + Marriage + + + Marriage + + Marriage + + + Birth + + Birth of Smith, Sarah + + + Birth + + Birth of Smith, Nicholas + + + Birth + + Birth of Smith, Mary + + + Birth + + Birth of Smith, Kevin + + + Birth + + Birth of Smith, Stephanie + + + Birth + + Birth of Smith, Nicholas + + + Birth + + Birth of Smith, Matthew + + + Birth + + Birth of Smith, Joshua + + + Birth + + Birth of Smith, Kimberly + + + Birth + + Birth of Smith, Andrew + + + Birth + + Birth of Smith, Shirley + + + Birth + + Birth of Smith, Timothy + + + Birth + + Birth of Smith, Cynthia + + + Birth + + Birth of Smith, Eric + + + Birth + + Birth of Smith, Laura + + + Birth + + Birth of Smith, Larry + + + Birth + + Birth of Smith, Katherine + + + Birth + + Birth of Smith, Brian + + + Birth + + Birth of Smith, John + + + Birth + + Birth of Smith, Brenda + + + Birth + + Birth of Smith, Donald + + + Birth + + Birth of Smith, Sharon + + + Birth + + Birth of Smith, Gary + + + Birth + + Birth of Smith, Betty + + + Birth + + Birth of Smith, Joseph + + + Birth + + Birth of Smith, Sharon - + M John @@ -296,8 +291,9 @@ + - + F Mary @@ -305,341 +301,387 @@ + - + M - Steven + Timothy Smith - + + - + F - Debra + Samantha Smith + + - + M - Jeffrey + Anthony Smith + + - + F - Patricia + Christine Smith + + - + M - William + Nicholas Smith - + + - + F - Dorothy + Pamela Smith + - + M - William + Edward Smith + + - + F - Brenda + Shirley Smith + - + M - Jason + John Smith + - + F - Amanda + Melissa Smith + - + M - Anthony + Stephen Smith + - + F - Susan + Jennifer Smith + - + M - Anthony + Daniel Smith + - + F Rebecca Smith + - + M - Michael + Justin Smith + - + F - Christine + Sarah Smith + - + M - Jeffrey + Nicholas Smith + - + F - Deborah + Mary Smith + - + M - Eric + Kevin Smith + - - M + + F - Charles + Stephanie Smith + - + M - Thomas + Nicholas Smith + - - F + + M - Nancy + Matthew Smith + - - M - - David - Smith - - - - - F - - Katherine - Smith - - - - - M - - Scott - Smith - - - - - F - - Betty - Smith - - - - - M - - Robert - Smith - - - - - F - - Anna - Smith - - - - - M - - John - Smith - - - - - M - - Richard - Smith - - - - + M Joshua Smith - + + - + F - Nancy + Kimberly + Smith + + + + + + M + + Andrew + Smith + + + + + + F + + Shirley + Smith + + + + + + M + + Timothy + Smith + + + + + + F + + Cynthia + Smith + + + + + + M + + Eric + Smith + + + + + + F + + Laura + Smith + + + + + + M + + Larry + Smith + + + + + + F + + Katherine Smith + - + M - Jacob + Brian Smith + - - F + + M - Elizabeth + John Smith + - - M + + F - Ryan + Brenda Smith + - - F + + M - Carol + Donald Smith + - - M + + F - George + Sharon Smith + - - F + + M - Rebecca + Gary Smith + - - M + + F - Edward + Betty Smith + - - F + + M - Amanda + Joseph Smith + - - M + + F - Jacob + Sharon Smith + - + @@ -660,51 +702,51 @@ - + + + - + - - - + - - - - - - + - - - + - + - - + + + + - + + + + + + + - + - - + diff --git a/generate_demo_family.py b/generate_demo_family.py index 6656e33..1919e13 100644 --- a/generate_demo_family.py +++ b/generate_demo_family.py @@ -11,7 +11,8 @@ def gen_handle(prefix, num): return f"_{prefix}{num:08d}" # Generate a person -def gen_person(pid, first_name, surname, birth_year, death_year=None, gender="M"): +def gen_person(pid, first_name, surname, birth_year, death_year=None, gender="M", + parentin_families=None, childof_families=None): handle = gen_handle("PERSON", pid) birth_handle = gen_handle("EVENT", pid * 10) death_handle = gen_handle("EVENT", pid * 10 + 1) if death_year else None @@ -26,6 +27,16 @@ def gen_person(pid, first_name, surname, birth_year, death_year=None, gender="M" """ if death_handle: person_xml += f""" +""" + # Add parentin references (for fathers and mothers) + if parentin_families: + for family_handle in parentin_families: + person_xml += f""" +""" + # Add childof references (for children) + if childof_families: + for family_handle in childof_families: + person_xml += f""" """ person_xml += """ """ @@ -110,12 +121,19 @@ def main(): # Father: John Smith, born 1950, died 2010 father_id = 1 father_handle = gen_handle("PERSON", father_id) - father_person, father_birth, father_death = gen_person(father_id, "John", "Smith", 1950, 2010, "M") + main_family_handle = gen_handle("FAMILY", 1) + father_person, father_birth, father_death = gen_person( + father_id, "John", "Smith", 1950, 2010, "M", + parentin_families=[main_family_handle] + ) # Mother: Mary Smith, born 1952, died 2015 mother_id = 2 mother_handle = gen_handle("PERSON", mother_id) - mother_person, mother_birth, mother_death = gen_person(mother_id, "Mary", "Smith", 1952, 2015, "F") + mother_person, mother_birth, mother_death = gen_person( + mother_id, "Mary", "Smith", 1952, 2015, "F", + parentin_families=[main_family_handle] + ) # Generate 15 children children = [] @@ -130,7 +148,10 @@ def main(): death_year = birth_year + random.randint(60, 90) if random.random() < 0.3 else None # 30% chance of death child_handle = gen_handle("PERSON", child_id) - child_person, child_birth, child_death = gen_person(child_id, first_name, "Smith", birth_year, death_year, gender) + child_person, child_birth, child_death = gen_person( + child_id, first_name, "Smith", birth_year, death_year, gender, + childof_families=[main_family_handle] + ) children.append(child_person) child_handles.append(child_handle) @@ -143,6 +164,35 @@ def main(): family_id = 1 family_xml, marriage_event = gen_family(family_id, father_handle, mother_handle, 1969, child_handles) + # Track person data for regeneration (needed for children who become parents) + import re + person_data = {} + # Store initial person data + person_data[father_id] = {"handle": father_handle, "name": "John", "surname": "Smith", + "birth": 1950, "death": 2010, "gender": "M", + "parentin": [main_family_handle], "childof": []} + person_data[mother_id] = {"handle": mother_handle, "name": "Mary", "surname": "Smith", + "birth": 1952, "death": 2015, "gender": "F", + "parentin": [main_family_handle], "childof": []} + for i, child_handle in enumerate(child_handles): + child_pid = 3 + i + gender = "M" if i % 2 == 0 else "F" + # Extract name from generated child XML + child_xml = children[i] + name_match = re.search(r'([^<]+)', child_xml) + first_name = name_match.group(1) if name_match else random.choice(male_names if gender == "M" else female_names) + birth_year = 1970 + (i * 2) + # Extract death year from child_events if it exists + death_year = None + for event in child_events: + if f"id=\"E{child_pid*10+1:04d}\"" in event: + match = re.search(r'val="(\d{4})', event) + if match: + death_year = int(match.group(1)) + person_data[child_pid] = {"handle": child_handle, "name": first_name, "surname": "Smith", + "birth": birth_year, "death": death_year, "gender": gender, + "parentin": [], "childof": [main_family_handle]} + # Generate grandchildren (children of first 5 children) grandchildren = [] grandchild_events = [] @@ -150,6 +200,7 @@ def main(): for i in range(5): # First 5 children have children parent_handle = child_handles[i] + parent_pid = 3 + i parent_gender = "M" if i % 2 == 0 else "F" spouse_gender = "F" if parent_gender == "M" else "M" @@ -157,8 +208,15 @@ def main(): spouse_name = random.choice(female_names if spouse_gender == "F" else male_names) spouse_birth = 1970 + (i * 2) + random.randint(-2, 2) spouse_handle = gen_handle("PERSON", grandchild_id) + child_family_handle = gen_handle("FAMILY", family_id + 1) + + person_data[grandchild_id] = {"handle": spouse_handle, "name": spouse_name, "surname": "Smith", + "birth": spouse_birth, "death": None, "gender": spouse_gender, + "parentin": [child_family_handle], "childof": []} + spouse_person, spouse_birth_event, spouse_death_event = gen_person( - grandchild_id, spouse_name, "Smith", spouse_birth, None, spouse_gender + grandchild_id, spouse_name, "Smith", spouse_birth, None, spouse_gender, + parentin_families=[child_family_handle] ) grandchildren.append(spouse_person) grandchild_events.append(spouse_birth_event) @@ -166,6 +224,9 @@ def main(): grandchild_events.append(spouse_death_event) grandchild_id += 1 + # Update parent to include parentin reference + person_data[parent_pid]["parentin"].append(child_family_handle) + # Create 3-5 children per couple num_grandchildren = random.randint(3, 5) grandchild_handles = [] @@ -174,8 +235,14 @@ def main(): gchild_name = random.choice(male_names if gchild_gender == "M" else female_names) gchild_birth = 1995 + (i * 3) + j gchild_handle = gen_handle("PERSON", grandchild_id) + + person_data[grandchild_id] = {"handle": gchild_handle, "name": gchild_name, "surname": "Smith", + "birth": gchild_birth, "death": None, "gender": gchild_gender, + "parentin": [], "childof": [child_family_handle]} + gchild_person, gchild_birth_event, gchild_death_event = gen_person( - grandchild_id, gchild_name, "Smith", gchild_birth, None, gchild_gender + grandchild_id, gchild_name, "Smith", gchild_birth, None, gchild_gender, + childof_families=[child_family_handle] ) grandchildren.append(gchild_person) grandchild_handles.append(gchild_handle) @@ -190,6 +257,17 @@ def main(): family_xml += fam_xml child_events.append(fam_marriage) + # Regenerate children XMLs with updated family references + children = [] + for i, child_handle in enumerate(child_handles): + child_pid = 3 + i + data = person_data[child_pid] + child_person, _, _ = gen_person( + child_pid, data["name"], data["surname"], data["birth"], data["death"], data["gender"], + parentin_families=data["parentin"], childof_families=data["childof"] + ) + children.append(child_person) + # Write XML file xml_content = f"""