dataquery-sdk 0.1.5__tar.gz → 0.2.0__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-0.1.5 → dataquery_sdk-0.2.0}/CHANGELOG.md +4 -1
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/CONTRIBUTING.md +2 -2
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/PKG-INFO +162 -37
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/README.md +160 -34
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery/__init__.py +7 -7
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery/cli.py +42 -10
- dataquery_sdk-0.2.0/dataquery/config/__init__.py +27 -0
- dataquery_sdk-0.2.0/dataquery/config/env.py +364 -0
- dataquery_sdk-0.2.0/dataquery/constants/__init__.py +85 -0
- dataquery_sdk-0.2.0/dataquery/constants/api.py +35 -0
- dataquery_sdk-0.2.0/dataquery/constants/download.py +51 -0
- dataquery_sdk-0.2.0/dataquery/constants/rate_limit.py +6 -0
- dataquery_sdk-0.2.0/dataquery/constants/sse.py +9 -0
- dataquery_sdk-0.2.0/dataquery/core/__init__.py +5 -0
- {dataquery_sdk-0.1.5/dataquery → dataquery_sdk-0.2.0/dataquery/core}/_mixins.py +319 -21
- {dataquery_sdk-0.1.5/dataquery → dataquery_sdk-0.2.0/dataquery/core}/client.py +357 -354
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery/dataquery.py +372 -334
- dataquery_sdk-0.2.0/dataquery/download/__init__.py +14 -0
- dataquery_sdk-0.2.0/dataquery/download/parallel.py +701 -0
- dataquery_sdk-0.1.5/dataquery/_download_utils.py → dataquery_sdk-0.2.0/dataquery/download/utils.py +36 -9
- dataquery_sdk-0.2.0/dataquery/sse/__init__.py +23 -0
- dataquery_sdk-0.2.0/dataquery/sse/client.py +473 -0
- dataquery_sdk-0.2.0/dataquery/sse/event_store.py +241 -0
- dataquery_sdk-0.2.0/dataquery/sse/subscriber.py +653 -0
- dataquery_sdk-0.2.0/dataquery/transport/__init__.py +61 -0
- {dataquery_sdk-0.1.5/dataquery → dataquery_sdk-0.2.0/dataquery/transport}/auth.py +6 -7
- {dataquery_sdk-0.1.5/dataquery → dataquery_sdk-0.2.0/dataquery/transport}/connection_pool.py +1 -4
- {dataquery_sdk-0.1.5/dataquery → dataquery_sdk-0.2.0/dataquery/transport}/rate_limiter.py +19 -28
- {dataquery_sdk-0.1.5/dataquery → dataquery_sdk-0.2.0/dataquery/transport}/retry.py +2 -3
- dataquery_sdk-0.2.0/dataquery/types/__init__.py +79 -0
- {dataquery_sdk-0.1.5/dataquery → dataquery_sdk-0.2.0/dataquery/types}/exceptions.py +22 -0
- {dataquery_sdk-0.1.5/dataquery → dataquery_sdk-0.2.0/dataquery/types}/models.py +49 -31
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery/utils.py +3 -6
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery_sdk.egg-info/PKG-INFO +162 -37
- dataquery_sdk-0.2.0/dataquery_sdk.egg-info/SOURCES.txt +43 -0
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/pyproject.toml +3 -4
- dataquery_sdk-0.1.5/dataquery/_parallel_download.py +0 -300
- dataquery_sdk-0.1.5/dataquery/config.py +0 -564
- dataquery_sdk-0.1.5/dataquery/sse_client.py +0 -280
- dataquery_sdk-0.1.5/dataquery/sse_subscriber.py +0 -437
- dataquery_sdk-0.1.5/dataquery_sdk.egg-info/SOURCES.txt +0 -31
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/LICENSE +0 -0
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/MANIFEST.in +0 -0
- /dataquery_sdk-0.1.5/dataquery/logging_config.py → /dataquery_sdk-0.2.0/dataquery/config/logging.py +0 -0
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery/py.typed +0 -0
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery_sdk.egg-info/dependency_links.txt +0 -0
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery_sdk.egg-info/entry_points.txt +0 -0
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery_sdk.egg-info/requires.txt +0 -0
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/dataquery_sdk.egg-info/top_level.txt +0 -0
- {dataquery_sdk-0.1.5 → dataquery_sdk-0.2.0}/setup.cfg +0 -0
|
@@ -26,4 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
26
26
|
## [0.1.4] - 2026-03-23
|
|
27
27
|
- Introduced circuit breaker environment variable (`DATAQUERY_CIRCUIT_BREAKER_THRESHOLD`)
|
|
28
28
|
## [0.1.5] - 2026-04-16
|
|
29
|
-
- Introduced file-group-id to the group downloads
|
|
29
|
+
- Introduced file-group-id to the group downloads
|
|
30
|
+
## [0.2.0] - 2026-05-06
|
|
31
|
+
- SSE auto-download with cross-process event replay and multi-group support
|
|
32
|
+
- Python 3.11+ only
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Contributing to DataQuery SDK
|
|
1
|
+
# Contributing to DataQuery SDK
|
|
2
2
|
|
|
3
3
|
Thank you for your interest in contributing to the DataQuery SDK! This document provides guidelines and information for contributors.
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ Thank you for your interest in contributing to the DataQuery SDK! This document
|
|
|
6
6
|
|
|
7
7
|
### Prerequisites
|
|
8
8
|
|
|
9
|
-
- Python 3.
|
|
9
|
+
- Python 3.11 or higher
|
|
10
10
|
- [uv](https://github.com/astral-sh/uv) package manager
|
|
11
11
|
- Git
|
|
12
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dataquery-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
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
6
|
Project-URL: Homepage, https://github.com/dataquery/dataquery-sdk
|
|
@@ -15,7 +15,6 @@ Classifier: Intended Audience :: Science/Research
|
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
@@ -23,7 +22,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
23
22
|
Classifier: Topic :: Office/Business :: Financial
|
|
24
23
|
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
25
24
|
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
26
|
-
Requires-Python: >=3.
|
|
25
|
+
Requires-Python: >=3.11
|
|
27
26
|
Description-Content-Type: text/markdown
|
|
28
27
|
License-File: LICENSE
|
|
29
28
|
Requires-Dist: aiohttp<4.0.0,>=3.8.0
|
|
@@ -67,15 +66,33 @@ Dynamic: license-file
|
|
|
67
66
|
|
|
68
67
|
Python SDK for the J.P. Morgan DataQuery API — authenticated file downloads, time-series queries, and real-time notification-driven downloads with OAuth 2.0, rate limiting, and automatic retries built in.
|
|
69
68
|
|
|
70
|
-
[](https://www.python.org/downloads/)
|
|
71
70
|
[](https://opensource.org/licenses/MIT)
|
|
72
71
|
[](https://github.com/astral-sh/ruff)
|
|
73
72
|
|
|
73
|
+
## Contents
|
|
74
|
+
|
|
75
|
+
- [Features](#features)
|
|
76
|
+
- [New here? Three steps to your first download](#new-here-three-steps-to-your-first-download)
|
|
77
|
+
- [Installation](#installation)
|
|
78
|
+
- [Configure credentials](#configure-credentials)
|
|
79
|
+
- [Quick start](#quick-start)
|
|
80
|
+
- [Auto-download (coming soon)](#auto-download-coming-soon)
|
|
81
|
+
- [CLI](#cli)
|
|
82
|
+
- [Configuration](#configuration)
|
|
83
|
+
- [Logging](#logging)
|
|
84
|
+
- [Error handling](#error-handling)
|
|
85
|
+
- [Troubleshooting](#troubleshooting)
|
|
86
|
+
- [Date formats](#date-formats)
|
|
87
|
+
- [Performance tuning](#performance-tuning)
|
|
88
|
+
- [API reference (most-used methods)](#api-reference-most-used-methods)
|
|
89
|
+
- [Examples](#examples) · [Development](#development) · [Requirements](#requirements) · [Support](#support)
|
|
90
|
+
|
|
74
91
|
## Features
|
|
75
92
|
|
|
76
|
-
- **
|
|
93
|
+
- **Streaming file downloads** — single streaming GET per file
|
|
77
94
|
- **Historical and date-range downloads** — fetch every file in a group (optionally filtered to one or many `file-group-id`s) between two dates
|
|
78
|
-
- **Notification-driven downloads (SSE)** — subscribe to the `/notification` stream and auto-download files as soon as they are published
|
|
95
|
+
- **Notification-driven downloads (SSE)** — subscribe to the `/events/notification` stream and auto-download files as soon as they are published
|
|
79
96
|
- **Time-series queries** — by expression, by instrument, or by group with attribute / filter projections
|
|
80
97
|
- **OAuth 2.0 with token caching and refresh** — or supply a bearer token directly
|
|
81
98
|
- **Token-bucket rate limiter** — 300 rpm / 5 tps defaults (configurable up to API limits)
|
|
@@ -84,6 +101,28 @@ Python SDK for the J.P. Morgan DataQuery API — authenticated file downloads, t
|
|
|
84
101
|
- **Optional pandas integration** — `to_dataframe(...)` on any response
|
|
85
102
|
- **CLI** — `dataquery groups | files | availability | download | download-group | auth | config`
|
|
86
103
|
|
|
104
|
+
## New here? Three steps to your first download
|
|
105
|
+
|
|
106
|
+
1. `pip install dataquery-sdk`
|
|
107
|
+
2. Put your OAuth credentials in a `.env` file (see [Configure credentials](#configure-credentials))
|
|
108
|
+
3. Run a one-liner to confirm everything works:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import asyncio
|
|
112
|
+
from dataquery import DataQuery
|
|
113
|
+
|
|
114
|
+
async def main():
|
|
115
|
+
async with DataQuery() as dq:
|
|
116
|
+
groups = await dq.list_groups_async(limit=5)
|
|
117
|
+
for g in groups:
|
|
118
|
+
print(g.group_id, "—", g.group_name)
|
|
119
|
+
|
|
120
|
+
asyncio.run(main())
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
If that prints groups, auth and networking are working. From there, jump to
|
|
124
|
+
[Quick start](#quick-start) (date-range download) or the [CLI](#cli).
|
|
125
|
+
|
|
87
126
|
## Installation
|
|
88
127
|
|
|
89
128
|
```bash
|
|
@@ -97,7 +136,7 @@ pip install "dataquery-sdk[pandas]"
|
|
|
97
136
|
pip install "dataquery-sdk[dev]"
|
|
98
137
|
```
|
|
99
138
|
|
|
100
|
-
Python 3.
|
|
139
|
+
Python 3.11+ is required.
|
|
101
140
|
|
|
102
141
|
## Configure credentials
|
|
103
142
|
|
|
@@ -140,9 +179,10 @@ async with DataQuery() as dq:
|
|
|
140
179
|
end_date="20250131",
|
|
141
180
|
destination_dir="./data",
|
|
142
181
|
)
|
|
143
|
-
|
|
182
|
+
# OperationReport (Pydantic model) — counts/timing/data/details are dicts on it.
|
|
183
|
+
print(f"{result.counts['successful_downloads']}/{result.counts['total_files']} files downloaded")
|
|
144
184
|
|
|
145
|
-
# sync
|
|
185
|
+
# sync — same arguments, drop the _async suffix
|
|
146
186
|
with DataQuery() as dq:
|
|
147
187
|
result = dq.run_group_download(
|
|
148
188
|
group_id="JPMAQS_GENERIC_RETURNS",
|
|
@@ -179,7 +219,6 @@ async with DataQuery() as dq:
|
|
|
179
219
|
file_group_id="JPMAQS_GENERIC_RETURNS",
|
|
180
220
|
file_datetime="20250115",
|
|
181
221
|
destination_path=Path("./downloads"),
|
|
182
|
-
num_parts=5, # parallel chunks
|
|
183
222
|
)
|
|
184
223
|
print(f"Downloaded: {result.local_path} ({result.file_size} bytes)")
|
|
185
224
|
```
|
|
@@ -227,8 +266,8 @@ async with DataQuery() as dq:
|
|
|
227
266
|
|
|
228
267
|
Real-time notification-driven downloads via the DataQuery SSE stream are under
|
|
229
268
|
active development and will be available in a future release. Once released,
|
|
230
|
-
`auto_download_async` will subscribe to the
|
|
231
|
-
|
|
269
|
+
`auto_download_async` will subscribe to the notification endpoint and download
|
|
270
|
+
files automatically as they are published — no polling required.
|
|
232
271
|
|
|
233
272
|
## CLI
|
|
234
273
|
|
|
@@ -248,17 +287,16 @@ dataquery availability --file-group-id JPMAQS_GENERIC_RETURNS --file-datetime 20
|
|
|
248
287
|
# Download a single file
|
|
249
288
|
dataquery download --file-group-id JPMAQS_GENERIC_RETURNS \
|
|
250
289
|
--file-datetime 20250115 \
|
|
251
|
-
--destination ./downloads
|
|
252
|
-
--num-parts 5
|
|
290
|
+
--destination ./downloads
|
|
253
291
|
|
|
254
|
-
# Watch a group and download as new files arrive
|
|
292
|
+
# Watch a group and download as new files arrive (calls auto_download_async under the hood —
|
|
293
|
+
# same SSE subscription, same event-replay state files)
|
|
255
294
|
dataquery download --watch --group-id JPMAQS_GENERIC_RETURNS --destination ./downloads
|
|
256
295
|
|
|
257
296
|
# Download everything in a date range
|
|
258
297
|
dataquery download-group --group-id JPMAQS_GENERIC_RETURNS \
|
|
259
298
|
--start-date 20250101 --end-date 20250131 \
|
|
260
|
-
--destination ./data
|
|
261
|
-
--max-concurrent 5 --num-parts 4
|
|
299
|
+
--destination ./data
|
|
262
300
|
|
|
263
301
|
# Restrict to one or more file-group-ids
|
|
264
302
|
dataquery download-group --group-id JPMAQS_GENERIC_RETURNS \
|
|
@@ -291,8 +329,6 @@ All environment variables use the `DATAQUERY_` prefix.
|
|
|
291
329
|
| `DATAQUERY_CLIENT_SECRET` | _(none)_ | Required for OAuth |
|
|
292
330
|
| `DATAQUERY_BEARER_TOKEN` | _(none)_ | Alternative to OAuth |
|
|
293
331
|
| `DATAQUERY_OAUTH_ENABLED` | `true` | Set `false` to use bearer-token mode |
|
|
294
|
-
| `DATAQUERY_OAUTH_TOKEN_URL` | `https://authe.jpmorgan.com/as/token.oauth2` | |
|
|
295
|
-
| `DATAQUERY_OAUTH_AUD` | `JPMC:URI:RS-06785-DataQueryExternalApi-PROD` | |
|
|
296
332
|
|
|
297
333
|
**API endpoints**
|
|
298
334
|
|
|
@@ -342,13 +378,57 @@ async with DataQuery(client_id="...", client_secret="...", timeout=60.0) as dq:
|
|
|
342
378
|
...
|
|
343
379
|
```
|
|
344
380
|
|
|
381
|
+
## Logging
|
|
382
|
+
|
|
383
|
+
The SDK logs through [structlog](https://www.structlog.org/) and emits
|
|
384
|
+
structured events for requests, retries, rate-limit waits, SSE reconnects, and
|
|
385
|
+
download progress. Two ways to drive it:
|
|
386
|
+
|
|
387
|
+
**Standard Python logging** — works without extra setup:
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
import logging
|
|
391
|
+
logging.basicConfig(level=logging.INFO)
|
|
392
|
+
logging.getLogger("dataquery").setLevel(logging.DEBUG) # SDK-only DEBUG
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
DEBUG includes per-chunk download progress and SSE keepalives — useful while
|
|
396
|
+
debugging, noisy in production.
|
|
397
|
+
|
|
398
|
+
**Structured (JSON) output** — recommended for long-running `auto_download`
|
|
399
|
+
services so a log shipper can parse the events:
|
|
400
|
+
|
|
401
|
+
```python
|
|
402
|
+
from pathlib import Path
|
|
403
|
+
from dataquery.config.logging import (
|
|
404
|
+
LogFormat, LogLevel, create_logging_config, create_logging_manager,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
cfg = create_logging_config(
|
|
408
|
+
level=LogLevel.INFO,
|
|
409
|
+
format=LogFormat.JSON, # or LogFormat.CONSOLE for humans
|
|
410
|
+
enable_file=True,
|
|
411
|
+
log_file=Path("./dataquery.log"),
|
|
412
|
+
enable_request_logging=False, # set True to log every HTTP request/response
|
|
413
|
+
)
|
|
414
|
+
create_logging_manager(cfg) # installs handlers on the root logger
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
`examples/system/enable_request_logging.py` is a runnable version showing
|
|
418
|
+
request/response logging for traffic debugging.
|
|
419
|
+
|
|
420
|
+
**Health snapshots for `auto_download`** — `manager.get_stats()` returns
|
|
421
|
+
notifications received, files downloaded / skipped / failed, the last event
|
|
422
|
+
id, and a bounded ring of recent errors. Wire it into a `/healthz` endpoint
|
|
423
|
+
for daemon-style deployments.
|
|
424
|
+
|
|
345
425
|
## Error handling
|
|
346
426
|
|
|
347
427
|
All errors inherit from `DataQueryError`:
|
|
348
428
|
|
|
349
429
|
```python
|
|
350
430
|
from dataquery import DataQuery
|
|
351
|
-
from dataquery.exceptions import (
|
|
431
|
+
from dataquery.types.exceptions import (
|
|
352
432
|
DataQueryError,
|
|
353
433
|
AuthenticationError,
|
|
354
434
|
NotFoundError,
|
|
@@ -375,6 +455,54 @@ async with DataQuery() as dq:
|
|
|
375
455
|
... # any other SDK-level failure
|
|
376
456
|
```
|
|
377
457
|
|
|
458
|
+
## Troubleshooting
|
|
459
|
+
|
|
460
|
+
**`AuthenticationError` / HTTP 401 on the first call**
|
|
461
|
+
|
|
462
|
+
- Verify both `DATAQUERY_CLIENT_ID` and `DATAQUERY_CLIENT_SECRET` are set:
|
|
463
|
+
`dataquery config show` will print the resolved config (secrets masked).
|
|
464
|
+
- Confirm OAuth is reaching the right endpoint:
|
|
465
|
+
`dataquery auth test` performs a token exchange and reports the failure mode.
|
|
466
|
+
- If the credentials are correct but the audience is wrong, set
|
|
467
|
+
`DATAQUERY_OAUTH_AUD` to the value provisioned for your client.
|
|
468
|
+
|
|
469
|
+
**`.env` file isn't picked up**
|
|
470
|
+
|
|
471
|
+
- The SDK looks for `.env` in the current working directory at instantiation.
|
|
472
|
+
Either `cd` to the directory containing `.env` before running, or pass the
|
|
473
|
+
path explicitly: `DataQuery(env_file=".env.production")`.
|
|
474
|
+
- Variables already set in the shell environment win over the `.env` file —
|
|
475
|
+
unset them (`unset DATAQUERY_CLIENT_ID`) if you want the file to take effect.
|
|
476
|
+
- The CLI accepts `--env-file PATH` on every subcommand for the same reason.
|
|
477
|
+
|
|
478
|
+
**Connection / proxy / SSL failures**
|
|
479
|
+
|
|
480
|
+
- Behind a corporate proxy, set `DATAQUERY_PROXY_ENABLED=true` and
|
|
481
|
+
`DATAQUERY_PROXY_URL=http://proxy.host:port`. Add `DATAQUERY_PROXY_USERNAME`
|
|
482
|
+
/ `DATAQUERY_PROXY_PASSWORD` if auth is required.
|
|
483
|
+
- For self-signed proxy CAs, set `DATAQUERY_PROXY_VERIFY_SSL=false` (insecure;
|
|
484
|
+
prefer pointing `SSL_CERT_FILE` at the corporate root CA bundle).
|
|
485
|
+
- Sporadic `NetworkError` after long idle periods usually means a stateful
|
|
486
|
+
middlebox is dropping the SSE socket — set
|
|
487
|
+
`heartbeat_timeout=90.0` on `auto_download_async` to force a reconnect when
|
|
488
|
+
no bytes arrive within the window.
|
|
489
|
+
|
|
490
|
+
**Rate-limit pauses**
|
|
491
|
+
|
|
492
|
+
- Default is 300 rpm / 5 tps. The SDK self-throttles via the token-bucket
|
|
493
|
+
limiter; if you see long sleeps before requests, lower
|
|
494
|
+
`DATAQUERY_REQUESTS_PER_MINUTE` is not the cure — it's likely working as
|
|
495
|
+
designed. Raise it (up to your provisioned limit) to go faster.
|
|
496
|
+
- `dq.get_rate_limit_info()` shows the current bucket state.
|
|
497
|
+
|
|
498
|
+
**SSE auto-download "missed" events after a restart**
|
|
499
|
+
|
|
500
|
+
- Confirm `enable_event_replay=True` (the default).
|
|
501
|
+
- Replay state lives under `<destination>/.sse_state/sse_<fingerprint>.json` —
|
|
502
|
+
if that directory was wiped, the next start has nothing to resume from. Use
|
|
503
|
+
`manager.clear_event_id()` (or `dataquery download --watch --reset-event-id`)
|
|
504
|
+
only when you intentionally want a clean slate.
|
|
505
|
+
|
|
378
506
|
## Date formats
|
|
379
507
|
|
|
380
508
|
```python
|
|
@@ -388,13 +516,9 @@ start_date="TODAY-1Y"
|
|
|
388
516
|
|
|
389
517
|
## Performance tuning
|
|
390
518
|
|
|
391
|
-
`run_group_download_async`
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
With `num_parts=1` (the default) each file downloads as a single streaming GET.
|
|
395
|
-
Set `num_parts > 1` to enable parallel HTTP range requests per file — the SDK
|
|
396
|
-
probes the file size first, then downloads byte ranges concurrently. Files under
|
|
397
|
-
10 MB always use a single stream regardless of `num_parts`.
|
|
519
|
+
`run_group_download_async` streams each file as a single GET. The SDK
|
|
520
|
+
automatically inserts delays between file starts so the configured
|
|
521
|
+
`requests_per_minute` is not exceeded.
|
|
398
522
|
|
|
399
523
|
```python
|
|
400
524
|
await dq.run_group_download_async(
|
|
@@ -402,15 +526,13 @@ await dq.run_group_download_async(
|
|
|
402
526
|
start_date="20250101",
|
|
403
527
|
end_date="20250131",
|
|
404
528
|
destination_dir="./data",
|
|
405
|
-
max_concurrent=5, # parallel files
|
|
406
|
-
num_parts=4, # parallel chunks per file (1 = single stream)
|
|
407
529
|
max_retries=3,
|
|
408
530
|
)
|
|
409
531
|
```
|
|
410
532
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
533
|
+
Tune throughput via `DATAQUERY_REQUESTS_PER_MINUTE` and `DATAQUERY_BURST_CAPACITY`
|
|
534
|
+
(see [Configuration](#environment-variables)) rather than per-call concurrency
|
|
535
|
+
flags.
|
|
414
536
|
|
|
415
537
|
## API reference (most-used methods)
|
|
416
538
|
|
|
@@ -437,8 +559,10 @@ exceeded.
|
|
|
437
559
|
| | `to_dataframe(response)` | requires `pandas` extra |
|
|
438
560
|
| | `get_stats()` / `get_pool_stats()` / `get_rate_limit_info()` | diagnostics |
|
|
439
561
|
|
|
440
|
-
Every async method
|
|
441
|
-
|
|
562
|
+
Every async method has a sync counterpart with the same name minus the
|
|
563
|
+
`_async` suffix — `list_groups_async` ↔ `list_groups`, `download_file_async` ↔
|
|
564
|
+
`download_file`, etc. Sync calls run the coroutine internally via
|
|
565
|
+
`asyncio.run`, so do not call them from inside an existing event loop.
|
|
442
566
|
|
|
443
567
|
## Examples
|
|
444
568
|
|
|
@@ -449,13 +573,14 @@ The `examples/` directory is organised by feature:
|
|
|
449
573
|
- `examples/instruments/` — instrument discovery + time series
|
|
450
574
|
- `examples/groups/` and `examples/groups_advanced/` — group discovery and time series
|
|
451
575
|
- `examples/grid/` — grid data
|
|
452
|
-
- `examples/system/` — SSE notification subscriber, diagnostics
|
|
576
|
+
- `examples/system/` — SSE notification subscriber (single + multi-group), diagnostics
|
|
453
577
|
|
|
454
578
|
Run any example directly:
|
|
455
579
|
|
|
456
580
|
```bash
|
|
457
581
|
python examples/files/download_file.py
|
|
458
|
-
python examples/system/
|
|
582
|
+
python examples/system/auto_download_example.py # single group
|
|
583
|
+
python examples/system/auto_download_multi_group_example.py # several groups in parallel
|
|
459
584
|
```
|
|
460
585
|
|
|
461
586
|
## Development
|
|
@@ -484,7 +609,7 @@ Pytest markers: `slow`, `integration`, `unit`, `asyncio`.
|
|
|
484
609
|
|
|
485
610
|
## Requirements
|
|
486
611
|
|
|
487
|
-
- Python 3.
|
|
612
|
+
- Python 3.11+
|
|
488
613
|
- `aiohttp>=3.8,<4`, `pydantic>=2,<3`, `structlog>=23`, `python-dotenv>=1`
|
|
489
614
|
- Optional: `pandas>=2` (for `to_dataframe`)
|
|
490
615
|
|