Skip to content

Commit f6d34ca

Browse files
committed
fix: support Reference constructor in pydantic validation
1 parent b4a029f commit f6d34ca

File tree

3 files changed

+88
-3
lines changed

3 files changed

+88
-3
lines changed

scim2_models/reference.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,16 @@ def __get_pydantic_core_schema__(
4646
_handler: GetCoreSchemaHandler,
4747
) -> core_schema.CoreSchema:
4848
return core_schema.no_info_after_validator_function(
49-
cls._validate, core_schema.str_schema()
49+
cls._validate,
50+
core_schema.union_schema(
51+
[core_schema.str_schema(), core_schema.is_instance_schema(cls)]
52+
),
5053
)
5154

5255
@classmethod
53-
def _validate(cls, input_value: str, /) -> str:
56+
def _validate(cls, input_value: Any, /) -> str:
57+
if isinstance(input_value, cls):
58+
return str(input_value)
5459
return input_value
5560

5661
@classmethod

scim2_models/rfc7643/resource_type.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def from_resource(cls, resource_model: type[Resource]) -> Self:
9090
id=name,
9191
name=name,
9292
description=name,
93-
endpoint=f"/{name}s", # type: ignore[arg-type]
93+
endpoint=Reference[URIReference](f"/{name}s"),
9494
schema_=schema,
9595
schema_extensions=[
9696
SchemaExtension(

tests/test_reference.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""Test Reference constructor functionality."""
2+
3+
from typing import Annotated
4+
from typing import Optional
5+
6+
import pytest
7+
8+
from scim2_models.annotations import Required
9+
from scim2_models.base import BaseModel
10+
from scim2_models.reference import ExternalReference
11+
from scim2_models.reference import Reference
12+
from scim2_models.reference import URIReference
13+
14+
15+
class ReferenceTestModel(BaseModel):
16+
"""Test model with Reference fields."""
17+
18+
schemas: Annotated[list[str], Required.true] = ["urn:example:test"]
19+
uri_ref: Optional[Reference[URIReference]] = None
20+
ext_ref: Optional[Reference[ExternalReference]] = None
21+
22+
23+
def test_reference_uri_string_assignment():
24+
"""Test that URI references accept string values."""
25+
model = ReferenceTestModel(uri_ref="https://example.com")
26+
assert model.uri_ref == "https://example.com"
27+
assert isinstance(model.uri_ref, str)
28+
29+
30+
def test_reference_uri_constructor():
31+
"""Test that URI references accept Reference[URIReference] constructor."""
32+
model = ReferenceTestModel(uri_ref=Reference[URIReference]("https://example.com"))
33+
assert model.uri_ref == "https://example.com"
34+
assert isinstance(model.uri_ref, str)
35+
36+
37+
def test_reference_external_string_assignment():
38+
"""Test that external references accept string values."""
39+
model = ReferenceTestModel(ext_ref="https://external.com")
40+
assert model.ext_ref == "https://external.com"
41+
assert isinstance(model.ext_ref, str)
42+
43+
44+
def test_reference_external_constructor():
45+
"""Test that external references accept Reference[ExternalReference] constructor."""
46+
model = ReferenceTestModel(
47+
ext_ref=Reference[ExternalReference]("https://external.com")
48+
)
49+
assert model.ext_ref == "https://external.com"
50+
assert isinstance(model.ext_ref, str)
51+
52+
53+
def test_reference_plain_constructor():
54+
"""Test that references accept plain Reference constructor."""
55+
model = ReferenceTestModel(uri_ref=Reference("https://example.com"))
56+
assert model.uri_ref == "https://example.com"
57+
assert isinstance(model.uri_ref, str)
58+
59+
60+
def test_reference_serialization():
61+
"""Test that Reference instances serialize correctly."""
62+
ref = Reference[URIReference]("https://example.com")
63+
model = ReferenceTestModel(uri_ref=ref)
64+
65+
dumped = model.model_dump()
66+
assert dumped["uri_ref"] == "https://example.com"
67+
68+
69+
def test_reference_validation_error():
70+
"""Test that invalid values still raise validation errors."""
71+
with pytest.raises(ValueError):
72+
ReferenceTestModel(uri_ref=123) # Invalid type should still fail
73+
74+
75+
def test_reference_userstring_behavior():
76+
"""Test that Reference still behaves like UserString."""
77+
ref = Reference[URIReference]("https://example.com")
78+
assert str(ref) == "https://example.com"
79+
assert ref == "https://example.com"
80+
assert ref.startswith("https://")

0 commit comments

Comments
 (0)