diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/types.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/types.py index 621cfc416..699bfc9ac 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/types.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/types.py @@ -3,16 +3,18 @@ from pydantic import Field from overture.schema.system.field_constraint import UniqueItemsConstraint -from overture.schema.system.primitive import uint8 +from overture.schema.system.primitive import int32 from .models import HierarchyItem AdminLevel = NewType( "AdminLevel", Annotated[ - uint8, + int32, Field( description="Integer representing the division's position in its country's administrative hierarchy, where lower numbers correspond to higher level administrative units.", + ge=0, + le=16, ), ], ) diff --git a/packages/overture-schema-divisions-theme/tests/division_area_baseline_schema.json b/packages/overture-schema-divisions-theme/tests/division_area_baseline_schema.json index f3e8c2abd..e86de89d9 100644 --- a/packages/overture-schema-divisions-theme/tests/division_area_baseline_schema.json +++ b/packages/overture-schema-divisions-theme/tests/division_area_baseline_schema.json @@ -457,7 +457,7 @@ "properties": { "admin_level": { "description": "Integer representing the division's position in its country's administrative hierarchy, where lower numbers correspond to higher level administrative units.", - "maximum": 255, + "maximum": 16, "minimum": 0, "title": "Admin Level", "type": "integer" diff --git a/packages/overture-schema-divisions-theme/tests/division_baseline_schema.json b/packages/overture-schema-divisions-theme/tests/division_baseline_schema.json index a2ee027b5..3cf5a93dd 100644 --- a/packages/overture-schema-divisions-theme/tests/division_baseline_schema.json +++ b/packages/overture-schema-divisions-theme/tests/division_baseline_schema.json @@ -524,7 +524,7 @@ "properties": { "admin_level": { "description": "Integer representing the division's position in its country's administrative hierarchy, where lower numbers correspond to higher level administrative units.", - "maximum": 255, + "maximum": 16, "minimum": 0, "title": "Admin Level", "type": "integer" diff --git a/packages/overture-schema-divisions-theme/tests/division_boundary_baseline_schema.json b/packages/overture-schema-divisions-theme/tests/division_boundary_baseline_schema.json index 336d2d484..6d18b17ce 100644 --- a/packages/overture-schema-divisions-theme/tests/division_boundary_baseline_schema.json +++ b/packages/overture-schema-divisions-theme/tests/division_boundary_baseline_schema.json @@ -370,7 +370,7 @@ "properties": { "admin_level": { "description": "Integer representing the division's position in its country's administrative hierarchy, where lower numbers correspond to higher level administrative units.", - "maximum": 255, + "maximum": 16, "minimum": 0, "title": "Admin Level", "type": "integer" diff --git a/packages/overture-schema-system/src/overture/schema/system/model_constraint/model_constraint.py b/packages/overture-schema-system/src/overture/schema/system/model_constraint/model_constraint.py index 9b8e0c924..1d7d22a44 100644 --- a/packages/overture-schema-system/src/overture/schema/system/model_constraint/model_constraint.py +++ b/packages/overture-schema-system/src/overture/schema/system/model_constraint/model_constraint.py @@ -56,10 +56,6 @@ def __init__(self, name: str | None = None): ) self.__name = name - def __validate_instance(self, model_instance: BaseModel) -> BaseModel: - self.validate_instance(model_instance) - return model_instance - @property def name(self) -> str: """Returns the name of the constraint, e.g. "FooConstraint" or "@foo".""" @@ -126,6 +122,15 @@ def decorate(self, model_class: type[BaseModel]) -> type[BaseModel]: metadata = Metadata.retrieve_from(model_class, Metadata()).copy() # type: ignore[union-attr] model_constraints = (*ModelConstraint.get_model_constraints(model_class), self) metadata[_MODEL_CONSTRAINT_KEY] = model_constraints + # Capture the constraint in a closure rather than passing a bound method. + # Some Pydantic versions unwrap bound methods passed through __validators__ + # and rebind `self` to the model instance, breaking the dispatch. + constraint = self + + def _after_validator(model_instance: BaseModel) -> BaseModel: + constraint.validate_instance(model_instance) + return model_instance + new_model_class = create_model( model_class.__name__, __config__=config, @@ -135,7 +140,7 @@ def decorate(self, model_class: type[BaseModel]) -> type[BaseModel]: __validators__={ self.name: cast( Callable[..., Any], - model_validator(mode="after")(self.__validate_instance), + model_validator(mode="after")(_after_validator), ) }, __metadata__=metadata,