diff --git a/graphify/build.py b/graphify/build.py index 1e040420e..5893ef2aa 100644 --- a/graphify/build.py +++ b/graphify/build.py @@ -311,8 +311,10 @@ def build( return build_from_json(combined, directed=directed, root=root) -def _norm_label(label: str) -> str: +def _norm_label(label: str | None) -> str: """Canonical dedup key — Unicode-aware, preserves CJK/word characters.""" + if not isinstance(label, str): + label = "" if label is None else str(label) label = unicodedata.normalize("NFKC", label) return re.sub(r"[\W_ ]+", " ", label.casefold(), flags=re.UNICODE).strip() diff --git a/graphify/dedup.py b/graphify/dedup.py index b2885fe5c..913975a26 100644 --- a/graphify/dedup.py +++ b/graphify/dedup.py @@ -15,8 +15,10 @@ # ── helpers ─────────────────────────────────────────────────────────────────── -def _norm(label: str) -> str: +def _norm(label: str | None) -> str: """Lowercase + collapse non-alphanumeric runs to space (Unicode-aware).""" + if not isinstance(label, str): + label = "" if label is None else str(label) label = unicodedata.normalize("NFKC", label) return re.sub(r"[\W_]+", " ", label.casefold(), flags=re.UNICODE).strip() diff --git a/graphify/export.py b/graphify/export.py index e9f7b5040..26fb20aca 100644 --- a/graphify/export.py +++ b/graphify/export.py @@ -102,8 +102,10 @@ def _obsidian_tag(name: str) -> str: return re.sub(r"[^a-zA-Z0-9_\-/]", "", name.replace(" ", "_")) -def _strip_diacritics(text: str) -> str: +def _strip_diacritics(text: str | None) -> str: import unicodedata + if not isinstance(text, str): + text = "" if text is None else str(text) nfkd = unicodedata.normalize("NFKD", text) return "".join(c for c in nfkd if not unicodedata.combining(c)) diff --git a/graphify/serve.py b/graphify/serve.py index a349f511b..6e05b6a98 100644 --- a/graphify/serve.py +++ b/graphify/serve.py @@ -51,8 +51,10 @@ def _communities_from_graph(G: nx.Graph) -> dict[int, list[str]]: return communities -def _strip_diacritics(text: str) -> str: +def _strip_diacritics(text: str | None) -> str: import unicodedata + if not isinstance(text, str): + text = "" if text is None else str(text) nfkd = unicodedata.normalize("NFKD", text) return "".join(c for c in nfkd if not unicodedata.combining(c))