Development¶
Setup¶
Running Tests¶
# Unit tests (no database required)
poetry run pytest
# Postgres integration tests (auto-spawns temporary Postgres via pytest-postgresql)
poetry run pytest tests/integration/test_integration_postgres.py -m integration
# DuckDB integration tests (no Docker, runs in-process)
poetry run pytest tests/integration/test_integration_duckdb.py -m integration
# SQLite integration tests
poetry run pytest tests/integration/test_integration.py
# Specific test file
poetry run pytest tests/test_mcp_server.py -v
Linting¶
Project Structure¶
slayer/
core/
enums.py # DataType, TimeGranularity, OrderDirection
models.py # SlayerModel, Column, ModelMeasure, DatasourceConfig
query.py # SlayerQuery, ColumnRef, TimeDimension, OrderItem
formula.py # Formula parser (Python ast-based) for `measures` API
sql/
generator.py # SQLGenerator — sqlglot AST-based SQL generation
client.py # SlayerSQLClient — SQLAlchemy execution with retry
engine/
query_engine.py # SlayerQueryEngine — central orchestrator
ingestion.py # Auto-ingestion with rollup-style FK joins
enriched.py # EnrichedQuery — fully resolved query for SQL generation
storage/
base.py # StorageBackend ABC
yaml_storage.py # YAML file storage
sqlite_storage.py # SQLite storage
api/server.py # FastAPI REST API
mcp/server.py # MCP server (FastMCP)
client/slayer_client.py # Python SDK
cli.py # CLI entry point (serve, mcp, query, ingest, models, datasources)
tests/
test_models.py # Core model tests
test_sql_generator.py # SQL generation tests
test_storage.py # YAML storage tests
test_sqlite_storage.py # SQLite storage tests
test_mcp_server.py # MCP server tool tests
integration/
test_integration.py # SQLite integration tests
test_integration_postgres.py # Postgres integration + rollup tests
test_integration_duckdb.py # DuckDB integration tests
test_jaffle_shop_duckdb.py # Jaffle Shop DuckDB example tests
test_jaffle_shop_notebook.py # Jaffle Shop notebook tests
conftest.py # Shared fixtures
Key Conventions¶
- Python 3.11+, Pydantic v2 for all models
- Use
poetry runfor all Python commands - Use keyword arguments for functions with more than 1 parameter
- SQL generation uses sqlglot AST building (not string concatenation)
- Dimension/measure SQL uses bare column names;
model_name.column_namefor complex expressions - Result column keys:
model_name.column_nameformat - Integration tests marked with
@pytest.mark.integration
Publishing¶
PyPI publishing is available via GitHub Actions (Actions → Publish to PyPI → Run workflow). Choose testpypi or pypi as target. Uses OIDC trusted publishing — no API tokens required.
Requires configuring the trusted publisher on pypi.org (Settings → Publishing → Add GitHub provider).