valentina-python-client 2.7.0__tar.gz → 2.8.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 (84) hide show
  1. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/PKG-INFO +1 -1
  2. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/pyproject.toml +1 -1
  3. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/__init__.py +1 -1
  4. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/users.py +31 -0
  5. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/endpoints.py +1 -0
  6. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/users.py +36 -0
  7. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/testing/_routes.py +1 -0
  8. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/LICENSE +0 -0
  9. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/README.md +0 -0
  10. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_codegen.py +0 -0
  11. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/__init__.py +0 -0
  12. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/client.py +0 -0
  13. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/registry.py +0 -0
  14. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/__init__.py +0 -0
  15. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/_audit_params.py +0 -0
  16. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/base.py +0 -0
  17. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/campaign_book_chapters.py +0 -0
  18. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/campaign_books.py +0 -0
  19. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/campaigns.py +0 -0
  20. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/character_autogen.py +0 -0
  21. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/character_blueprint.py +0 -0
  22. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/character_traits.py +0 -0
  23. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/characters.py +0 -0
  24. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/companies.py +0 -0
  25. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/developers.py +0 -0
  26. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/dicerolls.py +0 -0
  27. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/dictionary.py +0 -0
  28. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/global_admin.py +0 -0
  29. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/identity.py +0 -0
  30. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/options.py +0 -0
  31. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/system.py +0 -0
  32. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/services/user_lookup.py +0 -0
  33. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/testing/__init__.py +0 -0
  34. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/_sync/testing/_client.py +0 -0
  35. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/client.py +0 -0
  36. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/config.py +0 -0
  37. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/constants.py +0 -0
  38. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/exceptions.py +0 -0
  39. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/__init__.py +0 -0
  40. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/audit_logs.py +0 -0
  41. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/books.py +0 -0
  42. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/campaigns.py +0 -0
  43. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/chapters.py +0 -0
  44. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/character_autogen.py +0 -0
  45. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/character_blueprint.py +0 -0
  46. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/character_trait.py +0 -0
  47. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/characters.py +0 -0
  48. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/companies.py +0 -0
  49. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/developers.py +0 -0
  50. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/diceroll.py +0 -0
  51. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/dictionary.py +0 -0
  52. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/full_sheet.py +0 -0
  53. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/global_admin.py +0 -0
  54. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/pagination.py +0 -0
  55. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/shared.py +0 -0
  56. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/system.py +0 -0
  57. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/user_lookup.py +0 -0
  58. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/models/users.py +0 -0
  59. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/py.typed +0 -0
  60. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/registry.py +0 -0
  61. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/__init__.py +0 -0
  62. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/_audit_params.py +0 -0
  63. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/base.py +0 -0
  64. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/campaign_book_chapters.py +0 -0
  65. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/campaign_books.py +0 -0
  66. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/campaigns.py +0 -0
  67. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/character_autogen.py +0 -0
  68. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/character_blueprint.py +0 -0
  69. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/character_traits.py +0 -0
  70. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/characters.py +0 -0
  71. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/companies.py +0 -0
  72. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/developers.py +0 -0
  73. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/dicerolls.py +0 -0
  74. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/dictionary.py +0 -0
  75. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/global_admin.py +0 -0
  76. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/identity.py +0 -0
  77. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/options.py +0 -0
  78. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/system.py +0 -0
  79. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/services/user_lookup.py +0 -0
  80. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/testing/__init__.py +0 -0
  81. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/testing/_client.py +0 -0
  82. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/testing/_factories.py +0 -0
  83. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/testing/_router.py +0 -0
  84. {valentina_python_client-2.7.0 → valentina_python_client-2.8.0}/src/vclient/validate_constants.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: valentina-python-client
3
- Version: 2.7.0
3
+ Version: 2.8.0
4
4
  Summary: Async Python client library for the Valentina Noir API
5
5
  Author: Nate Landau
6
6
  Author-email: Nate Landau <github@natenate.org>
@@ -16,7 +16,7 @@
16
16
  name = "valentina-python-client"
17
17
  readme = "README.md"
18
18
  requires-python = ">=3.13"
19
- version = "2.7.0"
19
+ version = "2.8.0"
20
20
 
21
21
  [project.optional-dependencies]
22
22
  testing = ["polyfactory>=3.3.0"]
@@ -116,4 +116,4 @@ __all__ = (
116
116
  "users_service",
117
117
  )
118
118
 
119
- __version__ = "2.7.0"
119
+ __version__ = "2.8.0"
@@ -208,6 +208,37 @@ class SyncUsersService(SyncBaseService):
208
208
  )
209
209
  return User.model_validate(response.json())
210
210
 
211
+ def unlink_identity(self, user_id: str, *, provider: IdentityProvider) -> User:
212
+ """Disconnect a verified provider identity from a user.
213
+
214
+ The counterpart to link_identity for "disconnect your account" settings
215
+ flows: remove a single OAuth provider identity so it can no longer be
216
+ used to log in. Only the acting user themselves or a company ADMIN may
217
+ unlink identities. The provider's profile field on the returned User is
218
+ cleared to None.
219
+
220
+ The final remaining identity cannot be removed, since that would leave
221
+ the account unable to authenticate. Link another provider first.
222
+
223
+ Args:
224
+ user_id: The ID of the user losing the identity.
225
+ provider: The identity provider to disconnect.
226
+
227
+ Returns:
228
+ The updated User object with the provider's profile field cleared.
229
+
230
+ Raises:
231
+ AuthorizationError: If the acting user is neither the target user nor an admin.
232
+ NotFoundError: If the user has no identity from this provider
233
+ (code IDENTITY_NOT_LINKED).
234
+ ConflictError: If the provider is the user's only linked identity,
235
+ which cannot be removed (code LAST_IDENTITY).
236
+ """
237
+ response = self._delete(
238
+ self._format_endpoint(Endpoints.USER_IDENTITY, user_id=user_id, provider=provider)
239
+ )
240
+ return User.model_validate(response.json())
241
+
211
242
  def get_page(
212
243
  self,
213
244
  *,
@@ -49,6 +49,7 @@ class Endpoints:
49
49
  USER = f"{USERS}/{{user_id}}"
50
50
  USER_MERGE = f"{USERS}/merge"
51
51
  USER_IDENTITIES = f"{USER}/identities"
52
+ USER_IDENTITY = f"{USER_IDENTITIES}/{{provider}}"
52
53
  USER_APPROVE = f"{USER}/approve"
53
54
  USER_DENY = f"{USER}/deny"
54
55
  USER_STATISTICS = f"{USER}/statistics"
@@ -242,6 +242,42 @@ class UsersService(BaseService):
242
242
  )
243
243
  return User.model_validate(response.json())
244
244
 
245
+ async def unlink_identity(
246
+ self,
247
+ user_id: str,
248
+ *,
249
+ provider: IdentityProvider,
250
+ ) -> User:
251
+ """Disconnect a verified provider identity from a user.
252
+
253
+ The counterpart to link_identity for "disconnect your account" settings
254
+ flows: remove a single OAuth provider identity so it can no longer be
255
+ used to log in. Only the acting user themselves or a company ADMIN may
256
+ unlink identities. The provider's profile field on the returned User is
257
+ cleared to None.
258
+
259
+ The final remaining identity cannot be removed, since that would leave
260
+ the account unable to authenticate. Link another provider first.
261
+
262
+ Args:
263
+ user_id: The ID of the user losing the identity.
264
+ provider: The identity provider to disconnect.
265
+
266
+ Returns:
267
+ The updated User object with the provider's profile field cleared.
268
+
269
+ Raises:
270
+ AuthorizationError: If the acting user is neither the target user nor an admin.
271
+ NotFoundError: If the user has no identity from this provider
272
+ (code IDENTITY_NOT_LINKED).
273
+ ConflictError: If the provider is the user's only linked identity,
274
+ which cannot be removed (code LAST_IDENTITY).
275
+ """
276
+ response = await self._delete(
277
+ self._format_endpoint(Endpoints.USER_IDENTITY, user_id=user_id, provider=provider),
278
+ )
279
+ return User.model_validate(response.json())
280
+
245
281
  # User CRUD Methods
246
282
 
247
283
  async def get_page(
@@ -149,6 +149,7 @@ class Routes:
149
149
  USERS_DENY = RouteSpec("POST", Endpoints.USER_DENY, NO_CONTENT, None)
150
150
  USERS_MERGE = RouteSpec("POST", Endpoints.USER_MERGE, SINGLE, User)
151
151
  USERS_IDENTITY_LINK = RouteSpec("POST", Endpoints.USER_IDENTITIES, SINGLE, User)
152
+ USERS_IDENTITY_UNLINK = RouteSpec("DELETE", Endpoints.USER_IDENTITY, SINGLE, User)
152
153
 
153
154
  USERS_STATISTICS = RouteSpec("GET", Endpoints.USER_STATISTICS, SINGLE, RollStatistics)
154
155
  # User lookup (cross-company)