wiz-trader 0.22.0__tar.gz → 0.24.0__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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wiz_trader
3
- Version: 0.22.0
3
+ Version: 0.24.0
4
4
  Summary: A Python SDK for connecting to the Wizzer.
5
5
  Home-page: https://bitbucket.org/wizzer-tech/quotes_sdk.git
6
6
  Author: Pawan Wagh
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "wiz_trader"
7
- version = "0.22.0"
7
+ version = "0.24.0"
8
8
  description = "A Python SDK for connecting to the Wizzer."
9
9
  readme = "README.md"
10
10
  authors = [
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='wiz_trader',
5
- version='0.22.0',
5
+ version='0.24.0',
6
6
  description='A Python SDK for connecting to the Wizzer.',
7
7
  long_description=open('README.md').read() if open('README.md') else "",
8
8
  long_description_content_type='text/markdown',
@@ -3,6 +3,6 @@
3
3
  from .quotes import QuotesClient
4
4
  from .apis import WizzerClient
5
5
 
6
- __version__ = "0.22.0"
6
+ __version__ = "0.24.0"
7
7
 
8
8
  __all__ = ["QuotesClient", "WizzerClient"]
@@ -60,6 +60,7 @@ class QuotesClient:
60
60
  self.subscribed_instruments: set = set()
61
61
  self._running = False
62
62
  self._background_task = None
63
+ self._loop: Optional[asyncio.AbstractEventLoop] = None
63
64
 
64
65
  self._backoff_base = 1
65
66
  self._backoff_factor = 2
@@ -162,9 +163,6 @@ class QuotesClient:
162
163
  # -- Async core methods (for internal use) --
163
164
 
164
165
  async def _subscribe_async(self, instruments: List[str]) -> None:
165
- """
166
- Internal async subscription. Use `subscribe()` wrapper to schedule this.
167
- """
168
166
  if self.ws and self.ws.state == State.OPEN:
169
167
  new = set(instruments) - self.subscribed_instruments
170
168
  if new:
@@ -177,30 +175,13 @@ class QuotesClient:
177
175
  }))
178
176
  await asyncio.sleep(0.1)
179
177
  else:
180
- # queue it for next connect
181
178
  self.subscribed_instruments |= set(instruments)
182
179
 
183
- # -- Public wrappers for plain callback users --
184
-
185
- def subscribe(self, instruments: List[str]) -> None:
186
- """
187
- Schedule an async subscribe so users can call this without 'await'.
188
- """
189
- try:
190
- loop = asyncio.get_event_loop()
191
- except RuntimeError:
192
- loop = asyncio.new_event_loop()
193
- asyncio.set_event_loop(loop)
194
- loop.create_task(self._subscribe_async(instruments))
195
-
196
180
  async def _unsubscribe_async(self, instruments: List[str]) -> None:
197
- """
198
- Internal async unsubscription. Use `unsubscribe()` wrapper to schedule this.
199
- """
200
- # Only send unsubs if the socket is open
201
181
  if self.ws and self.ws.state == State.OPEN:
202
182
  to_remove = set(instruments) & self.subscribed_instruments
203
183
  if to_remove:
184
+ self.subscribed_instruments -= to_remove
204
185
  for batch in self._chunk_list(list(to_remove), self.batch_size):
205
186
  logger.info("Unsubscribing from %d instruments", len(batch))
206
187
  await self.ws.send(json.dumps({
@@ -208,24 +189,41 @@ class QuotesClient:
208
189
  "instruments": batch
209
190
  }))
210
191
  await asyncio.sleep(0.1)
211
- # remove them from our local set
212
- self.subscribed_instruments -= to_remove
213
192
  else:
214
- # if we're not connected yet, just remove from the queue
215
193
  self.subscribed_instruments -= set(instruments)
216
194
 
195
+ # -- Public wrappers for plain callback users --
196
+
197
+ def subscribe(self, instruments: List[str]) -> None:
198
+ """
199
+ Schedule subscribe onto the client’s event loop.
200
+ """
201
+ if self._loop:
202
+ asyncio.run_coroutine_threadsafe(
203
+ self._subscribe_async(instruments),
204
+ self._loop
205
+ )
206
+ else:
207
+ self.subscribed_instruments |= set(instruments)
208
+
217
209
  def unsubscribe(self, instruments: List[str]) -> None:
218
210
  """
219
- Schedule an async unsubscribe so users can call this without 'await'.
211
+ Schedule unsubscribe onto the client’s event loop.
220
212
  """
221
- try:
222
- loop = asyncio.get_event_loop()
223
- except RuntimeError:
224
- loop = asyncio.new_event_loop()
225
- asyncio.set_event_loop(loop)
226
- loop.create_task(self._unsubscribe_async(instruments))
227
-
228
- # You could add a similar unsubscribe wrapper if needed
213
+ if self._loop:
214
+ asyncio.run_coroutine_threadsafe(
215
+ self._unsubscribe_async(instruments),
216
+ self._loop
217
+ )
218
+ else:
219
+ self.subscribed_instruments -= set(instruments)
220
+
221
+ def unsubscribe_all(self) -> None:
222
+ """
223
+ Unsubscribe from all currently subscribed instruments.
224
+ """
225
+ if self.subscribed_instruments:
226
+ self.unsubscribe(list(self.subscribed_instruments))
229
227
 
230
228
  async def close(self) -> None:
231
229
  """
@@ -252,6 +250,7 @@ class QuotesClient:
252
250
  except RuntimeError:
253
251
  loop = asyncio.new_event_loop()
254
252
  asyncio.set_event_loop(loop)
253
+ self._loop = loop
255
254
 
256
255
  try:
257
256
  loop.run_until_complete(self._connect_with_backoff())
@@ -274,6 +273,7 @@ class QuotesClient:
274
273
  return
275
274
  self._running = True
276
275
  loop = asyncio.get_event_loop()
276
+ self._loop = loop
277
277
  self._background_task = loop.create_task(self._connect_with_backoff())
278
278
 
279
279
  def stop(self) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wiz_trader
3
- Version: 0.22.0
3
+ Version: 0.24.0
4
4
  Summary: A Python SDK for connecting to the Wizzer.
5
5
  Home-page: https://bitbucket.org/wizzer-tech/quotes_sdk.git
6
6
  Author: Pawan Wagh
File without changes
File without changes
File without changes