pangea-sdk 6.1.0__py3-none-any.whl → 6.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.
Files changed (51) hide show
  1. pangea/__init__.py +9 -1
  2. pangea/asyncio/__init__.py +1 -0
  3. pangea/asyncio/file_uploader.py +4 -2
  4. pangea/asyncio/request.py +53 -18
  5. pangea/asyncio/services/__init__.py +2 -0
  6. pangea/asyncio/services/ai_guard.py +9 -12
  7. pangea/asyncio/services/audit.py +12 -7
  8. pangea/asyncio/services/authn.py +36 -25
  9. pangea/asyncio/services/authz.py +6 -6
  10. pangea/asyncio/services/base.py +4 -0
  11. pangea/asyncio/services/file_scan.py +8 -2
  12. pangea/asyncio/services/intel.py +26 -28
  13. pangea/asyncio/services/redact.py +7 -3
  14. pangea/asyncio/services/sanitize.py +5 -1
  15. pangea/asyncio/services/share.py +5 -1
  16. pangea/asyncio/services/vault.py +19 -15
  17. pangea/audit_logger.py +3 -1
  18. pangea/deep_verify.py +13 -13
  19. pangea/deprecated.py +1 -1
  20. pangea/dump_audit.py +2 -3
  21. pangea/exceptions.py +8 -5
  22. pangea/file_uploader.py +4 -0
  23. pangea/request.py +64 -48
  24. pangea/response.py +21 -18
  25. pangea/services/__init__.py +2 -0
  26. pangea/services/ai_guard.py +35 -24
  27. pangea/services/audit/audit.py +16 -13
  28. pangea/services/audit/models.py +71 -34
  29. pangea/services/audit/signing.py +1 -1
  30. pangea/services/audit/util.py +10 -10
  31. pangea/services/authn/authn.py +36 -25
  32. pangea/services/authn/models.py +10 -56
  33. pangea/services/authz.py +10 -6
  34. pangea/services/base.py +7 -4
  35. pangea/services/embargo.py +6 -0
  36. pangea/services/file_scan.py +8 -2
  37. pangea/services/intel.py +36 -19
  38. pangea/services/redact.py +7 -3
  39. pangea/services/sanitize.py +5 -1
  40. pangea/services/share/share.py +13 -7
  41. pangea/services/vault/models/asymmetric.py +4 -0
  42. pangea/services/vault/models/common.py +4 -0
  43. pangea/services/vault/models/symmetric.py +4 -0
  44. pangea/services/vault/vault.py +17 -19
  45. pangea/tools.py +13 -9
  46. pangea/utils.py +3 -5
  47. pangea/verify_audit.py +23 -27
  48. {pangea_sdk-6.1.0.dist-info → pangea_sdk-6.2.0.dist-info}/METADATA +36 -17
  49. pangea_sdk-6.2.0.dist-info/RECORD +60 -0
  50. {pangea_sdk-6.1.0.dist-info → pangea_sdk-6.2.0.dist-info}/WHEEL +1 -1
  51. pangea_sdk-6.1.0.dist-info/RECORD +0 -60
@@ -1,5 +1,11 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Use `list` instead of `List`.
5
+ # ruff: noqa: UP006, UP035
6
+
7
+ from __future__ import annotations
8
+
3
9
  from typing import Any, Dict, List
4
10
 
5
11
  from pangea.response import APIRequestModel, APIResponseModel, PangeaResponse, PangeaResponseResult
@@ -1,5 +1,11 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Use `list` instead of `List`.
5
+ # ruff: noqa: UP006, UP035
6
+
7
+ from __future__ import annotations
8
+
3
9
  import io
4
10
  import logging
5
11
  from typing import Dict, List, Optional, Tuple
@@ -52,7 +58,7 @@ class FileScan(ServiceBase):
52
58
  """FileScan service client.
53
59
 
54
60
  Provides methods to interact with Pangea FileScan Service:
55
- https://pangea.cloud/docs/api/embargo
61
+ https://pangea.cloud/docs/api/file-scan
56
62
 
57
63
  The following information is needed:
58
64
  PANGEA_TOKEN - service token which can be found on the Pangea User
@@ -133,7 +139,7 @@ class FileScan(ServiceBase):
133
139
  files: Optional[List[Tuple]] = None
134
140
  if file or file_path:
135
141
  if file_path:
136
- file = open(file_path, "rb")
142
+ file = open(file_path, "rb") # noqa: SIM115
137
143
  if transfer_method == TransferMethod.POST_URL:
138
144
  params = get_file_upload_params(file) # type: ignore[arg-type]
139
145
  crc = params.crc_hex
pangea/services/intel.py CHANGED
@@ -1,10 +1,14 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Use `list` instead of `List`.
5
+ # ruff: noqa: UP006, UP035
6
+
3
7
  from __future__ import annotations
4
8
 
5
9
  import enum
6
10
  import hashlib
7
- from typing import Dict, List, Optional
11
+ from typing import Dict, List, Literal, Optional
8
12
 
9
13
  from pangea.exceptions import PangeaException
10
14
  from pangea.response import APIRequestModel, PangeaResponse, PangeaResponseResult
@@ -61,8 +65,20 @@ class FileReputationBulkRequest(APIRequestModel):
61
65
  hash_type (str): Type of hash, can be "sha256", "sha" or "md5"
62
66
  """
63
67
 
64
- hashes: List[str]
65
- hash_type: str
68
+ hashes: list[str]
69
+ """The hash of the file to be looked up"""
70
+
71
+ hash_type: Literal["sha256", "sha", "md5"]
72
+ """One of "sha256", "sha", "md5"."""
73
+
74
+ verbose: Optional[bool] = None
75
+ """Echo the API parameters in the response"""
76
+
77
+ raw: Optional[bool] = None
78
+ """Include raw data from this provider"""
79
+
80
+ provider: Optional[Literal["reversinglabs", "crowdstrike"]] = None
81
+ """Use reputation data from this provider"""
66
82
 
67
83
 
68
84
  class FileReputationData(IntelReputationData):
@@ -356,7 +372,8 @@ class DomainWhoIsRequest(DomainCommonRequest):
356
372
  Domain whois request data
357
373
  """
358
374
 
359
- pass
375
+ domain: str
376
+ """The domain to query."""
360
377
 
361
378
 
362
379
  class DomainWhoIsData(PangeaResponseResult):
@@ -530,11 +547,11 @@ class FileIntel(ServiceBase):
530
547
 
531
548
  def hash_reputation_bulk(
532
549
  self,
533
- hashes: List[str],
534
- hash_type: str,
535
- provider: Optional[str] = None,
536
- verbose: Optional[bool] = None,
537
- raw: Optional[bool] = None,
550
+ hashes: list[str],
551
+ hash_type: Literal["sha256", "sha", "md5"],
552
+ provider: Literal["reversinglabs", "crowdstrike"] | None = None,
553
+ verbose: bool | None = None,
554
+ raw: bool | None = None,
538
555
  ) -> PangeaResponse[FileReputationBulkResult]:
539
556
  """
540
557
  Reputation check V2
@@ -562,7 +579,7 @@ class FileIntel(ServiceBase):
562
579
  provider="reversinglabs",
563
580
  )
564
581
  """
565
- input = FileReputationBulkRequest( # type: ignore[call-arg]
582
+ input = FileReputationBulkRequest(
566
583
  hashes=hashes, hash_type=hash_type, verbose=verbose, raw=raw, provider=provider
567
584
  )
568
585
  return self.request.post("v2/reputation", FileReputationBulkResult, data=input.model_dump(exclude_none=True))
@@ -610,10 +627,10 @@ class FileIntel(ServiceBase):
610
627
 
611
628
  def filepath_reputation_bulk(
612
629
  self,
613
- filepaths: List[str],
614
- provider: Optional[str] = None,
615
- verbose: Optional[bool] = None,
616
- raw: Optional[bool] = None,
630
+ filepaths: list[str],
631
+ provider: Literal["reversinglabs", "crowdstrike"] | None = None,
632
+ verbose: bool | None = None,
633
+ raw: bool | None = None,
617
634
  ) -> PangeaResponse[FileReputationBulkResult]:
618
635
  """
619
636
  Reputation, from filepath V2
@@ -624,10 +641,10 @@ class FileIntel(ServiceBase):
624
641
  OperationId: file_intel_post_v2_reputation
625
642
 
626
643
  Args:
627
- filepaths (List[str]): The path list to the files to be looked up
628
- provider (str, optional): Use reputation data from these providers: "reversinglabs" or "crowdstrike"
629
- verbose (bool, optional): Echo the API parameters in the response
630
- raw (bool, optional): Include raw data from this provider
644
+ filepaths: The path list to the files to be looked up
645
+ provider: Use reputation data from these providers: "reversinglabs" or "crowdstrike"
646
+ verbose: Echo the API parameters in the response
647
+ raw: Include raw data from this provider
631
648
 
632
649
  Raises:
633
650
  PangeaAPIException: If an API Error happens
@@ -777,7 +794,7 @@ class DomainIntel(ServiceBase):
777
794
  provider="whoisxml",
778
795
  )
779
796
  """
780
- input = DomainWhoIsRequest(domain=domain, verbose=verbose, provider=provider, raw=raw) # type: ignore[call-arg]
797
+ input = DomainWhoIsRequest(domain=domain, verbose=verbose, provider=provider, raw=raw)
781
798
  return self.request.post("v1/whois", DomainWhoIsResult, data=input.model_dump(exclude_none=True))
782
799
 
783
800
 
pangea/services/redact.py CHANGED
@@ -1,5 +1,9 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Use `list` instead of `List`.
5
+ # ruff: noqa: UP006, UP035
6
+
3
7
  from __future__ import annotations
4
8
 
5
9
  import enum
@@ -276,7 +280,7 @@ class Redact(ServiceBase):
276
280
  Returns:
277
281
  Pangea Response with redacted text in the response.result property,
278
282
  available response fields can be found in our
279
- [API Documentation](https://pangea.cloud/docs/api/redact#redact).
283
+ [API Documentation](https://pangea.cloud/docs/api/redact#redact-post).
280
284
 
281
285
  Examples:
282
286
  response = redact.redact(text="Jenny Jenny... 555-867-5309")
@@ -335,7 +339,7 @@ class Redact(ServiceBase):
335
339
  Returns:
336
340
  Pangea Response with redacted data in the response.result field,
337
341
  available response fields can be found in our
338
- [API Documentation](https://pangea.cloud/docs/api/redact#redact-structured)
342
+ [API Documentation](https://pangea.cloud/docs/api/redact#redact-structured-post)
339
343
 
340
344
  Examples:
341
345
  data = {
@@ -378,7 +382,7 @@ class Redact(ServiceBase):
378
382
  Returns:
379
383
  Pangea Response with redacted data in the response.result field,
380
384
  available response fields can be found in our
381
- [API Documentation](https://pangea.cloud/docs/api/redact#unredact)
385
+ [API Documentation](https://pangea.cloud/docs/api/redact#unredact-post)
382
386
  """
383
387
  input = UnredactRequest(redacted_data=redacted_data, fpe_context=fpe_context)
384
388
  return self.request.post("v1/unredact", UnredactResult, data=input.model_dump(exclude_none=True))
@@ -1,5 +1,9 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Use `list` instead of `List`.
5
+ # ruff: noqa: UP006, UP035
6
+
3
7
  from __future__ import annotations
4
8
 
5
9
  import io
@@ -267,7 +271,7 @@ class Sanitize(ServiceBase):
267
271
  files: Optional[List[Tuple]] = None
268
272
  if file or file_path:
269
273
  if file_path:
270
- file = open(file_path, "rb")
274
+ file = open(file_path, "rb") # noqa: SIM115
271
275
  if (
272
276
  transfer_method == TransferMethod.POST_URL
273
277
  and file
@@ -1,10 +1,16 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Use `list` instead of `List`.
5
+ # ruff: noqa: UP006, UP035
6
+
3
7
  from __future__ import annotations
4
8
 
5
9
  import enum
6
10
  import io
7
- from typing import Dict, List, NewType, Optional, Tuple, Union
11
+ from typing import Dict, List, Optional, Tuple, Union
12
+
13
+ from pydantic import RootModel
8
14
 
9
15
  from pangea.config import PangeaConfig
10
16
  from pangea.response import APIRequestModel, PangeaResponse, PangeaResponseResult, TransferMethod
@@ -12,8 +18,8 @@ from pangea.services.base import ServiceBase
12
18
  from pangea.services.share.file_format import FileFormat
13
19
  from pangea.utils import get_file_size, get_file_upload_params
14
20
 
15
- Metadata = NewType("Metadata", Dict[str, str])
16
- Tags = NewType("Tags", List[str])
21
+ Metadata = RootModel[dict[str, str]]
22
+ Tags = RootModel[list[str]]
17
23
 
18
24
 
19
25
  class ItemOrder(str, enum.Enum):
@@ -916,10 +922,10 @@ class Share(ServiceBase):
916
922
 
917
923
  def get_archive(
918
924
  self,
919
- ids: List[str] = [],
920
- format: Optional[ArchiveFormat] = None,
921
- transfer_method: Optional[TransferMethod] = None,
922
- bucket_id: Optional[str] = None,
925
+ ids: list[str],
926
+ format: ArchiveFormat | None = None,
927
+ transfer_method: TransferMethod | None = None,
928
+ bucket_id: str | None = None,
923
929
  ) -> PangeaResponse[GetArchiveResult]:
924
930
  """
925
931
  Get archive
@@ -1,5 +1,9 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Use `list` instead of `List`.
5
+ # ruff: noqa: UP006, UP035
6
+
3
7
  from __future__ import annotations
4
8
 
5
9
  from enum import Enum
@@ -1,5 +1,9 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Use `list` instead of `List`.
5
+ # ruff: noqa: UP006, UP035
6
+
3
7
  from __future__ import annotations
4
8
 
5
9
  import enum
@@ -1,5 +1,9 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Use `list` instead of `List`.
5
+ # ruff: noqa: UP006, UP035
6
+
3
7
  from __future__ import annotations
4
8
 
5
9
  from enum import Enum
@@ -2,10 +2,9 @@
2
2
  # Author: Pangea Cyber Corporation
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Any, List, Literal, Optional, Union, cast, overload
5
+ from typing import TYPE_CHECKING, Annotated, Any, Literal, Optional, Union, cast, overload
6
6
 
7
7
  from pydantic import Field, TypeAdapter
8
- from typing_extensions import Annotated
9
8
 
10
9
  from pangea.response import PangeaResponse, PangeaResponseResult
11
10
  from pangea.services.base import ServiceBase
@@ -34,7 +33,6 @@ from pangea.services.vault.models.common import (
34
33
  EncryptTransformRequest,
35
34
  EncryptTransformResult,
36
35
  ExportEncryptionAlgorithm,
37
- ExportEncryptionType,
38
36
  ExportRequest,
39
37
  ExportResult,
40
38
  Folder,
@@ -98,7 +96,7 @@ vault_item_adapter: TypeAdapter[VaultItem] = TypeAdapter(VaultItem)
98
96
 
99
97
 
100
98
  class GetBulkResponse(PangeaResponseResult):
101
- items: List[VaultItem]
99
+ items: list[VaultItem]
102
100
 
103
101
 
104
102
  class Vault(ServiceBase):
@@ -164,7 +162,7 @@ class Vault(ServiceBase):
164
162
  Returns:
165
163
  A PangeaResponse where the id of the deleted secret or key
166
164
  is returned in the response.result field.
167
- Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault#delete).
165
+ Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault/v1-general#/v1/delete-post).
168
166
 
169
167
  Raises:
170
168
  PangeaAPIException: If an API Error happens
@@ -197,7 +195,7 @@ class Vault(ServiceBase):
197
195
  Returns:
198
196
  A PangeaResponse where the secret or key
199
197
  is returned in the response.result field.
200
- Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault#retrieve).
198
+ Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault/v1-general#/v1/get-post).
201
199
 
202
200
  Raises:
203
201
  PangeaAPIException: If an API Error happens
@@ -285,7 +283,7 @@ class Vault(ServiceBase):
285
283
  Returns:
286
284
  A PangeaResponse where a list of secrets or keys
287
285
  is returned in the response.result field.
288
- Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault#list).
286
+ Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault/v1-general#/v1/list-post).
289
287
 
290
288
  Examples:
291
289
  response = vault.list(
@@ -344,7 +342,7 @@ class Vault(ServiceBase):
344
342
  Returns:
345
343
  A PangeaResponse where the item ID is returned in the
346
344
  response.result field. Available response fields can be found in our
347
- [API documentation](https://pangea.cloud/docs/api/vault#update).
345
+ [API documentation](https://pangea.cloud/docs/api/vault/v1-general#/v1/update-post).
348
346
 
349
347
  Raises:
350
348
  PangeaAPIException: If an API Error happens
@@ -1679,7 +1677,7 @@ class Vault(ServiceBase):
1679
1677
  Returns:
1680
1678
  A PangeaResponse where the encrypted message in base64 is returned
1681
1679
  in the response.result field. Available response fields can be found
1682
- in our [API documentation](https://pangea.cloud/docs/api/vault#encrypt).
1680
+ in our [API documentation](https://pangea.cloud/docs/api/vault/v1-keys#/v1/key/encrypt-post).
1683
1681
 
1684
1682
  Raises:
1685
1683
  PangeaAPIException: If an API Error happens
@@ -1715,7 +1713,7 @@ class Vault(ServiceBase):
1715
1713
 
1716
1714
  Returns:
1717
1715
  A PangeaResponse where the decrypted message in base64 is returned
1718
- in the response.result field. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault#decrypt).
1716
+ in the response.result field. Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault/v1-keys#/v1/key/decrypt-post).
1719
1717
 
1720
1718
  Raises:
1721
1719
  PangeaAPIException: If an API Error happens
@@ -1749,7 +1747,7 @@ class Vault(ServiceBase):
1749
1747
  Returns:
1750
1748
  A PangeaResponse where the signature of the message in base64 is
1751
1749
  returned in the response.result field. Available response fields can
1752
- be found in our [API documentation](https://pangea.cloud/docs/api/vault#sign).
1750
+ be found in our [API documentation](https://pangea.cloud/docs/api/vault/v1-keys#/v1/key/sign-post).
1753
1751
 
1754
1752
  Raises:
1755
1753
  PangeaAPIException: If an API Error happens
@@ -1785,7 +1783,7 @@ class Vault(ServiceBase):
1785
1783
  Returns:
1786
1784
  A PangeaResponse where the signature is valid
1787
1785
  is returned in the response.result field.
1788
- Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault#verify).
1786
+ Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault/v1-keys#/v1/key/verify-post).
1789
1787
 
1790
1788
  Examples:
1791
1789
  response = vault.verify(
@@ -1823,7 +1821,7 @@ class Vault(ServiceBase):
1823
1821
  Returns:
1824
1822
  A PangeaResponse where the signature is valid
1825
1823
  is returned in the response.result field.
1826
- Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault#verify-jwt).
1824
+ Available response fields can be found in our [API documentation](https://pangea.cloud/docs/api/vault/v1-jwt#/v1/key/verify/jwt-post).
1827
1825
 
1828
1826
  Examples:
1829
1827
  response = vault.jwt_verify(jws="ewogICJhbGciO...")
@@ -1848,7 +1846,7 @@ class Vault(ServiceBase):
1848
1846
  Returns:
1849
1847
  A PangeaResponse where the signed JSON Web Token (JWS) is returned
1850
1848
  in the response.result field. Available response fields can be found
1851
- in our [API documentation](https://pangea.cloud/docs/api/vault#sign-a-jwt).
1849
+ in our [API documentation](https://pangea.cloud/docs/api/vault/v1-jwt#/v1/key/sign/jwt-post).
1852
1850
 
1853
1851
  Examples:
1854
1852
  response = vault.jwt_sign(
@@ -1878,7 +1876,7 @@ class Vault(ServiceBase):
1878
1876
  Returns:
1879
1877
  A PangeaResponse where the JSON Web Key Set (JWKS) object is
1880
1878
  returned in the response.result field. Available response fields can
1881
- be found in our [API documentation](https://pangea.cloud/docs/api/vault#retrieve-jwk).
1879
+ be found in our [API documentation](https://pangea.cloud/docs/api/vault/v1-jwt#/v1/get/jwk-post).
1882
1880
 
1883
1881
  Examples:
1884
1882
  response = vault.jwk_get("pvi_p6g5i3gtbvqvc3u6zugab6qs6r63tqf5")
@@ -1910,7 +1908,7 @@ class Vault(ServiceBase):
1910
1908
  Returns:
1911
1909
  A PangeaResponse where the state change object is returned in the
1912
1910
  response.result field. Available response fields can be found in our
1913
- [API documentation](https://pangea.cloud/docs/api/vault#change-state).
1911
+ [API documentation](https://pangea.cloud/docs/api/vault/v1-general#/v1/state/change-post).
1914
1912
 
1915
1913
  Raises:
1916
1914
  PangeaAPIException: If an API Error happens
@@ -2011,7 +2009,7 @@ class Vault(ServiceBase):
2011
2009
  Returns:
2012
2010
  A `PangeaResponse` where the encrypted object is returned in the
2013
2011
  `response.result` field. Available response fields can be found in
2014
- our [API documentation](https://pangea.cloud/docs/api/vault#encrypt-structured).
2012
+ our [API documentation](https://pangea.cloud/docs/api/vault/v1-keys#/v1/key/encrypt/structured-post).
2015
2013
 
2016
2014
  Raises:
2017
2015
  PangeaAPIException: If an API error happens.
@@ -2067,7 +2065,7 @@ class Vault(ServiceBase):
2067
2065
  Returns:
2068
2066
  A `PangeaResponse` where the decrypted object is returned in the
2069
2067
  `response.result` field. Available response fields can be found in
2070
- our [API documentation](https://pangea.cloud/docs/api/vault#decrypt-structured).
2068
+ our [API documentation](https://pangea.cloud/docs/api/vault/v1-keys#/v1/key/decrypt/structured-post).
2071
2069
 
2072
2070
  Examples:
2073
2071
  data = {"field1": [1, 2, "kxcbC9E9IlgVaSCChPWUMgUC3ko=", "6FfI/LCzatLRLNAc8SuBK/TDnGxp"], "field2": "data2"}
@@ -2211,7 +2209,7 @@ class Vault(ServiceBase):
2211
2209
  Returns:
2212
2210
  A `PangeaResponse` where the exported key is returned in the
2213
2211
  `response.result` field. Available response fields can be found in
2214
- our [API documentation](https://pangea.cloud/docs/api/vault#export).
2212
+ our [API documentation](https://pangea.cloud/docs/api/vault/v1-general#/v1/export-post).
2215
2213
 
2216
2214
  Raises:
2217
2215
  PangeaAPIException: If an API error happens.
pangea/tools.py CHANGED
@@ -1,5 +1,6 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+ from __future__ import annotations
3
4
 
4
5
  import enum
5
6
  import io
@@ -7,9 +8,10 @@ import json
7
8
  import logging
8
9
  import os
9
10
  import sys
11
+ from collections.abc import Iterator
10
12
  from datetime import datetime, timezone
11
13
  from logging.handlers import TimedRotatingFileHandler
12
- from typing import Dict, Iterator, List, Optional
14
+ from typing import Optional
13
15
 
14
16
  from pangea.config import PangeaConfig
15
17
  from pangea.exceptions import PangeaException
@@ -17,6 +19,8 @@ from pangea.services import Audit
17
19
 
18
20
 
19
21
  class TestEnvironment(str, enum.Enum):
22
+ __test__ = False
23
+
20
24
  DEVELOP = "DEV"
21
25
  LIVE = "LVE"
22
26
  STAGING = "STG"
@@ -28,15 +32,15 @@ class TestEnvironment(str, enum.Enum):
28
32
  return str(self.value)
29
33
 
30
34
 
31
- class Root(Dict):
35
+ class Root(dict):
32
36
  size: int
33
37
  tree_name: str
34
38
 
35
39
 
36
- class Event(Dict):
40
+ class Event(dict):
37
41
  membership_proof: str
38
42
  leaf_index: Optional[int]
39
- event: Dict
43
+ event: dict
40
44
  hash: str
41
45
  tree_size: Optional[int]
42
46
 
@@ -68,7 +72,7 @@ def exit_with_error(message: str):
68
72
  sys.exit(1)
69
73
 
70
74
 
71
- def file_events(root_hashes: Dict[int, str], f: io.TextIOWrapper) -> Iterator[Event]:
75
+ def file_events(root_hashes: dict[int, str], f: io.TextIOWrapper) -> Iterator[Event]:
72
76
  """
73
77
  Reads a file containing Events in JSON format with the following fields:
74
78
  - membership_proof: str
@@ -111,8 +115,8 @@ def make_aware_datetime(d: datetime) -> datetime:
111
115
  return d
112
116
 
113
117
 
114
- def filter_deep_none(data: Dict) -> Dict:
115
- return {k: v if not isinstance(v, Dict) else filter_deep_none(v) for k, v in data.items() if v is not None}
118
+ def filter_deep_none(data: dict) -> dict:
119
+ return {k: v if not isinstance(v, dict) else filter_deep_none(v) for k, v in data.items() if v is not None}
116
120
 
117
121
 
118
122
  def _load_env_var(env_var_name: str) -> str:
@@ -183,7 +187,7 @@ class SequenceFollower:
183
187
  self.numbers.remove(min_val)
184
188
  min_val += 1
185
189
 
186
- def holes(self) -> List[int]:
190
+ def holes(self) -> list[int]:
187
191
  if not self.numbers:
188
192
  return []
189
193
 
@@ -192,7 +196,7 @@ class SequenceFollower:
192
196
  return [val for val in range(min_val, max_val) if val not in self.numbers]
193
197
 
194
198
 
195
- loggers: Dict[str, bool] = {}
199
+ loggers: dict[str, bool] = {}
196
200
 
197
201
 
198
202
  def logger_set_pangea_config(logger_name: str, level=logging.DEBUG):
pangea/utils.py CHANGED
@@ -60,7 +60,7 @@ def canonicalize(data: dict) -> str:
60
60
  return json.dumps(
61
61
  data, ensure_ascii=False, allow_nan=False, separators=(",", ":"), sort_keys=True, default=default_encoder
62
62
  )
63
- elif isinstance(data, datetime.datetime) or isinstance(data, datetime.date):
63
+ elif isinstance(data, (datetime.datetime, datetime.date)):
64
64
  return format_datetime(data)
65
65
  else:
66
66
  return str(data)
@@ -151,10 +151,8 @@ def get_crc32c(data: str) -> str:
151
151
 
152
152
 
153
153
  def hash_256_filepath(filepath: str) -> str:
154
- data = open(filepath, "rb")
155
- hash = sha256(data.read()).hexdigest()
156
- data.close()
157
- return hash
154
+ with open(filepath, "rb") as data:
155
+ return sha256(data.read()).hexdigest()
158
156
 
159
157
 
160
158
  def get_prefix(hash: str, len: int = 5):