diff --git a/mypy/build.py b/mypy/build.py index 783a10aad532..27fb4162aeb2 100644 --- a/mypy/build.py +++ b/mypy/build.py @@ -40,7 +40,7 @@ from mypy.checker import TypeChecker from mypy.indirection import TypeIndirectionVisitor from mypy.errors import Errors, CompileError, report_internal_error -from mypy.util import DecodeError, decode_python_encoding +from mypy.util import DecodeError, decode_python_encoding, is_sub_path from mypy.report import Reports from mypy import moduleinfo from mypy.fixup import fixup_module @@ -2368,7 +2368,11 @@ def find_module_and_diagnose(manager: BuildManager, skipping_module(manager, caller_line, caller_state, id, path) raise ModuleNotFound - + if not manager.options.no_silence_site_packages: + for dir in manager.search_paths.package_path + manager.search_paths.typeshed_path: + if is_sub_path(path, dir): + # Silence errors in site-package dirs and typeshed + follow_imports = 'silent' return (path, follow_imports) else: # Could not find a module. Typically the reason is a diff --git a/mypy/main.py b/mypy/main.py index 9f1fe8828a26..702f36f878ec 100644 --- a/mypy/main.py +++ b/mypy/main.py @@ -385,6 +385,9 @@ def add_invertible_flag(flag: str, '--no-site-packages', action='store_true', dest='special-opts:no_executable', help="do not search for installed PEP 561 compliant packages") + imports_group.add_argument( + '--no-silence-site-packages', action='store_true', + help="Do not silence errors in PEP 561 compliant installed packages") platform_group = parser.add_argument_group( title='platform configuration', diff --git a/mypy/options.py b/mypy/options.py index 4a248b9fe7f3..33593fad763b 100644 --- a/mypy/options.py +++ b/mypy/options.py @@ -65,6 +65,8 @@ def __init__(self) -> None: self.custom_typeshed_dir = None # type: Optional[str] self.mypy_path = [] # type: List[str] self.report_dirs = {} # type: Dict[str, str] + # Show errors in PEP 561 packages/site-packages modules + self.no_silence_site_packages = False self.ignore_missing_imports = False self.follow_imports = 'normal' # normal|silent|skip|error # Whether to respect the follow_imports setting even for stub files. diff --git a/mypy/util.py b/mypy/util.py index 35aa5ccc3e60..987382d2cdf1 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -1,9 +1,12 @@ """Utility functions with no non-trivial dependencies.""" - +import genericpath # type: ignore # no stub files yet +import os +import pathlib import re import subprocess +import sys from xml.sax.saxutils import escape -from typing import TypeVar, List, Tuple, Optional, Dict +from typing import TypeVar, List, Tuple, Optional, Dict, Sequence T = TypeVar('T') @@ -204,3 +207,8 @@ def replace_object_state(new: object, old: object) -> None: setattr(new, attr, getattr(old, attr)) elif hasattr(new, attr): delattr(new, attr) + + +def is_sub_path(path1: str, path2: str) -> bool: + """Given two paths, return if path1 is a sub-path of path2.""" + return pathlib.Path(path2) in pathlib.Path(path1).parents diff --git a/test-data/packages/typedpkg/typedpkg/sample.py b/test-data/packages/typedpkg/typedpkg/sample.py index 6a5f88a0f372..7e88816e824a 100644 --- a/test-data/packages/typedpkg/typedpkg/sample.py +++ b/test-data/packages/typedpkg/typedpkg/sample.py @@ -4,4 +4,4 @@ def ex(a): # type: (Iterable[str]) -> Tuple[str, ...] """Example typed package.""" - return tuple(a) + return list(a) diff --git a/test-data/unit/fine-grained-modules.test b/test-data/unit/fine-grained-modules.test index 1442a7807d4d..dda28ed72fd1 100644 --- a/test-data/unit/fine-grained-modules.test +++ b/test-data/unit/fine-grained-modules.test @@ -751,6 +751,7 @@ main:1: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" main:2: error: Incompatible types in assignment (expression has type "int", variable has type "str") [case testAddFileWhichImportsLibModuleWithErrors] +# flags: --no-silence-site-packages import a a.x = 0 [file a.py.2] @@ -758,8 +759,8 @@ import broken x = broken.x z [out] -main:1: error: Cannot find module named 'a' -main:1: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" flag would help) +main:2: error: Cannot find module named 'a' +main:2: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" flag would help) == a.py:3: error: Name 'z' is not defined /test-data/unit/lib-stub/broken.pyi:2: error: Name 'y' is not defined