Query Dune Analytics with Ibis table expressions (Trino + automatic REST fallback)
Project description
ibis-dune
Ibis backend for Dune Analytics.
Overview
ibis-dune lets you query Dune with Ibis table expressions: build filters, joins, and aggregates in Python, compile them to Dune SQL, and execute on Trino (trino.api.dune.com). When your API plan cannot use Trino, the backend automatically falls back to Dune REST /sql/execute and keeps results consistent across both paths.
The backend handles Dune-specific concerns that plain Trino backends do not:
- Schema discovery —
get_schema()and schema-lesssql()infer column types without hand-written schemas - uint256 and varbinary — large integers and binary columns round-trip correctly in pandas, PyArrow, and rich previews
- Dune SQL helpers —
hex_literal,raw_predicate, andraw_scalarfor fragments Ibis cannot express natively - Typed errors —
DuneQueryErrorandDuneResultTooLargeErrorat the execution boundary
Install
ibis-frameworkfrom PyPI, not the legacyibispackage. Both import asibisand cannot coexist.
Install
Requires Python 3.11+.
pip install ibis-dune
This pulls in ibis-framework[trino] (12.x), dune-client (>=1.10), and sqlglot (>=26.4).
You need a Dune API key for live queries. Free-tier keys (no Trino access) work out of the box — the backend automatically falls back to REST when Trino rejects the performance tier. You do not need force_api=True.
Usage
import ibis
con = ibis.dune.connect(dune_api_key="YOUR_DUNE_API_KEY")
Or import the backend directly:
from ibis_dune import Backend
con = Backend().connect(dune_api_key="YOUR_DUNE_API_KEY")
By default queries run on Trino. If Trino rejects the performance tier, the backend switches to REST for that session. Call con.reset_to_trino() to try Trino again. Pass force_api=True to start on REST.
Connection options
Backend().connect() / ibis.dune.connect() accept:
| Parameter | Default | Purpose |
|---|---|---|
dune_api_key |
(required) | Dune API key |
force_api |
False |
Start on REST instead of Trino |
dune_sql_performance |
"medium" |
REST /sql/execute performance tier |
dune_api_warning_bytes |
1 GiB |
Log a warning when REST result exceeds this size |
dune_api_max_bytes |
4 GiB |
Refuse to fetch REST results larger than this |
After connect, con.uses_api is True when execution is routed through REST (either force_api=True or tier-triggered fallback). con.reset_to_trino() clears tier-triggered fallback but does not override force_api.
Example
import ibis
con = ibis.dune.connect(dune_api_key="YOUR_DUNE_API_KEY")
t = con.sql("SELECT CAST(42 AS BIGINT) AS n")
print(t.execute())
When querying Dune tables directly, always keep scans bounded — filter partitions and add .limit():
from ibis import _
t = (
con.table("logs", database="ethereum")
.filter(_.block_date == ibis.literal("2015-08-08", type="date"))
.select("block_number", "index", "data")
.limit(5)
)
print(t.execute())
Dune SQL helpers
Dune-specific SQL fragments compile through the backend compiler:
from ibis import _
from ibis_dune.ops import hex_literal, raw_predicate, raw_scalar
t = con.table("enterprise_evt_rented", database="iq_protocol_polygon")
t = t.filter(_.contract_address == hex_literal("0xbf9f6b1d910aa207daa400931430ef110570f8ff"))
t = t.filter(raw_predicate("evt_block_number > 1000"))
t = t.select(probe=raw_scalar("CAST(42 AS BIGINT)", "int64")).limit(5)
hex_literal— validated hex string literal (DuneHEXsyntax)raw_predicate— verbatim Trino SQL boolean filterraw_scalar— verbatim Trino SQL expression with an explicit ibis dtype
Errors
DuneQueryError— wraps Trino and REST query failures at the execution boundaryDuneResultTooLargeError— raised when a REST result exceedsdune_api_max_bytes
Development
git clone https://github.com/Firlej/ibis-dune.git
cd ibis-dune
python3 -m venv venv
source venv/bin/activate
pip install -e ".[dev]"
Offline tests (CI gate, no API key):
pytest -m "not integration and not trino and not parity_mock" -q
For integration tests against live Dune, copy tests/.env.example to tests/.env and set DUNE_API_KEY.
See CONTRIBUTING.md for test tiers, fixture refresh, and local workflow details.
To build and validate a release artifact locally:
python -m build
twine check dist/*
See UPSTREAM.md for upstream merge notes and publishing workflow.
License
Apache-2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ibis_dune-0.1.1.tar.gz.
File metadata
- Download URL: ibis_dune-0.1.1.tar.gz
- Upload date:
- Size: 29.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b94796bfea273972a5eeb634c7a5b05c6b70fa359636ee80fbaf048265f469f
|
|
| MD5 |
00e7c7d2bf01ee8b8ce0c0ca38c05383
|
|
| BLAKE2b-256 |
455e8dcfb21e86ab31c6c24e7892f2fbeaf937b5e5185667d8f5910b74bc6482
|
File details
Details for the file ibis_dune-0.1.1-py3-none-any.whl.
File metadata
- Download URL: ibis_dune-0.1.1-py3-none-any.whl
- Upload date:
- Size: 24.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
622959e01e25c6c2a4e906f35a1c04ace7163c64acb03ac2b17b37510055f497
|
|
| MD5 |
7c806d848a577d79341f7277da344be6
|
|
| BLAKE2b-256 |
b3221369985a9e97b3ff1e4f4355b6e1005fbff382f94b8f16dd84f2df3b2b14
|