auto-walrus 0.3.4__tar.gz → 0.4.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.
Potentially problematic release.
This version of auto-walrus might be problematic. Click here for more details.
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/.github/workflows/publish_to_pypi.yml +6 -6
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/.github/workflows/tox.yml +5 -4
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/.pre-commit-config.yaml +3 -3
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/PKG-INFO +3 -3
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/README.md +1 -1
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/auto_walrus.py +25 -14
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/pyproject.toml +2 -2
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/tests/main_test.py +63 -40
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/tox.ini +1 -1
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/.github/dependabot.yml +0 -0
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/.gitignore +0 -0
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/.pre-commit-hooks.yaml +0 -0
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/LICENSE +0 -0
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/requirements-dev.txt +0 -0
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/tests/__init__.py +0 -0
- {auto_walrus-0.3.4 → auto_walrus-0.4.0}/utils/bump_version.py +0 -0
|
@@ -8,9 +8,9 @@ jobs:
|
|
|
8
8
|
runs-on: ubuntu-latest
|
|
9
9
|
|
|
10
10
|
steps:
|
|
11
|
-
- uses: actions/checkout@
|
|
11
|
+
- uses: actions/checkout@v6
|
|
12
12
|
- name: Set up Python
|
|
13
|
-
uses: actions/setup-python@
|
|
13
|
+
uses: actions/setup-python@v6
|
|
14
14
|
with:
|
|
15
15
|
python-version: "3.x"
|
|
16
16
|
- name: Install pypa/build
|
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
- name: Build a binary wheel and a source tarball
|
|
23
23
|
run: python3 -m build
|
|
24
24
|
- name: Store the distribution packages
|
|
25
|
-
uses: actions/upload-artifact@
|
|
25
|
+
uses: actions/upload-artifact@v6
|
|
26
26
|
with:
|
|
27
27
|
name: python-package-distributions
|
|
28
28
|
path: dist/
|
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
|
|
43
43
|
steps:
|
|
44
44
|
- name: Download all the dists
|
|
45
|
-
uses: actions/download-artifact@
|
|
45
|
+
uses: actions/download-artifact@v7
|
|
46
46
|
with:
|
|
47
47
|
name: python-package-distributions
|
|
48
48
|
path: dist/
|
|
@@ -63,12 +63,12 @@ jobs:
|
|
|
63
63
|
|
|
64
64
|
steps:
|
|
65
65
|
- name: Download all the dists
|
|
66
|
-
uses: actions/download-artifact@
|
|
66
|
+
uses: actions/download-artifact@v7
|
|
67
67
|
with:
|
|
68
68
|
name: python-package-distributions
|
|
69
69
|
path: dist/
|
|
70
70
|
- name: Sign the dists with Sigstore
|
|
71
|
-
uses: sigstore/gh-action-sigstore-python@
|
|
71
|
+
uses: sigstore/gh-action-sigstore-python@v3.2.0
|
|
72
72
|
with:
|
|
73
73
|
inputs: >-
|
|
74
74
|
./dist/*.tar.gz
|
|
@@ -9,18 +9,18 @@ jobs:
|
|
|
9
9
|
tox:
|
|
10
10
|
strategy:
|
|
11
11
|
matrix:
|
|
12
|
-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
|
|
12
|
+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
13
13
|
os: [windows-latest, ubuntu-latest]
|
|
14
14
|
|
|
15
15
|
runs-on: ${{ matrix.os }}
|
|
16
16
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
18
|
-
- uses: actions/setup-python@
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
|
+
- uses: actions/setup-python@v6
|
|
19
19
|
with:
|
|
20
20
|
python-version: ${{ matrix.python-version }}
|
|
21
21
|
allow-prereleases: true
|
|
22
22
|
- name: Cache multiple paths
|
|
23
|
-
uses: actions/cache@
|
|
23
|
+
uses: actions/cache@v5
|
|
24
24
|
with:
|
|
25
25
|
path: |
|
|
26
26
|
~/.cache/pip
|
|
@@ -31,3 +31,4 @@ jobs:
|
|
|
31
31
|
run: python -m pip install --upgrade tox virtualenv setuptools pip
|
|
32
32
|
- name: run-tox
|
|
33
33
|
run: tox -e py
|
|
34
|
+
- run: pipx run auto-walrus -h
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
repos:
|
|
2
2
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
3
|
# Ruff version.
|
|
4
|
-
rev: 'v0.
|
|
4
|
+
rev: 'v0.9.2'
|
|
5
5
|
hooks:
|
|
6
6
|
# Run the formatter.
|
|
7
7
|
- id: ruff-format
|
|
@@ -9,13 +9,13 @@ repos:
|
|
|
9
9
|
- id: ruff
|
|
10
10
|
args: [--fix]
|
|
11
11
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
12
|
-
rev: 'v1.
|
|
12
|
+
rev: 'v1.14.1'
|
|
13
13
|
hooks:
|
|
14
14
|
- id: mypy
|
|
15
15
|
additional_dependencies: [pytest]
|
|
16
16
|
exclude: utils
|
|
17
17
|
- repo: https://github.com/codespell-project/codespell
|
|
18
|
-
rev: 'v2.
|
|
18
|
+
rev: 'v2.3.0'
|
|
19
19
|
hooks:
|
|
20
20
|
- id: codespell
|
|
21
21
|
files: \.(py|rst|md)$
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: auto-walrus
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Automatically apply the awesome walrus operator
|
|
5
5
|
Project-URL: Homepage, https://github.com/MarcoGorelli/auto-walrus
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/MarcoGorelli/auto-walrus
|
|
@@ -45,7 +45,7 @@ Sample `.pre-commit-config.yaml`:
|
|
|
45
45
|
|
|
46
46
|
```yaml
|
|
47
47
|
- repo: https://github.com/MarcoGorelli/auto-walrus
|
|
48
|
-
rev: 0.
|
|
48
|
+
rev: 0.4.0
|
|
49
49
|
hooks:
|
|
50
50
|
- id: auto-walrus
|
|
51
51
|
```
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import argparse
|
|
4
4
|
import ast
|
|
5
|
+
import dataclasses
|
|
5
6
|
import os
|
|
6
7
|
import pathlib
|
|
7
8
|
import re
|
|
@@ -30,6 +31,12 @@ EXCLUDES = (
|
|
|
30
31
|
)
|
|
31
32
|
|
|
32
33
|
|
|
34
|
+
@dataclasses.dataclass
|
|
35
|
+
class Config:
|
|
36
|
+
line_length: int
|
|
37
|
+
unsafe: bool = False
|
|
38
|
+
|
|
39
|
+
|
|
33
40
|
def name_lineno_coloffset_iterable(
|
|
34
41
|
tokens: Iterable[Token],
|
|
35
42
|
) -> list[tuple[str, int, int]]:
|
|
@@ -193,6 +200,7 @@ def related_vars_are_unused(
|
|
|
193
200
|
|
|
194
201
|
def visit_function_def(
|
|
195
202
|
node: ast.FunctionDef,
|
|
203
|
+
config: Config,
|
|
196
204
|
) -> list[tuple[Token, Token]]:
|
|
197
205
|
names = set()
|
|
198
206
|
assignments: set[Token] = set()
|
|
@@ -204,7 +212,7 @@ def visit_function_def(
|
|
|
204
212
|
related_vars: dict[str, list[Token]] = {}
|
|
205
213
|
in_body_vars: dict[Token, set[Token]] = {}
|
|
206
214
|
|
|
207
|
-
for _node in node.body:
|
|
215
|
+
for _node in ast.walk(node) if config.unsafe else node.body:
|
|
208
216
|
if isinstance(_node, ast.Assign):
|
|
209
217
|
process_assign(_node, assignments, related_vars)
|
|
210
218
|
elif isinstance(_node, ast.If):
|
|
@@ -255,7 +263,7 @@ def visit_function_def(
|
|
|
255
263
|
|
|
256
264
|
def auto_walrus(
|
|
257
265
|
content: str,
|
|
258
|
-
|
|
266
|
+
config: Config,
|
|
259
267
|
) -> str | None:
|
|
260
268
|
lines = content.splitlines()
|
|
261
269
|
try:
|
|
@@ -266,7 +274,7 @@ def auto_walrus(
|
|
|
266
274
|
walruses = []
|
|
267
275
|
for node in ast.walk(tree):
|
|
268
276
|
if isinstance(node, ast.FunctionDef):
|
|
269
|
-
walruses.extend(visit_function_def(node))
|
|
277
|
+
walruses.extend(visit_function_def(node, config))
|
|
270
278
|
lines_to_remove = []
|
|
271
279
|
walruses = sorted(walruses, key=lambda x: (-x[1][1], -x[1][2]))
|
|
272
280
|
|
|
@@ -290,13 +298,13 @@ def auto_walrus(
|
|
|
290
298
|
line_with_walrus = left_bit + replace + right_bit
|
|
291
299
|
else:
|
|
292
300
|
line_with_walrus = left_bit + "(" + replace + ")" + right_bit
|
|
293
|
-
if len(line_with_walrus) > line_length:
|
|
301
|
+
if len(line_with_walrus) > config.line_length:
|
|
294
302
|
# don't rewrite if it would split over multiple lines
|
|
295
303
|
continue
|
|
296
304
|
# replace assignment
|
|
297
305
|
line_without_assignment = (
|
|
298
|
-
f"{lines[_assignment[1]-1][:_assignment[2]]}"
|
|
299
|
-
f"{lines[_assignment[1]-1][_assignment[4]:]}"
|
|
306
|
+
f"{lines[_assignment[1] - 1][: _assignment[2]]}"
|
|
307
|
+
f"{lines[_assignment[1] - 1][_assignment[4] :]}"
|
|
300
308
|
)
|
|
301
309
|
if (ENDS_WITH_COMMENT.search(lines[_assignment[1] - 1]) is not None) or (
|
|
302
310
|
ENDS_WITH_COMMENT.search(lines[_if_statement[1] - 1]) is not None
|
|
@@ -348,7 +356,7 @@ def _get_config(paths: list[pathlib.Path]) -> dict[str, Any]:
|
|
|
348
356
|
|
|
349
357
|
def main(argv: Sequence[str] | None = None) -> int: # pragma: no cover
|
|
350
358
|
parser = argparse.ArgumentParser()
|
|
351
|
-
parser.add_argument("paths", nargs="
|
|
359
|
+
parser.add_argument("paths", nargs="+", metavar="path")
|
|
352
360
|
parser.add_argument(
|
|
353
361
|
"--files",
|
|
354
362
|
help="Regex pattern with which to match files to include",
|
|
@@ -361,18 +369,24 @@ def main(argv: Sequence[str] | None = None) -> int: # pragma: no cover
|
|
|
361
369
|
required=False,
|
|
362
370
|
default=r"^$",
|
|
363
371
|
)
|
|
372
|
+
parser.add_argument(
|
|
373
|
+
"--unsafe",
|
|
374
|
+
action="store_true",
|
|
375
|
+
help="Also process if statements inside other blocks (like for loops)",
|
|
376
|
+
)
|
|
364
377
|
# black formatter's default
|
|
365
378
|
parser.add_argument("--line-length", type=int, default=88)
|
|
366
379
|
args = parser.parse_args(argv)
|
|
367
380
|
paths = [pathlib.Path(path).resolve() for path in args.paths]
|
|
368
381
|
|
|
369
382
|
# Update defaults from pyproject.toml if present
|
|
370
|
-
|
|
371
|
-
parser.set_defaults(**
|
|
383
|
+
defaults = {k.replace("-", "_"): v for k, v in _get_config(paths).items()}
|
|
384
|
+
parser.set_defaults(**defaults)
|
|
372
385
|
args = parser.parse_args(argv)
|
|
373
386
|
|
|
374
387
|
ret = 0
|
|
375
388
|
|
|
389
|
+
config = Config(line_length=args.line_length, unsafe=args.unsafe)
|
|
376
390
|
for path in paths:
|
|
377
391
|
if path.is_file():
|
|
378
392
|
filepaths = iter((path,))
|
|
@@ -382,7 +396,7 @@ def main(argv: Sequence[str] | None = None) -> int: # pragma: no cover
|
|
|
382
396
|
for p in path.rglob("*")
|
|
383
397
|
if re.search(args.files, p.as_posix(), re.VERBOSE)
|
|
384
398
|
and not re.search(args.exclude, p.as_posix(), re.VERBOSE)
|
|
385
|
-
and not re.search(EXCLUDES, p.as_posix())
|
|
399
|
+
and not re.search(EXCLUDES, p.relative_to(path).as_posix())
|
|
386
400
|
and p.suffix == ".py"
|
|
387
401
|
)
|
|
388
402
|
|
|
@@ -392,10 +406,7 @@ def main(argv: Sequence[str] | None = None) -> int: # pragma: no cover
|
|
|
392
406
|
content = fd.read()
|
|
393
407
|
except UnicodeDecodeError:
|
|
394
408
|
continue
|
|
395
|
-
new_content = auto_walrus(
|
|
396
|
-
content,
|
|
397
|
-
line_length=args.line_length,
|
|
398
|
-
)
|
|
409
|
+
new_content = auto_walrus(content, config)
|
|
399
410
|
if new_content is not None and content != new_content:
|
|
400
411
|
sys.stdout.write(f"Rewriting {filepath}\n")
|
|
401
412
|
with open(filepath, "w", encoding="utf-8") as fd:
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "auto-walrus"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.4.0"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Marco Gorelli", email="33491632+MarcoGorelli@users.noreply.github.com" },
|
|
10
10
|
]
|
|
@@ -80,7 +80,7 @@ filterwarnings = [
|
|
|
80
80
|
'ignore:distutils Version classes are deprecated:DeprecationWarning',
|
|
81
81
|
]
|
|
82
82
|
xfail_strict = true
|
|
83
|
-
markers = ["config_content"]
|
|
83
|
+
markers = ["config_content", "project_dir_name"]
|
|
84
84
|
|
|
85
85
|
[tool.coverage.run]
|
|
86
86
|
plugins = ["covdefaults"]
|
|
@@ -7,6 +7,7 @@ from typing import Tuple
|
|
|
7
7
|
|
|
8
8
|
import pytest
|
|
9
9
|
|
|
10
|
+
from auto_walrus import Config
|
|
10
11
|
from auto_walrus import auto_walrus
|
|
11
12
|
from auto_walrus import main
|
|
12
13
|
|
|
@@ -15,12 +16,12 @@ from auto_walrus import main
|
|
|
15
16
|
("src", "expected"),
|
|
16
17
|
[
|
|
17
18
|
(
|
|
18
|
-
"def foo():\n
|
|
19
|
-
"def foo():\n
|
|
19
|
+
"def foo():\n a = 0\n if a:\n print(a)\n",
|
|
20
|
+
"def foo():\n if (a := 0):\n print(a)\n",
|
|
20
21
|
),
|
|
21
22
|
(
|
|
22
|
-
"def foo():\n
|
|
23
|
-
"def foo():\n
|
|
23
|
+
"def foo():\n a = 0\n if a > 3:\n print(a)\n",
|
|
24
|
+
"def foo():\n if (a := 0) > 3:\n print(a)\n",
|
|
24
25
|
),
|
|
25
26
|
(
|
|
26
27
|
"def foo():\n"
|
|
@@ -29,11 +30,7 @@ from auto_walrus import main
|
|
|
29
30
|
" print(a)\n"
|
|
30
31
|
" else:\n"
|
|
31
32
|
" pass\n",
|
|
32
|
-
"def foo():\n"
|
|
33
|
-
" if (a := 0):\n"
|
|
34
|
-
" print(a)\n"
|
|
35
|
-
" else:\n"
|
|
36
|
-
" pass\n",
|
|
33
|
+
"def foo():\n if (a := 0):\n print(a)\n else:\n pass\n",
|
|
37
34
|
),
|
|
38
35
|
(
|
|
39
36
|
"def foo():\n"
|
|
@@ -49,24 +46,20 @@ from auto_walrus import main
|
|
|
49
46
|
" print(a)\n",
|
|
50
47
|
),
|
|
51
48
|
(
|
|
52
|
-
"def foo():\n"
|
|
53
|
-
" a
|
|
54
|
-
" print(0)\n"
|
|
55
|
-
" if a:\n"
|
|
56
|
-
" print(a)\n",
|
|
57
|
-
"def foo():\n" " print(0)\n" " if (a := 0):\n" " print(a)\n",
|
|
49
|
+
"def foo():\n a = 0\n print(0)\n if a:\n print(a)\n",
|
|
50
|
+
"def foo():\n print(0)\n if (a := 0):\n print(a)\n",
|
|
58
51
|
),
|
|
59
52
|
(
|
|
60
|
-
"def foo():\n
|
|
61
|
-
"def foo():\n
|
|
53
|
+
"def foo():\n a = 0\n if (a):\n print(a)\n",
|
|
54
|
+
"def foo():\n if (a := 0):\n print(a)\n",
|
|
62
55
|
),
|
|
63
56
|
(
|
|
64
|
-
"def foo():\n
|
|
65
|
-
"def foo():\n
|
|
57
|
+
"def foo():\n b = 0; a = 0\n if a:\n print(a)\n",
|
|
58
|
+
"def foo():\n b = 0; \n if (a := 0):\n print(a)\n",
|
|
66
59
|
),
|
|
67
60
|
(
|
|
68
|
-
"def foo():\n
|
|
69
|
-
"def foo():\n
|
|
61
|
+
"def foo():\n a = 0\n if a:\n print(a)",
|
|
62
|
+
"def foo():\n if (a := 0):\n print(a)",
|
|
70
63
|
),
|
|
71
64
|
(
|
|
72
65
|
"def foo():\n"
|
|
@@ -97,7 +90,7 @@ from auto_walrus import main
|
|
|
97
90
|
],
|
|
98
91
|
)
|
|
99
92
|
def test_rewrite(src: str, expected: str) -> None:
|
|
100
|
-
ret = auto_walrus(src, 88)
|
|
93
|
+
ret = auto_walrus(src, Config(line_length=88))
|
|
101
94
|
assert ret == expected
|
|
102
95
|
|
|
103
96
|
|
|
@@ -110,43 +103,54 @@ def test_rewrite(src: str, expected: str) -> None:
|
|
|
110
103
|
" b[0] = 1\n"
|
|
111
104
|
" if a:\n"
|
|
112
105
|
" print(a)\n",
|
|
113
|
-
"def foo():\n
|
|
114
|
-
"def foo():\n
|
|
115
|
-
"def foo():\n
|
|
106
|
+
"def foo():\n a = 1\n a = 2\n if a:\n print(a)\n",
|
|
107
|
+
"def foo():\n a = (\n 0,)\n if a:\n print(a)\n",
|
|
108
|
+
"def foo():\n a = (b==True)\n if a:\n print(a)\n",
|
|
116
109
|
"def foo():\n"
|
|
117
110
|
" a = thequickbrownfoxjumpsoverthelazydog\n"
|
|
118
111
|
" if a:\n"
|
|
119
112
|
" print(a)\n",
|
|
120
|
-
"def foo():\n
|
|
121
|
-
"def foo():\n
|
|
122
|
-
"n = 10\
|
|
123
|
-
"a = 0\
|
|
124
|
-
"def foo():\n
|
|
113
|
+
"def foo():\n a = 0 # no-walrus\n if a:\n print(a)\n",
|
|
114
|
+
"def foo():\n a = 0\n if a: # no-walrus\n print(a)\n",
|
|
115
|
+
"n = 10\nif foo(a := n+1):\n print(n)\n",
|
|
116
|
+
"a = 0\nif False and a:\n print(a)\nelse:\n print(a)\n",
|
|
117
|
+
"def foo():\n a = 1\n if a:\n print(a)\n a = 2\n",
|
|
125
118
|
"def foo():\n"
|
|
126
119
|
" n = 10\n"
|
|
127
120
|
" if True:\n"
|
|
128
121
|
" pass\n"
|
|
129
122
|
" elif foo(a := n+1):\n"
|
|
130
123
|
" print(n)\n",
|
|
131
|
-
"def foo():\n"
|
|
132
|
-
" n = 10\n"
|
|
133
|
-
" if n > np.sin(foo.bar.quox):\n"
|
|
134
|
-
" print(n)\n",
|
|
135
|
-
"def foo():\n" " n = 10\n" " if True or n > 3:\n" " print(n)\n",
|
|
124
|
+
"def foo():\n n = 10\n if n > np.sin(foo.bar.quox):\n print(n)\n",
|
|
125
|
+
"def foo():\n n = 10\n if True or n > 3:\n print(n)\n",
|
|
136
126
|
],
|
|
137
127
|
)
|
|
138
128
|
def test_noop(src: str) -> None:
|
|
139
|
-
ret = auto_walrus(src, 40)
|
|
129
|
+
ret = auto_walrus(src, Config(line_length=40))
|
|
140
130
|
assert ret is None
|
|
141
131
|
|
|
142
132
|
|
|
133
|
+
@pytest.mark.parametrize(
|
|
134
|
+
("src", "expected"),
|
|
135
|
+
[
|
|
136
|
+
(
|
|
137
|
+
'def foo(data):\n if True:\n foo = data.get("blah")\n if foo:\n return foo\n return data',
|
|
138
|
+
'def foo(data):\n if True:\n if (foo := data.get("blah")):\n return foo\n return data',
|
|
139
|
+
),
|
|
140
|
+
],
|
|
141
|
+
)
|
|
142
|
+
def test_rewrite_unsafe(src: str, expected: str) -> None:
|
|
143
|
+
ret = auto_walrus(src, Config(line_length=88, unsafe=True))
|
|
144
|
+
assert ret == expected
|
|
145
|
+
|
|
146
|
+
|
|
143
147
|
ProjectDirT = Tuple[pathlib.Path, List[pathlib.Path]]
|
|
144
148
|
|
|
145
|
-
SRC_ORIG = "def foo():\n
|
|
146
|
-
SRC_CHANGED = "def foo():\n
|
|
149
|
+
SRC_ORIG = "def foo():\n a = 0\n if a:\n print(a)\n"
|
|
150
|
+
SRC_CHANGED = "def foo():\n if (a := 0):\n print(a)\n"
|
|
147
151
|
|
|
148
152
|
|
|
149
|
-
@pytest.fixture
|
|
153
|
+
@pytest.fixture
|
|
150
154
|
def project_dir(request: Any, tmp_path: pathlib.Path) -> ProjectDirT:
|
|
151
155
|
# tmp_path will be the root of the project, e.g.:
|
|
152
156
|
# tmp_path
|
|
@@ -158,6 +162,10 @@ def project_dir(request: Any, tmp_path: pathlib.Path) -> ProjectDirT:
|
|
|
158
162
|
# | └── c.py
|
|
159
163
|
# └── pyproject.toml
|
|
160
164
|
|
|
165
|
+
if project_dir_name := request.node.get_closest_marker("project_dir_name"):
|
|
166
|
+
tmp_path = tmp_path / project_dir_name.args[0]
|
|
167
|
+
tmp_path.mkdir(parents=True)
|
|
168
|
+
|
|
161
169
|
if config_content := request.node.get_closest_marker("config_content"):
|
|
162
170
|
(tmp_path / "pyproject.toml").write_text(config_content.args[0])
|
|
163
171
|
|
|
@@ -173,7 +181,7 @@ def project_dir(request: Any, tmp_path: pathlib.Path) -> ProjectDirT:
|
|
|
173
181
|
return tmp_path, python_files
|
|
174
182
|
|
|
175
183
|
|
|
176
|
-
PROJECT_CONFIG_EXCLUDE_A =
|
|
184
|
+
PROJECT_CONFIG_EXCLUDE_A = '[tool.auto-walrus]\nexclude = "/a"\n'
|
|
177
185
|
|
|
178
186
|
|
|
179
187
|
@pytest.mark.config_content(PROJECT_CONFIG_EXCLUDE_A)
|
|
@@ -209,3 +217,18 @@ def test_config_file_missing(project_dir: ProjectDirT) -> None:
|
|
|
209
217
|
main([str(project_root)])
|
|
210
218
|
for file in files:
|
|
211
219
|
assert file.read_text() == SRC_CHANGED, f"Unexpected result for {file}"
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@pytest.mark.project_dir_name("build/zoop")
|
|
223
|
+
def test_project_in_subdirectory_that_would_be_ignored(project_dir: ProjectDirT) -> None:
|
|
224
|
+
project_root, files = project_dir
|
|
225
|
+
main([str(project_root)])
|
|
226
|
+
for file in files:
|
|
227
|
+
assert file.read_text() == SRC_CHANGED, f"Unexpected result for {file}"
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def test_complains_when_no_paths(capsys: pytest.CaptureFixture[str]) -> None:
|
|
231
|
+
with pytest.raises(SystemExit) as ei:
|
|
232
|
+
main([])
|
|
233
|
+
assert ei.value.code == 2
|
|
234
|
+
assert "the following arguments are required" in capsys.readouterr().err
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|