Skip to content

Commit

Permalink
Use uv for dependencies handling (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkaMaul authored Sep 25, 2024
1 parent 4842dcb commit 0bdb2db
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 22 deletions.
18 changes: 11 additions & 7 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand All @@ -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; }
Expand Down
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,42 @@ 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 are installed using `uv pip install <package_name>` (after
activating the virtual environment).
1 change: 0 additions & 1 deletion hooks/post_gen_project.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import sys

REMOVE_PATHS = [
# We delete _cli.py and __main__.py if we're not generating a CLI.
Expand Down
7 changes: 7 additions & 0 deletions {{cookiecutter.project_slug}}/.github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down
7 changes: 7 additions & 0 deletions {{cookiecutter.project_slug}}/.github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 7 additions & 0 deletions {{cookiecutter.project_slug}}/.github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 7 additions & 5 deletions {{cookiecutter.project_slug}}/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 $(VENV)
@. $(VENV_BIN)/activate && uv pip install -e '.[$(INSTALL_EXTRA)]'

.PHONY: lint
lint: $(VENV)/pyvenv.cfg
Expand All @@ -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
Expand All @@ -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:
Expand Down
6 changes: 4 additions & 2 deletions {{cookiecutter.project_slug}}/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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"]
Expand 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 %}

0 comments on commit 0bdb2db

Please sign in to comment.