crypto-ws-api 2.0.8__tar.gz → 2.0.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,7 @@
1
+ ## 2.0.9 - 2024-04-14
2
+ ### Fix
3
+ * Creating asynchronous tasks done right
4
+
1
5
  ## 2.0.8 - 2024-03-31
2
6
  ### Fix
3
7
  * tons log records: `websockets socket.send() raised exception.`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: crypto-ws-api
3
- Version: 2.0.8
3
+ Version: 2.0.9
4
4
  Summary: Crypto WS API connector for ASYNC requests
5
5
  Author-email: Jerry Fedorenko <jerry.fedorenko@yahoo.com>
6
6
  Requires-Python: >=3.8
@@ -13,7 +13,7 @@ __maintainer__ = "Jerry Fedorenko"
13
13
  __contact__ = "https://github.com/DogsTailFarmer"
14
14
  __email__ = "jerry.fedorenko@yahoo.com"
15
15
  __credits__ = ["https://github.com/DanyaSWorlD"]
16
- __version__ = "2.0.8"
16
+ __version__ = "2.0.9"
17
17
 
18
18
  from pathlib import Path
19
19
  import shutil
@@ -66,7 +66,7 @@ class UserWSS:
66
66
  "request_limit_reached",
67
67
  "in_event",
68
68
  "_response_pool",
69
- "tasks_list",
69
+ "tasks",
70
70
  )
71
71
 
72
72
  def __init__(self, method, ws_id, exchange, endpoint, api_key, api_secret, passphrase=None):
@@ -87,10 +87,17 @@ class UserWSS:
87
87
  self.order_handling = False
88
88
  self.request_limit_reached = False
89
89
  self.in_event = asyncio.Event()
90
- self.tasks_list = []
90
+ self.tasks = set()
91
+
92
+ def tasks_manage(self, coro, name=None):
93
+ _t = asyncio.create_task(coro)
94
+ if name:
95
+ _t.set_name(name)
96
+ self.tasks.add(_t)
97
+ _t.add_done_callback(self.tasks.discard)
91
98
 
92
99
  async def _ws_listener(self):
93
- asyncio.ensure_future(self.ws_login())
100
+ self.tasks_manage(self.ws_login())
94
101
  async for msg in self._ws:
95
102
  # logger.info(f"_ws_listener: msg: {self.ws_id}: {msg}")
96
103
  if isinstance(msg, str):
@@ -119,8 +126,8 @@ class UserWSS:
119
126
  break
120
127
  else:
121
128
  self.operational_status = False
122
- [task.cancel() for task in self.tasks_list if not task.done()]
123
- self.tasks_list.clear()
129
+ [task.cancel() for task in self.tasks if not task.done()]
130
+ self.tasks.clear()
124
131
  logger.warning(f"Restart WSS for {self.ws_id}")
125
132
  continue
126
133
  except Exception as ex:
@@ -134,16 +141,12 @@ class UserWSS:
134
141
  else:
135
142
  if self.exchange == 'binance':
136
143
  self._listen_key = res.get('listenKey')
137
- _t = asyncio.ensure_future(self.heartbeat())
138
- _t.set_name(f"heartbeat-{self.ws_id}")
139
- self.tasks_list.append(_t)
144
+ self.tasks_manage(self.heartbeat(), f"heartbeat-{self.ws_id}")
140
145
  else:
141
146
  self._listen_key = f"{int(time.time() * 1000)}{self.ws_id}"
142
147
  self.operational_status = True
143
148
  self.order_handling = True
144
- _t = asyncio.ensure_future(self._keepalive())
145
- _t.set_name(f"keepalive-{self.ws_id}")
146
- self.tasks_list.append(_t)
149
+ self.tasks_manage(self._keepalive(), f"keepalive-{self.ws_id}")
147
150
  logger.info(f"UserWSS: 'logged in' for {self.ws_id}")
148
151
 
149
152
  async def request(self, _method=None, _params=None, _api_key=False, _signed=False):
@@ -275,8 +278,8 @@ class UserWSS:
275
278
  self.operational_status = None # Not restart and break all loops
276
279
  self.order_handling = False
277
280
  self.init = True
278
- [task.cancel() for task in self.tasks_list if not task.done()]
279
- self.tasks_list.clear()
281
+ [task.cancel() for task in self.tasks if not task.done()]
282
+ self.tasks.clear()
280
283
  if self._ws and not self._ws.closed:
281
284
  await self._ws.close(code=4000)
282
285
  gc.collect()
@@ -297,7 +300,7 @@ class UserWSS:
297
300
  elif self.exchange == 'bitfinex':
298
301
  return await self.bitfinex_error_handle(msg)
299
302
 
300
- #region BitfinexErrorHandle
303
+ # region BitfinexErrorHandle
301
304
  async def bitfinex_error_handle(self, msg):
302
305
  if isinstance(msg, dict):
303
306
  return await self._handle_dict_message(msg)
@@ -349,7 +352,7 @@ class UserWSS:
349
352
  msg[2][7]
350
353
  ]
351
354
  }
352
- #endregion
355
+ # endregion
353
356
 
354
357
  async def okx_error_handle(self, msg):
355
358
  if msg.get('code') == '1':
@@ -391,6 +394,7 @@ class UserWSSession:
391
394
  "_api_secret",
392
395
  "_passphrase",
393
396
  "user_wss",
397
+ "tasks_wss",
394
398
  )
395
399
 
396
400
  def __init__(self, exchange, endpoint, api_key, api_secret, passphrase=None):
@@ -403,6 +407,7 @@ class UserWSSession:
403
407
  self._api_secret = api_secret
404
408
  self._passphrase = passphrase
405
409
  self.user_wss = {}
410
+ self.tasks_wss = set()
406
411
 
407
412
  async def handle_request(
408
413
  self,
@@ -429,7 +434,9 @@ class UserWSSession:
429
434
  if user_wss.init:
430
435
  user_wss.init = False
431
436
  user_wss.operational_status = False
432
- asyncio.ensure_future(user_wss.start_wss())
437
+ _t = asyncio.create_task(user_wss.start_wss())
438
+ self.tasks_wss.add(_t)
439
+ _t.add_done_callback(self.tasks_wss.discard)
433
440
 
434
441
  duration = 0
435
442
  while not (user_wss.operational_status and user_wss.order_handling):
@@ -451,3 +458,5 @@ class UserWSSession:
451
458
  for ws in user_wss_copy.values():
452
459
  await ws.stop()
453
460
  self.user_wss.clear()
461
+ [task.cancel() for task in self.tasks_wss if not task.done()]
462
+ self.tasks_wss.clear()
File without changes
File without changes