datatoolpack 0.10.0__tar.gz → 0.11.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datatoolpack
3
- Version: 0.10.0
3
+ Version: 0.11.0
4
4
  Summary: Official Python SDK for the AutoData ML data preparation pipeline API
5
5
  Home-page: https://autodata.datatoolpack.com
6
6
  Author: AutoData Team
@@ -62,7 +62,7 @@ with AutoDataClient(api_key="dtpk_YOUR_API_KEY") as client:
62
62
  result = client.process(
63
63
  file_path="data.csv",
64
64
  target_columns=["price"],
65
- output_rows=20000,
65
+ output_rows=10000,
66
66
  )
67
67
  print(result["files"])
68
68
  ```
@@ -162,7 +162,7 @@ client.close()
162
162
  result = client.process(
163
163
  file_path="data.csv", # Path to input file (CSV, XLSX, Parquet, ...)
164
164
  target_columns=["price"], # y-column(s) for ML
165
- output_rows=20000, # Target row count in output
165
+ output_rows=10000, # Target row count in the synthetic output (default 10000)
166
166
  tools={ # Toggle pipeline steps (all optional)
167
167
  "anomaly": False, # Anomaly detection (off by default)
168
168
  "dtc": True, # Data Type Conversion
@@ -199,7 +199,7 @@ result = client.process(
199
199
  {"name": "dsg.csv", "url": "/download/.../dsg.csv", "size": 2097152, "description": "..."},
200
200
  {"name": "dsm_train.csv", ...},
201
201
  ],
202
- "row_count": 20000,
202
+ "row_count": 10000,
203
203
  "duration_seconds": 42.1,
204
204
  }
205
205
  ```
@@ -289,6 +289,72 @@ client.download_file("/api/v1/download/abc123.../dsg.csv", "dsg.csv")
289
289
 
290
290
  ---
291
291
 
292
+ ## Feature Selection (F4)
293
+
294
+ Rank a completed session's columns by predictive importance — **without re-running the pipeline**. Handy for trimming wide datasets before training.
295
+
296
+ ### `client.recommend_features(session_id, target_columns, methods, top_k)`
297
+
298
+ ```python
299
+ ranking = client.recommend_features(
300
+ session_id="abc123...", # a completed session you own
301
+ target_columns=["price"], # rank features against these target(s)
302
+ methods=["mutual_information"], # one or more methods (see below); default ["mutual_information"]
303
+ top_k=20, # number of top features to return (default 20)
304
+ )
305
+ # {
306
+ # "ranking": [{"feature": "sqft", "score": 0.81}, ...], # combined across methods
307
+ # "per_method": {"mutual_information": [...], "shap_importance": [...]},
308
+ # "warnings": [...],
309
+ # }
310
+ ```
311
+
312
+ **Available methods:** `variance_threshold`, `correlation_pruning`, `mutual_information`, `rfe`, `shap_importance`, `pca`. Pass several to blend their rankings, e.g. `methods=["mutual_information", "shap_importance"]`. (SHAP-based ranking uses a fast LightGBM model on the server; it degrades gracefully to `mutual_information` if those libraries are unavailable.)
313
+
314
+ ---
315
+
316
+ ## Inference & Retraining (v0.11.0+)
317
+
318
+ Apply a **completed** session's fitted transforms to new data — the missing
319
+ half of the ML lifecycle: train once, then score fresh production rows with
320
+ *exactly* the same encoding, imputation and scaling.
321
+
322
+ ### `client.infer(...)` — Score new data
323
+
324
+ Lightweight pipeline (Anomaly Detection → DTC → MDH → CDS). Outputs
325
+ `features.csv` (+ `y_columns.csv` if targets are present in the new file).
326
+
327
+ ```python
328
+ result = client.infer(
329
+ original_session_id="5d3bc0f0-...", # a completed training session you own
330
+ file_path="new_rows.csv", # columns must match the training data
331
+ download_path="./scored", # optional: save outputs locally
332
+ return_dataframes=True, # optional: get pandas DataFrames back
333
+ )
334
+ features_df = result["dataframes"]["features"]
335
+ ```
336
+
337
+ ### `client.retrain(...)` — Refresh a training set with new rows
338
+
339
+ Full pipeline including Split → CDS → DSM → DSG; produces
340
+ `retraining_output.csv` (features + targets combined).
341
+
342
+ ```python
343
+ result = client.retrain(
344
+ original_session_id="5d3bc0f0-...",
345
+ file_path="new_rows.csv",
346
+ run_dsg=True, output_rows=20000, # synthetic augmentation target
347
+ download_path="./retrained",
348
+ )
349
+ ```
350
+
351
+ Both calls are **synchronous** (the response arrives when processing ends;
352
+ default per-request timeout is ≥ 900 s — raise `timeout=` for very large
353
+ files), require the original session to be **completed and owned by you**,
354
+ and are free of credit charges in v1.
355
+
356
+ ---
357
+
292
358
  ## API Keys & Usage
293
359
 
294
360
  ### `client.list_keys()` — List API keys
@@ -336,6 +402,8 @@ Read data directly from databases and cloud storage instead of uploading files.
336
402
  | `kafka` | Apache Kafka | `bootstrap_servers`, `topic`, `group_id` |
337
403
  | `kinesis` | Amazon Kinesis | `stream_name`, `region`, `access_key_id`, `secret_access_key` |
338
404
 
405
+ > **More connectors:** AutoData supports 30+ source types. Beyond the common ones above you can also pass `oracle`, `redshift`, `cassandra`, `dynamodb`, `elasticsearch`, `clickhouse`, `timescaledb`, `synapse`, `azure_blob`, `adls`, `sap_hana`, `mqtt`, `opcua`, `influxdb`, `pi_web`, `salesforce`, `hubspot`, `stripe`, `netsuite`, `google_sheets`, `ga4`, `sharepoint`, and `http`/`rest` as `connector_type`. See **Dashboard → Documentation → Connector Data Sources** for each type's required `secrets` fields.
406
+
339
407
  ### Quick connector example
340
408
 
341
409
  ```python
@@ -363,7 +431,7 @@ with AutoDataClient(api_key="dtpk_...") as client:
363
431
  table="orders",
364
432
  target_columns=["price"],
365
433
  secrets={"connection_string": "postgresql://user:pass@host/db"},
366
- output_rows=20000,
434
+ output_rows=10000,
367
435
  )
368
436
  print(result["files"])
369
437
  ```
@@ -452,7 +520,7 @@ result = client.process_from_connector(
452
520
  table="orders",
453
521
  target_columns=["price"],
454
522
  secrets={"connection_string": "postgresql://..."},
455
- output_rows=20000,
523
+ output_rows=10000,
456
524
  incremental=True, # Only fetch new rows since last sync
457
525
  type_casts={"age": "int"}, # Override column types before processing
458
526
  wait=True,
@@ -474,7 +542,7 @@ client.write_output(
474
542
  if_exists="replace", # "replace", "append", "fail", or "merge"
475
543
  merge_keys=["id"], # column names for merge matching (when if_exists='merge')
476
544
  )
477
- # {"success": True, "rows_written": 20000, "table": "ml_prepared_data"}
545
+ # {"success": True, "rows_written": 10000, "table": "ml_prepared_data"}
478
546
  ```
479
547
 
480
548
  ---
@@ -639,6 +707,65 @@ client.delete_scheduled_run(run_id="run-id")
639
707
 
640
708
  ---
641
709
 
710
+ ## Triggers (F7)
711
+
712
+ Auto-start a pipeline when an external event fires — an inbound webhook, a connector watermark advancing, another pipeline completing, or a quality alert. Triggers are feature-flagged on the server (`FEATURE_FLAG_TRIGGERS`); if the flag is off, these endpoints return `404`.
713
+
714
+ ### `client.create_trigger(name, trigger_type, config, target_pipeline_config, enabled)`
715
+
716
+ ```python
717
+ trigger = client.create_trigger(
718
+ name="Reprocess on new S3 batch",
719
+ trigger_type="inbound_webhook", # inbound_webhook | watermark_advance | pipeline_completion | quality_alert
720
+ config={}, # type-specific (see table below)
721
+ target_pipeline_config={ # the pipeline to run when the trigger fires
722
+ "source_type": "s3",
723
+ "credential_id": "cred-uuid",
724
+ "table": "incoming/sales.csv",
725
+ "target_columns": ["revenue"],
726
+ "output_rows": 10000,
727
+ },
728
+ enabled=True,
729
+ )
730
+ # For inbound_webhook the secret is returned ONLY once — save it now:
731
+ print(trigger["webhook_secret"], trigger["inbound_url"])
732
+ ```
733
+
734
+ **Trigger types & their `config`:**
735
+
736
+ | `trigger_type` | `config` keys |
737
+ |-----------------------|---------------|
738
+ | `inbound_webhook` | optional `{"hmac_key": "..."}` — require HMAC-SHA256-signed requests |
739
+ | `watermark_advance` | `{"credential_id", "table", "watermark_column", "min_advance"}` |
740
+ | `pipeline_completion` | `{}` — chain off another pipeline finishing |
741
+ | `quality_alert` | `{}` — fire when a quality-alert rule trips |
742
+
743
+ ```python
744
+ # List / fetch / update / delete
745
+ triggers = client.list_triggers()
746
+ t = client.get_trigger(trigger_id)
747
+ client.update_trigger(trigger_id, enabled=False) # name | enabled | config | target_pipeline_config
748
+ client.delete_trigger(trigger_id)
749
+
750
+ # Dry-run: validate config + target WITHOUT firing
751
+ report = client.test_trigger(trigger_id)
752
+ # {"would_fire": True, "checks": {...}}
753
+ ```
754
+
755
+ **Firing an inbound webhook** from your own system:
756
+
757
+ ```bash
758
+ curl -X POST "https://autodata.datatoolpack.com/trigger/inbound/<webhook_secret>" \
759
+ -H "Content-Type: application/json" \
760
+ -d '{"any": "payload"}'
761
+ # If you set an hmac_key, also sign the raw body:
762
+ # X-Signature: sha256=<hex HMAC-SHA256 of the request body>
763
+ ```
764
+
765
+ Inbound firing is rate-limited and HMAC-verified server-side; repeated failures auto-disable the trigger.
766
+
767
+ ---
768
+
642
769
  ## Folder Listeners
643
770
 
644
771
  Automatically trigger pipelines when new files appear in cloud storage:
@@ -819,6 +946,11 @@ with AutoDataClient() as client:
819
946
  | `list_keys()` | List all API keys for the account |
820
947
  | `get_usage()` | Get credit usage statistics |
821
948
 
949
+ ### Feature Selection
950
+ | Method | Description |
951
+ |--------|-------------|
952
+ | `recommend_features(session_id, target_columns, ...)` | Rank a completed session's features (F4) |
953
+
822
954
  ### Connectors
823
955
  | Method | Description |
824
956
  |--------|-------------|
@@ -866,6 +998,16 @@ with AutoDataClient() as client:
866
998
  | `toggle_scheduled_run(run_id)` | Enable/disable a scheduled run |
867
999
  | `run_scheduled_now(run_id)` | Trigger a scheduled run immediately |
868
1000
 
1001
+ ### Triggers
1002
+ | Method | Description |
1003
+ |--------|-------------|
1004
+ | `list_triggers()` | List your triggers |
1005
+ | `create_trigger(name, trigger_type, ...)` | Create an event trigger (F7) |
1006
+ | `get_trigger(trigger_id)` | Fetch one trigger |
1007
+ | `update_trigger(trigger_id, ...)` | Update a trigger |
1008
+ | `delete_trigger(trigger_id)` | Delete a trigger |
1009
+ | `test_trigger(trigger_id)` | Dry-run a trigger without firing |
1010
+
869
1011
  ### Folder Listeners
870
1012
  | Method | Description |
871
1013
  |--------|-------------|
@@ -25,7 +25,7 @@ with AutoDataClient(api_key="dtpk_YOUR_API_KEY") as client:
25
25
  result = client.process(
26
26
  file_path="data.csv",
27
27
  target_columns=["price"],
28
- output_rows=20000,
28
+ output_rows=10000,
29
29
  )
30
30
  print(result["files"])
31
31
  ```
@@ -125,7 +125,7 @@ client.close()
125
125
  result = client.process(
126
126
  file_path="data.csv", # Path to input file (CSV, XLSX, Parquet, ...)
127
127
  target_columns=["price"], # y-column(s) for ML
128
- output_rows=20000, # Target row count in output
128
+ output_rows=10000, # Target row count in the synthetic output (default 10000)
129
129
  tools={ # Toggle pipeline steps (all optional)
130
130
  "anomaly": False, # Anomaly detection (off by default)
131
131
  "dtc": True, # Data Type Conversion
@@ -162,7 +162,7 @@ result = client.process(
162
162
  {"name": "dsg.csv", "url": "/download/.../dsg.csv", "size": 2097152, "description": "..."},
163
163
  {"name": "dsm_train.csv", ...},
164
164
  ],
165
- "row_count": 20000,
165
+ "row_count": 10000,
166
166
  "duration_seconds": 42.1,
167
167
  }
168
168
  ```
@@ -252,6 +252,72 @@ client.download_file("/api/v1/download/abc123.../dsg.csv", "dsg.csv")
252
252
 
253
253
  ---
254
254
 
255
+ ## Feature Selection (F4)
256
+
257
+ Rank a completed session's columns by predictive importance — **without re-running the pipeline**. Handy for trimming wide datasets before training.
258
+
259
+ ### `client.recommend_features(session_id, target_columns, methods, top_k)`
260
+
261
+ ```python
262
+ ranking = client.recommend_features(
263
+ session_id="abc123...", # a completed session you own
264
+ target_columns=["price"], # rank features against these target(s)
265
+ methods=["mutual_information"], # one or more methods (see below); default ["mutual_information"]
266
+ top_k=20, # number of top features to return (default 20)
267
+ )
268
+ # {
269
+ # "ranking": [{"feature": "sqft", "score": 0.81}, ...], # combined across methods
270
+ # "per_method": {"mutual_information": [...], "shap_importance": [...]},
271
+ # "warnings": [...],
272
+ # }
273
+ ```
274
+
275
+ **Available methods:** `variance_threshold`, `correlation_pruning`, `mutual_information`, `rfe`, `shap_importance`, `pca`. Pass several to blend their rankings, e.g. `methods=["mutual_information", "shap_importance"]`. (SHAP-based ranking uses a fast LightGBM model on the server; it degrades gracefully to `mutual_information` if those libraries are unavailable.)
276
+
277
+ ---
278
+
279
+ ## Inference & Retraining (v0.11.0+)
280
+
281
+ Apply a **completed** session's fitted transforms to new data — the missing
282
+ half of the ML lifecycle: train once, then score fresh production rows with
283
+ *exactly* the same encoding, imputation and scaling.
284
+
285
+ ### `client.infer(...)` — Score new data
286
+
287
+ Lightweight pipeline (Anomaly Detection → DTC → MDH → CDS). Outputs
288
+ `features.csv` (+ `y_columns.csv` if targets are present in the new file).
289
+
290
+ ```python
291
+ result = client.infer(
292
+ original_session_id="5d3bc0f0-...", # a completed training session you own
293
+ file_path="new_rows.csv", # columns must match the training data
294
+ download_path="./scored", # optional: save outputs locally
295
+ return_dataframes=True, # optional: get pandas DataFrames back
296
+ )
297
+ features_df = result["dataframes"]["features"]
298
+ ```
299
+
300
+ ### `client.retrain(...)` — Refresh a training set with new rows
301
+
302
+ Full pipeline including Split → CDS → DSM → DSG; produces
303
+ `retraining_output.csv` (features + targets combined).
304
+
305
+ ```python
306
+ result = client.retrain(
307
+ original_session_id="5d3bc0f0-...",
308
+ file_path="new_rows.csv",
309
+ run_dsg=True, output_rows=20000, # synthetic augmentation target
310
+ download_path="./retrained",
311
+ )
312
+ ```
313
+
314
+ Both calls are **synchronous** (the response arrives when processing ends;
315
+ default per-request timeout is ≥ 900 s — raise `timeout=` for very large
316
+ files), require the original session to be **completed and owned by you**,
317
+ and are free of credit charges in v1.
318
+
319
+ ---
320
+
255
321
  ## API Keys & Usage
256
322
 
257
323
  ### `client.list_keys()` — List API keys
@@ -299,6 +365,8 @@ Read data directly from databases and cloud storage instead of uploading files.
299
365
  | `kafka` | Apache Kafka | `bootstrap_servers`, `topic`, `group_id` |
300
366
  | `kinesis` | Amazon Kinesis | `stream_name`, `region`, `access_key_id`, `secret_access_key` |
301
367
 
368
+ > **More connectors:** AutoData supports 30+ source types. Beyond the common ones above you can also pass `oracle`, `redshift`, `cassandra`, `dynamodb`, `elasticsearch`, `clickhouse`, `timescaledb`, `synapse`, `azure_blob`, `adls`, `sap_hana`, `mqtt`, `opcua`, `influxdb`, `pi_web`, `salesforce`, `hubspot`, `stripe`, `netsuite`, `google_sheets`, `ga4`, `sharepoint`, and `http`/`rest` as `connector_type`. See **Dashboard → Documentation → Connector Data Sources** for each type's required `secrets` fields.
369
+
302
370
  ### Quick connector example
303
371
 
304
372
  ```python
@@ -326,7 +394,7 @@ with AutoDataClient(api_key="dtpk_...") as client:
326
394
  table="orders",
327
395
  target_columns=["price"],
328
396
  secrets={"connection_string": "postgresql://user:pass@host/db"},
329
- output_rows=20000,
397
+ output_rows=10000,
330
398
  )
331
399
  print(result["files"])
332
400
  ```
@@ -415,7 +483,7 @@ result = client.process_from_connector(
415
483
  table="orders",
416
484
  target_columns=["price"],
417
485
  secrets={"connection_string": "postgresql://..."},
418
- output_rows=20000,
486
+ output_rows=10000,
419
487
  incremental=True, # Only fetch new rows since last sync
420
488
  type_casts={"age": "int"}, # Override column types before processing
421
489
  wait=True,
@@ -437,7 +505,7 @@ client.write_output(
437
505
  if_exists="replace", # "replace", "append", "fail", or "merge"
438
506
  merge_keys=["id"], # column names for merge matching (when if_exists='merge')
439
507
  )
440
- # {"success": True, "rows_written": 20000, "table": "ml_prepared_data"}
508
+ # {"success": True, "rows_written": 10000, "table": "ml_prepared_data"}
441
509
  ```
442
510
 
443
511
  ---
@@ -602,6 +670,65 @@ client.delete_scheduled_run(run_id="run-id")
602
670
 
603
671
  ---
604
672
 
673
+ ## Triggers (F7)
674
+
675
+ Auto-start a pipeline when an external event fires — an inbound webhook, a connector watermark advancing, another pipeline completing, or a quality alert. Triggers are feature-flagged on the server (`FEATURE_FLAG_TRIGGERS`); if the flag is off, these endpoints return `404`.
676
+
677
+ ### `client.create_trigger(name, trigger_type, config, target_pipeline_config, enabled)`
678
+
679
+ ```python
680
+ trigger = client.create_trigger(
681
+ name="Reprocess on new S3 batch",
682
+ trigger_type="inbound_webhook", # inbound_webhook | watermark_advance | pipeline_completion | quality_alert
683
+ config={}, # type-specific (see table below)
684
+ target_pipeline_config={ # the pipeline to run when the trigger fires
685
+ "source_type": "s3",
686
+ "credential_id": "cred-uuid",
687
+ "table": "incoming/sales.csv",
688
+ "target_columns": ["revenue"],
689
+ "output_rows": 10000,
690
+ },
691
+ enabled=True,
692
+ )
693
+ # For inbound_webhook the secret is returned ONLY once — save it now:
694
+ print(trigger["webhook_secret"], trigger["inbound_url"])
695
+ ```
696
+
697
+ **Trigger types & their `config`:**
698
+
699
+ | `trigger_type` | `config` keys |
700
+ |-----------------------|---------------|
701
+ | `inbound_webhook` | optional `{"hmac_key": "..."}` — require HMAC-SHA256-signed requests |
702
+ | `watermark_advance` | `{"credential_id", "table", "watermark_column", "min_advance"}` |
703
+ | `pipeline_completion` | `{}` — chain off another pipeline finishing |
704
+ | `quality_alert` | `{}` — fire when a quality-alert rule trips |
705
+
706
+ ```python
707
+ # List / fetch / update / delete
708
+ triggers = client.list_triggers()
709
+ t = client.get_trigger(trigger_id)
710
+ client.update_trigger(trigger_id, enabled=False) # name | enabled | config | target_pipeline_config
711
+ client.delete_trigger(trigger_id)
712
+
713
+ # Dry-run: validate config + target WITHOUT firing
714
+ report = client.test_trigger(trigger_id)
715
+ # {"would_fire": True, "checks": {...}}
716
+ ```
717
+
718
+ **Firing an inbound webhook** from your own system:
719
+
720
+ ```bash
721
+ curl -X POST "https://autodata.datatoolpack.com/trigger/inbound/<webhook_secret>" \
722
+ -H "Content-Type: application/json" \
723
+ -d '{"any": "payload"}'
724
+ # If you set an hmac_key, also sign the raw body:
725
+ # X-Signature: sha256=<hex HMAC-SHA256 of the request body>
726
+ ```
727
+
728
+ Inbound firing is rate-limited and HMAC-verified server-side; repeated failures auto-disable the trigger.
729
+
730
+ ---
731
+
605
732
  ## Folder Listeners
606
733
 
607
734
  Automatically trigger pipelines when new files appear in cloud storage:
@@ -782,6 +909,11 @@ with AutoDataClient() as client:
782
909
  | `list_keys()` | List all API keys for the account |
783
910
  | `get_usage()` | Get credit usage statistics |
784
911
 
912
+ ### Feature Selection
913
+ | Method | Description |
914
+ |--------|-------------|
915
+ | `recommend_features(session_id, target_columns, ...)` | Rank a completed session's features (F4) |
916
+
785
917
  ### Connectors
786
918
  | Method | Description |
787
919
  |--------|-------------|
@@ -829,6 +961,16 @@ with AutoDataClient() as client:
829
961
  | `toggle_scheduled_run(run_id)` | Enable/disable a scheduled run |
830
962
  | `run_scheduled_now(run_id)` | Trigger a scheduled run immediately |
831
963
 
964
+ ### Triggers
965
+ | Method | Description |
966
+ |--------|-------------|
967
+ | `list_triggers()` | List your triggers |
968
+ | `create_trigger(name, trigger_type, ...)` | Create an event trigger (F7) |
969
+ | `get_trigger(trigger_id)` | Fetch one trigger |
970
+ | `update_trigger(trigger_id, ...)` | Update a trigger |
971
+ | `delete_trigger(trigger_id)` | Delete a trigger |
972
+ | `test_trigger(trigger_id)` | Dry-run a trigger without firing |
973
+
832
974
  ### Folder Listeners
833
975
  | Method | Description |
834
976
  |--------|-------------|
@@ -1,4 +1,4 @@
1
1
  from .client import AutoDataClient, AutoDataError
2
2
 
3
- __version__ = "0.10.0"
3
+ __version__ = "0.11.0"
4
4
  __all__ = ["AutoDataClient", "AutoDataError", "__version__"]
@@ -12,7 +12,7 @@ Usage::
12
12
  result = client.process(
13
13
  file_path="data.csv",
14
14
  target_columns=["price"],
15
- output_rows=20000,
15
+ output_rows=10000,
16
16
  )
17
17
  print(result["files"])
18
18
  """
@@ -789,7 +789,8 @@ class AutoDataClient:
789
789
  Object storage / data lakes / files:
790
790
  ``s3``, ``gcs``, ``azure_blob``, ``adls_gen2`` (Azure
791
791
  Data Lake Storage Gen2), ``delta`` (Delta Lake),
792
- ``google_sheets``.
792
+ ``google_sheets``, ``google_drive``, ``dropbox``,
793
+ ``onedrive``, ``box``.
793
794
 
794
795
  Streaming & IoT / time-series:
795
796
  ``kafka``, ``kinesis``, ``mqtt``, ``opcua`` (OPC-UA),
@@ -975,7 +976,7 @@ class AutoDataClient:
975
976
  "excluded_columns": adv.get("excluded_columns", []),
976
977
  "text_mode": adv.get("text_mode", 0),
977
978
  "text_cleaning": adv.get("text_cleaning", True),
978
- "mdh_mode": adv.get("mdh_mode", 1),
979
+ "mdh_mode": adv.get("mdh_mode", 0),
979
980
  "zscore_limit": adv.get("zscore_limit", 3.0),
980
981
  "similarity_p": adv.get("similarity_p", 95),
981
982
  "dsg_mode": adv.get("dsg_mode", "copula"),
@@ -1307,6 +1308,150 @@ class AutoDataClient:
1307
1308
  self._raise_for_error(r)
1308
1309
  return r.json()
1309
1310
 
1311
+ # ------------------------------------------------------------------
1312
+ # Inference & retraining — apply a COMPLETED session to new data
1313
+ # ------------------------------------------------------------------
1314
+
1315
+ def infer(
1316
+ self,
1317
+ original_session_id: str,
1318
+ file_path: str,
1319
+ enable_anomaly_detection: Optional[bool] = None,
1320
+ download_path: Optional[str] = None,
1321
+ return_dataframes: bool = False,
1322
+ timeout: Optional[float] = None,
1323
+ ) -> Dict:
1324
+ """Score a new CSV with a completed session's fitted transforms.
1325
+
1326
+ Runs the lightweight inference pipeline server-side (Anomaly
1327
+ Detection → DTC → MDH → CDS) using the artifacts the original
1328
+ training run stored, so new rows get *exactly* the same encoding,
1329
+ imputation and scaling as the training data. Synchronous — the call
1330
+ returns when the server finishes; raise ``timeout`` for big files.
1331
+
1332
+ Args:
1333
+ original_session_id: A COMPLETED pipeline session owned by the
1334
+ caller (the ``session_id`` returned by
1335
+ :meth:`process` / :meth:`process_from_connector`).
1336
+ file_path: Local CSV with new rows to score. Column
1337
+ names must match the original training data.
1338
+ enable_anomaly_detection: Override the original session's anomaly
1339
+ setting; ``None`` inherits it.
1340
+ download_path: Directory to save ``features.csv`` /
1341
+ ``y_columns.csv`` into (skipped when None).
1342
+ return_dataframes: Also load the CSV outputs into a
1343
+ ``dataframes`` dict (requires pandas).
1344
+ timeout: Per-request timeout in seconds
1345
+ (default ``max(client timeout, 900)``).
1346
+
1347
+ Returns:
1348
+ Server result dict: ``status``, ``new_session_id``,
1349
+ ``output_files`` — plus ``files`` (local paths) when downloaded
1350
+ and ``dataframes`` when requested.
1351
+ """
1352
+ extra: Dict[str, str] = {}
1353
+ if enable_anomaly_detection is not None:
1354
+ extra["enableAnomalyDetection"] = (
1355
+ "true" if enable_anomaly_detection else "false")
1356
+ return self._apply_session(
1357
+ "/inference", original_session_id, file_path, extra,
1358
+ download_path, return_dataframes, timeout)
1359
+
1360
+ def retrain(
1361
+ self,
1362
+ original_session_id: str,
1363
+ file_path: str,
1364
+ run_dsm: bool = True,
1365
+ run_dsg: bool = True,
1366
+ output_rows: Optional[int] = None,
1367
+ enable_anomaly_detection: Optional[bool] = None,
1368
+ download_path: Optional[str] = None,
1369
+ return_dataframes: bool = False,
1370
+ timeout: Optional[float] = None,
1371
+ ) -> Dict:
1372
+ """Re-run the FULL pipeline on new data with a completed session's config.
1373
+
1374
+ Unlike :meth:`infer` this includes the downstream stages
1375
+ (… → Split → CDS → DSM → DSG) and produces ``retraining_output.csv``
1376
+ (features + targets combined) — use it to refresh a training set with
1377
+ newly arrived rows. Synchronous, like :meth:`infer`.
1378
+
1379
+ Args:
1380
+ original_session_id: A COMPLETED session owned by the caller.
1381
+ file_path: Local CSV with the new training rows.
1382
+ run_dsm: Run the data-splitting stage (default True).
1383
+ run_dsg: Run synthetic generation (default True).
1384
+ output_rows: DSG target row count (None = server default).
1385
+ enable_anomaly_detection: Override; ``None`` inherits the original.
1386
+ download_path: Directory to save the output files into.
1387
+ return_dataframes: Also load CSV outputs as DataFrames.
1388
+ timeout: Per-request timeout (default ≥ 900s).
1389
+
1390
+ Returns:
1391
+ Server result dict: ``status``, ``new_session_id``,
1392
+ ``output_files`` [+ ``files`` / ``dataframes``].
1393
+ """
1394
+ extra = {
1395
+ "run_dsm": "true" if run_dsm else "false",
1396
+ "run_dsg": "true" if run_dsg else "false",
1397
+ }
1398
+ if output_rows is not None:
1399
+ extra["output_sample_size"] = str(output_rows)
1400
+ if enable_anomaly_detection is not None:
1401
+ extra["enableAnomalyDetection"] = (
1402
+ "true" if enable_anomaly_detection else "false")
1403
+ return self._apply_session(
1404
+ "/retraining", original_session_id, file_path, extra,
1405
+ download_path, return_dataframes, timeout)
1406
+
1407
+ def _apply_session(
1408
+ self,
1409
+ endpoint: str,
1410
+ original_session_id: str,
1411
+ file_path: str,
1412
+ extra_form: Dict[str, str],
1413
+ download_path: Optional[str],
1414
+ return_dataframes: bool,
1415
+ timeout: Optional[float],
1416
+ ) -> Dict:
1417
+ """Shared upload/response handling for :meth:`infer` / :meth:`retrain`."""
1418
+ data = {"original_session_id": original_session_id}
1419
+ data.update(extra_form)
1420
+ effective_timeout = timeout if timeout is not None else max(self.timeout, 900)
1421
+ with open(file_path, "rb") as f:
1422
+ r = self._request(
1423
+ "POST",
1424
+ self._url(endpoint),
1425
+ files={"file": (os.path.basename(file_path), f, "text/csv")},
1426
+ data=data,
1427
+ timeout=effective_timeout,
1428
+ )
1429
+ self._raise_for_error(r)
1430
+ result = r.json()
1431
+
1432
+ new_session_id = result.get("new_session_id")
1433
+ outputs = result.get("output_files") or []
1434
+ if new_session_id and (download_path or return_dataframes):
1435
+ import tempfile
1436
+ target_dir = download_path or tempfile.mkdtemp(prefix="autodata_infer_")
1437
+ files: Dict[str, str] = {}
1438
+ for out in outputs:
1439
+ name = out.get("name")
1440
+ if not name:
1441
+ continue
1442
+ local = os.path.join(target_dir, name)
1443
+ self.download_file(
1444
+ self._url(f"/download/{new_session_id}/{name}"), local)
1445
+ files[name] = local
1446
+ result["files"] = files
1447
+ if return_dataframes:
1448
+ pd = self._require_pandas()
1449
+ result["dataframes"] = {
1450
+ os.path.splitext(name)[0]: pd.read_csv(path)
1451
+ for name, path in files.items() if name.endswith(".csv")
1452
+ }
1453
+ return result
1454
+
1310
1455
  def apply_mapping(
1311
1456
  self,
1312
1457
  session_id: str,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datatoolpack
3
- Version: 0.10.0
3
+ Version: 0.11.0
4
4
  Summary: Official Python SDK for the AutoData ML data preparation pipeline API
5
5
  Home-page: https://autodata.datatoolpack.com
6
6
  Author: AutoData Team
@@ -62,7 +62,7 @@ with AutoDataClient(api_key="dtpk_YOUR_API_KEY") as client:
62
62
  result = client.process(
63
63
  file_path="data.csv",
64
64
  target_columns=["price"],
65
- output_rows=20000,
65
+ output_rows=10000,
66
66
  )
67
67
  print(result["files"])
68
68
  ```
@@ -162,7 +162,7 @@ client.close()
162
162
  result = client.process(
163
163
  file_path="data.csv", # Path to input file (CSV, XLSX, Parquet, ...)
164
164
  target_columns=["price"], # y-column(s) for ML
165
- output_rows=20000, # Target row count in output
165
+ output_rows=10000, # Target row count in the synthetic output (default 10000)
166
166
  tools={ # Toggle pipeline steps (all optional)
167
167
  "anomaly": False, # Anomaly detection (off by default)
168
168
  "dtc": True, # Data Type Conversion
@@ -199,7 +199,7 @@ result = client.process(
199
199
  {"name": "dsg.csv", "url": "/download/.../dsg.csv", "size": 2097152, "description": "..."},
200
200
  {"name": "dsm_train.csv", ...},
201
201
  ],
202
- "row_count": 20000,
202
+ "row_count": 10000,
203
203
  "duration_seconds": 42.1,
204
204
  }
205
205
  ```
@@ -289,6 +289,72 @@ client.download_file("/api/v1/download/abc123.../dsg.csv", "dsg.csv")
289
289
 
290
290
  ---
291
291
 
292
+ ## Feature Selection (F4)
293
+
294
+ Rank a completed session's columns by predictive importance — **without re-running the pipeline**. Handy for trimming wide datasets before training.
295
+
296
+ ### `client.recommend_features(session_id, target_columns, methods, top_k)`
297
+
298
+ ```python
299
+ ranking = client.recommend_features(
300
+ session_id="abc123...", # a completed session you own
301
+ target_columns=["price"], # rank features against these target(s)
302
+ methods=["mutual_information"], # one or more methods (see below); default ["mutual_information"]
303
+ top_k=20, # number of top features to return (default 20)
304
+ )
305
+ # {
306
+ # "ranking": [{"feature": "sqft", "score": 0.81}, ...], # combined across methods
307
+ # "per_method": {"mutual_information": [...], "shap_importance": [...]},
308
+ # "warnings": [...],
309
+ # }
310
+ ```
311
+
312
+ **Available methods:** `variance_threshold`, `correlation_pruning`, `mutual_information`, `rfe`, `shap_importance`, `pca`. Pass several to blend their rankings, e.g. `methods=["mutual_information", "shap_importance"]`. (SHAP-based ranking uses a fast LightGBM model on the server; it degrades gracefully to `mutual_information` if those libraries are unavailable.)
313
+
314
+ ---
315
+
316
+ ## Inference & Retraining (v0.11.0+)
317
+
318
+ Apply a **completed** session's fitted transforms to new data — the missing
319
+ half of the ML lifecycle: train once, then score fresh production rows with
320
+ *exactly* the same encoding, imputation and scaling.
321
+
322
+ ### `client.infer(...)` — Score new data
323
+
324
+ Lightweight pipeline (Anomaly Detection → DTC → MDH → CDS). Outputs
325
+ `features.csv` (+ `y_columns.csv` if targets are present in the new file).
326
+
327
+ ```python
328
+ result = client.infer(
329
+ original_session_id="5d3bc0f0-...", # a completed training session you own
330
+ file_path="new_rows.csv", # columns must match the training data
331
+ download_path="./scored", # optional: save outputs locally
332
+ return_dataframes=True, # optional: get pandas DataFrames back
333
+ )
334
+ features_df = result["dataframes"]["features"]
335
+ ```
336
+
337
+ ### `client.retrain(...)` — Refresh a training set with new rows
338
+
339
+ Full pipeline including Split → CDS → DSM → DSG; produces
340
+ `retraining_output.csv` (features + targets combined).
341
+
342
+ ```python
343
+ result = client.retrain(
344
+ original_session_id="5d3bc0f0-...",
345
+ file_path="new_rows.csv",
346
+ run_dsg=True, output_rows=20000, # synthetic augmentation target
347
+ download_path="./retrained",
348
+ )
349
+ ```
350
+
351
+ Both calls are **synchronous** (the response arrives when processing ends;
352
+ default per-request timeout is ≥ 900 s — raise `timeout=` for very large
353
+ files), require the original session to be **completed and owned by you**,
354
+ and are free of credit charges in v1.
355
+
356
+ ---
357
+
292
358
  ## API Keys & Usage
293
359
 
294
360
  ### `client.list_keys()` — List API keys
@@ -336,6 +402,8 @@ Read data directly from databases and cloud storage instead of uploading files.
336
402
  | `kafka` | Apache Kafka | `bootstrap_servers`, `topic`, `group_id` |
337
403
  | `kinesis` | Amazon Kinesis | `stream_name`, `region`, `access_key_id`, `secret_access_key` |
338
404
 
405
+ > **More connectors:** AutoData supports 30+ source types. Beyond the common ones above you can also pass `oracle`, `redshift`, `cassandra`, `dynamodb`, `elasticsearch`, `clickhouse`, `timescaledb`, `synapse`, `azure_blob`, `adls`, `sap_hana`, `mqtt`, `opcua`, `influxdb`, `pi_web`, `salesforce`, `hubspot`, `stripe`, `netsuite`, `google_sheets`, `ga4`, `sharepoint`, and `http`/`rest` as `connector_type`. See **Dashboard → Documentation → Connector Data Sources** for each type's required `secrets` fields.
406
+
339
407
  ### Quick connector example
340
408
 
341
409
  ```python
@@ -363,7 +431,7 @@ with AutoDataClient(api_key="dtpk_...") as client:
363
431
  table="orders",
364
432
  target_columns=["price"],
365
433
  secrets={"connection_string": "postgresql://user:pass@host/db"},
366
- output_rows=20000,
434
+ output_rows=10000,
367
435
  )
368
436
  print(result["files"])
369
437
  ```
@@ -452,7 +520,7 @@ result = client.process_from_connector(
452
520
  table="orders",
453
521
  target_columns=["price"],
454
522
  secrets={"connection_string": "postgresql://..."},
455
- output_rows=20000,
523
+ output_rows=10000,
456
524
  incremental=True, # Only fetch new rows since last sync
457
525
  type_casts={"age": "int"}, # Override column types before processing
458
526
  wait=True,
@@ -474,7 +542,7 @@ client.write_output(
474
542
  if_exists="replace", # "replace", "append", "fail", or "merge"
475
543
  merge_keys=["id"], # column names for merge matching (when if_exists='merge')
476
544
  )
477
- # {"success": True, "rows_written": 20000, "table": "ml_prepared_data"}
545
+ # {"success": True, "rows_written": 10000, "table": "ml_prepared_data"}
478
546
  ```
479
547
 
480
548
  ---
@@ -639,6 +707,65 @@ client.delete_scheduled_run(run_id="run-id")
639
707
 
640
708
  ---
641
709
 
710
+ ## Triggers (F7)
711
+
712
+ Auto-start a pipeline when an external event fires — an inbound webhook, a connector watermark advancing, another pipeline completing, or a quality alert. Triggers are feature-flagged on the server (`FEATURE_FLAG_TRIGGERS`); if the flag is off, these endpoints return `404`.
713
+
714
+ ### `client.create_trigger(name, trigger_type, config, target_pipeline_config, enabled)`
715
+
716
+ ```python
717
+ trigger = client.create_trigger(
718
+ name="Reprocess on new S3 batch",
719
+ trigger_type="inbound_webhook", # inbound_webhook | watermark_advance | pipeline_completion | quality_alert
720
+ config={}, # type-specific (see table below)
721
+ target_pipeline_config={ # the pipeline to run when the trigger fires
722
+ "source_type": "s3",
723
+ "credential_id": "cred-uuid",
724
+ "table": "incoming/sales.csv",
725
+ "target_columns": ["revenue"],
726
+ "output_rows": 10000,
727
+ },
728
+ enabled=True,
729
+ )
730
+ # For inbound_webhook the secret is returned ONLY once — save it now:
731
+ print(trigger["webhook_secret"], trigger["inbound_url"])
732
+ ```
733
+
734
+ **Trigger types & their `config`:**
735
+
736
+ | `trigger_type` | `config` keys |
737
+ |-----------------------|---------------|
738
+ | `inbound_webhook` | optional `{"hmac_key": "..."}` — require HMAC-SHA256-signed requests |
739
+ | `watermark_advance` | `{"credential_id", "table", "watermark_column", "min_advance"}` |
740
+ | `pipeline_completion` | `{}` — chain off another pipeline finishing |
741
+ | `quality_alert` | `{}` — fire when a quality-alert rule trips |
742
+
743
+ ```python
744
+ # List / fetch / update / delete
745
+ triggers = client.list_triggers()
746
+ t = client.get_trigger(trigger_id)
747
+ client.update_trigger(trigger_id, enabled=False) # name | enabled | config | target_pipeline_config
748
+ client.delete_trigger(trigger_id)
749
+
750
+ # Dry-run: validate config + target WITHOUT firing
751
+ report = client.test_trigger(trigger_id)
752
+ # {"would_fire": True, "checks": {...}}
753
+ ```
754
+
755
+ **Firing an inbound webhook** from your own system:
756
+
757
+ ```bash
758
+ curl -X POST "https://autodata.datatoolpack.com/trigger/inbound/<webhook_secret>" \
759
+ -H "Content-Type: application/json" \
760
+ -d '{"any": "payload"}'
761
+ # If you set an hmac_key, also sign the raw body:
762
+ # X-Signature: sha256=<hex HMAC-SHA256 of the request body>
763
+ ```
764
+
765
+ Inbound firing is rate-limited and HMAC-verified server-side; repeated failures auto-disable the trigger.
766
+
767
+ ---
768
+
642
769
  ## Folder Listeners
643
770
 
644
771
  Automatically trigger pipelines when new files appear in cloud storage:
@@ -819,6 +946,11 @@ with AutoDataClient() as client:
819
946
  | `list_keys()` | List all API keys for the account |
820
947
  | `get_usage()` | Get credit usage statistics |
821
948
 
949
+ ### Feature Selection
950
+ | Method | Description |
951
+ |--------|-------------|
952
+ | `recommend_features(session_id, target_columns, ...)` | Rank a completed session's features (F4) |
953
+
822
954
  ### Connectors
823
955
  | Method | Description |
824
956
  |--------|-------------|
@@ -866,6 +998,16 @@ with AutoDataClient() as client:
866
998
  | `toggle_scheduled_run(run_id)` | Enable/disable a scheduled run |
867
999
  | `run_scheduled_now(run_id)` | Trigger a scheduled run immediately |
868
1000
 
1001
+ ### Triggers
1002
+ | Method | Description |
1003
+ |--------|-------------|
1004
+ | `list_triggers()` | List your triggers |
1005
+ | `create_trigger(name, trigger_type, ...)` | Create an event trigger (F7) |
1006
+ | `get_trigger(trigger_id)` | Fetch one trigger |
1007
+ | `update_trigger(trigger_id, ...)` | Update a trigger |
1008
+ | `delete_trigger(trigger_id)` | Delete a trigger |
1009
+ | `test_trigger(trigger_id)` | Dry-run a trigger without firing |
1010
+
869
1011
  ### Folder Listeners
870
1012
  | Method | Description |
871
1013
  |--------|-------------|
@@ -7,7 +7,7 @@ with open(os.path.join(here, "README.md"), encoding="utf-8") as f:
7
7
 
8
8
  setup(
9
9
  name="datatoolpack",
10
- version="0.10.0",
10
+ version="0.11.0",
11
11
  description="Official Python SDK for the AutoData ML data preparation pipeline API",
12
12
  long_description=long_description,
13
13
  long_description_content_type="text/markdown",
File without changes