repo-review 0.12.1__tar.gz → 0.12.2__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.
- {repo_review-0.12.1 → repo_review-0.12.2}/.github/workflows/ci.yml +6 -3
- {repo_review-0.12.1 → repo_review-0.12.2}/.pre-commit-config.yaml +5 -5
- {repo_review-0.12.1 → repo_review-0.12.2}/PKG-INFO +3 -2
- {repo_review-0.12.1 → repo_review-0.12.2}/README.md +1 -1
- {repo_review-0.12.1 → repo_review-0.12.2}/action.yml +1 -1
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/index.html +5 -5
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/webapp.js +185 -22
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/webapp.md +1 -1
- {repo_review-0.12.1 → repo_review-0.12.2}/pyproject.toml +3 -1
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/__main__.py +8 -1
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_version.py +9 -4
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_package.py +2 -1
- {repo_review-0.12.1 → repo_review-0.12.2}/.devcontainer/devcontainer.json +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.git_archival.txt +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.gitattributes +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.github/CONTRIBUTING.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.github/ISSUE_TEMPLATE/new-issue.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.github/dependabot.yml +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.github/release.yml +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.github/workflows/cd.yml +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.gitignore +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.pre-commit-hooks.yaml +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/.readthedocs.yaml +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/LICENSE +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/.nojekyll +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/api/repo_review.resources.rst +1 -1
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/api/repo_review.rst +9 -9
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/changelog.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/checks.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/cli.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/conf.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/families.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/fixtures.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/index.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/intro.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/plugins.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/docs/programmatic.md +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/__init__.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_compat/__init__.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_compat/importlib/__init__.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_compat/importlib/resources/__init__.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_compat/importlib/resources/abc.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_compat/tomllib.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_compat/typing.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_version.pyi +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/checks.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/families.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/fixtures.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/ghpath.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/html.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/processor.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/py.typed +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/resources/__init__.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/resources/repo-review.schema.json +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/schema.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/testing.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/conftest.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_checks.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_cmd.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_depends.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_families.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_fixtures.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_multi.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_self.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_utilities/pyproject.py +0 -0
- {repo_review-0.12.1 → repo_review-0.12.2}/tests/test_utilities/pyproject.toml +0 -0
@@ -48,17 +48,20 @@ jobs:
|
|
48
48
|
fetch-depth: 0
|
49
49
|
persist-credentials: false
|
50
50
|
|
51
|
+
# Last one is activated
|
52
|
+
# yaml circular import issue on 3.14t on ubuntu
|
51
53
|
- uses: actions/setup-python@v5
|
52
54
|
with:
|
53
55
|
python-version: |
|
54
56
|
3.10
|
55
57
|
3.11
|
56
58
|
3.12
|
59
|
+
3.14
|
57
60
|
3.13
|
58
61
|
allow-prereleases: true
|
59
62
|
|
60
63
|
- name: Setup uv
|
61
|
-
uses:
|
64
|
+
uses: astral-sh/setup-uv@v6
|
62
65
|
|
63
66
|
- name: Install hatch
|
64
67
|
run: uv pip install --system hatch
|
@@ -88,7 +91,7 @@ jobs:
|
|
88
91
|
persist-credentials: false
|
89
92
|
|
90
93
|
- name: Setup uv
|
91
|
-
uses:
|
94
|
+
uses: astral-sh/setup-uv@v6
|
92
95
|
|
93
96
|
- uses: actions/setup-python@v5
|
94
97
|
with:
|
@@ -120,4 +123,4 @@ jobs:
|
|
120
123
|
- name: Run repo-review action
|
121
124
|
uses: ./
|
122
125
|
with:
|
123
|
-
plugins: sp-repo-review==2025.
|
126
|
+
plugins: sp-repo-review==2025.05.02
|
@@ -11,14 +11,14 @@ repos:
|
|
11
11
|
additional_dependencies: [black==24.*]
|
12
12
|
|
13
13
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
14
|
-
rev: "v0.
|
14
|
+
rev: "v0.11.8"
|
15
15
|
hooks:
|
16
16
|
- id: ruff
|
17
17
|
args: ["--fix", "--show-fixes"]
|
18
18
|
- id: ruff-format
|
19
19
|
|
20
20
|
- repo: https://github.com/rbubley/mirrors-prettier
|
21
|
-
rev: "v3.
|
21
|
+
rev: "v3.5.3"
|
22
22
|
hooks:
|
23
23
|
- id: prettier
|
24
24
|
types_or: [yaml, markdown, html, css, scss, javascript, json]
|
@@ -45,7 +45,7 @@ repos:
|
|
45
45
|
- id: rst-inline-touching-normal
|
46
46
|
|
47
47
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
48
|
-
rev: v1.
|
48
|
+
rev: v1.15.0
|
49
49
|
hooks:
|
50
50
|
- id: mypy
|
51
51
|
files: (src|web|tests)
|
@@ -79,12 +79,12 @@ repos:
|
|
79
79
|
exclude: .pre-commit-config.yaml
|
80
80
|
|
81
81
|
- repo: https://github.com/henryiii/validate-pyproject-schema-store
|
82
|
-
rev: 2025.
|
82
|
+
rev: 2025.04.28
|
83
83
|
hooks:
|
84
84
|
- id: validate-pyproject
|
85
85
|
|
86
86
|
- repo: https://github.com/python-jsonschema/check-jsonschema
|
87
|
-
rev: 0.
|
87
|
+
rev: 0.33.0
|
88
88
|
hooks:
|
89
89
|
- id: check-dependabot
|
90
90
|
- id: check-github-workflows
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: repo_review
|
3
|
-
Version: 0.12.
|
3
|
+
Version: 0.12.2
|
4
4
|
Summary: Framework that can run checks on repos
|
5
5
|
Project-URL: Changelog, https://github.com/scientific-python/repo-review/releases
|
6
6
|
Project-URL: Demo, https://scientific-python.github.io/repo-review
|
@@ -22,6 +22,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
24
24
|
Classifier: Programming Language :: Python :: 3.13
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
25
26
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
26
27
|
Classifier: Topic :: Software Development :: Quality Assurance
|
27
28
|
Classifier: Typing :: Typed
|
@@ -128,7 +129,7 @@ repos have some [pre-commit][] check.
|
|
128
129
|
## Development of repo-review and plugins
|
129
130
|
|
130
131
|
This project is intended to be fun and easy to develop and design checks for -
|
131
|
-
it requires and uses Python 3.10
|
132
|
+
it requires and uses Python 3.10+, and uses a lot of the new features in 3.9 and
|
132
133
|
3.10. It's maybe not entirely conventional, but it enables very simple plugin
|
133
134
|
development. It works locally, remotely, and in WebAssembly (using
|
134
135
|
[Pyodide][]). [See the docs][writing-a-plugin].
|
@@ -90,7 +90,7 @@ repos have some [pre-commit][] check.
|
|
90
90
|
## Development of repo-review and plugins
|
91
91
|
|
92
92
|
This project is intended to be fun and easy to develop and design checks for -
|
93
|
-
it requires and uses Python 3.10
|
93
|
+
it requires and uses Python 3.10+, and uses a lot of the new features in 3.9 and
|
94
94
|
3.10. It's maybe not entirely conventional, but it enables very simple plugin
|
95
95
|
development. It works locally, remotely, and in WebAssembly (using
|
96
96
|
[Pyodide][]). [See the docs][writing-a-plugin].
|
@@ -6,7 +6,7 @@
|
|
6
6
|
content="initial-scale=1, width=device-width"
|
7
7
|
/>
|
8
8
|
<script
|
9
|
-
src="https://cdn.jsdelivr.net/pyodide/v0.27.
|
9
|
+
src="https://cdn.jsdelivr.net/pyodide/v0.27.6/full/pyodide.js"
|
10
10
|
crossorigin
|
11
11
|
></script>
|
12
12
|
<!-- Production -->
|
@@ -64,10 +64,10 @@
|
|
64
64
|
<App
|
65
65
|
header={true}
|
66
66
|
deps={[
|
67
|
-
"repo-review~=0.12.
|
68
|
-
"sp-repo-review==2025.
|
69
|
-
"validate-pyproject
|
70
|
-
"validate-pyproject
|
67
|
+
"repo-review~=0.12.1",
|
68
|
+
"sp-repo-review==2025.05.02",
|
69
|
+
"validate-pyproject[all]~=0.24.0",
|
70
|
+
"validate-pyproject-schema-store==2025.04.28",
|
71
71
|
]}
|
72
72
|
/>,
|
73
73
|
);
|
@@ -1,5 +1,5 @@
|
|
1
1
|
const DEFAULT_MSG =
|
2
|
-
"Enter a GitHub repo and branch to review. Runs Python entirely in your browser using WebAssembly. Built with React, MaterialUI, and Pyodide.";
|
2
|
+
"Enter a GitHub repo and branch/tag to review. Runs Python entirely in your browser using WebAssembly. Built with React, MaterialUI, and Pyodide.";
|
3
3
|
|
4
4
|
const urlParams = new URLSearchParams(window.location.search);
|
5
5
|
const baseurl = window.location.pathname;
|
@@ -154,6 +154,39 @@ function Results(props) {
|
|
154
154
|
);
|
155
155
|
}
|
156
156
|
|
157
|
+
async function fetchRepoRefs(repo) {
|
158
|
+
if (!repo) return { branches: [], tags: [] };
|
159
|
+
try {
|
160
|
+
// Fetch both branches and tags from GitHub API
|
161
|
+
const [branchesResponse, tagsResponse] = await Promise.all([
|
162
|
+
fetch(`https://api.github.com/repos/${repo}/branches`),
|
163
|
+
fetch(`https://api.github.com/repos/${repo}/tags`),
|
164
|
+
]);
|
165
|
+
|
166
|
+
if (!branchesResponse.ok || !tagsResponse.ok) {
|
167
|
+
console.error("Error fetching repo data");
|
168
|
+
return { branches: [], tags: [] };
|
169
|
+
}
|
170
|
+
|
171
|
+
const branches = await branchesResponse.json();
|
172
|
+
const tags = await tagsResponse.json();
|
173
|
+
|
174
|
+
return {
|
175
|
+
branches: branches.map((branch) => ({
|
176
|
+
name: branch.name,
|
177
|
+
type: "branch",
|
178
|
+
})),
|
179
|
+
tags: tags.map((tag) => ({
|
180
|
+
name: tag.name,
|
181
|
+
type: "tag",
|
182
|
+
})),
|
183
|
+
};
|
184
|
+
} catch (error) {
|
185
|
+
console.error("Error fetching repo references:", error);
|
186
|
+
return { branches: [], tags: [] };
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
157
190
|
async function prepare_pyodide(deps) {
|
158
191
|
const deps_str = deps.map((i) => `"${i}"`).join(", ");
|
159
192
|
const pyodide = await loadPyodide();
|
@@ -196,28 +229,58 @@ class App extends React.Component {
|
|
196
229
|
this.state = {
|
197
230
|
results: [],
|
198
231
|
repo: urlParams.get("repo") || "",
|
199
|
-
|
232
|
+
ref: urlParams.get("ref") || "",
|
233
|
+
refType: urlParams.get("refType") || "branch",
|
234
|
+
refs: { branches: [], tags: [] },
|
200
235
|
msg: `<p>${DEFAULT_MSG}</p><h4>Packages:</h4> ${deps_str}`,
|
201
236
|
progress: false,
|
237
|
+
loadingRefs: false,
|
202
238
|
err_msg: "",
|
203
239
|
skip_reason: "",
|
204
240
|
url: "",
|
205
241
|
};
|
206
242
|
this.pyodide_promise = prepare_pyodide(props.deps);
|
243
|
+
this.refInputDebounce = null;
|
244
|
+
}
|
245
|
+
|
246
|
+
async fetchRepoReferences(repo) {
|
247
|
+
if (!repo) return;
|
248
|
+
|
249
|
+
this.setState({ loadingRefs: true });
|
250
|
+
const refs = await fetchRepoRefs(repo);
|
251
|
+
this.setState({
|
252
|
+
refs: refs,
|
253
|
+
loadingRefs: false,
|
254
|
+
});
|
255
|
+
}
|
256
|
+
|
257
|
+
handleRepoChange(repo) {
|
258
|
+
this.setState({ repo });
|
259
|
+
|
260
|
+
// debounce the API call to avoid too many requests
|
261
|
+
clearTimeout(this.refInputDebounce);
|
262
|
+
this.refInputDebounce = setTimeout(() => {
|
263
|
+
this.fetchRepoReferences(repo);
|
264
|
+
}, 500);
|
265
|
+
}
|
266
|
+
|
267
|
+
handleRefChange(ref, refType) {
|
268
|
+
this.setState({ ref, refType });
|
207
269
|
}
|
208
270
|
|
209
271
|
handleCompute() {
|
210
|
-
if (!this.state.repo || !this.state.
|
272
|
+
if (!this.state.repo || !this.state.ref) {
|
211
273
|
this.setState({ results: [], msg: DEFAULT_MSG });
|
212
274
|
window.history.replaceState(null, "", baseurl);
|
213
275
|
alert(
|
214
|
-
`Please enter a repo (${this.state.repo}) and branch (${this.state.
|
276
|
+
`Please enter a repo (${this.state.repo}) and branch/tag (${this.state.ref})`,
|
215
277
|
);
|
216
278
|
return;
|
217
279
|
}
|
218
280
|
const local_params = new URLSearchParams({
|
219
281
|
repo: this.state.repo,
|
220
|
-
|
282
|
+
ref: this.state.ref,
|
283
|
+
refType: this.state.refType,
|
221
284
|
});
|
222
285
|
window.history.replaceState(null, "", `${baseurl}?${local_params}`);
|
223
286
|
this.setState({
|
@@ -234,13 +297,13 @@ class App extends React.Component {
|
|
234
297
|
from repo_review.ghpath import GHPath
|
235
298
|
from dataclasses import replace
|
236
299
|
|
237
|
-
package = GHPath(repo="${state.repo}", branch="${state.
|
300
|
+
package = GHPath(repo="${state.repo}", branch="${state.ref}")
|
238
301
|
families, checks = process(package)
|
239
302
|
|
240
303
|
for v in families.values():
|
241
304
|
if v.get("description"):
|
242
305
|
v["description"] = md_as_html(v["description"])
|
243
|
-
checks = [
|
306
|
+
checks = [res.md_as_html() for res in checks]
|
244
307
|
|
245
308
|
(families, checks)
|
246
309
|
`);
|
@@ -249,7 +312,7 @@ class App extends React.Component {
|
|
249
312
|
this.setState({
|
250
313
|
msg: DEFAULT_MSG,
|
251
314
|
progress: false,
|
252
|
-
err_msg: "Invalid repository or branch. Please try again.",
|
315
|
+
err_msg: "Invalid repository or branch/tag. Please try again.",
|
253
316
|
});
|
254
317
|
return;
|
255
318
|
}
|
@@ -288,7 +351,7 @@ class App extends React.Component {
|
|
288
351
|
this.setState({
|
289
352
|
results: results,
|
290
353
|
families: families,
|
291
|
-
msg: `Results for ${state.repo}@${state.
|
354
|
+
msg: `Results for ${state.repo}@${state.ref} (${state.refType})`,
|
292
355
|
progress: false,
|
293
356
|
err_msg: "",
|
294
357
|
url: "",
|
@@ -300,13 +363,78 @@ class App extends React.Component {
|
|
300
363
|
}
|
301
364
|
|
302
365
|
componentDidMount() {
|
303
|
-
if (urlParams.get("repo")
|
304
|
-
this.
|
366
|
+
if (urlParams.get("repo")) {
|
367
|
+
this.fetchRepoReferences(urlParams.get("repo"));
|
368
|
+
|
369
|
+
if (urlParams.get("ref")) {
|
370
|
+
this.handleCompute();
|
371
|
+
}
|
305
372
|
}
|
306
373
|
}
|
307
374
|
|
308
375
|
render() {
|
309
|
-
const
|
376
|
+
const priorityBranches = ["HEAD", "main", "master", "develop", "stable"];
|
377
|
+
const branchMap = new Map(
|
378
|
+
this.state.refs.branches.map((branch) => [branch.name, branch]),
|
379
|
+
);
|
380
|
+
|
381
|
+
let availableOptions = [];
|
382
|
+
|
383
|
+
// If no repo is entered or API hasn't returned any branches/tags yet,
|
384
|
+
// show all five priority branches.
|
385
|
+
if (
|
386
|
+
this.state.repo === "" ||
|
387
|
+
(this.state.refs.branches.length === 0 &&
|
388
|
+
this.state.refs.tags.length === 0)
|
389
|
+
) {
|
390
|
+
availableOptions = [
|
391
|
+
{ label: "HEAD (default branch)", value: "HEAD", type: "branch" },
|
392
|
+
{ label: "main (branch)", value: "main", type: "branch" },
|
393
|
+
{ label: "master (branch)", value: "master", type: "branch" },
|
394
|
+
{ label: "develop (branch)", value: "develop", type: "branch" },
|
395
|
+
{ label: "stable (branch)", value: "stable", type: "branch" },
|
396
|
+
];
|
397
|
+
} else {
|
398
|
+
const prioritizedBranches = [
|
399
|
+
{ label: "HEAD (default branch)", value: "HEAD", type: "branch" },
|
400
|
+
];
|
401
|
+
|
402
|
+
priorityBranches.slice(1).forEach((branchName) => {
|
403
|
+
if (branchMap.has(branchName)) {
|
404
|
+
prioritizedBranches.push({
|
405
|
+
label: `${branchName} (branch)`,
|
406
|
+
value: branchName,
|
407
|
+
type: "branch",
|
408
|
+
});
|
409
|
+
// Remove from map so it doesn't get added twice.
|
410
|
+
branchMap.delete(branchName);
|
411
|
+
}
|
412
|
+
});
|
413
|
+
|
414
|
+
const otherBranches = [];
|
415
|
+
branchMap.forEach((branch) => {
|
416
|
+
otherBranches.push({
|
417
|
+
label: `${branch.name} (branch)`,
|
418
|
+
value: branch.name,
|
419
|
+
type: "branch",
|
420
|
+
});
|
421
|
+
});
|
422
|
+
otherBranches.sort((a, b) => a.value.localeCompare(b.value));
|
423
|
+
|
424
|
+
const tagOptions = this.state.refs.tags.map((tag) => ({
|
425
|
+
label: `${tag.name} (tag)`,
|
426
|
+
value: tag.name,
|
427
|
+
type: "tag",
|
428
|
+
}));
|
429
|
+
tagOptions.sort((a, b) => a.value.localeCompare(b.value));
|
430
|
+
|
431
|
+
availableOptions = [
|
432
|
+
...prioritizedBranches,
|
433
|
+
...otherBranches,
|
434
|
+
...tagOptions,
|
435
|
+
];
|
436
|
+
}
|
437
|
+
|
310
438
|
return (
|
311
439
|
<MyThemeProvider>
|
312
440
|
<MaterialUI.CssBaseline />
|
@@ -326,29 +454,64 @@ class App extends React.Component {
|
|
326
454
|
autoFocus={true}
|
327
455
|
onKeyDown={(e) => {
|
328
456
|
if (e.keyCode === 13)
|
329
|
-
document.getElementById("
|
457
|
+
document.getElementById("ref-select").focus();
|
330
458
|
}}
|
331
|
-
onInput={(e) => this.
|
459
|
+
onInput={(e) => this.handleRepoChange(e.target.value)}
|
332
460
|
defaultValue={urlParams.get("repo")}
|
333
461
|
sx={{ flexGrow: 3 }}
|
334
462
|
/>
|
335
463
|
<MaterialUI.Autocomplete
|
336
464
|
disablePortal
|
337
|
-
id="
|
338
|
-
options={
|
465
|
+
id="ref-select"
|
466
|
+
options={availableOptions}
|
467
|
+
loading={this.state.loadingRefs}
|
339
468
|
freeSolo={true}
|
340
469
|
onKeyDown={(e) => {
|
341
470
|
if (e.keyCode === 13) this.handleCompute();
|
342
471
|
}}
|
343
|
-
|
344
|
-
|
472
|
+
getOptionLabel={(option) =>
|
473
|
+
typeof option === "string" ? option : option.label
|
474
|
+
}
|
475
|
+
renderOption={(props, option) => (
|
476
|
+
<li {...props}>{option.label}</li>
|
477
|
+
)}
|
478
|
+
onInputChange={(e, value) => {
|
479
|
+
// If the user enters free text, treat it as a branch
|
480
|
+
if (typeof value === "string") {
|
481
|
+
this.handleRefChange(value, "branch");
|
482
|
+
}
|
483
|
+
}}
|
484
|
+
onChange={(e, option) => {
|
485
|
+
if (option) {
|
486
|
+
if (typeof option === "object") {
|
487
|
+
this.handleRefChange(option.value, option.type);
|
488
|
+
} else {
|
489
|
+
this.handleRefChange(option, "branch");
|
490
|
+
}
|
491
|
+
}
|
492
|
+
}}
|
493
|
+
defaultValue={urlParams.get("ref")}
|
345
494
|
renderInput={(params) => (
|
346
495
|
<MaterialUI.TextField
|
347
496
|
{...params}
|
348
|
-
label="Branch"
|
497
|
+
label="Branch/Tag"
|
349
498
|
variant="outlined"
|
350
|
-
helperText="e.g. main"
|
351
|
-
sx={{ flexGrow: 2, minWidth:
|
499
|
+
helperText="e.g. HEAD, main, or v1.0.0"
|
500
|
+
sx={{ flexGrow: 2, minWidth: 200 }}
|
501
|
+
InputProps={{
|
502
|
+
...params.InputProps,
|
503
|
+
endAdornment: (
|
504
|
+
<React.Fragment>
|
505
|
+
{this.state.loadingRefs ? (
|
506
|
+
<MaterialUI.CircularProgress
|
507
|
+
color="inherit"
|
508
|
+
size={20}
|
509
|
+
/>
|
510
|
+
) : null}
|
511
|
+
{params.InputProps.endAdornment}
|
512
|
+
</React.Fragment>
|
513
|
+
),
|
514
|
+
}}
|
352
515
|
/>
|
353
516
|
)}
|
354
517
|
/>
|
@@ -358,7 +521,7 @@ class App extends React.Component {
|
|
358
521
|
variant="contained"
|
359
522
|
size="large"
|
360
523
|
disabled={
|
361
|
-
this.state.progress || !this.state.repo || !this.state.
|
524
|
+
this.state.progress || !this.state.repo || !this.state.ref
|
362
525
|
}
|
363
526
|
>
|
364
527
|
<MaterialUI.Icon>start</MaterialUI.Icon>
|
@@ -20,7 +20,7 @@ You can also use the `html` output and write your own webapp. You need to provid
|
|
20
20
|
|
21
21
|
```html
|
22
22
|
<script
|
23
|
-
src="https://cdn.jsdelivr.net/pyodide/v0.
|
23
|
+
src="https://cdn.jsdelivr.net/pyodide/v0.27.6/full/pyodide.js"
|
24
24
|
crossorigin
|
25
25
|
></script>
|
26
26
|
```
|
@@ -24,6 +24,7 @@ classifiers = [
|
|
24
24
|
"Programming Language :: Python :: 3.11",
|
25
25
|
"Programming Language :: Python :: 3.12",
|
26
26
|
"Programming Language :: Python :: 3.13",
|
27
|
+
"Programming Language :: Python :: 3.14",
|
27
28
|
"Programming Language :: Python",
|
28
29
|
"Topic :: Software Development :: Quality Assurance",
|
29
30
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
@@ -148,7 +149,7 @@ skip-install = true
|
|
148
149
|
scripts.serve = "cd docs && echo 'Serving on http://localhost:8080' && python -m http.server 8080"
|
149
150
|
|
150
151
|
[[tool.hatch.envs.hatch-test.matrix]]
|
151
|
-
python = ["3.13", "3.12", "3.11", "3.10"]
|
152
|
+
python = ["3.14", "3.13", "3.12", "3.11", "3.10"]
|
152
153
|
|
153
154
|
|
154
155
|
[tool.pytest.ini_options]
|
@@ -201,6 +202,7 @@ messages_control.disable = [
|
|
201
202
|
"used-before-assignment", # False positive on conditional import
|
202
203
|
"unnecessary-ellipsis", # Not correct for typing
|
203
204
|
"import-outside-toplevel", # better handled elsewhere
|
205
|
+
"duplicate-code", # Triggers incorrectly
|
204
206
|
]
|
205
207
|
|
206
208
|
|
@@ -6,6 +6,7 @@ import json
|
|
6
6
|
import os
|
7
7
|
import sys
|
8
8
|
import typing
|
9
|
+
import urllib.error
|
9
10
|
from collections.abc import Mapping, Sequence
|
10
11
|
from pathlib import Path
|
11
12
|
from typing import Any, Literal
|
@@ -17,6 +18,7 @@ if typing.TYPE_CHECKING:
|
|
17
18
|
else:
|
18
19
|
import rich_click as click
|
19
20
|
|
21
|
+
import rich
|
20
22
|
import rich.console
|
21
23
|
import rich.markdown
|
22
24
|
import rich.syntax
|
@@ -265,7 +267,12 @@ def _remote_path_processor(package: Path) -> Path | GHPath:
|
|
265
267
|
msg = "online repo must be of the form 'gh:org/repo@branch[:path]' (:branch missing)"
|
266
268
|
raise click.BadParameter(msg)
|
267
269
|
org_repo, branch = org_repo_branch.split("@", maxsplit=1)
|
268
|
-
|
270
|
+
try:
|
271
|
+
return GHPath(repo=org_repo, branch=branch, path=p[0] if p else "")
|
272
|
+
except urllib.error.HTTPError as e:
|
273
|
+
rich.print(f"[red][bold]Error[/bold] accessing {e.url}", file=sys.stderr)
|
274
|
+
rich.print(f"[red]{e}", file=sys.stderr)
|
275
|
+
raise SystemExit(1) from None
|
269
276
|
|
270
277
|
|
271
278
|
@click.command(context_settings={"help_option_names": ["-h", "--help"]})
|
@@ -1,8 +1,13 @@
|
|
1
|
-
# file generated by
|
1
|
+
# file generated by setuptools-scm
|
2
2
|
# don't change, don't track in version control
|
3
|
+
|
4
|
+
__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
|
5
|
+
|
3
6
|
TYPE_CHECKING = False
|
4
7
|
if TYPE_CHECKING:
|
5
|
-
from typing import Tuple
|
8
|
+
from typing import Tuple
|
9
|
+
from typing import Union
|
10
|
+
|
6
11
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
7
12
|
else:
|
8
13
|
VERSION_TUPLE = object
|
@@ -12,5 +17,5 @@ __version__: str
|
|
12
17
|
__version_tuple__: VERSION_TUPLE
|
13
18
|
version_tuple: VERSION_TUPLE
|
14
19
|
|
15
|
-
__version__ = version = '0.12.
|
16
|
-
__version_tuple__ = version_tuple = (0, 12,
|
20
|
+
__version__ = version = '0.12.2'
|
21
|
+
__version_tuple__ = version_tuple = (0, 12, 2)
|
@@ -25,7 +25,8 @@ def test_local():
|
|
25
25
|
assert "BSD License" in results.families["general"]["description"]
|
26
26
|
assert "[tool.repo-review]" in results.families["validate-pyproject"]["description"]
|
27
27
|
for result in results.results:
|
28
|
-
|
28
|
+
if result.result is not None:
|
29
|
+
assert result.result
|
29
30
|
|
30
31
|
|
31
32
|
def test_broken_validate_pyproject(tmp_path: Path) -> None:
|
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
|
@@ -3,8 +3,8 @@ repo\_review package
|
|
3
3
|
|
4
4
|
.. automodule:: repo_review
|
5
5
|
:members:
|
6
|
-
:undoc-members:
|
7
6
|
:show-inheritance:
|
7
|
+
:undoc-members:
|
8
8
|
|
9
9
|
Subpackages
|
10
10
|
-----------
|
@@ -22,61 +22,61 @@ repo\_review.checks module
|
|
22
22
|
|
23
23
|
.. automodule:: repo_review.checks
|
24
24
|
:members:
|
25
|
-
:undoc-members:
|
26
25
|
:show-inheritance:
|
26
|
+
:undoc-members:
|
27
27
|
|
28
28
|
repo\_review.families module
|
29
29
|
----------------------------
|
30
30
|
|
31
31
|
.. automodule:: repo_review.families
|
32
32
|
:members:
|
33
|
-
:undoc-members:
|
34
33
|
:show-inheritance:
|
34
|
+
:undoc-members:
|
35
35
|
|
36
36
|
repo\_review.fixtures module
|
37
37
|
----------------------------
|
38
38
|
|
39
39
|
.. automodule:: repo_review.fixtures
|
40
40
|
:members:
|
41
|
-
:undoc-members:
|
42
41
|
:show-inheritance:
|
42
|
+
:undoc-members:
|
43
43
|
|
44
44
|
repo\_review.ghpath module
|
45
45
|
--------------------------
|
46
46
|
|
47
47
|
.. automodule:: repo_review.ghpath
|
48
48
|
:members:
|
49
|
-
:undoc-members:
|
50
49
|
:show-inheritance:
|
50
|
+
:undoc-members:
|
51
51
|
|
52
52
|
repo\_review.html module
|
53
53
|
------------------------
|
54
54
|
|
55
55
|
.. automodule:: repo_review.html
|
56
56
|
:members:
|
57
|
-
:undoc-members:
|
58
57
|
:show-inheritance:
|
58
|
+
:undoc-members:
|
59
59
|
|
60
60
|
repo\_review.processor module
|
61
61
|
-----------------------------
|
62
62
|
|
63
63
|
.. automodule:: repo_review.processor
|
64
64
|
:members:
|
65
|
-
:undoc-members:
|
66
65
|
:show-inheritance:
|
66
|
+
:undoc-members:
|
67
67
|
|
68
68
|
repo\_review.schema module
|
69
69
|
--------------------------
|
70
70
|
|
71
71
|
.. automodule:: repo_review.schema
|
72
72
|
:members:
|
73
|
-
:undoc-members:
|
74
73
|
:show-inheritance:
|
74
|
+
:undoc-members:
|
75
75
|
|
76
76
|
repo\_review.testing module
|
77
77
|
---------------------------
|
78
78
|
|
79
79
|
.. automodule:: repo_review.testing
|
80
80
|
:members:
|
81
|
-
:undoc-members:
|
82
81
|
:show-inheritance:
|
82
|
+
:undoc-members:
|
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
|
{repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_compat/importlib/resources/__init__.py
RENAMED
File without changes
|
{repo_review-0.12.1 → repo_review-0.12.2}/src/repo_review/_compat/importlib/resources/abc.py
RENAMED
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
|