Git Product home page Git Product logo

kitware / wslink Goto Github PK

View Code? Open in Web Editor NEW
83.0 12.0 26.0 2.44 MB

Python/JavaScript library for communicating over WebSocket

Home Page: https://kitware.github.io/wslink/

License: BSD 3-Clause "New" or "Revised" License

JavaScript 23.34% Python 69.61% HTML 0.56% CMake 0.32% C++ 0.43% Vue 1.26% TypeScript 4.48%
javascript-client rpc python-server rpc-call websockets vtk paraviewweb javascript-library python-library

wslink's Introduction

wslink

Wslink allows easy, bi-directional communication between a python server and a javascript or C++ client over a websocket. The client can make remote procedure calls (RPC) to the server, and the server can publish messages to topics that the client can subscribe to. The server can include binary attachments in these messages, which are communicated as a binary websocket message, avoiding the overhead of encoding and decoding.

RPC and publish/subscribe

The initial users of wslink driving its development are VTK and ParaView. ParaViewWeb and vtkWeb require:

  • RPC - a remote procedure call that can be fired by the client and return sometime later with a response from the server, possibly an error.

  • Publish/subscribe - client can subscribe to a topic provided by the server, possibly with a filter on the parts of interest. When the topic has updated results, the server publishes them to the client, without further action on the client's part.

Wslink is replacing a communication layer based on Autobahn WAMP, and so one of the goals is to be fairly compatible with WAMP, but simplify the interface to the point-to-point communication we actually use.

Examples

  • Set up a Python (3.3+) virtualenv using requirements.txt. Roughly:
    • cd wslink/python
    • pip install virtualenv
    • virtualenv runtime
    • source runtime/Scripts/activate (on Windows)
    • pip install -e . (to use current wslink for development)
  • Install node.js 10+ for the javascript client
  • cd wslink/js
  • npm run test
    • or:
  • npm run build:example
  • cd ../tests/simple
  • python server/simple.py
    • starts a webserver at localhost with buttons to test RPC and pub/sub methods

Existing API

Existing ParaViewWeb applications use these code patterns:

  • @exportRPC decorator in Python server code to register a method as being remotely callable
  • session.call("method.uri", [args]) in the JavaScript client to make an RPC call. Usually wrapped as an object method so it appears to be a normal class method.
  • session.subscribe("method.uri", callback) in JS client to initiate a pub/sub relationship.
    • server calls self.publish("method.uri", result) to push info back to the client

We don't support introspection or initial handshake about which methods are supported - the client and server must be in sync.

Message format:

{
const request = {
    wslink: 1.0,
    id: `rpc:${clientId}:${count}`,
    method: 'myapp.render.window.image',
    args: [],
    kwargs: { w: 512, h: 512 }
};

const response = {
    wslink: 1.0,
    id: `rpc:${clientId}:${count}`,
    result: {}, // either result or error, not both
    error: {}
};

// types used as prefix for id.
const types = ['rpc', 'publish', 'system'];
}
# add a binary attachment
def getImage(self):
    return {
        "size": [512, 512],
        "blob": session.addAttachment(memoryview(dataArray)),
        "mtime": dataArray.getMTime()
    }

Binary attachments

session.addAttachment() takes binary data and stores it, returning a string key that will be associated with the attachment. When a message is sent that uses the attachment key, a text header message and a binary message is sent beforehand with each attachment. The client will then substitute the binary buffer for the string key when it receives the final message.

Subscribe

The client tracks subscriptions - the server currently blindly sends out messages for any data it produces which might be subscribed to. This is not very efficient - if the client notifies the server of a subscription, it can send the data only when someone is listening. The ParaViewWeb app Visualizer makes an RPC call after subscribing to tell the server to start publishing.

Handshake

When the client initially connects, it sends a 'hello' to authenticate with the server, so the server knows this client can handle the messages it sends, and the server can provide the client with a unique client ID - which the client must embed in the rpc "id" field of its messages to the server.

  • The first message the client sends should be hello, with the secret key provided by its launcher.
  • Server authenticates the key, and responds with the client ID.
  • If the client sends the wrong key or no key, the server responds with an authentication error message.

Design

More extensive discussion in the design document.

wslink's People

Contributors

alesgenova avatar aronhelser avatar banesullivan avatar botellaa avatar bourdaisj avatar christianwitzler avatar dependabot[bot] avatar drewlazzerikitware avatar felipecybis avatar finetjul avatar floryst avatar genarks avatar jinjilynn avatar jourdain avatar jspanchu avatar kliment-slice avatar mgxd avatar psavery avatar scottwittenburg avatar semantic-release-bot avatar vicentebolea avatar yasushi-saito avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wslink's Issues

conda-forge package

We need to publish a conda-forge feedstock for wslink to ensure compatibility with the VTK conda-forge feedstock for trame.

Ref conda-forge/vtk-feedstock#258 (comment)

I will jump on this.

Once I create the feedstock and wslink goes through a release cycle the feedstock should be self-sustaining unless dependencies change.

Remove secret from logs

Hi,

The server is logging secrets when logging rpc messages. This is problematic from a security perspective, as it could potentially leak sensitive access tokens.

As logging the incoming rpc can still be handy I propose a PR to address this issue by replacing any "secret"-named argument by stars in the logged message. What do you think of this solution?

Regards,

Path segment must be bytes error in link 699 of wslink/launcher.py

Hello,

I am running a Paraview lite visualizer as a multi-user with apache2. For this, I have given the paraview path to Paraview - 5.9.1.

  1. I need to run "start.sh" file from terminal which contains wslink/launcher.py.

  2. When I run "start.sh" file, I am addressing the following error:

/data/pv/pv-5.9.1/lib/python3.8/site-packages/wslink/launcher.py:699: DeprecationWarning: Path segment must be bytes; passing <class 'str'> has never worked, and will raise an exception in the future.
  web_resource.putChild("upload", uploadResource)
  1. I tried working with Paraview 5.7.0, when I run start.sh with this, It does not show any error. But, in the server "http://localhost/paraview", it should the error as addessed in the link here: Paraview_error

  2. Any leads will be appreciated. Do the needful.

Regards,

Sunag R A.

design.md Update

Is your feature request related to a problem? Please describe.
It's not clear what the design of wslink is currently. design.md was written in 2017, and seems to contain several notes about possible implementations. Thus, I cannot tell without reading the code what design was actually implemented and how it has changed since 2017.

Describe the solution you'd like
An update to design.md to make it clear what has been implemented through version 1.11, and a removal of any notes that are no longer relevant.

Describe alternatives you've considered
Remove the design doc, and tell users to read the code instead (not ideal).

Additional context
Thanks for the project!

Increase max message size restriction

self.max_message_size = 512

For example, when sending a JWT token along with a message, this size ends up too small and results in the ValueError:
raise ValueError(
f"""Total size for message {id} exceeds the allocation limit allowed.
Maximum size = {self.max_message_size},
Received size = {total_size}."""

Proposal: increase e.g. self.max_message_size = 3000 to accommodate.

wslink features list

  • test that the launcher responds correctly when there aren't enough resources
  • concurrent processes work fine
  • secret generation
  • proxy handling
  • log files generated in the expected location
  • serving content from configured path
    • should be optional
  • tell user when process already ended
  • make sure sanitize is working

ServerProtocol @exportRpc("application.exit") not accessible

in websocket.py, the two RPC methods @exportRpc("application.exit") and @exportRpc("application.exit.later") are defined, but are not callable from the client.

Examining WslinkWebSocketServerProtocol::onConnect, looks like only LinkProtocol objects have their RPC's registered, and not the ServerProtocol.

Reported by @martinken

Inheritance class WebAppServer from web.Application is discouraged

Seeing this deprecation warning from aiohttp through wslink/trame

  File "/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/wslink/backends/aiohttp/__init__.py", line 38, in <module>
    class WebAppServer(AbstractWebApp, aiohttp_web.Application):
  File "/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/abc.py", line 106, in __new__
    cls = super().__new__(mcls, name, bases, namespace, **kwargs)
  File "/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/aiohttp/web_app.py", line 161, in __init_subclass__
    warnings.warn(
DeprecationWarning: Inheritance class WebAppServer from web.Application is discouraged

Suitable for this use-case?

Hi, I was wondering if it's possible to send numpy images from the python end to the js end via this library?

Thank you!

Server keeps running forever and trying to send messages to improperly disconnected clients

Describe the bug

Hi,
We have met this issue where in some cases the asyncio server doesn't detect a client has disconnected (probably when they disconnect improperly). This causes the wslink server to never pass through the disconnection code, and thus continue running forever.

To Reproduce

Hard to reproduce systematically. I'm still trying to find a way to product the issue with no doubt, though it's presumably:

  1. Connect a client to the wslink server
  2. Improper disconnection (e.g. loss of network)
  3. In some cases the server keeps running forever, never going through the "client {0} disconnected"
  4. If a new client connects (thus producing operations to the link), following exceptions are logged
ConnectionResetError: Cannot write to closing transport
ERROR:asyncio:Task exception was never retrieved
future: <Task finished name='Task-5179' coro=<WslinkHandler.sendWrappedMessage() done, defined at /opt/app/.venv/lib/python3.9/site-packages/wslink/backends/aiohttp/__init__.py:542> exception=ConnectionResetError('Cannot write to closing transport')>
Traceback (most recent call last):
  File "/opt/app/.venv/lib/python3.9/site-packages/wslink/backends/aiohttp/__init__.py", line 596, in sendWrappedMessage
    await ws.send_str(json_header)
  File "/opt/app/.venv/lib/python3.9/site-packages/aiohttp/web_ws.py", line 308, in send_str
    await self._writer.send(data, binary=False, compress=compress)
  File "/opt/app/.venv/lib/python3.9/site-packages/aiohttp/http_websocket.py", line 690, in send
    await self._send_frame(message, WSMsgType.TEXT, compress)
  File "/opt/app/.venv/lib/python3.9/site-packages/aiohttp/http_websocket.py", line 653, in _send_frame
    self._write(header + message)

Expected behavior / Fix

It's probably linked to issue known in wslink for a couple of years: aio-libs/aiohttp#5301 aio-libs/aiohttp#5212

As the case may be not fixed in aiohttp, it could be handled in wslink.

I'm thinking at the points where wslink is writing to the socket (ws.send_str in sendWrappedMessage and sendWrappedError), catch any ConnectionResetError, and in this case, close the socket (await self.onClose(client_id), del self.connections[client_id]), and if there are no more clients, schedule shutdown.

Do you think it's a good approach?
If it looks sound, I can start building up a PR. I'll try to find a reliable way to produce the issue as well.

wslink version:
v1.8.2

WSLink examples are broken.

Describe the bug

After introducing msgpack+chunking in PR C++ example is not working.

To Reproduce

Please try to run example

Code

Please check code here

Json data is sent instead of binary.

Expected behavior

example should work.

Platform:

Linux

Device:

  • Desktop
  • Mobile

OS:

  • Windows
  • MacOS
  • Linux
  • Android
  • iOS

Browsers Affected:

  • Chrome
  • Firefox
  • Safari
  • IE (Version)

wslink version:
vMAJOR.MINOR.PATCH

Python 3.12 - dependence on aiohttp fails

Describe the bug

pip install fails on Python 3.12 due to dependence on aiohttp which is currently not compatible with Python 3.12

To Reproduce

Steps to reproduce the behavior:

  1. install wslink from pip on command line

Code

pip install  wslink

Expected behavior

Installation.

Screenshots

~>pip3 install wslink
Collecting wslink
  Obtaining dependency information for wslink from https://files.pythonhosted.org/packages/07/24/95a870a3ecf48de85c5dbbdd286e2c38c51e8ddeaab7a65c43eca4ba8cbe/wslink-1.12.3-py3-none-any.whl.metadata
  Using cached wslink-1.12.3-py3-none-any.whl.metadata (3.0 kB)
Collecting aiohttp<4 (from wslink)
  Using cached aiohttp-3.8.5.tar.gz (7.4 MB)
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Installing backend dependencies ... done
  Preparing metadata (pyproject.toml) ... done
Requirement already satisfied: attrs>=17.3.0 in ./Python/lib/python3.12/site-packages (from aiohttp<4->wslink) (23.1.0)
Requirement already satisfied: charset-normalizer<4.0,>=2.0 in ./Python/lib/python3.12/site-packages (from aiohttp<4->wslink) (3.3.0)
Requirement already satisfied: multidict<7.0,>=4.5 in ./Python/lib/python3.12/site-packages (from aiohttp<4->wslink) (6.0.4)
Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in ./Python/lib/python3.12/site-packages (from aiohttp<4->wslink) (4.0.3)
Requirement already satisfied: yarl<2.0,>=1.0 in ./Python/lib/python3.12/site-packages (from aiohttp<4->wslink) (1.9.2)
Requirement already satisfied: frozenlist>=1.1.1 in ./Python/lib/python3.12/site-packages (from aiohttp<4->wslink) (1.4.0)
Requirement already satisfied: aiosignal>=1.1.2 in ./Python/lib/python3.12/site-packages (from aiohttp<4->wslink) (1.3.1)
Requirement already satisfied: idna>=2.0 in ./Python/lib/python3.12/site-packages (from yarl<2.0,>=1.0->aiohttp<4->wslink) (3.4)
Using cached wslink-1.12.3-py3-none-any.whl (33 kB)
Building wheels for collected packages: aiohttp
  Building wheel for aiohttp (pyproject.toml) ... error
  error: subprocess-exited-with-error
  
  × Building wheel for aiohttp (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [160 lines of output]
      *********************
      * Accelerated build *
      *********************
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.linux-x86_64-cpython-312
      creating build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/worker.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_ws.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_urldispatcher.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_server.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_runner.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_routedef.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_response.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_request.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_protocol.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_middlewares.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_log.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_fileresponse.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_exceptions.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web_app.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/web.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/typedefs.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/tracing.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/test_utils.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/tcp_helpers.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/streams.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/resolver.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/pytest_plugin.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/payload_streamer.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/payload.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/multipart.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/log.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/locks.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/http_writer.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/http_websocket.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/http_parser.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/http_exceptions.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/http.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/helpers.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/hdrs.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/formdata.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/cookiejar.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/connector.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/client_ws.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/client_reqrep.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/client_proto.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/client_exceptions.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/client.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/base_protocol.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/abc.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/__init__.py -> build/lib.linux-x86_64-cpython-312/aiohttp
      running egg_info
      writing aiohttp.egg-info/PKG-INFO
      writing dependency_links to aiohttp.egg-info/dependency_links.txt
      writing requirements to aiohttp.egg-info/requires.txt
      writing top-level names to aiohttp.egg-info/top_level.txt
      reading manifest file 'aiohttp.egg-info/SOURCES.txt'
      reading manifest template 'MANIFEST.in'
      warning: no files found matching 'aiohttp' anywhere in distribution
      warning: no previously-included files matching '*.pyc' found anywhere in distribution
      warning: no previously-included files matching '*.pyd' found anywhere in distribution
      warning: no previously-included files matching '*.so' found anywhere in distribution
      warning: no previously-included files matching '*.lib' found anywhere in distribution
      warning: no previously-included files matching '*.dll' found anywhere in distribution
      warning: no previously-included files matching '*.a' found anywhere in distribution
      warning: no previously-included files matching '*.obj' found anywhere in distribution
      warning: no previously-included files found matching 'aiohttp/*.html'
      no previously-included directories found matching 'docs/_build'
      adding license file 'LICENSE.txt'
      writing manifest file 'aiohttp.egg-info/SOURCES.txt'
      copying aiohttp/_cparser.pxd -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/_find_header.pxd -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/_headers.pxi -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/_helpers.pyi -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/_helpers.pyx -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/_http_parser.pyx -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/_http_writer.pyx -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/_websocket.pyx -> build/lib.linux-x86_64-cpython-312/aiohttp
      copying aiohttp/py.typed -> build/lib.linux-x86_64-cpython-312/aiohttp
      creating build/lib.linux-x86_64-cpython-312/aiohttp/.hash
      copying aiohttp/.hash/_cparser.pxd.hash -> build/lib.linux-x86_64-cpython-312/aiohttp/.hash
      copying aiohttp/.hash/_find_header.pxd.hash -> build/lib.linux-x86_64-cpython-312/aiohttp/.hash
      copying aiohttp/.hash/_helpers.pyi.hash -> build/lib.linux-x86_64-cpython-312/aiohttp/.hash
      copying aiohttp/.hash/_helpers.pyx.hash -> build/lib.linux-x86_64-cpython-312/aiohttp/.hash
      copying aiohttp/.hash/_http_parser.pyx.hash -> build/lib.linux-x86_64-cpython-312/aiohttp/.hash
      copying aiohttp/.hash/_http_writer.pyx.hash -> build/lib.linux-x86_64-cpython-312/aiohttp/.hash
      copying aiohttp/.hash/_websocket.pyx.hash -> build/lib.linux-x86_64-cpython-312/aiohttp/.hash
      copying aiohttp/.hash/hdrs.py.hash -> build/lib.linux-x86_64-cpython-312/aiohttp/.hash
      running build_ext
      building 'aiohttp._websocket' extension
      creating build/temp.linux-x86_64-cpython-312
      creating build/temp.linux-x86_64-cpython-312/aiohttp
      gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -I/home/alex/Python/include/python3.12 -c aiohttp/_websocket.c -o build/temp.linux-x86_64-cpython-312/aiohttp/_websocket.o
      aiohttp/_websocket.c: In function ‘__pyx_pf_7aiohttp_10_websocket__websocket_mask_cython’:
      aiohttp/_websocket.c:1475:3: warning: ‘Py_OptimizeFlag’ is deprecated [-Wdeprecated-declarations]
       1475 |   if (unlikely(!Py_OptimizeFlag)) {
            |   ^~
      In file included from /home/alex/Python/include/python3.12/Python.h:48,
                       from aiohttp/_websocket.c:6:
      /home/alex/Python/include/python3.12/cpython/pydebug.h:13:37: note: declared here
         13 | Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_OptimizeFlag;
            |                                     ^~~~~~~~~~~~~~~
      aiohttp/_websocket.c: In function ‘__Pyx_get_tp_dict_version’:
      aiohttp/_websocket.c:2680:5: warning: ‘ma_version_tag’ is deprecated [-Wdeprecated-declarations]
       2680 |     return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0;
            |     ^~~~~~
      In file included from /home/alex/Python/include/python3.12/dictobject.h:90,
                       from /home/alex/Python/include/python3.12/Python.h:61:
      /home/alex/Python/include/python3.12/cpython/dictobject.h:22:34: note: declared here
         22 |     Py_DEPRECATED(3.12) uint64_t ma_version_tag;
            |                                  ^~~~~~~~~~~~~~
      aiohttp/_websocket.c: In function ‘__Pyx_get_object_dict_version’:
      aiohttp/_websocket.c:2692:5: warning: ‘ma_version_tag’ is deprecated [-Wdeprecated-declarations]
       2692 |     return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0;
            |     ^~~~~~
      /home/alex/Python/include/python3.12/cpython/dictobject.h:22:34: note: declared here
         22 |     Py_DEPRECATED(3.12) uint64_t ma_version_tag;
            |                                  ^~~~~~~~~~~~~~
      aiohttp/_websocket.c: In function ‘__Pyx_object_dict_version_matches’:
      aiohttp/_websocket.c:2696:5: warning: ‘ma_version_tag’ is deprecated [-Wdeprecated-declarations]
       2696 |     if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict)))
            |     ^~
      /home/alex/Python/include/python3.12/cpython/dictobject.h:22:34: note: declared here
         22 |     Py_DEPRECATED(3.12) uint64_t ma_version_tag;
            |                                  ^~~~~~~~~~~~~~
      aiohttp/_websocket.c: In function ‘__Pyx_CLineForTraceback’:
      aiohttp/_websocket.c:2741:9: warning: ‘ma_version_tag’ is deprecated [-Wdeprecated-declarations]
       2741 |         __PYX_PY_DICT_LOOKUP_IF_MODIFIED(
            |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      /home/alex/Python/include/python3.12/cpython/dictobject.h:22:34: note: declared here
         22 |     Py_DEPRECATED(3.12) uint64_t ma_version_tag;
            |                                  ^~~~~~~~~~~~~~
      aiohttp/_websocket.c:2741:9: warning: ‘ma_version_tag’ is deprecated [-Wdeprecated-declarations]
       2741 |         __PYX_PY_DICT_LOOKUP_IF_MODIFIED(
            |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      /home/alex/Python/include/python3.12/cpython/dictobject.h:22:34: note: declared here
         22 |     Py_DEPRECATED(3.12) uint64_t ma_version_tag;
            |                                  ^~~~~~~~~~~~~~
      aiohttp/_websocket.c: In function ‘__Pyx_PyInt_As_long’:
      aiohttp/_websocket.c:3042:53: error: ‘PyLongObject’ {aka ‘struct _longobject’} has no member named ‘ob_digit’
       3042 |             const digit* digits = ((PyLongObject*)x)->ob_digit;
            |                                                     ^~
      aiohttp/_websocket.c:3097:53: error: ‘PyLongObject’ {aka ‘struct _longobject’} has no member named ‘ob_digit’
       3097 |             const digit* digits = ((PyLongObject*)x)->ob_digit;
            |                                                     ^~
      aiohttp/_websocket.c: In function ‘__Pyx_PyInt_As_int’:
      aiohttp/_websocket.c:3238:53: error: ‘PyLongObject’ {aka ‘struct _longobject’} has no member named ‘ob_digit’
       3238 |             const digit* digits = ((PyLongObject*)x)->ob_digit;
            |                                                     ^~
      aiohttp/_websocket.c:3293:53: error: ‘PyLongObject’ {aka ‘struct _longobject’} has no member named ‘ob_digit’
       3293 |             const digit* digits = ((PyLongObject*)x)->ob_digit;
            |                                                     ^~
      aiohttp/_websocket.c: In function ‘__Pyx_PyIndex_AsSsize_t’:
      aiohttp/_websocket.c:3744:45: error: ‘PyLongObject’ {aka ‘struct _longobject’} has no member named ‘ob_digit’
       3744 |     const digit* digits = ((PyLongObject*)b)->ob_digit;
            |                                             ^~
      error: command '/usr/bin/gcc' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for aiohttp
Failed to build aiohttp
ERROR: Could not build wheels for aiohttp, which is required to install pyproject.toml-based projects

Platform:

Fedora Linux 38

Device:

  • Desktop
  • Mobile

OS:

  • Windows
  • MacOS
  • Linux
  • Android
  • iOS

Browsers Affected:

  • Chrome
  • Firefox
  • Safari
  • IE (Version)

wslink version:
1.12.3

ImJoy-RPC backend?

Would it be possible to leverage imjoy-rpc as a communication backend for wslink (and this trame)? https://github.com/imjoy-team/imjoy-rpc

Does this even make sense?

ImJoy-rpc has a lot of the Jupyter nuances figured and is quite an awesome tool. It'd be great if we could leverage all of the success it's had on Jupyter and Google Colab.

cc @thewtex

Add loop task methods for callbacks and coroutines

When wslink made use of twisted, we had a example that did:

from twisted.internet import task
...
loopTask = task.LoopingCall(callback_method)
loopTask.start(2.0)

and that would schedule callback_method to be called repeatedly every two seconds. We can achieve something similar with just the schedule_callback method in wslink now, but not as simply. It would be nice to provide this capability. A first pass at it might look like:

    def loop_callback(period, callback, *args, **kwargs):
       cancel_handle = None
       canceled = False
       func = functools.partial(callback, *args, **kwargs)
       loop = asyncio.get_running_loop()

       def cancel():
          global canceled

          cancel_handle.cancel()
          canceled = True

       def task():
          global cancel_handle

          if not canceled:
             func()
             cancel_handle = loop.call_later(period, task)

       cancel_handle = loop.call_later(period, task)

       return cancel

Though it would be nice if the return value was an object with a cancel() method, so it behaves like the other scheduling methods.

Segmentation fault while installing wslink in Python

In a Ubuntu 18.04 I am unable to install wslink package:

pip install wslink
Collecting wslink
Using cached https://files.pythonhosted.org/packages/11/bf/f7214dfd45ca8051dce823243c437f3a8e3f14b863c90e2613e02b964311/wslink-0.2.0-py2.py3-none-any.whl
Collecting autobahn (from wslink)
Using cached https://files.pythonhosted.org/packages/6f/2a/8874a5a32a56ecc9c859f1daa281ffd87ec6047e49ab30804a0b3b2707d8/autobahn-20.7.1-py2.py3-none-any.whl
Collecting Twisted (from wslink)
Collecting cryptography>=2.7 (from autobahn->wslink)
Using cached https://files.pythonhosted.org/packages/70/d2/ae380f16d025459d282878e094518664a13a0e740cc957b1ada59590991d/cryptography-3.1.1-cp35-abi3-manylinux1_x86_64.whl
Collecting txaio>=20.3.1 (from autobahn->wslink)
Using cached https://files.pythonhosted.org/packages/4f/82/0cd8d81d57e55a598cd4cef10c6e971dbcaf437e4f138dc1624cf7c1388e/txaio-20.4.1-py2.py3-none-any.whl
Collecting Automat>=0.3.0 (from Twisted->wslink)
Using cached https://files.pythonhosted.org/packages/dd/83/5f6f3c1a562674d65efc320257bdc0873ec53147835aeef7762fe7585273/Automat-20.2.0-py2.py3-none-any.whl
Collecting PyHamcrest!=1.10.0,>=1.9.0 (from Twisted->wslink)
Using cached https://files.pythonhosted.org/packages/40/16/e54cc65891f01cb62893540f44ffd3e8dab0a22443e1b438f1a9f5574bee/PyHamcrest-2.0.2-py3-none-any.whl
Collecting hyperlink>=17.1.1 (from Twisted->wslink)
Using cached https://files.pythonhosted.org/packages/88/a5/74f77547e9b175eb894d4fec5c76b0c8176c045e5bf3ac6a4d4d3feab4bb/hyperlink-20.0.1-py2.py3-none-any.whl
Collecting zope.interface>=4.4.2 (from Twisted->wslink)
Using cached https://files.pythonhosted.org/packages/98/cc/3c153095d5eac26170498d298aa2efdc5c464142aeed6c62420f80099392/zope.interface-5.1.2-cp38-cp38-manylinux1_x86_64.whl
Collecting constantly>=15.1 (from Twisted->wslink)
Using cached https://files.pythonhosted.org/packages/b9/65/48c1909d0c0aeae6c10213340ce682db01b48ea900a7d9fce7a7910ff318/constantly-15.1.0-py2.py3-none-any.whl
Collecting incremental>=16.10.1 (from Twisted->wslink)
Using cached https://files.pythonhosted.org/packages/f5/1d/c98a587dc06e107115cf4a58b49de20b19222c83d75335a192052af4c4b7/incremental-17.5.0-py2.py3-none-any.whl
Collecting attrs>=19.2.0 (from Twisted->wslink)
Using cached https://files.pythonhosted.org/packages/14/df/479736ae1ef59842f512548bacefad1abed705e400212acba43f9b0fa556/attrs-20.2.0-py2.py3-none-any.whl
Collecting six>=1.4.1 (from cryptography>=2.7->autobahn->wslink)
Using cached https://files.pythonhosted.org/packages/ee/ff/48bde5c0f013094d729fe4b0316ba2a24774b3ff1c52d924a8a4cb04078a/six-1.15.0-py2.py3-none-any.whl
Collecting cffi!=1.11.3,>=1.8 (from cryptography>=2.7->autobahn->wslink)
Using cached https://files.pythonhosted.org/packages/c6/60/44b6c54dbbee7d5eafbc34e0a0b67207e85906fe8e36c830dfd3966dde1d/cffi-1.14.3-cp38-cp38-manylinux1_x86_64.whl
Collecting idna>=2.5 (from hyperlink>=17.1.1->Twisted->wslink)
Using cached https://files.pythonhosted.org/packages/a2/38/928ddce2273eaa564f6f50de919327bf3a00f091b5baba8dfa9460f3a8a8/idna-2.10-py2.py3-none-any.whl
Collecting setuptools (from zope.interface>=4.4.2->Twisted->wslink)
Using cached https://files.pythonhosted.org/packages/44/a6/7fb6e8b3f4a6051e72e4e2218889351f0ee484b9ee17e995f5ccff780300/setuptools-50.3.0-py3-none-any.whl
Collecting pycparser (from cffi!=1.11.3,>=1.8->cryptography>=2.7->autobahn->wslink)
Using cached https://files.pythonhosted.org/packages/ae/e7/d9c3a176ca4b02024debf82342dab36efadfc5776f9c8db077e8f6e71821/pycparser-2.20-py2.py3-none-any.whl
Installing collected packages: six, pycparser, cffi, cryptography, txaio, autobahn, attrs, Automat, PyHamcrest, idna, hyperlink, setuptools, zope.interface, constantly, incremental, Twisted, wslink
Segmentation fault (core dumped)

Code cleanup

  • Testing
    • Cleanup testing
      • /tests/chat-rpc-pub-sub
      • /tests/simple
      • /python/examples/*
      • /python/src/tests/*
    • Document testing process
    • Automate testing
  • Documentation
    • Fix WebSite generation
    • Improve content
  • JavaScript
    • Upgrade dependency
    • Cleanup code
  • Python
    • Cleanup code
  • CI
    • Move to github actions
    • Enable semantic-release
    • Automate testing
    • Automatic WebSite generation

Handling ssl connexion

Is your feature request related to a problem? Please describe.

We want to create a wss connexion using wslink and aiohttp. There is no wslink argument to activate the secure connexion.

Describe the solution you'd like

Allow forwarding a ssl_context to the aiohttp server.

Describe alternatives you've considered

We do not see an alternative without forking.

Additional context

We are creating a hosted https web app with wslink as a backend. This is why we need the ssl_context.

Is it possible to support modifying the default mouse behavior?

Is your feature request related to a problem? Please describe.

I want to implement length measurement on VR, so I want to change the left mouse button to measure length behavior and the right mouse button to rotate behavior

Describe the solution you'd like

A clear and concise description of what you want to happen.

Describe alternatives you've considered

A clear and concise description of any alternative solutions or features you've considered.

Additional context

image

Binary attachments in nested structures

In version 0.1.3 and before, the client can only unpack binary attachments into messages where the attachment is at the first level - directly in a result list, or in the value of a key/value pair in a result object.

It needs to do a recursive search for the attachment indicator.

RPC call application.exit.later unsuccessful: connection not open

Hey guys, I've encountered a problem. When we call the destroy method of SmartConnect, the cleanUp function within it initiates a session.close operation first. This results in an error when the destroy method of WebsocketConnection is called immediately afterwards, as model.session.call('application.exit.later', [timeout]) is called on a session that's already been closed.
Besides, could you help explain the function of 'application.exit.later' to me?

{code: -32099, message: 'RPC call application.exit.later unsuccessful: connection not open'}

Allow to launch wslink server without a shutdown timer

Hi,

We are building a paraview remote server around wslink, and need to disable the automatic shutdown timeout built-in (because our server lifetime will be handled by another mechanism).
What do you think to allow to pass 0 as timeout value to disable it?

(One could pass a huge value as argument, however it's not clean, and would be quite fragile.)

If it suits you, I propose a PR.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.