Exemple #1
0
   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)
Exemple #4
0
   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
Exemple #5
0
    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
Exemple #9
0
    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)
Exemple #10
0
    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)
Exemple #11
0
    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
Exemple #12
0
   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
Exemple #13
0
   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
Exemple #14
0
    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