error.py revision 781d71db
1"""0MQ Error classes and functions."""
2
3# Copyright (C) PyZMQ Developers
4# Distributed under the terms of the Modified BSD License.
5
6
7class ZMQBaseError(Exception):
8    """Base exception class for 0MQ errors in Python."""
9    pass
10
11class ZMQError(ZMQBaseError):
12    """Wrap an errno style error.
13
14    Parameters
15    ----------
16    errno : int
17        The ZMQ errno or None.  If None, then ``zmq_errno()`` is called and
18        used.
19    msg : string
20        Description of the error or None.
21    """
22    errno = None
23
24    def __init__(self, errno=None, msg=None):
25        """Wrap an errno style error.
26
27        Parameters
28        ----------
29        errno : int
30            The ZMQ errno or None.  If None, then ``zmq_errno()`` is called and
31            used.
32        msg : string
33            Description of the error or None.
34        """
35        from zmq.backend import strerror, zmq_errno
36        if errno is None:
37            errno = zmq_errno()
38        if isinstance(errno, int):
39            self.errno = errno
40            if msg is None:
41                self.strerror = strerror(errno)
42            else:
43                self.strerror = msg
44        else:
45            if msg is None:
46                self.strerror = str(errno)
47            else:
48                self.strerror = msg
49        # flush signals, because there could be a SIGINT
50        # waiting to pounce, resulting in uncaught exceptions.
51        # Doing this here means getting SIGINT during a blocking
52        # libzmq call will raise a *catchable* KeyboardInterrupt
53        # PyErr_CheckSignals()
54
55    def __str__(self):
56        return self.strerror
57
58    def __repr__(self):
59        return "ZMQError('%s')"%self.strerror
60
61
62class ZMQBindError(ZMQBaseError):
63    """An error for ``Socket.bind_to_random_port()``.
64
65    See Also
66    --------
67    .Socket.bind_to_random_port
68    """
69    pass
70
71
72class NotDone(ZMQBaseError):
73    """Raised when timeout is reached while waiting for 0MQ to finish with a Message
74
75    See Also
76    --------
77    .MessageTracker.wait : object for tracking when ZeroMQ is done
78    """
79    pass
80
81
82class ContextTerminated(ZMQError):
83    """Wrapper for zmq.ETERM
84
85    .. versionadded:: 13.0
86    """
87    pass
88
89
90class Again(ZMQError):
91    """Wrapper for zmq.EAGAIN
92
93    .. versionadded:: 13.0
94    """
95    pass
96
97
98def _check_rc(rc, errno=None):
99    """internal utility for checking zmq return condition
100
101    and raising the appropriate Exception class
102    """
103    if rc < 0:
104        from zmq.backend import zmq_errno
105        if errno is None:
106            errno = zmq_errno()
107        from zmq import EAGAIN, ETERM
108        if errno == EAGAIN:
109            raise Again(errno)
110        elif errno == ETERM:
111            raise ContextTerminated(errno)
112        else:
113            raise ZMQError(errno)
114
115_zmq_version_info = None
116_zmq_version = None
117
118class ZMQVersionError(NotImplementedError):
119    """Raised when a feature is not provided by the linked version of libzmq.
120
121    .. versionadded:: 14.2
122    """
123    min_version = None
124    def __init__(self, min_version, msg='Feature'):
125        global _zmq_version
126        if _zmq_version is None:
127            from zmq import zmq_version
128            _zmq_version = zmq_version()
129        self.msg = msg
130        self.min_version = min_version
131        self.version = _zmq_version
132
133    def __repr__(self):
134        return "ZMQVersionError('%s')" % str(self)
135
136    def __str__(self):
137        return "%s requires libzmq >= %s, have %s" % (self.msg, self.min_version, self.version)
138
139
140def _check_version(min_version_info, msg='Feature'):
141    """Check for libzmq
142
143    raises ZMQVersionError if current zmq version is not at least min_version
144
145    min_version_info is a tuple of integers, and will be compared against zmq.zmq_version_info().
146    """
147    global _zmq_version_info
148    if _zmq_version_info is None:
149        from zmq import zmq_version_info
150        _zmq_version_info = zmq_version_info()
151    if _zmq_version_info < min_version_info:
152        min_version = '.'.join(str(v) for v in min_version_info)
153        raise ZMQVersionError(min_version, msg)
154
155
156__all__ = [
157    'ZMQBaseError',
158    'ZMQBindError',
159    'ZMQError',
160    'NotDone',
161    'ContextTerminated',
162    'Again',
163    'ZMQVersionError',
164]
165