Skip to content

Commit fd80557

Browse files
Add config for using uv
Add config for using uv to pyproject.toml and templated pyproject.toml, add uv lockfile. … Co-authored-by: Oliver Copping <[email protected]>
1 parent 7bdc71a commit fd80557

File tree

4 files changed

+1613
-60
lines changed

4 files changed

+1613
-60
lines changed

pyproject.toml

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "python-copier-template"
77
dynamic = ["version"]
88
requires-python = ">=3.11"
99

10-
[project.optional-dependencies]
10+
[dependency-groups]
1111
dev = [
1212
"copier",
1313
"myst-parser",
@@ -18,8 +18,9 @@ dev = [
1818
"sphinx-autobuild",
1919
"sphinx-copybutton",
2020
"sphinx-design",
21-
"tox",
22-
"tox-direct",
21+
"tox-uv",
22+
"twine>=6.1.0",
23+
"uv~=0.7.0",
2324
]
2425

2526
[tool.setuptools_scm]
@@ -32,27 +33,51 @@ addopts = """
3233
# Doctest python code in docs, python code in src docstrings, test functions in tests
3334
testpaths = "tests"
3435

35-
# tox must currently be configured via an embedded ini string
36-
# See: https://github.com/tox-dev/tox/issues/999
36+
3737
[tool.tox]
38-
legacy_tox_ini = """
39-
[tox]
40-
skipsdist=True
38+
skipsdist = true
39+
requires = ["tox-uv>=1.25.0"]
40+
# envs to runs automatically with tox -p
41+
env_list = ["pre-commit", "tests", "docs"]
42+
43+
[tool.tox.env]
44+
passenv = { "*" = "" }
45+
# Include setuptools, pip, ... in the tox envs
46+
uv_seed = { enabled = true }
47+
48+
[tool.tox.env.pre-commit]
49+
description = "Run pre-commit"
50+
allowlist_externals = ["pre-commit"]
51+
commands = [
52+
[
53+
"pre-commit",
54+
"run",
55+
#"--all-files",
56+
"--show-diff-on-failure",
57+
{ replace = "posargs", default = [], extend = true },
58+
],
59+
]
60+
61+
[tool.tox.env.tests]
62+
description = "Run tests"
63+
allowlist_externals = ["pytest"]
64+
commands = [["pytest", { replace = "posargs", default = [], extend = true }]]
4165

42-
[testenv:{pre-commit,tests,docs}]
43-
# Don't create a virtualenv for the command, requires tox-direct plugin
44-
direct = True
45-
passenv = *
46-
allowlist_externals =
47-
pre-commit
48-
pytest
49-
sphinx-build
50-
sphinx-autobuild
51-
commands =
52-
pre-commit: pre-commit run --all-files --show-diff-on-failure {posargs}
53-
tests: pytest {posargs}
54-
docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html
55-
"""
66+
[tool.tox.env.docs]
67+
description = "Run docs"
68+
allowlist_externals = ["sphinx-build", "sphinx-autobuild"]
69+
commands = [
70+
[
71+
"sphinx-build",
72+
"-T",
73+
"docs",
74+
"build/html",
75+
{ replace = "posargs", default = [
76+
"-EW",
77+
"--keep-going",
78+
], extend = true },
79+
],
80+
]
5681

5782
[tool.ruff]
5883
src = ["src", "tests"]

template/pyproject.toml.jinja

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,26 @@ license.file = "LICENSE"
1818
readme = "README.md"
1919
requires-python = ">=3.11"
2020

21-
[project.optional-dependencies]
21+
[dependency-groups]
2222
dev = [
23+
"build",
2324
"copier",
2425
{% if type_checker=="mypy" %}"mypy",
2526
{% endif %}{% if sphinx %}"myst-parser",
2627
{% endif %}"pipdeptree",
2728
"pre-commit",
2829
{% if sphinx %}"pydata-sphinx-theme>=0.12",
2930
{% endif %}{% if type_checker=="pyright" %}"pyright",
30-
{% endif %}"pytest",
31+
{% endif %}"pytest>8.3.4",
3132
"pytest-cov",
3233
"ruff",
3334
{% if sphinx %}"sphinx-autobuild",
3435
"sphinx-copybutton",
3536
"sphinx-design",
36-
{% endif %}"tox-direct",
37+
{% endif %}"tox-uv",
38+
"twine",
3739
"types-mock",
40+
"uv~=0.7.0",
3841
]
3942

4043
[project.scripts]
@@ -47,7 +50,6 @@ GitHub = "{{ repo_url }}"
4750
email = "{{ author_email }}"
4851
name = "{{ author_name }}"
4952

50-
5153
[tool.setuptools_scm]
5254
version_file = "src/{{ package_name }}/_version.py"
5355
{% if type_checker=="pyright" %}
@@ -77,30 +79,78 @@ data_file = "/tmp/{{ package_name }}.coverage"
7779
# Tests are run from installed location, map back to the src directory
7880
source = ["src", "**/site-packages/"]
7981

80-
# tox must currently be configured via an embedded ini string
81-
# See: https://github.com/tox-dev/tox/issues/999
8282
[tool.tox]
83-
legacy_tox_ini = """
84-
[tox]
85-
skipsdist=True
83+
skipsdist = true
84+
requires = ["tox-uv>=1.25.0"]
85+
# envs to runs automatically with tox -p
86+
env_list = ["pre-commit", "type-checking", "docs"] # "tests"]
87+
88+
[tool.tox.env]
89+
passenv = { "*" = "" }
90+
# Include setuptools, pip, ... in the tox envs
91+
uv_seed = { enabled = true }
8692

87-
[testenv:{pre-commit,type-checking,tests{% if sphinx %},docs{% endif %}}]
88-
# Don't create a virtualenv for the command, requires tox-direct plugin
89-
direct = True
90-
passenv = *
91-
allowlist_externals =
92-
pytest
93-
pre-commit
94-
{{ type_checker }}
95-
{% if sphinx %} sphinx-build
96-
sphinx-autobuild
97-
{% endif %}commands =
98-
pre-commit: pre-commit run --all-files --show-diff-on-failure {posargs}
99-
type-checking: {{ type_checker }} src tests {posargs}
100-
tests: pytest --cov={{ package_name }} --cov-report term --cov-report xml:cov.xml {posargs}
101-
{% if sphinx %} docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html
102-
{% endif %}"""
93+
[tool.tox.env.pre-commit]
94+
description = "Run pre-commit"
95+
allowlist_externals = ["pre-commit"]
96+
commands = [
97+
[
98+
"pre-commit",
99+
"run",
100+
#"--all-files",
101+
"--show-diff-on-failure",
102+
{ replace = "posargs", default = [], extend = true },
103+
],
104+
]
105+
106+
[tool.tox.env.type-checking]
107+
description = "Run type-checking"
108+
allowlist_externals = ["{{ type_checker }}"]
109+
# needed otherwise throws reportUnknownMemberType errors
110+
deps = ["pytest"]
111+
commands = [
112+
[
113+
"{{ type_checker }}",
114+
"src",
115+
"tests",
116+
{ replace = "posargs", default = [
117+
], extend = true },
118+
],
119+
]
103120

121+
[tool.tox.env.tests]
122+
description = "Run tests"
123+
allowlist_externals = ["pytest"]
124+
commands = [
125+
[
126+
"pytest",
127+
"-vv",
128+
"--cov={{ package_name }}",
129+
"--cov-report",
130+
"term",
131+
"--cov-report",
132+
"xml:cov.xml",
133+
{ replace = "posargs", default = [
134+
], extend = true },
135+
],
136+
]
137+
138+
{% if sphinx %}[tool.tox.env.docs]
139+
description = "Run docs"
140+
allowlist_externals = ["sphinx-build", "sphinx-autobuild"]
141+
commands = [
142+
[
143+
"sphinx-build",
144+
"-T",
145+
"docs",
146+
"build/html",
147+
{ replace = "posargs", default = [
148+
"-EW",
149+
"--keep-going",
150+
], extend = true },
151+
],
152+
]
153+
{% endif %}
104154
[tool.ruff]
105155
src = ["src", "tests"]
106156
line-length = 88

tests/test_example.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,17 @@ def run_pipe(cmd: str, cwd=None):
3737

3838

3939
def make_venv(project_path: Path) -> callable:
40-
venv_path = project_path / "venv"
41-
run_pipe(f"python -m venv {venv_path}")
40+
venv_path = project_path / ".venv"
4241
run = functools.partial(run_pipe, cwd=str(project_path))
43-
run("./venv/bin/pip install -e .[dev]")
42+
run("uv sync") # Create a lockfile and install packages
43+
44+
for exe_path in [
45+
venv_path / "bin" / "tox",
46+
venv_path / "bin" / "python",
47+
venv_path / "bin" / "uv",
48+
]:
49+
assert exe_path.exists(), f"UV created a venv but did not install {exe_path}"
50+
4451
return run
4552

4653

@@ -53,14 +60,14 @@ def test_template_defaults(tmp_path: Path):
5360
catalog_info = tmp_path / "catalog-info.yaml"
5461
assert catalog_info.exists()
5562
assert 'typeCheckingMode = "strict"' in pyproject_toml.read_text()
56-
run("./venv/bin/tox -p")
63+
run(".venv/bin/tox -p")
5764
if not run_pipe("git tag --points-at HEAD"):
5865
# Only run linkcheck if not on a tag, as the CI might not have pushed
5966
# the docs for this tag yet, so we will fail
60-
run("./venv/bin/tox -e docs build -- -b linkcheck")
61-
run("./venv/bin/pip install build twine")
62-
run("./venv/bin/python -m build")
63-
run("./venv/bin/twine check --strict dist/*")
67+
run(".venv/bin/tox -p -e docs -- -b linkcheck")
68+
run(".venv/bin/uv pip install twine")
69+
run(".venv/bin/uv build")
70+
run(".venv/bin/twine check --strict dist/*")
6471

6572

6673
def test_template_with_extra_code_and_api_docs(tmp_path: Path):
@@ -100,7 +107,7 @@ class Thing:
100107
# Add to make sure pre-commit doesn't moan
101108
run("git add .")
102109
# Build
103-
run("./venv/bin/tox -p")
110+
run(".venv/bin/tox -p")
104111
# Check it generates the right output
105112
api_dir = tmp_path / "build" / "html" / "_api"
106113
top_html = api_dir / "python_copier_template_example.html"
@@ -121,13 +128,13 @@ class Thing:
121128
def test_template_mypy(tmp_path: Path):
122129
copy_project(tmp_path, type_checker="mypy")
123130
run = make_venv(tmp_path)
124-
run("./venv/bin/tox -p")
131+
run(".venv/bin/tox -p")
125132

126133

127134
def test_template_no_docs(tmp_path: Path):
128135
copy_project(tmp_path, docs_type="README")
129136
run = make_venv(tmp_path)
130-
run("./venv/bin/tox -p")
137+
run(".venv/bin/tox -p")
131138

132139

133140
def test_template_in_different_org_has_no_catalog(tmp_path: Path):
@@ -141,7 +148,7 @@ def test_template_no_docker_has_no_docs_and_works(tmp_path: Path):
141148
container_doc = tmp_path / "docs" / "how-to" / "run-container.md"
142149
assert not container_doc.exists()
143150
run = make_venv(tmp_path)
144-
run("./venv/bin/tox -p")
151+
run(".venv/bin/tox -p")
145152

146153

147154
def test_bad_repo_name(tmp_path: Path):
@@ -232,7 +239,7 @@ def test_pyright_works_in_standard_typing_mode(tmp_path: Path):
232239

233240
# Ensure pyright is still happy
234241
run = make_venv(tmp_path)
235-
run(f"./venv/bin/pyright {tmp_path}")
242+
run(f".venv/bin/pyright {tmp_path}")
236243

237244

238245
def test_ignores_mypy_strict_mode(tmp_path: Path):

0 commit comments

Comments
 (0)