Skip to content

Commit 23c521c

Browse files
committed
feat: SeekingAlpha as new datasource and Ticker_US as identifier type incl. test cases
SeekingAlpha as new datasource providing GICS classification data, implementation of US-Ticker as identifier type to easen integration of SeekingAlpha and support matching, cleanups for other clients
1 parent 6891085 commit 23c521c

14 files changed

Lines changed: 835 additions & 243 deletions

File tree

src/equities_classifier/clients/clienthelper.py

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,25 @@
1212

1313

1414
from typing import Any, cast
15-
1615
from collections import Counter
16+
from collections.abc import Collection, Mapping
1717

1818
import httpx
1919
from lxml import html
2020
from lxml.etree import _Element
2121

2222
from finance_enums import exchange_records_by_market_category
2323

24-
from equities_classifier.enums import (
25-
DataSourceID,
26-
SecurityIdentifierType,
27-
)
24+
from equities_classifier.enums import DataSourceID, SecurityIdentifierType
2825
from equities_classifier.models import SecurityIdentifier
2926
from equities_classifier.exceptions import ClientResponseError
3027
from equities_classifier.logginghelper import logger_equities_classifier
3128

3229

33-
class ClientHelper:
30+
# common error handler
31+
32+
33+
class ClientHelperErrorHandler:
3434
"""Helper methods for client processing."""
3535

3636
@staticmethod
@@ -290,7 +290,7 @@ def get_primary_ticker(
290290
if list_ticker and len(list_ticker) > 0 and list_mic_code and len(list_mic_code) > 0:
291291

292292
if len(list_ticker) != len(list_mic_code):
293-
ClientHelper.inconsistent_provider_data(
293+
ClientHelperErrorHandler.inconsistent_provider_data(
294294
provider,
295295
name,
296296
"count of 'ticker_exchange' and 'mic_code' differ",
@@ -311,15 +311,15 @@ def get_primary_ticker(
311311
if len(counter_tickers) > 0:
312312
ticker_new = counter_tickers.most_common(1)[0][0]
313313
if ticker_for_check and ticker_for_check != ticker_new:
314-
ClientHelper.inconsistent_provider_data(
314+
ClientHelperErrorHandler.inconsistent_provider_data(
315315
DataSourceID.OPENFIGI,
316316
name,
317317
f"ticker '{ticker_for_check}' currently set does not match assumed primary ticker '{ticker_new}'",
318318
error_object,
319319
)
320320
if (len(counter_tickers.most_common()) > 1 and
321321
counter_tickers.most_common(1)[0][1] == counter_tickers.most_common(2)[1][1]):
322-
ClientHelper.primary_ticker_not_unique(
322+
ClientHelperErrorHandler.primary_ticker_not_unique(
323323
DataSourceID.OPENFIGI,
324324
isin,
325325
error_object,
@@ -328,3 +328,43 @@ def get_primary_ticker(
328328
return ticker_new
329329

330330
return None
331+
332+
333+
# handling JSON maps
334+
335+
336+
def leaf_paths(
337+
data: Mapping[str, Any],
338+
path: tuple[str, ...] = (),
339+
exclude_leaves: Collection[str] = []
340+
) -> list[tuple[str, ...]]:
341+
"""Return all key paths from the root to every leaf."""
342+
343+
result: list[tuple[str, ...]] = []
344+
345+
for key, value in data.items():
346+
347+
if key in exclude_leaves:
348+
continue
349+
350+
current = (*path, key)
351+
if isinstance(value, Mapping):
352+
result.extend(leaf_paths(value, current, exclude_leaves))
353+
elif value:
354+
result.append(current)
355+
356+
return result
357+
358+
359+
def get_nested_value(data: dict[str, Any], path: tuple[str, ...], ) -> Any:
360+
"""Return a nested value from a dictionary."""
361+
362+
value: Any = data
363+
for key in path:
364+
if not isinstance(value, dict):
365+
return None
366+
value = value.get(key)
367+
if value is None:
368+
return None
369+
370+
return value

0 commit comments

Comments
 (0)