workos 5.31.1__tar.gz → 5.32.0__tar.gz

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.
Files changed (161) hide show
  1. {workos-5.31.1 → workos-5.32.0}/PKG-INFO +1 -1
  2. {workos-5.31.1 → workos-5.32.0}/tests/test_sync_http_client.py +52 -0
  3. {workos-5.31.1 → workos-5.32.0}/tests/test_user_management.py +25 -0
  4. {workos-5.31.1 → workos-5.32.0}/workos/__about__.py +1 -1
  5. {workos-5.31.1 → workos-5.32.0}/workos/exceptions.py +18 -0
  6. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/user.py +1 -0
  7. {workos-5.31.1 → workos-5.32.0}/workos/user_management.py +6 -0
  8. {workos-5.31.1 → workos-5.32.0}/workos/utils/_base_http_client.py +6 -0
  9. {workos-5.31.1 → workos-5.32.0}/workos.egg-info/PKG-INFO +1 -1
  10. {workos-5.31.1 → workos-5.32.0}/LICENSE +0 -0
  11. {workos-5.31.1 → workos-5.32.0}/README.md +0 -0
  12. {workos-5.31.1 → workos-5.32.0}/setup.cfg +0 -0
  13. {workos-5.31.1 → workos-5.32.0}/setup.py +0 -0
  14. {workos-5.31.1 → workos-5.32.0}/tests/test_async_http_client.py +0 -0
  15. {workos-5.31.1 → workos-5.32.0}/tests/test_audit_logs.py +0 -0
  16. {workos-5.31.1 → workos-5.32.0}/tests/test_client.py +0 -0
  17. {workos-5.31.1 → workos-5.32.0}/tests/test_directory_sync.py +0 -0
  18. {workos-5.31.1 → workos-5.32.0}/tests/test_events.py +0 -0
  19. {workos-5.31.1 → workos-5.32.0}/tests/test_fga.py +0 -0
  20. {workos-5.31.1 → workos-5.32.0}/tests/test_mfa.py +0 -0
  21. {workos-5.31.1 → workos-5.32.0}/tests/test_organization_domains.py +0 -0
  22. {workos-5.31.1 → workos-5.32.0}/tests/test_organizations.py +0 -0
  23. {workos-5.31.1 → workos-5.32.0}/tests/test_passwordless.py +0 -0
  24. {workos-5.31.1 → workos-5.32.0}/tests/test_portal.py +0 -0
  25. {workos-5.31.1 → workos-5.32.0}/tests/test_session.py +0 -0
  26. {workos-5.31.1 → workos-5.32.0}/tests/test_sso.py +0 -0
  27. {workos-5.31.1 → workos-5.32.0}/tests/test_user_management_list_sessions.py +0 -0
  28. {workos-5.31.1 → workos-5.32.0}/tests/test_user_management_revoke_session.py +0 -0
  29. {workos-5.31.1 → workos-5.32.0}/tests/test_vault.py +0 -0
  30. {workos-5.31.1 → workos-5.32.0}/tests/test_webhooks.py +0 -0
  31. {workos-5.31.1 → workos-5.32.0}/tests/test_widgets.py +0 -0
  32. {workos-5.31.1 → workos-5.32.0}/workos/__init__.py +0 -0
  33. {workos-5.31.1 → workos-5.32.0}/workos/_base_client.py +0 -0
  34. {workos-5.31.1 → workos-5.32.0}/workos/_client_configuration.py +0 -0
  35. {workos-5.31.1 → workos-5.32.0}/workos/async_client.py +0 -0
  36. {workos-5.31.1 → workos-5.32.0}/workos/audit_logs.py +0 -0
  37. {workos-5.31.1 → workos-5.32.0}/workos/client.py +0 -0
  38. {workos-5.31.1 → workos-5.32.0}/workos/directory_sync.py +0 -0
  39. {workos-5.31.1 → workos-5.32.0}/workos/events.py +0 -0
  40. {workos-5.31.1 → workos-5.32.0}/workos/fga.py +0 -0
  41. {workos-5.31.1 → workos-5.32.0}/workos/mfa.py +0 -0
  42. {workos-5.31.1 → workos-5.32.0}/workos/organization_domains.py +0 -0
  43. {workos-5.31.1 → workos-5.32.0}/workos/organizations.py +0 -0
  44. {workos-5.31.1 → workos-5.32.0}/workos/passwordless.py +0 -0
  45. {workos-5.31.1 → workos-5.32.0}/workos/portal.py +0 -0
  46. {workos-5.31.1 → workos-5.32.0}/workos/py.typed +0 -0
  47. {workos-5.31.1 → workos-5.32.0}/workos/session.py +0 -0
  48. {workos-5.31.1 → workos-5.32.0}/workos/sso.py +0 -0
  49. {workos-5.31.1 → workos-5.32.0}/workos/types/__init__.py +0 -0
  50. {workos-5.31.1 → workos-5.32.0}/workos/types/audit_logs/__init__.py +0 -0
  51. {workos-5.31.1 → workos-5.32.0}/workos/types/audit_logs/audit_log_event.py +0 -0
  52. {workos-5.31.1 → workos-5.32.0}/workos/types/audit_logs/audit_log_event_actor.py +0 -0
  53. {workos-5.31.1 → workos-5.32.0}/workos/types/audit_logs/audit_log_event_context.py +0 -0
  54. {workos-5.31.1 → workos-5.32.0}/workos/types/audit_logs/audit_log_event_target.py +0 -0
  55. {workos-5.31.1 → workos-5.32.0}/workos/types/audit_logs/audit_log_export.py +0 -0
  56. {workos-5.31.1 → workos-5.32.0}/workos/types/audit_logs/audit_log_metadata.py +0 -0
  57. {workos-5.31.1 → workos-5.32.0}/workos/types/directory_sync/__init__.py +0 -0
  58. {workos-5.31.1 → workos-5.32.0}/workos/types/directory_sync/directory.py +0 -0
  59. {workos-5.31.1 → workos-5.32.0}/workos/types/directory_sync/directory_group.py +0 -0
  60. {workos-5.31.1 → workos-5.32.0}/workos/types/directory_sync/directory_state.py +0 -0
  61. {workos-5.31.1 → workos-5.32.0}/workos/types/directory_sync/directory_type.py +0 -0
  62. {workos-5.31.1 → workos-5.32.0}/workos/types/directory_sync/directory_user.py +0 -0
  63. {workos-5.31.1 → workos-5.32.0}/workos/types/directory_sync/list_filters.py +0 -0
  64. {workos-5.31.1 → workos-5.32.0}/workos/types/events/__init__.py +0 -0
  65. {workos-5.31.1 → workos-5.32.0}/workos/types/events/authentication_payload.py +0 -0
  66. {workos-5.31.1 → workos-5.32.0}/workos/types/events/connection_payload_with_legacy_fields.py +0 -0
  67. {workos-5.31.1 → workos-5.32.0}/workos/types/events/directory_group_membership_payload.py +0 -0
  68. {workos-5.31.1 → workos-5.32.0}/workos/types/events/directory_group_with_previous_attributes.py +0 -0
  69. {workos-5.31.1 → workos-5.32.0}/workos/types/events/directory_payload.py +0 -0
  70. {workos-5.31.1 → workos-5.32.0}/workos/types/events/directory_payload_with_legacy_fields.py +0 -0
  71. {workos-5.31.1 → workos-5.32.0}/workos/types/events/directory_user_with_previous_attributes.py +0 -0
  72. {workos-5.31.1 → workos-5.32.0}/workos/types/events/event.py +0 -0
  73. {workos-5.31.1 → workos-5.32.0}/workos/types/events/event_model.py +0 -0
  74. {workos-5.31.1 → workos-5.32.0}/workos/types/events/event_type.py +0 -0
  75. {workos-5.31.1 → workos-5.32.0}/workos/types/events/list_filters.py +0 -0
  76. {workos-5.31.1 → workos-5.32.0}/workos/types/events/organization_domain_verification_failed_payload.py +0 -0
  77. {workos-5.31.1 → workos-5.32.0}/workos/types/events/previous_attributes.py +0 -0
  78. {workos-5.31.1 → workos-5.32.0}/workos/types/events/session_created_payload.py +0 -0
  79. {workos-5.31.1 → workos-5.32.0}/workos/types/feature_flags/__init__.py +0 -0
  80. {workos-5.31.1 → workos-5.32.0}/workos/types/feature_flags/feature_flag.py +0 -0
  81. {workos-5.31.1 → workos-5.32.0}/workos/types/feature_flags/list_filters.py +0 -0
  82. {workos-5.31.1 → workos-5.32.0}/workos/types/fga/__init__.py +0 -0
  83. {workos-5.31.1 → workos-5.32.0}/workos/types/fga/authorization_resource_types.py +0 -0
  84. {workos-5.31.1 → workos-5.32.0}/workos/types/fga/authorization_resources.py +0 -0
  85. {workos-5.31.1 → workos-5.32.0}/workos/types/fga/check.py +0 -0
  86. {workos-5.31.1 → workos-5.32.0}/workos/types/fga/list_filters.py +0 -0
  87. {workos-5.31.1 → workos-5.32.0}/workos/types/fga/warnings.py +0 -0
  88. {workos-5.31.1 → workos-5.32.0}/workos/types/fga/warrant.py +0 -0
  89. {workos-5.31.1 → workos-5.32.0}/workos/types/list_resource.py +0 -0
  90. {workos-5.31.1 → workos-5.32.0}/workos/types/metadata.py +0 -0
  91. {workos-5.31.1 → workos-5.32.0}/workos/types/mfa/__init__.py +0 -0
  92. {workos-5.31.1 → workos-5.32.0}/workos/types/mfa/authentication_challenge.py +0 -0
  93. {workos-5.31.1 → workos-5.32.0}/workos/types/mfa/authentication_challenge_verification_response.py +0 -0
  94. {workos-5.31.1 → workos-5.32.0}/workos/types/mfa/authentication_factor.py +0 -0
  95. {workos-5.31.1 → workos-5.32.0}/workos/types/mfa/authentication_factor_totp_and_challenge_response.py +0 -0
  96. {workos-5.31.1 → workos-5.32.0}/workos/types/mfa/enroll_authentication_factor_type.py +0 -0
  97. {workos-5.31.1 → workos-5.32.0}/workos/types/organization_domains/__init__.py +0 -0
  98. {workos-5.31.1 → workos-5.32.0}/workos/types/organization_domains/organization_domain.py +0 -0
  99. {workos-5.31.1 → workos-5.32.0}/workos/types/organizations/__init__.py +0 -0
  100. {workos-5.31.1 → workos-5.32.0}/workos/types/organizations/domain_data_input.py +0 -0
  101. {workos-5.31.1 → workos-5.32.0}/workos/types/organizations/list_filters.py +0 -0
  102. {workos-5.31.1 → workos-5.32.0}/workos/types/organizations/organization.py +0 -0
  103. {workos-5.31.1 → workos-5.32.0}/workos/types/organizations/organization_common.py +0 -0
  104. {workos-5.31.1 → workos-5.32.0}/workos/types/passwordless/__init__.py +0 -0
  105. {workos-5.31.1 → workos-5.32.0}/workos/types/passwordless/passwordless_session.py +0 -0
  106. {workos-5.31.1 → workos-5.32.0}/workos/types/passwordless/passwordless_session_type.py +0 -0
  107. {workos-5.31.1 → workos-5.32.0}/workos/types/portal/__init__.py +0 -0
  108. {workos-5.31.1 → workos-5.32.0}/workos/types/portal/portal_link.py +0 -0
  109. {workos-5.31.1 → workos-5.32.0}/workos/types/portal/portal_link_intent.py +0 -0
  110. {workos-5.31.1 → workos-5.32.0}/workos/types/portal/portal_link_intent_options.py +0 -0
  111. {workos-5.31.1 → workos-5.32.0}/workos/types/roles/__init__.py +0 -0
  112. {workos-5.31.1 → workos-5.32.0}/workos/types/roles/role.py +0 -0
  113. {workos-5.31.1 → workos-5.32.0}/workos/types/sso/__init__.py +0 -0
  114. {workos-5.31.1 → workos-5.32.0}/workos/types/sso/connection.py +0 -0
  115. {workos-5.31.1 → workos-5.32.0}/workos/types/sso/connection_domain.py +0 -0
  116. {workos-5.31.1 → workos-5.32.0}/workos/types/sso/profile.py +0 -0
  117. {workos-5.31.1 → workos-5.32.0}/workos/types/sso/sso_provider_type.py +0 -0
  118. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/__init__.py +0 -0
  119. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/authenticate_with_common.py +0 -0
  120. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/authentication_response.py +0 -0
  121. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/email_verification.py +0 -0
  122. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/impersonator.py +0 -0
  123. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/invitation.py +0 -0
  124. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/list_filters.py +0 -0
  125. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/magic_auth.py +0 -0
  126. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/oauth_tokens.py +0 -0
  127. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/organization_membership.py +0 -0
  128. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/password_hash_type.py +0 -0
  129. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/password_reset.py +0 -0
  130. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/screen_hint.py +0 -0
  131. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/session.py +0 -0
  132. {workos-5.31.1 → workos-5.32.0}/workos/types/user_management/user_management_provider_type.py +0 -0
  133. {workos-5.31.1 → workos-5.32.0}/workos/types/vault/__init__.py +0 -0
  134. {workos-5.31.1 → workos-5.32.0}/workos/types/vault/key.py +0 -0
  135. {workos-5.31.1 → workos-5.32.0}/workos/types/vault/object.py +0 -0
  136. {workos-5.31.1 → workos-5.32.0}/workos/types/webhooks/__init__.py +0 -0
  137. {workos-5.31.1 → workos-5.32.0}/workos/types/webhooks/webhook.py +0 -0
  138. {workos-5.31.1 → workos-5.32.0}/workos/types/webhooks/webhook_model.py +0 -0
  139. {workos-5.31.1 → workos-5.32.0}/workos/types/webhooks/webhook_payload.py +0 -0
  140. {workos-5.31.1 → workos-5.32.0}/workos/types/widgets/__init__.py +0 -0
  141. {workos-5.31.1 → workos-5.32.0}/workos/types/widgets/widget_scope.py +0 -0
  142. {workos-5.31.1 → workos-5.32.0}/workos/types/widgets/widget_token_response.py +0 -0
  143. {workos-5.31.1 → workos-5.32.0}/workos/types/workos_model.py +0 -0
  144. {workos-5.31.1 → workos-5.32.0}/workos/typing/__init__.py +0 -0
  145. {workos-5.31.1 → workos-5.32.0}/workos/typing/literals.py +0 -0
  146. {workos-5.31.1 → workos-5.32.0}/workos/typing/sync_or_async.py +0 -0
  147. {workos-5.31.1 → workos-5.32.0}/workos/typing/untyped_literal.py +0 -0
  148. {workos-5.31.1 → workos-5.32.0}/workos/typing/webhooks.py +0 -0
  149. {workos-5.31.1 → workos-5.32.0}/workos/utils/__init__.py +0 -0
  150. {workos-5.31.1 → workos-5.32.0}/workos/utils/crypto_provider.py +0 -0
  151. {workos-5.31.1 → workos-5.32.0}/workos/utils/http_client.py +0 -0
  152. {workos-5.31.1 → workos-5.32.0}/workos/utils/pagination_order.py +0 -0
  153. {workos-5.31.1 → workos-5.32.0}/workos/utils/request_helper.py +0 -0
  154. {workos-5.31.1 → workos-5.32.0}/workos/vault.py +0 -0
  155. {workos-5.31.1 → workos-5.32.0}/workos/webhooks.py +0 -0
  156. {workos-5.31.1 → workos-5.32.0}/workos/widgets.py +0 -0
  157. {workos-5.31.1 → workos-5.32.0}/workos.egg-info/SOURCES.txt +0 -0
  158. {workos-5.31.1 → workos-5.32.0}/workos.egg-info/dependency_links.txt +0 -0
  159. {workos-5.31.1 → workos-5.32.0}/workos.egg-info/not-zip-safe +0 -0
  160. {workos-5.31.1 → workos-5.32.0}/workos.egg-info/requires.txt +0 -0
  161. {workos-5.31.1 → workos-5.32.0}/workos.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: workos
3
- Version: 5.31.1
3
+ Version: 5.32.0
4
4
  Summary: WorkOS Python Client
5
5
  Home-page: https://github.com/workos-inc/workos-python
6
6
  Author: WorkOS
@@ -10,6 +10,7 @@ from workos.exceptions import (
10
10
  BadRequestException,
11
11
  BaseRequestException,
12
12
  ConflictException,
13
+ EmailVerificationRequiredException,
13
14
  ServerException,
14
15
  )
15
16
  from workos.utils.http_client import SyncHTTPClient
@@ -263,6 +264,57 @@ class TestSyncHTTPClient(object):
263
264
  assert str(ex) == "(message=No message, request_id=request-123)"
264
265
  assert ex.__class__ == ConflictException
265
266
 
267
+ def test_email_verification_required_exception(self):
268
+ request_id = "request-123"
269
+ email_verification_id = "email_verification_01J6K4PMSWQXVFGF5ZQJXC6VC8"
270
+
271
+ self.http_client._client.request = MagicMock(
272
+ return_value=httpx.Response(
273
+ status_code=403,
274
+ json={
275
+ "message": "Please verify your email to authenticate via password.",
276
+ "code": "email_verification_required",
277
+ "email_verification_id": email_verification_id,
278
+ },
279
+ headers={"X-Request-ID": request_id},
280
+ ),
281
+ )
282
+
283
+ try:
284
+ self.http_client.request("bad_place")
285
+ except EmailVerificationRequiredException as ex:
286
+ assert (
287
+ ex.message == "Please verify your email to authenticate via password."
288
+ )
289
+ assert ex.code == "email_verification_required"
290
+ assert ex.email_verification_id == email_verification_id
291
+ assert ex.request_id == request_id
292
+ assert ex.__class__ == EmailVerificationRequiredException
293
+ assert isinstance(ex, AuthorizationException)
294
+
295
+ def test_regular_authorization_exception_still_raised(self):
296
+ request_id = "request-123"
297
+
298
+ self.http_client._client.request = MagicMock(
299
+ return_value=httpx.Response(
300
+ status_code=403,
301
+ json={
302
+ "message": "You do not have permission to access this resource.",
303
+ "code": "forbidden",
304
+ },
305
+ headers={"X-Request-ID": request_id},
306
+ ),
307
+ )
308
+
309
+ try:
310
+ self.http_client.request("bad_place")
311
+ except AuthorizationException as ex:
312
+ assert ex.message == "You do not have permission to access this resource."
313
+ assert ex.code == "forbidden"
314
+ assert ex.request_id == request_id
315
+ assert ex.__class__ == AuthorizationException
316
+ assert not isinstance(ex, EmailVerificationRequiredException)
317
+
266
318
  def test_request_includes_base_headers(self, capture_and_mock_http_client_request):
267
319
  request_kwargs = capture_and_mock_http_client_request(self.http_client, {}, 200)
268
320
 
@@ -414,6 +414,7 @@ class TestUserManagement(UserManagementFixtures):
414
414
  assert user.id == "user_01H7ZGXFP5C6BBQY6Z7277ZCT0"
415
415
  assert user.profile_picture_url == "https://example.com/profile-picture.jpg"
416
416
  assert user.last_sign_in_at == "2021-06-25T19:07:33.155Z"
417
+ assert user.locale == "en-US"
417
418
 
418
419
  def test_get_user_by_external_id(
419
420
  self, mock_user, capture_and_mock_http_client_request
@@ -434,6 +435,7 @@ class TestUserManagement(UserManagementFixtures):
434
435
  assert user.id == "user_01H7ZGXFP5C6BBQY6Z7277ZCT0"
435
436
  assert user.profile_picture_url == "https://example.com/profile-picture.jpg"
436
437
  assert user.last_sign_in_at == "2021-06-25T19:07:33.155Z"
438
+ assert user.locale == "en-US"
437
439
  assert user.metadata == mock_user["metadata"]
438
440
 
439
441
  def test_list_users_auto_pagination(
@@ -492,6 +494,29 @@ class TestUserManagement(UserManagementFixtures):
492
494
  "password": "password",
493
495
  }
494
496
 
497
+ def test_update_user_with_locale(
498
+ self, mock_user, capture_and_mock_http_client_request
499
+ ):
500
+ request_kwargs = capture_and_mock_http_client_request(
501
+ self.http_client, mock_user, 200
502
+ )
503
+
504
+ params = {
505
+ "first_name": "Marcelina",
506
+ "locale": "fr-FR",
507
+ }
508
+ user = syncify(
509
+ self.user_management.update_user(
510
+ user_id="user_01H7ZGXFP5C6BBQY6Z7277ZCT0", **params
511
+ )
512
+ )
513
+
514
+ assert request_kwargs["url"].endswith("users/user_01H7ZGXFP5C6BBQY6Z7277ZCT0")
515
+ assert user.id == "user_01H7ZGXFP5C6BBQY6Z7277ZCT0"
516
+ assert request_kwargs["method"] == "put"
517
+ assert request_kwargs["json"]["first_name"] == "Marcelina"
518
+ assert request_kwargs["json"]["locale"] == "fr-FR"
519
+
495
520
  def test_delete_user(self, capture_and_mock_http_client_request):
496
521
  request_kwargs = capture_and_mock_http_client_request(
497
522
  http_client=self.http_client, status_code=204
@@ -12,7 +12,7 @@ __package_name__ = "workos"
12
12
 
13
13
  __package_url__ = "https://github.com/workos-inc/workos-python"
14
14
 
15
- __version__ = "5.31.1"
15
+ __version__ = "5.32.0"
16
16
 
17
17
  __author__ = "WorkOS"
18
18
 
@@ -45,6 +45,24 @@ class AuthorizationException(BaseRequestException):
45
45
  pass
46
46
 
47
47
 
48
+ class EmailVerificationRequiredException(AuthorizationException):
49
+ """Raised when email verification is required before authentication.
50
+
51
+ This exception includes an email_verification_id field that can be used
52
+ to retrieve the email verification object or resend the verification email.
53
+ """
54
+
55
+ def __init__(
56
+ self,
57
+ response: httpx.Response,
58
+ response_json: Optional[Mapping[str, Any]],
59
+ ) -> None:
60
+ super().__init__(response, response_json)
61
+ self.email_verification_id = self.extract_from_json(
62
+ "email_verification_id", None
63
+ )
64
+
65
+
48
66
  class AuthenticationException(BaseRequestException):
49
67
  pass
50
68
 
@@ -15,6 +15,7 @@ class User(WorkOSModel):
15
15
  email_verified: bool
16
16
  profile_picture_url: Optional[str] = None
17
17
  last_sign_in_at: Optional[str] = None
18
+ locale: Optional[str] = None
18
19
  created_at: str
19
20
  updated_at: str
20
21
  external_id: Optional[str] = None
@@ -225,6 +225,7 @@ class UserManagementModule(Protocol):
225
225
  password_hash_type: Optional[PasswordHashType] = None,
226
226
  external_id: Optional[str] = None,
227
227
  metadata: Optional[Metadata] = None,
228
+ locale: Optional[str] = None,
228
229
  ) -> SyncOrAsync[User]:
229
230
  """Update user attributes.
230
231
 
@@ -237,6 +238,7 @@ class UserManagementModule(Protocol):
237
238
  password (str): The password to set for the user. (Optional)
238
239
  password_hash (str): The hashed password to set for the user, used when migrating from another user store. Mutually exclusive with password. (Optional)
239
240
  password_hash_type (str): The algorithm originally used to hash the password, used when providing a password_hash. Valid values are 'bcrypt', `firebase-scrypt`, and `ssha`. (Optional)
241
+ locale (str): The user's locale. (Optional)
240
242
 
241
243
  Returns:
242
244
  User: Updated User response from WorkOS.
@@ -1002,6 +1004,7 @@ class UserManagement(UserManagementModule):
1002
1004
  password_hash_type: Optional[PasswordHashType] = None,
1003
1005
  external_id: Optional[str] = None,
1004
1006
  metadata: Optional[Metadata] = None,
1007
+ locale: Optional[str] = None,
1005
1008
  ) -> User:
1006
1009
  json = {
1007
1010
  "first_name": first_name,
@@ -1013,6 +1016,7 @@ class UserManagement(UserManagementModule):
1013
1016
  "password_hash_type": password_hash_type,
1014
1017
  "external_id": external_id,
1015
1018
  "metadata": metadata,
1019
+ "locale": locale,
1016
1020
  }
1017
1021
 
1018
1022
  response = self._http_client.request(
@@ -1688,6 +1692,7 @@ class AsyncUserManagement(UserManagementModule):
1688
1692
  password_hash_type: Optional[PasswordHashType] = None,
1689
1693
  external_id: Optional[str] = None,
1690
1694
  metadata: Optional[Metadata] = None,
1695
+ locale: Optional[str] = None,
1691
1696
  ) -> User:
1692
1697
  json = {
1693
1698
  "first_name": first_name,
@@ -1699,6 +1704,7 @@ class AsyncUserManagement(UserManagementModule):
1699
1704
  "password_hash_type": password_hash_type,
1700
1705
  "external_id": external_id,
1701
1706
  "metadata": metadata,
1707
+ "locale": locale,
1702
1708
  }
1703
1709
 
1704
1710
  response = await self._http_client.request(
@@ -20,6 +20,7 @@ from workos.exceptions import (
20
20
  ServerException,
21
21
  AuthenticationException,
22
22
  AuthorizationException,
23
+ EmailVerificationRequiredException,
23
24
  NotFoundException,
24
25
  BadRequestException,
25
26
  )
@@ -99,6 +100,11 @@ class BaseHTTPClient(Generic[_HttpxClientT]):
99
100
  if status_code == 401:
100
101
  raise AuthenticationException(response, response_json)
101
102
  elif status_code == 403:
103
+ if (
104
+ response_json is not None
105
+ and response_json.get("code") == "email_verification_required"
106
+ ):
107
+ raise EmailVerificationRequiredException(response, response_json)
102
108
  raise AuthorizationException(response, response_json)
103
109
  elif status_code == 404:
104
110
  raise NotFoundException(response, response_json)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: workos
3
- Version: 5.31.1
3
+ Version: 5.32.0
4
4
  Summary: WorkOS Python Client
5
5
  Home-page: https://github.com/workos-inc/workos-python
6
6
  Author: WorkOS
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes