ds-fetch-py-sdk
Python SDK for AI Commons Fetch: read-only SQL over your tenant's data lake, plus natural-language questions through ds-tools. For the command line, see ds-fetch-cli.
uv add ds-fetch-py-sdk # or: pip install ds-fetch-py-sdk
uv add 'ds-fetch-py-sdk[pandas]' # adds QueryResult.to_pandas()
Quick start
from ds_fetch_py_sdk import Fetch
with Fetch("dev") as fetch: # signs in with the browser on first use
for ds in fetch.datasets():
print(ds.name, ds.row_count, [c.name for c in ds.columns])
result = fetch.query("""
SELECT department, count(*) AS n
FROM gold."5003105c-8a84-5f77-ab74-5e57003112b8"
GROUP BY department
""")
print(result.records()) # [{'department': 'engineering', 'n': 1520}, ...]
answer = fetch.ask("Headcount per department?", datasets=[ds.name])
print(answer.sql, answer.rows)
Environments
| Name | Fetch API | Identity server |
|---|---|---|
local |
http://localhost:8080/api/fetch-dev/v1 |
https://auth-dev.grasp-daas.com |
dev |
https://grasp-daas.com/api/fetch-dev/v1 |
https://auth-dev.grasp-daas.com |
prod (default) |
https://grasp-daas.com/api/fetch/v1 |
https://auth.grasp-daas.com |
Pick one with Fetch("local") or AIC_ENV=local. Override single URLs with AIC_FETCH_URL,
AIC_TOOLS_URL and AIC_ISSUER, or pass your own Environment(...). Every URL must use HTTPS,
except on localhost, so tokens and passwords never travel in clear text.
API docs: prod ·
dev ·
local.
Authentication
| Method | Code | Environment |
|---|---|---|
| Bearer token | Fetch(token="eyJ…") |
AIC_TOKEN |
| Client credentials | Fetch(auth=ClientCredentials(id, secret)) |
AIC_CLIENT_ID, AIC_CLIENT_SECRET |
| Email and password | Fetch(auth=PasswordLogin(email, password)) |
AIC_EMAIL, AIC_PASSWORD, AIC_MFA_CODE |
| Browser sign-in / SSO | Fetch(auth=BrowserLogin()) |
default |
Local and dev sign in at the dev identity server, prod at prod's. Without arguments the client checks the environment variables in that order, then a cached session, then falls back to browser sign-in.
PasswordLogin posts to the identity server's /auth/login/. For accounts with MFA, pass
mfa_code= as a code or as a callable that takes the number of digits and returns the code. It
refreshes with /auth/token/refresh/ and caches the session like browser sign-in, but never the
password.
Every flow signs in at the environment's issuer, never at one a server names. OAuth flows read
its endpoints from RFC 8414 metadata, which must name that issuer and use HTTPS, and bind tokens
to Fetch with resource (RFC 8707). Browser sign-in uses authorization code + PKCE on
http://127.0.0.1:8976/callback, registers a public client on first use (RFC 7591), and offers
whatever SSO your tenant has configured. Sessions are cached in ~/.config/aic/credentials.json,
replaced atomically as a mode-600 file. Pass on_url= to show the sign-in URL your own way.
Expired tokens are refreshed, and a 401 triggers one renewal and retry.
Querying
query(sql, fresh=False)runs oneSELECTand returns aQueryResultwithcolumns,rows,records(),to_pandas(),truncated,elapsed_ms,cacheandrequest_id.fresh=Truereads S3 as it is now, bypassing the index and cache.validate(sql)checks oneSELECTasquerywould, without reading data, and returns aValidationwith the canonicalsql, thedatasetsit reads and the resultcolumns. Invalid SQL raisesQueryError, exactly as a query does.datasets(names=..., layers=..., limit=...)iterates every granted dataset across pages, or only the names and layers (gold,silver,bronze) you ask for;dataset(name)returns one.Dataset.refis the name quoted for SQL, andfile_count,row_countandbyte_sizesize the partitions you may read (rows and bytes for gold only).limit(default 100, at mostMAX_LIMIT= 500) is the page size: the server describes every dataset on a page within its timeout, so preferlayers=["gold"]over a large page. An unknown layer raisesValueError.sql(question, datasets=...)translates a question to SQL with ds-tools;ask(...)also runs it.tools.list(),tools.get(id)andtools.invoke(id, input)reach every ds-tools tool with the same sign-in.
validate, datasets and dataset are lookups: they have their own rate-limit budget, never
spend query allowance, and take no concurrency slot.
Retries follow the API contract: connection failures, timeouts, 429, 500, 503 and 5xx responses
without a JSON body are retried up to 3 attempts with exponential backoff, jitter and Retry-After. Everything else raises at once.
Errors
All errors derive from AICError.
| Exception | When |
|---|---|
AuthError |
Sign-in or token acquisition failed |
NetworkError |
The API could not be reached or timed out, after retries |
APIError |
The API returned an error; has status, code, message, request_id, retry_after |
QueryError |
The SQL was rejected (422); details lists each problem, e.g. unknown_column |
Pass language="nb" for Norwegian error messages.
License
Apache 2.0
Metadata
Release files for ds-fetch-py-sdk 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ds_fetch_py_sdk-1.1.0.tar.gz | 24.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ds_fetch_py_sdk-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 46.0 kB
Release files / ds_fetch_py_sdk-1.1.0.tar.gz
| Download URL | ds_fetch_py_sdk-1.1.0.tar.gz |
|---|---|
| Size | 24.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1c5505502959045cb4badde2f35787913782880f1058d310e115088c28d16688
|
|
BLAKE2b-256 checksum How to use checksums |
1c5585a798dedaee7ab9a56b5f7f563bbabe1590126b8c653736b399344e3b13
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logRelease files / ds_fetch_py_sdk-1.1.0-py3-none-any.whl
| Download URL | ds_fetch_py_sdk-1.1.0-py3-none-any.whl |
|---|---|
| Size | 21.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1a4dfd6a3a9520b6dfa75dda79561d3821d9296629caea2dbf98861f0056859d
|
|
BLAKE2b-256 checksum How to use checksums |
c2ef876f95fe3f0920689571723546c7d4e615fb18deadb58b91bd9a9476a408
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logSecurity for ds-fetch-py-sdk 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ds_fetch_py_sdk-1.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.