Example #1
0
    def test_get_params_with_consumer(self):
        client = WSClient(ordered=True)

        def consumer(message):
            message.content['method'] = 'FAKE'
            message.reply_channel.send({'text': dict(AsgiRequest(message).GET)})

        with apply_routes([route('websocket.receive', consumer, path=r'^/test'),
                           route('websocket.connect', consumer, path=r'^/test')]):
            path = '/test?key1=val1&key2=val2&key1=val3'
            client.send_and_consume('websocket.connect', path=path, check_accept=False)
            self.assertDictEqual(client.receive(), {'key2': ['val2'], 'key1': ['val1', 'val3']})

            client.send_and_consume('websocket.receive', path=path)
            self.assertDictEqual(client.receive(), {})
Example #2
0
    def test_get_params_with_consumer(self):
        client = WSClient(ordered=True)

        def consumer(message):
            message.content['method'] = 'FAKE'
            message.reply_channel.send({'text': dict(AsgiRequest(message).GET)})

        with apply_routes([route('websocket.receive', consumer, path=r'^/test'),
                           route('websocket.connect', consumer, path=r'^/test')]):
            path = '/test?key1=val1&key2=val2&key1=val3'
            client.send_and_consume('websocket.connect', path=path, check_accept=False)
            self.assertDictEqual(client.receive(), {'key2': ['val2'], 'key1': ['val1', 'val3']})

            client.send_and_consume('websocket.receive', path=path)
            self.assertDictEqual(client.receive(), {})
Example #3
0
    def test_list(self):

        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):

            for n in range(api_settings.DEFAULT_PAGE_SIZE + 1):
                TestModel.objects.create(name='Name-{}'.format(str(n)))

            json_content = self._send_and_consume('testmodel', {
                'action': 'list',
                'request_id': 'client-request-id',
                'data': None,
            })

            self.assertEqual(len(json_content['payload']['data']), api_settings.DEFAULT_PAGE_SIZE)

            json_content = self._send_and_consume('testmodel', {
                'action': 'list',
                'request_id': 'client-request-id',
                'data': {
                    'page': 2
                }
            })

            self.assertEqual(len(json_content['payload']['data']), 1)
            self.assertEqual('client-request-id', json_content['payload']['request_id'])
Example #4
0
    def test_trigger_outbound_delete(self):
        class TestBinding(WebsocketBinding):
            model = User
            stream = 'test'
            fields = ['username']

            def group_names(self, instance, action):
                return ["users3"]

            def has_permission(self, user, action, pk):
                return True

        user = User.objects.create(username='******', email='*****@*****.**')

        with apply_routes([route('test', TestBinding.consumer)]):
            client = HttpClient()
            client.join_group('users3')

            user.delete()

            received = client.receive()
            self.assertTrue('payload' in received)
            self.assertTrue('action' in received['payload'])
            self.assertTrue('data' in received['payload'])
            self.assertTrue('username' in received['payload']['data'])
            self.assertTrue('model' in received['payload'])
            self.assertTrue('pk' in received['payload'])

            self.assertEqual(received['payload']['action'], 'delete')
            self.assertEqual(received['payload']['model'], 'auth.user')
            self.assertEqual(received['payload']['pk'], 1)
            self.assertEqual(received['payload']['data']['username'], 'test')

            received = client.receive()
            self.assertIsNone(received)
Example #5
0
    def test_graceful_stop_when_waiting_for_main_worker(self):
        """
        Test to stop a worker group when main worker is processing a message.
        SIGTERM handler shouldn't raise an exception allowing to finish
        processing the message and exit gracefully.
        """
        callback, wait_running, wait_stopped = self.tracked_callback()
        channel_layer = self.make_channel_layer('test')

        Channel('test', channel_layer=channel_layer).send({'test': 'test'},
                                                          immediately=True)
        consumer = mock.Mock()
        channel_layer.router.add_route(route('test', consumer))
        # Proxy `send` for counting.
        channel_layer.send = mock.Mock(side_effect=channel_layer.send)

        with test_worker_group(channel_layer, n_threads=1,
                               callback=callback) as worker_group:
            wait_running()
            # Main worker processing msg, wait for it and exit gracefully.
            worker_group.sigterm_handler(None, None)
            wait_stopped()

        self.assertEqual(consumer.call_count, 1)
        self.assertEqual(channel_layer.send.call_count, 0)
Example #6
0
    def test_subscribe(self):

        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):

            json_content = self._send_and_consume('testmodel', {
                'action': 'subscribe',
                'data': {
                    'action': 'create'
                },
                'request_id': 'client-request-id'
            })

            expected_response = {
                'action': 'subscribe',
                'request_id': 'client-request-id',
                'data': {},
                'errors': [],
                'response_status': 200
            }

            self.assertEqual(json_content['payload'], expected_response)

            # it should be on the create group
            instance = TestModel.objects.create(name='test-name')

            expected = {
                'action': 'create',
                'data': TestModelSerializer(instance).data,
                'model': 'tests.testmodel',
                'pk': instance.id
            }
            actual = self._get_next_message()

            self.assertEqual(expected, actual['payload'])
Example #7
0
    def test_graceful_stop_with_multiple_threads(self):
        """
        Test that the whole worker group is stopped gracefully on termination
        signal: it should finish processing current messages and exit.
        """
        callback, wait_running, wait_stopped = self.tracked_callback()
        channel_layer = self.make_channel_layer('test')

        Channel('test', channel_layer=channel_layer).send({'test': 'test'},
                                                          immediately=True)
        consumer = mock.Mock()
        channel_layer.router.add_route(route('test', consumer))
        # Proxy `send` for counting.
        channel_layer.send = mock.Mock(side_effect=channel_layer.send)

        with test_worker_group(channel_layer, n_threads=3,
                               callback=callback) as worker_group:
            wait_running()
            # Sub-workers threads are started before main thread and most
            # often pick the message, so main thread is idle on termination
            # signal and causes raising StopWorkerGroupLoop, but that's not
            # always the case and sometimes main thread picks the message
            # and exception is not raised.
            try:
                worker_group.sigterm_handler(None, None)
            except StopWorkerGroupLoop:
                pass
            wait_stopped()

        self.assertEqual(consumer.call_count, 1)
        self.assertEqual(channel_layer.send.call_count, 0)
Example #8
0
    def test_trigger_outbound_delete(self):
        class TestBinding(WebsocketBinding):
            model = User
            stream = 'test'
            fields = ['username']

            def group_names(self, instance, action):
                return ["users3"]

            def has_permission(self, user, action, pk):
                return True

        user = User.objects.create(username='******', email='*****@*****.**')

        with apply_routes([route('test', TestBinding.consumer)]):
            client = HttpClient()
            client.join_group('users3')

            user.delete()

            received = client.receive()
            self.assertTrue('payload' in received)
            self.assertTrue('action' in received['payload'])
            self.assertTrue('data' in received['payload'])
            self.assertTrue('username' in received['payload']['data'])
            self.assertTrue('model' in received['payload'])
            self.assertTrue('pk' in received['payload'])

            self.assertEqual(received['payload']['action'], 'delete')
            self.assertEqual(received['payload']['model'], 'auth.user')
            self.assertEqual(received['payload']['pk'], 1)
            self.assertEqual(received['payload']['data']['username'], 'test')

            received = client.receive()
            self.assertIsNone(received)
Example #9
0
    def test_inbound_delete(self):
        user = User.objects.create(username='******', email='*****@*****.**')

        class Demultiplexer(WebsocketDemultiplexer):
            mapping = {
                'users': 'binding.users',
            }

            groups = ['inbound']

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', ]

            @classmethod
            def group_names(cls, instance, action):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]):
            client = HttpClient()
            client.send_and_consume('websocket.connect', path='/')
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': DELETE, 'pk': user.pk}
            })
            # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer
            client.consume('binding.users')

            self.assertIsNone(User.objects.filter(pk=user.pk).first())
Example #10
0
    def test_inbound_delete(self):
        user = User.objects.create(username='******', email='*****@*****.**')

        class Demultiplexer(WebsocketDemultiplexer):
            mapping = {
                'users': 'binding.users',
            }

            groups = ['inbound']

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', ]

            @classmethod
            def group_names(cls, instance, action):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]):
            client = HttpClient()
            client.send_and_consume('websocket.connect', path='/')
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': DELETE, 'pk': user.pk}
            })
            # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer
            client.consume('binding.users')

        self.assertIsNone(User.objects.filter(pk=user.pk).first())
        self.assertIsNone(client.receive())
Example #11
0
    def test_websocket_close_exception_close_code(self):
        def consumer(message):
            raise WebsocketCloseException(3001)

        client = WSClient(reply_channel='daphne.response.1')

        with apply_routes(route('websocket.receive', consumer)):
            client.send_and_consume('websocket.receive')

        self.assertEqual(
            client.get_next_message(client.reply_channel).content,
            {'close': 3001})
Example #12
0
    def test_channel_socket_exception(self):
        class MyChannelSocketException(ChannelSocketException):
            def run(self, message):
                message.reply_channel.send({'text': 'error'})

        def consumer(message):
            raise MyChannelSocketException

        client = WSClient()
        with apply_routes(route('websocket.receive', consumer)):
            client.send_and_consume('websocket.receive')

            self.assertEqual(client.receive(json=False), 'error')
Example #13
0
    def test_normal_run(self):
        consumer = mock.Mock()
        Channel('test').send({'test': 'test'}, immediately=True)
        channel_layer = channel_layers[DEFAULT_CHANNEL_LAYER]
        channel_layer.router.add_route(route('test', consumer))
        old_send = channel_layer.send
        channel_layer.send = mock.Mock(side_effect=old_send)  # proxy 'send' for counting

        worker = PatchedWorker(channel_layer)
        worker.termed = 2

        worker.run()
        self.assertEqual(consumer.call_count, 1)
        self.assertEqual(channel_layer.send.call_count, 0)
Example #14
0
    def test_inbound_create(self):
        self.assertEqual(User.objects.all().count(), 0)

        class Demultiplexer(WebsocketDemultiplexer):
            mapping = {
                'users': 'binding.users',
            }

            groups = ['inbound']

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', 'email', 'password', 'last_name']

            @classmethod
            def group_names(cls, instance, action):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        with apply_routes([
                Demultiplexer.as_route(path='/'),
                route('binding.users', UserBinding.consumer)
        ]):
            client = HttpClient()
            client.send_and_consume('websocket.connect', path='/')
            client.send_and_consume('websocket.receive',
                                    path='/',
                                    text={
                                        'stream': 'users',
                                        'payload': {
                                            'action': CREATE,
                                            'data': {
                                                'username': '******',
                                                'email': 'test@user_steam.com'
                                            }
                                        }
                                    })
            # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer
            client.consume('binding.users')

        self.assertEqual(User.objects.all().count(), 1)
        user = User.objects.all().first()
        self.assertEqual(user.username, 'test_inbound')
        self.assertEqual(user.email, 'test@user_steam.com')

        self.assertIsNone(client.receive())
Example #15
0
    def test_trigger_outbound_update(self):
        class TestBinding(WebsocketBinding):
            model = User
            stream = 'test'
            fields = ['__all__']

            @classmethod
            def group_names(cls, instance, action):
                return ["users2"]

            def has_permission(self, user, action, pk):
                return True

        # Make model and clear out pending sends
        user = User.objects.create(username='******', email='*****@*****.**')
        consumer_finished.send(sender=None)

        with apply_routes([route('test', TestBinding.consumer)]):
            client = HttpClient()
            client.join_group('users2')

            user.username = '******'
            user.save()

            consumer_finished.send(sender=None)
            received = client.receive()
            self.assertTrue('payload' in received)
            self.assertTrue('action' in received['payload'])
            self.assertTrue('data' in received['payload'])
            self.assertTrue('username' in received['payload']['data'])
            self.assertTrue('email' in received['payload']['data'])
            self.assertTrue('password' in received['payload']['data'])
            self.assertTrue('last_name' in received['payload']['data'])
            self.assertTrue('model' in received['payload'])
            self.assertTrue('pk' in received['payload'])

            self.assertEqual(received['payload']['action'], 'update')
            self.assertEqual(received['payload']['model'], 'auth.user')
            self.assertEqual(received['payload']['pk'], user.pk)

            self.assertEqual(received['payload']['data']['email'],
                             '*****@*****.**')
            self.assertEqual(received['payload']['data']['username'],
                             'test_new')
            self.assertEqual(received['payload']['data']['password'], '')
            self.assertEqual(received['payload']['data']['last_name'], '')

            received = client.receive()
            self.assertIsNone(received)
Example #16
0
    def test_channel_socket_exception(self):

        class MyChannelSocketException(ChannelSocketException):

            def run(self, message):
                message.reply_channel.send({'text': 'error'})

        def consumer(message):
            raise MyChannelSocketException

        client = WSClient()
        with apply_routes(route('websocket.receive', consumer)):
            client.send_and_consume('websocket.receive')

            self.assertEqual(client.receive(json=False), 'error')
Example #17
0
    def test_retrieve_404(self):
        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):

            json_content = self._send_and_consume('testmodel', {
                'action': 'retrieve',
                'pk': 1,
                'request_id': 'client-request-id'
            })
            expected = {
                'action': 'retrieve',
                'data': None,
                'errors': ['Not found.'],
                'response_status': 404,
                'request_id': 'client-request-id'
            }
            self.assertEqual(json_content['payload'], expected)
Example #18
0
    def test_ordering(self):

        client = WSClient(ordered=True)

        @enforce_ordering
        def consumer(message):
            message.reply_channel.send({'text': message['text']})

        with apply_routes(route('websocket.receive', consumer)):
            client.send_and_consume('websocket.receive', text='1')  # order = 0
            client.send_and_consume('websocket.receive', text='2')  # order = 1
            client.send_and_consume('websocket.receive', text='3')  # order = 2

            self.assertEqual(client.receive(), 1)
            self.assertEqual(client.receive(), 2)
            self.assertEqual(client.receive(), 3)
Example #19
0
    def test_ordering(self):

        client = WSClient(ordered=True)

        @enforce_ordering
        def consumer(message):
            message.reply_channel.send({'text': message['text']})

        with apply_routes(route('websocket.receive', consumer)):
            client.send_and_consume('websocket.receive', text='1')  # order = 0
            client.send_and_consume('websocket.receive', text='2')  # order = 1
            client.send_and_consume('websocket.receive', text='3')  # order = 2

            self.assertEqual(client.receive(), 1)
            self.assertEqual(client.receive(), 2)
            self.assertEqual(client.receive(), 3)
Example #20
0
    def test_trigger_outbound_update(self):
        class TestBinding(WebsocketBinding):
            model = User
            stream = 'test'
            fields = ['__all__']

            @classmethod
            def group_names(cls, instance, action):
                return ["users2"]

            def has_permission(self, user, action, pk):
                return True

        # Make model and clear out pending sends
        user = User.objects.create(username='******', email='*****@*****.**')
        consumer_finished.send(sender=None)

        with apply_routes([route('test', TestBinding.consumer)]):
            client = HttpClient()
            client.join_group('users2')

            user.username = '******'
            user.save()

            consumer_finished.send(sender=None)
            received = client.receive()
            self.assertTrue('payload' in received)
            self.assertTrue('action' in received['payload'])
            self.assertTrue('data' in received['payload'])
            self.assertTrue('username' in received['payload']['data'])
            self.assertTrue('email' in received['payload']['data'])
            self.assertTrue('password' in received['payload']['data'])
            self.assertTrue('last_name' in received['payload']['data'])
            self.assertTrue('model' in received['payload'])
            self.assertTrue('pk' in received['payload'])

            self.assertEqual(received['payload']['action'], 'update')
            self.assertEqual(received['payload']['model'], 'auth.user')
            self.assertEqual(received['payload']['pk'], user.pk)

            self.assertEqual(received['payload']['data']['email'], '*****@*****.**')
            self.assertEqual(received['payload']['data']['username'], 'test_new')
            self.assertEqual(received['payload']['data']['password'], '')
            self.assertEqual(received['payload']['data']['last_name'], '')

            received = client.receive()
            self.assertIsNone(received)
Example #21
0
    def test_inbound_update(self):
        user = User.objects.create(username='******', email='*****@*****.**')

        class Demultiplexer(WebsocketDemultiplexer):
            mapping = {
                'users': 'binding.users',
            }

            groups = ['inbound']

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', ]

            @classmethod
            def group_names(cls, instance, action):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]):
            client = HttpClient()
            client.send_and_consume('websocket.connect', path='/')
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'username': '******'}}
            })
            # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer
            client.consume('binding.users')

            user = User.objects.get(pk=user.pk)
            self.assertEqual(user.username, 'test_inbound')
            self.assertEqual(user.email, '*****@*****.**')

            # trying change field that not in binding fields
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'email': '*****@*****.**'}}
            })
            client.consume('binding.users')

            user = User.objects.get(pk=user.pk)
            self.assertEqual(user.username, 'test_inbound')
            self.assertEqual(user.email, '*****@*****.**')
Example #22
0
    def test_inbound_update(self):
        user = User.objects.create(username='******', email='*****@*****.**')

        class Demultiplexer(WebsocketDemultiplexer):
            mapping = {
                'users': 'binding.users',
            }

            groups = ['inbound']

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', ]

            @classmethod
            def group_names(cls, instance, action):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]):
            client = HttpClient()
            client.send_and_consume('websocket.connect', path='/')
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'username': '******'}}
            })
            # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer
            client.consume('binding.users')

            user = User.objects.get(pk=user.pk)
            self.assertEqual(user.username, 'test_inbound')
            self.assertEqual(user.email, '*****@*****.**')

            # trying change field that not in binding fields
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': UPDATE, 'pk': user.pk, 'data': {'email': '*****@*****.**'}}
            })
            client.consume('binding.users')

            user = User.objects.get(pk=user.pk)
            self.assertEqual(user.username, 'test_inbound')
            self.assertEqual(user.email, '*****@*****.**')
Example #23
0
    def test_retrieve(self):

        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):
            instance = TestModel.objects.create(name="Test")

            json_content = self._send_and_consume('testmodel', {
                'action': 'retrieve',
                'pk': instance.id,
                'request_id': 'client-request-id'
            })
            expected = {
                'action': 'retrieve',
                'data': TestModelSerializer(instance).data,
                'errors': [],
                'response_status': 200,
                'request_id': 'client-request-id'
            }
            self.assertTrue(json_content['payload'] == expected)
Example #24
0
 def start(self):
     rows_affected = self._acquire()
     if rows_affected == 0:
         return
     if rows_affected != 1:
         raise Exception()
     try:
         from channels.asgi import channel_layers
         from channels import route
         from channels import DEFAULT_CHANNEL_LAYER
         channel_layer = channel_layers[DEFAULT_CHANNEL_LAYER]
         if self.mqtt_client is None:
             channel_layer.router.add_route(
                 route(self.channel, self.consumer))
         self.mqtt_client = self.make_client()
         self.mqtt_client.loop_start()
     except:
         self._release()
Example #25
0
    def test_trigger_outbound_create_exclude(self):
        class TestBinding(WebsocketBinding):
            model = User
            stream = 'test'
            exclude = ['first_name', 'last_name']

            @classmethod
            def group_names(cls, instance):
                return ["users_exclude"]

            def has_permission(self, user, action, pk):
                return True

        with apply_routes([route('test', TestBinding.consumer)]):
            client = HttpClient()
            client.join_group('users_exclude')

            user = User.objects.create(username='******', email='*****@*****.**')
            received = client.receive()

            self.assertTrue('payload' in received)
            self.assertTrue('action' in received['payload'])
            self.assertTrue('data' in received['payload'])
            self.assertTrue('username' in received['payload']['data'])
            self.assertTrue('email' in received['payload']['data'])
            self.assertTrue('password' in received['payload']['data'])
            self.assertTrue('model' in received['payload'])
            self.assertTrue('pk' in received['payload'])

            self.assertFalse('last_name' in received['payload']['data'])
            self.assertFalse('first_name' in received['payload']['data'])

            self.assertEqual(received['payload']['action'], 'create')
            self.assertEqual(received['payload']['model'], 'auth.user')
            self.assertEqual(received['payload']['pk'], user.pk)

            self.assertEqual(received['payload']['data']['email'],
                             '*****@*****.**')
            self.assertEqual(received['payload']['data']['username'], 'test')
            self.assertEqual(received['payload']['data']['password'], '')

            received = client.receive()
            self.assertIsNone(received)
Example #26
0
    def test_subscribe_failure(self):

        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):

            json_content = self._send_and_consume('testmodel', {
                'action': 'subscribe',
                'data': {
                },
                'request_id': 'client-request-id'
            })

            expected = {
                'action': 'subscribe',
                'data': None,
                'errors': ['action required'],
                'request_id': 'client-request-id',
                'response_status': 400
            }
            self.assertEqual(expected, json_content['payload'])
Example #27
0
    def test_trigger_outbound_create_exclude(self):
        class TestBinding(WebsocketBinding):
            model = User
            stream = 'test'
            exclude = ['first_name', 'last_name']

            @classmethod
            def group_names(cls, instance):
                return ["users_exclude"]

            def has_permission(self, user, action, pk):
                return True

        with apply_routes([route('test', TestBinding.consumer)]):
            client = WSClient()
            client.join_group('users_exclude')

            user = User.objects.create(username='******', email='*****@*****.**')
            received = client.receive()

            self.assertTrue('payload' in received)
            self.assertTrue('action' in received['payload'])
            self.assertTrue('data' in received['payload'])
            self.assertTrue('username' in received['payload']['data'])
            self.assertTrue('email' in received['payload']['data'])
            self.assertTrue('password' in received['payload']['data'])
            self.assertTrue('model' in received['payload'])
            self.assertTrue('pk' in received['payload'])

            self.assertFalse('last_name' in received['payload']['data'])
            self.assertFalse('first_name' in received['payload']['data'])

            self.assertEqual(received['payload']['action'], 'create')
            self.assertEqual(received['payload']['model'], 'auth.user')
            self.assertEqual(received['payload']['pk'], user.pk)

            self.assertEqual(received['payload']['data']['email'], '*****@*****.**')
            self.assertEqual(received['payload']['data']['username'], 'test')
            self.assertEqual(received['payload']['data']['password'], '')

            received = client.receive()
            self.assertIsNone(received)
Example #28
0
    def test_update_failure(self):
        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):
            instance = TestModel.objects.create(name='some-test')

            json_content = self._send_and_consume('testmodel', {
                'action': 'update',
                'pk': -1,
                'data': {'name': 'some-value'},
                'request_id': 'client-request-id'
            })

            expected = {
                'data': None,
                'action': 'update',
                'errors': ['Not found.'],
                'response_status': 404,
                'request_id': 'client-request-id'
            }

            self.assertEqual(json_content['payload'], expected)
Example #29
0
    def test_run_with_consume_later_error(self):

        # consumer with ConsumeLater error at first call
        def _consumer(message, **kwargs):
            _consumer._call_count = getattr(_consumer, '_call_count', 0) + 1
            if _consumer._call_count == 1:
                raise ConsumeLater()

        Channel('test').send({'test': 'test'}, immediately=True)
        channel_layer = channel_layers[DEFAULT_CHANNEL_LAYER]
        channel_layer.router.add_route(route('test', _consumer))
        old_send = channel_layer.send
        channel_layer.send = mock.Mock(side_effect=old_send)  # proxy 'send' for counting

        worker = PatchedWorker(channel_layer)
        worker.termed = 2  # first loop with error, second with sending

        worker.run()
        self.assertEqual(getattr(_consumer, '_call_count', None), 2)
        self.assertEqual(channel_layer.send.call_count, 1)
Example #30
0
    def test_delete(self):

        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):

            instance = TestModel.objects.create(name='test-name')

            json_content = self._send_and_consume('testmodel', {
                'action': 'delete',
                'pk': instance.id,
                'request_id': 'client-request-id',
            })

            expected = {
                'action': 'delete',
                'errors': [],
                'data': {},
                'request_id': 'client-request-id',
                'response_status': 200
            }
            self.assertEqual(json_content['payload'], expected)
            self.assertEqual(TestModel.objects.count(), 0)
Example #31
0
    def test_update(self):
        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):
            instance = TestModel.objects.create(name='some-test')

            json_content = self._send_and_consume('testmodel', {
                'action': 'update',
                'pk': instance.id,
                'data': {'name': 'some-value'},
                'request_id': 'client-request-id'
            })

            instance.refresh_from_db()

            expected = {
                'action': 'update',
                'errors': [],
                'data': TestModelSerializer(instance).data,
                'response_status': 200,
                'request_id': 'client-request-id'
            }

            self.assertEqual(json_content['payload'], expected)
Example #32
0
    def test_create_failure(self):
        """Integration that asserts error handling of a message to the create channel."""

        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):
            json_content = self._send_and_consume('testmodel', {
                'action': 'create',
                'pk': None,
                'request_id': 'client-request-id',
                'data': {},
            })
            # it should not create an object
            self.assertEqual(TestModel.objects.count(), 0)

            expected = {
                'action': 'create',
                'data': None,
                'request_id': 'client-request-id',
                'errors': [{'name': ['This field is required.']}],
                'response_status': 400
            }
            # it should respond with an error
            self.assertEqual(json_content['payload'], expected)
Example #33
0
    def test_inbound_create(self):
        self.assertEqual(User.objects.all().count(), 0)

        class Demultiplexer(WebsocketDemultiplexer):
            mapping = {
                'users': 'binding.users',
            }

            groups = ['inbound']

        class UserBinding(WebsocketBinding):
            model = User
            stream = 'users'
            fields = ['username', 'email', 'password', 'last_name']

            @classmethod
            def group_names(cls, instance, action):
                return ['users_outbound']

            def has_permission(self, user, action, pk):
                return True

        with apply_routes([Demultiplexer.as_route(path='/'), route('binding.users', UserBinding.consumer)]):
            client = HttpClient()
            client.send_and_consume('websocket.connect', path='/')
            client.send_and_consume('websocket.receive', path='/', text={
                'stream': 'users',
                'payload': {'action': CREATE, 'data': {'username': '******', 'email': 'test@user_steam.com'}}
            })
            # our Demultiplexer route message to the inbound consumer, so call Demultiplexer consumer
            client.consume('binding.users')

        self.assertEqual(User.objects.all().count(), 1)
        user = User.objects.all().first()
        self.assertEqual(user.username, 'test_inbound')
        self.assertEqual(user.email, 'test@user_steam.com')

        self.assertIsNone(client.receive())
Example #34
0
    def test_create(self):
        """Integration that asserts routing a message to the create channel.

        Asserts response is correct and an object is created.
        """
        with apply_routes([route(TestModelResourceBinding.stream, TestModelResourceBinding.consumer)]):
            json_content = self._send_and_consume(TestModelResourceBinding.stream, {
                'action': 'create',
                'pk': None,
                'request_id': 'client-request-id',
                'data': {'name': 'some-thing'}})

            # it should create an object
            self.assertEqual(TestModel.objects.count(), 1)

            expected = {
                'action': 'create',
                'data': TestModelSerializer(TestModel.objects.first()).data,
                'errors': [],
                'request_id': 'client-request-id',
                'response_status': 201
            }
            # it should respond with the serializer.data
            self.assertEqual(json_content['payload'], expected)
Example #35
0
from channels import route, route_class
from channels.generic.websockets import WebsocketDemultiplexer

from posts.bindings import LiveblogResource

class APIDemultiplexer(WebsocketDemultiplexer):

    mapping = {
        'liveblogs': 'liveblogs'
    }


# The channel routing defines what channels get handled by what consumers,
# including optional matching on message attributes. WebSocket messages of all
# types have a 'path' attribute, so we're using that to route the socket.
# While this is under stream/ compared to the HTML page, we could have it on the
# same URL if we wanted; Daphne separates by protocol as it negotiates with a browser.
channel_routing = [
    route_class(APIDemultiplexer),
    route("liveblogs", LiveblogResource.consumer)

    # A default "http.request" route is always inserted by Django at the end of the routing list
    # that routes all unmatched HTTP requests to the Django view system. If you want lower-level
    # HTTP handling - e.g. long-polling - you can do it here and route by path, and let the rest
    # fall through to normal views.
]
from channels import route
from jobs import consumers

channel_routing = [
    # Wire up websocket channels to our consumers:
    route("websocket.connect", consumers.ws_connect),
    route("websocket.receive", consumers.ws_receive),
]
Example #37
0
from channels import route, route_class
from blocks.consumers.block import parse_block, repair_block, check_block_hash
from blocks.consumers.transaction import repair_transaction
from blocks.consumers.address import parse_address
from blocks.consumers.info import display_info
from blocks.consumers.websockets import ws_connect, ws_disconnect, ws_receive
from blocks.consumers.angular_consumers.demultiplexers import BlockDemultiplexer, LatestBlocksDemultiplexer

channel_routing = [
    # Blocks
    route('parse_block', parse_block),
    route('repair_block', repair_block),
    route('check_block_hash', check_block_hash),

    # Transactions
    route('repair_transaction', repair_transaction),

    # Addresses
    route('parse_address', parse_address),

    # Info
    route('display_info', display_info),

    # Demultiplexing
    route_class(BlockDemultiplexer, path="^/block/$"),
    route_class(LatestBlocksDemultiplexer, path="^/latest_blocks/$"),

    # Websockets
    route('websocket.connect', ws_connect),
    route('websocket.disconnect', ws_disconnect),
    route('websocket.receive', ws_receive),
Example #38
0
File: routing.py Project: Frky/moon
from . import consumers
from channels import route


channel_routing = [
    route('websocket.connect', consumers.ws_connect),
    route('websocket.receive', consumers.ws_receive),
        route('websocket.disconnect', consumers.ws_disconnect),
]
Example #39
0
from channels import route
from .consumers import ws_connect, ws_receive, ws_disconnect, chat_join, chat_leave, chat_send


# There's no path matching on these routes; we just rely on the matching
# from the top-level routing. We _could_ path match here if we wanted.
websocket_routing = [
    # Called when WebSockets connect
    route("websocket.connect", ws_connect),

    # Called when WebSockets get sent a data frame
    route("websocket.receive", ws_receive),

    # Called when WebSockets disconnect
    route("websocket.disconnect", ws_disconnect),
]


# You can have as many lists here as you like, and choose any name.
# Just refer to the individual names in the include() function.
custom_routing = [
    # Handling different chatt commands (websocket.receive is decoded and put
    # onto this channel) - routed on the "command" attribute of the decoded
    # message.
    route("chatt.receive", chat_join, command="^join$"),
    route("chatt.receive", chat_leave, command="^leave$"),
    route("chatt.receive", chat_send, command="^send$"),
]
Example #40
0
from channels import route

from blocks.consumers.info import display_info
from blocks.consumers.websockets import ws_connect, ws_disconnect, ws_receive

channel_routing = [
    # Info
    route("display_info", display_info),
    # Websockets
    route("websocket.connect", ws_connect),
    route("websocket.disconnect", ws_disconnect),
    route("websocket.receive", ws_receive),
]
from channels import route
from .consumers import (ws_connect_api, ws_receive_api, ws_disconnect_api,
                        chat_send_api, bot_send_api)

# There's no path matching on these routes; we just rely on the matching
# from the top-level routing. We _could_ path match here if we wanted.
websocket_routing = [
    # Called when WebSockets connect
    route("websocket.connect", ws_connect_api),

    # Called when WebSockets get sent a data frame
    route("websocket.receive", ws_receive_api),

    # Called when WebSockets disconnect
    route("websocket.disconnect", ws_disconnect_api),
]

# You can have as many lists here as you like, and choose any name.
# Just refer to the individual names in the include() function.
custom_routing = [
    # Handling different chat commands (websocket.receive is decoded and put
    # onto this channel) - routed on the "command" attribute of the decoded
    # message.
    # route("chat.receive", chat_join, command="^join$"),
    # route("chat.receive", chat_leave, command="^leave$"),
    # route("chat.receive", chat_send, command="^send$"),
    route("chat-api.receive", chat_send_api, command="^send$"),
    route("bot-api.receive", bot_send_api),
]
Example #42
0
from channels.staticfiles import StaticFilesConsumer
from channels import route
from login import consumers



channel_routing = [
    # This makes Django serve static files from settings.STATIC_URL, similar
    # to django.views.static.serve. This isn't ideal (not exactly production
    # quality) but it works for a minimal example.
    route('http.request', StaticFilesConsumer()),

    # Wire up websocket channels to our consumers:

    route('websocket.connect',
    	consumers.connect_to_nifty_channel,
    	path = r'^/nifty-channel/'
     	),
	
	route('websocket.disconnect',
		consumers.disconnect_from_nifty_channel,
		path = r'^/nifty-channel/',
     	),




	route('websocket.connect',
    	consumers.connect_to_leaderboard_channel,
    	path = r'^/leaderboard-channel/'
     	),
Example #43
0
from channels import route
from dashboard import consumers

channel_routing = [
    route('websocket.connect', consumers.ws_connect),
    route('websocket.receive', consumers.ws_receive),
    route('websocket.disconnect', consumers.ws_disconnect),
]
Example #44
0
from channels import route
from .consumers import ws_connect, ws_receive, ws_disconnect, handle_chat_message


# There's no path matching on these routes; we just rely on the matching
# from the top-level routing. We _could_ path match here if we wanted.
websocket_routing = [
    # Called when WebSockets connect
    route("websocket.connect", ws_connect),

    # Called when WebSockets get sent a data frame
    route("websocket.receive", ws_receive),

    # Called when WebSockets disconnect
    route("websocket.disconnect", ws_disconnect),
]


# You can have as many lists here as you like, and choose any name.
# Just refer to the individual names in the include() function.
custom_routing = [
    # Custom channel
    route("chat_messages", handle_chat_message),
]
Example #45
0
from channels import route
from .consumers import *

message_routing = [
    route("websocket.connect", ws_connect),
    route("websocket.disconnect", ws_disconnect),
    route("websocket.receive", ws_receive),
]
Example #46
0
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from channels import route
from django.conf.urls import include, url
from django.contrib import admin

from app.views import IndexView
from channels_example.app.consumers import ws_message, ws_add, ws_disconnect

urlpatterns = [
    url(r'^$', IndexView.as_view()),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^accounts/', include('django.contrib.auth.urls')),

]

channel_routing = [
    route("websocket.receive", ws_message),
    route("websocket.connect", ws_add),
    route("websocket.disconnect", ws_disconnect),
]
Example #47
0
from channels import route
from .consumers import (ws_connect, ws_disconnect, ws_message, chat_receive, friends_added, friend_delete, films_added_for_voting,
        film_delete, voting, settings_changed)


# There's no path matching on these routes; we just rely on the matching
# from the top-level routing. We could path match here if we wanted.
websocket_routing = [
    route("websocket.connect", ws_connect),
    route("websocket.receive", ws_message),
    route("websocket.disconnect", ws_disconnect)
]

room_routing = [
    route("room.receive", chat_receive, command="^chat$"),
    route("room.receive", friends_added, command="^add_friends$"),
    route("room.receive", friend_delete, command="^delete_friend"),
    route("room.receive", films_added_for_voting, command="^add_film_voting"),
    route("room.receive", film_delete, command="^delete_film_voting"),
    route("room.receive", voting, command="^voting"),
    route("room.receive", settings_changed, command="^settings"),
]
Example #48
0
from channels import route


# This function will display all messages received in the console
def message_handler(message):
    print(message['text'])


channel_routing = [
    route("websocket.receive",
          message_handler)  # we register our message handler
]

from channels import include

# The channel routing defines what channels get handled by what consumers,
# including optional matching on message attributes. In this example, we match
# on a path prefix, and then include routing from the chat module.
channel_routing = [
    # Include sub-routing from an app.
    include("chat.routing.websocket_routing", path=r"^/chat/stream"),

    # Custom handler for message sending (see Room.send_message).
    # Can't go in the include above as it's not got a 'path' attribute to match on.
    include("chat.routing.custom_routing"),

    # A default "http.request" route is always inserted by Django at the end of the routing list
    # that routes all unmatched HTTP requests to the Django view system. If you want lower-level
    # HTTP handling - e.g. long-polling - you can do it here and route by path, and let the rest
    # fall through to normal views.
]
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals

from channels import route

from .consumers import liveblog_connect, liveblog_disconnect

channel_routing = [
    route(
        'websocket.connect', liveblog_connect,
        path=r'^/liveblog/(?P<apphook>[a-zA-Z0-9_-]+)/'
             r'(?P<lang>[a-zA-Z_-]+)/(?P<post>[a-zA-Z0-9_-]+)/$'
    ),
    route(
        'websocket.disconnect', liveblog_disconnect,
        path=r'^/liveblog/(?P<apphook>[a-zA-Z0-9_-]+)/'
             r'(?P<lang>[a-zA-Z_-]+)/(?P<post>[a-zA-Z0-9_-]+)/$'
    ),
]
Example #50
0
from channels import include, route

from api.views.web_socket import ChatSocketView, CompositionSocketView

composition_routing = [
    route("websocket.connect", "api.consumers.base.pass_message"),
    route("websocket.receive", CompositionSocketView.as_view()),
    route("websocket.disconnect", CompositionSocketView.as_view()),
]


chat_routing = [
    route("websocket.connect", "api.consumers.base.pass_message"),
    route("websocket.receive", ChatSocketView.as_view()),
    route("websocket.disconnect", ChatSocketView.as_view()),
]

not_found_routing = [
    route("websocket.connect", "api.consumers.base.pass_message"),
    route("websocket.receive", "api.consumers.base.pass_message"),
    route("websocket.disconnect", "api.consumers.base.pass_message"),
]

main_routing = [
    # TODO поправить в настройках nginx
    include(composition_routing, path=r"^/ws/composition/(?P<composition_id>\d+)/$"),
    include(chat_routing, path=r"^/ws/chat/(?P<band_id>\d+)/$"),
    include(not_found_routing),
]
Example #51
0
from channels import route
from posts.consumers import connect_blog, disconnect_blog
from livetweets.consumers import connect_tweeter, disconnect_tweeter

# The channels routing defines what the channels get handled by what consumers,
# including optional matching on message attributes. Websocket messages of all
# types have a 'path' attribute, so we're using that to route the socket.
# While this is under stream/ compared to the HTML page, we could have it on the
# same URL if we wanted; Daphne separates by protocol as it negotiates with a browser

channel_routing = [
    # called when incoming Websockets connect
    route('websocket.connect', connect_blog, path=r'/liveblog/(?P<slug>[^/]+)/stream/$'),

    # called when the client closes the socket
    route('websocket.disconnet', disconnect_blog, path=r'^/liveblog/(?P<slug>[^/]+)/stream/$'),

    # called when incoming Websockets connect
    route('websocket.connect', connect_tweeter, path=r'/livetweets/stream/$'),

    # called when the client closes the socket
    route('websocket.disconnet', disconnect_tweeter, path=r'^/livetweets/stream/$'),

]
Example #52
0
from channels import route
from channels.staticfiles import StaticFilesConsumer

from posts.consumers import connect_blog, disconnect_blog, http_consumer


# The channel routing defines what channels get handled by what consumers,
# including optional matching on message attributes. WebSocket messages of all
# types have a 'path' attribute, so we're using that to route the socket.
# While this is under stream/ compared to the HTML page, we could have it on the
# same URL if we wanted; Daphne separates by protocol as it negotiates with a browser.
channel_routing = [
    # Called when incoming WebSockets connect
    route("websocket.connect", connect_blog, path=r'^/liveblog/(?P<slug>[^/]+)/stream/$'),

    # Called when the client closes the socket
    route("websocket.disconnect", disconnect_blog, path=r'^/liveblog/(?P<slug>[^/]+)/stream/$'),

    route("http.request", StaticFilesConsumer()),

    # A default "http.request" route is always inserted by Django at the end of the routing list
    # that routes all unmatched HTTP requests to the Django view system. If you want lower-level
    # HTTP handling - e.g. long-polling - you can do it here and route by path, and let the rest
    # fall through to normal views.
]
Example #53
0
from channels.staticfiles import StaticFilesConsumer
from channels import route
from . import consumers

channel_routing = [
    # This makes Django serve static files from settings.STATIC_URL, similar
    # to django.views.static.serve. This isn't ideal (not exactly production
    # quality) but it works for a minimal example.
    route('http.request', StaticFilesConsumer()),

    # Wire up websocket channels to our consumers:
    route('websocket.connect',
          consumers.connect_to_nifty_channel,
          path=r'^/nifty-channel/'),
    route(
        'websocket.disconnect',
        consumers.disconnect_from_nifty_channel,
        path=r'^/nifty-channel/',
    ),
    route('websocket.connect',
          consumers.connect_to_leaderboard_channel,
          path=r'^/leaderboard-channel/'),
    route(
        'websocket.disconnect',
        consumers.disconnect_from_leaderboard_channel,
        path=r'^/leaderboard-channel/',
    ),
    route('websocket.connect',
          consumers.connect_to_ticker_channel,
          path=r'^/ticker-channel/'),
    route(
Example #54
0
from channels import route

# This function will display all messages received in the console
def message_handler(message):
    print(message['text'])


channel_routing = [
    route("websocket.receive", message_handler)  # we register our message handler
]
Example #55
0
from channels import route, route_class
from .consumers import ChatServer, events, Demultiplexer, RoomBinding

chat_routing = [
    route_class(ChatServer, path=r'^(?P<slug>[^/]+)/stream/$'),
]

event_routing = [
    route('chat.receive', events.user_join, event=r'^user-join$'),
    route('chat.receive', events.user_leave, event=r'^user-leave$'),
    route('chat.receive', events.client_send, event=r'^message-send$'),
]

binding_routing = [
    route_class(Demultiplexer, path=r'^/binding/'),
    route('binding.room', RoomBinding.consumer),
]
Example #56
0
from channels import route_class, route
from values.consumers import Demultiplexer
from values.models import IntegerValueBinding


# The channel routing defines what channels get handled by what consumers,
# including optional matching on message attributes. In this example, we route
# all WebSocket connections to the class-based BindingConsumer (the consumer
# class itself specifies what channels it wants to consume)
channel_routing = [
    route_class(Demultiplexer, path='^/stream/?$'),
    route("binding.intval", IntegerValueBinding.consumer),
]
Example #57
0
from channels import route

from .consumers import (
    ws_connect, ws_receive, ws_disconnect, votes_update
)

websocket_routing = [
    route('websocket.connect', ws_connect),
    route('websocket.receive', ws_receive),
    route('websocket.disconnect', ws_disconnect),
]

votes_routing = [
    route('votes.receive', votes_update, command='^update$'),
]
# coding=utf-8
from __future__ import unicode_literals

from channels import include, route

from chat.views import ChatWebSocketView, DRFChatWebSocketView

routing = [
    route('websocket.connect', ChatWebSocketView.as_view(), path=r'^default/'),
    # include(DRFChatWebSocketView.as_view(), path=r'^drf/'),
]