Skip to content

Commit d2ab2e7

Browse files
authored
Allow trailing commas in ini configuration of multiline values (#14240)
Now these two samples are identical: ```ini [mypy] enable_error_code = truthy-bool, redundant-expr, unused-awaitable, ignore-without-code ``` and ```ini [mypy] enable_error_code = truthy-bool, redundant-expr, unused-awaitable, ignore-without-code, ``` I've covered some of the changed values, but not all (they are identical - no need to create so many slow tests). I've also checked `pyproject.toml`. It does not have this problem: it uses `[]` to create arrays, so no trailing commas are used there.
1 parent 924bc68 commit d2ab2e7

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

mypy/config_parser.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,15 @@ def check_follow_imports(choice: str) -> str:
137137
return choice
138138

139139

140+
def split_commas(value: str) -> list[str]:
141+
# Uses a bit smarter technique to allow last trailing comma
142+
# and to remove last `""` item from the split.
143+
items = value.split(",")
144+
if items and items[-1] == "":
145+
items.pop(-1)
146+
return items
147+
148+
140149
# For most options, the type of the default value set in options.py is
141150
# sufficient, and we don't have to do anything here. This table
142151
# exists to specify types for values initialized to None or container
@@ -151,13 +160,13 @@ def check_follow_imports(choice: str) -> str:
151160
"junit_xml": expand_path,
152161
"follow_imports": check_follow_imports,
153162
"no_site_packages": bool,
154-
"plugins": lambda s: [p.strip() for p in s.split(",")],
155-
"always_true": lambda s: [p.strip() for p in s.split(",")],
156-
"always_false": lambda s: [p.strip() for p in s.split(",")],
157-
"enable_incomplete_feature": lambda s: [p.strip() for p in s.split(",")],
158-
"disable_error_code": lambda s: validate_codes([p.strip() for p in s.split(",")]),
159-
"enable_error_code": lambda s: validate_codes([p.strip() for p in s.split(",")]),
160-
"package_root": lambda s: [p.strip() for p in s.split(",")],
163+
"plugins": lambda s: [p.strip() for p in split_commas(s)],
164+
"always_true": lambda s: [p.strip() for p in split_commas(s)],
165+
"always_false": lambda s: [p.strip() for p in split_commas(s)],
166+
"enable_incomplete_feature": lambda s: [p.strip() for p in split_commas(s)],
167+
"disable_error_code": lambda s: validate_codes([p.strip() for p in split_commas(s)]),
168+
"enable_error_code": lambda s: validate_codes([p.strip() for p in split_commas(s)]),
169+
"package_root": lambda s: [p.strip() for p in split_commas(s)],
161170
"cache_dir": expand_path,
162171
"python_executable": expand_path,
163172
"strict": bool,

test-data/unit/check-custom-plugin.test

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,15 @@ reveal_type(f()) # N: Revealed type is "builtins.int"
163163
\[mypy]
164164
plugins=<ROOT>/test-data/unit/plugins/customentry.py:register
165165

166+
[case testCustomPluginEntryPointFileTrailingComma]
167+
# flags: --config-file tmp/mypy.ini
168+
def f() -> str: ...
169+
reveal_type(f()) # N: Revealed type is "builtins.int"
170+
[file mypy.ini]
171+
\[mypy]
172+
plugins =
173+
<ROOT>/test-data/unit/plugins/customentry.py:register,
174+
166175
[case testCustomPluginEntryPoint]
167176
# flags: --config-file tmp/mypy.ini
168177
def f() -> str: ...

test-data/unit/cmdline.test

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,3 +1570,29 @@ foo.py:1: error: "int" not callable
15701570
1()
15711571
[out]
15721572
foo/m.py:1: error: "int" not callable
1573+
1574+
[case testCmdlineCfgEnableErrorCodeTrailingComma]
1575+
# cmd: mypy .
1576+
[file mypy.ini]
1577+
\[mypy]
1578+
enable_error_code =
1579+
truthy-bool,
1580+
redundant-expr,
1581+
[out]
1582+
1583+
[case testCmdlineCfgDisableErrorCodeTrailingComma]
1584+
# cmd: mypy .
1585+
[file mypy.ini]
1586+
\[mypy]
1587+
disable_error_code =
1588+
misc,
1589+
override,
1590+
[out]
1591+
1592+
[case testCmdlineCfgAlwaysTrueTrailingComma]
1593+
# cmd: mypy .
1594+
[file mypy.ini]
1595+
\[mypy]
1596+
always_true =
1597+
MY_VAR,
1598+
[out]

0 commit comments

Comments
 (0)