Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- AI Guard: detector overrides.
- AI Guard: topic detector.
- AI Guard: `ignore_recipe` in detector overrides.
- `base_url_template` has been added to `PangeaConfig` to allow for greater
control over the complete API URL. This option may be a full URL with the
optional `{SERVICE_NAME}` placeholder, which will be replaced by the slug of
the respective service name. This supersedes `environment` and `insecure`.

### Changed

- The minimum supported version of Python is now v3.9.2.
- Updated cryptography to v44.0.2.
- Redact: `score` in `RecognizerResult` is now a float.

### Removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ async def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = SanitizeAsync(token, config)
try:
# Create Sanitize file information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ async def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = SanitizeAsync(token, config)
try:
# Create Sanitize file information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ async def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = SanitizeAsync(token, config)
try:
# Create Sanitize file information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ async def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = SanitizeAsync(token, config)
try:
# Create Sanitize file information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ async def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = SanitizeAsync(token, config)
try:
# Create Sanitize file information
Expand Down
4 changes: 2 additions & 2 deletions examples/sanitize/sanitize_examples/sanitize_and_share.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = Sanitize(token, config)
try:
# Create Sanitize file information
Expand Down
4 changes: 2 additions & 2 deletions examples/sanitize/sanitize_examples/sanitize_multipart.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = Sanitize(token, config)
try:
# Create Sanitize file information
Expand Down
4 changes: 2 additions & 2 deletions examples/sanitize/sanitize_examples/sanitize_no_share.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = Sanitize(token, config)
try:
# Create Sanitize file information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = Sanitize(token, config)
try:
# Create Sanitize file information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
# Create Sanitize client with its token and its config
config = PangeaConfig(domain=domain)

# Create Sanitize client with its token and its config
client = Sanitize(token, config)
try:
# Create Sanitize file information
Expand Down
2 changes: 1 addition & 1 deletion examples/vault/vault_examples/encrypt_structured.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def main() -> None:
domain = os.getenv("PANGEA_DOMAIN")
assert domain

config = PangeaConfig(domain)
config = PangeaConfig(domain=domain)
vault = Vault(token, config)

# First create an encryption key, either from the Pangea Console or
Expand Down
2 changes: 1 addition & 1 deletion packages/pangea-django/.django-ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.django-base:
image: python:3.9@sha256:a847112640804ed2d03bb774d46bb1619bd37862fb2b7e48eebe425a168c153b
image: python:3.9.20@sha256:ef79f8314118b7cde6910d35f4166c902e7f87f47086686256556b97d991a0fb
before_script:
- !reference [.setup, update-pip]
- !reference [.setup, update-poetry]
Expand Down
2 changes: 1 addition & 1 deletion packages/pangea-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# Pangea Python SDK

A Python SDK for integrating with Pangea services. Supports Python v3.9 and
A Python SDK for integrating with Pangea services. Supports Python v3.9.2 and
above.

## Installation
Expand Down
41 changes: 23 additions & 18 deletions packages/pangea-sdk/pangea/config.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,30 @@
# Copyright 2022 Pangea Cyber Corporation
# Author: Pangea Cyber Corporation
from __future__ import annotations

from dataclasses import dataclass
from typing import Literal, Optional
from typing import Any, Optional

from pydantic import BaseModel, model_validator

@dataclass
class PangeaConfig:
"""Holds run time configuration information used by SDK components."""

domain: str = "aws.us.pangea.cloud"
"""
Used to set Pangea domain (and port if needed), it should not include service subdomain
just for particular use cases when environment = "local", domain could be set to an url including:
scheme (http:// or https://), subdomain, domain and port.
"""
class PangeaConfig(BaseModel):
"""Holds run time configuration information used by SDK components."""

environment: Literal["production", "local"] = "production"
base_url_template: str = "https://{SERVICE_NAME}.aws.us.pangea.cloud"
"""
Pangea environment, used to construct service URLs.

If set to "local", then `domain` must be the full host (i.e., hostname and
port) for the Pangea service that this `PangeaConfig` will be used for.
Template for constructing the base URL for API requests. The placeholder
`{SERVICE_NAME}` will be replaced with the service name slug. This is a
more powerful version of `domain` that allows for setting more than just
the host of the API server. Defaults to
`https://{SERVICE_NAME}.aws.us.pangea.cloud`.
"""

insecure: bool = False
domain: str = "aws.us.pangea.cloud"
"""
Set to true to use plain http
Base domain for API requests. This is a weaker version of `base_url_template`
that only allows for setting the host of the API server. Use
`base_url_template` for more control over the URL, such as setting
service-specific paths. Defaults to `aws.us.pangea.cloud`.
"""

request_retries: int = 3
Expand Down Expand Up @@ -58,3 +56,10 @@ class PangeaConfig:
"""
Extra user agent to be added to request user agent
"""

@model_validator(mode="before")
@classmethod
def _domain_backwards_compat(cls, data: Any) -> Any:
if isinstance(data, dict) and "base_url_template" not in data and "domain" in data:
return {**data, "base_url_template": f"https://{{SERVICE_NAME}}.{data['domain']}"}
return data
21 changes: 6 additions & 15 deletions packages/pangea-sdk/pangea/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from requests.adapters import HTTPAdapter, Retry
from requests_toolbelt import MultipartDecoder # type: ignore[import-untyped]
from typing_extensions import TypeVar
from yarl import URL

import pangea
import pangea.exceptions as pe
Expand Down Expand Up @@ -107,24 +108,16 @@ def _get_poll_path(self, request_id: str):
return f"request/{request_id}"

def _url(self, path: str) -> str:
if self.config.domain.startswith("http://") or self.config.domain.startswith("https://"):
# it's URL
url = f"{self.config.domain}/{path}"
else:
schema = "http://" if self.config.insecure else "https://"
domain = (
self.config.domain if self.config.environment == "local" else f"{self.service}.{self.config.domain}"
)
url = f"{schema}{domain}/{path}"
return url
url = URL(self.config.base_url_template.format(SERVICE_NAME=self.service))
return str(url / path)

def _headers(self) -> dict:
headers = {
"User-Agent": self._user_agent,
"Authorization": f"Bearer {self.token}",
}

# We want to ignore previous headers if user tryed to set them, so we will overwrite them.
# We want to ignore previous headers if user tried to set them, so we will overwrite them.
self._extra_headers.update(headers)
return self._extra_headers

Expand Down Expand Up @@ -628,9 +621,7 @@ def _init_session(self) -> requests.Session:
adapter = HTTPAdapter(max_retries=retry_config)
session = requests.Session()

if self.config.insecure:
session.mount("http://", adapter)
else:
session.mount("https://", adapter)
session.mount("http://", adapter)
session.mount("https://", adapter)

return session
Loading