Skip to content

Commit 4d44113

Browse files
authored
Merge pull request #14 from predict-idlab/integrate_ruff
Integrate formatting and linting Happens to fix a typing error with the new `core.Client` implementation of `__init__`
2 parents 326d432 + 70169cf commit 4d44113

File tree

16 files changed

+279
-139
lines changed

16 files changed

+279
-139
lines changed

.github/workflows/ci.yml

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,16 @@ on:
88
- main
99

1010
jobs:
11-
# Do not lint for now, as the code is not yet compliant
12-
#lint:
13-
# name: Lint
14-
# runs-on: ubuntu-latest
15-
# steps:
16-
# - uses: actions/checkout@v4
17-
# - uses: astral-sh/setup-uv@v3
18-
# - name: Ruff lint
19-
# run: uv run ruff check .
20-
# - name: Ruff format
21-
# run: uv run ruff format --diff .
22-
# # This isn't a general Python lint, this style is just used in this repository
23-
# - name: Prettier format
24-
# run: npx prettier --prose-wrap always --check "**/*.md"
25-
11+
lint:
12+
name: Run linting and format
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
- uses: astral-sh/setup-uv@v6
17+
- run: uv python install python3.13
18+
- run: uv run ruff check src/obelisk/
19+
- run: uv run ruff format --check src/obelisk/
20+
- run: uv run mypy src/obelisk/
2621
test:
2722
name: Run tests
2823
strategy:

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ In case of major restructuring, it may be needed to clean up the contents of `do
6969
followed by re-running the build.
7070
Manually triggering sphinx-apidoc is unnecessary.
7171

72+
### Hooks
73+
74+
We use some simple Git hooks to avoid fighting the CI too often.
75+
These are stored in the `hooks/` directory, and can be enabled by setting `git config core.hooksPath hooks/`.
76+
7277
## Credits
7378

7479
Base implementation originally by Pieter Moens <[email protected]>,

hooks/pre-commit

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/sh
2+
#
3+
# An example hook script to verify what is about to be committed.
4+
# Called by "git commit" with no arguments. The hook should
5+
# exit with non-zero status after issuing an appropriate message if
6+
# it wants to stop the commit.
7+
#
8+
# To enable this hook, rename this file to "pre-commit".
9+
10+
# Redirect output to stderr.
11+
exec 1>&2
12+
13+
uv run ruff format --check src/obelisk/
14+
uv run mypy src/obelisk/

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ dependencies = [
99
"pydantic>=2.10.6",
1010
"pytest>=8.3.5",
1111
"pytest-asyncio>=0.25.3",
12+
"mypy>=1.18.2",
1213
]
1314
authors = [
1415
{ name="Stef Pletinck", email="[email protected]"},

src/__init__.py

Whitespace-only changes.

src/obelisk/asynchronous/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
Relevant entrance points are :class:`client.Obelisk`.
66
It can be imported from the :mod:`.client` module, or directly from this one.
77
"""
8-
__all__= ['Obelisk', 'core']
8+
9+
__all__ = ["Obelisk", "core"]
910
from .client import Obelisk
1011
from . import core

src/obelisk/asynchronous/base.py

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
import httpx
77

88
from obelisk.exceptions import AuthenticationError
9-
from obelisk.strategies.retry import RetryStrategy, \
10-
NoRetryStrategy
9+
from obelisk.strategies.retry import RetryStrategy, NoRetryStrategy
1110
from obelisk.types import ObeliskKind
1211

1312

@@ -32,27 +31,33 @@ class BaseClient:
3231

3332
log: logging.Logger
3433

35-
def __init__(self, client: str, secret: str,
36-
retry_strategy: RetryStrategy = NoRetryStrategy(),
37-
kind: ObeliskKind = ObeliskKind.CLASSIC) -> None:
34+
def __init__(
35+
self,
36+
client: str,
37+
secret: str,
38+
retry_strategy: RetryStrategy = NoRetryStrategy(),
39+
kind: ObeliskKind = ObeliskKind.CLASSIC,
40+
) -> None:
3841
self._client = client
3942
self._secret = secret
4043
self.retry_strategy = retry_strategy
4144
self.kind = kind
4245

43-
self.log = logging.getLogger('obelisk')
46+
self.log = logging.getLogger("obelisk")
4447

4548
async def _get_token(self):
46-
auth_string = str(base64.b64encode(
47-
f'{self._client}:{self._secret}'.encode('utf-8')), 'utf-8')
49+
auth_string = str(
50+
base64.b64encode(f"{self._client}:{self._secret}".encode("utf-8")), "utf-8"
51+
)
4852
headers = {
49-
'Authorization': f'Basic {auth_string}',
50-
'Content-Type': ('application/json'
51-
if self.kind.use_json_auth else 'application/x-www-form-urlencoded')
52-
}
53-
payload = {
54-
'grant_type': 'client_credentials'
53+
"Authorization": f"Basic {auth_string}",
54+
"Content-Type": (
55+
"application/json"
56+
if self.kind.use_json_auth
57+
else "application/x-www-form-urlencoded"
58+
),
5559
}
60+
payload = {"grant_type": "client_credentials"}
5661

5762
async with httpx.AsyncClient() as client:
5863
response = None
@@ -64,7 +69,8 @@ async def _get_token(self):
6469
self.kind.token_url,
6570
json=payload if self.kind.use_json_auth else None,
6671
data=payload if not self.kind.use_json_auth else None,
67-
headers=headers)
72+
headers=headers,
73+
)
6874

6975
response = request.json()
7076
except Exception as e:
@@ -76,29 +82,33 @@ async def _get_token(self):
7682
raise last_error
7783

7884
if request.status_code != 200:
79-
if 'error' in response:
85+
if "error" in response:
8086
self.log.warning(f"Could not authenticate, {response['error']}")
8187
raise AuthenticationError
8288

83-
self._token = response['access_token']
84-
self._token_expires = (datetime.now()
85-
+ timedelta(seconds=response['expires_in']))
89+
self._token = response["access_token"]
90+
self._token_expires = datetime.now() + timedelta(
91+
seconds=response["expires_in"]
92+
)
8693

8794
async def _verify_token(self):
88-
if (self._token is None
89-
or self._token_expires < (datetime.now() - self.grace_period)):
95+
if self._token is None or self._token_expires < (
96+
datetime.now() - self.grace_period
97+
):
9098
retry = self.retry_strategy.make()
9199
first = True
92100
while first or await retry.should_retry():
93101
first = False
94102
try:
95103
await self._get_token()
96104
return
97-
except:
105+
except: # noqa: E722
106+
self.log.info("excepted, Retrying token fetch")
98107
continue
99108

100-
async def http_post(self, url: str, data: Any = None,
101-
params: Optional[dict] = None) -> httpx.Response:
109+
async def http_post(
110+
self, url: str, data: Any = None, params: Optional[dict] = None
111+
) -> httpx.Response:
102112
"""
103113
Send an HTTP POST request to Obelisk,
104114
with proper auth.
@@ -113,8 +123,8 @@ async def http_post(self, url: str, data: Any = None,
113123
await self._verify_token()
114124

115125
headers = {
116-
'Authorization': f'Bearer {self._token}',
117-
'Content-Type': 'application/json'
126+
"Authorization": f"Bearer {self._token}",
127+
"Content-Type": "application/json",
118128
}
119129
if params is None:
120130
params = {}
@@ -127,11 +137,12 @@ async def http_post(self, url: str, data: Any = None,
127137
self.log.debug(f"Retrying, last response: {response.status_code}")
128138

129139
try:
130-
response = await client.post(url,
131-
json=data,
132-
params={k: v for k, v in params.items() if
133-
v is not None},
134-
headers=headers)
140+
response = await client.post(
141+
url,
142+
json=data,
143+
params={k: v for k, v in params.items() if v is not None},
144+
headers=headers,
145+
)
135146

136147
if response.status_code // 100 == 2:
137148
return response
@@ -144,7 +155,6 @@ async def http_post(self, url: str, data: Any = None,
144155
raise last_error
145156
return response
146157

147-
148158
async def http_get(self, url: str, params: Optional[dict] = None) -> httpx.Response:
149159
"""
150160
Send an HTTP GET request to Obelisk,
@@ -160,8 +170,8 @@ async def http_get(self, url: str, params: Optional[dict] = None) -> httpx.Respo
160170
await self._verify_token()
161171

162172
headers = {
163-
'Authorization': f'Bearer {self._token}',
164-
'Content-Type': 'application/json'
173+
"Authorization": f"Bearer {self._token}",
174+
"Content-Type": "application/json",
165175
}
166176
if params is None:
167177
params = {}
@@ -174,10 +184,11 @@ async def http_get(self, url: str, params: Optional[dict] = None) -> httpx.Respo
174184
self.log.debug(f"Retrying, last response: {response.status_code}")
175185

176186
try:
177-
response = await client.get(url,
178-
params={k: v for k, v in params.items() if
179-
v is not None},
180-
headers=headers)
187+
response = await client.get(
188+
url,
189+
params={k: v for k, v in params.items() if v is not None},
190+
headers=headers,
191+
)
181192

182193
if response.status_code // 100 == 2:
183194
return response

src/obelisk/asynchronous/client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22
from datetime import datetime, timedelta
33
from math import floor
4-
from typing import AsyncGenerator, Generator, List, Literal, Optional
4+
from typing import AsyncGenerator, List, Literal, Optional
55

66
import httpx
77
from pydantic import ValidationError
@@ -90,7 +90,8 @@ async def fetch_single_chunk(
9090
"limitBy": limit_by,
9191
}
9292
response = await self.http_post(
93-
self.kind.query_url, data={k: v for k, v in payload.items() if v is not None}
93+
self.kind.query_url,
94+
data={k: v for k, v in payload.items() if v is not None},
9495
)
9596
if response.status_code != 200:
9697
self.log.warning(f"Unexpected status code: {response.status_code}")
@@ -188,7 +189,6 @@ async def query(
188189

189190
return result_set
190191

191-
192192
async def query_time_chunked(
193193
self,
194194
datasets: List[str],

0 commit comments

Comments
 (0)