def call(self, procedure, *args, **kwargs): """ Implements :func:`autobahn.wamp.interfaces.ICaller.call` """ if six.PY2 and type(procedure) == str: procedure = six.u(procedure) assert(isinstance(procedure, six.text_type)) if not self._transport: raise exception.TransportLost() request = util.id() if 'options' in kwargs and isinstance(kwargs['options'], types.CallOptions): opts = kwargs.pop('options') msg = message.Call(request, procedure, args = args, kwargs = kwargs, **opts.options) else: opts = None msg = message.Call(request, procedure, args = args, kwargs = kwargs) ## FIXME #def canceller(_d): # cancel_msg = message.Cancel(request) # self._transport.send(cancel_msg) #d = Deferred(canceller) d = self._create_future() self._call_reqs[request] = d, opts self._transport.send(msg) return d
def subscribe(self, handler, topic=None, options=None): """ Implements :func:`autobahn.wamp.interfaces.ISubscriber.subscribe` """ if six.PY2 and type(topic) == str: topic = six.u(topic) assert (topic is None or type(topic) == six.text_type) assert ((callable(handler) and topic is not None) or hasattr(handler, '__class__')) assert (options is None or isinstance(options, dict)) if not self._transport: raise exception.TransportLost() if callable(handler): # subscribe a single handler return self._subscribe(None, handler, topic, options) else: # subscribe all methods on an object decorated with "wamp.subscribe" on_replies = [] for k in inspect.getmembers(handler.__class__, is_method_or_function): proc = k[1] wampuris = filter(lambda x: x.is_handler(), proc.__dict__.get("_wampuris")) or () for pat in wampuris: subopts = pat.options or options or types.SubscribeOptions( match=u"wildcard" if pat.uri_type == uri.Pattern. URI_TYPE_WILDCARD else u"exact").message_attr() on_replies.append( self._subscribe(handler, proc, pat.uri(), subopts)) return txaio.gather(on_replies, consume_exceptions=True)
def _unsubscribe(self, subscription): """ Called from :meth:`autobahn.wamp.protocol.Subscription.unsubscribe` """ assert (isinstance(subscription, Subscription)) assert subscription.active assert (subscription.id in self._subscriptions) assert (subscription in self._subscriptions[subscription.id]) if not self._transport: raise exception.TransportLost() # remove handler subscription and mark as inactive self._subscriptions[subscription.id].remove(subscription) subscription.active = False # number of handler subscriptions left .. scount = len(self._subscriptions[subscription.id]) if scount == 0: # if the last handler was removed, unsubscribe from broker .. request_id = self._request_id_gen.next() on_reply = txaio.create_future() self._unsubscribe_reqs[request_id] = UnsubscribeRequest( request_id, on_reply, subscription.id) msg = message.Unsubscribe(request_id, subscription.id) self._transport.send(msg) return on_reply else: # there are still handlers active on the subscription! return txaio.create_future_success(scount)
def publish(self, topic, *args, **kwargs): """ Implements :func:`autobahn.wamp.interfaces.IPublisher.publish` """ if six.PY2 and type(topic) == str: topic = six.u(topic) assert(type(topic) == six.text_type) if not self._transport: raise exception.TransportLost() request = util.id() if 'options' in kwargs and isinstance(kwargs['options'], types.PublishOptions): opts = kwargs.pop('options') msg = message.Publish(request, topic, args = args, kwargs = kwargs, **opts.options) else: opts = None msg = message.Publish(request, topic, args = args, kwargs = kwargs) if opts and opts.options['acknowledge'] == True: d = self._create_future() self._publish_reqs[request] = d, opts self._transport.send(msg) return d else: self._transport.send(msg) return
def subscribe(self, handler, topic=None, options=None): """ Implements :func:`autobahn.wamp.interfaces.ISubscriber.subscribe` """ assert ((callable(handler) and topic is not None) or hasattr(handler, '__class__')) if topic and six.PY2 and type(topic) == str: topic = six.u(topic) assert (topic is None or type(topic) == six.text_type) assert (options is None or isinstance(options, types.SubscribeOptions)) if not self._transport: raise exception.TransportLost() def _subscribe(obj, fn, topic, options): request_id = util.id() on_reply = txaio.create_future() handler_obj = Handler(fn, obj, options.details_arg if options else None) self._subscribe_reqs[request_id] = SubscribeRequest( request_id, on_reply, handler_obj) if options: msg = message.Subscribe(request_id, topic, **options.message_attr()) else: msg = message.Subscribe(request_id, topic) self._transport.send(msg) return on_reply if callable(handler): # subscribe a single handler return _subscribe(None, handler, topic, options) else: # subscribe all methods on an object decorated with "wamp.subscribe" on_replies = [] for k in inspect.getmembers(handler.__class__, is_method_or_function): proc = k[1] if "_wampuris" in proc.__dict__: pat = proc.__dict__["_wampuris"][0] if pat.is_handler(): uri = pat.uri() subopts = options or pat.subscribe_options() on_replies.append( _subscribe(handler, proc, uri, subopts)) # XXX needs coverage return txaio.gather(on_replies, consume_exceptions=True)
def register(self, endpoint, procedure=None, options=None): """ Implements :func:`autobahn.wamp.interfaces.ICallee.register` """ assert ((callable(endpoint) and procedure is not None) or hasattr(endpoint, '__class__')) if procedure and six.PY2 and type(procedure) == str: procedure = six.u(procedure) assert (procedure is None or type(procedure) == six.text_type) assert (options is None or isinstance(options, types.RegisterOptions)) if not self._transport: raise exception.TransportLost() def _register(obj, fn, procedure, options): request_id = self._request_id_gen.next() on_reply = txaio.create_future() endpoint_obj = Endpoint(fn, obj, options.details_arg if options else None) self._register_reqs[request_id] = RegisterRequest( request_id, on_reply, procedure, endpoint_obj) if options: msg = message.Register(request_id, procedure, **options.message_attr()) else: msg = message.Register(request_id, procedure) self._transport.send(msg) return on_reply if callable(endpoint): # register a single callable return _register(None, endpoint, procedure, options) else: # register all methods on an object decorated with "wamp.register" on_replies = [] for k in inspect.getmembers(endpoint.__class__, is_method_or_function): proc = k[1] if "_wampuris" in proc.__dict__: for pat in proc.__dict__["_wampuris"]: if pat.is_endpoint(): uri = pat.uri() on_replies.append( _register(endpoint, proc, uri, options)) # XXX neds coverage return txaio.gather(on_replies, consume_exceptions=True)
def call(self, procedure, *args, **kwargs): """ Implements :func:`autobahn.wamp.interfaces.ICaller.call` """ if six.PY2 and type(procedure) == str: procedure = six.u(procedure) assert (isinstance(procedure, six.text_type)) if not self._transport: raise exception.TransportLost() request_id = self._request_id_gen.next() if 'options' in kwargs and isinstance(kwargs['options'], types.CallOptions): options = kwargs.pop('options') msg = message.Call(request_id, procedure, args=args, kwargs=kwargs, **options.message_attr()) else: options = None msg = message.Call(request_id, procedure, args=args, kwargs=kwargs) # FIXME # def canceller(_d): # cancel_msg = message.Cancel(request) # self._transport.send(cancel_msg) # d = Deferred(canceller) on_reply = txaio.create_future() self._call_reqs[request_id] = CallRequest(request_id, on_reply, options) try: # Notes: # # * this might raise autobahn.wamp.exception.SerializationError # when the user payload cannot be serialized # * we have to setup a PublishRequest() in _publish_reqs _before_ # calling transpor.send(), because a mock- or side-by-side transport # will immediately lead on an incoming WAMP message in onMessage() # self._transport.send(msg) except: if request_id in self._call_reqs: del self._call_reqs[request_id] raise return on_reply
def publish(self, topic, *args, **kwargs): """ Implements :func:`autobahn.wamp.interfaces.IPublisher.publish` """ if six.PY2 and type(topic) == str: topic = six.u(topic) assert (type(topic) == six.text_type) if not self._transport: raise exception.TransportLost() request_id = self._request_id_gen.next() if 'options' in kwargs and isinstance(kwargs['options'], types.PublishOptions): options = kwargs.pop('options') msg = message.Publish(request_id, topic, args=args, kwargs=kwargs, **options.message_attr()) else: options = None msg = message.Publish(request_id, topic, args=args, kwargs=kwargs) if options and options.acknowledge: # only acknowledged publications expect a reply .. on_reply = txaio.create_future() self._publish_reqs[request_id] = PublishRequest( request_id, on_reply) else: on_reply = None try: # Notes: # # * this might raise autobahn.wamp.exception.SerializationError # when the user payload cannot be serialized # * we have to setup a PublishRequest() in _publish_reqs _before_ # calling transpor.send(), because a mock- or side-by-side transport # will immediately lead on an incoming WAMP message in onMessage() # self._transport.send(msg) except Exception as e: if request_id in self._publish_reqs: del self._publish_reqs[request_id] raise e return on_reply
def register(self, endpoint, procedure=None, options=None): """ Implements :func:`autobahn.wamp.interfaces.ICallee.register` """ assert ((callable(endpoint) and procedure is not None) or hasattr(endpoint, '__class__')) if procedure and six.PY2 and type(procedure) == str: procedure = six.u(procedure) assert (procedure is None or type(procedure) == six.text_type) assert (options is None or isinstance(options, types.RegisterOptions)) if not self._transport: raise exception.TransportLost() def _register(obj, endpoint, procedure, options): request = util.id() d = self._create_future() self._register_reqs[request] = (d, obj, endpoint, procedure, options) if options is not None: msg = message.Register(request, procedure, **options.options) else: msg = message.Register(request, procedure) self._transport.send(msg) return d if callable(endpoint): ## register a single callable ## return _register(None, endpoint, procedure, options) else: ## register all methods on an object ## decorated with "wamp.procedure" ## dl = [] test = lambda x: inspect.ismethod(x) or inspect.isfunction(x) for k in inspect.getmembers(endpoint.__class__, test): proc = k[1] if "_wampuris" in proc.__dict__: pat = proc.__dict__["_wampuris"][0] if pat.is_endpoint(): uri = pat.uri() dl.append(_register(endpoint, proc, uri, options)) return self._gather_futures(dl, consume_exceptions=True)
def subscribe(self, handler, topic=None, options=None): """ Implements :func:`autobahn.wamp.interfaces.ISubscriber.subscribe` """ assert ((callable(handler) and topic is not None) or hasattr(handler, '__class__')) if topic and six.PY2 and type(topic) == str: topic = six.u(topic) assert (topic is None or type(topic) == six.text_type) assert (options is None or isinstance(options, types.SubscribeOptions)) if not self._transport: raise exception.TransportLost() def _subscribe(obj, handler, topic, options): request = util.id() d = self._create_future() self._subscribe_reqs[request] = (d, obj, handler, topic, options) if options is not None: msg = message.Subscribe(request, topic, **options.options) else: msg = message.Subscribe(request, topic) self._transport.send(msg) return d if callable(handler): ## register a single handler ## return _subscribe(None, handler, topic, options) else: ## register all methods on an object ## decorated with "wamp.topic" ## dl = [] test = lambda x: inspect.ismethod(x) or inspect.isfunction(x) for k in inspect.getmembers(handler.__class__, test): proc = k[1] if "_wampuris" in proc.__dict__: pat = proc.__dict__["_wampuris"][0] if pat.is_handler(): uri = pat.uri() dl.append(_subscribe(handler, proc, uri, options)) return self._gather_futures(dl, consume_exceptions=True)
def call(self, procedure, *args, **kwargs): """ Reimplemented to support calls with custom options """ if not self._transport: raise exception.TransportLost() request_id = random.randint(0, 9007199254740992) on_reply = txaio.create_future() self._call_reqs[request_id] = CallRequest(request_id, procedure, on_reply, {}) try: self._transport.send(AkCall(request_id, procedure, args, kwargs)) except Exception as e: if request_id in self._call_reqs: del self._call_reqs[request_id] raise e return on_reply
def _unregister(self, registration): """ Called from :meth:`autobahn.wamp.protocol.Registration.unregister` """ assert(isinstance(registration, Registration)) assert registration.active assert(registration.id in self._registrations) if not self._transport: raise exception.TransportLost() request = util.id() d = self._create_future() self._unregister_reqs[request] = (d, registration) msg = message.Unregister(request, registration.id) self._transport.send(msg) return d
def _unsubscribe(self, subscription): """ Called from :meth:`autobahn.wamp.protocol.Subscription.unsubscribe` """ assert(isinstance(subscription, Subscription)) assert subscription.active assert(subscription.id in self._subscriptions) if not self._transport: raise exception.TransportLost() request = util.id() d = self._create_future() self._unsubscribe_reqs[request] = (d, subscription) msg = message.Unsubscribe(request, subscription.id) self._transport.send(msg) return d
def _unregister(self, registration): """ Called from :meth:`autobahn.wamp.protocol.Registration.unregister` """ assert(isinstance(registration, Registration)) assert registration.active assert(registration.id in self._registrations) if not self._transport: raise exception.TransportLost() request_id = self._request_id_gen.next() on_reply = txaio.create_future() self._unregister_reqs[request_id] = UnregisterRequest(request_id, on_reply, registration.id) msg = message.Unregister(request_id, registration.id) self._transport.send(msg) return on_reply
def call(self, procedure, *args, **kwargs): """ Reimplemented to support calls with custom options """ if six.PY2 and type(procedure) == str: procedure = six.u(procedure) assert(isinstance(procedure, six.text_type)) if not self._transport: raise exception.TransportLost() request_id = util.id() on_reply = txaio.create_future() self._call_reqs[request_id] = CallRequest(request_id, procedure, on_reply, {}) try: self._transport.send(AkCall(request_id, procedure, args, kwargs)) except Exception as e: if request_id in self._call_reqs: del self._call_reqs[request_id] raise e return on_reply