From: Shane Jaroch Date: Sat, 24 Jan 2026 05:56:44 +0000 (-0500) Subject: fixup X-Git-Url: https://git.nutra.tk/v2?a=commitdiff_plain;h=ef848b686f5021323c4006fd2f2a67f448a52da1;p=gamesguru%2Fgetmyancestors.git fixup --- diff --git a/Makefile b/Makefile index f0eae5c..f9f5e37 100644 --- a/Makefile +++ b/Makefile @@ -89,15 +89,13 @@ format: ##H@@ Format with black & isort ruff check --fix --exit-zero $(ARGS) ${PY_CHANGED_FILES}; \ fi -.PHONY: lint/ -lint/: lint/ruff lint/pylint lint/mypy -lint/: ##H@@ Lint with ruff, pylint, and mypy - .PHONY: lint -lint: lint/ +lint: ruff pylint mypy +lint: ##H@@ Lint with ruff, pylint, and mypy + -.PHONY: lint/ruff -lint/ruff: +.PHONY: ruff +ruff: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ruff (lint) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -105,8 +103,8 @@ lint/ruff: ruff check ${PY_CHANGED_FILES}; \ fi -.PHONY: lint/pylint -lint/pylint: +.PHONY: pylint +pylint: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # pylint # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -114,8 +112,8 @@ lint/pylint: pylint -j 0 ${PY_CHANGED_FILES}; \ fi -.PHONY: lint/mypy -lint/mypy: +.PHONY: mypy +mypy: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # mypy # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -123,12 +121,6 @@ lint/mypy: mypy ${PY_CHANGED_FILES}; \ fi -.PHONY: pylint -pylint: lint/pylint - -.PHONY: mypy -mypy: lint/mypy - .PHONY: clean clean: ##H@@ Clean up build files/cache diff --git a/getmyancestors/classes/session.py b/getmyancestors/classes/session.py index 67c5954..b2cc603 100644 --- a/getmyancestors/classes/session.py +++ b/getmyancestors/classes/session.py @@ -817,11 +817,15 @@ class CachedSession(GMASession, CSession): self, cache_path, backend="filesystem", + serializer="json", expire_after=expire_after, allowable_codes=(200, 204), cache_control=cache_control, # Enable HTTP conditional requests (ETag/Last-Modified) allow_to_fetch_missing=(not offline_mode), # prevent fetch on miss ) + print( + f"DEBUG: CachedSession initialized. Backend=filesystem, Path={cache_path}, Offline={offline_mode}" + ) # Re-apply default headers as CSession.__init__ might have wiped them with self.lock: self.headers.update(self.DEFAULT_HEADERS) diff --git a/getmyancestors/classes/tree/core.py b/getmyancestors/classes/tree/core.py index f1228da..67ee680 100644 --- a/getmyancestors/classes/tree/core.py +++ b/getmyancestors/classes/tree/core.py @@ -10,6 +10,7 @@ import threading import time import xml.etree.ElementTree as ET from datetime import datetime +from enum import Enum from typing import Any, BinaryIO, Dict, Iterable, List, Optional, Set, Tuple, Union # global imports @@ -27,6 +28,32 @@ from .records import Fact, Memorie, Note, Source from .utils import GEONAME_FEATURE_MAP, cont +class ParentRelType(str, Enum): + """Parental relationship type in FamilySearch (PEDI)""" + + BIRTH = "birth" + ADOPTED = "adopted" + STEP = "step" + FOSTER = "foster" + + @staticmethod + def from_fs_type(facts: list | None) -> "ParentRelType | None": + """Parse from FamilySearch fact/relationship type""" + if not facts: + return None + for fact in facts: + ftype = fact.get("type", "") + if ftype == "http://gedcomx.org/BiologicalParent": + return ParentRelType.BIRTH + if ftype == "http://gedcomx.org/StepParent": + return ParentRelType.STEP + if ftype == "http://gedcomx.org/AdoptiveParent": + return ParentRelType.ADOPTED + if ftype == "http://gedcomx.org/FosterParent": + return ParentRelType.FOSTER + return None + + class Indi: """GEDCOM individual class :param fid' FamilySearch id @@ -49,7 +76,7 @@ class Indi: self.tree = tree self.num_prefix = "I" self.origin_file: Optional[str] = None - self.famc: Set["Fam"] = set() + self.famc: Dict["Fam", Optional[ParentRelType]] = {} self.fams: Set["Fam"] = set() self.famc_fid: Set[str] = set() self.fams_fid: Set[str] = set() @@ -150,11 +177,17 @@ class Indi: ), None, ) - source = ( - self.tree.ensure_source(source_data) - if self.tree and source_data - else None - ) + if self.tree: + if source_data: + source = self.tree.ensure_source(source_data) + else: + existing_source = self.tree.sources.get(source_id) + if existing_source: + source = existing_source + else: + source = self.tree.ensure_source({"id": source_id}) + else: + source = None if source and self.tree: citation = self.tree.ensure_citation(quote, source) self.citations.add(citation) @@ -189,9 +222,9 @@ class Indi: """add family fid (for spouse or parent)""" self.fams.add(fam) - def add_famc(self, fam: "Fam"): + def add_famc(self, fam: "Fam", rel_type: Optional[ParentRelType] = None): """add family fid (for child)""" - self.famc.add(fam) + self.famc[fam] = rel_type def get_notes(self): """retrieve individual notes""" @@ -417,8 +450,11 @@ class Indi: self.sealing_child.print(file) for fam in sorted(self.fams, key=lambda x: x.id or ""): file.write("1 FAMS @F%s@\n" % fam.id) - for fam in sorted(self.famc, key=lambda x: x.id or ""): + for fam in sorted(self.famc.keys(), key=lambda x: x.id or ""): file.write("1 FAMC @F%s@\n" % fam.id) + val = self.famc[fam] + if val: + file.write("2 PEDI %s\n" % val.value) # print(f'Fams Ids: {self.fams_ids}, {self.fams_fid}, {self.fams_num}', file=sys.stderr) # for num in self.fams_ids: # print(f'Famc Ids: {self.famc_ids}', file=sys.stderr) diff --git a/getmyancestors/mergemyanc.py b/getmyancestors/mergemyanc.py index 0db1724..e3e9e86 100755 --- a/getmyancestors/mergemyanc.py +++ b/getmyancestors/mergemyanc.py @@ -113,16 +113,18 @@ def main( def merge_names(target_set, source_set): # Combine all names and sort deterministically all_names = list(target_set) + list(source_set) - all_names.sort(key=lambda x: ( - str(x), - x.given or "", - x.surname or "", - x.prefix or "", - x.suffix or "", - x.kind or "", - str(x.alternative) if hasattr(x, 'alternative') else "", - x.note.text if hasattr(x, 'note') and x.note else "", - )) + all_names.sort( + key=lambda nm: ( + str(nm), + nm.given or "", + nm.surname or "", + nm.prefix or "", + nm.suffix or "", + nm.kind or "", + str(nm.alternative) if hasattr(nm, "alternative") else "", + nm.note.text if hasattr(nm, "note") and nm.note else "", + ) + ) # Rebuild target_set keeping first occurrence by string target_set.clear() seen = set() @@ -365,7 +367,7 @@ def main( for chil_fid in fam.chil_fid: if chil_fid in tree.indi: fam.children.add(tree.indi[chil_fid]) - tree.indi[chil_fid].famc.add(fam) + tree.indi[chil_fid].add_famc(fam) # compute number for family relationships and print GEDCOM file tree.reset_num() diff --git a/res/testdata b/res/testdata index cefbd8d..b308495 160000 --- a/res/testdata +++ b/res/testdata @@ -1 +1 @@ -Subproject commit cefbd8dbd42cbb85209bae8e242e57add0c0e520 +Subproject commit b3084953c34c25c3867bcc1e000dfb32e59ae6f5 diff --git a/tests/offline_test.py b/tests/offline_test.py index 34e268d..ad04938 100644 --- a/tests/offline_test.py +++ b/tests/offline_test.py @@ -132,7 +132,6 @@ def test_offline(): expectations = load_expectations() exp_ada = expectations.get("EXPECTED_ADA_LINES", 0) exp_marie = expectations.get("EXPECTED_MARIE_LINES", 0) - exp_merged = expectations.get("EXPECTED_MERGED_LINES", 0) # 2. Setup Cache setup_cache() @@ -303,10 +302,31 @@ def test_offline(): # Check merged file with exact diff (no line count tolerance) diff_result = subprocess.run( - ["git", "diff", "--no-index", "--exit-code", "--color=always", str(merged), str(ARTIFACTS_DIR / "merged_scientists.ged")], + [ + "git", + "diff", + "--no-index", + "--exit-code", + "--color=always", + str(merged), + str(ARTIFACTS_DIR / "merged_scientists.ged"), + ], + check=False, ) if diff_result.returncode != 0: - print(f"❌ Merged file differs from artifact (see diff above)") + print("❌ Merged file differs from artifact (see diff above)") + print("Diff Stat:") + subprocess.run( + [ + "git", + "diff", + "--no-index", + "--stat", + str(merged), + str(ARTIFACTS_DIR / "merged_scientists.ged"), + ], + check=False, + ) failed = True else: print(f"✓ Merged file matches artifact exactly ({l_merged} lines).")