scim2-models 0.3.5__tar.gz → 0.3.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scim2_models-0.3.5 → scim2_models-0.3.6}/PKG-INFO +1 -1
- {scim2_models-0.3.5 → scim2_models-0.3.6}/doc/changelog.rst +8 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/pyproject.toml +1 -1
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7643/resource.py +5 -4
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7643/resource_type.py +13 -1
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7644/list_response.py +2 -1
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_resource_type.py +34 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/uv.lock +165 -164
- {scim2_models-0.3.5 → scim2_models-0.3.6}/.github/FUNDING.yml +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/.github/workflows/release.yml +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/.github/workflows/tests.yaml +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/.gitignore +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/.pre-commit-config.yaml +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/.readthedocs.yml +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/LICENSE +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/README.md +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/conftest.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/doc/__init__.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/doc/conf.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/doc/contributing.rst +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/doc/index.rst +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/doc/reference.rst +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/doc/tutorial.rst +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.1-user-minimal.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.2-user-full.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.3-enterprise_user.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.4-group.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.5-service_provider_configuration.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.6-resource_type-group.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.6-resource_type-user.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.7.1-schema-enterprise_user.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.7.1-schema-group.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.7.1-schema-user.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.7.2-schema-resource_type.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.7.2-schema-schema.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7643-8.7.2-schema-service_provider_configuration.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.12-error-bad_request.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.12-error-not_found.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.14-user-post_request.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.14-user-post_response.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.3-user-post_request.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.3-user-post_response.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.4.1-user-known-resource.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.4.2-list_response-partial_attributes.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.4.3-list_response-post_query.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.4.3-search_request.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.1-user-put_request.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.1-user-put_response.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.1-patch_op-add_emails.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.1-patch_op-add_members.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.2-patch_op-remove_all_members.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.2-patch_op-remove_and_add_one_member.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.2-patch_op-remove_multi_complex_value.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.2-patch_op-remove_one_member.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.3-patch_op-replace_all_email_values.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.3-patch_op-replace_all_members.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.3-patch_op-replace_street_address.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.5.2.3-patch_op-replace_user_work_address.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.6-error-not_found.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.1-bulk_request-circular_conflict.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.1-list_response-circular_reference.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.2-bulk_request-enterprise_user.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.2-bulk_request-temporary_identifier.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.2-bulk_response-temporary_identifier.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.3-bulk_request-multiple_operations.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.3-bulk_response-error_invalid_syntax.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.3-bulk_response-multiple_errors.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.3-bulk_response-multiple_operations.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.3-error-invalid_syntax.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.7.4-error-payload_too_large.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-3.9-user-partial_response.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/samples/rfc7644-4-list_response-resource_types.json +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/__init__.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/base.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/constants.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/py.typed +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7643/__init__.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7643/enterprise_user.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7643/group.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7643/schema.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7643/service_provider_config.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7643/user.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7644/__init__.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7644/bulk.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7644/error.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7644/message.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7644/patch_op.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/rfc7644/search_request.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/scim2_models/utils.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/__init__.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/conftest.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_dynamic_resources.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_dynamic_schemas.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_enterprise_user.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_errors.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_group.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_list_response.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_model_attributes.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_model_serialization.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_model_validation.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_models.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_patch_op.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_resource_extension.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_schema.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_search_request.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_service_provider_configuration.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_user.py +0 -0
- {scim2_models-0.3.5 → scim2_models-0.3.6}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scim2-models
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: SCIM2 models serialization and validation with pydantic
|
|
5
5
|
Project-URL: documentation, https://scim2-models.readthedocs.io
|
|
6
6
|
Project-URL: repository, https://github.com/python-scim/scim2-models
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
[0.3.6] - 2025-07-02
|
|
5
|
+
--------------------
|
|
6
|
+
|
|
7
|
+
Added
|
|
8
|
+
^^^^^
|
|
9
|
+
- Fix :meth:`ResourceType.from_resource <scim2_models.ResourceType.from_resource>`
|
|
10
|
+
usage for resources with several extensions. :pr:`95`
|
|
11
|
+
|
|
4
12
|
[0.3.5] - 2025-06-05
|
|
5
13
|
--------------------
|
|
6
14
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scim2-models"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.6"
|
|
8
8
|
description = "SCIM2 models serialization and validation with pydantic"
|
|
9
9
|
authors = [{name="Yaal Coop", email="contact@yaal.coop"}]
|
|
10
10
|
license = {file = "LICENSE"}
|
|
@@ -4,7 +4,6 @@ from typing import Any
|
|
|
4
4
|
from typing import Generic
|
|
5
5
|
from typing import Optional
|
|
6
6
|
from typing import TypeVar
|
|
7
|
-
from typing import Union
|
|
8
7
|
from typing import get_args
|
|
9
8
|
from typing import get_origin
|
|
10
9
|
|
|
@@ -24,6 +23,7 @@ from ..base import Returned
|
|
|
24
23
|
from ..base import Uniqueness
|
|
25
24
|
from ..base import URIReference
|
|
26
25
|
from ..base import is_complex_attribute
|
|
26
|
+
from ..utils import UNION_TYPES
|
|
27
27
|
from ..utils import normalize_attribute_name
|
|
28
28
|
|
|
29
29
|
|
|
@@ -117,7 +117,7 @@ class ResourceMetaclass(BaseModelType):
|
|
|
117
117
|
extensions = kwargs["__pydantic_generic_metadata__"]["args"][0]
|
|
118
118
|
extensions = (
|
|
119
119
|
get_args(extensions)
|
|
120
|
-
if get_origin(extensions)
|
|
120
|
+
if get_origin(extensions) in UNION_TYPES
|
|
121
121
|
else [extensions]
|
|
122
122
|
)
|
|
123
123
|
for extension in extensions:
|
|
@@ -183,7 +183,8 @@ class Resource(BaseModel, Generic[AnyExtension], metaclass=ResourceMetaclass):
|
|
|
183
183
|
extension_models = cls.__pydantic_generic_metadata__.get("args", [])
|
|
184
184
|
extension_models = (
|
|
185
185
|
get_args(extension_models[0])
|
|
186
|
-
if len(extension_models) == 1
|
|
186
|
+
if len(extension_models) == 1
|
|
187
|
+
and get_origin(extension_models[0]) in UNION_TYPES
|
|
187
188
|
else extension_models
|
|
188
189
|
)
|
|
189
190
|
|
|
@@ -301,7 +302,7 @@ def model_to_schema(model: type[BaseModel]):
|
|
|
301
302
|
|
|
302
303
|
def get_reference_types(type) -> list[str]:
|
|
303
304
|
first_arg = get_args(type)[0]
|
|
304
|
-
types = get_args(first_arg) if get_origin(first_arg)
|
|
305
|
+
types = get_args(first_arg) if get_origin(first_arg) in UNION_TYPES else [first_arg]
|
|
305
306
|
|
|
306
307
|
def serialize_ref_type(ref_type):
|
|
307
308
|
if ref_type == URIReference:
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from typing import Annotated
|
|
2
2
|
from typing import Optional
|
|
3
|
+
from typing import get_args
|
|
4
|
+
from typing import get_origin
|
|
3
5
|
|
|
4
6
|
from pydantic import Field
|
|
5
7
|
from typing_extensions import Self
|
|
@@ -11,6 +13,7 @@ from ..base import Reference
|
|
|
11
13
|
from ..base import Required
|
|
12
14
|
from ..base import Returned
|
|
13
15
|
from ..base import URIReference
|
|
16
|
+
from ..utils import UNION_TYPES
|
|
14
17
|
from .resource import Resource
|
|
15
18
|
|
|
16
19
|
|
|
@@ -82,7 +85,16 @@ class ResourceType(Resource):
|
|
|
82
85
|
"""Build a naive ResourceType from a resource model."""
|
|
83
86
|
schema = resource_model.model_fields["schemas"].default[0]
|
|
84
87
|
name = schema.split(":")[-1]
|
|
85
|
-
|
|
88
|
+
if resource_model.__pydantic_generic_metadata__["args"]:
|
|
89
|
+
extensions = resource_model.__pydantic_generic_metadata__["args"][0]
|
|
90
|
+
extensions = (
|
|
91
|
+
get_args(extensions)
|
|
92
|
+
if get_origin(extensions) in UNION_TYPES
|
|
93
|
+
else [extensions]
|
|
94
|
+
)
|
|
95
|
+
else:
|
|
96
|
+
extensions = []
|
|
97
|
+
|
|
86
98
|
return ResourceType(
|
|
87
99
|
id=name,
|
|
88
100
|
name=name,
|
|
@@ -20,6 +20,7 @@ from ..base import BaseModelType
|
|
|
20
20
|
from ..base import Context
|
|
21
21
|
from ..base import Required
|
|
22
22
|
from ..rfc7643.resource import AnyResource
|
|
23
|
+
from ..utils import UNION_TYPES
|
|
23
24
|
from .message import Message
|
|
24
25
|
|
|
25
26
|
|
|
@@ -29,7 +30,7 @@ class ListResponseMetaclass(BaseModelType):
|
|
|
29
30
|
|
|
30
31
|
https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions
|
|
31
32
|
"""
|
|
32
|
-
if
|
|
33
|
+
if get_origin(resource_union) not in UNION_TYPES:
|
|
33
34
|
return resource_union
|
|
34
35
|
|
|
35
36
|
resource_types = get_args(resource_union)
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
from typing import Annotated
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
1
4
|
from scim2_models import EnterpriseUser
|
|
5
|
+
from scim2_models import Extension
|
|
2
6
|
from scim2_models import Reference
|
|
7
|
+
from scim2_models import Required
|
|
3
8
|
from scim2_models import ResourceType
|
|
4
9
|
from scim2_models import User
|
|
5
10
|
|
|
@@ -61,3 +66,32 @@ def test_from_resource_with_extensions():
|
|
|
61
66
|
== "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
|
|
62
67
|
)
|
|
63
68
|
assert not enterprise_user_rt.schema_extensions[0].required
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_from_resource_with_mulitple_extensions():
|
|
72
|
+
class TestExtension(Extension):
|
|
73
|
+
schemas: Annotated[list[str], Required.true] = [
|
|
74
|
+
"urn:ietf:params:scim:schemas:extension:Test:1.0:User"
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
test: Union[str, None] = None
|
|
78
|
+
test2: Union[list[str], None] = None
|
|
79
|
+
|
|
80
|
+
enterprise_user_rt = ResourceType.from_resource(
|
|
81
|
+
User[Union[EnterpriseUser, TestExtension]]
|
|
82
|
+
)
|
|
83
|
+
assert enterprise_user_rt.id == "User"
|
|
84
|
+
assert enterprise_user_rt.name == "User"
|
|
85
|
+
assert enterprise_user_rt.description == "User"
|
|
86
|
+
assert enterprise_user_rt.endpoint == "/Users"
|
|
87
|
+
assert enterprise_user_rt.schema_ == "urn:ietf:params:scim:schemas:core:2.0:User"
|
|
88
|
+
assert (
|
|
89
|
+
enterprise_user_rt.schema_extensions[0].schema_
|
|
90
|
+
== "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
|
|
91
|
+
)
|
|
92
|
+
assert not enterprise_user_rt.schema_extensions[0].required
|
|
93
|
+
assert (
|
|
94
|
+
enterprise_user_rt.schema_extensions[1].schema_
|
|
95
|
+
== "urn:ietf:params:scim:schemas:extension:Test:1.0:User"
|
|
96
|
+
)
|
|
97
|
+
assert not enterprise_user_rt.schema_extensions[1].required
|