Skip to content

Commit 8be999b

Browse files
authored
use pep 735 dependency groups instead of dev/test extras, use setup-uv (#32)
1 parent 255d6ee commit 8be999b

File tree

10 files changed

+162
-124
lines changed

10 files changed

+162
-124
lines changed

.github/workflows/test.yml

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ jobs:
1717
test:
1818
name: ${{ matrix.platform }} py${{ matrix.python-version }}
1919
runs-on: ${{ matrix.platform }}
20+
env:
21+
UV_PYTHON: ${{ matrix.python-version }}
2022
strategy:
2123
fail-fast: false
2224
matrix:
@@ -25,16 +27,5 @@ jobs:
2527

2628
steps:
2729
- uses: actions/checkout@v4
28-
29-
- name: Set up Python ${{ matrix.python-version }}
30-
uses: actions/setup-python@v4
31-
with:
32-
python-version: ${{ matrix.python-version }}
33-
34-
- name: Install dependencies
35-
run: |
36-
python -m pip install --upgrade pip
37-
pip install pytest build check-manifest pre-commit copier tomli
38-
39-
- name: Test
40-
run: pytest tests -v --color=yes
30+
- uses: astral-sh/setup-uv@v6
31+
- run: uv run pytest tests -v --color=yes

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,4 @@ dmypy.json
129129
.pyre/
130130
pyrepo
131131
.vscode/
132+
uv.lock

project/.github/workflows/ci.yml.jinja

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ name: CI
22

33
on:
44
push:
5-
branches:
6-
- main
7-
tags:
8-
- "v*"
5+
branches: [main]
6+
tags: [v*]
97
pull_request:
108
workflow_dispatch:
119
{% if test_pre_release -%}
@@ -24,8 +22,6 @@ concurrency:
2422
jobs:
2523
{%- if mode != 'simple' %}
2624
check-manifest:
27-
# check-manifest is a tool that checks that all files in version control are
28-
# included in the sdist (unless explicitly excluded)
2925
runs-on: ubuntu-latest
3026
steps:
3127
- uses: actions/checkout@v4
@@ -34,6 +30,10 @@ jobs:
3430
test:
3531
name: ${{ matrix.platform }} (${{ matrix.python-version }})
3632
runs-on: ${{ matrix.platform }}{% endraw %}
33+
{%- if test_pre_release %}
34+
env:
35+
UV_PRERELEASE: {% raw %}${{ github.event_name == 'schedule' && 'allow' || 'if-necessary-or-explicit' }}{% endraw %}
36+
{%- endif %}
3737
strategy:
3838
fail-fast: false
3939
matrix:
@@ -48,24 +48,16 @@ jobs:
4848
- uses: actions/checkout@v4
4949

5050
- name: 🐍 Set up Python ${{ matrix.python-version }}
51-
uses: actions/setup-python@v4
51+
uses: astral-sh/setup-uv@v6
5252
with:
5353
python-version: ${{ matrix.python-version }}
54-
cache-dependency-path: "pyproject.toml"
55-
cache: "pip"
54+
enable-cache: true
5655

5756
- name: Install Dependencies
58-
run: |
59-
python -m pip install -U pip
60-
{% endraw %}{%- if test_pre_release -%}
61-
# if running a cron job, we add the --pre flag to test against pre-releases
62-
{% raw %}python -m pip install .[test] ${{ github.event_name == 'schedule' && '--pre' || '' }}{% endraw %}
63-
{%- else -%}
64-
python -m pip install .[test]
65-
{%- endif %}
57+
run: uv sync --no-dev --group test
6658

6759
- name: 🧪 Run Tests
68-
run: pytest --color=yes --cov --cov-report=xml --cov-report=term-missing
60+
run: uv run pytest --cov --cov-report=xml --cov-report=term-missing{% endraw %}
6961
{%- if test_pre_release %}{% raw %}
7062

7163
# If something goes wrong with --pre tests, we can open an issue in the repo
@@ -84,14 +76,25 @@ jobs:
8476
{%- endif %}{% raw %}
8577

8678
- name: Coverage
87-
uses: codecov/codecov-action@v3
79+
uses: codecov/codecov-action@v5
80+
# with:
81+
# token: ${{ secrets.CODECOV_TOKEN }}
8882

89-
deploy:
90-
name: Deploy
83+
build-and-inspect-package:
84+
name: Build & inspect package.
9185
needs: test
92-
if: success() && startsWith(github.ref, 'refs/tags/'){% endraw %}{%- if test_pre_release %}{% raw %} && github.event_name != 'schedule'{% endraw %}{% endif %}{% raw %}
9386
runs-on: ubuntu-latest
87+
steps:
88+
- uses: actions/checkout@v4
89+
with:
90+
fetch-depth: 0
91+
- uses: hynek/build-and-inspect-python-package@v2
9492

93+
upload-to-pypi:
94+
name: Upload package to PyPI
95+
needs: build-and-inspect-package
96+
if: success() && startsWith(github.ref, 'refs/tags/'){% endraw %}{%- if test_pre_release %}{% raw %} && github.event_name != 'schedule'{% endraw %}{% endif %}{% raw %}
97+
runs-on: ubuntu-latest
9598
permissions:
9699
# IMPORTANT: this permission is mandatory for trusted publishing on PyPi
97100
# see https://docs.pypi.org/trusted-publishers/
@@ -100,24 +103,14 @@ jobs:
100103
contents: write
101104

102105
steps:
103-
- uses: actions/checkout@v4
104-
with:
105-
fetch-depth: 0
106-
107-
- name: 🐍 Set up Python
108-
uses: actions/setup-python@v4
106+
- name: Download built artifact to dist/
107+
uses: actions/download-artifact@v4
109108
with:
110-
python-version: "3.x"
111-
112-
- name: 👷 Build
113-
run: |
114-
python -m pip install build
115-
python -m build
116-
109+
name: Packages
110+
path: dist
117111
- name: 🚢 Publish to PyPI
118112
uses: pypa/gh-action-pypi-publish@release/v1
119-
120-
- uses: softprops/action-gh-release@v1
113+
- uses: softprops/action-gh-release@v2
121114
with:
122115
generate_release_notes: true
123116
files: './dist/*'

project/README.md.jinja

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,32 @@
77
[![codecov](https://codecov.io/gh/{{github_username}}/{{project_name}}/branch/main/graph/badge.svg)](https://codecov.io/gh/{{github_username}}/{{project_name}})
88

99
{{project_short_description}}
10+
11+
## Development
12+
13+
The easiest way to get started is to use the [github cli](https://cli.github.com)
14+
and [uv](https://docs.astral.sh/uv/getting-started/installation/):
15+
16+
```sh
17+
{% if github_username -%}
18+
gh repo fork {{github_username}}/{{project_name}} --clone
19+
# or just
20+
# gh repo clone {{github_username}}/{{project_name}}
21+
{%- else -%}
22+
# clone the repo or your fork locally
23+
{%- endif %}
24+
cd {{project_name}}
25+
uv sync
26+
```
27+
28+
Run tests:
29+
30+
```sh
31+
uv run pytest
32+
```
33+
34+
Lint files:
35+
36+
```sh
37+
uv run pre-commit run --all-files
38+
```

project/pyproject.toml.jinja

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,9 @@ classifiers = [
6262
dependencies = []
6363

6464
# https://peps.python.org/pep-0621/#dependencies-optional-dependencies
65-
# "extras" (e.g. for `pip install .[test]`)
66-
[project.optional-dependencies]
67-
# add dependencies used for testing here
68-
test = ["pytest", "pytest-cov"]
69-
# add anything else you like to have in your dev environment here
70-
dev = [
71-
"ipython",
72-
{%- if use_mypy %}
73-
"mypy",{%- endif %}
74-
"pdbpp", # https://github.com/pdbpp/pdbpp
75-
{%- if use_pre_commit %}
76-
"pre-commit",{%- endif %}
77-
"rich", # https://github.com/Textualize/rich
78-
{%- if use_ruff %}
79-
"ruff",{%- endif %}
80-
]
65+
# add dependencies for "extra" features here. Not dev dependencies.
66+
# [project.optional-dependencies]
67+
# name = ["dependency"]
8168

8269
[project.urls]
8370
{% if github_username -%}
@@ -97,14 +84,35 @@ repository = "https://github.com/{{github_username}}/{{project_name}}"
9784
# [project.entry-points."some.group"]
9885
# tomatoes = "{{module_name}}:main_tomatoes"
9986

87+
# https://peps.python.org/pep-0735/
88+
# setup with `uv sync` or `pip install -e . --group dev`
89+
[dependency-groups]
90+
test = ["pytest", "pytest-cov"]
91+
dev = [
92+
{ include-group = "test" },
93+
"ipython",
94+
{%- if use_mypy %}
95+
"mypy",{%- endif %}
96+
"pdbpp", # https://github.com/pdbpp/pdbpp
97+
{%- if use_pre_commit %}
98+
"pre-commit-uv",{%- endif %}
99+
"rich", # https://github.com/Textualize/rich
100+
{%- if use_ruff %}
101+
"ruff",{%- endif %}
102+
]
103+
104+
[tool.uv.sources]
105+
{{project_name}} = { workspace = true }
106+
100107
{% if use_ruff -%}
101108
# https://docs.astral.sh/ruff
102109
[tool.ruff]
103110
line-length = 88
104111
target-version = "py3{{ minimum_python }}"
105112
src = ["src"]
113+
fix = true
114+
# unsafe-fixes = true
106115

107-
# https://docs.astral.sh/ruff/rules
108116
[tool.ruff.lint]
109117
pydocstyle = { convention = "numpy" }
110118
select = [
@@ -119,7 +127,7 @@ select = [
119127
"B", # flake8-bugbear
120128
"A001", # flake8-builtins
121129
"RUF", # ruff-specific rules
122-
"TCH", # flake8-type-checking
130+
"TC", # flake8-type-checking
123131
"TID", # flake8-tidy-imports
124132
]
125133
ignore = [
@@ -128,6 +136,7 @@ ignore = [
128136

129137
[tool.ruff.lint.per-file-ignores]
130138
"tests/*.py" = ["D", "S"]
139+
"docs/*.py" = ["D", "A"]
131140

132141
# https://docs.astral.sh/ruff/formatter/
133142
[tool.ruff.format]
@@ -136,6 +145,13 @@ skip-magic-trailing-comma = false # default is false
136145
{%- endif -%}
137146
{%- if use_mypy %}
138147

148+
# https://docs.pytest.org/
149+
[tool.pytest.ini_options]
150+
minversion = "7.0"
151+
addopts = ["--color=yes"]
152+
testpaths = ["tests"]
153+
filterwarnings = ["error"]
154+
139155
# https://mypy.readthedocs.io/en/stable/config_file.html
140156
[tool.mypy]
141157
files = "src/**/"
@@ -144,19 +160,14 @@ disallow_any_generics = false
144160
disallow_subclassing_any = false
145161
show_error_codes = true
146162
pretty = true
163+
# plugins = ["pydantic.mypy"]
147164

148165
# # module specific overrides
149166
# [[tool.mypy.overrides]]
150167
# module = ["numpy.*",]
151168
# ignore_errors = true
152169
{%- endif %}
153170

154-
# https://docs.pytest.org/
155-
[tool.pytest.ini_options]
156-
minversion = "7.0"
157-
testpaths = ["tests"]
158-
filterwarnings = ["error"]
159-
160171
# https://coverage.readthedocs.io/
161172
[tool.coverage.report]
162173
show_missing = true
@@ -165,6 +176,7 @@ exclude_lines = [
165176
"if TYPE_CHECKING:",
166177
"@overload",
167178
"except ImportError",
179+
"raise AssertionError",
168180
"\\.\\.\\.",
169181
"raise NotImplementedError()",
170182
"pass",
@@ -181,4 +193,9 @@ ignore = [
181193
".pre-commit-config.yaml",
182194
".ruff_cache/**/*",
183195
"tests/**/*",
196+
"uv.lock",
184197
]
198+
199+
# https://github.com/crate-ci/typos/blob/master/docs/reference.md
200+
[tool.typos.default]
201+
extend-ignore-identifiers-re = []
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
def test_something():
2-
pass
1+
import {{module_name}}
2+
3+
4+
def test_imports_with_version():
5+
assert isinstance({{module_name}}.__version__, str)

project/{% if use_pre_commit %}.pre-commit-config.yaml{% endif %}.jinja

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ ci:
99

1010
repos:
1111
- repo: https://github.com/abravalheri/validate-pyproject
12-
rev: v0.22
12+
rev: v0.24.1
1313
hooks:
1414
- id: validate-pyproject
1515
{%- if use_ruff %}
1616

1717
- repo: https://github.com/crate-ci/typos
18-
rev: v1.24.6
18+
rev: v1.32.0
1919
hooks:
2020
- id: typos
2121
args: [--force-exclude] # omitting --write-changes
2222

2323
- repo: https://github.com/astral-sh/ruff-pre-commit
24-
rev: v0.7.2
24+
rev: v0.11.10
2525
hooks:
2626
- id: ruff
2727
args: [--fix] # may also add '--unsafe-fixes'
@@ -30,7 +30,7 @@ repos:
3030
{%- if use_mypy %}
3131

3232
- repo: https://github.com/pre-commit/mirrors-mypy
33-
rev: v1.13.0
33+
rev: v1.15.0
3434
hooks:
3535
- id: mypy
3636
files: "^src/"

pyproject.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[project]
2+
name = "pyrepo-copier"
3+
version = "0.1.0"
4+
readme = "README.md"
5+
license = { text = "BSD-3-Clause" }
6+
7+
[tool.mypy]
8+
disallow_any_decorated = false
9+
disallow_any_generics = true
10+
disallow_any_unimported = false
11+
disallow_subclassing_any = false
12+
disallow_untyped_calls = true
13+
disallow_untyped_defs = false
14+
ignore_missing_imports = true
15+
warn_unused_ignores = true
16+
warn_return_any = true
17+
18+
[tool.pytest.ini_options]
19+
norecursedirs = "{{project_name}}"
20+
21+
[dependency-groups]
22+
dev = [
23+
"check-manifest>=0.50",
24+
"copier>=9.7.1",
25+
"pre-commit>=4.2.0",
26+
"pytest>=8.3.5",
27+
"tomli>=2.2.1",
28+
]

0 commit comments

Comments
 (0)