duty 1.4.2__tar.gz → 1.4.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {duty-1.4.2 → duty-1.4.3}/CHANGELOG.md +8 -0
- {duty-1.4.2 → duty-1.4.3}/CONTRIBUTING.md +2 -3
- {duty-1.4.2 → duty-1.4.3}/PKG-INFO +5 -9
- {duty-1.4.2 → duty-1.4.3}/README.md +2 -6
- {duty-1.4.2 → duty-1.4.3}/config/ruff.toml +1 -1
- {duty-1.4.2 → duty-1.4.3}/duties.py +4 -2
- {duty-1.4.2 → duty-1.4.3}/mkdocs.yml +4 -2
- {duty-1.4.2 → duty-1.4.3}/pyproject.toml +32 -4
- {duty-1.4.2 → duty-1.4.3}/scripts/gen_credits.py +6 -6
- {duty-1.4.2 → duty-1.4.3}/scripts/make +42 -62
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/blacken_docs.py +5 -1
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/ruff.py +2 -2
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/safety.py +4 -1
- {duty-1.4.2 → duty-1.4.3}/src/duty/collection.py +2 -2
- {duty-1.4.2 → duty-1.4.3}/src/duty/context.py +5 -2
- {duty-1.4.2 → duty-1.4.3}/src/duty/decorator.py +3 -1
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_blacken_docs.py +5 -1
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_ruff.py +2 -2
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_safety.py +4 -1
- {duty-1.4.2 → duty-1.4.3}/src/duty/validation.py +5 -2
- {duty-1.4.2 → duty-1.4.3}/tests/test_context.py +5 -1
- duty-1.4.2/devdeps.txt +0 -32
- {duty-1.4.2 → duty-1.4.3}/CODE_OF_CONDUCT.md +0 -0
- {duty-1.4.2 → duty-1.4.3}/LICENSE +0 -0
- {duty-1.4.2 → duty-1.4.3}/config/coverage.ini +0 -0
- {duty-1.4.2 → duty-1.4.3}/config/git-changelog.toml +0 -0
- {duty-1.4.2 → duty-1.4.3}/config/mypy.ini +0 -0
- {duty-1.4.2 → duty-1.4.3}/config/pytest.ini +0 -0
- {duty-1.4.2 → duty-1.4.3}/config/vscode/launch.json +0 -0
- {duty-1.4.2 → duty-1.4.3}/config/vscode/settings.json +0 -0
- {duty-1.4.2 → duty-1.4.3}/config/vscode/tasks.json +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/.overrides/main.html +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/.overrides/partials/comments.html +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/changelog.md +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/code_of_conduct.md +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/contributing.md +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/credits.md +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/css/material.css +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/css/mkdocstrings.css +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/demo.svg +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/gen_credits.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/index.md +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/js/feedback.js +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/license.md +0 -0
- {duty-1.4.2 → duty-1.4.3}/docs/usage.md +0 -0
- {duty-1.4.2 → duty-1.4.3}/scripts/gen_ref_nav.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/__init__.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/__main__.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/__init__.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/_io.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/autoflake.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/black.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/build.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/coverage.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/flake8.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/git_changelog.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/griffe.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/interrogate.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/isort.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/mkdocs.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/mypy.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/pytest.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/ssort.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/callables/twine.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/cli.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/debug.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/exceptions.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/py.typed +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/__init__.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_autoflake.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_base.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_black.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_build.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_coverage.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_flake8.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_git_changelog.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_griffe.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_interrogate.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_isort.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_mkdocs.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_mypy.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_pytest.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_ssort.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/src/duty/tools/_twine.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/__init__.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/conftest.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/fixtures/arguments.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/fixtures/basic.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/fixtures/booleans.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/fixtures/code.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/fixtures/list.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/fixtures/multiple.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/fixtures/precedence.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/fixtures/validation.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/test_cli.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/test_collection.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/test_decorator.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/test_running.py +0 -0
- {duty-1.4.2 → duty-1.4.3}/tests/test_validation.py +0 -0
|
@@ -5,6 +5,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
7
|
<!-- insertion marker -->
|
|
8
|
+
## [1.4.3](https://github.com/pawamoy/duty/releases/tag/1.4.3) - 2024-10-17
|
|
9
|
+
|
|
10
|
+
<small>[Compare with 1.4.2](https://github.com/pawamoy/duty/compare/1.4.2...1.4.3)</small>
|
|
11
|
+
|
|
12
|
+
### Build
|
|
13
|
+
|
|
14
|
+
- Drop support for Python 3.8 ([4f5d6ec](https://github.com/pawamoy/duty/commit/4f5d6ecbb0a84e5c42cab4d584239f16e8397d86) by Timothée Mazzucotelli).
|
|
15
|
+
|
|
8
16
|
## [1.4.2](https://github.com/pawamoy/duty/releases/tag/1.4.2) - 2024-09-10
|
|
9
17
|
|
|
10
18
|
<small>[Compare with 1.4.1](https://github.com/pawamoy/duty/compare/1.4.1...1.4.2)</small>
|
|
@@ -23,12 +23,11 @@ make setup
|
|
|
23
23
|
> You can install it with:
|
|
24
24
|
>
|
|
25
25
|
> ```bash
|
|
26
|
-
>
|
|
27
|
-
> pipx install uv
|
|
26
|
+
> curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
28
27
|
> ```
|
|
29
28
|
>
|
|
30
29
|
> Now you can try running `make setup` again,
|
|
31
|
-
> or simply `uv
|
|
30
|
+
> or simply `uv sync`.
|
|
32
31
|
|
|
33
32
|
You now have the dependencies installed.
|
|
34
33
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: duty
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.3
|
|
4
4
|
Summary: A simple task runner.
|
|
5
5
|
Keywords: task-runner,task,runner,cross-platform
|
|
6
6
|
Author-Email: =?utf-8?q?Timoth=C3=A9e_Mazzucotelli?= <dev@pawamoy.fr>
|
|
@@ -10,12 +10,12 @@ Classifier: Intended Audience :: Developers
|
|
|
10
10
|
Classifier: Programming Language :: Python
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Classifier: Topic :: Documentation
|
|
20
20
|
Classifier: Topic :: Software Development
|
|
21
21
|
Classifier: Topic :: Utilities
|
|
@@ -28,7 +28,7 @@ Project-URL: Issues, https://github.com/pawamoy/duty/issues
|
|
|
28
28
|
Project-URL: Discussions, https://github.com/pawamoy/duty/discussions
|
|
29
29
|
Project-URL: Gitter, https://gitter.im/duty/community
|
|
30
30
|
Project-URL: Funding, https://github.com/sponsors/pawamoy
|
|
31
|
-
Requires-Python: >=3.
|
|
31
|
+
Requires-Python: >=3.9
|
|
32
32
|
Requires-Dist: eval-type-backport; python_version < "3.10"
|
|
33
33
|
Requires-Dist: failprint!=1.0.0,>=0.11
|
|
34
34
|
Requires-Dist: typing-extensions>=4.0; python_version < "3.11"
|
|
@@ -39,7 +39,6 @@ Description-Content-Type: text/markdown
|
|
|
39
39
|
[](https://github.com/pawamoy/duty/actions?query=workflow%3Aci)
|
|
40
40
|
[](https://pawamoy.github.io/duty/)
|
|
41
41
|
[](https://pypi.org/project/duty/)
|
|
42
|
-
[](https://gitpod.io/#https://github.com/pawamoy/duty)
|
|
43
42
|
[](https://app.gitter.im/#/room/#duty:gitter.im)
|
|
44
43
|
|
|
45
44
|
A simple task runner.
|
|
@@ -50,17 +49,14 @@ Inspired by [Invoke](https://github.com/pyinvoke/invoke).
|
|
|
50
49
|
|
|
51
50
|
## Installation
|
|
52
51
|
|
|
53
|
-
With `pip`:
|
|
54
|
-
|
|
55
52
|
```bash
|
|
56
53
|
pip install duty
|
|
57
54
|
```
|
|
58
55
|
|
|
59
|
-
With [`
|
|
56
|
+
With [`uv`](https://docs.astral.sh/uv/):
|
|
60
57
|
|
|
61
58
|
```bash
|
|
62
|
-
|
|
63
|
-
pipx install duty
|
|
59
|
+
uv tool install duty
|
|
64
60
|
```
|
|
65
61
|
|
|
66
62
|
## Quick start
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
[](https://github.com/pawamoy/duty/actions?query=workflow%3Aci)
|
|
4
4
|
[](https://pawamoy.github.io/duty/)
|
|
5
5
|
[](https://pypi.org/project/duty/)
|
|
6
|
-
[](https://gitpod.io/#https://github.com/pawamoy/duty)
|
|
7
6
|
[](https://app.gitter.im/#/room/#duty:gitter.im)
|
|
8
7
|
|
|
9
8
|
A simple task runner.
|
|
@@ -14,17 +13,14 @@ Inspired by [Invoke](https://github.com/pyinvoke/invoke).
|
|
|
14
13
|
|
|
15
14
|
## Installation
|
|
16
15
|
|
|
17
|
-
With `pip`:
|
|
18
|
-
|
|
19
16
|
```bash
|
|
20
17
|
pip install duty
|
|
21
18
|
```
|
|
22
19
|
|
|
23
|
-
With [`
|
|
20
|
+
With [`uv`](https://docs.astral.sh/uv/):
|
|
24
21
|
|
|
25
22
|
```bash
|
|
26
|
-
|
|
27
|
-
pipx install duty
|
|
23
|
+
uv tool install duty
|
|
28
24
|
```
|
|
29
25
|
|
|
30
26
|
## Quick start
|
|
@@ -7,11 +7,13 @@ import sys
|
|
|
7
7
|
from contextlib import contextmanager
|
|
8
8
|
from importlib.metadata import version as pkgversion
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import TYPE_CHECKING
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
11
|
|
|
12
12
|
from duty import duty, tools
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
|
+
from collections.abc import Iterator
|
|
16
|
+
|
|
15
17
|
from duty.context import Context
|
|
16
18
|
|
|
17
19
|
|
|
@@ -53,7 +55,7 @@ def changelog(ctx: Context, bump: str = "") -> None:
|
|
|
53
55
|
ctx.run(tools.git_changelog(bump=bump or None), title="Updating changelog")
|
|
54
56
|
|
|
55
57
|
|
|
56
|
-
@duty(pre=["
|
|
58
|
+
@duty(pre=["check-quality", "check-types", "check-docs", "check-api"])
|
|
57
59
|
def check(ctx: Context) -> None:
|
|
58
60
|
"""Check it all!"""
|
|
59
61
|
|
|
@@ -129,13 +129,15 @@ plugins:
|
|
|
129
129
|
show_root_heading: true
|
|
130
130
|
show_root_full_path: false
|
|
131
131
|
show_signature_annotations: true
|
|
132
|
+
show_source: true
|
|
132
133
|
show_symbol_type_heading: true
|
|
133
134
|
show_symbol_type_toc: true
|
|
134
135
|
signature_crossrefs: true
|
|
135
136
|
summary: true
|
|
136
|
-
- git-
|
|
137
|
+
- git-revision-date-localized:
|
|
137
138
|
enabled: !ENV [DEPLOY, false]
|
|
138
|
-
|
|
139
|
+
enable_creation_date: true
|
|
140
|
+
type: timeago
|
|
139
141
|
- minify:
|
|
140
142
|
minify_html: !ENV [DEPLOY, false]
|
|
141
143
|
- group:
|
|
@@ -11,7 +11,7 @@ authors = [
|
|
|
11
11
|
{ name = "Timothée Mazzucotelli", email = "dev@pawamoy.fr" },
|
|
12
12
|
]
|
|
13
13
|
readme = "README.md"
|
|
14
|
-
requires-python = ">=3.
|
|
14
|
+
requires-python = ">=3.9"
|
|
15
15
|
keywords = [
|
|
16
16
|
"task-runner",
|
|
17
17
|
"task",
|
|
@@ -25,12 +25,12 @@ classifiers = [
|
|
|
25
25
|
"Programming Language :: Python",
|
|
26
26
|
"Programming Language :: Python :: 3",
|
|
27
27
|
"Programming Language :: Python :: 3 :: Only",
|
|
28
|
-
"Programming Language :: Python :: 3.8",
|
|
29
28
|
"Programming Language :: Python :: 3.9",
|
|
30
29
|
"Programming Language :: Python :: 3.10",
|
|
31
30
|
"Programming Language :: Python :: 3.11",
|
|
32
31
|
"Programming Language :: Python :: 3.12",
|
|
33
32
|
"Programming Language :: Python :: 3.13",
|
|
33
|
+
"Programming Language :: Python :: 3.14",
|
|
34
34
|
"Topic :: Documentation",
|
|
35
35
|
"Topic :: Software Development",
|
|
36
36
|
"Topic :: Utilities",
|
|
@@ -41,7 +41,7 @@ dependencies = [
|
|
|
41
41
|
"failprint>=0.11,!=1.0.0",
|
|
42
42
|
"typing-extensions>=4.0; python_version < '3.11'",
|
|
43
43
|
]
|
|
44
|
-
version = "1.4.
|
|
44
|
+
version = "1.4.3"
|
|
45
45
|
|
|
46
46
|
[project.license]
|
|
47
47
|
text = "ISC"
|
|
@@ -74,7 +74,6 @@ source-includes = [
|
|
|
74
74
|
"scripts",
|
|
75
75
|
"share",
|
|
76
76
|
"tests",
|
|
77
|
-
"devdeps.txt",
|
|
78
77
|
"duties.py",
|
|
79
78
|
"mkdocs.yml",
|
|
80
79
|
"*.md",
|
|
@@ -85,3 +84,32 @@ source-includes = [
|
|
|
85
84
|
data = [
|
|
86
85
|
{ path = "share/**/*", relative-to = "." },
|
|
87
86
|
]
|
|
87
|
+
|
|
88
|
+
[tool.uv]
|
|
89
|
+
dev-dependencies = [
|
|
90
|
+
"editables>=0.5",
|
|
91
|
+
"build>=1.2",
|
|
92
|
+
"git-changelog>=2.5",
|
|
93
|
+
"twine>=5.1",
|
|
94
|
+
"duty>=1.4",
|
|
95
|
+
"ruff>=0.4",
|
|
96
|
+
"pytest>=8.2",
|
|
97
|
+
"pytest-cov>=5.0",
|
|
98
|
+
"pytest-randomly>=3.15",
|
|
99
|
+
"pytest-xdist>=3.6",
|
|
100
|
+
"mypy>=1.10",
|
|
101
|
+
"types-markdown>=3.6",
|
|
102
|
+
"types-pyyaml>=6.0",
|
|
103
|
+
"black>=24.4",
|
|
104
|
+
"markdown-callouts>=0.4",
|
|
105
|
+
"markdown-exec>=1.8",
|
|
106
|
+
"mkdocs>=1.6",
|
|
107
|
+
"mkdocs-coverage>=1.0",
|
|
108
|
+
"mkdocs-gen-files>=0.5",
|
|
109
|
+
"mkdocs-git-revision-date-localized-plugin>=1.2",
|
|
110
|
+
"mkdocs-literate-nav>=0.6",
|
|
111
|
+
"mkdocs-material>=9.5",
|
|
112
|
+
"mkdocs-minify-plugin>=0.8",
|
|
113
|
+
"mkdocstrings[python]>=0.25",
|
|
114
|
+
"tomli>=2.0; python_version < '3.11'",
|
|
115
|
+
]
|
|
@@ -5,17 +5,18 @@ from __future__ import annotations
|
|
|
5
5
|
import os
|
|
6
6
|
import sys
|
|
7
7
|
from collections import defaultdict
|
|
8
|
+
from collections.abc import Iterable
|
|
8
9
|
from importlib.metadata import distributions
|
|
9
10
|
from itertools import chain
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
from textwrap import dedent
|
|
12
|
-
from typing import
|
|
13
|
+
from typing import Union
|
|
13
14
|
|
|
14
15
|
from jinja2 import StrictUndefined
|
|
15
16
|
from jinja2.sandbox import SandboxedEnvironment
|
|
16
17
|
from packaging.requirements import Requirement
|
|
17
18
|
|
|
18
|
-
#
|
|
19
|
+
# YORE: EOL 3.10: Replace block with line 2.
|
|
19
20
|
if sys.version_info >= (3, 11):
|
|
20
21
|
import tomllib
|
|
21
22
|
else:
|
|
@@ -26,11 +27,10 @@ with project_dir.joinpath("pyproject.toml").open("rb") as pyproject_file:
|
|
|
26
27
|
pyproject = tomllib.load(pyproject_file)
|
|
27
28
|
project = pyproject["project"]
|
|
28
29
|
project_name = project["name"]
|
|
29
|
-
|
|
30
|
-
devdeps = [line.strip() for line in devdeps_file if line.strip() and not line.strip().startswith(("-e", "#"))]
|
|
30
|
+
devdeps = [dep for dep in pyproject["tool"]["uv"]["dev-dependencies"] if not dep.startswith("-e")]
|
|
31
31
|
|
|
32
|
-
PackageMetadata =
|
|
33
|
-
Metadata =
|
|
32
|
+
PackageMetadata = dict[str, Union[str, Iterable[str]]]
|
|
33
|
+
Metadata = dict[str, PackageMetadata]
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def _merge_fields(metadata: dict) -> PackageMetadata:
|
|
@@ -9,12 +9,10 @@ import subprocess
|
|
|
9
9
|
import sys
|
|
10
10
|
from contextlib import contextmanager
|
|
11
11
|
from pathlib import Path
|
|
12
|
+
from textwrap import dedent
|
|
12
13
|
from typing import Any, Iterator
|
|
13
14
|
|
|
14
|
-
PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.
|
|
15
|
-
|
|
16
|
-
exe = ""
|
|
17
|
-
prefix = ""
|
|
15
|
+
PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.9 3.10 3.11 3.12 3.13 3.14").split()
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
def shell(cmd: str, capture_output: bool = False, **kwargs: Any) -> str | None:
|
|
@@ -37,17 +35,13 @@ def environ(**kwargs: str) -> Iterator[None]:
|
|
|
37
35
|
os.environ.update(original)
|
|
38
36
|
|
|
39
37
|
|
|
40
|
-
def uv_install() -> None:
|
|
38
|
+
def uv_install(venv: Path) -> None:
|
|
41
39
|
"""Install dependencies using uv."""
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if "CI" not in os.environ:
|
|
48
|
-
shell("uv pip install --no-deps -e .")
|
|
49
|
-
else:
|
|
50
|
-
shell("uv pip install --no-deps .")
|
|
40
|
+
with environ(UV_PROJECT_ENVIRONMENT=str(venv), PYO3_USE_ABI3_FORWARD_COMPATIBILITY="1"):
|
|
41
|
+
if "CI" in os.environ:
|
|
42
|
+
shell("uv sync --no-editable")
|
|
43
|
+
else:
|
|
44
|
+
shell("uv sync")
|
|
51
45
|
|
|
52
46
|
|
|
53
47
|
def setup() -> None:
|
|
@@ -59,7 +53,7 @@ def setup() -> None:
|
|
|
59
53
|
default_venv = Path(".venv")
|
|
60
54
|
if not default_venv.exists():
|
|
61
55
|
shell("uv venv --python python")
|
|
62
|
-
uv_install()
|
|
56
|
+
uv_install(default_venv)
|
|
63
57
|
|
|
64
58
|
if PYTHON_VERSIONS:
|
|
65
59
|
for version in PYTHON_VERSIONS:
|
|
@@ -67,39 +61,22 @@ def setup() -> None:
|
|
|
67
61
|
venv_path = Path(f".venvs/{version}")
|
|
68
62
|
if not venv_path.exists():
|
|
69
63
|
shell(f"uv venv --python {version} {venv_path}")
|
|
70
|
-
with environ(
|
|
71
|
-
uv_install()
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def activate(path: str) -> None:
|
|
75
|
-
"""Activate a virtual environment."""
|
|
76
|
-
global exe, prefix # noqa: PLW0603
|
|
77
|
-
|
|
78
|
-
if (bin := Path(path, "bin")).exists():
|
|
79
|
-
activate_script = bin / "activate_this.py"
|
|
80
|
-
elif (scripts := Path(path, "Scripts")).exists():
|
|
81
|
-
activate_script = scripts / "activate_this.py"
|
|
82
|
-
exe = ".exe"
|
|
83
|
-
prefix = f"{path}/Scripts/"
|
|
84
|
-
else:
|
|
85
|
-
raise ValueError(f"make: activate: Cannot find activation script in {path}")
|
|
86
|
-
|
|
87
|
-
if not activate_script.exists():
|
|
88
|
-
raise ValueError(f"make: activate: Cannot find activation script in {path}")
|
|
89
|
-
|
|
90
|
-
exec(activate_script.read_text(), {"__file__": str(activate_script)}) # noqa: S102
|
|
64
|
+
with environ(UV_PROJECT_ENVIRONMENT=str(venv_path.resolve())):
|
|
65
|
+
uv_install(venv_path)
|
|
91
66
|
|
|
92
67
|
|
|
93
|
-
def run(version: str, cmd: str, *args: str, **kwargs: Any) -> None:
|
|
68
|
+
def run(version: str, cmd: str, *args: str, no_sync: bool = False, **kwargs: Any) -> None:
|
|
94
69
|
"""Run a command in a virtual environment."""
|
|
95
70
|
kwargs = {"check": True, **kwargs}
|
|
71
|
+
uv_run = ["uv", "run"]
|
|
72
|
+
if no_sync:
|
|
73
|
+
uv_run.append("--no-sync")
|
|
96
74
|
if version == "default":
|
|
97
|
-
|
|
98
|
-
|
|
75
|
+
with environ(UV_PROJECT_ENVIRONMENT=".venv"):
|
|
76
|
+
subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510
|
|
99
77
|
else:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
subprocess.run([f"{prefix}{cmd}{exe}", *args], **kwargs) # noqa: S603, PLW1510
|
|
78
|
+
with environ(UV_PROJECT_ENVIRONMENT=f".venvs/{version}", MULTIRUN="1"):
|
|
79
|
+
subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510
|
|
103
80
|
|
|
104
81
|
|
|
105
82
|
def multirun(cmd: str, *args: str, **kwargs: Any) -> None:
|
|
@@ -124,10 +101,10 @@ def clean() -> None:
|
|
|
124
101
|
for path in paths_to_clean:
|
|
125
102
|
shell(f"rm -rf {path}")
|
|
126
103
|
|
|
127
|
-
cache_dirs =
|
|
128
|
-
for dirpath in Path(".").rglob("
|
|
129
|
-
if
|
|
130
|
-
shutil.rmtree(
|
|
104
|
+
cache_dirs = {".cache", ".pytest_cache", ".mypy_cache", ".ruff_cache", "__pycache__"}
|
|
105
|
+
for dirpath in Path(".").rglob("*/"):
|
|
106
|
+
if dirpath.parts[0] not in (".venv", ".venvs") and dirpath.name in cache_dirs:
|
|
107
|
+
shutil.rmtree(dirpath, ignore_errors=True)
|
|
131
108
|
|
|
132
109
|
|
|
133
110
|
def vscode() -> None:
|
|
@@ -143,22 +120,25 @@ def main() -> int:
|
|
|
143
120
|
if len(args) > 1:
|
|
144
121
|
run("default", "duty", "--help", args[1])
|
|
145
122
|
else:
|
|
146
|
-
print(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
123
|
+
print(
|
|
124
|
+
dedent(
|
|
125
|
+
"""
|
|
126
|
+
Available commands
|
|
127
|
+
help Print this help. Add task name to print help.
|
|
128
|
+
setup Setup all virtual environments (install dependencies).
|
|
129
|
+
run Run a command in the default virtual environment.
|
|
130
|
+
multirun Run a command for all configured Python versions.
|
|
131
|
+
allrun Run a command in all virtual environments.
|
|
132
|
+
3.x Run a command in the virtual environment for Python 3.x.
|
|
133
|
+
clean Delete build artifacts and cache files.
|
|
134
|
+
vscode Configure VSCode to work on this project.
|
|
135
|
+
"""
|
|
136
|
+
),
|
|
137
|
+
flush=True,
|
|
138
|
+
) # noqa: T201
|
|
139
|
+
if os.path.exists(".venv"):
|
|
140
|
+
print("\nAvailable tasks", flush=True) # noqa: T201
|
|
141
|
+
run("default", "duty", "--list", no_sync=True)
|
|
162
142
|
return 0
|
|
163
143
|
|
|
164
144
|
while args:
|
|
@@ -4,10 +4,14 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from
|
|
7
|
+
from re import Pattern
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
8
9
|
|
|
9
10
|
from failprint.lazy import lazy
|
|
10
11
|
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Sequence
|
|
14
|
+
|
|
11
15
|
|
|
12
16
|
@lazy(name="blacken_docs")
|
|
13
17
|
def run(
|
|
@@ -5,12 +5,12 @@ from __future__ import annotations
|
|
|
5
5
|
import os
|
|
6
6
|
import subprocess
|
|
7
7
|
import sys
|
|
8
|
-
from functools import
|
|
8
|
+
from functools import cache
|
|
9
9
|
|
|
10
10
|
from failprint.lazy import lazy
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
@
|
|
13
|
+
@cache
|
|
14
14
|
def _find_ruff() -> str:
|
|
15
15
|
from ruff.__main__ import find_ruff_bin
|
|
16
16
|
|
|
@@ -5,10 +5,13 @@ from __future__ import annotations
|
|
|
5
5
|
import importlib
|
|
6
6
|
import sys
|
|
7
7
|
from io import StringIO
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import TYPE_CHECKING, Literal, cast
|
|
9
9
|
|
|
10
10
|
from failprint.lazy import lazy
|
|
11
11
|
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Sequence
|
|
14
|
+
|
|
12
15
|
|
|
13
16
|
@lazy(name="safety.check")
|
|
14
17
|
def check(
|
|
@@ -6,11 +6,11 @@ import inspect
|
|
|
6
6
|
import sys
|
|
7
7
|
from copy import deepcopy
|
|
8
8
|
from importlib import util as importlib_util
|
|
9
|
-
from typing import Any, Callable, ClassVar,
|
|
9
|
+
from typing import Any, Callable, ClassVar, Union
|
|
10
10
|
|
|
11
11
|
from duty.context import Context
|
|
12
12
|
|
|
13
|
-
DutyListType =
|
|
13
|
+
DutyListType = list[Union[str, Callable, "Duty"]]
|
|
14
14
|
default_duties_file = "duties.py"
|
|
15
15
|
|
|
16
16
|
|
|
@@ -4,14 +4,17 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
from contextlib import contextmanager, suppress
|
|
7
|
-
from typing import Any, Callable,
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Callable, Union
|
|
8
8
|
|
|
9
9
|
from failprint.runners import run as failprint_run
|
|
10
10
|
|
|
11
11
|
from duty.exceptions import DutyFailure
|
|
12
12
|
from duty.tools import Tool
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from collections.abc import Iterator
|
|
16
|
+
|
|
17
|
+
CmdType = Union[str, list[str], Callable]
|
|
15
18
|
|
|
16
19
|
|
|
17
20
|
class Context:
|
|
@@ -4,11 +4,13 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import inspect
|
|
6
6
|
from functools import wraps
|
|
7
|
-
from typing import TYPE_CHECKING, Any, Callable,
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Callable, overload
|
|
8
8
|
|
|
9
9
|
from duty.collection import Duty, DutyListType
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
+
from collections.abc import Iterable
|
|
13
|
+
|
|
12
14
|
from duty.context import Context
|
|
13
15
|
|
|
14
16
|
|
|
@@ -4,10 +4,14 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from
|
|
7
|
+
from re import Pattern
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
8
9
|
|
|
9
10
|
from duty.tools._base import Tool
|
|
10
11
|
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Sequence
|
|
14
|
+
|
|
11
15
|
|
|
12
16
|
class blacken_docs(Tool): # noqa: N801
|
|
13
17
|
"""Call [blacken-docs](https://github.com/adamchainz/blacken-docs)."""
|
|
@@ -5,12 +5,12 @@ from __future__ import annotations
|
|
|
5
5
|
import os
|
|
6
6
|
import subprocess
|
|
7
7
|
import sys
|
|
8
|
-
from functools import
|
|
8
|
+
from functools import cache
|
|
9
9
|
|
|
10
10
|
from duty.tools._base import Tool
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
@
|
|
13
|
+
@cache
|
|
14
14
|
def _find_ruff() -> str:
|
|
15
15
|
from ruff.__main__ import find_ruff_bin
|
|
16
16
|
|
|
@@ -5,10 +5,13 @@ from __future__ import annotations
|
|
|
5
5
|
import importlib
|
|
6
6
|
import sys
|
|
7
7
|
from io import StringIO
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import TYPE_CHECKING, Literal, cast
|
|
9
9
|
|
|
10
10
|
from duty.tools._base import Tool
|
|
11
11
|
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Sequence
|
|
14
|
+
|
|
12
15
|
|
|
13
16
|
class safety(Tool): # noqa: N801
|
|
14
17
|
"""Call [Safety](https://github.com/pyupio/safety)."""
|
|
@@ -12,9 +12,12 @@ import textwrap
|
|
|
12
12
|
from contextlib import suppress
|
|
13
13
|
from functools import cached_property, partial
|
|
14
14
|
from inspect import Parameter, Signature, signature
|
|
15
|
-
from typing import Any, Callable, ForwardRef,
|
|
15
|
+
from typing import TYPE_CHECKING, Any, Callable, ForwardRef, Union, get_args, get_origin
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from collections.abc import Sequence
|
|
19
|
+
|
|
20
|
+
# YORE: EOL 3.9: Replace block with lines 6-13.
|
|
18
21
|
if sys.version_info < (3, 10):
|
|
19
22
|
from eval_type_backport import eval_type_backport as eval_type
|
|
20
23
|
|
|
@@ -96,4 +96,8 @@ def test_workdir_as_context_manager(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
|
96
96
|
records.append(failure.value.code)
|
|
97
97
|
|
|
98
98
|
base = records[0]
|
|
99
|
-
|
|
99
|
+
|
|
100
|
+
# If the repository is checked out near the root of the filesystem, the working directory will
|
|
101
|
+
# eventually be the root, so cap the lowest depth at 1.
|
|
102
|
+
expected_depths = [max(1, base - offset) for offset in range(len(records))]
|
|
103
|
+
assert records == expected_depths
|
duty-1.4.2/devdeps.txt
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# dev
|
|
2
|
-
editables>=0.5
|
|
3
|
-
|
|
4
|
-
# maintenance
|
|
5
|
-
build>=1.2
|
|
6
|
-
git-changelog>=2.5
|
|
7
|
-
twine>=5.0; python_version < '3.13'
|
|
8
|
-
|
|
9
|
-
# ci
|
|
10
|
-
duty>=1.4
|
|
11
|
-
ruff>=0.4
|
|
12
|
-
pytest>=8.2
|
|
13
|
-
pytest-cov>=5.0
|
|
14
|
-
pytest-randomly>=3.15
|
|
15
|
-
pytest-xdist>=3.6
|
|
16
|
-
mypy>=1.10
|
|
17
|
-
types-markdown>=3.6
|
|
18
|
-
types-pyyaml>=6.0
|
|
19
|
-
|
|
20
|
-
# docs
|
|
21
|
-
black>=24.4
|
|
22
|
-
markdown-callouts>=0.4
|
|
23
|
-
markdown-exec>=1.8
|
|
24
|
-
mkdocs>=1.6
|
|
25
|
-
mkdocs-coverage>=1.0
|
|
26
|
-
mkdocs-gen-files>=0.5
|
|
27
|
-
mkdocs-git-committers-plugin-2>=2.3
|
|
28
|
-
mkdocs-literate-nav>=0.6
|
|
29
|
-
mkdocs-material>=9.5
|
|
30
|
-
mkdocs-minify-plugin>=0.8
|
|
31
|
-
mkdocstrings[python]>=0.25
|
|
32
|
-
tomli>=2.0; python_version < '3.11'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|