Skip to content

Commit 588406e

Browse files
authored
Allow unknown fields in Edge config models (#418)
To minimize potential breaking changes when a client uses a different version of the edge config than the edge-endpoint, we should allow unknown fields. This changes means that the edge-endpoint will accept any fields it doesn't know about without raising exceptions, and then just ignore them, which is likely the best way of handling a version mismatch.
1 parent bc7d739 commit 588406e

File tree

3 files changed

+20
-9
lines changed

3 files changed

+20
-9
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ packages = [
99
{include = "**/*.py", from = "src"},
1010
]
1111
readme = "README.md"
12-
version = "0.25.0"
12+
version = "0.25.1"
1313

1414
[tool.poetry.dependencies]
1515
# For certifi, use ">=" instead of "^" since it upgrades its "major version" every year, not really following semver

src/groundlight/edge/config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
class GlobalConfig(BaseModel): # pylint: disable=too-few-public-methods
1010
"""Global runtime settings for edge-endpoint behavior."""
1111

12-
model_config = ConfigDict(extra="forbid")
12+
model_config = ConfigDict(extra="ignore")
1313

1414
refresh_rate: float = Field(
1515
default=60.0,
@@ -27,7 +27,7 @@ class InferenceConfig(BaseModel): # pylint: disable=too-few-public-methods
2727
"""
2828

2929
# Keep shared presets immutable (DEFAULT/NO_CLOUD/etc.) so one mutation cannot globally change behavior.
30-
model_config = ConfigDict(extra="forbid", frozen=True)
30+
model_config = ConfigDict(extra="ignore", frozen=True)
3131

3232
name: str = Field(..., exclude=True, description="A unique name for this inference config preset.")
3333
enabled: bool = Field(
@@ -76,7 +76,7 @@ class DetectorConfig(BaseModel): # pylint: disable=too-few-public-methods
7676
Configuration for a specific detector.
7777
"""
7878

79-
model_config = ConfigDict(extra="forbid")
79+
model_config = ConfigDict(extra="ignore")
8080

8181
detector_id: str = Field(..., description="Detector ID")
8282
edge_inference_config: str = Field(..., description="Config for edge inference.")
@@ -85,7 +85,7 @@ class DetectorConfig(BaseModel): # pylint: disable=too-few-public-methods
8585
class ConfigBase(BaseModel):
8686
"""Shared detector/inference configuration behavior for edge config models."""
8787

88-
model_config = ConfigDict(extra="forbid")
88+
model_config = ConfigDict(extra="ignore")
8989

9090
edge_inference_configs: dict[str, InferenceConfig] = Field(default_factory=dict)
9191
detectors: list[DetectorConfig] = Field(default_factory=list)

test/unit/test_edge_config.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,21 @@ def test_edge_endpoint_config_from_yaml_requires_exactly_one_input():
235235
EdgeEndpointConfig.from_yaml(filename=" ")
236236

237237

238-
def test_edge_endpoint_config_rejects_extra_top_level_fields():
239-
"""Rejects unknown top-level fields to avoid silent config drift."""
240-
with pytest.raises(ValueError, match="Extra inputs are not permitted"):
241-
EdgeEndpointConfig.model_validate({"global_config": {}, "unknown_field": True})
238+
def test_edge_endpoint_config_ignores_extra_fields_at_all_levels():
239+
"""Unknown fields are silently ignored at every nesting level for forward compatibility."""
240+
config = EdgeEndpointConfig.model_validate({
241+
"global_config": {"refresh_rate": REFRESH_RATE_SECONDS, "unknown_global_field": "ignored"},
242+
"edge_inference_configs": {
243+
"default": {"enabled": True, "unknown_inference_field": 42},
244+
},
245+
"detectors": [
246+
{"detector_id": "det_1", "edge_inference_config": "default", "unknown_detector_field": [1, 2]},
247+
],
248+
"unknown_top_level_field": True,
249+
})
250+
assert config.global_config.refresh_rate == REFRESH_RATE_SECONDS
251+
assert config.edge_inference_configs["default"].enabled is True
252+
assert config.detectors[0].detector_id == "det_1"
242253

243254

244255
def test_model_dump_shape_for_edge_endpoint_config():

0 commit comments

Comments
 (0)