perspective icon indicating copy to clipboard operation
perspective copied to clipboard

Calling get_hosted_table_names on the Python websocketclients always returns None

Open tjader opened this issue 2 years ago • 0 comments

Bug Report

Steps to Reproduce:

When using the method get_hosted_table_names PerspectiveTornadoClient or PerspectiveAIOHTTPClient I always get back None

  1. Start the tornado streaming server (in the examples folder). This one has one table named data_source_one managed
  2. Run the following script
import asyncio
from perspective.client.aiohttp import PerspectiveAIOHTTPClient
from perspective.client.tornado import PerspectiveTornadoClient

async def main_current(client_cls):
    client = client_cls()
    try:
        await client.connect('ws://127.0.0.1:8080/websocket')
        names = await client.get_hosted_table_names()
        print(f"{client_cls.__name__} - current: {names}")
    finally:
        await client.terminate()

if __name__ == '__main__':
    for client_cls in [PerspectiveTornadoClient, PerspectiveAIOHTTPClient]:
        asyncio.run(main_current(client_cls))

Expected Result:

I would expect ['data_source_one'] to be printed.

Actual Result:

Instead of ['data_source_one'] , names is None.

Environment:

Using perspective 2.5.1 on Python 3.11 inside a conda environment

Additional Context:

I think the issue can be fixed inside the method perspective.client.base.PerspectiveClient:get_hosted_table_names. If I understand the code correctly, this method should call self.post with a Future object, and return the future object instead. I.e. something like

    def get_hosted_table_names(self):
        fut = asyncio.Future()
        msg = {"cmd": "get_hosted_table_names"}
        self.post(msg, future=fut)
        return fut

A hacky version of my exampe shows it works, although I'm not sure what type of future object you normally use

import asyncio
from perspective.client.aiohttp import PerspectiveAIOHTTPClient
from perspective.client.tornado import PerspectiveTornadoClient

async def main_working(client_cls):
    client = client_cls()
    try:
        await client.connect('ws://127.0.0.1:8080/websocket')

        # get_hosted_table_names is just a thin wrapper around the post function. 
        # this code replicates its functionality
        fut = asyncio.Future()
        client.post(msg = {"cmd": "get_hosted_table_names"}, future=fut)
        names = await fut
        print(f"{client_cls.__name__} - workaround: {names}")
    finally:
        await client.terminate()


if __name__ == '__main__':
    for client_cls in [PerspectiveTornadoClient, PerspectiveAIOHTTPClient]:      
        asyncio.run(main_working(client_cls))

tjader avatar Sep 07 '23 09:09 tjader