diff --git a/.changelog-pending/2026-07-28T20-32-35-c7b77690a4486560659df08d947039af4cd52055.md b/.changelog-pending/2026-07-28T20-32-35-c7b77690a4486560659df08d947039af4cd52055.md new file mode 100644 index 00000000..f092f200 --- /dev/null +++ b/.changelog-pending/2026-07-28T20-32-35-c7b77690a4486560659df08d947039af4cd52055.md @@ -0,0 +1,5 @@ +* [#704](https://github.com/workos/workos-python/pull/704) feat(generated)!: regenerate from spec (1 change) + + **Fixes** + * **[sso](https://workos.com/docs/reference/sso)**: + * Removed `callback_endpoint` from `Connection` diff --git a/.last-synced-sha b/.last-synced-sha index dd187756..93c9c21a 100644 --- a/.last-synced-sha +++ b/.last-synced-sha @@ -1 +1 @@ -904c5bccd2c6d0511ad2d0760e57d139143f1773 +ae3ebbb08d9b4bf9b2391558e820b7eb6f511fb9 diff --git a/src/workos/common/models/connection_state.py b/src/workos/common/models/connection_state.py index c519ac06..67f56b11 100644 --- a/src/workos/common/models/connection_state.py +++ b/src/workos/common/models/connection_state.py @@ -5,7 +5,6 @@ from __future__ import annotations from enum import Enum -from typing import Optional from typing import Literal, TypeAlias @@ -20,7 +19,7 @@ class ConnectionState(str, Enum): DELETING = "deleting" @classmethod - def _missing_(cls, value: object) -> Optional["ConnectionState"]: + def _missing_(cls, value: object) -> ConnectionState | None: if not isinstance(value, str): return None unknown = str.__new__(cls, value) diff --git a/src/workos/common/models/connection_type.py b/src/workos/common/models/connection_type.py index cd67feea..31b74d2b 100644 --- a/src/workos/common/models/connection_type.py +++ b/src/workos/common/models/connection_type.py @@ -5,7 +5,6 @@ from __future__ import annotations from enum import Enum -from typing import Optional from typing import Literal, TypeAlias @@ -65,7 +64,7 @@ class ConnectionType(str, Enum): XERO_OAUTH = "XeroOAuth" @classmethod - def _missing_(cls, value: object) -> Optional["ConnectionType"]: + def _missing_(cls, value: object) -> ConnectionType | None: if not isinstance(value, str): return None unknown = str.__new__(cls, value) diff --git a/src/workos/sso/_resource.py b/src/workos/sso/_resource.py index 4cbf89a4..241ac076 100644 --- a/src/workos/sso/_resource.py +++ b/src/workos/sso/_resource.py @@ -2,36 +2,43 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional, Union +from typing import TYPE_CHECKING, Any, Literal if TYPE_CHECKING: from .._client import AsyncWorkOSClient, WorkOSClient -from .._types import RequestOptions, enum_value -from .models import Connection, Profile, SSOLogoutAuthorizeResponse, SSOTokenResponse -from .models import ConnectionsConnectionType, SSOProvider from workos.common.models.pagination_order import PaginationOrder + from .._pagination import AsyncPage, SyncPage +from .._types import RequestOptions, enum_value +from .models import ( + Connection, + ConnectionsConnectionType, + Profile, + SSOLogoutAuthorizeResponse, + SSOProvider, + SSOTokenResponse, +) class SSO: """SSO API resources.""" - def __init__(self, client: "WorkOSClient") -> None: + def __init__(self, client: WorkOSClient) -> None: self._client = client def list_connections( self, *, - limit: Optional[int] = None, - before: Optional[str] = None, - after: Optional[str] = None, - order: Optional[Union[PaginationOrder, str]] = "desc", - connection_type: Optional[Union[ConnectionsConnectionType, str]] = None, - domain: Optional[str] = None, - organization_id: Optional[str] = None, - search: Optional[str] = None, - request_options: Optional[RequestOptions] = None, + limit: int | None = None, + before: str | None = None, + after: str | None = None, + order: PaginationOrder | str | None = "desc", + connection_type: ConnectionsConnectionType | str | None = None, + domain: str | None = None, + organization_id: str | None = None, + search: str | None = None, + request_options: RequestOptions | None = None, ) -> SyncPage[Connection]: """List Connections @@ -86,7 +93,7 @@ def get_connection( self, id: str, *, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> Connection: """Get a Connection @@ -117,7 +124,7 @@ def delete_connection( self, id: str, *, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> None: """Delete a Connection @@ -143,20 +150,20 @@ def delete_connection( def get_authorization_url( self, *, - provider_scopes: Optional[List[str]] = None, - provider_query_params: Optional[Dict[str, str]] = None, - client_id: Optional[str] = None, - domain: Optional[str] = None, - provider: Optional[Union[SSOProvider, str]] = None, + provider_scopes: list[str] | None = None, + provider_query_params: dict[str, str] | None = None, + client_id: str | None = None, + domain: str | None = None, + provider: SSOProvider | str | None = None, redirect_uri: str, - state: Optional[str] = None, - connection: Optional[str] = None, - organization: Optional[str] = None, - domain_hint: Optional[str] = None, - login_hint: Optional[str] = None, - nonce: Optional[str] = None, - prompt: Optional[Literal["login"]] = None, - request_options: Optional[RequestOptions] = None, + state: str | None = None, + connection: str | None = None, + organization: str | None = None, + domain_hint: str | None = None, + login_hint: str | None = None, + nonce: str | None = None, + prompt: Literal["login"] | None = None, + request_options: RequestOptions | None = None, ) -> str: """Initiate SSO @@ -177,7 +184,7 @@ def get_authorization_url( domain_hint: Can be used to pre-fill the domain field when initiating authentication with Microsoft OAuth or with a Google SAML connection type. login_hint: Can be used to pre-fill the username/email address field of the IdP sign-in page for the user, if you know their username ahead of time. Currently supported for OAuth, OpenID Connect, Okta, Entra ID, and custom SAML connections. nonce: A random string generated by the client that is used to mitigate replay attacks. - prompt: If set to `login`, forces re-authentication at the identity provider. For SAML connections this sets `ForceAuthn="true"` in the SAML request. + prompt: If set to `login`, forces re-authentication at the identity provider. For supported SAML providers this sets `ForceAuthn="true"` in the SAML request; providers that don't support it are unaffected. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -218,7 +225,7 @@ def get_logout_url( self, *, token: str, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> str: """Logout Redirect @@ -252,7 +259,7 @@ def authorize_logout( self, *, profile_id: str, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> SSOLogoutAuthorizeResponse: """Logout Authorize @@ -272,7 +279,7 @@ def authorize_logout( RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. """ - body: Dict[str, Any] = { + body: dict[str, Any] = { "profile_id": profile_id, } return self._client.request( @@ -287,7 +294,7 @@ def get_profile( self, *, access_token: str, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> Profile: """Get a User Profile @@ -325,7 +332,7 @@ def get_profile_and_token( self, *, code: str, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> SSOTokenResponse: """Get a Profile and Token @@ -346,7 +353,7 @@ def get_profile_and_token( RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. """ - body: Dict[str, Any] = { + body: dict[str, Any] = { "code": code, } body["grant_type"] = "authorization_code" @@ -368,15 +375,15 @@ def get_authorization_url_with_pkce( self, *, redirect_uri: str, - client_id: Optional[str] = None, - connection: Optional[str] = None, - organization: Optional[str] = None, - provider: Optional[Union[SSOProvider, str]] = None, - domain_hint: Optional[str] = None, - login_hint: Optional[str] = None, - provider_scopes: Optional[List[str]] = None, - provider_query_params: Optional[Dict[str, str]] = None, - ) -> Dict[str, str]: + client_id: str | None = None, + connection: str | None = None, + organization: str | None = None, + provider: SSOProvider | str | None = None, + domain_hint: str | None = None, + login_hint: str | None = None, + provider_scopes: list[str] | None = None, + provider_query_params: dict[str, str] | None = None, + ) -> dict[str, str]: """Generate an SSO authorization URL with auto-generated PKCE parameters.""" from ..pkce import PKCE @@ -412,12 +419,12 @@ def get_profile_and_token_pkce( *, code: str, code_verifier: str, - client_id: Optional[str] = None, - request_options: Optional[RequestOptions] = None, + client_id: str | None = None, + request_options: RequestOptions | None = None, ) -> SSOTokenResponse: """Exchange an authorization code using a PKCE code_verifier for SSO.""" resolved_client_id = client_id or self._client._require_client_id() - body: Dict[str, Any] = { + body: dict[str, Any] = { "client_id": resolved_client_id, "code": code, "grant_type": "authorization_code", @@ -440,21 +447,21 @@ def get_profile_and_token_pkce( class AsyncSSO: """SSO API resources (async).""" - def __init__(self, client: "AsyncWorkOSClient") -> None: + def __init__(self, client: AsyncWorkOSClient) -> None: self._client = client async def list_connections( self, *, - limit: Optional[int] = None, - before: Optional[str] = None, - after: Optional[str] = None, - order: Optional[Union[PaginationOrder, str]] = "desc", - connection_type: Optional[Union[ConnectionsConnectionType, str]] = None, - domain: Optional[str] = None, - organization_id: Optional[str] = None, - search: Optional[str] = None, - request_options: Optional[RequestOptions] = None, + limit: int | None = None, + before: str | None = None, + after: str | None = None, + order: PaginationOrder | str | None = "desc", + connection_type: ConnectionsConnectionType | str | None = None, + domain: str | None = None, + organization_id: str | None = None, + search: str | None = None, + request_options: RequestOptions | None = None, ) -> AsyncPage[Connection]: """List Connections @@ -509,7 +516,7 @@ async def get_connection( self, id: str, *, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> Connection: """Get a Connection @@ -540,7 +547,7 @@ async def delete_connection( self, id: str, *, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> None: """Delete a Connection @@ -566,20 +573,20 @@ async def delete_connection( def get_authorization_url( self, *, - provider_scopes: Optional[List[str]] = None, - provider_query_params: Optional[Dict[str, str]] = None, - client_id: Optional[str] = None, - domain: Optional[str] = None, - provider: Optional[Union[SSOProvider, str]] = None, + provider_scopes: list[str] | None = None, + provider_query_params: dict[str, str] | None = None, + client_id: str | None = None, + domain: str | None = None, + provider: SSOProvider | str | None = None, redirect_uri: str, - state: Optional[str] = None, - connection: Optional[str] = None, - organization: Optional[str] = None, - domain_hint: Optional[str] = None, - login_hint: Optional[str] = None, - nonce: Optional[str] = None, - prompt: Optional[Literal["login"]] = None, - request_options: Optional[RequestOptions] = None, + state: str | None = None, + connection: str | None = None, + organization: str | None = None, + domain_hint: str | None = None, + login_hint: str | None = None, + nonce: str | None = None, + prompt: Literal["login"] | None = None, + request_options: RequestOptions | None = None, ) -> str: """Initiate SSO @@ -600,7 +607,7 @@ def get_authorization_url( domain_hint: Can be used to pre-fill the domain field when initiating authentication with Microsoft OAuth or with a Google SAML connection type. login_hint: Can be used to pre-fill the username/email address field of the IdP sign-in page for the user, if you know their username ahead of time. Currently supported for OAuth, OpenID Connect, Okta, Entra ID, and custom SAML connections. nonce: A random string generated by the client that is used to mitigate replay attacks. - prompt: If set to `login`, forces re-authentication at the identity provider. For SAML connections this sets `ForceAuthn="true"` in the SAML request. + prompt: If set to `login`, forces re-authentication at the identity provider. For supported SAML providers this sets `ForceAuthn="true"` in the SAML request; providers that don't support it are unaffected. request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override. Returns: @@ -641,7 +648,7 @@ def get_logout_url( self, *, token: str, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> str: """Logout Redirect @@ -675,7 +682,7 @@ async def authorize_logout( self, *, profile_id: str, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> SSOLogoutAuthorizeResponse: """Logout Authorize @@ -695,7 +702,7 @@ async def authorize_logout( RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. """ - body: Dict[str, Any] = { + body: dict[str, Any] = { "profile_id": profile_id, } return await self._client.request( @@ -710,7 +717,7 @@ async def get_profile( self, *, access_token: str, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> Profile: """Get a User Profile @@ -748,7 +755,7 @@ async def get_profile_and_token( self, *, code: str, - request_options: Optional[RequestOptions] = None, + request_options: RequestOptions | None = None, ) -> SSOTokenResponse: """Get a Profile and Token @@ -769,7 +776,7 @@ async def get_profile_and_token( RateLimitExceededError: If rate limited (429). ServerError: If the server returns a 5xx error. """ - body: Dict[str, Any] = { + body: dict[str, Any] = { "code": code, } body["grant_type"] = "authorization_code" @@ -791,15 +798,15 @@ async def get_authorization_url_with_pkce( self, *, redirect_uri: str, - client_id: Optional[str] = None, - connection: Optional[str] = None, - organization: Optional[str] = None, - provider: Optional[Union[SSOProvider, str]] = None, - domain_hint: Optional[str] = None, - login_hint: Optional[str] = None, - provider_scopes: Optional[List[str]] = None, - provider_query_params: Optional[Dict[str, str]] = None, - ) -> Dict[str, str]: + client_id: str | None = None, + connection: str | None = None, + organization: str | None = None, + provider: SSOProvider | str | None = None, + domain_hint: str | None = None, + login_hint: str | None = None, + provider_scopes: list[str] | None = None, + provider_query_params: dict[str, str] | None = None, + ) -> dict[str, str]: """Generate an SSO authorization URL with auto-generated PKCE parameters.""" from ..pkce import PKCE @@ -835,12 +842,12 @@ async def get_profile_and_token_pkce( *, code: str, code_verifier: str, - client_id: Optional[str] = None, - request_options: Optional[RequestOptions] = None, + client_id: str | None = None, + request_options: RequestOptions | None = None, ) -> SSOTokenResponse: """Exchange an authorization code using a PKCE code_verifier for SSO.""" resolved_client_id = client_id or self._client._require_client_id() - body: Dict[str, Any] = { + body: dict[str, Any] = { "client_id": resolved_client_id, "code": code, "grant_type": "authorization_code", diff --git a/src/workos/sso/models/connection.py b/src/workos/sso/models/connection.py index 0c513b04..4807d984 100644 --- a/src/workos/sso/models/connection.py +++ b/src/workos/sso/models/connection.py @@ -5,16 +5,15 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import cast -from typing import Any, Dict, List, Literal, Optional -from workos._types import _raise_deserialize_error -from workos._types import _format_datetime, _parse_datetime +from typing import Any, Literal, cast -from .connection_domain import ConnectionDomain +from workos._types import _format_datetime, _parse_datetime, _raise_deserialize_error from workos.common.models.connection_state import ConnectionState from workos.common.models.connection_status import ConnectionStatus from workos.common.models.connection_type import ConnectionType +from .connection_domain import ConnectionDomain + @dataclass(slots=True) class Connection: @@ -24,29 +23,27 @@ class Connection: """Distinguishes the Connection object.""" id: str """Unique identifier for the Connection.""" - connection_type: "ConnectionType" + connection_type: ConnectionType """The type of the SSO Connection used to authenticate the user. The Connection type may be used to dynamically generate authorization URLs.""" name: str """A human-readable name for the Connection. This will most commonly be the organization's name.""" - state: "ConnectionState" + state: ConnectionState """Indicates whether a Connection is able to authenticate users.""" - domains: List["ConnectionDomain"] + domains: list[ConnectionDomain] """List of Organization Domains.""" created_at: datetime """An ISO 8601 timestamp.""" updated_at: datetime """An ISO 8601 timestamp.""" - organization_id: Optional[str] = None + organization_id: str | None = None """Unique identifier for the Organization in which the Connection resides.""" - status: Optional["ConnectionStatus"] = None + status: ConnectionStatus | None = None """Deprecated. Use `state` instead. .. deprecated:: This field is deprecated.""" - callback_endpoint: Optional[str] = None - """The immutable callback endpoint for this Connection. For SAML connections this is the ACS URL; for OIDC connections this is the redirect URI.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "Connection": + def from_dict(cls, data: dict[str, Any]) -> Connection: """Deserialize from a dictionary.""" try: return cls( @@ -56,7 +53,7 @@ def from_dict(cls, data: Dict[str, Any]) -> "Connection": name=data["name"], state=ConnectionState(data["state"]), domains=[ - ConnectionDomain.from_dict(cast(Dict[str, Any], item)) + ConnectionDomain.from_dict(cast(dict[str, Any], item)) for item in cast(list[Any], data["domains"]) ], created_at=_parse_datetime(data["created_at"]), @@ -65,14 +62,13 @@ def from_dict(cls, data: Dict[str, Any]) -> "Connection": status=ConnectionStatus(_v_status) if (_v_status := data.get("status")) is not None else None, - callback_endpoint=data.get("callback_endpoint"), ) except (KeyError, ValueError) as e: _raise_deserialize_error("Connection", e) - def to_dict(self) -> Dict[str, Any]: + def to_dict(self) -> dict[str, Any]: """Serialize to a dictionary.""" - result: Dict[str, Any] = {} + result: dict[str, Any] = {} result["object"] = self.object result["id"] = self.id result["connection_type"] = ( @@ -93,6 +89,4 @@ def to_dict(self) -> Dict[str, Any]: result["status"] = ( self.status.value if isinstance(self.status, Enum) else self.status ) - if self.callback_endpoint is not None: - result["callback_endpoint"] = self.callback_endpoint return result diff --git a/src/workos/sso/models/connection_domain.py b/src/workos/sso/models/connection_domain.py index 96a4f53d..ddae9d30 100644 --- a/src/workos/sso/models/connection_domain.py +++ b/src/workos/sso/models/connection_domain.py @@ -1,6 +1,7 @@ # This file is auto-generated by oagen. Do not edit. from typing import TypeAlias + from workos.common.models.connection_activated_data_domain import ( ConnectionActivatedDataDomain, ) diff --git a/src/workos/sso/models/connections_connection_type.py b/src/workos/sso/models/connections_connection_type.py index 23a0c60f..414ea61c 100644 --- a/src/workos/sso/models/connections_connection_type.py +++ b/src/workos/sso/models/connections_connection_type.py @@ -5,7 +5,6 @@ from __future__ import annotations from enum import Enum -from typing import Optional from typing import Literal, TypeAlias @@ -62,7 +61,7 @@ class ConnectionsConnectionType(str, Enum): XERO_OAUTH = "XeroOAuth" @classmethod - def _missing_(cls, value: object) -> Optional["ConnectionsConnectionType"]: + def _missing_(cls, value: object) -> ConnectionsConnectionType | None: if not isinstance(value, str): return None unknown = str.__new__(cls, value) diff --git a/src/workos/sso/models/profile.py b/src/workos/sso/models/profile.py index f6e58f0f..c758541f 100644 --- a/src/workos/sso/models/profile.py +++ b/src/workos/sso/models/profile.py @@ -4,12 +4,11 @@ from dataclasses import dataclass from enum import Enum -from typing import cast -from typing import Any, Dict, List, Literal, Optional -from workos._types import _raise_deserialize_error +from typing import Any, Literal, cast -from workos.common.models.slim_role import SlimRole +from workos._types import _raise_deserialize_error from workos.common.models.profile_connection_type import ProfileConnectionType +from workos.common.models.slim_role import SlimRole @dataclass(slots=True) @@ -20,35 +19,35 @@ class Profile: """Distinguishes the profile object.""" id: str """Unique identifier of the profile.""" - organization_id: Optional[str] + organization_id: str | None """The ID of the organization the user belongs to.""" connection_id: str """The ID of the SSO connection used for authentication.""" - connection_type: "ProfileConnectionType" + connection_type: ProfileConnectionType """The type of SSO connection.""" idp_id: str """The user's unique identifier from the identity provider.""" email: str """The user's email address.""" - first_name: Optional[str] + first_name: str | None """The user's first name.""" - last_name: Optional[str] + last_name: str | None """The user's last name.""" - name: Optional[str] + name: str | None """The user's full name.""" - raw_attributes: Dict[str, Any] + raw_attributes: dict[str, Any] """The complete set of raw attributes returned by the identity provider.""" - role: Optional["SlimRole"] = None + role: SlimRole | None = None """The role assigned to the user within the organization, if applicable.""" - roles: Optional[List["SlimRole"]] = None + roles: list[SlimRole] | None = None """The roles assigned to the user within the organization, if applicable.""" - groups: Optional[List[str]] = None + groups: list[str] | None = None """The groups the user belongs to, as returned by the identity provider.""" - custom_attributes: Optional[Dict[str, Any]] = None + custom_attributes: dict[str, Any] | None = None """Custom attribute mappings defined for the connection, returned as key-value pairs.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "Profile": + def from_dict(cls, data: dict[str, Any]) -> Profile: """Deserialize from a dictionary.""" try: return cls( @@ -63,11 +62,11 @@ def from_dict(cls, data: Dict[str, Any]) -> "Profile": last_name=data["last_name"], name=data["name"], raw_attributes=data["raw_attributes"], - role=SlimRole.from_dict(cast(Dict[str, Any], _v_role)) + role=SlimRole.from_dict(cast(dict[str, Any], _v_role)) if (_v_role := data.get("role")) is not None else None, roles=[ - SlimRole.from_dict(cast(Dict[str, Any], item)) + SlimRole.from_dict(cast(dict[str, Any], item)) for item in cast(list[Any], _v_roles) ] if (_v_roles := data.get("roles")) is not None @@ -78,9 +77,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "Profile": except (KeyError, ValueError) as e: _raise_deserialize_error("Profile", e) - def to_dict(self) -> Dict[str, Any]: + def to_dict(self) -> dict[str, Any]: """Serialize to a dictionary.""" - result: Dict[str, Any] = {} + result: dict[str, Any] = {} result["object"] = self.object result["id"] = self.id if self.organization_id is not None: diff --git a/src/workos/sso/models/sso_authorize_url_response.py b/src/workos/sso/models/sso_authorize_url_response.py index ae08dfa0..44bebf78 100644 --- a/src/workos/sso/models/sso_authorize_url_response.py +++ b/src/workos/sso/models/sso_authorize_url_response.py @@ -3,7 +3,8 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Any, Dict +from typing import Any + from workos._types import _raise_deserialize_error @@ -15,7 +16,7 @@ class SSOAuthorizeUrlResponse: """An OAuth 2.0 authorization URL.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "SSOAuthorizeUrlResponse": + def from_dict(cls, data: dict[str, Any]) -> SSOAuthorizeUrlResponse: """Deserialize from a dictionary.""" try: return cls( @@ -24,8 +25,8 @@ def from_dict(cls, data: Dict[str, Any]) -> "SSOAuthorizeUrlResponse": except (KeyError, ValueError) as e: _raise_deserialize_error("SSOAuthorizeUrlResponse", e) - def to_dict(self) -> Dict[str, Any]: + def to_dict(self) -> dict[str, Any]: """Serialize to a dictionary.""" - result: Dict[str, Any] = {} + result: dict[str, Any] = {} result["url"] = self.url return result diff --git a/src/workos/sso/models/sso_logout_authorize_request.py b/src/workos/sso/models/sso_logout_authorize_request.py index 359ae4f0..3114fa38 100644 --- a/src/workos/sso/models/sso_logout_authorize_request.py +++ b/src/workos/sso/models/sso_logout_authorize_request.py @@ -3,7 +3,8 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Any, Dict +from typing import Any + from workos._types import _raise_deserialize_error @@ -15,7 +16,7 @@ class SSOLogoutAuthorizeRequest: """The unique ID of the profile to log out.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "SSOLogoutAuthorizeRequest": + def from_dict(cls, data: dict[str, Any]) -> SSOLogoutAuthorizeRequest: """Deserialize from a dictionary.""" try: return cls( @@ -24,8 +25,8 @@ def from_dict(cls, data: Dict[str, Any]) -> "SSOLogoutAuthorizeRequest": except (KeyError, ValueError) as e: _raise_deserialize_error("SSOLogoutAuthorizeRequest", e) - def to_dict(self) -> Dict[str, Any]: + def to_dict(self) -> dict[str, Any]: """Serialize to a dictionary.""" - result: Dict[str, Any] = {} + result: dict[str, Any] = {} result["profile_id"] = self.profile_id return result diff --git a/src/workos/sso/models/sso_logout_authorize_response.py b/src/workos/sso/models/sso_logout_authorize_response.py index 0d438f3b..dc9be7b2 100644 --- a/src/workos/sso/models/sso_logout_authorize_response.py +++ b/src/workos/sso/models/sso_logout_authorize_response.py @@ -3,7 +3,8 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Any, Dict +from typing import Any + from workos._types import _raise_deserialize_error @@ -17,7 +18,7 @@ class SSOLogoutAuthorizeResponse: """The logout token to be used in the [Logout Redirect](https://workos.com/docs/reference/sso/logout) endpoint.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "SSOLogoutAuthorizeResponse": + def from_dict(cls, data: dict[str, Any]) -> SSOLogoutAuthorizeResponse: """Deserialize from a dictionary.""" try: return cls( @@ -27,9 +28,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "SSOLogoutAuthorizeResponse": except (KeyError, ValueError) as e: _raise_deserialize_error("SSOLogoutAuthorizeResponse", e) - def to_dict(self) -> Dict[str, Any]: + def to_dict(self) -> dict[str, Any]: """Serialize to a dictionary.""" - result: Dict[str, Any] = {} + result: dict[str, Any] = {} result["logout_url"] = self.logout_url result["logout_token"] = self.logout_token return result diff --git a/src/workos/sso/models/sso_provider.py b/src/workos/sso/models/sso_provider.py index fc546042..57f061b7 100644 --- a/src/workos/sso/models/sso_provider.py +++ b/src/workos/sso/models/sso_provider.py @@ -5,7 +5,6 @@ from __future__ import annotations from enum import Enum -from typing import Optional from typing import Literal, TypeAlias @@ -27,7 +26,7 @@ class SSOProvider(str, Enum): XERO_OAUTH = "XeroOAuth" @classmethod - def _missing_(cls, value: object) -> Optional["SSOProvider"]: + def _missing_(cls, value: object) -> SSOProvider | None: if not isinstance(value, str): return None unknown = str.__new__(cls, value) diff --git a/src/workos/sso/models/sso_token_response.py b/src/workos/sso/models/sso_token_response.py index 0c5777ad..c1046416 100644 --- a/src/workos/sso/models/sso_token_response.py +++ b/src/workos/sso/models/sso_token_response.py @@ -3,8 +3,8 @@ from __future__ import annotations from dataclasses import dataclass -from typing import cast -from typing import Any, Dict, Literal, Optional +from typing import Any, Literal, cast + from workos._types import _raise_deserialize_error from .profile import Profile @@ -21,22 +21,22 @@ class SSOTokenResponse: """An access token that can be exchanged for a user profile. Access tokens are short-lived — see the `expires_in` field for the exact lifetime.""" expires_in: int """The lifetime of the access token in seconds.""" - profile: "Profile" + profile: Profile """The user profile returned by the identity provider.""" - oauth_tokens: Optional["SSOTokenResponseOAuthToken"] = None + oauth_tokens: SSOTokenResponseOAuthToken | None = None """OAuth tokens issued by the identity provider, if available.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "SSOTokenResponse": + def from_dict(cls, data: dict[str, Any]) -> SSOTokenResponse: """Deserialize from a dictionary.""" try: return cls( token_type=data.get("token_type", "Bearer"), access_token=data["access_token"], expires_in=data["expires_in"], - profile=Profile.from_dict(cast(Dict[str, Any], data["profile"])), + profile=Profile.from_dict(cast(dict[str, Any], data["profile"])), oauth_tokens=SSOTokenResponseOAuthToken.from_dict( - cast(Dict[str, Any], _v_oauth_tokens) + cast(dict[str, Any], _v_oauth_tokens) ) if (_v_oauth_tokens := data.get("oauth_tokens")) is not None else None, @@ -44,9 +44,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "SSOTokenResponse": except (KeyError, ValueError) as e: _raise_deserialize_error("SSOTokenResponse", e) - def to_dict(self) -> Dict[str, Any]: + def to_dict(self) -> dict[str, Any]: """Serialize to a dictionary.""" - result: Dict[str, Any] = {} + result: dict[str, Any] = {} result["token_type"] = self.token_type result["access_token"] = self.access_token result["expires_in"] = self.expires_in diff --git a/src/workos/sso/models/sso_token_response_oauth_token.py b/src/workos/sso/models/sso_token_response_oauth_token.py index ea90e36d..4588871c 100644 --- a/src/workos/sso/models/sso_token_response_oauth_token.py +++ b/src/workos/sso/models/sso_token_response_oauth_token.py @@ -1,6 +1,7 @@ # This file is auto-generated by oagen. Do not edit. from typing import TypeAlias + from workos.user_management.models.authenticate_response_oauth_token import ( AuthenticateResponseOAuthToken, ) diff --git a/src/workos/sso/models/token_query.py b/src/workos/sso/models/token_query.py index 56c666fa..355aa3c0 100644 --- a/src/workos/sso/models/token_query.py +++ b/src/workos/sso/models/token_query.py @@ -3,7 +3,8 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Any, Dict, Literal +from typing import Any, Literal + from workos._types import _raise_deserialize_error @@ -21,7 +22,7 @@ class TokenQuery: """The grant type for the token request.""" @classmethod - def from_dict(cls, data: Dict[str, Any]) -> "TokenQuery": + def from_dict(cls, data: dict[str, Any]) -> TokenQuery: """Deserialize from a dictionary.""" try: return cls( @@ -33,9 +34,9 @@ def from_dict(cls, data: Dict[str, Any]) -> "TokenQuery": except (KeyError, ValueError) as e: _raise_deserialize_error("TokenQuery", e) - def to_dict(self) -> Dict[str, Any]: + def to_dict(self) -> dict[str, Any]: """Serialize to a dictionary.""" - result: Dict[str, Any] = {} + result: dict[str, Any] = {} result["client_id"] = self.client_id result["client_secret"] = self.client_secret result["code"] = self.code diff --git a/tests/fixtures/connection.json b/tests/fixtures/connection.json index 5d7d3b2c..92c555ad 100644 --- a/tests/fixtures/connection.json +++ b/tests/fixtures/connection.json @@ -13,7 +13,6 @@ "domain": "foo-corp.com" } ], - "callback_endpoint": "https://auth.workos.com/sso/saml/acs/conn_externalkey", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" } diff --git a/tests/fixtures/list_connection.json b/tests/fixtures/list_connection.json index 36fec9bc..aacf2f3d 100644 --- a/tests/fixtures/list_connection.json +++ b/tests/fixtures/list_connection.json @@ -15,7 +15,6 @@ "domain": "foo-corp.com" } ], - "callback_endpoint": "https://auth.workos.com/sso/saml/acs/conn_externalkey", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z" } diff --git a/tests/test_authorization_models_round_trip.py b/tests/test_authorization_models_round_trip.py index decdb23b..e1d76eb9 100644 --- a/tests/test_authorization_models_round_trip.py +++ b/tests/test_authorization_models_round_trip.py @@ -3,7 +3,6 @@ """Model round-trip tests: from_dict(to_dict()) preserves data.""" from tests.generated_helpers import load_fixture - from workos.authorization.models import ( AuthorizationCheck, AuthorizationPermission, diff --git a/tests/test_sso.py b/tests/test_sso.py index a4d92208..d1121068 100644 --- a/tests/test_sso.py +++ b/tests/test_sso.py @@ -3,18 +3,9 @@ import json import pytest -from workos import WorkOSClient, AsyncWorkOSClient -from tests.generated_helpers import load_fixture -from workos.common.models import PaginationOrder -from workos.sso.models import ( - Connection, - Profile, - SSOLogoutAuthorizeResponse, - SSOTokenResponse, - ConnectionsConnectionType, -) -from workos._pagination import AsyncPage, SyncPage +from tests.generated_helpers import load_fixture +from workos import AsyncWorkOSClient, WorkOSClient from workos._errors import ( AuthenticationError, BadRequestError, @@ -23,6 +14,15 @@ ServerError, UnprocessableEntityError, ) +from workos._pagination import AsyncPage, SyncPage +from workos.common.models import PaginationOrder +from workos.sso.models import ( + Connection, + ConnectionsConnectionType, + Profile, + SSOLogoutAuthorizeResponse, + SSOTokenResponse, +) class TestSSO: diff --git a/tests/test_sso_models_round_trip.py b/tests/test_sso_models_round_trip.py index 3b8dd9d6..1af23692 100644 --- a/tests/test_sso_models_round_trip.py +++ b/tests/test_sso_models_round_trip.py @@ -3,7 +3,6 @@ """Model round-trip tests: from_dict(to_dict()) preserves data.""" from tests.generated_helpers import load_fixture - from workos.sso.models import ( Connection, ConnectionDomain, @@ -75,7 +74,6 @@ def test_connection_omits_absent_optional_non_nullable_fields(self): instance = Connection.from_dict(data) serialized = instance.to_dict() assert "organization_id" not in serialized - assert "callback_endpoint" not in serialized def test_connection_round_trips_unknown_enum_values(self): data = { @@ -93,7 +91,6 @@ def test_connection_round_trips_unknown_enum_values(self): "domain": "foo-corp.com", } ], - "callback_endpoint": "https://auth.workos.com/sso/saml/acs/conn_externalkey", "created_at": "2026-01-15T12:00:00.000Z", "updated_at": "2026-01-15T12:00:00.000Z", }