Skip to content

Commit 2c511e9

Browse files
authored
VER: Release 0.71.0
See release notes.
2 parents 289cec3 + 29273a2 commit 2c511e9

File tree

14 files changed

+318
-23
lines changed

14 files changed

+318
-23
lines changed

CHANGELOG.md

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

3+
## 0.71.0 - 2026-02-17
4+
5+
#### Enhancements
6+
- Added `slow_reader_behavior` field to `AuthenticationRequest` message
7+
- Added `SlowReaderBehavior` enum
8+
- Added support for using compression in the live API:
9+
- Added `compression` parameter to the `Live` client constructor
10+
- Added `compression` property to the `Live` client
11+
- Added `compression` field to `AuthenticationRequest`
12+
- Upgraded `databento-dbn` to 0.49.0:
13+
- Added support for decompressing Zstd in the Python `DBNDecoder` and new optional `compression` parameter
14+
315
## 0.70.0 - 2026-01-27
416

517
#### Enhancements

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The library is fully compatible with distributions of Anaconda 2023.x and above.
3232
The minimum dependencies as found in the `pyproject.toml` are also listed below:
3333
- python = "^3.10"
3434
- aiohttp = "^3.8.3"
35-
- databento-dbn = "~0.48.0"
35+
- databento-dbn = "~0.49.0"
3636
- numpy = ">=1.23.5"
3737
- pandas = ">=1.5.3"
3838
- pip-system-certs = ">=4.0" (Windows only)

databento/common/enums.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,14 @@ class JobState(StringyMixin, str, Enum):
257257
PROCESSING = "processing"
258258
DONE = "done"
259259
EXPIRED = "expired"
260+
261+
262+
@unique
263+
class SlowReaderBehavior(StringyMixin, str, Enum):
264+
"""
265+
Live session parameter which controls gateway behavior when the client
266+
falls behind real time.
267+
"""
268+
269+
SKIP = "skip"
270+
WARN = "warn"

databento/live/client.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414

1515
import databento_dbn
1616
import pandas as pd
17+
from databento_dbn import Compression
1718
from databento_dbn import DBNRecord
1819
from databento_dbn import Schema
1920
from databento_dbn import SType
2021

2122
from databento.common.constants import ALL_SYMBOLS
2223
from databento.common.cram import BUCKET_ID_LENGTH
2324
from databento.common.enums import ReconnectPolicy
25+
from databento.common.enums import SlowReaderBehavior
2426
from databento.common.error import BentoError
2527
from databento.common.parsing import optional_datetime_to_unix_nanoseconds
2628
from databento.common.publishers import Dataset
@@ -63,6 +65,13 @@ class Live:
6365
The reconnect policy for the live session.
6466
- "none": the client will not reconnect (default)
6567
- "reconnect": the client will reconnect automatically
68+
slow_reader_behavior: SlowReadBehavior | str, optional
69+
The live gateway behavior when the client falls behind real time.
70+
- "skip": skip records to immediately catch up
71+
- "warn": send a slow reader warning `SystemMsg` but continue reading every record
72+
compression : Compression or str, default "none"
73+
The compression format for live data. Set to "zstd" for
74+
Zstandard-compressed data from the gateway.
6675
6776
"""
6877

@@ -82,6 +91,8 @@ def __init__(
8291
ts_out: bool = False,
8392
heartbeat_interval_s: int | None = None,
8493
reconnect_policy: ReconnectPolicy | str = ReconnectPolicy.NONE,
94+
slow_reader_behavior: SlowReaderBehavior | str | None = None,
95+
compression: Compression = Compression.NONE,
8596
) -> None:
8697
if key is None:
8798
key = os.environ.get("DATABENTO_API_KEY")
@@ -99,6 +110,7 @@ def __init__(
99110

100111
self._dataset: Dataset | str = ""
101112
self._ts_out = ts_out
113+
self._compression = compression
102114
self._heartbeat_interval_s = heartbeat_interval_s
103115

104116
self._metadata: SessionMetadata = SessionMetadata()
@@ -112,6 +124,8 @@ def __init__(
112124
user_gateway=self._gateway,
113125
user_port=port,
114126
reconnect_policy=reconnect_policy,
127+
slow_reader_behavior=slow_reader_behavior,
128+
compression=compression,
115129
)
116130

117131
self._session._user_callbacks.append(ClientRecordCallback(self._map_symbol))
@@ -291,6 +305,18 @@ def ts_out(self) -> bool:
291305
"""
292306
return self._ts_out
293307

308+
@property
309+
def compression(self) -> Compression:
310+
"""
311+
Returns the compression mode for this live client.
312+
313+
Returns
314+
-------
315+
Compression
316+
317+
"""
318+
return self._compression
319+
294320
def add_callback(
295321
self,
296322
record_callback: RecordCallback,

databento/live/gateway.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
from typing import SupportsBytes
88
from typing import TypeVar
99

10+
from databento_dbn import Compression
1011
from databento_dbn import Encoding
1112
from databento_dbn import Schema
1213
from databento_dbn import SType
1314

15+
from databento.common.enums import SlowReaderBehavior
1416
from databento.common.publishers import Dataset
1517
from databento.common.system import USER_AGENT
1618

@@ -117,9 +119,16 @@ class AuthenticationRequest(GatewayControl):
117119
encoding: Encoding = Encoding.DBN
118120
details: str | None = None
119121
ts_out: str = "0"
122+
compression: Compression | str = Compression.NONE
120123
heartbeat_interval_s: int | None = None
124+
slow_reader_behavior: SlowReaderBehavior | str | None = None
121125
client: str = USER_AGENT
122126

127+
def __post_init__(self) -> None:
128+
# Temporary work around for LSG support
129+
if self.slow_reader_behavior in [SlowReaderBehavior.SKIP, "skip"]:
130+
self.slow_reader_behavior = "drop"
131+
123132

124133
@dataclasses.dataclass
125134
class SubscriptionRequest(GatewayControl):

databento/live/protocol.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import Final
88

99
import databento_dbn
10+
from databento_dbn import Compression
1011
from databento_dbn import DBNRecord
1112
from databento_dbn import Metadata
1213
from databento_dbn import Schema
@@ -16,6 +17,7 @@
1617

1718
from databento.common import cram
1819
from databento.common.constants import ALL_SYMBOLS
20+
from databento.common.enums import SlowReaderBehavior
1921
from databento.common.error import BentoError
2022
from databento.common.iterator import chunk
2123
from databento.common.parsing import optional_datetime_to_unix_nanoseconds
@@ -60,6 +62,8 @@ class DatabentoLiveProtocol(asyncio.BufferedProtocol):
6062
heartbeat_interval_s: int, optional
6163
The interval in seconds at which the gateway will send heartbeat records if no
6264
other data records are sent.
65+
compression : Compression, default Compression.NONE
66+
The compression format for the session.
6367
6468
See Also
6569
--------
@@ -73,6 +77,8 @@ def __init__(
7377
dataset: Dataset | str,
7478
ts_out: bool = False,
7579
heartbeat_interval_s: int | None = None,
80+
slow_reader_behavior: SlowReaderBehavior | str | None = None,
81+
compression: Compression = Compression.NONE,
7682
) -> None:
7783
self.__api_key = api_key
7884
self.__transport: asyncio.Transport | None = None
@@ -81,9 +87,12 @@ def __init__(
8187
self._dataset = validate_semantic_string(dataset, "dataset")
8288
self._ts_out = ts_out
8389
self._heartbeat_interval_s = heartbeat_interval_s
90+
self._slow_reader_behavior: SlowReaderBehavior | str | None = slow_reader_behavior
91+
self._compression = compression
8492

8593
self._dbn_decoder = databento_dbn.DBNDecoder(
8694
upgrade_policy=VersionUpgradePolicy.UPGRADE_TO_V3,
95+
compression=compression,
8796
)
8897
self._gateway_decoder = GatewayDecoder()
8998

@@ -440,14 +449,17 @@ def _(self, message: ChallengeRequest) -> None:
440449
auth=response,
441450
dataset=self._dataset,
442451
ts_out=str(int(self._ts_out)),
452+
compression=str(self._compression).lower(),
443453
heartbeat_interval_s=self._heartbeat_interval_s,
454+
slow_reader_behavior=self._slow_reader_behavior,
444455
)
445456
logger.debug(
446-
"sending CRAM challenge response auth='%s' dataset=%s encoding=%s ts_out=%s heartbeat_interval_s=%s client='%s'",
457+
"sending CRAM challenge response auth='%s' dataset=%s encoding=%s ts_out=%s compression=%s heartbeat_interval_s=%s client='%s'",
447458
auth_request.auth,
448459
auth_request.dataset,
449460
auth_request.encoding,
450461
auth_request.ts_out,
462+
auth_request.compression,
451463
auth_request.heartbeat_interval_s,
452464
auth_request.client,
453465
)

databento/live/session.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414

1515
import databento_dbn
1616
import pandas as pd
17+
from databento_dbn import Compression
1718
from databento_dbn import DBNRecord
1819
from databento_dbn import Schema
1920
from databento_dbn import SType
2021

2122
from databento.common.constants import ALL_SYMBOLS
2223
from databento.common.enums import ReconnectPolicy
24+
from databento.common.enums import SlowReaderBehavior
2325
from databento.common.error import BentoError
2426
from databento.common.publishers import Dataset
2527
from databento.common.types import ClientRecordCallback
@@ -205,8 +207,17 @@ def __init__(
205207
metadata: SessionMetadata,
206208
ts_out: bool = False,
207209
heartbeat_interval_s: int | None = None,
210+
slow_reader_behavior: SlowReaderBehavior | str | None = None,
211+
compression: Compression = Compression.NONE,
208212
):
209-
super().__init__(api_key, dataset, ts_out, heartbeat_interval_s)
213+
super().__init__(
214+
api_key,
215+
dataset,
216+
ts_out,
217+
heartbeat_interval_s,
218+
slow_reader_behavior,
219+
compression,
220+
)
210221

211222
self._dbn_queue = dbn_queue
212223
self._loop = loop
@@ -302,6 +313,8 @@ class LiveSession:
302313
The reconnect policy for the live session.
303314
- "none": the client will not reconnect (default)
304315
- "reconnect": the client will reconnect automatically
316+
compression : Compression, optional
317+
The compression format for the session. Defaults to no compression.
305318
"""
306319

307320
def __init__(
@@ -313,6 +326,8 @@ def __init__(
313326
user_gateway: str | None = None,
314327
user_port: int = DEFAULT_REMOTE_PORT,
315328
reconnect_policy: ReconnectPolicy | str = ReconnectPolicy.NONE,
329+
slow_reader_behavior: SlowReaderBehavior | str | None = None,
330+
compression: Compression = Compression.NONE,
316331
) -> None:
317332
self._dbn_queue = DBNQueue()
318333
self._lock = threading.RLock()
@@ -329,6 +344,8 @@ def __init__(
329344
self._api_key = api_key
330345
self._ts_out = ts_out
331346
self._heartbeat_interval_s = heartbeat_interval_s or 30
347+
self._slow_reader_behavior = slow_reader_behavior
348+
self._compression = compression
332349

333350
self._protocol: _SessionProtocol | None = None
334351
self._transport: asyncio.Transport | None = None
@@ -579,6 +596,8 @@ def _create_protocol(self, dataset: Dataset | str) -> _SessionProtocol:
579596
metadata=self._metadata,
580597
ts_out=self.ts_out,
581598
heartbeat_interval_s=self.heartbeat_interval_s,
599+
slow_reader_behavior=self._slow_reader_behavior,
600+
compression=self._compression,
582601
)
583602

584603
def _connect(

databento/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.70.0"
1+
__version__ = "0.71.0"

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "databento"
3-
version = "0.70.0"
3+
version = "0.71.0"
44
description = "Official Python client library for Databento"
55
readme = "README.md"
66
requires-python = ">=3.10"
@@ -10,7 +10,7 @@ dynamic = [ "classifiers" ]
1010
dependencies = [
1111
"aiohttp>=3.8.3,<4.0.0; python_version < '3.12'",
1212
"aiohttp>=3.9.0,<4.0.0; python_version >= '3.12'",
13-
"databento-dbn~=0.48.0",
13+
"databento-dbn~=0.49.0",
1414
"numpy>=1.23.5; python_version < '3.12'",
1515
"numpy>=1.26.0; python_version >= '3.12'",
1616
"pandas>=1.5.3,<4.0.0",

tests/mockliveserver/fixture.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,14 @@ def stdout(self) -> asyncio.StreamReader:
7070
async def _send_command(
7171
self,
7272
command: str,
73-
timeout: float = 1.0,
73+
timeout: float = 10.0,
7474
) -> None:
7575
if self._process.stdin is None:
7676
raise RuntimeError("cannot write command to mock live server")
7777
self._process.stdin.write(
7878
f"{command.strip()}\n".encode(),
7979
)
80+
await self._process.stdin.drain()
8081

8182
try:
8283
line = await asyncio.wait_for(self.stdout.readline(), timeout)

0 commit comments

Comments
 (0)