scim2-client 0.1.5__tar.gz → 0.1.7__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_client-0.1.5 → scim2_client-0.1.7}/PKG-INFO +4 -4
- {scim2_client-0.1.5 → scim2_client-0.1.7}/README.md +2 -2
- {scim2_client-0.1.5 → scim2_client-0.1.7}/pyproject.toml +4 -4
- {scim2_client-0.1.5 → scim2_client-0.1.7}/scim2_client/__init__.py +2 -0
- {scim2_client-0.1.5 → scim2_client-0.1.7}/scim2_client/client.py +69 -27
- {scim2_client-0.1.5 → scim2_client-0.1.7}/scim2_client/errors.py +14 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: scim2-client
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: Pythonically build SCIM requests and parse SCIM responses
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: scim,scim2,provisioning,httpx,api
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
21
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
22
|
Requires-Dist: httpx (>=0.27.0,<0.28.0)
|
|
23
|
-
Requires-Dist: scim2-models (>=0.1.
|
|
23
|
+
Requires-Dist: scim2-models (>=0.1.8,<0.2.0)
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
|
|
26
26
|
# scim2-client
|
|
@@ -67,9 +67,9 @@ assert user.meta.last_updated == datetime.datetime(
|
|
|
67
67
|
)
|
|
68
68
|
|
|
69
69
|
# Update resources
|
|
70
|
-
user.display_name = "
|
|
70
|
+
user.display_name = "Babs Jensen"
|
|
71
71
|
user = scim.replace(user)
|
|
72
|
-
assert user.display_name == "
|
|
72
|
+
assert user.display_name == "Babs Jensen"
|
|
73
73
|
assert user.meta.last_updated == datetime.datetime(
|
|
74
74
|
2024, 4, 13, 12, 0, 30, tzinfo=datetime.timezone.utc
|
|
75
75
|
)
|
|
@@ -42,9 +42,9 @@ assert user.meta.last_updated == datetime.datetime(
|
|
|
42
42
|
)
|
|
43
43
|
|
|
44
44
|
# Update resources
|
|
45
|
-
user.display_name = "
|
|
45
|
+
user.display_name = "Babs Jensen"
|
|
46
46
|
user = scim.replace(user)
|
|
47
|
-
assert user.display_name == "
|
|
47
|
+
assert user.display_name == "Babs Jensen"
|
|
48
48
|
assert user.meta.last_updated == datetime.datetime(
|
|
49
49
|
2024, 4, 13, 12, 0, 30, tzinfo=datetime.timezone.utc
|
|
50
50
|
)
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "scim2-client"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.7"
|
|
8
8
|
description = "Pythonically build SCIM requests and parse SCIM responses"
|
|
9
9
|
authors = ["Yaal Coop <contact@yaal.coop>"]
|
|
10
10
|
license = "MIT"
|
|
@@ -27,7 +27,7 @@ classifiers = [
|
|
|
27
27
|
[tool.poetry.dependencies]
|
|
28
28
|
python = "^3.9"
|
|
29
29
|
httpx = "^0.27.0"
|
|
30
|
-
scim2-models = "^0.1.
|
|
30
|
+
scim2-models = "^0.1.8"
|
|
31
31
|
|
|
32
32
|
[tool.poetry.group.doc]
|
|
33
33
|
optional = true
|
|
@@ -38,10 +38,10 @@ pytest-coverage = "^0.0"
|
|
|
38
38
|
pytest-httpserver = "^1.0.10"
|
|
39
39
|
|
|
40
40
|
[tool.poetry.group.doc.dependencies]
|
|
41
|
+
autodoc-pydantic = "^2.2.0"
|
|
42
|
+
myst-parser = "^3.0.1"
|
|
41
43
|
shibuya = "^2024.5.15"
|
|
42
44
|
sphinx = "^7.3.7"
|
|
43
|
-
myst-parser = "^3.0.1"
|
|
44
|
-
autodoc-pydantic = "^2.2.0"
|
|
45
45
|
|
|
46
46
|
[tool.coverage.run]
|
|
47
47
|
source = [
|
|
@@ -5,6 +5,7 @@ from .errors import ResponsePayloadValidationError
|
|
|
5
5
|
from .errors import SCIMClientError
|
|
6
6
|
from .errors import SCIMRequestError
|
|
7
7
|
from .errors import SCIMResponseError
|
|
8
|
+
from .errors import SCIMResponseErrorObject
|
|
8
9
|
from .errors import UnexpectedContentFormat
|
|
9
10
|
from .errors import UnexpectedContentType
|
|
10
11
|
from .errors import UnexpectedStatusCode
|
|
@@ -14,6 +15,7 @@ __all__ = [
|
|
|
14
15
|
"SCIMClientError",
|
|
15
16
|
"SCIMRequestError",
|
|
16
17
|
"SCIMResponseError",
|
|
18
|
+
"SCIMResponseErrorObject",
|
|
17
19
|
"UnexpectedContentFormat",
|
|
18
20
|
"UnexpectedContentType",
|
|
19
21
|
"UnexpectedStatusCode",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import json.decoder
|
|
3
|
+
import sys
|
|
3
4
|
from typing import Dict
|
|
4
5
|
from typing import List
|
|
5
6
|
from typing import Optional
|
|
@@ -28,6 +29,7 @@ from .errors import ResponsePayloadValidationError
|
|
|
28
29
|
from .errors import SCIMClientError
|
|
29
30
|
from .errors import SCIMRequestError
|
|
30
31
|
from .errors import SCIMResponseError
|
|
32
|
+
from .errors import SCIMResponseErrorObject
|
|
31
33
|
from .errors import UnexpectedContentFormat
|
|
32
34
|
from .errors import UnexpectedContentType
|
|
33
35
|
from .errors import UnexpectedStatusCode
|
|
@@ -61,12 +63,18 @@ class SCIMClient:
|
|
|
61
63
|
404,
|
|
62
64
|
500,
|
|
63
65
|
]
|
|
64
|
-
"""Resource creation HTTP codes
|
|
65
|
-
|
|
66
|
+
"""Resource creation HTTP codes.
|
|
67
|
+
|
|
68
|
+
As defined at :rfc:`RFC7644 §3.3 <7644#section-3.3>` and
|
|
69
|
+
:rfc:`RFC7644 §3.12 <7644#section-3.12>`.
|
|
70
|
+
"""
|
|
66
71
|
|
|
67
72
|
QUERY_RESPONSE_STATUS_CODES: List[int] = [200, 400, 307, 308, 401, 403, 404, 500]
|
|
68
|
-
"""Resource querying HTTP codes
|
|
69
|
-
|
|
73
|
+
"""Resource querying HTTP codes.
|
|
74
|
+
|
|
75
|
+
As defined at :rfc:`RFC7644 §3.4.2 <7644#section-3.4.2>` and
|
|
76
|
+
:rfc:`RFC7644 §3.12 <7644#section-3.12>`.
|
|
77
|
+
"""
|
|
70
78
|
|
|
71
79
|
SEARCH_RESPONSE_STATUS_CODES: List[int] = [
|
|
72
80
|
200,
|
|
@@ -81,8 +89,11 @@ class SCIMClient:
|
|
|
81
89
|
500,
|
|
82
90
|
501,
|
|
83
91
|
]
|
|
84
|
-
"""Resource querying HTTP codes
|
|
85
|
-
|
|
92
|
+
"""Resource querying HTTP codes.
|
|
93
|
+
|
|
94
|
+
As defined at :rfc:`RFC7644 §3.4.3 <7644#section-3.4.3>` and
|
|
95
|
+
:rfc:`RFC7644 §3.12 <7644#section-3.12>`.
|
|
96
|
+
"""
|
|
86
97
|
|
|
87
98
|
DELETION_RESPONSE_STATUS_CODES: List[int] = [
|
|
88
99
|
204,
|
|
@@ -96,8 +107,11 @@ class SCIMClient:
|
|
|
96
107
|
500,
|
|
97
108
|
501,
|
|
98
109
|
]
|
|
99
|
-
"""Resource deletion HTTP codes
|
|
100
|
-
|
|
110
|
+
"""Resource deletion HTTP codes.
|
|
111
|
+
|
|
112
|
+
As defined at :rfc:`RFC7644 §3.6 <7644#section-3.6>` and
|
|
113
|
+
:rfc:`RFC7644 §3.12 <7644#section-3.12>`.
|
|
114
|
+
"""
|
|
101
115
|
|
|
102
116
|
REPLACEMENT_RESPONSE_STATUS_CODES: List[int] = [
|
|
103
117
|
200,
|
|
@@ -112,8 +126,11 @@ class SCIMClient:
|
|
|
112
126
|
500,
|
|
113
127
|
501,
|
|
114
128
|
]
|
|
115
|
-
"""Resource querying HTTP codes
|
|
116
|
-
|
|
129
|
+
"""Resource querying HTTP codes.
|
|
130
|
+
|
|
131
|
+
As defined at :rfc:`RFC7644 §3.4.2 <7644#section-3.4.2>` and
|
|
132
|
+
:rfc:`RFC7644 §3.12 <7644#section-3.12>`.
|
|
133
|
+
"""
|
|
117
134
|
|
|
118
135
|
def __init__(self, client: Client, resource_types: Optional[Tuple[Type]] = None):
|
|
119
136
|
self.client = client
|
|
@@ -146,6 +163,7 @@ class SCIMClient:
|
|
|
146
163
|
expected_status_codes: List[int],
|
|
147
164
|
expected_types: Optional[Type] = None,
|
|
148
165
|
check_response_payload: bool = True,
|
|
166
|
+
raise_scim_errors: bool = False,
|
|
149
167
|
scim_ctx: Optional[Context] = None,
|
|
150
168
|
):
|
|
151
169
|
if expected_status_codes and response.status_code not in expected_status_codes:
|
|
@@ -178,10 +196,14 @@ class SCIMClient:
|
|
|
178
196
|
if not check_response_payload:
|
|
179
197
|
return response_payload
|
|
180
198
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
199
|
+
if (
|
|
200
|
+
response_payload
|
|
201
|
+
and response_payload.get("schemas") == Error.model_fields["schemas"].default
|
|
202
|
+
):
|
|
203
|
+
error = Error.model_validate(response_payload)
|
|
204
|
+
if raise_scim_errors:
|
|
205
|
+
raise SCIMResponseErrorObject(source=error)
|
|
206
|
+
return error
|
|
185
207
|
|
|
186
208
|
if not expected_types:
|
|
187
209
|
return response_payload
|
|
@@ -206,7 +228,7 @@ class SCIMClient:
|
|
|
206
228
|
return actual_type.model_validate(response_payload, scim_ctx=scim_ctx)
|
|
207
229
|
except ValidationError as exc:
|
|
208
230
|
scim_exc = ResponsePayloadValidationError(source=response)
|
|
209
|
-
if
|
|
231
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
210
232
|
scim_exc.add_note(str(exc))
|
|
211
233
|
raise scim_exc from exc
|
|
212
234
|
|
|
@@ -216,6 +238,7 @@ class SCIMClient:
|
|
|
216
238
|
check_request_payload: bool = True,
|
|
217
239
|
check_response_payload: bool = True,
|
|
218
240
|
check_status_code: bool = True,
|
|
241
|
+
raise_scim_errors: bool = False,
|
|
219
242
|
**kwargs,
|
|
220
243
|
) -> Union[AnyResource, Error, Dict]:
|
|
221
244
|
"""Perform a POST request to create, as defined in :rfc:`RFC7644 §3.3
|
|
@@ -228,6 +251,9 @@ class SCIMClient:
|
|
|
228
251
|
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
229
252
|
If set, the raw payload will be returned.
|
|
230
253
|
:param check_status_code: Whether to validate that the response status code is valid.
|
|
254
|
+
:param raise_scim_errors: If :data:`True` and the server returned an
|
|
255
|
+
:class:`~scim2_models.Error` object, a :class:`~scim2_client.SCIMResponseErrorObject`
|
|
256
|
+
exception will be raised. If :data:`False` the error object is returned.
|
|
231
257
|
:param kwargs: Additional parameters passed to the underlying HTTP request
|
|
232
258
|
library.
|
|
233
259
|
|
|
@@ -252,7 +278,6 @@ class SCIMClient:
|
|
|
252
278
|
which value will excluded from the request payload, and which values are expected in
|
|
253
279
|
the response payload.
|
|
254
280
|
"""
|
|
255
|
-
|
|
256
281
|
if not check_request_payload:
|
|
257
282
|
payload = resource
|
|
258
283
|
url = kwargs.pop("url", None)
|
|
@@ -272,7 +297,7 @@ class SCIMClient:
|
|
|
272
297
|
resource = resource_type.model_validate(resource)
|
|
273
298
|
except ValidationError as exc:
|
|
274
299
|
scim_exc = RequestPayloadValidationError(source=resource)
|
|
275
|
-
if
|
|
300
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
276
301
|
scim_exc.add_note(str(exc))
|
|
277
302
|
raise scim_exc from exc
|
|
278
303
|
|
|
@@ -284,7 +309,7 @@ class SCIMClient:
|
|
|
284
309
|
response = self.client.post(url, json=payload, **kwargs)
|
|
285
310
|
except RequestError as exc:
|
|
286
311
|
scim_exc = RequestNetworkError(source=payload)
|
|
287
|
-
if
|
|
312
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
288
313
|
scim_exc.add_note(str(exc))
|
|
289
314
|
raise scim_exc from exc
|
|
290
315
|
|
|
@@ -295,6 +320,7 @@ class SCIMClient:
|
|
|
295
320
|
),
|
|
296
321
|
expected_types=([resource.__class__] if check_request_payload else None),
|
|
297
322
|
check_response_payload=check_response_payload,
|
|
323
|
+
raise_scim_errors=raise_scim_errors,
|
|
298
324
|
scim_ctx=Context.RESOURCE_CREATION_RESPONSE,
|
|
299
325
|
)
|
|
300
326
|
|
|
@@ -306,6 +332,7 @@ class SCIMClient:
|
|
|
306
332
|
check_request_payload: bool = True,
|
|
307
333
|
check_response_payload: bool = True,
|
|
308
334
|
check_status_code: bool = True,
|
|
335
|
+
raise_scim_errors: bool = False,
|
|
309
336
|
**kwargs,
|
|
310
337
|
) -> Union[AnyResource, ListResponse[AnyResource], Error, Dict]:
|
|
311
338
|
"""Perform a GET request to read resources, as defined in :rfc:`RFC7644
|
|
@@ -322,6 +349,9 @@ class SCIMClient:
|
|
|
322
349
|
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
323
350
|
If set, the raw payload will be returned.
|
|
324
351
|
:param check_status_code: Whether to validate that the response status code is valid.
|
|
352
|
+
:param raise_scim_errors: If :data:`True` and the server returned an
|
|
353
|
+
:class:`~scim2_models.Error` object, a :class:`~scim2_client.SCIMResponseErrorObject`
|
|
354
|
+
exception will be raised. If :data:`False` the error object is returned.
|
|
325
355
|
:param kwargs: Additional parameters passed to the underlying HTTP request library.
|
|
326
356
|
|
|
327
357
|
:return:
|
|
@@ -368,7 +398,6 @@ class SCIMClient:
|
|
|
368
398
|
which value will excluded from the request payload, and which values are expected in
|
|
369
399
|
the response payload.
|
|
370
400
|
"""
|
|
371
|
-
|
|
372
401
|
if resource_type and check_request_payload:
|
|
373
402
|
self.check_resource_type(resource_type)
|
|
374
403
|
|
|
@@ -409,7 +438,7 @@ class SCIMClient:
|
|
|
409
438
|
response = self.client.get(url, params=payload, **kwargs)
|
|
410
439
|
except RequestError as exc:
|
|
411
440
|
scim_exc = RequestNetworkError(source=payload)
|
|
412
|
-
if
|
|
441
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
413
442
|
scim_exc.add_note(str(exc))
|
|
414
443
|
raise scim_exc from exc
|
|
415
444
|
|
|
@@ -420,6 +449,7 @@ class SCIMClient:
|
|
|
420
449
|
),
|
|
421
450
|
expected_types=expected_types,
|
|
422
451
|
check_response_payload=check_response_payload,
|
|
452
|
+
raise_scim_errors=raise_scim_errors,
|
|
423
453
|
scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
|
|
424
454
|
)
|
|
425
455
|
|
|
@@ -429,6 +459,7 @@ class SCIMClient:
|
|
|
429
459
|
check_request_payload: bool = True,
|
|
430
460
|
check_response_payload: bool = True,
|
|
431
461
|
check_status_code: bool = True,
|
|
462
|
+
raise_scim_errors: bool = False,
|
|
432
463
|
**kwargs,
|
|
433
464
|
) -> Union[AnyResource, ListResponse[AnyResource], Error, Dict]:
|
|
434
465
|
"""Perform a POST search request to read all available resources, as
|
|
@@ -442,6 +473,9 @@ class SCIMClient:
|
|
|
442
473
|
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
443
474
|
If set, the raw payload will be returned.
|
|
444
475
|
:param check_status_code: Whether to validate that the response status code is valid.
|
|
476
|
+
:param raise_scim_errors: If :data:`True` and the server returned an
|
|
477
|
+
:class:`~scim2_models.Error` object, a :class:`~scim2_client.SCIMResponseErrorObject`
|
|
478
|
+
exception will be raised. If :data:`False` the error object is returned.
|
|
445
479
|
:param kwargs: Additional parameters passed to the underlying
|
|
446
480
|
HTTP request library.
|
|
447
481
|
|
|
@@ -467,7 +501,6 @@ class SCIMClient:
|
|
|
467
501
|
which value will excluded from the request payload, and which values are expected in
|
|
468
502
|
the response payload.
|
|
469
503
|
"""
|
|
470
|
-
|
|
471
504
|
if not check_request_payload:
|
|
472
505
|
payload = search_request
|
|
473
506
|
|
|
@@ -486,7 +519,7 @@ class SCIMClient:
|
|
|
486
519
|
response = self.client.post(url, json=payload)
|
|
487
520
|
except RequestError as exc:
|
|
488
521
|
scim_exc = RequestNetworkError(source=payload)
|
|
489
|
-
if
|
|
522
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
490
523
|
scim_exc.add_note(str(exc))
|
|
491
524
|
raise scim_exc from exc
|
|
492
525
|
|
|
@@ -497,6 +530,7 @@ class SCIMClient:
|
|
|
497
530
|
),
|
|
498
531
|
expected_types=[ListResponse[Union[self.resource_types]]],
|
|
499
532
|
check_response_payload=check_response_payload,
|
|
533
|
+
raise_scim_errors=raise_scim_errors,
|
|
500
534
|
scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
|
|
501
535
|
)
|
|
502
536
|
|
|
@@ -506,6 +540,7 @@ class SCIMClient:
|
|
|
506
540
|
id: str,
|
|
507
541
|
check_response_payload: bool = True,
|
|
508
542
|
check_status_code: bool = True,
|
|
543
|
+
raise_scim_errors: bool = False,
|
|
509
544
|
**kwargs,
|
|
510
545
|
) -> Optional[Union[Error, Dict]]:
|
|
511
546
|
"""Perform a DELETE request to create, as defined in :rfc:`RFC7644 §3.6
|
|
@@ -516,6 +551,9 @@ class SCIMClient:
|
|
|
516
551
|
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
517
552
|
If set, the raw payload will be returned.
|
|
518
553
|
:param check_status_code: Whether to validate that the response status code is valid.
|
|
554
|
+
:param raise_scim_errors: If :data:`True` and the server returned an
|
|
555
|
+
:class:`~scim2_models.Error` object, a :class:`~scim2_client.SCIMResponseErrorObject`
|
|
556
|
+
exception will be raised. If :data:`False` the error object is returned.
|
|
519
557
|
:param kwargs: Additional parameters passed to the underlying
|
|
520
558
|
HTTP request library.
|
|
521
559
|
|
|
@@ -533,7 +571,6 @@ class SCIMClient:
|
|
|
533
571
|
response = scim.delete(User, "foobar")
|
|
534
572
|
# 'response' may be None, or an Error object
|
|
535
573
|
"""
|
|
536
|
-
|
|
537
574
|
self.check_resource_type(resource_type)
|
|
538
575
|
delete_url = self.resource_endpoint(resource_type) + f"/{id}"
|
|
539
576
|
url = kwargs.pop("url", delete_url)
|
|
@@ -542,7 +579,7 @@ class SCIMClient:
|
|
|
542
579
|
response = self.client.delete(url, **kwargs)
|
|
543
580
|
except RequestError as exc:
|
|
544
581
|
scim_exc = RequestNetworkError()
|
|
545
|
-
if
|
|
582
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
546
583
|
scim_exc.add_note(str(exc))
|
|
547
584
|
raise scim_exc from exc
|
|
548
585
|
|
|
@@ -552,6 +589,7 @@ class SCIMClient:
|
|
|
552
589
|
self.DELETION_RESPONSE_STATUS_CODES if check_status_code else None
|
|
553
590
|
),
|
|
554
591
|
check_response_payload=check_response_payload,
|
|
592
|
+
raise_scim_errors=raise_scim_errors,
|
|
555
593
|
)
|
|
556
594
|
|
|
557
595
|
def replace(
|
|
@@ -560,6 +598,7 @@ class SCIMClient:
|
|
|
560
598
|
check_request_payload: bool = True,
|
|
561
599
|
check_response_payload: bool = True,
|
|
562
600
|
check_status_code: bool = True,
|
|
601
|
+
raise_scim_errors: bool = False,
|
|
563
602
|
**kwargs,
|
|
564
603
|
) -> Union[AnyResource, Error, Dict]:
|
|
565
604
|
"""Perform a PUT request to replace a resource, as defined in
|
|
@@ -572,6 +611,9 @@ class SCIMClient:
|
|
|
572
611
|
:param check_response_payload: Whether to validate that the response payload is valid.
|
|
573
612
|
If set, the raw payload will be returned.
|
|
574
613
|
:param check_status_code: Whether to validate that the response status code is valid.
|
|
614
|
+
:param raise_scim_errors: If :data:`True` and the server returned an
|
|
615
|
+
:class:`~scim2_models.Error` object, a :class:`~scim2_client.SCIMResponseErrorObject`
|
|
616
|
+
exception will be raised. If :data:`False` the error object is returned.
|
|
575
617
|
:param kwargs: Additional parameters passed to the underlying
|
|
576
618
|
HTTP request library.
|
|
577
619
|
|
|
@@ -598,7 +640,6 @@ class SCIMClient:
|
|
|
598
640
|
which value will excluded from the request payload, and which values are expected in
|
|
599
641
|
the response payload.
|
|
600
642
|
"""
|
|
601
|
-
|
|
602
643
|
if not check_request_payload:
|
|
603
644
|
payload = resource
|
|
604
645
|
url = kwargs.pop("url", None)
|
|
@@ -619,7 +660,7 @@ class SCIMClient:
|
|
|
619
660
|
resource = resource_type.model_validate(resource)
|
|
620
661
|
except ValidationError as exc:
|
|
621
662
|
scim_exc = RequestPayloadValidationError(source=resource)
|
|
622
|
-
if
|
|
663
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
623
664
|
scim_exc.add_note(str(exc))
|
|
624
665
|
raise scim_exc from exc
|
|
625
666
|
|
|
@@ -637,7 +678,7 @@ class SCIMClient:
|
|
|
637
678
|
response = self.client.put(url, json=payload, **kwargs)
|
|
638
679
|
except RequestError as exc:
|
|
639
680
|
scim_exc = RequestNetworkError(source=payload)
|
|
640
|
-
if
|
|
681
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
641
682
|
scim_exc.add_note(str(exc))
|
|
642
683
|
raise scim_exc from exc
|
|
643
684
|
|
|
@@ -648,6 +689,7 @@ class SCIMClient:
|
|
|
648
689
|
),
|
|
649
690
|
expected_types=([resource.__class__] if check_request_payload else None),
|
|
650
691
|
check_response_payload=check_response_payload,
|
|
692
|
+
raise_scim_errors=raise_scim_errors,
|
|
651
693
|
scim_ctx=Context.RESOURCE_REPLACEMENT_RESPONSE,
|
|
652
694
|
)
|
|
653
695
|
|
|
@@ -60,6 +60,20 @@ class SCIMResponseError(SCIMClientError):
|
|
|
60
60
|
validation."""
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
class SCIMResponseErrorObject(SCIMResponseError):
|
|
64
|
+
"""The server response returned a :class:`scim2_models.Error` object.
|
|
65
|
+
|
|
66
|
+
Those errors are only raised when the :code:`raise_scim_errors` parameter is :data:`True`.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(self, *args, **kwargs):
|
|
70
|
+
message = kwargs.pop(
|
|
71
|
+
"message",
|
|
72
|
+
f"The server returned a SCIM Error object: {kwargs['source'].detail}",
|
|
73
|
+
)
|
|
74
|
+
super().__init__(message, *args, **kwargs)
|
|
75
|
+
|
|
76
|
+
|
|
63
77
|
class UnexpectedStatusCode(SCIMResponseError):
|
|
64
78
|
"""Error raised when a server returned an unexpected status code for a
|
|
65
79
|
given :class:`~scim2_models.Context`."""
|