dataquery-sdk 1.2.1__tar.gz → 1.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/CHANGELOG.md +7 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/PKG-INFO +8 -5
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/__init__.py +10 -16
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/cli.py +58 -7
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/config/env.py +5 -34
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/config/logging.py +3 -30
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/constants/__init__.py +1 -13
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/constants/api.py +1 -5
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/constants/download.py +0 -9
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/core/_mixins.py +92 -113
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/core/_sync.py +2 -21
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/core/client.py +91 -290
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/dataquery.py +116 -529
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/download/__init__.py +1 -2
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/download/parallel.py +7 -61
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/download/utils.py +3 -19
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/export.py +2 -10
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/function_registry.py +1 -9
- dataquery_sdk-1.2.3/dataquery/mcp_proxy.py +265 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/sse/__init__.py +1 -2
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/sse/client.py +14 -146
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/sse/event_store.py +8 -56
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/sse/subscriber.py +12 -185
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/transport/__init__.py +1 -2
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/transport/auth.py +9 -39
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/transport/connection_pool.py +3 -23
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/transport/rate_limiter.py +4 -41
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/transport/retry.py +5 -48
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/types/exceptions.py +14 -3
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/types/models.py +43 -56
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/utils.py +21 -232
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery_sdk.egg-info/PKG-INFO +8 -5
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery_sdk.egg-info/SOURCES.txt +1 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery_sdk.egg-info/requires.txt +4 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/pyproject.toml +10 -4
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/CONTRIBUTING.md +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/LICENSE +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/MANIFEST.in +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/README.md +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/config/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/constants/rate_limit.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/constants/sse.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/core/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/data/function.json +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/py.typed +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery/types/__init__.py +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery_sdk.egg-info/dependency_links.txt +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery_sdk.egg-info/entry_points.txt +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/dataquery_sdk.egg-info/top_level.txt +0 -0
- {dataquery_sdk-1.2.1 → dataquery_sdk-1.2.3}/setup.cfg +0 -0
|
@@ -44,5 +44,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
44
44
|
- Written research: new `download_zip_async` helper that downloads a group over a date range (split into calendar-month windows to fit the available-files endpoint limit) and safely extracts ZIP archives as each download completes, overlapping unzip with in-flight downloads
|
|
45
45
|
- Group downloads: `run_group_download_async` accepts an `on_file_complete` async callback awaited per file on `completed`/`already_exists`
|
|
46
46
|
- Extraction is Zip Slip-guarded, skips current-day archives, and surfaces failures via `extraction_errors` (downgrading overall status to `partial`); date windows with no available files no longer mark a multi-window run as `partial`
|
|
47
|
+
## [1.2.2] - 2026-07-18
|
|
48
|
+
- MCP: new `mcp-connect` CLI command
|
|
49
|
+
## [1.2.3] - 2026-07-23
|
|
50
|
+
- Pagination: new client-driven `get_next_page_async(page)` helper — read `next_link` off any paged response and hand the page back to fetch the next one (manual counterpart to the SDK-driven `iter_pages`); next-page links are resolved against the surface the page came from and never sent off-host
|
|
51
|
+
- Pagination models: `items`, `page-size`, and `info` fields, plus the `next_link` property and `get_self_link()` accessor, moved onto the shared `Paginated` mixin; `FileList` is now paginated; list fields default to empty instead of being required so partial/empty envelopes parse cleanly
|
|
52
|
+
- New `APIResponseError` raised when a 2xx response carries an `errors`/`error` envelope (e.g. `498 Unrecognized Page Token`); an `info` `204` "no content" envelope now yields an empty page so pagination stops cleanly, while any other unrecognized body fails loudly
|
|
53
|
+
- Exports: `Paginated`, `Link`, `APIResponseError` are now part of the public API
|
|
47
54
|
|
|
48
55
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataquery-sdk
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3
|
|
4
4
|
Summary: Python SDK for DATAQUERY Data API - Query, download, and check availability of economic data files
|
|
5
5
|
Author-email: DATAQUERY SDK Team <dataquery_support@jpmorgan.com>
|
|
6
|
-
Project-URL: Homepage, https://github.com/
|
|
7
|
-
Project-URL: Bug Tracker, https://github.com/
|
|
8
|
-
Project-URL: Documentation, https://github.com/
|
|
9
|
-
Project-URL: Source Code, https://github.com/
|
|
6
|
+
Project-URL: Homepage, https://github.com/jpmorganchase/dataquery-sdk
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/jpmorganchase/dataquery-sdk/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/jpmorganchase/dataquery-sdk/wiki
|
|
9
|
+
Project-URL: Source Code, https://github.com/jpmorganchase/dataquery-sdk
|
|
10
10
|
Keywords: dataquery,data,api,economic,financial,download,async,oauth,rate-limiting,sdk
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
@@ -49,6 +49,8 @@ Requires-Dist: mike>=1.1.0; extra == "docs"
|
|
|
49
49
|
Requires-Dist: pymdown-extensions>=10.21.3; extra == "docs"
|
|
50
50
|
Provides-Extra: pandas
|
|
51
51
|
Requires-Dist: pandas>=2.0.0; extra == "pandas"
|
|
52
|
+
Provides-Extra: mcp
|
|
53
|
+
Requires-Dist: fastmcp>=2.14; extra == "mcp"
|
|
52
54
|
Provides-Extra: all
|
|
53
55
|
Requires-Dist: pytest>=7.0.0; extra == "all"
|
|
54
56
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "all"
|
|
@@ -61,6 +63,7 @@ Requires-Dist: mkdocs-material>=9.0.0; extra == "all"
|
|
|
61
63
|
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == "all"
|
|
62
64
|
Requires-Dist: mike>=1.1.0; extra == "all"
|
|
63
65
|
Requires-Dist: pandas>=2.0.0; extra == "all"
|
|
66
|
+
Requires-Dist: fastmcp>=2.14; extra == "all"
|
|
64
67
|
Requires-Dist: pip-audit>=2.7.0; extra == "all"
|
|
65
68
|
Requires-Dist: build>=1.3.0; extra == "all"
|
|
66
69
|
Requires-Dist: urllib3>=2.7.0; extra == "all"
|
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
"""
|
|
2
|
-
DATAQUERY SDK - Python SDK for DATAQUERY Data API
|
|
1
|
+
"""DATAQUERY SDK - Python SDK for DATAQUERY Data API."""
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
to economic data files with advanced features like querying, downloading, availability
|
|
6
|
-
checking, rate limiting, retry logic, connection pool monitoring, and comprehensive logging.
|
|
7
|
-
|
|
8
|
-
Quick Start:
|
|
9
|
-
>>> from dataquery import DataQuery
|
|
10
|
-
>>> async with DataQuery() as dq:
|
|
11
|
-
... groups = await dq.list_groups_async()
|
|
12
|
-
... print(f"Found {len(groups)} groups")
|
|
13
|
-
|
|
14
|
-
For more information, visit: https://github.com/dataquery/dataquery-sdk
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
__version__ = "1.2.1"
|
|
3
|
+
__version__ = "1.2.3"
|
|
18
4
|
__author__ = "DATAQUERY SDK Team"
|
|
19
5
|
__email__ = "dataquery_support@jpmorgan.com"
|
|
20
6
|
__license__ = "MIT"
|
|
@@ -34,6 +20,7 @@ from .function_registry import (
|
|
|
34
20
|
from .sse.client import SSEClient, SSEEvent
|
|
35
21
|
from .sse.subscriber import NotificationDownloadManager
|
|
36
22
|
from .types.exceptions import (
|
|
23
|
+
APIResponseError,
|
|
37
24
|
AuthenticationError,
|
|
38
25
|
AvailabilityError,
|
|
39
26
|
ConfigurationError,
|
|
@@ -45,6 +32,7 @@ from .types.exceptions import (
|
|
|
45
32
|
GroupNotFoundError,
|
|
46
33
|
NetworkError,
|
|
47
34
|
NotFoundError,
|
|
35
|
+
PaginationError,
|
|
48
36
|
RateLimitError,
|
|
49
37
|
ValidationError,
|
|
50
38
|
WorkflowError,
|
|
@@ -62,6 +50,8 @@ from .types.models import (
|
|
|
62
50
|
FileList,
|
|
63
51
|
Group,
|
|
64
52
|
GroupList,
|
|
53
|
+
Link,
|
|
54
|
+
Paginated,
|
|
65
55
|
)
|
|
66
56
|
from .utils import download_zip_async
|
|
67
57
|
|
|
@@ -71,6 +61,8 @@ __all__ = [
|
|
|
71
61
|
"ClientConfig",
|
|
72
62
|
"Group",
|
|
73
63
|
"GroupList",
|
|
64
|
+
"Paginated",
|
|
65
|
+
"Link",
|
|
74
66
|
"FileInfo",
|
|
75
67
|
"FileList",
|
|
76
68
|
"AvailabilityInfo",
|
|
@@ -81,9 +73,11 @@ __all__ = [
|
|
|
81
73
|
"DownloadProgress",
|
|
82
74
|
"DateRange",
|
|
83
75
|
"DataQueryError",
|
|
76
|
+
"APIResponseError",
|
|
84
77
|
"AuthenticationError",
|
|
85
78
|
"ValidationError",
|
|
86
79
|
"NotFoundError",
|
|
80
|
+
"PaginationError",
|
|
87
81
|
"RateLimitError",
|
|
88
82
|
"NetworkError",
|
|
89
83
|
"ConfigurationError",
|
|
@@ -4,14 +4,13 @@ import argparse
|
|
|
4
4
|
import asyncio
|
|
5
5
|
import json
|
|
6
6
|
import sys
|
|
7
|
+
from collections.abc import AsyncGenerator
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
from typing import Any, Dict, List, Optional
|
|
9
10
|
|
|
10
11
|
from dataquery import DataQuery
|
|
11
12
|
from dataquery.types.exceptions import DataQueryError
|
|
12
13
|
|
|
13
|
-
# ── Output helpers (legacy-CLI "summary + --- JSON ---" format) ────────────
|
|
14
|
-
|
|
15
14
|
|
|
16
15
|
def _to_dict(payload: Any) -> Dict[str, Any]:
|
|
17
16
|
"""Normalize a Pydantic model or dict into a plain dict for JSON dump."""
|
|
@@ -203,8 +202,6 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
203
202
|
p_fn.add_argument("--list", action="store_true", help="List all available functions")
|
|
204
203
|
p_fn.add_argument("--json", action="store_true", help="Output raw JSON")
|
|
205
204
|
|
|
206
|
-
# ── DataQuery API v2 endpoints (skill-facing surface) ────────────────
|
|
207
|
-
|
|
208
205
|
def _ts_args(p: argparse.ArgumentParser) -> None:
|
|
209
206
|
p.add_argument("--data", choices=["REFERENCE_DATA", "NO_REFERENCE_DATA", "ALL"], default=None)
|
|
210
207
|
p.add_argument("--start-date", help="YYYYMMDD or TODAY-Nx (x=D/W/M/Y). Default: TODAY-1D")
|
|
@@ -290,6 +287,20 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
290
287
|
|
|
291
288
|
subparsers.add_parser("heartbeat", help="Check if DataQuery is running")
|
|
292
289
|
|
|
290
|
+
p_connect = subparsers.add_parser(
|
|
291
|
+
"mcp-connect",
|
|
292
|
+
help="Connect a local stdio MCP client to a remote MCP server (AuthE OAuth)",
|
|
293
|
+
description=(
|
|
294
|
+
"Bridge a desktop MCP client (stdio) to a remote streamable-HTTP MCP\n"
|
|
295
|
+
"server, authenticating with an OAuth client-credentials (AuthE) token\n"
|
|
296
|
+
"minted from the DATAQUERY_* environment. Point your MCP client's\n"
|
|
297
|
+
"`command` at: dataquery mcp-connect --url <MCP_URL>"
|
|
298
|
+
),
|
|
299
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
300
|
+
)
|
|
301
|
+
p_connect.add_argument("--url", required=True, help="Remote MCP endpoint URL")
|
|
302
|
+
p_connect.add_argument("--name", default="dataquery-mcp", help="Proxy server name (default: dataquery-mcp)")
|
|
303
|
+
|
|
293
304
|
return parser
|
|
294
305
|
|
|
295
306
|
|
|
@@ -503,9 +514,6 @@ async def cmd_search(args: argparse.Namespace) -> int:
|
|
|
503
514
|
return 0
|
|
504
515
|
|
|
505
516
|
|
|
506
|
-
# ── DataQuery API v2 command handlers ────────────────────────────────────
|
|
507
|
-
|
|
508
|
-
|
|
509
517
|
async def cmd_groups_search(args: argparse.Namespace) -> int:
|
|
510
518
|
async with DataQuery(args.env_file) as dq:
|
|
511
519
|
items = await dq.search_groups_async(args.keywords, page=args.page)
|
|
@@ -716,6 +724,48 @@ def cmd_function_help(args: argparse.Namespace) -> int:
|
|
|
716
724
|
return 0
|
|
717
725
|
|
|
718
726
|
|
|
727
|
+
async def cmd_mcp_connect(args: argparse.Namespace) -> int:
|
|
728
|
+
"""Bridge a desktop MCP client (stdio) to a remote streamable-HTTP MCP server."""
|
|
729
|
+
try:
|
|
730
|
+
import httpx
|
|
731
|
+
from fastmcp import FastMCP
|
|
732
|
+
from fastmcp.client.transports import StreamableHttpTransport
|
|
733
|
+
except ImportError:
|
|
734
|
+
print(
|
|
735
|
+
"The MCP bridge requires the 'mcp' extra. Install it with:\n"
|
|
736
|
+
" pip install 'dataquery-sdk[mcp]'\n"
|
|
737
|
+
"or run it directly with:\n"
|
|
738
|
+
" uvx --from 'dataquery-sdk[mcp]' dataquery mcp-connect --url <MCP_URL>",
|
|
739
|
+
file=sys.stderr,
|
|
740
|
+
)
|
|
741
|
+
return 1
|
|
742
|
+
|
|
743
|
+
from dataquery.config import EnvConfig
|
|
744
|
+
from dataquery.transport.auth import TokenManager
|
|
745
|
+
|
|
746
|
+
config = EnvConfig.create_client_config(env_file=Path(args.env_file) if getattr(args, "env_file", None) else None)
|
|
747
|
+
token_manager = TokenManager(config)
|
|
748
|
+
|
|
749
|
+
class _AutheAuth(httpx.Auth):
|
|
750
|
+
"""Stamp a fresh AuthE bearer token (from the SDK TokenManager) per request."""
|
|
751
|
+
|
|
752
|
+
async def async_auth_flow(self, request: httpx.Request) -> AsyncGenerator[httpx.Request, httpx.Response]:
|
|
753
|
+
header = await token_manager.get_valid_token()
|
|
754
|
+
if not header:
|
|
755
|
+
raise DataQueryError(
|
|
756
|
+
"Could not obtain an OAuth token \u2014 check DATAQUERY_CLIENT_ID, "
|
|
757
|
+
"DATAQUERY_CLIENT_SECRET, DATAQUERY_OAUTH_TOKEN_URL and "
|
|
758
|
+
"DATAQUERY_OAUTH_AUD."
|
|
759
|
+
)
|
|
760
|
+
request.headers["Authorization"] = header
|
|
761
|
+
yield request
|
|
762
|
+
|
|
763
|
+
transport = StreamableHttpTransport(args.url, auth=_AutheAuth())
|
|
764
|
+
proxy = FastMCP.as_proxy(transport, name=args.name)
|
|
765
|
+
await proxy.run_async(transport="stdio", show_banner=False)
|
|
766
|
+
return 0
|
|
767
|
+
|
|
768
|
+
|
|
719
769
|
def main_sync(ns: argparse.Namespace) -> int:
|
|
720
770
|
if ns.command == "config":
|
|
721
771
|
if ns.config_command == "show":
|
|
@@ -745,6 +795,7 @@ _ASYNC_COMMANDS = {
|
|
|
745
795
|
"expression-timeseries": cmd_expression_timeseries,
|
|
746
796
|
"grid-data": cmd_grid_data,
|
|
747
797
|
"heartbeat": cmd_heartbeat,
|
|
798
|
+
"mcp-connect": cmd_mcp_connect,
|
|
748
799
|
}
|
|
749
800
|
|
|
750
801
|
|
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Environment-based configuration for the DATAQUERY SDK.
|
|
3
|
-
|
|
4
|
-
Loads settings from environment variables (or a ``.env`` file) into a
|
|
5
|
-
:class:`ClientConfig` Pydantic model. Field declarations live on
|
|
6
|
-
``ClientConfig`` — this module only handles the env-var → field projection,
|
|
7
|
-
type coercion, and cross-field validation.
|
|
8
|
-
|
|
9
|
-
Single source of truth: :data:`ClientConfig.model_fields`. The
|
|
10
|
-
``DEFAULTS`` table here is derived from the model at import time so the two
|
|
11
|
-
cannot drift.
|
|
12
|
-
"""
|
|
1
|
+
"""Environment-based configuration for the DATAQUERY SDK."""
|
|
13
2
|
|
|
14
3
|
from __future__ import annotations
|
|
15
4
|
|
|
@@ -57,12 +46,7 @@ def _unwrap_optional(annotation: Any) -> Any:
|
|
|
57
46
|
|
|
58
47
|
|
|
59
48
|
def _build_defaults() -> Dict[str, Optional[str]]:
|
|
60
|
-
"""Compute the ``EnvConfig.DEFAULTS`` table from the model.
|
|
61
|
-
|
|
62
|
-
Booleans become ``"true"``/``"false"`` (lowercase, matching the
|
|
63
|
-
tokens :meth:`EnvConfig.get_bool` accepts). Numeric / string defaults
|
|
64
|
-
are stringified directly. ``None`` defaults stay ``None``.
|
|
65
|
-
"""
|
|
49
|
+
"""Compute the ``EnvConfig.DEFAULTS`` table from the model."""
|
|
66
50
|
defaults: Dict[str, Optional[str]] = {}
|
|
67
51
|
for field_name, field in ClientConfig.model_fields.items():
|
|
68
52
|
env_key = _env_name_for(field_name)
|
|
@@ -79,12 +63,7 @@ def _build_defaults() -> Dict[str, Optional[str]]:
|
|
|
79
63
|
|
|
80
64
|
|
|
81
65
|
class EnvConfig:
|
|
82
|
-
"""Environment-based configuration loader for the DataQuery SDK.
|
|
83
|
-
|
|
84
|
-
All methods are class methods — this class is a namespace, never
|
|
85
|
-
instantiated. Field definitions, types, and defaults all originate from
|
|
86
|
-
:class:`dataquery.types.models.ClientConfig`.
|
|
87
|
-
"""
|
|
66
|
+
"""Environment-based configuration loader for the DataQuery SDK."""
|
|
88
67
|
|
|
89
68
|
PREFIX = "DATAQUERY_"
|
|
90
69
|
DEFAULTS: Dict[str, Optional[str]] = _build_defaults()
|
|
@@ -146,11 +125,7 @@ class EnvConfig:
|
|
|
146
125
|
config_data: Optional[Dict[str, Any]] = None,
|
|
147
126
|
env_file: Optional[Path] = None,
|
|
148
127
|
) -> ClientConfig:
|
|
149
|
-
"""Build a :class:`ClientConfig` from env vars or an explicit dict.
|
|
150
|
-
|
|
151
|
-
When ``config_data`` is provided the env-var path is skipped entirely
|
|
152
|
-
— the dict is passed straight to :class:`ClientConfig`.
|
|
153
|
-
"""
|
|
128
|
+
"""Build a :class:`ClientConfig` from env vars or an explicit dict."""
|
|
154
129
|
if config_data is not None:
|
|
155
130
|
return ClientConfig(**config_data)
|
|
156
131
|
|
|
@@ -275,11 +250,7 @@ class EnvConfig:
|
|
|
275
250
|
|
|
276
251
|
@classmethod
|
|
277
252
|
def create_env_template(cls, output_path: Optional[Path] = None) -> Path:
|
|
278
|
-
"""Write a ``.env`` template listing every supported variable.
|
|
279
|
-
|
|
280
|
-
Lines are auto-generated from :data:`ClientConfig.model_fields` so a
|
|
281
|
-
new field shows up here automatically (no separate maintenance).
|
|
282
|
-
"""
|
|
253
|
+
"""Write a ``.env`` template listing every supported variable."""
|
|
283
254
|
if output_path is None:
|
|
284
255
|
output_path = Path(".env.template")
|
|
285
256
|
if not isinstance(output_path, Path):
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Enhanced logging configuration for the DATAQUERY SDK.
|
|
3
|
-
|
|
4
|
-
Provides structured logging, performance metrics, request/response logging,
|
|
5
|
-
and configurable log levels and formats.
|
|
6
|
-
"""
|
|
1
|
+
"""Enhanced logging configuration for the DATAQUERY SDK."""
|
|
7
2
|
|
|
8
3
|
import logging
|
|
9
4
|
from dataclasses import dataclass, field
|
|
@@ -353,21 +348,7 @@ def create_logging_config(
|
|
|
353
348
|
enable_request_logging: bool = False,
|
|
354
349
|
enable_performance_logging: bool = True,
|
|
355
350
|
) -> LoggingConfig:
|
|
356
|
-
"""
|
|
357
|
-
Create logging configuration.
|
|
358
|
-
|
|
359
|
-
Args:
|
|
360
|
-
level: Log level
|
|
361
|
-
format: Log format
|
|
362
|
-
enable_console: Whether to enable console logging
|
|
363
|
-
enable_file: Whether to enable file logging
|
|
364
|
-
log_file: Path to log file
|
|
365
|
-
enable_request_logging: Whether to log HTTP requests/responses
|
|
366
|
-
enable_performance_logging: Whether to log performance metrics
|
|
367
|
-
|
|
368
|
-
Returns:
|
|
369
|
-
Logging configuration
|
|
370
|
-
"""
|
|
351
|
+
"""Create logging configuration."""
|
|
371
352
|
return LoggingConfig(
|
|
372
353
|
level=level,
|
|
373
354
|
format=format,
|
|
@@ -380,13 +361,5 @@ def create_logging_config(
|
|
|
380
361
|
|
|
381
362
|
|
|
382
363
|
def create_logging_manager(config: LoggingConfig) -> LoggingManager:
|
|
383
|
-
"""
|
|
384
|
-
Create a logging manager with the specified configuration.
|
|
385
|
-
|
|
386
|
-
Args:
|
|
387
|
-
config: Logging configuration
|
|
388
|
-
|
|
389
|
-
Returns:
|
|
390
|
-
Configured logging manager
|
|
391
|
-
"""
|
|
364
|
+
"""Create a logging manager with the specified configuration."""
|
|
392
365
|
return LoggingManager(config)
|
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
"""Internal tunable constants used across the SDK.
|
|
2
|
-
|
|
3
|
-
Centralizing these values here avoids drift between code paths that must agree
|
|
4
|
-
(e.g. the single-stream and parallel downloaders share thresholds) and gives a
|
|
5
|
-
single place to adjust tunables. Pydantic model field defaults and validation
|
|
6
|
-
bounds are intentionally NOT hoisted here — those are part of the public
|
|
7
|
-
schema.
|
|
8
|
-
|
|
9
|
-
Constants are organized into topical submodules; this ``__init__`` re-exports
|
|
10
|
-
them so existing call sites using ``from . import constants as C`` keep
|
|
11
|
-
working without change. New code may also import from a specific submodule,
|
|
12
|
-
e.g. ``from dataquery.constants.api import API_GROUPS``.
|
|
13
|
-
"""
|
|
1
|
+
"""Internal tunable constants used across the SDK."""
|
|
14
2
|
|
|
15
3
|
from __future__ import annotations
|
|
16
4
|
|
|
@@ -26,15 +26,6 @@ TEMP_SUFFIX = ".part"
|
|
|
26
26
|
MBPS_TO_BYTES_PER_SECOND = 125_000
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
# Default size, in days, of each chunk when splitting a date range so that
|
|
30
|
-
# the available-files endpoint is queried over a smaller window per call.
|
|
31
|
-
# Used by ``split_date_range_into_chunks``. The endpoint caps each call at
|
|
32
|
-
# one calendar month; smaller windows just keep responses lighter. (The old
|
|
33
|
-
# group-level limits, e.g. 14 days for RESEARCH_EQUITY_ALL, were lifted
|
|
34
|
-
# server-side.)
|
|
35
29
|
DEFAULT_WRITTEN_RESEARCH_CHUNK_DAYS: int = 7
|
|
36
30
|
|
|
37
|
-
# Error string set on the OperationReport when the available-files endpoint
|
|
38
|
-
# returns nothing for a date window. Chunked workflows match on it to tell
|
|
39
|
-
# a quiet window apart from a real failure.
|
|
40
31
|
NO_FILES_FOUND_ERROR: str = "No available files found for date range"
|