From bbd5431551d39059c03d6fde72ea8c2686ef0440 Mon Sep 17 00:00:00 2001 From: Matt Bogosian Date: Wed, 22 Dec 2021 16:57:58 -0600 Subject: [PATCH 1/2] Allows for exclude as a multiline basic string in TOML files Multiple regexes are expressed as a sequence. Fixes #11825. --- docs/source/config_file.rst | 35 +++++++++++++++++++++ mypy/config_parser.py | 7 +++++ test-data/unit/cmdline.pyproject.test | 45 +++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index c34f23d9e169..17c892cb796e 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -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 + ] + + 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 @@ -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 *************************** @@ -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 single-quoted string (no escaping necessary) + "^file2\\.py$", # TOML double-quoted string (backslash needs escaping) + ] # mypy per-module options: diff --git a/mypy/config_parser.py b/mypy/config_parser.py index 24e61df0441c..4185179605c9 100644 --- a/mypy/config_parser.py +++ b/mypy/config_parser.py @@ -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). @@ -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, }) diff --git a/test-data/unit/cmdline.pyproject.test b/test-data/unit/cmdline.pyproject.test index 83f4745d0786..ea561ed164e7 100644 --- a/test-data/unit/cmdline.pyproject.test +++ b/test-data/unit/cmdline.pyproject.test @@ -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! From 57332df52d81e271d0cf0586081b1183567e4658 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 29 Dec 2021 15:26:37 -0600 Subject: [PATCH 2/2] Update docs/source/config_file.rst Co-authored-by: Matthew W --- docs/source/config_file.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/config_file.rst b/docs/source/config_file.rst index 17c892cb796e..c5d819a4d66c 100644 --- a/docs/source/config_file.rst +++ b/docs/source/config_file.rst @@ -997,8 +997,8 @@ of your repo (or append it to the end of an existing ``pyproject.toml`` file) an warn_return_any = true warn_unused_configs = true exclude = [ - '^file1\.py$', # TOML single-quoted string (no escaping necessary) - "^file2\\.py$", # TOML double-quoted string (backslash needs escaping) + '^file1\.py$', # TOML literal string (single-quotes, no escaping necessary) + "^file2\\.py$", # TOML basic string (double-quotes, backslash and other characters need escaping) ] # mypy per-module options: