valentina-python-client 2.4.0__tar.gz → 2.4.2__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.4.0 → valentina_python_client-2.4.2}/PKG-INFO +1 -1
  2. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/pyproject.toml +1 -1
  3. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/__init__.py +4 -1
  4. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/base.py +14 -6
  5. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/base.py +22 -6
  6. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/LICENSE +0 -0
  7. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/README.md +0 -0
  8. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_codegen.py +0 -0
  9. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/__init__.py +0 -0
  10. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/client.py +0 -0
  11. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/registry.py +0 -0
  12. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/__init__.py +0 -0
  13. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/_audit_params.py +0 -0
  14. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/campaign_book_chapters.py +0 -0
  15. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/campaign_books.py +0 -0
  16. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/campaigns.py +0 -0
  17. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/character_autogen.py +0 -0
  18. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/character_blueprint.py +0 -0
  19. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/character_traits.py +0 -0
  20. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/characters.py +0 -0
  21. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/companies.py +0 -0
  22. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/developers.py +0 -0
  23. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/dicerolls.py +0 -0
  24. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/dictionary.py +0 -0
  25. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/global_admin.py +0 -0
  26. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/options.py +0 -0
  27. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/system.py +0 -0
  28. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/user_lookup.py +0 -0
  29. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/user_self_registration.py +0 -0
  30. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/services/users.py +0 -0
  31. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/testing/__init__.py +0 -0
  32. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/_sync/testing/_client.py +0 -0
  33. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/client.py +0 -0
  34. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/config.py +0 -0
  35. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/constants.py +0 -0
  36. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/endpoints.py +0 -0
  37. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/exceptions.py +0 -0
  38. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/__init__.py +0 -0
  39. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/audit_logs.py +0 -0
  40. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/books.py +0 -0
  41. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/campaigns.py +0 -0
  42. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/chapters.py +0 -0
  43. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/character_autogen.py +0 -0
  44. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/character_blueprint.py +0 -0
  45. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/character_trait.py +0 -0
  46. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/characters.py +0 -0
  47. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/companies.py +0 -0
  48. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/developers.py +0 -0
  49. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/diceroll.py +0 -0
  50. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/dictionary.py +0 -0
  51. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/full_sheet.py +0 -0
  52. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/global_admin.py +0 -0
  53. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/pagination.py +0 -0
  54. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/shared.py +0 -0
  55. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/system.py +0 -0
  56. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/user_lookup.py +0 -0
  57. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/models/users.py +0 -0
  58. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/py.typed +0 -0
  59. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/registry.py +0 -0
  60. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/__init__.py +0 -0
  61. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/_audit_params.py +0 -0
  62. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/campaign_book_chapters.py +0 -0
  63. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/campaign_books.py +0 -0
  64. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/campaigns.py +0 -0
  65. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/character_autogen.py +0 -0
  66. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/character_blueprint.py +0 -0
  67. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/character_traits.py +0 -0
  68. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/characters.py +0 -0
  69. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/companies.py +0 -0
  70. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/developers.py +0 -0
  71. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/dicerolls.py +0 -0
  72. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/dictionary.py +0 -0
  73. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/global_admin.py +0 -0
  74. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/options.py +0 -0
  75. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/system.py +0 -0
  76. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/user_lookup.py +0 -0
  77. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/user_self_registration.py +0 -0
  78. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/services/users.py +0 -0
  79. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/testing/__init__.py +0 -0
  80. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/testing/_client.py +0 -0
  81. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/testing/_factories.py +0 -0
  82. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/testing/_router.py +0 -0
  83. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/src/vclient/testing/_routes.py +0 -0
  84. {valentina_python_client-2.4.0 → valentina_python_client-2.4.2}/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.4.0
3
+ Version: 2.4.2
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.4.0"
19
+ version = "2.4.2"
20
20
 
21
21
  [project.optional-dependencies]
22
22
  testing = ["polyfactory>=3.3.0"]
@@ -28,6 +28,9 @@ class _PropagateHandler(_logging.Handler):
28
28
  _logger.add(
29
29
  _PropagateHandler(),
30
30
  format="{message}",
31
+ # Forward TRACE too (e.g. the "Send request" line) and let the consumer's
32
+ # stdlib logging level decide what to show; the sink must not pre-filter it.
33
+ level="TRACE",
31
34
  filter=lambda record: record["name"].startswith("vclient"),
32
35
  )
33
36
 
@@ -113,4 +116,4 @@ __all__ = (
113
116
  "users_service",
114
117
  )
115
118
 
116
- __version__ = "2.4.0"
119
+ __version__ = "2.4.2"
@@ -168,8 +168,8 @@ class SyncBaseService:
168
168
  config = self._client._config
169
169
  max_attempts = config.max_retries + 1 if config.auto_retry_rate_limit else 1
170
170
  retry_statuses = config.retry_statuses
171
- request_logger = logger.bind(method=method, url=path)
172
- request_logger.debug("Send request")
171
+ request_logger = logger.bind(method=method, url=path, params=params)
172
+ request_logger.trace("Send request")
173
173
  last_error: RateLimitError | ServerError | None = None
174
174
  for attempt in range(max_attempts):
175
175
  try:
@@ -196,7 +196,7 @@ class SyncBaseService:
196
196
  time.sleep(delay)
197
197
  continue
198
198
  try:
199
- self._raise_for_status(response, method, path)
199
+ self._raise_for_status(response, method, path, params=params)
200
200
  self._log_success_response(response, request_logger)
201
201
  return response
202
202
  except RateLimitError as e:
@@ -243,7 +243,7 @@ class SyncBaseService:
243
243
  header_request_id = response.headers.get(REQUEST_ID_HEADER)
244
244
  if header_request_id:
245
245
  success_bind["request_id"] = header_request_id
246
- request_logger.bind(**success_bind).debug("Receive response")
246
+ request_logger.bind(**success_bind).debug("Request complete")
247
247
 
248
248
  @staticmethod
249
249
  def _inject_request_id_fallback(
@@ -260,13 +260,17 @@ class SyncBaseService:
260
260
  if header_id:
261
261
  response_data["request_id"] = header_id
262
262
 
263
- def _raise_for_status(self, response: httpx.Response, method: str, url: str) -> None:
263
+ def _raise_for_status(
264
+ self, response: httpx.Response, method: str, url: str, params: dict[str, Any] | None = None
265
+ ) -> None:
264
266
  """Raise appropriate exception for error responses.
265
267
 
266
268
  Args:
267
269
  response: The HTTP response to check.
268
270
  method: The HTTP method of the request.
269
271
  url: The URL path of the request.
272
+ params: The query parameters of the request, logged to disambiguate
273
+ paginated calls that share the same path.
270
274
 
271
275
  Raises:
272
276
  AuthenticationError: For 401 responses.
@@ -289,7 +293,11 @@ class SyncBaseService:
289
293
  message = response.text or f"HTTP {status_code}"
290
294
  self._inject_request_id_fallback(response_data, response)
291
295
  error_logger = logger.bind(
292
- method=method, url=url, status=status_code, request_id=response_data.get("request_id")
296
+ method=method,
297
+ url=url,
298
+ params=params,
299
+ status=status_code,
300
+ request_id=response_data.get("request_id"),
293
301
  )
294
302
  if status_code == 429:
295
303
  retry_after = self._parse_retry_after(response)
@@ -176,9 +176,13 @@ class BaseService:
176
176
  config = self._client._config # noqa: SLF001
177
177
  max_attempts = config.max_retries + 1 if config.auto_retry_rate_limit else 1
178
178
  retry_statuses = config.retry_statuses
179
- request_logger = logger.bind(method=method, url=path)
179
+ # Bind params so paginated requests are distinguishable in logs; without
180
+ # limit/offset, identical paths look like duplicate (thundering-herd) calls.
181
+ request_logger = logger.bind(method=method, url=path, params=params)
180
182
 
181
- request_logger.debug("Send request")
183
+ # TRACE so the in-flight request is visible only when diagnosing hangs; the
184
+ # "Request complete" DEBUG line below is the superset record for normal use.
185
+ request_logger.trace("Send request")
182
186
 
183
187
  last_error: RateLimitError | ServerError | None = None
184
188
 
@@ -209,7 +213,7 @@ class BaseService:
209
213
  continue
210
214
 
211
215
  try:
212
- self._raise_for_status(response, method, path)
216
+ self._raise_for_status(response, method, path, params=params)
213
217
  self._log_success_response(response, request_logger)
214
218
  return response # noqa: TRY300
215
219
  except RateLimitError as e:
@@ -268,7 +272,7 @@ class BaseService:
268
272
  header_request_id = response.headers.get(REQUEST_ID_HEADER)
269
273
  if header_request_id:
270
274
  success_bind["request_id"] = header_request_id
271
- request_logger.bind(**success_bind).debug("Receive response")
275
+ request_logger.bind(**success_bind).debug("Request complete")
272
276
 
273
277
  @staticmethod
274
278
  def _inject_request_id_fallback(
@@ -285,13 +289,21 @@ class BaseService:
285
289
  if header_id:
286
290
  response_data["request_id"] = header_id
287
291
 
288
- def _raise_for_status(self, response: httpx.Response, method: str, url: str) -> None:
292
+ def _raise_for_status(
293
+ self,
294
+ response: httpx.Response,
295
+ method: str,
296
+ url: str,
297
+ params: dict[str, Any] | None = None,
298
+ ) -> None:
289
299
  """Raise appropriate exception for error responses.
290
300
 
291
301
  Args:
292
302
  response: The HTTP response to check.
293
303
  method: The HTTP method of the request.
294
304
  url: The URL path of the request.
305
+ params: The query parameters of the request, logged to disambiguate
306
+ paginated calls that share the same path.
295
307
 
296
308
  Raises:
297
309
  AuthenticationError: For 401 responses.
@@ -317,7 +329,11 @@ class BaseService:
317
329
  self._inject_request_id_fallback(response_data, response)
318
330
 
319
331
  error_logger = logger.bind(
320
- method=method, url=url, status=status_code, request_id=response_data.get("request_id")
332
+ method=method,
333
+ url=url,
334
+ params=params,
335
+ status=status_code,
336
+ request_id=response_data.get("request_id"),
321
337
  )
322
338
 
323
339
  if status_code == 429: # noqa: PLR2004