diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index e511102..c2083db 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -50,7 +50,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12"] + python-version: ["3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index f26bdb1..c2f0d00 100644 --- a/.gitignore +++ b/.gitignore @@ -1,143 +1,89 @@ -# Byte-compiled / optimized / DLL files __pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ +__pypackages__/ +.cache .coverage .coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover +.dmypy.json +.DS_Store +.eggs/ +.env .hypothesis/ +.idea/ +.installed.cfg +.ipynb_checkpoints +.mypy_cache/ +.nox/ +.pdm-build/ +.pdm-python +.pdm.toml +.pybuilder/ +.pyre/ .pytest_cache/ -cover/ - -# Translations +.Python +.python-version +.pytype/ +.ropeproject +.scrapy +.spyderproject +.spyproject +.tox/ +.venv +.vscode +.webassets-cache +*.bak +*.cover +*.egg +*.egg-info/ +*.log +*.manifest *.mo +*.orig *.pot - -# Django stuff: -*.log -local_settings.py +*.py,cover +*.py[cod] +*.sage.py +*.so +*.spec *.sqlite3 +**/.DS_Store +*~ +*$py.class +/site +archive +build/ +celerybeat-schedule +celerybeat.pid +cover/ +coverage.xml +cython_debug/ db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation +develop-eggs/ +dist/ +dmypy.json docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# package/env management -.python-version -.env -.venv +downloads/ +eggs/ env/ -venv/ ENV/ -*.bak +htmlcov/ +instance/ +ipython_config.py +lib/ +lib64/ +local_settings.py +MANIFEST +nosetests.xml +parts/ +pdm.lock +pip-delete-this-directory.txt +pip-log.txt Pipfile.lock poetry.lock -pdm.lock -.pdm.toml -.pdm-python -.pdm-build/ +profile_default/ +sdist/ +share/python-wheels/ +target/ uv.lock - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# IDEs -.idea/ -.vscode - -# misc -*.orig -archive -*~ -**/.DS_Store +var/ +venv/ +wheels/ diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000..eb02b8c --- /dev/null +++ b/.mailmap @@ -0,0 +1,13 @@ +# I pick the account with the most modified files in git shortlog -sne +# This is used by Git to consolidate the users who used multiple accounts +Andreas Prlic Andreas Prlic <36012160+andreas-invitae@users.noreply.github.com> +Andreas Prlic Andreas Prlic +Caitlin Gong Caitlin Gong +Katie Stahl katie stahl +Manuel Holtgrewe Manuel Holtgrewe +Meng Meng Wang +Reece Hart Reece Hart +Reece Hart Reece Hart +Reece Hart Reece Hart +Reece Hart Reece Hart +Rudy Rico Rudolph Rico diff --git a/Makefile b/Makefile index bbcce4d..fd467f4 100644 --- a/Makefile +++ b/Makefile @@ -12,10 +12,12 @@ endif SHELL:=zsh -eu -o pipefail -o null_glob SELF:=$(firstword $(MAKEFILE_LIST)) -VE_DIR=venv +VE_DIR:=.venv +PY_VERSION:=3.13 +SRC_DIRS:=src TEST_DIRS:=tests -DOC_TESTS:=src ./README.md +DOC_TESTS:=${SRC_DIRS} # ./README.md ############################################################################ @@ -40,22 +42,18 @@ devready: #=> venv: make a Python 3 virtual environment ${VE_DIR}: - python3 --version - python3 -mvenv $@; \ - source $@/bin/activate; \ - python3 -m ensurepip --upgrade; \ - pip install --upgrade pip setuptools wheel - + uv venv --python ${PY_VERSION} $@ + #=> develop: install package in develop mode .PHONY: develop develop: - pip install -e ".[dev,tests]" + uv sync --extra dev --extra tests pre-commit install #=> install: install package .PHONY: install install: - pip install "." + uv sync #=> build: make sdist and wheel .PHONY: build @@ -72,42 +70,39 @@ build: %: #=> test-docs: test example code in docs .PHONY: test test-code test-docs test: - pytest --cov src -test-docs: - pytest docs + pytest --cov ${SRC_DIRS} test-code: - pytest src + pytest ${TEST_DIRS} +test-docs: + pytest ${DOC_TESTS} +stest: + pytest -vvv -s -k ${t} test-%: - pytest -m '$*' src + pytest -m '$*' ${TEST_DIRS} #=> tox -- run all tox tests tox: - tox + uvx tox #=> cqa: execute code quality tests cqa: - ruff format --check - ruff check - -#=> reformat: reformat code -.PHONY: reformat -reformat: - ruff check --fix - ruff format + uvx ruff format --check + uvx ruff check ############################################################################ #= UTILITY TARGETS -#=> rename: rename files and substitute content for new repo name -.PHONY: rename -rename: - ./sbin/rename-package +#=> reformat: reformat code +.PHONY: reformat +reformat: + uvx ruff check --fix + uvx ruff format #=> docs -- make sphinx docs .PHONY: docs docs: develop # RTD makes json. Build here to ensure that it works. - make -C doc html json + make -C docs html json ############################################################################ #= CLEANUP @@ -116,6 +111,8 @@ docs: develop .PHONY: clean clean: rm -frv **/*~ **/*.bak + -make -C docs $@ + -make -C examples $@ #=> cleaner: remove files and directories that are easily rebuilt .PHONY: cleaner @@ -126,17 +123,31 @@ cleaner: clean rm -frv **/*.pyc rm -frv **/*.orig rm -frv **/*.rej + -make -C docs $@ + -make -C examples $@ -#=> cleanest: remove files and directories that require more time/network fetches to rebuild +#=> cleanest: remove files and directories that are more expensive to rebuild .PHONY: cleanest cleanest: cleaner rm -frv .eggs .tox venv + -make -C docs $@ + -make -C examples $@ #=> distclean: remove untracked files and other detritus .PHONY: distclean distclean: cleanest git clean -df + +############################################################################ +#= Repo renamer + +#=> rename: rename files and substitute content for new repo name +.PHONY: rename +rename: + ./sbin/rename-package + + ## ## Copyright 2023 Source Code Committers ## diff --git a/README.md b/README.md index 212e681..87525ea 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ [![codecov](https://codecov.io/gh/biocommons/biocommons.example/graph/badge.svg?token=CCUMQQV5R6)](https://codecov.io/gh/biocommons/biocommons.example) +--- + This repo provides a template for biocommons Python packages. Here's how to use it: 1. Click the [Use this template](https://github.com/biocommons/example/generate) @@ -11,28 +13,43 @@ This repo provides a template for biocommons Python packages. Here's how to use 1. Remove this header. 1. Commit and push. +Delete this section in your generated template. + +--- + ## Installation To install from pypi: ```pip install biocommons.example``` ## Developer Setup -Developers must install zsh, which is required by the Makefile. zsh is included by default in MacOS, and is readily available on all modern Linux distributions. +### Prerequisites -Setup like this: +- [GNU make](https://www.gnu.org/software/make/): Current mechanism for consistent invocation of developer tools. + - Mac: [Install brew](https://brew.sh/), then [install make](https://formulae.brew.sh/formula/make) + - Ubuntu: `sudo apt install make` +- [uv](https://docs.astral.sh/uv/): An extremely fast Python package and project manager, written in Rust. + - All platforms: See the [uv installation instructions](https://docs.astral.sh/uv/getting-started/installation/). +- [zsh](https://www.zsh.org/): Shell used by the Makefile + - Mac: included by default + - Ubuntu: `sudo apt install zsh` + +### One-time developer setup + +Create a Python virtual environment and install dependencies: make devready + +### Development + +Activate your environment: + source venv/bin/activate Code reformatting: make reformat -Install pre-commit hook: - - # included in `make devready`, not necessary for new installations - pre-commit install - Test: make test # for current environment @@ -77,7 +94,3 @@ Try it: * Quality tools: Code linting and reformatting with Ruff * GitHub Actions for testing and packaging - -## ToDo - -* Add devcontainer support diff --git a/pyproject.toml b/pyproject.toml index 928791a..c3a12dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,25 +9,35 @@ license = { file = "LICENSE.txt" } requires-python = ">=3.10" classifiers = [ "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ] dynamic = ["version"] -dependencies = ["coloredlogs ~= 15.0", "pyyaml ~= 6.0"] +dependencies = [ + "coloredlogs ~= 15.0", + "pyyaml ~= 6.0", +] [project.optional-dependencies] dev = [ - "build ~= 0.8", + "deptry>=0.23.0", "ipython ~= 8.4", - "pre-commit ~= 3.4", - "ruff == 0.4.4", + "mkdocs-material>=8.5.10", + "mkdocs>=1.4.2", + "mkdocstrings[python]>=0.26.1", + "pre-commit>=3.8.0", + "pytest-cov>=4.0.0", + "pytest>=7.2.0", + "ruff>=0.11.5", + "tox-uv>=1.11.3", + "ty>=0.0.1a16", + ] tests = [ "pytest-cov ~= 4.1", - "pytest-optional-tests", "pytest ~= 7.1", "vcrpy", "tox ~= 4.15", diff --git a/tox.ini b/tox.ini index 6890940..e9293f7 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,19 @@ [tox] -requires = - tox >= 4 -env_list = py{310,311,312} -isolated_build = True +skipsdist = true +envlist = py39, py310, py311, py312, py313 -[gh] +[gh-actions] python = - 3.10 = py310 - 3.11 = py311 - 3.12 = py312 + 3.9: py39 + 3.10: py310 + 3.11: py311 + 3.12: py312 + 3.13: py313 + +[testenv] +passenv = PYTHON_VERSION +allowlist_externals = uv +commands = + uv sync --python {envpython} + uv run python -m pytest --doctest-modules tests --cov --cov-config=pyproject.toml --cov-report=xml + ty check