pangea-sdk 3.7.0__py3-none-any.whl → 3.8.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.
@@ -1,13 +1,14 @@
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.authn.models as m
8
+ from pangea.asyncio.services.base import ServiceBaseAsync
9
+ from pangea.config import PangeaConfig
7
10
  from pangea.response import PangeaResponse
8
11
 
9
- from .base import ServiceBaseAsync
10
-
11
12
  SERVICE_NAME = "authn"
12
13
 
13
14
 
@@ -38,10 +39,24 @@ class AuthNAsync(ServiceBaseAsync):
38
39
 
39
40
  def __init__(
40
41
  self,
41
- token,
42
- config=None,
43
- logger_name="pangea",
44
- ):
42
+ token: str,
43
+ config: PangeaConfig | None = None,
44
+ logger_name: str = "pangea",
45
+ ) -> None:
46
+ """
47
+ AuthN client
48
+
49
+ Initializes a new AuthN client.
50
+
51
+ Args:
52
+ token: Pangea API token.
53
+ config: Configuration.
54
+ logger_name: Logger name.
55
+
56
+ Examples:
57
+ config = PangeaConfig(domain="pangea_domain")
58
+ authn = AuthNAsync(token="pangea_token", config=config)
59
+ """
45
60
  super().__init__(token, config, logger_name=logger_name)
46
61
  self.user = AuthNAsync.UserAsync(token, config, logger_name=logger_name)
47
62
  self.flow = AuthNAsync.FlowAsync(token, config, logger_name=logger_name)
@@ -54,10 +69,10 @@ class AuthNAsync(ServiceBaseAsync):
54
69
 
55
70
  def __init__(
56
71
  self,
57
- token,
58
- config=None,
59
- logger_name="pangea",
60
- ):
72
+ token: str,
73
+ config: PangeaConfig | None = None,
74
+ logger_name: str = "pangea",
75
+ ) -> None:
61
76
  super().__init__(token, config, logger_name=logger_name)
62
77
 
63
78
  async def invalidate(self, session_id: str) -> PangeaResponse[m.SessionInvalidateResult]:
@@ -114,6 +129,9 @@ class AuthNAsync(ServiceBaseAsync):
114
129
  Examples:
115
130
  response = authn.session.list()
116
131
  """
132
+ if isinstance(filter, dict):
133
+ filter = m.SessionListFilter(**filter)
134
+
117
135
  input = m.SessionListRequest(filter=filter, last=last, order=order, order_by=order_by, size=size)
118
136
  return await self.request.post("v2/session/list", m.SessionListResults, data=input.dict(exclude_none=True))
119
137
 
@@ -146,10 +164,10 @@ class AuthNAsync(ServiceBaseAsync):
146
164
 
147
165
  def __init__(
148
166
  self,
149
- token,
150
- config=None,
151
- logger_name="pangea",
152
- ):
167
+ token: str,
168
+ config: PangeaConfig | None = None,
169
+ logger_name: str = "pangea",
170
+ ) -> None:
153
171
  super().__init__(token, config, logger_name=logger_name)
154
172
  self.session = AuthNAsync.ClientAsync.SessionAsync(token, config, logger_name=logger_name)
155
173
  self.password = AuthNAsync.ClientAsync.PasswordAsync(token, config, logger_name=logger_name)
@@ -206,10 +224,10 @@ class AuthNAsync(ServiceBaseAsync):
206
224
 
207
225
  def __init__(
208
226
  self,
209
- token,
210
- config=None,
211
- logger_name="pangea",
212
- ):
227
+ token: str,
228
+ config: PangeaConfig | None = None,
229
+ logger_name: str = "pangea",
230
+ ) -> None:
213
231
  super().__init__(token, config, logger_name=logger_name)
214
232
 
215
233
  async def invalidate(self, token: str, session_id: str) -> PangeaResponse[m.ClientSessionInvalidateResult]:
@@ -272,6 +290,9 @@ class AuthNAsync(ServiceBaseAsync):
272
290
  token="ptu_wuk7tvtpswyjtlsx52b7yyi2l7zotv4a",
273
291
  )
274
292
  """
293
+ if isinstance(filter, dict):
294
+ filter = m.SessionListFilter(**filter)
295
+
275
296
  input = m.ClientSessionListRequest(
276
297
  token=token, filter=filter, last=last, order=order, order_by=order_by, size=size
277
298
  )
@@ -338,10 +359,10 @@ class AuthNAsync(ServiceBaseAsync):
338
359
 
339
360
  def __init__(
340
361
  self,
341
- token,
342
- config=None,
343
- logger_name="pangea",
344
- ):
362
+ token: str,
363
+ config: PangeaConfig | None = None,
364
+ logger_name: str = "pangea",
365
+ ) -> None:
345
366
  super().__init__(token, config, logger_name=logger_name)
346
367
 
347
368
  async def change(
@@ -379,10 +400,10 @@ class AuthNAsync(ServiceBaseAsync):
379
400
 
380
401
  def __init__(
381
402
  self,
382
- token,
383
- config=None,
384
- logger_name="pangea",
385
- ):
403
+ token: str,
404
+ config: PangeaConfig | None = None,
405
+ logger_name: str = "pangea",
406
+ ) -> None:
386
407
  super().__init__(token, config, logger_name=logger_name)
387
408
 
388
409
  async def check(self, token: str) -> PangeaResponse[m.ClientTokenCheckResult]:
@@ -416,10 +437,10 @@ class AuthNAsync(ServiceBaseAsync):
416
437
 
417
438
  def __init__(
418
439
  self,
419
- token,
420
- config=None,
421
- logger_name="pangea",
422
- ):
440
+ token: str,
441
+ config: PangeaConfig | None = None,
442
+ logger_name: str = "pangea",
443
+ ) -> None:
423
444
  super().__init__(token, config, logger_name=logger_name)
424
445
  self.profile = AuthNAsync.UserAsync.ProfileAsync(token, config, logger_name=logger_name)
425
446
  self.authenticators = AuthNAsync.UserAsync.AuthenticatorsAsync(token, config, logger_name=logger_name)
@@ -593,6 +614,9 @@ class AuthNAsync(ServiceBaseAsync):
593
614
  Examples:
594
615
  response = authn.user.list()
595
616
  """
617
+ if isinstance(filter, dict):
618
+ filter = m.UserListFilter(**filter)
619
+
596
620
  input = m.UserListRequest(
597
621
  filter=filter,
598
622
  last=last,
@@ -607,10 +631,10 @@ class AuthNAsync(ServiceBaseAsync):
607
631
 
608
632
  def __init__(
609
633
  self,
610
- token,
611
- config=None,
612
- logger_name="pangea",
613
- ):
634
+ token: str,
635
+ config: PangeaConfig | None = None,
636
+ logger_name: str = "pangea",
637
+ ) -> None:
614
638
  super().__init__(token, config, logger_name=logger_name)
615
639
 
616
640
  async def list(
@@ -642,6 +666,9 @@ class AuthNAsync(ServiceBaseAsync):
642
666
  Examples:
643
667
  response = authn.user.invites.list()
644
668
  """
669
+ if isinstance(filter, dict):
670
+ filter = m.UserInviteListFilter(**filter)
671
+
645
672
  input = m.UserInviteListRequest(filter=filter, last=last, order=order, order_by=order_by, size=size)
646
673
  return await self.request.post(
647
674
  "v2/user/invite/list", m.UserInviteListResult, data=input.dict(exclude_none=True)
@@ -676,10 +703,10 @@ class AuthNAsync(ServiceBaseAsync):
676
703
 
677
704
  def __init__(
678
705
  self,
679
- token,
680
- config=None,
681
- logger_name="pangea",
682
- ):
706
+ token: str,
707
+ config: PangeaConfig | None = None,
708
+ logger_name: str = "pangea",
709
+ ) -> None:
683
710
  super().__init__(token, config, logger_name=logger_name)
684
711
 
685
712
  async def delete(
@@ -747,10 +774,10 @@ class AuthNAsync(ServiceBaseAsync):
747
774
 
748
775
  def __init__(
749
776
  self,
750
- token,
751
- config=None,
752
- logger_name="pangea",
753
- ):
777
+ token: str,
778
+ config: PangeaConfig | None = None,
779
+ logger_name: str = "pangea",
780
+ ) -> None:
754
781
  super().__init__(token, config, logger_name=logger_name)
755
782
 
756
783
  async def get(
@@ -827,10 +854,10 @@ class AuthNAsync(ServiceBaseAsync):
827
854
 
828
855
  def __init__(
829
856
  self,
830
- token,
831
- config=None,
832
- logger_name="pangea",
833
- ):
857
+ token: str,
858
+ config: PangeaConfig | None = None,
859
+ logger_name: str = "pangea",
860
+ ) -> None:
834
861
  super().__init__(token, config, logger_name=logger_name)
835
862
 
836
863
  async def complete(self, flow_id: str) -> PangeaResponse[m.FlowCompleteResult]:
@@ -967,10 +994,10 @@ class AuthNAsync(ServiceBaseAsync):
967
994
 
968
995
  def __init__(
969
996
  self,
970
- token,
971
- config=None,
972
- logger_name="pangea",
973
- ):
997
+ token: str,
998
+ config: PangeaConfig | None = None,
999
+ logger_name: str = "pangea",
1000
+ ) -> None:
974
1001
  super().__init__(token, config, logger_name=logger_name)
975
1002
 
976
1003
  async def create(
@@ -1064,6 +1091,8 @@ class AuthNAsync(ServiceBaseAsync):
1064
1091
  Examples:
1065
1092
  response = authn.agreements.list()
1066
1093
  """
1094
+ if isinstance(filter, dict):
1095
+ filter = m.AgreementListFilter(**filter)
1067
1096
 
1068
1097
  input = m.AgreementListRequest(filter=filter, last=last, order=order, order_by=order_by, size=size)
1069
1098
  return await self.request.post(
@@ -0,0 +1,259 @@
1
+ # Copyright 2022 Pangea Cyber Corporation
2
+ # Author: Pangea Cyber Corporation
3
+
4
+ from typing import Dict, List, Optional, Union
5
+
6
+ from pangea.asyncio.services.base import ServiceBaseAsync
7
+ from pangea.response import PangeaResponse
8
+ from pangea.services.authz import (
9
+ CheckRequest,
10
+ CheckResult,
11
+ ItemOrder,
12
+ ListResourcesRequest,
13
+ ListResourcesResult,
14
+ ListSubjectsRequest,
15
+ ListSubjectsResult,
16
+ Resource,
17
+ Subject,
18
+ Tuple,
19
+ TupleCreateRequest,
20
+ TupleCreateResult,
21
+ TupleDeleteRequest,
22
+ TupleDeleteResult,
23
+ TupleListFilter,
24
+ TupleListRequest,
25
+ TupleListResult,
26
+ TupleOrderBy,
27
+ )
28
+
29
+
30
+ class AuthZAsync(ServiceBaseAsync):
31
+ """AuthZ service client. (Beta)
32
+
33
+ Provides methods to interact with the Pangea AuthZ Service.
34
+ Documentation for the AuthZ Service API can be found at
35
+ <https://pangea.cloud/docs/api/authz>. Note that this service is in Beta and
36
+ is subject to change.
37
+
38
+ Examples:
39
+ import os
40
+ from pangea.config import PangeaConfig
41
+ from pangea.services import AuthZ
42
+
43
+ PANGEA_TOKEN = os.getenv("PANGEA_AUTHZ_TOKEN")
44
+
45
+ authz_config = PangeaConfig(domain="aws.us.pangea.cloud")
46
+
47
+ # Setup Pangea AuthZ service client
48
+ authz = AuthZAsync(token=PANGEA_TOKEN, config=authz_config)
49
+ """
50
+
51
+ service_name = "authz"
52
+
53
+ def __init__(self, token: str, config=None, logger_name="pangea", config_id: Optional[str] = None):
54
+ super().__init__(token, config, logger_name, config_id=config_id)
55
+
56
+ async def tuple_create(self, tuples: List[Tuple]) -> PangeaResponse[TupleCreateResult]:
57
+ """Create tuples. (Beta)
58
+
59
+ Create tuples in the AuthZ Service. The request will fail if there is no schema
60
+ or the tuples do not validate against the schema.
61
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
62
+
63
+ Args:
64
+ tuples (List[Tuple]): List of tuples to be created.
65
+
66
+ Raises:
67
+ PangeaAPIException: If an API Error happens.
68
+
69
+ Returns:
70
+ Pangea Response with empty result.
71
+ Available response fields can be found in our
72
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/create).
73
+
74
+ Examples:
75
+ await authz.tuple_create(
76
+ tuples=[
77
+ Tuple(
78
+ resource=Resource(type="file", id="file_1"),
79
+ relation="owner",
80
+ subject=Subject(type="user", id="user_1"),
81
+ )
82
+ ]
83
+ )
84
+ """
85
+
86
+ input_data = TupleCreateRequest(tuples=tuples)
87
+ return await self.request.post("v1/tuple/create", TupleCreateResult, data=input_data.dict(exclude_none=True))
88
+
89
+ async def tuple_list(
90
+ self,
91
+ filter: TupleListFilter,
92
+ size: Optional[int] = None,
93
+ last: Optional[str] = None,
94
+ order: Optional[ItemOrder] = None,
95
+ order_by: Optional[TupleOrderBy] = None,
96
+ ) -> PangeaResponse[TupleListResult]:
97
+ """List tuples. (Beta)
98
+
99
+ Return a paginated list of filtered tuples. The filter is given in terms
100
+ of a tuple. Fill out the fields that you want to filter. If the filter
101
+ is empty it will return all the tuples.
102
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
103
+
104
+ Args:
105
+ filter (TupleListFilter): The filter for listing tuples.
106
+ size (Optional[int]): The size of the result set. Default is None.
107
+ last (Optional[str]): The last token from a previous response. Default is None.
108
+ order (Optional[ItemOrder]): Order results asc(ending) or desc(ending).
109
+ order_by (Optional[TupleOrderBy]): Which field to order results by.
110
+
111
+ Raises:
112
+ PangeaAPIException: If an API Error happens.
113
+
114
+ Returns:
115
+ Pangea Response with a list of tuples and the last token.
116
+ Available response fields can be found in our
117
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/list).
118
+
119
+ Examples:
120
+ await authz.tuple_list(TupleListFilter(subject_type="user", subject_id="user_1"))
121
+ """
122
+ input_data = TupleListRequest(
123
+ filter=filter.dict(exclude_none=True), size=size, last=last, order=order, order_by=order_by
124
+ )
125
+ return await self.request.post("v1/tuple/list", TupleListResult, data=input_data.dict(exclude_none=True))
126
+
127
+ async def tuple_delete(self, tuples: List[Tuple]) -> PangeaResponse[TupleDeleteResult]:
128
+ """Delete tuples. (Beta)
129
+
130
+ Delete tuples in the AuthZ Service.
131
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
132
+
133
+ Args:
134
+ tuples (List[Tuple]): List of tuples to be deleted.
135
+
136
+ Raises:
137
+ PangeaAPIException: If an API Error happens.
138
+
139
+ Returns:
140
+ Pangea Response with empty result.
141
+ Available response fields can be found in our
142
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/tuple/delete).
143
+
144
+ Examples:
145
+ await authz.tuple_delete(
146
+ tuples=[
147
+ Tuple(
148
+ resource=Resource(type="file", id="file_1"),
149
+ relation="owner",
150
+ subject=Subject(type="user", id="user_1"),
151
+ )
152
+ ]
153
+ )
154
+ """
155
+
156
+ input_data = TupleDeleteRequest(tuples=tuples)
157
+ return await self.request.post("v1/tuple/delete", TupleDeleteResult, data=input_data.dict(exclude_none=True))
158
+
159
+ async def check(
160
+ self,
161
+ resource: Resource,
162
+ action: str,
163
+ subject: Subject,
164
+ debug: Optional[bool] = None,
165
+ attributes: Optional[Dict[str, Union[int, str]]] = None,
166
+ ) -> PangeaResponse[CheckResult]:
167
+ """Perform a check request. (Beta)
168
+
169
+ Check if a subject has permission to perform an action on the resource.
170
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
171
+
172
+ Args:
173
+ resource (Resource): The resource to check.
174
+ action (str): The action to check.
175
+ subject (Subject): The subject to check.
176
+ debug (Optional[bool]): Setting this value to True will provide a detailed analysis of the check.
177
+ attributes (Optional[Dict[str, Union[int, str]]]): Additional attributes for the check.
178
+
179
+ Raises:
180
+ PangeaAPIException: If an API Error happens.
181
+
182
+ Returns:
183
+ Pangea Response with the result of the check.
184
+ Available response fields can be found in our
185
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/check).
186
+
187
+ Examples:
188
+ await authz.check(
189
+ resource=Resource(type="file", id="file_1"),
190
+ action="update",
191
+ subject=Subject(type="user", id="user_1"),
192
+ debug=True,
193
+ )
194
+ """
195
+
196
+ input_data = CheckRequest(resource=resource, action=action, subject=subject, debug=debug, attributes=attributes)
197
+ return await self.request.post("v1/check", CheckResult, data=input_data.dict(exclude_none=True))
198
+
199
+ async def list_resources(self, type: str, action: str, subject: Subject) -> PangeaResponse[ListResourcesResult]:
200
+ """List resources. (Beta)
201
+
202
+ Given a type, action, and subject, list all the resources in the
203
+ type that the subject has access to the action with.
204
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
205
+
206
+ Args:
207
+ type (str): The type to filter resources.
208
+ action (str): The action to filter resources.
209
+ subject (Subject): The subject to filter resources.
210
+
211
+ Raises:
212
+ PangeaAPIException: If an API Error happens.
213
+
214
+ Returns:
215
+ Pangea Response with a list of resource IDs.
216
+ Available response fields can be found in our
217
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-resources).
218
+
219
+ Examples:
220
+ await authz.list_resources(
221
+ type="file",
222
+ action="update",
223
+ subject=Subject(type="user", id="user_1"),
224
+ )
225
+ """
226
+
227
+ input_data = ListResourcesRequest(type=type, action=action, subject=subject)
228
+ return await self.request.post(
229
+ "v1/list-resources", ListResourcesResult, data=input_data.dict(exclude_none=True)
230
+ )
231
+
232
+ async def list_subjects(self, resource: Resource, action: str) -> PangeaResponse[ListSubjectsResult]:
233
+ """List subjects. (Beta)
234
+
235
+ Given a resource and an action, return the list of subjects who have
236
+ access to the action for the given resource.
237
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
238
+
239
+ Args:
240
+ resource (Resource): The resource to filter subjects.
241
+ action (str): The action to filter subjects.
242
+
243
+ Raises:
244
+ PangeaAPIException: If an API Error happens.
245
+
246
+ Returns:
247
+ Pangea Response with a list of subjects.
248
+ Available response fields can be found in our
249
+ [API Documentation](https://pangea.cloud/docs/api/authz#/v1/list-subjects).
250
+
251
+ Examples:
252
+ await authz.list_subjects(
253
+ resource=Resource(type="file", id="file_1"),
254
+ action="update",
255
+ )
256
+ """
257
+
258
+ input_data = ListSubjectsRequest(resource=resource, action=action)
259
+ return await self.request.post("v1/list-subjects", ListSubjectsResult, data=input_data.dict(exclude_none=True))
@@ -1,18 +1,18 @@
1
1
  # Copyright 2022 Pangea Cyber Corporation
2
2
  # Author: Pangea Cyber Corporation
3
3
 
4
- from typing import Optional, Type, Union
4
+ from typing import Dict, Optional, Type, Union
5
5
 
6
6
  from pangea.asyncio.request import PangeaRequestAsync
7
7
  from pangea.exceptions import AcceptedRequestException
8
- from pangea.response import PangeaResponse, PangeaResponseResult
9
- from pangea.services.base import ServiceBase
8
+ from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult
9
+ from pangea.services.base import PangeaRequest, ServiceBase
10
10
 
11
11
 
12
12
  class ServiceBaseAsync(ServiceBase):
13
13
  @property
14
- def request(self):
15
- if not self._request:
14
+ def request(self) -> PangeaRequestAsync: # type: ignore[override]
15
+ if self._request is None or isinstance(self._request, PangeaRequest):
16
16
  self._request = PangeaRequestAsync(
17
17
  config=self.config,
18
18
  token=self.token,
@@ -28,7 +28,7 @@ class ServiceBaseAsync(ServiceBase):
28
28
  exception: Optional[AcceptedRequestException] = None,
29
29
  response: Optional[PangeaResponse] = None,
30
30
  request_id: Optional[str] = None,
31
- result_class: Union[Type[PangeaResponseResult], dict] = dict, # type: ignore[assignment]
31
+ result_class: Union[Type[PangeaResponseResult], Type[Dict]] = dict,
32
32
  ) -> PangeaResponse:
33
33
  """
34
34
  Poll result
@@ -58,6 +58,9 @@ class ServiceBaseAsync(ServiceBase):
58
58
  else:
59
59
  raise AttributeError("Need to set exception, response or request_id")
60
60
 
61
+ async def download_file(self, url: str, filename: Optional[str] = None) -> AttachedFile: # type: ignore[override]
62
+ return await self.request.download_file(url=url, filename=filename)
63
+
61
64
  async def close(self):
62
65
  await self.request.session.close()
63
66
  # Loop over all attributes to check if they are derived from ServiceBaseAsync and close them
@@ -2,16 +2,15 @@
2
2
  # Author: Pangea Cyber Corporation
3
3
  import io
4
4
  import logging
5
- from typing import Dict, Optional
5
+ from typing import Dict, List, Optional, Tuple
6
6
 
7
7
  import pangea.services.file_scan as m
8
8
  from pangea.asyncio.request import PangeaRequestAsync
9
+ from pangea.asyncio.services.base import ServiceBaseAsync
9
10
  from pangea.request import PangeaConfig
10
11
  from pangea.response import PangeaResponse, TransferMethod
11
12
  from pangea.utils import FileUploadParams, get_file_upload_params
12
13
 
13
- from .base import ServiceBaseAsync
14
-
15
14
 
16
15
  class FileScanAsync(ServiceBaseAsync):
17
16
  """FileScan service client.
@@ -96,7 +95,7 @@ class FileScanAsync(ServiceBaseAsync):
96
95
  size = params.size
97
96
  else:
98
97
  crc, sha, size = None, None, None
99
- files = [("upload", ("filename", file, "application/octet-stream"))]
98
+ files: List[Tuple] = [("upload", ("filename", file, "application/octet-stream"))]
100
99
  else:
101
100
  raise ValueError("Need to set file_path or file arguments")
102
101
 
@@ -4,11 +4,10 @@ import hashlib
4
4
  from typing import List, Optional
5
5
 
6
6
  import pangea.services.intel as m
7
+ from pangea.asyncio.services.base import ServiceBaseAsync
7
8
  from pangea.response import PangeaResponse
8
9
  from pangea.utils import hash_256_filepath
9
10
 
10
- from .base import ServiceBaseAsync
11
-
12
11
 
13
12
  class FileIntelAsync(ServiceBaseAsync):
14
13
  """File Intel service client
@@ -77,7 +76,7 @@ class FileIntelAsync(ServiceBaseAsync):
77
76
  provider: Optional[str] = None,
78
77
  verbose: Optional[bool] = None,
79
78
  raw: Optional[bool] = None,
80
- ) -> PangeaResponse[m.FileReputationResult]:
79
+ ) -> PangeaResponse[m.FileReputationBulkResult]:
81
80
  """
82
81
  Reputation check
83
82
 
@@ -183,7 +182,7 @@ class FileIntelAsync(ServiceBaseAsync):
183
182
  hash = hash_256_filepath(filepath)
184
183
  hashes.append(hash)
185
184
 
186
- return await self.hash_reputation_bulk( # type: ignore[return-value]
185
+ return await self.hash_reputation_bulk(
187
186
  hashes=hashes, hash_type="sha256", verbose=verbose, raw=raw, provider=provider
188
187
  )
189
188
 
@@ -252,7 +251,7 @@ class DomainIntelAsync(ServiceBaseAsync):
252
251
  verbose: Optional[bool] = None,
253
252
  raw: Optional[bool] = None,
254
253
  provider: Optional[str] = None,
255
- ) -> PangeaResponse[m.DomainReputationResult]:
254
+ ) -> PangeaResponse[m.DomainReputationBulkResult]:
256
255
  """
257
256
  Reputation
258
257
 
@@ -374,7 +373,7 @@ class IpIntelAsync(ServiceBaseAsync):
374
373
 
375
374
  async def reputation_bulk(
376
375
  self, ips: List[str], verbose: Optional[bool] = None, raw: Optional[bool] = None, provider: Optional[str] = None
377
- ) -> PangeaResponse[m.IPReputationResult]:
376
+ ) -> PangeaResponse[m.IPReputationBulkResult]:
378
377
  """
379
378
  Reputation
380
379
 
@@ -1,13 +1,14 @@
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
8
+ from pangea.asyncio.services.base import ServiceBaseAsync
9
+ from pangea.config import PangeaConfig
7
10
  from pangea.response import PangeaResponse
8
11
 
9
- from .base import ServiceBaseAsync
10
-
11
12
 
12
13
  class RedactAsync(ServiceBaseAsync):
13
14
  """Redact service client.
@@ -36,7 +37,24 @@ class RedactAsync(ServiceBaseAsync):
36
37
 
37
38
  service_name = "redact"
38
39
 
39
- 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
+
40
58
  super().__init__(token, config, logger_name, config_id=config_id)
41
59
 
42
60
  async def redact(