Skip to content

Commit cec283f

Browse files
committed
feat: implement PatchOp.patch
1 parent 7a7a044 commit cec283f

15 files changed

+2060
-558
lines changed

doc/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Changelog
77
Added
88
^^^^^
99
- Proper path validation for :attr:`~scim2_models.SearchRequest.attributes`, :attr:`~scim2_models.SearchRequest.excluded_attributes` and :attr:`~scim2_models.SearchRequest.sort_by`.
10+
- Implement :meth:`~scim2_models.PatchOp.patch`
1011

1112
Fixed
1213
^^^^^

doc/tutorial.rst

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,49 @@ This can be used by client applications that intends to dynamically discover ser
403403
:language: json
404404
:caption: schema-group.json
405405
406-
Bulk and Patch operations
407-
=========================
406+
Patch operations
407+
================
408+
409+
:class:`~scim2_models.PatchOp` allows you to apply patch operations to modify SCIM resources.
410+
The :meth:`~scim2_models.PatchOp.patch` method applies operations in sequence and returns whether the resource was modified. The return code is a boolean indicating whether the object have been modified by the operations.
411+
412+
.. note::
413+
:class:`~scim2_models.PatchOp` takes a type parameter that should be the class of the resource
414+
that is expected to be patched.
415+
416+
.. code-block:: python
417+
418+
>>> from scim2_models import User, PatchOp, PatchOperation
419+
>>> user = User(user_name="john.doe", nick_name="Johnny")
420+
421+
>>> payload = {
422+
... "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
423+
... "Operations": [
424+
... {"op": "replace", "path": "nickName", "value": "John" },
425+
... {"op": "add", "path": "emails", "value": [{"value": "[email protected]"}]},
426+
... ]
427+
... }
428+
>>> patch = PatchOp[User].model_validate(
429+
... payload, scim_ctx=Context.RESOURCE_PATCH_REQUEST
430+
... )
431+
432+
>>> modified = patch.patch(user)
433+
>>> print(modified)
434+
True
435+
>>> print(user.nick_name)
436+
John
437+
>>> print(user.emails[0].value)
438+
john@example.com
439+
440+
.. warning::
441+
442+
Patch operations are validated in the :attr:`~scim2_models.Context.RESOURCE_PATCH_REQUEST`
443+
context. Make sure to validate patch operations with the correct context to
444+
ensure proper validation of mutability and required constraints.
445+
446+
Bulk operations
447+
===============
408448

409449
.. todo::
410450

411-
Bulk and Patch operations are not implemented yet, but any help is welcome!
451+
Bulk operations are not implemented yet, but any help is welcome!

scim2_models/rfc7644/message.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,6 @@ def __new__(
114114

115115
def get_resource_class(obj) -> Optional[type[Resource]]:
116116
"""Extract the resource class from generic type parameter."""
117-
metadata = getattr(obj.__class__, "__pydantic_generic_metadata__", None)
118-
if not metadata or not metadata.get("args"):
119-
return None
120-
117+
metadata = getattr(obj.__class__, "__pydantic_generic_metadata__", {"args": [None]})
121118
resource_class = metadata["args"][0]
122-
if isinstance(resource_class, type) and issubclass(resource_class, Resource):
123-
return resource_class
124-
125-
return None
119+
return resource_class

0 commit comments

Comments
 (0)