5 Poetry

Last edited

History

  • 2015 - python packages has 3 tools: setuptools, virtualenv and pip
  • 2016 - pyproject.toml is standard
  • 2018 - poetry unifies all these tools to manage packaging, dependencies and environments (uv, hatch/rye do similar).

Note

Poetry is meant to be used during development/building, production runtimes (docker images) shouldn’t have poetry.
Build your wheel using poetry in CI and then pass it in to the Dockerfile, as the runtime just needs python.

Why poetry?

At this point I think uv is better, I’d only use poetry if it’s familar to the team and you’ve already built around it.

Setup

pipx install poetry
# Or via their installer
curl -sSL https://install.python-poetry.org | python3 -

New project

poetry new subnetting_game
.
└── subnetting-game
    ├── pyproject.toml
    ├── README.md
    ├── src
    │   └── subnetting_game
    │       └── __init__.py
    └── tests
        └── __init__.py

Example Poetry pyproject.toml

All project metadata should be in the top level [project], the old way was to put it inside the [tool.poetry] but poetry wanted that junk out of their scope, so keep poetry to only things it needs.

[tool.poetry]
# Tell Poetry which local Python package to include when building/installing this project.
# Sort of like: pip install -e <dirs>
# look in /src, include /subnetting_game
packages = [{include = "subnetting_game", from = "src"}] 

[build-system] # if you're using poetry, use their backend
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Commands

poetry check # validate pyproject.toml
poetry install # install all packages from pyproject.toml into .venv
source .venv/bin/activate # not needed but then don't have to prefix all cmds with 'poetry run x`
poetry show # list packages in lock file
poetry lock --no-update # update lock file --no-update moves to the latest covered by its constraint
poetry check --lock # check if it's consistent

peotry add <package> # add dependency, updates (pyproject.toml/poetry.lock/venv)
poetry update <package> # update a package (pyproject.toml/poetry.lock/venv)
poetry remove <package> # remove a package (pyproject.toml/poetry.lock/venv)

poetry env list
eval $(poetry env activate) # activate (although u could just use source ./venv as well)

Note

TODO (CHECK THIS?): Just type py to get a Python session for your Poetry project on Linux and macOS. This requires the Python Launcher for Unix, and you must configure Poetry to use in-project environments.

Dependency Constraints

Warning

We should avoid putting upperbounds on dependices, unfortunately poetry defaults to carets which include upper-bounds.
Best practice (if you’re a tryhard) poetry add "rich>=13.7.1 to override and not use carets. (even CCCS uses carets, i think it’s okay unless it’s a huge IMPORTANT longterm project)

Caret ^

^ a poetry-specific (borrowed from npm) way to control dependincies.

^ = allow releases with a minimum version, except breaking changes, following Semantic Versioning.

  • 1.0.0+ allow 0.X.X (minor, patch)
  • 0.X < 1.X allow 0.0.X (patch)
rich = "^13.7.1"
rich = ">=13.7.1,<14"

Tidle ~

Same a caret but stricter, only allows patches:

rich = "~13.7.1"
rich = ">=13.7.1,==13.7.*"

Dependency Groups

# Add a dependency to a group  -------------------
poetry add --group=tests pytest pytest-sugar

# Results ----------------------------------------
[tool.poetry.group.tests.dependencies]
pytest = "^8.1.1"
pytest-sugar = "^1.0.0"

# If you wish to make them optional (not defaults) add 
[tool.poetry.group.tests]
optional = true

# Then install with -------------------------------
poetry install --with tests # note: theres a bunch of flags for install

Plugins

# Install a plugin
pipx inject poetry <plugin-name>
pipx uninject poetry <plugin-name>

poetry self show plugins

plugin: export to requirements.txt

pipx inject poetry poetry-plugin-export
poetry export --format=requirements.txt --output=requirements.txt

plugins: bundle deployments

When you want to ship the environment rather than run poetry install on the deployment machine.

pipx inject poetry poetry-plugin-bundle
poetry bundle venv /tmp/clue-venv # not working yet...

In theory the above command works and you can use that to build and then keep the bundle only in the runtime container.

FROM debian:12-slim AS builder
RUN apt-get update && \
    apt-get install --no-install-suggests --no-install-recommends --yes pipx
ENV PATH="/root/.local/bin:${PATH}"
RUN pipx install poetry
RUN pipx inject poetry poetry-plugin-bundle
WORKDIR /src
COPY . .
RUN poetry bundle venv --python=/usr/bin/python3 --only=main /venv

FROM gcr.io/distroless/python3-debian12
COPY --from=builder /venv /venv
ENTRYPOINT ["/venv/bin/random-wikipedia-article"]