From 6464322611d0e5f0c1d71e80812bc803fe327027 Mon Sep 17 00:00:00 2001 From: David Tucker Date: Sat, 26 Oct 2019 16:35:23 -0700 Subject: [PATCH 1/2] Fix MypyItem.mypy_path --- src/pytest_mypy.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/pytest_mypy.py b/src/pytest_mypy.py index 17d0f02..fc4ef72 100644 --- a/src/pytest_mypy.py +++ b/src/pytest_mypy.py @@ -1,5 +1,7 @@ """Mypy static type checker plugin for Pytest""" +import os + import pytest import mypy.api @@ -83,6 +85,18 @@ def pytest_runtestloop(session): terminal.write_line(stderr, red=True) +# mypy.errors.remove_path_prefix is not public. +# https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/errors.py#L647-L654 +def _remove_path_prefix(path, prefix): + """If path starts with prefix, return copy of path with the prefix removed. + Otherwise, return path. If path is None, return None. + """ + if prefix is not None and path.startswith(prefix): + return path[len(prefix):] + else: + return path + + class MypyItem(pytest.Item, pytest.File): """A File that Mypy Runs On.""" @@ -96,7 +110,22 @@ def __init__(self, *args, **kwargs): def mypy_path(self): """Get the path that is expected to show up in Mypy results.""" - return self.fspath.relto(self.config.rootdir) + # Mypy does not currently expose this computation, so... + # https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/build.py#L214 + prefix = ignore_prefix = os.getcwd() + # https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/errors.py#L208-L214 + prefix = os.path.normpath(prefix) + # Add separator to the end, if not given. + if os.path.basename(prefix) != '': + prefix += os.sep + ignore_prefix = prefix + # https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/errors.py#L535 + # https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/errors.py#L216-L221 + if '--show-absolute-path' in mypy_argv: + return os.path.abspath(str(self.fspath)) + else: + path = os.path.normpath(str(self.fspath)) + return _remove_path_prefix(path, ignore_prefix) def reportinfo(self): """Produce a heading for the test report.""" From 5aecc102c3f1323f45c8bc6d8849e5a82f85d241 Mon Sep 17 00:00:00 2001 From: David Tucker Date: Sun, 27 Oct 2019 10:36:42 -0700 Subject: [PATCH 2/2] Remove MypyItem.mypy_path --- src/pytest_mypy.py | 47 ++++++++++------------------------------------ 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/src/pytest_mypy.py b/src/pytest_mypy.py index fc4ef72..3bff367 100644 --- a/src/pytest_mypy.py +++ b/src/pytest_mypy.py @@ -48,7 +48,7 @@ def pytest_collect_file(path, parent): def pytest_runtestloop(session): """Run mypy on collected MypyItems, then sort the output.""" mypy_items = { - item.mypy_path(): item + os.path.abspath(str(item.fspath)): item for item in session.items if isinstance(item, MypyItem) } @@ -72,7 +72,7 @@ def pytest_runtestloop(session): continue mypy_path, _, error = line.partition(':') try: - item = mypy_items[mypy_path] + item = mypy_items[os.path.abspath(mypy_path)] except KeyError: unmatched_lines.append(line) else: @@ -85,18 +85,6 @@ def pytest_runtestloop(session): terminal.write_line(stderr, red=True) -# mypy.errors.remove_path_prefix is not public. -# https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/errors.py#L647-L654 -def _remove_path_prefix(path, prefix): - """If path starts with prefix, return copy of path with the prefix removed. - Otherwise, return path. If path is None, return None. - """ - if prefix is not None and path.startswith(prefix): - return path[len(prefix):] - else: - return path - - class MypyItem(pytest.Item, pytest.File): """A File that Mypy Runs On.""" @@ -108,34 +96,19 @@ def __init__(self, *args, **kwargs): self.add_marker(self.MARKER) self.mypy_errors = [] - def mypy_path(self): - """Get the path that is expected to show up in Mypy results.""" - # Mypy does not currently expose this computation, so... - # https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/build.py#L214 - prefix = ignore_prefix = os.getcwd() - # https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/errors.py#L208-L214 - prefix = os.path.normpath(prefix) - # Add separator to the end, if not given. - if os.path.basename(prefix) != '': - prefix += os.sep - ignore_prefix = prefix - # https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/errors.py#L535 - # https://github.com/python/mypy/blob/fdcbb74b2e01f6afd0549da6375a66aab839fd9a/mypy/errors.py#L216-L221 - if '--show-absolute-path' in mypy_argv: - return os.path.abspath(str(self.fspath)) - else: - path = os.path.normpath(str(self.fspath)) - return _remove_path_prefix(path, ignore_prefix) - - def reportinfo(self): - """Produce a heading for the test report.""" - return self.fspath, None, self.mypy_path() - def runtest(self): """Raise an exception if mypy found errors for this item.""" if self.mypy_errors: raise MypyError('\n'.join(self.mypy_errors)) + def reportinfo(self): + """Produce a heading for the test report.""" + return ( + self.fspath, + None, + self.config.invocation_dir.bestrelpath(self.fspath), + ) + def repr_failure(self, excinfo): """ Unwrap mypy errors so we get a clean error message without the