diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2f2d08f..a329887 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -35,14 +35,13 @@ jobs: cd /tmp/python-project git init . && git add . && git commit -m "Initial commit" - make dev - make reformat + make format - git diff --exit-code || { >&2 echo "please reformat"; exit 1; } + git diff --exit-code || { >&2 echo "please format"; exit 1; } make lint make test - make package + make build make doc cd .. && rm -rf /tmp/python-project @@ -54,14 +53,13 @@ jobs: cd /tmp/python-project git init . && git add . && git commit -m "Initial commit" - make dev - make reformat + make format - git diff --exit-code || { >&2 echo "please reformat"; exit 1; } + git diff --exit-code || { >&2 echo "please format"; exit 1; } make lint make test - make package + make build make doc cd .. && rm -rf /tmp/python-project @@ -73,14 +71,13 @@ jobs: cd /tmp/tob-r-and-e-python-project git init . && git add . && git commit -m "Initial commit" - make dev - make reformat + make format - git diff --exit-code || { >&2 echo "please reformat"; exit 1; } + git diff --exit-code || { >&2 echo "please format"; exit 1; } make lint make test - make package + make build make doc cd .. && rm -rf /tmp/tob-r-and-e-python-project @@ -92,14 +89,13 @@ jobs: cd /tmp/bit-trails git init . && git add . && git commit -m "Initial commit" - make dev - make reformat + make format - git diff --exit-code || { >&2 echo "please reformat"; exit 1; } + git diff --exit-code || { >&2 echo "please format"; exit 1; } make lint make test - make package + make build make doc cd .. && rm -rf /tmp/bit-trails @@ -112,13 +108,12 @@ jobs: cd /tmp/python-project git init . && git add . && git commit -m "Initial commit" - make dev - make reformat + make format - git diff --exit-code || { >&2 echo "please reformat"; exit 1; } + git diff --exit-code || { >&2 echo "please format"; exit 1; } make lint make test - make package + make build make doc cd .. && rm -rf /tmp/python-project diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index b93239a..0352cb2 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -10,27 +10,16 @@ permissions: {} jobs: zizmor: - name: zizmor latest via PyPI runs-on: ubuntu-latest permissions: - security-events: write # needed by upload-sarif for all repositories + security-events: write + contents: read # only needed for private repos + actions: read # only needed for private repos steps: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - - name: Install the latest version of uv - uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 - - name: Run zizmor 🌈 - # Run it for both this repo and the templated cookiecutter repo. - run: uvx zizmor --format sarif . {{cookiecutter.project_slug}}/.github/workflows > results.sarif - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # v3.29.5 - with: - sarif_file: results.sarif - category: zizmor + uses: zizmorcore/zizmor-action@5ca5fc7a4779c5263a3ffa0e1f693009994446d1 # v0.1.2 diff --git a/{{cookiecutter.project_slug}}/.github/dependabot.yml b/{{cookiecutter.project_slug}}/.github/dependabot.yml index 99d80f9..f3d7b30 100644 --- a/{{cookiecutter.project_slug}}/.github/dependabot.yml +++ b/{{cookiecutter.project_slug}}/.github/dependabot.yml @@ -1,7 +1,7 @@ version: 2 updates: - - package-ecosystem: pip + - package-ecosystem: uv directory: / groups: python: diff --git a/{{cookiecutter.project_slug}}/.github/workflows/docs.yml b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml index 781955f..812d98d 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/docs.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml @@ -18,10 +18,6 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 - - name: setup - run: | - make dev INSTALL_EXTRA=doc - - name: build docs run: | make doc diff --git a/{{cookiecutter.project_slug}}/.github/workflows/lint.yml b/{{cookiecutter.project_slug}}/.github/workflows/lint.yml index 5a1ac38..a44838c 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/lint.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/lint.yml @@ -20,4 +20,4 @@ jobs: uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 - name: lint - run: make lint INSTALL_EXTRA=lint + run: make lint diff --git a/{{cookiecutter.project_slug}}/.github/workflows/release.yml b/{{cookiecutter.project_slug}}/.github/workflows/release.yml index 07a653f..e93ae1c 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/release.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 - name: Build distributions - run: uv build + run: make build - name: Upload distributions uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 diff --git a/{{cookiecutter.project_slug}}/.github/workflows/tests.yml b/{{cookiecutter.project_slug}}/.github/workflows/tests.yml index cf6d6f3..9355238 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/tests.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/tests.yml @@ -13,10 +13,10 @@ jobs: strategy: matrix: python: - - "3.9" - "3.10" - "3.11" - "3.12" + - "3.13" runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -25,9 +25,8 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 - - - name: Install Python ${{ matrix.python }} - run: uv python install ${{ matrix.python }} + with: + python-version: ${{ matrix.python }} - name: test - run: make test INSTALL_EXTRA=test + run: make test diff --git a/{{cookiecutter.project_slug}}/.github/workflows/zizmor.yml b/{{cookiecutter.project_slug}}/.github/workflows/zizmor.yml index bdb6825..0352cb2 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/zizmor.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/zizmor.yml @@ -10,28 +10,16 @@ permissions: {} jobs: zizmor: - name: zizmor latest via PyPI runs-on: ubuntu-latest permissions: - security-events: write # needed by upload-sarif for all repositories - contents: read # needed by upload-sarif for private repositories - actions: read # needed by upload-sarif for private repositories + security-events: write + contents: read # only needed for private repos + actions: read # only needed for private repos steps: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - - name: Install the latest version of uv - uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 - - name: Run zizmor 🌈 - run: uvx zizmor --format sarif . > results.sarif - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # v3.29.5 - with: - sarif_file: results.sarif - category: zizmor + uses: zizmorcore/zizmor-action@5ca5fc7a4779c5263a3ffa0e1f693009994446d1 # v0.1.2 diff --git a/{{cookiecutter.project_slug}}/Makefile b/{{cookiecutter.project_slug}}/Makefile index 4f99666..fae43d4 100644 --- a/{{cookiecutter.project_slug}}/Makefile +++ b/{{cookiecutter.project_slug}}/Makefile @@ -2,30 +2,9 @@ SHELL := /bin/bash PY_IMPORT = {{ cookiecutter.__project_import }} -ALL_PY_SRCS := $(shell find src -name '*.py') \ - $(shell find test -name '*.py') - -# Optionally overriden by the user, if they're using a virtual environment manager. -# Warning: changing this name to something else than '.venv' will make working with -# uv harder. -VENV ?= .venv - -# On Windows, venv scripts/shims are under `Scripts` instead of `bin`. -VENV_BIN := $(VENV)/bin -ifeq ($(OS),Windows_NT) - VENV_BIN := $(VENV)/Scripts -endif - -# Optionally overridden by the user in the `release` target. -BUMP_ARGS := - # Optionally overridden by the user in the `test` target. TESTS := -# Optionally overridden by the user/CI, to limit the installation to a specific -# subset of development dependencies. -INSTALL_EXTRA := dev - # If the user selects a specific test pattern to run, set `pytest` to fail fast # and only run tests that match the pattern. # Otherwise, run all tests and enable coverage assertions, since we expect @@ -42,21 +21,14 @@ endif all: @echo "Run my targets individually!" -.PHONY: dev -dev: $(VENV)/pyvenv.cfg - {%- if cookiecutter.entry_point %} .PHONY: run -run: $(VENV)/pyvenv.cfg +run: uv run {{ cookiecutter.entry_point }} $(ARGS) {%- endif %} -$(VENV)/pyvenv.cfg: pyproject.toml - uv venv $(VENV) - uv pip install -e '.[$(INSTALL_EXTRA)]' - .PHONY: lint -lint: $(VENV)/pyvenv.cfg +lint: uv run ruff format --check && \ uv run ruff check && \ uv run mypy @@ -65,29 +37,25 @@ lint: $(VENV)/pyvenv.cfg uv run interrogate -c pyproject.toml . {%- endif %} -.PHONY: reformat -reformat: +.PHONY: format +format: uv run ruff format && \ uv run ruff check --fix -.PHONY: test tests -test tests: $(VENV)/pyvenv.cfg +.PHONY: test +test: uv run pytest --cov=$(PY_IMPORT) $(T) $(TEST_ARGS) uv run coverage report -m $(COV_ARGS) .PHONY: doc {%- if cookiecutter.documentation == 'pdoc' %} -doc: $(VENV)/pyvenv.cfg +doc: uv run pdoc -o html $(PY_IMPORT) {%- elif cookiecutter.documentation == 'none' %} doc: @echo "No documentation set up" {%- endif %} -.PHONY: package -package: $(VENV)/pyvenv.cfg +.PHONY: build +build: uv build - -.PHONY: edit -edit: - $(EDITOR) $(ALL_PY_SRCS) diff --git a/{{cookiecutter.project_slug}}/pyproject.toml b/{{cookiecutter.project_slug}}/pyproject.toml index b364bd1..868dacd 100644 --- a/{{cookiecutter.project_slug}}/pyproject.toml +++ b/{{cookiecutter.project_slug}}/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "{{ cookiecutter.project_slug }}" -dynamic = ["version"] +version = "{{ cookiecutter.version }}" description = "{{ cookiecutter.project_description }}" readme = "README.md" license-files = ["LICENSE"] @@ -20,12 +20,13 @@ classifiers = [ "Programming Language :: Python :: 3", ] dependencies = [] -requires-python = ">=3.9" +requires-python = ">=3.10" -[tool.setuptools.dynamic] -version = { attr = "{{ cookiecutter.__project_import }}.__version__" } +[build-system] +requires = ["uv_build>=0.8.14,<0.9.0"] +build-backend = "uv_build" -[project.optional-dependencies] +[dependency-groups] doc = [ {%- if cookiecutter.documentation == "pdoc" -%} "pdoc" @@ -35,7 +36,7 @@ test = ["pytest", "pytest-cov", "pretend", "coverage[toml]"] lint = [ # NOTE: ruff is under active development, so we pin conservatively here # and let Dependabot periodically perform this update. - "ruff ~= 0.6.2", + "ruff ~= 0.12", "mypy >= 1.0", "types-html5lib", "types-requests", @@ -44,7 +45,11 @@ lint = [ "interrogate", {%- endif %} ] -dev = ["{{ cookiecutter.project_slug }}[doc,test,lint]", "twine", "build"] +dev = [ + {include-group = "doc"}, + {include-group = "test"}, + {include-group = "lint"}, +] {% if cookiecutter.entry_point -%} [project.scripts] @@ -110,3 +115,11 @@ exclude = ["env", "test", "{{ cookiecutter.__project_src_path }}/_cli.py"] ignore-semiprivate = true fail-under = 100 {%- endif %} + +[tool.uv.sources] +{{ cookiecutter.project_slug }} = { workspace = true } + +{%- if cookiecutter.project_namespace_import %} +[tool.uv.build-backend] +module-name = "{{ cookiecutter.__project_import }}" +{%- endif %} diff --git a/{{cookiecutter.project_slug}}/src/{{cookiecutter.__module_import}}/__init__.py b/{{cookiecutter.project_slug}}/src/{{cookiecutter.__module_import}}/__init__.py index 5ae53f4..7c4677d 100644 --- a/{{cookiecutter.project_slug}}/src/{{cookiecutter.__module_import}}/__init__.py +++ b/{{cookiecutter.project_slug}}/src/{{cookiecutter.__module_import}}/__init__.py @@ -1,3 +1,5 @@ """The `{{ cookiecutter.project_slug }}` APIs.""" -__version__ = "{{ cookiecutter.version }}" +import importlib.metadata + +__version__ = importlib.metadata.version("{{ cookiecutter.project_slug }}")