diff --git a/mypy/myunit/__init__.py b/mypy/myunit/__init__.py index 26b9a4574661..495c222e9563 100644 --- a/mypy/myunit/__init__.py +++ b/mypy/myunit/__init__.py @@ -131,7 +131,10 @@ def tear_down(self) -> None: if self.suite: self.suite.tear_down() os.chdir(self.old_cwd) - self.tmpdir.cleanup() + try: + self.tmpdir.cleanup() + except OSError: + pass self.old_cwd = None self.tmpdir = None diff --git a/mypy/test/data.py b/mypy/test/data.py index a0573d55479c..5913f7e813be 100644 --- a/mypy/test/data.py +++ b/mypy/test/data.py @@ -5,12 +5,12 @@ import posixpath import re from os import remove, rmdir -import shutil import pytest # type: ignore # no pytest in typeshed from typing import Callable, List, Tuple, Set, Optional, Iterator, Any from mypy.myunit import TestCase, SkipTestCaseException +from mypy.util import delete_folder, delete_file def parse_test_cases( @@ -228,13 +228,13 @@ def tear_down(self) -> None: # First remove files. for is_dir, path in reversed(self.clean_up): if not is_dir: - remove(path) + delete_file(path) # Then remove directories. for is_dir, path in reversed(self.clean_up): if is_dir: pycache = os.path.join(path, '__pycache__') if os.path.isdir(pycache): - shutil.rmtree(pycache) + delete_folder(pycache) try: rmdir(path) except OSError as error: @@ -251,7 +251,7 @@ def tear_down(self) -> None: # Be defensive -- only call rmtree if we're sure we aren't removing anything # valuable. if path.startswith('tmp/') and os.path.isdir(path): - shutil.rmtree(path) + delete_folder(path) raise super().tear_down() diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py index 7f95873bbd58..1db268b45f11 100644 --- a/mypy/test/testcheck.py +++ b/mypy/test/testcheck.py @@ -21,6 +21,7 @@ ) from mypy.errors import CompileError from mypy.options import Options +from mypy.util import delete_folder from mypy import experiments @@ -113,10 +114,7 @@ def run_case(self, testcase: DataDrivenTestCase) -> None: experiments.STRICT_OPTIONAL = old_strict_optional def clear_cache(self) -> None: - dn = defaults.CACHE_DIR - - if os.path.exists(dn): - shutil.rmtree(dn) + delete_folder(defaults.CACHE_DIR) def run_case_once(self, testcase: DataDrivenTestCase, incremental: int = 0) -> None: find_module_clear_caches() diff --git a/mypy/test/testcmdline.py b/mypy/test/testcmdline.py index 8e56b42bc766..6ecff97b6b68 100644 --- a/mypy/test/testcmdline.py +++ b/mypy/test/testcmdline.py @@ -17,6 +17,7 @@ from mypy.test.data import parse_test_cases, DataDrivenTestCase from mypy.test.helpers import assert_string_arrays_equal from mypy.version import __version__, base_version +from mypy.util import delete_file # Path to Python 3 interpreter python3_path = sys.executable @@ -58,7 +59,7 @@ def test_python_evaluation(testcase: DataDrivenTestCase) -> None: # Split output into lines. out = [s.rstrip('\n\r') for s in str(outb, 'utf8').splitlines()] # Remove temp file. - os.remove(program_path) + delete_file(program_path) # Compare actual output to expected. if testcase.output_files: for path, expected_content in testcase.output_files: diff --git a/mypy/test/testpythoneval.py b/mypy/test/testpythoneval.py index 85e9aa3751d7..a2e0b1de0b91 100644 --- a/mypy/test/testpythoneval.py +++ b/mypy/test/testpythoneval.py @@ -25,7 +25,7 @@ from mypy.test.config import test_data_prefix, test_temp_dir from mypy.test.data import DataDrivenTestCase, parse_test_cases from mypy.test.helpers import assert_string_arrays_equal -from mypy.util import try_find_python2_interpreter +from mypy.util import try_find_python2_interpreter, delete_file # Files which contain test case descriptions. @@ -94,7 +94,7 @@ def test_python_evaluation(testcase: DataDrivenTestCase) -> None: returncode, interp_out = run([interpreter, program], env=env) out += interp_out # Remove temp file. - os.remove(program_path) + delete_file(program_path) assert_string_arrays_equal(adapt_output(testcase), out, 'Invalid output ({}, line {})'.format( testcase.file, testcase.line)) diff --git a/mypy/test/teststubgen.py b/mypy/test/teststubgen.py index aa76f2fbc90f..4c93e55f1799 100644 --- a/mypy/test/teststubgen.py +++ b/mypy/test/teststubgen.py @@ -22,6 +22,7 @@ parse_signature, parse_all_signatures, build_signature, find_unique_signatures, infer_sig_from_docstring ) +from mypy.util import delete_folder, delete_file class StubgenUtilSuite(Suite): @@ -136,8 +137,8 @@ def test_stubgen(testcase: DataDrivenTestCase) -> None: testcase.file, testcase.line)) finally: handle.close() - os.unlink(handle.name) - shutil.rmtree(out_dir) + delete_file(handle.name) + delete_folder(out_dir) def reset_importlib_caches() -> None: diff --git a/mypy/util.py b/mypy/util.py index 1e8e31898d23..9b4b20a0c153 100644 --- a/mypy/util.py +++ b/mypy/util.py @@ -2,6 +2,9 @@ import re import subprocess +import os +import sys +import shutil from xml.sax.saxutils import escape from typing import TypeVar, List, Tuple, Optional, Sequence, Dict @@ -134,3 +137,21 @@ def id(self, o: object) -> int: self.id_map[o] = self.next_id self.next_id += 1 return self.id_map[o] + + +def delete_folder(folder_path: str) -> None: + if sys.platform.startswith('win'): + shutil.rmtree(folder_path, ignore_errors=True) + else: + if os.path.exists(folder_path): + shutil.rmtree(folder_path) + + +def delete_file(file_path: str) -> None: + if sys.platform.startswith('win'): + try: + os.remove(file_path) + except OSError: + pass + else: + os.remove(file_path)