From c6c0462fc0153bd1a15fefa3cc8c27ddee172e5a Mon Sep 17 00:00:00 2001 From: David Roe Date: Wed, 22 Jul 2026 02:12:30 -0400 Subject: [PATCH 1/2] Require Python 3.9+, SPDX license metadata, psycodict.__version__ Three packaging changes for 1.0, taken together because they interlock: - requires-python >= 3.9 (3.8 has been end-of-life since October 2024). The unit matrix drops 3.8 and the "oldest supported pair" database row becomes py3.9/PG13; ruff's target-version moves to py39. - license = "GPL-2.0-or-later" (PEP 639 SPDX expression), replacing the free-text {text = "GPL v2+"}. The wheel now carries a proper License-Expression field. This needs setuptools >= 77, which is what previously kept it out: on py3.8, pip resolves setuptools 75.x, which rejects the string form. With the 3.9 floor the workaround disappears; build-system pins setuptools>=77 (wheel is no longer needed there). - psycodict.__version__, the single source of truth: pyproject declares version dynamic and reads the literal via [tool.setuptools.dynamic], so the attribute also works from an uninstalled checkout (which is how LMFDB runs psycodict today). Verified: build + twine check --strict pass; wheel METADATA shows Metadata-Version 2.4, License-Expression GPL-2.0-or-later, Requires-Python >=3.9; installed psycodict.__version__ matches importlib.metadata.version; database-free suite 326 passed; ruff clean. Co-Authored-By: Claude Fable 5 --- .github/workflows/ci.yml | 4 ++-- psycodict/__init__.py | 4 ++++ pyproject.toml | 16 +++++++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08b53fb..941a9a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,7 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v7 @@ -80,7 +80,7 @@ jobs: # deploys. Add a row here when a new PostgreSQL major is released. matrix: include: - - {python: "3.8", postgres: "13"} + - {python: "3.9", postgres: "13"} - {python: "3.11", postgres: "15"} - {python: "3.12", postgres: "16"} - {python: "3.13", postgres: "17"} diff --git a/psycodict/__init__.py b/psycodict/__init__.py index 7275c6f..cf7d297 100644 --- a/psycodict/__init__.py +++ b/psycodict/__init__.py @@ -25,6 +25,10 @@ """ +# Single source of truth for the package version: pyproject.toml reads it via +# ``[tool.setuptools.dynamic]``, and it works from an uninstalled checkout too. +__version__ = "0.1.13" + try: import psycopg assert psycopg diff --git a/pyproject.toml b/pyproject.toml index 02f5232..711c09f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,20 @@ [build-system] -requires = ["setuptools", "wheel"] +# setuptools >= 77 implements PEP 639, required for the SPDX `license` string +# below; it is available on every interpreter >= 3.9. +requires = ["setuptools>=77"] build-backend = "setuptools.build_meta" [project] name = "psycodict" -version = "0.1.13" +# Version lives in psycodict/__init__.py (__version__); see [tool.setuptools.dynamic]. +dynamic = ["version"] description = "dictionary-based python interface to PostgreSQL databases" # Required by the `twine check --strict` gate in CI: without it the package # has no long_description and the PyPI project page renders empty. readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.9" authors = [{name = "David Roe", email = "roed.math@gmail.com"}, {name = "Edgar Costa", email = "edgarc@mit.edu"}] -license = {text = "GPL v2+"} +license = "GPL-2.0-or-later" keywords = ["postgres", "database", "interface"] [project.urls] @@ -23,6 +26,9 @@ pgsource = ["psycopg>=3.1"] pgbinary = ["psycopg[binary]>=3.1"] test = ["pytest>=7"] +[tool.setuptools.dynamic] +version = {attr = "psycodict.__version__"} + [tool.pytest.ini_options] testpaths = ["tests"] markers = [ @@ -34,7 +40,7 @@ log_cli_level = "WARNING" filterwarnings = ["error::DeprecationWarning:psycodict.*"] [tool.ruff] -target-version = "py38" +target-version = "py39" [tool.ruff.lint.per-file-ignores] # The psycopg2 availability check in __init__.py deliberately runs before the From a8ac4a2c0e760b959b36536732c5b0887e34ca43 Mon Sep 17 00:00:00 2001 From: David Roe Date: Wed, 22 Jul 2026 03:02:20 -0400 Subject: [PATCH 2/2] Add py3.14 and PostgreSQL 18 to the CI matrices Python 3.14 joins the unit matrix, and {py3.14, PG18} becomes the matrix's newest-pair corner, per the comment asking for a new row when a PostgreSQL major is released. Co-Authored-By: Claude Fable 5 --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 941a9a4..6cd024e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,7 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v7 @@ -84,6 +84,7 @@ jobs: - {python: "3.11", postgres: "15"} - {python: "3.12", postgres: "16"} - {python: "3.13", postgres: "17"} + - {python: "3.14", postgres: "18"} services: postgres: image: postgres:${{ matrix.postgres }}