lumera 0.8.3__py3-none-any.whl → 0.9.1__py3-none-any.whl

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.
lumera/pb.py CHANGED
@@ -318,51 +318,84 @@ def delete(collection: str, record_id: str) -> None:
318
318
  # =============================================================================
319
319
 
320
320
 
321
- def bulk_delete(collection: str, record_ids: Sequence[str]) -> dict[str, Any]:
321
+ def bulk_delete(
322
+ collection: str,
323
+ record_ids: Sequence[str],
324
+ *,
325
+ transaction: bool = False,
326
+ ) -> dict[str, Any]:
322
327
  """Delete multiple records by ID.
323
328
 
324
329
  Args:
325
330
  collection: Collection name or ID
326
331
  record_ids: List of record IDs to delete (max 1000)
332
+ transaction: If True, use all-or-nothing semantics (rollback on any failure).
333
+ If False (default), partial success is allowed.
327
334
 
328
335
  Returns:
329
336
  Result with succeeded/failed counts and any errors:
330
337
  {
331
338
  "succeeded": 10,
332
339
  "failed": 0,
333
- "errors": []
340
+ "errors": [],
341
+ "rolled_back": false # only present if transaction=True and failed
334
342
  }
335
343
 
336
344
  Example:
337
345
  >>> result = pb.bulk_delete("deposits", ["id1", "id2", "id3"])
338
346
  >>> print(f"Deleted {result['succeeded']} records")
347
+
348
+ >>> # Use transaction mode for all-or-nothing
349
+ >>> result = pb.bulk_delete("deposits", ids, transaction=True)
339
350
  """
340
- return _bulk_delete_records(collection, record_ids)
351
+ return _bulk_delete_records(collection, record_ids, transaction=transaction)
341
352
 
342
353
 
343
354
  def bulk_update(
344
355
  collection: str,
345
- record_ids: Sequence[str],
346
- data: dict[str, Any],
356
+ records: Sequence[dict[str, Any]],
357
+ *,
358
+ transaction: bool = False,
347
359
  ) -> dict[str, Any]:
348
- """Update multiple records with the same data.
360
+ """Update multiple records with individual data per record.
361
+
362
+ Each record must have an 'id' field plus fields to update.
363
+ Records must exist (returns error if not found, does not create).
349
364
 
350
365
  Args:
351
366
  collection: Collection name or ID
352
- record_ids: List of record IDs to update (max 1000)
353
- data: Fields to update on all records
367
+ records: List of records to update (max 1000). Each must have 'id' field.
368
+ transaction: If True, use all-or-nothing semantics (rollback on any failure).
369
+ If False (default), partial success is allowed.
354
370
 
355
371
  Returns:
356
- Result with succeeded/failed counts
372
+ Result with succeeded/failed counts:
373
+ {
374
+ "succeeded": 2,
375
+ "failed": 0,
376
+ "errors": [],
377
+ "rolled_back": false # only present if transaction=True and failed
378
+ }
357
379
 
358
380
  Example:
359
- >>> result = pb.bulk_update("deposits", ["id1", "id2"], {"status": "processed"})
381
+ >>> result = pb.bulk_update("deposits", [
382
+ ... {"id": "rec1", "status": "approved", "amount": 100},
383
+ ... {"id": "rec2", "status": "rejected", "amount": 200},
384
+ ... ])
360
385
  >>> print(f"Updated {result['succeeded']} records")
386
+
387
+ >>> # Use transaction mode for all-or-nothing
388
+ >>> result = pb.bulk_update("deposits", records, transaction=True)
361
389
  """
362
- return _bulk_update_records(collection, record_ids, data)
390
+ return _bulk_update_records(collection, records, transaction=transaction)
363
391
 
364
392
 
365
- def bulk_upsert(collection: str, records: Sequence[dict[str, Any]]) -> dict[str, Any]:
393
+ def bulk_upsert(
394
+ collection: str,
395
+ records: Sequence[dict[str, Any]],
396
+ *,
397
+ transaction: bool = False,
398
+ ) -> dict[str, Any]:
366
399
  """Create or update multiple records by ID.
367
400
 
368
401
  Each record can include an "id" field. Records with matching IDs will be
@@ -371,25 +404,44 @@ def bulk_upsert(collection: str, records: Sequence[dict[str, Any]]) -> dict[str,
371
404
  Args:
372
405
  collection: Collection name or ID
373
406
  records: List of records (max 1000)
407
+ transaction: If True, use all-or-nothing semantics (rollback on any failure).
408
+ If False (default), partial success is allowed.
374
409
 
375
410
  Returns:
376
- Result with succeeded/failed counts and created record IDs
411
+ Result with succeeded/failed counts and created record IDs:
412
+ {
413
+ "succeeded": 2,
414
+ "failed": 0,
415
+ "errors": [],
416
+ "records": [{"id": "..."}, ...],
417
+ "rolled_back": false # only present if transaction=True and failed
418
+ }
377
419
 
378
420
  Example:
379
421
  >>> result = pb.bulk_upsert("deposits", [
380
422
  ... {"id": "existing_id", "amount": 100},
381
423
  ... {"amount": 200}, # creates new record
382
424
  ... ])
425
+
426
+ >>> # Use transaction mode for all-or-nothing
427
+ >>> result = pb.bulk_upsert("deposits", records, transaction=True)
383
428
  """
384
- return _bulk_upsert_records(collection, records)
429
+ return _bulk_upsert_records(collection, records, transaction=transaction)
385
430
 
386
431
 
387
- def bulk_insert(collection: str, records: Sequence[dict[str, Any]]) -> dict[str, Any]:
432
+ def bulk_insert(
433
+ collection: str,
434
+ records: Sequence[dict[str, Any]],
435
+ *,
436
+ transaction: bool = False,
437
+ ) -> dict[str, Any]:
388
438
  """Insert multiple new records.
389
439
 
390
440
  Args:
391
441
  collection: Collection name or ID
392
442
  records: List of records to create (max 1000)
443
+ transaction: If True, use all-or-nothing semantics (rollback on any failure).
444
+ If False (default), partial success is allowed.
393
445
 
394
446
  Returns:
395
447
  Result with succeeded/failed counts and created record IDs:
@@ -397,7 +449,8 @@ def bulk_insert(collection: str, records: Sequence[dict[str, Any]]) -> dict[str,
397
449
  "succeeded": 2,
398
450
  "failed": 0,
399
451
  "errors": [],
400
- "records": [{"id": "..."}, {"id": "..."}]
452
+ "records": [{"id": "..."}, {"id": "..."}],
453
+ "rolled_back": false # only present if transaction=True and failed
401
454
  }
402
455
 
403
456
  Example:
@@ -407,8 +460,11 @@ def bulk_insert(collection: str, records: Sequence[dict[str, Any]]) -> dict[str,
407
460
  ... ])
408
461
  >>> for rec in result["records"]:
409
462
  ... print(f"Created: {rec['id']}")
463
+
464
+ >>> # Use transaction mode for all-or-nothing
465
+ >>> result = pb.bulk_insert("deposits", records, transaction=True)
410
466
  """
411
- return _bulk_insert_records(collection, records)
467
+ return _bulk_insert_records(collection, records, transaction=transaction)
412
468
 
413
469
 
414
470
  def iter_all(
lumera/sdk.py CHANGED
@@ -591,12 +591,15 @@ def delete_record(collection_id_or_name: str, record_id: str) -> None:
591
591
  def bulk_delete_records(
592
592
  collection_id_or_name: str,
593
593
  record_ids: Sequence[str],
594
+ *,
595
+ transaction: bool = False,
594
596
  ) -> dict[str, Any]:
595
597
  """Bulk delete records by IDs.
596
598
 
597
599
  Args:
598
600
  collection_id_or_name: Collection name or ID
599
601
  record_ids: List of record IDs to delete (max 1000)
602
+ transaction: If True, use all-or-nothing semantics (rollback on any failure)
600
603
 
601
604
  Returns:
602
605
  Result with succeeded/failed counts and any errors
@@ -607,46 +610,54 @@ def bulk_delete_records(
607
610
  raise ValueError("record_ids is required")
608
611
 
609
612
  path = f"collections/{collection_id_or_name}/records/bulk/delete"
610
- result = _api_request("POST", path, json_body={"ids": list(record_ids)})
613
+ body: dict[str, Any] = {"ids": list(record_ids)}
614
+ if transaction:
615
+ body["transaction"] = True
616
+ result = _api_request("POST", path, json_body=body)
611
617
  return result if isinstance(result, dict) else {}
612
618
 
613
619
 
614
620
  def bulk_update_records(
615
621
  collection_id_or_name: str,
616
- record_ids: Sequence[str],
617
- data: Mapping[str, Any],
622
+ records: Sequence[Mapping[str, Any]],
623
+ *,
624
+ transaction: bool = False,
618
625
  ) -> dict[str, Any]:
619
- """Update multiple records with the same data.
626
+ """Update multiple records with individual data per record.
620
627
 
621
628
  Args:
622
629
  collection_id_or_name: Collection name or ID
623
- record_ids: List of record IDs to update (max 1000)
624
- data: Fields to update on all records
630
+ records: List of records to update (max 1000). Each record must have an 'id' field.
631
+ transaction: If True, use all-or-nothing semantics (rollback on any failure)
625
632
 
626
633
  Returns:
627
634
  Result with succeeded/failed counts
628
635
  """
629
636
  if not collection_id_or_name:
630
637
  raise ValueError("collection_id_or_name is required")
631
- if not record_ids:
632
- raise ValueError("record_ids is required")
633
- if not data:
634
- raise ValueError("data is required")
638
+ if not records:
639
+ raise ValueError("records is required")
635
640
 
636
641
  path = f"collections/{collection_id_or_name}/records/bulk/update"
637
- result = _api_request("POST", path, json_body={"ids": list(record_ids), "data": dict(data)})
642
+ body: dict[str, Any] = {"records": [dict(r) for r in records]}
643
+ if transaction:
644
+ body["transaction"] = True
645
+ result = _api_request("POST", path, json_body=body)
638
646
  return result if isinstance(result, dict) else {}
639
647
 
640
648
 
641
649
  def bulk_upsert_records(
642
650
  collection_id_or_name: str,
643
651
  records: Sequence[Mapping[str, Any]],
652
+ *,
653
+ transaction: bool = False,
644
654
  ) -> dict[str, Any]:
645
655
  """Upsert multiple records (create or update by ID).
646
656
 
647
657
  Args:
648
658
  collection_id_or_name: Collection name or ID
649
659
  records: List of records (max 1000). Include 'id' field to update existing.
660
+ transaction: If True, use all-or-nothing semantics (rollback on any failure)
650
661
 
651
662
  Returns:
652
663
  Result with succeeded/failed counts and created record IDs
@@ -657,19 +668,25 @@ def bulk_upsert_records(
657
668
  raise ValueError("records is required")
658
669
 
659
670
  path = f"collections/{collection_id_or_name}/records/bulk/upsert"
660
- result = _api_request("POST", path, json_body={"records": [dict(r) for r in records]})
671
+ body: dict[str, Any] = {"records": [dict(r) for r in records]}
672
+ if transaction:
673
+ body["transaction"] = True
674
+ result = _api_request("POST", path, json_body=body)
661
675
  return result if isinstance(result, dict) else {}
662
676
 
663
677
 
664
678
  def bulk_insert_records(
665
679
  collection_id_or_name: str,
666
680
  records: Sequence[Mapping[str, Any]],
681
+ *,
682
+ transaction: bool = False,
667
683
  ) -> dict[str, Any]:
668
684
  """Insert multiple new records.
669
685
 
670
686
  Args:
671
687
  collection_id_or_name: Collection name or ID
672
688
  records: List of records to create (max 1000)
689
+ transaction: If True, use all-or-nothing semantics (rollback on any failure)
673
690
 
674
691
  Returns:
675
692
  Result with succeeded/failed counts and created record IDs
@@ -680,7 +697,10 @@ def bulk_insert_records(
680
697
  raise ValueError("records is required")
681
698
 
682
699
  path = f"collections/{collection_id_or_name}/records/bulk/insert"
683
- result = _api_request("POST", path, json_body={"records": [dict(r) for r in records]})
700
+ body: dict[str, Any] = {"records": [dict(r) for r in records]}
701
+ if transaction:
702
+ body["transaction"] = True
703
+ result = _api_request("POST", path, json_body=body)
684
704
  return result if isinstance(result, dict) else {}
685
705
 
686
706
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lumera
3
- Version: 0.8.3
3
+ Version: 0.9.1
4
4
  Summary: SDK for building on Lumera platform
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: requests
@@ -5,11 +5,11 @@ lumera/exceptions.py,sha256=bNsx4iYaroAAGsYxErfELC2B5ZJ3w5lVa1kKdIx5s9g,2173
5
5
  lumera/google.py,sha256=zpWW1qSlzLZY5Ip7cGAzrv9sJrQf3JBKH2ODc1cCM_E,1130
6
6
  lumera/llm.py,sha256=pUTZK7t3GTK0vfxMI1PJgJwNendyuiJc5MB1pUj2vxE,14412
7
7
  lumera/locks.py,sha256=8l_qxb8nrxge7YJ-ApUTJ5MeYpIdxDeEa94Eim9O-YM,6806
8
- lumera/pb.py,sha256=EZABRPVbrSJ8_9Yh-BLt9cp4omkwo5r10Qs8v7wc1qc,18236
9
- lumera/sdk.py,sha256=EZVH1FnT7smkvFgT6QjVf4gDnVuktF1w7RZFaeTPgDE,30470
8
+ lumera/pb.py,sha256=fTGjcclIGmXxQsBCDhXVrPyKBkdPJ3DRwNZfICT5X8E,20434
9
+ lumera/sdk.py,sha256=0Q4b0LXbr7Vl0SpstH1IKEZwGek33Jz-4ICMRe_Z60A,31217
10
10
  lumera/storage.py,sha256=b0W6JNSGfmhJIcmK3vrATXAwxIr_bfrj-hPuQRVLTYU,8206
11
11
  lumera/webhooks.py,sha256=L_Q5YHBJKQNpv7G9Nq0QqlGMRch6x9ptlwu1xD2qwUc,8661
12
- lumera-0.8.3.dist-info/METADATA,sha256=TRrXqx2Cm1DMVzzg-V3aoe9832IEsnnL13WMOrAriAg,1611
13
- lumera-0.8.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
- lumera-0.8.3.dist-info/top_level.txt,sha256=HgfK4XQkpMTnM2E5iWM4kB711FnYqUY9dglzib3pWlE,7
15
- lumera-0.8.3.dist-info/RECORD,,
12
+ lumera-0.9.1.dist-info/METADATA,sha256=gbS5AHAHUaw4sh8EHbKKb1ONZnzD2ph-lOidiUv49iE,1611
13
+ lumera-0.9.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ lumera-0.9.1.dist-info/top_level.txt,sha256=HgfK4XQkpMTnM2E5iWM4kB711FnYqUY9dglzib3pWlE,7
15
+ lumera-0.9.1.dist-info/RECORD,,
File without changes