Skip to content

Commit a5b11e7

Browse files
committed
Lint: Add upgrade rules
And stabilise on up-to-date typing APIs
1 parent 9a79e16 commit a5b11e7

File tree

7 files changed

+98
-101
lines changed

7 files changed

+98
-101
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,6 @@ strict = true
5959
include = ["src/obelisk/**/*.py"]
6060

6161
[tool.ruff.lint]
62-
select = ["E4", "E7", "E9", "F", "ASYNC", "S", "B", "FIX", "SIM", "C90", "N", "PERF"]
62+
select = ["E4", "E7", "E9", "F", "ASYNC", "S", "B", "FIX", "SIM", "C90", "N", "PERF", "UP"]
6363
# Ignore N815, camelcase field names are usually for serialisation reasons
6464
ignore = ["N815"]

src/obelisk/asynchronous/base.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from datetime import datetime, timedelta
22
import logging
33
import base64
4-
from typing import Any, Optional
4+
from typing import Any
55

66
import httpx
77

@@ -19,9 +19,9 @@ class BaseClient:
1919
_client: str = ""
2020
_secret: str = ""
2121

22-
_token: Optional[str] = None
22+
_token: str | None = None
2323
"""Current authentication token"""
24-
_token_expires: Optional[datetime] = None
24+
_token_expires: datetime | None = None
2525
"""Deadline after which token is no longer useable"""
2626

2727
grace_period: timedelta = timedelta(seconds=10)
@@ -47,7 +47,7 @@ def __init__(
4747

4848
async def _get_token(self) -> None:
4949
auth_string = str(
50-
base64.b64encode(f"{self._client}:{self._secret}".encode("utf-8")), "utf-8"
50+
base64.b64encode(f"{self._client}:{self._secret}".encode()), "utf-8"
5151
)
5252
headers = {
5353
"Authorization": f"Basic {auth_string}",
@@ -113,7 +113,7 @@ async def _verify_token(self) -> None:
113113
continue
114114

115115
async def http_post(
116-
self, url: str, data: Any = None, params: Optional[dict[str, str]] = None
116+
self, url: str, data: Any = None, params: dict[str, str] | None = None
117117
) -> httpx.Response:
118118
"""
119119
Send an HTTP POST request to Obelisk,
@@ -162,7 +162,7 @@ async def http_post(
162162
return response
163163

164164
async def http_get(
165-
self, url: str, params: Optional[dict[str, str]] = None
165+
self, url: str, params: dict[str, str] | None = None
166166
) -> httpx.Response:
167167
"""
168168
Send an HTTP GET request to Obelisk,

src/obelisk/asynchronous/client.py

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import json
22
from datetime import datetime, timedelta
33
from math import floor
4-
from typing import Any, AsyncGenerator, List, Literal, Optional
4+
from typing import Any, Literal
5+
from collections.abc import AsyncGenerator
56

67
import httpx
78
from pydantic import ValidationError
@@ -23,16 +24,16 @@ class Obelisk(BaseClient):
2324

2425
async def fetch_single_chunk(
2526
self,
26-
datasets: List[str],
27-
metrics: Optional[List[str]] = None,
28-
fields: Optional[List[str]] = None,
29-
from_timestamp: Optional[int] = None,
30-
to_timestamp: Optional[int] = None,
31-
order_by: Optional[dict[str, Any]] = None,
32-
filter_: Optional[dict[str, Any]] = None,
33-
limit: Optional[int] = None,
34-
limit_by: Optional[dict[str, Any]] = None,
35-
cursor: Optional[str] = None,
27+
datasets: list[str],
28+
metrics: list[str] | None = None,
29+
fields: list[str] | None = None,
30+
from_timestamp: int | None = None,
31+
to_timestamp: int | None = None,
32+
order_by: dict[str, Any] | None = None,
33+
filter_: dict[str, Any] | None = None,
34+
limit: int | None = None,
35+
limit_by: dict[str, Any] | None = None,
36+
cursor: str | None = None,
3637
) -> QueryResult:
3738
"""
3839
Queries one chunk of events from Obelisk for given parameters,
@@ -111,16 +112,16 @@ async def fetch_single_chunk(
111112

112113
async def query(
113114
self,
114-
datasets: List[str],
115-
metrics: Optional[List[str]] = None,
116-
fields: Optional[List[str]] = None,
117-
from_timestamp: Optional[int] = None,
118-
to_timestamp: Optional[int] = None,
119-
order_by: Optional[dict[str, Any]] = None,
120-
filter_: Optional[dict[str, Any]] = None,
121-
limit: Optional[int] = None,
122-
limit_by: Optional[dict[str, Any]] = None,
123-
) -> List[Datapoint]:
115+
datasets: list[str],
116+
metrics: list[str] | None = None,
117+
fields: list[str] | None = None,
118+
from_timestamp: int | None = None,
119+
to_timestamp: int | None = None,
120+
order_by: dict[str, Any] | None = None,
121+
filter_: dict[str, Any] | None = None,
122+
limit: int | None = None,
123+
limit_by: dict[str, Any] | None = None,
124+
) -> list[Datapoint]:
124125
"""
125126
Queries data from obelisk,
126127
automatically iterating when a cursor is returned.
@@ -157,8 +158,8 @@ async def query(
157158
to a specified maximum number.
158159
"""
159160

160-
cursor: Optional[str] | Literal[True] = True
161-
result_set: List[Datapoint] = []
161+
cursor: str | None | Literal[True] = True
162+
result_set: list[Datapoint] = []
162163

163164
while cursor:
164165
actual_cursor = cursor if cursor is not True else None
@@ -191,14 +192,14 @@ async def query(
191192

192193
async def query_time_chunked(
193194
self,
194-
datasets: List[str],
195-
metrics: List[str],
195+
datasets: list[str],
196+
metrics: list[str],
196197
from_time: datetime,
197198
to_time: datetime,
198199
jump: timedelta,
199-
filter_: Optional[dict[str, Any]] = None,
200+
filter_: dict[str, Any] | None = None,
200201
direction: Literal["asc", "desc"] = "asc",
201-
) -> AsyncGenerator[List[Datapoint], None]:
202+
) -> AsyncGenerator[list[Datapoint], None]:
202203
"""
203204
Fetches all data matching the provided filters,
204205
yielding one chunk at a time.
@@ -239,7 +240,7 @@ async def query_time_chunked(
239240
async def send(
240241
self,
241242
dataset: str,
242-
data: List[dict[str, Any]],
243+
data: list[dict[str, Any]],
243244
precision: TimestampPrecision = TimestampPrecision.MILLISECONDS,
244245
mode: IngestMode = IngestMode.DEFAULT,
245246
) -> httpx.Response:

src/obelisk/asynchronous/core.py

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,12 @@
2525
)
2626
from typing import (
2727
Annotated,
28-
AsyncIterator,
29-
Dict,
30-
Iterator,
31-
List,
3228
Literal,
33-
Optional,
3429
Any,
3530
cast,
3631
get_args,
3732
)
33+
from collections.abc import AsyncIterator, Iterator
3834
from typing_extensions import Self
3935
from numbers import Number
4036

@@ -71,7 +67,7 @@ def type_suffix(metric: str) -> DataType:
7167
"""Type of aggregation Obelisk can process"""
7268

7369

74-
Datapoint = Dict[str, Any]
70+
Datapoint = dict[str, Any]
7571
"""Datapoints resulting from queries are modeled as simple dicts, as fields can come and go depending on query."""
7672

7773

@@ -92,11 +88,11 @@ class IncomingDatapoint(BaseModel):
9288
.. automethod:: check_metric_type(self)
9389
"""
9490

95-
timestamp: Optional[AwareDatetime] = None
91+
timestamp: AwareDatetime | None = None
9692
metric: str
9793
value: Any
98-
labels: Optional[Dict[str, str]] = None
99-
location: Optional[ObeliskPosition] = None
94+
labels: dict[str, str] | None = None
95+
location: ObeliskPosition | None = None
10096

10197
@model_validator(mode="after")
10298
def check_metric_type(self) -> Self:
@@ -130,23 +126,21 @@ def check_metric_type(self) -> Self:
130126

131127
class QueryParams(BaseModel):
132128
dataset: str
133-
groupBy: Optional[List[FieldName]] = None
134-
aggregator: Optional[Aggregator] = None
135-
fields: Optional[List[FieldName]] = None
136-
orderBy: Optional[List[str]] = (
129+
groupBy: list[FieldName] | None = None
130+
aggregator: Aggregator | None = None
131+
fields: list[FieldName] | None = None
132+
orderBy: list[str] | None = (
137133
None # More complex than just FieldName, can be prefixed with - to invert sort
138134
)
139-
dataType: Optional[DataType] = None
140-
filter_: Annotated[Optional[str | Filter], Field(serialization_alias="filter")] = (
141-
None
142-
)
135+
dataType: DataType | None = None
136+
filter_: Annotated[str | Filter | None, Field(serialization_alias="filter")] = None
143137
"""
144138
Obelisk CORE handles filtering in `RSQL format <https://obelisk.pages.ilabt.imec.be/obelisk-core/query.html#rsql-format>`__ ,
145139
to make it easier to also programatically write these filters, we provide the :class:`Filter` option as well.
146140
147141
Suffix to avoid collisions.
148142
"""
149-
cursor: Optional[str] = None
143+
cursor: str | None = None
150144
limit: int = 1000
151145

152146
model_config = ConfigDict(arbitrary_types_allowed=True)
@@ -164,14 +158,14 @@ def to_dict(self) -> dict[str, Any]:
164158

165159
class ChunkedParams(BaseModel):
166160
dataset: str
167-
groupBy: Optional[List[FieldName]] = None
168-
aggregator: Optional[Aggregator] = None
169-
fields: Optional[List[FieldName]] = None
170-
orderBy: Optional[List[str]] = (
161+
groupBy: list[FieldName] | None = None
162+
aggregator: Aggregator | None = None
163+
fields: list[FieldName] | None = None
164+
orderBy: list[str] | None = (
171165
None # More complex than just FieldName, can be prefixed with - to invert sort
172166
)
173-
dataType: Optional[DataType] = None
174-
filter_: Optional[str | Filter] = None
167+
dataType: DataType | None = None
168+
filter_: str | Filter | None = None
175169
"""Underscore suffix to avoid name collisions"""
176170
start: datetime
177171
end: datetime
@@ -208,8 +202,8 @@ def chunks(self) -> Iterator[QueryParams]:
208202

209203

210204
class QueryResult(BaseModel):
211-
cursor: Optional[str] = None
212-
items: List[Datapoint]
205+
cursor: str | None = None
206+
items: list[Datapoint]
213207

214208

215209
class Client(BaseClient):
@@ -233,7 +227,7 @@ def __init__(
233227
async def send(
234228
self,
235229
dataset: str,
236-
data: List[IncomingDatapoint],
230+
data: list[IncomingDatapoint],
237231
) -> httpx.Response:
238232
"""
239233
Publishes data to Obelisk
@@ -285,9 +279,9 @@ async def fetch_single_chunk(self, params: QueryParams) -> QueryResult:
285279
self.log.warning(msg)
286280
raise ObeliskError(msg) from e
287281

288-
async def query(self, params: QueryParams) -> List[Datapoint]:
282+
async def query(self, params: QueryParams) -> list[Datapoint]:
289283
params.cursor = None
290-
result_set: List[Datapoint] = []
284+
result_set: list[Datapoint] = []
291285
result_limit = params.limit
292286

293287
# Obelisk CORE does not actually stop emitting a cursor when done, limit serves as page limit
@@ -305,6 +299,6 @@ async def query(self, params: QueryParams) -> List[Datapoint]:
305299

306300
async def query_time_chunked(
307301
self, params: ChunkedParams
308-
) -> AsyncIterator[List[Datapoint]]:
302+
) -> AsyncIterator[list[Datapoint]]:
309303
for chunk in params.chunks():
310304
yield await self.query(chunk)

src/obelisk/sync/client.py

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import asyncio
22
from datetime import datetime, timedelta
33
from math import floor
4-
from typing import Any, Generator, List, Literal, Optional
4+
from typing import Any, Literal
5+
from collections.abc import Generator
56

67
import httpx
78

@@ -44,16 +45,16 @@ def __init__(
4445

4546
def fetch_single_chunk(
4647
self,
47-
datasets: List[str],
48-
metrics: Optional[List[str]] = None,
49-
fields: Optional[List[str]] = None,
50-
from_timestamp: Optional[int] = None,
51-
to_timestamp: Optional[int] = None,
52-
order_by: Optional[dict[str, Any]] = None,
53-
filter_: Optional[dict[str, Any]] = None,
54-
limit: Optional[int] = None,
55-
limit_by: Optional[dict[str, Any]] = None,
56-
cursor: Optional[str] = None,
48+
datasets: list[str],
49+
metrics: list[str] | None = None,
50+
fields: list[str] | None = None,
51+
from_timestamp: int | None = None,
52+
to_timestamp: int | None = None,
53+
order_by: dict[str, Any] | None = None,
54+
filter_: dict[str, Any] | None = None,
55+
limit: int | None = None,
56+
limit_by: dict[str, Any] | None = None,
57+
cursor: str | None = None,
5758
) -> QueryResult:
5859
"""
5960
Queries one chunk of events from Obelisk for given parameters,
@@ -114,16 +115,16 @@ def fetch_single_chunk(
114115

115116
def query(
116117
self,
117-
datasets: List[str],
118-
metrics: Optional[List[str]] = None,
119-
fields: Optional[List[str]] = None,
120-
from_timestamp: Optional[int] = None,
121-
to_timestamp: Optional[int] = None,
122-
order_by: Optional[dict[str, Any]] = None,
123-
filter_: Optional[dict[str, Any]] = None,
124-
limit: Optional[int] = None,
125-
limit_by: Optional[dict[str, Any]] = None,
126-
) -> List[Datapoint]:
118+
datasets: list[str],
119+
metrics: list[str] | None = None,
120+
fields: list[str] | None = None,
121+
from_timestamp: int | None = None,
122+
to_timestamp: int | None = None,
123+
order_by: dict[str, Any] | None = None,
124+
filter_: dict[str, Any] | None = None,
125+
limit: int | None = None,
126+
limit_by: dict[str, Any] | None = None,
127+
) -> list[Datapoint]:
127128
"""
128129
Queries data from obelisk,
129130
automatically iterating when a cursor is returned.
@@ -177,14 +178,14 @@ def query(
177178

178179
def query_time_chunked(
179180
self,
180-
datasets: List[str],
181-
metrics: List[str],
181+
datasets: list[str],
182+
metrics: list[str],
182183
from_time: datetime,
183184
to_time: datetime,
184185
jump: timedelta,
185-
filter_: Optional[dict[str, Any]] = None,
186+
filter_: dict[str, Any] | None = None,
186187
direction: Literal["asc", "desc"] = "asc",
187-
) -> Generator[List[Datapoint], None, None]:
188+
) -> Generator[list[Datapoint], None, None]:
188189
"""
189190
Fetches all data matching the provided filters,
190191
yielding one chunk at a time.
@@ -225,7 +226,7 @@ def query_time_chunked(
225226
def send(
226227
self,
227228
dataset: str,
228-
data: List[dict[str, Any]],
229+
data: list[dict[str, Any]],
229230
precision: TimestampPrecision = TimestampPrecision.MILLISECONDS,
230231
mode: IngestMode = IngestMode.DEFAULT,
231232
) -> httpx.Response:

0 commit comments

Comments
 (0)