pangea-sdk 5.1.0__py3-none-any.whl → 5.2.0b1__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__ = "5.1.0"
1
+ __version__ = "5.2.0beta1"
2
2
 
3
3
  from pangea.asyncio.request import PangeaRequestAsync
4
4
  from pangea.config import PangeaConfig
pangea/asyncio/request.py CHANGED
@@ -4,13 +4,13 @@ from __future__ import annotations
4
4
 
5
5
  import asyncio
6
6
  import json
7
- import os
8
7
  import time
9
- from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, Union
8
+ from typing import Dict, List, Optional, Sequence, Tuple, Type, Union, cast
10
9
 
11
10
  import aiohttp
12
11
  from aiohttp import FormData
13
12
  from pydantic import BaseModel
13
+ from pydantic_core import to_jsonable_python
14
14
  from typing_extensions import Any, TypeVar
15
15
 
16
16
  import pangea.exceptions as pe
@@ -56,17 +56,20 @@ class PangeaRequestAsync(PangeaRequestBase):
56
56
  if data is None:
57
57
  data = {}
58
58
 
59
+ # Normalize.
60
+ data = cast(dict[str, Any], to_jsonable_python(data))
61
+
59
62
  if url is None:
60
63
  url = self._url(endpoint)
61
64
 
62
65
  # Set config ID if available
63
- if self.config_id and data.get("config_id", None) is None: # type: ignore[union-attr]
64
- data["config_id"] = self.config_id # type: ignore[index]
66
+ if self.config_id and data.get("config_id", None) is None:
67
+ data["config_id"] = self.config_id
65
68
 
66
69
  self.logger.debug(
67
70
  json.dumps({"service": self.service, "action": "post", "url": url, "data": data}, default=default_encoder)
68
71
  )
69
- transfer_method = data.get("transfer_method", None) # type: ignore[union-attr]
72
+ transfer_method = data.get("transfer_method", None)
70
73
 
71
74
  if files and type(data) is dict and (transfer_method == TransferMethod.POST_URL.value):
72
75
  requests_response = await self._full_post_presigned_url(
@@ -0,0 +1,65 @@
1
+ from __future__ import annotations
2
+
3
+ from pangea.asyncio.services.base import ServiceBaseAsync
4
+ from pangea.response import PangeaResponse, PangeaResponseResult
5
+ from pangea.services.data_guard import TextGuardResult
6
+
7
+
8
+ class DataGuard(ServiceBaseAsync):
9
+ """Data Guard service client.
10
+
11
+ Provides methods to interact with Pangea's Data Guard service.
12
+ """
13
+
14
+ service_name = "data-guard"
15
+
16
+ async def guard_text(
17
+ self,
18
+ text: str,
19
+ *,
20
+ recipe: str = "pangea_prompt_guard",
21
+ debug: bool = False,
22
+ ) -> PangeaResponse[TextGuardResult]:
23
+ """
24
+ Text guard (Beta)
25
+
26
+ Guard text.
27
+
28
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
29
+
30
+ OperationId: data_guard_post_v1_text_guard
31
+
32
+ Args:
33
+ text: Text.
34
+ recipe: Recipe.
35
+ debug: Debug.
36
+
37
+ Examples:
38
+ response = await data_guard.guard_text("text")
39
+ """
40
+
41
+ return await self.request.post(
42
+ "v1/text/guard", TextGuardResult, data={"text": text, "recipe": recipe, "debug": debug}
43
+ )
44
+
45
+ async def guard_file(
46
+ self,
47
+ file_url: str,
48
+ ) -> PangeaResponse[PangeaResponseResult]:
49
+ """
50
+ File guard (Beta)
51
+
52
+ Guard a file URL.
53
+
54
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
55
+
56
+ OperationId: data_guard_post_v1_file_guard
57
+
58
+ Args:
59
+ file_url: File URL.
60
+
61
+ Examples:
62
+ response = await data_guard.guard_file("https://example.org/file.txt")
63
+ """
64
+
65
+ return await self.request.post("v1/file/guard", PangeaResponseResult, data={"file_url": file_url})
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from pangea.asyncio.services.base import ServiceBaseAsync
6
+ from pangea.services.prompt_guard import GuardResult, Message
7
+
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Iterable
10
+
11
+ from pangea.response import PangeaResponse
12
+
13
+
14
+ class PromptGuard(ServiceBaseAsync):
15
+ """Prompt Guard service client.
16
+
17
+ Provides methods to interact with Pangea's Prompt Guard service.
18
+ """
19
+
20
+ service_name = "prompt-guard"
21
+
22
+ async def guard(self, messages: Iterable[Message]) -> PangeaResponse[GuardResult]:
23
+ """
24
+ Guard (Beta)
25
+
26
+ Guard messages.
27
+
28
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
29
+
30
+ OperationId: prompt_guard_post_v1_guard
31
+
32
+ Args:
33
+ messages: Messages..
34
+
35
+ Examples:
36
+ response = await prompt_guard.guard([Message(role="user", content="hello world")])
37
+ """
38
+
39
+ return await self.request.post("v1/guard", GuardResult, data={"messages": messages})
pangea/request.py CHANGED
@@ -6,10 +6,11 @@ import copy
6
6
  import json
7
7
  import logging
8
8
  import time
9
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Tuple, Type, Union
9
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Tuple, Type, Union, cast
10
10
 
11
11
  import requests
12
12
  from pydantic import BaseModel
13
+ from pydantic_core import to_jsonable_python
13
14
  from requests.adapters import HTTPAdapter, Retry
14
15
  from requests_toolbelt import MultipartDecoder # type: ignore
15
16
  from typing_extensions import TypeVar
@@ -232,6 +233,9 @@ class PangeaRequest(PangeaRequestBase):
232
233
  if data is None:
233
234
  data = {}
234
235
 
236
+ # Normalize.
237
+ data = cast(dict[str, Any], to_jsonable_python(data))
238
+
235
239
  if url is None:
236
240
  url = self._url(endpoint)
237
241
 
@@ -1,9 +1,11 @@
1
1
  from .audit.audit import Audit
2
2
  from .authn.authn import AuthN
3
3
  from .authz import AuthZ
4
+ from .data_guard import DataGuard
4
5
  from .embargo import Embargo
5
6
  from .file_scan import FileScan
6
7
  from .intel import DomainIntel, FileIntel, IpIntel, UrlIntel, UserIntel
8
+ from .prompt_guard import PromptGuard
7
9
  from .redact import Redact
8
10
  from .sanitize import Sanitize
9
11
  from .share.share import Share
@@ -0,0 +1,147 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import List, Optional
4
+
5
+ from typing_extensions import Literal
6
+
7
+ from pangea.response import PangeaResponse, PangeaResponseResult
8
+ from pangea.services.base import ServiceBase
9
+ from pangea.services.intel import UserBreachedData
10
+
11
+
12
+ class TextGuardSecurityIssues(PangeaResponseResult):
13
+ compromised_email_addresses: int
14
+ malicious_domain_count: int
15
+ malicious_ip_count: int
16
+ malicious_url_count: int
17
+ redacted_item_count: int
18
+
19
+
20
+ class TextGuardFindings(PangeaResponseResult):
21
+ artifact_count: int
22
+ malicious_count: int
23
+ security_issues: TextGuardSecurityIssues
24
+
25
+
26
+ class RedactRecognizerResult(PangeaResponseResult):
27
+ field_type: str
28
+ """The entity name."""
29
+
30
+ score: float
31
+ """The certainty score that the entity matches this specific snippet."""
32
+
33
+ text: str
34
+ """The text snippet that matched."""
35
+
36
+ start: int
37
+ """The starting index of a snippet."""
38
+
39
+ end: int
40
+ """The ending index of a snippet."""
41
+
42
+ redacted: bool
43
+ """Indicates if this rule was used to anonymize a text snippet."""
44
+
45
+
46
+ class RedactReport(PangeaResponseResult):
47
+ count: int
48
+ recognizer_results: List[RedactRecognizerResult]
49
+
50
+
51
+ class IntelResults(PangeaResponseResult):
52
+ category: List[str]
53
+ """
54
+ The categories that apply to this indicator as determined by the provider.
55
+ """
56
+
57
+ score: int
58
+ """The score, given by the Pangea service, for the indicator."""
59
+
60
+ verdict: Literal["malicious", "suspicious", "unknown", "benign"]
61
+
62
+
63
+ class TextGuardReport(PangeaResponseResult):
64
+ domain_intel: Optional[IntelResults] = None
65
+ ip_intel: Optional[IntelResults] = None
66
+ redact: RedactReport
67
+ url_intel: Optional[IntelResults] = None
68
+ user_intel: Optional[UserBreachedData] = None
69
+
70
+
71
+ class TextGuardArtifact(PangeaResponseResult):
72
+ defanged: bool
73
+ end: int
74
+ start: int
75
+ type: str
76
+ value: str
77
+ verdict: Optional[str] = None
78
+ """The verdict, given by the Pangea service, for the indicator."""
79
+
80
+
81
+ class TextGuardResult(PangeaResponseResult):
82
+ artifacts: Optional[List[TextGuardArtifact]] = None
83
+ findings: TextGuardFindings
84
+ redacted_prompt: str
85
+
86
+ # `debug=True` only.
87
+ report: Optional[TextGuardReport] = None
88
+
89
+
90
+ class DataGuard(ServiceBase):
91
+ """Data Guard service client.
92
+
93
+ Provides methods to interact with Pangea's Data Guard service.
94
+ """
95
+
96
+ service_name = "data-guard"
97
+
98
+ def guard_text(
99
+ self,
100
+ text: str,
101
+ *,
102
+ recipe: str = "pangea_prompt_guard",
103
+ debug: bool = False,
104
+ ) -> PangeaResponse[TextGuardResult]:
105
+ """
106
+ Text guard (Beta)
107
+
108
+ Guard text.
109
+
110
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
111
+
112
+ OperationId: data_guard_post_v1_text_guard
113
+
114
+ Args:
115
+ text: Text.
116
+ recipe: Recipe.
117
+ debug: Debug.
118
+
119
+ Examples:
120
+ response = data_guard.guard_text("text")
121
+ """
122
+
123
+ return self.request.post(
124
+ "v1/text/guard", TextGuardResult, data={"text": text, "recipe": recipe, "debug": debug}
125
+ )
126
+
127
+ def guard_file(
128
+ self,
129
+ file_url: str,
130
+ ) -> PangeaResponse[PangeaResponseResult]:
131
+ """
132
+ File guard (Beta)
133
+
134
+ Guard a file URL.
135
+
136
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
137
+
138
+ OperationId: data_guard_post_v1_file_guard
139
+
140
+ Args:
141
+ file_url: File URL.
142
+
143
+ Examples:
144
+ response = data_guard.guard_file("https://example.org/file.txt")
145
+ """
146
+
147
+ return self.request.post("v1/file/guard", PangeaResponseResult, data={"file_url": file_url})
@@ -0,0 +1,48 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ from pangea.response import APIRequestModel, PangeaResponse, PangeaResponseResult
6
+ from pangea.services.base import ServiceBase
7
+
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Iterable
10
+
11
+
12
+ class Message(APIRequestModel):
13
+ role: str
14
+ content: str
15
+
16
+
17
+ class GuardResult(PangeaResponseResult):
18
+ prompt_injection_detected: bool
19
+ prompt_injection_type: Optional[str] = None
20
+ prompt_injection_detector: Optional[str] = None
21
+
22
+
23
+ class PromptGuard(ServiceBase):
24
+ """Prompt Guard service client.
25
+
26
+ Provides methods to interact with Pangea's Prompt Guard service.
27
+ """
28
+
29
+ service_name = "prompt-guard"
30
+
31
+ def guard(self, messages: Iterable[Message]) -> PangeaResponse[GuardResult]:
32
+ """
33
+ Guard (Beta)
34
+
35
+ Guard messages.
36
+
37
+ How to install a [Beta release](https://pangea.cloud/docs/sdk/python/#beta-releases).
38
+
39
+ OperationId: prompt_guard_post_v1_guard
40
+
41
+ Args:
42
+ messages: Messages.
43
+
44
+ Examples:
45
+ response = prompt_guard.guard([Message(role="user", content="hello world")])
46
+ """
47
+
48
+ return self.request.post("v1/guard", GuardResult, data={"messages": messages})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pangea-sdk
3
- Version: 5.1.0
3
+ Version: 5.2.0b1
4
4
  Summary: Pangea API SDK
5
5
  Home-page: https://pangea.cloud/docs/sdk/python/
6
6
  License: MIT
@@ -71,13 +71,13 @@ compatibility guarantees as stable releases. [Beta changelog](https://github.com
71
71
  Via pip:
72
72
 
73
73
  ```bash
74
- $ pip3 install pangea-sdk==3.8.0b2
74
+ $ pip3 install pangea-sdk==5.2.0b1
75
75
  ```
76
76
 
77
77
  Via poetry:
78
78
 
79
79
  ```bash
80
- $ poetry add pangea-sdk==3.8.0b2
80
+ $ poetry add pangea-sdk==5.2.0b1
81
81
  ```
82
82
 
83
83
  ## Usage
@@ -1,15 +1,17 @@
1
- pangea/__init__.py,sha256=ie7DdC7-YE5szWaPCHAlk2umsSOUBPoE_0HSaSazcqE,246
1
+ pangea/__init__.py,sha256=DOhpkGYAdPZn1XFB2SFVZRtUkHB0rrqx21nRI5UVs08,251
2
2
  pangea/asyncio/__init__.py,sha256=kjEMkqMQ521LlMSu5jn3_WgweyArwVZ2C-s3x7mR6Pk,45
3
3
  pangea/asyncio/file_uploader.py,sha256=wI7epib7Rc5jtZw4eJ1L1SlmutDG6CPv59C8N2UPhtY,1436
4
- pangea/asyncio/request.py,sha256=b9GNZl-gOk-NhJtOU0Ds7RCF88c_mHpNo0H-3H-hK9I,17478
4
+ pangea/asyncio/request.py,sha256=Pwk3dAzO_A7I1NyrIqK5V80xvtAL80KiNSjbrXjzQzA,17519
5
5
  pangea/asyncio/services/__init__.py,sha256=3IkiTqY_RtFndI7aoDTrb1yLv8xos_cKhmGS1TULcmw,386
6
6
  pangea/asyncio/services/audit.py,sha256=bZ7gdkVWkzqLqUVc1Wnf3oDAaCLg97-zTWhY8UdX0_Y,26549
7
7
  pangea/asyncio/services/authn.py,sha256=rPeLJweL8mYH_t4ebcQn4n_Wglr3kClKNnCXNCimZU4,46622
8
8
  pangea/asyncio/services/authz.py,sha256=HgW9R8DeW19wS7fpgq0NWOx41wZWcn6NYS4NMbi8p1A,9482
9
9
  pangea/asyncio/services/base.py,sha256=4FtKtlq74NmE9myrgIt9HMA6JDnP4mPZ6krafWr286o,2663
10
+ pangea/asyncio/services/data_guard.py,sha256=f6VzZCcfAHpttCjqt5SExtbsrH1HkIRFmZ2c3nRlcwU,1713
10
11
  pangea/asyncio/services/embargo.py,sha256=ctzj3kip6xos-Eu3JuOskrCGYC8T3JlsgAopZHiPSXM,3068
11
12
  pangea/asyncio/services/file_scan.py,sha256=PLG1O-PL4Yk9uY9D6NbMrZ5LHg70Z311s7bFe46UMZA,7108
12
13
  pangea/asyncio/services/intel.py,sha256=cCm3VwWxUzEUCNhuPCeejJvr4uOeLXuYDbDwTzNG6Aw,38121
14
+ pangea/asyncio/services/prompt_guard.py,sha256=oKnJM-ykWmFdbcdYzDPmjgY4P09a3fyzYuCDc2p0G5M,1044
13
15
  pangea/asyncio/services/redact.py,sha256=jRNtXr_DZ_cY7guhut-eZmOEhy2uN_VCXrjGH6bkh74,7265
14
16
  pangea/asyncio/services/sanitize.py,sha256=bf98J-s-P51oSKqNBgR0wj5mlHOCBwpjWz7k0NdXCKQ,7899
15
17
  pangea/asyncio/services/share.py,sha256=UYJeUKA3NLSFA8R0X7B6yBi2U1g4q04O4ftrp9SMCzA,26097
@@ -23,9 +25,9 @@ pangea/dump_audit.py,sha256=1Je8D2fXwU4PWcZ-ZD4icfO3DNFvWqJkwsac4qFEhOo,7025
23
25
  pangea/exceptions.py,sha256=OBtzUECpNa6vNp8ySkHC-tm4QjFRCOAHBkMHqzAlOu8,5656
24
26
  pangea/file_uploader.py,sha256=4RQ44xt-faApC61nn2PlwHT7XYrJ4GeQA8Ug4tySEAg,1227
25
27
  pangea/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- pangea/request.py,sha256=-XC1azZtymldOAQLbrSRzNX-h0B_lK-bQcinXyK0QKs,24410
28
+ pangea/request.py,sha256=ZRH4NCnbzjpzkcNnOomelK5uB49T_20PfHP_j4Swgmw,24545
27
29
  pangea/response.py,sha256=lPAcYsF9Xg166CiyhCofVmQA-W4jevh0MQXxUa8Re68,7737
28
- pangea/services/__init__.py,sha256=-QsZxRzRq_V1x1lmS_mu4310MNm0DkM4r6g6rfVGnOc,340
30
+ pangea/services/__init__.py,sha256=LmW8wdR3Vyi2_-rI9xqc9eHeQIjbfaO4e_Z3FMjNEFc,412
29
31
  pangea/services/audit/audit.py,sha256=IFv7jANA8S2SypQVS47x94_Cr5Z9zSsL9Dp9eXw9RHk,39593
30
32
  pangea/services/audit/exceptions.py,sha256=bhVuYe4ammacOVxwg98CChxvwZf5FKgR2DcgqILOcwc,471
31
33
  pangea/services/audit/models.py,sha256=1h1B9eSYQMYG3f8WNi1UcDX2-impRrET_ErjJYUnj7M,14678
@@ -35,9 +37,11 @@ pangea/services/authn/authn.py,sha256=cZKl2Ixc6HwHnkRecpSaAGTQUgaZUtxfLa0T3S03HM
35
37
  pangea/services/authn/models.py,sha256=HH5su6jx3O9AwVGzASXZ99-eIWjgXEP5LhIVdewM13s,22394
36
38
  pangea/services/authz.py,sha256=HfDnovAokzAHvnjYdOCwceM-1sCmzODnjNEbQBUSfo8,12222
37
39
  pangea/services/base.py,sha256=lwhHoe5Juy28Ir3Mfj2lHdM58gxZRaxa2SRFi4_DBRw,3453
40
+ pangea/services/data_guard.py,sha256=CzJ4Q-aakmWm8NhaWNWkT0QA6zFlyY49j2yerGOPUmc,3689
38
41
  pangea/services/embargo.py,sha256=9Wfku4td5ORaIENKmnGmS5jxJJIRfWp6Q51L36Jsy0I,3897
39
42
  pangea/services/file_scan.py,sha256=QiO80uKqB_BnAOiYQKznXfxpa5j40qqETE3-zBRT_QE,7813
40
43
  pangea/services/intel.py,sha256=CziBhC5K6O_kBXpD8zgJLpDtLHzBRgATGW4gHHFJT48,52039
44
+ pangea/services/prompt_guard.py,sha256=i0wlUjOMhdAuJytXp72OXcSzQwaWcXUiJxon7xVOJqg,1233
41
45
  pangea/services/redact.py,sha256=ZYXkzEoriLJyCqaj5dqmgsC56mIz4T3pPToZ7TcNfhg,11465
42
46
  pangea/services/sanitize.py,sha256=XP5D4CcbCZfzgU567X6H5eFBWwZuYSsHdvsdrQAZekY,12767
43
47
  pangea/services/share/file_format.py,sha256=1svO1ee_aenA9zoO_AaU-Rk5Ulp7kcPOc_KwNoluyQE,2797
@@ -51,6 +55,6 @@ pangea/services/vault/vault.py,sha256=ow-Zm7PYzfWIfUcA4UNnpeL2DHfZM4C7inRDmNR3zQ
51
55
  pangea/tools.py,sha256=2-Y4SAHWFv6Ocj42J_bWrVy27M5G3wi7a8LJn0dabHc,6427
52
56
  pangea/utils.py,sha256=KNkWK8o9j4iRDLUfAiobL-Hy5fcAxjl0DOFWXAqLK3E,5032
53
57
  pangea/verify_audit.py,sha256=nSP17OzoSPdvezRExwfcf45H8ZPZnxZu-CbEp3qFJO0,17354
54
- pangea_sdk-5.1.0.dist-info/METADATA,sha256=5vdMrWyqNEhM-sU0GbglC7Y8VfLkTVDe5_Z32-TNT8E,7495
55
- pangea_sdk-5.1.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
56
- pangea_sdk-5.1.0.dist-info/RECORD,,
58
+ pangea_sdk-5.2.0b1.dist-info/METADATA,sha256=WZN1H9C4M0BcIs3Tk9Mm950jBEv3pX_2YKH8l9F4Quk,7497
59
+ pangea_sdk-5.2.0b1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
60
+ pangea_sdk-5.2.0b1.dist-info/RECORD,,