Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.63.0 - 2025-09-02

#### Enhancements
- Upgraded `databento-dbn` to 0.41.0

#### Bug fixes
- Fixed an issue where calling `Live.stop()` would not clean up the client state once the socket is closed

## 0.62.0 - 2025-08-19

This release delivers a number of breaking changes to the Python interface for DBN records to provide a cleaner and more consistent API.
Expand Down
4 changes: 2 additions & 2 deletions databento/historical/api/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ def submit_job(
schema : Schema or str {'mbo', 'mbp-1', 'mbp-10', 'trades', 'tbbo', 'ohlcv-1s', 'ohlcv-1m', 'ohlcv-1h', 'ohlcv-1d', 'definition', 'statistics', 'status'}, default 'trades' # noqa
The data record schema for the request.
start : pd.Timestamp, datetime, date, str, or int
The start of the request time range (inclusive).
The inclusive start of the request range.
Filters on `ts_recv` if it exists in the schema, otherwise `ts_event`.
Assumes UTC as timezone unless passed a tz-aware object.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
end : pd.Timestamp, datetime, date, str, or int, optional
The end of the request time range (exclusive).
The exclusive end of the request range.
Filters on `ts_recv` if it exists in the schema, otherwise `ts_event`.
Assumes UTC as timezone unless passed a tz-aware object.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
Expand Down
20 changes: 10 additions & 10 deletions databento/historical/api/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ def list_datasets(
Parameters
----------
start_date : date or str, optional
The start date (UTC) for the request range.
The inclusive UTC start date of the request range.
If `None` then first date available.
end_date : date or str, optional
The end date (UTC) for the request range.
The exclusive UTC end date of the request range.
If `None` then last date available.

Returns
Expand Down Expand Up @@ -202,10 +202,10 @@ def get_dataset_condition(
dataset : Dataset or str
The dataset code (string identifier) for the request.
start_date : date or str, optional
The start date (UTC) for the request range.
The inclusive UTC start date of the request range.
If `None` then first date available.
end_date : date or str, optional
The end date (UTC) for the request range.
The inclusive UTC end date of the request range.
If `None` then last date available.

Returns
Expand Down Expand Up @@ -279,11 +279,11 @@ def get_record_count(
dataset : Dataset or str
The dataset code for the request.
start : pd.Timestamp, datetime, date, str, or int
The start datetime for the request range (inclusive).
The inclusive start of the request range.
Assumes UTC as timezone unless otherwise specified.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
end : pd.Timestamp, datetime, date, str, or int, optional
The end datetime for the request range (exclusive).
The exclusive end of the request range.
Assumes UTC as timezone unless otherwise specified.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
Defaults to the forward filled value of `start` based on the resolution provided.
Expand Down Expand Up @@ -347,11 +347,11 @@ def get_billable_size(
dataset : Dataset or str
The dataset code for the request.
start : pd.Timestamp, datetime, date, str, or int
The start datetime for the request range (inclusive).
The inclusive start of the request range.
Assumes UTC as timezone unless otherwise specified.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
end : pd.Timestamp, datetime, date, str, or int, optional
The end datetime for the request range (exclusive).
The exclusive end of the request range.
Assumes UTC as timezone unless otherwise specified.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
Defaults to the forward filled value of `start` based on the resolution provided.
Expand Down Expand Up @@ -417,11 +417,11 @@ def get_cost(
dataset : Dataset or str
The dataset code for the request.
start : pd.Timestamp, datetime, date, str, or int
The start datetime for the request range (inclusive).
The inclusive start of the request range.
Assumes UTC as timezone unless otherwise specified.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
end : pd.Timestamp, datetime, date, str, or int, optional
The end datetime for the request range (exclusive).
The exclusive end of the request range.
Assumes UTC as timezone unless otherwise specified.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
Defaults to the forward filled value of `start` based on the resolution provided.
Expand Down
5 changes: 3 additions & 2 deletions databento/historical/api/symbology.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ def resolve(
stype_out : SType or str, default 'instrument_id'
The output symbology type to resolve to.
start_date : date or str
The start date (UTC) of the request time range (inclusive).
The inclusive UTC start date of the request range.
end_date : date or str, optional
The end date (UTC) of the request time range (exclusive).
The exclusive UTC end date of the request range.
Defaults to the forward filled value of `start` based on the resolution provided.

Returns
-------
Expand Down
8 changes: 4 additions & 4 deletions databento/historical/api/timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ def get_range(
dataset : Dataset or str
The dataset code (string identifier) for the request.
start : pd.Timestamp, datetime, date, str, or int
The start datetime of the request time range (inclusive).
The inclusive start of the request range.
Filters on `ts_recv` if it exists in the schema, otherwise `ts_event`.
Assumes UTC as timezone unless passed a tz-aware object.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
end : pd.Timestamp, datetime, date, str, or int, optional
The end datetime of the request time range (exclusive).
The exclusive end of the request range.
Filters on `ts_recv` if it exists in the schema, otherwise `ts_event`.
Assumes UTC as timezone unless passed a tz-aware object.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
Expand Down Expand Up @@ -158,12 +158,12 @@ async def get_range_async(
dataset : Dataset or str
The dataset code (string identifier) for the request.
start : pd.Timestamp, datetime, date, str, or int
The start of the request time range (inclusive).
The inclusive start of the request range.
Filters on `ts_recv` if it exists in the schema, otherwise `ts_event`.
Assumes UTC as timezone unless passed a tz-aware object.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
end : pd.Timestamp, datetime, date, str, or int, optional
The end of the request time range (exclusive).
The exclusive end of the request range.
Filters on `ts_recv` if it exists in the schema, otherwise `ts_event`.
Assumes UTC as timezone unless passed a tz-aware object.
If an integer is passed, then this represents nanoseconds since the UNIX epoch.
Expand Down
8 changes: 3 additions & 5 deletions databento/live/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,9 @@ def stop(self) -> None:
with self._lock:
if self._transport is None:
return
if self._transport.can_write_eof():
self._transport.write_eof()
self._transport.close()
if self._protocol is not None:
self._protocol.disconnected.add_done_callback(lambda _: self._cleanup())
self._loop.call_soon_threadsafe(self._transport.close)

def start(self) -> None:
"""
Expand Down Expand Up @@ -516,8 +516,6 @@ def terminate(self) -> None:
with self._lock:
if self._transport is None:
return
if self._transport.can_write_eof():
self._transport.write_eof()
self._transport.abort()
self._cleanup()

Expand Down
2 changes: 1 addition & 1 deletion databento/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.62.0"
__version__ = "0.63.0"
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "databento"
version = "0.62.0"
version = "0.63.0"
description = "Official Python client library for Databento"
authors = [
"Databento <support@databento.com>",
Expand Down Expand Up @@ -32,7 +32,7 @@ aiohttp = [
{version = "^3.8.3", python = "<3.12"},
{version = "^3.9.0", python = "^3.12"}
]
databento-dbn = "~=0.40.0"
databento-dbn = "~=0.41.0"
numpy = [
{version = ">=1.23.5", python = "<3.12"},
{version = ">=1.26.0", python = "^3.12"}
Expand Down
37 changes: 37 additions & 0 deletions tests/test_live_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from __future__ import annotations

import asyncio
import pathlib
import platform
import random
Expand Down Expand Up @@ -255,6 +256,42 @@ async def test_live_connect_auth(
assert message.encoding == Encoding.DBN


async def test_live_client_reuse(
mock_live_server: MockLiveServerInterface,
live_client: client.Live,
) -> None:
"""
Test that calling stop will *eventually* close a the connection and trigger
a cleanup of the client state.
"""
live_client.subscribe(
dataset=Dataset.GLBX_MDP3,
schema=Schema.MBO,
)

await mock_live_server.wait_for_message_of_type(
message_type=gateway.AuthenticationRequest,
)

live_client.start()
live_client.stop()

await asyncio.sleep(1)

live_client.subscribe(
dataset=Dataset.GLBX_MDP3,
schema=Schema.MBP_1,
)

await mock_live_server.wait_for_message_of_type(
message_type=gateway.AuthenticationRequest,
)

live_client.start()
live_client.stop()
await live_client.wait_for_close()


async def test_live_connect_auth_with_heartbeat_interval(
mock_live_server: MockLiveServerInterface,
test_live_api_key: str,
Expand Down
Loading