quickbase-extract 0.4.2__tar.gz → 0.4.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.
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/CHANGELOG.md +7 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/PKG-INFO +1 -1
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/pyproject.toml +1 -1
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/report_data.py +14 -10
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/.editorconfig +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/.gitignore +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/.pre-commit-config.yaml +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/.python-version +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/LICENSE.txt +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/README.md +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/TODO.md +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/__init__.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/api_handlers.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/cache_manager.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/cache_orchestration.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/cache_sync.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/config.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/py.typed +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/report_metadata.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/utils.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/tests/conftest.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/tests/test_api_handlers.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/tests/test_cache_manager.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/tests/test_cache_orchestration.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/tests/test_cache_sync.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/tests/test_report_data.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/tests/test_report_metadata.py +0 -0
- {quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/tests/test_utils.py +0 -0
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.3] - 2026-05-13
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Changed `ask_values` parameter type annotations from `dict` to `Mapping` in `get_data`, `get_data_parallel`, `_validate_ask_values`, `_normalize_ask_values`, and `_replace_ask_placeholders` to accept any mapping type and correctly reflect read-only intent; added `from collections.abc import Mapping` import
|
|
13
|
+
- Added `None` guard for `query_data` before subscripting in `get_data` to prevent `TypeError` when `handle_query` returns `None`
|
|
14
|
+
|
|
8
15
|
## [0.4.2] - 2026-05-13
|
|
9
16
|
|
|
10
17
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quickbase-extract
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Extract and cache Quickbase report data with built-in error handling and S3 support
|
|
5
5
|
Project-URL: Homepage, https://github.com/tbrezler/quickbase-extract
|
|
6
6
|
Project-URL: Repository, https://github.com/tbrezler/quickbase-extract.git
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "quickbase-extract"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.3"
|
|
8
8
|
description = "Extract and cache Quickbase report data with built-in error handling and S3 support"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import json
|
|
4
4
|
import logging
|
|
5
5
|
import re
|
|
6
|
+
from collections.abc import Mapping
|
|
6
7
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
7
8
|
|
|
8
9
|
from quickbase_extract.api_handlers import handle_query
|
|
@@ -13,7 +14,7 @@ logger = logging.getLogger(__name__)
|
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def _validate_ask_values(
|
|
16
|
-
ask_values:
|
|
17
|
+
ask_values: Mapping[str, str | list[str]],
|
|
17
18
|
placeholders_in_filter: set[str],
|
|
18
19
|
report_config: ReportConfig,
|
|
19
20
|
) -> None:
|
|
@@ -57,7 +58,7 @@ def _validate_ask_values(
|
|
|
57
58
|
)
|
|
58
59
|
|
|
59
60
|
|
|
60
|
-
def _normalize_ask_values(ask_values:
|
|
61
|
+
def _normalize_ask_values(ask_values: Mapping[str, str | list[str]]) -> dict[str, list[str]]:
|
|
61
62
|
"""Normalize all ask_values to lists for consistent processing.
|
|
62
63
|
|
|
63
64
|
Converts single string values to single-element lists, leaving list values
|
|
@@ -81,7 +82,7 @@ def _normalize_ask_values(ask_values: dict[str, str | list[str]]) -> dict[str, l
|
|
|
81
82
|
|
|
82
83
|
def _replace_ask_placeholders(
|
|
83
84
|
report_filter: str,
|
|
84
|
-
ask_values:
|
|
85
|
+
ask_values: Mapping[str, str | list[str]],
|
|
85
86
|
report_config: ReportConfig,
|
|
86
87
|
) -> str:
|
|
87
88
|
"""Replace ask-the-user placeholders in a Quickbase filter with actual values.
|
|
@@ -215,7 +216,7 @@ def get_data(
|
|
|
215
216
|
report_config: ReportConfig,
|
|
216
217
|
report_metadata: dict[ReportConfig, dict],
|
|
217
218
|
cache: bool = False,
|
|
218
|
-
ask_values:
|
|
219
|
+
ask_values: Mapping[str, str | list[str]] | None = None,
|
|
219
220
|
) -> list[dict]:
|
|
220
221
|
"""Query a Quickbase table for data using cached report metadata.
|
|
221
222
|
|
|
@@ -270,6 +271,8 @@ def get_data(
|
|
|
270
271
|
where=report_filter,
|
|
271
272
|
sort_by=info["sort_by"],
|
|
272
273
|
)
|
|
274
|
+
if query_data is None:
|
|
275
|
+
raise ValueError(f"Query returned no response for {report_config}")
|
|
273
276
|
data = query_data["data"]
|
|
274
277
|
|
|
275
278
|
# Transform records
|
|
@@ -300,18 +303,19 @@ def get_data_parallel(
|
|
|
300
303
|
report_metadata: dict,
|
|
301
304
|
cache: bool = False,
|
|
302
305
|
max_workers: int = 8,
|
|
303
|
-
ask_values:
|
|
306
|
+
ask_values: Mapping[ReportConfig, Mapping[str, str | list[str]]] | None = None,
|
|
304
307
|
) -> dict[ReportConfig, list[dict]]:
|
|
305
308
|
"""Fetch multiple reports in parallel using cached report metadata.
|
|
306
309
|
|
|
307
310
|
Executes data fetching for multiple reports concurrently to improve
|
|
308
|
-
performance. Uses a fail-fast approach: if any report fetch fails,
|
|
309
|
-
|
|
311
|
+
performance. Uses a fail-fast approach: if any report fetch fails, the exception is raised
|
|
312
|
+
immediately and pending (not yet started) tasks will not be executed. Already
|
|
313
|
+
running tasks will complete before the exception propagates.
|
|
310
314
|
|
|
311
315
|
Args:
|
|
312
316
|
client: Quickbase API client. Should be thread-safe for concurrent use.
|
|
313
317
|
cache_manager: CacheManager instance for cache operations.
|
|
314
|
-
|
|
318
|
+
report_configs: List of ReportConfig instances to fetch.
|
|
315
319
|
report_metadata: Full metadata dict (from load_report_metadata_batch).
|
|
316
320
|
Keyed by ReportConfig instances.
|
|
317
321
|
cache: Whether to cache retrieved data. Defaults to False.
|
|
@@ -331,7 +335,7 @@ def get_data_parallel(
|
|
|
331
335
|
KeyError: If any report_config not found in report_metadata.
|
|
332
336
|
ValueError: If ask placeholders in any filter are missing values.
|
|
333
337
|
Exception: First exception encountered during parallel execution.
|
|
334
|
-
|
|
338
|
+
Pending tasks are not started; already running tasks complete first.
|
|
335
339
|
|
|
336
340
|
Example:
|
|
337
341
|
>>> cache_manager = CacheManager(cache_root=Path("my_project/dev/cache"))
|
|
@@ -440,7 +444,7 @@ def load_data_batch(
|
|
|
440
444
|
|
|
441
445
|
Args:
|
|
442
446
|
cache_manager: CacheManager instance for cache operations.
|
|
443
|
-
|
|
447
|
+
report_configs: List of ReportConfig instances to load.
|
|
444
448
|
report_metadata: Dict mapping ReportConfig -> metadata dict
|
|
445
449
|
(from load_report_metadata_batch).
|
|
446
450
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/cache_orchestration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{quickbase_extract-0.4.2 → quickbase_extract-0.4.3}/src/quickbase_extract/report_metadata.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|