pangea-sdk 3.8.0b4__py3-none-any.whl → 3.9.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.
@@ -76,7 +76,7 @@ class FileIntelAsync(ServiceBaseAsync):
76
76
  provider: Optional[str] = None,
77
77
  verbose: Optional[bool] = None,
78
78
  raw: Optional[bool] = None,
79
- ) -> PangeaResponse[m.FileReputationResult]:
79
+ ) -> PangeaResponse[m.FileReputationBulkResult]:
80
80
  """
81
81
  Reputation check
82
82
 
@@ -182,7 +182,7 @@ class FileIntelAsync(ServiceBaseAsync):
182
182
  hash = hash_256_filepath(filepath)
183
183
  hashes.append(hash)
184
184
 
185
- return await self.hash_reputation_bulk( # type: ignore[return-value]
185
+ return await self.hash_reputation_bulk(
186
186
  hashes=hashes, hash_type="sha256", verbose=verbose, raw=raw, provider=provider
187
187
  )
188
188
 
@@ -251,7 +251,7 @@ class DomainIntelAsync(ServiceBaseAsync):
251
251
  verbose: Optional[bool] = None,
252
252
  raw: Optional[bool] = None,
253
253
  provider: Optional[str] = None,
254
- ) -> PangeaResponse[m.DomainReputationResult]:
254
+ ) -> PangeaResponse[m.DomainReputationBulkResult]:
255
255
  """
256
256
  Reputation
257
257
 
@@ -373,7 +373,7 @@ class IpIntelAsync(ServiceBaseAsync):
373
373
 
374
374
  async def reputation_bulk(
375
375
  self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
376
- ) -> PangeaResponse[m.IPReputationResult]:
376
+ ) -> PangeaResponse[m.IPReputationBulkResult]:
377
377
  """
378
378
  Reputation
379
379
 
@@ -1,10 +1,12 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+ from __future__ import annotations
3
4
 
4
5
  from typing import Dict, List, Optional, Union
5
6
 
6
7
  import pangea.services.redact as m
7
8
  from pangea.asyncio.services.base import ServiceBaseAsync
9
+ from pangea.config import PangeaConfig
8
10
  from pangea.response import PangeaResponse
9
11
 
10
12
 
@@ -35,7 +37,24 @@ class RedactAsync(ServiceBaseAsync):
35
37
 
36
38
  service_name = "redact"
37
39
 
38
- def __init__(self, token, config=None, logger_name="pangea", config_id: Optional[str] = None):
40
+ def __init__(
41
+ self, token: str, config: PangeaConfig | None = None, logger_name: str = "pangea", config_id: str | None = None
42
+ ) -> None:
43
+ """
44
+ Redact client
45
+
46
+ Initializes a new Redact client.
47
+
48
+ Args:
49
+ token: Pangea API token.
50
+ config: Configuration.
51
+ logger_name: Logger name.
52
+
53
+ Examples:
54
+ config = PangeaConfig(domain="pangea_domain")
55
+ redact = RedactAsync(token="pangea_token", config=config)
56
+ """
57
+
39
58
  super().__init__(token, config, logger_name, config_id=config_id)
40
59
 
41
60
  async def redact(
@@ -45,6 +64,7 @@ class RedactAsync(ServiceBaseAsync):
45
64
  rules: Optional[List[str]] = None,
46
65
  rulesets: Optional[List[str]] = None,
47
66
  return_result: Optional[bool] = None,
67
+ redaction_method_overrides: Optional[m.RedactionMethodOverrides] = None,
48
68
  ) -> PangeaResponse[m.RedactResult]:
49
69
  """
50
70
  Redact
@@ -60,6 +80,7 @@ class RedactAsync(ServiceBaseAsync):
60
80
  rules (list[str], optional): An array of redact rule short names
61
81
  rulesets (list[str], optional): An array of redact rulesets short names
62
82
  return_result(bool, optional): Setting this value to false will omit the redacted result only returning count
83
+ redaction_method_overrides: A set of redaction method overrides for any enabled rule. These methods override the config declared methods
63
84
 
64
85
  Raises:
65
86
  PangeaAPIException: If an API Error happens
@@ -73,7 +94,14 @@ class RedactAsync(ServiceBaseAsync):
73
94
  response = redact.redact(text="Jenny Jenny... 555-867-5309")
74
95
  """
75
96
 
76
- input = m.RedactRequest(text=text, debug=debug, rules=rules, rulesets=rulesets, return_result=return_result)
97
+ input = m.RedactRequest(
98
+ text=text,
99
+ debug=debug,
100
+ rules=rules,
101
+ rulesets=rulesets,
102
+ return_result=return_result,
103
+ redaction_method_overrides=redaction_method_overrides,
104
+ )
77
105
  return await self.request.post("v1/redact", m.RedactResult, data=input.dict(exclude_none=True))
78
106
 
79
107
  async def redact_structured(
@@ -85,6 +113,7 @@ class RedactAsync(ServiceBaseAsync):
85
113
  rules: Optional[List[str]] = None,
86
114
  rulesets: Optional[List[str]] = None,
87
115
  return_result: Optional[bool] = None,
116
+ redaction_method_overrides: Optional[m.RedactionMethodOverrides] = None,
88
117
  ) -> PangeaResponse[m.StructuredResult]:
89
118
  """
90
119
  Redact structured
@@ -104,6 +133,7 @@ class RedactAsync(ServiceBaseAsync):
104
133
  rules (list[str], optional): An array of redact rule short names
105
134
  rulesets (list[str], optional): An array of redact rulesets short names
106
135
  return_result(bool, optional): Setting this value to false will omit the redacted result only returning count
136
+ redaction_method_overrides: A set of redaction method overrides for any enabled rule. These methods override the config declared methods
107
137
 
108
138
  Raises:
109
139
  PangeaAPIException: If an API Error happens
@@ -130,5 +160,29 @@ class RedactAsync(ServiceBaseAsync):
130
160
  rules=rules,
131
161
  rulesets=rulesets,
132
162
  return_result=return_result,
163
+ redaction_method_overrides=redaction_method_overrides,
133
164
  )
134
165
  return await self.request.post("v1/redact_structured", m.StructuredResult, data=input.dict(exclude_none=True))
166
+
167
+ async def unredact(self, redacted_data: m.RedactedData, fpe_context: str) -> PangeaResponse[m.UnredactResult]:
168
+ """
169
+ Unredact
170
+
171
+ Decrypt or unredact fpe redactions
172
+
173
+ OperationId: redact_post_v1_unredact
174
+
175
+ Args:
176
+ redacted_data: Data to unredact
177
+ fpe_context (base64): FPE context used to decrypt and unredact data
178
+
179
+ Raises:
180
+ PangeaAPIException: If an API Error happens
181
+
182
+ Returns:
183
+ Pangea Response with redacted data in the response.result field,
184
+ available response fields can be found in our
185
+ [API Documentation](https://pangea.cloud/docs/api/redact#unredact)
186
+ """
187
+ input = m.UnredactRequest(redacted_data=redacted_data, fpe_context=fpe_context)
188
+ return await self.request.post("v1/unredact", m.UnredactResult, data=input.dict(exclude_none=True))
@@ -1,9 +1,12 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+ from __future__ import annotations
4
+
3
5
  import datetime
4
6
  from typing import Dict, Optional, Union
5
7
 
6
8
  from pangea.asyncio.services.base import ServiceBaseAsync
9
+ from pangea.config import PangeaConfig
7
10
  from pangea.response import PangeaResponse
8
11
  from pangea.services.vault.models.asymmetric import (
9
12
  AsymmetricGenerateRequest,
@@ -17,6 +20,8 @@ from pangea.services.vault.models.asymmetric import (
17
20
  )
18
21
  from pangea.services.vault.models.common import (
19
22
  AsymmetricAlgorithm,
23
+ DecryptTransformRequest,
24
+ DecryptTransformResult,
20
25
  DeleteRequest,
21
26
  DeleteResult,
22
27
  EncodedPrivateKey,
@@ -24,6 +29,8 @@ from pangea.services.vault.models.common import (
24
29
  EncodedSymmetricKey,
25
30
  EncryptStructuredRequest,
26
31
  EncryptStructuredResult,
32
+ EncryptTransformRequest,
33
+ EncryptTransformResult,
27
34
  FolderCreateRequest,
28
35
  FolderCreateResult,
29
36
  GetRequest,
@@ -50,6 +57,7 @@ from pangea.services.vault.models.common import (
50
57
  SymmetricAlgorithm,
51
58
  Tags,
52
59
  TDict,
60
+ TransformAlphabet,
53
61
  UpdateRequest,
54
62
  UpdateResult,
55
63
  )
@@ -98,10 +106,24 @@ class VaultAsync(ServiceBaseAsync):
98
106
 
99
107
  def __init__(
100
108
  self,
101
- token,
102
- config=None,
103
- logger_name="pangea",
104
- ):
109
+ token: str,
110
+ config: PangeaConfig | None = None,
111
+ logger_name: str = "pangea",
112
+ ) -> None:
113
+ """
114
+ Vault client
115
+
116
+ Initializes a new Vault client.
117
+
118
+ Args:
119
+ token: Pangea API token.
120
+ config: Configuration.
121
+ logger_name: Logger name.
122
+
123
+ Examples:
124
+ config = PangeaConfig(domain="pangea_domain")
125
+ vault = VaultAsync(token="pangea_token", config=config)
126
+ """
105
127
  super().__init__(token, config, logger_name)
106
128
 
107
129
  # Delete endpoint
@@ -1278,3 +1300,92 @@ class VaultAsync(ServiceBaseAsync):
1278
1300
  EncryptStructuredResult,
1279
1301
  data=input.dict(exclude_none=True),
1280
1302
  )
1303
+
1304
+ async def encrypt_transform(
1305
+ self,
1306
+ id: str,
1307
+ plain_text: str,
1308
+ alphabet: TransformAlphabet,
1309
+ tweak: str | None = None,
1310
+ version: int | None = None,
1311
+ ) -> PangeaResponse[EncryptTransformResult]:
1312
+ """
1313
+ Encrypt transform
1314
+
1315
+ Encrypt using a format-preserving algorithm (FPE).
1316
+
1317
+ OperationId: vault_post_v1_key_encrypt_transform
1318
+
1319
+ Args:
1320
+ id: The item ID.
1321
+ plain_text: A message to be encrypted.
1322
+ alphabet: Set of characters to use for format-preserving encryption (FPE).
1323
+ tweak: User provided tweak string. If not provided, a random string will be generated and returned.
1324
+ version: The item version. Defaults to the current version.
1325
+
1326
+ Raises:
1327
+ PangeaAPIException: If an API error happens.
1328
+
1329
+ Returns:
1330
+ A `PangeaResponse` containing the encrypted message.
1331
+
1332
+ Examples:
1333
+ await vault.encrypt_transform(
1334
+ id="pvi_[...]",
1335
+ plain_text="message to encrypt",
1336
+ alphabet=TransformAlphabet.ALPHANUMERIC,
1337
+ tweak="MTIzMTIzMT==",
1338
+ )
1339
+ """
1340
+
1341
+ input = EncryptTransformRequest(
1342
+ id=id,
1343
+ plain_text=plain_text,
1344
+ alphabet=alphabet,
1345
+ tweak=tweak,
1346
+ version=version,
1347
+ )
1348
+ return await self.request.post(
1349
+ "v1/key/encrypt/transform",
1350
+ EncryptTransformResult,
1351
+ data=input.dict(exclude_none=True),
1352
+ )
1353
+
1354
+ async def decrypt_transform(
1355
+ self, id: str, cipher_text: str, tweak: str, alphabet: TransformAlphabet, version: int | None = None
1356
+ ) -> PangeaResponse[DecryptTransformResult]:
1357
+ """
1358
+ Decrypt transform
1359
+
1360
+ Decrypt using a format-preserving algorithm (FPE).
1361
+
1362
+ OperationId: vault_post_v1_key_decrypt_transform
1363
+
1364
+ Args:
1365
+ id: The item ID.
1366
+ cipher_text: A message encrypted by Vault.
1367
+ tweak: User provided tweak string.
1368
+ alphabet: Set of characters to use for format-preserving encryption (FPE).
1369
+ version: The item version. Defaults to the current version.
1370
+
1371
+ Raises:
1372
+ PangeaAPIException: If an API error happens.
1373
+
1374
+ Returns:
1375
+ A `PangeaResponse` containing the decrypted message.
1376
+
1377
+ Examples:
1378
+ await vault.decrypt_transform(
1379
+ id="pvi_[...]",
1380
+ cipher_text="encrypted message",
1381
+ tweak="MTIzMTIzMT==",
1382
+ alphabet=TransformAlphabet.ALPHANUMERIC,
1383
+ )
1384
+ """
1385
+
1386
+ input = DecryptTransformRequest(id=id, cipher_text=cipher_text, tweak=tweak, alphabet=alphabet, version=version)
1387
+ return await self.request.post(
1388
+ "v1/key/decrypt/transform",
1389
+ DecryptTransformResult,
1390
+ data=input.dict(exclude_none=True),
1391
+ )
pangea/request.py CHANGED
@@ -5,12 +5,12 @@ import copy
5
5
  import json
6
6
  import logging
7
7
  import time
8
- from typing import Dict, List, Optional, Tuple, Type, Union
8
+ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type, Union
9
9
 
10
- import aiohttp
11
10
  import requests
12
11
  from requests.adapters import HTTPAdapter, Retry
13
12
  from requests_toolbelt import MultipartDecoder # type: ignore
13
+ from typing_extensions import TypeVar
14
14
 
15
15
  import pangea
16
16
  import pangea.exceptions as pe
@@ -18,6 +18,9 @@ from pangea.config import PangeaConfig
18
18
  from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult, ResponseStatus, TransferMethod
19
19
  from pangea.utils import default_encoder
20
20
 
21
+ if TYPE_CHECKING:
22
+ import aiohttp
23
+
21
24
 
22
25
  class MultipartResponse(object):
23
26
  pangea_json: Dict[str, str]
@@ -187,6 +190,9 @@ class PangeaRequestBase(object):
187
190
  raise pe.PangeaAPIException(f"{summary} ", response)
188
191
 
189
192
 
193
+ TResult = TypeVar("TResult", bound=PangeaResponseResult, default=PangeaResponseResult)
194
+
195
+
190
196
  class PangeaRequest(PangeaRequestBase):
191
197
  """An object that makes direct calls to Pangea Service APIs.
192
198
 
@@ -202,12 +208,12 @@ class PangeaRequest(PangeaRequestBase):
202
208
  def post(
203
209
  self,
204
210
  endpoint: str,
205
- result_class: Type[PangeaResponseResult],
211
+ result_class: Type[TResult],
206
212
  data: Union[str, Dict] = {},
207
213
  files: Optional[List[Tuple]] = None,
208
214
  poll_result: bool = True,
209
215
  url: Optional[str] = None,
210
- ) -> PangeaResponse:
216
+ ) -> PangeaResponse[TResult]:
211
217
  """Makes the POST call to a Pangea Service endpoint.
212
218
 
213
219
  Args:
@@ -343,7 +349,7 @@ class PangeaRequest(PangeaRequestBase):
343
349
 
344
350
  return data, files
345
351
 
346
- def _handle_queued_result(self, response: PangeaResponse) -> PangeaResponse[Type[PangeaResponseResult]]:
352
+ def _handle_queued_result(self, response: PangeaResponse[TResult]) -> PangeaResponse[TResult]:
347
353
  if self._queued_retry_enabled and response.http_status == 202:
348
354
  self.logger.debug(
349
355
  json.dumps(
@@ -355,7 +361,7 @@ class PangeaRequest(PangeaRequestBase):
355
361
 
356
362
  return response
357
363
 
358
- def get(self, path: str, result_class: Type[PangeaResponseResult], check_response: bool = True) -> PangeaResponse:
364
+ def get(self, path: str, result_class: Type[TResult], check_response: bool = True) -> PangeaResponse[TResult]:
359
365
  """Makes the GET call to a Pangea Service endpoint.
360
366
 
361
367
  Args:
@@ -427,21 +433,21 @@ class PangeaRequest(PangeaRequestBase):
427
433
  raise pe.DownloadFileError(f"Failed to download file. Status: {response.status_code}", response.text)
428
434
 
429
435
  def poll_result_by_id(
430
- self, request_id: str, result_class: Union[Type[PangeaResponseResult], Type[dict]], check_response: bool = True
431
- ):
436
+ self, request_id: str, result_class: Type[TResult], check_response: bool = True
437
+ ) -> PangeaResponse[TResult]:
432
438
  path = self._get_poll_path(request_id)
433
439
  self.logger.debug(json.dumps({"service": self.service, "action": "poll_result_once", "url": path}))
434
- return self.get(path, result_class, check_response=check_response) # type: ignore[arg-type]
440
+ return self.get(path, result_class, check_response=check_response)
435
441
 
436
442
  def poll_result_once(
437
- self, response: PangeaResponse, check_response: bool = True
438
- ) -> PangeaResponse[Type[PangeaResponseResult]]:
443
+ self, response: PangeaResponse[TResult], check_response: bool = True
444
+ ) -> PangeaResponse[TResult]:
439
445
  request_id = response.request_id
440
446
  if not request_id:
441
447
  raise pe.PangeaException("Poll result error: response did not include a 'request_id'")
442
448
 
443
449
  if response.status != ResponseStatus.ACCEPTED.value:
444
- raise pe.PangeaException("Response already proccesed")
450
+ raise pe.PangeaException("Response already processed")
445
451
 
446
452
  return self.poll_result_by_id(request_id, response.result_class, check_response=check_response)
447
453
 
@@ -453,8 +459,10 @@ class PangeaRequest(PangeaRequestBase):
453
459
  ) -> PangeaResponse:
454
460
  # Send request
455
461
  try:
456
- # This should return 202 (AcceptedRequestException) at least zero size file is sent
457
- return self.post(endpoint=endpoint, result_class=result_class, data=data, poll_result=False)
462
+ # This should return 202 (AcceptedRequestException)
463
+ resp = self.post(endpoint=endpoint, result_class=result_class, data=data, poll_result=False)
464
+ raise pe.PresignedURLException("Should return 202", resp)
465
+
458
466
  except pe.AcceptedRequestException as e:
459
467
  accepted_exception = e
460
468
  except Exception as e:
@@ -512,9 +520,6 @@ class PangeaRequest(PangeaRequestBase):
512
520
  raise AttributeError("files attribute should have at least 1 file")
513
521
 
514
522
  response = self.request_presigned_url(endpoint=endpoint, result_class=result_class, data=data)
515
-
516
- if response.success: # This should only happen when uploading a zero bytes file
517
- return response.raw_response
518
523
  if response.accepted_result is None:
519
524
  raise pe.PangeaException("No accepted_result field when requesting presigned url")
520
525
  if response.accepted_result.post_url is None:
@@ -526,7 +531,7 @@ class PangeaRequest(PangeaRequestBase):
526
531
  self.post_presigned_url(url=presigned_url, data=data_to_presigned, files=files)
527
532
  return response.raw_response
528
533
 
529
- def _poll_result_retry(self, response: PangeaResponse) -> PangeaResponse[Type[PangeaResponseResult]]:
534
+ def _poll_result_retry(self, response: PangeaResponse[TResult]) -> PangeaResponse[TResult]:
530
535
  retry_count = 1
531
536
  start = time.time()
532
537
 
@@ -538,9 +543,7 @@ class PangeaRequest(PangeaRequestBase):
538
543
  self.logger.debug(json.dumps({"service": self.service, "action": "poll_result_retry", "step": "exit"}))
539
544
  return self._check_response(response)
540
545
 
541
- def _poll_presigned_url(
542
- self, response: PangeaResponse[Type[PangeaResponseResult]]
543
- ) -> PangeaResponse[Type[PangeaResponseResult]]:
546
+ def _poll_presigned_url(self, response: PangeaResponse[TResult]) -> PangeaResponse[TResult]:
544
547
  if response.http_status != 202:
545
548
  raise AttributeError("Response should be 202")
546
549
 
pangea/response.py CHANGED
@@ -3,16 +3,15 @@
3
3
  import datetime
4
4
  import enum
5
5
  import os
6
- from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, Union
6
+ from typing import Any, Dict, Generic, List, Optional, Type, Union
7
7
 
8
8
  import aiohttp
9
9
  import requests
10
10
  from pydantic import BaseModel
11
+ from typing_extensions import TypeVar
11
12
 
12
13
  from pangea.utils import format_datetime
13
14
 
14
- T = TypeVar("T")
15
-
16
15
 
17
16
  class AttachedFile(object):
18
17
  filename: str
@@ -29,7 +28,6 @@ class AttachedFile(object):
29
28
  filename = self.filename if self.filename else "default_save_filename"
30
29
 
31
30
  filepath = os.path.join(dest_folder, filename)
32
- filepath = self._find_available_file(filepath)
33
31
  directory = os.path.dirname(filepath)
34
32
  if not os.path.exists(directory):
35
33
  os.makedirs(directory)
@@ -37,17 +35,6 @@ class AttachedFile(object):
37
35
  with open(filepath, "wb") as file:
38
36
  file.write(self.file)
39
37
 
40
- def _find_available_file(self, file_path):
41
- base_name, ext = os.path.splitext(file_path)
42
- counter = 1
43
- while os.path.exists(file_path):
44
- if ext:
45
- file_path = f"{base_name}_{counter}{ext}"
46
- else:
47
- file_path = f"{base_name}_{counter}"
48
- counter += 1
49
- return file_path
50
-
51
38
 
52
39
  class TransferMethod(str, enum.Enum):
53
40
  MULTIPART = "multipart"
@@ -155,22 +142,34 @@ class ResponseStatus(str, enum.Enum):
155
142
 
156
143
 
157
144
  class ResponseHeader(APIResponseModel):
158
- """
159
- Pangea response API header.
160
-
161
- Arguments:
162
- request_id -- The request ID.
163
- request_time -- The time the request was issued, ISO8601.
164
- response_time -- The time the response was issued, ISO8601.
165
- status -- Pangea response status
166
- summary -- The summary of the response.
167
- """
145
+ """Pangea response API header."""
168
146
 
169
147
  request_id: str
148
+ """A unique identifier assigned to each request made to the API."""
149
+
170
150
  request_time: str
151
+ """
152
+ Timestamp indicating the exact moment when a request is made to the API.
153
+ """
154
+
171
155
  response_time: str
156
+ """
157
+ Duration it takes for the API to process a request and generate a response.
158
+ """
159
+
172
160
  status: str
161
+ """
162
+ Represents the status or outcome of the API request.
163
+ """
164
+
173
165
  summary: str
166
+ """
167
+ Provides a concise and brief overview of the purpose or primary objective of
168
+ the API endpoint.
169
+ """
170
+
171
+
172
+ T = TypeVar("T", bound=PangeaResponseResult, default=PangeaResponseResult)
174
173
 
175
174
 
176
175
  class PangeaResponse(Generic[T], ResponseHeader):
@@ -179,14 +178,14 @@ class PangeaResponse(Generic[T], ResponseHeader):
179
178
  result: Optional[T] = None
180
179
  pangea_error: Optional[PangeaError] = None
181
180
  accepted_result: Optional[AcceptedResult] = None
182
- result_class: Union[Type[PangeaResponseResult], Type[dict]] = PangeaResponseResult
181
+ result_class: Type[T] = PangeaResponseResult # type: ignore[assignment]
183
182
  _json: Any
184
183
  attached_files: List[AttachedFile] = []
185
184
 
186
185
  def __init__(
187
186
  self,
188
187
  response: requests.Response,
189
- result_class: Union[Type[PangeaResponseResult], Type[dict]],
188
+ result_class: Type[T],
190
189
  json: dict,
191
190
  attached_files: List[AttachedFile] = [],
192
191
  ):
@@ -198,7 +197,7 @@ class PangeaResponse(Generic[T], ResponseHeader):
198
197
  self.attached_files = attached_files
199
198
 
200
199
  self.result = (
201
- self.result_class(**self.raw_result) # type: ignore[assignment]
200
+ self.result_class(**self.raw_result)
202
201
  if self.raw_result is not None and issubclass(self.result_class, PangeaResponseResult) and self.success
203
202
  else None
204
203
  )
@@ -5,6 +5,4 @@ from .embargo import Embargo
5
5
  from .file_scan import FileScan
6
6
  from .intel import DomainIntel, FileIntel, IpIntel, UrlIntel, UserIntel
7
7
  from .redact import Redact
8
- from .sanitize import Sanitize
9
- from .share.share import Share
10
8
  from .vault.vault import Vault