Skip to content

Commit 90c2333

Browse files
Mlaz-codeclaude
andcommitted
style: apply ruff lint + pyright type fixes
Preparatory pass before wiring ruff + pyright into CI. pyproject.toml already had [tool.ruff] (rules E, F, I, UP) and [tool.pyright] configured; these were just never invoked. Ruff: 424 findings → 0. Bulk were PEP 604 modernization auto-fixes: - Optional[X] → X | None (317 sites) - Union[X, Y] → X | Y (80 sites) - typing.Dict/List/etc. → dict/list (12 sites) - import sort + unused imports (8 sites) Remaining 5 hand-fixed: 4 x E501 line-too-long (reflowed), 1 x E402 in test_dataframe.py where the import follows pytest.importorskip() by design (added noqa). Pyright: 8 errors → 0. - src/sharpapi/models.py: BaseModel isinstance check replaces hasattr (pyright can't narrow via hasattr). - tests: added `assert ... is not None` narrowing before attribute access on Optional fields (account.key, account.features, account.limits, meta.pagination). No behavior change. 87/87 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent eae13af commit 90c2333

10 files changed

Lines changed: 365 additions & 351 deletions

File tree

src/sharpapi/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
print(f"+{opp.ev_percentage}% on {opp.selection} @ {opp.sportsbook}")
1818
"""
1919

20+
from ._utils import american_to_decimal, american_to_probability, decimal_to_american
2021
from .async_client import AsyncSharpAPI
2122
from .client import SharpAPI
2223
from .exceptions import (
@@ -28,12 +29,12 @@
2829
ValidationError,
2930
)
3031
from .models import (
31-
APIResponse,
3232
AccountInfo,
33+
APIResponse,
3334
ArbitrageLeg,
3435
ArbitrageOpportunity,
35-
EVOpportunity,
3636
Event,
37+
EVOpportunity,
3738
GameState,
3839
League,
3940
LowHoldOpportunity,
@@ -49,7 +50,6 @@
4950
Sportsbook,
5051
)
5152
from .streaming import EventStream
52-
from ._utils import american_to_decimal, american_to_probability, decimal_to_american
5353

5454
__version__ = "0.2.1"
5555

src/sharpapi/async_client.py

Lines changed: 81 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from __future__ import annotations
44

55
import asyncio
6-
from typing import Any, Optional, Union
6+
from typing import Any
77

88
import httpx
99

@@ -20,18 +20,18 @@
2020
)
2121
from ._utils import _clean_params
2222
from .models import (
23-
APIResponse,
2423
AccountInfo,
24+
APIResponse,
2525
ArbitrageOpportunity,
26-
EVOpportunity,
2726
Event,
27+
EVOpportunity,
2828
League,
2929
LowHoldOpportunity,
3030
MiddleOpportunity,
3131
OddsLine,
3232
RateLimitInfo,
33-
Sportsbook,
3433
Sport,
34+
Sportsbook,
3535
)
3636

3737

@@ -93,7 +93,7 @@ def rate_limit(self) -> RateLimitInfo:
9393
return self._last_rate_limit
9494

9595
async def _request(self, method: str, path: str, params: dict | None = None, **kwargs) -> Any:
96-
"""Make an async API request and return parsed JSON. Retries 502/503/504 with jittered backoff."""
96+
"""Make an async request, return parsed JSON. Retries 502/503/504 with jittered backoff."""
9797
if params:
9898
params = _clean_params(params)
9999

@@ -148,18 +148,18 @@ def __init__(self, client: AsyncSharpAPI):
148148
async def get(
149149
self,
150150
*,
151-
sportsbook: Optional[Union[str, list[str]]] = None,
152-
add_sportsbook: Optional[Union[str, list[str]]] = None,
153-
sport: Optional[Union[str, list[str]]] = None,
154-
league: Optional[Union[str, list[str]]] = None,
155-
market: Optional[Union[str, list[str]]] = None,
156-
event: Optional[Union[str, list[str]]] = None,
157-
live: Optional[bool] = None,
158-
sort: Optional[str] = None,
159-
group_by: Optional[str] = None,
160-
fields: Optional[Union[str, list[str]]] = None,
161-
limit: Optional[int] = None,
162-
offset: Optional[int] = None,
151+
sportsbook: str | list[str] | None = None,
152+
add_sportsbook: str | list[str] | None = None,
153+
sport: str | list[str] | None = None,
154+
league: str | list[str] | None = None,
155+
market: str | list[str] | None = None,
156+
event: str | list[str] | None = None,
157+
live: bool | None = None,
158+
sort: str | None = None,
159+
group_by: str | None = None,
160+
fields: str | list[str] | None = None,
161+
limit: int | None = None,
162+
offset: int | None = None,
163163
) -> APIResponse[list[OddsLine]]:
164164
"""Get current odds snapshot."""
165165
data = await self._client._get("/odds", {
@@ -181,15 +181,15 @@ async def get(
181181
async def best(
182182
self,
183183
*,
184-
sport: Optional[Union[str, list[str]]] = None,
185-
league: Optional[Union[str, list[str]]] = None,
186-
market: Optional[Union[str, list[str]]] = None,
187-
event: Optional[Union[str, list[str]]] = None,
188-
live: Optional[bool] = None,
189-
sportsbook: Optional[Union[str, list[str]]] = None,
190-
add_sportsbook: Optional[Union[str, list[str]]] = None,
191-
limit: Optional[int] = None,
192-
offset: Optional[int] = None,
184+
sport: str | list[str] | None = None,
185+
league: str | list[str] | None = None,
186+
market: str | list[str] | None = None,
187+
event: str | list[str] | None = None,
188+
live: bool | None = None,
189+
sportsbook: str | list[str] | None = None,
190+
add_sportsbook: str | list[str] | None = None,
191+
limit: int | None = None,
192+
offset: int | None = None,
193193
) -> APIResponse[list[OddsLine]]:
194194
"""Get best odds per selection across all sportsbooks."""
195195
data = await self._client._get("/odds/best", {
@@ -209,7 +209,7 @@ async def comparison(
209209
self,
210210
event_id: str,
211211
*,
212-
market: Optional[str] = None,
212+
market: str | None = None,
213213
) -> APIResponse[list[OddsLine]]:
214214
"""Get side-by-side odds comparison for an event."""
215215
data = await self._client._get("/odds/comparison", {
@@ -233,21 +233,21 @@ def __init__(self, client: AsyncSharpAPI):
233233
async def get(
234234
self,
235235
*,
236-
sport: Optional[Union[str, list[str]]] = None,
237-
league: Optional[Union[str, list[str]]] = None,
238-
sportsbook: Optional[Union[str, list[str]]] = None,
239-
add_sportsbook: Optional[Union[str, list[str]]] = None,
240-
market: Optional[Union[str, list[str]]] = None,
241-
min_ev: Optional[float] = None,
242-
max_ev: Optional[float] = None,
243-
min_market_width: Optional[float] = None,
244-
max_market_width: Optional[float] = None,
245-
max_odds_age: Optional[int] = None,
246-
date_range: Optional[str] = None,
247-
live: Optional[bool] = None,
248-
sort: Optional[str] = None,
249-
limit: Optional[int] = None,
250-
offset: Optional[int] = None,
236+
sport: str | list[str] | None = None,
237+
league: str | list[str] | None = None,
238+
sportsbook: str | list[str] | None = None,
239+
add_sportsbook: str | list[str] | None = None,
240+
market: str | list[str] | None = None,
241+
min_ev: float | None = None,
242+
max_ev: float | None = None,
243+
min_market_width: float | None = None,
244+
max_market_width: float | None = None,
245+
max_odds_age: int | None = None,
246+
date_range: str | None = None,
247+
live: bool | None = None,
248+
sort: str | None = None,
249+
limit: int | None = None,
250+
offset: int | None = None,
251251
) -> APIResponse[list[EVOpportunity]]:
252252
"""Get +EV opportunities. Requires Pro tier or higher."""
253253
data = await self._client._get("/opportunities/ev", {
@@ -279,18 +279,18 @@ def __init__(self, client: AsyncSharpAPI):
279279
async def get(
280280
self,
281281
*,
282-
sport: Optional[Union[str, list[str]]] = None,
283-
league: Optional[Union[str, list[str]]] = None,
284-
sportsbook: Optional[Union[str, list[str]]] = None,
285-
add_sportsbook: Optional[Union[str, list[str]]] = None,
286-
market: Optional[Union[str, list[str]]] = None,
287-
min_profit: Optional[float] = None,
288-
max_odds_age: Optional[int] = None,
289-
live: Optional[bool] = None,
290-
sort: Optional[str] = None,
291-
group: Optional[str] = None,
292-
limit: Optional[int] = None,
293-
offset: Optional[int] = None,
282+
sport: str | list[str] | None = None,
283+
league: str | list[str] | None = None,
284+
sportsbook: str | list[str] | None = None,
285+
add_sportsbook: str | list[str] | None = None,
286+
market: str | list[str] | None = None,
287+
min_profit: float | None = None,
288+
max_odds_age: int | None = None,
289+
live: bool | None = None,
290+
sort: str | None = None,
291+
group: str | None = None,
292+
limit: int | None = None,
293+
offset: int | None = None,
294294
) -> APIResponse[list[ArbitrageOpportunity]]:
295295
"""Get arbitrage opportunities. Requires Hobby tier or higher."""
296296
data = await self._client._get("/opportunities/arbitrage", {
@@ -319,17 +319,17 @@ def __init__(self, client: AsyncSharpAPI):
319319
async def get(
320320
self,
321321
*,
322-
sport: Optional[Union[str, list[str]]] = None,
323-
league: Optional[Union[str, list[str]]] = None,
324-
sportsbook: Optional[Union[str, list[str]]] = None,
325-
market: Optional[Union[str, list[str]]] = None,
326-
min_size: Optional[float] = None,
327-
max_odds_age: Optional[int] = None,
328-
live: Optional[bool] = None,
329-
state: Optional[str] = None,
330-
sort: Optional[str] = None,
331-
limit: Optional[int] = None,
332-
offset: Optional[int] = None,
322+
sport: str | list[str] | None = None,
323+
league: str | list[str] | None = None,
324+
sportsbook: str | list[str] | None = None,
325+
market: str | list[str] | None = None,
326+
min_size: float | None = None,
327+
max_odds_age: int | None = None,
328+
live: bool | None = None,
329+
state: str | None = None,
330+
sort: str | None = None,
331+
limit: int | None = None,
332+
offset: int | None = None,
333333
) -> APIResponse[list[MiddleOpportunity]]:
334334
"""Get middle opportunities. Requires Pro tier or higher."""
335335
data = await self._client._get("/opportunities/middles", {
@@ -357,16 +357,16 @@ def __init__(self, client: AsyncSharpAPI):
357357
async def get(
358358
self,
359359
*,
360-
sport: Optional[Union[str, list[str]]] = None,
361-
league: Optional[Union[str, list[str]]] = None,
362-
sportsbook: Optional[Union[str, list[str]]] = None,
363-
market: Optional[Union[str, list[str]]] = None,
364-
max_hold: Optional[float] = None,
365-
live: Optional[bool] = None,
366-
state: Optional[str] = None,
367-
sort: Optional[str] = None,
368-
limit: Optional[int] = None,
369-
offset: Optional[int] = None,
360+
sport: str | list[str] | None = None,
361+
league: str | list[str] | None = None,
362+
sportsbook: str | list[str] | None = None,
363+
market: str | list[str] | None = None,
364+
max_hold: float | None = None,
365+
live: bool | None = None,
366+
state: str | None = None,
367+
sort: str | None = None,
368+
limit: int | None = None,
369+
offset: int | None = None,
370370
) -> APIResponse[list[LowHoldOpportunity]]:
371371
"""Get low-hold opportunities."""
372372
data = await self._client._get("/opportunities/low_hold", {
@@ -404,7 +404,7 @@ class _AsyncLeaguesResource:
404404
def __init__(self, client: AsyncSharpAPI):
405405
self._client = client
406406

407-
async def list(self, *, sport: Optional[str] = None) -> APIResponse[list[League]]:
407+
async def list(self, *, sport: str | None = None) -> APIResponse[list[League]]:
408408
"""List all leagues, optionally filtered by sport."""
409409
data = await self._client._get("/leagues", {"sport": sport})
410410
return parse_response(data, League)
@@ -439,11 +439,11 @@ def __init__(self, client: AsyncSharpAPI):
439439
async def list(
440440
self,
441441
*,
442-
sport: Optional[str] = None,
443-
league: Optional[Union[str, list[str]]] = None,
444-
live: Optional[bool] = None,
445-
limit: Optional[int] = None,
446-
offset: Optional[int] = None,
442+
sport: str | None = None,
443+
league: str | list[str] | None = None,
444+
live: bool | None = None,
445+
limit: int | None = None,
446+
offset: int | None = None,
447447
) -> APIResponse[list[Event]]:
448448
"""List events."""
449449
data = await self._client._get("/events", {

0 commit comments

Comments
 (0)