8000 Add --exclude by hauntsaninja · Pull Request #9992 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Add --exclude #9992

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

Merged
merged 22 commits into from
Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
use regexes for exclude
  • Loading branch information
hauntsaninja committed Feb 2, 2021
commit 7e92e9bdba8cfe9a9ce7e037b2effd6e70577b33
6 changes: 3 additions & 3 deletions docs/source/command_line.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ for full details, see :ref:`running-mypy`.

.. option:: --exclude

Asks mypy to exclude a given file name, directory name or subpath while
recursively discovering files to check. This flag may be repeated multiple
times.
A regular expression that matches file names 8000 , directory names and paths
which mypy should ignore while recursively discovering files to check.
Use forward slashes on all platforms.


Optional arguments
Expand Down
7 changes: 4 additions & 3 deletions docs/source/config_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,11 @@ section of the command line docs.

.. confval:: exclude

:type: comma-separated list of strings
:type: regular expression

A comma-separated list of file names, directory names or subpaths which mypy
should ignore while recursively discovering files to check.
A regular expression that matches file names, directory names and paths
which mypy should ignore while recursively discovering files to check.
Use forward slashes on all platforms.

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

Expand Down
1 change: 1 addition & 0 deletions mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2569,6 +2569,7 @@ def log_configuration(manager: BuildManager, sources: List[BuildSource]) -> None
("Current Executable", sys.executable),
("Cache Dir", manager.options.cache_dir),
("Compiled", str(not __file__.endswith(".py"))),
("Exclude", manager.options.exclude),
]

for conf_name, conf_value in configuration_vars:
Expand Down
1 change: 0 additions & 1 deletion mypy/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ def check_follow_imports(choice: str) -> str:
'custom_typing_module': str,
'custom_typeshed_dir': expand_path,
'mypy_path': lambda s: [expand_path(p.strip()) for p in re.split('[,:]', s)],
'exclude': lambda s: [expand_path(p.strip()) for p in s.split(",")],
'files': split_and_match_files,
'quickstart_file': expand_path,
'junit_xml': expand_path,
Expand Down
19 changes: 9 additions & 10 deletions mypy/find_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

import functools
import os
import re

from typing import List, Sequence, Set, Tuple, Optional
from typing_extensions import Final

from mypy.modulefinder import BuildSource, PYTHON_EXTENSIONS, mypy_path, matches_exclude_pattern
from mypy.modulefinder import BuildSource, PYTHON_EXTENSIONS, mypy_path
from mypy.fscache import FileSystemCache
from mypy.options import Options

Expand Down Expand Up @@ -103,16 +104,14 @@ def find_sources_in_dir(self, path: str) -> List[BuildSource]:
seen = set() # type: Set[str]
names = sorted(self.fscache.listdir(path), key=keyfunc)
for name in names:
# Skip certain names altogether
if (
name in ("__pycache__", "site-packages", "node_modules")
or name.startswith(".")
or name.endswith("~")
):
continue
subpath = os.path.join(path, name)
if any(matches_exclude_pattern(subpath, pattern) for pattern in self.exclude):
continue

if self.exclude:
subpath_str = "/" + os.path.abspath(subpath).replace(os.sep, "/")
if self.fscache.isdir(subpath):
subpath_str += "/"
if re.search(self.exclude, subpath_str):
continue

if self.fscache.isdir(subpath):
sub_sources = self.find_sources_in_dir(subpath)
Expand Down
11 changes: 6 additions & 5 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ def add_invertible_flag(flag: str,
# Options object. Options that require further processing should have
# their `dest` prefixed with `special-opts:`, which will cause them to be
# parsed into the separate special_opts namespace object.
options = Options()

# Note: we have a style guide for formatting the mypy --help text. See
# https://github.com/python/mypy/wiki/Documentation-Conventions
Expand Down Expand Up @@ -811,9 +812,11 @@ def add_invertible_flag(flag: str,
code_group.add_argument(
"--exclude",
metavar="PATH",
action="append",
default=[],
help="File names, directory names or subpaths to avoid checking",
default=options.exclude,
help=(
"Regex to match file names, directory names or paths to avoid checking. "
"Defaults to '%(default)s'."
)
)
code_group.add_argument(
'-m', '--module', action='append', metavar='MODULE',
Expand Down Expand Up @@ -843,8 +846,6 @@ def add_invertible_flag(flag: str,
if config_file and not os.path.exists(config_file):
parser.error("Cannot find config file '%s'" % config_file)

options = Options()

def set_strict_flags() -> None:
for dest, value in strict_flag_assignments:
setattr(options, dest, value)
Expand Down
24 changes: 8 additions & 16 deletions mypy/modulefinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import collections
import functools
import os
import re
import subprocess
import sys
from enum import Enum
Expand Down Expand Up @@ -450,10 +451,13 @@ def find_modules_recursive(self, module: str) -> List[BuildSource]:
):
continue
subpath = os.path.join(package_path, name)
if self.options and any(
matches_exclude_pattern(subpath, pattern) for pattern in self.options.exclude
):
continue

if self.options and self.options.exclude:
subpath_str = "/" + os.path.abspath(subpath).replace(os.sep, "/")
if self.fscache.isdir(subpath):
subpath_str += "/"
if re.search(self.options.exclude, subpath_str):
continue

if self.fscache.isdir(subpath):
# Only recurse into packages
Expand All @@ -475,18 +479,6 @@ def find_modules_recursive(self, module: str) -> List[BuildSource]:
return sources


def matches_exclude_pattern(path: str, pattern: str) -> bool:
path = os.path.splitdrive(path)[1]
path_components = path.split(os.sep)
pattern_components = pattern.replace(os.sep, "/").split("/")
if len(path_components) < len(pattern_components):
return False
return all(
path == pattern
for path, pattern in zip(reversed(path_components), reversed(pattern_components))
)


def verify_module(fscache: FileSystemCache, id: str, path: str, prefix: str) -> bool:
"""Check that all packages containing id have a __init__ file."""
if path.endswith(('__init__.py', '__init__.pyi')):
Expand Down
2 changes: 1 addition & 1 deletion mypy/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def __init__(self) -> None:
# top-level __init__.py to your packages.
self.explicit_package_bases = False
# File names, directory names or subpaths to avoid checking
self.exclude = [] # type: List[str]
self.exclude = "/(__pycache__|site-packages|node_modules)/|/(\\.[^/]+|[^/]+~)/?$" # type: str

# disallow_any options
self.disallow_any_generics = False
Expand Down
23 changes: 9 additions & 14 deletions mypy/test/test_find_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def test_find_sources_exclude(self) -> None:
options = Options()
options.namespace_packages = True

# special cased name
# default
finder = SourceFinder(FakeFSCache({"/dir/a.py", "/dir/venv/site-packages/b.py"}), options)
assert find_sources(finder, "/") == [("a", "/dir")]

Expand All @@ -270,7 +270,7 @@ def test_find_sources_exclude(self) -> None:
}

# file name
options.exclude = ["f.py"]
options.exclude = "/f.py"
finder = SourceFinder(FakeFSCache(files), options)
assert find_sources(finder, "/") == [
("a2", "/pkg"),
Expand All @@ -279,7 +279,7 @@ def test_find_sources_exclude(self) -> None:
]

# directory name
options.exclude = ["a1"]
options.exclude = "/a1/"
finder = SourceFinder(FakeFSCache(files), options)
assert find_sources(finder, "/") == [
("a2", "/pkg"),
Expand All @@ -288,15 +288,15 @@ def test_find_sources_exclude(self) -> None:
]

# paths
options.exclude = ["/pkg/a1"]
options.exclude = "/pkg/a1/"
finder = SourceFinder(FakeFSCache(files), options)
assert find_sources(finder, "/") == [
("a2", "/pkg"),
("a2.b.c.d.e", "/pkg"),
("a2.b.f", "/pkg"),
]

options.exclude = ["b/c"]
options.exclude = "b/c/"
finder = SourceFinder(FakeFSCache(files), options)
assert find_sources(finder, "/") == [
("a2", "/pkg"),
Expand All @@ -305,24 +305,19 @@ def test_find_sources_exclude(self) -> None:
]

# nothing should be ignored as a result of this
options.exclude = [
"/pkg/a", "2", "1", "pk", "kg", "g.py", "bc", "/b", "/xxx/pkg/a2/b/f.py"
"xxx/pkg/a2/b/f.py"
]
options.exclude = "|".join((
"/pkg/a/", "/2", "/1", "/pk/", "/kg", "/g.py", "/bc", "/xxx/pkg/a2/b/f.py"
"xxx/pkg/a2/b/f.py",
))
finder = SourceFinder(FakeFSCache(files), options)
assert len(find_sources(finder, "/")) == len(files)

# nothing should be ignored as a result of this
files = {
"pkg/a1/b/c/d/e.py",
"pkg/a1/b/f.py",
"pkg/a2/__init__.py",
"pkg/a2/b/c/d/e.py",
"pkg/a2/b/f.py",
}
options.exclude = [
"/pkg/a", "2", "1", "pk", "kg", "g.py", "bc", "/b", "/xxx/pkg/a2/b/f.py",
"xxx/pkg/a2/b/f.py", "/pkg/a1", "/pkg/a2"
]
finder = SourceFinder(FakeFSCache(files), options)
assert len(find_sources(finder, "/")) == len(files)
2 changes: 1 addition & 1 deletion mypy_self_check.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ pretty = True
always_false = MYPYC
plugins = misc/proper_plugin.py
python_version = 3.5
exclude = mypy/typeshed
exclude = /(mypy/typeshed|__pycache__|site-packages|node_modules)/|/(\.[^/]+|[^/]+~)/?$
0