Skip to content

Commit 3493015

Browse files
authored
Merge pull request #8 from python-scim/python3.10
Python 3.10 support
2 parents 3a9d459 + 5a598a6 commit 3493015

File tree

9 files changed

+107
-11
lines changed

9 files changed

+107
-11
lines changed

.github/workflows/tests.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
- '3.13'
2222
- '3.12'
2323
- '3.11'
24+
- '3.10'
2425
steps:
2526
- uses: actions/checkout@v4
2627
- name: Install uv

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ keywords = ["scim", "scim2", "provisioning", "rfc7643", "rfc7644"]
1616
classifiers = [
1717
"Intended Audience :: Developers",
1818
"Development Status :: 4 - Beta",
19+
"Programming Language :: Python :: 3.10",
1920
"Programming Language :: Python :: 3.11",
2021
"Programming Language :: Python :: 3.12",
2122
"Programming Language :: Python :: 3.13",
@@ -26,7 +27,7 @@ classifiers = [
2627
"Operating System :: OS Independent",
2728
]
2829

29-
requires-python = ">= 3.11"
30+
requires-python = ">= 3.10"
3031
dependencies = [
3132
"scim2-filter-parser>=0.7.0",
3233
"scim2-models>=0.2.4",
@@ -106,6 +107,7 @@ doctest_optionflags= "ALLOW_UNICODE IGNORE_EXCEPTION_DETAIL ELLIPSIS"
106107
requires = ["tox>=4.19"]
107108
env_list = [
108109
"style",
110+
"py310",
109111
"py311",
110112
"py312",
111113
"py313",

scim2_server/backend.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def register_resource_type(self, resource_type: ResourceType):
8282
self.models_dict[resource_type.id] = Resource.from_schema(base_schema)
8383
if extensions:
8484
self.models_dict[resource_type.id] = self.models_dict[resource_type.id][
85-
Union[*extensions]
85+
Union[tuple(extensions)] # noqa: UP007
8686
]
8787

8888
def get_resource_types(self):
@@ -332,7 +332,7 @@ def create_resource(
332332
) -> Resource | None:
333333
resource = resource.model_copy(deep=True)
334334
resource.id = uuid.uuid4().hex
335-
utcnow = datetime.datetime.now(datetime.UTC)
335+
utcnow = datetime.datetime.now(datetime.timezone.utc)
336336
resource.meta = Meta(
337337
resource_type=self.resource_types[resource_type_id].name,
338338
created=utcnow,
@@ -374,7 +374,9 @@ def update_resource(
374374
updated_resource = self.models_dict[resource_type_id].model_validate(
375375
resource.model_dump()
376376
)
377-
self._touch_resource(updated_resource, datetime.datetime.now(datetime.UTC))
377+
self._touch_resource(
378+
updated_resource, datetime.datetime.now(datetime.timezone.utc)
379+
)
378380

379381
for unique_attribute in self.unique_attributes[resource_type_id]:
380382
new_value = unique_attribute.get_attribute(updated_resource)

scim2_server/provider.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ def query_resource(self, request: Request, resource: ResourceType | None):
311311
for s in results
312312
]
313313

314-
return ListResponse[Union[*self.backend.get_models()]](
314+
return ListResponse[Union[tuple(self.backend.get_models())]]( # noqa: UP007
315315
total_results=total_results,
316316
items_per_page=search_request.count,
317317
start_index=search_request.start_index,

scim2_server/utils.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import datetime
22
import importlib
33
import json
4+
import re
5+
import sys
46
from typing import Any
57

68
from pydantic import EmailStr
@@ -178,7 +180,13 @@ def parse_new_value(model: BaseModel, attribute_name: str, value: Any) -> Any:
178180
if field_root_type is bool and isinstance(value, str):
179181
new_value = not value.lower() == "false"
180182
elif field_root_type is datetime.datetime and isinstance(value, str):
181-
new_value = datetime.datetime.fromisoformat(value)
183+
# ISO 8601 datetime format (notably with the Z suffix) are only supported from Python 3.11
184+
if sys.version_info < (3, 11): # pragma: no cover
185+
new_value = datetime.datetime.fromisoformat(
186+
re.sub(r"Z$", "+00:00", value)
187+
)
188+
else:
189+
new_value = datetime.datetime.fromisoformat(value)
182190
elif field_root_type is EmailStr and isinstance(value, str):
183191
new_value = value
184192
elif hasattr(field_root_type, "model_fields"):

tests/integration/test_basic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def test_unique_constraints(self, wsgi):
8585
assert r.json()["userName"] == "bjensen2@example.com"
8686

8787
def test_sort(self, provider, wsgi):
88-
TypedListResponse = ListResponse[Union[*provider.backend.get_models()]]
88+
TypedListResponse = ListResponse[Union[tuple(provider.backend.get_models())]] # noqa: UP007
8989

9090
def assert_sorted(sort_by: str, sorted: list[str], endpoint: str = "/v2/Users"):
9191
for order_by, inverted in (

tests/integration/test_scim_provider.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,13 +544,17 @@ def test_resource_search_post(self, wsgi, first_fake_user):
544544
assert r.status_code == 404
545545

546546
def test_resource_meta_dates(self, wsgi, fake_user_data):
547-
@time_machine.travel(datetime.datetime(2024, 3, 14, 6, 00, tzinfo=datetime.UTC))
547+
@time_machine.travel(
548+
datetime.datetime(2024, 3, 14, 6, 00, tzinfo=datetime.timezone.utc)
549+
)
548550
def create_user():
549551
r = wsgi.post("/v2/Users", json=fake_user_data[1])
550552
assert r.status_code == 201
551553
return r.json()
552554

553-
@time_machine.travel(datetime.datetime(2024, 3, 16, 8, 30, tzinfo=datetime.UTC))
555+
@time_machine.travel(
556+
datetime.datetime(2024, 3, 16, 8, 30, tzinfo=datetime.timezone.utc)
557+
)
554558
def update_user(user_id):
555559
r = wsgi.put(f"/v2/Users/{user_id}", json={"userName": "Foo"})
556560
assert r.status_code == 200

tests/test_operators.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,9 @@ class Foo(Resource):
283283

284284
f = Foo()
285285
AddOperator("dt", "2010-01-23T04:56:22Z")(f)
286-
assert f.dt == datetime.datetime(2010, 1, 23, 4, 56, 22, tzinfo=datetime.UTC)
286+
assert f.dt == datetime.datetime(
287+
2010, 1, 23, 4, 56, 22, tzinfo=datetime.timezone.utc
288+
)
287289

288290
def test_add_operator_extension_simple(self):
289291
u = User[EnterpriseUser]()

0 commit comments

Comments
 (0)