Skip to content

Commit 23a97bf

Browse files
committed
chore: apply ruff migrations
1 parent 3e7500c commit 23a97bf

9 files changed

Lines changed: 47 additions & 68 deletions

File tree

scim2_server/backend.py

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@
44
import pickle
55
import uuid
66
from threading import Lock
7-
from typing import Dict
8-
from typing import List
9-
from typing import Optional
10-
from typing import Tuple
117
from typing import Union
128

139
from scim2_filter_parser import lexer
@@ -35,10 +31,10 @@ class Backend:
3531
"""The base class for a SCIM provider backend."""
3632

3733
def __init__(self):
38-
self.schemas: Dict[str, Schema] = {}
39-
self.resource_types: Dict[str, ResourceType] = {}
40-
self.resource_types_by_endpoint: Dict[str, ResourceType] = {}
41-
self.models_dict: Dict[str, BaseModel] = {}
34+
self.schemas: dict[str, Schema] = {}
35+
self.resource_types: dict[str, ResourceType] = {}
36+
self.resource_types_by_endpoint: dict[str, ResourceType] = {}
37+
self.models_dict: dict[str, BaseModel] = {}
4238

4339
def __enter__(self):
4440
"""Allows the backend to be used as a context manager.
@@ -59,7 +55,7 @@ def get_schemas(self):
5955
"""Returns all schemas registered with the backend."""
6056
return self.schemas.values()
6157

62-
def get_schema(self, schema_id: str) -> Optional[Schema]:
58+
def get_schema(self, schema_id: str) -> Schema | None:
6359
"""Gets a schema by its id."""
6460
return self.schemas.get(schema_id)
6561

@@ -93,15 +89,15 @@ def get_resource_types(self):
9389
"""Returns all resource types registered with the backend."""
9490
return self.resource_types.values()
9591

96-
def get_resource_type(self, resource_type_id: str) -> Optional[ResourceType]:
92+
def get_resource_type(self, resource_type_id: str) -> ResourceType | None:
9793
"""Returns the resource type by its id."""
9894
return self.resource_types.get(resource_type_id)
9995

100-
def get_resource_type_by_endpoint(self, endpoint: str) -> Optional[ResourceType]:
96+
def get_resource_type_by_endpoint(self, endpoint: str) -> ResourceType | None:
10197
"""Returns the resource type by its endpoint."""
10298
return self.resource_types_by_endpoint.get(endpoint.lower())
10399

104-
def get_model(self, resource_type_id: str) -> Optional[BaseModel]:
100+
def get_model(self, resource_type_id: str) -> BaseModel | None:
105101
"""Returns the Pydantic Python model for a given resource type."""
106102
return self.models_dict.get(resource_type_id)
107103

@@ -112,8 +108,8 @@ def get_models(self):
112108
def query_resources(
113109
self,
114110
search_request: SearchRequest,
115-
resource_type_id: Optional[str] = None,
116-
) -> Tuple[int, List[Resource]]:
111+
resource_type_id: str | None = None,
112+
) -> tuple[int, list[Resource]]:
117113
"""Queries the backend for a set of resources.
118114
119115
:param search_request: SearchRequest instance describing the
@@ -131,7 +127,7 @@ def query_resources(
131127
"""
132128
raise NotImplementedError
133129

134-
def get_resource(self, resource_type_id: str, object_id: str) -> Optional[Resource]:
130+
def get_resource(self, resource_type_id: str, object_id: str) -> Resource | None:
135131
"""Queries the backend for a resources by its ID.
136132
137133
:param resource_type_id: ID of the resource type to get the
@@ -155,7 +151,7 @@ def delete_resource(self, resource_type_id: str, object_id: str) -> bool:
155151

156152
def create_resource(
157153
self, resource_type_id: str, resource: Resource
158-
) -> Optional[Resource]:
154+
) -> Resource | None:
159155
"""Creates a resource.
160156
161157
:param resource_type_id: ID of the resource type to create.
@@ -168,7 +164,7 @@ def create_resource(
168164

169165
def update_resource(
170166
self, resource_type_id: str, resource: Resource
171-
) -> Optional[Resource]:
167+
) -> Resource | None:
172168
"""Updates a resource. The resource is identified by its ID.
173169
174170
:param resource_type_id: ID of the resource type to update.
@@ -193,7 +189,7 @@ class InMemoryBackend(Backend):
193189
class UniquenessDescriptor:
194190
"""Used to mimic uniqueness constraints e.g. from a SQL database."""
195191

196-
schema: Optional[str]
192+
schema: str | None
197193
attribute_name: str
198194
case_exact: bool
199195

@@ -207,8 +203,8 @@ def get_attribute(self, resource: Resource):
207203

208204
@classmethod
209205
def collect_unique_attrs(
210-
cls, attributes: List[Attribute], schema: Optional[str]
211-
) -> List[UniquenessDescriptor]:
206+
cls, attributes: list[Attribute], schema: str | None
207+
) -> list[UniquenessDescriptor]:
212208
ret = []
213209
for attr in attributes:
214210
if attr.uniqueness != Uniqueness.none:
@@ -221,8 +217,8 @@ def collect_unique_attrs(
221217

222218
@classmethod
223219
def collect_resource_unique_attrs(
224-
cls, resource_type: ResourceType, schemas: Dict[str, Schema]
225-
) -> List[List[UniquenessDescriptor]]:
220+
cls, resource_type: ResourceType, schemas: dict[str, Schema]
221+
) -> list[list[UniquenessDescriptor]]:
226222
ret = cls.collect_unique_attrs(schemas[resource_type.schema_].attributes, None)
227223
for extension in resource_type.schema_extensions or []:
228224
ret.extend(
@@ -234,8 +230,8 @@ def collect_resource_unique_attrs(
234230

235231
def __init__(self):
236232
super().__init__()
237-
self.resources: List[Resource] = []
238-
self.unique_attributes: Dict[str, List[List[str]]] = {}
233+
self.resources: list[Resource] = []
234+
self.unique_attributes: dict[str, list[list[str]]] = {}
239235
self.lock: Lock = Lock()
240236

241237
def __enter__(self):
@@ -261,8 +257,8 @@ def register_resource_type(self, resource_type: ResourceType):
261257
def query_resources(
262258
self,
263259
search_request: SearchRequest,
264-
resource_type_id: Optional[str] = None,
265-
) -> Tuple[int, List[Resource]]:
260+
resource_type_id: str | None = None,
261+
) -> tuple[int, list[Resource]]:
266262
start_index = (search_request.start_index or 1) - 1
267263

268264
tree = None
@@ -304,7 +300,7 @@ def query_resources(
304300
found_resources = found_resources[: search_request.count]
305301
return len(found_resources), found_resources
306302

307-
def _get_resource_idx(self, resource_type_id: str, object_id: str) -> Optional[int]:
303+
def _get_resource_idx(self, resource_type_id: str, object_id: str) -> int | None:
308304
return next(
309305
(
310306
idx
@@ -314,7 +310,7 @@ def _get_resource_idx(self, resource_type_id: str, object_id: str) -> Optional[i
314310
None,
315311
)
316312

317-
def get_resource(self, resource_type_id: str, object_id: str) -> Optional[Resource]:
313+
def get_resource(self, resource_type_id: str, object_id: str) -> Resource | None:
318314
resource_dict_idx = self._get_resource_idx(resource_type_id, object_id)
319315
if resource_dict_idx is not None:
320316
return self.resources[resource_dict_idx].model_copy(deep=True)
@@ -333,7 +329,7 @@ def delete_resource(self, resource_type_id: str, object_id: str) -> bool:
333329

334330
def create_resource(
335331
self, resource_type_id: str, resource: Resource
336-
) -> Optional[Resource]:
332+
) -> Resource | None:
337333
resource = resource.model_copy(deep=True)
338334
resource.id = uuid.uuid4().hex
339335
utcnow = datetime.datetime.now(datetime.UTC)
@@ -372,7 +368,7 @@ def _touch_resource(resource: Resource, last_modified: datetime.datetime):
372368

373369
def update_resource(
374370
self, resource_type_id: str, resource: Resource
375-
) -> Optional[Resource]:
371+
) -> Resource | None:
376372
found_res_idx = self._get_resource_idx(resource_type_id, resource.id)
377373
if found_res_idx is not None:
378374
updated_resource = self.models_dict[resource_type_id].model_validate(

scim2_server/filter.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from types import NoneType
2-
from typing import List
32

43
from scim2_filter_parser import ast as scim2ast
54
from scim2_models import BaseModel
@@ -12,8 +11,8 @@
1211

1312

1413
def evaluate_filter(
15-
obj: BaseModel | List[BaseModel], tree: scim2ast.AST
16-
) -> bool | List[bool]:
14+
obj: BaseModel | list[BaseModel], tree: scim2ast.AST
15+
) -> bool | list[bool]:
1716
"""This implementation is limited by the specifics of the
1817
scim2_filter_parser module.
1918
@@ -29,7 +28,7 @@ def evaluate_filter(
2928
case scim2ast.Filter:
3029
if tree.namespace is not None:
3130
obj = ResolveOperator(tree.namespace.attr_name)(obj).get_values()
32-
if isinstance(obj, List):
31+
if isinstance(obj, list):
3332
return [
3433
o
3534
for o in obj
@@ -124,5 +123,5 @@ def check_comparable_value(value):
124123
"Boolean and Binary attributes SHALL cause a failed response (HTTP
125124
status code 400) with "scimType" of "invalidFilter"."
126125
"""
127-
if isinstance(value, (bytes, bool, NoneType)):
126+
if isinstance(value, bytes | bool | NoneType):
128127
raise SCIMException(Error.make_invalid_filter_error())

scim2_server/provider.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
import json
33
import logging
44
import traceback
5-
from typing import Dict
6-
from typing import Optional
75
from typing import Union
86
from urllib.parse import urljoin
97

@@ -118,7 +116,7 @@ def __init__(self, backend: Backend):
118116
@staticmethod
119117
def adjust_location(
120118
request: Request, resource: Resource, cp=False
121-
) -> Optional[Resource]:
119+
) -> Resource | None:
122120
"""Adjusts the "meta.location" attribute of a resource to match the
123121
hostname the client used to access this server. If a static URL is
124122
used,
@@ -246,7 +244,7 @@ def call_single_resource(
246244
)
247245

248246
@staticmethod
249-
def get_attrs_from_request(request: Request) -> Dict:
247+
def get_attrs_from_request(request: Request) -> dict:
250248
"""Parses the "attributes" an "excludedAttributes" HTTP request
251249
parameters."""
252250
ret = {}
@@ -296,7 +294,7 @@ def build_search_request(self, request: Request) -> SearchRequest:
296294
search_request.sort_order = SearchRequest.SortOrder.descending
297295
return search_request
298296

299-
def query_resource(self, request: Request, resource: Optional[ResourceType]):
297+
def query_resource(self, request: Request, resource: ResourceType | None):
300298
search_request = self.build_search_request(request)
301299

302300
kwargs = {}

tests/conftest.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import importlib
22
import json
3-
from typing import List
43

54
import httpx
65
import pytest
@@ -21,7 +20,7 @@ def static_data():
2120
return load_default_schemas(), load_default_resource_types()
2221

2322

24-
def load_json_resource(json_name: str) -> List:
23+
def load_json_resource(json_name: str) -> list:
2524
fp = importlib.resources.files("tests") / json_name
2625
with open(fp) as f:
2726
return json.load(f)

tests/integration/test_basic.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from typing import List
21
from typing import Union
32

43
from scim2_models import ListResponse
@@ -88,7 +87,7 @@ def test_unique_constraints(self, wsgi):
8887
def test_sort(self, provider, wsgi):
8988
TypedListResponse = ListResponse[Union[*provider.backend.get_models()]]
9089

91-
def assert_sorted(sort_by: str, sorted: List[str], endpoint: str = "/v2/Users"):
90+
def assert_sorted(sort_by: str, sorted: list[str], endpoint: str = "/v2/Users"):
9291
for order_by, inverted in (
9392
(None, False),
9493
("ascending", False),

tests/integration/test_scim_provider.py

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

547547
def test_resource_meta_dates(self, wsgi, fake_user_data):
548-
@time_machine.travel(
549-
datetime.datetime(2024, 3, 14, 6, 00, tzinfo=datetime.timezone.utc)
550-
)
548+
@time_machine.travel(datetime.datetime(2024, 3, 14, 6, 00, tzinfo=datetime.UTC))
551549
def create_user():
552550
r = wsgi.post("/v2/Users", json=fake_user_data[1])
553551
assert r.status_code == 201
554552
return r.json()
555553

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

tests/test_operators.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import base64
22
import datetime
3-
from typing import List
4-
from typing import Optional
53

64
import pytest
75
from scim2_models import BaseModel
@@ -280,14 +278,12 @@ def test_add_operator_binary_data(self):
280278

281279
def test_add_operator_datetime(self):
282280
class Foo(Resource):
283-
schemas: List[str] = ["urn:example:2.0:Foo"]
284-
dt: Optional[datetime.datetime] = None
281+
schemas: list[str] = ["urn:example:2.0:Foo"]
282+
dt: datetime.datetime | None = None
285283

286284
f = Foo()
287285
AddOperator("dt", "2010-01-23T04:56:22Z")(f)
288-
assert f.dt == datetime.datetime(
289-
2010, 1, 23, 4, 56, 22, tzinfo=datetime.timezone.utc
290-
)
286+
assert f.dt == datetime.datetime(2010, 1, 23, 4, 56, 22, tzinfo=datetime.UTC)
291287

292288
def test_add_operator_extension_simple(self):
293289
u = User[EnterpriseUser]()

tests/test_utils.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
from typing import Annotated
2-
from typing import List
3-
from typing import Optional
42

53
import pytest
64
from scim2_filter_parser.lexer import SCIMLexer
@@ -358,8 +356,8 @@ def test_dump_extension(self, provider):
358356

359357
def test_merge_resources_immutable(self):
360358
class Foo(Resource):
361-
schemas: List[str] = ["urn:example:2.0:Foo"]
362-
immutable_string: Annotated[Optional[str], Mutability.immutable] = None
359+
schemas: list[str] = ["urn:example:2.0:Foo"]
360+
immutable_string: Annotated[str | None, Mutability.immutable] = None
363361

364362
stored = Foo()
365363
merge_resources(stored, Foo(immutable_string="ABC"))
@@ -370,9 +368,9 @@ class Foo(Resource):
370368

371369
def test_is_multi_valued(self):
372370
class Foo(Resource):
373-
schemas: List[str] = ["urn:example:2.0:Foo"]
374-
some_string: Optional[str] = None
375-
multi_valued_string: Optional[List[str]] = None
371+
schemas: list[str] = ["urn:example:2.0:Foo"]
372+
some_string: str | None = None
373+
multi_valued_string: list[str] | None = None
376374

377375
res = Foo()
378376
assert is_multi_valued(res, "schemas")

tests/utils.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
from typing import Dict
2-
from typing import Iterable
3-
from typing import Optional
1+
from collections.abc import Iterable
42

53

6-
def compare_dicts(a: Dict, b: Dict, ignore_keys: Optional[Iterable] = None):
4+
def compare_dicts(a: dict, b: dict, ignore_keys: Iterable | None = None):
75
"""Asserts that the dictionary a is a subset of b."""
86
if ignore_keys is None:
97
ignore_keys = set()

0 commit comments

Comments
 (0)