From c6d8de5c057d0efea4baff71a0d824a5cece5c11 Mon Sep 17 00:00:00 2001 From: Rob Maierle Date: Fri, 13 Jun 2025 08:42:15 -0400 Subject: [PATCH 1/4] DOC: Update wording around request range --- databento/historical/api/batch.py | 4 ++-- databento/historical/api/metadata.py | 20 ++++++++++---------- databento/historical/api/symbology.py | 5 +++-- databento/historical/api/timeseries.py | 8 ++++---- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/databento/historical/api/batch.py b/databento/historical/api/batch.py index a74ed8d..5928168 100644 --- a/databento/historical/api/batch.py +++ b/databento/historical/api/batch.py @@ -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. diff --git a/databento/historical/api/metadata.py b/databento/historical/api/metadata.py index 3869170..4fcf6f4 100644 --- a/databento/historical/api/metadata.py +++ b/databento/historical/api/metadata.py @@ -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 @@ -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 @@ -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. @@ -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. @@ -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. diff --git a/databento/historical/api/symbology.py b/databento/historical/api/symbology.py index 9b59309..11001b0 100644 --- a/databento/historical/api/symbology.py +++ b/databento/historical/api/symbology.py @@ -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 ------- diff --git a/databento/historical/api/timeseries.py b/databento/historical/api/timeseries.py index 67a9b80..a4b763d 100644 --- a/databento/historical/api/timeseries.py +++ b/databento/historical/api/timeseries.py @@ -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. @@ -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. From 803ea0c8e72c4f6f8d34a84cbd44dd90caa01981 Mon Sep 17 00:00:00 2001 From: Nick Macholl Date: Mon, 25 Aug 2025 08:51:40 -0700 Subject: [PATCH 2/4] FIX: Fix Live.stop() disconnection with cleanup --- CHANGELOG.md | 5 +++++ databento/live/session.py | 8 +++----- tests/test_live_client.py | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48bccf1..88c5c52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.62.1 - TBD + +#### 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. diff --git a/databento/live/session.py b/databento/live/session.py index abcedfb..06852e2 100644 --- a/databento/live/session.py +++ b/databento/live/session.py @@ -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: """ @@ -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() diff --git a/tests/test_live_client.py b/tests/test_live_client.py index ba46ae2..a6df5c2 100644 --- a/tests/test_live_client.py +++ b/tests/test_live_client.py @@ -4,6 +4,7 @@ from __future__ import annotations +import asyncio import pathlib import platform import random @@ -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, From 1da6594d0d7ced36e82c23a0f7bec873c7013469 Mon Sep 17 00:00:00 2001 From: Nick Macholl Date: Tue, 26 Aug 2025 14:29:39 -0700 Subject: [PATCH 3/4] MOD: Upgrade databento-dbn to v0.41.0 --- CHANGELOG.md | 5 ++++- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88c5c52..a1652d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog -## 0.62.1 - TBD +## 0.63.0 - TBD + +#### 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 diff --git a/pyproject.toml b/pyproject.toml index d51bb5b..46a4abf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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"} From 7ac602c81ac03c4b487295b05d48635bc19a44d9 Mon Sep 17 00:00:00 2001 From: Nick Macholl Date: Tue, 2 Sep 2025 13:07:53 -0700 Subject: [PATCH 4/4] VER: Release 0.63.0 --- CHANGELOG.md | 2 +- databento/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1652d6..9996c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.63.0 - TBD +## 0.63.0 - 2025-09-02 #### Enhancements - Upgraded `databento-dbn` to 0.41.0 diff --git a/databento/version.py b/databento/version.py index 647040d..c60bb1b 100644 --- a/databento/version.py +++ b/databento/version.py @@ -1 +1 @@ -__version__ = "0.62.0" +__version__ = "0.63.0" diff --git a/pyproject.toml b/pyproject.toml index 46a4abf..c1e3b30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 ",