pangea-sdk 3.3.0__py3-none-any.whl → 3.4.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.
pangea/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "3.3.0"
1
+ __version__ = "3.4.0"
2
2
 
3
3
  from pangea.asyncio.request import PangeaRequestAsync
4
4
  from pangea.config import PangeaConfig
pangea/asyncio/request.py CHANGED
@@ -53,11 +53,7 @@ class PangeaRequestAsync(PangeaRequestBase):
53
53
 
54
54
  transfer_method = data.get("transfer_method", None)
55
55
 
56
- if (
57
- files is not None
58
- and type(data) is dict
59
- and (transfer_method == TransferMethod.DIRECT.value or transfer_method == TransferMethod.POST_URL.value)
60
- ):
56
+ if files is not None and type(data) is dict and (transfer_method == TransferMethod.POST_URL.value):
61
57
  requests_response = await self._full_post_presigned_url(
62
58
  endpoint, result_class=result_class, data=data, files=files
63
59
  )
@@ -66,9 +62,10 @@ class PangeaRequestAsync(PangeaRequestBase):
66
62
  url, headers=self._headers(), data=data, files=files, presigned_url_post=False
67
63
  )
68
64
 
69
- pangea_response = PangeaResponse(
70
- requests_response, result_class=result_class, json=await requests_response.json()
71
- )
65
+ json_resp = await requests_response.json()
66
+ self.logger.debug(json.dumps({"service": self.service, "action": "post", "url": url, "response": json_resp}))
67
+
68
+ pangea_response = PangeaResponse(requests_response, result_class=result_class, json=json_resp)
72
69
  if poll_result:
73
70
  pangea_response = await self._handle_queued_result(pangea_response)
74
71
 
@@ -143,13 +140,13 @@ class PangeaRequestAsync(PangeaRequestBase):
143
140
  resp = await self._http_put(url=url, files=files)
144
141
  self.logger.debug(
145
142
  json.dumps(
146
- {"service": self.service, "action": "put presigned", "url": url, "response": resp.text},
143
+ {"service": self.service, "action": "put presigned", "url": url, "response": await resp.text()},
147
144
  default=default_encoder,
148
145
  )
149
146
  )
150
147
 
151
- if resp.status_code < 200 or resp.status_code >= 300:
152
- raise pe.PresignedUploadError(f"presigned PUT failure: {resp.status_code}", resp.text)
148
+ if resp.status < 200 or resp.status >= 300:
149
+ raise pe.PresignedUploadError(f"presigned PUT failure: {resp.status}", await resp.text())
153
150
 
154
151
  async def _http_post(
155
152
  self,
@@ -196,7 +193,7 @@ class PangeaRequestAsync(PangeaRequestBase):
196
193
  form = FormData()
197
194
  name, value = files[0]
198
195
  form.add_field(name, value[1], filename=value[0], content_type=value[2])
199
- return self.session.put(url, headers=headers, data=form)
196
+ return await self.session.put(url, headers=headers, data=form)
200
197
 
201
198
  async def _full_post_presigned_url(
202
199
  self,
@@ -209,8 +206,8 @@ class PangeaRequestAsync(PangeaRequestBase):
209
206
  raise AttributeError("files attribute should have at least 1 file")
210
207
 
211
208
  response = await self.request_presigned_url(endpoint=endpoint, result_class=result_class, data=data)
212
- data_to_presigned = response.accepted_result.accepted_status.upload_details
213
- presigned_url = response.accepted_result.accepted_status.upload_url
209
+ data_to_presigned = response.accepted_result.post_form_data
210
+ presigned_url = response.accepted_result.post_url
214
211
 
215
212
  await self.post_presigned_url(url=presigned_url, data=data_to_presigned, files=files)
216
213
  return response.raw_response
@@ -231,14 +228,14 @@ class PangeaRequestAsync(PangeaRequestBase):
231
228
  except Exception as e:
232
229
  raise e
233
230
 
234
- # Receive 202 with accepted_status
231
+ # Receive 202
235
232
  return await self._poll_presigned_url(accepted_exception.response)
236
233
 
237
234
  async def _poll_presigned_url(self, response: PangeaResponse) -> AcceptedResult:
238
235
  if response.http_status != 202:
239
236
  raise AttributeError("Response should be 202")
240
237
 
241
- if response.accepted_result.accepted_status.upload_url:
238
+ if response.accepted_result is not None and response.accepted_result.has_upload_url:
242
239
  return response
243
240
 
244
241
  self.logger.debug(json.dumps({"service": self.service, "action": "poll_presigned_url", "step": "start"}))
@@ -248,7 +245,7 @@ class PangeaRequestAsync(PangeaRequestBase):
248
245
 
249
246
  while (
250
247
  loop_resp.accepted_result is not None
251
- and not loop_resp.accepted_result.accepted_status.upload_url
248
+ and not loop_resp.accepted_result.has_upload_url
252
249
  and not self._reach_timeout(start)
253
250
  ):
254
251
  await asyncio.sleep(self._get_delay(retry_count, start))
@@ -275,7 +272,7 @@ class PangeaRequestAsync(PangeaRequestBase):
275
272
 
276
273
  self.logger.debug(json.dumps({"service": self.service, "action": "poll_presigned_url", "step": "exit"}))
277
274
 
278
- if loop_resp.accepted_result is not None and not loop_resp.accepted_result.accepted_status.upload_url:
275
+ if loop_resp.accepted_result is not None and not loop_resp.accepted_result.has_upload_url:
279
276
  return loop_resp
280
277
  else:
281
278
  raise loop_exc
@@ -49,7 +49,8 @@ class FileScanAsync(ServiceBaseAsync):
49
49
  raw: Optional[bool] = None,
50
50
  provider: Optional[str] = None,
51
51
  sync_call: bool = True,
52
- transfer_method: TransferMethod = TransferMethod.DIRECT,
52
+ transfer_method: TransferMethod = TransferMethod.POST_URL,
53
+ source_url: Optional[str] = None,
53
54
  ) -> PangeaResponse[m.FileScanResult]:
54
55
  """
55
56
  Scan
@@ -88,7 +89,7 @@ class FileScanAsync(ServiceBaseAsync):
88
89
  if file or file_path:
89
90
  if file_path:
90
91
  file = open(file_path, "rb")
91
- if transfer_method == TransferMethod.DIRECT or transfer_method == TransferMethod.POST_URL:
92
+ if transfer_method == TransferMethod.POST_URL:
92
93
  params = get_file_upload_params(file)
93
94
  crc = params.crc_hex
94
95
  sha = params.sha256_hex
@@ -103,10 +104,11 @@ class FileScanAsync(ServiceBaseAsync):
103
104
  verbose=verbose,
104
105
  raw=raw,
105
106
  provider=provider,
106
- transfer_crc32c=crc,
107
- transfer_sha256=sha,
108
- transfer_size=size,
107
+ crc32c=crc,
108
+ sha256=sha,
109
+ size=size,
109
110
  transfer_method=transfer_method,
111
+ source_url=source_url,
110
112
  )
111
113
  data = input.dict(exclude_none=True)
112
114
  return await self.request.post("v1/scan", m.FileScanResult, data=data, files=files, poll_result=sync_call)
@@ -125,12 +127,10 @@ class FileScanAsync(ServiceBaseAsync):
125
127
  provider=provider,
126
128
  transfer_method=transfer_method,
127
129
  )
128
- if params is not None and (
129
- transfer_method == TransferMethod.POST_URL or transfer_method == TransferMethod.DIRECT
130
- ):
131
- input.transfer_crc32c = params.crc_hex
132
- input.transfer_sha256 = params.sha256_hex
133
- input.transfer_size = params.size
130
+ if params is not None and (transfer_method == TransferMethod.POST_URL):
131
+ input.crc32c = params.crc_hex
132
+ input.sha256 = params.sha256_hex
133
+ input.size = params.size
134
134
 
135
135
  data = input.dict(exclude_none=True)
136
136
  return await self.request.request_presigned_url("v1/scan", m.FileScanResult, data=data)
@@ -156,7 +156,7 @@ class FileUploaderAsync:
156
156
  if transfer_method == TransferMethod.PUT_URL:
157
157
  files = [("file", ("filename", file, "application/octet-stream"))]
158
158
  await self._request.put_presigned_url(url=url, files=files)
159
- elif transfer_method == TransferMethod.POST_URL or transfer_method == TransferMethod.DIRECT:
159
+ elif transfer_method == TransferMethod.POST_URL:
160
160
  files = [("file", ("filename", file, "application/octet-stream"))]
161
161
  await self._request.post_presigned_url(url=url, data=file_details, files=files)
162
162
  else:
pangea/request.py CHANGED
@@ -205,11 +205,7 @@ class PangeaRequest(PangeaRequestBase):
205
205
 
206
206
  transfer_method = data.get("transfer_method", None)
207
207
 
208
- if (
209
- files is not None
210
- and type(data) is dict
211
- and (transfer_method == TransferMethod.DIRECT.value or transfer_method == TransferMethod.POST_URL.value)
212
- ):
208
+ if files is not None and type(data) is dict and (transfer_method == TransferMethod.POST_URL.value):
213
209
  requests_response = self._full_post_presigned_url(
214
210
  endpoint, result_class=result_class, data=data, files=files
215
211
  )
@@ -218,7 +214,10 @@ class PangeaRequest(PangeaRequestBase):
218
214
  url, headers=self._headers(), data=data, files=files, multipart_post=True
219
215
  )
220
216
 
221
- pangea_response = PangeaResponse(requests_response, result_class=result_class, json=requests_response.json())
217
+ json_resp = requests_response.json()
218
+ self.logger.debug(json.dumps({"service": self.service, "action": "post", "url": url, "response": json_resp}))
219
+
220
+ pangea_response = PangeaResponse(requests_response, result_class=result_class, json=json_resp)
222
221
  if poll_result:
223
222
  pangea_response = self._handle_queued_result(pangea_response)
224
223
 
@@ -287,7 +286,7 @@ class PangeaRequest(PangeaRequestBase):
287
286
  except Exception as e:
288
287
  raise e
289
288
 
290
- # Receive 202 with accepted_status
289
+ # Receive 202
291
290
  return self._poll_presigned_url(accepted_exception.response)
292
291
 
293
292
  def post_presigned_url(self, url: str, data: Dict, files: List[Tuple]):
@@ -382,8 +381,8 @@ class PangeaRequest(PangeaRequestBase):
382
381
  raise AttributeError("files attribute should have at least 1 file")
383
382
 
384
383
  response = self.request_presigned_url(endpoint=endpoint, result_class=result_class, data=data)
385
- data_to_presigned = response.accepted_result.accepted_status.upload_details
386
- presigned_url = response.accepted_result.accepted_status.upload_url
384
+ data_to_presigned = response.accepted_result.post_form_data
385
+ presigned_url = response.accepted_result.post_url
387
386
 
388
387
  self.post_presigned_url(url=presigned_url, data=data_to_presigned, files=files)
389
388
  return response.raw_response
@@ -416,7 +415,7 @@ class PangeaRequest(PangeaRequestBase):
416
415
  if response.http_status != 202:
417
416
  raise AttributeError("Response should be 202")
418
417
 
419
- if response.accepted_result.accepted_status.upload_url:
418
+ if response.accepted_result is not None and response.accepted_result.has_upload_url:
420
419
  return response
421
420
 
422
421
  self.logger.debug(json.dumps({"service": self.service, "action": "poll_presigned_url", "step": "start"}))
@@ -426,7 +425,7 @@ class PangeaRequest(PangeaRequestBase):
426
425
 
427
426
  while (
428
427
  loop_resp.accepted_result is not None
429
- and not loop_resp.accepted_result.accepted_status.upload_url
428
+ and not loop_resp.accepted_result.has_upload_url
430
429
  and not self._reach_timeout(start)
431
430
  ):
432
431
  time.sleep(self._get_delay(retry_count, start))
@@ -453,7 +452,7 @@ class PangeaRequest(PangeaRequestBase):
453
452
 
454
453
  self.logger.debug(json.dumps({"service": self.service, "action": "poll_presigned_url", "step": "exit"}))
455
454
 
456
- if loop_resp.accepted_result is not None and not loop_resp.accepted_result.accepted_status.upload_url:
455
+ if loop_resp.accepted_result is not None and not loop_resp.accepted_result.has_upload_url:
457
456
  return loop_resp
458
457
  else:
459
458
  raise loop_exc
pangea/response.py CHANGED
@@ -13,11 +13,10 @@ T = TypeVar("T")
13
13
 
14
14
 
15
15
  class TransferMethod(str, enum.Enum):
16
- DIRECT = "post-url" # deprecated, use POST_URL instead
17
16
  MULTIPART = "multipart"
18
17
  POST_URL = "post-url"
19
18
  PUT_URL = "put-url"
20
- # URL = "url"
19
+ SOURCE_URL = "source-url"
21
20
 
22
21
  def __str__(self):
23
22
  return str(self.value)
@@ -79,7 +78,16 @@ class AcceptedStatus(APIResponseModel):
79
78
 
80
79
 
81
80
  class AcceptedResult(PangeaResponseResult):
82
- accepted_status: Optional[AcceptedStatus] = None
81
+ ttl_mins: int
82
+ retry_counter: int
83
+ location: str
84
+ post_url: Optional[str] = None
85
+ post_form_data: Dict[str, Any] = {}
86
+ put_url: Optional[str] = None
87
+
88
+ @property
89
+ def has_upload_url(self) -> bool:
90
+ return self.post_url is not None or self.put_url is not None
83
91
 
84
92
 
85
93
  class PangeaError(PangeaResponseResult):
@@ -23,10 +23,11 @@ class FileScanRequest(APIRequestModel):
23
23
  verbose: Optional[bool] = None
24
24
  raw: Optional[bool] = None
25
25
  provider: Optional[str] = None
26
- transfer_size: Optional[int] = None
27
- transfer_crc32c: Optional[str] = None
28
- transfer_sha256: Optional[str] = None
29
- transfer_method: TransferMethod = TransferMethod.DIRECT
26
+ size: Optional[int] = None
27
+ crc32c: Optional[str] = None
28
+ sha256: Optional[str] = None
29
+ source_url: Optional[str] = None
30
+ transfer_method: TransferMethod = TransferMethod.POST_URL
30
31
 
31
32
 
32
33
  class FileScanData(PangeaResponseResult):
@@ -81,7 +82,8 @@ class FileScan(ServiceBase):
81
82
  raw: Optional[bool] = None,
82
83
  provider: Optional[str] = None,
83
84
  sync_call: bool = True,
84
- transfer_method: TransferMethod = TransferMethod.DIRECT,
85
+ transfer_method: TransferMethod = TransferMethod.POST_URL,
86
+ source_url: Optional[str] = None,
85
87
  ) -> PangeaResponse[FileScanResult]:
86
88
  """
87
89
  Scan
@@ -120,7 +122,7 @@ class FileScan(ServiceBase):
120
122
  if file or file_path:
121
123
  if file_path:
122
124
  file = open(file_path, "rb")
123
- if transfer_method == TransferMethod.DIRECT or transfer_method == TransferMethod.POST_URL:
125
+ if transfer_method == TransferMethod.POST_URL:
124
126
  params = get_file_upload_params(file)
125
127
  crc = params.crc_hex
126
128
  sha = params.sha256_hex
@@ -135,10 +137,11 @@ class FileScan(ServiceBase):
135
137
  verbose=verbose,
136
138
  raw=raw,
137
139
  provider=provider,
138
- transfer_crc32c=crc,
139
- transfer_sha256=sha,
140
- transfer_size=size,
140
+ crc32c=crc,
141
+ sha256=sha,
142
+ size=size,
141
143
  transfer_method=transfer_method,
144
+ source_url=source_url,
142
145
  )
143
146
  data = input.dict(exclude_none=True)
144
147
  return self.request.post("v1/scan", FileScanResult, data=data, files=files, poll_result=sync_call)
@@ -157,12 +160,10 @@ class FileScan(ServiceBase):
157
160
  provider=provider,
158
161
  transfer_method=transfer_method,
159
162
  )
160
- if params is not None and (
161
- transfer_method == TransferMethod.POST_URL or transfer_method == TransferMethod.DIRECT
162
- ):
163
- input.transfer_crc32c = params.crc_hex
164
- input.transfer_sha256 = params.sha256_hex
165
- input.transfer_size = params.size
163
+ if params is not None and (transfer_method == TransferMethod.POST_URL):
164
+ input.crc32c = params.crc_hex
165
+ input.sha256 = params.sha256_hex
166
+ input.size = params.size
166
167
 
167
168
  data = input.dict(exclude_none=True)
168
169
  return self.request.request_presigned_url("v1/scan", FileScanResult, data=data)
@@ -188,7 +189,7 @@ class FileUploader:
188
189
  if transfer_method == TransferMethod.PUT_URL:
189
190
  files = [("file", ("filename", file, "application/octet-stream"))]
190
191
  self._request.put_presigned_url(url=url, files=files)
191
- elif transfer_method == TransferMethod.POST_URL or transfer_method == TransferMethod.DIRECT:
192
+ elif transfer_method == TransferMethod.POST_URL:
192
193
  files = [("file", ("filename", file, "application/octet-stream"))]
193
194
  self._request.post_presigned_url(url=url, data=file_details, files=files)
194
195
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pangea-sdk
3
- Version: 3.3.0
3
+ Version: 3.4.0
4
4
  Summary: Pangea API SDK
5
5
  License: MIT
6
6
  Keywords: Pangea,SDK,Audit
@@ -1,11 +1,11 @@
1
- pangea/__init__.py,sha256=GgLmx-eZWNCnGMva8AGtHJ4JesBsSPfw8YdDVyuKXOo,200
2
- pangea/asyncio/request.py,sha256=akSpGTjC8j8Jr6uK40Zu8v9HQXX_QOf7dKgweq5K6DM,12642
1
+ pangea/__init__.py,sha256=IdKL3uBCgPwFlLeZHTLAAY32MvYJBkmSYEBKIOoYXzI,200
2
+ pangea/asyncio/request.py,sha256=HXD0LscN0lfGoN9Nu0C8fMMkAZT7LLg2UotbD-A57q4,12628
3
3
  pangea/asyncio/services/__init__.py,sha256=_CEDza6E9VmEs6d_vubWetfeqTogH7UxT7XrTVRw4Mo,290
4
4
  pangea/asyncio/services/audit.py,sha256=xHvz5ReJpmk_StK3mr_uDqCI80J6Aj7-EglEBWS0Qqc,16480
5
5
  pangea/asyncio/services/authn.py,sha256=HssvrZ3fr2oP5sgYBj1Rr5Yf-fKiHhrWTue5LOAeyOk,43288
6
6
  pangea/asyncio/services/base.py,sha256=hmdY5-IS_H2WGMeVfzotn11Z1c2B2iJTHi4USBbmptA,2304
7
7
  pangea/asyncio/services/embargo.py,sha256=8WguyWZUaGVwGpNzic5h8QzLueirA9WpBBik4mpCTeA,3056
8
- pangea/asyncio/services/file_scan.py,sha256=DnysLA0oEsxkHPdt4Pal6oWKiYdl7TZz8eX20Bs_Zl8,6280
8
+ pangea/asyncio/services/file_scan.py,sha256=o_6Cddk8bXXlh4Aj_DUQJYlE9Q6U0XGPlZxML88PTfw,6151
9
9
  pangea/asyncio/services/intel.py,sha256=LdJSxCohXsI4Vk8bG74jXTBYAL9N45lb5LIX7nBXqLI,22248
10
10
  pangea/asyncio/services/redact.py,sha256=W9eKMw1XyY6tgRudRrtuCpyQYhgttvmsYngoiMld0C4,5152
11
11
  pangea/asyncio/services/vault.py,sha256=JhxUdmPNYZzp3eiAQFR6vsfyS9L3ddKWes-Cv7rj2ow,43425
@@ -15,8 +15,8 @@ pangea/deep_verify.py,sha256=WiA_2gqtrSCQYoTMKX9ILlNgnknsH4UxZpJXLVG2uyc,8343
15
15
  pangea/deprecated.py,sha256=IjFYEVvY1E0ld0SMkEYC1o62MAleX3nnT1If2dFVbHo,608
16
16
  pangea/dump_audit.py,sha256=Ws0KuZyHoaySsQ2lq9EKK2iw65O8x4zL1Mii0ChDh0k,6511
17
17
  pangea/exceptions.py,sha256=JMx_Dym7W2cgcPSHN4bz9Rlrm-3BZGNpIYu3VBXZLBU,5277
18
- pangea/request.py,sha256=5BP-wFI6x7lfJ41-6bTcpcg3pyviMgrX_4nX_M9yyXg,18640
19
- pangea/response.py,sha256=mOgeFqafEH_MdDILSo-ju5cWicXlvSd1CXzbsHObiJo,5363
18
+ pangea/request.py,sha256=GShc12dltLSapfayHChnHEmL9l4feyYCA-O-PQ4k_VY,18641
19
+ pangea/response.py,sha256=8cA08NjP_2jIq73lybBaBK0N7XnYLd0f9rOHNcnESg4,5552
20
20
  pangea/services/__init__.py,sha256=auqKaEAOLiazHCzOQVwrUwd2ABFw_bF-ptoOq1bpa68,253
21
21
  pangea/services/audit/audit.py,sha256=50zkQE2HQ0cQtFroFSVjUxX1M4RQsf6pBUeMidSkEHI,30295
22
22
  pangea/services/audit/exceptions.py,sha256=CVdaQZCvQKx1n-iIjWz5wnStUGU6cXDwKqe7MoijAXk,451
@@ -27,7 +27,7 @@ pangea/services/authn/authn.py,sha256=sGQUPQ8VLEMtu8AkEhWPyY6Q6AxCsfrX-XNUzkC-o1
27
27
  pangea/services/authn/models.py,sha256=V-hj1KfbSuaWJMVgd-Q3fWTsnbj3EdPumnzXtjHOR8g,18150
28
28
  pangea/services/base.py,sha256=bRSuuhLv6iQrPVjhasOjTBqOgxTRRhCD204v3tNjVOE,2731
29
29
  pangea/services/embargo.py,sha256=F3jx7SbElnjhbDEUR3oHfWsQ8G8zf_kfp6_q1_vmOIc,3871
30
- pangea/services/file_scan.py,sha256=K4zDhZtY-Co622QgSOueGfkCaAJVy04mO6sqQ22TBS4,6999
30
+ pangea/services/file_scan.py,sha256=iwqvJcaNE1nJN4VpLcYKtgWFfgnbLLxnbUylhIdEPTk,6882
31
31
  pangea/services/intel.py,sha256=oTvTxCtdnoaZRlt0anUKnkRT2FVfc9LG8ftDIX09jHk,30399
32
32
  pangea/services/redact.py,sha256=vH4sg_t8MnoSjSY-F42JZhe8EfRmVCclslDN7U1hNP4,7756
33
33
  pangea/services/vault/models/asymmetric.py,sha256=ac2Exc66elXxO-HxBqtvLPQWNI7y_00kb6SVqBPKecA,1450
@@ -38,6 +38,6 @@ pangea/services/vault/vault.py,sha256=t3KU59FjUfVawbMZt7A51cDQoyapftChdihTqllVrT
38
38
  pangea/tools.py,sha256=A9gkHpAkECwqnUKA-O09vG-n6Gmq2g_LYr61BUs-n54,6403
39
39
  pangea/utils.py,sha256=09dHX9CKmyKNWccSF2z7LyCYYYduZ9AWP6D5Ylnfty8,3360
40
40
  pangea/verify_audit.py,sha256=gWhde7gETKSWfBaMm5gEckAO2xmYB_vmgcZ_4FvvyfU,10616
41
- pangea_sdk-3.3.0.dist-info/METADATA,sha256=7xobhjV_WaLEGoK4-jsG9YZG_PqDEhYlXD3c6CnnxS0,6934
42
- pangea_sdk-3.3.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
43
- pangea_sdk-3.3.0.dist-info/RECORD,,
41
+ pangea_sdk-3.4.0.dist-info/METADATA,sha256=HkC7uL-xyRL0Vlcqoe16pHLZmo2JdNW4z0_iywI9Z3c,6934
42
+ pangea_sdk-3.4.0.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
43
+ pangea_sdk-3.4.0.dist-info/RECORD,,