Skip to content

Commit 120a977

Browse files
committed
ADD: Add Python client set_symbology_json
1 parent 8d95a01 commit 120a977

File tree

5 files changed

+85
-22
lines changed

5 files changed

+85
-22
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 0.31.0 - TBD
4+
5+
#### Enhancements
6+
- Added `DBNStore.insert_symbology_json` convenience method for adding symbology data from a JSON dict or file path
7+
38
## 0.30.0 - 2024-02-22
49

510
#### Enhancements

databento/common/dbnstore.py

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import logging
77
from collections.abc import Generator
88
from collections.abc import Iterator
9+
from collections.abc import Mapping
910
from io import BytesIO
1011
from os import PathLike
1112
from pathlib import Path
@@ -18,6 +19,7 @@
1819
Final,
1920
Literal,
2021
Protocol,
22+
TextIO,
2123
overload,
2224
)
2325

@@ -108,20 +110,16 @@ class DataSource(abc.ABC):
108110
Abstract base class for backing DBNStore instances with data.
109111
"""
110112

111-
def __init__(self, source: object) -> None:
112-
...
113+
def __init__(self, source: object) -> None: ...
113114

114115
@property
115-
def name(self) -> str:
116-
...
116+
def name(self) -> str: ...
117117

118118
@property
119-
def nbytes(self) -> int:
120-
...
119+
def nbytes(self) -> int: ...
121120

122121
@property
123-
def reader(self) -> IO[bytes]:
124-
...
122+
def reader(self) -> IO[bytes]: ...
125123

126124

127125
class FileDataSource(DataSource):
@@ -675,6 +673,27 @@ def from_bytes(cls, data: BytesIO | bytes | IO[bytes]) -> DBNStore:
675673
"""
676674
return cls(MemoryDataSource(data))
677675

676+
def insert_symbology_json(
677+
self,
678+
json_data: str | Mapping[str, Any] | TextIO,
679+
clear_existing: bool = True,
680+
) -> None:
681+
"""
682+
Insert the given JSON data obtained from the `symbology.resolve`
683+
endpoint or a `symbology.json` file.
684+
685+
Parameters
686+
----------
687+
json_data : str | Mapping[str, Any] | TextIO
688+
The JSON data to insert.
689+
clear_existing : bool, default True
690+
If existing symbology data should be cleared from the internal mappings.
691+
692+
"""
693+
if clear_existing:
694+
self._instrument_map.clear()
695+
self._instrument_map.insert_json(json_data)
696+
678697
def replay(self, callback: Callable[[Any], None]) -> None:
679698
"""
680699
Replay data by passing records sequentially to the given callback.
@@ -834,8 +853,7 @@ def to_df(
834853
schema: Schema | str | None = ...,
835854
tz: pytz.BaseTzInfo | str = ...,
836855
count: None = ...,
837-
) -> pd.DataFrame:
838-
...
856+
) -> pd.DataFrame: ...
839857

840858
@overload
841859
def to_df(
@@ -846,16 +864,17 @@ def to_df(
846864
schema: Schema | str | None = ...,
847865
tz: pytz.BaseTzInfo | str = ...,
848866
count: int = ...,
849-
) -> DataFrameIterator:
850-
...
867+
) -> DataFrameIterator: ...
851868

852869
def to_df(
853870
self,
854871
price_type: Literal["fixed", "float", "decimal"] = "float",
855872
pretty_ts: bool = True,
856873
map_symbols: bool = True,
857874
schema: Schema | str | None = None,
858-
tz: pytz.BaseTzInfo | str | Default[pytz.BaseTzInfo] = Default[pytz.BaseTzInfo](pytz.UTC),
875+
tz: pytz.BaseTzInfo | str | Default[pytz.BaseTzInfo] = Default[pytz.BaseTzInfo](
876+
pytz.UTC,
877+
),
859878
count: int | None = None,
860879
) -> pd.DataFrame | DataFrameIterator:
861880
"""
@@ -903,7 +922,9 @@ def to_df(
903922
if isinstance(tz, Default):
904923
tz = tz.value # consume default
905924
elif not pretty_ts:
906-
raise ValueError("A timezone was specified when `pretty_ts` is `False`. Did you mean to set `pretty_ts=True`?")
925+
raise ValueError(
926+
"A timezone was specified when `pretty_ts` is `False`. Did you mean to set `pretty_ts=True`?",
927+
)
907928

908929
if not isinstance(tz, pytz.BaseTzInfo):
909930
tz = pytz.timezone(tz)
@@ -1096,16 +1117,14 @@ def to_ndarray( # type: ignore [misc]
10961117
self,
10971118
schema: Schema | str | None = ...,
10981119
count: None = ...,
1099-
) -> np.ndarray[Any, Any]:
1100-
...
1120+
) -> np.ndarray[Any, Any]: ...
11011121

11021122
@overload
11031123
def to_ndarray(
11041124
self,
11051125
schema: Schema | str | None = ...,
11061126
count: int = ...,
1107-
) -> NDArrayIterator:
1108-
...
1127+
) -> NDArrayIterator: ...
11091128

11101129
def to_ndarray(
11111130
self,
@@ -1242,12 +1261,10 @@ def _schema_struct_map(self) -> dict[Schema, type[DBNRecord]]:
12421261

12431262
class NDArrayIterator(Protocol):
12441263
@abc.abstractmethod
1245-
def __iter__(self) -> NDArrayIterator:
1246-
...
1264+
def __iter__(self) -> NDArrayIterator: ...
12471265

12481266
@abc.abstractmethod
1249-
def __next__(self) -> np.ndarray[Any, Any]:
1250-
...
1267+
def __next__(self) -> np.ndarray[Any, Any]: ...
12511268

12521269

12531270
class NDArrayStreamIterator(NDArrayIterator):

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ types-pytz = "^2024.1.0.20240203"
5757
requires = ["poetry-core"]
5858
build-backend = "poetry.core.masonry.api"
5959

60+
[tool.black]
61+
line_length = 100
62+
6063
[tool.mypy]
6164
python_version = 3.8
6265
disallow_untyped_defs = true

tests/conftest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Pytest fixtures.
33
"""
4+
45
from __future__ import annotations
56

67
import asyncio
@@ -219,6 +220,7 @@ def fixture_thread_loop() -> Generator[asyncio.AbstractEventLoop, None, None]:
219220
yield loop
220221
loop.stop()
221222

223+
222224
@pytest.fixture(name="mock_live_server")
223225
def fixture_mock_live_server(
224226
thread_loop: asyncio.AbstractEventLoop,
@@ -266,6 +268,7 @@ def fixture_mock_live_server(
266268
loop=thread_loop,
267269
).result()
268270

271+
269272
@pytest.fixture(name="historical_client")
270273
def fixture_historical_client(
271274
test_api_key: str,

tests/test_common_symbology.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,3 +961,38 @@ def test_instrument_map_symbols_json(
961961
# Assert
962962
assert outfile == written_path
963963
assert outfile.read_text() == expected_path.read_text()
964+
965+
966+
def test_insert_symbology_json_mismatched_stypes(
967+
test_data_path: Callable[[Dataset, Schema], pathlib.Path],
968+
) -> None:
969+
"""
970+
Test setting JSON symbology data.
971+
"""
972+
# Arrange
973+
store = DBNStore.from_file(test_data_path(Dataset.XNAS_ITCH, Schema.TRADES))
974+
975+
result = {
976+
"NVDA": [
977+
{
978+
"d0": store.start.date().isoformat(),
979+
"d1": store.end.date().isoformat(),
980+
"s": "6155",
981+
},
982+
],
983+
}
984+
sym_resp = create_symbology_response(
985+
result=result,
986+
symbols=store.symbols,
987+
stype_in=SType.RAW_SYMBOL,
988+
stype_out=SType.INSTRUMENT_ID,
989+
start_date=store.start.date(),
990+
end_date=store.end.date(),
991+
)
992+
993+
# Act
994+
store.insert_symbology_json(sym_resp)
995+
996+
# Assert
997+
assert store.to_df().iloc[0]["symbol"] == "NVDA"
998+
assert store.to_df().iloc[0]["instrument_id"] == 6155

0 commit comments

Comments
 (0)