Scopes¶
Generated from the docstrings. Scopes are the graph-traversal entry points a
Catalog exposes, such as cat.themes and cat.codelists.
DatasetScope ¶
Scope for a single dataset — enables graph navigation.
Entry point: store.dataset("housing-stats").
Navigation::
ds = store.dataset("housing-stats")
ds.codelists # CodelistsScope
ds.themes # ThemesScope
ds.related("codelist") # list[BaseDataset]
ds.upstream(depth=5) # list[BaseDataset]
ds.downstream() # list[BaseDataset]
ds.lineage_records() # list[dict]
codelists
property
¶
Navigate to codelists used by this dataset (lazy).
Resolves via the dataset's SDMX dataflow → DSD → codelist URNs.
themes
property
¶
Navigate to themes (concepts) assigned to this dataset (lazy).
related ¶
Datasets sharing an entity via edge type.
Returns a lazy QueryBuilder — chain .include(), .filter(),
.limit(), .collect() etc. before materializing.
Gremlin equivalent: g.V(id).out(edge).in(edge).dedup()
Supported edges: "codelist".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge
|
str
|
The kind of entity the datasets share. |
required |
Returns:
| Type | Description |
|---|---|
QueryBuilder[BaseDataset]
|
A query over the datasets linked to this one through edge. |
Raises:
| Type | Description |
|---|---|
ValueError
|
edge is not a supported edge type. |
Example
store.dataset("id").related("codelist").include("publisher").limit(10).collect()
upstream ¶
Transitive ancestors via lineage (recursive CTE).
Returns a lazy QueryBuilder — chain .include(), .filter(),
.limit(), .collect() etc. before materializing.
Gremlin equivalent: g.V(id).repeat(in('derivedFrom')).times(depth)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
relationship
|
str | None
|
Follow only lineage edges of this relationship; all of them when |
None
|
depth
|
int
|
How many lineage hops to follow. |
10
|
Returns:
| Type | Description |
|---|---|
QueryBuilder[BaseDataset]
|
A query over this dataset's ancestors, to depth hops. |
Example
store.dataset("id").upstream(depth=3).include("publisher").collect()
downstream ¶
Transitive descendants via lineage (recursive CTE).
Returns a lazy QueryBuilder — chain .include(), .filter(),
.limit(), .collect() etc. before materializing.
Gremlin equivalent: g.V(id).repeat(out('derivedFrom')).times(depth)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
relationship
|
str | None
|
Follow only lineage edges of this relationship; all of them when |
None
|
depth
|
int
|
How many lineage hops to follow. |
10
|
Returns:
| Type | Description |
|---|---|
QueryBuilder[BaseDataset]
|
A query over this dataset's descendants, to depth hops. |
Example
store.dataset("id").downstream().include("publisher").collect()
lineage_records ¶
lineage_records(
*,
role: str = "either",
relationship: str | None = None,
confidence: str | None = None,
) -> list[dict[str, object]]
Return lineage rows involving this dataset as plain dicts.
DatasetsScope ¶
Search across the catalog's datasets.
Entry point: cat.datasets. Replaces the older cat.search /
cat.semantic_search / cat.hybrid_search triple — now a
single find(query, mode=...) returning
SearchResult[Hit[BaseDataset]].
find ¶
find(
query: str,
*,
mode: str = "bm25",
lang: str = "en",
limit: int = 50,
offset: int = 0,
operator: str = "or",
fuzzy: int = 0,
rrf_k: int = 60,
oversample: int = 200,
) -> SearchResult[Hit[BaseDataset]]
Search datasets; returns Hit objects wrapping BaseDataset.
ThemesScope ¶
Scope over all SKOS concept schemes in the catalog.
Entry point: store.themes.
collect ¶
Terminal: all concept scheme handles.
A plain list, not an ItemList: a SchemeScope is keyed by
scheme URI and has no id, so it never satisfied what an
item list is for. Use store.themes[uri] to address one.
SchemeScope ¶
Scope over concepts within a single SKOS concept scheme.
Entry point: store.themes["https://example.com/themes"].
The scheme field is the scheme URI.
datasets
property
¶
Navigate to datasets tagged with any concept in this scheme (lazy).
Returns a QueryBuilder pre-filtered to datasets citing concepts
from this scheme.
collect ¶
Terminal: materialize concepts in this scheme as ConceptRef objects.
Use .rows() for enriched tabular results after .enrich().
resolve ¶
Terminal: fully hydrate the scheme including all its concepts.
labels ¶
Return {notation: display_label} for concepts in this scheme.
enrich ¶
Add computed fields. Returns new scope (lazy).
filter ¶
Keep items where expressions are truthy. Returns new scope (lazy).
sort_by ¶
Order items by expression. Returns new scope (lazy).
ConceptsScope ¶
Search and direct lookup over indexed SDMX Concept rows.
Entry point: cat.concepts. Concepts carry definitional text in
sdmx.concept.description — the single highest-value vector
target in an SDMX catalog, since a query like "income inequality"
finds "Gini coefficient" through its definition rather than its
label.
find ¶
find(
query: str,
*,
scheme_urn: str | Sequence[str] | None = None,
mode: str = "bm25",
lang: str = "en",
limit: int = 20,
offset: int = 0,
operator: str = "or",
fuzzy: int = 0,
rrf_k: int = 60,
oversample: int = 200,
) -> SearchResult[Hit[ConceptHit]]
Search concept rows; returns Hit objects wrapping ConceptHit.
ConceptScope ¶
Scope for a single concept within a scheme, identified by notation.
Entry point: store.themes["https://example.com/themes"]["13"].
CodelistsScope ¶
Scope over all codelists in the shared structural tables.
Entry point: store.codelists.
lang ¶
Set language for label resolution. Returns new scope (lazy).
filter ¶
Filter codelists by label text (case-insensitive). Returns new scope (lazy).
collect ¶
Terminal: all codelists as scope handles.
Use .rows() for enriched tabular results after .enrich().
batch_labels ¶
Terminal: resolve labels for (codelist_urn, code_id) pairs in one query.
Returns a dict mapping (urn, code_id) → label. Falls back to the
code ID itself when the requested language has no entry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pairs
|
list[tuple[str, str]]
|
Sequence of |
required |
lang
|
str | None
|
Language code; defaults to the scope's |
None
|
Returns:
| Type | Description |
|---|---|
dict[tuple[str, str], str]
|
|
dict[tuple[str, str], str]
|
A pair with no label in lang falls back to its code id. |
enrich ¶
Add computed fields. Returns new scope (lazy).
CodelistScope ¶
Scope for a codelist identified by URN.
Entry point: store.codelist("urn:...:CL_GEO(1.0)")
or store.codelists["urn:...:CL_GEO(1.0)"].
datasets
property
¶
Navigate to datasets using this codelist (lazy).
lang ¶
Set language for code label resolution. Returns new scope (lazy).
collect ¶
Terminal: resolve codelist and return all codes.
Use .rows() for enriched tabular results after .enrich().
label ¶
Terminal: human-readable label for this codelist in lang.
Resolves via the sdmxlib localized_text table.
batch_labels ¶
Terminal: resolve labels for code_ids in a single SQL query.
Returns a dict mapping code_id → label. Falls back to the
code ID itself when the requested language has no entry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code_ids
|
list[str]
|
Code IDs to resolve (e.g. |
required |
lang
|
str | None
|
Language code; defaults to the scope's |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
|
dict[str, str]
|
label in lang falls back to the id itself. |
enrich ¶
Add computed fields to per-code results. Returns new scope (lazy).
CodesScope ¶
Search and direct lookup over indexed SDMX code rows.
Entry point: cat.codes. Wraps the BM25/vector/hybrid paths
against entity_type="code" rows in the Lance index, plus a
pure-SQL get(code_urn) for cases where the URN is already known.
find ¶
find(
query: str,
*,
codelist_urn: str | Sequence[str] | None = None,
dataset_ids: Sequence[str] | None = None,
mode: str = "bm25",
lang: str = "en",
limit: int = 20,
offset: int = 0,
operator: str = "or",
fuzzy: int = 0,
rrf_k: int = 60,
oversample: int = 200,
) -> SearchResult[Hit[CodeHit]]
Search code rows; returns Hit objects wrapping CodeHit.
mode is one of "bm25" (default; Tantivy FTS), "vector"
(cosine over embeddings — requires an embedding model, returns
nothing for FTS-only codelists), or "hybrid" (RRF merge of
the two).
get ¶
Direct SQL lookup of a single code by URN — no Lance index involved.
Resolves the code's labels in any one language present
(default: prefer en, fall back to whichever language has
the label). For multi-language access, fetch the underlying
sdmx.code row directly.
CodeScope ¶
DimensionsScope ¶
DimensionScope ¶
DimensionInfo ¶
Plain data object describing a dimension of a dataset.
It has no lazy properties; navigate to the codelist through
DimensionScope.codelist.
Mutable rather than frozen so it satisfies sdmxlib's SupportsId,
the bound on ItemList[T] since 0.61 — a protocol declaring a
writable id, which a frozen attrs class cannot provide. This is
also the project convention (CLAUDE.md: domain objects use @define
and copy with attrs.evolve()); the frozen spelling was the outlier.
ReferenceMetadataScope ¶
Search over indexed SDMX reference-metadata sections.
Entry point: cat.reference_metadata. Where EditionView.codes
searches short controlled-vocabulary labels, this searches the prose of
methodology documents — reference guides, quality reports — indexed one
chunk per section. Hits carry set_urn / attribute_path so a
caller can pull the full typed section via
EditionView.metadata_report or resolve the artefacts the document
describes.
target_urn scopes the search to metadata attached to a given
artefact — the semantic-search analogue of EditionView.metadata_for.
find ¶
find(
query: str,
*,
target_urn: str | None = None,
mode: str = "bm25",
lang: str = "en",
limit: int = 20,
offset: int = 0,
operator: str = "or",
fuzzy: int = 0,
rrf_k: int = 60,
oversample: int = 200,
) -> SearchResult[Hit[ReferenceMetadataHit]]
Search reference-metadata section chunks.
target_urn restricts results to sections whose MetadataSet
targets that artefact URN — resolved via
EditionView.metadata_for, so a semantic hit and its structured
resolution stay consistent. Other arguments mirror the code/concept
scopes (mode, lang, limit, offset, operator,
fuzzy, rrf_k, oversample).
Expressions¶
expr ¶
Sub-traversal expression language for scope-based graph queries.
Expressions describe computations over related graph data without executing
any SQL. They are context-free objects — like pl.col() in Polars — and
can be reused across .enrich(), .filter(), and .sort_by() on any
collection scope.
Usage:
import statcatlib as sc
n_datasets = sc.each("datasets").count()
has_data = sc.each("datasets").exists()
store.themes["subjects"].enrich(n=n_datasets).filter(has_data).collect()
Expr ¶
Base class for all expression nodes.
TraversalExpr ¶
Bases: Expr
A traversal along one or more edges from the current scope position.
Created by sc.each("edge1", "edge2", ...). Strings are always
edge labels (table names or relationship names in the graph).
AliasedExpr ¶
An expression with a named output column.
Created by expr.alias("name") or via **kwargs in .enrich().
FilteredExpr ¶
Bases: Expr
A traversal with far-side filtering applied.
Created by sc.each("datasets").filter(status="current").
each ¶
Create a sub-traversal expression starting from the current scope.
Each argument is an edge label (relationship name). Multiple arguments describe a multi-hop path::
sc.each("datasets") # one hop
sc.each("datasets", "dimensions") # two hops
sc.each("datasets", "dimensions", "codelist") # three hops
The returned expression is context-free and can be used in .enrich(),
.filter(), and .sort_by() on any collection scope.