repo-review 0.10.4__tar.gz → 0.10.6__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.
Files changed (66) hide show
  1. {repo_review-0.10.4 → repo_review-0.10.6}/.github/workflows/ci.yml +12 -4
  2. {repo_review-0.10.4 → repo_review-0.10.6}/.pre-commit-config.yaml +5 -5
  3. {repo_review-0.10.4 → repo_review-0.10.6}/PKG-INFO +14 -4
  4. {repo_review-0.10.4 → repo_review-0.10.6}/README.md +3 -0
  5. {repo_review-0.10.4 → repo_review-0.10.6}/docs/api/repo_review.rst +8 -0
  6. {repo_review-0.10.4 → repo_review-0.10.6}/docs/fixtures.md +1 -1
  7. {repo_review-0.10.4 → repo_review-0.10.6}/docs/index.html +2 -2
  8. {repo_review-0.10.4 → repo_review-0.10.6}/docs/intro.md +4 -1
  9. {repo_review-0.10.4 → repo_review-0.10.6}/docs/plugins.md +17 -1
  10. {repo_review-0.10.4 → repo_review-0.10.6}/noxfile.py +2 -0
  11. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/__init__.py +0 -1
  12. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/__main__.py +3 -1
  13. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/_compat/importlib/resources/abc.py +1 -0
  14. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/_version.py +2 -2
  15. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/checks.py +23 -0
  16. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/ghpath.py +4 -8
  17. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/processor.py +9 -13
  18. repo_review-0.10.6/src/repo_review/testing.py +70 -0
  19. {repo_review-0.10.4 → repo_review-0.10.6}/tests/test_cmd.py +1 -1
  20. repo_review-0.10.6/tests/test_depends.py +61 -0
  21. {repo_review-0.10.4 → repo_review-0.10.6}/tests/test_package.py +13 -0
  22. {repo_review-0.10.4 → repo_review-0.10.6}/.devcontainer/devcontainer.json +0 -0
  23. {repo_review-0.10.4 → repo_review-0.10.6}/.git_archival.txt +0 -0
  24. {repo_review-0.10.4 → repo_review-0.10.6}/.gitattributes +0 -0
  25. {repo_review-0.10.4 → repo_review-0.10.6}/.github/CONTRIBUTING.md +0 -0
  26. {repo_review-0.10.4 → repo_review-0.10.6}/.github/dependabot.yml +0 -0
  27. {repo_review-0.10.4 → repo_review-0.10.6}/.github/matchers/pylint.json +0 -0
  28. {repo_review-0.10.4 → repo_review-0.10.6}/.github/workflows/cd.yml +0 -0
  29. {repo_review-0.10.4 → repo_review-0.10.6}/.gitignore +0 -0
  30. {repo_review-0.10.4 → repo_review-0.10.6}/.pre-commit-hooks.yaml +0 -0
  31. {repo_review-0.10.4 → repo_review-0.10.6}/.readthedocs.yaml +0 -0
  32. {repo_review-0.10.4 → repo_review-0.10.6}/LICENSE +0 -0
  33. {repo_review-0.10.4 → repo_review-0.10.6}/action.yml +0 -0
  34. {repo_review-0.10.4 → repo_review-0.10.6}/docs/.nojekyll +0 -0
  35. {repo_review-0.10.4 → repo_review-0.10.6}/docs/api/repo_review.resources.rst +0 -0
  36. {repo_review-0.10.4 → repo_review-0.10.6}/docs/changelog.md +0 -0
  37. {repo_review-0.10.4 → repo_review-0.10.6}/docs/checks.md +0 -0
  38. {repo_review-0.10.4 → repo_review-0.10.6}/docs/cli.md +0 -0
  39. {repo_review-0.10.4 → repo_review-0.10.6}/docs/conf.py +0 -0
  40. {repo_review-0.10.4 → repo_review-0.10.6}/docs/families.md +0 -0
  41. {repo_review-0.10.4 → repo_review-0.10.6}/docs/index.md +0 -0
  42. {repo_review-0.10.4 → repo_review-0.10.6}/docs/programmatic.md +0 -0
  43. {repo_review-0.10.4 → repo_review-0.10.6}/docs/webapp.js +0 -0
  44. {repo_review-0.10.4 → repo_review-0.10.6}/docs/webapp.md +0 -0
  45. {repo_review-0.10.4 → repo_review-0.10.6}/pyproject.toml +0 -0
  46. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/_compat/__init__.py +0 -0
  47. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/_compat/importlib/__init__.py +0 -0
  48. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/_compat/importlib/resources/__init__.py +0 -0
  49. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/_compat/tomllib.py +0 -0
  50. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/_compat/typing.py +0 -0
  51. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/_version.pyi +0 -0
  52. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/families.py +0 -0
  53. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/fixtures.py +0 -0
  54. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/html.py +0 -0
  55. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/py.typed +0 -0
  56. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/resources/__init__.py +0 -0
  57. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/resources/repo-review.schema.json +0 -0
  58. {repo_review-0.10.4 → repo_review-0.10.6}/src/repo_review/schema.py +0 -0
  59. {repo_review-0.10.4 → repo_review-0.10.6}/tests/conftest.py +0 -0
  60. {repo_review-0.10.4 → repo_review-0.10.6}/tests/test_checks.py +0 -0
  61. {repo_review-0.10.4 → repo_review-0.10.6}/tests/test_families.py +0 -0
  62. {repo_review-0.10.4 → repo_review-0.10.6}/tests/test_fixtures.py +0 -0
  63. {repo_review-0.10.4 → repo_review-0.10.6}/tests/test_multi.py +0 -0
  64. {repo_review-0.10.4 → repo_review-0.10.6}/tests/test_self.py +0 -0
  65. {repo_review-0.10.4 → repo_review-0.10.6}/tests/test_utilities/pyproject.py +0 -0
  66. {repo_review-0.10.4 → repo_review-0.10.6}/tests/test_utilities/pyproject.toml +0 -0
@@ -26,7 +26,7 @@ jobs:
26
26
  - uses: actions/setup-python@v5
27
27
  with:
28
28
  python-version: "3.x"
29
- - uses: pre-commit/action@v3.0.0
29
+ - uses: pre-commit/action@v3.0.1
30
30
  with:
31
31
  extra_args: --hook-stage manual --all-files
32
32
  - name: Run PyLint
@@ -53,8 +53,13 @@ jobs:
53
53
  with:
54
54
  python-version: ${{ matrix.python-version }}
55
55
 
56
+ - name: Setup uv
57
+ uses: yezz123/setup-uv@v4
58
+ with:
59
+ uv-venv: ".venv"
60
+
56
61
  - name: Install package
57
- run: python -m pip install .[test,cli]
62
+ run: uv pip install .[test,cli]
58
63
 
59
64
  - name: Test package
60
65
  run: python -m pytest -ra
@@ -80,7 +85,10 @@ jobs:
80
85
  with:
81
86
  fetch-depth: 0
82
87
 
83
- - uses: wntrblm/nox@2023.04.22
88
+ - name: Setup uv
89
+ uses: yezz123/setup-uv@v4
90
+
91
+ - uses: wntrblm/nox@2024.04.15
84
92
  with:
85
93
  python-versions: "3.11"
86
94
 
@@ -106,4 +114,4 @@ jobs:
106
114
  - name: Run repo-review action
107
115
  uses: ./
108
116
  with:
109
- plugins: sp-repo-review==2023.12.21
117
+ plugins: sp-repo-review==2024.03.10
@@ -10,20 +10,20 @@ repos:
10
10
  additional_dependencies: [black==23.*]
11
11
 
12
12
  - repo: https://github.com/astral-sh/ruff-pre-commit
13
- rev: "v0.1.14"
13
+ rev: "v0.4.1"
14
14
  hooks:
15
15
  - id: ruff
16
16
  args: ["--fix", "--show-fixes"]
17
17
  - id: ruff-format
18
18
 
19
19
  - repo: https://github.com/pre-commit/mirrors-prettier
20
- rev: "v3.1.0"
20
+ rev: "v4.0.0-alpha.8"
21
21
  hooks:
22
22
  - id: prettier
23
23
  types_or: [yaml, markdown, html, css, scss, javascript, json]
24
24
 
25
25
  - repo: https://github.com/pre-commit/pre-commit-hooks
26
- rev: v4.5.0
26
+ rev: v4.6.0
27
27
  hooks:
28
28
  - id: check-added-large-files
29
29
  - id: check-case-conflict
@@ -44,7 +44,7 @@ repos:
44
44
  - id: rst-inline-touching-normal
45
45
 
46
46
  - repo: https://github.com/pre-commit/mirrors-mypy
47
- rev: v1.8.0
47
+ rev: v1.9.0
48
48
  hooks:
49
49
  - id: mypy
50
50
  files: (src|web|tests)
@@ -64,7 +64,7 @@ repos:
64
64
  args: ["-Lhist,absense", "-w"]
65
65
 
66
66
  - repo: https://github.com/shellcheck-py/shellcheck-py
67
- rev: v0.9.0.6
67
+ rev: v0.10.0.1
68
68
  hooks:
69
69
  - id: shellcheck
70
70
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: repo_review
3
- Version: 0.10.4
3
+ Version: 0.10.6
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
@@ -34,11 +34,18 @@ Requires-Dist: click>=8; extra == 'cli'
34
34
  Requires-Dist: rich-click; extra == 'cli'
35
35
  Requires-Dist: rich>=12.2; extra == 'cli'
36
36
  Provides-Extra: dev
37
- Requires-Dist: repo-review[cli,test]; extra == 'dev'
37
+ Requires-Dist: click>=8; extra == 'dev'
38
+ Requires-Dist: pytest>=7; extra == 'dev'
39
+ Requires-Dist: rich-click; extra == 'dev'
40
+ Requires-Dist: rich>=12.2; extra == 'dev'
41
+ Requires-Dist: sp-repo-review>=2023.12.21; extra == 'dev'
42
+ Requires-Dist: validate-pyproject>=0.14; extra == 'dev'
38
43
  Provides-Extra: docs
44
+ Requires-Dist: click>=8; extra == 'docs'
39
45
  Requires-Dist: furo; extra == 'docs'
40
46
  Requires-Dist: myst-parser>=0.13; extra == 'docs'
41
- Requires-Dist: repo-review[cli]; extra == 'docs'
47
+ Requires-Dist: rich-click; extra == 'docs'
48
+ Requires-Dist: rich>=12.2; extra == 'docs'
42
49
  Requires-Dist: sphinx-autodoc-typehints; extra == 'docs'
43
50
  Requires-Dist: sphinx-copybutton; extra == 'docs'
44
51
  Requires-Dist: sphinx-github-changelog; extra == 'docs'
@@ -57,6 +64,7 @@ Description-Content-Type: text/markdown
57
64
  [![Documentation Status][docs-badge]][docs-link]
58
65
 
59
66
  [![PyPI version][pypi-version]][pypi-link]
67
+ [![Conda-Forge][conda-badge]][conda-link]
60
68
  [![PyPI platforms][pypi-platforms]][pypi-link]
61
69
 
62
70
  <!-- SPHINX-START -->
@@ -212,6 +220,8 @@ This was developed for [Scikit-HEP][] before moving to Scientific-Python.
212
220
  [sp-repo-review]: https://pypi.org/project/sp-repo-review
213
221
  [validate-pyproject]: https://validate-pyproject.readthedocs.io
214
222
  [validate-pyproject-schema-store]: https://github.com/henryiii/validate-pyproject-schema-store
223
+ [conda-badge]: https://img.shields.io/conda/vn/conda-forge/repo-review
224
+ [conda-link]: https://github.com/conda-forge/repo-review-feedstock
215
225
 
216
226
  [intro-pre-commit]: https://repo-review.readthedocs.io/en/latest/intro.html#pre-commit
217
227
  [intro-github-actions]: https://repo-review.readthedocs.io/en/latest/intro.html#github-actions
@@ -4,6 +4,7 @@
4
4
  [![Documentation Status][docs-badge]][docs-link]
5
5
 
6
6
  [![PyPI version][pypi-version]][pypi-link]
7
+ [![Conda-Forge][conda-badge]][conda-link]
7
8
  [![PyPI platforms][pypi-platforms]][pypi-link]
8
9
 
9
10
  <!-- SPHINX-START -->
@@ -159,6 +160,8 @@ This was developed for [Scikit-HEP][] before moving to Scientific-Python.
159
160
  [sp-repo-review]: https://pypi.org/project/sp-repo-review
160
161
  [validate-pyproject]: https://validate-pyproject.readthedocs.io
161
162
  [validate-pyproject-schema-store]: https://github.com/henryiii/validate-pyproject-schema-store
163
+ [conda-badge]: https://img.shields.io/conda/vn/conda-forge/repo-review
164
+ [conda-link]: https://github.com/conda-forge/repo-review-feedstock
162
165
 
163
166
  [intro-pre-commit]: https://repo-review.readthedocs.io/en/latest/intro.html#pre-commit
164
167
  [intro-github-actions]: https://repo-review.readthedocs.io/en/latest/intro.html#github-actions
@@ -72,3 +72,11 @@ repo\_review.schema module
72
72
  :members:
73
73
  :undoc-members:
74
74
  :show-inheritance:
75
+
76
+ repo\_review.testing module
77
+ ---------------------------
78
+
79
+ .. automodule:: repo_review.testing
80
+ :members:
81
+ :undoc-members:
82
+ :show-inheritance:
@@ -3,7 +3,7 @@
3
3
  Like pytest fixtures, fixtures in repo-review are requested by name. There are five built-in fixtures:
4
4
 
5
5
  - `root`: {class}`~importlib.resources.abc.Traversable` - The repository path. All checks or fixtures that depend on the root of the repository should use this.
6
- - `package`: `~importlib.resources.abc.Traversable` - The path to the package directory. This is the same as `root` unless `--package-dir` is passed.
6
+ - `package`: {class}`~importlib.resources.abc.Traversable` - The path to the package directory. This is the same as `root` unless `--package-dir` is passed.
7
7
  - `name`: `str` - The name of the current check. (Special fixture only provided for checks, not collection functions.)
8
8
  - {func}`~repo_review.fixtures.pyproject`: `dict[str, Any]` - The `pyproject.toml` in the package if it exists, an empty dict otherwise.
9
9
  - {func}`~repo_review.fixtures.list_all`: `bool` - Returns `True`` if repo-review is just trying to collect all checks to list them.
@@ -65,8 +65,8 @@
65
65
  header={true}
66
66
  deps={[
67
67
  "repo-review~=0.10.0",
68
- "sp-repo-review==2023.12.21",
69
- "validate-pyproject-schema-store==2024.1.23",
68
+ "sp-repo-review==2024.03.10",
69
+ "validate-pyproject-schema-store==2024.04.20",
70
70
  "validate-pyproject[all]~=0.16.0",
71
71
  ]}
72
72
  />,
@@ -31,10 +31,13 @@ pipx inject repo-review <plugin(s)>
31
31
  repo-review .
32
32
  ```
33
33
 
34
- Any other way you like installing things works too, including `pip install`.
34
+ Any other way you like installing things works too, including `pip install` and `uv pip install`.
35
35
  Remember the `[cli]` extra if you are using the command line
36
36
  interface.
37
37
 
38
+ A conda-forge package is also available. You can use `conda`, `mamba`, `micromamba`, or `pixi` to
39
+ install from the conda-forge channel.
40
+
38
41
  Plugins are also encouraged to support pre-commit and GitHub Actions.
39
42
 
40
43
  ## Running checks
@@ -6,7 +6,7 @@ nicer display names. When writing a plugin, you should also do a few things
6
6
  when setting up the package. These suggestions assume you are using a
7
7
  standardized backend, such as `hatchling`, `flit-core`, `pdm-backend`, or
8
8
  `setuptools>=61`. If you are using some other build backend, please adjust
9
- accordingly.
9
+ accordingly. Notably, Poetry calls `project.entry-points` "`tool.poetry.plugins`".
10
10
 
11
11
  ## Entry points
12
12
 
@@ -53,6 +53,22 @@ You have `processed.results` and `processed.families` from the return of
53
53
  {func}`~repo_review.processor.collect_all` to get `.fixtures`, `.checks`, and
54
54
  `.families`.
55
55
 
56
+ ### Unit testing
57
+
58
+ You can also run unit tests with the {func}`~repo_review.testing.compute_check` helper. It is used like this:
59
+
60
+ ```python
61
+ def test_has_tool_ruff_unit() -> None:
62
+ assert repo_review.testing.compute_check("RF001", ruff={}).result
63
+ assert not repo_review.testing.compute_check("RF001", ruff=None).result
64
+ ```
65
+
66
+ It takes the check name and any fixtures as keyword arguments. It returns a
67
+ {class}`~repo_review.checks.Check` instance, so you can see if the `.result` is
68
+ `True`/`False`/`None`, or check any of the other properties.
69
+
70
+ .. versionadded:: 0.10.5
71
+
56
72
  ## An existing package
57
73
 
58
74
  Since writing a plugin does not require depending on repo-review, you can also
@@ -8,6 +8,8 @@ import nox
8
8
 
9
9
  DIR = Path(__file__).parent.resolve()
10
10
 
11
+ nox.needs_version = ">=2024.3.2"
12
+ nox.options.default_venv_backend = "uv|virtualenv"
11
13
  nox.options.sessions = ["lint", "pylint", "tests"]
12
14
 
13
15
 
@@ -4,7 +4,6 @@ Copyright (c) 2022 Henry Schreiner. All rights reserved.
4
4
  Review repos with a set of checks defined by plugins.
5
5
  """
6
6
 
7
-
8
7
  from __future__ import annotations
9
8
 
10
9
  from ._version import version as __version__
@@ -41,7 +41,9 @@ def __dir__() -> list[str]:
41
41
  return __all__
42
42
 
43
43
 
44
- rich.traceback.install(suppress=[click, rich, orig_click], show_locals=True, width=None)
44
+ rich.traceback.install(
45
+ suppress=[click, rich, orig_click], show_locals=False, width=None
46
+ )
45
47
 
46
48
  Status = Literal["empty", "passed", "skips", "errors"]
47
49
  Formats = Literal["rich", "json", "html", "svg"]
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import sys
4
4
 
5
5
  if sys.version_info < (3, 11):
6
+ # pylint: disable-next=deprecated-class
6
7
  from importlib.abc import Traversable
7
8
  else:
8
9
  from importlib.resources.abc import Traversable
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.10.4'
16
- __version_tuple__ = version_tuple = (0, 10, 4)
15
+ __version__ = version = '0.10.6'
16
+ __version_tuple__ = version_tuple = (0, 10, 6)
@@ -120,3 +120,26 @@ def get_check_description(name: str, check: Check) -> str:
120
120
  .. versionadded:: 0.8
121
121
  """
122
122
  return (check.__doc__ or "").format(self=check, name=name)
123
+
124
+
125
+ def process_result_bool(
126
+ result: str | bool | None, check: Check, name: str
127
+ ) -> str | None:
128
+ """
129
+ This converts a bool into a string given a check and name. If the result is a string
130
+ or None, it is returned as is.
131
+
132
+ :param result: The result to process.
133
+ :param check: The check instance.
134
+ :param name: The name of the check.
135
+ :return: The final string or None.
136
+
137
+ .. versionadded:: 0.11
138
+ """
139
+ if isinstance(result, bool):
140
+ return (
141
+ ""
142
+ if result
143
+ else (check.check.__doc__ or "Check failed").format(name=name, self=check)
144
+ )
145
+ return result
@@ -76,12 +76,10 @@ class GHPath(Traversable):
76
76
  return (self.path or self.repo).split("/")[-1]
77
77
 
78
78
  @typing.overload # type: ignore[override]
79
- def open(self, mode: Literal["r"], encoding: str | None = ...) -> io.StringIO:
80
- ...
79
+ def open(self, mode: Literal["r"], encoding: str | None = ...) -> io.StringIO: ...
81
80
 
82
81
  @typing.overload
83
- def open(self, mode: Literal["rb"]) -> io.BytesIO:
84
- ...
82
+ def open(self, mode: Literal["rb"]) -> io.BytesIO: ...
85
83
 
86
84
  def open(
87
85
  self, mode: Literal["r", "rb"] = "r", encoding: str | None = "utf-8"
@@ -164,12 +162,10 @@ class EmptyTraversable(Traversable):
164
162
  return self._fake_name
165
163
 
166
164
  @typing.overload # type: ignore[override]
167
- def open(self, mode: Literal["r"], encoding: str | None = ...) -> io.StringIO:
168
- ...
165
+ def open(self, mode: Literal["r"], encoding: str | None = ...) -> io.StringIO: ...
169
166
 
170
167
  @typing.overload
171
- def open(self, mode: Literal["rb"]) -> io.BytesIO:
172
- ...
168
+ def open(self, mode: Literal["rb"]) -> io.BytesIO: ...
173
169
 
174
170
  def open(
175
171
  self, mode: Literal["r", "rb"] = "r", encoding: str | None = "utf-8"
@@ -10,7 +10,13 @@ from typing import Any, TypeVar
10
10
  import markdown_it
11
11
 
12
12
  from ._compat.importlib.resources.abc import Traversable
13
- from .checks import Check, collect_checks, get_check_url, is_allowed
13
+ from .checks import (
14
+ Check,
15
+ collect_checks,
16
+ get_check_url,
17
+ is_allowed,
18
+ process_result_bool,
19
+ )
14
20
  from .families import Family, collect_families
15
21
  from .fixtures import apply_fixtures, collect_fixtures, compute_fixtures, pyproject
16
22
  from .ghpath import EmptyTraversable
@@ -108,8 +114,7 @@ class HasFamily(typing.Protocol):
108
114
  """
109
115
 
110
116
  @property
111
- def family(self) -> str:
112
- ...
117
+ def family(self) -> str: ...
113
118
 
114
119
 
115
120
  T = TypeVar("T", bound=HasFamily)
@@ -212,16 +217,7 @@ def process(
212
217
  for name in ts.static_order():
213
218
  if all(completed.get(n, "") == "" for n in graph[name]):
214
219
  result = apply_fixtures({"name": name, **fixtures}, tasks[name].check)
215
- if isinstance(result, bool):
216
- completed[name] = (
217
- ""
218
- if result
219
- else (tasks[name].check.__doc__ or "Check failed").format(
220
- name=name, self=tasks[name]
221
- )
222
- )
223
- else:
224
- completed[name] = result
220
+ completed[name] = process_result_bool(result, tasks[name], name)
225
221
  else:
226
222
  completed[name] = None
227
223
 
@@ -0,0 +1,70 @@
1
+ """
2
+ Helpers for testing repo-review plugins.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import importlib.metadata
8
+ import textwrap
9
+ from typing import Any
10
+
11
+ from ._compat import tomllib
12
+ from .checks import Check, get_check_url, process_result_bool
13
+ from .fixtures import apply_fixtures
14
+ from .processor import Result
15
+
16
+ __all__ = ["toml_loads", "compute_check"]
17
+
18
+
19
+ def __dir__() -> list[str]:
20
+ return __all__
21
+
22
+
23
+ def toml_loads(contents: str, /) -> Any:
24
+ """
25
+ A helper function to quickly load a TOML string for Python 3.10+.
26
+
27
+ :param contents: The TOML string to load.
28
+ :return: The loaded TOML.
29
+
30
+ .. versionadded:: 0.10.6
31
+ """
32
+ return tomllib.loads(contents)
33
+
34
+
35
+ def compute_check(name: str, /, **fixtures: Any) -> Result:
36
+ """
37
+ A helper function to compute a check given fixtures, intended for testing.
38
+ Currently, all fixtures are required to be passed in as keyword arguments,
39
+ transitive fixtures are not supported.
40
+
41
+ :param name: The name of the check to compute.
42
+ :param fixtures: The fixtures to use when computing the check.
43
+ :return: The computed result.
44
+
45
+ .. versionadded:: 0.10.5
46
+ """
47
+
48
+ check_functions = (
49
+ ep.load() for ep in importlib.metadata.entry_points(group="repo_review.checks")
50
+ )
51
+ checks = {
52
+ k: v
53
+ for func in check_functions
54
+ for k, v in apply_fixtures(fixtures, func).items()
55
+ }
56
+ check: Check = checks[name]
57
+ completed_raw = apply_fixtures({"name": name, **fixtures}, check.check)
58
+ completed = process_result_bool(completed_raw, check, name)
59
+ result = None if completed is None else not completed
60
+ doc = check.__doc__ or ""
61
+ err_msg = completed or ""
62
+
63
+ return Result(
64
+ family=check.family,
65
+ name=name,
66
+ description=doc.format(self=check, name=name).strip(),
67
+ result=result,
68
+ err_msg=textwrap.dedent(err_msg),
69
+ url=get_check_url(name, check),
70
+ )
@@ -31,7 +31,7 @@ def test_cmd_pyproject():
31
31
 
32
32
 
33
33
  def test_cmd_dual():
34
- subprocess.run(["repo-review", "../repo-review", "../repo-review"], check=True)
34
+ subprocess.run(["repo-review", "tests/..", "."], check=True)
35
35
 
36
36
 
37
37
  def test_cmd_html():
@@ -0,0 +1,61 @@
1
+ from pathlib import Path
2
+
3
+ import pytest
4
+
5
+ import repo_review.processor
6
+ from repo_review._compat.importlib.resources.abc import Traversable
7
+
8
+
9
+ class E100:
10
+ "Was passed correctly"
11
+
12
+ family = "example"
13
+
14
+ @staticmethod
15
+ def check(package: Traversable) -> bool:
16
+ """
17
+ Requires Path(".") to be passed
18
+ """
19
+
20
+ return package == Path()
21
+
22
+
23
+ class E200:
24
+ "Always true"
25
+
26
+ family = "example"
27
+ requires = frozenset(["E100"])
28
+
29
+ @staticmethod
30
+ def check() -> bool:
31
+ """
32
+ Can't be false.
33
+ """
34
+
35
+ return True
36
+
37
+
38
+ def test_ignore_filter_single(monkeypatch: pytest.MonkeyPatch) -> None:
39
+ monkeypatch.setattr(
40
+ repo_review.processor,
41
+ "collect_checks",
42
+ lambda _: {"E100": E100, "E200": E200},
43
+ )
44
+ _, results = repo_review.processor.process(Path(), ignore={"E100"})
45
+
46
+ assert len(results) == 1
47
+ assert results[0].name == "E200"
48
+ assert results[0].result
49
+
50
+
51
+ def test_select_filter_single(monkeypatch: pytest.MonkeyPatch) -> None:
52
+ monkeypatch.setattr(
53
+ repo_review.processor,
54
+ "collect_checks",
55
+ lambda _: {"E100": E100, "E200": E200},
56
+ )
57
+ _, results = repo_review.processor.process(Path(), select={"E200"})
58
+
59
+ assert len(results) == 1
60
+ assert results[0].name == "E200"
61
+ assert results[0].result
@@ -6,6 +6,7 @@ from pathlib import Path
6
6
  import pytest
7
7
 
8
8
  import repo_review as m
9
+ import repo_review.testing
9
10
  from repo_review.processor import process
10
11
 
11
12
  DIR = Path(__file__).parent.resolve()
@@ -43,3 +44,15 @@ def test_broken_validate_pyproject(tmp_path: Path) -> None:
43
44
  (result,) = (r for r in results.results if r.name == "VPP001")
44
45
  assert "must match pattern" in result.err_msg
45
46
  assert not result.result
47
+
48
+
49
+ def test_testing_function():
50
+ pytest.importorskip("sp_repo_review")
51
+
52
+ assert repo_review.testing.compute_check("RF001", ruff={}).result
53
+ assert not repo_review.testing.compute_check("RF001", ruff=None).result
54
+
55
+
56
+ def test_toml_function():
57
+ pyproject = repo_review.testing.toml_loads("one.two = 3")
58
+ assert pyproject == {"one": {"two": 3}}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes