scim2-client 0.1.0__tar.gz → 0.1.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scim2-client
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Pythonically build SCIM requests and parse SCIM responses
5
5
  License: MIT
6
6
  Keywords: scim,scim2,provisioning,httpx,api
@@ -20,12 +20,14 @@ 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.0,<0.2.0)
23
+ Requires-Dist: scim2-models (>=0.1.1,<0.2.0)
24
24
  Description-Content-Type: text/markdown
25
25
 
26
26
  # scim2-client
27
27
 
28
- A SCIM client library built upon [scim2-models](https://scim2-models.readthedocs.io), that pythonically build requests and parse responses, following the [RFC7643](https://datatracker.ietf.org/doc/html/rfc7643.html) and [RFC7644](https://datatracker.ietf.org/doc/html/rfc7644.html) specifications.
28
+ A SCIM client Python library built upon [scim2-models](https://scim2-models.readthedocs.io) and [httpx](https://github.com/encode/httpx),
29
+ that pythonically build requests and parse responses,
30
+ following the [RFC7643](https://datatracker.ietf.org/doc/html/rfc7643.html) and [RFC7644](https://datatracker.ietf.org/doc/html/rfc7644.html) specifications.
29
31
  ## Installation
30
32
 
31
33
  ```shell
@@ -1,6 +1,8 @@
1
1
  # scim2-client
2
2
 
3
- A SCIM client library built upon [scim2-models](https://scim2-models.readthedocs.io), that pythonically build requests and parse responses, following the [RFC7643](https://datatracker.ietf.org/doc/html/rfc7643.html) and [RFC7644](https://datatracker.ietf.org/doc/html/rfc7644.html) specifications.
3
+ A SCIM client Python library built upon [scim2-models](https://scim2-models.readthedocs.io) and [httpx](https://github.com/encode/httpx),
4
+ that pythonically build requests and parse responses,
5
+ following the [RFC7643](https://datatracker.ietf.org/doc/html/rfc7643.html) and [RFC7644](https://datatracker.ietf.org/doc/html/rfc7644.html) specifications.
4
6
  ## Installation
5
7
 
6
8
  ```shell
@@ -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.0"
7
+ version = "0.1.1"
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.0"
30
+ scim2-models = "^0.1.1"
31
31
 
32
32
  [tool.poetry.group.doc]
33
33
  optional = true
@@ -10,6 +10,7 @@ from httpx import Client
10
10
  from httpx import Response
11
11
  from pydantic import ValidationError
12
12
  from scim2_models import AnyResource
13
+ from scim2_models import Context
13
14
  from scim2_models import Error
14
15
  from scim2_models import ListResponse
15
16
  from scim2_models import PatchOp
@@ -44,6 +45,7 @@ class SCIMClient:
44
45
  response: Response,
45
46
  expected_status_codes: List[int],
46
47
  expected_type: Optional[Type] = None,
48
+ scim_ctx: Optional[Context] = None,
47
49
  ):
48
50
  if response.status_code not in expected_status_codes:
49
51
  raise UnexpectedStatusCode(response)
@@ -77,7 +79,8 @@ class SCIMClient:
77
79
  pass
78
80
 
79
81
  if expected_type:
80
- return expected_type.model_validate(response_payload)
82
+ return expected_type.model_validate(response_payload, scim_ctx=scim_ctx)
83
+
81
84
  return response_payload
82
85
 
83
86
  def create(self, resource: AnyResource, **kwargs) -> Union[AnyResource, Error]:
@@ -95,7 +98,7 @@ class SCIMClient:
95
98
 
96
99
  self.check_resource_type(resource.__class__)
97
100
  url = self.resource_endpoint(resource.__class__)
98
- dump = resource.model_dump(exclude_none=True, by_alias=True, mode="json")
101
+ dump = resource.model_dump(scim_ctx=Context.RESOURCE_CREATION_REQUEST)
99
102
  response = self.client.post(url, json=dump, **kwargs)
100
103
 
101
104
  expected_status_codes = [
@@ -113,7 +116,12 @@ class SCIMClient:
113
116
  404,
114
117
  500,
115
118
  ]
116
- return self.check_response(response, expected_status_codes, resource.__class__)
119
+ return self.check_response(
120
+ response,
121
+ expected_status_codes,
122
+ resource.__class__,
123
+ scim_ctx=Context.RESOURCE_CREATION_RESPONSE,
124
+ )
117
125
 
118
126
  def query(
119
127
  self,
@@ -142,7 +150,8 @@ class SCIMClient:
142
150
  self.check_resource_type(resource_type)
143
151
  payload = (
144
152
  search_request.model_dump(
145
- by_alias=True, exclude_none=True, exclude_unset=True, mode="json"
153
+ exclude_unset=True,
154
+ scim_ctx=Context.RESOURCE_QUERY_REQUEST,
146
155
  )
147
156
  if search_request
148
157
  else None
@@ -171,7 +180,12 @@ class SCIMClient:
171
180
  500,
172
181
  ]
173
182
  response = self.client.get(url, params=payload, **kwargs)
174
- return self.check_response(response, expected_status_codes, expected_type)
183
+ return self.check_response(
184
+ response,
185
+ expected_status_codes,
186
+ expected_type,
187
+ scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
188
+ )
175
189
 
176
190
  def query_all(
177
191
  self,
@@ -196,7 +210,7 @@ class SCIMClient:
196
210
 
197
211
  payload = (
198
212
  search_request.model_dump(
199
- by_alias=True, exclude_none=True, exclude_unset=True, mode="json"
213
+ exclude_unset=True, scim_ctx=Context.RESOURCE_QUERY_REQUEST
200
214
  )
201
215
  if search_request
202
216
  else None
@@ -220,7 +234,10 @@ class SCIMClient:
220
234
  ]
221
235
 
222
236
  return self.check_response(
223
- response, expected_status_codes, ListResponse[Union[self.resource_types]]
237
+ response,
238
+ expected_status_codes,
239
+ ListResponse[Union[self.resource_types]],
240
+ scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
224
241
  )
225
242
 
226
243
  def search(
@@ -244,7 +261,7 @@ class SCIMClient:
244
261
 
245
262
  payload = (
246
263
  search_request.model_dump(
247
- by_alias=True, exclude_none=True, exclude_unset=True, mode="json"
264
+ exclude_unset=True, scim_ctx=Context.RESOURCE_QUERY_RESPONSE
248
265
  )
249
266
  if search_request
250
267
  else None
@@ -269,7 +286,10 @@ class SCIMClient:
269
286
  501,
270
287
  ]
271
288
  return self.check_response(
272
- response, expected_status_codes, ListResponse[Union[self.resource_types]]
289
+ response,
290
+ expected_status_codes,
291
+ ListResponse[Union[self.resource_types]],
292
+ scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
273
293
  )
274
294
 
275
295
  def delete(self, resource_type: Type, id: str, **kwargs) -> Optional[Error]:
@@ -323,7 +343,7 @@ class SCIMClient:
323
343
  if not resource.id:
324
344
  raise Exception("Resource must have an id")
325
345
 
326
- dump = resource.model_dump(exclude_none=True, by_alias=True, mode="json")
346
+ dump = resource.model_dump(scim_ctx=Context.RESOURCE_REPLACEMENT_REQUEST)
327
347
  url = self.resource_endpoint(resource.__class__) + f"/{resource.id}"
328
348
  response = self.client.put(url, json=dump, **kwargs)
329
349
 
@@ -344,7 +364,12 @@ class SCIMClient:
344
364
  500,
345
365
  501,
346
366
  ]
347
- return self.check_response(response, expected_status_codes, resource.__class__)
367
+ return self.check_response(
368
+ response,
369
+ expected_status_codes,
370
+ resource.__class__,
371
+ scim_ctx=Context.RESOURCE_REPLACEMENT_RESPONSE,
372
+ )
348
373
 
349
374
  def modify(
350
375
  self, resource: AnyResource, op: PatchOp, **kwargs