From 6742ec25c41c68815a8664f94f8d5bf3061d32e2 Mon Sep 17 00:00:00 2001 From: Alexis Date: Thu, 22 Aug 2024 17:18:12 +0200 Subject: [PATCH 1/8] Use `uv` for dependencies handling --- README.md | 27 +++++++++++++++----- hooks/post_gen_project.py | 1 - {{cookiecutter.project_slug}}/Makefile | 12 +++++---- {{cookiecutter.project_slug}}/pyproject.toml | 6 +++-- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c132694..cb31786 100644 --- a/README.md +++ b/README.md @@ -11,28 +11,41 @@ Both command-line and library packages can be generated. ## Usage -Install the `cookiecutter` CLI: +- Install [`uv`](https://docs.astral.sh/uv/) ```bash -python -m pip install cookiecutter +# On any platform with cURL and sh +curl -LsSf https://astral.sh/uv/install.sh | sh -# or, if you have pipx -pipx install cookiecutter +# On Windows +powershell -c "irm https://astral.sh/uv/install.ps1 | iex" + +# With Brew +brew install uv ``` -Use `cookiecutter` to generate a project using this template: +Please refer to [`uv` documentation](https://docs.astral.sh/uv/getting-started/installation/) for more installation options. + +- Use `cookiecutter` to generate a project using this template: ```bash # creates the project directory in $PWD -cookiecutter gh:trailofbits/cookiecutter-python +uvx cookiecutter gh:trailofbits/cookiecutter-python ``` Alternatively, tell `cookiecutter` where to put the new project directory: ```bash # creates ~/tmp/$project -cookiecutter -o ~/tmp gh:trailofbits/cookiecutter-python +uvx cookiecutter -o ~/tmp gh:trailofbits/cookiecutter-python ``` `cookiecutter` will prompt you for the project's name and all other relevant metadata. + +## Note + +The project will be generated using `uv`, a near drop-in replacement for +`pip` which is still in active development. + +Packages should be installed using diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 846a135..ff8ac06 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -1,5 +1,4 @@ import os -import sys REMOVE_PATHS = [ # We delete _cli.py and __main__.py if we're not generating a CLI. diff --git a/{{cookiecutter.project_slug}}/Makefile b/{{cookiecutter.project_slug}}/Makefile index 687ff6b..c1bad5a 100644 --- a/{{cookiecutter.project_slug}}/Makefile +++ b/{{cookiecutter.project_slug}}/Makefile @@ -46,12 +46,14 @@ dev: $(VENV)/pyvenv.cfg {%- if cookiecutter.entry_point %} .PHONY: run run: $(VENV)/pyvenv.cfg + # Once we can specify the default VENV name in uv, use `uv run` here + # https://github.com/astral-sh/uv/issues/1422 @. $(VENV_BIN)/activate && {{ cookiecutter.entry_point }} $(ARGS) {%- endif %} $(VENV)/pyvenv.cfg: pyproject.toml - python -m venv env - $(VENV_BIN)/python -m pip install -e .[$(INSTALL_EXTRA)] + uv venv env + @. $(VENV_BIN)/activate && uv pip install -e '.[$(INSTALL_EXTRA)]' .PHONY: lint lint: $(VENV)/pyvenv.cfg @@ -68,8 +70,8 @@ lint: $(VENV)/pyvenv.cfg .PHONY: reformat reformat: . $(VENV_BIN)/activate && \ - ruff check --fix && \ - ruff format + ruff format && \ + ruff check --fix .PHONY: test tests test tests: $(VENV)/pyvenv.cfg @@ -89,7 +91,7 @@ doc: .PHONY: package package: $(VENV)/pyvenv.cfg - $(VENV_BIN)/python -m build + uvx --from build pyproject-build --installer uv .PHONY: edit edit: diff --git a/{{cookiecutter.project_slug}}/pyproject.toml b/{{cookiecutter.project_slug}}/pyproject.toml index bed568d..8c8a098 100644 --- a/{{cookiecutter.project_slug}}/pyproject.toml +++ b/{{cookiecutter.project_slug}}/pyproject.toml @@ -30,7 +30,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.4.0", + "ruff ~= 0.6.2", "mypy >= 1.0", "types-html5lib", "types-requests", @@ -77,7 +77,7 @@ warn_unused_ignores = true [tool.ruff] line-length = 100 -target-version = "py38" +include = ["src/**/*.py", "test/**/*.py"] [tool.ruff.lint] select = ["ALL"] @@ -97,9 +97,11 @@ ignore = ["D203", "D213", "COM812", "ISC001"] "S101", # asserts are expected in tests ] +{%- if cookiecutter.docstring_coverage %} [tool.interrogate] # don't enforce documentation coverage for packaging, testing, the virtual # environment, or the CLI (which is documented separately). exclude = ["env", "test", "{{ cookiecutter.__project_src_path }}/_cli.py"] ignore-semiprivate = true fail-under = 100 +{%- endif %} \ No newline at end of file From 474bfb0664466cfd6cfa4237ea2c40b8c7527915 Mon Sep 17 00:00:00 2001 From: Alexis Date: Thu, 22 Aug 2024 17:22:50 +0200 Subject: [PATCH 2/8] Update the missing sentence in the README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cb31786..8eb832e 100644 --- a/README.md +++ b/README.md @@ -48,4 +48,5 @@ metadata. The project will be generated using `uv`, a near drop-in replacement for `pip` which is still in active development. -Packages should be installed using +Packages either installed using `uv pip install ` (after +activating the virtual environment). \ No newline at end of file From 4afcd72b7fd0c1ea231a670c08dd1ccb14d12325 Mon Sep 17 00:00:00 2001 From: Alexis Date: Thu, 22 Aug 2024 17:24:10 +0200 Subject: [PATCH 3/8] Fix typo in Makefile --- {{cookiecutter.project_slug}}/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/{{cookiecutter.project_slug}}/Makefile b/{{cookiecutter.project_slug}}/Makefile index c1bad5a..d150226 100644 --- a/{{cookiecutter.project_slug}}/Makefile +++ b/{{cookiecutter.project_slug}}/Makefile @@ -52,7 +52,7 @@ run: $(VENV)/pyvenv.cfg {%- endif %} $(VENV)/pyvenv.cfg: pyproject.toml - uv venv env + uv venv $(VENV) @. $(VENV_BIN)/activate && uv pip install -e '.[$(INSTALL_EXTRA)]' .PHONY: lint From 875ac46c8b044e2b0ebfb299333bebe1aeea5627 Mon Sep 17 00:00:00 2001 From: Alexis Date: Thu, 22 Aug 2024 17:28:53 +0200 Subject: [PATCH 4/8] Fix typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8eb832e..29a5d28 100644 --- a/README.md +++ b/README.md @@ -48,5 +48,5 @@ metadata. The project will be generated using `uv`, a near drop-in replacement for `pip` which is still in active development. -Packages either installed using `uv pip install ` (after +Packages are installed using `uv pip install ` (after activating the virtual environment). \ No newline at end of file From d62976a9b5d0c5c985ef5506853a83cfa41a2be2 Mon Sep 17 00:00:00 2001 From: Alexis Date: Thu, 22 Aug 2024 17:34:28 +0200 Subject: [PATCH 5/8] Update Actions --- .github/workflows/tests.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fe4dd88..ffdab18 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,8 +18,12 @@ jobs: with: python-version: "3.x" - - name: install cookiecutter - run: python -m pip install cookiecutter + - name: install uv + run: > + curl --no-progress-meter --location --fail + --proto '=https' --tlsv1.2 + "https://astral.sh/uv/install.sh" + | sh # we need the git config setup here to make sure the subsequent git commit in each test works - name: setup fake git committer @@ -29,7 +33,7 @@ jobs: - name: run template (default) run: | - cookiecutter --no-input -o /tmp . + uvx cookiecutter --no-input -o /tmp . [[ -d /tmp/python-project/src/python_project ]] || { >&2 echo "not generated?"; exit 1; } @@ -48,7 +52,7 @@ jobs: - name: run template (no entry point) run: | - cookiecutter --no-input -o /tmp . entry_point='' + uvx cookiecutter --no-input -o /tmp . entry_point='' [[ ! -f /tmp/python-project/python_project/__main__.py ]] || { >&2 echo "not expecting main"; exit 1; } @@ -67,7 +71,7 @@ jobs: - name: run template (namespace) run: | - cookiecutter --no-input -o /tmp . project_namespace_import=tob.r_and_e + uvx cookiecutter --no-input -o /tmp . project_namespace_import=tob.r_and_e [[ -d /tmp/tob-r-and-e-python-project/src/tob/r_and_e/python_project ]] || { >&2 echo "not generated?"; exit 1; } @@ -86,7 +90,7 @@ jobs: - name: run template (namespace, short slug) run: | - cookiecutter --no-input -o /tmp . project_namespace_import=tob.r_and_e "project_name=Bit Trails" project_slug=bit-trails + uvx cookiecutter --no-input -o /tmp . project_namespace_import=tob.r_and_e "project_name=Bit Trails" project_slug=bit-trails [[ -d /tmp/bit-trails/src/tob/r_and_e/bit_trails ]] || { >&2 echo "not generated?"; exit 1; } @@ -105,7 +109,7 @@ jobs: - name: run template (no docs) run: | - cookiecutter --no-input -o /tmp . documentation='none' + uvx cookiecutter --no-input -o /tmp . documentation='none' [[ -d /tmp/python-project/src/python_project ]] || { >&2 echo "not generated?"; exit 1; } [[ ! -f /tmp/python-project/.github/workflows/docs.yml ]] || { >&2 echo "not expecting docs.yml"; exit 1; } From d62754b8018e33779cf7e847e940a394dcdb1491 Mon Sep 17 00:00:00 2001 From: Alexis Date: Wed, 25 Sep 2024 17:22:22 +0200 Subject: [PATCH 6/8] Install UV in workflows --- {{cookiecutter.project_slug}}/.github/workflows/docs.yml | 7 +++++++ {{cookiecutter.project_slug}}/.github/workflows/lint.yml | 7 +++++++ {{cookiecutter.project_slug}}/.github/workflows/tests.yml | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/{{cookiecutter.project_slug}}/.github/workflows/docs.yml b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml index 79cb494..836d3ae 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/docs.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml @@ -16,6 +16,13 @@ jobs: python-version-file: pyproject.toml cache: "pip" cache-dependency-path: pyproject.toml + + - name: install uv + run: > + curl --no-progress-meter --location --fail + --proto '=https' --tlsv1.2 + "https://astral.sh/uv/install.sh" + | sh - name: setup run: | diff --git a/{{cookiecutter.project_slug}}/.github/workflows/lint.yml b/{{cookiecutter.project_slug}}/.github/workflows/lint.yml index f484a39..41faacc 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/lint.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/lint.yml @@ -17,6 +17,13 @@ jobs: python-version-file: pyproject.toml cache: "pip" cache-dependency-path: pyproject.toml + + - name: install uv + run: > + curl --no-progress-meter --location --fail + --proto '=https' --tlsv1.2 + "https://astral.sh/uv/install.sh" + | sh - name: lint run: make lint INSTALL_EXTRA=lint diff --git a/{{cookiecutter.project_slug}}/.github/workflows/tests.yml b/{{cookiecutter.project_slug}}/.github/workflows/tests.yml index 9bd0005..6641fb6 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/tests.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/tests.yml @@ -24,6 +24,13 @@ jobs: python-version: ${{ matrix.python }} cache: "pip" cache-dependency-path: pyproject.toml + + - name: install uv + run: > + curl --no-progress-meter --location --fail + --proto '=https' --tlsv1.2 + "https://astral.sh/uv/install.sh" + | sh - name: test run: make test INSTALL_EXTRA=test From 472958bf259438250d05b19a985843714554d26c Mon Sep 17 00:00:00 2001 From: Alexis Date: Wed, 25 Sep 2024 17:41:17 +0200 Subject: [PATCH 7/8] Fix workflows --- {{cookiecutter.project_slug}}/.github/workflows/docs.yml | 2 +- {{cookiecutter.project_slug}}/.github/workflows/lint.yml | 4 ++-- {{cookiecutter.project_slug}}/.github/workflows/release.yml | 4 ++-- {{cookiecutter.project_slug}}/.github/workflows/tests.yml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/{{cookiecutter.project_slug}}/.github/workflows/docs.yml b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml index 836d3ae..4664e7f 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/docs.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/setup-python@v5 with: python-version-file: pyproject.toml - cache: "pip" + # cache: "uv" # Wait on https://github.com/actions/setup-python/pull/818 to be merged cache-dependency-path: pyproject.toml - name: install uv diff --git a/{{cookiecutter.project_slug}}/.github/workflows/lint.yml b/{{cookiecutter.project_slug}}/.github/workflows/lint.yml index 41faacc..6c0054e 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/lint.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/lint.yml @@ -15,8 +15,8 @@ jobs: - uses: actions/setup-python@v5 with: python-version-file: pyproject.toml - cache: "pip" - cache-dependency-path: pyproject.toml + # cache: "uv" # Wait on https://github.com/actions/setup-python/pull/818 to be merged + # cache-dependency-path: pyproject.toml - name: install uv run: > diff --git a/{{cookiecutter.project_slug}}/.github/workflows/release.yml b/{{cookiecutter.project_slug}}/.github/workflows/release.yml index 9898a24..01690bb 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/release.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/release.yml @@ -25,8 +25,8 @@ jobs: - uses: actions/setup-python@v5 with: python-version-file: pyproject.toml - cache: "pip" - cache-dependency-path: pyproject.toml + # cache: "uv" # Wait on https://github.com/actions/setup-python/pull/818 to be merged + # cache-dependency-path: pyproject.toml - name: deps run: python -m pip install -U setuptools build wheel diff --git a/{{cookiecutter.project_slug}}/.github/workflows/tests.yml b/{{cookiecutter.project_slug}}/.github/workflows/tests.yml index 6641fb6..cca1815 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/tests.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/tests.yml @@ -22,8 +22,8 @@ jobs: - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - cache: "pip" - cache-dependency-path: pyproject.toml + # cache: "uv" # Wait on https://github.com/actions/setup-python/pull/818 to be merged + # cache-dependency-path: pyproject.toml - name: install uv run: > From a1743a7d66da5801b7fc150d1659fd7a495dd9b6 Mon Sep 17 00:00:00 2001 From: Alexis Date: Wed, 25 Sep 2024 18:05:17 +0200 Subject: [PATCH 8/8] Use official uv action --- .../.github/workflows/docs.yml | 15 ++++----------- .../.github/workflows/lint.yml | 10 +++++----- .../.github/workflows/release.yml | 13 +++++-------- .../.github/workflows/tests.yml | 18 +++++++----------- 4 files changed, 21 insertions(+), 35 deletions(-) diff --git a/{{cookiecutter.project_slug}}/.github/workflows/docs.yml b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml index d3cd121..ca6c622 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/docs.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml @@ -11,18 +11,11 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - name: Install uv + uses: astral-sh/setup-uv@v3 with: - python-version-file: pyproject.toml - # cache: "uv" # Wait on https://github.com/actions/setup-python/pull/818 to be merged - # cache-dependency-path: pyproject.toml - - - name: install uv - run: > - curl --no-progress-meter --location --fail - --proto '=https' --tlsv1.2 - "https://astral.sh/uv/install.sh" - | sh + enable-cache: true + cache-dependency-glob: pyproject.toml - name: setup run: | diff --git a/{{cookiecutter.project_slug}}/.github/workflows/lint.yml b/{{cookiecutter.project_slug}}/.github/workflows/lint.yml index 6c0054e..77eb058 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/lint.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/lint.yml @@ -12,12 +12,12 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - name: Install uv + uses: astral-sh/setup-uv@v3 with: - python-version-file: pyproject.toml - # cache: "uv" # Wait on https://github.com/actions/setup-python/pull/818 to be merged - # cache-dependency-path: pyproject.toml - + enable-cache: true + cache-dependency-glob: pyproject.toml + - name: install uv run: > curl --no-progress-meter --location --fail diff --git a/{{cookiecutter.project_slug}}/.github/workflows/release.yml b/{{cookiecutter.project_slug}}/.github/workflows/release.yml index 01690bb..65fe7da 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/release.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/release.yml @@ -22,17 +22,14 @@ jobs: with: persist-credentials: false - - uses: actions/setup-python@v5 + - name: Install uv + uses: astral-sh/setup-uv@v3 with: - python-version-file: pyproject.toml - # cache: "uv" # Wait on https://github.com/actions/setup-python/pull/818 to be merged - # cache-dependency-path: pyproject.toml - - - name: deps - run: python -m pip install -U setuptools build wheel + enable-cache: true + cache-dependency-glob: pyproject.toml - name: build - run: python -m build + run: uvx --from build pyproject-build --installer uv - name: publish uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/{{cookiecutter.project_slug}}/.github/workflows/tests.yml b/{{cookiecutter.project_slug}}/.github/workflows/tests.yml index cca1815..0bf01c6 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/tests.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/tests.yml @@ -19,18 +19,14 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - name: Install uv + uses: astral-sh/setup-uv@v3 with: - python-version: ${{ matrix.python }} - # cache: "uv" # Wait on https://github.com/actions/setup-python/pull/818 to be merged - # cache-dependency-path: pyproject.toml - - - name: install uv - run: > - curl --no-progress-meter --location --fail - --proto '=https' --tlsv1.2 - "https://astral.sh/uv/install.sh" - | sh + enable-cache: true + cache-dependency-glob: pyproject.toml + + - name: Install Python ${{ matrix.python }} + run: uv python install ${{ matrix.python }} - name: test run: make test INSTALL_EXTRA=test