Source code for prescient_sdk.config
from __future__ import annotations
import logging
from typing import Literal
from pydantic import Field, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
logger = logging.getLogger("prescient_sdk")
[docs]
class Settings(BaseSettings):
"""
Default configuration for the Prescient SDK.
Configuration is handled using [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)
Order of precedence for configuration values:
1. Environment variables are always highest precedence and will override any other configuration values
2. `config.env` file: if a `config.env` file is present in the root of the project, it will be used
"""
prescient_endpoint_url: str = Field(
description="Base URL of the Prescient API endpoint."
)
prescient_api_key: str | None = Field(
default=None,
description=(
"Static API key for authenticating to Prescient endpoints. When set, "
"the SDK skips the OAuth2/IDP flow and sends the key in the "
"`api-key` request header. `prescient_aws_role` is ignored "
"when ``prescient_api_key`` is set (STS requires an IDP id_token); "
"bucket credentials are fetched from `/fileproxy/credentials` instead."
),
)
prescient_auth_provider: Literal["microsoft", "google"] = Field(
default="microsoft",
description="OAuth2 authentication provider. Determines which provider-specific fields are required.",
)
prescient_client_id: str | None = Field(
default=None,
description=(
"OAuth2 client ID issued by the selected authentication provider. "
"Required when `prescient_api_key` is not set."
),
)
prescient_auth_url: str | None = Field(
default=None,
description=(
"OAuth2 token endpoint URL used to exchange credentials for access tokens. "
"Required when `prescient_api_key` is not set."
),
)
prescient_auth_token_path: str | None = Field(
default=None,
description="Deprecated. Retained for backwards compatibility; no longer used.",
)
prescient_tenant_id: str | None = Field(
default=None,
description="Microsoft Entra tenant ID. Required when `prescient_auth_provider` is `microsoft`.",
)
prescient_google_client_secret: str | None = Field(
default=None,
description="Google OAuth2 client secret. Required when `prescient_auth_provider` is `google`.",
)
prescient_google_redirect_port: int | None = Field(
default=8765,
description=(
"Loopback port for the Google OAuth2 redirect URI. Set to the registered "
"port when using a Web-application OAuth client; leave as the default for "
"Desktop-app OAuth clients, which permit any local port."
),
)
prescient_aws_role: str | None = Field(
default=None,
min_length=20,
description=(
"Optional AWS IAM role ARN. When set, the client assumes this role via STS "
"to obtain bucket credentials. When unset, the client fetches temporary "
"credentials from the Prescient API's `/fileproxy/credentials` endpoint."
),
)
prescient_aws_region: str | None = Field(
default=None,
description="AWS region used when assuming `prescient_aws_role`. Required only when that role is set.",
)
prescient_upload_role: str | None = Field(
default=None,
min_length=20,
description="Optional AWS IAM role ARN used by the upload helpers to write to the upload bucket.",
)
prescient_upload_bucket: str | None = Field(
default=None,
description="Optional AWS S3 bucket name targeted by the upload helpers.",
)
model_config = SettingsConfigDict(
env_file="config.env",
env_file_encoding="utf-8",
env_prefix="",
case_sensitive=False,
)
@model_validator(mode="after")
def validate_provider_fields(self) -> "Settings":
if self.prescient_api_key:
if self.prescient_aws_role:
logger.warning(
"prescient_aws_role cannot be used with prescient_api_key; "
"STS requires an IDP id_token. Unset one of them. "
"prescient_aws_role will be ignored."
)
return self
if not self.prescient_client_id:
raise ValueError(
"prescient_client_id is required when prescient_api_key is not set"
)
if not self.prescient_auth_url:
raise ValueError(
"prescient_auth_url is required when prescient_api_key is not set"
)
if self.prescient_auth_provider == "microsoft" and not self.prescient_tenant_id:
raise ValueError(
"prescient_tenant_id is required when prescient_auth_provider is 'microsoft'"
)
if (
self.prescient_auth_provider == "google"
and not self.prescient_google_client_secret
):
raise ValueError(
"prescient_google_client_secret is required when prescient_auth_provider is 'google'"
)
return self