diff options
Diffstat (limited to 'trollius/py33_exceptions.py')
-rw-r--r-- | trollius/py33_exceptions.py | 144 |
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) |