Skip to content

Ignore errors when deleting files and folders on Windows #3289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion mypy/myunit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions mypy/test/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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:
Expand All @@ -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()

Expand Down
6 changes: 2 additions & 4 deletions mypy/test/testcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
)
from mypy.errors import CompileError
from mypy.options import Options
from mypy.util import delete_folder

from mypy import experiments

Expand Down Expand Up @@ -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()
Expand Down
3 changes: 2 additions & 1 deletion mypy/test/testcmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions mypy/test/testpythoneval.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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))
Expand Down
5 changes: 3 additions & 2 deletions mypy/test/teststubgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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:
Expand Down
21 changes: 21 additions & 0 deletions mypy/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)