Skip to content

Commit 5ccd226

Browse files
authored
Merge pull request #9364 from jdufresne/oserror
Use unified OSError and its subclasses
2 parents 7e609a0 + d282fb9 commit 5ccd226

12 files changed

+48
-68
lines changed

news/f0af302f-aef7-4323-8332-819f0be13d79.trivial.rst

Whitespace-only changes.

setup.cfg

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,6 @@ per-file-ignores =
2929
noxfile.py: G
3030
# B011: Do not call assert False since python -O removes these calls
3131
tests/*: B011
32-
# TODO: Remove IOError from except (OSError, IOError) blocks in
33-
# these files when Python 2 is removed.
34-
# In Python 3, IOError have been merged into OSError
35-
# https://github.com/PyCQA/flake8-bugbear/issues/110
36-
src/pip/_internal/utils/filesystem.py: B014
37-
src/pip/_internal/network/cache.py: B014
38-
src/pip/_internal/utils/misc.py: B014
3932

4033
[mypy]
4134
follow_imports = silent

src/pip/_internal/commands/install.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -435,10 +435,10 @@ def run(self, options, args):
435435
write_output(
436436
'Successfully installed %s', installed_desc,
437437
)
438-
except EnvironmentError as error:
438+
except OSError as error:
439439
show_traceback = (self.verbosity >= 1)
440440

441-
message = create_env_error_message(
441+
message = create_os_error_message(
442442
error, show_traceback, options.use_user_site,
443443
)
444444
logger.error(message, exc_info=show_traceback) # noqa
@@ -697,16 +697,16 @@ def format_options(option_names):
697697
)
698698

699699

700-
def create_env_error_message(error, show_traceback, using_user_site):
701-
# type: (EnvironmentError, bool, bool) -> str
702-
"""Format an error message for an EnvironmentError
700+
def create_os_error_message(error, show_traceback, using_user_site):
701+
# type: (OSError, bool, bool) -> str
702+
"""Format an error message for an OSError
703703
704704
It may occur anytime during the execution of the install command.
705705
"""
706706
parts = []
707707

708708
# Mention the error if we are not going to show a traceback
709-
parts.append("Could not install packages due to an EnvironmentError")
709+
parts.append("Could not install packages due to an OSError")
710710
if not show_traceback:
711711
parts.append(": ")
712712
parts.append(str(error))

src/pip/_internal/network/cache.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def suppressed_cache_errors():
2929
"""
3030
try:
3131
yield
32-
except (OSError, IOError):
32+
except OSError:
3333
pass
3434

3535

src/pip/_internal/req/req_file.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ def get_file_content(url, session):
553553
try:
554554
with open(url, 'rb') as f:
555555
content = auto_decode(f.read())
556-
except IOError as exc:
556+
except OSError as exc:
557557
raise InstallationError(
558558
f'Could not open requirements file: {exc}'
559559
)

src/pip/_internal/req/req_tracker.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import contextlib
2-
import errno
32
import hashlib
43
import logging
54
import os
@@ -103,10 +102,8 @@ def add(self, req):
103102
try:
104103
with open(entry_path) as fp:
105104
contents = fp.read()
106-
except IOError as e:
107-
# if the error is anything other than "file does not exist", raise.
108-
if e.errno != errno.ENOENT:
109-
raise
105+
except FileNotFoundError:
106+
pass
110107
else:
111108
message = '{} is already being built: {}'.format(
112109
req.link, contents)

src/pip/_internal/self_outdated_check.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def __init__(self, cache_dir):
5050
try:
5151
with open(self.statefile_path) as statefile:
5252
self.state = json.load(statefile)
53-
except (IOError, ValueError, KeyError):
53+
except (OSError, ValueError, KeyError):
5454
# Explicitly suppressing exceptions, since we don't want to
5555
# error out if the cache file is invalid.
5656
pass

src/pip/_internal/utils/filesystem.py

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import errno
21
import fnmatch
32
import os
43
import os.path
@@ -64,7 +63,7 @@ def copy2_fixed(src, dest):
6463
"""
6564
try:
6665
shutil.copy2(src, dest)
67-
except (OSError, IOError):
66+
except OSError:
6867
for f in [src, dest]:
6968
try:
7069
is_socket_file = is_socket(f)
@@ -148,27 +147,22 @@ def _test_writable_dir_win(path):
148147
file = os.path.join(path, name)
149148
try:
150149
fd = os.open(file, os.O_RDWR | os.O_CREAT | os.O_EXCL)
151-
# Python 2 doesn't support FileExistsError and PermissionError.
152-
except OSError as e:
153-
# exception FileExistsError
154-
if e.errno == errno.EEXIST:
155-
continue
156-
# exception PermissionError
157-
if e.errno == errno.EPERM or e.errno == errno.EACCES:
158-
# This could be because there's a directory with the same name.
159-
# But it's highly unlikely there's a directory called that,
160-
# so we'll assume it's because the parent dir is not writable.
161-
# This could as well be because the parent dir is not readable,
162-
# due to non-privileged user access.
163-
return False
164-
raise
150+
except FileExistsError:
151+
pass
152+
except PermissionError:
153+
# This could be because there's a directory with the same name.
154+
# But it's highly unlikely there's a directory called that,
155+
# so we'll assume it's because the parent dir is not writable.
156+
# This could as well be because the parent dir is not readable,
157+
# due to non-privileged user access.
158+
return False
165159
else:
166160
os.close(fd)
167161
os.unlink(file)
168162
return True
169163

170164
# This should never be reached
171-
raise EnvironmentError(
165+
raise OSError(
172166
'Unexpected condition testing for writable directory'
173167
)
174168

src/pip/_internal/utils/misc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def rmtree_errorhandler(func, path, exc_info):
138138
read-only attribute, and hopefully continue without problems."""
139139
try:
140140
has_attr_readonly = not (os.stat(path).st_mode & stat.S_IWRITE)
141-
except (IOError, OSError):
141+
except OSError:
142142
# it's equivalent to os.path.exists
143143
return
144144

src/pip/_internal/utils/virtualenv.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def _get_pyvenv_cfg_lines():
5353
# writes with UTF-8. (pypa/pip#8717)
5454
with open(pyvenv_cfg_file, encoding='utf-8') as f:
5555
return f.read().splitlines() # avoids trailing newlines
56-
except IOError:
56+
except OSError:
5757
return None
5858

5959

src/pip/_internal/vcs/versioncontrol.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""Handles all VCS (version control) support"""
22

3-
import errno
43
import logging
54
import os
65
import shutil
@@ -772,16 +771,13 @@ def run_command(
772771
extra_environ=extra_environ,
773772
extra_ok_returncodes=extra_ok_returncodes,
774773
log_failed_cmd=log_failed_cmd)
775-
except OSError as e:
774+
except FileNotFoundError:
776775
# errno.ENOENT = no such file or directory
777776
# In other words, the VCS executable isn't available
778-
if e.errno == errno.ENOENT:
779-
raise BadCommand(
780-
'Cannot find command {cls.name!r} - do you have '
781-
'{cls.name!r} installed and in your '
782-
'PATH?'.format(**locals()))
783-
else:
784-
raise # re-raise exception if a different error occurred
777+
raise BadCommand(
778+
'Cannot find command {cls.name!r} - do you have '
779+
'{cls.name!r} installed and in your '
780+
'PATH?'.format(**locals()))
785781

786782
@classmethod
787783
def is_repository_directory(cls, path):

tests/unit/test_command_install.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pip._vendor.packaging.requirements import Requirement
66

77
from pip._internal.commands.install import (
8-
create_env_error_message,
8+
create_os_error_message,
99
decide_user_install,
1010
reject_location_related_install_options,
1111
)
@@ -81,35 +81,35 @@ def test_rejection_for_location_requirement_options():
8181

8282
@pytest.mark.parametrize('error, show_traceback, using_user_site, expected', [
8383
# show_traceback = True, using_user_site = True
84-
(EnvironmentError("Illegal byte sequence"), True, True, 'Could not install'
85-
' packages due to an EnvironmentError.\n'),
86-
(EnvironmentError(errno.EACCES, "No file permission"), True, True, 'Could'
87-
' not install packages due to an EnvironmentError.\nCheck the'
84+
(OSError("Illegal byte sequence"), True, True, 'Could not install'
85+
' packages due to an OSError.\n'),
86+
(OSError(errno.EACCES, "No file permission"), True, True, 'Could'
87+
' not install packages due to an OSError.\nCheck the'
8888
' permissions.\n'),
8989
# show_traceback = True, using_user_site = False
90-
(EnvironmentError("Illegal byte sequence"), True, False, 'Could not'
91-
' install packages due to an EnvironmentError.\n'),
92-
(EnvironmentError(errno.EACCES, "No file permission"), True, False, 'Could'
93-
' not install packages due to an EnvironmentError.\nConsider using the'
90+
(OSError("Illegal byte sequence"), True, False, 'Could not'
91+
' install packages due to an OSError.\n'),
92+
(OSError(errno.EACCES, "No file permission"), True, False, 'Could'
93+
' not install packages due to an OSError.\nConsider using the'
9494
' `--user` option or check the permissions.\n'),
9595
# show_traceback = False, using_user_site = True
96-
(EnvironmentError("Illegal byte sequence"), False, True, 'Could not'
97-
' install packages due to an EnvironmentError: Illegal byte'
96+
(OSError("Illegal byte sequence"), False, True, 'Could not'
97+
' install packages due to an OSError: Illegal byte'
9898
' sequence\n'),
99-
(EnvironmentError(errno.EACCES, "No file permission"), False, True, 'Could'
100-
' not install packages due to an EnvironmentError: [Errno 13] No file'
99+
(OSError(errno.EACCES, "No file permission"), False, True, 'Could'
100+
' not install packages due to an OSError: [Errno 13] No file'
101101
' permission\nCheck the permissions.\n'),
102102
# show_traceback = False, using_user_site = False
103-
(EnvironmentError("Illegal byte sequence"), False, False, 'Could not'
104-
' install packages due to an EnvironmentError: Illegal byte sequence'
103+
(OSError("Illegal byte sequence"), False, False, 'Could not'
104+
' install packages due to an OSError: Illegal byte sequence'
105105
'\n'),
106-
(EnvironmentError(errno.EACCES, "No file permission"), False, False,
107-
'Could not install packages due to an EnvironmentError: [Errno 13] No'
106+
(OSError(errno.EACCES, "No file permission"), False, False,
107+
'Could not install packages due to an OSError: [Errno 13] No'
108108
' file permission\nConsider using the `--user` option or check the'
109109
' permissions.\n'),
110110
])
111-
def test_create_env_error_message(
111+
def test_create_os_error_message(
112112
error, show_traceback, using_user_site, expected
113113
):
114-
msg = create_env_error_message(error, show_traceback, using_user_site)
114+
msg = create_os_error_message(error, show_traceback, using_user_site)
115115
assert msg == expected

0 commit comments

Comments
 (0)