sdmxlib 0.19.2__tar.gz → 0.20.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/PKG-INFO +1 -1
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/pyproject.toml +1 -1
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/code_query.py +60 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/README.md +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/api/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/api/client.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/api/federated.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/api/filters.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/api/policy.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/api/providers.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/api/query.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/api/registry.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/api/session.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/catalog.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/data_store.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_csv/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_csv/reader.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_csv/writer.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_json/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_json/metadata.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_json/reader.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_json/writer.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_ml21/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_ml21/namespaces.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_ml21/reader.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_ml21/writer.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_ml30/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_ml30/metadata.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_ml30/namespaces.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_ml30/reader.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/formats/sdmx_ml30/writer.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/local/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/local/_data_store.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/local/_registry.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/annotations.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/base.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/binding.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/category.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/codelist.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/collections.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/concept.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/constraint.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/convert.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/dataflow.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/dataset.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/datastructure.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/expr.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/hierarchy.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/in_memory_registry.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/istring.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/mapping.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/message.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/metadataflow.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/metadataset.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/metadatastructure.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/organisation.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/provision.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/ref.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/registry.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/representation.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/urn.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/model/validation.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/polars.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/py.typed +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/rest.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/storage/__init__.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/storage/lazy.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/storage/readers.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/storage/schema.py +0 -0
- {sdmxlib-0.19.2 → sdmxlib-0.20.0}/src/sdmxlib/storage/writers.py +0 -0
|
@@ -145,6 +145,23 @@ class _AnyAncestorMatches(Predicate):
|
|
|
145
145
|
depth: int | None = None
|
|
146
146
|
|
|
147
147
|
|
|
148
|
+
@attrs.frozen
|
|
149
|
+
class _InHierarchy(Predicate):
|
|
150
|
+
"""The code is a node in a Hierarchy, optionally at a named Level.
|
|
151
|
+
|
|
152
|
+
Compiles to ``EXISTS`` against ``sdmx.hierarchy_node`` joined on
|
|
153
|
+
``code_urn``. EXISTS (rather than INNER JOIN) preserves row identity
|
|
154
|
+
when a code appears at multiple nodes in the same hierarchy.
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
hierarchy_urn: str
|
|
158
|
+
level_id: str | None = None
|
|
159
|
+
|
|
160
|
+
def level(self, level_id: str) -> _InHierarchy:
|
|
161
|
+
"""Narrow membership to a named Level within the same Hierarchy."""
|
|
162
|
+
return attrs.evolve(self, level_id=level_id)
|
|
163
|
+
|
|
164
|
+
|
|
148
165
|
# ── Sort keys ───────────────────────────────────────────────────────────
|
|
149
166
|
|
|
150
167
|
|
|
@@ -328,6 +345,26 @@ class _CodeAccessor:
|
|
|
328
345
|
"""Sub-query ref for descendants. Use ``.any(predicate)`` to compose."""
|
|
329
346
|
return _NarrowerTransitiveSubRef(depth=depth)
|
|
330
347
|
|
|
348
|
+
def hierarchy(self, hierarchy: object) -> _InHierarchy:
|
|
349
|
+
"""Predicate: code is a node in ``hierarchy``.
|
|
350
|
+
|
|
351
|
+
Accepts a URN string or any artefact with a maintainable URN
|
|
352
|
+
(e.g. a :class:`Hierarchy`). Chain ``.level(level_id)`` to narrow
|
|
353
|
+
to nodes at a specific Level:
|
|
354
|
+
|
|
355
|
+
q.filter(code.hierarchy(h).level("Province"))
|
|
356
|
+
|
|
357
|
+
Compiles to a single ``EXISTS`` against ``sdmx.hierarchy_node`` —
|
|
358
|
+
no row multiplication when a code appears at multiple nodes.
|
|
359
|
+
"""
|
|
360
|
+
if isinstance(hierarchy, str):
|
|
361
|
+
urn = hierarchy
|
|
362
|
+
else:
|
|
363
|
+
from sdmxlib.model.in_memory_registry import artefact_urn # noqa: PLC0415
|
|
364
|
+
|
|
365
|
+
urn = str(artefact_urn(hierarchy))
|
|
366
|
+
return _InHierarchy(hierarchy_urn=urn, level_id=None)
|
|
367
|
+
|
|
331
368
|
|
|
332
369
|
code = _CodeAccessor()
|
|
333
370
|
"""Predicate accessor namespace — exposed at the top level as ``sl.code``."""
|
|
@@ -633,10 +670,33 @@ def _emit_predicate(
|
|
|
633
670
|
return _emit_any_ancestor_matches(pred, row_alias=row_alias)
|
|
634
671
|
if isinstance(pred, _AnyDescendantMatches):
|
|
635
672
|
return _emit_any_descendant_matches(pred, row_alias=row_alias)
|
|
673
|
+
if isinstance(pred, _InHierarchy):
|
|
674
|
+
return _emit_in_hierarchy(pred, row_alias=row_alias)
|
|
636
675
|
msg = f"Unsupported predicate kind: {type(pred).__name__}"
|
|
637
676
|
raise NotImplementedError(msg)
|
|
638
677
|
|
|
639
678
|
|
|
679
|
+
def _emit_in_hierarchy(pred: _InHierarchy, *, row_alias: str) -> tuple[str, list[object]]:
|
|
680
|
+
"""Compile a Hierarchy/Level membership predicate to an EXISTS clause."""
|
|
681
|
+
inner = f"{row_alias}_hn"
|
|
682
|
+
if pred.level_id is None:
|
|
683
|
+
clause = (
|
|
684
|
+
f"EXISTS ("
|
|
685
|
+
f"SELECT 1 FROM sdmx.hierarchy_node {inner} "
|
|
686
|
+
f"WHERE {inner}.code_urn = {row_alias}.code_urn "
|
|
687
|
+
f"AND {inner}.hierarchy_urn = ?)"
|
|
688
|
+
)
|
|
689
|
+
return clause, [pred.hierarchy_urn]
|
|
690
|
+
clause = (
|
|
691
|
+
f"EXISTS ("
|
|
692
|
+
f"SELECT 1 FROM sdmx.hierarchy_node {inner} "
|
|
693
|
+
f"WHERE {inner}.code_urn = {row_alias}.code_urn "
|
|
694
|
+
f"AND {inner}.hierarchy_urn = ? "
|
|
695
|
+
f"AND {inner}.level_id = ?)"
|
|
696
|
+
)
|
|
697
|
+
return clause, [pred.hierarchy_urn, pred.level_id]
|
|
698
|
+
|
|
699
|
+
|
|
640
700
|
def _emit_eq(
|
|
641
701
|
pred: _Eq,
|
|
642
702
|
*,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|