Exemple #1
0
 class __Server:
     def __init__(self):
         scheduler = IOLoopScheduler(IOLoop.current())
         self.messages = Subject()
         only_messages = self.messages.filter(lambda msg: msg[
             0] == 'message').map(lambda msg: msg[1]).publish()
         only_messages.subscribe(lambda msg: print(msg))
         only_messages.connect()
         self._app = Application([
             (r'/exchange', ExchangeHandler),
             (r'/', MainHandler),
         ])
Exemple #2
0
    class __Server:
        def __init__(self):
            scheduler = IOLoopScheduler(IOLoop.current())
            self._app = make_app()
            self.messages = Subject()
            only_messages = self.messages.filter(lambda msg: msg[
                0] == 'message').map(lambda msg: msg[1]).publish()
            only_messages.subscribe(lambda msg: print(msg))
            only_messages.connect()

        def start(self):
            self._app.listen(8888)
Exemple #3
0
    class Instance:
        def __init__(self):
            scheduler = IOLoopScheduler(IOLoop.current())
            self._app = Application([
                (r'/exchange', ExchangeHandler),
            ])
            self._servers = [
                ['localhost', '8888'],
                ['localhost', '7777'],
            ]
            self._current_server = 0

            self.messages = Subject()

            def passthrough_to_matching_server(msg):
                if self.matching_server_connection is None:
                    print('server is DOWN')
                    return
                self.matching_server_connection.write_message(msg)

            self.only_messages = self.messages.filter(lambda msg: msg[0] == 'message').map(lambda msg: msg[1]).subscribe(passthrough_to_matching_server)

        def connect_to_server(self, host, port):
            def on_connect(conn):
                self.matching_server_connection = conn
                print("Connected to matching server")

            def on_message_callback(message):
                if message is None:
                    self.matching_server_connection = None
                    self.connect_to_server()
                else:
                    self.message.on_next(message)

            future = websocket_connect(
                'ws://{}:{}/exchange'.format(host, port),
                on_message_callback=on_message_callback
            )
            Observable.from_future(future).subscribe(on_connect, lambda error: self.connect_to_next_server())

        def connect_to_next_server(self):
            print('Could not connecto to server, finding next server')
            if self._current_server == len(self._servers) - 1:
                self._current_server = 0
            else:
                self._current_server += 1
            self.connect_to_server(*self._servers[self._current_server])

        def start(self):
            self.connect_to_server(*self._servers[self._current_server])
            print('Starting transaction server on port 9999')
            self._app.listen(9999)
    class __Server:
        def __init__(self):
            scheduler = IOLoopScheduler(IOLoop.current())
            self._app = make_app()
            self.orders = PriorityQueue()
            self.posted_orders = []
            self.fulfilled_orders = []

            self.messages = Subject()

            only_messages = self.messages.filter(lambda msg: msg[0] == 'message')\
                .map(lambda msg : msg[1].split(',')).publish()

            def queue_order(msg):
                self.orders.put(Order.from_list(msg))


            only_messages \
                .filter(lambda msg: msg[0] == 'order') \
                .map(lambda msg : msg[1:])\
                .subscribe(queue_order)

            def process_order(time):
                try:
                    order = self.orders.get_nowait()
                    print('processing order: {} [{}]'.format(
                        order, order.timestamp))
                    matching = None
                    for posted in self.posted_orders:
                        if posted.matches(order):
                            matching = posted
                            break

                    if matching is None:
                        self.posted_orders.append(order)
                        print('could not find match, posted order count is {}'.
                              format(len(self.posted_orders)))
                    else:
                        self.posted_orders.remove(posted)
                        self.fulfilled_orders.append(posted)
                        self.fulfilled_orders.append(order)
                        print('order fulfilled: {}'.format(order))
                        print('fulfilled by: {}'.format(posted))
                except QueueEmpty:
                    pass

            Observable.interval(100,
                                scheduler=scheduler).subscribe(process_order)
            only_messages.connect()

        def start(self):
            self._app.listen(8888)
Exemple #5
0
    class __Server:
        def __init__(self):
            scheduler = IOLoopScheduler(IOLoop.current())
            self.messages = Subject()
            only_messages = self.messages.filter(lambda message: message[0] == 'message')\
                .map(lambda message : message[1])\
                .publish()

            only_messages.subscribe(lambda message: print(message))
            only_messages.connect()

            self.__app = Application([
                (r'/exchange', ExchangeHandler),
                (r'/', MainHandler),
            ])

        def start(self):
            self.__app.listen(8888)
Exemple #6
0
    def resolve_new_message(self, info, token, room_id, **kwargs):
        user = shortcuts.get_user_by_token(token)
        user_id = user.pk

        room = Room.objects.get(pk=room_id)
        room.members.get(pk=user.pk)

        source = Subject()

        def handler(event):
            if event is not None:
                source.on_next(event)

        pubsub = redis_client.pubsub()
        pubsub.subscribe(**{f'room-{room_id}': handler})

        pubsub.run_in_thread(sleep_time=0.001)

        return source.filter(lambda event: isinstance(event['data'], bytes))\
                     .map(lambda event: json.loads(event['data'].decode()))\
                     .filter(lambda event: event['type'] == 'NEW_MESSAGE')\
                     .map(lambda event: Message.objects.get(pk=event['pk']))\
                     .filter(lambda message: message.room.pk == room_id)
Exemple #7
0
    if VARS['sock'] is None:
        raise RuntimeError('Not connected')
    msg = merge(_msg, {'from': VARS['endpoint_id']})
    VARS['sock'].write_message(json.dumps(msg))


def respond(recipient, msg_id, params):
    """respond to a request"""
    VARS['message_queue'].on_next({
        'method': 'request.response',
        'to': recipient,
        'id': msg_id,
        'data': params
    })


def map_req_to_req_stream(request):
    """incoming requests get mapped to the request stream"""
    topic = request['data']['topic']
    params = request['data'].setdefault('params')

    @once
    def _respond(params):
        return respond(request['from'], request['id'], params)

    return {'topic': topic, 'params': params, 'respond': _respond}


request_stream = (EVENT_SOURCE.filter(
    lambda evt: evt['method'] == 'request').map(map_req_to_req_stream))
Exemple #8
0
from rx import Observable, Observer
from rx.subjects import Subject

AA = Subject()

aa = AA.filter(lambda s: s == 'A') \
    .map(lambda s: s.lower()).publish()

aa.subscribe(lambda a: print(a))
AA.subscribe(lambda a: print("{}".format(2)))

aa.connect()
Observable.from_("A,B,C,D,D,E,F,G,H".split(','))\
    .subscribe(AA.on_next)

for s in "A,B,C,D,D,E,F,G,H":
    AA.on_next(s)
import pytest
from datetime import datetime

from rx import Observable
from rx.subjects import Subject

# All test coroutines will be treated as marked.
pytestmark = pytest.mark.asyncio

# notifies all stream how testing goes on
testingStatusStream = Subject()

entitlementStatusStream = Subject()
subscriptionManagerStream = Subject()
entitlementStatusesDuringTest = entitlementStatusStream\
                                .take_until(testingStatusStream.filter(lambda x: x == 'testing finished').take(1)) \
                                .reduce(lambda acc,x: acc + [x['msg']],[])


async def consume(baseurl, path, stream):
    async with websockets.connect(urljoin(baseurl, path)) as ws:
        async for msg in ws:
            #print('new msg arrived')
            #print(json.loads(msg))
            stream.on_next({'ws': ws, 'path': path, 'msg': json.loads(msg)})


@pytest.yield_fixture()
def event_loop():
    loop = asyncio.get_event_loop()
Exemple #10
0
class ExposedThing(object):
    """An entity that serves to define the behavior of a Thing.
    An application uses this class when it acts as the Thing 'server'."""
    class HandlerKeys(EnumListMixin):
        """Enumeration of handler keys."""

        RETRIEVE_PROPERTY = "retrieve_property"
        UPDATE_PROPERTY = "update_property"
        INVOKE_ACTION = "invoke_action"
        OBSERVE = "observe"

    class InteractionStateKeys(EnumListMixin):
        """Enumeration of interaction state keys."""

        PROPERTY_VALUES = "property_values"

    def __init__(self, servient, thing):
        self._servient = servient
        self._thing = thing

        self._interaction_states = {
            self.InteractionStateKeys.PROPERTY_VALUES: {}
        }

        self._handlers_global = {
            self.HandlerKeys.RETRIEVE_PROPERTY:
            self._default_retrieve_property_handler,
            self.HandlerKeys.UPDATE_PROPERTY:
            self._default_update_property_handler,
            self.HandlerKeys.INVOKE_ACTION: self._default_invoke_action_handler
        }

        self._handlers = {
            self.HandlerKeys.RETRIEVE_PROPERTY: {},
            self.HandlerKeys.UPDATE_PROPERTY: {},
            self.HandlerKeys.INVOKE_ACTION: {}
        }

        self._events_stream = Subject()

    def __str__(self):
        return "<{}> {}".format(self.__class__.__name__, self.id)

    def __eq__(self, other):
        return self.servient == other.servient and self.thing == other.thing

    def __hash__(self):
        return hash((self.servient, self.thing))

    def __getattr__(self, name):
        """Search for members that raised an AttributeError in
        the private Thing instance before propagating the exception."""

        return getattr(self.thing, name)

    def __setattr__(self, name, value):
        """Setter for ThingFragment attributes."""

        name_camel = to_camel(name)

        if name_camel not in Thing.THING_FRAGMENT_WRITABLE_FIELDS:
            return super(ExposedThing, self).__setattr__(name, value)

        return self._thing.__setattr__(name, value)

    def _set_property_value(self, prop, value):
        """Sets a Property value."""

        prop_values = self.InteractionStateKeys.PROPERTY_VALUES
        self._interaction_states[prop_values][prop] = value

    def _get_property_value(self, prop):
        """Returns a Property value."""

        prop_values = self.InteractionStateKeys.PROPERTY_VALUES
        return self._interaction_states[prop_values].get(prop, None)

    def _set_handler(self, handler_type, handler, interaction=None):
        """Sets the currently defined handler for the given handler type."""

        if interaction is None or handler_type not in self._handlers:
            self._handlers_global[handler_type] = handler
        else:
            self._handlers[handler_type][interaction] = handler

    def _get_handler(self, handler_type, interaction=None):
        """Returns the currently defined handler for the given handler type."""

        interaction_handler = self._handlers.get(handler_type,
                                                 {}).get(interaction, None)
        return interaction_handler or self._handlers_global[handler_type]

    def _find_interaction(self, name):
        """Raises ValueError if the given interaction does not exist in this Thing."""

        interaction = self._thing.find_interaction(name=name)

        if not interaction:
            raise ValueError("Interaction not found: {}".format(name))

        return interaction

    def _default_retrieve_property_handler(self, property_name):
        """Default handler for property reads."""

        future_read = Future()
        prop = self._find_interaction(name=property_name)
        prop_value = self._get_property_value(prop)
        future_read.set_result(prop_value)

        return future_read

    def _default_update_property_handler(self, property_name, value):
        """Default handler for onUpdateProperty."""

        future_write = Future()
        prop = self._find_interaction(name=property_name)
        self._set_property_value(prop, value)
        future_write.set_result(None)

        return future_write

    # noinspection PyMethodMayBeStatic,PyUnusedLocal
    def _default_invoke_action_handler(self, parameters):
        """Default handler for onInvokeAction."""

        future_invoke = Future()
        future_invoke.set_exception(
            NotImplementedError("Undefined action handler"))

        return future_invoke

    @property
    def id(self):
        """Returns the ID of the Thing."""

        return self.thing.id

    @property
    def servient(self):
        """Servient that contains this ExposedThing."""

        return self._servient

    @property
    def thing(self):
        """Returns the object that represents the Thing beneath this ExposedThing."""

        return self._thing

    @property
    def properties(self):
        """Returns a dictionary of ThingProperty items."""

        return ExposedThingPropertyDict(exposed_thing=self)

    @property
    def actions(self):
        """Returns a dictionary of ThingAction items."""

        return ExposedThingActionDict(exposed_thing=self)

    @property
    def events(self):
        """Returns a dictionary of ThingEvent items."""

        return ExposedThingEventDict(exposed_thing=self)

    @tornado.gen.coroutine
    def read_property(self, name):
        """Takes the Property name as the name argument, then requests from
        the underlying platform and the Protocol Bindings to retrieve the
        Property on the remote Thing and return the result. Returns a Future
        that resolves with the Property value or rejects with an Error."""

        proprty = self.thing.properties[name]

        handler = self._handlers.get(self.HandlerKeys.RETRIEVE_PROPERTY,
                                     {}).get(proprty, None)

        if handler:
            value = yield handler()
        else:
            value = yield self._default_retrieve_property_handler(name)

        raise tornado.gen.Return(value)

    @tornado.gen.coroutine
    def write_property(self, name, value):
        """Takes the Property name as the name argument and the new value as the
        value argument, then requests from the underlying platform and the Protocol
        Bindings to update the Property on the remote Thing and return the result.
        Returns a Future that resolves on success or rejects with an Error."""

        proprty = self.thing.properties[name]

        if not proprty.writable:
            raise TypeError("Property is non-writable")

        handler = self._handlers.get(self.HandlerKeys.UPDATE_PROPERTY,
                                     {}).get(proprty, None)

        if handler:
            yield handler(value)
        else:
            yield self._default_update_property_handler(name, value)

        event_init = PropertyChangeEventInit(name=name, value=value)
        self._events_stream.on_next(
            PropertyChangeEmittedEvent(init=event_init))

    @tornado.gen.coroutine
    def invoke_action(self, name, input_value=None):
        """Invokes an Action with the given parameters and yields with the invocation result."""

        action = self.thing.actions[name]

        handler = self._get_handler(
            handler_type=self.HandlerKeys.INVOKE_ACTION, interaction=action)

        result = yield handler({"input": input_value})

        event_init = ActionInvocationEventInit(action_name=name,
                                               return_value=result)
        emitted_event = ActionInvocationEmittedEvent(init=event_init)
        self._events_stream.on_next(emitted_event)

        raise tornado.gen.Return(result)

    def on_event(self, name):
        """Returns an Observable for the Event specified in the name argument,
        allowing subscribing to and unsubscribing from notifications."""

        if name not in self.thing.events:
            # noinspection PyUnresolvedReferences
            return Observable.throw(Exception("Unknown event"))

        def event_filter(item):
            return item.name == name

        # noinspection PyUnresolvedReferences
        return self._events_stream.filter(event_filter)

    def on_property_change(self, name):
        """Returns an Observable for the Property specified in the name argument,
        allowing subscribing to and unsubscribing from notifications."""

        try:
            interaction = self._find_interaction(name=name)
        except ValueError:
            # noinspection PyUnresolvedReferences
            return Observable.throw(Exception("Unknown property"))

        if not interaction.observable:
            # noinspection PyUnresolvedReferences
            return Observable.throw(Exception("Property is not observable"))

        def property_change_filter(item):
            return item.name == DefaultThingEvent.PROPERTY_CHANGE and \
                   item.data.name == name

        # noinspection PyUnresolvedReferences
        return self._events_stream.filter(property_change_filter)

    def on_td_change(self):
        """Returns an Observable, allowing subscribing to and unsubscribing
        from notifications to the Thing Description."""
        def td_change_filter(item):
            return item.name == DefaultThingEvent.DESCRIPTION_CHANGE

        # noinspection PyUnresolvedReferences
        return self._events_stream.filter(td_change_filter)

    def expose(self):
        """Start serving external requests for the Thing, so that
        WoT interactions using Properties, Actions and Events will be possible."""

        self._servient.enable_exposed_thing(self.thing.id)

    def destroy(self):
        """Stop serving external requests for the Thing and destroy the object.
        Note that eventual unregistering should be done before invoking this method."""

        self._servient.remove_exposed_thing(self.thing.id)

    def emit_event(self, event_name, payload):
        """Emits an the event initialized with the event name specified by
        the event_name argument and data specified by the payload argument."""

        if not self.thing.find_interaction(name=event_name):
            raise ValueError("Unknown event: {}".format(event_name))

        self._events_stream.on_next(EmittedEvent(name=event_name,
                                                 init=payload))

    def add_property(self, name, property_init, value=None):
        """Adds a Property defined by the argument and updates the Thing Description.
        Takes an instance of ThingPropertyInit as argument."""

        if isinstance(property_init, dict):
            property_init = PropertyFragmentDict(property_init)

        prop = Property(thing=self._thing, name=name, init_dict=property_init)

        self._thing.add_interaction(prop)
        self._set_property_value(prop, value)

        event_data = ThingDescriptionChangeEventInit(
            td_change_type=TDChangeType.PROPERTY,
            method=TDChangeMethod.ADD,
            name=name,
            data=property_init.to_dict(),
            description=ThingDescription.from_thing(self.thing).to_dict())

        self._events_stream.on_next(
            ThingDescriptionChangeEmittedEvent(init=event_data))

    def remove_property(self, name):
        """Removes the Property specified by the name argument,
        updates the Thing Description and returns the object."""

        self._thing.remove_interaction(name=name)

        event_data = ThingDescriptionChangeEventInit(
            td_change_type=TDChangeType.PROPERTY,
            method=TDChangeMethod.REMOVE,
            name=name)

        self._events_stream.on_next(
            ThingDescriptionChangeEmittedEvent(init=event_data))

    def add_action(self, name, action_init, action_handler=None):
        """Adds an Action to the Thing object as defined by the action
        argument of type ThingActionInit and updates th,e Thing Description."""

        if isinstance(action_init, dict):
            action_init = ActionFragmentDict(action_init)

        action = Action(thing=self._thing, name=name, init_dict=action_init)

        self._thing.add_interaction(action)

        event_data = ThingDescriptionChangeEventInit(
            td_change_type=TDChangeType.ACTION,
            method=TDChangeMethod.ADD,
            name=name,
            data=action_init.to_dict(),
            description=ThingDescription.from_thing(self.thing).to_dict())

        self._events_stream.on_next(
            ThingDescriptionChangeEmittedEvent(init=event_data))

        if action_handler:
            self.set_action_handler(name, action_handler)

    def remove_action(self, name):
        """Removes the Action specified by the name argument,
        updates the Thing Description and returns the object."""

        self._thing.remove_interaction(name=name)

        event_data = ThingDescriptionChangeEventInit(
            td_change_type=TDChangeType.ACTION,
            method=TDChangeMethod.REMOVE,
            name=name)

        self._events_stream.on_next(
            ThingDescriptionChangeEmittedEvent(init=event_data))

    def add_event(self, name, event_init):
        """Adds an event to the Thing object as defined by the event argument
        of type ThingEventInit and updates the Thing Description."""

        if isinstance(event_init, dict):
            event_init = EventFragmentDict(event_init)

        event = Event(thing=self._thing, name=name, init_dict=event_init)

        self._thing.add_interaction(event)

        event_data = ThingDescriptionChangeEventInit(
            td_change_type=TDChangeType.EVENT,
            method=TDChangeMethod.ADD,
            name=name,
            data=event_init.to_dict(),
            description=ThingDescription.from_thing(self.thing).to_dict())

        self._events_stream.on_next(
            ThingDescriptionChangeEmittedEvent(init=event_data))

    def remove_event(self, name):
        """Removes the event specified by the name argument,
        updates the Thing Description and returns the object."""

        self._thing.remove_interaction(name=name)

        event_data = ThingDescriptionChangeEventInit(
            td_change_type=TDChangeType.EVENT,
            method=TDChangeMethod.REMOVE,
            name=name)

        self._events_stream.on_next(
            ThingDescriptionChangeEmittedEvent(init=event_data))

    def set_action_handler(self, name, action_handler):
        """Takes name as string argument and action_handler as argument of type ActionHandler.
        Sets the handler function for the specified Action matched by name.
        Throws on error. Returns a reference to the same object for supporting chaining."""

        action = self.thing.actions[name]

        self._set_handler(handler_type=self.HandlerKeys.INVOKE_ACTION,
                          handler=action_handler,
                          interaction=action)

        return self

    def set_property_read_handler(self, name, read_handler):
        """Takes name as string argument and read_handler as argument of type PropertyReadHandler.
        Sets the handler function for reading the specified Property matched by name.
        Throws on error. Returns a reference to the same object for supporting chaining."""

        proprty = self.thing.properties[name]

        self._set_handler(handler_type=self.HandlerKeys.RETRIEVE_PROPERTY,
                          handler=read_handler,
                          interaction=proprty)

        return self

    def set_property_write_handler(self, name, write_handler):
        """Takes name as string argument and write_handler as argument of type PropertyWriteHandler.
        Sets the handler function for writing the specified Property matched by name.
        Throws on error. Returns a reference to the same object for supporting chaining."""

        proprty = self.thing.properties[name]

        self._set_handler(handler_type=self.HandlerKeys.UPDATE_PROPERTY,
                          handler=write_handler,
                          interaction=proprty)

        return self

    def subscribe(self, *args, **kwargs):
        """Subscribes to changes on the TD of this thing."""

        observable = self.on_td_change()
        return observable.subscribe_on(IOLoopScheduler()).subscribe(
            *args, **kwargs)