scim2-client 0.2.2__tar.gz → 0.3.0__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.2.2 → scim2_client-0.3.0}/.github/workflows/tests.yaml +3 -1
- {scim2_client-0.2.2 → scim2_client-0.3.0}/.pre-commit-config.yaml +2 -2
- {scim2_client-0.2.2 → scim2_client-0.3.0}/PKG-INFO +11 -7
- {scim2_client-0.2.2 → scim2_client-0.3.0}/README.md +6 -5
- {scim2_client-0.2.2 → scim2_client-0.3.0}/doc/changelog.rst +21 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/doc/conf.py +1 -0
- scim2_client-0.3.0/doc/reference.rst +14 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/doc/tutorial.rst +27 -11
- {scim2_client-0.2.2 → scim2_client-0.3.0}/pyproject.toml +21 -4
- {scim2_client-0.2.2 → scim2_client-0.3.0}/scim2_client/__init__.py +4 -2
- scim2_client-0.3.0/scim2_client/client.py +995 -0
- scim2_client-0.3.0/scim2_client/engines/httpx.py +430 -0
- scim2_client-0.3.0/scim2_client/engines/werkzeug.py +245 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/scim2_client/errors.py +8 -5
- scim2_client-0.3.0/tests/__init__.py +0 -0
- scim2_client-0.3.0/tests/engines/__init__.py +0 -0
- scim2_client-0.3.0/tests/engines/test_httpx.py +111 -0
- scim2_client-0.3.0/tests/engines/test_werkzeug.py +63 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/tests/test_create.py +16 -16
- {scim2_client-0.2.2 → scim2_client-0.3.0}/tests/test_delete.py +8 -8
- {scim2_client-0.2.2 → scim2_client-0.3.0}/tests/test_query.py +44 -44
- {scim2_client-0.2.2 → scim2_client-0.3.0}/tests/test_replace.py +13 -13
- {scim2_client-0.2.2 → scim2_client-0.3.0}/tests/test_search.py +12 -12
- {scim2_client-0.2.2 → scim2_client-0.3.0}/tests/test_utils.py +2 -2
- {scim2_client-0.2.2 → scim2_client-0.3.0}/uv.lock +337 -208
- scim2_client-0.2.2/doc/reference.rst +0 -6
- scim2_client-0.2.2/scim2_client/client.py +0 -687
- {scim2_client-0.2.2 → scim2_client-0.3.0}/.github/FUNDING.yml +0 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/.github/workflows/release.yml +0 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/.gitignore +0 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/.readthedocs.yml +0 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/LICENSE.md +0 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/doc/__init__.py +0 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/doc/contributing.rst +0 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/doc/index.rst +0 -0
- {scim2_client-0.2.2/tests → scim2_client-0.3.0/scim2_client/engines}/__init__.py +0 -0
- {scim2_client-0.2.2 → scim2_client-0.3.0}/scim2_client/py.typed +0 -0
|
@@ -31,6 +31,8 @@ jobs:
|
|
|
31
31
|
enable-cache: true
|
|
32
32
|
- name: Install Python ${{ matrix.python }}
|
|
33
33
|
run: uv python install ${{ matrix.python }}
|
|
34
|
+
- name: Install dependencies
|
|
35
|
+
run: uv sync --all-extras
|
|
34
36
|
- name: Run tests
|
|
35
37
|
run: uv run pytest --showlocals
|
|
36
38
|
|
|
@@ -44,7 +46,7 @@ jobs:
|
|
|
44
46
|
with:
|
|
45
47
|
enable-cache: true
|
|
46
48
|
- name: Install minimum dependencies
|
|
47
|
-
run: uv sync --resolution=lowest-direct
|
|
49
|
+
run: uv sync --resolution=lowest-direct --all-extras
|
|
48
50
|
- name: Run tests
|
|
49
51
|
run: uv run pytest --showlocals
|
|
50
52
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
repos:
|
|
3
3
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
4
|
-
rev: 'v0.
|
|
4
|
+
rev: 'v0.8.0'
|
|
5
5
|
hooks:
|
|
6
6
|
- id: ruff
|
|
7
7
|
args: [--fix, --exit-non-zero-on-fix]
|
|
@@ -16,7 +16,7 @@ repos:
|
|
|
16
16
|
exclude: "\\.svg$|\\.map$|\\.min\\.css$|\\.min\\.js$|\\.po$|\\.pot$"
|
|
17
17
|
- id: check-toml
|
|
18
18
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
19
|
-
rev: v1.
|
|
19
|
+
rev: v1.13.0
|
|
20
20
|
hooks:
|
|
21
21
|
- id: mypy
|
|
22
22
|
additional_dependencies: [pydantic]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: scim2-client
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Pythonically build SCIM requests and parse SCIM responses
|
|
5
5
|
Project-URL: documentation, https://scim2-client.readthedocs.io
|
|
6
6
|
Project-URL: repository, https://github.com/python-scim/scim2-client
|
|
@@ -222,15 +222,19 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
222
222
|
Classifier: Programming Language :: Python :: 3.13
|
|
223
223
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
224
224
|
Requires-Python: >=3.9
|
|
225
|
-
Requires-Dist: httpx>=0.24.0
|
|
226
225
|
Requires-Dist: scim2-models>=0.2.0
|
|
226
|
+
Provides-Extra: httpx
|
|
227
|
+
Requires-Dist: httpx>=0.28.0; extra == 'httpx'
|
|
228
|
+
Provides-Extra: werkzeug
|
|
229
|
+
Requires-Dist: werkzeug>=3.1.3; extra == 'werkzeug'
|
|
227
230
|
Description-Content-Type: text/markdown
|
|
228
231
|
|
|
229
232
|
# scim2-client
|
|
230
233
|
|
|
231
|
-
A SCIM client Python library built upon [scim2-models](https://scim2-models.readthedocs.io)
|
|
234
|
+
A SCIM client Python library built upon [scim2-models](https://scim2-models.readthedocs.io) ,
|
|
232
235
|
that pythonically build requests and parse responses,
|
|
233
236
|
following the [RFC7643](https://datatracker.ietf.org/doc/html/rfc7643.html) and [RFC7644](https://datatracker.ietf.org/doc/html/rfc7644.html) specifications.
|
|
237
|
+
You can use whatever request engine you prefer to perform network requests, but scim2-models comes with [httpx](https://github.com/encode/httpx) support.
|
|
234
238
|
|
|
235
239
|
It aims to be used in SCIM client applications, or in unit tests for SCIM server applications.
|
|
236
240
|
|
|
@@ -244,7 +248,7 @@ It allows users and groups creations, modifications and deletions to be synchron
|
|
|
244
248
|
## Installation
|
|
245
249
|
|
|
246
250
|
```shell
|
|
247
|
-
pip install scim2-client
|
|
251
|
+
pip install scim2-client[httpx]
|
|
248
252
|
```
|
|
249
253
|
|
|
250
254
|
## Usage
|
|
@@ -257,10 +261,10 @@ Here is an example of usage:
|
|
|
257
261
|
import datetime
|
|
258
262
|
from httpx import Client
|
|
259
263
|
from scim2_models import User, EnterpriseUser, Group, Error
|
|
260
|
-
from scim2_client import
|
|
264
|
+
from scim2_client.engines.httpx import SyncSCIMClient
|
|
261
265
|
|
|
262
|
-
client = Client(base_url=
|
|
263
|
-
scim =
|
|
266
|
+
client = Client(base_url="https://auth.example/scim/v2", headers={"Authorization": "Bearer foobar"})
|
|
267
|
+
scim = SyncSCIMClient(client, resource_types=(User[EnterpriseUser], Group))
|
|
264
268
|
|
|
265
269
|
# Query resources
|
|
266
270
|
user = scim.query(User[EnterpriseUser], "2819c223-7f76-453a-919d-413861904646")
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# scim2-client
|
|
2
2
|
|
|
3
|
-
A SCIM client Python library built upon [scim2-models](https://scim2-models.readthedocs.io)
|
|
3
|
+
A SCIM client Python library built upon [scim2-models](https://scim2-models.readthedocs.io) ,
|
|
4
4
|
that pythonically build requests and parse responses,
|
|
5
5
|
following the [RFC7643](https://datatracker.ietf.org/doc/html/rfc7643.html) and [RFC7644](https://datatracker.ietf.org/doc/html/rfc7644.html) specifications.
|
|
6
|
+
You can use whatever request engine you prefer to perform network requests, but scim2-models comes with [httpx](https://github.com/encode/httpx) support.
|
|
6
7
|
|
|
7
8
|
It aims to be used in SCIM client applications, or in unit tests for SCIM server applications.
|
|
8
9
|
|
|
@@ -16,7 +17,7 @@ It allows users and groups creations, modifications and deletions to be synchron
|
|
|
16
17
|
## Installation
|
|
17
18
|
|
|
18
19
|
```shell
|
|
19
|
-
pip install scim2-client
|
|
20
|
+
pip install scim2-client[httpx]
|
|
20
21
|
```
|
|
21
22
|
|
|
22
23
|
## Usage
|
|
@@ -29,10 +30,10 @@ Here is an example of usage:
|
|
|
29
30
|
import datetime
|
|
30
31
|
from httpx import Client
|
|
31
32
|
from scim2_models import User, EnterpriseUser, Group, Error
|
|
32
|
-
from scim2_client import
|
|
33
|
+
from scim2_client.engines.httpx import SyncSCIMClient
|
|
33
34
|
|
|
34
|
-
client = Client(base_url=
|
|
35
|
-
scim =
|
|
35
|
+
client = Client(base_url="https://auth.example/scim/v2", headers={"Authorization": "Bearer foobar"})
|
|
36
|
+
scim = SyncSCIMClient(client, resource_types=(User[EnterpriseUser], Group))
|
|
36
37
|
|
|
37
38
|
# Query resources
|
|
38
39
|
user = scim.query(User[EnterpriseUser], "2819c223-7f76-453a-919d-413861904646")
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
[0.3.0] - 2024-11-29
|
|
5
|
+
--------------------
|
|
6
|
+
|
|
7
|
+
.. warning::
|
|
8
|
+
|
|
9
|
+
This version comes with breaking changes:
|
|
10
|
+
|
|
11
|
+
- `httpx` is no longer a direct dependency, it is shipped in the `httpx` packaging extra.
|
|
12
|
+
- ``scim2_client.SCIMClient`` has moved to ``scim2_client.engines.httpx.SyncSCIMClient``.
|
|
13
|
+
- The ``resource_types`` parameters has been renamed ``resource_models``.
|
|
14
|
+
|
|
15
|
+
Added
|
|
16
|
+
^^^^^
|
|
17
|
+
- The `Unknown resource type` request error keeps a reference to the faulty payload.
|
|
18
|
+
- New `werkzeug` request engine for application development purpose.
|
|
19
|
+
- New `AsyncSCIMClient` request engine. :issue:`1`
|
|
20
|
+
|
|
21
|
+
Changed
|
|
22
|
+
^^^^^^^
|
|
23
|
+
- Separate httpx network code and SCIM code in separate file as a basis for async support (and maybe other request engines).
|
|
24
|
+
|
|
4
25
|
[0.2.2] - 2024-11-12
|
|
5
26
|
--------------------
|
|
6
27
|
|
|
@@ -42,6 +42,7 @@ toctree_collapse = False
|
|
|
42
42
|
intersphinx_mapping = {
|
|
43
43
|
"python": ("https://docs.python.org/3", None),
|
|
44
44
|
"scim2_models": ("https://scim2-models.readthedocs.io/en/latest/", None),
|
|
45
|
+
"werkzeug": ("https://werkzeug.palletsprojects.com", None),
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
# -- Options for HTML output ----------------------------------------------
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Reference
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
.. automodule:: scim2_client.engines.httpx
|
|
5
|
+
:members:
|
|
6
|
+
:member-order: bysource
|
|
7
|
+
|
|
8
|
+
.. automodule:: scim2_client.engines.werkzeug
|
|
9
|
+
:members:
|
|
10
|
+
:member-order: bysource
|
|
11
|
+
|
|
12
|
+
.. automodule:: scim2_client
|
|
13
|
+
:members:
|
|
14
|
+
:member-order: bysource
|
|
@@ -4,18 +4,20 @@ Tutorial
|
|
|
4
4
|
Initialization
|
|
5
5
|
==============
|
|
6
6
|
|
|
7
|
-
scim2-client depends on `httpx <https://github.com/encode/httpx>`_ to perform network requests.
|
|
8
|
-
|
|
7
|
+
scim2-client depends on request engines such as `httpx <https://github.com/encode/httpx>`_ to perform network requests.
|
|
8
|
+
This tutorial demonstrate how to use scim2-client with httpx, and suppose you have installed the `httpx` extra for example with ``pip install scim2-models[httpx]``.
|
|
9
|
+
|
|
10
|
+
As a start you will need to instantiate a httpx :code:`Client` object that you can parameter as your will, and then pass it to a :class:`SCIM client <scim2_client.BaseSCIMClient>` object.
|
|
9
11
|
In addition to your SCIM server root endpoint, you will probably want to provide some authorization headers through the httpx :code:`Client` :code:`headers` parameter:
|
|
10
12
|
|
|
11
13
|
.. code-block:: python
|
|
12
14
|
|
|
13
15
|
from httpx import Client
|
|
14
16
|
from scim2_models import User, EnterpriseUserUser, Group
|
|
15
|
-
from scim2_client import
|
|
17
|
+
from scim2_client.engines.httpx import SyncSCIMClient
|
|
16
18
|
|
|
17
19
|
client = Client(base_url="https://auth.example/scim/v2", headers={"Authorization": "Bearer foobar"})
|
|
18
|
-
scim =
|
|
20
|
+
scim = SyncSCIMClient(client, resource_types=(User[EnterpriseUser], Group))
|
|
19
21
|
|
|
20
22
|
You need to give to indicate to :class:`~scim2_client.SCIMClient` all the different :class:`~scim2_models.Resource` types that you will need to manipulate with the :code:`resource_types` parameter.
|
|
21
23
|
This is needed so scim2-client will be able to guess which resource type to instante when an arbitrary payload is met.
|
|
@@ -31,11 +33,11 @@ Performing actions
|
|
|
31
33
|
scim2-client allows your application to interact with a SCIM server as described in :rfc:`RFC7644 §3 <7644#section-3>`, so you can read and manage the resources.
|
|
32
34
|
The following actions are available:
|
|
33
35
|
|
|
34
|
-
- :meth:`~scim2_client.
|
|
35
|
-
- :meth:`~scim2_client.
|
|
36
|
-
- :meth:`~scim2_client.
|
|
37
|
-
- :meth:`~scim2_client.
|
|
38
|
-
- :meth:`~scim2_client.
|
|
36
|
+
- :meth:`~scim2_client.BaseSCIMClient.create`
|
|
37
|
+
- :meth:`~scim2_client.BaseSCIMClient.query`
|
|
38
|
+
- :meth:`~scim2_client.BaseSCIMClient.replace`
|
|
39
|
+
- :meth:`~scim2_client.BaseSCIMClient.delete`
|
|
40
|
+
- :meth:`~scim2_client.BaseSCIMClient.search`
|
|
39
41
|
|
|
40
42
|
Have a look at the :doc:`reference` to see usage examples and the exhaustive set of parameters, but generally it looks like this:
|
|
41
43
|
|
|
@@ -58,7 +60,7 @@ Have a look at the :doc:`reference` to see usage examples and the exhaustive set
|
|
|
58
60
|
Request and response validation
|
|
59
61
|
===============================
|
|
60
62
|
|
|
61
|
-
By default, the data passed to the :class
|
|
63
|
+
By default, the data passed to the :class:`SCIM client <scim2_client.BaseSCIMClient>` as well as the server response will be validated against the SCIM specifications, and will raise an error if they don't respect them.
|
|
62
64
|
However sometimes you want to accept invalid inputs and outputs.
|
|
63
65
|
To achieve this, all the methods provide the following parameters, all are :data:`True` by default:
|
|
64
66
|
|
|
@@ -81,10 +83,24 @@ To achieve this, all the methods provide the following parameters, all are :data
|
|
|
81
83
|
which value will excluded from the request payload, and which values are
|
|
82
84
|
expected in the response payload.
|
|
83
85
|
|
|
86
|
+
Engines
|
|
87
|
+
=======
|
|
88
|
+
|
|
89
|
+
scim2-client comes with a light abstraction layers that allows for different requests engines.
|
|
90
|
+
Currently those engines are shipped:
|
|
91
|
+
|
|
92
|
+
- :class:`~scim2_client.engines.httpx.SyncSCIMClient`: A synchronous engine using `httpx <https://github.com/encode/httpx>`_ to perform the HTTP requests.
|
|
93
|
+
- :class:`~scim2_client.engines.httpx.AsyncSCIMClient`: An asynchronous engine using `httpx <https://github.com/encode/httpx>`_ to perform the HTTP requests. It has the very same API than its synchronous version, except it is asynchronous.
|
|
94
|
+
- :class:`~scim2_client.engines.werkzeug.TestSCIMClient`: A test engine for development purposes.
|
|
95
|
+
It takes a WSGI app and directly execute the server code instead of performing real HTTP requests.
|
|
96
|
+
This is faster in unit test suites, and helpful to catch the server exceptions.
|
|
97
|
+
|
|
98
|
+
You can easily implement your own engine by inheriting from :class:`~scim2_client.BaseSCIMClient`.
|
|
99
|
+
|
|
84
100
|
Additional request parameters
|
|
85
101
|
=============================
|
|
86
102
|
|
|
87
|
-
Any additional parameter will be passed to the underlying
|
|
103
|
+
Any additional parameter will be passed to the underlying engine methods.
|
|
88
104
|
This can be useful if you need to explicitly pass a certain URL for example:
|
|
89
105
|
|
|
90
106
|
.. code-block:: python
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scim2-client"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Pythonically build SCIM requests and parse SCIM responses"
|
|
9
9
|
authors = [{name="Yaal Coop", email="contact@yaal.coop"}]
|
|
10
10
|
license = {file = "LICENSE.md"}
|
|
@@ -27,10 +27,18 @@ classifiers = [
|
|
|
27
27
|
|
|
28
28
|
requires-python = ">= 3.9"
|
|
29
29
|
dependencies = [
|
|
30
|
-
"httpx>=0.24.0",
|
|
31
30
|
"scim2-models>=0.2.0",
|
|
32
31
|
]
|
|
33
32
|
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
httpx = [
|
|
35
|
+
"httpx>=0.28.0",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
werkzeug = [
|
|
39
|
+
"werkzeug>=3.1.3",
|
|
40
|
+
]
|
|
41
|
+
|
|
34
42
|
[project.urls]
|
|
35
43
|
documentation = "https://scim2-client.readthedocs.io"
|
|
36
44
|
repository = "https://github.com/python-scim/scim2-client"
|
|
@@ -39,12 +47,16 @@ funding = "https://github.com/sponsors/python-scim"
|
|
|
39
47
|
|
|
40
48
|
[dependency-groups]
|
|
41
49
|
dev = [
|
|
50
|
+
"mypy>=1.13.0",
|
|
51
|
+
"portpicker>=1.6.0",
|
|
42
52
|
"pre-commit-uv>=4.1.4",
|
|
43
53
|
"pytest>=8.2.1",
|
|
54
|
+
"pytest-asyncio>=0.24.0",
|
|
44
55
|
"pytest-coverage>=0.0",
|
|
45
|
-
"pytest-httpserver>=1.0
|
|
56
|
+
"pytest-httpserver>=1.1.0",
|
|
57
|
+
"scim2-server >= 0.1.2; python_version>='3.10'",
|
|
46
58
|
"tox-uv>=1.16.0",
|
|
47
|
-
"
|
|
59
|
+
"werkzeug>=3.1.3",
|
|
48
60
|
]
|
|
49
61
|
doc = [
|
|
50
62
|
"autodoc-pydantic>=2.2.0",
|
|
@@ -105,6 +117,10 @@ plugins = [
|
|
|
105
117
|
"pydantic.mypy"
|
|
106
118
|
]
|
|
107
119
|
|
|
120
|
+
[tool.pytest.ini_options]
|
|
121
|
+
asyncio_mode="auto"
|
|
122
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
123
|
+
|
|
108
124
|
[tool.tox]
|
|
109
125
|
requires = ["tox>=4.19"]
|
|
110
126
|
env_list = [
|
|
@@ -120,6 +136,7 @@ env_list = [
|
|
|
120
136
|
]
|
|
121
137
|
|
|
122
138
|
[tool.tox.env_run_base]
|
|
139
|
+
extras = ["httpx", "werkzeug"]
|
|
123
140
|
runner = "uv-venv-lock-runner"
|
|
124
141
|
dependency_groups = ["dev"]
|
|
125
142
|
commands = [
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from .client import
|
|
1
|
+
from .client import BaseSCIMClient
|
|
2
|
+
from .client import BaseSyncSCIMClient
|
|
2
3
|
from .errors import RequestNetworkError
|
|
3
4
|
from .errors import RequestPayloadValidationError
|
|
4
5
|
from .errors import ResponsePayloadValidationError
|
|
@@ -11,7 +12,8 @@ from .errors import UnexpectedContentType
|
|
|
11
12
|
from .errors import UnexpectedStatusCode
|
|
12
13
|
|
|
13
14
|
__all__ = [
|
|
14
|
-
"
|
|
15
|
+
"BaseSCIMClient",
|
|
16
|
+
"BaseSyncSCIMClient",
|
|
15
17
|
"SCIMClientError",
|
|
16
18
|
"SCIMRequestError",
|
|
17
19
|
"SCIMResponseError",
|