summaryrefslogtreecommitdiff
path: root/trollius/py33_exceptions.py
diff options
context:
space:
mode:
Diffstat (limited to 'trollius/py33_exceptions.py')
-rw-r--r--trollius/py33_exceptions.py144
1 files changed, 144 insertions, 0 deletions
diff --git a/trollius/py33_exceptions.py b/trollius/py33_exceptions.py
new file mode 100644
index 0000000..94cbfca
--- /dev/null
+++ b/trollius/py33_exceptions.py
@@ -0,0 +1,144 @@
+__all__ = ['BlockingIOError', 'BrokenPipeError', 'ChildProcessError',
+ 'ConnectionRefusedError', 'ConnectionResetError',
+ 'InterruptedError', 'ConnectionAbortedError', 'PermissionError',
+ 'FileNotFoundError',
+ ]
+
+import errno
+import select
+import socket
+import sys
+try:
+ import ssl
+except ImportError:
+ ssl = None
+
+from .compat import PY33
+
+if PY33:
+ import builtins
+ BlockingIOError = builtins.BlockingIOError
+ BrokenPipeError = builtins.BrokenPipeError
+ ChildProcessError = builtins.ChildProcessError
+ ConnectionRefusedError = builtins.ConnectionRefusedError
+ ConnectionResetError = builtins.ConnectionResetError
+ InterruptedError = builtins.InterruptedError
+ ConnectionAbortedError = builtins.ConnectionAbortedError
+ PermissionError = builtins.PermissionError
+ FileNotFoundError = builtins.FileNotFoundError
+ ProcessLookupError = builtins.ProcessLookupError
+
+else:
+ # Python < 3.3
+ class BlockingIOError(OSError):
+ pass
+
+ class BrokenPipeError(OSError):
+ pass
+
+ class ChildProcessError(OSError):
+ pass
+
+ class ConnectionRefusedError(OSError):
+ pass
+
+ class InterruptedError(OSError):
+ pass
+
+ class ConnectionResetError(OSError):
+ pass
+
+ class ConnectionAbortedError(OSError):
+ pass
+
+ class PermissionError(OSError):
+ pass
+
+ class FileNotFoundError(OSError):
+ pass
+
+ class ProcessLookupError(OSError):
+ pass
+
+
+_MAP_ERRNO = {
+ errno.EACCES: PermissionError,
+ errno.EAGAIN: BlockingIOError,
+ errno.EALREADY: BlockingIOError,
+ errno.ECHILD: ChildProcessError,
+ errno.ECONNABORTED: ConnectionAbortedError,
+ errno.ECONNREFUSED: ConnectionRefusedError,
+ errno.ECONNRESET: ConnectionResetError,
+ errno.EINPROGRESS: BlockingIOError,
+ errno.EINTR: InterruptedError,
+ errno.ENOENT: FileNotFoundError,
+ errno.EPERM: PermissionError,
+ errno.EPIPE: BrokenPipeError,
+ errno.ESHUTDOWN: BrokenPipeError,
+ errno.EWOULDBLOCK: BlockingIOError,
+ errno.ESRCH: ProcessLookupError,
+}
+
+if sys.platform == 'win32':
+ from trollius import _overlapped
+ _MAP_ERRNO.update({
+ _overlapped.ERROR_CONNECTION_REFUSED: ConnectionRefusedError,
+ _overlapped.ERROR_CONNECTION_ABORTED: ConnectionAbortedError,
+ _overlapped.ERROR_NETNAME_DELETED: ConnectionResetError,
+ })
+
+
+def get_error_class(key, default):
+ return _MAP_ERRNO.get(key, default)
+
+
+if sys.version_info >= (3,):
+ def reraise(tp, value, tb=None):
+ if value.__traceback__ is not tb:
+ raise value.with_traceback(tb)
+ raise value
+else:
+ exec("""def reraise(tp, value, tb=None):
+ raise tp, value, tb
+""")
+
+
+def _wrap_error(exc, mapping, key):
+ if key not in mapping:
+ return
+ new_err_cls = mapping[key]
+ new_err = new_err_cls(*exc.args)
+
+ # raise a new exception with the original traceback
+ if hasattr(exc, '__traceback__'):
+ traceback = exc.__traceback__
+ else:
+ traceback = sys.exc_info()[2]
+ reraise(new_err_cls, new_err, traceback)
+
+
+if not PY33:
+ def wrap_error(func, *args, **kw):
+ """
+ Wrap socket.error, IOError, OSError, select.error to raise new specialized
+ exceptions of Python 3.3 like InterruptedError (PEP 3151).
+ """
+ try:
+ return func(*args, **kw)
+ except (socket.error, IOError, OSError) as exc:
+ if ssl is not None and isinstance(exc, ssl.SSLError):
+ raise
+ if hasattr(exc, 'winerror'):
+ _wrap_error(exc, _MAP_ERRNO, exc.winerror)
+ # _MAP_ERRNO does not contain all Windows errors.
+ # For some errors like "file not found", exc.errno should
+ # be used (ex: ENOENT).
+ _wrap_error(exc, _MAP_ERRNO, exc.errno)
+ raise
+ except select.error as exc:
+ if exc.args:
+ _wrap_error(exc, _MAP_ERRNO, exc.args[0])
+ raise
+else:
+ def wrap_error(func, *args, **kw):
+ return func(*args, **kw)