From 117227a9014cd833e57da66a66c24a641aa091eb Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Sun, 8 Feb 2026 11:47:52 -0500 Subject: [PATCH] Add setuptools to requirements for Python 3.12+ compatibility Python 3.12 no longer bundles setuptools in virtual environments. Pyramid imports pkg_resources from setuptools, causing CI to fail with ModuleNotFoundError: No module named 'pkg_resources'. --- CLAUDE.md | 26 ++++++++++++++++++++++++++ requirements.py3.txt | 4 ++++ 2 files changed, 30 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index cd09102..49b929e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -127,6 +127,32 @@ alembic -c data/development.ini history ### Important Migration Notes +**Idempotent Migrations**: `make init-db` creates all tables from models, so migrations that run afterward must not fail if tables/columns already exist. Always guard `create_table` with `_table_exists` and `add_column` with `_column_exists`: + +```python +def _table_exists(name): + conn = op.get_bind() + result = conn.execute( + sa.text("SELECT name FROM sqlite_master WHERE type='table' AND name=:name"), + {"name": name}, + ) + return result.fetchone() is not None + + +def _column_exists(table, column): + conn = op.get_bind() + result = conn.execute(sa.text(f"PRAGMA table_info({table})")) + return any(row[1] == column for row in result.fetchall()) + + +def upgrade(): + if not _table_exists("mps_new_table"): + op.create_table(...) + + if not _column_exists("mps_shop", "new_column"): + op.add_column(...) +``` + **SQLite Column Defaults**: When adding NOT NULL columns with defaults to existing tables in SQLite, use `server_default` with raw SQL values: ```python diff --git a/requirements.py3.txt b/requirements.py3.txt index d150550..d8995b3 100644 --- a/requirements.py3.txt +++ b/requirements.py3.txt @@ -1,6 +1,10 @@ # python 2 -> 3 compat. six +# Python 3.12+ no longer bundles setuptools in venvs. +# Pyramid imports pkg_resources which lives in setuptools. +setuptools + # Pyramid with SQLAlchemy. plaster_pastedeploy pyramid