Skip to main content

Python packages

Monolith is a primarily Python codebase and uses uv as its Python package manager. The Mono CLI provides a convenient wrapper around uv.

Monorepository structure

Monolith is a monorepository containing multiple Python projects. Each project has its own set of dependencies and the ones in apps/ tend to be deployed as services (application, server...). This isolation allows us to only deploy what is needed for each service.

For this, Monolith leverages uv workspaces. We'll explain the basics in this guide, but refer to the official documentation for anything that is not covered here.

Everything is configured through pyproject.toml files and the single uv.lock at the root.

monolith
├── apps
│ └── database
│ ├── src/database
│ └── pyproject.toml
├── libs
│ ├── stoneware
│ │ ├── src/stoneware
│ │ └── pyproject.toml
│ └── shared
│ ├── src/shared
│ └── pyproject.toml
├── pyproject.toml
└── uv.lock

We're going to dig into those files in the sections below.

Lockfile

uv.lock is a file automatically created by uv, which contains the exact package versions to use in development and deployments. One requirement of uv workspaces is that you can't have a package with different versions in different projects. This can be annoying but has the following benefits:

  • Single virtual environment in dev, which plays much better with code editors or Jupyter notebooks
  • Avoids problems like "package B uses Pandas 2.0 and package A, but package A uses Pandas 1.0, so they are incompatible"

At some point we will likely outgrow this constraint, but we should strive to preserve it as long as possible.

Root pyproject.toml

Here is the current root pyproject.toml:

[project]
name = "monolith"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"


[dependency-groups]
dev = [
"dagit>=1.10.11",
"dagster-webserver>=1.10.11",
"ipykernel>=6.29.5",
"mono",
"nbstripout>=0.8.1",
"pytest>=8.3.5",
"ruff>=0.11.6",
]
process-eng = ["aspen[aspen]"]

[tool.uv.sources]
shared = { workspace = true }
spatial = { workspace = true }
stoneware = { workspace = true }
data-infrastructure = { workspace = true }
dagster-tools = { workspace = true }
data-tools = { workspace = true }
datasmart = { workspace = true }
database = { workspace = true }
mono = { workspace = true }
aspen = { workspace = true }

[tool.uv.workspace]
members = ["libs/*", "apps/*"]
exclude = ["apps/docs", "apps/stoneware-app"]

Here's what it means:

  • project section: metadata and Python version

Project pyproject.toml

Dependency isolation

  • Dependencies are not isolated in the venv, so may get errors in production