summaryrefslogtreecommitdiffstats
path: root/src/console/zmq/sugar/context.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/console/zmq/sugar/context.py')
-rwxr-xr-xsrc/console/zmq/sugar/context.py192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/console/zmq/sugar/context.py b/src/console/zmq/sugar/context.py
new file mode 100755
index 00000000..86a9c5dc
--- /dev/null
+++ b/src/console/zmq/sugar/context.py
@@ -0,0 +1,192 @@
+# coding: utf-8
+"""Python bindings for 0MQ."""
+
+# Copyright (C) PyZMQ Developers
+# Distributed under the terms of the Modified BSD License.
+
+import atexit
+import weakref
+
+from zmq.backend import Context as ContextBase
+from . import constants
+from .attrsettr import AttributeSetter
+from .constants import ENOTSUP, ctx_opt_names
+from .socket import Socket
+from zmq.error import ZMQError
+
+from zmq.utils.interop import cast_int_addr
+
+
+class Context(ContextBase, AttributeSetter):
+ """Create a zmq Context
+
+ A zmq Context creates sockets via its ``ctx.socket`` method.
+ """
+ sockopts = None
+ _instance = None
+ _shadow = False
+ _exiting = False
+
+ def __init__(self, io_threads=1, **kwargs):
+ super(Context, self).__init__(io_threads=io_threads, **kwargs)
+ if kwargs.get('shadow', False):
+ self._shadow = True
+ else:
+ self._shadow = False
+ self.sockopts = {}
+
+ self._exiting = False
+ if not self._shadow:
+ ctx_ref = weakref.ref(self)
+ def _notify_atexit():
+ ctx = ctx_ref()
+ if ctx is not None:
+ ctx._exiting = True
+ atexit.register(_notify_atexit)
+
+ def __del__(self):
+ """deleting a Context should terminate it, without trying non-threadsafe destroy"""
+ if not self._shadow and not self._exiting:
+ self.term()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.term()
+
+ @classmethod
+ def shadow(cls, address):
+ """Shadow an existing libzmq context
+
+ address is the integer address of the libzmq context
+ or an FFI pointer to it.
+
+ .. versionadded:: 14.1
+ """
+ address = cast_int_addr(address)
+ return cls(shadow=address)
+
+ @classmethod
+ def shadow_pyczmq(cls, ctx):
+ """Shadow an existing pyczmq context
+
+ ctx is the FFI `zctx_t *` pointer
+
+ .. versionadded:: 14.1
+ """
+ from pyczmq import zctx
+
+ underlying = zctx.underlying(ctx)
+ address = cast_int_addr(underlying)
+ return cls(shadow=address)
+
+ # static method copied from tornado IOLoop.instance
+ @classmethod
+ def instance(cls, io_threads=1):
+ """Returns a global Context instance.
+
+ Most single-threaded applications have a single, global Context.
+ Use this method instead of passing around Context instances
+ throughout your code.
+
+ A common pattern for classes that depend on Contexts is to use
+ a default argument to enable programs with multiple Contexts
+ but not require the argument for simpler applications:
+
+ class MyClass(object):
+ def __init__(self, context=None):
+ self.context = context or Context.instance()
+ """
+ if cls._instance is None or cls._instance.closed:
+ cls._instance = cls(io_threads=io_threads)
+ return cls._instance
+
+ #-------------------------------------------------------------------------
+ # Hooks for ctxopt completion
+ #-------------------------------------------------------------------------
+
+ def __dir__(self):
+ keys = dir(self.__class__)
+
+ for collection in (
+ ctx_opt_names,
+ ):
+ keys.extend(collection)
+ return keys
+
+ #-------------------------------------------------------------------------
+ # Creating Sockets
+ #-------------------------------------------------------------------------
+
+ @property
+ def _socket_class(self):
+ return Socket
+
+ def socket(self, socket_type):
+ """Create a Socket associated with this Context.
+
+ Parameters
+ ----------
+ socket_type : int
+ The socket type, which can be any of the 0MQ socket types:
+ REQ, REP, PUB, SUB, PAIR, DEALER, ROUTER, PULL, PUSH, etc.
+ """
+ if self.closed:
+ raise ZMQError(ENOTSUP)
+ s = self._socket_class(self, socket_type)
+ for opt, value in self.sockopts.items():
+ try:
+ s.setsockopt(opt, value)
+ except ZMQError:
+ # ignore ZMQErrors, which are likely for socket options
+ # that do not apply to a particular socket type, e.g.
+ # SUBSCRIBE for non-SUB sockets.
+ pass
+ return s
+
+ def setsockopt(self, opt, value):
+ """set default socket options for new sockets created by this Context
+
+ .. versionadded:: 13.0
+ """
+ self.sockopts[opt] = value
+
+ def getsockopt(self, opt):
+ """get default socket options for new sockets created by this Context
+
+ .. versionadded:: 13.0
+ """
+ return self.sockopts[opt]
+
+ def _set_attr_opt(self, name, opt, value):
+ """set default sockopts as attributes"""
+ if name in constants.ctx_opt_names:
+ return self.set(opt, value)
+ else:
+ self.sockopts[opt] = value
+
+ def _get_attr_opt(self, name, opt):
+ """get default sockopts as attributes"""
+ if name in constants.ctx_opt_names:
+ return self.get(opt)
+ else:
+ if opt not in self.sockopts:
+ raise AttributeError(name)
+ else:
+ return self.sockopts[opt]
+
+ def __delattr__(self, key):
+ """delete default sockopts as attributes"""
+ key = key.upper()
+ try:
+ opt = getattr(constants, key)
+ except AttributeError:
+ raise AttributeError("no such socket option: %s" % key)
+ else:
+ if opt not in self.sockopts:
+ raise AttributeError(key)
+ else:
+ del self.sockopts[opt]
+
+__all__ = ['Context']