bw-essentials-core 0.1.19__tar.gz → 0.1.20__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.

Potentially problematic release.


This version of bw-essentials-core might be problematic. Click here for more details.

Files changed (36) hide show
  1. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/PKG-INFO +1 -1
  2. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/api_client.py +36 -0
  3. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/master_data.py +51 -0
  4. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials_core.egg-info/PKG-INFO +1 -1
  5. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/setup.py +1 -1
  6. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/README.md +0 -0
  7. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/__init__.py +0 -0
  8. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/constants/__init__.py +0 -0
  9. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/constants/services.py +0 -0
  10. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/data_loch/__init__.py +0 -0
  11. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/data_loch/data_loch.py +0 -0
  12. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/email_client/__init__.py +0 -0
  13. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/email_client/email_client.py +0 -0
  14. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/notifications/__init__.py +0 -0
  15. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/notifications/teams_notification_schemas.py +0 -0
  16. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/notifications/teams_notifications.py +0 -0
  17. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/s3_utils/__init__.py +0 -0
  18. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/s3_utils/s3_utils.py +0 -0
  19. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/__init__.py +0 -0
  20. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/broker.py +0 -0
  21. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/job_scheduler.py +0 -0
  22. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/market_pricer.py +0 -0
  23. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/model_portfolio_reporting.py +0 -0
  24. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/notification.py +0 -0
  25. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/payment.py +0 -0
  26. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/portfolio_catalogue.py +0 -0
  27. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/portfolio_content.py +0 -0
  28. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/trade_placement.py +0 -0
  29. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/user_app.py +0 -0
  30. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/user_portfolio.py +0 -0
  31. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials/services/user_portfolio_reporting.py +0 -0
  32. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials_core.egg-info/SOURCES.txt +0 -0
  33. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials_core.egg-info/dependency_links.txt +0 -0
  34. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials_core.egg-info/requires.txt +0 -0
  35. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/bw_essentials_core.egg-info/top_level.txt +0 -0
  36. {bw_essentials_core-0.1.19 → bw_essentials_core-0.1.20}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bw-essentials-core
3
- Version: 0.1.19
3
+ Version: 0.1.20
4
4
  Summary: Reusable utilities for S3, email, Data Loch, Microsoft Teams Notifications and more.
5
5
  Author: InvestorAI
6
6
  Author-email: support+tech@investorai.in
@@ -15,6 +15,7 @@ import logging
15
15
  import os
16
16
  import sys
17
17
  import time
18
+ import httpx
18
19
  from importlib.util import spec_from_file_location, module_from_spec
19
20
  from typing import Optional, Dict, Any
20
21
 
@@ -195,6 +196,41 @@ class ApiClient:
195
196
  """
196
197
  return self._request("get", url, endpoint, params=params)
197
198
 
199
+ async def _async_get(self, url: str, endpoint: str, headers: dict | None = None, params: dict | None = None):
200
+ """
201
+ Async GET request, aligned with the sync _request() style.
202
+ """
203
+ headers = self._update_headers(headers or {})
204
+ params = params or {}
205
+ formatted_url = f"{url.rstrip('/')}/{endpoint.lstrip('/')}"
206
+
207
+ logger.info(f"GET {formatted_url} | Headers: {headers} | Params: {params}")
208
+
209
+ start = time.time()
210
+ try:
211
+ async with httpx.AsyncClient() as client:
212
+ response = await client.get(formatted_url, headers=headers, params=params)
213
+
214
+ elapsed_time_ms = (time.time() - start) * 1000
215
+
216
+ # parse JSON safely
217
+ try:
218
+ json_data = response.json()
219
+ except ValueError:
220
+ logger.error(f"Non-JSON response from {formatted_url}")
221
+ json_data = None
222
+
223
+ self._log_response("GET", formatted_url, response.status_code, elapsed_time_ms, json_data)
224
+
225
+ response.raise_for_status()
226
+ return json_data
227
+
228
+ except Exception as exc:
229
+ elapsed_time_ms = (time.time() - start) * 1000
230
+ logger.error(f"GET {formatted_url} failed after {elapsed_time_ms:.2f}ms")
231
+ logger.exception(exc)
232
+ raise
233
+
198
234
  def _post(
199
235
  self,
200
236
  url: str,
@@ -299,3 +299,54 @@ class MasterData(ApiClient):
299
299
  response = self._get(url=self.base_url, endpoint=self.urls["broker_partner_mapping_details"].format(broker_partner, broker))
300
300
  logger.info(f"Broker partner mapping {response =}")
301
301
  return response.get('data', {})
302
+
303
+ async def get_broker_data_async(self, symbols, broker, username=None):
304
+ """
305
+ Asynchronously retrieve broker-specific data for specified symbols.
306
+
307
+ This function fetches broker-specific details such as margin and leverage
308
+ for a list of provided trading symbols from the broker master service.
309
+
310
+ Args:
311
+ username (str) [Optional]: The user_id for whom data is requested.
312
+ symbols (str): A comma-separated string of trading symbols.
313
+ broker (str): The broker identifier for which data is requested.
314
+
315
+ Returns:
316
+ list: A list of dictionaries containing broker data for each symbol
317
+ or an empty list if no data is available.
318
+ """
319
+ logger.info(f"In - get_broker_data_async {broker =}")
320
+ broker_data_response = await self._async_get(
321
+ url=f"{self.base_url}",
322
+ endpoint = self.urls["broker_details"].format(broker),
323
+ params={"symbols": symbols, "user_id": username},
324
+ headers={}
325
+ )
326
+ return broker_data_response.get('data', [])
327
+
328
+ def get_broker_data_all(self, symbols, broker, username=None):
329
+ """
330
+ Retrieve broker-specific data for specified symbols.
331
+
332
+ This function fetches broker-specific details such as margin and leverage
333
+ for a list of provided trading symbols from the broker master service.
334
+
335
+ Args:
336
+ username (str) [Optional]: The user_id for whom data is requested.
337
+ symbols (str): A comma-separated string of trading symbols.
338
+ broker (str): The broker identifier for which data is requested.
339
+
340
+ Returns:
341
+ dict: A dictionary containing broker data for the first symbol or
342
+ an empty dictionary if no data is available.
343
+ """
344
+ logger.info(f"In - get_broker_data {broker =}")
345
+ broker_data_response = self._get(
346
+ url=f"{self.base_url}",
347
+ endpoint=self.urls['broker_details'].format(broker),
348
+ params={"symbols": symbols, "user_id": username},
349
+ )
350
+ if broker_data_response.get('data'):
351
+ return broker_data_response.get('data')
352
+ return {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bw-essentials-core
3
- Version: 0.1.19
3
+ Version: 0.1.20
4
4
  Summary: Reusable utilities for S3, email, Data Loch, Microsoft Teams Notifications and more.
5
5
  Author: InvestorAI
6
6
  Author-email: support+tech@investorai.in
@@ -10,7 +10,7 @@ from setuptools import setup, find_packages
10
10
 
11
11
  setup(
12
12
  name="bw-essentials-core",
13
- version="0.1.19",
13
+ version="0.1.20",
14
14
  author="InvestorAI",
15
15
  author_email="support+tech@investorai.in",
16
16
  description="Reusable utilities for S3, email, Data Loch, Microsoft Teams Notifications and more.",