I have this code to interact with a websocket api using async
and websokets
python libraries:
#!/usr/bin/env python3
import sys, json
import asyncio
from websockets import connect
class AsyncWebsocket():
async def __aenter__(self):
self._conn = connect('wss://ws.myws.com/v2')
self.websocket = await self._conn.__aenter__()
return self
async def __aexit__(self, *args, **kwargs):
await self._conn.__aexit__(*args, **kwargs)
async def send(self, message):
await self.websocket.send(message)
async def receive(self):
return await self.websocket.recv()
class mtest():
def __init__(self, api_token):
self.aws = AsyncWebsocket()
self.loop = asyncio.get_event_loop()
self.api_token = api_token
self.authorize()
def authorize(self):
jdata = self.__async_exec({
'authorize': self.api_token
})
try:
print (jdata['email'])
ret = True
except:
ret = False
return ret
def sendtest(self):
jdata = self.__async_exec({
"hello": 1
})
print (jdata)
def __async_exec(self, jdata):
try:
ret = json.loads(self.loop.run_until_complete(self.__async_send_recieve(jdata)))
except:
ret = None
return ret
async def __async_send_recieve(self, jdata):
async with self.aws:
await self.aws.send(json.dumps(jdata))
return await self.aws.receive()
So I have the following in main.py:
from webclass import *
a = mtest('12341234')
print (a.sendtest())
The problem is that it doesn't preserve the authorized session, so this is the output:
root@ubupc1:/home/dinocob# python3 test.py
asd@gmail.com
{'error': {'message': 'Please log in.', 'code': 'AuthorizationRequired'}}
As you see, the login call are working ok, but when calling and sending the hello
in sendtest
function, the session is not the same.
I think that the issue might be in the context_manager or the with
statement.
async def __async_send_recieve(self, jdata):
async with self.aws:
await self.aws.send(json.dumps(jdata))
return await self.aws.receive()
When you invoke 'with' the context should play out as following (with better exception handling and all the benefits of context managers, so you can picture the flow of __async_send_recieve
as:
self.aws.__aenter__()
self.aws.send(data)
self.aws.receive()
self.aws.__aexit__()
To prove this theory, add a print statement into the __aenter__
and __aexit__
functions, and you should be able to better visualize the context manager flow.
The fix would be to re-authorize in every request. But I imagine what you want to do is have your test class to manage the context used to communicate with the remote server. (my async syntax might be a little wrong here, but conceptually with context managers):
class Mtest():
def __init__(self, ...):
...
def __enter__(self,):
self.authorize()
def __exit__(self):
self.deauthorize()
async def make_async_request(self, data):
await self.aws.send(json.dumps(data))
return await self.aws.receive()
with Mtest(api_key) as m:
m.make_async_request({'test_data': 'dummy_test_data'})
m.make_async_request({'more_data': 'more_mock_data'})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With