Summary
ofsc.models.Property.gui_match is a field-validator that rejects any value not in the allowed-hints list — including None. Real OFSC tenants return gui: null for properties with no GUI hint, so AsyncOFSMetadata.get_properties() raises ValidationError on parse for any tenant that has such a property.
Missing gui (default-to-None) is accepted; only an explicit null in the response fails. The two paths should behave the same.
Affected versions
Confirmed in 2.25.0; the validator code is unchanged in earlier 2.x versions.
Reproduction
from ofsc.models import Property
# Real tenants return gui: null explicitly. This raises:
Property.model_validate({
'label': 'foo',
'name': 'Foo',
'type': 'string',
'gui': None,
'translations': [{'language': 'en', 'name': 'Foo'}],
})
# ValidationError: 1 validation error for Property
# gui
# Value error, None is not a valid GUI value
# Missing 'gui' (defaults to None) is accepted:
Property.model_validate({
'label': 'foo', 'name': 'Foo', 'type': 'string',
'translations': [{'language': 'en', 'name': 'Foo'}],
})
# OK; p.gui == None
Root cause (ofsc/models/metadata.py)
@field_validator("gui")
@classmethod
def gui_match(cls, v):
if v not in [
"text", "checkbox", "combobox", "radiogroup", "file",
"signature", "image", "url", "phone", "email",
"capture", "geo", "attachments",
]:
raise ValueError(f"{v} is not a valid GUI value")
return v
The field is declared gui: Optional[str] = None — None is a valid value at the type level — but the validator never short-circuits on it.
Proposed fix
@field_validator("gui")
@classmethod
def gui_match(cls, v):
if v is None:
return v
if v not in [
"text", "checkbox", "combobox", "radiogroup", "file",
"signature", "image", "url", "phone", "email",
"capture", "geo", "attachments",
]:
raise ValueError(f"{v} is not a valid GUI value")
return v
Happy to send a PR with the fix + a regression test that exercises both explicit-null and missing-key paths.
Workaround
For downstream consumers, the workaround is to subclass Property and override gui_match to permit None, and use a custom OFSResponseList[YourProperty] with metadata._get_paginated_list(...) instead of metadata.get_properties() (which hard-codes the upstream PropertyListResponse).
Summary
ofsc.models.Property.gui_matchis a field-validator that rejects any value not in the allowed-hints list — includingNone. Real OFSC tenants returngui: nullfor properties with no GUI hint, soAsyncOFSMetadata.get_properties()raisesValidationErroron parse for any tenant that has such a property.Missing
gui(default-to-None) is accepted; only an explicitnullin the response fails. The two paths should behave the same.Affected versions
Confirmed in 2.25.0; the validator code is unchanged in earlier 2.x versions.
Reproduction
Root cause (
ofsc/models/metadata.py)The field is declared
gui: Optional[str] = None—Noneis a valid value at the type level — but the validator never short-circuits on it.Proposed fix
Happy to send a PR with the fix + a regression test that exercises both explicit-null and missing-key paths.
Workaround
For downstream consumers, the workaround is to subclass
Propertyand overridegui_matchto permitNone, and use a customOFSResponseList[YourProperty]withmetadata._get_paginated_list(...)instead ofmetadata.get_properties()(which hard-codes the upstreamPropertyListResponse).