Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserves interpreting multi-line strings as a single value for exclude in TOML files #11828

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/source/config_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,35 @@ section of the command line docs.

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

.. note::

Note that the TOML equivalent differs slightly. It can be either a single string
(including a multi-line string) -- which is treated as a single regular
expression -- or an array of such strings. The following TOML examples are
equivalent to the above INI example.

Array of strings:

.. code-block:: toml

[tool.mypy]
exclude = [
"^file1\\.py$", # TOML's double-quoted strings require escaping backslashes
'^file2\.py$', # but TOML's single-quoted strings do not
]
hauntsaninja marked this conversation as resolved.
Show resolved Hide resolved

A single, multi-line string:

.. code-block:: toml

[tool.mypy]
exclude = '''(?x)(
^file1\.py$
|^file2\.py$,
)'''

See :ref:`using-a-pyproject-toml`.

.. confval:: namespace_packages

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


.. _using-a-pyproject-toml:

Using a pyproject.toml file
***************************

Expand Down Expand Up @@ -965,6 +996,10 @@ of your repo (or append it to the end of an existing ``pyproject.toml`` file) an
python_version = "2.7"
warn_return_any = true
warn_unused_configs = true
exclude = [
'^file1\.py$', # TOML literal string (single-quotes, no escaping necessary)
"^file2\\.py$", # TOML basic string (double-quotes, backslash and other characters need escaping)
]
hauntsaninja marked this conversation as resolved.
Show resolved Hide resolved

# mypy per-module options:

Expand Down
7 changes: 7 additions & 0 deletions mypy/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ def expand_path(path: str) -> str:
return os.path.expandvars(os.path.expanduser(path))


def str_or_array_as_list(v: Union[str, Sequence[str]]) -> List[str]:
if isinstance(v, str):
return [v.strip()] if v.strip() else []
return [p.strip() for p in v if p.strip()]


def split_and_match_files_list(paths: Sequence[str]) -> List[str]:
"""Take a list of files/directories (with support for globbing through the glob library).

Expand Down Expand Up @@ -143,6 +149,7 @@ def check_follow_imports(choice: str) -> str:
'disable_error_code': try_split,
'enable_error_code': try_split,
'package_root': try_split,
'exclude': str_or_array_as_list,
})


Expand Down
45 changes: 45 additions & 0 deletions test-data/unit/cmdline.pyproject.test
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,48 @@ def g(a: int) -> int:
[out]
pyproject.toml: toml config file contains [[tool.mypy.overrides]] sections with conflicting values. Module 'x' has two different values for 'disallow_untyped_defs'
== Return code: 0

[case testMultilineLiteralExcludePyprojectTOML]
# cmd: mypy x
[file pyproject.toml]
\[tool.mypy]
exclude = '''(?x)(
(^|/)[^/]*skipme_\.py$
|(^|/)_skipme[^/]*\.py$
)'''
[file x/__init__.py]
i: int = 0
[file x/_skipme_please.py]
This isn't even syntatically valid!
[file x/please_skipme_.py]
Neither is this!

[case testMultilineBasicExcludePyprojectTOML]
# cmd: mypy x
[file pyproject.toml]
\[tool.mypy]
exclude = """(?x)(
(^|/)[^/]*skipme_\\.py$
|(^|/)_skipme[^/]*\\.py$
)"""
[file x/__init__.py]
i: int = 0
[file x/_skipme_please.py]
This isn't even syntatically valid!
[file x/please_skipme_.py]
Neither is this!

[case testSequenceExcludePyprojectTOML]
# cmd: mypy x
[file pyproject.toml]
\[tool.mypy]
exclude = [
'(^|/)[^/]*skipme_\.py$', # literal (no escaping)
"(^|/)_skipme[^/]*\\.py$", # basic (backslash needs escaping)
]
[file x/__init__.py]
i: int = 0
[file x/_skipme_please.py]
This isn't even syntatically valid!
[file x/please_skipme_.py]
Neither is this!