Skip to content

Switch packaging from Poetry to setuptools + PEP 621 #72

Description

@trvrb

Via Claude

Summary

Propose migrating evofr's packaging from Poetry (poetry-core backend + [tool.poetry] metadata) to setuptools with PEP 621 [project] metadata.

Motivation

1. Caret constraints silently over-cap dependencies

Poetry's default constraint syntax (poetry add writes ^X.Y.Z) caps at the next major version, so pyproject.toml had:

numpy = "^1.22.4"   # => >=1.22.4,<2.0.0
pandas = "^1.4.2"   # => >=1.4.2,<2.0.0

For a library, upper-capping is an anti-pattern: it stops evofr from composing with downstream environments on modern numpy/pandas, and the cap propagates to everything that depends on evofr.

Concrete failure: on Python 3.12 with pandas 3.x already installed, pip install evofr ignores the installed pandas (it violates <2.0), tries to install pandas==1.5.3 to satisfy the cap, and fails — pandas 1.5.x has no cp312 wheel and won't build from source on 3.12. (0.2.1 relaxed numpy/pandas to >= as a stopgap, but the caret convention is the root cause.)

2. evofr is a library, not an application

Poetry's headline value is the lockfile (poetry.lock) + managed virtualenvs for reproducible application deployments. A published library neither ships nor uses a lockfile — consumers resolve against their own environments. So the main benefit doesn't apply, while the constraint-capping default actively hurts.

3. Tooling friction

poetry build / poetry publish require Poetry as an extra maintainer dependency. The standard python -m build + twine flow works with any PEP 517 backend and needs no Poetry.

Proposed change

  • Replace [tool.poetry] with a PEP 621 [project] table (name, version, description, authors, license, readme, requires-python, dependencies, optional-dependencies, and [project.scripts] evofr = "evofr.cli:main").
  • [build-system]: requires = ["setuptools>=61"], build-backend = "setuptools.build_meta".
  • Move dev deps into [project.optional-dependencies] (e.g. a dev extra).
  • Use >= lower bounds; add an upper bound only where a real, known incompatibility exists.
  • Build/publish via python -m build + twine upload.

Notes / non-goals

  • No change to the public API or to pip install evofr for consumers — the wheel is the same kind of artifact.
  • Could pair this with GitHub Actions Trusted Publishing so tagged releases publish automatically. The CI workflow already matches version tags ([0-9]+.[0-9]+.[0-9]+*) and a comment references a "release job," but no publish job currently exists.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions