Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions parser/typerelations.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
— with no hand-coding: every binding is a projection of the catalog, so the
mapping belongs in the catalog rather than in each generator.
"""
import os
import re
from pathlib import Path

Expand All @@ -32,16 +33,34 @@ def _pairs(text: str, array: str) -> list:
return _PAIR_RE.findall(m.group(1)) if m else []


def _locate_catalog(src_root: Path | None) -> Path | None:
"""The ``meos_catalog.c`` path from the resolved source root, or the ``MDB_SRC_ROOT`` checkout.

The object-model resolver returns the ``meos/src`` directory when it can, but on the
installed-headers build path it cannot (the headers carry no source tree), while the provisioning
still checks out the full repository under ``MDB_SRC_ROOT``. Consulting that env var too keeps the
registry present in both build paths.
"""
candidates = []
if src_root is not None:
candidates.append(Path(src_root) / "temporal" / "meos_catalog.c")
mdb = os.environ.get("MDB_SRC_ROOT")
if mdb:
candidates.append(Path(mdb) / "meos" / "src" / "temporal" / "meos_catalog.c")
for candidate in candidates:
if candidate.exists():
return candidate
return None


def attach_type_relations(idl: dict, src_root: Path | None) -> dict:
"""Attach ``idl["typeRelations"]`` from the ``meos_catalog.c`` arrays.

Degrades to no attachment — never a fabricated map — when the source tree is
not available, mirroring the honest-signal contract of the object-model scan.
"""
if src_root is None:
return idl
catalog = Path(src_root) / "temporal" / "meos_catalog.c"
if not catalog.exists():
catalog = _locate_catalog(src_root)
if catalog is None:
return idl

text = re.sub(r"//.*", "", catalog.read_text(errors="ignore"))
Expand Down
28 changes: 26 additions & 2 deletions tests/test_typerelations.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
asserts the canonical numeric mappings against the live MobilityDB tree when it
is available (skipped, never fabricated, when it is not).
"""
import os
import sys
import tempfile
import unittest
Expand Down Expand Up @@ -71,8 +72,31 @@ def test_non_orderable_base_has_set_but_no_span(self):
self.assertEqual(by_base["text"], {"temporal": "ttext", "set": "textset"})

def test_absent_source_degrades_without_fabricating(self):
self.assertNotIn("typeRelations", attach_type_relations({}, None))
self.assertNotIn("typeRelations", attach_type_relations({}, Path("/no/such/tree")))
saved = os.environ.pop("MDB_SRC_ROOT", None)
try:
self.assertNotIn("typeRelations", attach_type_relations({}, None))
self.assertNotIn("typeRelations", attach_type_relations({}, Path("/no/such/tree")))
finally:
if saved is not None:
os.environ["MDB_SRC_ROOT"] = saved

def test_mdb_src_root_resolves_when_object_model_root_is_absent(self):
# The installed-headers build path resolves no meos/src root, but MDB_SRC_ROOT points at the
# full checkout; the registry must still attach from there.
with tempfile.TemporaryDirectory() as d:
catalog = Path(d) / "meos" / "src" / "temporal"
catalog.mkdir(parents=True)
(catalog / "meos_catalog.c").write_text(_FIXTURE)
saved = os.environ.get("MDB_SRC_ROOT")
os.environ["MDB_SRC_ROOT"] = d
try:
by_base = attach_type_relations({}, None)["typeRelations"]["byBase"]
finally:
if saved is None:
os.environ.pop("MDB_SRC_ROOT", None)
else:
os.environ["MDB_SRC_ROOT"] = saved
self.assertEqual(by_base["float8"]["spanset"], "floatspanset")


class TypeRelationsSourceTest(unittest.TestCase):
Expand Down
Loading