Skip to content

PySemantic

A lightweight, graph-based Semantic Layer for Python and SQL.
Define metrics once. Generate SQL everywhere.

Python 3.11+ MIT License PyPI Typer CLI

See It in Action

Write a Python query โ€” get production-ready SQL:

from pysemantic.client import SemanticLayer

sl = SemanticLayer(model_path="./models")

sql = sl.query(
    measures=["total_order_price", "total_number_of_distinct_orders"],
    dimensions=["customer_state", "customer_city"],
    filters=[{"field": "customer_state", "operator": "IN", "value": "('SP', 'RJ')"}],
    order_by=["total_order_price DESC"],
    limit=10,
)
SELECT
  customers.customer_city AS customer_city,
  customers.customer_state AS customer_state,
  SUM(order_items.price) AS total_order_price,
  COUNT(DISTINCT order_items.order_id) AS total_number_of_distinct_orders
FROM order_items
LEFT JOIN orders
  ON order_items.order_id = orders.order_id
LEFT JOIN customers
  ON orders.customer_id = customers.customer_id
WHERE
  customers.customer_state IN ('SP', 'RJ')
GROUP BY
  1, 2
ORDER BY
  total_order_price DESC
LIMIT 10
pysemantic query ./models \
  -m "total_order_price,total_number_of_distinct_orders" \
  -d customer_state,customer_city \
  -f "customer_state IN ('SP', 'RJ')" \
  --order-by "total_order_price DESC" \
  --limit 10

pysemantic query demo


Why PySemantic?

๐ŸŽฏ

Single Source of Truth

Define a metric once โ€” use it across dashboards, notebooks, and APIs. No more scattered business logic.

๐Ÿ”—

Automatic Join Resolution

Declare entity relationships in your models. PySemantic finds the shortest join path automatically.

๐Ÿ›ก๏ธ

SQL Injection Safe

Structured filters with operator whitelisting and value escaping. No raw string interpolation.

๐ŸŒ

Multi-Dialect Support

MySQL, Postgres, and more via SQLGlot. One model, any database.

โšก

Zero Infrastructure

Pure Python library. No server, no daemon, no Docker. Install and query.

๐Ÿ”ฎ

Interactive Studio

Explore models, visualize the entity graph, and test queries in the browser โ€” powered by Streamlit.


Architecture

PySemantic processes queries through a clean, four-stage pipeline:

User Query (measures, dimensions, filters)
    โ”‚
    โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   AST    โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ Planner  โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚Generator โ”‚โ”€โ”€โ”€โ–ถ SQL string
โ”‚ (Parser) โ”‚     โ”‚(Resolver)โ”‚     โ”‚(Compiler)โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                      โ”‚
                โ”Œโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”
                โ”‚ Registry  โ”‚
                โ”‚ + Entity  โ”‚
                โ”‚   Graph   โ”‚
                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
Layer Responsibility
AST Parses raw input into a structured, validated syntax tree
Registry Loads model files, validates them, builds the entity graph
Planner Resolves measures/dimensions to models, calculates join paths
Generator Translates the logical plan into dialect-specific SQL

Ready to define your first semantic model?