Skip to content

Commit 3d4d168

Browse files
committed
fix: support for scim2_models 0.1.8
1 parent c10f447 commit 3d4d168

10 files changed

+126
-167
lines changed

.pre-commit-config.yaml

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
repos:
33
- repo: https://github.com/astral-sh/ruff-pre-commit
4-
rev: 'v0.4.7'
4+
rev: 'v0.5.0'
55
hooks:
66
- id: ruff
77
args: [--fix, --exit-non-zero-on-fix]
@@ -19,7 +19,3 @@ repos:
1919
rev: v1.7.5
2020
hooks:
2121
- id: docformatter
22-
- repo: https://github.com/rtts/djhtml
23-
rev: 3.0.6
24-
hooks:
25-
- id: djhtml

doc/changelog.rst

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
Changelog
22
=========
33

4+
Fixed
5+
^^^^^
6+
- Support for scim2-models 0.1.8
7+
48
[0.1.6] - 2024-06-05
59
--------------------
610

poetry.lock

+84-84
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ classifiers = [
2727
[tool.poetry.dependencies]
2828
python = "^3.9"
2929
httpx = "^0.27.0"
30-
scim2-models = "^0.1.5"
30+
scim2-models = "^0.1.8"
3131

3232
[tool.poetry.group.doc]
3333
optional = true
@@ -38,10 +38,10 @@ pytest-coverage = "^0.0"
3838
pytest-httpserver = "^1.0.10"
3939

4040
[tool.poetry.group.doc.dependencies]
41+
autodoc-pydantic = "^2.2.0"
42+
myst-parser = "^3.0.1"
4143
shibuya = "^2024.5.15"
4244
sphinx = "^7.3.7"
43-
myst-parser = "^3.0.1"
44-
autodoc-pydantic = "^2.2.0"
4545

4646
[tool.coverage.run]
4747
source = [

scim2_client/client.py

+29-18
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,18 @@ class SCIMClient:
6363
404,
6464
500,
6565
]
66-
"""Resource creation HTTP codes defined at :rfc:`RFC7644 §3.3
67-
<7644#section-3.3>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
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+
"""
6871

6972
QUERY_RESPONSE_STATUS_CODES: List[int] = [200, 400, 307, 308, 401, 403, 404, 500]
70-
"""Resource querying HTTP codes defined at :rfc:`RFC7644 §3.4.2
71-
<7644#section-3.4.2>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
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+
"""
7278

7379
SEARCH_RESPONSE_STATUS_CODES: List[int] = [
7480
200,
@@ -83,8 +89,11 @@ class SCIMClient:
8389
500,
8490
501,
8591
]
86-
"""Resource querying HTTP codes defined at :rfc:`RFC7644 §3.4.3
87-
<7644#section-3.4.3>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
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+
"""
8897

8998
DELETION_RESPONSE_STATUS_CODES: List[int] = [
9099
204,
@@ -98,8 +107,11 @@ class SCIMClient:
98107
500,
99108
501,
100109
]
101-
"""Resource deletion HTTP codes defined at :rfc:`RFC7644 §3.6
102-
<7644#section-3.6>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
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+
"""
103115

104116
REPLACEMENT_RESPONSE_STATUS_CODES: List[int] = [
105117
200,
@@ -114,8 +126,11 @@ class SCIMClient:
114126
500,
115127
501,
116128
]
117-
"""Resource querying HTTP codes defined at :rfc:`RFC7644 §3.4.2
118-
<7644#section-3.4.2>` and :rfc:`RFC7644 §3.12 <7644#section-3.12>`"""
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+
"""
119134

120135
def __init__(self, client: Client, resource_types: Optional[Tuple[Type]] = None):
121136
self.client = client
@@ -181,13 +196,14 @@ def check_response(
181196
if not check_response_payload:
182197
return response_payload
183198

184-
try:
199+
if (
200+
response_payload
201+
and response_payload.get("schemas") == Error.model_fields["schemas"].default
202+
):
185203
error = Error.model_validate(response_payload)
186204
if raise_scim_errors:
187205
raise SCIMResponseErrorObject(source=error)
188206
return error
189-
except ValidationError:
190-
pass
191207

192208
if not expected_types:
193209
return response_payload
@@ -262,7 +278,6 @@ def create(
262278
which value will excluded from the request payload, and which values are expected in
263279
the response payload.
264280
"""
265-
266281
if not check_request_payload:
267282
payload = resource
268283
url = kwargs.pop("url", None)
@@ -383,7 +398,6 @@ def query(
383398
which value will excluded from the request payload, and which values are expected in
384399
the response payload.
385400
"""
386-
387401
if resource_type and check_request_payload:
388402
self.check_resource_type(resource_type)
389403

@@ -487,7 +501,6 @@ def search(
487501
which value will excluded from the request payload, and which values are expected in
488502
the response payload.
489503
"""
490-
491504
if not check_request_payload:
492505
payload = search_request
493506

@@ -558,7 +571,6 @@ def delete(
558571
response = scim.delete(User, "foobar")
559572
# 'response' may be None, or an Error object
560573
"""
561-
562574
self.check_resource_type(resource_type)
563575
delete_url = self.resource_endpoint(resource_type) + f"/{id}"
564576
url = kwargs.pop("url", delete_url)
@@ -628,7 +640,6 @@ def replace(
628640
which value will excluded from the request payload, and which values are expected in
629641
the response payload.
630642
"""
631-
632643
if not check_request_payload:
633644
payload = resource
634645
url = kwargs.pop("url", None)

tests/test_create.py

-11
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
def test_create_user(httpserver):
1919
"""Nominal case for a User creation object."""
20-
2120
httpserver.expect_request("/Users", method="POST").respond_with_json(
2221
{
2322
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
@@ -61,7 +60,6 @@ def test_create_user(httpserver):
6160
def test_create_dict_user(httpserver):
6261
"""Nominal case for a User creation object, when passing a dict instead of
6362
a resource."""
64-
6563
httpserver.expect_request("/Users", method="POST").respond_with_json(
6664
{
6765
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
@@ -107,7 +105,6 @@ def test_create_dict_user(httpserver):
107105

108106
def test_create_dict_user_bad_schema(httpserver):
109107
"""Test when passing a resource dict with an unknown or invalid schema."""
110-
111108
httpserver.expect_request("/Users", method="POST").respond_with_json(
112109
{
113110
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
@@ -139,7 +136,6 @@ def test_create_dict_user_bad_schema(httpserver):
139136

140137
def test_dont_check_response_payload(httpserver):
141138
"""Test the check_response_payload_attribute."""
142-
143139
httpserver.expect_request("/Users", method="POST").respond_with_json(
144140
{"foo": "bar"}, status=201
145141
)
@@ -157,7 +153,6 @@ def test_dont_check_request_payload(httpserver):
157153
158154
TODO: Actually check that the payload is sent through the network
159155
"""
160-
161156
httpserver.expect_request("/Users", method="POST").respond_with_json(
162157
{
163158
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
@@ -202,7 +197,6 @@ def test_dont_check_request_payload(httpserver):
202197

203198
def test_conflict(httpserver):
204199
"""Nominal case for a User creation object."""
205-
206200
httpserver.expect_request("/Users", method="POST").respond_with_json(
207201
{
208202
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
@@ -228,7 +222,6 @@ def test_conflict(httpserver):
228222

229223
def test_no_200(httpserver):
230224
"""User creation object should return 201 codes and no 200."""
231-
232225
httpserver.expect_request("/Users", method="POST").respond_with_json(
233226
{
234227
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
@@ -257,7 +250,6 @@ def test_no_200(httpserver):
257250
@pytest.mark.parametrize("code", [400, 401, 403, 404, 500])
258251
def test_errors(httpserver, code):
259252
"""Test error cases defined in RFC7644."""
260-
261253
httpserver.expect_request("/Users", method="POST").respond_with_json(
262254
{
263255
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
@@ -283,7 +275,6 @@ def test_errors(httpserver, code):
283275
def test_invalid_resource_type(httpserver):
284276
"""Test that resource_types passed to the method must be part of
285277
SCIMClient.resource_types."""
286-
287278
client = Client(base_url=f"http://localhost:{httpserver.port}")
288279
scim_client = SCIMClient(client, resource_types=(User,))
289280
with pytest.raises(SCIMRequestError, match=r"Unknown resource type"):
@@ -292,7 +283,6 @@ def test_invalid_resource_type(httpserver):
292283

293284
def test_request_validation_error(httpserver):
294285
"""Test that incorrect input raise a RequestPayloadValidationError."""
295-
296286
client = Client(base_url=f"http://localhost:{httpserver.port}")
297287
scim_client = SCIMClient(client, resource_types=(User,))
298288
with pytest.raises(
@@ -308,7 +298,6 @@ def test_request_validation_error(httpserver):
308298

309299
def test_request_network_error(httpserver):
310300
"""Test that httpx exceptions are transformed in RequestNetworkError."""
311-
312301
client = Client(base_url=f"http://localhost:{httpserver.port}")
313302
scim_client = SCIMClient(client, resource_types=(User,))
314303
user_request = User(user_name="[email protected]")

tests/test_delete.py

-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
def test_delete_user(httpserver):
1313
"""Nominal case for a User deletion."""
14-
1514
httpserver.expect_request(
1615
"/Users/2819c223-7f76-453a-919d-413861904646", method="DELETE"
1716
).respond_with_data(status=204, content_type="application/scim+json")
@@ -25,7 +24,6 @@ def test_delete_user(httpserver):
2524
@pytest.mark.parametrize("code", [400, 401, 403, 404, 412, 500, 501])
2625
def test_errors(httpserver, code):
2726
"""Test error cases defined in RFC7644."""
28-
2927
httpserver.expect_request(
3028
"/Users/2819c223-7f76-453a-919d-413861904646", method="DELETE"
3129
).respond_with_json(
@@ -51,7 +49,6 @@ def test_errors(httpserver, code):
5149
def test_invalid_resource_type(httpserver):
5250
"""Test that resource_types passed to the method must be part of
5351
SCIMClient.resource_types."""
54-
5552
client = Client(base_url=f"http://localhost:{httpserver.port}")
5653
scim_client = SCIMClient(client, resource_types=(User,))
5754
with pytest.raises(SCIMRequestError, match=r"Unknown resource type"):
@@ -60,7 +57,6 @@ def test_invalid_resource_type(httpserver):
6057

6158
def test_dont_check_response_payload(httpserver):
6259
"""Test the check_response_payload attribute."""
63-
6460
httpserver.expect_request(
6561
"/Users/2819c223-7f76-453a-919d-413861904646", method="DELETE"
6662
).respond_with_json(
@@ -86,7 +82,6 @@ def test_dont_check_response_payload(httpserver):
8682

8783
def test_request_network_error(httpserver):
8884
"""Test that httpx exceptions are transformed in RequestNetworkError."""
89-
9085
client = Client(base_url=f"http://localhost:{httpserver.port}")
9186
scim_client = SCIMClient(client, resource_types=(User,))
9287
with pytest.raises(

0 commit comments

Comments
 (0)