lumera 0.5.4__py3-none-any.whl → 0.6.0__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
@@ -60,6 +60,11 @@ __all__ = [
60
60
  "upsert",
61
61
  "delete",
62
62
  "iter_all",
63
+ # Bulk operations
64
+ "bulk_delete",
65
+ "bulk_update",
66
+ "bulk_upsert",
67
+ "bulk_insert",
63
68
  # Collection operations
64
69
  "list_collections",
65
70
  "get_collection",
@@ -107,6 +112,18 @@ from .sdk import (
107
112
  from .sdk import (
108
113
  upsert_record as _upsert_record,
109
114
  )
115
+ from .sdk import (
116
+ bulk_delete_records as _bulk_delete_records,
117
+ )
118
+ from .sdk import (
119
+ bulk_update_records as _bulk_update_records,
120
+ )
121
+ from .sdk import (
122
+ bulk_upsert_records as _bulk_upsert_records,
123
+ )
124
+ from .sdk import (
125
+ bulk_insert_records as _bulk_insert_records,
126
+ )
110
127
 
111
128
 
112
129
  def search(
@@ -296,6 +313,104 @@ def delete(collection: str, record_id: str) -> None:
296
313
  _delete_record(collection, record_id)
297
314
 
298
315
 
316
+ # =============================================================================
317
+ # Bulk Operations
318
+ # =============================================================================
319
+
320
+
321
+ def bulk_delete(collection: str, record_ids: Sequence[str]) -> dict[str, Any]:
322
+ """Delete multiple records by ID.
323
+
324
+ Args:
325
+ collection: Collection name or ID
326
+ record_ids: List of record IDs to delete (max 1000)
327
+
328
+ Returns:
329
+ Result with succeeded/failed counts and any errors:
330
+ {
331
+ "succeeded": 10,
332
+ "failed": 0,
333
+ "errors": []
334
+ }
335
+
336
+ Example:
337
+ >>> result = pb.bulk_delete("deposits", ["id1", "id2", "id3"])
338
+ >>> print(f"Deleted {result['succeeded']} records")
339
+ """
340
+ return _bulk_delete_records(collection, record_ids)
341
+
342
+
343
+ def bulk_update(
344
+ collection: str,
345
+ record_ids: Sequence[str],
346
+ data: dict[str, Any],
347
+ ) -> dict[str, Any]:
348
+ """Update multiple records with the same data.
349
+
350
+ Args:
351
+ collection: Collection name or ID
352
+ record_ids: List of record IDs to update (max 1000)
353
+ data: Fields to update on all records
354
+
355
+ Returns:
356
+ Result with succeeded/failed counts
357
+
358
+ Example:
359
+ >>> result = pb.bulk_update("deposits", ["id1", "id2"], {"status": "processed"})
360
+ >>> print(f"Updated {result['succeeded']} records")
361
+ """
362
+ return _bulk_update_records(collection, record_ids, data)
363
+
364
+
365
+ def bulk_upsert(collection: str, records: Sequence[dict[str, Any]]) -> dict[str, Any]:
366
+ """Create or update multiple records by ID.
367
+
368
+ Each record can include an "id" field. Records with matching IDs will be
369
+ updated; records without IDs or with non-existent IDs create new records.
370
+
371
+ Args:
372
+ collection: Collection name or ID
373
+ records: List of records (max 1000)
374
+
375
+ Returns:
376
+ Result with succeeded/failed counts and created record IDs
377
+
378
+ Example:
379
+ >>> result = pb.bulk_upsert("deposits", [
380
+ ... {"id": "existing_id", "amount": 100},
381
+ ... {"amount": 200}, # creates new record
382
+ ... ])
383
+ """
384
+ return _bulk_upsert_records(collection, records)
385
+
386
+
387
+ def bulk_insert(collection: str, records: Sequence[dict[str, Any]]) -> dict[str, Any]:
388
+ """Insert multiple new records.
389
+
390
+ Args:
391
+ collection: Collection name or ID
392
+ records: List of records to create (max 1000)
393
+
394
+ Returns:
395
+ Result with succeeded/failed counts and created record IDs:
396
+ {
397
+ "succeeded": 2,
398
+ "failed": 0,
399
+ "errors": [],
400
+ "records": [{"id": "..."}, {"id": "..."}]
401
+ }
402
+
403
+ Example:
404
+ >>> result = pb.bulk_insert("deposits", [
405
+ ... {"external_id": "dep-001", "amount": 100},
406
+ ... {"external_id": "dep-002", "amount": 200},
407
+ ... ])
408
+ >>> for rec in result["records"]:
409
+ ... print(f"Created: {rec['id']}")
410
+ """
411
+ return _bulk_insert_records(collection, records)
412
+
413
+
299
414
  def iter_all(
300
415
  collection: str,
301
416
  *,
lumera/sdk.py CHANGED
@@ -576,6 +576,113 @@ def delete_record(collection_id_or_name: str, record_id: str) -> None:
576
576
  _api_request("DELETE", path)
577
577
 
578
578
 
579
+ # =============================================================================
580
+ # Bulk Record Operations
581
+ # =============================================================================
582
+
583
+
584
+ def bulk_delete_records(
585
+ collection_id_or_name: str,
586
+ record_ids: Sequence[str],
587
+ ) -> dict[str, Any]:
588
+ """Bulk delete records by IDs.
589
+
590
+ Args:
591
+ collection_id_or_name: Collection name or ID
592
+ record_ids: List of record IDs to delete (max 1000)
593
+
594
+ Returns:
595
+ Result with succeeded/failed counts and any errors
596
+ """
597
+ if not collection_id_or_name:
598
+ raise ValueError("collection_id_or_name is required")
599
+ if not record_ids:
600
+ raise ValueError("record_ids is required")
601
+
602
+ path = f"collections/{collection_id_or_name}/records/bulk/delete"
603
+ result = _api_request("POST", path, json_body={"ids": list(record_ids)})
604
+ return result if isinstance(result, dict) else {}
605
+
606
+
607
+ def bulk_update_records(
608
+ collection_id_or_name: str,
609
+ record_ids: Sequence[str],
610
+ data: Mapping[str, Any],
611
+ ) -> dict[str, Any]:
612
+ """Update multiple records with the same data.
613
+
614
+ Args:
615
+ collection_id_or_name: Collection name or ID
616
+ record_ids: List of record IDs to update (max 1000)
617
+ data: Fields to update on all records
618
+
619
+ Returns:
620
+ Result with succeeded/failed counts
621
+ """
622
+ if not collection_id_or_name:
623
+ raise ValueError("collection_id_or_name is required")
624
+ if not record_ids:
625
+ raise ValueError("record_ids is required")
626
+ if not data:
627
+ raise ValueError("data is required")
628
+
629
+ path = f"collections/{collection_id_or_name}/records/bulk/update"
630
+ result = _api_request(
631
+ "POST", path, json_body={"ids": list(record_ids), "data": dict(data)}
632
+ )
633
+ return result if isinstance(result, dict) else {}
634
+
635
+
636
+ def bulk_upsert_records(
637
+ collection_id_or_name: str,
638
+ records: Sequence[Mapping[str, Any]],
639
+ ) -> dict[str, Any]:
640
+ """Upsert multiple records (create or update by ID).
641
+
642
+ Args:
643
+ collection_id_or_name: Collection name or ID
644
+ records: List of records (max 1000). Include 'id' field to update existing.
645
+
646
+ Returns:
647
+ Result with succeeded/failed counts and created record IDs
648
+ """
649
+ if not collection_id_or_name:
650
+ raise ValueError("collection_id_or_name is required")
651
+ if not records:
652
+ raise ValueError("records is required")
653
+
654
+ path = f"collections/{collection_id_or_name}/records/bulk/upsert"
655
+ result = _api_request(
656
+ "POST", path, json_body={"records": [dict(r) for r in records]}
657
+ )
658
+ return result if isinstance(result, dict) else {}
659
+
660
+
661
+ def bulk_insert_records(
662
+ collection_id_or_name: str,
663
+ records: Sequence[Mapping[str, Any]],
664
+ ) -> dict[str, Any]:
665
+ """Insert multiple new records.
666
+
667
+ Args:
668
+ collection_id_or_name: Collection name or ID
669
+ records: List of records to create (max 1000)
670
+
671
+ Returns:
672
+ Result with succeeded/failed counts and created record IDs
673
+ """
674
+ if not collection_id_or_name:
675
+ raise ValueError("collection_id_or_name is required")
676
+ if not records:
677
+ raise ValueError("records is required")
678
+
679
+ path = f"collections/{collection_id_or_name}/records/bulk/insert"
680
+ result = _api_request(
681
+ "POST", path, json_body={"records": [dict(r) for r in records]}
682
+ )
683
+ return result if isinstance(result, dict) else {}
684
+
685
+
579
686
  def replay_hook(
580
687
  collection_id_or_name: str,
581
688
  event: str,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lumera
3
- Version: 0.5.4
3
+ Version: 0.6.0
4
4
  Summary: SDK for building on Lumera platform
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: requests
@@ -4,10 +4,10 @@ lumera/exceptions.py,sha256=bNsx4iYaroAAGsYxErfELC2B5ZJ3w5lVa1kKdIx5s9g,2173
4
4
  lumera/google.py,sha256=3IVNL1HaOtsTmunl0alnGFuUAkzQQRyCEA3CKjlPqO0,10183
5
5
  lumera/llm.py,sha256=pUTZK7t3GTK0vfxMI1PJgJwNendyuiJc5MB1pUj2vxE,14412
6
6
  lumera/locks.py,sha256=8l_qxb8nrxge7YJ-ApUTJ5MeYpIdxDeEa94Eim9O-YM,6806
7
- lumera/pb.py,sha256=_UxVzg0xIcR_97GGVgbfoLL-Usi0PBdcIbqzUBiniqs,14911
8
- lumera/sdk.py,sha256=6Vw0f5MX-yjmy7KBZzEYNdjtXk2P4Oxibpa_UpcM7bs,26859
7
+ lumera/pb.py,sha256=oJf37awGIoJ25VA1eSA3lMUXorOtNynVC7yG30X4-lU,18236
8
+ lumera/sdk.py,sha256=XnzVtAGonhhQ2pDMtNKEOG5ZVH1sPLK-gsyTfCfBLSA,30233
9
9
  lumera/storage.py,sha256=kQQJYVRnxcpDZQ_gB2iZy6anb3hyZN7b8a_oNuE2yYE,8191
10
- lumera-0.5.4.dist-info/METADATA,sha256=PnOwwoKlwZJzsK_bIKLj1u_Eo7X6O2TBYuw_1R5Tt50,1611
11
- lumera-0.5.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
- lumera-0.5.4.dist-info/top_level.txt,sha256=HgfK4XQkpMTnM2E5iWM4kB711FnYqUY9dglzib3pWlE,7
13
- lumera-0.5.4.dist-info/RECORD,,
10
+ lumera-0.6.0.dist-info/METADATA,sha256=4rhyTGFp6Iw1Zv-ZOtDcyThUvMSljTTtyLp-EKnEyvE,1611
11
+ lumera-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
+ lumera-0.6.0.dist-info/top_level.txt,sha256=HgfK4XQkpMTnM2E5iWM4kB711FnYqUY9dglzib3pWlE,7
13
+ lumera-0.6.0.dist-info/RECORD,,
File without changes