Skip to main content

pyoso SDK

pyoso is the Python client for querying the OSO data warehouse. It sends read-only Trino SQL to the OSO API and returns results as pandas DataFrames, with optional analytics metadata about how each table was built.

pyoso is the query client, not the modeling SDK

pyoso (from pyoso import Client) reads data out of the warehouse. It is a different surface from the import oso / @oso.model SDK used to author User-Defined Models (UDMs). Do not conflate them: use pyoso to run queries, and the import oso SDK to define models. For authoring models, see the Data modeling tutorial.

Install

pip install pyoso

For the optional semantic-modeling layer (see below), install the extra:

pip install pyoso[semantic]

Client

from pyoso import Client

client = Client()

Client() reads your API key from the OSO_API_KEY environment variable. You can also pass it explicitly:

client = Client(api_key="your_api_key")

If no key is found in the environment or arguments, the constructor raises an error. Point the client at a non-default API host with client_opts:

from pyoso import Client
from pyoso.client import ClientConfig

client = Client(client_opts=ClientConfig(base_url="https://api.oso.xyz/v1/"))

client.to_pandas(query)

Runs a single SQL statement and returns the result as a pandas.DataFrame. This is the everyday method for pulling data.

df = client.to_pandas("SELECT * FROM oso.projects_v1 LIMIT 5")
print(df)

Only a single statement is supported per call — no semicolon-separated batches or multiple queries.

client.query(query)QueryResponse

Runs a query and returns a QueryResponse object carrying both the data and analytics metadata. Use it when you want to inspect data provenance and freshness alongside the results.

response = client.query("SELECT * FROM oso.artifacts_v1 LIMIT 5")

df = response.to_pandas() # same DataFrame as to_pandas()
response.analytics # DataAnalytics for the query's dependency tree
response.data # raw QueryData (columns + rows)

QueryResponse members:

  • response.to_pandas() — convert the result rows to a DataFrame.
  • response.analytics — a DataAnalytics object (see below).
  • response.data — the raw QueryData (.columns and .data).

response.analytics.print_tree()

response.analytics is a DataAnalytics object that models the dependency tree of the tables your query touched — how each was constructed from upstream sources and how fresh it is. print_tree() renders that tree to stdout.

response = client.query("SELECT * FROM oso.artifacts_v1 LIMIT 5")
response.analytics.print_tree()

Other useful members:

  • analytics.root_keys — top-level nodes in the dependency tree.
  • analytics.sources — the leaf sources (nodes with no dependencies).
  • analytics.get(key) — the DataStatus (materialization info) for one node.
  • analytics.print_tree(key) — print the subtree rooted at a specific key.

Notebook helper: marimo_db

For marimo notebooks, pyoso ships a helper that returns a database connection you can pass to mo.sql(...). Put this in a cell at the top of your notebook:

from pyoso.notebook import marimo_db

pyoso_db_conn = marimo_db()

Then query with mo.sql(...) using that connection:

df = mo.sql("SELECT * FROM oso.projects_v1 LIMIT 10", engine=pyoso_db_conn)

Optional: semantic layer

When installed with the [semantic] extra, the client exposes a semantic attribute — a registry for building queries against OSO's semantic models (entities and their relationships) instead of writing raw SQL. This is optional and off unless the oso_semantic package is present.

See also

  • Querying OSO — first queries with pyoso and over MCP.
  • Data model — the public oso.* marts you'll query.
  • Notebooking — build and share notebooks on OSO data.
  • Data modeling — author UDMs with the import oso SDK (a different surface from this client).