Skip to content

Commit 53fb451

Browse files
authored
Introduce Justfile, use uv (#671)
* Introduce Justfile, use uv in CI * Pin actions * Set `COVERAGE_PROCESS_START` * Always cover with sysmon * Use FAST=1 with Pypy * Tweaks * Also run lints * Remove pdm, tox, migrate to uv * Tweak .readthedocs.yml * Tweak * Tweak * Use full path for just * Try making BUILDDIR configurable * Actually pass the argument * Tweak some more * Try pipx? * Just via asdf * Fix * Build docs on 3.13 * Docs
1 parent 5d23a08 commit 53fb451

File tree

11 files changed

+2066
-1722
lines changed

11 files changed

+2066
-1722
lines changed

.github/workflows/main.yml

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,22 @@ jobs:
1616

1717
strategy:
1818
matrix:
19-
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "pypy-3.10"]
19+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "pypy3.10"]
2020
fail-fast: false
2121

2222
steps:
2323
- uses: "actions/checkout@v4"
2424
with:
2525
persist-credentials: false
2626

27-
- uses: "pdm-project/setup-pdm@v4"
28-
with:
29-
python-version: "${{ matrix.python-version }}"
30-
allow-python-prereleases: true
31-
cache: true
32-
version: "2.21.0"
27+
- uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3.0.0
28+
- uses: hynek/setup-cached-uv@757bedc3f972eb7227a1aa657651f15a8527c817 # v2.3.0
3329

34-
- name: "Run Tox"
30+
- name: "Run Tests"
31+
env:
32+
FAST: ${{ startsWith(matrix.python-version, 'pypy') && '1' || '' }}
3533
run: |
36-
python -Im pip install --upgrade tox tox-gh-actions
37-
38-
python -Im tox
34+
just --set python ${{ startsWith(matrix.python-version, 'pypy') && matrix.python-version || format('python{0}', matrix.python-version) }} cov
3935
4036
- name: Upload coverage data
4137
uses: actions/upload-artifact@v4
@@ -55,33 +51,28 @@ jobs:
5551
with:
5652
persist-credentials: false
5753

58-
- uses: "actions/setup-python@v5"
59-
with:
60-
cache: "pip"
61-
python-version: "3.12"
62-
63-
- run: "python -Im pip install --upgrade coverage[toml]"
64-
6554
- name: Download coverage data
6655
uses: actions/download-artifact@v4
6756
with:
6857
pattern: coverage-data-*
6958
merge-multiple: true
7059

60+
- uses: hynek/setup-cached-uv@757bedc3f972eb7227a1aa657651f15a8527c817 # v2.3.0
61+
7162
- name: "Combine coverage"
7263
run: |
73-
python -Im coverage combine
74-
python -Im coverage html
75-
python -Im coverage json
64+
uv run --group test coverage combine
65+
uv run --group test coverage html
66+
uv run --group test coverage json
7667
7768
# Report and write to summary.
78-
python -Im coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
69+
uv run --group test coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
7970
80-
export TOTAL=$(python -c "import json;print(json.load(open('coverage.json'))['totals']['percent_covered_display'])")
71+
export TOTAL=$(uv run python -c "import json;print(json.load(open('coverage.json'))['totals']['percent_covered_display'])")
8172
echo "total=$TOTAL" >> $GITHUB_ENV
8273
8374
# Report again and fail if under the threshold.
84-
python -Im coverage report --fail-under=100
75+
uv run --group test coverage report --fail-under=100
8576
8677
- name: "Upload HTML report."
8778
uses: "actions/upload-artifact@v4"
@@ -90,19 +81,20 @@ jobs:
9081
path: "htmlcov"
9182
if: always()
9283

93-
- name: "Make badge"
94-
if: github.ref == 'refs/heads/main'
95-
uses: "schneegans/[email protected]"
84+
lint:
85+
name: "Run linters"
86+
runs-on: "ubuntu-latest"
87+
steps:
88+
- uses: "actions/checkout@v4"
9689
with:
97-
# GIST_TOKEN is a GitHub personal access token with scope "gist".
98-
auth: ${{ secrets.GIST_TOKEN }}
99-
gistID: 22405310d6a663164d894a2beab4d44d
100-
filename: covbadge.json
101-
label: Coverage
102-
message: ${{ env.total }}%
103-
minColorRange: 50
104-
maxColorRange: 90
105-
valColorRange: ${{ env.total }}
90+
persist-credentials: false
91+
92+
- uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3.0.0
93+
- uses: hynek/setup-cached-uv@757bedc3f972eb7227a1aa657651f15a8527c817 # v2.3.0
94+
95+
- name: "Run linters"
96+
run: |
97+
just lint
10698
10799
package:
108100
name: "Build & verify package"
@@ -112,18 +104,14 @@ jobs:
112104
- uses: "actions/checkout@v4"
113105
with:
114106
persist-credentials: false
115-
- uses: "pdm-project/setup-pdm@v4"
116-
with:
117-
python-version: "3.12"
118-
version: "2.21.0"
119107

120-
- name: "Install check-wheel-content and twine"
121-
run: "python -m pip install twine check-wheel-contents"
108+
- uses: hynek/setup-cached-uv@757bedc3f972eb7227a1aa657651f15a8527c817
109+
122110
- name: "Build package"
123-
run: "pdm build"
111+
run: "uvx pdm build"
124112
- name: "List result"
125113
run: "ls -l dist"
126114
- name: "Check wheel contents"
127-
run: "check-wheel-contents --toplevel cattr,cattrs dist/*.whl"
115+
run: "uvx check-wheel-contents --toplevel cattr,cattrs dist/*.whl"
128116
- name: "Check long_description"
129-
run: "python -m twine check dist/*"
117+
run: "uvx twine check dist/*"

.readthedocs.yml

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,22 @@ sphinx:
44
configuration: docs/conf.py
55

66
build:
7-
os: ubuntu-20.04
7+
os: ubuntu-lts-latest
88
tools:
9-
# Keep version in sync with tox.ini (docs and gh-actions).
10-
python: "3.11"
9+
python: "3.13"
1110
jobs:
12-
# Need the tags to calculate the version
13-
post_checkout:
14-
- git fetch --tags
15-
post_create_environment:
16-
- "curl -sSL https://github.com/raw/pdm-project/pdm/main/install-pdm.py | python3 -"
11+
create_environment:
12+
- asdf plugin add uv
13+
- asdf plugin add just
14+
- asdf install uv latest
15+
- asdf global uv latest
16+
- asdf install just latest
17+
- asdf global just latest
18+
install:
19+
- UV_PROJECT_ENVIRONMENT=$READTHEDOCS_VIRTUALENV_PATH uv sync --group docs --all-extras --link-mode=copy
1720
post_install:
18-
- "VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH ~/.local/bin/pdm sync -dG :all,docs"
21+
# Need the tags to calculate the version
22+
- git fetch --tags
23+
build:
24+
html:
25+
- UV_PROJECT_ENVIRONMENT=$READTHEDOCS_VIRTUALENV_PATH just docs $READTHEDOCS_OUTPUT

CONTRIBUTING.md

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,38 +55,45 @@ Ready to contribute? Here's how to set up _cattrs_ for local development.
5555
$ git clone [email protected]:your_name_here/cattrs.git
5656
```
5757

58-
3. Install your local copy into a virtualenv. Assuming you have [PDM](https://pdm.fming.dev/latest/) installed, this is how you set up your fork for local development::
58+
3. Install your local copy into a virtualenv. Assuming you have [uv](https://docs.astral.sh/uv/) installed, this is how you set up your fork for local development::
5959

6060
```shell
6161
$ cd cattrs/
62-
$ pdm install -d -G :all
62+
$ uv sync --all-groups --all-extras
6363
```
6464

6565
4. Create a branch for local development::
6666

6767
```shell
68-
$ git checkout -b name-of-your-bugfix-or-feature
68+
$ git switch -c name-of-your-bugfix-or-feature
6969
```
7070

7171
Now you can make your changes locally.
7272

73-
5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox::
73+
5. When you're done making changes, check that your changes pass lints and the tests, including testing other Python versions::
7474

7575
```shell
76-
$ make lint
77-
$ make test
78-
$ tox
76+
$ just lint
77+
$ just test
78+
$ just --set python python3.9 test # Test on other versions
7979
```
8080

81-
6. Commit your changes and push your branch to GitHub::
81+
6. Write any necessary documentation, including updating the changelog (HISTORY.md). The docs can be built like so:
82+
83+
```shell
84+
$ just docs
85+
$ just htmllive # Build the docs, serve then and autoreload on changes
86+
```
87+
88+
7. Commit your changes and push your branch to GitHub::
8289

8390
```shell
8491
$ git add .
8592
$ git commit -m "Your detailed description of your changes."
8693
$ git push origin name-of-your-bugfix-or-feature
8794
```
8895

89-
7. Submit a pull request through the GitHub website.
96+
8. Submit a pull request through the GitHub website.
9097

9198
## Pull Request Guidelines
9299

@@ -106,5 +113,5 @@ Before you submit a pull request, check that it meets these guidelines:
106113
To run a subset of tests:
107114

108115
```shell
109-
$ pdm run pytest tests.test_unstructure
116+
$ just test tests/test_unstructure.py
110117
```

HISTORY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ Our backwards-compatibility policy can be found [here](https://github.com/python
3535
- The default disambiguation hook factory is now only enabled for converters with `unstructure_strat=AS_DICT` (the default).
3636
Since the strategy doesn't support tuples, it is skipped for `unstructure_strat=AS_TUPLE` converters.
3737
([#673](https://github.com/python-attrs/cattrs/pull/673))
38+
- Switch to [`uv`](https://docs.astral.sh/uv/) and [`just`](https://just.systems/man/en/) in lieu of PDM, tox and Make.
39+
See [the Contributing section](https://catt.rs/en/v25.2.0/contributing.html#get-started) for new workflow instructions.
40+
([#671](https://github.com/python-attrs/cattrs/pull/671))
3841

3942
## 25.1.1 (2025-06-04)
4043

Justfile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
python := ""
2+
3+
lint:
4+
uv run -p python3.13 --group lint ruff check src/ tests bench
5+
uv run -p python3.13 --group lint black --check src tests docs/conf.py
6+
7+
test *args="-x --ff -n auto tests":
8+
uv run {{ if python != '' { '-p ' + python } else { '' } }} --all-extras --group test pytest {{args}}
9+
10+
cov *args="-x --ff -n auto tests":
11+
@uv run {{ if python != '' { '-p ' + python } else { '' } }} python -c 'import pathlib, site; pathlib.Path(f"{site.getsitepackages()[0]}/cov.pth").write_text("import coverage; coverage.process_startup()")'
12+
COVERAGE_PROCESS_START={{justfile_directory()}}/pyproject.toml uv run {{ if python != '' { '-p ' + python } else { '' } }} --all-extras --group test coverage run -m pytest {{args}}
13+
14+
bench-cmp:
15+
uv run pytest bench --benchmark-compare
16+
17+
bench:
18+
uv run pytest bench --benchmark-save base
19+
20+
docs output_dir="_build": ## generate Sphinx HTML documentation, including API docs
21+
make -C docs -e BUILDDIR={{output_dir}} clean
22+
make -C docs -e BUILDDIR={{output_dir}} doctest
23+
make -C docs -e BUILDDIR={{output_dir}} html
24+
25+
htmllive: docs ## compile the docs watching for changes
26+
make -C docs htmllive

Makefile

Lines changed: 0 additions & 80 deletions
This file was deleted.

docs/Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# You can set these variables from the command line.
55
SPHINXOPTS =
6-
SPHINXBUILD = pdm run sphinx-build
6+
SPHINXBUILD = uv run --all-extras --group docs sphinx-build
77
PAPER =
88
BUILDDIR = _build
99

@@ -173,15 +173,15 @@ pseudoxml:
173173

174174
.PHONY: apidoc
175175
apidoc:
176-
pdm run sphinx-apidoc -o . ../src/cattrs/ '../**/converters.py' -f -M
176+
uv run sphinx-apidoc -o . ../src/cattrs/ '../**/converters.py' -f -M
177177

178178
## htmlview to open the index page built by the html target in your browser
179179
.PHONY: htmlview
180180
htmlview: html
181-
pdm run python -c "import os, webbrowser; webbrowser.open('file://' + os.path.realpath('$(BUILDDIR)/html/index.html'))"
181+
uv run python -c "import os, webbrowser; webbrowser.open('file://' + os.path.realpath('$(BUILDDIR)/html/index.html'))"
182182

183183
## htmllive to rebuild and reload HTML files in your browser
184184
.PHONY: htmllive
185-
htmllive: SPHINXBUILD = pdm run sphinx-autobuild
185+
htmllive: SPHINXBUILD = uv run sphinx-autobuild
186186
htmllive: SPHINXERRORHANDLING = --re-ignore="/\.idea/|/venv/|/pep-0000.rst|/topic/"
187187
htmllive: html

0 commit comments

Comments
 (0)