diff --git a/pytest_mypy/collect.py b/pytest_mypy/collect.py index 8517dcc..7ac8bc1 100644 --- a/pytest_mypy/collect.py +++ b/pytest_mypy/collect.py @@ -1,3 +1,4 @@ +import tempfile from typing import Any, Dict, List import pytest @@ -96,7 +97,7 @@ def pytest_collect_file(path, parent): def pytest_addoption(parser: Parser) -> None: group = parser.getgroup('mypy-tests') - group.addoption('--mypy-testing-base', type=str, default='/tmp', + group.addoption('--mypy-testing-base', type=str, default=tempfile.gettempdir(), help='Base directory for tests to use') group.addoption('--mypy-ini-file', type=str, help='Which .ini file to use as a default config for tests') diff --git a/pytest_mypy/item.py b/pytest_mypy/item.py index e854234..39e28d1 100644 --- a/pytest_mypy/item.py +++ b/pytest_mypy/item.py @@ -7,7 +7,6 @@ from pathlib import Path from typing import Any, Dict, List, Tuple, Callable, Optional -import capturer import pytest from _pytest._code import ExceptionInfo from _pytest._code.code import ReprEntry, ReprFileLocation @@ -17,7 +16,12 @@ from mypy.main import process_options from pytest_mypy import utils from pytest_mypy.collect import File, YamlTestFile -from pytest_mypy.utils import TypecheckAssertionError, assert_string_arrays_equal, fname_to_module +from pytest_mypy.utils import ( + TypecheckAssertionError, + capture_std_streams, + assert_string_arrays_equal, + fname_to_module, +) class TraceLastReprEntry(ReprEntry): @@ -163,6 +167,9 @@ def typecheck_in_new_subprocess(self, execution_path: Path, mypy_cmd_options: Li # add current directory to path self.environment_variables['PYTHONPATH'] = str(execution_path) + # Windows requires this to be set, otherwise the interpreter crashes + if 'SYSTEMROOT' in os.environ: + self.environment_variables['SYSTEMROOT'] = os.environ['SYSTEMROOT'] completed = subprocess.run([mypy_executable, *mypy_cmd_options], stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=os.getcwd(), @@ -180,12 +187,10 @@ def typecheck_in_same_process(self, execution_path: Path, mypy_cmd_options: List # add current directory to path sys.path.insert(0, str(execution_path)) - with capturer.CaptureOutput(merged=False) as captured_std_streams: + with capture_std_streams() as (stdout, stderr): return_code = run_mypy_typechecking(mypy_cmd_options) - stdout = captured_std_streams.stdout.get_text() - stderr = captured_std_streams.stderr.get_text() - return return_code, (stdout, stderr) + return return_code, (stdout.getvalue(), stderr.getvalue()) def execute_extension_hook(self) -> None: extension_hook_fqname = self.config.option.mypy_extension_hook diff --git a/pytest_mypy/tests/test-extension.yml b/pytest_mypy/tests/test-extension.yml index 9fcbcf7..fe6ece2 100644 --- a/pytest_mypy/tests/test-extension.yml +++ b/pytest_mypy/tests/test-extension.yml @@ -3,5 +3,5 @@ # if hook works, main should contain 'reveal_type(1)' reveal_type: 1 out: | - main:1: note: Revealed type is 'builtins.int' + main:1: note: Revealed type is 'Literal[1]?' diff --git a/pytest_mypy/utils.py b/pytest_mypy/utils.py index d08f713..1373339 100644 --- a/pytest_mypy/utils.py +++ b/pytest_mypy/utils.py @@ -1,11 +1,13 @@ # Borrowed from Pew. # See https://github.com/berdario/pew/blob/master/pew/_utils.py#L82 +import contextlib import inspect +import io import os import re import sys from pathlib import Path -from typing import Callable, List, Optional, Tuple +from typing import Callable, Iterator, List, Optional, Tuple from decorator import contextmanager @@ -310,3 +312,15 @@ def cd(path): yield finally: os.chdir(prev_cwd) + + +@contextmanager +def capture_std_streams() -> Iterator[Tuple[io.StringIO, io.StringIO]]: + """Context manager to temporarily capture stdout and stderr. + + Returns ``(stdout, stderr)``. + """ + out = io.StringIO() + err = io.StringIO() + with contextlib.redirect_stdout(out), contextlib.redirect_stderr(err): + yield out, err diff --git a/setup.py b/setup.py index 4cab8a6..5b3b736 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,6 @@ 'pytest', 'mypy>=0.730', 'decorator', - 'capturer', 'pyyaml' ]