devhelm 1.4.0__tar.gz → 1.5.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.
- {devhelm-1.4.0 → devhelm-1.5.0}/PKG-INFO +1 -1
- {devhelm-1.4.0 → devhelm-1.5.0}/pyproject.toml +1 -1
- {devhelm-1.4.0 → devhelm-1.5.0}/scripts/inject_strict_config.py +25 -7
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/_generated.py +191 -188
- {devhelm-1.4.0 → devhelm-1.5.0}/uv.lock +1 -1
- {devhelm-1.4.0 → devhelm-1.5.0}/.github/workflows/ci.yml +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/.github/workflows/release.yml +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/.github/workflows/spec-check.yml +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/.gitignore +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/LICENSE +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/Makefile +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/README.md +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/docs/openapi/monitoring-api.json +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/scripts/emit_response_enums.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/scripts/regen-from.sh +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/scripts/release.sh +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/scripts/typegen.sh +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/__init__.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/_enums.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/_errors.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/_http.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/_pagination.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/_validation.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/client.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/py.typed +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/__init__.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/alert_channels.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/api_keys.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/dependencies.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/deploy_lock.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/environments.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/forensics.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/incidents.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/maintenance_windows.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/monitors.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/notification_policies.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/resource_groups.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/secrets.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/services.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/status.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/status_pages.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/tags.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/resources/webhooks.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/src/devhelm/types.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/__init__.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/run_sdk.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_api_keys.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_client.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_dependencies.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_errors.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_http.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_maintenance_windows.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_negative_validation.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_schemas.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_services.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_spec_parity.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.0}/tests/test_typing.py +0 -0
- {devhelm-1.4.0 → devhelm-1.5.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.
|
|
3
|
+
Version: 1.5.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
|
|
@@ -50,7 +50,24 @@ from pathlib import Path
|
|
|
50
50
|
# `root-model-extra`), so skip them. Their behavior is governed by the
|
|
51
51
|
# inner type, which on its own enforces strict validation.
|
|
52
52
|
CLASS_RE = re.compile(r"^class\s+([A-Za-z_][\w]*)\s*\(\s*(BaseModel)\s*\)\s*:\s*$")
|
|
53
|
-
|
|
53
|
+
CONFIG_LINE_STRICT = " model_config = ConfigDict(extra='forbid', populate_by_name=True)"
|
|
54
|
+
CONFIG_LINE_TOLERANT = " model_config = ConfigDict(extra='ignore', populate_by_name=True)"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _is_response_shape(class_name: str) -> bool:
|
|
58
|
+
"""Response-shape classes tolerate unknown fields (Postel's Law)."""
|
|
59
|
+
if class_name[0].islower():
|
|
60
|
+
return False
|
|
61
|
+
if class_name.endswith(("Request", "Params")):
|
|
62
|
+
return False
|
|
63
|
+
return bool(
|
|
64
|
+
class_name.endswith(("Dto", "Response"))
|
|
65
|
+
or class_name.startswith(("SingleValueResponse", "TableValueResult", "CursorPage"))
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# Keep the old name for backward compat in case anything imports it
|
|
70
|
+
CONFIG_LINE = CONFIG_LINE_STRICT
|
|
54
71
|
|
|
55
72
|
# Doc-banner injections keyed by class name. Inserted as a leading docstring
|
|
56
73
|
# inside the target class so the note shows up in IDE hovers and stays put
|
|
@@ -130,6 +147,7 @@ def inject(source: str) -> tuple[str, int]:
|
|
|
130
147
|
i += 1
|
|
131
148
|
continue
|
|
132
149
|
class_name = m.group(1)
|
|
150
|
+
config_line = CONFIG_LINE_TOLERANT if _is_response_shape(class_name) else CONFIG_LINE_STRICT
|
|
133
151
|
# Look at the very next line. If it's already model_config or pass,
|
|
134
152
|
# leave the class alone (idempotency / empty class).
|
|
135
153
|
next_idx = i + 1
|
|
@@ -141,10 +159,10 @@ def inject(source: str) -> tuple[str, int]:
|
|
|
141
159
|
out.append(f' """{banner}"""\n')
|
|
142
160
|
modified += 1
|
|
143
161
|
if "model_config" in next_line:
|
|
144
|
-
#
|
|
145
|
-
#
|
|
146
|
-
if
|
|
147
|
-
out.append(
|
|
162
|
+
# Replace the existing config line if it doesn't match the
|
|
163
|
+
# desired strictness or is missing populate_by_name.
|
|
164
|
+
if next_line.strip() != config_line.strip():
|
|
165
|
+
out.append(config_line + "\n")
|
|
148
166
|
i += 2 # replace the existing model_config line
|
|
149
167
|
modified += 1
|
|
150
168
|
continue
|
|
@@ -154,11 +172,11 @@ def inject(source: str) -> tuple[str, int]:
|
|
|
154
172
|
# exact match (NOT startswith) — fields like `passed: Annotated[...]`
|
|
155
173
|
# also start with "pass" but are not empty class markers.
|
|
156
174
|
if next_line.strip() in ("pass", "pass\n"):
|
|
157
|
-
out.append(
|
|
175
|
+
out.append(config_line + "\n")
|
|
158
176
|
i += 2 # skip the pass
|
|
159
177
|
modified += 1
|
|
160
178
|
continue
|
|
161
|
-
out.append(
|
|
179
|
+
out.append(config_line + "\n")
|
|
162
180
|
modified += 1
|
|
163
181
|
i += 1
|
|
164
182
|
return "".join(out), modified
|