diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1da37e8..24ac6f8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] name: build - Python ${{ matrix.python-version }} (${{ matrix.os }}) runs-on: ${{ matrix.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 2714179..27416e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.68.0 - 2025-12-09 + +This release adds support for Python 3.14. + +#### Enhancements +- Added support for Python 3.14 +- Functions which accept a path as an argument now expand user directories +- Upgraded `databento-dbn` to 0.45.0 + - Added support for Python 3.14 + ## 0.67.0 - 2025-12-02 #### Enhancements @@ -351,7 +361,7 @@ was preventing `ts_out` from being correctly decoded in the Python DBNDecoder ## 0.45.0 - 2024-11-12 -This release adds support for Python v3.13. +This release adds support for Python 3.13. #### Enhancements - Added support for Python 3.13 @@ -675,7 +685,7 @@ This release adds support for transcoding DBN data into Apache parquet. ## 0.24.0 - 2023-11-23 -This release adds support for DBN v2 as well as Python v3.12. +This release adds support for DBN v2 as well as Python 3.12. DBN v2 delivers improvements to the `Metadata` header symbology, new `stype_in` and `stype_out` fields for `SymbolMappingMsg`, and extends the symbol field length for `SymbolMappingMsg` and `InstrumentDefMsg`. The entire change notes are available [here](https://github.com/databento/dbn/releases/tag/v0.14.0). Users who wish to convert DBN v1 files to v2 can use the `dbn-cli` tool available in the [databento-dbn](https://github.com/databento/dbn/) crate. On a future date, the Databento live and historical APIs will stop serving DBN v1. diff --git a/README.md b/README.md index f316c4f..2cee56a 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ The library is fully compatible with distributions of Anaconda 2023.x and above. The minimum dependencies as found in the `pyproject.toml` are also listed below: - python = "^3.10" - aiohttp = "^3.8.3" -- databento-dbn = "~0.44.0" +- databento-dbn = "~0.45.0" - numpy = ">=1.23.5" - pandas = ">=1.5.3" - pip-system-certs = ">=4.0" (Windows only) diff --git a/databento/common/dbnstore.py b/databento/common/dbnstore.py index f4e572a..722f2aa 100644 --- a/databento/common/dbnstore.py +++ b/databento/common/dbnstore.py @@ -60,6 +60,7 @@ from databento.common.validation import validate_enum from databento.common.validation import validate_file_write_path from databento.common.validation import validate_maybe_enum +from databento.common.validation import validate_path logger = logging.getLogger(__name__) @@ -138,15 +139,15 @@ class FileDataSource(DataSource): The name of the file. nbytes : int The size of the data in bytes; equal to the file size. - path : PathLike[str] or str + path : Path The path of the file. reader : IO[bytes] A `BufferedReader` for this file-backed data. """ - def __init__(self, source: PathLike[str] | str): - self._path = Path(source) + def __init__(self, source: Path): + self._path = source if not self._path.is_file() or not self._path.exists(): raise FileNotFoundError(source) @@ -653,7 +654,7 @@ def from_file(cls, path: PathLike[str] | str) -> DBNStore: If an empty file is specified. """ - return cls(FileDataSource(path)) + return cls(FileDataSource(validate_path(path, "path"))) @classmethod def from_bytes(cls, data: BytesIO | bytes | IO[bytes]) -> DBNStore: diff --git a/databento/common/symbology.py b/databento/common/symbology.py index 0549ba2..731ead9 100644 --- a/databento/common/symbology.py +++ b/databento/common/symbology.py @@ -23,6 +23,7 @@ from databento_dbn import SymbolMappingMsgV1 from databento.common.parsing import datetime_to_unix_nanoseconds +from databento.common.validation import validate_path class MappingInterval(NamedTuple): @@ -49,7 +50,7 @@ def _validate_path_pair( in_file: PathLike[str] | str, out_file: PathLike[str] | str | None, ) -> tuple[Path, Path]: - in_file_valid = Path(in_file) + in_file_valid = validate_path(in_file, "in_file") if not in_file_valid.exists(): raise ValueError(f"{in_file_valid} does not exist") @@ -57,7 +58,7 @@ def _validate_path_pair( raise ValueError(f"{in_file_valid} is not a file") if out_file is not None: - out_file_valid = Path(out_file) + out_file_valid = validate_path(out_file, "out_file") else: out_file_valid = in_file_valid.with_name( f"{in_file_valid.stem}_mapped{in_file_valid.suffix}", diff --git a/databento/common/types.py b/databento/common/types.py index 6727aac..f8bc032 100644 --- a/databento/common/types.py +++ b/databento/common/types.py @@ -1,6 +1,5 @@ import datetime as dt import logging -import pathlib import warnings from collections.abc import Callable from os import PathLike @@ -13,6 +12,7 @@ import pandas as pd from databento.common.error import BentoWarning +from databento.common.validation import validate_file_write_path logger = logging.getLogger(__name__) @@ -110,7 +110,7 @@ def __init__( is_managed = False if isinstance(stream, (str, PathLike)): - stream = pathlib.Path(stream).open("xb") + stream = validate_file_write_path(stream, "stream", False).open("xb") is_managed = True if not hasattr(stream, "write"): diff --git a/databento/common/validation.py b/databento/common/validation.py index ebd3aa1..ff63c91 100644 --- a/databento/common/validation.py +++ b/databento/common/validation.py @@ -20,7 +20,8 @@ def validate_path(value: PathLike[str] | str, param: str) -> Path: """ - Validate whether the given value is a valid path. + Validate whether the given value is a valid path. This also expands user + directories to form valid paths. Parameters ---------- @@ -38,10 +39,12 @@ def validate_path(value: PathLike[str] | str, param: str) -> Path: ------ TypeError If value is not a valid path. + RuntimeError + If a user's home directory cannot be expanded. """ try: - return Path(value) + return Path(value).expanduser() except TypeError: raise TypeError( f"The `{param}` was not a valid path type. " "Use any of [PathLike[str], str].", @@ -72,6 +75,10 @@ def validate_file_write_path( Raises ------ + TypeError + If value is not a valid path. + RuntimeError + If a user's home directory cannot be expanded. IsADirectoryError If path is a directory. FileExistsError diff --git a/databento/version.py b/databento/version.py index a2f665b..251b74b 100644 --- a/databento/version.py +++ b/databento/version.py @@ -1 +1 @@ -__version__ = "0.67.0" +__version__ = "0.68.0" diff --git a/pyproject.toml b/pyproject.toml index 65ee4ca..160b313 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "databento" -version = "0.67.0" +version = "0.68.0" description = "Official Python client library for Databento" readme = "README.md" requires-python = ">=3.10" @@ -10,7 +10,7 @@ dynamic = [ "classifiers" ] dependencies = [ "aiohttp>=3.8.3,<4.0.0; python_version < '3.12'", "aiohttp>=3.9.0,<4.0.0; python_version >= '3.12'", - "databento-dbn~=0.44.0", + "databento-dbn~=0.45.0", "numpy>=1.23.5; python_version < '3.12'", "numpy>=1.26.0; python_version >= '3.12'", "pandas>=1.5.3", @@ -42,7 +42,7 @@ classifiers = [ ] [tool.poetry.dependencies] -python = ">=3.10,<3.14" +python = ">=3.10,<3.15" [tool.poetry.group.dev.dependencies] black = "^23.9.1"