marpledata 3.3.0__tar.gz → 3.4.0.dev1__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.
Files changed (64) hide show
  1. marpledata-3.4.0.dev1/.env.local +3 -0
  2. marpledata-3.4.0.dev1/.env.nightly +2 -0
  3. marpledata-3.4.0.dev1/.env.staging +4 -0
  4. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/CHANGELOG.md +10 -0
  5. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/PKG-INFO +35 -1
  6. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/README.md +34 -0
  7. marpledata-3.4.0.dev1/augment-dataset.py +681 -0
  8. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/api/db.rst +4 -0
  9. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/api/marple.db.DB.rst +2 -1
  10. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/api/marple.db.DataStream.rst +1 -0
  11. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/api/marple.db.Dataset.rst +5 -0
  12. marpledata-3.4.0.dev1/docs/api/marple.db.LAKE_ARROW_SCHEMA.rst +6 -0
  13. marpledata-3.4.0.dev1/docs/api/marple.db.SCHEMA.rst +6 -0
  14. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/api/marple.db.Signal.rst +1 -0
  15. marpledata-3.4.0.dev1/docs/api/marple.db.SignalUpload.rst +32 -0
  16. marpledata-3.4.0.dev1/docs/api/marple.db.SignalsAlreadyExistError.rst +6 -0
  17. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/getting-started.rst +4 -0
  18. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/tutorials.rst +22 -0
  19. marpledata-3.4.0.dev1/ingest-ibiza.py +538 -0
  20. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/pyproject.toml +1 -1
  21. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/src/marple/__init__.py +1 -1
  22. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/src/marple/db/__init__.py +26 -2
  23. marpledata-3.4.0.dev1/src/marple/db/constants.py +52 -0
  24. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/src/marple/db/dataset.py +184 -42
  25. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/src/marple/db/datastream.py +3 -9
  26. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/src/marple/db/signal.py +62 -4
  27. marpledata-3.4.0.dev1/src/marple/db/signal_upload.py +317 -0
  28. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/src/marple/utils.py +7 -2
  29. marpledata-3.4.0.dev1/tests/test_signal_upload.py +332 -0
  30. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/uv.lock +1 -1
  31. marpledata-3.3.0/src/marple/db/constants.py +0 -19
  32. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/.flake8 +0 -0
  33. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/.gitignore +0 -0
  34. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/.python-version +0 -0
  35. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/.uv-cache/.gitignore +0 -0
  36. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/.uv-cache/.lock +0 -0
  37. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/.uv-cache/CACHEDIR.TAG +0 -0
  38. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/.uv-cache/interpreter-v4/c2c2931c8a99aae1/588e1e7c128e2872.msgpack +0 -0
  39. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/.uv-cache/sdists-v9/.gitignore +0 -0
  40. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/AGENTS.md +0 -0
  41. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/CONTRIBUTING.md +0 -0
  42. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/LICENSE +0 -0
  43. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/DEPLOYMENT.md +0 -0
  44. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/_static/custom.css +0 -0
  45. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/_static/favicon.png +0 -0
  46. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/_static/logo.png +0 -0
  47. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/api/insight.rst +0 -0
  48. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/api/marple.Insight.rst +0 -0
  49. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/api/marple.db.DatasetList.rst +0 -0
  50. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/api.rst +0 -0
  51. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/conf.py +0 -0
  52. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/docs/index.rst +0 -0
  53. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/example.py +0 -0
  54. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/examples_race.csv +0 -0
  55. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/pytest.xml +0 -0
  56. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/src/marple/db/sql.py +0 -0
  57. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/src/marple/insight.py +0 -0
  58. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/src/marple/py.typed +0 -0
  59. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/tests/conftest.py +0 -0
  60. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/tests/support.py +0 -0
  61. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/tests/test_db.py +0 -0
  62. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/tests/test_insight.py +0 -0
  63. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/tests/test_reliability.py +0 -0
  64. {marpledata-3.3.0 → marpledata-3.4.0.dev1}/tests/test_sql.py +0 -0
@@ -0,0 +1,3 @@
1
+ MDB_URL=http://localhost:8000/api/v1
2
+ MDB_TOKEN=mdb_9iSQvvT6r75iUhIksAyut_0jrWsRryR_unc6vrWviwU
3
+
@@ -0,0 +1,2 @@
1
+ MDB_URL=https://db.nightly.marpledata.com/api/v1
2
+ MDB_TOKEN=mdb_2FFW5oalKPBnK_7aejBzkZO-FGxHHIIpInlwYkOMypM
@@ -0,0 +1,4 @@
1
+ MDB_TOKEN=mdb_BfGpBUolaa4OlZpl-npTdq497-fVlXrCIRSUEVgox7Y
2
+ MDB_URL=https://db.staging.marpledata.com/api/v1
3
+ INSIGHT_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJodHRwczovL2FwcC5nZXRtYXJwbGUuaW8vYXBpLyIsImlzcyI6Imh0dHBzOi8vZGV2LXY4OHh3a213LmV1LmF1dGgwLmNvbS8iLCJpYXQiOjE3NzQ4NzI2MDMuNDk5NDc5OCwiZXhwIjoxNzc3NDY0NTkwLjgyNywic3ViIjoiZmMyZGQ1NmUtM2NiMC00YjEzLWIwYjMtMDFmYjZmNjk1MzNmIiwiaHR0cHM6Ly9tYXJwbGVkYXRhLmNvbS9lbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaHR0cHM6Ly9tYXJwbGVkYXRhLmNvbS9hcGlfdG9rZW4iOiJiNDAzYWNlZi0xOWI0LTQ1MTMtYmJmMy0wN2Q2MzQ1MTY1ZTQifQ.-LxExjnpxFD_xGZE6xdX20GHalXMWRBSN02Bjt9lx00
4
+ INSIGHT_URL=https://insight.staging.marpledata.com/api/v1
@@ -5,6 +5,16 @@ All notable changes to the Python SDK package `marpledata` will be documented in
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
+ ## [3.4.0] - 2026-07-16
9
+
10
+ ### Added
11
+
12
+ - `Dataset.add_signal` and `Dataset.add_signals` to upload signal data onto an existing dataset (presign → write → PUT → complete). Accepts DataFrame, Arrow table, or on-disk parquet matching `LAKE_ARROW_SCHEMA` (`time` plus `value` and/or `value_text`); supports concurrent uploads, batch-level `overwrite`, import `priority`, and automatic ~1M-row groups / ~16M-row file splits.
13
+ - `Signal.wait_until_available` to poll until a signal is queryable (storage status is no longer `FROZEN_TO_COLD`; typical after `add_signal`).
14
+ - `SignalUpload` input model and `SignalsAlreadyExistError` for HTTP 409 presign conflicts (duplicate / already exists).
15
+ - Exported `LAKE_ARROW_SCHEMA` describing the input columns for signal upload (alongside existing realtime `SCHEMA` for `Dataset.append`).
16
+ - `Dataset.get_signals(signal_ids=...)` to fetch signals by ID (order preserved), plus `refresh` on `get_signal` / `get_signals` to bypass the local cache.
17
+
8
18
  ## [3.3.0] - 2026-06-29
9
19
 
10
20
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: marpledata
3
- Version: 3.3.0
3
+ Version: 3.4.0.dev1
4
4
  Summary: Marple SDK for Python
5
5
  Project-URL: Homepage, https://www.marpledata.com/
6
6
  Project-URL: Documentation, https://marpledata.gitlab.io/marple-sdk/
@@ -87,6 +87,37 @@ dataset = stream.push_file("examples_race.csv", metadata={"driver": "Mbaerto"})
87
87
  dataset = dataset.wait_for_import(timeout=10)
88
88
  ```
89
89
 
90
+ #### Add signals to an imported dataset
91
+
92
+ Upload additional signals (for example derived channels) on an existing dataset.
93
+ Each signal is a DataFrame, Arrow table, or on-disk parquet matching `LAKE_ARROW_SCHEMA`:
94
+ columns `time` (int64 nanoseconds) plus `value` and/or `value_text`.
95
+ Times must overlap the dataset time range. Use `overwrite=True` to replace an existing signal name;
96
+ a conflict without overwrite raises `SignalsAlreadyExistError`.
97
+
98
+ ```python
99
+ import pandas as pd
100
+ from marple.db import LAKE_ARROW_SCHEMA # time + value and/or value_text
101
+
102
+ speed = dataset.get_signal("car.speed").get_data()
103
+ derived = pd.DataFrame({
104
+ "time": speed.index.asi8,
105
+ "value": speed["value"] * 3.6,
106
+ })
107
+ # Single signal: wait until available before reading
108
+ signal = dataset.add_signal(
109
+ "car.speed_kmh",
110
+ derived,
111
+ metadata={"unit": "km/h"},
112
+ ).wait_until_available()
113
+
114
+ # Batch: returns IDs as soon as upload completes (no wait)
115
+ ids = dataset.add_signals([
116
+ {"name": "car.speed_kmh", "data": derived, "metadata": {"unit": "km/h"}},
117
+ ], overwrite=True, concurrency=4)
118
+ signals = dataset.get_signals(signal_ids=ids)
119
+ ```
120
+
90
121
  #### Upload large files
91
122
 
92
123
  `stream.push_file(...)` starts an ingestion and lets the Marple DB API choose the best upload mode. Depending on the deployment and file size, the SDK can upload through the API server, upload directly to Azure Blob Storage, use a single presigned URL, or split the file into multipart uploads.
@@ -173,6 +204,9 @@ if len(datasets) > 0:
173
204
  - **List streams**: `db.get_streams()`
174
205
  - **List datasets in a stream**: `stream.get_datasets()`
175
206
  - **Upload a file to a file-stream**: `stream.push_file(file_path, metadata={...}, concurrency=4)`
207
+ - **Add signals to a dataset**: `dataset.add_signal(name, data, ...)` / `dataset.add_signals([...])` — data matches `LAKE_ARROW_SCHEMA` (`time` + `value` and/or `value_text`)
208
+ - **Wait until a signal is available**: `signal.wait_until_available(timeout=60)`
209
+ - **Fetch signals by ID**: `dataset.get_signals(signal_ids=[...], refresh=False)`
176
210
  - **Wait for a dataset to import**: `dataset.wait_for_import(timeout=60)`
177
211
  - **Download original uploaded file**: `dataset.download(destination_folder=".")`
178
212
  - **Download parquet for a signal**: `dataset.get_signal(signal_name).download(destination_folder=".")`
@@ -52,6 +52,37 @@ dataset = stream.push_file("examples_race.csv", metadata={"driver": "Mbaerto"})
52
52
  dataset = dataset.wait_for_import(timeout=10)
53
53
  ```
54
54
 
55
+ #### Add signals to an imported dataset
56
+
57
+ Upload additional signals (for example derived channels) on an existing dataset.
58
+ Each signal is a DataFrame, Arrow table, or on-disk parquet matching `LAKE_ARROW_SCHEMA`:
59
+ columns `time` (int64 nanoseconds) plus `value` and/or `value_text`.
60
+ Times must overlap the dataset time range. Use `overwrite=True` to replace an existing signal name;
61
+ a conflict without overwrite raises `SignalsAlreadyExistError`.
62
+
63
+ ```python
64
+ import pandas as pd
65
+ from marple.db import LAKE_ARROW_SCHEMA # time + value and/or value_text
66
+
67
+ speed = dataset.get_signal("car.speed").get_data()
68
+ derived = pd.DataFrame({
69
+ "time": speed.index.asi8,
70
+ "value": speed["value"] * 3.6,
71
+ })
72
+ # Single signal: wait until available before reading
73
+ signal = dataset.add_signal(
74
+ "car.speed_kmh",
75
+ derived,
76
+ metadata={"unit": "km/h"},
77
+ ).wait_until_available()
78
+
79
+ # Batch: returns IDs as soon as upload completes (no wait)
80
+ ids = dataset.add_signals([
81
+ {"name": "car.speed_kmh", "data": derived, "metadata": {"unit": "km/h"}},
82
+ ], overwrite=True, concurrency=4)
83
+ signals = dataset.get_signals(signal_ids=ids)
84
+ ```
85
+
55
86
  #### Upload large files
56
87
 
57
88
  `stream.push_file(...)` starts an ingestion and lets the Marple DB API choose the best upload mode. Depending on the deployment and file size, the SDK can upload through the API server, upload directly to Azure Blob Storage, use a single presigned URL, or split the file into multipart uploads.
@@ -138,6 +169,9 @@ if len(datasets) > 0:
138
169
  - **List streams**: `db.get_streams()`
139
170
  - **List datasets in a stream**: `stream.get_datasets()`
140
171
  - **Upload a file to a file-stream**: `stream.push_file(file_path, metadata={...}, concurrency=4)`
172
+ - **Add signals to a dataset**: `dataset.add_signal(name, data, ...)` / `dataset.add_signals([...])` — data matches `LAKE_ARROW_SCHEMA` (`time` + `value` and/or `value_text`)
173
+ - **Wait until a signal is available**: `signal.wait_until_available(timeout=60)`
174
+ - **Fetch signals by ID**: `dataset.get_signals(signal_ids=[...], refresh=False)`
141
175
  - **Wait for a dataset to import**: `dataset.wait_for_import(timeout=60)`
142
176
  - **Download original uploaded file**: `dataset.download(destination_folder=".")`
143
177
  - **Download parquet for a signal**: `dataset.get_signal(signal_name).download(destination_folder=".")`