pangea-sdk 6.2.0b1__py3-none-any.whl → 6.3.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 (55) 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 +70 -169
  5. pangea/asyncio/services/__init__.py +2 -1
  6. pangea/asyncio/services/ai_guard.py +9 -12
  7. pangea/asyncio/services/audit.py +13 -307
  8. pangea/asyncio/services/authn.py +40 -32
  9. pangea/asyncio/services/authz.py +51 -17
  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 +11 -268
  14. pangea/asyncio/services/sanitize.py +5 -1
  15. pangea/asyncio/services/share.py +5 -1
  16. pangea/asyncio/services/vault.py +71 -55
  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 +80 -200
  24. pangea/response.py +21 -18
  25. pangea/services/__init__.py +2 -1
  26. pangea/services/ai_guard.py +35 -24
  27. pangea/services/audit/audit.py +17 -314
  28. pangea/services/audit/models.py +69 -307
  29. pangea/services/audit/signing.py +1 -1
  30. pangea/services/audit/util.py +10 -10
  31. pangea/services/authn/authn.py +39 -31
  32. pangea/services/authn/models.py +183 -148
  33. pangea/services/authz.py +108 -60
  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 +14 -476
  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 +15 -12
  43. pangea/services/vault/models/keys.py +4 -9
  44. pangea/services/vault/models/secret.py +3 -8
  45. pangea/services/vault/models/symmetric.py +4 -0
  46. pangea/services/vault/vault.py +69 -59
  47. pangea/tools.py +13 -9
  48. pangea/utils.py +3 -5
  49. pangea/verify_audit.py +23 -27
  50. {pangea_sdk-6.2.0b1.dist-info → pangea_sdk-6.3.0.dist-info}/METADATA +36 -17
  51. pangea_sdk-6.3.0.dist-info/RECORD +60 -0
  52. {pangea_sdk-6.2.0b1.dist-info → pangea_sdk-6.3.0.dist-info}/WHEEL +1 -1
  53. pangea/asyncio/services/management.py +0 -576
  54. pangea/services/management.py +0 -720
  55. pangea_sdk-6.2.0b1.dist-info/RECORD +0 -62
pangea/services/authz.py CHANGED
@@ -1,12 +1,16 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
3
4
  from __future__ import annotations
4
5
 
5
6
  import enum
6
- from typing import Any, Dict, List, Optional, Union
7
+ from collections.abc import Mapping, Sequence
8
+ from typing import Annotated, Any, Optional, Union
9
+
10
+ from pydantic import Field
7
11
 
8
12
  from pangea.config import PangeaConfig
9
- from pangea.response import APIRequestModel, APIResponseModel, PangeaResponse, PangeaResponseResult
13
+ from pangea.response import APIRequestModel, APIResponseModel, PangeaDateTime, PangeaResponse, PangeaResponseResult
10
14
  from pangea.services.base import ServiceBase
11
15
 
12
16
 
@@ -43,20 +47,18 @@ class Resource(PangeaResponseResult):
43
47
 
44
48
  class Subject(PangeaResponseResult):
45
49
  type: str
46
- id: Optional[str] = None
47
- action: Optional[str] = None
50
+ id: Annotated[str, Field(pattern="^([a-zA-Z0-9_][a-zA-Z0-9/|_.@-]*)$")]
51
+ action: Annotated[Optional[str], Field(pattern="^([a-zA-Z0-9_][a-zA-Z0-9/|_]*)$")] = None
48
52
 
49
53
 
50
54
  class Tuple(PangeaResponseResult):
51
55
  resource: Resource
52
- relation: str
56
+ relation: Annotated[str, Field(pattern="^([a-zA-Z0-9_][a-zA-Z0-9/|_]*)$")]
53
57
  subject: Subject
54
- expires_at: Optional[str] = None
58
+ expires_at: Optional[PangeaDateTime] = None
55
59
  """A time in ISO-8601 format"""
56
-
57
-
58
- class TupleCreateRequest(APIRequestModel):
59
- tuples: List[Tuple]
60
+ attributes: Optional[dict[str, Any]] = None
61
+ """A JSON object of attribute data."""
60
62
 
61
63
 
62
64
  class TupleCreateResult(PangeaResponseResult):
@@ -66,54 +68,54 @@ class TupleCreateResult(PangeaResponseResult):
66
68
  class TupleListFilter(APIRequestModel):
67
69
  resource_type: Optional[str] = None
68
70
  """Only records where resource type equals this value."""
69
- resource_type__contains: Optional[List[str]] = None
71
+ resource_type__contains: Optional[list[str]] = None
70
72
  """Only records where resource type includes each substring."""
71
- resource_type__in: Optional[List[str]] = None
73
+ resource_type__in: Optional[list[str]] = None
72
74
  """Only records where resource type equals one of the provided substrings."""
73
75
  resource_id: Optional[str] = None
74
76
  """Only records where resource id equals this value."""
75
- resource_id__contains: Optional[List[str]] = None
77
+ resource_id__contains: Optional[list[str]] = None
76
78
  """Only records where resource id includes each substring."""
77
- resource_id__in: Optional[List[str]] = None
79
+ resource_id__in: Optional[list[str]] = None
78
80
  """Only records where resource id equals one of the provided substrings."""
79
81
  relation: Optional[str] = None
80
82
  """Only records where relation equals this value."""
81
- relation__contains: Optional[List[str]] = None
83
+ relation__contains: Optional[list[str]] = None
82
84
  """Only records where relation includes each substring."""
83
- relation__in: Optional[List[str]] = None
85
+ relation__in: Optional[list[str]] = None
84
86
  """Only records where relation equals one of the provided substrings."""
85
87
  subject_type: Optional[str] = None
86
88
  """Only records where subject type equals this value."""
87
- subject_type__contains: Optional[List[str]] = None
89
+ subject_type__contains: Optional[list[str]] = None
88
90
  """Only records where subject type includes each substring."""
89
- subject_type__in: Optional[List[str]] = None
91
+ subject_type__in: Optional[list[str]] = None
90
92
  """Only records where subject type equals one of the provided substrings."""
91
93
  subject_id: Optional[str] = None
92
94
  """Only records where subject id equals this value."""
93
- subject_id__contains: Optional[List[str]] = None
95
+ subject_id__contains: Optional[list[str]] = None
94
96
  """Only records where subject id includes each substring."""
95
- subject_id__in: Optional[List[str]] = None
97
+ subject_id__in: Optional[list[str]] = None
96
98
  """Only records where subject id equals one of the provided substrings."""
97
99
  subject_action: Optional[str] = None
98
100
  """Only records where subject action equals this value."""
99
- subject_action__contains: Optional[List[str]] = None
101
+ subject_action__contains: Optional[list[str]] = None
100
102
  """Only records where subject action includes each substring."""
101
- subject_action__in: Optional[List[str]] = None
103
+ subject_action__in: Optional[list[str]] = None
102
104
  """Only records where subject action equals one of the provided substrings."""
103
- expires_at: Optional[str] = None
105
+ expires_at: Optional[PangeaDateTime] = None
104
106
  """Only records where expires_at equals this value."""
105
- expires_at__gt: Optional[str] = None
107
+ expires_at__gt: Optional[PangeaDateTime] = None
106
108
  """Only records where expires_at is greater than this value."""
107
- expires_at__gte: Optional[str] = None
109
+ expires_at__gte: Optional[PangeaDateTime] = None
108
110
  """Only records where expires_at is greater than or equal to this value."""
109
- expires_at__lt: Optional[str] = None
111
+ expires_at__lt: Optional[PangeaDateTime] = None
110
112
  """Only records where expires_at is less than this value."""
111
- expires_at__lte: Optional[str] = None
113
+ expires_at__lte: Optional[PangeaDateTime] = None
112
114
  """Only records where expires_at is less than or equal to this value."""
113
115
 
114
116
 
115
117
  class TupleListRequest(APIRequestModel):
116
- filter: Optional[Union[Dict, TupleListFilter]] = None
118
+ filter: Optional[Union[dict, TupleListFilter]] = None
117
119
  size: Optional[int] = None
118
120
  last: Optional[str] = None
119
121
  order: Optional[ItemOrder] = None
@@ -121,37 +123,27 @@ class TupleListRequest(APIRequestModel):
121
123
 
122
124
 
123
125
  class TupleListResult(PangeaResponseResult):
124
- tuples: List[Tuple]
126
+ tuples: list[Tuple]
125
127
  last: str
126
128
  count: int
127
129
 
128
130
 
129
131
  class TupleDeleteRequest(APIRequestModel):
130
- tuples: List[Tuple]
132
+ tuples: list[Tuple]
131
133
 
132
134
 
133
135
  class TupleDeleteResult(PangeaResponseResult):
134
136
  pass
135
137
 
136
138
 
137
- class CheckRequest(APIRequestModel):
138
- resource: Resource
139
- action: str
140
- subject: Subject
141
- debug: Optional[bool] = None
142
- """In the event of an allowed check, return a path that granted access."""
143
- attributes: Optional[Dict[str, Any]] = None
144
- """A JSON object of attribute data."""
145
-
146
-
147
139
  class DebugPath(APIResponseModel):
148
- type: str
149
- id: str
140
+ type: Optional[str] = None
141
+ id: Optional[str] = None
150
142
  action: Optional[str] = None
151
143
 
152
144
 
153
145
  class Debug(APIResponseModel):
154
- path: List[DebugPath]
146
+ path: list[DebugPath]
155
147
 
156
148
 
157
149
  class CheckResult(PangeaResponseResult):
@@ -162,27 +154,47 @@ class CheckResult(PangeaResponseResult):
162
154
  debug: Optional[Debug] = None
163
155
 
164
156
 
157
+ class BulkCheckRequestItem(APIRequestModel):
158
+ resource: Resource
159
+ action: Annotated[str, Field(pattern="^([a-zA-Z0-9_][a-zA-Z0-9/|_]*)$")]
160
+ subject: Subject
161
+
162
+
163
+ class BulkCheckItemResult(APIResponseModel):
164
+ checked: str
165
+ allowed: bool
166
+ depth: int
167
+ debug: Optional[Debug] = None
168
+
169
+
170
+ class BulkCheckResult(PangeaResponseResult):
171
+ schema_id: str
172
+ schema_version: int
173
+ allowed: bool
174
+ results: list[BulkCheckItemResult]
175
+
176
+
165
177
  class ListResourcesRequest(APIRequestModel):
166
178
  type: str
167
179
  action: str
168
180
  subject: Subject
169
- attributes: Optional[Dict[str, Any]] = None
181
+ attributes: Optional[dict[str, Any]] = None
170
182
 
171
183
 
172
184
  class ListResourcesResult(PangeaResponseResult):
173
- ids: List[str]
185
+ ids: list[str]
174
186
 
175
187
 
176
188
  class ListSubjectsRequest(APIRequestModel):
177
189
  resource: Resource
178
190
  action: str
179
- attributes: Optional[Dict[str, Any]] = None
191
+ attributes: Optional[dict[str, Any]] = None
180
192
  debug: Optional[bool] = None
181
193
  """Return a path for each found subject"""
182
194
 
183
195
 
184
196
  class ListSubjectsResult(PangeaResponseResult):
185
- subjects: List[Subject]
197
+ subjects: list[Subject]
186
198
 
187
199
 
188
200
  class AuthZ(ServiceBase):
@@ -228,7 +240,7 @@ class AuthZ(ServiceBase):
228
240
 
229
241
  super().__init__(token, config, logger_name, config_id=config_id)
230
242
 
231
- def tuple_create(self, tuples: list[Tuple]) -> PangeaResponse[TupleCreateResult]:
243
+ def tuple_create(self, tuples: Sequence[Tuple]) -> PangeaResponse[TupleCreateResult]:
232
244
  """Create tuples.
233
245
 
234
246
  Create tuples in the AuthZ Service. The request will fail if there is no schema
@@ -243,7 +255,7 @@ class AuthZ(ServiceBase):
243
255
  Returns:
244
256
  Pangea Response with empty result.
245
257
  Available response fields can be found in our
246
- [API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/create).
258
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/create-post).
247
259
 
248
260
  Examples:
249
261
  response = authz.tuple_create(
@@ -257,8 +269,7 @@ class AuthZ(ServiceBase):
257
269
  )
258
270
  """
259
271
 
260
- input_data = TupleCreateRequest(tuples=tuples)
261
- return self.request.post("v1/tuple/create", TupleCreateResult, data=input_data.model_dump(exclude_none=True))
272
+ return self.request.post("v1/tuple/create", TupleCreateResult, data={"tuples": tuples})
262
273
 
263
274
  def tuple_list(
264
275
  self,
@@ -287,7 +298,7 @@ class AuthZ(ServiceBase):
287
298
  Returns:
288
299
  Pangea Response with a list of tuples and the last token.
289
300
  Available response fields can be found in our
290
- [API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/list).
301
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/list-post).
291
302
 
292
303
  Examples:
293
304
  authz.tuple_list(TupleListFilter(subject_type="user", subject_id="user_1"))
@@ -311,7 +322,7 @@ class AuthZ(ServiceBase):
311
322
  Returns:
312
323
  Pangea Response with empty result.
313
324
  Available response fields can be found in our
314
- [API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/delete).
325
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/delete-post).
315
326
 
316
327
  Examples:
317
328
  response = authz.tuple_delete(
@@ -333,8 +344,9 @@ class AuthZ(ServiceBase):
333
344
  resource: Resource,
334
345
  action: str,
335
346
  subject: Subject,
347
+ *,
336
348
  debug: bool | None = None,
337
- attributes: dict[str, Any] | None = None,
349
+ attributes: Mapping[str, Any] | None = None,
338
350
  ) -> PangeaResponse[CheckResult]:
339
351
  """Perform a check request.
340
352
 
@@ -345,7 +357,7 @@ class AuthZ(ServiceBase):
345
357
  action: The action to check.
346
358
  subject: The subject to check.
347
359
  debug: In the event of an allowed check, return a path that granted access.
348
- attributes: Additional attributes for the check.
360
+ attributes: A JSON object of attribute data.
349
361
 
350
362
  Raises:
351
363
  PangeaAPIException: If an API Error happens.
@@ -353,7 +365,7 @@ class AuthZ(ServiceBase):
353
365
  Returns:
354
366
  Pangea Response with the result of the check.
355
367
  Available response fields can be found in our
356
- [API Documentation](https://pangea.cloud/docs/api/authz#/v1/check).
368
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/check-post).
357
369
 
358
370
  Examples:
359
371
  response = authz.check(
@@ -364,8 +376,44 @@ class AuthZ(ServiceBase):
364
376
  )
365
377
  """
366
378
 
367
- input_data = CheckRequest(resource=resource, action=action, subject=subject, debug=debug, attributes=attributes)
368
- return self.request.post("v1/check", CheckResult, data=input_data.model_dump(exclude_none=True))
379
+ return self.request.post(
380
+ "v1/check",
381
+ CheckResult,
382
+ data={"resource": resource, "action": action, "subject": subject, "debug": debug, "attributes": attributes},
383
+ )
384
+
385
+ def bulk_check(
386
+ self,
387
+ checks: Sequence[BulkCheckRequestItem],
388
+ *,
389
+ debug: bool | None = None,
390
+ attributes: Mapping[str, Any] | None = None,
391
+ ) -> PangeaResponse[BulkCheckResult]:
392
+ """Perform a bulk check request
393
+
394
+ Perform multiple checks in a single request to see if a subjects have
395
+ permission to do actions on the resources.
396
+
397
+ Args:
398
+ checks: Check requests to perform.
399
+ debug: In the event of an allowed check, return a path that granted access.
400
+ attributes: A JSON object of attribute data.
401
+
402
+ Examples:
403
+ authz.bulk_check(
404
+ checks=[
405
+ BulkCheckRequestItem(
406
+ resource=Resource(type="file", id="file_1"),
407
+ action="read",
408
+ subject=Subject(type="user", id="user_1", action="read"),
409
+ )
410
+ ]
411
+ )
412
+ """
413
+
414
+ return self.request.post(
415
+ "v1/check/bulk", BulkCheckResult, data={"checks": checks, "debug": debug, "attributes": attributes}
416
+ )
369
417
 
370
418
  def list_resources(
371
419
  self, type: str, action: str, subject: Subject, attributes: dict[str, Any] | None = None
@@ -387,7 +435,7 @@ class AuthZ(ServiceBase):
387
435
  Returns:
388
436
  Pangea Response with a list of resource IDs.
389
437
  Available response fields can be found in our
390
- [API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-resources).
438
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-resources-post).
391
439
 
392
440
  Examples:
393
441
  authz.list_resources(
@@ -422,7 +470,7 @@ class AuthZ(ServiceBase):
422
470
  Returns:
423
471
  Pangea Response with a list of subjects.
424
472
  Available response fields can be found in our
425
- [API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-subjects).
473
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-subjects-post).
426
474
 
427
475
  Examples:
428
476
  response = authz.list_subjects(
pangea/services/base.py CHANGED
@@ -1,10 +1,14 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
+
4
+ # TODO: Modernize.
5
+ # ruff: noqa: UP006, UP035
6
+
3
7
  from __future__ import annotations
4
8
 
5
9
  import copy
6
10
  import logging
7
- from typing import Dict, Optional, Type, Union
11
+ from typing import Optional, Type, Union
8
12
 
9
13
  from typing_extensions import TypeVar
10
14
 
@@ -17,7 +21,7 @@ from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult
17
21
  TResult = TypeVar("TResult", bound=PangeaResponseResult, default=PangeaResponseResult)
18
22
 
19
23
 
20
- class ServiceBase(object):
24
+ class ServiceBase:
21
25
  service_name: str = "base"
22
26
 
23
27
  def __init__(
@@ -43,8 +47,7 @@ class ServiceBase(object):
43
47
  self._token = token
44
48
  self.config_id: Optional[str] = config_id
45
49
  self._request: Optional[Union[PangeaRequest, PangeaRequestAsync]] = None
46
- extra_headers: Dict = {}
47
- self.request.set_extra_headers(extra_headers)
50
+ self.request.set_extra_headers({})
48
51
 
49
52
  @property
50
53
  def token(self) -> str:
@@ -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