From 9bce21dc2f309e733e386d9cd7bfa7871ea7ef04 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Thu, 23 Jul 2026 16:54:51 +0200 Subject: [PATCH] Resolve meos_catalog.c through MDB_SRC_ROOT for the installed-headers path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The object-model resolver returns the meos/src directory only when a source tree sits beside the headers. On the installed-headers build path the headers carry no source, so it returns none and the type-relation registry drops out — even though the provisioning checks out the full repository under MDB_SRC_ROOT. Locate meos_catalog.c from the resolved source root when present, otherwise from MDB_SRC_ROOT/meos/src, so the registry attaches on both build paths. A test covers the MDB_SRC_ROOT fallback, and the degrade test clears the env var so it still proves honest absence when neither source is available. --- parser/typerelations.py | 27 +++++++++++++++++++++++---- tests/test_typerelations.py | 28 ++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/parser/typerelations.py b/parser/typerelations.py index 03a8376..0695b47 100644 --- a/parser/typerelations.py +++ b/parser/typerelations.py @@ -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 @@ -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")) diff --git a/tests/test_typerelations.py b/tests/test_typerelations.py index a69b5d1..f502f63 100644 --- a/tests/test_typerelations.py +++ b/tests/test_typerelations.py @@ -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 @@ -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):