From 10ae02e0e9436bea031b9d950d19310238c7c191 Mon Sep 17 00:00:00 2001 From: Brent Wilkins Date: Thu, 4 Sep 2025 11:35:08 -0600 Subject: [PATCH] chore (python-cli): Version bump with related improvements (October version) * Bumped Python version to the oldest currently supported version (3.10) * Made the `cli` package get its version via the installed package or ultimately from `pyproject.toml` for a single source of truth on that * Added testing for new single source of truth version code to a CI workflow * A few [CommonMark](https://commonmark.org/) compliancy tweaks in the markdown files * I had to use `.python-version` to get such an old version running for testing, so I sorted and added that to `.gitignore` --- .../.github/workflows/test-version.yml | 82 +++++++++++++++++++ starter-templates/python-cli/.gitignore | 15 ++-- starter-templates/python-cli/README.md | 1 + starter-templates/python-cli/cli/__init__.py | 13 ++- starter-templates/python-cli/knowledge.md | 5 ++ starter-templates/python-cli/pyproject.toml | 19 +++-- 6 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 starter-templates/python-cli/.github/workflows/test-version.yml diff --git a/starter-templates/python-cli/.github/workflows/test-version.yml b/starter-templates/python-cli/.github/workflows/test-version.yml new file mode 100644 index 0000000..453c080 --- /dev/null +++ b/starter-templates/python-cli/.github/workflows/test-version.yml @@ -0,0 +1,82 @@ +name: Test Version Management + +on: + push: + branches: [ main, develop ] + tags: + - 'v*' + pull_request: + branches: [ main ] + +jobs: + test-version: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.10', '3.11', '3.12', '3.13'] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history for version tools that use git + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install package and dev dependencies + run: | + python -m pip install --upgrade pip + pip install -e .[dev] + + - name: Test version can be imported + run: | + python -c "import cli; print(f'Package version: {cli.__version__}')" + + - name: Test importlib.metadata version access + run: | + python -c "import importlib.metadata; version = importlib.metadata.version('cli'); print(f'Metadata version: {version}')" + + - name: Verify version consistency + run: | + # Get version from package import + IMPORT_VERSION=$(python -c "import cli; print(cli.__version__)") + # Get version from metadata + METADATA_VERSION=$(python -c "import importlib.metadata; print(importlib.metadata.version('cli'))") + + echo "Import version: $IMPORT_VERSION" + echo "Metadata version: $METADATA_VERSION" + + if [ "$IMPORT_VERSION" != "$METADATA_VERSION" ]; then + echo "ERROR: Version mismatch between import and metadata!" + exit 1 + fi + + echo "SUCCESS: Version consistency verified" + + + - name: Run type checking and formatting + run: | + mypy cli + black --check cli + + # Only run on tag pushes to verify git tag matches version + - name: Verify version matches git tag + if: startsWith(github.ref, 'refs/tags/v') + run: | + # Extract version from git tag (e.g., 'v1.2.3' -> '1.2.3') + TAG_VERSION=${GITHUB_REF#refs/tags/v} + # Get version from installed package + INSTALLED_VERSION=$(python -c "import importlib.metadata; print(importlib.metadata.version('cli'))") + + echo "Git tag version: $TAG_VERSION" + echo "Installed version: $INSTALLED_VERSION" + + if [ "$TAG_VERSION" != "$INSTALLED_VERSION" ]; then + echo "ERROR: Git tag version doesn't match installed version!" + exit 1 + fi + + echo "SUCCESS: Git tag and installed versions match" diff --git a/starter-templates/python-cli/.gitignore b/starter-templates/python-cli/.gitignore index dfc60df..d7dd712 100644 --- a/starter-templates/python-cli/.gitignore +++ b/starter-templates/python-cli/.gitignore @@ -1,11 +1,12 @@ -__pycache__/ -*.py[cod] *$py.class +**.log +*.egg-info/ +*.py[cod] +.DS_Store .env +.python-version .venv/ -venv/ -.DS_Store -**.log -dist/ +__pycache__/ build/ -*.egg-info/ +dist/ +venv/ diff --git a/starter-templates/python-cli/README.md b/starter-templates/python-cli/README.md index 8632681..7b2f470 100644 --- a/starter-templates/python-cli/README.md +++ b/starter-templates/python-cli/README.md @@ -32,6 +32,7 @@ pip install dist/*.whl ``` ## Project Structure + - `cli/` - Source files - `tests/` - Test files - `pyproject.toml` - Project configuration diff --git a/starter-templates/python-cli/cli/__init__.py b/starter-templates/python-cli/cli/__init__.py index ebf5982..31ac525 100644 --- a/starter-templates/python-cli/cli/__init__.py +++ b/starter-templates/python-cli/cli/__init__.py @@ -1,3 +1,14 @@ """A Python CLI application.""" -__version__ = "0.1.0" +from importlib.metadata import PackageNotFoundError, version + +try: + __version__ = version("cli") +except PackageNotFoundError: + # Package not installed, fallback for development + try: + import toml # type: ignore[import-untyped] + + __version__ = toml.load("pyproject.toml")["project"]["version"] + except Exception: + __version__ = "unknown" diff --git a/starter-templates/python-cli/knowledge.md b/starter-templates/python-cli/knowledge.md index be474f6..e3124da 100644 --- a/starter-templates/python-cli/knowledge.md +++ b/starter-templates/python-cli/knowledge.md @@ -1,17 +1,22 @@ # Python CLI Template Knowledge ## Project Overview + A minimal Python CLI application template with modern Python features and type hints. ## Key Features + - Uses virtual environments for isolation - Type hints and mypy for static type checking - Modern Python packaging with pyproject.toml - Black for code formatting ## Verifying changes + After every change, run: + ```bash mypy cli && black --check cli ``` + This will check for type errors and formatting issues. diff --git a/starter-templates/python-cli/pyproject.toml b/starter-templates/python-cli/pyproject.toml index 3eea2b6..ebb276c 100644 --- a/starter-templates/python-cli/pyproject.toml +++ b/starter-templates/python-cli/pyproject.toml @@ -2,27 +2,28 @@ name = "cli" version = "0.1.0" description = "A Python CLI application" -requires-python = ">=3.8" +requires-python = ">=3.10" dependencies = [] [project.optional-dependencies] dev = [ - "mypy>=1.8.0", - "black>=24.1.1", - "pytest>=8.0.0", + "black>=25.1.0", + "mypy>=1.17.1", + "pytest>=8.4.2", + "toml>=0.10.2", # In case someone forgets to run `pip install -e ".[dev]"` ] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" +[tool.black] +line-length = 88 +target-version = ['py310'] + [tool.mypy] -python_version = "3.8" +python_version = "3.10" strict = true warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true - -[tool.black] -line-length = 88 -target-version = ['py38']