Skip to content

Commit 6edf718

Browse files
authored
python(chore): sift-stack-py v0.14.0 prep (#540)
1 parent d89a2eb commit 6edf718

3 files changed

Lines changed: 96 additions & 7 deletions

File tree

python/CHANGELOG.md

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,99 @@ All notable changes to this project will be documented in this file.
33

44
This project adheres to [Semantic Versioning](http://semver.org/).
55

6+
## [v0.14.0] - April 28, 2026
67

7-
https://github.com/sift-stack/sift/commit/e1305363e95cafb4c980fdd493f69e72660a52fb
8+
### What's New
9+
10+
#### Data Import API in SiftClient
11+
The `sift_client` module now exposes a data import API supporting CSV, Parquet, TDMS, and HDF5. With this addition, all features previously available only in `sift_py` are now available in `sift_client`, which remains the recommended interface for new development. `sift_py` (deprecated since [v0.10.0](#v0100---january-30-2026)) continues to work and ship in this release.
12+
13+
Migrating from `sift_py`: the per-format upload services (`CsvUploadService`, `ParquetUploadService`, `Hdf5UploadService`, `TdmsUploadService`) collapse into a single `client.data_import.import_from_path` method. `sift_py` only auto-detected for CSV via `simple_upload`; other formats required more setup. `sift_client` unifies all four with auto-detection built into `import_from_path` itself: the `config` argument is optional, so the common call takes just a file path and target asset. Call `client.data_import.detect_config(...)` first if you want to inspect or patch the config before importing. `import_from_path` returns a `Job` you can optionally wait on.
14+
```python
15+
# sift_py (deprecated)
16+
from sift_py.data_import.csv import CsvUploadService
17+
from sift_py.rest import SiftRestConfig
18+
19+
rest_conf: SiftRestConfig = {"uri": sift_uri, "apikey": apikey}
20+
csv_service = CsvUploadService(rest_conf)
21+
import_service = csv_service.simple_upload(asset_name="my_asset", path="data.csv")
22+
import_service.wait_until_complete()
23+
24+
# sift_client
25+
from sift_client import SiftClient
26+
27+
client = SiftClient(api_key=apikey, grpc_url=grpc_url, rest_url=rest_url)
28+
job = client.data_import.import_from_path("data.csv", asset="my_asset")
29+
job.wait_until_complete()
30+
```
31+
32+
Format-by-format support:
33+
- **CSV**: auto-detected from `.csv`. Supports an optional JSON metadata row (row 1 or row 2) for specifying channel names, units, data types, and the time column format.
34+
- **Parquet**: requires an explicit `data_type` (`PARQUET_FLATDATASET` or `PARQUET_SINGLE_CHANNEL_PER_ROW`) since `.parquet` alone doesn't disambiguate the layout. Detection only reads the file footer, so it stays fast on large files.
35+
- **HDF5**: new in this release. Auto-detected from `.h5` / `.hdf5`. Detection works out-of-the-box for files with a compound-dataset layout (first field = time) or a shared root-level `time` dataset; other layouts may need a hand-built `config`.
36+
- **TDMS**: new in this release. Auto-detected from `.tdms` and recognizes the common timing conventions (group-level `xchannel`, first-channel `TimeStamp`, or per-channel waveform properties). `TdmsImportConfig` controls handling of untimed channels (`fallback_method`), complex values (`complex_component`), scaled vs. raw data, and waveform start-time overrides.
37+
38+
#### Parquet as an Export Output Format
39+
`client.data_export.export(...)` now accepts `ExportOutputFormat.PARQUET` alongside the existing CSV and Sun/WinPlot options. Unlike the `sift_py` `DataService` + `DataFrame.to_parquet()` pattern (async-only, buffers everything in memory, name-strings only), the new export API runs as a server-side job, works sync or async, accepts `Asset`/`Channel` objects or IDs, and scales to large exports.
40+
41+
```python
42+
# sift_py (deprecated): no dedicated export API, so query in-memory and write yourself
43+
import pandas as pd
44+
from sift_py.data.query import ChannelQuery, DataQuery
45+
from sift_py.data.service import DataService
46+
from sift_py.grpc.transport import use_sift_async_channel
47+
48+
async with use_sift_async_channel({"uri": sift_uri, "apikey": apikey}) as channel:
49+
result = await DataService(channel).execute(DataQuery(
50+
asset_name="my_asset",
51+
start_time=start,
52+
end_time=stop,
53+
channels=[ChannelQuery(channel_name="my_channel")],
54+
))
55+
pd.DataFrame(result.all_channels()[0].columns()).to_parquet("out.parquet")
56+
57+
# sift_client
58+
from sift_client import SiftClient
59+
from sift_client.sift_types.export import ExportOutputFormat
60+
61+
client = SiftClient(api_key=apikey, grpc_url=grpc_url, rest_url=rest_url)
62+
job = client.data_export.export(
63+
assets=["my_asset"], # accepts Asset objects or IDs
64+
channels=["my_channel"], # accepts Channel objects or IDs
65+
start_time=start,
66+
stop_time=stop,
67+
output_format=ExportOutputFormat.PARQUET,
68+
)
69+
files = job.wait_and_download(output_dir="./exports")
70+
```
71+
72+
`wait_and_download` polls the job to completion, downloads the resulting archive, and returns the list of downloaded file paths. Both arguments shown are optional: if `output_dir` is omitted, a temporary directory is created and used. By default the downloaded zip is extracted (and the archive deleted) so you get the Parquet files directly; pass `extract=False` to keep the zip instead, which is useful if you want to hand the whole bundle off to another system without unpacking it client-side.
73+
74+
#### Test Result Logging
75+
Test result create and update events can now be optionally written to a `.jsonl` log file during a test run, then replayed against the Sift API later via the new `import-test-result-log` CLI command (installed with the package).
76+
77+
#### Progress Indicators
78+
Adds progress indicators for job polling and file downloads for better visibility during long-running operations.
79+
80+
#### Stop Bundling `google.api`, `protoc_gen_openapiv2`, and `buf.validate`
81+
Previously the package shipped its own bundled copies of the generated Python bindings for `google.api`, `protoc_gen_openapiv2`, and `buf.validate`. With this release:
82+
- `google.api` and `protoc_gen_openapiv2` are now pulled in via the `googleapis-common-protos` and `protoc-gen-openapiv2` runtime dependencies, so pip installs the upstream-maintained versions.
83+
- `buf.validate` has been removed entirely. The protovalidate field annotations were stripped from the affected `.proto` files, so the generated `_pb2.py` files no longer reference `buf.validate`.
84+
85+
### Bugfixes
86+
- Add `py.typed` to the generated proto directory so type checkers pick up protobuf types correctly.
87+
88+
### Full Changelog
89+
- [Add data import API to sift_client](https://github.com/sift-stack/sift/pull/515)
90+
- [Add HDF5 client-side detect_config](https://github.com/sift-stack/sift/pull/536)
91+
- [Add TDMS client-side detect_config](https://github.com/sift-stack/sift/pull/538)
92+
- [Add optional logging of test result create and update events](https://github.com/sift-stack/sift/pull/529)
93+
- [Add progress indicators for job polling and file downloads](https://github.com/sift-stack/sift/pull/517)
94+
- [Refactor files using run_in_executor](https://github.com/sift-stack/sift/pull/518)
95+
- [Add Parquet as an export output format](https://github.com/sift-stack/sift/pull/510)
96+
- [Add py.typed file to proto dir](https://github.com/sift-stack/sift/pull/524)
97+
- [Remove vendored google.api and protoc_gen_openapiv2 modules from buf](https://github.com/sift-stack/sift/pull/543)
98+
- [Remove protovalidate from client-side protos](https://github.com/sift-stack/sift/pull/545)
899

9100
## [v0.13.0] - March 24, 2026
10101
### What's New

python/lib/sift_client/resources/sync_stubs/__init__.pyi

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -653,9 +653,8 @@ class DataImportAPI:
653653
is inferred from the file extension when ``data_type`` is not
654654
provided.
655655
656-
CSV, Parquet, and HDF5 files are supported for auto-detection.
657-
For other formats (TDMS), create the config manually
658-
using ``TdmsImportConfig``.
656+
CSV, Parquet, HDF5, and TDMS files are supported for
657+
auto-detection.
659658
660659
For CSV files, the server scans the first two rows for an optional
661660
JSON metadata row. Row 1 is checked first; row 2 is checked only
@@ -733,8 +732,7 @@ class DataImportAPI:
733732
completion before proceeding.
734733
735734
When ``config`` is omitted the file format is auto-detected via
736-
``detect_config`` (CSV, Parquet, and HDF5). For other formats
737-
(TDMS), ``config`` must be provided.
735+
``detect_config`` (CSV, Parquet, HDF5, and TDMS).
738736
When ``asset`` is provided it overrides the config value;
739737
otherwise the config's ``asset_name`` is used.
740738
If neither ``run`` nor ``run_name`` is provided (and none is

python/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "sift_stack_py"
7-
version = "0.13.0"
7+
version = "0.14.0"
88
description = "Python client library for the Sift API"
99
requires-python = ">=3.8"
1010
readme = { file = "README.md", content-type = "text/markdown" }

0 commit comments

Comments
 (0)