Skip to content

Commit 74da737

Browse files
committed
Migrate from tox/poetry to uv and just
- Remove `tox` and related CI configs. - Add `uv` for dependency management and testing. - Add `justfile` for command running. - Update `pyproject.toml` to use `[dependency-groups]`. - Update CI workflows to use `astral-sh/setup-uv`. - Update documentation (`TESTING.rst`, `PACKAGING.rst`, `CLAUDE.md`) to reflect new workflow. - Add `qrcode/tests/test_main.py` to cover `__main__.py`.
1 parent 78d77fb commit 74da737

File tree

10 files changed

+152
-144
lines changed

10 files changed

+152
-144
lines changed

.github/workflows/linting.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@ jobs:
1111
- name: Checkout Code
1212
uses: actions/checkout@v4
1313

14-
- name: Install Dependencies
15-
run: pip install ruff
14+
- name: Install uv
15+
uses: astral-sh/setup-uv@v5
16+
with:
17+
enable-cache: true
18+
cache-dependency-glob: "uv.lock"
1619

1720
- name: Code Linting
1821
if: always()
19-
run: ruff check qrcode
22+
run: uv run ruff check qrcode
2023

2124
- name: Code Formatting
2225
if: always()
23-
run: ruff format --check qrcode
26+
run: uv run ruff format --check qrcode

.github/workflows/push.yml

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,29 @@ name: Testsuite Run
33
on: [push]
44

55
jobs:
6-
build:
6+
test:
7+
name: Test Python ${{ matrix.python-version }}
78
runs-on: ubuntu-latest
89
strategy:
9-
max-parallel: 4
10+
fail-fast: false
1011
matrix:
1112
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
1213

1314
steps:
1415
- uses: actions/checkout@v4
1516

16-
- name: Set up Python ${{ matrix.python-version }}
17-
uses: actions/setup-python@v5
17+
- name: Install uv
18+
uses: astral-sh/setup-uv@v5
1819
with:
1920
python-version: ${{ matrix.python-version }}
21+
enable-cache: true
22+
cache-dependency-glob: "uv.lock"
2023

21-
- name: Install dependencies
22-
run: |
23-
pip install --disable-pip-version-check tox tox-gh-actions
24-
- name: Test with tox
25-
run: tox
24+
- name: Test with pil
25+
run: uv run --extra pil --group dev pytest
26+
27+
- name: Test with png
28+
run: uv run --extra png --group dev pytest
29+
30+
- name: Test with none
31+
run: uv run --group dev pytest

.github/workflows/python-app.yml

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

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ cov.xml
99
dist/
1010
htmlcov/
1111
poetry.lock
12+
uv.lock
1213
qrcode.egg-info/

PACKAGING.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
Packaging quick reminder
22
========================
33

4-
Make sure maintainer dependencies are installed::
5-
6-
poetry install
4+
Release commands are handled via ``zest.releaser``, which is included in the
5+
dev dependency group.
76

87
Run release command and follow prompt instructions::
98

10-
poetry run fullrelease
9+
uv run fullrelease

TESTING.rst

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
Testing
22
=======
33

4-
First, install dev dependencies::
4+
This project uses `uv <https://github.com/astral-sh/uv>`_ for dependency management and running tests.
5+
It also uses `just <https://github.com/casey/just>`_ as a command runner for convenience.
56

6-
poetry install --with dev
7+
Setup
8+
-----
79

8-
To run all tests, you'll need to install multiple Python interpreters. On a
9-
modern Ubuntu distribution you can use ``add-apt-repository
10-
ppa:deadsnakes/ppa``.
10+
1. Install ``uv`` (see `installation instructions <https://github.com/astral-sh/uv?tab=readme-ov-file#installation>`_).
11+
2. Install ``just`` (see `installation instructions <https://github.com/casey/just?tab=readme-ov-file#installation>`_).
1112

12-
Depending on if you can install the wheels directly for your OS, you may need
13-
the libraries to build PIL, too. Here's the Ubuntu commands::
13+
Running Tests
14+
-------------
1415

15-
sudo apt-get install build-essential python-dev python3-dev
16-
sudo apt-get install libjpeg8-dev zlib1g-dev
16+
To run the full test suite (all Python versions and variants)::
1717

18-
Here's the OSX Homebrew command:
18+
just test
1919

20-
brew install libjpeg libtiff little-cms2 openjpeg webp
20+
To run a quick test on your current environment (fastest)::
2121

22-
Finally, just run ``tox``::
22+
just test quick
2323

24-
poetry run tox
25-
# or
26-
poetry shell
27-
tox
24+
To run tests for a specific Python version::
2825

29-
If you want, you can test against a specific version like this: ``tox -e py312-pil``
26+
just test 3.12
3027

28+
To run tests for a specific Python version and variant (pil, png, none)::
29+
30+
just test 3.12 pil
3131

3232
Linting
3333
-------
3434

35-
Run `ruff` to check formatting::
35+
To run all checks (formatting, linting, and tests)::
3636

37-
ruff format qrcode
37+
just check

justfile

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Justfile for python-qrcode
2+
# Modern development commands using uv
3+
4+
# Default recipe - show available commands
5+
default:
6+
@just --list
7+
8+
# Run tests
9+
# Usage:
10+
# just test -> run all test matrices + coverage
11+
# just test quick -> quick test with current Python (no coverage)
12+
# just test [3.10|3.11|...] -> run specific python version (all variants)
13+
# just test [3.10|...] [pil|png|none] -> run specific python and variant
14+
test *ARGS='':
15+
#!/usr/bin/env bash
16+
set -euo pipefail
17+
18+
ARGS=( {{ ARGS }} )
19+
20+
if [ ${#ARGS[@]} -eq 0 ]; then
21+
# No args: run all
22+
echo "Running all test environments..."
23+
just _test-matrix
24+
just _coverage-report
25+
elif [ ${#ARGS[@]} -eq 1 ]; then
26+
ARG="${ARGS[0]}"
27+
if [ "$ARG" = "quick" ]; then
28+
uv run --quiet --group dev pytest -q
29+
elif [[ "$ARG" =~ ^3\.[0-9]+$ ]]; then
30+
# Run all variants for this python version
31+
just _test-env "$ARG" pil
32+
just _test-env "$ARG" png
33+
just _test-env "$ARG" none
34+
else
35+
echo "Unknown argument: $ARG"
36+
exit 1
37+
fi
38+
elif [ ${#ARGS[@]} -eq 2 ]; then
39+
just _test-env "${ARGS[0]}" "${ARGS[1]}"
40+
else
41+
echo "Usage: just test [quick | PYTHON_VER | PYTHON_VER VARIANT]"
42+
exit 1
43+
fi
44+
45+
# Run all test environments (internal)
46+
_test-matrix:
47+
#!/usr/bin/env bash
48+
set -e
49+
echo "Cleaning old coverage files..."
50+
rm -rf .coverage* htmlcov
51+
for py in 3.10 3.11 3.12 3.13 3.14; do
52+
just _test-env $py pil
53+
just _test-env $py png
54+
just _test-env $py none
55+
done
56+
57+
# Run a specific test environment (internal)
58+
_test-env PYTHON VARIANT:
59+
@printf "Testing: Python %-5s - %-5s " "{{ PYTHON }}" "{{ VARIANT }}"
60+
@if [ "{{ VARIANT }}" = "pil" ]; then \
61+
uv run --quiet --python {{ PYTHON }} --extra pil --group dev coverage run -m pytest -q; \
62+
elif [ "{{ VARIANT }}" = "png" ]; then \
63+
uv run --quiet --python {{ PYTHON }} --extra png --group dev coverage run -m pytest -q; \
64+
elif [ "{{ VARIANT }}" = "none" ]; then \
65+
uv run --quiet --python {{ PYTHON }} --group dev coverage run -m pytest -q; \
66+
else \
67+
echo "Unknown variant: {{ VARIANT }}"; exit 1; \
68+
fi
69+
@echo "✓"
70+
71+
# Generate coverage report (internal)
72+
_coverage-report:
73+
@uv run --quiet --group dev coverage combine --quiet .coverage* 2>/dev/null || true
74+
@echo ""
75+
@echo "Test coverage:"
76+
@uv run --quiet --group dev coverage report -m
77+
@uv run --quiet --group dev coverage html
78+
@echo "Coverage report saved to htmlcov/index.html"
79+
80+
# Run all checks (format, lint, tests)
81+
check:
82+
@echo "Running all checks..."
83+
@echo "→ Formatting..."
84+
@uv run --quiet ruff format --check qrcode
85+
@echo "→ Linting..."
86+
@uv run --quiet ruff check qrcode
87+
@echo "→ Testing..."
88+
@just test

pyproject.toml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ changelog = "https://github.com/lincolnloop/python-qrcode/blob/main/CHANGES.rst"
5050
[project.scripts]
5151
qr = "qrcode.console_scripts:main"
5252

53+
[dependency-groups]
54+
dev = [
55+
"pytest",
56+
"pytest-cov",
57+
"ruff",
58+
"pypng",
59+
"pillow>=9.1.0",
60+
"docutils>=0.21.2",
61+
"zest-releaser[recommended]>=9.2.0",
62+
]
63+
5364
[tool.poetry]
5465
packages = [{ include = "qrcode" }]
5566
readme = ["README.rst", "CHANGES.rst"]
@@ -61,16 +72,6 @@ readme = ["README.rst", "CHANGES.rst"]
6172
# { destination = "share/man/man1", from = [ "doc/qr.1" ] },
6273
# ]
6374

64-
[tool.poetry.group.dev.dependencies]
65-
pytest = { version = "*" }
66-
pytest-cov = { version = "*" }
67-
tox = { version = "*" }
68-
ruff = { version = "*" }
69-
pypng = { version = "*" }
70-
pillow = { version = ">=9.1.0" }
71-
docutils = "^0.21.2"
72-
zest-releaser = { extras = ["recommended"], version = "^9.2.0" }
73-
7475
[tool.zest-releaser]
7576
less-zeros = "yes"
7677
version-levels = 2

qrcode/tests/test_main.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import runpy
2+
from unittest import mock
3+
4+
5+
def test_main_execution():
6+
with mock.patch("qrcode.console_scripts.main") as mock_main:
7+
runpy.run_module("qrcode", run_name="__main__")
8+
mock_main.assert_called_once()

tox.ini

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

0 commit comments

Comments
 (0)