From e3072b64ab9161389e5813054f7c6f3a90fe55ae Mon Sep 17 00:00:00 2001 From: donbarbos Date: Wed, 9 Sep 2026 10:50:13 +0400 Subject: [PATCH] [Authlib] Use Flask in integrations --- stubs/Authlib/@tests/stubtest_allowlist.txt | 3 --- stubs/Authlib/METADATA.toml | 3 ++- .../integrations/flask_client/__init__.pyi | 8 +++++--- .../integrations/flask_client/apps.pyi | 13 ++++++------- .../integrations/flask_client/integration.pyi | 4 +++- .../flask_oauth1/authorization_server.pyi | 13 +++++++------ .../integrations/flask_oauth1/cache.pyi | 10 +++++++--- .../flask_oauth1/resource_protector.pyi | 10 ++++++---- .../flask_oauth2/authorization_server.pyi | 7 ++++--- .../integrations/flask_oauth2/errors.pyi | 8 +++++--- .../integrations/flask_oauth2/requests.pyi | 19 +++++++++++-------- .../flask_oauth2/resource_protector.pyi | 5 +++-- .../integrations/flask_oauth2/signals.pyi | 8 ++++---- 13 files changed, 63 insertions(+), 48 deletions(-) diff --git a/stubs/Authlib/@tests/stubtest_allowlist.txt b/stubs/Authlib/@tests/stubtest_allowlist.txt index d84c31291389..98002c5bac78 100644 --- a/stubs/Authlib/@tests/stubtest_allowlist.txt +++ b/stubs/Authlib/@tests/stubtest_allowlist.txt @@ -45,8 +45,5 @@ authlib.oidc.core.grants.implicit.OpenIDImplicitGrant.validate_consent_request authlib.integrations.django_client.* authlib.integrations.django_oauth1.* authlib.integrations.django_oauth2.* -authlib.integrations.flask_client.* -authlib.integrations.flask_oauth1.* -authlib.integrations.flask_oauth2.* authlib.integrations.sqla_oauth2.* authlib.integrations.starlette_client.* diff --git a/stubs/Authlib/METADATA.toml b/stubs/Authlib/METADATA.toml index fac7a8d163d5..d4984a274e2d 100644 --- a/stubs/Authlib/METADATA.toml +++ b/stubs/Authlib/METADATA.toml @@ -1,4 +1,5 @@ version = "1.8.0" upstream-repository = "https://github.com/authlib/authlib" dependencies = ["cryptography"] -optional-dependencies = ["requests", "httpx2"] +# Requires a version of flask with a `py.typed` file +optional-dependencies = ["requests", "httpx2", "Flask>=2.0.0"] diff --git a/stubs/Authlib/authlib/integrations/flask_client/__init__.pyi b/stubs/Authlib/authlib/integrations/flask_client/__init__.pyi index 575d8ae26f86..0dcc913e0463 100644 --- a/stubs/Authlib/authlib/integrations/flask_client/__init__.pyi +++ b/stubs/Authlib/authlib/integrations/flask_client/__init__.pyi @@ -1,5 +1,7 @@ from _typeshed import Incomplete +from flask import Flask + from ..base_client import BaseOAuth, OAuthError as OAuthError from .apps import FlaskOAuth1App as FlaskOAuth1App, FlaskOAuth2App as FlaskOAuth2App from .integration import FlaskIntegration as FlaskIntegration, token_update as token_update @@ -8,12 +10,12 @@ class OAuth(BaseOAuth): oauth1_client_cls = FlaskOAuth1App oauth2_client_cls = FlaskOAuth2App framework_integration_cls = FlaskIntegration - app: Incomplete - def __init__(self, app=None, cache=None, fetch_token=None, update_token=None): ... + app: Flask | None + def __init__(self, app: Flask | None = None, cache=None, fetch_token=None, update_token=None) -> None: ... cache: Incomplete fetch_token: Incomplete update_token: Incomplete - def init_app(self, app, cache=None, fetch_token=None, update_token=None): ... + def init_app(self, app: Flask, cache=None, fetch_token=None, update_token=None) -> None: ... def create_client(self, name): ... def register(self, name, overwrite=False, **kwargs): ... diff --git a/stubs/Authlib/authlib/integrations/flask_client/apps.pyi b/stubs/Authlib/authlib/integrations/flask_client/apps.pyi index f11d6d1b7e74..70bf6bcb4581 100644 --- a/stubs/Authlib/authlib/integrations/flask_client/apps.pyi +++ b/stubs/Authlib/authlib/integrations/flask_client/apps.pyi @@ -1,11 +1,10 @@ from _typeshed import Incomplete -from typing import TypeAlias + +from werkzeug.wrappers import Response from ..base_client import BaseApp, OAuth1Mixin, OAuth2Mixin, OpenIDMixin from ..requests_client import OAuth1Session, OAuth2Session -_Response: TypeAlias = Incomplete # actual type is werkzeug.wrappers.Response - class FlaskAppMixin: @property def token(self): ... @@ -13,16 +12,16 @@ class FlaskAppMixin: def token(self, token): ... def save_authorize_data(self, **kwargs) -> None: ... - def authorize_redirect(self, redirect_uri=None, **kwargs): ... + def authorize_redirect(self, redirect_uri=None, **kwargs) -> Response: ... class FlaskOAuth1App(FlaskAppMixin, OAuth1Mixin, BaseApp): client_cls = OAuth1Session - def authorize_access_token(self, **kwargs): ... + def authorize_access_token(self, **kwargs) -> dict[Incomplete, Incomplete]: ... class FlaskOAuth2App(FlaskAppMixin, OAuth2Mixin, OpenIDMixin, BaseApp): client_cls = OAuth2Session def logout_redirect( self, post_logout_redirect_uri=None, id_token_hint=None, *, state=None, client_id=None, logout_hint=None, ui_locales=None - ) -> _Response: ... + ) -> Response: ... def validate_logout_response(self): ... - def authorize_access_token(self, **kwargs): ... + def authorize_access_token(self, **kwargs) -> dict[Incomplete, Incomplete]: ... diff --git a/stubs/Authlib/authlib/integrations/flask_client/integration.pyi b/stubs/Authlib/authlib/integrations/flask_client/integration.pyi index 7bcacdd47d99..ccc894f187ea 100644 --- a/stubs/Authlib/authlib/integrations/flask_client/integration.pyi +++ b/stubs/Authlib/authlib/integrations/flask_client/integration.pyi @@ -1,8 +1,10 @@ from _typeshed import Incomplete +from blinker import NamedSignal + from ..base_client import FrameworkIntegration -token_update: Incomplete +token_update: NamedSignal class FlaskIntegration(FrameworkIntegration): def update_token(self, token, refresh_token=None, access_token=None) -> None: ... diff --git a/stubs/Authlib/authlib/integrations/flask_oauth1/authorization_server.pyi b/stubs/Authlib/authlib/integrations/flask_oauth1/authorization_server.pyi index 1a4f39d999a9..be1e84f6d4fe 100644 --- a/stubs/Authlib/authlib/integrations/flask_oauth1/authorization_server.pyi +++ b/stubs/Authlib/authlib/integrations/flask_oauth1/authorization_server.pyi @@ -3,18 +3,19 @@ from _typeshed import Incomplete from collections.abc import Callable from authlib.oauth1 import AuthorizationServer as _AuthorizationServer, OAuth1Request +from flask import Flask, Response log: logging.Logger class AuthorizationServer(_AuthorizationServer): - app: Incomplete + app: Flask | None query_client: Incomplete token_generator: Incomplete - def __init__(self, app=None, query_client=None, token_generator=None): ... + def __init__(self, app: Flask | None = None, query_client=None, token_generator=None) -> None: ... SUPPORTED_SIGNATURE_METHODS: Incomplete - def init_app(self, app, query_client=None, token_generator=None): ... - def register_hook(self, name, func) -> None: ... - def create_token_generator(self, app) -> Callable[[], dict[str, str]]: ... + def init_app(self, app: Flask, query_client=None, token_generator=None) -> None: ... + def register_hook(self, name: str, func) -> None: ... + def create_token_generator(self, app: Flask) -> Callable[[], dict[str, str]]: ... def get_client_by_id(self, client_id): ... def exists_nonce(self, nonce, request): ... def create_temporary_credential(self, request): ... @@ -26,4 +27,4 @@ class AuthorizationServer(_AuthorizationServer): def create_authorization_response(self, request=None, grant_user=None): ... def create_token_response(self, request=None): ... def create_oauth1_request(self, request) -> OAuth1Request: ... - def handle_response(self, status_code, payload, headers): ... + def handle_response(self, status_code, payload, headers) -> Response: ... diff --git a/stubs/Authlib/authlib/integrations/flask_oauth1/cache.pyi b/stubs/Authlib/authlib/integrations/flask_oauth1/cache.pyi index a88e4f9bcd6f..a3ee17809142 100644 --- a/stubs/Authlib/authlib/integrations/flask_oauth1/cache.pyi +++ b/stubs/Authlib/authlib/integrations/flask_oauth1/cache.pyi @@ -1,8 +1,12 @@ from _typeshed import Incomplete from collections.abc import Callable -def register_temporary_credential_hooks(authorization_server, cache, key_prefix: str = "temporary_credential:") -> None: ... +from authlib.oauth1.rfc5849.authorization_server import AuthorizationServer + +def register_temporary_credential_hooks( + authorization_server: AuthorizationServer, cache, key_prefix: str = "temporary_credential:" +) -> None: ... def create_exists_nonce_func( - cache, key_prefix="nonce:", expires=86400 + cache, key_prefix: str = "nonce:", expires=86400 ) -> Callable[[Incomplete, Incomplete, Incomplete, Incomplete], Incomplete]: ... -def register_nonce_hooks(authorization_server, cache, key_prefix: str = "nonce:", expires=86400) -> None: ... +def register_nonce_hooks(authorization_server: AuthorizationServer, cache, key_prefix: str = "nonce:", expires=86400) -> None: ... diff --git a/stubs/Authlib/authlib/integrations/flask_oauth1/resource_protector.pyi b/stubs/Authlib/authlib/integrations/flask_oauth1/resource_protector.pyi index dec0175c3059..b63d437d17bd 100644 --- a/stubs/Authlib/authlib/integrations/flask_oauth1/resource_protector.pyi +++ b/stubs/Authlib/authlib/integrations/flask_oauth1/resource_protector.pyi @@ -1,18 +1,20 @@ from _typeshed import Incomplete from authlib.oauth1 import ResourceProtector as _ResourceProtector +from flask import Flask +from werkzeug.local import LocalProxy class ResourceProtector(_ResourceProtector): - app: Incomplete + app: Flask | None query_client: Incomplete query_token: Incomplete - def __init__(self, app=None, query_client=None, query_token=None, exists_nonce=None) -> None: ... + def __init__(self, app: Flask | None = None, query_client=None, query_token=None, exists_nonce=None) -> None: ... SUPPORTED_SIGNATURE_METHODS: Incomplete - def init_app(self, app, query_client=None, query_token=None, exists_nonce=None): ... + def init_app(self, app: Flask, query_client=None, query_token=None, exists_nonce=None) -> None: ... def get_client_by_id(self, client_id): ... def get_token_credential(self, request): ... def exists_nonce(self, nonce, request): ... def acquire_credential(self): ... def __call__(self, scope=None): ... -current_credential: Incomplete +current_credential: LocalProxy[Incomplete] diff --git a/stubs/Authlib/authlib/integrations/flask_oauth2/authorization_server.pyi b/stubs/Authlib/authlib/integrations/flask_oauth2/authorization_server.pyi index 3856935af6cf..fa3ff6e4e6ce 100644 --- a/stubs/Authlib/authlib/integrations/flask_oauth2/authorization_server.pyi +++ b/stubs/Authlib/authlib/integrations/flask_oauth2/authorization_server.pyi @@ -2,12 +2,13 @@ from _typeshed import Incomplete from authlib.oauth2 import AuthorizationServer as _AuthorizationServer from authlib.oauth2.rfc6750 import BearerTokenGenerator +from flask import Flask, Response from .requests import FlaskJsonRequest, FlaskOAuth2Request class AuthorizationServer(_AuthorizationServer): - def __init__(self, app=None, query_client=None, save_token=None) -> None: ... - def init_app(self, app, query_client=None, save_token=None) -> None: ... + def __init__(self, app: Flask | None = None, query_client=None, save_token=None) -> None: ... + def init_app(self, app: Flask, query_client=None, save_token=None) -> None: ... scopes_supported: Incomplete def load_config(self, config) -> None: ... def query_client(self, client_id): ... @@ -15,7 +16,7 @@ class AuthorizationServer(_AuthorizationServer): def get_error_uri(self, request, error): ... def create_oauth2_request(self, request) -> FlaskOAuth2Request: ... def create_json_request(self, request) -> FlaskJsonRequest: ... - def handle_response(self, status_code, payload, headers): ... + def handle_response(self, status_code, payload, headers) -> Response: ... def send_signal(self, name, *args, **kwargs) -> None: ... def create_bearer_token_generator(self, config) -> BearerTokenGenerator: ... diff --git a/stubs/Authlib/authlib/integrations/flask_oauth2/errors.pyi b/stubs/Authlib/authlib/integrations/flask_oauth2/errors.pyi index 63389264ebcc..4a1b003bea5f 100644 --- a/stubs/Authlib/authlib/integrations/flask_oauth2/errors.pyi +++ b/stubs/Authlib/authlib/integrations/flask_oauth2/errors.pyi @@ -1,12 +1,14 @@ from _typeshed import Incomplete from typing_extensions import Never -# Inherits from werkzeug.exceptions.HTTPException -class _HTTPException: +from werkzeug.exceptions import HTTPException +from werkzeug.sansio.response import Response as SansIOResponse + +class _HTTPException(HTTPException): code: Incomplete body: Incomplete headers: Incomplete - def __init__(self, code, body, headers, response=None) -> None: ... + def __init__(self, code, body, headers, response: SansIOResponse | None = None) -> None: ... # Params depends on `werkzeug` package version def get_body(self, environ=None, scope=None): ... def get_headers(self, environ=None, scope=None): ... diff --git a/stubs/Authlib/authlib/integrations/flask_oauth2/requests.pyi b/stubs/Authlib/authlib/integrations/flask_oauth2/requests.pyi index f2e657d31aa6..3a8c03d05cfe 100644 --- a/stubs/Authlib/authlib/integrations/flask_oauth2/requests.pyi +++ b/stubs/Authlib/authlib/integrations/flask_oauth2/requests.pyi @@ -1,27 +1,30 @@ +from collections import defaultdict from functools import cached_property from authlib.oauth2.rfc6749 import JsonPayload, JsonRequest, OAuth2Payload, OAuth2Request +from flask.wrappers import Request +from werkzeug.datastructures.structures import CombinedMultiDict, ImmutableMultiDict, MultiDict class FlaskOAuth2Payload(OAuth2Payload): - def __init__(self, request) -> None: ... + def __init__(self, request: Request) -> None: ... @property - def data(self): ... + def data(self) -> CombinedMultiDict[str, str]: ... @cached_property - def datalist(self): ... + def datalist(self) -> defaultdict[str, list[str]]: ... class FlaskOAuth2Request(OAuth2Request): payload: FlaskOAuth2Payload - def __init__(self, request) -> None: ... + def __init__(self, request: Request) -> None: ... @property - def args(self): ... + def args(self) -> MultiDict[str, str]: ... # type: ignore[override] @property - def form(self): ... + def form(self) -> ImmutableMultiDict[str, str]: ... class FlaskJsonPayload(JsonPayload): - def __init__(self, request) -> None: ... + def __init__(self, request: Request) -> None: ... @property def data(self): ... class FlaskJsonRequest(JsonRequest): payload: FlaskJsonPayload - def __init__(self, request) -> None: ... + def __init__(self, request: Request) -> None: ... diff --git a/stubs/Authlib/authlib/integrations/flask_oauth2/resource_protector.pyi b/stubs/Authlib/authlib/integrations/flask_oauth2/resource_protector.pyi index c0b262f8faf7..d60fd9cce339 100644 --- a/stubs/Authlib/authlib/integrations/flask_oauth2/resource_protector.pyi +++ b/stubs/Authlib/authlib/integrations/flask_oauth2/resource_protector.pyi @@ -4,12 +4,13 @@ from contextlib import contextmanager from typing_extensions import Never from authlib.oauth2 import ResourceProtector as _ResourceProtector +from werkzeug.local import LocalProxy class ResourceProtector(_ResourceProtector): def raise_error_response(self, error) -> Never: ... def acquire_token(self, scopes=None, **kwargs): ... @contextmanager def acquire(self, scopes=None) -> Generator[Incomplete]: ... - def __call__(self, scopes=None, optional=False, **kwargs): ... + def __call__(self, scopes=None, optional: bool = False, **kwargs): ... -current_token: Incomplete +current_token: LocalProxy[Incomplete] diff --git a/stubs/Authlib/authlib/integrations/flask_oauth2/signals.pyi b/stubs/Authlib/authlib/integrations/flask_oauth2/signals.pyi index f64d46c1d023..3523fe2a3326 100644 --- a/stubs/Authlib/authlib/integrations/flask_oauth2/signals.pyi +++ b/stubs/Authlib/authlib/integrations/flask_oauth2/signals.pyi @@ -1,5 +1,5 @@ -from _typeshed import Incomplete +from blinker import NamedSignal -client_authenticated: Incomplete -token_revoked: Incomplete -token_authenticated: Incomplete +client_authenticated: NamedSignal +token_revoked: NamedSignal +token_authenticated: NamedSignal