[pypy-commit] pypy py3.5: Remove WindowsError, and add support for the "winerror" parameter in OSError.
amauryfa
pypy.commits at gmail.com
Sat Apr 1 12:12:31 EDT 2017
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.5
Changeset: r90896:1b8d1cb66a57
Date: 2017-04-01 18:11 +0200
http://bitbucket.org/pypy/pypy/changeset/1b8d1cb66a57/
Log: Remove WindowsError, and add support for the "winerror" parameter in
OSError. Also maybe fix wrap_oserror on Windows.
This is a shoot in the dark: I don't have Windows. But most of
interp_exceptions can be tested on Linux.
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -9,6 +9,7 @@
from rpython.rlib.objectmodel import we_are_translated, specialize
from rpython.rlib.objectmodel import dont_inline
from rpython.rlib import rstack, rstackovf
+from rpython.rlib import rwin32
from pypy.interpreter import debug
@@ -568,33 +569,6 @@
# 31: ANSI color code "red"
ansi_print(text, esc="31", file=file, newline=newline)
-try:
- WindowsError
-except NameError:
- _WINDOWS = False
-else:
- _WINDOWS = True
-
- def wrap_windowserror(space, e, w_filename=None):
- XXX # WindowsError no longer exists in Py3.5
- # instead, OSError has a kwarg winerror that overrides
- # any errno supplied
- from rpython.rlib import rwin32
-
- winerror = e.winerror
- try:
- msg = rwin32.FormatError(winerror)
- except ValueError:
- msg = 'Windows Error %d' % winerror
- exc = space.w_WindowsError
- if w_filename is not None:
- w_error = space.call_function(exc, space.newint(winerror),
- space.newtext(msg), w_filename)
- else:
- w_error = space.call_function(exc, space.newint(winerror),
- space.newtext(msg))
- return OperationError(exc, w_error)
-
@specialize.arg(3, 6)
def wrap_oserror2(space, e, w_filename=None, exception_name='w_OSError',
w_exception_class=None, w_filename2=None, eintr_retry=False):
@@ -612,9 +586,6 @@
"""
assert isinstance(e, OSError)
- if _WINDOWS and isinstance(e, WindowsError):
- return wrap_windowserror(space, e, w_filename)
-
if w_exception_class is None:
w_exc = getattr(space, exception_name)
else:
@@ -631,28 +602,37 @@
def _wrap_oserror2_impl(space, e, w_filename, w_filename2, w_exc, eintr_retry):
# move the common logic in its own function, instead of having it
# duplicated 4 times in all 4 specialized versions of wrap_oserror2()
- errno = e.errno
- if errno == EINTR:
- space.getexecutioncontext().checksignals()
- if eintr_retry:
- return None
+ if rwin32.WIN32 and isinstance(e, WindowsError):
+ winerror = e.winerror
+ try:
+ msg = rwin32.FormatError(winerror)
+ except ValueError:
+ msg = 'Windows Error %d' % winerror
+ w_errno = space.w_None
+ w_winerror = space.newint(winerror)
+ w_msg = space.newtext(msg)
+ else:
+ errno = e.errno
+ if errno == EINTR:
+ space.getexecutioncontext().checksignals()
+ if eintr_retry:
+ return None
- try:
- msg = strerror(errno)
- except ValueError:
- msg = u'error %d' % errno
- if w_filename is not None:
- if w_filename2 is not None:
- w_error = space.call_function(w_exc, space.newint(errno),
- space.newunicode(msg), w_filename,
- space.w_None, w_filename2)
- else:
- w_error = space.call_function(w_exc, space.newint(errno),
- space.newunicode(msg), w_filename)
- else:
- w_error = space.call_function(w_exc, space.newint(errno),
- space.newunicode(msg))
+ try:
+ msg = strerror(errno)
+ except ValueError:
+ msg = u'error %d' % errno
+ w_errno = space.newint(errno)
+ w_winerror = space.w_None
+ w_msg = space.newunicode(msg)
+
+ if w_filename is None:
+ w_filename = space.w_None
+ if w_filename2 is None:
+ w_filename2 = space.w_None
+ w_error = space.call_function(w_exc, w_errno, w_msg, w_filename,
+ w_winerror, w_filename2)
operror = OperationError(w_exc, w_error)
if eintr_retry:
raise operror
diff --git a/pypy/module/exceptions/__init__.py b/pypy/module/exceptions/__init__.py
--- a/pypy/module/exceptions/__init__.py
+++ b/pypy/module/exceptions/__init__.py
@@ -1,4 +1,4 @@
-import sys
+from rpython.rlib import rwin32
from pypy.interpreter.mixedmodule import MixedModule
class Module(MixedModule):
@@ -73,8 +73,8 @@
'ZeroDivisionError' : 'interp_exceptions.W_ZeroDivisionError',
}
- if sys.platform.startswith("win"):
- interpleveldefs['WindowsError'] = 'interp_exceptions.W_WindowsError'
+ if rwin32.WIN32:
+ interpleveldefs['WindowsError'] = 'interp_exceptions.W_OSError'
def setup_after_space_initialization(self):
from pypy.objspace.std.transparent import register_proxyable
diff --git a/pypy/module/exceptions/interp_exceptions.py b/pypy/module/exceptions/interp_exceptions.py
--- a/pypy/module/exceptions/interp_exceptions.py
+++ b/pypy/module/exceptions/interp_exceptions.py
@@ -444,6 +444,7 @@
def __init__(self, space):
self.w_errno = None
+ self.w_winerror = None
self.w_strerror = None
self.w_filename = None
self.w_filename2 = None
@@ -476,18 +477,36 @@
w_errno = args_w[0]
w_strerror = args_w[1]
w_filename = None
+ w_winerror = None
w_filename2 = None
if len(args_w) > 2:
w_filename = args_w[2]
- if len(args_w) > 4:
- w_filename2 = args_w[4]
- return w_errno, w_strerror, w_filename, w_filename2
- return None, None, None, None
+ if len(args_w) > 3:
+ w_winerror = args_w[3]
+ if len(args_w) > 4:
+ w_filename2 = args_w[4]
+ if rwin32.WIN32 and w_winerror:
+ # Under Windows, if the winerror constructor argument is
+ # an integer, the errno attribute is determined from the
+ # Windows error code, and the errno argument is
+ # ignored.
+ # On other platforms, the winerror argument is
+ # ignored, and the winerror attribute does not exist.
+ try:
+ winerror = space.int_w(w_winerror)
+ except OperationError:
+ w_winerror = None
+ else:
+ w_errno = space.newint(
+ WINERROR_TO_ERRNO.get(winerror, DEFAULT_WIN32_ERRNO))
+ return w_errno, w_winerror, w_strerror, w_filename, w_filename2
+ return None, None, None, None, None
@staticmethod
def descr_new(space, w_subtype, __args__):
args_w, kwds_w = __args__.unpack()
w_errno = None
+ w_winerror = None
w_strerror = None
w_filename = None
w_filename2 = None
@@ -495,7 +514,7 @@
if kwds_w:
raise oefmt(space.w_TypeError,
"OSError does not take keyword arguments")
- (w_errno, w_strerror, w_filename, w_filename2
+ (w_errno, w_winerror, w_strerror, w_filename, w_filename2
) = W_OSError._parse_init_args(space, args_w)
if (not space.is_none(w_errno) and
space.is_w(w_subtype, space.gettypeobject(W_OSError.typedef))):
@@ -513,8 +532,8 @@
exc = space.allocate_instance(W_OSError, w_subtype)
W_OSError.__init__(exc, space)
if not W_OSError._use_init(space, w_subtype):
- exc._init_error(space, args_w, w_errno, w_strerror, w_filename,
- w_filename2)
+ exc._init_error(space, args_w, w_errno, w_winerror, w_strerror,
+ w_filename, w_filename2)
return exc
def descr_init(self, space, __args__):
@@ -525,18 +544,17 @@
if kwds_w:
raise oefmt(space.w_TypeError,
"OSError does not take keyword arguments")
- (w_errno, w_strerror, w_filename, w_filename2
+ (w_errno, w_winerror, w_strerror, w_filename, w_filename2
) = W_OSError._parse_init_args(space, args_w)
- self._init_error(space, args_w, w_errno, w_strerror, w_filename,
- w_filename2)
+ self._init_error(space, args_w, w_errno, w_winerror, w_strerror,
+ w_filename, w_filename2)
- def _init_error(self, space, args_w, w_errno, w_strerror, w_filename,
- w_filename2):
+ def _init_error(self, space, args_w, w_errno, w_winerror, w_strerror,
+ w_filename, w_filename2):
W_BaseException.descr_init(self, space, args_w)
- if w_errno:
- self.w_errno = w_errno
- if w_strerror:
- self.w_strerror = w_strerror
+ self.w_errno = w_errno
+ self.w_winerror = w_winerror
+ self.w_strerror = w_strerror
if not space.is_none(w_filename):
if space.isinstance_w(
@@ -546,7 +564,8 @@
except OperationError:
self.w_filename = w_filename
else:
- self.w_filename = w_filename
+ if not space.is_none(w_filename):
+ self.w_filename = w_filename
if not space.is_none(w_filename2):
self.w_filename2 = w_filename2
# filename is removed from the args tuple (for compatibility
@@ -575,6 +594,20 @@
strerror = space.unicode_w(space.str(self.w_strerror))
else:
strerror = u""
+ if rwin32.WIN32 and self.w_winerror:
+ winerror = space.unicode_w(space.str(self.w_winerror))
+ # If available, winerror has the priority over errno
+ if self.w_filename:
+ if self.w_filename2:
+ return space.newunicode(u"[WinError %s] %s: %s -> %s" % (
+ winerror, strerror,
+ space.unicode_w(space.repr(self.w_filename)),
+ space.unicode_w(space.repr(self.w_filename2))))
+ return space.newunicode(u"[WinError %s] %s: %s" % (
+ winerror, strerror,
+ space.unicode_w(space.repr(self.w_filename))))
+ return space.newunicode(u"[WinError %s] %s" % (
+ winerror, strerror))
if self.w_filename:
if self.w_filename2:
return space.newunicode(u"[Errno %s] %s: %s -> %s" % (
@@ -597,6 +630,12 @@
def descr_set_written(self, space, w_written):
self.written = space.int_w(w_written)
+
+if hasattr(rwin32, 'build_winerror_to_errno'):
+ WINERROR_TO_ERRNO, DEFAULT_WIN32_ERRNO = rwin32.build_winerror_to_errno()
+else:
+ WINERROR_TO_ERRNO, DEFAULT_WIN32_ERRNO = {}, 22 # EINVAL
+
W_OSError.typedef = TypeDef(
'OSError',
W_Exception.typedef,
@@ -609,62 +648,11 @@
strerror = readwrite_attrproperty_w('w_strerror', W_OSError),
filename = readwrite_attrproperty_w('w_filename', W_OSError),
filename2= readwrite_attrproperty_w('w_filename2',W_OSError),
+ winerror = readwrite_attrproperty_w('w_winerror', W_OSError),
characters_written = GetSetProperty(W_OSError.descr_get_written,
W_OSError.descr_set_written),
)
-class W_WindowsError(W_OSError):
- """MS-Windows OS system call failed."""
-
- def __init__(self, space):
- self.w_winerror = space.w_None
- W_OSError.__init__(self, space)
-
- def descr_init(self, space, __args__):
- # Set errno to the POSIX errno, and winerror to the Win32
- # error code.
- W_OSError.descr_init(self, space, __args__)
- try:
- errno = space.int_w(self.w_errno)
- except OperationError:
- errno = self._default_errno
- else:
- errno = self._winerror_to_errno.get(errno, self._default_errno)
- self.w_winerror = self.w_errno
- self.w_errno = space.newint(errno)
-
- def descr_str(self, space):
- if (not space.is_w(self.w_winerror, space.w_None) and
- not space.is_w(self.w_strerror, space.w_None)):
- winerror = space.int_w(self.w_winerror)
- strerror = space.unicode_w(self.w_strerror)
- if self.w_filename:
- return space.newunicode(u"[Error %d] %s: %s" % (
- winerror,
- strerror,
- space.unicode_w(self.w_filename)))
- return space.newunicode(u"[Error %d] %s" % (winerror,
- strerror))
- return W_BaseException.descr_str(self, space)
-
- if hasattr(rwin32, 'build_winerror_to_errno'):
- _winerror_to_errno, _default_errno = rwin32.build_winerror_to_errno()
- # Python 2 doesn't map ERROR_DIRECTORY (267) to ENOTDIR but
- # Python 3 (CPython issue #12802) and build_winerror_to_errno do
- del _winerror_to_errno[267]
- else:
- _winerror_to_errno, _default_errno = {}, 22 # EINVAL
-
-W_WindowsError.typedef = TypeDef(
- "WindowsError",
- W_OSError.typedef,
- __doc__ = W_WindowsError.__doc__,
- __new__ = _new(W_WindowsError),
- __init__ = interp2app(W_WindowsError.descr_init),
- __str__ = interp2app(W_WindowsError.descr_str),
- winerror = readwrite_attrproperty_w('w_winerror', W_WindowsError),
- )
-
W_BlockingIOError = _new_exception(
"BlockingIOError", W_OSError, "I/O operation would block")
W_ConnectionError = _new_exception(
diff --git a/pypy/module/exceptions/test/test_exc.py b/pypy/module/exceptions/test/test_exc.py
--- a/pypy/module/exceptions/test/test_exc.py
+++ b/pypy/module/exceptions/test/test_exc.py
@@ -101,12 +101,13 @@
WindowsError
except NameError:
skip('WindowsError not present')
- ee = WindowsError(3, "x", "y")
- assert str(ee) == "[Error 3] x: y"
+ ee = WindowsError(None, "x", "y", 3)
+ assert type(ee) is FileNotFoundError
+ assert str(ee) == "[WinError 3] x: 'y'"
# winerror=3 (ERROR_PATH_NOT_FOUND) maps to errno=2 (ENOENT)
assert ee.winerror == 3
assert ee.errno == 2
- assert str(WindowsError(3, "x")) == "[Error 3] x"
+ assert str(WindowsError(3, "x")) == "[Errno 3] x"
def test_syntax_error(self):
s = SyntaxError()
More information about the pypy-commit
mailing list