devhelm 1.7.0__tar.gz → 1.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 (61) hide show
  1. {devhelm-1.7.0 → devhelm-1.8.0}/PKG-INFO +1 -1
  2. {devhelm-1.7.0 → devhelm-1.8.0}/pyproject.toml +1 -1
  3. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/_pagination.py +6 -3
  4. devhelm-1.8.0/tests/test_pagination.py +34 -0
  5. {devhelm-1.7.0 → devhelm-1.8.0}/uv.lock +1 -1
  6. {devhelm-1.7.0 → devhelm-1.8.0}/.github/workflows/ci.yml +0 -0
  7. {devhelm-1.7.0 → devhelm-1.8.0}/.github/workflows/release.yml +0 -0
  8. {devhelm-1.7.0 → devhelm-1.8.0}/.github/workflows/spec-check.yml +0 -0
  9. {devhelm-1.7.0 → devhelm-1.8.0}/.gitignore +0 -0
  10. {devhelm-1.7.0 → devhelm-1.8.0}/LICENSE +0 -0
  11. {devhelm-1.7.0 → devhelm-1.8.0}/Makefile +0 -0
  12. {devhelm-1.7.0 → devhelm-1.8.0}/README.md +0 -0
  13. {devhelm-1.7.0 → devhelm-1.8.0}/docs/openapi/monitoring-api.json +0 -0
  14. {devhelm-1.7.0 → devhelm-1.8.0}/scripts/emit_response_enums.py +0 -0
  15. {devhelm-1.7.0 → devhelm-1.8.0}/scripts/inject_strict_config.py +0 -0
  16. {devhelm-1.7.0 → devhelm-1.8.0}/scripts/regen-from.sh +0 -0
  17. {devhelm-1.7.0 → devhelm-1.8.0}/scripts/release.sh +0 -0
  18. {devhelm-1.7.0 → devhelm-1.8.0}/scripts/typegen.sh +0 -0
  19. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/__init__.py +0 -0
  20. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/_enums.py +0 -0
  21. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/_errors.py +0 -0
  22. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/_generated.py +0 -0
  23. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/_http.py +0 -0
  24. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/_validation.py +0 -0
  25. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/client.py +0 -0
  26. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/py.typed +0 -0
  27. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/__init__.py +0 -0
  28. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/alert_channels.py +0 -0
  29. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/api_keys.py +0 -0
  30. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/dependencies.py +0 -0
  31. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/deploy_lock.py +0 -0
  32. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/environments.py +0 -0
  33. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/forensics.py +0 -0
  34. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/incidents.py +0 -0
  35. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/maintenance_windows.py +0 -0
  36. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/monitors.py +0 -0
  37. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/notification_policies.py +0 -0
  38. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/resource_groups.py +0 -0
  39. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/secrets.py +0 -0
  40. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/services.py +0 -0
  41. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/status.py +0 -0
  42. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/status_pages.py +0 -0
  43. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/tags.py +0 -0
  44. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/resources/webhooks.py +0 -0
  45. {devhelm-1.7.0 → devhelm-1.8.0}/src/devhelm/types.py +0 -0
  46. {devhelm-1.7.0 → devhelm-1.8.0}/tests/__init__.py +0 -0
  47. {devhelm-1.7.0 → devhelm-1.8.0}/tests/run_sdk.py +0 -0
  48. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_api_keys.py +0 -0
  49. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_client.py +0 -0
  50. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_dependencies.py +0 -0
  51. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_errors.py +0 -0
  52. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_http.py +0 -0
  53. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_inject_strict_config.py +0 -0
  54. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_maintenance_windows.py +0 -0
  55. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_negative_validation.py +0 -0
  56. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_schemas.py +0 -0
  57. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_services.py +0 -0
  58. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_spec_parity.py +0 -0
  59. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_status_page_maintenance.py +0 -0
  60. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_typing.py +0 -0
  61. {devhelm-1.7.0 → devhelm-1.8.0}/tests/test_validation_helpers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devhelm
3
- Version: 1.7.0
3
+ Version: 1.8.0
4
4
  Summary: DevHelm SDK for Python — typed client for monitors, incidents, alerting, and more
5
5
  Project-URL: Homepage, https://github.com/devhelmhq/sdk-python
6
6
  Project-URL: Repository, https://github.com/devhelmhq/sdk-python.git
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "devhelm"
3
- version = "1.7.0"
3
+ version = "1.8.0"
4
4
  description = "DevHelm SDK for Python — typed client for monitors, incidents, alerting, and more"
5
5
  authors = [{ name = "DevHelm", email = "hello@devhelm.io" }]
6
6
  license = "MIT"
@@ -23,6 +23,7 @@ class Page(Generic[T]):
23
23
  has_prev: bool = False
24
24
  total_elements: int | None = None
25
25
  total_pages: int | None = None
26
+ next_cursor: str | None = None
26
27
 
27
28
 
28
29
  @dataclass
@@ -40,17 +41,18 @@ class _PageEnvelope(BaseModel):
40
41
  Items are validated separately via ``parse_list(model_class, ...)`` so the
41
42
  envelope only describes the surrounding pagination shape; that keeps this
42
43
  layer P5-clean (no casts) without forcing every model to be expressed
43
- twice. ``extra="forbid"`` so unknown envelope keys surface as a typed
44
- ``DevhelmValidationError`` (P1) rather than silently disappearing.
44
+ twice. ``extra="ignore"`` so additive response fields (``nextCursor``,
45
+ future envelope keys) cannot break ``list()`` Postel's Law.
45
46
  """
46
47
 
47
- model_config = ConfigDict(extra="forbid")
48
+ model_config = ConfigDict(extra="ignore")
48
49
 
49
50
  data: list[Any] = [] # validated separately
50
51
  hasNext: bool = False
51
52
  hasPrev: bool = False
52
53
  totalElements: int | None = None
53
54
  totalPages: int | None = None
55
+ nextCursor: str | None = None
54
56
 
55
57
 
56
58
  class _CursorPageEnvelope(BaseModel):
@@ -142,6 +144,7 @@ def fetch_page(
142
144
  has_prev=envelope.hasPrev,
143
145
  total_elements=envelope.totalElements,
144
146
  total_pages=envelope.totalPages,
147
+ next_cursor=envelope.nextCursor,
145
148
  )
146
149
 
147
150
 
@@ -0,0 +1,34 @@
1
+ """Offset-page envelope must tolerate additive TableValueResult fields."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from devhelm._pagination import _validate_page
6
+
7
+
8
+ def test_page_envelope_accepts_next_cursor() -> None:
9
+ envelope = _validate_page(
10
+ {
11
+ "data": [],
12
+ "hasNext": False,
13
+ "hasPrev": False,
14
+ "totalElements": 0,
15
+ "totalPages": 0,
16
+ "nextCursor": None,
17
+ }
18
+ )
19
+ assert envelope.nextCursor is None
20
+ assert envelope.data == []
21
+
22
+
23
+ def test_page_envelope_ignores_unknown_keys() -> None:
24
+ envelope = _validate_page(
25
+ {"data": [], "hasNext": False, "hasPrev": False, "futureField": True}
26
+ )
27
+ assert envelope.hasNext is False
28
+
29
+
30
+ def test_page_envelope_leaves_items_unparsed() -> None:
31
+ envelope = _validate_page(
32
+ {"data": [{"id": "not-validated-here"}], "hasNext": False, "hasPrev": False}
33
+ )
34
+ assert envelope.data[0]["id"] == "not-validated-here"
@@ -315,7 +315,7 @@ wheels = [
315
315
 
316
316
  [[package]]
317
317
  name = "devhelm"
318
- version = "1.7.0"
318
+ version = "1.8.0"
319
319
  source = { editable = "." }
320
320
  dependencies = [
321
321
  { name = "httpx" },
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