mirror of
https://github.com/stack-auth/stack.git
synced 2026-07-20 21:29:36 +08:00
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:
parent
6c0c58d2eb
commit
bfff27d4e7
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user