pangea-sdk 3.8.0b1__tar.gz → 5.3.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/PKG-INFO +43 -35
  2. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/README.md +31 -15
  3. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/__init__.py +1 -1
  4. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/file_uploader.py +1 -1
  5. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/request.py +49 -31
  6. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/services/__init__.py +2 -0
  7. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/services/audit.py +192 -31
  8. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/services/authn.py +187 -109
  9. pangea_sdk-5.3.0/pangea/asyncio/services/authz.py +285 -0
  10. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/services/base.py +21 -2
  11. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/services/embargo.py +2 -2
  12. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/services/file_scan.py +24 -9
  13. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/services/intel.py +108 -34
  14. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/services/redact.py +72 -4
  15. pangea_sdk-5.3.0/pangea/asyncio/services/sanitize.py +217 -0
  16. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/services/share.py +246 -73
  17. pangea_sdk-5.3.0/pangea/asyncio/services/vault.py +2240 -0
  18. pangea_sdk-5.3.0/pangea/crypto/rsa.py +135 -0
  19. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/deep_verify.py +7 -1
  20. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/dump_audit.py +9 -8
  21. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/request.py +83 -59
  22. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/response.py +49 -31
  23. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/__init__.py +2 -0
  24. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/audit/audit.py +205 -42
  25. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/audit/models.py +56 -8
  26. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/audit/signing.py +6 -5
  27. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/audit/util.py +3 -3
  28. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/authn/authn.py +140 -70
  29. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/authn/models.py +167 -11
  30. pangea_sdk-5.3.0/pangea/services/authz.py +400 -0
  31. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/base.py +39 -8
  32. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/embargo.py +2 -2
  33. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/file_scan.py +32 -15
  34. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/intel.py +157 -32
  35. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/redact.py +152 -4
  36. pangea_sdk-5.3.0/pangea/services/sanitize.py +388 -0
  37. pangea_sdk-5.3.0/pangea/services/share/share.py +1440 -0
  38. pangea_sdk-5.3.0/pangea/services/vault/models/asymmetric.py +169 -0
  39. pangea_sdk-5.3.0/pangea/services/vault/models/common.py +727 -0
  40. pangea_sdk-5.3.0/pangea/services/vault/models/keys.py +94 -0
  41. pangea_sdk-5.3.0/pangea/services/vault/models/secret.py +48 -0
  42. pangea_sdk-5.3.0/pangea/services/vault/models/symmetric.py +109 -0
  43. pangea_sdk-5.3.0/pangea/services/vault/vault.py +2237 -0
  44. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/tools.py +6 -7
  45. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/utils.py +16 -27
  46. pangea_sdk-5.3.0/pangea/verify_audit.py +519 -0
  47. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pyproject.toml +32 -16
  48. pangea_sdk-3.8.0b1/pangea/asyncio/services/vault.py +0 -1280
  49. pangea_sdk-3.8.0b1/pangea/services/share/share.py +0 -864
  50. pangea_sdk-3.8.0b1/pangea/services/vault/models/asymmetric.py +0 -67
  51. pangea_sdk-3.8.0b1/pangea/services/vault/models/common.py +0 -429
  52. pangea_sdk-3.8.0b1/pangea/services/vault/models/secret.py +0 -24
  53. pangea_sdk-3.8.0b1/pangea/services/vault/models/symmetric.py +0 -63
  54. pangea_sdk-3.8.0b1/pangea/services/vault/vault.py +0 -1296
  55. pangea_sdk-3.8.0b1/pangea/verify_audit.py +0 -332
  56. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/asyncio/__init__.py +0 -0
  57. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/audit_logger.py +0 -0
  58. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/config.py +0 -0
  59. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/deprecated.py +0 -0
  60. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/exceptions.py +0 -0
  61. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/file_uploader.py +0 -0
  62. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/py.typed +0 -0
  63. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/audit/exceptions.py +0 -0
  64. {pangea_sdk-3.8.0b1 → pangea_sdk-5.3.0}/pangea/services/share/file_format.py +0 -0
@@ -1,31 +1,23 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: pangea-sdk
3
- Version: 3.8.0b1
3
+ Version: 5.3.0
4
4
  Summary: Pangea API SDK
5
- Home-page: https://pangea.cloud/docs/sdk/python/
6
5
  License: MIT
7
6
  Keywords: Pangea,SDK,Audit
8
7
  Author: Glenn Gallien
9
8
  Author-email: glenn.gallien@pangea.cloud
10
- Requires-Python: >=3.7.2,<4.0.0
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.8
14
- Classifier: Programming Language :: Python :: 3.9
15
- Classifier: Programming Language :: Python :: 3.10
16
- Classifier: Programming Language :: Python :: 3.11
9
+ Requires-Python: >=3.9
17
10
  Classifier: Topic :: Software Development
18
11
  Classifier: Topic :: Software Development :: Libraries
19
- Requires-Dist: aiohttp (>=3.8.6,<4.0.0)
20
- Requires-Dist: asyncio (>=3.4.3,<4.0.0)
21
- Requires-Dist: cryptography (>=42.0.5,<43.0.0)
22
- Requires-Dist: deprecated (>=1.2.14,<2.0.0)
23
- Requires-Dist: google-crc32c (>=1.5.0,<2.0.0)
24
- Requires-Dist: pydantic (>=1.10.14,<2.0.0)
25
- Requires-Dist: python-dateutil (>=2.9.0,<3.0.0)
26
- Requires-Dist: requests (>=2.31.0,<3.0.0)
27
- Requires-Dist: requests-toolbelt (>=1.0.0,<2.0.0)
28
- Project-URL: Repository, https://github.com/pangeacyber/pangea-python/tree/main/packages/pangea-sdk
12
+ Requires-Dist: aiohttp
13
+ Requires-Dist: cryptography
14
+ Requires-Dist: deprecated
15
+ Requires-Dist: google-crc32c
16
+ Requires-Dist: pydantic
17
+ Requires-Dist: python-dateutil
18
+ Requires-Dist: requests
19
+ Requires-Dist: requests-toolbelt
20
+ Requires-Dist: typing-extensions
29
21
  Description-Content-Type: text/markdown
30
22
 
31
23
  <a href="https://pangea.cloud?utm_source=github&utm_medium=python-sdk" target="_blank" rel="noopener noreferrer">
@@ -35,15 +27,17 @@ Description-Content-Type: text/markdown
35
27
  <br />
36
28
 
37
29
  [![documentation](https://img.shields.io/badge/documentation-pangea-blue?style=for-the-badge&labelColor=551B76)][Documentation]
38
- [![Slack](https://img.shields.io/badge/Slack-4A154B?style=for-the-badge&logo=slack&logoColor=white)][Slack]
30
+ [![Discourse](https://img.shields.io/badge/Discourse-4A154B?style=for-the-badge&logo=discourse&logoColor=white)][Discourse]
39
31
 
40
32
  # Pangea Python SDK
41
33
 
42
- A Python SDK for integrating with Pangea services. Supports Python v3.7 and
34
+ A Python SDK for integrating with Pangea services. Supports Python v3.9 and
43
35
  above.
44
36
 
45
37
  ## Installation
46
38
 
39
+ #### GA releases
40
+
47
41
  Via pip:
48
42
 
49
43
  ```bash
@@ -56,10 +50,33 @@ Via poetry:
56
50
  $ poetry add pangea-sdk
57
51
  ```
58
52
 
53
+ <a name="beta-releases"></a>
54
+
55
+ #### Beta releases
56
+
57
+ Pre-release versions may be available with the `b` (beta) denotation in the
58
+ version number. These releases serve to preview Beta and Early Access services
59
+ and APIs. Per Semantic Versioning, they are considered unstable and do not carry
60
+ the same compatibility guarantees as stable releases.
61
+ [Beta changelog](https://github.com/pangeacyber/pangea-python/blob/beta/CHANGELOG.md).
62
+
63
+ Via pip:
64
+
65
+ ```bash
66
+ $ pip3 install pangea-sdk==5.2.0b2
67
+ ```
68
+
69
+ Via poetry:
70
+
71
+ ```bash
72
+ $ poetry add pangea-sdk==5.2.0b2
73
+ ```
74
+
59
75
  ## Usage
60
76
 
61
77
  - [Documentation][]
62
- - [Examples][]
78
+ - [GA Examples][]
79
+ - [Beta Examples][]
63
80
 
64
81
  General usage would be to create a token for a service through the
65
82
  [Pangea Console][] and then construct an API client for that respective service.
@@ -118,16 +135,6 @@ if __name__ == "__main__":
118
135
  asyncio.run(main())
119
136
  ```
120
137
 
121
-
122
- <a name="beta-releases"></a>
123
-
124
- ## Beta releases
125
-
126
- Pre-release versions may be available with the `beta` denotation in the version
127
- number. These releases serve to preview beta services and APIs. Per Semantic
128
- Versioning, they are considered unstable and do not carry the same compatibility
129
- guarantees as stable releases.
130
-
131
138
  ## Secure Audit Log - Integrity Tools
132
139
 
133
140
  The Python Pangea SDK also includes some extra features to validate Audit Service log's integrity. Here we explain how to run them.
@@ -213,8 +220,9 @@ It accepts multiple file formats:
213
220
 
214
221
 
215
222
  [Documentation]: https://pangea.cloud/docs/sdk/python/
216
- [Examples]: https://github.com/pangeacyber/pangea-python/tree/main/examples
223
+ [GA Examples]: https://github.com/pangeacyber/pangea-python/tree/main/examples
224
+ [Beta Examples]: https://github.com/pangeacyber/pangea-python/tree/beta/examples
217
225
  [Pangea Console]: https://console.pangea.cloud/
218
- [Slack]: https://pangea.cloud/join-slack/
226
+ [Discourse]: https://l.pangea.cloud/Jd4wlGs
219
227
  [Secure Audit Log]: https://pangea.cloud/docs/audit
220
228
 
@@ -5,15 +5,17 @@
5
5
  <br />
6
6
 
7
7
  [![documentation](https://img.shields.io/badge/documentation-pangea-blue?style=for-the-badge&labelColor=551B76)][Documentation]
8
- [![Slack](https://img.shields.io/badge/Slack-4A154B?style=for-the-badge&logo=slack&logoColor=white)][Slack]
8
+ [![Discourse](https://img.shields.io/badge/Discourse-4A154B?style=for-the-badge&logo=discourse&logoColor=white)][Discourse]
9
9
 
10
10
  # Pangea Python SDK
11
11
 
12
- A Python SDK for integrating with Pangea services. Supports Python v3.7 and
12
+ A Python SDK for integrating with Pangea services. Supports Python v3.9 and
13
13
  above.
14
14
 
15
15
  ## Installation
16
16
 
17
+ #### GA releases
18
+
17
19
  Via pip:
18
20
 
19
21
  ```bash
@@ -26,10 +28,33 @@ Via poetry:
26
28
  $ poetry add pangea-sdk
27
29
  ```
28
30
 
31
+ <a name="beta-releases"></a>
32
+
33
+ #### Beta releases
34
+
35
+ Pre-release versions may be available with the `b` (beta) denotation in the
36
+ version number. These releases serve to preview Beta and Early Access services
37
+ and APIs. Per Semantic Versioning, they are considered unstable and do not carry
38
+ the same compatibility guarantees as stable releases.
39
+ [Beta changelog](https://github.com/pangeacyber/pangea-python/blob/beta/CHANGELOG.md).
40
+
41
+ Via pip:
42
+
43
+ ```bash
44
+ $ pip3 install pangea-sdk==5.2.0b2
45
+ ```
46
+
47
+ Via poetry:
48
+
49
+ ```bash
50
+ $ poetry add pangea-sdk==5.2.0b2
51
+ ```
52
+
29
53
  ## Usage
30
54
 
31
55
  - [Documentation][]
32
- - [Examples][]
56
+ - [GA Examples][]
57
+ - [Beta Examples][]
33
58
 
34
59
  General usage would be to create a token for a service through the
35
60
  [Pangea Console][] and then construct an API client for that respective service.
@@ -88,16 +113,6 @@ if __name__ == "__main__":
88
113
  asyncio.run(main())
89
114
  ```
90
115
 
91
-
92
- <a name="beta-releases"></a>
93
-
94
- ## Beta releases
95
-
96
- Pre-release versions may be available with the `beta` denotation in the version
97
- number. These releases serve to preview beta services and APIs. Per Semantic
98
- Versioning, they are considered unstable and do not carry the same compatibility
99
- guarantees as stable releases.
100
-
101
116
  ## Secure Audit Log - Integrity Tools
102
117
 
103
118
  The Python Pangea SDK also includes some extra features to validate Audit Service log's integrity. Here we explain how to run them.
@@ -183,7 +198,8 @@ It accepts multiple file formats:
183
198
 
184
199
 
185
200
  [Documentation]: https://pangea.cloud/docs/sdk/python/
186
- [Examples]: https://github.com/pangeacyber/pangea-python/tree/main/examples
201
+ [GA Examples]: https://github.com/pangeacyber/pangea-python/tree/main/examples
202
+ [Beta Examples]: https://github.com/pangeacyber/pangea-python/tree/beta/examples
187
203
  [Pangea Console]: https://console.pangea.cloud/
188
- [Slack]: https://pangea.cloud/join-slack/
204
+ [Discourse]: https://l.pangea.cloud/Jd4wlGs
189
205
  [Secure Audit Log]: https://pangea.cloud/docs/audit
@@ -1,4 +1,4 @@
1
- __version__ = "3.8.0beta1"
1
+ __version__ = "5.3.0"
2
2
 
3
3
  from pangea.asyncio.request import PangeaRequestAsync
4
4
  from pangea.config import PangeaConfig
@@ -28,7 +28,7 @@ class FileUploaderAsync:
28
28
  ) -> None:
29
29
  if transfer_method == TransferMethod.PUT_URL:
30
30
  files = [("file", ("filename", file, "application/octet-stream"))]
31
- await self._request.put_presigned_url(url=url, files=files) # type: ignore[arg-type]
31
+ await self._request.put_presigned_url(url=url, files=files)
32
32
  elif transfer_method == TransferMethod.POST_URL:
33
33
  files = [("file", ("filename", file, "application/octet-stream"))]
34
34
  await self._request.post_presigned_url(url=url, data=file_details, files=files) # type: ignore[arg-type]
@@ -1,20 +1,24 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+ from __future__ import annotations
3
4
 
4
5
  import asyncio
5
6
  import json
6
- import os
7
7
  import time
8
- from typing import Dict, List, Optional, Tuple, Type, Union
8
+ from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, Union
9
9
 
10
10
  import aiohttp
11
11
  from aiohttp import FormData
12
+ from pydantic import BaseModel
13
+ from typing_extensions import Any, TypeVar
12
14
 
13
15
  import pangea.exceptions as pe
14
16
  from pangea.request import MultipartResponse, PangeaRequestBase
15
17
  from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult, ResponseStatus, TransferMethod
16
18
  from pangea.utils import default_encoder
17
19
 
20
+ TResult = TypeVar("TResult", bound=PangeaResponseResult)
21
+
18
22
 
19
23
  class PangeaRequestAsync(PangeaRequestBase):
20
24
  """An object that makes direct calls to Pangea Service APIs.
@@ -28,12 +32,12 @@ class PangeaRequestAsync(PangeaRequestBase):
28
32
  async def post(
29
33
  self,
30
34
  endpoint: str,
31
- result_class: Type[PangeaResponseResult],
32
- data: Union[str, Dict] = {},
33
- files: List[Tuple] = [],
35
+ result_class: Type[TResult],
36
+ data: str | BaseModel | dict[str, Any] | None = None,
37
+ files: Optional[List[Tuple]] = None,
34
38
  poll_result: bool = True,
35
39
  url: Optional[str] = None,
36
- ) -> PangeaResponse:
40
+ ) -> PangeaResponse[TResult]:
37
41
  """Makes the POST call to a Pangea Service endpoint.
38
42
 
39
43
  Args:
@@ -44,6 +48,13 @@ class PangeaRequestAsync(PangeaRequestBase):
44
48
  PangeaResponse which contains the response in its entirety and
45
49
  various properties to retrieve individual fields
46
50
  """
51
+
52
+ if isinstance(data, BaseModel):
53
+ data = data.model_dump(exclude_none=True)
54
+
55
+ if data is None:
56
+ data = {}
57
+
47
58
  if url is None:
48
59
  url = self._url(endpoint)
49
60
 
@@ -91,9 +102,7 @@ class PangeaRequestAsync(PangeaRequestBase):
91
102
 
92
103
  return self._check_response(pangea_response)
93
104
 
94
- async def get(
95
- self, path: str, result_class: Type[PangeaResponseResult], check_response: bool = True
96
- ) -> PangeaResponse[Type[PangeaResponseResult]]:
105
+ async def get(self, path: str, result_class: Type[TResult], check_response: bool = True) -> PangeaResponse[TResult]:
97
106
  """Makes the GET call to a Pangea Service endpoint.
98
107
 
99
108
  Args:
@@ -110,7 +119,7 @@ class PangeaRequestAsync(PangeaRequestBase):
110
119
 
111
120
  async with self.session.get(url, headers=self._headers()) as requests_response:
112
121
  await self._check_http_errors(requests_response)
113
- pangea_response = PangeaResponse( # type: ignore[var-annotated]
122
+ pangea_response = PangeaResponse(
114
123
  requests_response, result_class=result_class, json=await requests_response.json()
115
124
  )
116
125
 
@@ -131,11 +140,11 @@ class PangeaRequestAsync(PangeaRequestBase):
131
140
  raise pe.ServiceTemporarilyUnavailable(await resp.json())
132
141
 
133
142
  async def poll_result_by_id(
134
- self, request_id: str, result_class: Union[Type[PangeaResponseResult], Type[dict]], check_response: bool = True
135
- ):
143
+ self, request_id: str, result_class: Type[TResult], check_response: bool = True
144
+ ) -> PangeaResponse[TResult]:
136
145
  path = self._get_poll_path(request_id)
137
146
  self.logger.debug(json.dumps({"service": self.service, "action": "poll_result_once", "url": path}))
138
- return await self.get(path, result_class, check_response=check_response) # type: ignore[arg-type]
147
+ return await self.get(path, result_class, check_response=check_response)
139
148
 
140
149
  async def poll_result_once(self, response: PangeaResponse, check_response: bool = True):
141
150
  request_id = response.request_id
@@ -160,7 +169,7 @@ class PangeaRequestAsync(PangeaRequestBase):
160
169
  if resp.status < 200 or resp.status >= 300:
161
170
  raise pe.PresignedUploadError(f"presigned POST failure: {resp.status}", await resp.text())
162
171
 
163
- async def put_presigned_url(self, url: str, files: List[Tuple]):
172
+ async def put_presigned_url(self, url: str, files: Sequence[Tuple]):
164
173
  # Send put request with file as body
165
174
  resp = await self._http_put(url=url, files=files)
166
175
  self.logger.debug(
@@ -173,7 +182,20 @@ class PangeaRequestAsync(PangeaRequestBase):
173
182
  if resp.status < 200 or resp.status >= 300:
174
183
  raise pe.PresignedUploadError(f"presigned PUT failure: {resp.status}", await resp.text())
175
184
 
176
- async def download_file(self, url: str, filename: Optional[str] = None) -> AttachedFile:
185
+ async def download_file(self, url: str, filename: str | None = None) -> AttachedFile:
186
+ """
187
+ Download file
188
+
189
+ Download a file from the specified URL and save it with the given
190
+ filename.
191
+
192
+ Args:
193
+ url: URL of the file to download
194
+ filename: Name to save the downloaded file as. If not provided, the
195
+ filename will be determined from the Content-Disposition header or
196
+ the URL.
197
+ """
198
+
177
199
  self.logger.debug(
178
200
  json.dumps(
179
201
  {
@@ -209,16 +231,16 @@ class PangeaRequestAsync(PangeaRequestBase):
209
231
  )
210
232
 
211
233
  return AttachedFile(filename=filename, file=await response.read(), content_type=content_type)
212
- else:
213
- raise pe.DownloadFileError(f"Failed to download file. Status: {response.status}", await response.text())
234
+ raise pe.DownloadFileError(f"Failed to download file. Status: {response.status}", await response.text())
214
235
 
215
- async def _get_pangea_json(self, reader: aiohttp.MultipartReader) -> Optional[Dict]:
236
+ async def _get_pangea_json(self, reader: aiohttp.multipart.MultipartResponseWrapper) -> Optional[Dict[str, Any]]:
216
237
  # Iterate through parts
217
238
  async for part in reader:
218
- return await part.json()
239
+ if isinstance(part, aiohttp.BodyPartReader):
240
+ return await part.json()
219
241
  return None
220
242
 
221
- async def _get_attached_files(self, reader: aiohttp.MultipartReader) -> List[AttachedFile]:
243
+ async def _get_attached_files(self, reader: aiohttp.multipart.MultipartResponseWrapper) -> List[AttachedFile]:
222
244
  files = []
223
245
  i = 0
224
246
 
@@ -229,7 +251,7 @@ class PangeaRequestAsync(PangeaRequestBase):
229
251
  if name is None:
230
252
  name = f"default_file_name_{i}"
231
253
  i += 1
232
- files.append(AttachedFile(name, await part.read(), content_type))
254
+ files.append(AttachedFile(name, await part.read(), content_type)) # type: ignore[union-attr]
233
255
 
234
256
  return files
235
257
 
@@ -237,13 +259,12 @@ class PangeaRequestAsync(PangeaRequestBase):
237
259
  # Parse the multipart response
238
260
  multipart_reader = aiohttp.MultipartReader.from_response(resp)
239
261
 
240
- pangea_json = await self._get_pangea_json(multipart_reader) # type: ignore[arg-type]
262
+ pangea_json = await self._get_pangea_json(multipart_reader)
241
263
  self.logger.debug(
242
264
  json.dumps({"service": self.service, "action": "multipart response", "response": pangea_json})
243
265
  )
244
266
 
245
- multipart_reader = multipart_reader.__aiter__()
246
- attached_files = await self._get_attached_files(multipart_reader) # type: ignore[arg-type]
267
+ attached_files = await self._get_attached_files(multipart_reader)
247
268
  return MultipartResponse(pangea_json, attached_files) # type: ignore[arg-type]
248
269
 
249
270
  async def _http_post(
@@ -251,7 +272,7 @@ class PangeaRequestAsync(PangeaRequestBase):
251
272
  url: str,
252
273
  headers: Dict = {},
253
274
  data: Union[str, Dict] = {},
254
- files: List[Tuple] = [],
275
+ files: Optional[List[Tuple]] = [],
255
276
  presigned_url_post: bool = False,
256
277
  ) -> aiohttp.ClientResponse:
257
278
  if files:
@@ -276,7 +297,7 @@ class PangeaRequestAsync(PangeaRequestBase):
276
297
  async def _http_put(
277
298
  self,
278
299
  url: str,
279
- files: List[Tuple],
300
+ files: Sequence[Tuple],
280
301
  headers: Dict = {},
281
302
  ) -> aiohttp.ClientResponse:
282
303
  self.logger.debug(
@@ -328,9 +349,7 @@ class PangeaRequestAsync(PangeaRequestBase):
328
349
  # Receive 202
329
350
  return await self._poll_presigned_url(accepted_exception.response)
330
351
 
331
- async def _poll_presigned_url(
332
- self, response: PangeaResponse[Type[PangeaResponseResult]]
333
- ) -> PangeaResponse[Type[PangeaResponseResult]]:
352
+ async def _poll_presigned_url(self, response: PangeaResponse[TResult]) -> PangeaResponse[TResult]:
334
353
  if response.http_status != 202:
335
354
  raise AttributeError("Response should be 202")
336
355
 
@@ -373,8 +392,7 @@ class PangeaRequestAsync(PangeaRequestBase):
373
392
 
374
393
  if loop_resp.accepted_result is not None and not loop_resp.accepted_result.has_upload_url:
375
394
  return loop_resp
376
- else:
377
- raise loop_exc
395
+ raise loop_exc
378
396
 
379
397
  async def _handle_queued_result(self, response: PangeaResponse) -> PangeaResponse:
380
398
  if self._queued_retry_enabled and response.http_status == 202:
@@ -1,8 +1,10 @@
1
1
  from .audit import AuditAsync
2
2
  from .authn import AuthNAsync
3
+ from .authz import AuthZAsync
3
4
  from .embargo import EmbargoAsync
4
5
  from .file_scan import FileScanAsync
5
6
  from .intel import DomainIntelAsync, FileIntelAsync, IpIntelAsync, UrlIntelAsync, UserIntelAsync
6
7
  from .redact import RedactAsync
8
+ from .sanitize import SanitizeAsync
7
9
  from .share import ShareAsync
8
10
  from .vault import VaultAsync