Skip to content

Commit 321a0e6

Browse files
committed
Test and fix trailing commas in many multiline string options in pyproject.toml
1 parent 5ee02cd commit 321a0e6

File tree

3 files changed

+153
-3
lines changed

3 files changed

+153
-3
lines changed

mypy/config_parser.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,12 @@ def parse_version(v: str | float) -> tuple[int, int]:
5555
def try_split(v: str | Sequence[str], split_regex: str = "[,]") -> list[str]:
5656
"""Split and trim a str or list of str into a list of str"""
5757
if isinstance(v, str):
58-
return [p.strip() for p in re.split(split_regex, v)]
59-
60-
return [p.strip() for p in v]
58+
items = [p.strip() for p in re.split(split_regex, v)]
59+
else:
60+
items = [p.strip() for p in v]
61+
if items and items[-1] == "":
62+
items.pop(-1)
63+
return items
6164

6265

6366
def validate_codes(codes: list[str]) -> list[str]:

test-data/unit/cmdline.pyproject.test

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,118 @@ Neither is this!
133133
description = "Factory ⸻ A code generator 🏭"
134134
\[tool.mypy]
135135
[file x.py]
136+
137+
[case testPyprojectFilesTrailingComma]
138+
# cmd: mypy
139+
[file pyproject.toml]
140+
\[tool.mypy]
141+
files = """
142+
a.py,
143+
b.py,
144+
"""
145+
[file a.py]
146+
x: str = 'x' # ok
147+
[file b.py]
148+
y: int = 'y' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
149+
[file c.py]
150+
# This should not trigger any errors, because it is not included:
151+
z: int = 'z'
152+
[out]
153+
154+
[case testPyprojectPluginsTrailingComma]
155+
# cmd: mypy .
156+
[file pyproject.toml]
157+
\[tool.mypy]
158+
plugins = """
159+
<ROOT>/test-data/unit/plugins/function_sig_hook.py,
160+
<ROOT>/test-data/unit/plugins/method_in_decorator.py,
161+
"""
162+
[out]
163+
164+
[case testPyprojectAlwaysTrueTrailingComma]
165+
# cmd: mypy .
166+
[file pyproject.toml]
167+
\[tool.mypy]
168+
always_true = """
169+
FLAG_A,
170+
FLAG_B,
171+
"""
172+
[file a.py]
173+
FLAG_A = False
174+
FLAG_B = False
175+
if not FLAG_A: # unreachable
176+
x: int = 'x'
177+
if not FLAG_B: # unreachable
178+
y: int = 'y'
179+
180+
[case testPyprojectAlwaysFalseTrailingComma]
181+
# cmd: mypy .
182+
[file pyproject.toml]
183+
\[tool.mypy]
184+
always_false = """
185+
FLAG_A,
186+
FLAG_B,
187+
"""
188+
[file a.py]
189+
FLAG_A = True
190+
FLAG_B = True
191+
if FLAG_A: # unreachable
192+
x: int = 'x'
193+
if FLAG_B: # unreachable
194+
y: int = 'y'
195+
196+
[case testPyprojectEnableErrorCodeTrailingComma]
197+
# cmd: mypy .
198+
[file pyproject.toml]
199+
\[tool.mypy]
200+
enable_error_code = """
201+
redundant-expr,
202+
ignore-without-code,
203+
"""
204+
[file a.py]
205+
1 + 'a' # type: ignore # E: "type: ignore" comment without error code (consider "type: ignore[operator]" instead)
206+
207+
[case testPyprojectDisableErrorCodeTrailingComma]
208+
# cmd: mypy .
209+
[file pyproject.toml]
210+
\[tool.mypy]
211+
disable_error_code = """
212+
operator,
213+
import,
214+
"""
215+
[file a.py]
216+
1 + 'a'
217+
218+
[case testPyprojectModulesTrailingComma]
219+
# cmd: mypy
220+
[file pyproject.toml]
221+
\[tool.mypy]
222+
modules = """
223+
a,
224+
b,
225+
"""
226+
[file a.py]
227+
x: str = 'x' # ok
228+
[file b.py]
229+
y: int = 'y' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
230+
[file c.py]
231+
# This should not trigger any errors, because it is not included:
232+
z: int = 'z'
233+
[out]
234+
235+
[case testPyprojectPackagesTrailingComma]
236+
# cmd: mypy
237+
[file pyproject.toml]
238+
\[tool.mypy]
239+
packages = """
240+
a,
241+
b,
242+
"""
243+
[file a/__init__.py]
244+
x: str = 'x' # ok
245+
[file b/__init__.py]
246+
y: int = 'y' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
247+
[file c/__init__.py]
248+
# This should not trigger any errors, because it is not included:
249+
z: int = 'z'
250+
[out]

test-data/unit/cmdline.test

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,38 @@ always_true =
13421342
MY_VAR,
13431343
[out]
13441344

1345+
[case testCmdlineCfgModulesTrailingComma]
1346+
# cmd: mypy
1347+
[file mypy.ini]
1348+
\[mypy]
1349+
modules =
1350+
a,
1351+
b,
1352+
[file a.py]
1353+
x: str = 'x' # ok
1354+
[file b.py]
1355+
y: int = 'y' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
1356+
[file c.py]
1357+
# This should not trigger any errors, because it is not included:
1358+
z: int = 'z'
1359+
[out]
1360+
1361+
[case testCmdlineCfgPackagesTrailingComma]
1362+
# cmd: mypy
1363+
[file mypy.ini]
1364+
\[mypy]
1365+
packages =
1366+
a,
1367+
b,
1368+
[file a/__init__.py]
1369+
x: str = 'x' # ok
1370+
[file b/__init__.py]
1371+
y: int = 'y' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
1372+
[file c/__init__.py]
1373+
# This should not trigger any errors, because it is not included:
1374+
z: int = 'z'
1375+
[out]
1376+
13451377
[case testTypeVarTupleUnpackEnabled]
13461378
# cmd: mypy --enable-incomplete-feature=TypeVarTuple --enable-incomplete-feature=Unpack a.py
13471379
[file a.py]

0 commit comments

Comments
 (0)