pangea-sdk 5.0.0__py3-none-any.whl → 5.2.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.
@@ -0,0 +1,1278 @@
1
+ # Copyright 2022 Pangea Cyber Corporation
2
+ # Author: Pangea Cyber Corporation
3
+ from __future__ import annotations
4
+
5
+ import enum
6
+ import io
7
+ from typing import Dict, List, NewType, Optional, Tuple, Union
8
+
9
+ from pangea.config import PangeaConfig
10
+ from pangea.response import APIRequestModel, PangeaResponse, PangeaResponseResult, TransferMethod
11
+ from pangea.services.base import ServiceBase
12
+ from pangea.services.share.file_format import FileFormat
13
+ from pangea.utils import get_file_size, get_file_upload_params
14
+
15
+ Metadata = NewType("Metadata", Dict[str, str])
16
+ Tags = NewType("Tags", List[str])
17
+
18
+
19
+ class ItemOrder(str, enum.Enum):
20
+ ASC = "asc"
21
+ DESC = "desc"
22
+
23
+ def __str__(self):
24
+ return str(self.value)
25
+
26
+ def __repr__(self):
27
+ return str(self.value)
28
+
29
+
30
+ class ArchiveFormat(str, enum.Enum):
31
+ TAR = "tar"
32
+ ZIP = "zip"
33
+
34
+ def __str__(self):
35
+ return str(self.value)
36
+
37
+ def __repr__(self):
38
+ return str(self.value)
39
+
40
+
41
+ class LinkType(str, enum.Enum):
42
+ UPLOAD = "upload"
43
+ DOWNLOAD = "download"
44
+ EDITOR = "editor"
45
+
46
+ def __str__(self):
47
+ return str(self.value)
48
+
49
+ def __repr__(self):
50
+ return str(self.value)
51
+
52
+
53
+ class AuthenticatorType(str, enum.Enum):
54
+ EMAIL_OTP = "email_otp"
55
+ PASSWORD = "password"
56
+ SMS_OTP = "sms_otp"
57
+ SOCIAL = "social"
58
+
59
+ def __str__(self):
60
+ return str(self.value)
61
+
62
+ def __repr__(self):
63
+ return str(self.value)
64
+
65
+
66
+ class ItemOrderBy(str, enum.Enum):
67
+ ID = "id"
68
+ CREATED_AT = "created_at"
69
+ NAME = "name"
70
+ PARENT_ID = "parent_id"
71
+ TYPE = "type"
72
+ UPDATED_AT = "updated_at"
73
+
74
+ def __str__(self):
75
+ return str(self.value)
76
+
77
+ def __repr__(self):
78
+ return str(self.value)
79
+
80
+
81
+ class ShareLinkOrderBy(str, enum.Enum):
82
+ ID = "id"
83
+ BUCKET_ID = "bucket_id"
84
+ TARGET = "target"
85
+ LINK_TYPE = "link_type"
86
+ ACCESS_COUNT = "access_count"
87
+ MAX_ACCESS_COUNT = "max_access_count"
88
+ CREATED_AT = "created_at"
89
+ EXPIRES_AT = "expires_at"
90
+ LAST_ACCESSED_AT = "last_accessed_at"
91
+ LINK = "link"
92
+
93
+ def __str__(self):
94
+ return str(self.value)
95
+
96
+ def __repr__(self):
97
+ return str(self.value)
98
+
99
+
100
+ class DeleteRequest(APIRequestModel):
101
+ id: Optional[str] = None
102
+ """The ID of the object to delete."""
103
+
104
+ force: Optional[bool] = None
105
+ """If true, delete a folder even if it's not empty. Deletes the contents of folder as well."""
106
+
107
+ bucket_id: Optional[str] = None
108
+ """The bucket to use, if not the default."""
109
+
110
+
111
+ class ItemData(PangeaResponseResult):
112
+ billable_size: Optional[int] = None
113
+ """The number of billable bytes (includes Metadata, Tags, etc.) for the object."""
114
+
115
+ created_at: str
116
+ """The date and time the object was created."""
117
+
118
+ id: str
119
+ """The ID of a stored object."""
120
+
121
+ md5: Optional[str] = None
122
+ """The MD5 hash of the file contents. Cannot be written to."""
123
+
124
+ metadata: Optional[Metadata] = None
125
+ """A set of string-based key/value pairs used to provide additional data about an object."""
126
+
127
+ metadata_protected: Optional[Metadata] = None
128
+ """Protected (read-only) metadata."""
129
+
130
+ sha256: Optional[str] = None
131
+ """The SHA256 hash of the file contents. Cannot be written to."""
132
+
133
+ sha512: Optional[str] = None
134
+ """The SHA512 hash of the file contents. Cannot be written to."""
135
+
136
+ size: Optional[int] = None
137
+ """The size of the object in bytes."""
138
+
139
+ tags: Optional[Tags] = None
140
+ """A list of user-defined tags."""
141
+
142
+ tags_protected: Optional[Tags] = None
143
+ """Protected (read-only) flags."""
144
+
145
+ type: str
146
+ """The type of the item (file or dir). Cannot be written to."""
147
+
148
+ updated_at: str
149
+ """The date and time the object was last updated."""
150
+
151
+ name: str
152
+ """The name of the object."""
153
+
154
+ folder: str
155
+ """The full path to the folder the object is stored in."""
156
+
157
+ parent_id: Optional[str] = None
158
+ """The parent ID (a folder). Blanks means the root folder."""
159
+
160
+ external_bucket_key: Optional[str] = None
161
+ """The key in the external bucket that contains this file."""
162
+
163
+
164
+ class DeleteResult(PangeaResponseResult):
165
+ count: int
166
+ """Number of objects deleted."""
167
+
168
+
169
+ class FolderCreateRequest(APIRequestModel):
170
+ name: Optional[str] = None
171
+ """The name of an object."""
172
+
173
+ metadata: Optional[Metadata] = None
174
+ """A set of string-based key/value pairs used to provide additional data about an object."""
175
+
176
+ parent_id: Optional[str] = None
177
+ """The ID of a stored object."""
178
+
179
+ folder: Optional[str] = None
180
+ """The folder to place the folder in. Must match `parent_id` if also set."""
181
+
182
+ tags: Optional[Tags] = None
183
+ """A list of user-defined tags"""
184
+
185
+ bucket_id: Optional[str] = None
186
+ """The bucket to use, if not the default."""
187
+
188
+
189
+ class FolderCreateResult(PangeaResponseResult):
190
+ object: ItemData
191
+ """Information on the created folder."""
192
+
193
+
194
+ class GetRequest(APIRequestModel):
195
+ id: Optional[str] = None
196
+ """The ID of the object to retrieve."""
197
+
198
+ password: Optional[str] = None
199
+ """If the file was protected with a password, the password to decrypt with."""
200
+
201
+ transfer_method: Optional[TransferMethod] = None
202
+ """The requested transfer method for the file data."""
203
+
204
+ bucket_id: Optional[str] = None
205
+ """The bucket to use, if not the default."""
206
+
207
+
208
+ class GetResult(PangeaResponseResult):
209
+ object: ItemData
210
+ """File information."""
211
+
212
+ dest_url: Optional[str] = None
213
+ """A URL where the file can be downloaded from. (transfer_method: dest-url)"""
214
+
215
+
216
+ class PutRequest(APIRequestModel):
217
+ transfer_method: Optional[TransferMethod] = None
218
+ """The transfer method used to upload the file data."""
219
+
220
+ bucket_id: Optional[str] = None
221
+ """The bucket to use, if not the default."""
222
+
223
+ size: Optional[int] = None
224
+ """The size (in bytes) of the file. If the upload doesn't match, the call will fail."""
225
+
226
+ crc32c: Optional[str] = None
227
+ """The hexadecimal-encoded CRC32C hash of the file data, which will be verified by the server if provided."""
228
+
229
+ sha256: Optional[str] = None
230
+ """The SHA256 hash of the file data, which will be verified by the server if provided."""
231
+
232
+ md5: Optional[str] = None
233
+ """The hexadecimal-encoded MD5 hash of the file data, which will be verified by the server if provided."""
234
+
235
+ name: Optional[str] = None
236
+ """The name of the object to store."""
237
+
238
+ format: Optional[FileFormat] = None
239
+ """The format of the file, which will be verified by the server if provided. Uploads not matching the supplied format will be rejected."""
240
+
241
+ metadata: Optional[Metadata] = None
242
+ """A set of string-based key/value pairs used to provide additional data about an object."""
243
+
244
+ mimetype: Optional[str] = None
245
+ """The MIME type of the file, which will be verified by the server if provided. Uploads not matching the supplied MIME type will be rejected."""
246
+
247
+ parent_id: Optional[str] = None
248
+ """The parent ID of the object (a folder). Leave blank to keep in the root folder."""
249
+
250
+ folder: Optional[str] = None
251
+ """The path to the parent folder. Leave blank for the root folder. Path must resolve to `parent_id` if also set."""
252
+
253
+ password: Optional[str] = None
254
+ """An optional password to protect the file with. Downloading the file will require this password."""
255
+
256
+ password_algorithm: Optional[str] = None
257
+ """An optional password algorithm to protect the file with. See symmetric vault password_algorithm."""
258
+
259
+ sha1: Optional[str] = None
260
+ """The hexadecimal-encoded SHA1 hash of the file data, which will be verified by the server if provided."""
261
+
262
+ sha512: Optional[str] = None
263
+ """The hexadecimal-encoded SHA512 hash of the file data, which will be verified by the server if provided."""
264
+
265
+ tags: Optional[Tags] = None
266
+ """A list of user-defined tags"""
267
+
268
+
269
+ class PutResult(PangeaResponseResult):
270
+ object: ItemData
271
+
272
+
273
+ class UpdateRequest(APIRequestModel):
274
+ id: Optional[str]
275
+ """An identifier for the file to update."""
276
+
277
+ folder: Optional[str] = None
278
+ """
279
+ Set the parent (folder). Leave blank for the root folder. Path must resolve
280
+ to `parent_id` if also set.
281
+ """
282
+
283
+ add_metadata: Optional[Metadata] = None
284
+ """A list of Metadata key/values to set in the object. If a provided key exists, the value will be replaced."""
285
+
286
+ add_password: Optional[str] = None
287
+ """Protect the file with the supplied password."""
288
+
289
+ add_password_algorithm: Optional[str] = None
290
+ """The algorithm to use to password protect the file."""
291
+
292
+ add_tags: Optional[Tags] = None
293
+ """A list of Tags to add. It is not an error to provide a tag which already exists."""
294
+
295
+ name: Optional[str] = None
296
+ """Sets the object's Name."""
297
+
298
+ metadata: Optional[Metadata] = None
299
+ """Set the object's metadata."""
300
+
301
+ remove_metadata: Optional[Metadata] = None
302
+ """A list of metadata key/values to remove in the object. It is not an error for a provided key to not exist. If a provided key exists but doesn't match the provided value, it will not be removed."""
303
+
304
+ remove_password: Optional[str] = None
305
+ """Remove the supplied password from the file."""
306
+
307
+ remove_tags: Optional[Tags] = None
308
+ """A list of tags to remove. It is not an error to provide a tag which is not present."""
309
+
310
+ parent_id: Optional[str] = None
311
+ """Set the parent (folder) of the object. Can be an empty string for the root folder."""
312
+
313
+ tags: Optional[Tags] = None
314
+ """Set the object's tags."""
315
+
316
+ updated_at: Optional[str] = None
317
+ """The date and time the object was last updated. If included, the update will fail if this doesn't match the date and time of the last update for the object."""
318
+
319
+ bucket_id: Optional[str] = None
320
+ """The bucket to use, if not the default."""
321
+
322
+
323
+ class UpdateResult(PangeaResponseResult):
324
+ object: ItemData
325
+
326
+
327
+ class FilterList(APIRequestModel):
328
+ created_at: Optional[str] = None
329
+ """Only records where created_at equals this value."""
330
+
331
+ created_at__gt: Optional[str] = None
332
+ """Only records where created_at is greater than this value."""
333
+
334
+ created_at__gte: Optional[str] = None
335
+ """Only records where created_at is greater than or equal to this value."""
336
+
337
+ created_at__lt: Optional[str] = None
338
+ """Only records where created_at is less than this value."""
339
+
340
+ created_at__lte: Optional[str] = None
341
+ """Only records where created_at is less than or equal to this value."""
342
+
343
+ folder: Optional[str] = None
344
+ """Only records where the object exists in the supplied parent folder path name."""
345
+
346
+ id: Optional[str] = None
347
+ """Only records where id equals this value."""
348
+
349
+ id__in: Optional[List[str]] = None
350
+ """Only records where id equals one of the provided substrings."""
351
+
352
+ name: Optional[str] = None
353
+ """Only records where name equals this value."""
354
+
355
+ name__contains: Optional[List[str]] = None
356
+ """Only records where name includes each substring."""
357
+
358
+ name__in: Optional[List[str]] = None
359
+ """Only records where name equals one of the provided substrings."""
360
+
361
+ parent_id: Optional[str] = None
362
+ """Only records where parent_id equals this value."""
363
+
364
+ parent_id__in: Optional[List[str]] = None
365
+ """Only records where parent_id equals one of the provided substrings."""
366
+
367
+ size: Optional[int] = None
368
+ """Only records where size equals this value."""
369
+
370
+ size__gt: Optional[int] = None
371
+ """Only records where size is greater than this value."""
372
+
373
+ size__gte: Optional[int] = None
374
+ """Only records where size is greater than or equal to this value."""
375
+
376
+ size__lt: Optional[int] = None
377
+ """Only records where size is less than to this value."""
378
+
379
+ size__lte: Optional[int] = None
380
+ """Only records where size is less than or equal to this value."""
381
+
382
+ tags: Optional[List[str]] = None
383
+ """A list of tags that all must be present."""
384
+
385
+ type: Optional[str] = None
386
+ """Only records where type equals this value."""
387
+
388
+ type__contains: Optional[List[str]] = None
389
+ """Only records where type includes each substring."""
390
+
391
+ type__in: Optional[List[str]] = None
392
+ """Only records where type equals one of the provided substrings."""
393
+
394
+ updated_at: Optional[str] = None
395
+ """Only records where updated_at equals this value."""
396
+
397
+ updated_at__gt: Optional[str] = None
398
+ """Only records where updated_at is greater than this value."""
399
+
400
+ updated_at__gte: Optional[str] = None
401
+ """Only records where updated_at is greater than or equal to this value."""
402
+
403
+ updated_at__lt: Optional[str] = None
404
+ """Only records where updated_at is less than this value."""
405
+
406
+ updated_at__lte: Optional[str] = None
407
+ """Only records where updated_at is less than or equal to this value."""
408
+
409
+
410
+ class ListRequest(APIRequestModel):
411
+ filter: Optional[Union[Dict[str, str], FilterList]] = None
412
+ last: Optional[str] = None
413
+ """Reflected value from a previous response to obtain the next page of results."""
414
+
415
+ order: Optional[ItemOrder] = None
416
+ """Order results asc(ending) or desc(ending)."""
417
+
418
+ order_by: Optional[ItemOrderBy] = None
419
+ """Which field to order results by."""
420
+
421
+ size: Optional[int] = None
422
+ """Maximum results to include in the response."""
423
+
424
+ include_external_bucket_key: bool = False
425
+ """If true, include the `external_bucket_key` in results."""
426
+
427
+ bucket_id: Optional[str] = None
428
+ """The bucket to use, if not the default."""
429
+
430
+
431
+ class ListResult(PangeaResponseResult):
432
+ count: int
433
+ """The total number of objects matched by the list request."""
434
+
435
+ last: Optional[str] = None
436
+ """Used to fetch the next page of the current listing when provided in a repeated request's last parameter."""
437
+
438
+ objects: List[ItemData]
439
+
440
+
441
+ class GetArchiveRequest(APIRequestModel):
442
+ ids: List[str] = []
443
+ """The IDs of the objects to include in the archive. Folders include all children."""
444
+
445
+ format: Optional[ArchiveFormat] = None
446
+ """The format to use to build the archive."""
447
+
448
+ transfer_method: Optional[TransferMethod] = None
449
+ """The requested transfer method for the file data."""
450
+
451
+ bucket_id: Optional[str] = None
452
+ """The bucket to use, if not the default."""
453
+
454
+
455
+ class GetArchiveResult(PangeaResponseResult):
456
+ count: int
457
+ """Number of objects included in the archive."""
458
+
459
+ dest_url: Optional[str] = None
460
+ """A location where the archive can be downloaded from. (transfer_method: dest-url)"""
461
+
462
+ objects: List[ItemData] = []
463
+ """A list of all objects included in the archive."""
464
+
465
+
466
+ class Authenticator(PangeaResponseResult):
467
+ auth_type: AuthenticatorType
468
+ """An authentication mechanism."""
469
+
470
+ auth_context: str
471
+ """An email address, a phone number or a password to access share link."""
472
+
473
+
474
+ class ShareLinkItemBase(PangeaResponseResult):
475
+ targets: List[str] = []
476
+ """List of storage IDs."""
477
+
478
+ link_type: Optional[LinkType] = None
479
+ """Type of link."""
480
+
481
+ expires_at: Optional[str] = None
482
+ """The date and time the share link expires."""
483
+
484
+ max_access_count: Optional[int] = None
485
+ """The maximum number of times a user can be authenticated to access the share link."""
486
+
487
+ authenticators: Optional[List[Authenticator]] = None
488
+ """A list of authenticators."""
489
+
490
+ title: Optional[str] = None
491
+ """An optional title to use in accessing shares."""
492
+
493
+ message: Optional[str] = None
494
+ """An optional message to use in accessing shares."""
495
+
496
+ notify_email: Optional[str] = None
497
+ """An email address"""
498
+
499
+ tags: Optional[Tags] = None
500
+ """A list of user-defined tags"""
501
+
502
+
503
+ class ShareLinkCreateItem(ShareLinkItemBase):
504
+ pass
505
+
506
+
507
+ class ShareLinkCreateRequest(APIRequestModel):
508
+ links: List[ShareLinkCreateItem] = []
509
+ bucket_id: Optional[str] = None
510
+ """The bucket to use, if not the default."""
511
+
512
+
513
+ class ShareLinkItem(ShareLinkItemBase):
514
+ id: str
515
+ """The ID of a share link."""
516
+
517
+ access_count: int
518
+ """The number of times a user has authenticated to access the share link."""
519
+
520
+ created_at: str
521
+ """The date and time the share link was created."""
522
+
523
+ last_accessed_at: Optional[str] = None
524
+ """The date and time the share link was last accessed."""
525
+
526
+ link: Optional[str] = None
527
+ """A URL to access the file/folders shared with a link."""
528
+
529
+ bucket_id: str
530
+ """The ID of a share bucket resource."""
531
+
532
+
533
+ class ShareLinkCreateResult(PangeaResponseResult):
534
+ share_link_objects: List[ShareLinkItem] = []
535
+
536
+
537
+ class ShareLinkGetRequest(APIRequestModel):
538
+ id: str
539
+ """The ID of a share link."""
540
+
541
+
542
+ class ShareLinkGetResult(PangeaResponseResult):
543
+ share_link_object: ShareLinkItem
544
+
545
+
546
+ class FilterShareLinkList(APIRequestModel):
547
+ id: Optional[str] = None
548
+ id__contains: Optional[List[str]] = None
549
+ id__in: Optional[List[str]] = None
550
+ target: Optional[str] = None
551
+ target__contains: Optional[List[str]] = None
552
+ target__in: Optional[List[str]] = None
553
+ link_type: Optional[str] = None
554
+ link_type__contains: Optional[List[str]] = None
555
+ link_type__in: Optional[List[str]] = None
556
+ access_count: Optional[int] = None
557
+ access_count__gt: Optional[int] = None
558
+ access_count__gte: Optional[int] = None
559
+ access_count__lt: Optional[int] = None
560
+ access_count__lte: Optional[int] = None
561
+ max_access_count: Optional[int] = None
562
+ max_access_count__gt: Optional[int] = None
563
+ max_access_count__gte: Optional[int] = None
564
+ max_access_count__lt: Optional[int] = None
565
+ max_access_count__lte: Optional[int] = None
566
+ created_at: Optional[str] = None
567
+ created_at__gt: Optional[str] = None
568
+ created_at__gte: Optional[str] = None
569
+ created_at__lt: Optional[str] = None
570
+ created_at__lte: Optional[str] = None
571
+ expires_at: Optional[str] = None
572
+ expires_at__gt: Optional[str] = None
573
+ expires_at__gte: Optional[str] = None
574
+ expires_at__lt: Optional[str] = None
575
+ expires_at__lte: Optional[str] = None
576
+ last_accessed_at: Optional[str] = None
577
+ last_accessed_at__gt: Optional[str] = None
578
+ last_accessed_at__gte: Optional[str] = None
579
+ last_accessed_at__lt: Optional[str] = None
580
+ last_accessed_at__lte: Optional[str] = None
581
+ link: Optional[str] = None
582
+ link__contains: Optional[List[str]] = None
583
+ link__in: Optional[List[str]] = None
584
+ title: Optional[str] = None
585
+ title__contains: Optional[List[str]] = None
586
+ title__in: Optional[List[str]] = None
587
+ message: Optional[str] = None
588
+ message__contains: Optional[List[str]] = None
589
+ message__in: Optional[List[str]] = None
590
+ notify_email: Optional[str] = None
591
+ notify_email__contains: Optional[List[str]] = None
592
+ notify_email__in: Optional[List[str]] = None
593
+ tags: Optional[List[str]] = None
594
+
595
+
596
+ class ShareLinkListRequest(APIRequestModel):
597
+ filter: Optional[Union[FilterShareLinkList, Dict[str, str]]] = None
598
+
599
+ last: Optional[str] = None
600
+ """Reflected value from a previous response to obtain the next page of results."""
601
+
602
+ order: Optional[ItemOrder] = None
603
+ """Order results asc(ending) or desc(ending)."""
604
+
605
+ order_by: Optional[ShareLinkOrderBy] = None
606
+ """Which field to order results by."""
607
+
608
+ size: Optional[int] = None
609
+ """Maximum results to include in the response."""
610
+
611
+ bucket_id: Optional[str] = None
612
+ """The bucket to use, if not the default."""
613
+
614
+
615
+ class ShareLinkListResult(PangeaResponseResult):
616
+ count: int
617
+ """The total number of share links matched by the list request."""
618
+
619
+ last: Optional[str] = None
620
+ """Used to fetch the next page of the current listing when provided in a repeated request's last parameter."""
621
+
622
+ share_link_objects: List[ShareLinkItem] = []
623
+
624
+
625
+ class ShareLinkDeleteRequest(APIRequestModel):
626
+ ids: List[str]
627
+ bucket_id: Optional[str] = None
628
+ """The bucket to use, if not the default."""
629
+
630
+
631
+ class ShareLinkDeleteResult(PangeaResponseResult):
632
+ share_link_objects: List[ShareLinkItem] = []
633
+
634
+
635
+ class ShareLinkSendItem(APIRequestModel):
636
+ id: str
637
+ email: str
638
+
639
+
640
+ class ShareLinkSendRequest(APIRequestModel):
641
+ links: List[ShareLinkSendItem]
642
+
643
+ sender_email: str
644
+ """An email address."""
645
+
646
+ sender_name: Optional[str]
647
+ """The sender name information. Can be sender's full name for example."""
648
+
649
+
650
+ class ShareLinkSendResult(PangeaResponseResult):
651
+ share_link_objects: List[ShareLinkItem]
652
+
653
+
654
+ class Bucket(PangeaResponseResult):
655
+ id: str
656
+ """The ID of a share bucket resource."""
657
+
658
+ default: bool
659
+ """If true, is the default bucket."""
660
+
661
+ name: str
662
+ """The bucket's friendly name."""
663
+
664
+ transfer_methods: List[TransferMethod]
665
+
666
+
667
+ class BucketsResult(PangeaResponseResult):
668
+ buckets: List[Bucket]
669
+ """A list of available buckets."""
670
+
671
+
672
+ class Share(ServiceBase):
673
+ """Secure Share service client."""
674
+
675
+ service_name = "share"
676
+
677
+ def __init__(
678
+ self, token: str, config: PangeaConfig | None = None, logger_name: str = "pangea", config_id: str | None = None
679
+ ) -> None:
680
+ """
681
+ Secure Share client
682
+
683
+ Initializes a new Secure Share client.
684
+
685
+ Args:
686
+ token: Pangea API token.
687
+ config: Configuration.
688
+ logger_name: Logger name.
689
+ config_id: Configuration ID.
690
+
691
+ Examples:
692
+ config = PangeaConfig(domain="aws.us.pangea.cloud")
693
+ authz = Share(token="pangea_token", config=config)
694
+ """
695
+
696
+ super().__init__(token, config, logger_name, config_id=config_id)
697
+
698
+ def buckets(self) -> PangeaResponse[BucketsResult]:
699
+ """
700
+ Buckets
701
+
702
+ Get information on the accessible buckets.
703
+
704
+ OperationId: share_post_v1_buckets
705
+
706
+ Returns:
707
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
708
+
709
+ Examples:
710
+ response = share.buckets()
711
+ """
712
+ return self.request.post("v1/buckets", BucketsResult)
713
+
714
+ def delete(
715
+ self,
716
+ id: Optional[str] = None,
717
+ force: Optional[bool] = None,
718
+ bucket_id: Optional[str] = None,
719
+ ) -> PangeaResponse[DeleteResult]:
720
+ """
721
+ Delete
722
+
723
+ Delete object by ID or path. If both are supplied, the path must match
724
+ that of the object represented by the ID.
725
+
726
+ OperationId: share_post_v1_delete
727
+
728
+ Args:
729
+ id (str, optional): The ID of the object to delete.
730
+ force (bool, optional): If true, delete a folder even if it's not empty.
731
+ bucket_id (str, optional): The bucket to use, if not the default.
732
+
733
+ Returns:
734
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
735
+
736
+ Examples:
737
+ response = share.delete(id="pos_3djfmzg2db4c6donarecbyv5begtj2bm")
738
+ """
739
+ input = DeleteRequest(id=id, force=force, bucket_id=bucket_id)
740
+ return self.request.post("v1/delete", DeleteResult, data=input.model_dump(exclude_none=True))
741
+
742
+ def folder_create(
743
+ self,
744
+ name: Optional[str] = None,
745
+ metadata: Optional[Metadata] = None,
746
+ parent_id: Optional[str] = None,
747
+ folder: Optional[str] = None,
748
+ tags: Optional[Tags] = None,
749
+ bucket_id: Optional[str] = None,
750
+ ) -> PangeaResponse[FolderCreateResult]:
751
+ """
752
+ Create a folder
753
+
754
+ Create a folder, either by name or path and parent_id.
755
+
756
+ OperationId: share_post_v1_folder_create
757
+
758
+ Args:
759
+ name (str, optional): The name of an object.
760
+ metadata (Metadata, optional): A set of string-based key/value pairs used to provide additional data about an object.
761
+ parent_id (str, optional): The ID of a stored object.
762
+ folder (str, optional): The folder to place the folder in. Must
763
+ match `parent_id` if also set.
764
+ tags (Tags, optional): A list of user-defined tags.
765
+ bucket_id (str, optional): The bucket to use, if not the default.
766
+
767
+ Returns:
768
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
769
+
770
+ Examples:
771
+ response = share.folder_create(
772
+ metadata={
773
+ "created_by": "jim",
774
+ "priority": "medium",
775
+ },
776
+ parent_id="pos_3djfmzg2db4c6donarecbyv5begtj2bm",
777
+ folder="/",
778
+ tags=["irs_2023", "personal"],
779
+ )
780
+ """
781
+ input = FolderCreateRequest(
782
+ name=name, metadata=metadata, parent_id=parent_id, folder=folder, tags=tags, bucket_id=bucket_id
783
+ )
784
+ return self.request.post("v1/folder/create", FolderCreateResult, data=input.model_dump(exclude_none=True))
785
+
786
+ def get(
787
+ self,
788
+ id: Optional[str] = None,
789
+ transfer_method: Optional[TransferMethod] = None,
790
+ bucket_id: Optional[str] = None,
791
+ password: Optional[str] = None,
792
+ ) -> PangeaResponse[GetResult]:
793
+ """
794
+ Get an object
795
+
796
+ Get object. If both ID and Path are supplied, the call will fail if the
797
+ target object doesn't match both properties.
798
+
799
+ OperationId: share_post_v1_get
800
+
801
+ Args:
802
+ id (str, optional): The ID of the object to retrieve.
803
+ transfer_method (TransferMethod, optional): The requested transfer method for the file data.
804
+ bucket_id (str, optional): The bucket to use, if not the default.
805
+ password (str, optional): If the file was protected with a password, the password to decrypt with.
806
+
807
+ Returns:
808
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
809
+
810
+ Examples:
811
+ response = share.get(
812
+ id="pos_3djfmzg2db4c6donarecbyv5begtj2bm",
813
+ folder="/",
814
+ )
815
+ """
816
+ input = GetRequest(id=id, transfer_method=transfer_method, bucket_id=bucket_id, password=password)
817
+ return self.request.post("v1/get", GetResult, data=input.model_dump(exclude_none=True))
818
+
819
+ def get_archive(
820
+ self,
821
+ ids: List[str] = [],
822
+ format: Optional[ArchiveFormat] = None,
823
+ transfer_method: Optional[TransferMethod] = None,
824
+ bucket_id: Optional[str] = None,
825
+ ) -> PangeaResponse[GetArchiveResult]:
826
+ """
827
+ Get archive
828
+
829
+ Get an archive file of multiple objects.
830
+
831
+ OperationId: share_post_v1_get_archive
832
+
833
+ Args:
834
+ ids (List[str]): The IDs of the objects to include in the archive. Folders include all children.
835
+ format (ArchiveFormat, optional): The format to use for the built archive.
836
+ transfer_method (TransferMethod, optional): The requested transfer method for the file data.
837
+ bucket_id (str, optional): The bucket to use, if not the default.
838
+
839
+ Returns:
840
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
841
+
842
+ Examples:
843
+ response = share.get_archive(
844
+ ids=["pos_3djfmzg2db4c6donarecbyv5begtj2bm"],
845
+ )
846
+ """
847
+ if (
848
+ transfer_method is not None
849
+ and transfer_method != TransferMethod.DEST_URL
850
+ and transfer_method != TransferMethod.MULTIPART
851
+ ):
852
+ raise ValueError(f"Only {TransferMethod.DEST_URL} and {TransferMethod.MULTIPART} are supported")
853
+
854
+ input = GetArchiveRequest(ids=ids, format=format, transfer_method=transfer_method, bucket_id=bucket_id)
855
+ return self.request.post("v1/get_archive", GetArchiveResult, data=input.model_dump(exclude_none=True))
856
+
857
+ def list(
858
+ self,
859
+ filter: Optional[Union[Dict[str, str], FilterList]] = None,
860
+ last: Optional[str] = None,
861
+ order: Optional[ItemOrder] = None,
862
+ order_by: Optional[ItemOrderBy] = None,
863
+ size: Optional[int] = None,
864
+ bucket_id: Optional[str] = None,
865
+ ) -> PangeaResponse[ListResult]:
866
+ """
867
+ List
868
+
869
+ List or filter/search records.
870
+
871
+ OperationId: share_post_v1_list
872
+
873
+ Args:
874
+ filter (Union[Dict[str, str], FilterList], optional):
875
+ last (str, optional): Reflected value from a previous response to obtain the next page of results.
876
+ order (ItemOrder, optional): Order results asc(ending) or desc(ending).
877
+ order_by (ItemOrderBy, optional): Which field to order results by.
878
+ size (int, optional): Maximum results to include in the response.
879
+ bucket_id (str, optional): The bucket to use, if not the default.
880
+
881
+ Returns:
882
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
883
+
884
+ Examples:
885
+ response = share.list()
886
+ """
887
+ input = ListRequest(filter=filter, last=last, order=order, order_by=order_by, size=size, bucket_id=bucket_id)
888
+ return self.request.post("v1/list", ListResult, data=input.model_dump(exclude_none=True))
889
+
890
+ def put(
891
+ self,
892
+ file: io.BufferedReader,
893
+ name: Optional[str] = None,
894
+ folder: Optional[str] = None,
895
+ format: Optional[FileFormat] = None,
896
+ metadata: Optional[Metadata] = None,
897
+ mimetype: Optional[str] = None,
898
+ parent_id: Optional[str] = None,
899
+ tags: Optional[Tags] = None,
900
+ transfer_method: Optional[TransferMethod] = TransferMethod.POST_URL,
901
+ crc32c: Optional[str] = None,
902
+ md5: Optional[str] = None,
903
+ sha1: Optional[str] = None,
904
+ sha256: Optional[str] = None,
905
+ sha512: Optional[str] = None,
906
+ size: Optional[int] = None,
907
+ bucket_id: Optional[str] = None,
908
+ password: Optional[str] = None,
909
+ password_algorithm: Optional[str] = None,
910
+ ) -> PangeaResponse[PutResult]:
911
+ """
912
+ Upload a file
913
+
914
+ Upload a file.
915
+
916
+ OperationId: share_post_v1_put
917
+
918
+ Args:
919
+ file (io.BufferedReader):
920
+ name (str, optional): The name of the object to store.
921
+ folder (str, optional): The path to the parent folder. Leave blank
922
+ for the root folder. Path must resolve to `parent_id` if also set.
923
+ format (FileFormat, optional): The format of the file, which will be verified by the server if provided. Uploads not matching the supplied format will be rejected.
924
+ metadata (Metadata, optional): A set of string-based key/value pairs used to provide additional data about an object.
925
+ mimetype (str, optional): The MIME type of the file, which will be verified by the server if provided. Uploads not matching the supplied MIME type will be rejected.
926
+ parent_id (str, optional): The parent ID of the object (a folder). Leave blank to keep in the root folder.
927
+ tags (Tags, optional): A list of user-defined tags.
928
+ transfer_method (TransferMethod, optional): The transfer method used to upload the file data.
929
+ crc32c (str, optional): The hexadecimal-encoded CRC32C hash of the file data, which will be verified by the server if provided.
930
+ md5 (str, optional): The hexadecimal-encoded MD5 hash of the file data, which will be verified by the server if provided.
931
+ sha1 (str, optional): The hexadecimal-encoded SHA1 hash of the file data, which will be verified by the server if provided.
932
+ sha256 (str, optional): The SHA256 hash of the file data, which will be verified by the server if provided.
933
+ sha512 (str, optional): The hexadecimal-encoded SHA512 hash of the file data, which will be verified by the server if provided.
934
+ size (str, optional): The size (in bytes) of the file. If the upload doesn't match, the call will fail.
935
+ bucket_id (str, optional): The bucket to use, if not the default.
936
+ password (str, optional): An optional password to protect the file with. Downloading the file will require this password.
937
+ password_algorithm (str, optional): An optional password algorithm to protect the file with. See symmetric vault password_algorithm.
938
+ Returns:
939
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
940
+
941
+ Examples:
942
+ try:
943
+ with open("./path/to/file.pdf", "rb") as f:
944
+ response = share.put(file=f)
945
+ print(f"Response: {response.result}")
946
+ except pe.PangeaAPIException as e:
947
+ print(f"Request Error: {e.response.summary}")
948
+ for err in e.errors:
949
+ print(f"\\t{err.detail} \\n")
950
+ """
951
+ files: List[Tuple] = [("upload", (name, file, "application/octet-stream"))]
952
+
953
+ if transfer_method == TransferMethod.POST_URL:
954
+ params = get_file_upload_params(file)
955
+ crc32c = params.crc_hex
956
+ sha256 = params.sha256_hex
957
+ size = params.size
958
+ elif size is None and get_file_size(file=file) == 0:
959
+ # Needed to upload zero byte files
960
+ size = 0
961
+
962
+ input = PutRequest(
963
+ name=name,
964
+ format=format,
965
+ metadata=metadata,
966
+ mimetype=mimetype,
967
+ parent_id=parent_id,
968
+ folder=folder,
969
+ tags=tags,
970
+ transfer_method=transfer_method,
971
+ crc32c=crc32c,
972
+ md5=md5,
973
+ sha1=sha1,
974
+ sha256=sha256,
975
+ sha512=sha512,
976
+ size=size,
977
+ bucket_id=bucket_id,
978
+ password=password,
979
+ password_algorithm=password_algorithm,
980
+ )
981
+ data = input.model_dump(exclude_none=True)
982
+ return self.request.post("v1/put", PutResult, data=data, files=files)
983
+
984
+ def request_upload_url(
985
+ self,
986
+ name: Optional[str] = None,
987
+ folder: Optional[str] = None,
988
+ format: Optional[FileFormat] = None,
989
+ metadata: Optional[Metadata] = None,
990
+ mimetype: Optional[str] = None,
991
+ parent_id: Optional[str] = None,
992
+ tags: Optional[Tags] = None,
993
+ transfer_method: Optional[TransferMethod] = TransferMethod.PUT_URL,
994
+ md5: Optional[str] = None,
995
+ sha1: Optional[str] = None,
996
+ sha512: Optional[str] = None,
997
+ crc32c: Optional[str] = None,
998
+ sha256: Optional[str] = None,
999
+ size: Optional[int] = None,
1000
+ bucket_id: Optional[str] = None,
1001
+ ) -> PangeaResponse[PutResult]:
1002
+ """
1003
+ Request upload URL
1004
+
1005
+ Request an upload URL.
1006
+
1007
+ OperationId: share_post_v1_put 2
1008
+
1009
+ Args:
1010
+ name (str, optional): The name of the object to store.
1011
+ folder (str, optional): The path to the parent folder. Leave blank
1012
+ for the root folder. Path must resolve to `parent_id` if also set.
1013
+ format (FileFormat, optional): The format of the file, which will be verified by the server if provided. Uploads not matching the supplied format will be rejected.
1014
+ metadata (Metadata, optional): A set of string-based key/value pairs used to provide additional data about an object.
1015
+ mimetype (str, optional): The MIME type of the file, which will be verified by the server if provided. Uploads not matching the supplied MIME type will be rejected.
1016
+ parent_id (str, optional): The parent ID of the object (a folder). Leave blank to keep in the root folder.
1017
+ tags (Tags, optional): A list of user-defined tags.
1018
+ transfer_method (TransferMethod, optional): The transfer method used to upload the file data.
1019
+ md5 (str, optional): The hexadecimal-encoded MD5 hash of the file data, which will be verified by the server if provided.
1020
+ sha1 (str, optional): The hexadecimal-encoded SHA1 hash of the file data, which will be verified by the server if provided.
1021
+ sha512 (str, optional): The hexadecimal-encoded SHA512 hash of the file data, which will be verified by the server if provided.
1022
+ crc32c (str, optional): The hexadecimal-encoded CRC32C hash of the file data, which will be verified by the server if provided.
1023
+ sha256 (str, optional): The SHA256 hash of the file data, which will be verified by the server if provided.
1024
+ size (str, optional): The size (in bytes) of the file. If the upload doesn't match, the call will fail.
1025
+ bucket_id (str, optional): The bucket to use, if not the default.
1026
+
1027
+ Returns:
1028
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
1029
+
1030
+ Examples:
1031
+ response = share.request_upload_url(
1032
+ transfer_method=TransferMethod.POST_URL,
1033
+ crc32c="515f7c32",
1034
+ sha256="c0b56b1a154697f79d27d57a3a2aad4c93849aa2239cd23048fc6f45726271cc",
1035
+ size=222089,
1036
+ metadata={
1037
+ "created_by": "jim",
1038
+ "priority": "medium",
1039
+ },
1040
+ parent_id="pos_3djfmzg2db4c6donarecbyv5begtj2bm",
1041
+ folder="/",
1042
+ tags=["irs_2023", "personal"],
1043
+ )
1044
+ """
1045
+ input = PutRequest(
1046
+ name=name,
1047
+ format=format,
1048
+ metadata=metadata,
1049
+ mimetype=mimetype,
1050
+ parent_id=parent_id,
1051
+ folder=folder,
1052
+ tags=tags,
1053
+ transfer_method=transfer_method,
1054
+ crc32c=crc32c,
1055
+ md5=md5,
1056
+ sha1=sha1,
1057
+ sha256=sha256,
1058
+ sha512=sha512,
1059
+ size=size,
1060
+ bucket_id=bucket_id,
1061
+ )
1062
+
1063
+ data = input.model_dump(exclude_none=True)
1064
+ return self.request.request_presigned_url("v1/put", PutResult, data=data)
1065
+
1066
+ def update(
1067
+ self,
1068
+ id: Optional[str] = None,
1069
+ folder: Optional[str] = None,
1070
+ add_metadata: Optional[Metadata] = None,
1071
+ remove_metadata: Optional[Metadata] = None,
1072
+ metadata: Optional[Metadata] = None,
1073
+ add_tags: Optional[Tags] = None,
1074
+ remove_tags: Optional[Tags] = None,
1075
+ tags: Optional[Tags] = None,
1076
+ parent_id: Optional[str] = None,
1077
+ updated_at: Optional[str] = None,
1078
+ bucket_id: Optional[str] = None,
1079
+ ) -> PangeaResponse[UpdateResult]:
1080
+ """
1081
+ Update a file
1082
+
1083
+ Update a file.
1084
+
1085
+ OperationId: share_post_v1_update
1086
+
1087
+ Args:
1088
+ id (str, optional): An identifier for the file to update.
1089
+ path (str, optional): Set the parent (folder). Leave blank for the
1090
+ root folder. Path must resolve to `parent_id` if also set.
1091
+ add_metadata (Metadata, optional): A list of Metadata key/values to set in the object. If a provided key exists, the value will be replaced.
1092
+ remove_metadata (Metadata, optional): A list of Metadata key/values to remove in the object. It is not an error for a provided key to not exist. If a provided key exists but doesn't match the provided value, it will not be removed.
1093
+ metadata (Metadata, optional): Set the object's Metadata.
1094
+ add_tags (Tags, optional): A list of Tags to add. It is not an error to provide a tag which already exists.
1095
+ remove_tags (Tags, optional): A list of Tags to remove. It is not an error to provide a tag which is not present.
1096
+ tags (Tags, optional): Set the object's Tags.
1097
+ parent_id (str, optional): Set the parent (folder) of the object.
1098
+ updated_at (str, optional): The date and time the object was last updated. If included, the update will fail if this doesn't match what's stored.
1099
+ bucket_id (str, optional): The bucket to use, if not the default.
1100
+
1101
+ Returns:
1102
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
1103
+
1104
+ Examples:
1105
+ response = share.update(
1106
+ id="pos_3djfmzg2db4c6donarecbyv5begtj2bm",
1107
+ remove_metadata={
1108
+ "created_by": "jim",
1109
+ "priority": "medium",
1110
+ },
1111
+ remove_tags=["irs_2023", "personal"],
1112
+ )
1113
+ """
1114
+ input = UpdateRequest(
1115
+ id=id,
1116
+ folder=folder,
1117
+ add_metadata=add_metadata,
1118
+ remove_metadata=remove_metadata,
1119
+ metadata=metadata,
1120
+ add_tags=add_tags,
1121
+ remove_tags=remove_tags,
1122
+ tags=tags,
1123
+ parent_id=parent_id,
1124
+ updated_at=updated_at,
1125
+ bucket_id=bucket_id,
1126
+ )
1127
+ return self.request.post("v1/update", UpdateResult, data=input.model_dump(exclude_none=True))
1128
+
1129
+ def share_link_create(
1130
+ self, links: List[ShareLinkCreateItem], bucket_id: Optional[str] = None
1131
+ ) -> PangeaResponse[ShareLinkCreateResult]:
1132
+ """
1133
+ Create share links
1134
+
1135
+ Create a share link.
1136
+
1137
+ OperationId: share_post_v1_share_link_create
1138
+
1139
+ Args:
1140
+ links (List[ShareLinkCreateItem]):
1141
+ bucket_id (str, optional): The bucket to use, if not the default.
1142
+
1143
+ Returns:
1144
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
1145
+
1146
+ Examples:
1147
+ response = share.share_link_create(
1148
+ links=[
1149
+ {
1150
+ targets: ["pos_3djfmzg2db4c6donarecbyv5begtj2bm"],
1151
+ link_type: LinkType.DOWNLOAD,
1152
+ authenticators: [
1153
+ {
1154
+ "auth_type": AuthenticatorType.PASSWORD,
1155
+ "auth_context": "my_fav_Pa55word",
1156
+ }
1157
+ ],
1158
+ }
1159
+ ],
1160
+ )
1161
+ """
1162
+ input = ShareLinkCreateRequest(links=links, bucket_id=bucket_id)
1163
+ return self.request.post(
1164
+ "v1/share/link/create", ShareLinkCreateResult, data=input.model_dump(exclude_none=True)
1165
+ )
1166
+
1167
+ def share_link_get(self, id: str) -> PangeaResponse[ShareLinkGetResult]:
1168
+ """
1169
+ Get share link
1170
+
1171
+ Get a share link.
1172
+
1173
+ OperationId: share_post_v1_share_link_get
1174
+
1175
+ Args:
1176
+ id (str, optional): The ID of a share link.
1177
+
1178
+ Returns:
1179
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
1180
+
1181
+ Examples:
1182
+ response = share.share_link_get(
1183
+ id="psl_3djfmzg2db4c6donarecbyv5begtj2bm"
1184
+ )
1185
+ """
1186
+ input = ShareLinkGetRequest(id=id)
1187
+ return self.request.post("v1/share/link/get", ShareLinkGetResult, data=input.model_dump(exclude_none=True))
1188
+
1189
+ def share_link_list(
1190
+ self,
1191
+ filter: Optional[Union[Dict[str, str], FilterShareLinkList]] = None,
1192
+ last: Optional[str] = None,
1193
+ order: Optional[ItemOrder] = None,
1194
+ order_by: Optional[ShareLinkOrderBy] = None,
1195
+ size: Optional[int] = None,
1196
+ bucket_id: Optional[str] = None,
1197
+ ) -> PangeaResponse[ShareLinkListResult]:
1198
+ """
1199
+ List share links
1200
+
1201
+ Look up share links by filter options.
1202
+
1203
+ OperationId: share_post_v1_share_link_list
1204
+
1205
+ Args:
1206
+ filter (Union[Dict[str, str], ShareLinkListFilter], optional):
1207
+ last (str, optional): Reflected value from a previous response to obtain the next page of results.
1208
+ order (ItemOrder, optional): Order results asc(ending) or desc(ending).
1209
+ order_by (ItemOrderBy, optional): Which field to order results by.
1210
+ size (int, optional): Maximum results to include in the response.
1211
+ bucket_id (str, optional): The bucket to use, if not the default.
1212
+
1213
+ Returns:
1214
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
1215
+
1216
+ Examples:
1217
+ response = share.share_link_list()
1218
+ """
1219
+ input = ShareLinkListRequest(
1220
+ filter=filter, last=last, order=order, order_by=order_by, size=size, bucket_id=bucket_id
1221
+ )
1222
+ return self.request.post("v1/share/link/list", ShareLinkListResult, data=input.model_dump(exclude_none=True))
1223
+
1224
+ def share_link_delete(
1225
+ self, ids: List[str], bucket_id: Optional[str] = None
1226
+ ) -> PangeaResponse[ShareLinkDeleteResult]:
1227
+ """
1228
+ Delete share links
1229
+
1230
+ Delete share links.
1231
+
1232
+ OperationId: share_post_v1_share_link_delete
1233
+
1234
+ Args:
1235
+ ids (List[str]): list of the share link's id to delete
1236
+ bucket_id (str, optional): The bucket to use, if not the default
1237
+
1238
+ Returns:
1239
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
1240
+
1241
+ Examples:
1242
+ response = share.share_link_delete(
1243
+ ids=["psl_3djfmzg2db4c6donarecbyv5begtj2bm"]
1244
+ )
1245
+ """
1246
+ input = ShareLinkDeleteRequest(ids=ids, bucket_id=bucket_id)
1247
+ return self.request.post(
1248
+ "v1/share/link/delete", ShareLinkDeleteResult, data=input.model_dump(exclude_none=True)
1249
+ )
1250
+
1251
+ def share_link_send(
1252
+ self, links: List[ShareLinkSendItem], sender_email: str, sender_name: Optional[str] = None
1253
+ ) -> PangeaResponse[ShareLinkSendResult]:
1254
+ """
1255
+ Send share links
1256
+
1257
+ Send a secure share-link notification to a set of email addresses. The
1258
+ notification email will contain an Open button that the recipient can
1259
+ use to follow the secured share-link to authenticate and then access the
1260
+ shared content.
1261
+
1262
+ OperationId: share_post_v1_share_link_send
1263
+
1264
+ Args:
1265
+ sender_email: An email address.
1266
+
1267
+ Returns:
1268
+ A PangeaResponse. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/share).
1269
+
1270
+ Examples:
1271
+ response = share.share_link_send(
1272
+ links=[ShareLinkSendItem(id=link.id, email="foo@example.org")],
1273
+ sender_email="sender@example.org",
1274
+ )
1275
+ """
1276
+
1277
+ input = ShareLinkSendRequest(links=links, sender_email=sender_email, sender_name=sender_name)
1278
+ return self.request.post("v1/share/link/send", ShareLinkSendResult, data=input.model_dump(exclude_none=True))