Skip to content

Commit 0f1e618

Browse files
committed
feat: Adjust the PatchOp model
1 parent 3eaab56 commit 0f1e618

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

scim2_models/base.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,40 @@ class Context(Enum):
278278
- not dump attributes annotated with :attr:`~scim2_models.Returned.request` unless they are explicitly included.
279279
"""
280280

281+
RESOURCE_PATCH_REQUEST = auto()
282+
"""The resource patch request context.
283+
284+
Should be used for clients building a payload for a PATCH request,
285+
and servers validating PATCH request payloads.
286+
287+
- When used for serialization, it will not dump attributes annotated with :attr:`~scim2_models.Mutability.read_only`.
288+
- When used for validation, it will raise a :class:`~pydantic.ValidationError`:
289+
- when finding attributes annotated with :attr:`~scim2_models.Mutability.read_only`,
290+
- when attributes annotated with :attr:`Required.true <scim2_models.Required.true>` are missing or null.
291+
"""
292+
293+
RESOURCE_PATCH_RESPONSE = auto()
294+
"""The resource patch response context.
295+
296+
Should be used for servers building a payload for a PATCH response,
297+
and clients validating patch response payloads.
298+
299+
- When used for validation, it will raise a :class:`~pydantic.ValidationError` when finding attributes annotated with :attr:`~scim2_models.Returned.never` or when attributes annotated with :attr:`~scim2_models.Returned.always` are missing or :data:`None`;
300+
- When used for serialization, it will:
301+
- always dump attributes annotated with :attr:`~scim2_models.Returned.always`;
302+
- never dump attributes annotated with :attr:`~scim2_models.Returned.never`;
303+
- dump attributes annotated with :attr:`~scim2_models.Returned.default` unless they are explicitly excluded;
304+
- not dump attributes annotated with :attr:`~scim2_models.Returned.request` unless they are explicitly included.
305+
"""
306+
281307
@classmethod
282308
def is_request(cls, ctx: "Context") -> bool:
283309
return ctx in (
284310
cls.RESOURCE_CREATION_REQUEST,
285311
cls.RESOURCE_QUERY_REQUEST,
286312
cls.RESOURCE_REPLACEMENT_REQUEST,
287313
cls.SEARCH_REQUEST,
314+
cls.RESOURCE_PATCH_REQUEST,
288315
)
289316

290317
@classmethod
@@ -294,6 +321,7 @@ def is_response(cls, ctx: "Context") -> bool:
294321
cls.RESOURCE_QUERY_RESPONSE,
295322
cls.RESOURCE_REPLACEMENT_RESPONSE,
296323
cls.SEARCH_RESPONSE,
324+
cls.RESOURCE_PATCH_RESPONSE,
297325
)
298326

299327

scim2_models/rfc7644/patch_op.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
from pydantic import Field
77
from pydantic import field_validator
88

9+
from .message import Message
910
from ..base import ComplexAttribute
1011
from ..base import Required
11-
from .message import Message
1212

1313

1414
class PatchOperation(ComplexAttribute):
@@ -17,7 +17,7 @@ class Op(str, Enum):
1717
remove = "remove"
1818
add = "add"
1919

20-
op: Optional[Optional[Op]] = None
20+
op: Op
2121
"""Each PATCH operation object MUST have exactly one "op" member, whose
2222
value indicates the operation to perform and MAY be one of "add", "remove",
2323
or "replace".
@@ -63,8 +63,14 @@ class PatchOp(Message):
6363
"urn:ietf:params:scim:api:messages:2.0:PatchOp"
6464
]
6565

66-
operations: Optional[list[PatchOperation]] = Field(
67-
None, serialization_alias="Operations"
68-
)
66+
operations: list[PatchOperation, Required.true] = Field(serialization_alias="Operations", min_length=1)
6967
"""The body of an HTTP PATCH request MUST contain the attribute
7068
"Operations", whose value is an array of one or more PATCH operations."""
69+
70+
@field_validator('schemas')
71+
@classmethod
72+
def validate_schemas(cls, value):
73+
expected = ["urn:ietf:params:scim:api:messages:2.0:PatchOp"]
74+
if value != expected:
75+
raise ValueError(f"`schemas` must be exactly {expected}")
76+
return value

tests/test_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def test_everything_is_optional():
149149
ResourceType,
150150
ServiceProviderConfig,
151151
ListResponse[User],
152-
PatchOp,
152+
# PatchOp,
153153
BulkRequest,
154154
BulkResponse,
155155
SearchRequest,

0 commit comments

Comments
 (0)