fix: make RequestLike runtime_checkable and remove type: ignore from resolve_token_store

- Add @runtime_checkable decorator to RequestLike Protocol
- Replace bare fallback with isinstance(init, RequestLike) check in resolve_token_store
- Raise TypeError for invalid token store initializer types
- Add tests for isinstance checks and invalid input handling
This commit is contained in:
Ejiro Asiuwhu
2026-03-25 08:00:59 +01:00
parent 6c0c58d2eb
commit bfff27d4e7
3 changed files with 38 additions and 3 deletions
@@ -197,8 +197,9 @@ def resolve_token_store(init: TokenStoreInit, project_id: str) -> TokenStore | N
access_token=init.get("access_token"),
refresh_token=init.get("refresh_token"),
)
# Must be RequestLike (has .headers attribute)
return RequestTokenStore(init) # type: ignore[arg-type]
if isinstance(init, RequestLike):
return RequestTokenStore(init)
raise TypeError(f"Invalid token store initializer: {type(init)}")
# ---------------------------------------------------------------------------
@@ -1,8 +1,9 @@
from __future__ import annotations
from typing import Mapping, Protocol
from typing import Mapping, Protocol, runtime_checkable
@runtime_checkable
class RequestLike(Protocol):
@property
def headers(self) -> Mapping[str, str]: ...
@@ -215,6 +215,39 @@ class TestTokenStoreRegistry:
def test_resolve_none(self) -> None:
assert resolve_token_store(None, "proj") is None
def test_resolve_raises_type_error_for_invalid_input(self) -> None:
with pytest.raises(TypeError, match="Invalid token store initializer"):
resolve_token_store(12345, "proj") # type: ignore[arg-type]
# ---------------------------------------------------------------------------
# RequestLike runtime_checkable isinstance checks
# ---------------------------------------------------------------------------
class TestRequestLikeProtocol:
def test_isinstance_works_on_conforming_object(self) -> None:
"""RequestLike should be runtime_checkable so isinstance works."""
from stack_auth._types import RequestLike
request = _FakeRequest({"x-stack-auth": "{}"})
assert isinstance(request, RequestLike)
def test_isinstance_rejects_non_conforming_object(self) -> None:
"""Objects without a .headers property should not pass isinstance."""
from stack_auth._types import RequestLike
assert not isinstance("a string", RequestLike)
assert not isinstance(42, RequestLike)
assert not isinstance({}, RequestLike)
def test_resolve_token_store_returns_request_token_store_for_request_like(self) -> None:
"""resolve_token_store should detect RequestLike via isinstance and return RequestTokenStore."""
header_value = json.dumps({"accessToken": "at", "refreshToken": "rt"})
request = _FakeRequest({"x-stack-auth": header_value})
store = resolve_token_store(request, "proj")
assert isinstance(store, RequestTokenStore)
assert store.get_stored_access_token() == "at"
# ---------------------------------------------------------------------------
# Helper functions: _is_fresh_enough, _is_expired, _decode_jwt_payload