pangea-sdk 6.3.0__py3-none-any.whl → 6.5.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 +3 -11
- pangea/_constants.py +4 -0
- pangea/_typing.py +5 -0
- pangea/asyncio/__init__.py +2 -1
- pangea/asyncio/file_uploader.py +3 -2
- pangea/asyncio/request.py +47 -10
- pangea/asyncio/services/__init__.py +19 -2
- pangea/asyncio/services/ai_guard.py +31 -29
- pangea/asyncio/services/authn.py +25 -8
- pangea/asyncio/services/base.py +21 -6
- pangea/asyncio/services/file_scan.py +1 -1
- pangea/asyncio/services/prompt_guard.py +3 -0
- pangea/config.py +4 -2
- pangea/file_uploader.py +4 -1
- pangea/request.py +72 -12
- pangea/response.py +5 -1
- pangea/services/__init__.py +19 -2
- pangea/services/ai_guard.py +84 -60
- pangea/services/audit/audit.py +2 -0
- pangea/services/audit/util.py +2 -0
- pangea/services/authn/authn.py +4 -5
- pangea/services/base.py +3 -0
- pangea/services/file_scan.py +3 -2
- pangea/services/prompt_guard.py +3 -0
- pangea/services/vault/vault.py +3 -0
- {pangea_sdk-6.3.0.dist-info → pangea_sdk-6.5.0.dist-info}/METADATA +17 -18
- pangea_sdk-6.5.0.dist-info/RECORD +62 -0
- pangea_sdk-6.5.0.dist-info/WHEEL +4 -0
- pangea_sdk-6.3.0.dist-info/RECORD +0 -60
- pangea_sdk-6.3.0.dist-info/WHEEL +0 -4
pangea/__init__.py
CHANGED
@@ -1,15 +1,7 @@
|
|
1
|
-
__version__ = "6.
|
1
|
+
__version__ = "6.5.0"
|
2
2
|
|
3
|
-
from pangea.asyncio.request import PangeaRequestAsync
|
4
3
|
from pangea.config import PangeaConfig
|
5
4
|
from pangea.file_uploader import FileUploader
|
6
|
-
from pangea.
|
7
|
-
from pangea.response import PangeaResponse
|
5
|
+
from pangea.response import PangeaResponse, PangeaResponseResult, TransferMethod
|
8
6
|
|
9
|
-
__all__ = (
|
10
|
-
"FileUploader",
|
11
|
-
"PangeaConfig",
|
12
|
-
"PangeaRequest",
|
13
|
-
"PangeaRequestAsync",
|
14
|
-
"PangeaResponse",
|
15
|
-
)
|
7
|
+
__all__ = ("FileUploader", "PangeaConfig", "PangeaResponse", "PangeaResponseResult", "TransferMethod")
|
pangea/_constants.py
ADDED
pangea/_typing.py
ADDED
pangea/asyncio/__init__.py
CHANGED
pangea/asyncio/file_uploader.py
CHANGED
@@ -6,9 +6,10 @@ from __future__ import annotations
|
|
6
6
|
import io
|
7
7
|
import logging
|
8
8
|
|
9
|
+
from pangea import PangeaConfig, TransferMethod
|
9
10
|
from pangea.asyncio.request import PangeaRequestAsync
|
10
|
-
|
11
|
-
|
11
|
+
|
12
|
+
__all__ = ("FileUploaderAsync",)
|
12
13
|
|
13
14
|
|
14
15
|
class FileUploaderAsync:
|
pangea/asyncio/request.py
CHANGED
@@ -10,6 +10,7 @@ import asyncio
|
|
10
10
|
import json
|
11
11
|
import time
|
12
12
|
from collections.abc import Iterable, Mapping
|
13
|
+
from random import random
|
13
14
|
from typing import Dict, List, Optional, Sequence, Tuple, Type, Union, cast
|
14
15
|
|
15
16
|
import aiohttp
|
@@ -19,10 +20,13 @@ from pydantic_core import to_jsonable_python
|
|
19
20
|
from typing_extensions import Any, TypeAlias, TypeVar, override
|
20
21
|
|
21
22
|
import pangea.exceptions as pe
|
23
|
+
from pangea._constants import MAX_RETRY_DELAY, RETRYABLE_HTTP_CODES
|
22
24
|
from pangea.request import MultipartResponse, PangeaRequestBase
|
23
25
|
from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult, ResponseStatus, TransferMethod
|
24
26
|
from pangea.utils import default_encoder
|
25
27
|
|
28
|
+
__all__ = ("PangeaRequestAsync",)
|
29
|
+
|
26
30
|
_FileName: TypeAlias = Union[str, None]
|
27
31
|
_FileContent: TypeAlias = Union[str, bytes]
|
28
32
|
_FileContentType: TypeAlias = str
|
@@ -462,13 +466,46 @@ class PangeaRequestAsync(PangeaRequestBase):
|
|
462
466
|
|
463
467
|
@override
|
464
468
|
def _init_session(self) -> aiohttp.ClientSession:
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
469
|
+
return aiohttp.ClientSession(middlewares=[self._retry_middleware])
|
470
|
+
|
471
|
+
def _calculate_retry_timeout(self, remaining_retries: int) -> float:
|
472
|
+
max_retries = self.config.request_retries
|
473
|
+
nb_retries = min(max_retries - remaining_retries, 1000)
|
474
|
+
sleep_seconds = min(self.config.request_backoff * pow(2.0, nb_retries), MAX_RETRY_DELAY)
|
475
|
+
jitter = 1 - 0.25 * random()
|
476
|
+
timeout = sleep_seconds * jitter
|
477
|
+
return max(timeout, 0)
|
478
|
+
|
479
|
+
async def _retry_middleware(
|
480
|
+
self, request: aiohttp.ClientRequest, handler: aiohttp.ClientHandlerType
|
481
|
+
) -> aiohttp.ClientResponse:
|
482
|
+
max_retries = self.config.request_retries
|
483
|
+
request_ids = set[str]()
|
484
|
+
retries_taken = 0
|
485
|
+
for retries_taken in range(max_retries + 1):
|
486
|
+
remaining_retries = max_retries - retries_taken
|
487
|
+
|
488
|
+
if len(request_ids) > 0:
|
489
|
+
request.headers["X-Pangea-Retried-Request-Ids"] = ",".join(request_ids)
|
490
|
+
|
491
|
+
response = await handler(request)
|
492
|
+
|
493
|
+
request_id = response.headers.get("x-request-id")
|
494
|
+
if request_id:
|
495
|
+
request_ids.add(request_id)
|
496
|
+
|
497
|
+
if not response.ok and remaining_retries > 0 and self._should_retry(response):
|
498
|
+
await self._sleep_for_retry(retries_taken=retries_taken, max_retries=max_retries)
|
499
|
+
continue
|
500
|
+
|
501
|
+
break
|
502
|
+
|
503
|
+
return response
|
504
|
+
|
505
|
+
def _should_retry(self, response: aiohttp.ClientResponse) -> bool:
|
506
|
+
return response.status in RETRYABLE_HTTP_CODES
|
507
|
+
|
508
|
+
async def _sleep_for_retry(self, *, retries_taken: int, max_retries: int) -> None:
|
509
|
+
remaining_retries = max_retries - retries_taken
|
510
|
+
timeout = self._calculate_retry_timeout(remaining_retries)
|
511
|
+
await asyncio.sleep(timeout)
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# ruff: noqa: F401
|
2
|
-
|
3
1
|
from .ai_guard import AIGuardAsync
|
4
2
|
from .audit import AuditAsync
|
5
3
|
from .authn import AuthNAsync
|
@@ -12,3 +10,22 @@ from .redact import RedactAsync
|
|
12
10
|
from .sanitize import SanitizeAsync
|
13
11
|
from .share import ShareAsync
|
14
12
|
from .vault import VaultAsync
|
13
|
+
|
14
|
+
__all__ = (
|
15
|
+
"AIGuardAsync",
|
16
|
+
"AuditAsync",
|
17
|
+
"AuthNAsync",
|
18
|
+
"AuthZAsync",
|
19
|
+
"DomainIntelAsync",
|
20
|
+
"EmbargoAsync",
|
21
|
+
"FileIntelAsync",
|
22
|
+
"FileScanAsync",
|
23
|
+
"IpIntelAsync",
|
24
|
+
"PromptGuardAsync",
|
25
|
+
"RedactAsync",
|
26
|
+
"SanitizeAsync",
|
27
|
+
"ShareAsync",
|
28
|
+
"UrlIntelAsync",
|
29
|
+
"UserIntelAsync",
|
30
|
+
"VaultAsync",
|
31
|
+
)
|
@@ -15,11 +15,9 @@ class AIGuardAsync(ServiceBaseAsync):
|
|
15
15
|
Provides methods to interact with Pangea's AI Guard service.
|
16
16
|
|
17
17
|
Examples:
|
18
|
-
from pangea import PangeaConfig
|
19
18
|
from pangea.asyncio.services import AIGuardAsync
|
20
19
|
|
21
|
-
|
22
|
-
ai_guard = AIGuardAsync(token="pangea_token", config=config)
|
20
|
+
ai_guard = AIGuardAsync(token="pangea_token")
|
23
21
|
"""
|
24
22
|
|
25
23
|
service_name = "ai-guard"
|
@@ -39,11 +37,9 @@ class AIGuardAsync(ServiceBaseAsync):
|
|
39
37
|
config_id: Configuration ID.
|
40
38
|
|
41
39
|
Examples:
|
42
|
-
from pangea import PangeaConfig
|
43
40
|
from pangea.asyncio.services import AIGuardAsync
|
44
41
|
|
45
|
-
|
46
|
-
ai_guard = AIGuardAsync(token="pangea_token", config=config)
|
42
|
+
ai_guard = AIGuardAsync(token="pangea_token")
|
47
43
|
"""
|
48
44
|
|
49
45
|
super().__init__(token, config, logger_name, config_id)
|
@@ -53,29 +49,31 @@ class AIGuardAsync(ServiceBaseAsync):
|
|
53
49
|
self,
|
54
50
|
text: str,
|
55
51
|
*,
|
56
|
-
recipe: str | None = None,
|
57
52
|
debug: bool | None = None,
|
58
|
-
overrides: Overrides | None = None,
|
59
53
|
log_fields: LogFields | None = None,
|
54
|
+
overrides: Overrides | None = None,
|
55
|
+
recipe: str | None = None,
|
60
56
|
) -> PangeaResponse[TextGuardResult]:
|
61
57
|
"""
|
62
|
-
|
58
|
+
Guard LLM input and output text
|
63
59
|
|
64
|
-
|
65
|
-
|
60
|
+
Detect, remove, or block malicious content and intent in LLM inputs and
|
61
|
+
outputs to prevent model manipulation and data leakage.
|
66
62
|
|
67
63
|
OperationId: ai_guard_post_v1_text_guard
|
68
64
|
|
69
65
|
Args:
|
70
66
|
text: Text to be scanned by AI Guard for PII, sensitive data,
|
71
67
|
malicious content, and other data types defined by the
|
72
|
-
configuration. Supports processing up to
|
73
|
-
recipe: Recipe key of a configuration of data types and settings
|
74
|
-
defined in the Pangea User Console. It specifies the rules that
|
75
|
-
are to be applied to the text, such as defang malicious URLs.
|
68
|
+
configuration. Supports processing up to 20 KiB of text.
|
76
69
|
debug: Setting this value to true will provide a detailed analysis
|
77
70
|
of the text data
|
78
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.
|
79
77
|
|
80
78
|
Examples:
|
81
79
|
response = await ai_guard.guard_text("text")
|
@@ -92,24 +90,26 @@ class AIGuardAsync(ServiceBaseAsync):
|
|
92
90
|
log_fields: LogFields | None = None,
|
93
91
|
) -> PangeaResponse[TextGuardResult]:
|
94
92
|
"""
|
95
|
-
|
93
|
+
Guard LLM input and output text
|
96
94
|
|
97
|
-
|
98
|
-
|
95
|
+
Detect, remove, or block malicious content and intent in LLM inputs and
|
96
|
+
outputs to prevent model manipulation and data leakage.
|
99
97
|
|
100
98
|
OperationId: ai_guard_post_v1_text_guard
|
101
99
|
|
102
100
|
Args:
|
103
101
|
messages: Structured messages data to be scanned by AI Guard for
|
104
102
|
PII, sensitive data, malicious content, and other data types
|
105
|
-
defined by the configuration. Supports processing up to
|
106
|
-
JSON text
|
107
|
-
recipe: Recipe key of a configuration of data types and settings
|
108
|
-
defined in the Pangea User Console. It specifies the rules that
|
109
|
-
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.
|
110
105
|
debug: Setting this value to true will provide a detailed analysis
|
111
106
|
of the text data
|
112
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.
|
113
113
|
|
114
114
|
Examples:
|
115
115
|
response = await ai_guard.guard_text(messages=[Message(role="user", content="hello world")])
|
@@ -126,10 +126,10 @@ class AIGuardAsync(ServiceBaseAsync):
|
|
126
126
|
log_fields: LogFields | None = None,
|
127
127
|
) -> PangeaResponse[TextGuardResult]:
|
128
128
|
"""
|
129
|
-
|
129
|
+
Guard LLM input and output text
|
130
130
|
|
131
|
-
|
132
|
-
|
131
|
+
Detect, remove, or block malicious content and intent in LLM inputs and
|
132
|
+
outputs to prevent model manipulation and data leakage.
|
133
133
|
|
134
134
|
OperationId: ai_guard_post_v1_text_guard
|
135
135
|
|
@@ -141,12 +141,14 @@ class AIGuardAsync(ServiceBaseAsync):
|
|
141
141
|
PII, sensitive data, malicious content, and other data types
|
142
142
|
defined by the configuration. Supports processing up to 10KB of
|
143
143
|
JSON text
|
144
|
-
recipe: Recipe key of a configuration of data types and settings
|
145
|
-
defined in the Pangea User Console. It specifies the rules that
|
146
|
-
are to be applied to the text, such as defang malicious URLs.
|
147
144
|
debug: Setting this value to true will provide a detailed analysis
|
148
145
|
of the text data
|
149
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.
|
150
152
|
|
151
153
|
Examples:
|
152
154
|
response = await ai_guard.guard_text("text")
|
pangea/asyncio/services/authn.py
CHANGED
@@ -10,9 +10,9 @@ from collections.abc import Mapping
|
|
10
10
|
from typing import Dict, List, Literal, Optional, Union
|
11
11
|
|
12
12
|
import pangea.services.authn.models as m
|
13
|
+
from pangea import PangeaResponse, PangeaResponseResult
|
13
14
|
from pangea.asyncio.services.base import ServiceBaseAsync
|
14
15
|
from pangea.config import PangeaConfig
|
15
|
-
from pangea.response import PangeaResponse, PangeaResponseResult
|
16
16
|
|
17
17
|
__all__ = ["AuthNAsync"]
|
18
18
|
|
@@ -66,11 +66,18 @@ class AuthNAsync(ServiceBaseAsync):
|
|
66
66
|
authn = AuthNAsync(token="pangea_token", config=config)
|
67
67
|
"""
|
68
68
|
super().__init__(token, config, logger_name=logger_name)
|
69
|
-
self.
|
70
|
-
self.flow = AuthNAsync.FlowAsync(token, config, logger_name=logger_name)
|
69
|
+
self.agreements = AuthNAsync.AgreementsAsync(token, config, logger_name=logger_name)
|
71
70
|
self.client = AuthNAsync.ClientAsync(token, config, logger_name=logger_name)
|
71
|
+
self.flow = AuthNAsync.FlowAsync(token, config, logger_name=logger_name)
|
72
72
|
self.session = AuthNAsync.SessionAsync(token, config, logger_name=logger_name)
|
73
|
-
self.
|
73
|
+
self.user = AuthNAsync.UserAsync(token, config, logger_name=logger_name)
|
74
|
+
|
75
|
+
async def close(self) -> None:
|
76
|
+
await self.agreements.close()
|
77
|
+
await self.client.close()
|
78
|
+
await self.flow.close()
|
79
|
+
await self.session.close()
|
80
|
+
await self.user.close()
|
74
81
|
|
75
82
|
class SessionAsync(ServiceBaseAsync):
|
76
83
|
service_name = _SERVICE_NAME
|
@@ -179,10 +186,15 @@ class AuthNAsync(ServiceBaseAsync):
|
|
179
186
|
logger_name: str = "pangea",
|
180
187
|
) -> None:
|
181
188
|
super().__init__(token, config, logger_name=logger_name)
|
182
|
-
self.session = AuthNAsync.ClientAsync.SessionAsync(token, config, logger_name=logger_name)
|
183
189
|
self.password = AuthNAsync.ClientAsync.PasswordAsync(token, config, logger_name=logger_name)
|
190
|
+
self.session = AuthNAsync.ClientAsync.SessionAsync(token, config, logger_name=logger_name)
|
184
191
|
self.token_endpoints = AuthNAsync.ClientAsync.TokenAsync(token, config, logger_name=logger_name)
|
185
192
|
|
193
|
+
async def close(self) -> None:
|
194
|
+
await self.password.close()
|
195
|
+
await self.session.close()
|
196
|
+
await self.token_endpoints.close()
|
197
|
+
|
186
198
|
async def userinfo(self, code: str) -> PangeaResponse[m.ClientUserinfoResult]:
|
187
199
|
"""
|
188
200
|
Get User (client token)
|
@@ -470,9 +482,14 @@ class AuthNAsync(ServiceBaseAsync):
|
|
470
482
|
logger_name: str = "pangea",
|
471
483
|
) -> None:
|
472
484
|
super().__init__(token, config, logger_name=logger_name)
|
473
|
-
self.profile = AuthNAsync.UserAsync.ProfileAsync(token, config, logger_name=logger_name)
|
474
485
|
self.authenticators = AuthNAsync.UserAsync.AuthenticatorsAsync(token, config, logger_name=logger_name)
|
475
486
|
self.invites = AuthNAsync.UserAsync.InvitesAsync(token, config, logger_name=logger_name)
|
487
|
+
self.profile = AuthNAsync.UserAsync.ProfileAsync(token, config, logger_name=logger_name)
|
488
|
+
|
489
|
+
async def close(self) -> None:
|
490
|
+
await self.authenticators.close()
|
491
|
+
await self.invites.close()
|
492
|
+
await self.profile.close()
|
476
493
|
|
477
494
|
async def create(
|
478
495
|
self,
|
@@ -932,7 +949,7 @@ class AuthNAsync(ServiceBaseAsync):
|
|
932
949
|
return await self.request.post(
|
933
950
|
"v2/user/group/assign",
|
934
951
|
data={"id": user_id, "group_ids": group_ids},
|
935
|
-
result_class=
|
952
|
+
result_class=PangeaResponseResult,
|
936
953
|
)
|
937
954
|
|
938
955
|
async def remove(self, user_id: str, group_id: str) -> PangeaResponse[PangeaResponseResult]:
|
@@ -946,7 +963,7 @@ class AuthNAsync(ServiceBaseAsync):
|
|
946
963
|
return await self.request.post(
|
947
964
|
"v2/user/group/remove",
|
948
965
|
data={"id": user_id, "group_id": group_id},
|
949
|
-
result_class=
|
966
|
+
result_class=PangeaResponseResult,
|
950
967
|
)
|
951
968
|
|
952
969
|
async def list(self, user_id: str) -> PangeaResponse[m.GroupList]:
|
pangea/asyncio/services/base.py
CHANGED
@@ -6,14 +6,20 @@
|
|
6
6
|
|
7
7
|
from __future__ import annotations
|
8
8
|
|
9
|
+
from types import TracebackType
|
9
10
|
from typing import Dict, Optional, Type, Union
|
10
11
|
|
11
12
|
from typing_extensions import override
|
12
13
|
|
14
|
+
from pangea import PangeaResponse, PangeaResponseResult
|
15
|
+
from pangea._typing import T
|
13
16
|
from pangea.asyncio.request import PangeaRequestAsync
|
14
17
|
from pangea.exceptions import AcceptedRequestException
|
15
|
-
from pangea.
|
16
|
-
from pangea.
|
18
|
+
from pangea.request import PangeaRequest
|
19
|
+
from pangea.response import AttachedFile
|
20
|
+
from pangea.services.base import ServiceBase
|
21
|
+
|
22
|
+
__all__ = ("ServiceBaseAsync",)
|
17
23
|
|
18
24
|
|
19
25
|
class ServiceBaseAsync(ServiceBase):
|
@@ -85,8 +91,17 @@ class ServiceBaseAsync(ServiceBase):
|
|
85
91
|
return await self.request.download_file(url=url, filename=filename)
|
86
92
|
|
87
93
|
async def close(self):
|
94
|
+
"""Close the underlying aiohttp client."""
|
95
|
+
|
88
96
|
await self.request.session.close()
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
97
|
+
|
98
|
+
async def __aenter__(self: T) -> T:
|
99
|
+
return self
|
100
|
+
|
101
|
+
async def __aexit__(
|
102
|
+
self,
|
103
|
+
exc_type: type[BaseException] | None,
|
104
|
+
exc: BaseException | None,
|
105
|
+
exc_tb: TracebackType | None,
|
106
|
+
) -> None:
|
107
|
+
await self.close()
|
@@ -11,9 +11,9 @@ import logging
|
|
11
11
|
from typing import Dict, List, Optional, Tuple
|
12
12
|
|
13
13
|
import pangea.services.file_scan as m
|
14
|
+
from pangea import PangeaConfig
|
14
15
|
from pangea.asyncio.request import PangeaRequestAsync
|
15
16
|
from pangea.asyncio.services.base import ServiceBaseAsync
|
16
|
-
from pangea.request import PangeaConfig
|
17
17
|
from pangea.response import PangeaResponse, TransferMethod
|
18
18
|
from pangea.utils import FileUploadParams, get_file_upload_params
|
19
19
|
|
pangea/config.py
CHANGED
@@ -6,6 +6,8 @@ from typing import Any, Optional
|
|
6
6
|
|
7
7
|
from pydantic import BaseModel, model_validator
|
8
8
|
|
9
|
+
__all__ = ("PangeaConfig",)
|
10
|
+
|
9
11
|
|
10
12
|
class PangeaConfig(BaseModel):
|
11
13
|
"""Holds run time configuration information used by SDK components."""
|
@@ -34,12 +36,12 @@ class PangeaConfig(BaseModel):
|
|
34
36
|
|
35
37
|
request_backoff: float = 0.5
|
36
38
|
"""
|
37
|
-
|
39
|
+
A backoff factor to apply between request attempts.
|
38
40
|
"""
|
39
41
|
|
40
42
|
request_timeout: int = 5
|
41
43
|
"""
|
42
|
-
|
44
|
+
Unused.
|
43
45
|
"""
|
44
46
|
|
45
47
|
poll_result_timeout: int = 30
|
pangea/file_uploader.py
CHANGED
@@ -8,9 +8,12 @@ import io
|
|
8
8
|
import logging
|
9
9
|
from typing import Dict, Optional
|
10
10
|
|
11
|
-
from pangea.
|
11
|
+
from pangea.config import PangeaConfig
|
12
|
+
from pangea.request import PangeaRequest
|
12
13
|
from pangea.response import TransferMethod
|
13
14
|
|
15
|
+
__all__ = ("FileUploader",)
|
16
|
+
|
14
17
|
|
15
18
|
class FileUploader:
|
16
19
|
def __init__(self):
|
pangea/request.py
CHANGED
@@ -11,18 +11,20 @@ import json
|
|
11
11
|
import logging
|
12
12
|
import time
|
13
13
|
from collections.abc import Iterable, Mapping
|
14
|
+
from random import random
|
14
15
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, Union, cast
|
15
16
|
|
16
17
|
import requests
|
17
18
|
from pydantic import BaseModel
|
18
19
|
from pydantic_core import to_jsonable_python
|
19
|
-
from requests.adapters import HTTPAdapter
|
20
|
+
from requests.adapters import HTTPAdapter
|
20
21
|
from requests_toolbelt import MultipartDecoder # type: ignore[import-untyped]
|
21
22
|
from typing_extensions import TypeAlias, TypeVar, override
|
22
23
|
from yarl import URL
|
23
24
|
|
24
25
|
import pangea
|
25
26
|
import pangea.exceptions as pe
|
27
|
+
from pangea._constants import MAX_RETRY_DELAY, RETRYABLE_HTTP_CODES
|
26
28
|
from pangea.config import PangeaConfig
|
27
29
|
from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult, ResponseStatus, TransferMethod
|
28
30
|
from pangea.utils import default_encoder
|
@@ -46,6 +48,70 @@ _Files: TypeAlias = Union[Mapping[str, _FileSpec], Iterable[tuple[str, _FileSpec
|
|
46
48
|
_HeadersUpdateMapping: TypeAlias = Mapping[str, str]
|
47
49
|
|
48
50
|
|
51
|
+
class PangeaHTTPAdapter(HTTPAdapter):
|
52
|
+
"""Custom HTTP adapter that keeps track of retried request IDs."""
|
53
|
+
|
54
|
+
@override
|
55
|
+
def __init__(self, config: PangeaConfig, *args, **kwargs):
|
56
|
+
super().__init__(*args, **kwargs)
|
57
|
+
self.config = config
|
58
|
+
|
59
|
+
@override
|
60
|
+
def send(
|
61
|
+
self,
|
62
|
+
request: requests.PreparedRequest,
|
63
|
+
stream: bool = False,
|
64
|
+
timeout: None | float | tuple[float, float] | tuple[float, None] = None,
|
65
|
+
verify: bool | str = True,
|
66
|
+
cert: None | bytes | str | tuple[bytes | str, bytes | str] = None,
|
67
|
+
proxies: Mapping[str, str] | None = None,
|
68
|
+
) -> requests.Response:
|
69
|
+
max_retries = self.config.request_retries
|
70
|
+
request_ids = set[str]()
|
71
|
+
retries_taken = 0
|
72
|
+
for retries_taken in range(max_retries + 1):
|
73
|
+
remaining_retries = max_retries - retries_taken
|
74
|
+
|
75
|
+
if len(request_ids) > 0:
|
76
|
+
request.headers["X-Pangea-Retried-Request-Ids"] = ",".join(request_ids)
|
77
|
+
|
78
|
+
response = super().send(request, stream, timeout, verify, cert, proxies)
|
79
|
+
|
80
|
+
request_id = response.headers.get("x-request-id")
|
81
|
+
if request_id:
|
82
|
+
request_ids.add(request_id)
|
83
|
+
|
84
|
+
try:
|
85
|
+
response.raise_for_status()
|
86
|
+
except requests.HTTPError as error:
|
87
|
+
if remaining_retries > 0 and self._should_retry(error.response):
|
88
|
+
error.response.close()
|
89
|
+
self._sleep_for_retry(retries_taken=retries_taken, max_retries=max_retries, config=self.config)
|
90
|
+
continue
|
91
|
+
|
92
|
+
break
|
93
|
+
|
94
|
+
break
|
95
|
+
|
96
|
+
return response
|
97
|
+
|
98
|
+
def _calculate_retry_timeout(self, remaining_retries: int, config: PangeaConfig) -> float:
|
99
|
+
max_retries = config.request_retries
|
100
|
+
nb_retries = min(max_retries - remaining_retries, 1000)
|
101
|
+
sleep_seconds = min(config.request_backoff * pow(2.0, nb_retries), MAX_RETRY_DELAY)
|
102
|
+
jitter = 1 - 0.25 * random()
|
103
|
+
timeout = sleep_seconds * jitter
|
104
|
+
return max(timeout, 0)
|
105
|
+
|
106
|
+
def _sleep_for_retry(self, *, retries_taken: int, max_retries: int, config: PangeaConfig) -> None:
|
107
|
+
remaining_retries = max_retries - retries_taken
|
108
|
+
timeout = self._calculate_retry_timeout(remaining_retries, config)
|
109
|
+
time.sleep(timeout)
|
110
|
+
|
111
|
+
def _should_retry(self, response: requests.Response) -> bool:
|
112
|
+
return response.status_code in RETRYABLE_HTTP_CODES
|
113
|
+
|
114
|
+
|
49
115
|
class MultipartResponse:
|
50
116
|
pangea_json: Dict[str, str]
|
51
117
|
attached_files: List = []
|
@@ -111,8 +177,8 @@ class PangeaRequestBase:
|
|
111
177
|
|
112
178
|
return self._queued_retry_enabled
|
113
179
|
|
114
|
-
def _get_delay(self, retry_count, start):
|
115
|
-
delay = retry_count * retry_count
|
180
|
+
def _get_delay(self, retry_count: int, start: float) -> float:
|
181
|
+
delay: float = retry_count * retry_count
|
116
182
|
now = time.time()
|
117
183
|
# if with this delay exceed timeout, reduce delay
|
118
184
|
if now - start + delay >= self.config.poll_result_timeout:
|
@@ -120,10 +186,10 @@ class PangeaRequestBase:
|
|
120
186
|
|
121
187
|
return delay
|
122
188
|
|
123
|
-
def _reach_timeout(self, start):
|
189
|
+
def _reach_timeout(self, start: float) -> bool:
|
124
190
|
return time.time() - start >= self.config.poll_result_timeout
|
125
191
|
|
126
|
-
def _get_poll_path(self, request_id: str):
|
192
|
+
def _get_poll_path(self, request_id: str) -> str:
|
127
193
|
return f"request/{request_id}"
|
128
194
|
|
129
195
|
def _url(self, path: str) -> str:
|
@@ -628,13 +694,7 @@ class PangeaRequest(PangeaRequestBase):
|
|
628
694
|
|
629
695
|
@override
|
630
696
|
def _init_session(self) -> requests.Session:
|
631
|
-
|
632
|
-
total=self.config.request_retries,
|
633
|
-
backoff_factor=self.config.request_backoff,
|
634
|
-
status_forcelist=[500, 502, 503, 504],
|
635
|
-
)
|
636
|
-
|
637
|
-
adapter = HTTPAdapter(max_retries=retry_config)
|
697
|
+
adapter = PangeaHTTPAdapter(config=self.config)
|
638
698
|
session = requests.Session()
|
639
699
|
|
640
700
|
session.mount("http://", adapter)
|
pangea/response.py
CHANGED
@@ -18,6 +18,8 @@ from typing_extensions import TypeVar
|
|
18
18
|
|
19
19
|
from pangea.utils import format_datetime
|
20
20
|
|
21
|
+
__all__ = ("PangeaResponse", "PangeaResponseResult", "TransferMethod")
|
22
|
+
|
21
23
|
|
22
24
|
class AttachedFile:
|
23
25
|
filename: str
|
@@ -243,7 +245,9 @@ class PangeaResponse(ResponseHeader, Generic[T]):
|
|
243
245
|
|
244
246
|
@property
|
245
247
|
def http_status(self) -> int: # type: ignore[return]
|
246
|
-
|
248
|
+
# Must be an explicit None check because Response's boolean
|
249
|
+
# representation is equal to whether or not the response is OK.
|
250
|
+
if self.raw_response is not None:
|
247
251
|
if isinstance(self.raw_response, aiohttp.ClientResponse):
|
248
252
|
return self.raw_response.status
|
249
253
|
else:
|
pangea/services/__init__.py
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# ruff: noqa: F401
|
2
|
-
|
3
1
|
from .ai_guard import AIGuard
|
4
2
|
from .audit.audit import Audit
|
5
3
|
from .authn.authn import AuthN
|
@@ -12,3 +10,22 @@ from .redact import Redact
|
|
12
10
|
from .sanitize import Sanitize
|
13
11
|
from .share.share import Share
|
14
12
|
from .vault.vault import Vault
|
13
|
+
|
14
|
+
__all__ = (
|
15
|
+
"AIGuard",
|
16
|
+
"Audit",
|
17
|
+
"AuthN",
|
18
|
+
"AuthZ",
|
19
|
+
"DomainIntel",
|
20
|
+
"Embargo",
|
21
|
+
"FileIntel",
|
22
|
+
"FileScan",
|
23
|
+
"IpIntel",
|
24
|
+
"PromptGuard",
|
25
|
+
"Redact",
|
26
|
+
"Sanitize",
|
27
|
+
"Share",
|
28
|
+
"UrlIntel",
|
29
|
+
"UserIntel",
|
30
|
+
"Vault",
|
31
|
+
)
|
pangea/services/ai_guard.py
CHANGED
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
3
3
|
from collections.abc import Sequence
|
4
4
|
from typing import Generic, Literal, Optional, overload
|
5
5
|
|
6
|
-
from pydantic import BaseModel, ConfigDict
|
7
6
|
from typing_extensions import TypeVar
|
8
7
|
|
9
8
|
from pangea.config import PangeaConfig
|
@@ -21,9 +20,7 @@ MaliciousEntityAction = Literal["report", "defang", "disabled", "block"]
|
|
21
20
|
PiiEntityAction = Literal["disabled", "report", "block", "mask", "partial_masking", "replacement", "hash", "fpe"]
|
22
21
|
|
23
22
|
|
24
|
-
class Message(
|
25
|
-
model_config = ConfigDict(extra="forbid")
|
26
|
-
|
23
|
+
class Message(APIRequestModel):
|
27
24
|
role: str
|
28
25
|
content: str
|
29
26
|
|
@@ -31,18 +28,21 @@ class Message(BaseModel):
|
|
31
28
|
class CodeDetectionOverride(APIRequestModel):
|
32
29
|
disabled: Optional[bool] = None
|
33
30
|
action: Optional[Literal["report", "block"]] = None
|
31
|
+
threshold: Optional[float] = None
|
34
32
|
|
35
33
|
|
36
34
|
class LanguageDetectionOverride(APIRequestModel):
|
37
35
|
disabled: Optional[bool] = None
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
action: Optional[Literal["", "report", "allow", "block"]] = ""
|
37
|
+
languages: Optional[list[str]] = None
|
38
|
+
threshold: Optional[float] = None
|
41
39
|
|
42
40
|
|
43
41
|
class TopicDetectionOverride(APIRequestModel):
|
44
42
|
disabled: Optional[bool] = None
|
45
|
-
|
43
|
+
action: Optional[Literal["", "report", "block"]] = ""
|
44
|
+
topics: Optional[list[str]] = None
|
45
|
+
threshold: Optional[float] = None
|
46
46
|
|
47
47
|
|
48
48
|
class PromptInjectionOverride(APIRequestModel):
|
@@ -145,6 +145,8 @@ class SecretsDetectionOverride(APIRequestModel):
|
|
145
145
|
|
146
146
|
|
147
147
|
class Overrides(APIRequestModel):
|
148
|
+
"""Overrides flags."""
|
149
|
+
|
148
150
|
ignore_recipe: Optional[bool] = None
|
149
151
|
"""Bypass existing Recipe content and create an on-the-fly Recipe."""
|
150
152
|
|
@@ -159,7 +161,7 @@ class Overrides(APIRequestModel):
|
|
159
161
|
secrets_detection: Optional[SecretsDetectionOverride] = None
|
160
162
|
selfharm: Optional[SelfHarmOverride] = None
|
161
163
|
sentiment: Optional[SentimentOverride] = None
|
162
|
-
|
164
|
+
topic: Optional[TopicDetectionOverride] = None
|
163
165
|
|
164
166
|
|
165
167
|
class LogFields(APIRequestModel):
|
@@ -249,15 +251,24 @@ class SecretsEntityResult(APIResponseModel):
|
|
249
251
|
|
250
252
|
|
251
253
|
class LanguageDetectionResult(APIResponseModel):
|
252
|
-
|
253
|
-
action: str
|
254
|
+
action: Optional[str] = None
|
254
255
|
"""The action taken by this Detector"""
|
255
256
|
|
257
|
+
language: Optional[str] = None
|
258
|
+
|
259
|
+
|
260
|
+
class Topic(APIResponseModel):
|
261
|
+
topic: str
|
262
|
+
confidence: float
|
263
|
+
|
256
264
|
|
257
265
|
class TopicDetectionResult(APIResponseModel):
|
258
|
-
action: str
|
266
|
+
action: Optional[str] = None
|
259
267
|
"""The action taken by this Detector"""
|
260
268
|
|
269
|
+
topics: Optional[list[Topic]] = None
|
270
|
+
"""List of topics detected"""
|
271
|
+
|
261
272
|
|
262
273
|
class CodeDetectionResult(APIResponseModel):
|
263
274
|
language: str
|
@@ -274,38 +285,49 @@ class TextGuardDetector(APIResponseModel, Generic[_T]):
|
|
274
285
|
|
275
286
|
|
276
287
|
class TextGuardDetectors(APIResponseModel):
|
277
|
-
|
278
|
-
|
279
|
-
malicious_entity: Optional[TextGuardDetector[MaliciousEntityResult]] = None
|
288
|
+
code_detection: Optional[TextGuardDetector[CodeDetectionResult]] = None
|
289
|
+
competitors: Optional[TextGuardDetector[object]] = None
|
280
290
|
custom_entity: Optional[TextGuardDetector[object]] = None
|
281
|
-
|
282
|
-
|
291
|
+
gibberish: Optional[TextGuardDetector[object]] = None
|
292
|
+
hardening: Optional[TextGuardDetector[object]] = None
|
283
293
|
language_detection: Optional[TextGuardDetector[LanguageDetectionResult]] = None
|
284
|
-
|
285
|
-
|
294
|
+
malicious_entity: Optional[TextGuardDetector[MaliciousEntityResult]] = None
|
295
|
+
pii_entity: Optional[TextGuardDetector[PiiEntityResult]] = None
|
296
|
+
profanity_and_toxicity: Optional[TextGuardDetector[object]] = None
|
297
|
+
prompt_injection: Optional[TextGuardDetector[PromptInjectionResult]] = None
|
298
|
+
secrets_detection: Optional[TextGuardDetector[SecretsEntityResult]] = None
|
299
|
+
selfharm: Optional[TextGuardDetector[object]] = None
|
300
|
+
sentiment: Optional[TextGuardDetector[object]] = None
|
301
|
+
topic: Optional[TextGuardDetector[TopicDetectionResult]] = None
|
286
302
|
|
287
303
|
|
288
304
|
class TextGuardResult(PangeaResponseResult):
|
289
305
|
detectors: TextGuardDetectors
|
290
306
|
"""Result of the recipe analyzing and input prompt."""
|
291
307
|
|
292
|
-
|
293
|
-
"""
|
308
|
+
access_rules: Optional[object] = None
|
309
|
+
"""Result of the recipe evaluating configured rules"""
|
310
|
+
|
311
|
+
blocked: Optional[bool] = None
|
312
|
+
"""Whether or not the prompt triggered a block detection."""
|
313
|
+
|
314
|
+
fpe_context: Optional[str] = None
|
315
|
+
"""
|
316
|
+
If an FPE redaction method returned results, this will be the context passed to
|
317
|
+
unredact.
|
318
|
+
"""
|
294
319
|
|
295
320
|
prompt_messages: Optional[object] = None
|
296
321
|
"""Updated structured prompt, if applicable."""
|
297
322
|
|
298
|
-
|
299
|
-
"""
|
323
|
+
prompt_text: Optional[str] = None
|
324
|
+
"""Updated prompt text, if applicable."""
|
300
325
|
|
301
|
-
recipe: str
|
326
|
+
recipe: Optional[str] = None
|
302
327
|
"""The Recipe that was used."""
|
303
328
|
|
304
|
-
|
305
|
-
"""
|
306
|
-
If an FPE redaction method returned results, this will be the context passed
|
307
|
-
to unredact.
|
308
|
-
"""
|
329
|
+
transformed: Optional[bool] = None
|
330
|
+
"""Whether or not the original input was transformed."""
|
309
331
|
|
310
332
|
|
311
333
|
class AIGuard(ServiceBase):
|
@@ -314,11 +336,9 @@ class AIGuard(ServiceBase):
|
|
314
336
|
Provides methods to interact with Pangea's AI Guard service.
|
315
337
|
|
316
338
|
Examples:
|
317
|
-
from pangea import PangeaConfig
|
318
339
|
from pangea.services import AIGuard
|
319
340
|
|
320
|
-
|
321
|
-
ai_guard = AIGuard(token="pangea_token", config=config)
|
341
|
+
ai_guard = AIGuard(token="pangea_token")
|
322
342
|
"""
|
323
343
|
|
324
344
|
service_name = "ai-guard"
|
@@ -338,11 +358,9 @@ class AIGuard(ServiceBase):
|
|
338
358
|
config_id: Configuration ID.
|
339
359
|
|
340
360
|
Examples:
|
341
|
-
from pangea import PangeaConfig
|
342
361
|
from pangea.services import AIGuard
|
343
362
|
|
344
|
-
|
345
|
-
ai_guard = AIGuard(token="pangea_token", config=config)
|
363
|
+
ai_guard = AIGuard(token="pangea_token")
|
346
364
|
"""
|
347
365
|
|
348
366
|
super().__init__(token, config, logger_name, config_id)
|
@@ -352,29 +370,31 @@ class AIGuard(ServiceBase):
|
|
352
370
|
self,
|
353
371
|
text: str,
|
354
372
|
*,
|
355
|
-
recipe: str | None = None,
|
356
373
|
debug: bool | None = None,
|
357
|
-
overrides: Overrides | None = None,
|
358
374
|
log_fields: LogFields | None = None,
|
375
|
+
overrides: Overrides | None = None,
|
376
|
+
recipe: str | None = None,
|
359
377
|
) -> PangeaResponse[TextGuardResult]:
|
360
378
|
"""
|
361
|
-
|
379
|
+
Guard LLM input and output text
|
362
380
|
|
363
|
-
|
364
|
-
|
381
|
+
Detect, remove, or block malicious content and intent in LLM inputs and
|
382
|
+
outputs to prevent model manipulation and data leakage.
|
365
383
|
|
366
384
|
OperationId: ai_guard_post_v1_text_guard
|
367
385
|
|
368
386
|
Args:
|
369
387
|
text: Text to be scanned by AI Guard for PII, sensitive data,
|
370
388
|
malicious content, and other data types defined by the
|
371
|
-
configuration. Supports processing up to
|
372
|
-
recipe: Recipe key of a configuration of data types and settings
|
373
|
-
defined in the Pangea User Console. It specifies the rules that
|
374
|
-
are to be applied to the text, such as defang malicious URLs.
|
389
|
+
configuration. Supports processing up to 20 KiB of text.
|
375
390
|
debug: Setting this value to true will provide a detailed analysis
|
376
391
|
of the text data
|
377
392
|
log_field: Additional fields to include in activity log
|
393
|
+
overrides: Overrides flags. Note: This parameter has no effect when
|
394
|
+
the request is made by AIDR
|
395
|
+
recipe: Recipe key of a configuration of data types and settings
|
396
|
+
defined in the Pangea User Console. It specifies the rules that
|
397
|
+
are to be applied to the text, such as defang malicious URLs.
|
378
398
|
|
379
399
|
Examples:
|
380
400
|
response = ai_guard.guard_text("text")
|
@@ -391,24 +411,26 @@ class AIGuard(ServiceBase):
|
|
391
411
|
log_fields: LogFields | None = None,
|
392
412
|
) -> PangeaResponse[TextGuardResult]:
|
393
413
|
"""
|
394
|
-
|
414
|
+
Guard LLM input and output text
|
395
415
|
|
396
|
-
|
397
|
-
|
416
|
+
Detect, remove, or block malicious content and intent in LLM inputs and
|
417
|
+
outputs to prevent model manipulation and data leakage.
|
398
418
|
|
399
419
|
OperationId: ai_guard_post_v1_text_guard
|
400
420
|
|
401
421
|
Args:
|
402
422
|
messages: Structured messages data to be scanned by AI Guard for
|
403
423
|
PII, sensitive data, malicious content, and other data types
|
404
|
-
defined by the configuration. Supports processing up to
|
405
|
-
JSON text
|
406
|
-
recipe: Recipe key of a configuration of data types and settings
|
407
|
-
defined in the Pangea User Console. It specifies the rules that
|
408
|
-
are to be applied to the text, such as defang malicious URLs.
|
424
|
+
defined by the configuration. Supports processing up to 20 KiB
|
425
|
+
of JSON text using Pangea message format.
|
409
426
|
debug: Setting this value to true will provide a detailed analysis
|
410
427
|
of the text data
|
411
428
|
log_field: Additional fields to include in activity log
|
429
|
+
overrides: Overrides flags. Note: This parameter has no effect when
|
430
|
+
the request is made by AIDR
|
431
|
+
recipe: Recipe key of a configuration of data types and settings
|
432
|
+
defined in the Pangea User Console. It specifies the rules that
|
433
|
+
are to be applied to the text, such as defang malicious URLs.
|
412
434
|
|
413
435
|
Examples:
|
414
436
|
response = ai_guard.guard_text(messages=[Message(role="user", content="hello world")])
|
@@ -419,16 +441,16 @@ class AIGuard(ServiceBase):
|
|
419
441
|
text: str | None = None,
|
420
442
|
*,
|
421
443
|
messages: Sequence[Message] | None = None,
|
422
|
-
recipe: str | None = None,
|
423
444
|
debug: bool | None = None,
|
424
|
-
overrides: Overrides | None = None,
|
425
445
|
log_fields: LogFields | None = None,
|
446
|
+
overrides: Overrides | None = None,
|
447
|
+
recipe: str | None = None,
|
426
448
|
) -> PangeaResponse[TextGuardResult]:
|
427
449
|
"""
|
428
|
-
|
450
|
+
Guard LLM input and output text
|
429
451
|
|
430
|
-
|
431
|
-
|
452
|
+
Detect, remove, or block malicious content and intent in LLM inputs and
|
453
|
+
outputs to prevent model manipulation and data leakage.
|
432
454
|
|
433
455
|
OperationId: ai_guard_post_v1_text_guard
|
434
456
|
|
@@ -440,12 +462,14 @@ class AIGuard(ServiceBase):
|
|
440
462
|
PII, sensitive data, malicious content, and other data types
|
441
463
|
defined by the configuration. Supports processing up to 10KB of
|
442
464
|
JSON text
|
443
|
-
recipe: Recipe key of a configuration of data types and settings
|
444
|
-
defined in the Pangea User Console. It specifies the rules that
|
445
|
-
are to be applied to the text, such as defang malicious URLs.
|
446
465
|
debug: Setting this value to true will provide a detailed analysis
|
447
466
|
of the text data
|
448
467
|
log_field: Additional fields to include in activity log
|
468
|
+
overrides: Overrides flags. Note: This parameter has no effect when
|
469
|
+
the request is made by AIDR
|
470
|
+
recipe: Recipe key of a configuration of data types and settings
|
471
|
+
defined in the Pangea User Console. It specifies the rules that
|
472
|
+
are to be applied to the text, such as defang malicious URLs.
|
449
473
|
|
450
474
|
Examples:
|
451
475
|
response = ai_guard.guard_text("text")
|
pangea/services/audit/audit.py
CHANGED
pangea/services/audit/util.py
CHANGED
pangea/services/authn/authn.py
CHANGED
@@ -10,11 +10,10 @@ from collections.abc import Mapping
|
|
10
10
|
from typing import Dict, List, Literal, Optional, Union
|
11
11
|
|
12
12
|
import pangea.services.authn.models as m
|
13
|
-
from pangea
|
14
|
-
from pangea.response import PangeaResponse, PangeaResponseResult
|
13
|
+
from pangea import PangeaConfig, PangeaResponse, PangeaResponseResult
|
15
14
|
from pangea.services.base import ServiceBase
|
16
15
|
|
17
|
-
__all__ =
|
16
|
+
__all__ = ("AuthN",)
|
18
17
|
|
19
18
|
|
20
19
|
_SERVICE_NAME = "authn"
|
@@ -930,7 +929,7 @@ class AuthN(ServiceBase):
|
|
930
929
|
return self.request.post(
|
931
930
|
"v2/user/group/assign",
|
932
931
|
data={"id": user_id, "group_ids": group_ids},
|
933
|
-
result_class=
|
932
|
+
result_class=PangeaResponseResult,
|
934
933
|
)
|
935
934
|
|
936
935
|
def remove(self, user_id: str, group_id: str) -> PangeaResponse[PangeaResponseResult]:
|
@@ -944,7 +943,7 @@ class AuthN(ServiceBase):
|
|
944
943
|
return self.request.post(
|
945
944
|
"v2/user/group/remove",
|
946
945
|
data={"id": user_id, "group_id": group_id},
|
947
|
-
result_class=
|
946
|
+
result_class=PangeaResponseResult,
|
948
947
|
)
|
949
948
|
|
950
949
|
def list(self, user_id: str) -> PangeaResponse[m.GroupList]:
|
pangea/services/base.py
CHANGED
@@ -18,6 +18,9 @@ from pangea.exceptions import AcceptedRequestException
|
|
18
18
|
from pangea.request import PangeaRequest
|
19
19
|
from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult
|
20
20
|
|
21
|
+
__all__ = ("ServiceBase",)
|
22
|
+
|
23
|
+
|
21
24
|
TResult = TypeVar("TResult", bound=PangeaResponseResult, default=PangeaResponseResult)
|
22
25
|
|
23
26
|
|
pangea/services/file_scan.py
CHANGED
@@ -10,8 +10,9 @@ import io
|
|
10
10
|
import logging
|
11
11
|
from typing import Dict, List, Optional, Tuple
|
12
12
|
|
13
|
-
from pangea
|
14
|
-
from pangea.
|
13
|
+
from pangea import PangeaConfig, PangeaResponse, PangeaResponseResult, TransferMethod
|
14
|
+
from pangea.request import PangeaRequest
|
15
|
+
from pangea.response import APIRequestModel
|
15
16
|
from pangea.services.base import ServiceBase
|
16
17
|
from pangea.utils import FileUploadParams, get_file_upload_params
|
17
18
|
|
pangea/services/prompt_guard.py
CHANGED
pangea/services/vault/vault.py
CHANGED
@@ -88,6 +88,9 @@ if TYPE_CHECKING:
|
|
88
88
|
from pangea.request import TResult
|
89
89
|
|
90
90
|
|
91
|
+
__all__ = ("ExportEncryptionAlgorithm", "ItemType", "ItemVersionState", "TransformAlphabet", "Vault")
|
92
|
+
|
93
|
+
|
91
94
|
VaultItem = Annotated[
|
92
95
|
Union[AsymmetricKey, SymmetricKey, Secret, ClientSecret, Folder, PangeaToken], Field(discriminator="type")
|
93
96
|
]
|
@@ -1,24 +1,25 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: pangea-sdk
|
3
|
-
Version: 6.
|
3
|
+
Version: 6.5.0
|
4
4
|
Summary: Pangea API SDK
|
5
|
-
License: MIT
|
6
5
|
Keywords: Pangea,SDK,Audit
|
7
6
|
Author: Glenn Gallien
|
8
|
-
Author-email: glenn.gallien@pangea.cloud
|
9
|
-
|
7
|
+
Author-email: Glenn Gallien <glenn.gallien@pangea.cloud>
|
8
|
+
License-Expression: MIT
|
10
9
|
Classifier: Topic :: Software Development
|
11
10
|
Classifier: Topic :: Software Development :: Libraries
|
12
|
-
Requires-Dist: aiohttp
|
13
|
-
Requires-Dist: cryptography
|
14
|
-
Requires-Dist: deprecated
|
15
|
-
Requires-Dist: google-crc32c
|
16
|
-
Requires-Dist: pydantic
|
17
|
-
Requires-Dist: python-dateutil
|
18
|
-
Requires-Dist: requests
|
19
|
-
Requires-Dist: requests-toolbelt
|
20
|
-
Requires-Dist: typing-extensions
|
21
|
-
Requires-Dist: yarl
|
11
|
+
Requires-Dist: aiohttp>=3.12.15,<4.0.0
|
12
|
+
Requires-Dist: cryptography>=45.0.6,<46.0.0
|
13
|
+
Requires-Dist: deprecated>=1.2.18,<2.0.0
|
14
|
+
Requires-Dist: google-crc32c>=1.7.1,<2.0.0
|
15
|
+
Requires-Dist: pydantic>=2.11.7,<3.0.0
|
16
|
+
Requires-Dist: python-dateutil>=2.9.0.post0,<3.0.0
|
17
|
+
Requires-Dist: requests>=2.32.4,<3.0.0
|
18
|
+
Requires-Dist: requests-toolbelt>=1.0.0,<2.0.0
|
19
|
+
Requires-Dist: typing-extensions>=4.14.1,<5.0.0
|
20
|
+
Requires-Dist: yarl>=1.20.1,<2.0.0
|
21
|
+
Requires-Python: >=3.9.2, <4.0.0
|
22
|
+
Project-URL: repository, https://github.com/pangeacyber/pangea-python
|
22
23
|
Description-Content-Type: text/markdown
|
23
24
|
|
24
25
|
<a href="https://pangea.cloud?utm_source=github&utm_medium=python-sdk" target="_blank" rel="noopener noreferrer">
|
@@ -116,8 +117,7 @@ The SDK supports the following configuration options via `PangeaConfig`:
|
|
116
117
|
Use `base_url_template` for more control over the URL, such as setting
|
117
118
|
service-specific paths. Defaults to `aws.us.pangea.cloud`.
|
118
119
|
- `request_retries` — Number of retries on the initial request.
|
119
|
-
- `request_backoff` —
|
120
|
-
- `request_timeout` — Timeout used on initial request attempts.
|
120
|
+
- `request_backoff` — A backoff factor to apply between request attempts.
|
121
121
|
- `poll_result_timeout` — Timeout used to poll results after 202 (in secs).
|
122
122
|
- `queued_retry_enabled` — Enable queued request retry support.
|
123
123
|
- `custom_user_agent` — Custom user agent to be used in the request headers.
|
@@ -243,4 +243,3 @@ It accepts multiple file formats:
|
|
243
243
|
[Beta Examples]: https://github.com/pangeacyber/pangea-python/tree/beta/examples
|
244
244
|
[Pangea Console]: https://console.pangea.cloud/
|
245
245
|
[Secure Audit Log]: https://pangea.cloud/docs/audit
|
246
|
-
|
@@ -0,0 +1,62 @@
|
|
1
|
+
pangea/__init__.py,sha256=5742d82dc2d689975ba2a51445ea8d77a80526dca1b8be128b1cc08bf65a8c4e,293
|
2
|
+
pangea/_constants.py,sha256=8061a843aae14a2144c3530a486239f3c087bc5a241b509ff5292474f7518d56,113
|
3
|
+
pangea/_typing.py,sha256=f8beebc1fdfed94696cf215e09d06b6b5be360718d923df71c32fad4a13ff856,81
|
4
|
+
pangea/asyncio/__init__.py,sha256=f7acf2b406f0ef488a96a1b0175d850937f7e7cfe28e405536ea3ed6f04ec872,79
|
5
|
+
pangea/asyncio/file_uploader.py,sha256=2e7f85bec1ccf9fab8be902f7e86107af7ac42033ec9c2ea836313fb9f31a14d,1435
|
6
|
+
pangea/asyncio/request.py,sha256=acb314586c7a3d93bbc42640caf55c3904117c1a7b2340660517b71c4fd888b6,20943
|
7
|
+
pangea/asyncio/services/__init__.py,sha256=8f7f59d02a43014cdd9f90bad5bfa4642b6ff493d741f438c24252485a799173,803
|
8
|
+
pangea/asyncio/services/ai_guard.py,sha256=e2cdb2567f24f1def800e3e1e5532a0cea6603e0c4674fc0ec0af2593963d448,6393
|
9
|
+
pangea/asyncio/services/audit.py,sha256=b26670cc229adfb5b3a3bc8da9af91a7b58258d5d74027e3280db93efc4bf1fa,26127
|
10
|
+
pangea/asyncio/services/authn.py,sha256=8d634843649bfb4be7de11c6289e3b5e6fbf103b39f2f6e05fa37053f6bd13bd,52815
|
11
|
+
pangea/asyncio/services/authz.py,sha256=bed490de21185062fb6929f84be5238b0cd71e531e016d2fa757db53baf1e98f,10796
|
12
|
+
pangea/asyncio/services/base.py,sha256=e52604639395c696b9a741ed515d8eaa958d97c70ff2a6316d0be95607af64c4,3416
|
13
|
+
pangea/asyncio/services/embargo.py,sha256=72dce3de48a9eb1a2cf84bb726e3ac92b086602f13dc996c800a2964788f4973,3068
|
14
|
+
pangea/asyncio/services/file_scan.py,sha256=e4291bddc5caa5ca0eeca4d4bba7a3af5b82e37fba1096fdd56b86387ae84471,7202
|
15
|
+
pangea/asyncio/services/intel.py,sha256=48a0cec9ef9bef74929a7bdea6e450fde8f8a27ef5b8278286d21f33499cc133,40193
|
16
|
+
pangea/asyncio/services/prompt_guard.py,sha256=c7c419cd3fed27c792b720210c3674e13d045cb7f73dde770457b7f6db3a7e4d,2597
|
17
|
+
pangea/asyncio/services/redact.py,sha256=df9e8a779b30c3ac09b3103a0c5209bd510995ed349fb1e28dd20d6fad585fd1,8014
|
18
|
+
pangea/asyncio/services/sanitize.py,sha256=3b26d30147e1ffbbd84706fa0a3a78687668787848960f1c689fc156b75b0350,8691
|
19
|
+
pangea/asyncio/services/share.py,sha256=015f456c0f88314e53161701b541e85ca0d061f38858024964a5babc5a2105bb,30816
|
20
|
+
pangea/asyncio/services/vault.py,sha256=6d82146265981fc2eac9c7f20f23684bcdc145631de7ab7e44cb7407e4d4f1c4,78564
|
21
|
+
pangea/audit_logger.py,sha256=0ceccbe68c97c1a3e5b2e2ba5511d79ff94f74d73867b2c71a3efc440ad7b390,3861
|
22
|
+
pangea/config.py,sha256=29b484ab5fe1e2fa76ab66087cf09c26d69609101178a21f3639d7282fe38133,1973
|
23
|
+
pangea/crypto/rsa.py,sha256=9b04a2372e7bd4a006af717aa043340975a497d0f4db7721f2575b65978b8ffe,4747
|
24
|
+
pangea/deep_verify.py,sha256=67cbe7af1122c1ade171324ee9c919a5d49ead01e3b609d452595a59300c7702,8637
|
25
|
+
pangea/deprecated.py,sha256=df288ced69d2387ab9e513ad26f8638930d298e1086b407ce583dcb557e9f965,597
|
26
|
+
pangea/dump_audit.py,sha256=6fcf63295ddec32efb580fc0cd53084f4e3f135094c53a658fde0851124cee77,7081
|
27
|
+
pangea/exceptions.py,sha256=1221fb362343c8debd6589558a417c775b403b7fc3a346ca97c7455e0858f2dd,5585
|
28
|
+
pangea/file_uploader.py,sha256=291bb3db303ae9a3b22864bd3d7516d6abfdbcb1ce18c7754479006e11a4ddc6,1329
|
29
|
+
pangea/py.typed,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
|
30
|
+
pangea/request.py,sha256=3c06dc471ef8ea14a1b76d0afc43963de40c8c5cf18f0b3b29f74ccf383f575d,27938
|
31
|
+
pangea/response.py,sha256=d4e1b96cf584d23de9efbb56622bc6fcefced920fc8744eeabd5a537aace292d,7821
|
32
|
+
pangea/services/__init__.py,sha256=28fd94d3e4dcbac5b91f71941714bb35cfcbc7127e5f4b816f178b42618eebea,667
|
33
|
+
pangea/services/ai_guard.py,sha256=a0775d7b8dd62ba9ff520fe54006e7f8aabf778b96c65e2f43ceb61f8c65ed4e,16922
|
34
|
+
pangea/services/audit/audit.py,sha256=e348eb0803ae6729bf42c11f8608488cf9b728a5b03f1f41dd9289f93ed1e16e,39231
|
35
|
+
pangea/services/audit/exceptions.py,sha256=6e156e61ee1a9a669c395c7083df020a1c6fc197f914a811d83720a882ce7307,471
|
36
|
+
pangea/services/audit/models.py,sha256=a44e23b58027fdce4974fad705fa4a1f0a5102a3bf0d34823b2f901e43cc6a3c,15471
|
37
|
+
pangea/services/audit/signing.py,sha256=56c424b2d40bd6fc4874dd86871a783fe14b06957f048bc3b010a4440650a64f,5593
|
38
|
+
pangea/services/audit/util.py,sha256=7435420fbd15e981c55469966e6dc0387a1fc48f8e7de25e4cc0d843ee564b1a,7683
|
39
|
+
pangea/services/authn/authn.py,sha256=d3d83ef3dca6852e6d51e41758431bd9e8ca9d3b9e6972a4f0c82b744036e90a,51169
|
40
|
+
pangea/services/authn/models.py,sha256=56b7b3e66fc8bc1bd2377ba3adcb09dfcf2eeeb0f241474c53ca77b27a8f65c9,27218
|
41
|
+
pangea/services/authz.py,sha256=0c9c78d41e56f14ac63f711af6dfaa0780d27488b5b6f8ed0cc58e355e607458,16191
|
42
|
+
pangea/services/base.py,sha256=727c70092a99b7e96f606f5eb5b2515d5c6d1c7ebbb8c5b4ee9b5f55b7d57eae,3864
|
43
|
+
pangea/services/embargo.py,sha256=deb1372268c18365545d096319920279db2bd78a6c59dca60b6a6699d245d9ca,4000
|
44
|
+
pangea/services/file_scan.py,sha256=81295add5526825de203b0dcac27f504aa29bee9cf1b979c22f5f80f0cd83af7,7952
|
45
|
+
pangea/services/intel.py,sha256=52ba27ce09f31b966c986f4a9b5d89c3f6ade5b6005e817e36a818907ed659f8,56958
|
46
|
+
pangea/services/prompt_guard.py,sha256=1729c7cd6977347f862b6afd203eb67775432e04395cf7aab88ac92358544b5b,3485
|
47
|
+
pangea/services/redact.py,sha256=2c93073caf210f13cb11535f46011201680be0604c8890bfa6bd705c66fbf56f,13225
|
48
|
+
pangea/services/sanitize.py,sha256=d19942ac483c8a626d472a2fcb8a9925bd59019f29a483904e3fe7a1c049d823,13019
|
49
|
+
pangea/services/share/file_format.py,sha256=d6cbced5e7bf69e9c0f73a0efc0694f91939525a7b91c3ce73f2b036896ec901,2797
|
50
|
+
pangea/services/share/share.py,sha256=2214e296a59c4361a5b09ee41c7b956d77cdbbc8ef16d3c19c478cdba48db18f,52403
|
51
|
+
pangea/services/vault/models/asymmetric.py,sha256=17a24c77d0656096528df84945abea71a76640901b71de5dadeccb2d0fd9244b,5058
|
52
|
+
pangea/services/vault/models/common.py,sha256=570d3208b10cca6883ac51242a598fad811e8d427f2689c578c12fcbbc30660d,18050
|
53
|
+
pangea/services/vault/models/keys.py,sha256=d808b0bfa5026d3785ca4bc6616e9e5ddec9de180898609df1fe5d6281c9d9c1,2805
|
54
|
+
pangea/services/vault/models/secret.py,sha256=473e9c293456a256d6f165b7dfe17b456076f4623f957883ef685e95ba65bc59,1152
|
55
|
+
pangea/services/vault/models/symmetric.py,sha256=56a27f0b7c63d9ee0eb671623f29e05fafec39c5ca15fd7285ab5217d3e607dd,2629
|
56
|
+
pangea/services/vault/vault.py,sha256=3c9b356254ee77570f9e1c940cc82e204ca13748be85a1b592ecc0ff88728049,77676
|
57
|
+
pangea/tools.py,sha256=264c15a65bf1ecc08f45274f8454cbbce97a87b6ed6946d712e1e0532d041c15,6452
|
58
|
+
pangea/utils.py,sha256=4304ce0c8fc3f1bcbceae5de0343297612480afcf96da294b5fbf5ae0b90b215,4943
|
59
|
+
pangea/verify_audit.py,sha256=f957a940a1ed4aa651aa120a894b4bb9f6bbcb0c1d30d2cdd92ba18a780ca285,17288
|
60
|
+
pangea_sdk-6.5.0.dist-info/WHEEL,sha256=0f7d664a881437bddec71c703c3c2f01fd13581519f95130abcc96e296ef0426,79
|
61
|
+
pangea_sdk-6.5.0.dist-info/METADATA,sha256=ea6b911a8867d4bc54ff4ce3843c3e632b9ce8f151e31e9304c7ee73efc1d1cf,8029
|
62
|
+
pangea_sdk-6.5.0.dist-info/RECORD,,
|
@@ -1,60 +0,0 @@
|
|
1
|
-
pangea/__init__.py,sha256=sj1sB7F5uQpLZtaAqYFcpmFREs0nbe4XOBnRWOCA1uE,370
|
2
|
-
pangea/asyncio/__init__.py,sha256=TIiYYY-DR4X6d3rGBqpCBQkPMFkogzYLXYvi_RvmCEM,64
|
3
|
-
pangea/asyncio/file_uploader.py,sha256=FwR-p-Xgtmq3UDW6_ptRQLTL4_2AIzdaY358WjxwJBw,1436
|
4
|
-
pangea/asyncio/request.py,sha256=VX5e7xIUmtP8TBan6efiAcc9cCdXGUJOAYZN-mhgRqQ,19395
|
5
|
-
pangea/asyncio/services/__init__.py,sha256=m0nqw9_7mlachetzNxyJKZDOtEe2j2_UHFCELAE3Irg,484
|
6
|
-
pangea/asyncio/services/ai_guard.py,sha256=QaeiKZSn8aDuBPfEsF_KgUbkAtaaauSd_RTGBAbBU3g,6274
|
7
|
-
pangea/asyncio/services/audit.py,sha256=smZwzCKa37Wzo7yNqa-Rp7WCWNXXQCfjKA25PvxL8fo,26127
|
8
|
-
pangea/asyncio/services/authn.py,sha256=z22Q0ym87Sf1_X9oQzj2kiQ5Lbb0KmK4iBNEdr3XfRo,52291
|
9
|
-
pangea/asyncio/services/authz.py,sha256=vtSQ3iEYUGL7aSn4S-UjiwzXHlMeAW0vp1fbU7rx6Y8,10796
|
10
|
-
pangea/asyncio/services/base.py,sha256=ntvuwfyAuhyfrptlBg1NFViGlFb3tf9uqxnC1PiBX6U,3206
|
11
|
-
pangea/asyncio/services/embargo.py,sha256=ctzj3kip6xos-Eu3JuOskrCGYC8T3JlsgAopZHiPSXM,3068
|
12
|
-
pangea/asyncio/services/file_scan.py,sha256=OCKvrTZgsTCKA6P261PSRl4anWcU-CvDPtXfrTqAxgE,7210
|
13
|
-
pangea/asyncio/services/intel.py,sha256=SKDOye-b73SSmnvepuRQ_ej4on71uCeChtIfM0mcwTM,40193
|
14
|
-
pangea/asyncio/services/prompt_guard.py,sha256=NbYt-0tRtO5VH7kLmC1lJ5JSV-ztlb9dNFaKKs_fZUM,2553
|
15
|
-
pangea/asyncio/services/redact.py,sha256=356Kd5sww6wJsxA6DFIJvVEJle00n7HijdINb61YX9E,8014
|
16
|
-
pangea/asyncio/services/sanitize.py,sha256=OybTAUfh_7vYRwb6Cjp4aHZoeHhIlg8caJ_BVrdbA1A,8691
|
17
|
-
pangea/asyncio/services/share.py,sha256=AV9FbA-IMU5TFhcBtUHoXKDQYfOIWAJJZKW6vFohBbs,30816
|
18
|
-
pangea/asyncio/services/vault.py,sha256=bYIUYmWYH8LqycfyDyNoS83BRWMd56t-RMt0B-TU8cQ,78564
|
19
|
-
pangea/audit_logger.py,sha256=DOzL5oyXwaPlsuK6VRHXn_lPdNc4Z7LHGj78RArXs5A,3861
|
20
|
-
pangea/config.py,sha256=Z2WT_UG0qBQzzVzBfloXYFxS21mSg1YXQ36cAVCqrJk,1963
|
21
|
-
pangea/crypto/rsa.py,sha256=mwSiNy571KAGr3F6oEM0CXWkl9D023ch8ldbZZeLj_4,4747
|
22
|
-
pangea/deep_verify.py,sha256=Z8vnrxEiwa3hcTJO6ckZpdSerQHjtgnUUllaWTAMdwI,8637
|
23
|
-
pangea/deprecated.py,sha256=3yiM7WnSOHq55ROtJvhjiTDSmOEIa0B85YPctVfp-WU,597
|
24
|
-
pangea/dump_audit.py,sha256=b89jKV3ewy77WA_AzVMIT04_E1CUxTplj94IURJM7nc,7081
|
25
|
-
pangea/exceptions.py,sha256=EiH7NiNDyN69ZYlVikF8d1tAO3_Do0bKl8dFXghY8t0,5585
|
26
|
-
pangea/file_uploader.py,sha256=bDX9jZTw4h_gwFf9AjtfJYxQchLM2lVMgH93WhgCXsY,1275
|
27
|
-
pangea/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
|
-
pangea/request.py,sha256=g5kQiV_hB4A38FVQnPX5Y64Y-N9LePWnf7QiFbxleOw,25541
|
29
|
-
pangea/response.py,sha256=gE5m82v8BruKwGTMZlT_Krv1YwYAmp6dhpKnVWGZpWg,7597
|
30
|
-
pangea/services/__init__.py,sha256=CzgsgeO-wR4xTn7OUE2DhoIF4HoYQO-uA-yBhjNSF4g,428
|
31
|
-
pangea/services/ai_guard.py,sha256=bXf4hFFeNYvmdeiSwcDgAwgveTNwLXe5-KirOea3Qt0,15986
|
32
|
-
pangea/services/audit/audit.py,sha256=sBRghIhGscR46CxvWYN7FGHjZyqqtFOB4xH8CwxAsw4,39172
|
33
|
-
pangea/services/audit/exceptions.py,sha256=bhVuYe4ammacOVxwg98CChxvwZf5FKgR2DcgqILOcwc,471
|
34
|
-
pangea/services/audit/models.py,sha256=pE4jtYAn_c5JdPrXBfpKHwpRAqO_DTSCOy-QHkPMajw,15471
|
35
|
-
pangea/services/audit/signing.py,sha256=VsQkstQL1vxIdN2Ghxp4P-FLBpV_BIvDsBCkRAZQpk8,5593
|
36
|
-
pangea/services/audit/util.py,sha256=dna9AKodlJ-C_VAXFebMu2r57Fl1DdRWdb1SyG7VLpA,7651
|
37
|
-
pangea/services/authn/authn.py,sha256=vQUwf9wKKF0o-bcsyiBHky0cZ1UTqfqRCGeWPqNXdck,51206
|
38
|
-
pangea/services/authn/models.py,sha256=Vrez5m_IvBvSN3ujrcsJ388u7rDyQUdMU8p3snqPZck,27218
|
39
|
-
pangea/services/authz.py,sha256=DJx41B5W8UrGP3Ea9t-qB4DSdIi1tvjtDMWONV5gdFg,16191
|
40
|
-
pangea/services/base.py,sha256=ShkR0elPiYPln323x4L4F_hGhjQ5fB0zpGZ9J4SLk4g,3835
|
41
|
-
pangea/services/embargo.py,sha256=3rE3ImjBg2VUXQljGZICedsr14psWdymC2pmmdJF2co,4000
|
42
|
-
pangea/services/file_scan.py,sha256=DzFYJyBrByWZHUQN8ll8OvzsynT8qegMzaEMXJfiP2Q,7934
|
43
|
-
pangea/services/intel.py,sha256=UronzgnzG5ZsmG9Km12Jw_at5bYAXoF-NqgYkH7WWfg,56958
|
44
|
-
pangea/services/prompt_guard.py,sha256=Cq8ume2_YPfHre4iN6FYkyTV7NrdwLXlr_wnilfKotE,3446
|
45
|
-
pangea/services/redact.py,sha256=LJMHPK8hDxPLEVNfRgESAWgL4GBMiJC_pr1wXGb79W8,13225
|
46
|
-
pangea/services/sanitize.py,sha256=0ZlCrEg8imJtRyovy4qZJb1ZAZ8ppIOQTj_nocBJ2CM,13019
|
47
|
-
pangea/services/share/file_format.py,sha256=1svO1ee_aenA9zoO_AaU-Rk5Ulp7kcPOc_KwNoluyQE,2797
|
48
|
-
pangea/services/share/share.py,sha256=IhTilqWcQ2GlsJ7kHHuVbXfNu8jvFtPBnEeM26SNsY8,52403
|
49
|
-
pangea/services/vault/models/asymmetric.py,sha256=F6JMd9BlYJZSjfhJRavqcadmQJAbcd5drezLLQ_ZJEs,5058
|
50
|
-
pangea/services/vault/models/common.py,sha256=Vw0yCLEMymiDrFEkKlmPrYEejUJ_JonFeMEvy7wwZg0,18050
|
51
|
-
pangea/services/vault/models/keys.py,sha256=2Aiwv6UCbTeFykvGYW6eXd7J3hgImGCd8f5dYoHJ2cE,2805
|
52
|
-
pangea/services/vault/models/secret.py,sha256=Rz6cKTRWolbW8WW33-F7RWB29GI_lXiD72helbplvFk,1152
|
53
|
-
pangea/services/vault/models/symmetric.py,sha256=VqJ_C3xj2e4OtnFiPyngX6_sOcXKFf1yhatSF9PmB90,2629
|
54
|
-
pangea/services/vault/vault.py,sha256=dYkaDleCeJIiDVdwMeJXYnvKFICKI8U0uLdfX1BZYr4,77572
|
55
|
-
pangea/tools.py,sha256=JkwVplvx7MCPRSdPhFTLvOl6h7btaUbXEuHgUy0EHBU,6452
|
56
|
-
pangea/utils.py,sha256=QwTODI_D8by86uXeA0MpdhJICvz5baKUtfv1rguQshU,4943
|
57
|
-
pangea/verify_audit.py,sha256=-VepQKHtSqZRqhIKiUtLufa7ywwdMNLN2SuhingMooU,17288
|
58
|
-
pangea_sdk-6.3.0.dist-info/METADATA,sha256=pe3QGeeLCoriUi0Ty34u_vBGoGxHReAqxTeZcopf3GA,8015
|
59
|
-
pangea_sdk-6.3.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
60
|
-
pangea_sdk-6.3.0.dist-info/RECORD,,
|
pangea_sdk-6.3.0.dist-info/WHEEL
DELETED