Skip to content

Commit 4a344ed

Browse files
positamawillcocksonhauntsaninja
authored andcommitted
Preserves interpreting multi-line strings as a single value for exclude in TOML files (#11828)
Multiple regexes are expressed as a sequence. Fixes #11825. Co-authored-by: Matthew W <[email protected]> Co-authored-by: Shantanu <[email protected]>
1 parent d4bda9a commit 4a344ed

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

docs/source/config_file.rst

+35
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,35 @@ section of the command line docs.
214214

215215
This option may only be set in the global section (``[mypy]``).
216216

217+
.. note::
218+
219+
Note that the TOML equivalent differs slightly. It can be either a single string
220+
(including a multi-line string) -- which is treated as a single regular
221+
expression -- or an array of such strings. The following TOML examples are
222+
equivalent to the above INI example.
223+
224+
Array of strings:
225+
226+
.. code-block:: toml
227+
228+
[tool.mypy]
229+
exclude = [
230+
"^file1\\.py$", # TOML's double-quoted strings require escaping backslashes
231+
'^file2\.py$', # but TOML's single-quoted strings do not
232+
]
233+
234+
A single, multi-line string:
235+
236+
.. code-block:: toml
237+
238+
[tool.mypy]
239+
exclude = '''(?x)(
240+
^file1\.py$
241+
|^file2\.py$,
242+
)'''
243+
244+
See :ref:`using-a-pyproject-toml`.
245+
217246
.. confval:: namespace_packages
218247

219248
:type: boolean
@@ -907,6 +936,8 @@ These options may only be set in the global section (``[mypy]``).
907936
Controls how much debug output will be generated. Higher numbers are more verbose.
908937

909938

939+
.. _using-a-pyproject-toml:
940+
910941
Using a pyproject.toml file
911942
***************************
912943

@@ -965,6 +996,10 @@ of your repo (or append it to the end of an existing ``pyproject.toml`` file) an
965996
python_version = "2.7"
966997
warn_return_any = true
967998
warn_unused_configs = true
999+
exclude = [
1000+
'^file1\.py$', # TOML literal string (single-quotes, no escaping necessary)
1001+
"^file2\\.py$", # TOML basic string (double-quotes, backslash and other characters need escaping)
1002+
]
9681003
9691004
# mypy per-module options:
9701005

mypy/config_parser.py

+7
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ def expand_path(path: str) -> str:
5757
return os.path.expandvars(os.path.expanduser(path))
5858

5959

60+
def str_or_array_as_list(v: Union[str, Sequence[str]]) -> List[str]:
61+
if isinstance(v, str):
62+
return [v.strip()] if v.strip() else []
63+
return [p.strip() for p in v if p.strip()]
64+
65+
6066
def split_and_match_files_list(paths: Sequence[str]) -> List[str]:
6167
"""Take a list of files/directories (with support for globbing through the glob library).
6268
@@ -143,6 +149,7 @@ def check_follow_imports(choice: str) -> str:
143149
'disable_error_code': try_split,
144150
'enable_error_code': try_split,
145151
'package_root': try_split,
152+
'exclude': str_or_array_as_list,
146153
})
147154

148155

test-data/unit/cmdline.pyproject.test

+45
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,48 @@ def g(a: int) -> int:
8080
[out]
8181
pyproject.toml: toml config file contains [[tool.mypy.overrides]] sections with conflicting values. Module 'x' has two different values for 'disallow_untyped_defs'
8282
== Return code: 0
83+
84+
[case testMultilineLiteralExcludePyprojectTOML]
85+
# cmd: mypy x
86+
[file pyproject.toml]
87+
\[tool.mypy]
88+
exclude = '''(?x)(
89+
(^|/)[^/]*skipme_\.py$
90+
|(^|/)_skipme[^/]*\.py$
91+
)'''
92+
[file x/__init__.py]
93+
i: int = 0
94+
[file x/_skipme_please.py]
95+
This isn't even syntatically valid!
96+
[file x/please_skipme_.py]
97+
Neither is this!
98+
99+
[case testMultilineBasicExcludePyprojectTOML]
100+
# cmd: mypy x
101+
[file pyproject.toml]
102+
\[tool.mypy]
103+
exclude = """(?x)(
104+
(^|/)[^/]*skipme_\\.py$
105+
|(^|/)_skipme[^/]*\\.py$
106+
)"""
107+
[file x/__init__.py]
108+
i: int = 0
109+
[file x/_skipme_please.py]
110+
This isn't even syntatically valid!
111+
[file x/please_skipme_.py]
112+
Neither is this!
113+
114+
[case testSequenceExcludePyprojectTOML]
115+
# cmd: mypy x
116+
[file pyproject.toml]
117+
\[tool.mypy]
118+
exclude = [
119+
'(^|/)[^/]*skipme_\.py$', # literal (no escaping)
120+
"(^|/)_skipme[^/]*\\.py$", # basic (backslash needs escaping)
121+
]
122+
[file x/__init__.py]
123+
i: int = 0
124+
[file x/_skipme_please.py]
125+
This isn't even syntatically valid!
126+
[file x/please_skipme_.py]
127+
Neither is this!

0 commit comments

Comments
 (0)