Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Client does not support binary data #601

Closed
jpowie01 opened this issue Dec 2, 2017 · 6 comments
Closed

Test Client does not support binary data #601

jpowie01 opened this issue Dec 2, 2017 · 6 comments
Assignees
Labels

Comments

@jpowie01
Copy link

jpowie01 commented Dec 2, 2017

Hello,
I've found an issue with emitting binary data using Test Client. Is there a way that I can use it in tests? As far as I looked into the code I found that this class always set binary argument to False. Why? Was it done on purpose?

Example use:

web_socket.test_client(app)
...
image = open('example_file.dcm', 'rb')
binary_data = image.read()
web_socket_client.emit('my_event', {'ref_id': 123, 'image': binary_data}, namespace='/my_namespace')

Example error:

venv/lib/python3.6/site-packages/flask_socketio/test_client.py:121: in emit
    self.socketio.server._handle_eio_message(self.sid, pkt.encode())
venv/lib/python3.6/site-packages/socketio/packet.py:71: in encode
    encoded_packet += self.json.dumps(data, separators=(',', ':'))
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py:238: in dumps
    **kw).encode(obj)
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py:199: in encode
    chunks = self.iterencode(o, _one_shot=True)
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py:257: in iterencode
    return _iterencode(o, 0)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <json.encoder.JSONEncoder object at 0x1109da6a0>
o = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00...00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

    def default(self, o):
        """Implement this method in a subclass such that it returns
            a serializable object for ``o``, or calls the base implementation
            (to raise a ``TypeError``).

            For example, to support arbitrary iterators, you could
            implement default like this::

                def default(self, o):
                    try:
                        iterable = iter(o)
                    except TypeError:
                        pass
                    else:
                        return list(iterable)
                    # Let the base class default method raise the TypeError
                    return JSONEncoder.default(self, o)

            """
        raise TypeError("Object of type '%s' is not JSON serializable" %
>                       o.__class__.__name__)
E       TypeError: Object of type 'bytes' is not JSON serializable

/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py:180: TypeError

FYI: I can properly send binary data from the JS level but I cannot manage Flask-SocketIO itself to be used during testing.

Does anybody managed to workaround this issue somehow or tried to resolve this bug? Maybe am I using it wrong?

@miguelgrinberg miguelgrinberg self-assigned this Dec 2, 2017
@miguelgrinberg
Copy link
Owner

I'll look into it, seems like it was an oversight on my part.

@jpowie01
Copy link
Author

jpowie01 commented Dec 7, 2017

Did you find out where the root cause of this issue is? I've tried to fix it on myself but I don’t have enough knowledge about this library, so I failed :(

Let me know if I could help somehow as this is blocking tests on my project.

@miguelgrinberg
Copy link
Owner

@jpowie01 Can I ask you to retest your application with the master branch in this repo? I think binary packets should work now.

@jpowie01
Copy link
Author

jpowie01 commented Dec 8, 2017

Thank you very much for such quick help :) It works properly!

But I've got another concern. I've used Test Client like above:

web_socket_client = web_socket.test_client(app)
...
image = open('example_file.dcm', 'rb')
binary_data = image.read()
web_socket_client.emit('my_event', {'ref_id': 123, 'image': binary_data}, namespace='/my_namespace')
assert web_socket_client.get_received(namespace='/my_namespace')

... and it failed. I've checked the queue inside of the Test Client and it was empty:

>>> print(web_socket_client.queue)
{'a40cc08de24348c9a0acc957cf9a7da4': []}

But the logs show me that some message has been sent:

------------------------------------------------ Captured stderr call ------------------------------------------------
received event "my_event" from a40cc08de24348c9a0acc957cf9a7da4 [/my_namespace]
emitting event "my_response" to a40cc08de24348c9a0acc957cf9a7da4 [/my_namespace]

Code used for handling such event looks like this:

class MyEventNamespace(Namespace):
    def on_my_event(self, request: Dict) -> None:
        ...
        emit('my_response', {'data': some_data})
web_socket.on_namespace(MyEventNamespace('/my_namespace'))

My solution to this problem was to change the client to work on a specific namespace like this:

web_socket_client = web_socket.test_client(app, namespace='/my_namespace')

...and it works! I've received this message and I could find it on the queue.

Do I have to create Test Client for each of my namespaces? Or is it another bug? Maybe is it a proper behaviour? Could you expain what happened here?

@miguelgrinberg
Copy link
Owner

Yes, you have to think of the test client in the same way you use a real client. When you create the test client, it "connects" to the server, using the namespace provided. In the most common case the arguments that you pass to the test_client() function are passed directly to connect(), so you definitely need to pass the namespace there.

As a side note, you can call connect() directly if you want, even call it multiple times to connect multiple namespaces.

@jpowie01
Copy link
Author

jpowie01 commented Dec 8, 2017

Cool! Thanks for help :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants