pyprojkit 0.1.0__tar.gz → 0.2.0__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.
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/PKG-INFO +2 -1
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/README.md +1 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/pyproject.toml +1 -1
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/config/project.py +22 -1
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/tasks.py +24 -6
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/versions.py +1 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/LICENSE +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/__init__.py +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/_paths.py +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/_run.py +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/cli.py +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/config/__init__.py +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/config/base.py +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/config/profiles.py +1 -1
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/config/tools.py +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/discovery.py +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/sessions.py +0 -0
- {pyprojkit-0.1.0 → pyprojkit-0.2.0}/src/pyprojkit/sync.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyprojkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Development workflow toolkit for Python projects: pyproject.toml sync, doit tasks, nox sessions
|
|
5
5
|
Author: mm21
|
|
6
6
|
Author-email: mm21 <mm21.dev@gmail.com>
|
|
@@ -277,6 +277,7 @@ All tasks share the same layout:
|
|
|
277
277
|
- `__cache__/`: caches (doit db, pytest cache, coverage data, nox envs)
|
|
278
278
|
- `__out__/`: generated artifacts (`test/` coverage + JUnit results, `doc/html`, `analysis/`, `uv/` build artifacts)
|
|
279
279
|
- `badges/`: generated badge SVGs
|
|
280
|
+
- `src/<package>`: package sources consumed by the `init` and `analysis` tasks; the containing directory is configurable via `ProjectConfig.packages_dir` (default `"src"`)
|
|
280
281
|
|
|
281
282
|
## Custom profiles
|
|
282
283
|
|
|
@@ -234,6 +234,7 @@ All tasks share the same layout:
|
|
|
234
234
|
- `__cache__/`: caches (doit db, pytest cache, coverage data, nox envs)
|
|
235
235
|
- `__out__/`: generated artifacts (`test/` coverage + JUnit results, `doc/html`, `analysis/`, `uv/` build artifacts)
|
|
236
236
|
- `badges/`: generated badge SVGs
|
|
237
|
+
- `src/<package>`: package sources consumed by the `init` and `analysis` tasks; the containing directory is configurable via `ProjectConfig.packages_dir` (default `"src"`)
|
|
237
238
|
|
|
238
239
|
## Custom profiles
|
|
239
240
|
|
|
@@ -5,6 +5,7 @@ Project-wide configuration, declared in a project's `pyprojconf.py`.
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
7
|
from dataclasses import dataclass, field
|
|
8
|
+
from pathlib import Path
|
|
8
9
|
from typing import Any, Sequence
|
|
9
10
|
|
|
10
11
|
from .. import _paths
|
|
@@ -81,6 +82,7 @@ class MkinitConfig:
|
|
|
81
82
|
Arguments passed to mkinit.
|
|
82
83
|
"""
|
|
83
84
|
|
|
85
|
+
|
|
84
86
|
@dataclass(kw_only=True)
|
|
85
87
|
class SphinxConfig:
|
|
86
88
|
"""
|
|
@@ -98,6 +100,7 @@ class SphinxConfig:
|
|
|
98
100
|
built documentation when the doc task is run with `--copy`.
|
|
99
101
|
"""
|
|
100
102
|
|
|
103
|
+
|
|
101
104
|
@dataclass(kw_only=True)
|
|
102
105
|
class DocConfig:
|
|
103
106
|
"""
|
|
@@ -114,11 +117,13 @@ class DocConfig:
|
|
|
114
117
|
Enables the `doc` task; opt-in.
|
|
115
118
|
"""
|
|
116
119
|
|
|
120
|
+
|
|
117
121
|
@dataclass(kw_only=True)
|
|
118
122
|
class AnalysisConfig:
|
|
119
123
|
"""
|
|
120
124
|
Static analysis configuration.
|
|
121
125
|
"""
|
|
126
|
+
|
|
122
127
|
mypy: MypyConfig | None = field(default_factory=MypyConfig)
|
|
123
128
|
pyright: bool = True
|
|
124
129
|
|
|
@@ -128,11 +133,14 @@ class PublishConfig:
|
|
|
128
133
|
"""
|
|
129
134
|
Configuration for building and publishing via uv.
|
|
130
135
|
"""
|
|
136
|
+
|
|
131
137
|
out_dir: str = str(_paths.UV_PATH)
|
|
132
138
|
"""
|
|
133
139
|
Directory for build artifacts; cleaned before each build so stale artifacts are
|
|
134
140
|
never published.
|
|
135
141
|
"""
|
|
142
|
+
|
|
143
|
+
|
|
136
144
|
@dataclass(kw_only=True)
|
|
137
145
|
class ToolsConfig:
|
|
138
146
|
"""
|
|
@@ -142,6 +150,7 @@ class ToolsConfig:
|
|
|
142
150
|
`pyprojkit.config.profiles`. The default instance corresponds to the default
|
|
143
151
|
profile.
|
|
144
152
|
"""
|
|
153
|
+
|
|
145
154
|
formatting: FormattingConfig = field(default_factory=FormattingConfig.default)
|
|
146
155
|
test: TestConfig | None = field(default_factory=TestConfig)
|
|
147
156
|
doit: DoitConfig = field(default_factory=DoitConfig)
|
|
@@ -157,6 +166,7 @@ class ToolsConfig:
|
|
|
157
166
|
|
|
158
167
|
A key not otherwise managed creates a new managed table.
|
|
159
168
|
"""
|
|
169
|
+
|
|
160
170
|
@classmethod
|
|
161
171
|
def default(cls) -> ToolsConfig:
|
|
162
172
|
"""
|
|
@@ -174,6 +184,7 @@ class ProjectConfig:
|
|
|
174
184
|
|
|
175
185
|
A project's `pyprojconf.py` must define a module-level instance named `config`.
|
|
176
186
|
"""
|
|
187
|
+
|
|
177
188
|
package: str
|
|
178
189
|
"""
|
|
179
190
|
Import name of the package, e.g. `"trilium_alchemy"`.
|
|
@@ -182,13 +193,23 @@ class ProjectConfig:
|
|
|
182
193
|
"""
|
|
183
194
|
Supported Python versions.
|
|
184
195
|
"""
|
|
196
|
+
packages_dir: str = "src"
|
|
197
|
+
"""
|
|
198
|
+
Directory containing packages, relative to the project root.
|
|
199
|
+
"""
|
|
185
200
|
format_paths: Sequence[str] = ("src", "test", "doc", "examples")
|
|
186
201
|
"""
|
|
187
202
|
Directories to format (those which exist), in addition to `*.py` and `*.toml` files
|
|
188
203
|
at the project root.
|
|
189
204
|
"""
|
|
190
|
-
|
|
191
205
|
tools: ToolsConfig = field(default_factory=ToolsConfig.default)
|
|
192
206
|
"""
|
|
193
207
|
Tool configurations.
|
|
194
208
|
"""
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def package_path(self) -> Path:
|
|
212
|
+
"""
|
|
213
|
+
Path to the package directory, relative to the project root.
|
|
214
|
+
"""
|
|
215
|
+
return Path(self.packages_dir) / self.package
|
|
@@ -22,6 +22,7 @@ from __future__ import annotations
|
|
|
22
22
|
|
|
23
23
|
import os
|
|
24
24
|
import shutil
|
|
25
|
+
import xml.etree.ElementTree as ET
|
|
25
26
|
from pathlib import Path
|
|
26
27
|
from typing import Callable
|
|
27
28
|
|
|
@@ -40,7 +41,22 @@ __all__ = [
|
|
|
40
41
|
"TaskFactory",
|
|
41
42
|
]
|
|
42
43
|
|
|
43
|
-
TaskCreator = Callable[..., Task]
|
|
44
|
+
type TaskCreator = Callable[..., Task]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _normalize_svg(path: Path | str):
|
|
48
|
+
"""
|
|
49
|
+
Rewrite SVG with attributes sorted, as genbadge doesn't order them
|
|
50
|
+
deterministically.
|
|
51
|
+
"""
|
|
52
|
+
ET.register_namespace("", "http://www.w3.org/2000/svg")
|
|
53
|
+
ET.register_namespace("xlink", "http://www.w3.org/1999/xlink")
|
|
54
|
+
tree = ET.parse(path)
|
|
55
|
+
for elem in tree.iter():
|
|
56
|
+
attrib = sorted(elem.attrib.items())
|
|
57
|
+
elem.attrib.clear()
|
|
58
|
+
elem.attrib.update(attrib)
|
|
59
|
+
tree.write(path, encoding="unicode")
|
|
44
60
|
|
|
45
61
|
|
|
46
62
|
class TaskFactory:
|
|
@@ -172,6 +188,8 @@ class TaskFactory:
|
|
|
172
188
|
(create_folder, [_paths.BADGES_PATH]),
|
|
173
189
|
(run, (tests_args,)),
|
|
174
190
|
(run, (cov_args,)),
|
|
191
|
+
(_normalize_svg, [_paths.PYTEST_BADGE_PATH]),
|
|
192
|
+
(_normalize_svg, [_paths.COV_BADGE_PATH]),
|
|
175
193
|
],
|
|
176
194
|
targets=[
|
|
177
195
|
str(_paths.PYTEST_BADGE_PATH),
|
|
@@ -218,13 +236,13 @@ class TaskFactory:
|
|
|
218
236
|
Create `init` task which generates `__init__.py` files using mkinit.
|
|
219
237
|
"""
|
|
220
238
|
mkinit = self._require(self._config.tools.doc.mkinit, "tools.doc.mkinit")
|
|
221
|
-
|
|
239
|
+
package_path = self._config.package_path
|
|
222
240
|
|
|
223
241
|
def task_init() -> Task:
|
|
224
242
|
return Task(
|
|
225
243
|
"init",
|
|
226
244
|
actions=[
|
|
227
|
-
(run, (["mkinit",
|
|
245
|
+
(run, (["mkinit", str(package_path), *mkinit.args],)),
|
|
228
246
|
],
|
|
229
247
|
targets=[],
|
|
230
248
|
file_dep=[],
|
|
@@ -306,7 +324,7 @@ class TaskFactory:
|
|
|
306
324
|
Create `analysis` task which runs static analysis tools.
|
|
307
325
|
"""
|
|
308
326
|
analysis = self._require(self._config.tools.analysis, "tools.analysis")
|
|
309
|
-
|
|
327
|
+
package_path = self._config.package_path
|
|
310
328
|
|
|
311
329
|
def task_analysis() -> Task:
|
|
312
330
|
actions = []
|
|
@@ -322,14 +340,14 @@ class TaskFactory:
|
|
|
322
340
|
str(_paths.MYPY_HTML_PATH),
|
|
323
341
|
"--cobertura-xml-report",
|
|
324
342
|
str(_paths.MYPY_XML_PATH),
|
|
325
|
-
|
|
343
|
+
str(package_path),
|
|
326
344
|
],
|
|
327
345
|
),
|
|
328
346
|
)
|
|
329
347
|
)
|
|
330
348
|
|
|
331
349
|
if analysis.pyright:
|
|
332
|
-
actions.append((run, (["pyright",
|
|
350
|
+
actions.append((run, (["pyright", str(package_path)],)))
|
|
333
351
|
|
|
334
352
|
return Task(
|
|
335
353
|
"analysis",
|
|
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
|