diff --git a/cicerone/spec/schema.py b/cicerone/spec/schema.py index 316fef2..989aa69 100644 --- a/cicerone/spec/schema.py +++ b/cicerone/spec/schema.py @@ -26,6 +26,7 @@ class Schema(pydantic.BaseModel): properties: dict[str, Schema] = pydantic.Field(default_factory=dict) required: list[str] = pydantic.Field(default_factory=list) items: Schema | None = None + prefix_items: tuple[Schema, ...] | None = pydantic.Field(None, alias="prefixItems") # Composition keywords all_of: list[Schema] | None = pydantic.Field(None, alias="allOf") one_of: list[Schema] | None = pydantic.Field(None, alias="oneOf") @@ -45,6 +46,8 @@ def __str__(self) -> str: parts.append(f"required={self.required}") if self.items: parts.append(f"items={self.items.type or 'object'}") + if self.prefix_items: + parts.append(f"prefixItems=({', '.join(item.type or 'object' for item in self.prefix_items)})") content = ", ".join(parts) if parts else "empty schema" return f"" @@ -59,6 +62,7 @@ def from_dict(cls, data: dict[str, typing.Any]) -> Schema: "required", "properties", "items", + "prefixItems", "allOf", "oneOf", "anyOf", @@ -72,6 +76,7 @@ def from_dict(cls, data: dict[str, typing.Any]) -> Schema: required=data.get("required", []), properties=model_utils.parse_collection(data, "properties", cls.from_dict), items=model_utils.parse_nested_object(data, "items", cls.from_dict), + prefixItems=model_utils.parse_list_or_none(data, "prefixItems", cls.from_dict), allOf=model_utils.parse_list_or_none(data, "allOf", cls.from_dict), oneOf=model_utils.parse_list_or_none(data, "oneOf", cls.from_dict), anyOf=model_utils.parse_list_or_none(data, "anyOf", cls.from_dict), diff --git a/tests/spec/test_schema.py b/tests/spec/test_schema.py index abaf065..f8cbff0 100644 --- a/tests/spec/test_schema.py +++ b/tests/spec/test_schema.py @@ -55,6 +55,15 @@ def test_array_schema(self): assert schema.items is not None assert schema.items.type == "string" + def test_array_schema_tuples(self): + """Test creating a schema with tuple-like array items.""" + data = {"type": "array", "prefixItems": [{"type": "string"}, {"type": "integer"}]} + schema = cicerone_spec.Schema.from_dict(data) + assert schema.type == "array" + assert schema.prefix_items is not None + assert schema.prefix_items[0].type == "string" + assert schema.prefix_items[1].type == "integer" + def test_schema_str_representation(self): """Test __str__ method of Schema.""" data = {