Skip to content

Commit 5c1fa34

Browse files
committed
Drop dep back to released linkml-map 0.5.2; xfail reverse tests until 0.5.3
The previous commit pinned linkml-map >= 0.5.3 but 0.5.3 isn't on PyPI yet. That broke installs and CI. Better path: - pyproject: 'linkml-map >= 0.5.2' (the released version) - Reverse adapter raises a clear RuntimeError on 0.5.2 instead of the cryptic FunctionNotDefined from linkml-map's evaluator - Reverse tests use a conditional xfail keyed on 'is_str' presence in linkml-map's FUNCTIONS; passes as xfail on 0.5.2, will auto-flip to pass on 0.5.3 without code changes - Forward adapter and codes utility unchanged (work on 0.5.2) - README updated to reflect the version situation When 0.5.3 ships: 1. Bump dep constraint to '>= 0.5.3' 2. Remove the runtime guard in adapter.py 3. Remove the xfail marker in tests 4. Tests will pass cleanly
1 parent df7458b commit 5c1fa34

4 files changed

Lines changed: 57 additions & 7 deletions

File tree

pyproject.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ dependencies = [
4848
"tomlkit >= 0.11.4",
4949
"inflect >= 6.0.0",
5050
"linkml-runtime >= 1.10.0, < 2",
51-
# The reverse Frictionless adapter trans-spec relies on the
51+
# NB: the *reverse* Frictionless adapter trans-spec needs the
5252
# is_str / is_bool / is_list type predicates, which land in
53-
# linkml-map 0.5.3.
54-
"linkml-map >= 0.5.3, < 1",
53+
# linkml-map 0.5.3. Forward adapter and codes utility work on
54+
# 0.5.2. Bump this and remove the xfail in
55+
# tests/test_adapters/test_frictionless.py once 0.5.3 ships.
56+
"linkml-map >= 0.5.2, < 1",
5557
"click >= 8.1.7, < 9",
5658
"deprecated >= 1.2.15, < 2",
5759
"sqlalchemy >= 2.0.36, < 3",

schema_automator/adapters/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,13 @@ post-processing in `adapter.py` strips nulls. This idiom is preferred
5959
over reaching for `callable(x)` (which would couple to a `linkml-map`
6060
implementation detail) and over a Python-side fallback.
6161

62-
The full set of `is_*` predicates is available in `linkml-map`
63-
versions after 0.5.2.
62+
The full set of `is_*` predicates is available in `linkml-map` 0.5.3
63+
and later. The currently released version (0.5.2) only has
64+
`is_numeric`. The Frictionless adapter's *forward* direction works on
65+
0.5.2 (it uses only `is_numeric`); the *reverse* direction needs 0.5.3
66+
and raises a clear `RuntimeError` on earlier versions. The
67+
reverse-direction tests are marked `xfail` until the dep can be bumped
68+
to `>= 0.5.3`.
6469

6570
## Import boundary
6671

schema_automator/adapters/frictionless/adapter.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@
99
(``is_str``, ``is_bool``, ``is_list``, ``is_numeric``) to filter
1010
linkml-map's null-safe wrapper sentinel — each constraint slot has a
1111
known semantic type, so the predicates double as sentinel-filter and
12-
type-correctness check. This idiom requires the type predicates added
13-
post-linkml-map 0.5.2.
12+
type-correctness check.
13+
14+
The full set of type predicates lands in linkml-map 0.5.3. The current
15+
released version (0.5.2) only has ``is_numeric``. The forward adapter
16+
and codes utility work on 0.5.2; the reverse adapter raises a clear
17+
error on 0.5.2 and works on 0.5.3+.
1418
"""
1519

1620
from __future__ import annotations
@@ -19,10 +23,27 @@
1923
from typing import Any
2024

2125
from linkml_map.transformer.object_transformer import ObjectTransformer
26+
from linkml_map.utils.eval_utils import FUNCTIONS as _LINKML_MAP_FUNCTIONS
2227
from linkml_map.utils.loaders import load_specification
2328
from linkml_runtime.utils.schemaview import SchemaView
2429

2530

31+
_REVERSE_REQUIRED_PREDICATES = ("is_str", "is_bool", "is_list")
32+
33+
34+
def _check_reverse_supported() -> None:
35+
"""Raise a clear error if the installed linkml-map lacks the type
36+
predicates the reverse trans-spec depends on (i.e., on 0.5.2)."""
37+
missing = [p for p in _REVERSE_REQUIRED_PREDICATES if p not in _LINKML_MAP_FUNCTIONS]
38+
if missing:
39+
raise RuntimeError(
40+
"The DD → Frictionless reverse adapter requires linkml-map "
41+
f">= 0.5.3 for the {', '.join(missing)} type predicate(s). "
42+
"Installed linkml-map is missing those. Upgrade with "
43+
"`pip install --upgrade linkml-map` once 0.5.3 ships."
44+
)
45+
46+
2647
_PKG_ROOT = Path(__file__).resolve().parents[2]
2748
_DD_SCHEMA = _PKG_ROOT / "metamodels" / "data_dictionary.yaml"
2849
_FRICTIONLESS_SCHEMA = _PKG_ROOT / "metamodels" / "frictionless.yaml"
@@ -76,6 +97,10 @@ def frictionless_to_dd(table_schema: dict) -> dict:
7697
def dd_to_frictionless(data_dictionary: dict) -> dict:
7798
"""Translate a canonical DD into a Frictionless Table Schema.
7899
100+
Requires linkml-map >= 0.5.3 (for the is_str / is_bool / is_list type
101+
predicates the reverse trans-spec uses). Raises ``RuntimeError`` on
102+
earlier linkml-map releases with a message pointing at the upgrade.
103+
79104
Lossy in several places: per-code labels and per-code metadata are
80105
dropped (Frictionless ``enum`` is just an array of values); DD
81106
``unit`` has no Frictionless equivalent; DD type values
@@ -92,5 +117,6 @@ def dd_to_frictionless(data_dictionary: dict) -> dict:
92117
dict
93118
A Frictionless Table Schema document with ``fields``.
94119
"""
120+
_check_reverse_supported()
95121
tr = _make_transformer(_DD_TO_FRICTIONLESS_SPEC, _DD_SCHEMA, _FRICTIONLESS_SCHEMA)
96122
return _strip_nulls(tr.map_object(data_dictionary, source_type="DataDictionary"))

tests/test_adapters/test_frictionless.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,29 @@
44
from pathlib import Path
55

66
import pytest
7+
from linkml_map.utils.eval_utils import FUNCTIONS as _LINKML_MAP_FUNCTIONS
78

89
from schema_automator.adapters.frictionless.adapter import (
910
dd_to_frictionless,
1011
frictionless_to_dd,
1112
)
1213

1314

15+
# The reverse adapter's trans-spec uses linkml-map's is_str / is_bool /
16+
# is_list type predicates, which land in linkml-map 0.5.3. On 0.5.2 (the
17+
# current PyPI release) the reverse trans-spec raises FunctionNotDefined
18+
# at evaluation time. xfail the reverse-direction tests until the dep
19+
# constraint can be bumped to >= 0.5.3.
20+
_HAS_TYPE_PREDICATES = "is_str" in _LINKML_MAP_FUNCTIONS
21+
_REVERSE_REQUIRES_LINKML_MAP_053 = pytest.mark.xfail(
22+
not _HAS_TYPE_PREDICATES,
23+
reason="Reverse adapter trans-spec requires linkml-map >= 0.5.3 "
24+
"(is_str / is_bool / is_list type predicates)",
25+
strict=True,
26+
raises=Exception,
27+
)
28+
29+
1430
# ----------------------------------------------------------------------
1531
# Forward direction (Frictionless → DD) — driven by the trans-spec.
1632
# ----------------------------------------------------------------------
@@ -177,6 +193,7 @@ def test_real_world_finance_vix(self):
177193
# ----------------------------------------------------------------------
178194

179195

196+
@_REVERSE_REQUIRES_LINKML_MAP_053
180197
class TestDDToFrictionless:
181198
def test_minimal_field(self):
182199
source = {"entries": [{"name": "x", "type": "string", "description": "y"}]}

0 commit comments

Comments
 (0)