Skip to content
21 changes: 18 additions & 3 deletions mypy/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -2521,14 +2521,29 @@ def log_configuration(manager: BuildManager) -> None:
"""Output useful configuration information to LOG and TRACE"""

manager.log()
configuration_vars = (
configuration_vars = [
("Mypy Version", __version__),
("Config File", (manager.options.config_file or "Default")),
("Configured Executable", manager.options.python_executable),
]

src_pth_str = "Source Path"
src_pths = list(manager.source_set.source_paths.copy())
src_pths.sort()

if len(src_pths) > 1:
src_pth_str += "s"
configuration_vars.append((src_pth_str, " ".join(src_pths)))
elif len(src_pths) == 1:
configuration_vars.append((src_pth_str, src_pths.pop()))
else:
configuration_vars.append((src_pth_str, "None"))

configuration_vars.extend([
("Configured Executable", manager.options.python_executable or "None"),
("Current Executable", sys.executable),
("Cache Dir", manager.options.cache_dir),
("Compiled", str(not __file__.endswith(".py"))),
)
])

for conf_name, conf_value in configuration_vars:
manager.log("{:24}{}".format(conf_name + ":", conf_value))
Expand Down
1 change: 1 addition & 0 deletions mypy/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def split_and_match_files(paths: str) -> List[str]:
# These two are for backwards compatibility
'silent_imports': bool,
'almost_silent': bool,
'no_site_packages': bool,
'plugins': lambda s: [p.strip() for p in s.split(',')],
'always_true': lambda s: [p.strip() for p in s.split(',')],
'always_false': lambda s: [p.strip() for p in s.split(',')],
Expand Down
4 changes: 2 additions & 2 deletions mypy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def infer_python_executable(options: Options,
python_executable = special_opts.python_executable or options.python_executable

if python_executable is None:
if not special_opts.no_executable:
if not special_opts.no_executable and not options.no_site_packages:
python_executable = _python_executable_from_version(options.python_version)
options.python_executable = python_executable

Expand Down Expand Up @@ -839,7 +839,7 @@ def set_strict_flags() -> None:
except PythonExecutableInferenceError as e:
parser.error(str(e))

if special_opts.no_executable:
if special_opts.no_executable or options.no_site_packages:
options.python_executable = None

# Paths listed in the config file will be ignored if any paths are passed on
Expand Down
1 change: 1 addition & 0 deletions mypy/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def __init__(self) -> None:
self.report_dirs = {} # type: Dict[str, str]
# Show errors in PEP 561 packages/site-packages modules
self.no_silence_site_packages = False
self.no_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.
Expand Down
22 changes: 18 additions & 4 deletions mypy/test/testpep561.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from contextlib import contextmanager
import os
import pytest # type: ignore
import re
import subprocess
from subprocess import PIPE
import sys
Expand Down Expand Up @@ -72,7 +73,7 @@ def install_package(pkg: str,
working_dir = os.path.join(package_path, pkg)
with tempfile.TemporaryDirectory() as dir:
if use_pip:
install_cmd = [python_executable, '-m', 'pip', 'install', '-b {}'.format(dir)]
install_cmd = [python_executable, '-m', 'pip', 'install', '-b', '{}'.format(dir)]
if editable:
install_cmd.append('-e')
install_cmd.append('.')
Expand Down Expand Up @@ -100,10 +101,11 @@ def test_pep561(testcase: DataDrivenTestCase) -> None:
else:
python = sys.executable
assert python is not None, "Should be impossible"
pkgs, args = parse_pkgs(testcase.input[0])
pkgs, pip_args = parse_pkgs(testcase.input[0])
mypy_args = parse_mypy_args(testcase.input[1])
use_pip = True
editable = False
for arg in args:
for arg in pip_args:
if arg == 'no-pip':
use_pip = False
elif arg == 'editable':
Expand All @@ -122,9 +124,14 @@ def test_pep561(testcase: DataDrivenTestCase) -> None:
with open(program, 'w', encoding='utf-8') as f:
for s in testcase.input:
f.write('{}\n'.format(s))
cmd_line = [program, '--no-incremental', '--no-error-summary']
cmd_line = mypy_args + [program, '--no-incremental', '--no-error-summary']
if python_executable != sys.executable:
cmd_line.append('--python-executable={}'.format(python_executable))
if testcase.files != []:
for name, content in testcase.files:
if 'mypy.ini' in name:
with open('mypy.ini', 'w') as m:
m.write(content)
output = []
# Type check the module
out, err, returncode = mypy.api.run(cmd_line)
Expand Down Expand Up @@ -153,6 +160,13 @@ def parse_pkgs(comment: str) -> Tuple[List[str], List[str]]:
return ([pkg.strip() for pkg in pkgs_str.split(',')], [arg.strip() for arg in args])


def parse_mypy_args(line: str) -> List[str]:
m = re.match('# flags: (.*)$', line)
if not m:
return [] # No args; mypy will spit out an error.
return m.group(1).split()


@pytest.mark.skipif(sys.platform == 'darwin' and hasattr(sys, 'base_prefix') and
sys.base_prefix != sys.prefix,
reason="Temporarily skip to avoid having a virtualenv within a venv.")
Expand Down
41 changes: 41 additions & 0 deletions test-data/unit/pep561.test
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
[case testTypedPkgNoSitePkgsIgnoredImports]
# pkgs: typedpkg
# flags: --no-site-packages
from typedpkg.sample import ex
from typedpkg import dne
a = ex([''])
reveal_type(a)
[file mypy.ini]
\[mypy]
ignore_missing_imports = True
[out]
testTypedPkgNoSitePkgsIgnoredImports.py:6: note: Revealed type is 'Any'

[case testTypedPkgSimple]
# pkgs: typedpkg
from typedpkg.sample import ex
Expand All @@ -7,6 +20,34 @@ reveal_type(a)
[out]
testTypedPkgSimple.py:5: note: Revealed type is 'builtins.tuple[builtins.str]'

[case testTypedPkg_config_nositepackages]
# pkgs: typedpkg
from typedpkg.sample import ex
from typedpkg import dne
a = ex([''])
reveal_type(a)
[file mypy.ini]
\[mypy]
no_site_packages=True
[out]
testTypedPkg_config_nositepackages.py:2: error: Cannot find implementation or library stub for module named 'typedpkg.sample'
testTypedPkg_config_nositepackages.py:2: note: See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports
testTypedPkg_config_nositepackages.py:3: error: Cannot find implementation or library stub for module named 'typedpkg'
testTypedPkg_config_nositepackages.py:5: note: Revealed type is 'Any'

[case testTypedPkg_args_nositepackages]
# pkgs: typedpkg
# flags: --no-site-packages
from typedpkg.sample import ex
from typedpkg import dne
a = ex([''])
reveal_type(a)
[out]
testTypedPkg_args_nositepackages.py:3: error: Cannot find implementation or library stub for module named 'typedpkg.sample'
testTypedPkg_args_nositepackages.py:3: note: See https://mypy.readthedocs.io/en/latest/running_mypy.html#missing-imports
testTypedPkg_args_nositepackages.py:4: error: Cannot find implementation or library stub for module named 'typedpkg'
testTypedPkg_args_nositepackages.py:6: note: Revealed type is 'Any'

[case testTypedPkgStubs]
# pkgs: typedpkg-stubs
from typedpkg.sample import ex
Expand Down
Empty file added test.py
Empty file.