Skip to content

feat!: Generate the Python SDK via the OpenAPI spec#604

Open
gjtorikian wants to merge 39 commits intonext-majorfrom
oagen
Open

feat!: Generate the Python SDK via the OpenAPI spec#604
gjtorikian wants to merge 39 commits intonext-majorfrom
oagen

Conversation

@gjtorikian
Copy link
Copy Markdown
Contributor

@gjtorikian gjtorikian commented Apr 1, 2026

This PR moves the Python SDK from the old handwritten implementation to a generated client surface while intentionally preserving most familiar product namespaces.

The goal for the next major is higher API parity with the WorkOS spec, broader sync/async coverage, and more consistent request, model, pagination, and error handling without turning the upgrade into a full rewrite for most users.

What Changed

Client architecture

  • Replaces handwritten client internals with generated WorkOSClient and AsyncWorkOSClient clients (class names unchanged from v5).
  • Moves request handling onto a shared httpx stack with retries, timeout/connection handling, per-request RequestOptions, and automatic POST idempotency keys.
  • Normalizes pagination around SyncPage / AsyncPage.
  • Normalizes exceptions under workos._errors with *Error names and richer request metadata.
  • Replaces Pydantic runtime models and workos.types.* imports with generated model packages and from_dict() / to_dict() helpers.

Product surface and compatibility

  • Preserves familiar namespaces such as api_keys, audit_logs, authorization, connect, directory_sync, events, organization_domains, organizations, passwordless, pipes, sso, user_management, webhooks, widgets, and vault.
  • Renames portal to admin_portal.
  • Adds first-class radar support.
  • Keeps mfa as an alias for multi_factor_auth.
  • Keeps targeted inline compatibility helpers such as sealed-session loading and PKCE/AuthKit helpers.

Async parity and coverage

  • Brings async coverage much closer to sync coverage.
  • Areas that were previously unavailable or incomplete in async, including Admin Portal, MFA, Passwordless, Webhooks, Widgets, and Vault, now have first-class async support.
  • Adds broad generated test coverage, including model round-trip tests and generated client behavior tests.

Breaking Changes

  • Python 3.10+ is now required.
  • workos.client and workos.async_client module paths are removed (use from workos import WorkOSClient, AsyncWorkOSClient instead -- the class names themselves are unchanged).
  • portal becomes admin_portal.
  • fga is removed from the client surface.
  • Models are no longer Pydantic models.
  • workos.types.* imports are removed.
  • Exception class names move from *Exception to *Error.
  • Retry behavior is now enabled by default.

Migration Notes

  • Most integrations should not need a namespace-by-namespace rewrite.
  • The main upgrade work is import updates, portal -> admin_portal, fga removal, model serialization/import changes, and exception/retry review.
  • A fresh v6 migration guide is included in docs/V6_MIGRATION_GUIDE.md.

gjtorikian and others added 27 commits March 26, 2026 23:45
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace mypy with pyright as the primary type checker. pyright is
faster, catches more real bugs (better type narrowing, generic
inference, union handling), and is the industry standard for production
Python SDKs (used by OpenAI, Anthropic, Stripe).

- Replace mypy with pyright in noxfile.py (typecheck + ci sessions)
- Swap mypy for pyright in type_check dependency group
- Remove [tool.mypy] config section
- Add [tool.pyright] with typeCheckingMode = "strict"
- Update uv.lock

The generated SDK passes pyright strict with 0 errors across 374 files.

This also addresses #600 (SsoProviderType enum removal) — the emitter
generates all spec enums as str/Enum classes, restoring attribute
access (e.g., EnumName.VALUE) that was lost when v5 switched to
Literal type aliases.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add pyrightconfig.json to configure pyright for this codebase
- Fix test type errors with proper annotations and constructors
- Fix dead assertions in test_audit_logs.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rning

Future pytest-asyncio versions will default async fixture loop scope to
"function". Set it explicitly to avoid surprises on upgrade.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Delete the entire legacy stack that the generated code replaces:

- All 10 _compat.py bridge files
- All handwritten service modules (sso.py, connect.py, etc.)
- Old client.py, async_client.py, _base_client.py, _client_configuration.py
- Entire types/ directory (~170 files of Pydantic models)
- typing/ directory (legacy type helpers)
- utils/ directory (legacy HTTP client, request helpers)
- exceptions.py (replaced by _errors.py)
- All legacy test files and fixtures

The generated _resource.py + _client.py + models/ are now the sole
implementation. Update __init__.py to export from the generated
_client.py. Add new conftest.py with workos/async_workos fixtures
for the generated test suite.

436 tests pass, 0 failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add all auto-generated resource modules, models, types, and tests
- Add verify_event/verify_header back to Webhooks as @oagen-ignore methods
- Add list_connections/get_connection/delete_connection to SSO as @oagen-ignore methods
- Rename organizations update_organization→update, delete_organization→delete
- Fix docstring exception names (*Error→*Exception) across all resource files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Regenerated from updated emitter with:
- Audit log exports: exports/export -> create_export/get_export
- Authorization role permissions: unwieldy names replaced with
  set_organization_role_permissions, add_organization_role_permission, etc.
- Default request timeout restored to 30s (was 25s)
- Event model hand-maintained via oagen-ignore with id, event, data,
  created_at fields (emitter produces empty placeholder for oneOf unions)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Regenerated from updated emitter that no longer emits unnecessary
`pass` in models with zero fields, fixing ruff format CI failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The generated Event stub is now replaced by the @oagen-ignore block
version, eliminating the F811 duplicate class definition lint error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Regenerated from updated oagen core (top-level @oagen-ignore replacement)
and emitters (skip fixtures/tests for empty discriminated union models).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restores `from workos.exceptions import ...` and `from workos.types.<service> import ...`
import paths. Updates V6 migration guide to remove these as breaking changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gjtorikian gjtorikian requested review from a team as code owners April 1, 2026 17:09
@gjtorikian gjtorikian removed the request for review from a team April 1, 2026 17:09
gjtorikian and others added 12 commits April 2, 2026 22:53
- Add describe_object (sync + async) to vault.py for GET /vault/v1/kv/:id/metadata,
  matching the Node SDK's describeObject method
- Add test_passwordless.py with sync + async tests for create_session and send_session
- Add test_vault.py with sync + async tests for all vault operations including
  read, describe, list, create, update, delete, data keys, and encrypt/decrypt round-trip
- Add JSON fixtures for passwordless and vault test data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Regenerated from oagen-emitters with:

- Error classes renamed *Exception → *Error (PEP 8)
- Two-tier error hierarchy: WorkOSError → APIError → specific errors
- Client class WorkOS is canonical (was WorkOSClient)
- Typed ListMetadata dataclass replaces Dict[str, Any]
- _parse_datetime helper with Python 3.10 version gating
- Clean __init__.py exports (only core public API)
- Remove exceptions.py compat re-export module
- Remove all backwards-compat aliases (greenfield project)
- Update hand-written tests to use canonical *Error names

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New hand-maintained modules:
- actions.py: AuthKit Actions request verification and response signing (H03)
- pkce.py: PKCE code verifier/challenge utilities (H08)
- public_client.py: Factory for PKCE-only public client usage (H19)

Session enhancements:
- seal_session_from_auth_response for auth response sealing (H07)

@oagen-ignore blocks in generated files:
- user_management: load_sealed_session, authenticate_with_session_cookie (H05),
  get_authorization_url_with_pkce (H10), authenticate_with_code_pkce (H11)
- sso: get_authorization_url_with_pkce (H15), get_profile_and_token_pkce (H16)

Emitter: wire actions and pkce onto WorkOS/AsyncWorkOS client

Tests for all helpers including webhook verification (H01/H02),
session management (H04/H06), and all new inline helpers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Regenerate SDK with Client suffix restored on all client classes.
Also fixes hand-maintained files (session, passwordless, vault,
public_client) and adds TYPE_CHECKING imports for forward-ref
return types. Updates migration guide accordingly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Regenerate SDK with Dto token removal. Enum types like
GenerateLinkDtoIntent are now GenerateLinkIntent. Collision
cases (OrganizationDto, RedirectUriDto) retain the suffix to
avoid conflicts with existing models of the same base name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants