scim2-models 0.3.6__py3-none-any.whl → 0.3.7__py3-none-any.whl

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/constants.py CHANGED
@@ -1,4 +1,4 @@
1
- PYTHON_RESERVED_WORDS = [
1
+ PYTHON_RESERVED_WORDS: list[str] = [
2
2
  "False",
3
3
  "def",
4
4
  "if",
@@ -34,5 +34,5 @@ PYTHON_RESERVED_WORDS = [
34
34
  "pass",
35
35
  ]
36
36
 
37
- PYDANTIC_RESERVED_WORDS = ["schema"]
38
- RESERVED_WORDS = PYTHON_RESERVED_WORDS + PYDANTIC_RESERVED_WORDS
37
+ PYDANTIC_RESERVED_WORDS: list[str] = ["schema"]
38
+ RESERVED_WORDS: list[str] = PYTHON_RESERVED_WORDS + PYDANTIC_RESERVED_WORDS
@@ -0,0 +1,168 @@
1
+ from enum import Enum
2
+ from enum import auto
3
+
4
+
5
+ class Context(Enum):
6
+ """Represent the different HTTP contexts detailed in :rfc:`RFC7644 §3.2 <7644#section-3.2>`.
7
+
8
+ Contexts are intended to be used during model validation and serialization.
9
+ For instance a client preparing a resource creation POST request can use
10
+ :code:`resource.model_dump(Context.RESOURCE_CREATION_REQUEST)` and
11
+ the server can then validate it with
12
+ :code:`resource.model_validate(Context.RESOURCE_CREATION_REQUEST)`.
13
+ """
14
+
15
+ DEFAULT = auto()
16
+ """The default context.
17
+
18
+ All fields are accepted during validation, and all fields are
19
+ serialized during a dump.
20
+ """
21
+
22
+ RESOURCE_CREATION_REQUEST = auto()
23
+ """The resource creation request context.
24
+
25
+ Should be used for clients building a payload for a resource creation request,
26
+ and servers validating resource creation request payloads.
27
+
28
+ - When used for serialization, it will not dump attributes annotated with :attr:`~scim2_models.Mutability.read_only`.
29
+ - When used for validation, it will raise a :class:`~pydantic.ValidationError`:
30
+ - when finding attributes annotated with :attr:`~scim2_models.Mutability.read_only`,
31
+ - when attributes annotated with :attr:`Required.true <scim2_models.Required.true>` are missing on null.
32
+ """
33
+
34
+ RESOURCE_CREATION_RESPONSE = auto()
35
+ """The resource creation response context.
36
+
37
+ Should be used for servers building a payload for a resource
38
+ creation response, and clients validating resource creation response
39
+ payloads.
40
+
41
+ - 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`;
42
+ - When used for serialization, it will:
43
+ - always dump attributes annotated with :attr:`~scim2_models.Returned.always`;
44
+ - never dump attributes annotated with :attr:`~scim2_models.Returned.never`;
45
+ - dump attributes annotated with :attr:`~scim2_models.Returned.default` unless they are explicitly excluded;
46
+ - not dump attributes annotated with :attr:`~scim2_models.Returned.request` unless they are explicitly included.
47
+ """
48
+
49
+ RESOURCE_QUERY_REQUEST = auto()
50
+ """The resource query request context.
51
+
52
+ Should be used for clients building a payload for a resource query request,
53
+ and servers validating resource query request payloads.
54
+
55
+ - When used for serialization, it will not dump attributes annotated with :attr:`~scim2_models.Mutability.write_only`.
56
+ - When used for validation, it will raise a :class:`~pydantic.ValidationError` when finding attributes annotated with :attr:`~scim2_models.Mutability.write_only`.
57
+ """
58
+
59
+ RESOURCE_QUERY_RESPONSE = auto()
60
+ """The resource query response context.
61
+
62
+ Should be used for servers building a payload for a resource query
63
+ response, and clients validating resource query response payloads.
64
+
65
+ - 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`;
66
+ - When used for serialization, it will:
67
+ - always dump attributes annotated with :attr:`~scim2_models.Returned.always`;
68
+ - never dump attributes annotated with :attr:`~scim2_models.Returned.never`;
69
+ - dump attributes annotated with :attr:`~scim2_models.Returned.default` unless they are explicitly excluded;
70
+ - not dump attributes annotated with :attr:`~scim2_models.Returned.request` unless they are explicitly included.
71
+ """
72
+
73
+ RESOURCE_REPLACEMENT_REQUEST = auto()
74
+ """The resource replacement request context.
75
+
76
+ Should be used for clients building a payload for a resource replacement request,
77
+ and servers validating resource replacement request payloads.
78
+
79
+ - When used for serialization, it will not dump attributes annotated with :attr:`~scim2_models.Mutability.read_only`.
80
+ - When used for validation, it will ignore attributes annotated with :attr:`scim2_models.Mutability.read_only` and raise a :class:`~pydantic.ValidationError`:
81
+ - when finding attributes annotated with :attr:`~scim2_models.Mutability.immutable` different than :paramref:`~scim2_models.BaseModel.model_validate.original`:
82
+ - when attributes annotated with :attr:`Required.true <scim2_models.Required.true>` are missing on null.
83
+ """
84
+
85
+ RESOURCE_REPLACEMENT_RESPONSE = auto()
86
+ """The resource replacement response context.
87
+
88
+ Should be used for servers building a payload for a resource
89
+ replacement response, and clients validating resource query
90
+ replacement payloads.
91
+
92
+ - 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`;
93
+ - When used for serialization, it will:
94
+ - always dump attributes annotated with :attr:`~scim2_models.Returned.always`;
95
+ - never dump attributes annotated with :attr:`~scim2_models.Returned.never`;
96
+ - dump attributes annotated with :attr:`~scim2_models.Returned.default` unless they are explicitly excluded;
97
+ - not dump attributes annotated with :attr:`~scim2_models.Returned.request` unless they are explicitly included.
98
+ """
99
+
100
+ SEARCH_REQUEST = auto()
101
+ """The search request context.
102
+
103
+ Should be used for clients building a payload for a search request,
104
+ and servers validating search request payloads.
105
+
106
+ - When used for serialization, it will not dump attributes annotated with :attr:`~scim2_models.Mutability.write_only`.
107
+ - When used for validation, it will raise a :class:`~pydantic.ValidationError` when finding attributes annotated with :attr:`~scim2_models.Mutability.write_only`.
108
+ """
109
+
110
+ SEARCH_RESPONSE = auto()
111
+ """The resource query response context.
112
+
113
+ Should be used for servers building a payload for a search response,
114
+ and clients validating resource search payloads.
115
+
116
+ - 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`;
117
+ - When used for serialization, it will:
118
+ - always dump attributes annotated with :attr:`~scim2_models.Returned.always`;
119
+ - never dump attributes annotated with :attr:`~scim2_models.Returned.never`;
120
+ - dump attributes annotated with :attr:`~scim2_models.Returned.default` unless they are explicitly excluded;
121
+ - not dump attributes annotated with :attr:`~scim2_models.Returned.request` unless they are explicitly included.
122
+ """
123
+
124
+ RESOURCE_PATCH_REQUEST = auto()
125
+ """The resource patch request context.
126
+
127
+ Should be used for clients building a payload for a PATCH request,
128
+ and servers validating PATCH request payloads.
129
+
130
+ - When used for serialization, it will not dump attributes annotated with :attr:`~scim2_models.Mutability.read_only`.
131
+ - When used for validation, it will raise a :class:`~pydantic.ValidationError`:
132
+ - when finding attributes annotated with :attr:`~scim2_models.Mutability.read_only`,
133
+ - when attributes annotated with :attr:`Required.true <scim2_models.Required.true>` are missing or null.
134
+ """
135
+
136
+ RESOURCE_PATCH_RESPONSE = auto()
137
+ """The resource patch response context.
138
+
139
+ Should be used for servers building a payload for a PATCH response,
140
+ and clients validating patch response payloads.
141
+
142
+ - 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`;
143
+ - When used for serialization, it will:
144
+ - always dump attributes annotated with :attr:`~scim2_models.Returned.always`;
145
+ - never dump attributes annotated with :attr:`~scim2_models.Returned.never`;
146
+ - dump attributes annotated with :attr:`~scim2_models.Returned.default` unless they are explicitly excluded;
147
+ - not dump attributes annotated with :attr:`~scim2_models.Returned.request` unless they are explicitly included.
148
+ """
149
+
150
+ @classmethod
151
+ def is_request(cls, ctx: "Context") -> bool:
152
+ return ctx in (
153
+ cls.RESOURCE_CREATION_REQUEST,
154
+ cls.RESOURCE_QUERY_REQUEST,
155
+ cls.RESOURCE_REPLACEMENT_REQUEST,
156
+ cls.SEARCH_REQUEST,
157
+ cls.RESOURCE_PATCH_REQUEST,
158
+ )
159
+
160
+ @classmethod
161
+ def is_response(cls, ctx: "Context") -> bool:
162
+ return ctx in (
163
+ cls.RESOURCE_CREATION_RESPONSE,
164
+ cls.RESOURCE_QUERY_RESPONSE,
165
+ cls.RESOURCE_REPLACEMENT_RESPONSE,
166
+ cls.SEARCH_RESPONSE,
167
+ cls.RESOURCE_PATCH_RESPONSE,
168
+ )
@@ -0,0 +1,82 @@
1
+ from collections import UserString
2
+ from typing import Any
3
+ from typing import Generic
4
+ from typing import TypeVar
5
+ from typing import get_args
6
+ from typing import get_origin
7
+
8
+ from pydantic import GetCoreSchemaHandler
9
+ from pydantic_core import core_schema
10
+ from typing_extensions import NewType
11
+
12
+ from .utils import UNION_TYPES
13
+
14
+ ReferenceTypes = TypeVar("ReferenceTypes")
15
+
16
+ URIReference = NewType("URIReference", str)
17
+ ExternalReference = NewType("ExternalReference", str)
18
+
19
+
20
+ class Reference(UserString, Generic[ReferenceTypes]):
21
+ """Reference type as defined in :rfc:`RFC7643 §2.3.7 <7643#section-2.3.7>`.
22
+
23
+ References can take different type parameters:
24
+
25
+ - Any :class:`~scim2_models.Resource` subtype, or :class:`~typing.ForwardRef` of a Resource subtype, or :data:`~typing.Union` of those,
26
+ - :data:`~scim2_models.ExternalReference`
27
+ - :data:`~scim2_models.URIReference`
28
+
29
+ Examples
30
+ --------
31
+
32
+ .. code-block:: python
33
+
34
+ class Foobar(Resource):
35
+ bff: Reference[User]
36
+ managers: Reference[Union["User", "Group"]]
37
+ photo: Reference[ExternalReference]
38
+ website: Reference[URIReference]
39
+
40
+ """
41
+
42
+ @classmethod
43
+ def __get_pydantic_core_schema__(
44
+ cls,
45
+ _source: type[Any],
46
+ _handler: GetCoreSchemaHandler,
47
+ ) -> core_schema.CoreSchema:
48
+ return core_schema.no_info_after_validator_function(
49
+ cls._validate,
50
+ core_schema.union_schema(
51
+ [core_schema.str_schema(), core_schema.is_instance_schema(cls)]
52
+ ),
53
+ )
54
+
55
+ @classmethod
56
+ def _validate(cls, input_value: Any, /) -> str:
57
+ return str(input_value)
58
+
59
+ @classmethod
60
+ def get_types(cls, type_annotation: Any) -> list[str]:
61
+ """Get reference types from a type annotation.
62
+
63
+ :param type_annotation: Type annotation to extract reference types from
64
+ :type type_annotation: Any
65
+ :return: List of reference type strings
66
+ :rtype: list[str]
67
+ """
68
+ first_arg = get_args(type_annotation)[0]
69
+ types = (
70
+ get_args(first_arg) if get_origin(first_arg) in UNION_TYPES else [first_arg]
71
+ )
72
+
73
+ def serialize_ref_type(ref_type: Any) -> str:
74
+ if ref_type == URIReference:
75
+ return "uri"
76
+
77
+ elif ref_type == ExternalReference:
78
+ return "external"
79
+
80
+ return str(get_args(ref_type)[0])
81
+
82
+ return list(map(serialize_ref_type, types))
@@ -4,10 +4,10 @@ from typing import Optional
4
4
 
5
5
  from pydantic import Field
6
6
 
7
- from ..base import ComplexAttribute
8
- from ..base import Mutability
9
- from ..base import Reference
10
- from ..base import Required
7
+ from ..annotations import Mutability
8
+ from ..annotations import Required
9
+ from ..attributes import ComplexAttribute
10
+ from ..reference import Reference
11
11
  from .resource import Extension
12
12
 
13
13
 
@@ -6,11 +6,11 @@ from typing import Union
6
6
 
7
7
  from pydantic import Field
8
8
 
9
- from ..base import ComplexAttribute
10
- from ..base import MultiValuedComplexAttribute
11
- from ..base import Mutability
12
- from ..base import Reference
13
- from ..base import Required
9
+ from ..annotations import Mutability
10
+ from ..annotations import Required
11
+ from ..attributes import ComplexAttribute
12
+ from ..attributes import MultiValuedComplexAttribute
13
+ from ..reference import Reference
14
14
  from .resource import Resource
15
15
 
16
16