From 7d80557a3e7708d40d9e179bb51fe2ed2714cd29 Mon Sep 17 00:00:00 2001 From: golem Date: Mon, 5 Oct 2026 00:21:58 -0600 Subject: [PATCH] doc: README and CLAUDE.md for the uv workflow; fix debug env var and platform claims Co-Authored-By: Claude Opus 5.5 (1M context) --- CLAUDE.md | 21 +++++----- README.md | 106 ++++++++++++++++++++---------------------------- tests/README.md | 8 ++-- 3 files changed, 59 insertions(+), 76 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4e6a8d7..da03542 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,24 +4,25 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## What this is -`app_skellington` is a small Python library (published to PyPI) for building CLI applications. It has nothing runnable on its own. It glues together argparse-based multi-level command menus, name-based dependency injection, ConfigObj INI config with spec validation, and colorlog logging. It targets Python >=3.8 on Linux, Windows and Mac. Runtime deps are `appdirs`, `configobj` and `colorlog`. +`app_skellington` is a small Python library (published to PyPI) for building CLI applications. It has nothing runnable on its own. It glues together argparse-based multi-level command menus, name-based dependency injection, ConfigObj INI config with spec validation, and colorlog logging. It targets Python >=3.8. Only Linux is tested; Windows and macOS are goals. Runtime deps are `appdirs`, `configobj` and `colorlog`. ## Commands ```bash -pip install -e '.[dev]' pytest # dev extras = ruff, pre-commit; pytest is NOT in the extras -pytest tests # full suite from repo root (or `pytest .` from inside tests/) -pytest tests/cfg/test_cfg.py::TestConfig_e2e::test_uses_spec_as_defaults # single test -pytest tests -k "" +uv sync # .venv with the package (editable) + dev group: ruff, pytest, pre-commit, pyyaml +uv run pytest # full suite (testpaths = tests) +uv run pytest tests/cfg/test_cfg.py::TestConfig_e2e::test_uses_spec_as_defaults # single test +uv run pytest -k "" +uv run --python 3.8 pytest # any supported Python; uv.lock forks per version -ruff check --fix # lint + import sorting (config in pyproject.toml) -ruff format # formatter, line length 88 +uv run ruff check --fix # lint + import sorting (config in pyproject.toml) +uv run ruff format # formatter, line length 88 -python -m build # sdist + wheel into dist/ -python -m setuptools_scm # print the version the build will get +uv build # sdist + wheel into dist/; the version shows in the file names +uv lock # after any dependency change; commit uv.lock ``` -- **Versioning is tag-driven.** setuptools_scm uses `release-branch-semver` and derives the version from the latest `vX.Y.Z` git tag. It writes `app_skellington/_version.py` at build time. That file is tracked, but don't hand-edit it. `pip install -e .` also rewrites it, so `git restore` it rather than committing the churn. A release means tagging, then `python -m build`, then `twine upload dist/*`. The README covers the full publish steps. +- **Versioning is tag-driven.** setuptools_scm uses `release-branch-semver` and derives the version from the latest `vX.Y.Z` git tag. It generates `app_skellington/_version.py`, which is git-ignored, so never commit it. The release steps (tag on `main`, `uv build`, TestPyPI, verify, PyPI) are in the README's Publish section. - **ruff** handles formatting (88 columns) and lint (`E`, `F`, `W`, `I`). E501 is ignored on purpose, since the formatter owns line length. Keep the `ruff==` pin in `pyproject.toml` equal to the `rev:` in `.pre-commit-config.yaml`. - Tests cover only `cfg` (ConfigObj fixtures live in `tests/cfg/`) plus a CommandTree constructor smoke test. `tests/test_log.py` is empty. diff --git a/README.md b/README.md index 83db7b2..68a2d40 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,12 @@ Application framework for Python, features include: - Simple to define services and automatic dependency injection based on name (with custom invocation as an option). \*WIP - INI-style config and and validation (provided through ConfigObj). - Colored logging (provided through colorlog) - - Works on Linux, Windows, and Mac. + - Linux supported. Windows and macOS are goals, but untested. Principles: - Lend to creating beautiful, easy to read and understand code in the application. - Minimize coupling of applications to this framework. - - Compatible with Linux, Windows, and Mac. Try to be compatible as possible otherwise. + - Aim for Linux, Windows and macOS. Only Linux is tested today; full multi-platform CI is a long-term goal. - Try to be compatible with alternate Python runtimes such as PyPy and older python environments. \*WIP # Python Package Index (PyPi) - Installation Instruction @@ -70,7 +70,7 @@ argument. # Debug - Turn on Logging -Set 'APPSKELLINGTON_ENABLE_LOGGING' environment variable to any value which turns +Set the 'APPSKELLINGTON_DEBUG' environment variable to any value to turn on AppSkellington-level logging. For example, APPSKELLINGTON_DEBUG=1 @@ -82,83 +82,65 @@ or # Tests -Tests are a WIP and not fully built out yet. Recommendation is to run 'pytest' in the 'tests' directory. +``` +uv run pytest # full suite +uv run pytest tests/cfg/test_cfg.py::TestConfig_e2e::test_uses_spec_as_defaults +uv run pytest -k "" +uv run --python 3.8 pytest # against another supported Python +``` # Development -I recommend pyenv to install a reliable, controlled python of preferred version locally. +Install [uv](https://docs.astral.sh/uv/). It manages Python versions and the +virtual environment, so you don't need pyenv or a hand-made venv. ``` -curl https://pyenv.run | bash - -# Add to .bashrc or similar for different shells: -tee -a "$HOME"/.profile <<'EOF' - -export PYENV_ROOT="$HOME/.pyenv" -[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH" -eval "$(pyenv init -)" - -EOF -``` - * reference https://github.com/pyenv/pyenv - * Use pyenv to install desired python version, and/or create any virtual environments you desire - -Clone the repo: -```commandline git clone https://git-repos.zavage.net/zavage-software/app_skellington.git +cd app_skellington +uv sync # creates .venv with the package (editable) + dev tools +uv run pre-commit install # ruff lint + format on every commit ``` -Install pre-commit hooks: -```commandline -pre-commit install +Lint and format (ruff, line length 88): +``` +uv run ruff check --fix +uv run ruff format ``` -Build: +Build the sdist and wheel into `dist/`: ``` -python -m build +uv build ``` -Install: - -``` -pip install . -``` - -Formatting and Linters: -``` -black app_skellington -isort app_skellington -flake8 app_skellington -``` - -Publish: - -``` -# Push latest commit, or on commit ready to publish: -git push - -# Create a tag with the desired version number and push: -git tag -a v0.2.0 -m "0.2.0 provides modern pyproject.toml build with setuptools, versioning, and publishing" -git push origin v0.2.0 - -# Build the wheel: -python -m build - -# Publish to pypi: -twine check dist/* -twine upload dist/* -``` - * Reference https://packaging.python.org/en/latest/overview/ - +Dependencies are locked in `uv.lock`. After editing dependencies in +`pyproject.toml`, run `uv lock` and commit the result. # Version -setuptools_scm will infer the version based on the latest tag in your Git history. -Ensure you are tagging your commits with meaningful version numbers like v1.0.0, v1.1.0, etc. +setuptools_scm derives the version from the latest `vX.Y.Z` git tag. Between +tags you get development versions like `0.3.0.dev4+g1a2b3c4`. The generated +`app_skellington/_version.py` is git-ignored. -You can view the current version number with the command: + uv build # the version appears in the dist/ file names - python -m setuptools_scm +# Publish + +Publish only from a tagged commit on `main`, after CI is green, and only after +TestPyPI has been checked. + +``` +git switch main && git pull --ff-only +git tag -a v0.2.3 -m "0.2.3: " +git push origin v0.2.3 +rm -rf dist && uv build +ls dist # must be exactly app_skellington-0.2.3.tar.gz and app_skellington-0.2.3-py3-none-any.whl + +uv publish --publish-url https://test.pypi.org/legacy/ dist/* # TestPyPI first +scripts/verify_index_release.sh 0.2.3 # every supported Python +uv publish dist/* # then PyPI +scripts/verify_index_release.sh 0.2.3 https://pypi.org/simple/ +``` + * Reference https://packaging.python.org/en/latest/overview/ # License diff --git a/tests/README.md b/tests/README.md index 5715a51..20f4492 100644 --- a/tests/README.md +++ b/tests/README.md @@ -4,14 +4,14 @@ Contained is the early stages of unit testing for app_skellington framework. Usage ----- -Run all tests (cwd is testing directory): +Run all tests (from the repo root): - pytest . + uv run pytest Run test by keyword: - pytest -k "" . + uv run pytest -k "" Run test by directory: - pytest + uv run pytest tests/