scim2-cli 0.6.0__tar.gz → 0.7.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.
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/PKG-INFO +7 -4
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/README.md +2 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/pyproject.toml +6 -4
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/pyproject.toml.orig +6 -4
- scim2_cli-0.7.1/scim2_cli/test.py +124 -0
- scim2_cli-0.6.0/scim2_cli/test.py +0 -56
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/LICENSE.md +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/__init__.py +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/bulk.py +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/create.py +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/delete.py +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/modify.py +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/py.typed +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/query.py +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/replace.py +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/search.py +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/session.py +0 -0
- {scim2_cli-0.6.0 → scim2_cli-0.7.1}/scim2_cli/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: scim2-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: SCIM application development CLI
|
|
5
5
|
Keywords: scim,scim2,provisioning,rfc7643,rfc7644
|
|
6
6
|
Author: Yaal Coop
|
|
@@ -207,19 +207,20 @@ License: Apache License
|
|
|
207
207
|
See the License for the specific language governing permissions and
|
|
208
208
|
limitations under the License.
|
|
209
209
|
Classifier: Intended Audience :: Developers
|
|
210
|
-
Classifier: Development Status ::
|
|
210
|
+
Classifier: Development Status :: 4 - Beta
|
|
211
211
|
Classifier: Programming Language :: Python :: 3.11
|
|
212
212
|
Classifier: Programming Language :: Python :: 3.12
|
|
213
213
|
Classifier: Programming Language :: Python :: 3.13
|
|
214
214
|
Classifier: Programming Language :: Python :: 3.14
|
|
215
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
215
216
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
216
217
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
217
218
|
Classifier: Environment :: Web Environment
|
|
218
219
|
Classifier: Programming Language :: Python
|
|
219
220
|
Classifier: Operating System :: OS Independent
|
|
220
221
|
Requires-Dist: click>=8.5.0
|
|
221
|
-
Requires-Dist: scim2-client[httpx2]>=0.
|
|
222
|
-
Requires-Dist: scim2-tester>=0.
|
|
222
|
+
Requires-Dist: scim2-client[httpx2]>=0.14.0
|
|
223
|
+
Requires-Dist: scim2-tester>=0.6.4
|
|
223
224
|
Requires-Dist: sphinx-click-rst-to-ansi-formatter>=0.2.0
|
|
224
225
|
Requires-Dist: pydanclick>=0.5.0
|
|
225
226
|
Requires-Dist: pygments>=2.18.0
|
|
@@ -230,6 +231,8 @@ Project-URL: changelog, https://scim2-cli.readthedocs.io/en/latest/changelog.htm
|
|
|
230
231
|
Project-URL: funding, https://github.com/sponsors/python-scim
|
|
231
232
|
Description-Content-Type: text/markdown
|
|
232
233
|
|
|
234
|
+
<img alt="python-scim logo" src="https://raw.githubusercontent.com/python-scim/.github/refs/heads/main/python-scim.svg" height="72" align="right">
|
|
235
|
+
|
|
233
236
|
# scim2-cli
|
|
234
237
|
|
|
235
238
|
An utility command line to help you perform requests against a SCIM server, while validating input and response payloads. It also uses [scim2-tester](https://scim2-tester.readthedocs.io) to perform a [SCIM server compliance test](https://scim2-cli.readthedocs.io/en/latest/reference.html#scim-url-test).
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<img alt="python-scim logo" src="https://raw.githubusercontent.com/python-scim/.github/refs/heads/main/python-scim.svg" height="72" align="right">
|
|
2
|
+
|
|
1
3
|
# scim2-cli
|
|
2
4
|
|
|
3
5
|
An utility command line to help you perform requests against a SCIM server, while validating input and response payloads. It also uses [scim2-tester](https://scim2-tester.readthedocs.io) to perform a [SCIM server compliance test](https://scim2-cli.readthedocs.io/en/latest/reference.html#scim-url-test).
|
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scim2-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.7.1"
|
|
8
8
|
description = "SCIM application development CLI"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
keywords = [
|
|
@@ -16,11 +16,12 @@ keywords = [
|
|
|
16
16
|
]
|
|
17
17
|
classifiers = [
|
|
18
18
|
"Intended Audience :: Developers",
|
|
19
|
-
"Development Status ::
|
|
19
|
+
"Development Status :: 4 - Beta",
|
|
20
20
|
"Programming Language :: Python :: 3.11",
|
|
21
21
|
"Programming Language :: Python :: 3.12",
|
|
22
22
|
"Programming Language :: Python :: 3.13",
|
|
23
23
|
"Programming Language :: Python :: 3.14",
|
|
24
|
+
"Programming Language :: Python :: 3.15",
|
|
24
25
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
25
26
|
"License :: OSI Approved :: Apache Software License",
|
|
26
27
|
"Environment :: Web Environment",
|
|
@@ -30,8 +31,8 @@ classifiers = [
|
|
|
30
31
|
requires-python = ">= 3.11"
|
|
31
32
|
dependencies = [
|
|
32
33
|
"click>=8.5.0",
|
|
33
|
-
"scim2-client[httpx2]>=0.
|
|
34
|
-
"scim2-tester>=0.
|
|
34
|
+
"scim2-client[httpx2]>=0.14.0",
|
|
35
|
+
"scim2-tester>=0.6.4",
|
|
35
36
|
"sphinx-click-rst-to-ansi-formatter>=0.2.0",
|
|
36
37
|
"pydanclick>=0.5.0",
|
|
37
38
|
"pygments>=2.18.0",
|
|
@@ -161,6 +162,7 @@ env_list = [
|
|
|
161
162
|
"py312",
|
|
162
163
|
"py313",
|
|
163
164
|
"py314",
|
|
165
|
+
"py315",
|
|
164
166
|
"minversions",
|
|
165
167
|
"doc",
|
|
166
168
|
"bundle",
|
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scim2-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.7.1"
|
|
8
8
|
description = "SCIM application development CLI"
|
|
9
9
|
authors = [{name="Yaal Coop", email="contact@yaal.coop"}]
|
|
10
10
|
license = {file = "LICENSE.md"}
|
|
@@ -12,11 +12,12 @@ readme = "README.md"
|
|
|
12
12
|
keywords = ["scim", "scim2", "provisioning", "rfc7643", "rfc7644"]
|
|
13
13
|
classifiers = [
|
|
14
14
|
"Intended Audience :: Developers",
|
|
15
|
-
"Development Status ::
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
16
|
"Programming Language :: Python :: 3.11",
|
|
17
17
|
"Programming Language :: Python :: 3.12",
|
|
18
18
|
"Programming Language :: Python :: 3.13",
|
|
19
19
|
"Programming Language :: Python :: 3.14",
|
|
20
|
+
"Programming Language :: Python :: 3.15",
|
|
20
21
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
21
22
|
"License :: OSI Approved :: Apache Software License",
|
|
22
23
|
"Environment :: Web Environment",
|
|
@@ -27,8 +28,8 @@ classifiers = [
|
|
|
27
28
|
requires-python = ">= 3.11"
|
|
28
29
|
dependencies = [
|
|
29
30
|
"click>=8.5.0",
|
|
30
|
-
"scim2-client[httpx2]>=0.
|
|
31
|
-
"scim2-tester>=0.
|
|
31
|
+
"scim2-client[httpx2]>=0.14.0",
|
|
32
|
+
"scim2-tester>=0.6.4",
|
|
32
33
|
"sphinx-click-rst-to-ansi-formatter>=0.2.0",
|
|
33
34
|
"pydanclick>=0.5.0",
|
|
34
35
|
"pygments>=2.18.0",
|
|
@@ -148,6 +149,7 @@ env_list = [
|
|
|
148
149
|
"py312",
|
|
149
150
|
"py313",
|
|
150
151
|
"py314",
|
|
152
|
+
"py315",
|
|
151
153
|
"minversions",
|
|
152
154
|
"doc",
|
|
153
155
|
"bundle",
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import secrets
|
|
2
|
+
import sys
|
|
3
|
+
from collections import Counter
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from scim2_tester import Outcome
|
|
7
|
+
from scim2_tester import Status
|
|
8
|
+
from scim2_tester import iter_check_server
|
|
9
|
+
from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter
|
|
10
|
+
|
|
11
|
+
from .utils import DOC_URL
|
|
12
|
+
from .utils import Color
|
|
13
|
+
from .utils import escape_control_characters
|
|
14
|
+
|
|
15
|
+
OUTCOME_COLORS = {
|
|
16
|
+
Outcome.PASSED: Color.green,
|
|
17
|
+
Outcome.WARNING: Color.yellow,
|
|
18
|
+
Outcome.FAILED: Color.red,
|
|
19
|
+
Outcome.SKIPPED: Color.bright_black,
|
|
20
|
+
}
|
|
21
|
+
OUTCOME_LABELS = {
|
|
22
|
+
Outcome.PASSED: ("passed", "passed"),
|
|
23
|
+
Outcome.WARNING: ("warning", "warnings"),
|
|
24
|
+
Outcome.FAILED: ("failed", "failed"),
|
|
25
|
+
Outcome.SKIPPED: ("skipped", "skipped"),
|
|
26
|
+
}
|
|
27
|
+
STATUS_WIDTH = max(len(status.name) for status in Status)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def summary(outcomes: Counter[Outcome], seed: int) -> str:
|
|
31
|
+
"""Count the results of each outcome, in the order of the outcomes."""
|
|
32
|
+
counts = []
|
|
33
|
+
for outcome in Outcome:
|
|
34
|
+
count = outcomes[outcome]
|
|
35
|
+
if not count:
|
|
36
|
+
continue
|
|
37
|
+
singular, plural = OUTCOME_LABELS[outcome]
|
|
38
|
+
counts.append(f"{count} {plural if count > 1 else singular}")
|
|
39
|
+
return f"{', '.join(counts) or 'no checks ran'} (seed {seed})"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="test")
|
|
43
|
+
@click.pass_context
|
|
44
|
+
@click.option(
|
|
45
|
+
"-v",
|
|
46
|
+
"--verbose",
|
|
47
|
+
count=True,
|
|
48
|
+
help="Show every result with its reason. Pass it twice to also show the data.",
|
|
49
|
+
)
|
|
50
|
+
@click.option(
|
|
51
|
+
"--check-status-code/--dont-check-status-code",
|
|
52
|
+
is_flag=True,
|
|
53
|
+
default=True,
|
|
54
|
+
help="Fail on unexpected return codes.",
|
|
55
|
+
)
|
|
56
|
+
@click.option(
|
|
57
|
+
"--check-content-type/--dont-check-content-type",
|
|
58
|
+
is_flag=True,
|
|
59
|
+
default=True,
|
|
60
|
+
help="Fail on unexpected content types.",
|
|
61
|
+
)
|
|
62
|
+
@click.option(
|
|
63
|
+
"--strict",
|
|
64
|
+
is_flag=True,
|
|
65
|
+
help="Fail on deviations from the recommendations of the RFCs.",
|
|
66
|
+
)
|
|
67
|
+
@click.option(
|
|
68
|
+
"--seed",
|
|
69
|
+
type=int,
|
|
70
|
+
help="Send the same generated values as the run that printed this seed.",
|
|
71
|
+
)
|
|
72
|
+
def test_cli(
|
|
73
|
+
ctx: click.Context,
|
|
74
|
+
verbose: int,
|
|
75
|
+
check_status_code: bool,
|
|
76
|
+
check_content_type: bool,
|
|
77
|
+
strict: bool,
|
|
78
|
+
seed: int | None,
|
|
79
|
+
) -> None:
|
|
80
|
+
"""Perform a server SCIM compliance check using :doc:`scim2-tester <scim2_tester:index>`.
|
|
81
|
+
|
|
82
|
+
.. code-block:: bash
|
|
83
|
+
|
|
84
|
+
test
|
|
85
|
+
"""
|
|
86
|
+
client = ctx.obj.client
|
|
87
|
+
client.check_response_status_codes = check_status_code
|
|
88
|
+
client.check_response_content_type = check_content_type
|
|
89
|
+
if seed is None:
|
|
90
|
+
seed = secrets.randbelow(2**32)
|
|
91
|
+
click.echo(f"Performing a SCIM compliance check on {client.client.base_url} ...")
|
|
92
|
+
results = iter_check_server(client, seed=seed)
|
|
93
|
+
failed = False
|
|
94
|
+
outcomes: Counter[Outcome] = Counter()
|
|
95
|
+
for result in results:
|
|
96
|
+
outcome = result.status.outcome
|
|
97
|
+
outcomes[outcome] += 1
|
|
98
|
+
if outcome is Outcome.FAILED or (strict and outcome is Outcome.WARNING):
|
|
99
|
+
failed = True
|
|
100
|
+
if not verbose and outcome in (Outcome.PASSED, Outcome.SKIPPED):
|
|
101
|
+
continue
|
|
102
|
+
status = click.style(
|
|
103
|
+
result.status.name.ljust(STATUS_WIDTH), fg=OUTCOME_COLORS[outcome]
|
|
104
|
+
)
|
|
105
|
+
label = " ".join(
|
|
106
|
+
escape_control_characters(part)
|
|
107
|
+
for part in (result.title, result.resource_type, result.attribute)
|
|
108
|
+
if part
|
|
109
|
+
)
|
|
110
|
+
click.echo(f"{status} {label}")
|
|
111
|
+
|
|
112
|
+
if result.reason:
|
|
113
|
+
click.echo(f" {escape_control_characters(result.reason)}")
|
|
114
|
+
if verbose > 1 and result.data:
|
|
115
|
+
click.echo(f" {escape_control_characters(result.data)}")
|
|
116
|
+
|
|
117
|
+
if failed:
|
|
118
|
+
color = Color.red
|
|
119
|
+
elif outcomes[Outcome.WARNING] or not outcomes:
|
|
120
|
+
color = Color.yellow
|
|
121
|
+
else:
|
|
122
|
+
color = Color.green
|
|
123
|
+
click.secho(summary(outcomes, seed), fg=color)
|
|
124
|
+
sys.exit(1 if failed else 0)
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
|
|
3
|
-
import click
|
|
4
|
-
from scim2_tester import Status
|
|
5
|
-
from scim2_tester import check_server
|
|
6
|
-
from sphinx_click.rst_to_ansi_formatter import make_rst_to_ansi_formatter
|
|
7
|
-
|
|
8
|
-
from .utils import DOC_URL
|
|
9
|
-
from .utils import Color
|
|
10
|
-
from .utils import escape_control_characters
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@click.command(cls=make_rst_to_ansi_formatter(DOC_URL), name="test")
|
|
14
|
-
@click.pass_context
|
|
15
|
-
@click.option("-v", "--verbose", is_flag=True, help="Enables verbose mode")
|
|
16
|
-
@click.option(
|
|
17
|
-
"--check-status-code/--dont-check-status-code",
|
|
18
|
-
is_flag=True,
|
|
19
|
-
default=True,
|
|
20
|
-
help="Fail on unexpected return codes.",
|
|
21
|
-
)
|
|
22
|
-
@click.option(
|
|
23
|
-
"--check-content-type/--dont-check-content-type",
|
|
24
|
-
is_flag=True,
|
|
25
|
-
default=True,
|
|
26
|
-
help="Fail on unexpected content types.",
|
|
27
|
-
)
|
|
28
|
-
def test_cli(
|
|
29
|
-
ctx: click.Context, verbose: bool, check_status_code: bool, check_content_type: bool
|
|
30
|
-
) -> None:
|
|
31
|
-
"""Perform a server SCIM compliance check using :doc:`scim2-tester <scim2_tester:index>`.
|
|
32
|
-
|
|
33
|
-
.. code-block:: bash
|
|
34
|
-
|
|
35
|
-
test
|
|
36
|
-
"""
|
|
37
|
-
client = ctx.obj.client
|
|
38
|
-
client.check_response_status_codes = check_status_code
|
|
39
|
-
client.check_response_content_type = check_content_type
|
|
40
|
-
results = check_server(client)
|
|
41
|
-
click.echo(f"Performing a SCIM compliance check on {client.client.base_url} ...")
|
|
42
|
-
success = True
|
|
43
|
-
for result in results:
|
|
44
|
-
if result.status == Status.SUCCESS:
|
|
45
|
-
status = click.style(result.status.name, fg=Color.green)
|
|
46
|
-
else:
|
|
47
|
-
status = click.style(result.status.name, fg=Color.red)
|
|
48
|
-
success = False
|
|
49
|
-
click.echo(f"{status} {escape_control_characters(result.title)}")
|
|
50
|
-
|
|
51
|
-
if result.reason:
|
|
52
|
-
click.echo(f" {escape_control_characters(result.reason)}")
|
|
53
|
-
if verbose and result.data:
|
|
54
|
-
click.echo(f" {escape_control_characters(result.data)}")
|
|
55
|
-
|
|
56
|
-
sys.exit(0 if success else 1)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|