Python API reference
The Python API of the queria package
queria also ships a Python package for reading Queria’s data. Read the catalog and run queries from notebooks and scripts, no subprocess required.
Overview
import queria
# what is published, and what is in it
queria.list_datasets()
queria.tables("calendar")
queria.columns("calendar", "mart_calendar")
# the data itself
with queria.connect() as conn:
# referenced datasets are attached automatically
df = conn.sql("""
SELECT date, holiday_name
FROM calendar.main.mart_calendar
WHERE is_holiday AND date >= DATE '2026-01-01'
""").df()
The catalog functions and connect() are independent. The first ask queria.io over HTTP; the second opens a DuckLake connection to data.queria.io. Listing datasets opens no connection.
Connection.sql() returns DuckDB’s DuckDBPyRelation, so DuckDB’s standard APIs work as-is: .df() (pandas), .pl() (Polars), .arrow(), .fetchall(), and more.
Stability
The official API is:
- The catalog functions
queria.list_datasets()/search()/info()/tables()/columns(), and thequeria.CatalogErrorexception queria.connect()and the public methods ofConnection(sql/execute/attach/close)- The constants
queria.DEFAULT_STORAGE(the default catalog base URL) andqueria.__version__
The dicts the catalog functions return keep every key listed in the tables below. Keys may be added. Some keys, such as licenses, are absent when the dataset declared none, so read them with row.get(...).
The declaration info() and tables() return follows the dataset.yml and *.table.yml you write to publish a dataset (see Publishing a dataset).
Everything else inside the modules may change without notice.
Catalog
queria.list_datasets()
queria.list_datasets(
*,
limit: int | None = None,
token: str | None = None,
) -> list[dict]
Returns every dataset you can read: the public ones anonymously, plus your own private ones when a token is in play. Without limit you get all of them, following the pages when there are more than one request returns.
import pandas as pd
pd.DataFrame(queria.list_datasets())
Keys of a row:
| Key | Description |
|---|---|
handle |
The account that published it |
name |
The dataset name — what you write as <name>.<schema>.<table> in SQL |
qualified_name |
<handle>/<name> |
title / description |
Title and description |
keywords |
Array of keywords |
licenses |
Array of licences. Absent entirely when none were declared |
visibility |
public or private |
catalog_url |
URL of the DuckLake catalog |
page_url |
The dataset’s page on queria.io |
bytes |
Total size of the published data |
updated_at |
When it was last published |
queria.search()
queria.search(
keyword: str | None = None,
*,
entry_type: str | None = None,
limit: int = 50,
columns: Sequence[str] = (),
keys: Sequence[str] = (),
geo: bool = False,
token: str | None = None,
) -> dict
Searches across datasets, tables and columns. Only entries containing every whitespace-separated word come back, so adding a word narrows the result. entry_type takes dataset, table or column to keep just one kind.
columns, keys and geo narrow by the columns a table holds, with the same meaning as --column, --key and --geo on queria search. With any of them, keyword may be left out.
queria.search(columns=["町丁目", "人口"]) # tables with a town block column and a population column
queria.search("park", keys=["city"], geo=True)
The result has three keys:
| Key | Description |
|---|---|
datasets |
The datasets that matched, shaped like list_datasets() rows |
entries |
The tables and columns that matched: entry_type / qualified_name / schema_name / table_name / column_name / title / description |
has_more |
Whether limit is what ended the list |
queria.info()
queria.info(name: str, *, token: str | None = None) -> dict
Returns one dataset’s catalog row together with the declaration it published.
| Key | Description |
|---|---|
dataset |
A row shaped like list_datasets() returns |
declaration |
The published declaration. Licences, sources, update frequency, and the tables with their columns are all in here |
name takes either a dataset name (e_stat) or one qualified with the account (queria/e_stat). When more than one account publishes the name, the dataset name alone does not decide it: you get an error naming the candidates.
queria.tables()
queria.tables(name: str, *, token: str | None = None) -> list[dict]
Returns the tables that are published. Tables the declaration describes but does not publish are left out.
Each entry is the declaration’s own definition of that table, so schema and name address it and the columns are nested under fields. Use columns() to get those flat.
queria.columns()
queria.columns(
name: str,
table: str | None = None,
*,
token: str | None = None,
) -> list[dict]
Returns the columns of the published tables as a flat list. Pass table to narrow it to one.
Each record is the declaration’s column definition (name / type / description, plus title / nullable / index / semantic when declared) with schema_name and table_name added. An unknown table name is an error.
The token
Every catalog function takes token. Left out, it is resolved the way the CLI resolves it: the QUERIA_TOKEN environment variable, then the config file queria login writes.
A token changes the answer here, because authenticating adds your private datasets to the result. To read only the public catalog on a machine that has a token saved, pass token="".
The token on connect() is the same value. It is attached to requests to the storage, where it raises the rate limits, and it is also what looks up the owner of a private dataset when attaching one (see Authentication).
Connecting
queria.connect()
queria.connect(
storage: str = "https://data.queria.io",
*,
user_agent: str | None = None,
token: str | None = None,
api_url: str | None = None,
) -> Connection
Opens a connection to Queria’s public catalogs.
| Argument | Description |
|---|---|
storage |
Base URL (or local path) of the catalog storage |
user_agent |
HTTP User-Agent reported to the storage. Defaults to queria-python/<version> |
token |
API token attached as a Bearer Authorization header to every request to the storage. Raises the rate limits, and lets you attach your own private datasets (see Authentication) |
api_url |
Base URL of queria.io, used to look up which account owns a dataset name. You normally leave this out. Pointing storage somewhere other than the default without this leaves qualified names unresolved, treated as short ones |
On connect, it loads the ducklake / httpfs extensions. Datasets are attached on first reference.
Connection
Use it as a context manager to guarantee the underlying duckdb connection is closed:
with queria.connect() as conn:
conn.sql("SELECT * FROM calendar.main.mart_calendar LIMIT 10").show()
Connection.sql()
Connection.sql(query: str) -> duckdb.DuckDBPyRelation
Runs a query. Any dataset the query references that isn’t connected yet is attached automatically.
Connection.execute()
Connection.execute(query: str) -> None
Runs a statement that returns no result (such as COPY). Like sql(), it auto-attaches referenced datasets.
Connection.attach()
Connection.attach(dataset: str) -> None
Explicitly attaches a dataset by name (idempotent). Normally the auto-attach in sql() is all you need.
Takes both a short name such as sales and a qualified one such as alice/sales. A short name is looked up on queria.io to find its owner, so when two accounts publish the same name, write the handle as well (a short name raises instead, naming the candidates).
The name you use in SQL is the short one either way: after attaching alice/sales, write sales.main.…. Two different datasets cannot share one short name in the same connection.
To attach a private dataset, pass a token to connect(token=...). Without one, that dataset is treated as not existing.
Connection.close()
Connection.close() -> None
Closes the underlying duckdb connection.
