pangea-sdk 6.2.0b2__py3-none-any.whl → 6.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__ = "6.2.0beta2"
1
+ __version__ = "6.4.0"
2
2
 
3
3
  from pangea.asyncio.request import PangeaRequestAsync
4
4
  from pangea.config import PangeaConfig
pangea/asyncio/request.py CHANGED
@@ -10,13 +10,13 @@ import asyncio
10
10
  import json
11
11
  import time
12
12
  from collections.abc import Iterable, Mapping
13
- from typing import Dict, List, Optional, Sequence, Tuple, Type, Union, cast, overload
13
+ from typing import Dict, List, Optional, Sequence, Tuple, Type, Union, cast
14
14
 
15
15
  import aiohttp
16
16
  from aiohttp import FormData
17
- from pydantic import BaseModel, TypeAdapter
17
+ from pydantic import BaseModel
18
18
  from pydantic_core import to_jsonable_python
19
- from typing_extensions import Any, Literal, TypeAlias, TypeVar, override
19
+ from typing_extensions import Any, TypeAlias, TypeVar, override
20
20
 
21
21
  import pangea.exceptions as pe
22
22
  from pangea.request import MultipartResponse, PangeaRequestBase
@@ -32,6 +32,10 @@ _FileSpecTuple3: TypeAlias = tuple[_FileName, _FileContent, _FileContentType]
32
32
  _FileSpecTuple4: TypeAlias = tuple[_FileName, _FileContent, _FileContentType, _FileCustomHeaders]
33
33
  _FileSpec: TypeAlias = Union[_FileContent, _FileSpecTuple2, _FileSpecTuple3, _FileSpecTuple4]
34
34
  _Files: TypeAlias = Union[Mapping[str, _FileSpec], Iterable[tuple[str, _FileSpec]]]
35
+ _LooseHeaders = Union[
36
+ Mapping[str, str],
37
+ Iterable[tuple[str, str]],
38
+ ]
35
39
 
36
40
 
37
41
  TResult = TypeVar("TResult", bound=PangeaResponseResult)
@@ -46,24 +50,6 @@ class PangeaRequestAsync(PangeaRequestBase):
46
50
  be set in PangeaConfig.
47
51
  """
48
52
 
49
- async def delete(self, endpoint: str) -> None:
50
- """
51
- Makes a DELETE call to a Pangea endpoint.
52
-
53
- Args:
54
- endpoint: The Pangea API endpoint.
55
- """
56
-
57
- url = self._url(endpoint)
58
-
59
- self.logger.debug(
60
- json.dumps({"service": self.service, "action": "delete", "url": url}, default=default_encoder)
61
- )
62
-
63
- requests_response = await self._http_delete(url, headers=self._headers())
64
- await self._check_http_errors(requests_response)
65
-
66
- @overload
67
53
  async def post(
68
54
  self,
69
55
  endpoint: str,
@@ -72,60 +58,18 @@ class PangeaRequestAsync(PangeaRequestBase):
72
58
  files: Optional[List[Tuple]] = None,
73
59
  poll_result: bool = True,
74
60
  url: Optional[str] = None,
75
- *,
76
- pangea_response: Literal[True] = True,
77
61
  ) -> PangeaResponse[TResult]:
78
- """
79
- Makes a POST call to a Pangea Service endpoint.
62
+ """Makes the POST call to a Pangea Service endpoint.
80
63
 
81
64
  Args:
82
- endpoint: The Pangea Service API endpoint.
83
- data: The POST body payload object
65
+ endpoint(str): The Pangea Service API endpoint.
66
+ data(dict): The POST body payload object
84
67
 
85
68
  Returns:
86
69
  PangeaResponse which contains the response in its entirety and
87
70
  various properties to retrieve individual fields
88
71
  """
89
72
 
90
- @overload
91
- async def post(
92
- self,
93
- endpoint: str,
94
- result_class: Type[TResult],
95
- data: str | BaseModel | Mapping[str, Any] | None = None,
96
- files: Optional[List[Tuple]] = None,
97
- poll_result: bool = True,
98
- url: Optional[str] = None,
99
- *,
100
- pangea_response: Literal[False],
101
- ) -> TResult:
102
- """
103
- Makes a POST call to a Pangea Service endpoint.
104
-
105
- Args:
106
- endpoint: The Pangea Service API endpoint.
107
- data: The POST body payload object
108
- """
109
-
110
- async def post(
111
- self,
112
- endpoint: str,
113
- result_class: Type[TResult],
114
- data: str | BaseModel | Mapping[str, Any] | None = None,
115
- files: Optional[List[Tuple]] = None,
116
- poll_result: bool = True,
117
- url: Optional[str] = None,
118
- *,
119
- pangea_response: bool = True,
120
- ) -> PangeaResponse[TResult] | TResult:
121
- """
122
- Makes a POST call to a Pangea Service endpoint.
123
-
124
- Args:
125
- endpoint: The Pangea Service API endpoint.
126
- data: The POST body payload object
127
- """
128
-
129
73
  if isinstance(data, BaseModel):
130
74
  data = data.model_dump(exclude_none=True)
131
75
 
@@ -165,13 +109,9 @@ class PangeaRequestAsync(PangeaRequestBase):
165
109
 
166
110
  await self._check_http_errors(requests_response)
167
111
 
168
- if not pangea_response:
169
- type_adapter = TypeAdapter(result_class)
170
- return type_adapter.validate_python(await requests_response.json())
171
-
172
112
  if "multipart/form-data" in requests_response.headers.get("content-type", ""):
173
113
  multipart_response = await self._process_multipart_response(requests_response)
174
- pangea_response_obj: PangeaResponse = PangeaResponse(
114
+ pangea_response: PangeaResponse = PangeaResponse(
175
115
  requests_response,
176
116
  result_class=result_class,
177
117
  json=multipart_response.pangea_json,
@@ -184,110 +124,49 @@ class PangeaRequestAsync(PangeaRequestBase):
184
124
  json.dumps({"service": self.service, "action": "post", "url": url, "response": json_resp})
185
125
  )
186
126
 
187
- pangea_response_obj = PangeaResponse(requests_response, result_class=result_class, json=json_resp)
127
+ pangea_response = PangeaResponse(requests_response, result_class=result_class, json=json_resp)
188
128
  except aiohttp.ContentTypeError as e:
189
129
  raise pe.PangeaException(
190
130
  f"Failed to decode json response. {e}. Body: {await requests_response.text()}"
191
131
  ) from e
192
132
 
193
133
  if poll_result:
194
- pangea_response_obj = await self._handle_queued_result(pangea_response_obj)
134
+ pangea_response = await self._handle_queued_result(pangea_response)
195
135
 
196
- return self._check_response(pangea_response_obj)
136
+ return self._check_response(pangea_response)
197
137
 
198
- @overload
199
- async def get(
200
- self,
201
- path: str,
202
- result_class: Type[TResult],
203
- check_response: bool = True,
204
- *,
205
- params: (
206
- Mapping[str | bytes | int | float, str | bytes | int | float | Iterable[str | bytes | int | float] | None]
207
- | None
208
- ) = None,
209
- pangea_response: Literal[True] = True,
210
- ) -> PangeaResponse[TResult]:
211
- """
212
- Makes the GET call to a Pangea Service endpoint.
138
+ async def get(self, path: str, result_class: Type[TResult], check_response: bool = True) -> PangeaResponse[TResult]:
139
+ """Makes the GET call to a Pangea Service endpoint.
213
140
 
214
141
  Args:
215
- path: Additional URL path
216
- params: Dictionary of querystring data to attach to the request
142
+ endpoint(str): The Pangea Service API endpoint.
143
+ path(str): Additional URL path
217
144
 
218
145
  Returns:
219
146
  PangeaResponse which contains the response in its entirety and
220
147
  various properties to retrieve individual fields
221
148
  """
222
149
 
223
- @overload
224
- async def get(
225
- self,
226
- path: str,
227
- result_class: Type[TResult],
228
- check_response: bool = True,
229
- *,
230
- params: (
231
- Mapping[str | bytes | int | float, str | bytes | int | float | Iterable[str | bytes | int | float] | None]
232
- | None
233
- ) = None,
234
- pangea_response: Literal[False] = False,
235
- ) -> TResult:
236
- """
237
- Makes the GET call to a Pangea Service endpoint.
238
-
239
- Args:
240
- path: Additional URL path
241
- params: Dictionary of querystring data to attach to the request
242
- """
243
-
244
- async def get(
245
- self,
246
- path: str,
247
- result_class: Type[TResult],
248
- check_response: bool = True,
249
- *,
250
- params: (
251
- Mapping[str | bytes | int | float, str | bytes | int | float | Iterable[str | bytes | int | float] | None]
252
- | None
253
- ) = None,
254
- pangea_response: bool = True,
255
- ) -> PangeaResponse[TResult] | TResult:
256
- """
257
- Makes the GET call to a Pangea Service endpoint.
258
-
259
- Args:
260
- path: Additional URL path
261
- params: Dictionary of querystring data to attach to the request
262
- pangea_response: Whether or not the response body follows Pangea's
263
- standard response schema
264
- """
265
-
266
150
  url = self._url(path)
267
151
  self.logger.debug(json.dumps({"service": self.service, "action": "get", "url": url}))
268
152
 
269
- async with self.session.get(url, params=params, headers=self._headers()) as requests_response:
153
+ async with self.session.get(url, headers=self._headers()) as requests_response:
270
154
  await self._check_http_errors(requests_response)
271
-
272
- if not pangea_response:
273
- type_adapter = TypeAdapter(result_class)
274
- return type_adapter.validate_python(await requests_response.json())
275
-
276
- pangea_response_obj = PangeaResponse(
155
+ pangea_response = PangeaResponse(
277
156
  requests_response, result_class=result_class, json=await requests_response.json()
278
157
  )
279
158
 
280
159
  self.logger.debug(
281
160
  json.dumps(
282
- {"service": self.service, "action": "get", "url": url, "response": pangea_response_obj.json},
161
+ {"service": self.service, "action": "get", "url": url, "response": pangea_response.json},
283
162
  default=default_encoder,
284
163
  )
285
164
  )
286
165
 
287
166
  if check_response is False:
288
- return pangea_response_obj
167
+ return pangea_response
289
168
 
290
- return self._check_response(pangea_response_obj)
169
+ return self._check_response(pangea_response)
291
170
 
292
171
  async def _check_http_errors(self, resp: aiohttp.ClientResponse):
293
172
  if resp.status == 503:
@@ -421,18 +300,10 @@ class PangeaRequestAsync(PangeaRequestBase):
421
300
  attached_files = await self._get_attached_files(multipart_reader)
422
301
  return MultipartResponse(pangea_json, attached_files) # type: ignore[arg-type]
423
302
 
424
- async def _http_delete(
425
- self,
426
- url: str,
427
- *,
428
- headers: Mapping[str, str | bytes | None] = {},
429
- ) -> aiohttp.ClientResponse:
430
- return await self.session.delete(url, headers=headers)
431
-
432
303
  async def _http_post(
433
304
  self,
434
305
  url: str,
435
- headers: Mapping[str, str] = {},
306
+ headers: _LooseHeaders = {}, # noqa: B006
436
307
  data: str | dict[str, Any] | None = None,
437
308
  files: _Files | None = None,
438
309
  presigned_url_post: bool = False,
@@ -469,7 +340,7 @@ class PangeaRequestAsync(PangeaRequestBase):
469
340
  self,
470
341
  url: str,
471
342
  files: Sequence[Tuple],
472
- headers: Mapping[str, str] = {},
343
+ headers: _LooseHeaders = {}, # noqa: B006
473
344
  ) -> aiohttp.ClientResponse:
474
345
  self.logger.debug(
475
346
  json.dumps({"service": self.service, "action": "http_put", "url": url}, default=default_encoder)
@@ -7,7 +7,6 @@ from .authz import AuthZAsync
7
7
  from .embargo import EmbargoAsync
8
8
  from .file_scan import FileScanAsync
9
9
  from .intel import DomainIntelAsync, FileIntelAsync, IpIntelAsync, UrlIntelAsync, UserIntelAsync
10
- from .management import ManagementAsync
11
10
  from .prompt_guard import PromptGuardAsync
12
11
  from .redact import RedactAsync
13
12
  from .sanitize import SanitizeAsync
@@ -1,26 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Mapping
3
+ from collections.abc import Sequence
4
4
  from typing import overload
5
5
 
6
- from typing_extensions import Literal, TypeVar
7
-
8
6
  from pangea.asyncio.services.base import ServiceBaseAsync
9
7
  from pangea.config import PangeaConfig
10
8
  from pangea.response import PangeaResponse
11
- from pangea.services.ai_guard import (
12
- AuditDataActivityConfig,
13
- ConnectionsConfig,
14
- LogFields,
15
- Overrides,
16
- RecipeConfig,
17
- ServiceConfig,
18
- ServiceConfigFilter,
19
- ServiceConfigsPage,
20
- TextGuardResult,
21
- )
22
-
23
- _T = TypeVar("_T")
9
+ from pangea.services.ai_guard import LogFields, Message, Overrides, TextGuardResult
24
10
 
25
11
 
26
12
  class AIGuardAsync(ServiceBaseAsync):
@@ -29,11 +15,9 @@ class AIGuardAsync(ServiceBaseAsync):
29
15
  Provides methods to interact with Pangea's AI Guard service.
30
16
 
31
17
  Examples:
32
- from pangea import PangeaConfig
33
18
  from pangea.asyncio.services import AIGuardAsync
34
19
 
35
- config = PangeaConfig(domain="aws.us.pangea.cloud")
36
- ai_guard = AIGuardAsync(token="pangea_token", config=config)
20
+ ai_guard = AIGuardAsync(token="pangea_token")
37
21
  """
38
22
 
39
23
  service_name = "ai-guard"
@@ -53,11 +37,9 @@ class AIGuardAsync(ServiceBaseAsync):
53
37
  config_id: Configuration ID.
54
38
 
55
39
  Examples:
56
- from pangea import PangeaConfig
57
40
  from pangea.asyncio.services import AIGuardAsync
58
41
 
59
- config = PangeaConfig(domain="aws.us.pangea.cloud")
60
- ai_guard = AIGuardAsync(token="pangea_token", config=config)
42
+ ai_guard = AIGuardAsync(token="pangea_token")
61
43
  """
62
44
 
63
45
  super().__init__(token, config, logger_name, config_id)
@@ -67,29 +49,31 @@ class AIGuardAsync(ServiceBaseAsync):
67
49
  self,
68
50
  text: str,
69
51
  *,
70
- recipe: str | None = None,
71
52
  debug: bool | None = None,
72
- overrides: Overrides | None = None,
73
53
  log_fields: LogFields | None = None,
74
- ) -> PangeaResponse[TextGuardResult[None]]:
54
+ overrides: Overrides | None = None,
55
+ recipe: str | None = None,
56
+ ) -> PangeaResponse[TextGuardResult]:
75
57
  """
76
- Text Guard for scanning LLM inputs and outputs
58
+ Guard LLM input and output text
77
59
 
78
- Analyze and redact text to avoid manipulation of the model, addition of
79
- malicious content, and other undesirable data transfers.
60
+ Detect, remove, or block malicious content and intent in LLM inputs and
61
+ outputs to prevent model manipulation and data leakage.
80
62
 
81
63
  OperationId: ai_guard_post_v1_text_guard
82
64
 
83
65
  Args:
84
66
  text: Text to be scanned by AI Guard for PII, sensitive data,
85
67
  malicious content, and other data types defined by the
86
- configuration. Supports processing up to 10KB of text.
87
- recipe: Recipe key of a configuration of data types and settings
88
- defined in the Pangea User Console. It specifies the rules that
89
- are to be applied to the text, such as defang malicious URLs.
68
+ configuration. Supports processing up to 20 KiB of text.
90
69
  debug: Setting this value to true will provide a detailed analysis
91
70
  of the text data
92
71
  log_field: Additional fields to include in activity log
72
+ overrides: Overrides flags. Note: This parameter has no effect when
73
+ the request is made by AIDR
74
+ recipe: Recipe key of a configuration of data types and settings
75
+ defined in the Pangea User Console. It specifies the rules that
76
+ are to be applied to the text, such as defang malicious URLs.
93
77
 
94
78
  Examples:
95
79
  response = await ai_guard.guard_text("text")
@@ -99,51 +83,53 @@ class AIGuardAsync(ServiceBaseAsync):
99
83
  async def guard_text(
100
84
  self,
101
85
  *,
102
- messages: _T,
86
+ messages: Sequence[Message],
103
87
  recipe: str | None = None,
104
88
  debug: bool | None = None,
105
89
  overrides: Overrides | None = None,
106
90
  log_fields: LogFields | None = None,
107
- ) -> PangeaResponse[TextGuardResult[_T]]:
91
+ ) -> PangeaResponse[TextGuardResult]:
108
92
  """
109
- Text Guard for scanning LLM inputs and outputs
93
+ Guard LLM input and output text
110
94
 
111
- Analyze and redact text to avoid manipulation of the model, addition of
112
- malicious content, and other undesirable data transfers.
95
+ Detect, remove, or block malicious content and intent in LLM inputs and
96
+ outputs to prevent model manipulation and data leakage.
113
97
 
114
98
  OperationId: ai_guard_post_v1_text_guard
115
99
 
116
100
  Args:
117
101
  messages: Structured messages data to be scanned by AI Guard for
118
102
  PII, sensitive data, malicious content, and other data types
119
- defined by the configuration. Supports processing up to 10KB of
120
- JSON text
121
- recipe: Recipe key of a configuration of data types and settings
122
- defined in the Pangea User Console. It specifies the rules that
123
- are to be applied to the text, such as defang malicious URLs.
103
+ defined by the configuration. Supports processing up to 20 KiB
104
+ of JSON text using Pangea message format.
124
105
  debug: Setting this value to true will provide a detailed analysis
125
106
  of the text data
126
107
  log_field: Additional fields to include in activity log
108
+ overrides: Overrides flags. Note: This parameter has no effect when
109
+ the request is made by AIDR
110
+ recipe: Recipe key of a configuration of data types and settings
111
+ defined in the Pangea User Console. It specifies the rules that
112
+ are to be applied to the text, such as defang malicious URLs.
127
113
 
128
114
  Examples:
129
- response = await ai_guard.guard_text(messages=[{"role": "user", "content": "hello world"}])
115
+ response = await ai_guard.guard_text(messages=[Message(role="user", content="hello world")])
130
116
  """
131
117
 
132
- async def guard_text( # type: ignore[misc]
118
+ async def guard_text(
133
119
  self,
134
120
  text: str | None = None,
135
121
  *,
136
- messages: _T | None = None,
122
+ messages: Sequence[Message] | None = None,
137
123
  recipe: str | None = None,
138
124
  debug: bool | None = None,
139
125
  overrides: Overrides | None = None,
140
126
  log_fields: LogFields | None = None,
141
- ) -> PangeaResponse[TextGuardResult[None]]:
127
+ ) -> PangeaResponse[TextGuardResult]:
142
128
  """
143
- Text Guard for scanning LLM inputs and outputs
129
+ Guard LLM input and output text
144
130
 
145
- Analyze and redact text to avoid manipulation of the model, addition of
146
- malicious content, and other undesirable data transfers.
131
+ Detect, remove, or block malicious content and intent in LLM inputs and
132
+ outputs to prevent model manipulation and data leakage.
147
133
 
148
134
  OperationId: ai_guard_post_v1_text_guard
149
135
 
@@ -155,12 +141,14 @@ class AIGuardAsync(ServiceBaseAsync):
155
141
  PII, sensitive data, malicious content, and other data types
156
142
  defined by the configuration. Supports processing up to 10KB of
157
143
  JSON text
158
- recipe: Recipe key of a configuration of data types and settings
159
- defined in the Pangea User Console. It specifies the rules that
160
- are to be applied to the text, such as defang malicious URLs.
161
144
  debug: Setting this value to true will provide a detailed analysis
162
145
  of the text data
163
146
  log_field: Additional fields to include in activity log
147
+ overrides: Overrides flags. Note: This parameter has no effect when
148
+ the request is made by AIDR
149
+ recipe: Recipe key of a configuration of data types and settings
150
+ defined in the Pangea User Console. It specifies the rules that
151
+ are to be applied to the text, such as defang malicious URLs.
164
152
 
165
153
  Examples:
166
154
  response = await ai_guard.guard_text("text")
@@ -181,81 +169,3 @@ class AIGuardAsync(ServiceBaseAsync):
181
169
  "log_fields": log_fields,
182
170
  },
183
171
  )
184
-
185
- async def get_service_config(self, id: str) -> PangeaResponse[ServiceConfig]:
186
- """
187
- OperationId: ai_guard_post_v1beta_config
188
- """
189
- return await self.request.post("v1beta/config", data={"id": id}, result_class=ServiceConfig)
190
-
191
- async def create_service_config(
192
- self,
193
- name: str,
194
- *,
195
- id: str | None = None,
196
- audit_data_activity: AuditDataActivityConfig | None = None,
197
- connections: ConnectionsConfig | None = None,
198
- recipes: Mapping[str, RecipeConfig] | None = None,
199
- ) -> PangeaResponse[ServiceConfig]:
200
- """
201
- OperationId: ai_guard_post_v1beta_config_create
202
- """
203
- return await self.request.post(
204
- "v1beta/config/create",
205
- data={
206
- "name": name,
207
- "id": id,
208
- "audit_data_activity": audit_data_activity,
209
- "connections": connections,
210
- "recipes": recipes,
211
- },
212
- result_class=ServiceConfig,
213
- )
214
-
215
- async def update_service_config(
216
- self,
217
- id: str,
218
- name: str,
219
- *,
220
- audit_data_activity: AuditDataActivityConfig | None = None,
221
- connections: ConnectionsConfig | None = None,
222
- recipes: Mapping[str, RecipeConfig] | None = None,
223
- ) -> PangeaResponse[ServiceConfig]:
224
- """
225
- OperationId: ai_guard_post_v1beta_config_update
226
- """
227
- return await self.request.post(
228
- "v1beta/config/update",
229
- data={
230
- "id": id,
231
- "name": name,
232
- "audit_data_activity": audit_data_activity,
233
- "connections": connections,
234
- "recipes": recipes,
235
- },
236
- result_class=ServiceConfig,
237
- )
238
-
239
- async def delete_service_config(self, id: str) -> PangeaResponse[ServiceConfig]:
240
- """
241
- OperationId: ai_guard_post_v1beta_config_delete
242
- """
243
- return await self.request.post("v1beta/config/delete", data={"id": id}, result_class=ServiceConfig)
244
-
245
- async def list_service_configs(
246
- self,
247
- *,
248
- filter: ServiceConfigFilter | None = None,
249
- last: str | None = None,
250
- order: Literal["asc", "desc"] | None = None,
251
- order_by: Literal["id", "created_at", "updated_at"] | None = None,
252
- size: int | None = None,
253
- ) -> PangeaResponse[ServiceConfigsPage]:
254
- """
255
- OperationId: ai_guard_post_v1beta_config_list
256
- """
257
- return await self.request.post(
258
- "v1beta/config/list",
259
- data={"filter": filter, "last": last, "order": order, "order_by": order_by, "size": size},
260
- result_class=ServiceConfigsPage,
261
- )