diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 80b23759..20800c4e 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -21,7 +21,6 @@ jobs: max-parallel: 3 matrix: python: - - version: "3.7" - version: "3.8" - version: "3.9" - version: "3.10" diff --git a/authlib/common/errors.py b/authlib/common/errors.py index bc72c077..084f4217 100644 --- a/authlib/common/errors.py +++ b/authlib/common/errors.py @@ -1,4 +1,3 @@ -#: coding: utf-8 from authlib.consts import default_json_headers @@ -20,11 +19,11 @@ def __init__(self, error=None, description=None, uri=None): if uri is not None: self.uri = uri - message = '{}: {}'.format(self.error, self.description) - super(AuthlibBaseError, self).__init__(message) + message = f'{self.error}: {self.description}' + super().__init__(message) def __repr__(self): - return '<{} "{}">'.format(self.__class__.__name__, self.error) + return f'<{self.__class__.__name__} "{self.error}">' class AuthlibHTTPError(AuthlibBaseError): @@ -33,7 +32,7 @@ class AuthlibHTTPError(AuthlibBaseError): def __init__(self, error=None, description=None, uri=None, status_code=None): - super(AuthlibHTTPError, self).__init__(error, description, uri) + super().__init__(error, description, uri) if status_code is not None: self.status_code = status_code diff --git a/authlib/consts.py b/authlib/consts.py index ab9a4db6..f3144e7e 100644 --- a/authlib/consts.py +++ b/authlib/consts.py @@ -2,7 +2,7 @@ version = '1.2.1' author = 'Hsiaoming Yang ' homepage = 'https://authlib.org/' -default_user_agent = '{}/{} (+{})'.format(name, version, homepage) +default_user_agent = f'{name}/{version} (+{homepage})' default_json_headers = [ ('Content-Type', 'application/json'), diff --git a/authlib/deprecate.py b/authlib/deprecate.py index ba87f3c3..7d581d69 100644 --- a/authlib/deprecate.py +++ b/authlib/deprecate.py @@ -10,7 +10,7 @@ class AuthlibDeprecationWarning(DeprecationWarning): def deprecate(message, version=None, link_uid=None, link_file=None): if version: - message += '\nIt will be compatible before version {}.'.format(version) + message += f'\nIt will be compatible before version {version}.' if link_uid and link_file: - message += '\nRead more '.format(link_uid, link_file) + message += f'\nRead more ' warnings.warn(AuthlibDeprecationWarning(message), stacklevel=2) diff --git a/authlib/integrations/base_client/async_app.py b/authlib/integrations/base_client/async_app.py index 182d16d4..640896e7 100644 --- a/authlib/integrations/base_client/async_app.py +++ b/authlib/integrations/base_client/async_app.py @@ -36,7 +36,7 @@ async def create_authorization_url(self, redirect_uri=None, **kwargs): if self.request_token_params: params.update(self.request_token_params) request_token = await client.fetch_request_token(self.request_token_url, **params) - log.debug('Fetch request token: {!r}'.format(request_token)) + log.debug(f'Fetch request token: {request_token!r}') url = client.create_authorization_url(self.authorize_url, **kwargs) state = request_token['oauth_token'] return {'url': url, 'request_token': request_token, 'state': state} diff --git a/authlib/integrations/base_client/async_openid.py b/authlib/integrations/base_client/async_openid.py index a11acc7a..68100f2f 100644 --- a/authlib/integrations/base_client/async_openid.py +++ b/authlib/integrations/base_client/async_openid.py @@ -4,7 +4,7 @@ __all__ = ['AsyncOpenIDMixin'] -class AsyncOpenIDMixin(object): +class AsyncOpenIDMixin: async def fetch_jwk_set(self, force=False): metadata = await self.load_server_metadata() jwk_set = metadata.get('jwks') diff --git a/authlib/integrations/base_client/framework_integration.py b/authlib/integrations/base_client/framework_integration.py index 91028b80..9243e8f0 100644 --- a/authlib/integrations/base_client/framework_integration.py +++ b/authlib/integrations/base_client/framework_integration.py @@ -2,7 +2,7 @@ import time -class FrameworkIntegration(object): +class FrameworkIntegration: expires_in = 3600 def __init__(self, name, cache=None): diff --git a/authlib/integrations/base_client/registry.py b/authlib/integrations/base_client/registry.py index be6c4d3d..68d1be5d 100644 --- a/authlib/integrations/base_client/registry.py +++ b/authlib/integrations/base_client/registry.py @@ -15,7 +15,7 @@ ) -class BaseOAuth(object): +class BaseOAuth: """Registry for oauth clients. Create an instance for registry:: diff --git a/authlib/integrations/base_client/sync_app.py b/authlib/integrations/base_client/sync_app.py index 18d10d08..50fa27a7 100644 --- a/authlib/integrations/base_client/sync_app.py +++ b/authlib/integrations/base_client/sync_app.py @@ -12,7 +12,7 @@ log = logging.getLogger(__name__) -class BaseApp(object): +class BaseApp: client_cls = None OAUTH_APP_CONFIG = None @@ -89,7 +89,7 @@ def _send_token_request(self, session, method, url, token, kwargs): return session.request(method, url, **kwargs) -class OAuth1Base(object): +class OAuth1Base: client_cls = None def __init__( @@ -144,7 +144,7 @@ def create_authorization_url(self, redirect_uri=None, **kwargs): client.redirect_uri = redirect_uri params = self.request_token_params or {} request_token = client.fetch_request_token(self.request_token_url, **params) - log.debug('Fetch request token: {!r}'.format(request_token)) + log.debug(f'Fetch request token: {request_token!r}') url = client.create_authorization_url(self.authorize_url, **kwargs) state = request_token['oauth_token'] return {'url': url, 'request_token': request_token, 'state': state} @@ -169,7 +169,7 @@ def fetch_access_token(self, request_token=None, **kwargs): return token -class OAuth2Base(object): +class OAuth2Base: client_cls = None def __init__( @@ -251,7 +251,7 @@ def _create_oauth2_authorization_url(client, authorization_endpoint, **kwargs): code_verifier = generate_token(48) kwargs['code_verifier'] = code_verifier rv['code_verifier'] = code_verifier - log.debug('Using code_verifier: {!r}'.format(code_verifier)) + log.debug(f'Using code_verifier: {code_verifier!r}') scope = kwargs.get('scope', client.scope) if scope and 'openid' in scope.split(): diff --git a/authlib/integrations/base_client/sync_openid.py b/authlib/integrations/base_client/sync_openid.py index edaa5d2f..ac51907a 100644 --- a/authlib/integrations/base_client/sync_openid.py +++ b/authlib/integrations/base_client/sync_openid.py @@ -2,7 +2,7 @@ from authlib.oidc.core import UserInfo, CodeIDToken, ImplicitIDToken -class OpenIDMixin(object): +class OpenIDMixin: def fetch_jwk_set(self, force=False): metadata = self.load_server_metadata() jwk_set = metadata.get('jwks') diff --git a/authlib/integrations/django_client/apps.py b/authlib/integrations/django_client/apps.py index dbf3a221..07bdf719 100644 --- a/authlib/integrations/django_client/apps.py +++ b/authlib/integrations/django_client/apps.py @@ -6,7 +6,7 @@ ) -class DjangoAppMixin(object): +class DjangoAppMixin: def save_authorize_data(self, request, **kwargs): state = kwargs.pop('state', None) if state: diff --git a/authlib/integrations/django_oauth1/authorization_server.py b/authlib/integrations/django_oauth1/authorization_server.py index 5dc9d983..70c2b6bc 100644 --- a/authlib/integrations/django_oauth1/authorization_server.py +++ b/authlib/integrations/django_oauth1/authorization_server.py @@ -76,7 +76,7 @@ def handle_response(self, status_code, payload, headers): class CacheAuthorizationServer(BaseServer): def __init__(self, client_model, token_model, token_generator=None): - super(CacheAuthorizationServer, self).__init__( + super().__init__( client_model, token_model, token_generator) self._temporary_expires_in = self._config.get( 'temporary_credential_expires_in', 86400) diff --git a/authlib/integrations/django_oauth1/nonce.py b/authlib/integrations/django_oauth1/nonce.py index 535bf7e6..0bd70e31 100644 --- a/authlib/integrations/django_oauth1/nonce.py +++ b/authlib/integrations/django_oauth1/nonce.py @@ -6,9 +6,9 @@ def exists_nonce_in_cache(nonce, request, timeout): timestamp = request.timestamp client_id = request.client_id token = request.token - key = '{}{}-{}-{}'.format(key_prefix, nonce, timestamp, client_id) + key = f'{key_prefix}{nonce}-{timestamp}-{client_id}' if token: - key = '{}-{}'.format(key, token) + key = f'{key}-{token}' rv = bool(cache.get(key)) cache.set(key, 1, timeout=timeout) diff --git a/authlib/integrations/django_oauth2/authorization_server.py b/authlib/integrations/django_oauth2/authorization_server.py index 6802f073..08a27595 100644 --- a/authlib/integrations/django_oauth2/authorization_server.py +++ b/authlib/integrations/django_oauth2/authorization_server.py @@ -26,7 +26,7 @@ def __init__(self, client_model, token_model): self.client_model = client_model self.token_model = token_model scopes_supported = self.config.get('scopes_supported') - super(AuthorizationServer, self).__init__(scopes_supported=scopes_supported) + super().__init__(scopes_supported=scopes_supported) # add default token generator self.register_token_generator('default', self.create_bearer_token_generator()) diff --git a/authlib/integrations/django_oauth2/resource_protector.py b/authlib/integrations/django_oauth2/resource_protector.py index 6ffe5c4b..5e797e6f 100644 --- a/authlib/integrations/django_oauth2/resource_protector.py +++ b/authlib/integrations/django_oauth2/resource_protector.py @@ -51,7 +51,7 @@ def decorated(request, *args, **kwargs): class BearerTokenValidator(_BearerTokenValidator): def __init__(self, token_model, realm=None, **extra_attributes): self.token_model = token_model - super(BearerTokenValidator, self).__init__(realm, **extra_attributes) + super().__init__(realm, **extra_attributes) def authenticate_token(self, token_string): try: diff --git a/authlib/integrations/flask_client/__init__.py b/authlib/integrations/flask_client/__init__.py index 648e104a..ecdca2df 100644 --- a/authlib/integrations/flask_client/__init__.py +++ b/authlib/integrations/flask_client/__init__.py @@ -10,7 +10,7 @@ class OAuth(BaseOAuth): framework_integration_cls = FlaskIntegration def __init__(self, app=None, cache=None, fetch_token=None, update_token=None): - super(OAuth, self).__init__( + super().__init__( cache=cache, fetch_token=fetch_token, update_token=update_token) self.app = app if app: @@ -35,7 +35,7 @@ def init_app(self, app, cache=None, fetch_token=None, update_token=None): def create_client(self, name): if not self.app: raise RuntimeError('OAuth is not init with Flask app.') - return super(OAuth, self).create_client(name) + return super().create_client(name) def register(self, name, overwrite=False, **kwargs): self._registry[name] = (overwrite, kwargs) diff --git a/authlib/integrations/flask_client/apps.py b/authlib/integrations/flask_client/apps.py index b01024a9..7567f4b3 100644 --- a/authlib/integrations/flask_client/apps.py +++ b/authlib/integrations/flask_client/apps.py @@ -6,10 +6,10 @@ ) -class FlaskAppMixin(object): +class FlaskAppMixin: @property def token(self): - attr = '_oauth_token_{}'.format(self.name) + attr = f'_oauth_token_{self.name}' token = g.get(attr) if token: return token @@ -20,7 +20,7 @@ def token(self): @token.setter def token(self, token): - attr = '_oauth_token_{}'.format(self.name) + attr = f'_oauth_token_{self.name}' setattr(g, attr, token) def _get_requested_token(self, *args, **kwargs): diff --git a/authlib/integrations/flask_client/integration.py b/authlib/integrations/flask_client/integration.py index 345c4b4c..f4ea57e3 100644 --- a/authlib/integrations/flask_client/integration.py +++ b/authlib/integrations/flask_client/integration.py @@ -21,7 +21,7 @@ def update_token(self, token, refresh_token=None, access_token=None): def load_config(oauth, name, params): rv = {} for k in params: - conf_key = '{}_{}'.format(name, k).upper() + conf_key = f'{name}_{k}'.upper() v = oauth.app.config.get(conf_key, None) if v is not None: rv[k] = v diff --git a/authlib/integrations/flask_oauth1/authorization_server.py b/authlib/integrations/flask_oauth1/authorization_server.py index 56b81603..3a2a5600 100644 --- a/authlib/integrations/flask_oauth1/authorization_server.py +++ b/authlib/integrations/flask_oauth1/authorization_server.py @@ -159,11 +159,11 @@ def check_authorization_request(self): return req def create_authorization_response(self, request=None, grant_user=None): - return super(AuthorizationServer, self)\ + return super()\ .create_authorization_response(request, grant_user) def create_token_response(self, request=None): - return super(AuthorizationServer, self).create_token_response(request) + return super().create_token_response(request) def create_oauth1_request(self, request): if request is None: diff --git a/authlib/integrations/flask_oauth1/cache.py b/authlib/integrations/flask_oauth1/cache.py index c22211ba..fdfc9a5a 100644 --- a/authlib/integrations/flask_oauth1/cache.py +++ b/authlib/integrations/flask_oauth1/cache.py @@ -58,9 +58,9 @@ def create_exists_nonce_func(cache, key_prefix='nonce:', expires=86400): :param expires: Expire time for nonce """ def exists_nonce(nonce, timestamp, client_id, oauth_token): - key = '{}{}-{}-{}'.format(key_prefix, nonce, timestamp, client_id) + key = f'{key_prefix}{nonce}-{timestamp}-{client_id}' if oauth_token: - key = '{}-{}'.format(key, oauth_token) + key = f'{key}-{oauth_token}' rv = cache.has(key) cache.set(key, 1, timeout=expires) return rv diff --git a/authlib/integrations/flask_oauth2/authorization_server.py b/authlib/integrations/flask_oauth2/authorization_server.py index 15f72f9f..14510b27 100644 --- a/authlib/integrations/flask_oauth2/authorization_server.py +++ b/authlib/integrations/flask_oauth2/authorization_server.py @@ -39,7 +39,7 @@ def save_token(token, request): """ def __init__(self, app=None, query_client=None, save_token=None): - super(AuthorizationServer, self).__init__() + super().__init__() self._query_client = query_client self._save_token = save_token self._error_uris = None diff --git a/authlib/integrations/flask_oauth2/errors.py b/authlib/integrations/flask_oauth2/errors.py index 2217d99d..23c9e57c 100644 --- a/authlib/integrations/flask_oauth2/errors.py +++ b/authlib/integrations/flask_oauth2/errors.py @@ -6,7 +6,7 @@ if _version in ('0', '1'): class _HTTPException(HTTPException): def __init__(self, code, body, headers, response=None): - super(_HTTPException, self).__init__(None, response) + super().__init__(None, response) self.code = code self.body = body @@ -20,7 +20,7 @@ def get_headers(self, environ=None): else: class _HTTPException(HTTPException): def __init__(self, code, body, headers, response=None): - super(_HTTPException, self).__init__(None, response) + super().__init__(None, response) self.code = code self.body = body diff --git a/authlib/integrations/httpx_client/assertion_client.py b/authlib/integrations/httpx_client/assertion_client.py index 9142965f..83dc58b2 100644 --- a/authlib/integrations/httpx_client/assertion_client.py +++ b/authlib/integrations/httpx_client/assertion_client.py @@ -38,7 +38,7 @@ async def request(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAU await self.refresh_token() auth = self.token_auth - return await super(AsyncAssertionClient, self).request( + return await super().request( method, url, auth=auth, **kwargs) async def _refresh_token(self, data): @@ -77,5 +77,5 @@ def request(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, ** self.refresh_token() auth = self.token_auth - return super(AssertionClient, self).request( + return super().request( method, url, auth=auth, **kwargs) diff --git a/authlib/integrations/httpx_client/oauth2_client.py b/authlib/integrations/httpx_client/oauth2_client.py index 152b4a25..d4ee0f58 100644 --- a/authlib/integrations/httpx_client/oauth2_client.py +++ b/authlib/integrations/httpx_client/oauth2_client.py @@ -32,7 +32,7 @@ def auth_flow(self, request: Request) -> typing.Generator[Request, Response, Non headers['Content-Length'] = str(len(body)) yield build_request(url=url, headers=headers, body=body, initial_request=request) except KeyError as error: - description = 'Unsupported token_type: {}'.format(str(error)) + description = f'Unsupported token_type: {str(error)}' raise UnsupportedTokenTypeError(description=description) @@ -87,7 +87,7 @@ async def request(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAU auth = self.token_auth - return await super(AsyncOAuth2Client, self).request( + return await super().request( method, url, auth=auth, **kwargs) @asynccontextmanager @@ -100,7 +100,7 @@ async def stream(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAUL auth = self.token_auth - async with super(AsyncOAuth2Client, self).stream( + async with super().stream( method, url, auth=auth, **kwargs) as resp: yield resp @@ -203,7 +203,7 @@ def request(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, ** auth = self.token_auth - return super(OAuth2Client, self).request( + return super().request( method, url, auth=auth, **kwargs) def stream(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, **kwargs): @@ -216,5 +216,5 @@ def stream(self, method, url, withhold_token=False, auth=USE_CLIENT_DEFAULT, **k auth = self.token_auth - return super(OAuth2Client, self).stream( + return super().stream( method, url, auth=auth, **kwargs) diff --git a/authlib/integrations/requests_client/assertion_session.py b/authlib/integrations/requests_client/assertion_session.py index 5d4e6bc7..d07c0016 100644 --- a/authlib/integrations/requests_client/assertion_session.py +++ b/authlib/integrations/requests_client/assertion_session.py @@ -42,5 +42,5 @@ def request(self, method, url, withhold_token=False, auth=None, **kwargs): kwargs.setdefault('timeout', self.default_timeout) if not withhold_token and auth is None: auth = self.token_auth - return super(AssertionSession, self).request( + return super().request( method, url, auth=auth, **kwargs) diff --git a/authlib/integrations/requests_client/oauth1_session.py b/authlib/integrations/requests_client/oauth1_session.py index ebf3999d..8c49fa98 100644 --- a/authlib/integrations/requests_client/oauth1_session.py +++ b/authlib/integrations/requests_client/oauth1_session.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from requests import Session from requests.auth import AuthBase from authlib.oauth1 import ( diff --git a/authlib/integrations/requests_client/oauth2_session.py b/authlib/integrations/requests_client/oauth2_session.py index 3b468197..9e2426a2 100644 --- a/authlib/integrations/requests_client/oauth2_session.py +++ b/authlib/integrations/requests_client/oauth2_session.py @@ -26,7 +26,7 @@ def __call__(self, req): req.url, req.headers, req.body = self.prepare( req.url, req.headers, req.body) except KeyError as error: - description = 'Unsupported token_type: {}'.format(str(error)) + description = f'Unsupported token_type: {str(error)}' raise UnsupportedTokenTypeError(description=description) return req @@ -106,5 +106,5 @@ def request(self, method, url, withhold_token=False, auth=None, **kwargs): if not self.token: raise MissingTokenError() auth = self.token_auth - return super(OAuth2Session, self).request( + return super().request( method, url, auth=auth, **kwargs) diff --git a/authlib/integrations/starlette_client/__init__.py b/authlib/integrations/starlette_client/__init__.py index 76b64977..7546c547 100644 --- a/authlib/integrations/starlette_client/__init__.py +++ b/authlib/integrations/starlette_client/__init__.py @@ -11,7 +11,7 @@ class OAuth(BaseOAuth): framework_integration_cls = StarletteIntegration def __init__(self, config=None, cache=None, fetch_token=None, update_token=None): - super(OAuth, self).__init__( + super().__init__( cache=cache, fetch_token=fetch_token, update_token=update_token) self.config = config diff --git a/authlib/integrations/starlette_client/apps.py b/authlib/integrations/starlette_client/apps.py index 1ebd7097..114cbaff 100644 --- a/authlib/integrations/starlette_client/apps.py +++ b/authlib/integrations/starlette_client/apps.py @@ -7,7 +7,7 @@ from ..httpx_client import AsyncOAuth1Client, AsyncOAuth2Client -class StarletteAppMixin(object): +class StarletteAppMixin: async def save_authorize_data(self, request, **kwargs): state = kwargs.pop('state', None) if state: diff --git a/authlib/integrations/starlette_client/integration.py b/authlib/integrations/starlette_client/integration.py index afe789bd..04ffd786 100644 --- a/authlib/integrations/starlette_client/integration.py +++ b/authlib/integrations/starlette_client/integration.py @@ -59,7 +59,7 @@ def load_config(oauth, name, params): rv = {} for k in params: - conf_key = '{}_{}'.format(name, k).upper() + conf_key = f'{name}_{k}'.upper() v = oauth.config.get(conf_key, default=None) if v is not None: rv[k] = v diff --git a/authlib/jose/drafts/_jwe_algorithms.py b/authlib/jose/drafts/_jwe_algorithms.py index 798984e6..c01b7e7d 100644 --- a/authlib/jose/drafts/_jwe_algorithms.py +++ b/authlib/jose/drafts/_jwe_algorithms.py @@ -19,7 +19,7 @@ def __init__(self, key_size=None): self.name = 'ECDH-1PU' self.description = 'ECDH-1PU in the Direct Key Agreement mode' else: - self.name = 'ECDH-1PU+A{}KW'.format(key_size) + self.name = f'ECDH-1PU+A{key_size}KW' self.description = ( 'ECDH-1PU using Concat KDF and CEK wrapped ' 'with A{}KW').format(key_size) diff --git a/authlib/jose/errors.py b/authlib/jose/errors.py index b93523f2..abdaeeb9 100644 --- a/authlib/jose/errors.py +++ b/authlib/jose/errors.py @@ -21,7 +21,7 @@ class BadSignatureError(JoseError): error = 'bad_signature' def __init__(self, result): - super(BadSignatureError, self).__init__() + super().__init__() self.result = result @@ -29,8 +29,8 @@ class InvalidHeaderParameterNameError(JoseError): error = 'invalid_header_parameter_name' def __init__(self, name): - description = 'Invalid Header Parameter Name: {}'.format(name) - super(InvalidHeaderParameterNameError, self).__init__( + description = f'Invalid Header Parameter Name: {name}' + super().__init__( description=description) @@ -40,7 +40,7 @@ class InvalidEncryptionAlgorithmForECDH1PUWithKeyWrappingError(JoseError): def __init__(self): description = 'In key agreement with key wrapping mode ECDH-1PU algorithm ' \ 'only supports AES_CBC_HMAC_SHA2 family encryption algorithms' - super(InvalidEncryptionAlgorithmForECDH1PUWithKeyWrappingError, self).__init__( + super().__init__( description=description) @@ -48,8 +48,8 @@ class InvalidAlgorithmForMultipleRecipientsMode(JoseError): error = 'invalid_algorithm_for_multiple_recipients_mode' def __init__(self, alg): - description = '{} algorithm cannot be used in multiple recipients mode'.format(alg) - super(InvalidAlgorithmForMultipleRecipientsMode, self).__init__( + description = f'{alg} algorithm cannot be used in multiple recipients mode' + super().__init__( description=description) @@ -82,24 +82,24 @@ class InvalidClaimError(JoseError): error = 'invalid_claim' def __init__(self, claim): - description = 'Invalid claim "{}"'.format(claim) - super(InvalidClaimError, self).__init__(description=description) + description = f'Invalid claim "{claim}"' + super().__init__(description=description) class MissingClaimError(JoseError): error = 'missing_claim' def __init__(self, claim): - description = 'Missing "{}" claim'.format(claim) - super(MissingClaimError, self).__init__(description=description) + description = f'Missing "{claim}" claim' + super().__init__(description=description) class InsecureClaimError(JoseError): error = 'insecure_claim' def __init__(self, claim): - description = 'Insecure claim "{}"'.format(claim) - super(InsecureClaimError, self).__init__(description=description) + description = f'Insecure claim "{claim}"' + super().__init__(description=description) class ExpiredTokenError(JoseError): diff --git a/authlib/jose/rfc7515/jws.py b/authlib/jose/rfc7515/jws.py index 00f17385..cf19c4ba 100644 --- a/authlib/jose/rfc7515/jws.py +++ b/authlib/jose/rfc7515/jws.py @@ -18,7 +18,7 @@ from .models import JWSHeader, JWSObject -class JsonWebSignature(object): +class JsonWebSignature: #: Registered Header Parameter Names defined by Section 4.1 REGISTERED_HEADER_PARAMETER_NAMES = frozenset([ @@ -38,7 +38,7 @@ def __init__(self, algorithms=None, private_headers=None): def register_algorithm(cls, algorithm): if not algorithm or algorithm.algorithm_type != 'JWS': raise ValueError( - 'Invalid algorithm for JWS, {!r}'.format(algorithm)) + f'Invalid algorithm for JWS, {algorithm!r}') cls.ALGORITHMS_REGISTRY[algorithm.name] = algorithm def serialize_compact(self, protected, payload, key): diff --git a/authlib/jose/rfc7515/models.py b/authlib/jose/rfc7515/models.py index caccfb4e..5da3c7e0 100644 --- a/authlib/jose/rfc7515/models.py +++ b/authlib/jose/rfc7515/models.py @@ -1,4 +1,4 @@ -class JWSAlgorithm(object): +class JWSAlgorithm: """Interface for JWS algorithm. JWA specification (RFC7518) SHOULD implement the algorithms for JWS with this base implementation. """ @@ -52,7 +52,7 @@ def __init__(self, protected, header): obj.update(protected) if header: obj.update(header) - super(JWSHeader, self).__init__(obj) + super().__init__(obj) self.protected = protected self.header = header @@ -66,7 +66,7 @@ def from_dict(cls, obj): class JWSObject(dict): """A dict instance to represent a JWS object.""" def __init__(self, header, payload, type='compact'): - super(JWSObject, self).__init__( + super().__init__( header=header, payload=payload, ) diff --git a/authlib/jose/rfc7516/jwe.py b/authlib/jose/rfc7516/jwe.py index f5e82f44..084bccad 100644 --- a/authlib/jose/rfc7516/jwe.py +++ b/authlib/jose/rfc7516/jwe.py @@ -20,7 +20,7 @@ ) -class JsonWebEncryption(object): +class JsonWebEncryption: #: Registered Header Parameter Names defined by Section 4.1 REGISTERED_HEADER_PARAMETER_NAMES = frozenset([ 'alg', 'enc', 'zip', @@ -42,7 +42,7 @@ def register_algorithm(cls, algorithm): """Register an algorithm for ``alg`` or ``enc`` or ``zip`` of JWE.""" if not algorithm or algorithm.algorithm_type != 'JWE': raise ValueError( - 'Invalid algorithm for JWE, {!r}'.format(algorithm)) + f'Invalid algorithm for JWE, {algorithm!r}') if algorithm.algorithm_location == 'alg': cls.ALG_REGISTRY[algorithm.name] = algorithm diff --git a/authlib/jose/rfc7516/models.py b/authlib/jose/rfc7516/models.py index 0c1a04f1..279563cf 100644 --- a/authlib/jose/rfc7516/models.py +++ b/authlib/jose/rfc7516/models.py @@ -2,7 +2,7 @@ from abc import ABCMeta -class JWEAlgorithmBase(object, metaclass=ABCMeta): +class JWEAlgorithmBase(metaclass=ABCMeta): """Base interface for all JWE algorithms. """ EXTRA_HEADERS = None @@ -47,7 +47,7 @@ def unwrap(self, enc_alg, ek, headers, key, sender_key, tag=None): raise NotImplementedError -class JWEEncAlgorithm(object): +class JWEEncAlgorithm: name = None description = None algorithm_type = 'JWE' @@ -90,7 +90,7 @@ def decrypt(self, ciphertext, aad, iv, tag, key): raise NotImplementedError -class JWEZipAlgorithm(object): +class JWEZipAlgorithm: name = None description = None algorithm_type = 'JWE' @@ -114,7 +114,7 @@ def __init__(self, protected, unprotected): obj.update(protected) if unprotected: obj.update(unprotected) - super(JWESharedHeader, self).__init__(obj) + super().__init__(obj) self.protected = protected if protected else {} self.unprotected = unprotected if unprotected else {} @@ -142,7 +142,7 @@ def __init__(self, protected, unprotected, header): obj.update(unprotected) if header: obj.update(header) - super(JWEHeader, self).__init__(obj) + super().__init__(obj) self.protected = protected if protected else {} self.unprotected = unprotected if unprotected else {} self.header = header if header else {} diff --git a/authlib/jose/rfc7517/asymmetric_key.py b/authlib/jose/rfc7517/asymmetric_key.py index 2c59aa5c..35b1937c 100644 --- a/authlib/jose/rfc7517/asymmetric_key.py +++ b/authlib/jose/rfc7517/asymmetric_key.py @@ -16,7 +16,7 @@ class AsymmetricKey(Key): SSH_PUBLIC_PREFIX = b'' def __init__(self, private_key=None, public_key=None, options=None): - super(AsymmetricKey, self).__init__(options) + super().__init__(options) self.private_key = private_key self.public_key = public_key @@ -122,7 +122,7 @@ def as_bytes(self, encoding=None, is_private=False, password=None): elif encoding == 'DER': encoding = Encoding.DER else: - raise ValueError('Invalid encoding: {!r}'.format(encoding)) + raise ValueError(f'Invalid encoding: {encoding!r}') raw_key = self.as_key(is_private) if is_private: diff --git a/authlib/jose/rfc7517/base_key.py b/authlib/jose/rfc7517/base_key.py index c8c958ce..1afe8d48 100644 --- a/authlib/jose/rfc7517/base_key.py +++ b/authlib/jose/rfc7517/base_key.py @@ -9,7 +9,7 @@ from ..errors import InvalidUseError -class Key(object): +class Key: """This is the base class for a JSON Web Key.""" kty = '_' @@ -71,10 +71,10 @@ def check_key_op(self, operation): """ key_ops = self.tokens.get('key_ops') if key_ops is not None and operation not in key_ops: - raise ValueError('Unsupported key_op "{}"'.format(operation)) + raise ValueError(f'Unsupported key_op "{operation}"') if operation in self.PRIVATE_KEY_OPS and self.public_only: - raise ValueError('Invalid key_op "{}" for public key'.format(operation)) + raise ValueError(f'Invalid key_op "{operation}" for public key') use = self.tokens.get('use') if use: @@ -111,7 +111,7 @@ def thumbprint(self): def check_required_fields(cls, data): for k in cls.REQUIRED_JSON_FIELDS: if k not in data: - raise ValueError('Missing required field: "{}"'.format(k)) + raise ValueError(f'Missing required field: "{k}"') @classmethod def validate_raw_key(cls, key): diff --git a/authlib/jose/rfc7517/jwk.py b/authlib/jose/rfc7517/jwk.py index dcb38b2c..b1578c49 100644 --- a/authlib/jose/rfc7517/jwk.py +++ b/authlib/jose/rfc7517/jwk.py @@ -3,7 +3,7 @@ from ._cryptography_key import load_pem_key -class JsonWebKey(object): +class JsonWebKey: JWK_KEY_CLS = {} @classmethod diff --git a/authlib/jose/rfc7517/key_set.py b/authlib/jose/rfc7517/key_set.py index c4f7720b..3416ce9b 100644 --- a/authlib/jose/rfc7517/key_set.py +++ b/authlib/jose/rfc7517/key_set.py @@ -1,7 +1,7 @@ from authlib.common.encoding import json_dumps -class KeySet(object): +class KeySet: """This class represents a JSON Web Key Set.""" def __init__(self, keys): diff --git a/authlib/jose/rfc7518/ec_key.py b/authlib/jose/rfc7518/ec_key.py index 0457f836..05f0c044 100644 --- a/authlib/jose/rfc7518/ec_key.py +++ b/authlib/jose/rfc7518/ec_key.py @@ -91,7 +91,7 @@ def dumps_public_key(self): @classmethod def generate_key(cls, crv='P-256', options=None, is_private=False) -> 'ECKey': if crv not in cls.DSS_CURVES: - raise ValueError('Invalid crv value: "{}"'.format(crv)) + raise ValueError(f'Invalid crv value: "{crv}"') raw_key = ec.generate_private_key( curve=cls.DSS_CURVES[crv](), backend=default_backend(), diff --git a/authlib/jose/rfc7518/jwe_algs.py b/authlib/jose/rfc7518/jwe_algs.py index 2ef0b46f..b57654a9 100644 --- a/authlib/jose/rfc7518/jwe_algs.py +++ b/authlib/jose/rfc7518/jwe_algs.py @@ -85,8 +85,8 @@ def unwrap(self, enc_alg, ek, headers, key): class AESAlgorithm(JWEAlgorithm): def __init__(self, key_size): - self.name = 'A{}KW'.format(key_size) - self.description = 'AES Key Wrap using {}-bit key'.format(key_size) + self.name = f'A{key_size}KW' + self.description = f'AES Key Wrap using {key_size}-bit key' self.key_size = key_size def prepare_key(self, raw_data): @@ -99,7 +99,7 @@ def generate_preset(self, enc_alg, key): def _check_key(self, key): if len(key) * 8 != self.key_size: raise ValueError( - 'A key of size {} bits is required.'.format(self.key_size)) + f'A key of size {self.key_size} bits is required.') def wrap_cek(self, cek, key): op_key = key.get_op_key('wrapKey') @@ -127,8 +127,8 @@ class AESGCMAlgorithm(JWEAlgorithm): EXTRA_HEADERS = frozenset(['iv', 'tag']) def __init__(self, key_size): - self.name = 'A{}GCMKW'.format(key_size) - self.description = 'Key wrapping with AES GCM using {}-bit key'.format(key_size) + self.name = f'A{key_size}GCMKW' + self.description = f'Key wrapping with AES GCM using {key_size}-bit key' self.key_size = key_size def prepare_key(self, raw_data): @@ -141,7 +141,7 @@ def generate_preset(self, enc_alg, key): def _check_key(self, key): if len(key) * 8 != self.key_size: raise ValueError( - 'A key of size {} bits is required.'.format(self.key_size)) + f'A key of size {self.key_size} bits is required.') def wrap(self, enc_alg, headers, key, preset=None): if preset and 'cek' in preset: @@ -201,7 +201,7 @@ def __init__(self, key_size=None): self.name = 'ECDH-ES' self.description = 'ECDH-ES in the Direct Key Agreement mode' else: - self.name = 'ECDH-ES+A{}KW'.format(key_size) + self.name = f'ECDH-ES+A{key_size}KW' self.description = ( 'ECDH-ES using Concat KDF and CEK wrapped ' 'with A{}KW').format(key_size) diff --git a/authlib/jose/rfc7518/jwe_encs.py b/authlib/jose/rfc7518/jwe_encs.py index 8d749bfb..f951d101 100644 --- a/authlib/jose/rfc7518/jwe_encs.py +++ b/authlib/jose/rfc7518/jwe_encs.py @@ -25,7 +25,7 @@ class CBCHS2EncAlgorithm(JWEEncAlgorithm): IV_SIZE = 128 def __init__(self, key_size, hash_type): - self.name = 'A{}CBC-HS{}'.format(key_size, hash_type) + self.name = f'A{key_size}CBC-HS{hash_type}' tpl = 'AES_{}_CBC_HMAC_SHA_{} authenticated encryption algorithm' self.description = tpl.format(key_size, hash_type) @@ -35,7 +35,7 @@ def __init__(self, key_size, hash_type): self.key_len = key_size // 8 self.CEK_SIZE = key_size * 2 - self.hash_alg = getattr(hashlib, 'sha{}'.format(hash_type)) + self.hash_alg = getattr(hashlib, f'sha{hash_type}') def _hmac(self, ciphertext, aad, iv, key): al = encode_int(len(aad) * 8, 64) @@ -96,8 +96,8 @@ class GCMEncAlgorithm(JWEEncAlgorithm): IV_SIZE = 96 def __init__(self, key_size): - self.name = 'A{}GCM'.format(key_size) - self.description = 'AES GCM using {}-bit key'.format(key_size) + self.name = f'A{key_size}GCM' + self.description = f'AES GCM using {key_size}-bit key' self.key_size = key_size self.CEK_SIZE = key_size diff --git a/authlib/jose/rfc7518/jws_algs.py b/authlib/jose/rfc7518/jws_algs.py index eae8a9d6..2c028403 100644 --- a/authlib/jose/rfc7518/jws_algs.py +++ b/authlib/jose/rfc7518/jws_algs.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.jose.rfc7518 ~~~~~~~~~~~~~~~~~~~~ @@ -50,9 +49,9 @@ class HMACAlgorithm(JWSAlgorithm): SHA512 = hashlib.sha512 def __init__(self, sha_type): - self.name = 'HS{}'.format(sha_type) - self.description = 'HMAC using SHA-{}'.format(sha_type) - self.hash_alg = getattr(self, 'SHA{}'.format(sha_type)) + self.name = f'HS{sha_type}' + self.description = f'HMAC using SHA-{sha_type}' + self.hash_alg = getattr(self, f'SHA{sha_type}') def prepare_key(self, raw_data): return OctKey.import_key(raw_data) @@ -80,9 +79,9 @@ class RSAAlgorithm(JWSAlgorithm): SHA512 = hashes.SHA512 def __init__(self, sha_type): - self.name = 'RS{}'.format(sha_type) - self.description = 'RSASSA-PKCS1-v1_5 using SHA-{}'.format(sha_type) - self.hash_alg = getattr(self, 'SHA{}'.format(sha_type)) + self.name = f'RS{sha_type}' + self.description = f'RSASSA-PKCS1-v1_5 using SHA-{sha_type}' + self.hash_alg = getattr(self, f'SHA{sha_type}') self.padding = padding.PKCS1v15() def prepare_key(self, raw_data): @@ -116,7 +115,7 @@ def __init__(self, name, curve, sha_type): self.name = name self.curve = curve self.description = f'ECDSA using {self.curve} and SHA-{sha_type}' - self.hash_alg = getattr(self, 'SHA{}'.format(sha_type)) + self.hash_alg = getattr(self, f'SHA{sha_type}') def prepare_key(self, raw_data): key = ECKey.import_key(raw_data) @@ -162,10 +161,10 @@ class RSAPSSAlgorithm(JWSAlgorithm): SHA512 = hashes.SHA512 def __init__(self, sha_type): - self.name = 'PS{}'.format(sha_type) + self.name = f'PS{sha_type}' tpl = 'RSASSA-PSS using SHA-{} and MGF1 with SHA-{}' self.description = tpl.format(sha_type, sha_type) - self.hash_alg = getattr(self, 'SHA{}'.format(sha_type)) + self.hash_alg = getattr(self, f'SHA{sha_type}') def prepare_key(self, raw_data): return RSAKey.import_key(raw_data) diff --git a/authlib/jose/rfc7518/oct_key.py b/authlib/jose/rfc7518/oct_key.py index c2e16b14..1db321a7 100644 --- a/authlib/jose/rfc7518/oct_key.py +++ b/authlib/jose/rfc7518/oct_key.py @@ -13,7 +13,7 @@ class OctKey(Key): REQUIRED_JSON_FIELDS = ['k'] def __init__(self, raw_key=None, options=None): - super(OctKey, self).__init__(options) + super().__init__(options) self.raw_key = raw_key @property diff --git a/authlib/jose/rfc7519/__init__.py b/authlib/jose/rfc7519/__init__.py index b98efc94..5eea5b7f 100644 --- a/authlib/jose/rfc7519/__init__.py +++ b/authlib/jose/rfc7519/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.jose.rfc7519 ~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/jose/rfc7519/claims.py b/authlib/jose/rfc7519/claims.py index 31c42eb0..6a9877bc 100644 --- a/authlib/jose/rfc7519/claims.py +++ b/authlib/jose/rfc7519/claims.py @@ -38,7 +38,7 @@ class BaseClaims(dict): REGISTERED_CLAIMS = [] def __init__(self, payload, header, options=None, params=None): - super(BaseClaims, self).__init__(payload) + super().__init__(payload) self.header = header self.options = options or {} self.params = params or {} diff --git a/authlib/jose/rfc7519/jwt.py b/authlib/jose/rfc7519/jwt.py index caed4471..3737d303 100644 --- a/authlib/jose/rfc7519/jwt.py +++ b/authlib/jose/rfc7519/jwt.py @@ -13,7 +13,7 @@ from ..rfc7517 import KeySet, Key -class JsonWebToken(object): +class JsonWebToken: SENSITIVE_NAMES = ('password', 'token', 'secret', 'secret_key') # Thanks to sentry SensitiveDataFilter SENSITIVE_VALUES = re.compile(r'|'.join([ diff --git a/authlib/jose/rfc8037/okp_key.py b/authlib/jose/rfc8037/okp_key.py index ea05801e..40f74689 100644 --- a/authlib/jose/rfc8037/okp_key.py +++ b/authlib/jose/rfc8037/okp_key.py @@ -95,7 +95,7 @@ def dumps_public_key(self, public_key=None): @classmethod def generate_key(cls, crv='Ed25519', options=None, is_private=False) -> 'OKPKey': if crv not in PRIVATE_KEYS_MAP: - raise ValueError('Invalid crv value: "{}"'.format(crv)) + raise ValueError(f'Invalid crv value: "{crv}"') private_key_cls = PRIVATE_KEYS_MAP[crv] raw_key = private_key_cls.generate() if not is_private: diff --git a/authlib/jose/util.py b/authlib/jose/util.py index adc8ad8b..5b0c759f 100644 --- a/authlib/jose/util.py +++ b/authlib/jose/util.py @@ -9,7 +9,7 @@ def extract_header(header_segment, error_cls): try: header = json_loads(header_data.decode('utf-8')) except ValueError as e: - raise error_cls('Invalid header string: {}'.format(e)) + raise error_cls(f'Invalid header string: {e}') if not isinstance(header, dict): raise error_cls('Header must be a json object') @@ -20,7 +20,7 @@ def extract_segment(segment, error_cls, name='payload'): try: return urlsafe_b64decode(segment) except (TypeError, binascii.Error): - msg = 'Invalid {} padding'.format(name) + msg = f'Invalid {name} padding' raise error_cls(msg) @@ -29,9 +29,9 @@ def ensure_dict(s, structure_name): try: s = json_loads(to_unicode(s)) except (ValueError, TypeError): - raise DecodeError('Invalid {}'.format(structure_name)) + raise DecodeError(f'Invalid {structure_name}') if not isinstance(s, dict): - raise DecodeError('Invalid {}'.format(structure_name)) + raise DecodeError(f'Invalid {structure_name}') return s diff --git a/authlib/oauth1/__init__.py b/authlib/oauth1/__init__.py index af1ba079..c9a73ddf 100644 --- a/authlib/oauth1/__init__.py +++ b/authlib/oauth1/__init__.py @@ -1,5 +1,3 @@ -# coding: utf-8 - from .rfc5849 import ( OAuth1Request, ClientAuth, diff --git a/authlib/oauth1/client.py b/authlib/oauth1/client.py index aa01c260..1f74f321 100644 --- a/authlib/oauth1/client.py +++ b/authlib/oauth1/client.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from authlib.common.urls import ( url_decode, add_params_to_uri, @@ -12,7 +11,7 @@ ) -class OAuth1Client(object): +class OAuth1Client: auth_class = ClientAuth def __init__(self, session, client_id, client_secret=None, @@ -71,7 +70,7 @@ def token(self, token): if 'oauth_verifier' in token: self.auth.verifier = token['oauth_verifier'] else: - message = 'oauth_token is missing: {!r}'.format(token) + message = f'oauth_token is missing: {token!r}' self.handle_error('missing_token', message) def create_authorization_url(self, url, request_token=None, **kwargs): @@ -170,4 +169,4 @@ def parse_response_token(self, status_code, text): @staticmethod def handle_error(error_type, error_description): - raise ValueError('{}: {}'.format(error_type, error_description)) + raise ValueError(f'{error_type}: {error_description}') diff --git a/authlib/oauth1/rfc5849/base_server.py b/authlib/oauth1/rfc5849/base_server.py index 46898bb2..5d29deb9 100644 --- a/authlib/oauth1/rfc5849/base_server.py +++ b/authlib/oauth1/rfc5849/base_server.py @@ -18,7 +18,7 @@ ) -class BaseServer(object): +class BaseServer: SIGNATURE_METHODS = { SIGNATURE_HMAC_SHA1: verify_hmac_sha1, SIGNATURE_RSA_SHA1: verify_rsa_sha1, diff --git a/authlib/oauth1/rfc5849/client_auth.py b/authlib/oauth1/rfc5849/client_auth.py index 41b9e0ce..2c59b594 100644 --- a/authlib/oauth1/rfc5849/client_auth.py +++ b/authlib/oauth1/rfc5849/client_auth.py @@ -29,7 +29,7 @@ CONTENT_TYPE_MULTI_PART = 'multipart/form-data' -class ClientAuth(object): +class ClientAuth: SIGNATURE_METHODS = { SIGNATURE_HMAC_SHA1: sign_hmac_sha1, SIGNATURE_RSA_SHA1: sign_rsa_sha1, diff --git a/authlib/oauth1/rfc5849/errors.py b/authlib/oauth1/rfc5849/errors.py index 0eea07bd..93396fce 100644 --- a/authlib/oauth1/rfc5849/errors.py +++ b/authlib/oauth1/rfc5849/errors.py @@ -13,7 +13,7 @@ class OAuth1Error(AuthlibHTTPError): def __init__(self, description=None, uri=None, status_code=None): - super(OAuth1Error, self).__init__(None, description, uri, status_code) + super().__init__(None, description, uri, status_code) def get_headers(self): """Get a list of headers.""" @@ -51,7 +51,7 @@ class MissingRequiredParameterError(OAuth1Error): def __init__(self, key): description = f'missing "{key}" in parameters' - super(MissingRequiredParameterError, self).__init__(description=description) + super().__init__(description=description) class DuplicatedOAuthProtocolParameterError(OAuth1Error): diff --git a/authlib/oauth1/rfc5849/models.py b/authlib/oauth1/rfc5849/models.py index 76befe9d..c9f3ea61 100644 --- a/authlib/oauth1/rfc5849/models.py +++ b/authlib/oauth1/rfc5849/models.py @@ -1,5 +1,4 @@ - -class ClientMixin(object): +class ClientMixin: def get_default_redirect_uri(self): """A method to get client default redirect_uri. For instance, the database table for client has a column called ``default_redirect_uri``:: @@ -30,7 +29,7 @@ def get_rsa_public_key(self): raise NotImplementedError() -class TokenCredentialMixin(object): +class TokenCredentialMixin: def get_oauth_token(self): """A method to get the value of ``oauth_token``. For instance, the database table has a column called ``oauth_token``:: diff --git a/authlib/oauth1/rfc5849/parameters.py b/authlib/oauth1/rfc5849/parameters.py index 4746aeaa..0e64e5c6 100644 --- a/authlib/oauth1/rfc5849/parameters.py +++ b/authlib/oauth1/rfc5849/parameters.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """ authlib.spec.rfc5849.parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -38,7 +36,7 @@ def prepare_headers(oauth_params, headers=None, realm=None): # step 1, 2, 3 in Section 3.5.1 header_parameters = ', '.join([ - '{0}="{1}"'.format(escape(k), escape(v)) for k, v in oauth_params + f'{escape(k)}="{escape(v)}"' for k, v in oauth_params if k.startswith('oauth_') ]) @@ -48,10 +46,10 @@ def prepare_headers(oauth_params, headers=None, realm=None): # .. _`RFC2617 section 1.2`: https://tools.ietf.org/html/rfc2617#section-1.2 if realm: # NOTE: realm should *not* be escaped - header_parameters = 'realm="{}", '.format(realm) + header_parameters + header_parameters = f'realm="{realm}", ' + header_parameters # the auth-scheme name set to "OAuth" (case insensitive). - headers['Authorization'] = 'OAuth {}'.format(header_parameters) + headers['Authorization'] = f'OAuth {header_parameters}' return headers diff --git a/authlib/oauth1/rfc5849/signature.py b/authlib/oauth1/rfc5849/signature.py index 6ba67e2d..bfb87fee 100644 --- a/authlib/oauth1/rfc5849/signature.py +++ b/authlib/oauth1/rfc5849/signature.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth1.rfc5849.signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -234,7 +233,7 @@ def normalize_parameters(params): # 3. The name of each parameter is concatenated to its corresponding # value using an "=" character (ASCII code 61) as a separator, even # if the value is empty. - parameter_parts = ['{0}={1}'.format(k, v) for k, v in key_values] + parameter_parts = [f'{k}={v}' for k, v in key_values] # 4. The sorted name/value pairs are concatenated together into a # single string by using an "&" character (ASCII code 38) as diff --git a/authlib/oauth1/rfc5849/wrapper.py b/authlib/oauth1/rfc5849/wrapper.py index 25b3fc9c..c03687ed 100644 --- a/authlib/oauth1/rfc5849/wrapper.py +++ b/authlib/oauth1/rfc5849/wrapper.py @@ -14,7 +14,7 @@ from .util import unescape -class OAuth1Request(object): +class OAuth1Request: def __init__(self, method, uri, body=None, headers=None): InsecureTransportError.check(uri) self.method = method diff --git a/authlib/oauth2/auth.py b/authlib/oauth2/auth.py index c7bf5a31..c87241a9 100644 --- a/authlib/oauth2/auth.py +++ b/authlib/oauth2/auth.py @@ -6,9 +6,9 @@ def encode_client_secret_basic(client, method, uri, headers, body): - text = '{}:{}'.format(client.client_id, client.client_secret) + text = f'{client.client_id}:{client.client_secret}' auth = to_native(base64.b64encode(to_bytes(text, 'latin1'))) - headers['Authorization'] = 'Basic {}'.format(auth) + headers['Authorization'] = f'Basic {auth}' return uri, headers, body @@ -32,7 +32,7 @@ def encode_none(client, method, uri, headers, body): return uri, headers, body -class ClientAuth(object): +class ClientAuth: """Attaches OAuth Client Information to HTTP requests. :param client_id: Client ID, which you get from client registration. @@ -66,7 +66,7 @@ def prepare(self, method, uri, headers, body): return self.auth_method(self, method, uri, headers, body) -class TokenAuth(object): +class TokenAuth: """Attach token information to HTTP requests. :param token: A dict or OAuth2Token instance of an OAuth 2.0 token diff --git a/authlib/oauth2/base.py b/authlib/oauth2/base.py index 97300c20..9bcb15f8 100644 --- a/authlib/oauth2/base.py +++ b/authlib/oauth2/base.py @@ -6,14 +6,14 @@ class OAuth2Error(AuthlibHTTPError): def __init__(self, description=None, uri=None, status_code=None, state=None, redirect_uri=None, redirect_fragment=False, error=None): - super(OAuth2Error, self).__init__(error, description, uri, status_code) + super().__init__(error, description, uri, status_code) self.state = state self.redirect_uri = redirect_uri self.redirect_fragment = redirect_fragment def get_body(self): """Get a list of body.""" - error = super(OAuth2Error, self).get_body() + error = super().get_body() if self.state: error.append(('state', self.state)) return error @@ -23,4 +23,4 @@ def __call__(self, uri=None): params = self.get_body() loc = add_params_to_uri(self.redirect_uri, params, self.redirect_fragment) return 302, '', [('Location', loc)] - return super(OAuth2Error, self).__call__(uri=uri) + return super().__call__(uri=uri) diff --git a/authlib/oauth2/client.py b/authlib/oauth2/client.py index c6eeb329..3ccdfd4a 100644 --- a/authlib/oauth2/client.py +++ b/authlib/oauth2/client.py @@ -17,7 +17,7 @@ } -class OAuth2Client(object): +class OAuth2Client: """Construct a new OAuth 2 protocol client. :param session: Requests session object to communicate with diff --git a/authlib/oauth2/rfc6749/__init__.py b/authlib/oauth2/rfc6749/__init__.py index 959de522..e1748e3d 100644 --- a/authlib/oauth2/rfc6749/__init__.py +++ b/authlib/oauth2/rfc6749/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth2.rfc6749 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/oauth2/rfc6749/authenticate_client.py b/authlib/oauth2/rfc6749/authenticate_client.py index a61113b6..adcfd25f 100644 --- a/authlib/oauth2/rfc6749/authenticate_client.py +++ b/authlib/oauth2/rfc6749/authenticate_client.py @@ -24,7 +24,7 @@ __all__ = ['ClientAuthentication'] -class ClientAuthentication(object): +class ClientAuthentication: def __init__(self, query_client): self.query_client = query_client self._methods = { diff --git a/authlib/oauth2/rfc6749/authorization_server.py b/authlib/oauth2/rfc6749/authorization_server.py index d92f4283..e5d4a67a 100644 --- a/authlib/oauth2/rfc6749/authorization_server.py +++ b/authlib/oauth2/rfc6749/authorization_server.py @@ -9,7 +9,7 @@ from .util import scope_to_list -class AuthorizationServer(object): +class AuthorizationServer: """Authorization server that handles Authorization Endpoint and Token Endpoint. diff --git a/authlib/oauth2/rfc6749/errors.py b/authlib/oauth2/rfc6749/errors.py index 53c2dff6..63ffb47e 100644 --- a/authlib/oauth2/rfc6749/errors.py +++ b/authlib/oauth2/rfc6749/errors.py @@ -86,14 +86,14 @@ class InvalidClientError(OAuth2Error): status_code = 400 def get_headers(self): - headers = super(InvalidClientError, self).get_headers() + headers = super().get_headers() if self.status_code == 401: error_description = self.get_error_description() # safe escape error_description = error_description.replace('"', '|') extras = [ - 'error="{}"'.format(self.error), - 'error_description="{}"'.format(error_description) + f'error="{self.error}"', + f'error_description="{error_description}"' ] headers.append( ('WWW-Authenticate', 'Basic ' + ', '.join(extras)) @@ -128,7 +128,7 @@ class UnsupportedResponseTypeError(OAuth2Error): error = 'unsupported_response_type' def __init__(self, response_type): - super(UnsupportedResponseTypeError, self).__init__() + super().__init__() self.response_type = response_type def get_error_description(self): @@ -144,7 +144,7 @@ class UnsupportedGrantTypeError(OAuth2Error): error = 'unsupported_grant_type' def __init__(self, grant_type): - super(UnsupportedGrantTypeError, self).__init__() + super().__init__() self.grant_type = grant_type def get_error_description(self): @@ -180,21 +180,21 @@ class ForbiddenError(OAuth2Error): status_code = 401 def __init__(self, auth_type=None, realm=None): - super(ForbiddenError, self).__init__() + super().__init__() self.auth_type = auth_type self.realm = realm def get_headers(self): - headers = super(ForbiddenError, self).get_headers() + headers = super().get_headers() if not self.auth_type: return headers extras = [] if self.realm: - extras.append('realm="{}"'.format(self.realm)) - extras.append('error="{}"'.format(self.error)) + extras.append(f'realm="{self.realm}"') + extras.append(f'error="{self.error}"') error_description = self.description - extras.append('error_description="{}"'.format(error_description)) + extras.append(f'error_description="{error_description}"') headers.append( ('WWW-Authenticate', f'{self.auth_type} ' + ', '.join(extras)) ) diff --git a/authlib/oauth2/rfc6749/grants/base.py b/authlib/oauth2/rfc6749/grants/base.py index 97ce90a1..0d2bf453 100644 --- a/authlib/oauth2/rfc6749/grants/base.py +++ b/authlib/oauth2/rfc6749/grants/base.py @@ -3,7 +3,7 @@ from ..errors import InvalidRequestError -class BaseGrant(object): +class BaseGrant: #: Allowed client auth methods for token endpoint TOKEN_ENDPOINT_AUTH_METHODS = ['client_secret_basic'] @@ -93,7 +93,7 @@ def execute_hook(self, hook_type, *args, **kwargs): hook(self, *args, **kwargs) -class TokenEndpointMixin(object): +class TokenEndpointMixin: #: Allowed HTTP methods of this token endpoint TOKEN_ENDPOINT_HTTP_METHODS = ['POST'] @@ -112,7 +112,7 @@ def create_token_response(self): raise NotImplementedError() -class AuthorizationEndpointMixin(object): +class AuthorizationEndpointMixin: RESPONSE_TYPES = set() ERROR_RESPONSE_FRAGMENT = False diff --git a/authlib/oauth2/rfc6749/models.py b/authlib/oauth2/rfc6749/models.py index 45996008..fe4922bb 100644 --- a/authlib/oauth2/rfc6749/models.py +++ b/authlib/oauth2/rfc6749/models.py @@ -7,7 +7,7 @@ from authlib.deprecate import deprecate -class ClientMixin(object): +class ClientMixin: """Implementation of OAuth 2 Client described in `Section 2`_ with some methods to help validation. A client has at least these information: @@ -146,7 +146,7 @@ def check_grant_type(self, grant_type): raise NotImplementedError() -class AuthorizationCodeMixin(object): +class AuthorizationCodeMixin: def get_redirect_uri(self): """A method to get authorization code's ``redirect_uri``. For instance, the database table for authorization code has a @@ -171,7 +171,7 @@ def get_scope(self): raise NotImplementedError() -class TokenMixin(object): +class TokenMixin: def check_client(self, client): """A method to check if this token is issued to the given client. For instance, ``client_id`` is saved on token table:: diff --git a/authlib/oauth2/rfc6749/requests.py b/authlib/oauth2/rfc6749/requests.py index a4ba19f3..1c0e4859 100644 --- a/authlib/oauth2/rfc6749/requests.py +++ b/authlib/oauth2/rfc6749/requests.py @@ -3,7 +3,7 @@ from .errors import InsecureTransportError -class OAuth2Request(object): +class OAuth2Request: def __init__(self, method: str, uri: str, body=None, headers=None): InsecureTransportError.check(uri) #: HTTP method @@ -72,7 +72,7 @@ def state(self): return self.data.get('state') -class JsonRequest(object): +class JsonRequest: def __init__(self, method, uri, body=None, headers=None): self.method = method self.uri = uri diff --git a/authlib/oauth2/rfc6749/resource_protector.py b/authlib/oauth2/rfc6749/resource_protector.py index 6be8b13a..1964bc3d 100644 --- a/authlib/oauth2/rfc6749/resource_protector.py +++ b/authlib/oauth2/rfc6749/resource_protector.py @@ -10,7 +10,7 @@ from .errors import MissingAuthorizationError, UnsupportedTokenTypeError -class TokenValidator(object): +class TokenValidator: """Base token validator class. Subclass this validator to register into ResourceProtector instance. """ @@ -81,7 +81,7 @@ def validate_token(self, token, scopes, request): raise NotImplementedError() -class ResourceProtector(object): +class ResourceProtector: def __init__(self): self._token_validators = {} self._default_realm = None diff --git a/authlib/oauth2/rfc6749/token_endpoint.py b/authlib/oauth2/rfc6749/token_endpoint.py index fb0bd403..0ede557f 100644 --- a/authlib/oauth2/rfc6749/token_endpoint.py +++ b/authlib/oauth2/rfc6749/token_endpoint.py @@ -1,4 +1,4 @@ -class TokenEndpoint(object): +class TokenEndpoint: #: Endpoint name to be registered ENDPOINT_NAME = None #: Supported token types diff --git a/authlib/oauth2/rfc6749/wrappers.py b/authlib/oauth2/rfc6749/wrappers.py index 479ef326..2ecf8248 100644 --- a/authlib/oauth2/rfc6749/wrappers.py +++ b/authlib/oauth2/rfc6749/wrappers.py @@ -8,7 +8,7 @@ def __init__(self, params): elif params.get('expires_in'): params['expires_at'] = int(time.time()) + \ int(params['expires_in']) - super(OAuth2Token, self).__init__(params) + super().__init__(params) def is_expired(self): expires_at = self.get('expires_at') diff --git a/authlib/oauth2/rfc6750/__init__.py b/authlib/oauth2/rfc6750/__init__.py index ac88cce4..ef3880ba 100644 --- a/authlib/oauth2/rfc6750/__init__.py +++ b/authlib/oauth2/rfc6750/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth2.rfc6750 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/oauth2/rfc6750/errors.py b/authlib/oauth2/rfc6750/errors.py index 3ce462a3..1be92a35 100644 --- a/authlib/oauth2/rfc6750/errors.py +++ b/authlib/oauth2/rfc6750/errors.py @@ -36,7 +36,7 @@ class InvalidTokenError(OAuth2Error): def __init__(self, description=None, uri=None, status_code=None, state=None, realm=None, **extra_attributes): - super(InvalidTokenError, self).__init__( + super().__init__( description, uri, status_code, state) self.realm = realm self.extra_attributes = extra_attributes @@ -50,7 +50,7 @@ def get_headers(self): https://tools.ietf.org/html/rfc6750#section-3 """ - headers = super(InvalidTokenError, self).get_headers() + headers = super().get_headers() extras = [] if self.realm: diff --git a/authlib/oauth2/rfc6750/parameters.py b/authlib/oauth2/rfc6750/parameters.py index 5f4e1006..8914a909 100644 --- a/authlib/oauth2/rfc6750/parameters.py +++ b/authlib/oauth2/rfc6750/parameters.py @@ -17,7 +17,7 @@ def add_to_headers(token, headers=None): Authorization: Bearer h480djs93hd8 """ headers = headers or {} - headers['Authorization'] = 'Bearer {}'.format(token) + headers['Authorization'] = f'Bearer {token}' return headers diff --git a/authlib/oauth2/rfc6750/token.py b/authlib/oauth2/rfc6750/token.py index a9276509..1ab4dc5b 100644 --- a/authlib/oauth2/rfc6750/token.py +++ b/authlib/oauth2/rfc6750/token.py @@ -1,4 +1,4 @@ -class BearerTokenGenerator(object): +class BearerTokenGenerator: """Bearer token generator which can create the payload for token response by OAuth 2 server. A typical token response would be: diff --git a/authlib/oauth2/rfc7009/__init__.py b/authlib/oauth2/rfc7009/__init__.py index 0b8bc7f2..2b9c1202 100644 --- a/authlib/oauth2/rfc7009/__init__.py +++ b/authlib/oauth2/rfc7009/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth2.rfc7009 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/oauth2/rfc7521/client.py b/authlib/oauth2/rfc7521/client.py index 6d0ade66..e7ce2c3c 100644 --- a/authlib/oauth2/rfc7521/client.py +++ b/authlib/oauth2/rfc7521/client.py @@ -2,7 +2,7 @@ from authlib.oauth2.base import OAuth2Error -class AssertionClient(object): +class AssertionClient: """Constructs a new Assertion Framework for OAuth 2.0 Authorization Grants per RFC7521_. diff --git a/authlib/oauth2/rfc7523/__init__.py b/authlib/oauth2/rfc7523/__init__.py index 627992b8..ec9d3d32 100644 --- a/authlib/oauth2/rfc7523/__init__.py +++ b/authlib/oauth2/rfc7523/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth2.rfc7523 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/oauth2/rfc7523/auth.py b/authlib/oauth2/rfc7523/auth.py index bd537552..77644667 100644 --- a/authlib/oauth2/rfc7523/auth.py +++ b/authlib/oauth2/rfc7523/auth.py @@ -3,7 +3,7 @@ from .client import ASSERTION_TYPE -class ClientSecretJWT(object): +class ClientSecretJWT: """Authentication method for OAuth 2.0 Client. This authentication method is called ``client_secret_jwt``, which is using ``client_id`` and ``client_secret`` constructed with JWT to identify a client. diff --git a/authlib/oauth2/rfc7523/client.py b/authlib/oauth2/rfc7523/client.py index 8127c7be..2a6a1bfc 100644 --- a/authlib/oauth2/rfc7523/client.py +++ b/authlib/oauth2/rfc7523/client.py @@ -7,7 +7,7 @@ log = logging.getLogger(__name__) -class JWTBearerClientAssertion(object): +class JWTBearerClientAssertion: """Implementation of Using JWTs for Client Authentication, which is defined by RFC7523. """ diff --git a/authlib/oauth2/rfc7523/token.py b/authlib/oauth2/rfc7523/token.py index 6f826605..27fab5f4 100644 --- a/authlib/oauth2/rfc7523/token.py +++ b/authlib/oauth2/rfc7523/token.py @@ -3,7 +3,7 @@ from authlib.jose import jwt -class JWTBearerTokenGenerator(object): +class JWTBearerTokenGenerator: """A JSON Web Token formatted bearer token generator for jwt-bearer grant type. This token generator can be registered into authorization server:: diff --git a/authlib/oauth2/rfc7523/validator.py b/authlib/oauth2/rfc7523/validator.py index bbbff41b..f2423b8a 100644 --- a/authlib/oauth2/rfc7523/validator.py +++ b/authlib/oauth2/rfc7523/validator.py @@ -29,7 +29,7 @@ class JWTBearerTokenValidator(BearerTokenValidator): token_cls = JWTBearerToken def __init__(self, public_key, issuer=None, realm=None, **extra_attributes): - super(JWTBearerTokenValidator, self).__init__(realm, **extra_attributes) + super().__init__(realm, **extra_attributes) self.public_key = public_key claims_options = { 'exp': {'essential': True}, diff --git a/authlib/oauth2/rfc7591/endpoint.py b/authlib/oauth2/rfc7591/endpoint.py index 6104fcfa..d26e0614 100644 --- a/authlib/oauth2/rfc7591/endpoint.py +++ b/authlib/oauth2/rfc7591/endpoint.py @@ -14,7 +14,7 @@ ) -class ClientRegistrationEndpoint(object): +class ClientRegistrationEndpoint: """The client registration endpoint is an OAuth 2.0 endpoint designed to allow a client to be registered with the authorization server. """ diff --git a/authlib/oauth2/rfc7592/endpoint.py b/authlib/oauth2/rfc7592/endpoint.py index 5508c3cc..cec9aad1 100644 --- a/authlib/oauth2/rfc7592/endpoint.py +++ b/authlib/oauth2/rfc7592/endpoint.py @@ -9,7 +9,7 @@ from ..rfc7591 import InvalidClientMetadataError -class ClientConfigurationEndpoint(object): +class ClientConfigurationEndpoint: ENDPOINT_NAME = 'client_configuration' #: The claims validation class diff --git a/authlib/oauth2/rfc7636/__init__.py b/authlib/oauth2/rfc7636/__init__.py index d943f3e1..c03043bd 100644 --- a/authlib/oauth2/rfc7636/__init__.py +++ b/authlib/oauth2/rfc7636/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth2.rfc7636 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/oauth2/rfc7636/challenge.py b/authlib/oauth2/rfc7636/challenge.py index 63211279..8303092e 100644 --- a/authlib/oauth2/rfc7636/challenge.py +++ b/authlib/oauth2/rfc7636/challenge.py @@ -28,7 +28,7 @@ def compare_s256_code_challenge(code_verifier, code_challenge): return create_s256_code_challenge(code_verifier) == code_challenge -class CodeChallenge(object): +class CodeChallenge: """CodeChallenge extension to Authorization Code Grant. It is used to improve the security of Authorization Code flow for public clients by sending extra "code_challenge" and "code_verifier" to the authorization @@ -108,7 +108,7 @@ def validate_code_verifier(self, grant): func = self.CODE_CHALLENGE_METHODS.get(method) if not func: - raise RuntimeError('No verify method for "{}"'.format(method)) + raise RuntimeError(f'No verify method for "{method}"') # If the values are not equal, an error response indicating # "invalid_grant" MUST be returned. diff --git a/authlib/oauth2/rfc7662/__init__.py b/authlib/oauth2/rfc7662/__init__.py index 9be72256..045aeda5 100644 --- a/authlib/oauth2/rfc7662/__init__.py +++ b/authlib/oauth2/rfc7662/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth2.rfc7662 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/oauth2/rfc8414/__init__.py b/authlib/oauth2/rfc8414/__init__.py index 2cdbfbdc..b1b151c5 100644 --- a/authlib/oauth2/rfc8414/__init__.py +++ b/authlib/oauth2/rfc8414/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth2.rfc8414 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/oauth2/rfc8414/models.py b/authlib/oauth2/rfc8414/models.py index 3e89a5c9..2dc790bd 100644 --- a/authlib/oauth2/rfc8414/models.py +++ b/authlib/oauth2/rfc8414/models.py @@ -335,7 +335,7 @@ def introspection_endpoint_auth_methods_supported(self): def validate(self): """Validate all server metadata value.""" for key in self.REGISTRY_KEYS: - object.__getattribute__(self, 'validate_{}'.format(key))() + object.__getattribute__(self, f'validate_{key}')() def __getattr__(self, key): try: @@ -349,20 +349,20 @@ def __getattr__(self, key): def _validate_alg_values(data, key, auth_methods_supported): value = data.get(key) if value and not isinstance(value, list): - raise ValueError('"{}" MUST be JSON array'.format(key)) + raise ValueError(f'"{key}" MUST be JSON array') auth_methods = set(auth_methods_supported) jwt_auth_methods = {'private_key_jwt', 'client_secret_jwt'} if auth_methods & jwt_auth_methods: if not value: - raise ValueError('"{}" is required'.format(key)) + raise ValueError(f'"{key}" is required') if value and 'none' in value: raise ValueError( - 'the value "none" MUST NOT be used in "{}"'.format(key)) + f'the value "none" MUST NOT be used in "{key}"') def validate_array_value(metadata, key): values = metadata.get(key) if values is not None and not isinstance(values, list): - raise ValueError('"{}" MUST be JSON array'.format(key)) + raise ValueError(f'"{key}" MUST be JSON array') diff --git a/authlib/oauth2/rfc8414/well_known.py b/authlib/oauth2/rfc8414/well_known.py index dc948d88..42d70b3b 100644 --- a/authlib/oauth2/rfc8414/well_known.py +++ b/authlib/oauth2/rfc8414/well_known.py @@ -14,9 +14,9 @@ def get_well_known_url(issuer, external=False, suffix='oauth-authorization-serve parsed = urlparse.urlparse(issuer) path = parsed.path if path and path != '/': - url_path = '/.well-known/{}{}'.format(suffix, path) + url_path = f'/.well-known/{suffix}{path}' else: - url_path = '/.well-known/{}'.format(suffix) + url_path = f'/.well-known/{suffix}' if not external: return url_path return parsed.scheme + '://' + parsed.netloc + url_path diff --git a/authlib/oauth2/rfc8628/__init__.py b/authlib/oauth2/rfc8628/__init__.py index 2d4447f8..6ad59fdf 100644 --- a/authlib/oauth2/rfc8628/__init__.py +++ b/authlib/oauth2/rfc8628/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth2.rfc8628 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/oauth2/rfc8628/endpoint.py b/authlib/oauth2/rfc8628/endpoint.py index 5bcdb9fc..49221f09 100644 --- a/authlib/oauth2/rfc8628/endpoint.py +++ b/authlib/oauth2/rfc8628/endpoint.py @@ -3,7 +3,7 @@ from authlib.common.urls import add_params_to_uri -class DeviceAuthorizationEndpoint(object): +class DeviceAuthorizationEndpoint: """This OAuth 2.0 [RFC6749] protocol extension enables OAuth clients to request user authorization from applications on devices that have limited input capabilities or lack a suitable browser. Such devices diff --git a/authlib/oauth2/rfc8628/models.py b/authlib/oauth2/rfc8628/models.py index 0ec1e366..39eb9a13 100644 --- a/authlib/oauth2/rfc8628/models.py +++ b/authlib/oauth2/rfc8628/models.py @@ -1,7 +1,7 @@ import time -class DeviceCredentialMixin(object): +class DeviceCredentialMixin: def get_client_id(self): raise NotImplementedError() diff --git a/authlib/oauth2/rfc8693/__init__.py b/authlib/oauth2/rfc8693/__init__.py index 110b3874..1a74f856 100644 --- a/authlib/oauth2/rfc8693/__init__.py +++ b/authlib/oauth2/rfc8693/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ authlib.oauth2.rfc8693 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/authlib/oidc/core/claims.py b/authlib/oidc/core/claims.py index ca6958f7..f8674585 100644 --- a/authlib/oidc/core/claims.py +++ b/authlib/oidc/core/claims.py @@ -173,7 +173,7 @@ def validate_at_hash(self): access_token = self.params.get('access_token') if access_token and 'at_hash' not in self: raise MissingClaimError('at_hash') - super(ImplicitIDToken, self).validate_at_hash() + super().validate_at_hash() class HybridIDToken(ImplicitIDToken): @@ -181,7 +181,7 @@ class HybridIDToken(ImplicitIDToken): REGISTERED_CLAIMS = _REGISTERED_CLAIMS + ['c_hash'] def validate(self, now=None, leeway=0): - super(HybridIDToken, self).validate(now=now, leeway=leeway) + super().validate(now=now, leeway=leeway) self.validate_c_hash() def validate_c_hash(self): diff --git a/authlib/oidc/core/grants/code.py b/authlib/oidc/core/grants/code.py index 68d740a2..9ac3bfbb 100644 --- a/authlib/oidc/core/grants/code.py +++ b/authlib/oidc/core/grants/code.py @@ -20,7 +20,7 @@ log = logging.getLogger(__name__) -class OpenIDToken(object): +class OpenIDToken: def get_jwt_config(self, grant): # pragma: no cover """Get the JWT configuration for OpenIDCode extension. The JWT configuration will be used to generate ``id_token``. Developers diff --git a/authlib/oidc/core/grants/implicit.py b/authlib/oidc/core/grants/implicit.py index a498f45d..15bc1fac 100644 --- a/authlib/oidc/core/grants/implicit.py +++ b/authlib/oidc/core/grants/implicit.py @@ -85,7 +85,7 @@ def validate_authorization_request(self): redirect_uri=self.request.redirect_uri, redirect_fragment=True, ) - redirect_uri = super(OpenIDImplicitGrant, self).validate_authorization_request() + redirect_uri = super().validate_authorization_request() try: validate_nonce(self.request, self.exists_nonce, required=True) except OAuth2Error as error: diff --git a/authlib/oidc/core/util.py b/authlib/oidc/core/util.py index 37d23ded..6df005d2 100644 --- a/authlib/oidc/core/util.py +++ b/authlib/oidc/core/util.py @@ -3,7 +3,7 @@ def create_half_hash(s, alg): - hash_type = 'sha{}'.format(alg[2:]) + hash_type = f'sha{alg[2:]}' hash_alg = getattr(hashlib, hash_type, None) if not hash_alg: return None diff --git a/authlib/oidc/discovery/models.py b/authlib/oidc/discovery/models.py index db1a8046..d9329efd 100644 --- a/authlib/oidc/discovery/models.py +++ b/authlib/oidc/discovery/models.py @@ -48,7 +48,7 @@ def validate_jwks_uri(self): jwks_uri = self.get('jwks_uri') if jwks_uri is None: raise ValueError('"jwks_uri" is required') - return super(OpenIDProviderMetadata, self).validate_jwks_uri() + return super().validate_jwks_uri() def validate_acr_values_supported(self): """OPTIONAL. JSON array containing a list of the Authentication @@ -280,4 +280,4 @@ def _validate_boolean_value(metadata, key): if key not in metadata: return if metadata[key] not in (True, False): - raise ValueError('"{}" MUST be boolean'.format(key)) + raise ValueError(f'"{key}" MUST be boolean') diff --git a/docs/changelog.rst b/docs/changelog.rst index 84abe891..e252decd 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,6 +6,8 @@ Changelog Here you can see the full list of changes between each Authlib release. +- End support for python 3.7 + Version 1.2.1 ------------- diff --git a/docs/conf.py b/docs/conf.py index e2fdff43..7ba1f6e6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,8 +1,8 @@ import authlib -project = u'Authlib' -copyright = u'© 2017, Hsiaoming Ltd' -author = u'Hsiaoming Yang' +project = 'Authlib' +copyright = '© 2017, Hsiaoming Ltd' +author = 'Hsiaoming Yang' version = authlib.__version__ release = version diff --git a/setup.cfg b/setup.cfg index d3d3cfcb..88919dd6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,7 +24,6 @@ classifiers = Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 3 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 diff --git a/tests/clients/test_django/test_oauth_client.py b/tests/clients/test_django/test_oauth_client.py index 274f1f9a..a2f402c7 100644 --- a/tests/clients/test_django/test_oauth_client.py +++ b/tests/clients/test_django/test_oauth_client.py @@ -110,7 +110,7 @@ def test_oauth2_authorize(self): with mock.patch('requests.sessions.Session.send') as send: send.return_value = mock_send_value(get_bearer_token()) - request2 = self.factory.get('/authorize?state={}'.format(state)) + request2 = self.factory.get(f'/authorize?state={state}') request2.session = request.session token = client.authorize_access_token(request2) @@ -156,11 +156,11 @@ def test_oauth2_authorize_code_challenge(self): verifier = state_data['code_verifier'] def fake_send(sess, req, **kwargs): - self.assertIn('code_verifier={}'.format(verifier), req.body) + self.assertIn(f'code_verifier={verifier}', req.body) return mock_send_value(get_bearer_token()) with mock.patch('requests.sessions.Session.send', fake_send): - request2 = self.factory.get('/authorize?state={}'.format(state)) + request2 = self.factory.get(f'/authorize?state={state}') request2.session = request.session token = client.authorize_access_token(request2) self.assertEqual(token['access_token'], 'a') @@ -192,7 +192,7 @@ def test_oauth2_authorize_code_verifier(self): with mock.patch('requests.sessions.Session.send') as send: send.return_value = mock_send_value(get_bearer_token()) - request2 = self.factory.get('/authorize?state={}'.format(state)) + request2 = self.factory.get(f'/authorize?state={state}') request2.session = request.session token = client.authorize_access_token(request2) @@ -230,7 +230,7 @@ def test_openid_authorize(self): with mock.patch('requests.sessions.Session.send') as send: send.return_value = mock_send_value(token) - request2 = self.factory.get('/authorize?state={}&code=foo'.format(state)) + request2 = self.factory.get(f'/authorize?state={state}&code=foo') request2.session = request.session token = client.authorize_access_token(request2) diff --git a/tests/clients/test_flask/test_oauth_client.py b/tests/clients/test_flask/test_oauth_client.py index 07898220..9f0bde6f 100644 --- a/tests/clients/test_flask/test_oauth_client.py +++ b/tests/clients/test_flask/test_oauth_client.py @@ -320,7 +320,7 @@ def fake_send(sess, req, **kwargs): self.assertIn(f'code_verifier={verifier}', req.body) return mock_send_value(get_bearer_token()) - path = '/?code=a&state={}'.format(state) + path = f'/?code=a&state={state}' with app.test_request_context(path=path): # session is cleared in tests session[f'_state_dev_{state}'] = data @@ -365,7 +365,7 @@ def test_openid_authorize(self): alg='HS256', iss='https://i.b', aud='dev', exp=3600, nonce=query_data['nonce'], ) - path = '/?code=a&state={}'.format(state) + path = f'/?code=a&state={state}' with app.test_request_context(path=path): session[f'_state_dev_{state}'] = session_data with mock.patch('requests.sessions.Session.send') as send: diff --git a/tests/clients/test_requests/test_oauth2_session.py b/tests/clients/test_requests/test_oauth2_session.py index fd26da64..8afc8dea 100644 --- a/tests/clients/test_requests/test_oauth2_session.py +++ b/tests/clients/test_requests/test_oauth2_session.py @@ -57,7 +57,7 @@ def test_add_token_to_header(self): token = 'Bearer ' + self.token['access_token'] def verifier(r, **kwargs): - auth_header = r.headers.get(str('Authorization'), None) + auth_header = r.headers.get('Authorization', None) self.assertEqual(auth_header, token) resp = mock.MagicMock() return resp @@ -493,7 +493,7 @@ def test_use_client_token_auth(self): token = 'Bearer ' + self.token['access_token'] def verifier(r, **kwargs): - auth_header = r.headers.get(str('Authorization'), None) + auth_header = r.headers.get('Authorization', None) self.assertEqual(auth_header, token) resp = mock.MagicMock() return resp diff --git a/tests/clients/test_starlette/test_oauth_client.py b/tests/clients/test_starlette/test_oauth_client.py index 6052eca7..8796a96b 100644 --- a/tests/clients/test_starlette/test_oauth_client.py +++ b/tests/clients/test_starlette/test_oauth_client.py @@ -174,7 +174,7 @@ async def test_oauth2_authorize_code_challenge(): req_scope.update( { 'path': '/', - 'query_string': 'code=a&state={}'.format(state).encode(), + 'query_string': f'code=a&state={state}'.encode(), 'session': req.session, } ) diff --git a/tests/clients/util.py b/tests/clients/util.py index 8ae77456..1b2fbc0e 100644 --- a/tests/clients/util.py +++ b/tests/clients/util.py @@ -10,7 +10,7 @@ def read_key_file(name): file_path = os.path.join(ROOT, 'keys', name) - with open(file_path, 'r') as f: + with open(file_path) as f: if name.endswith('.json'): return json.load(f) return f.read() diff --git a/tests/core/test_oidc/test_discovery.py b/tests/core/test_oidc/test_discovery.py index b0921cbe..611acb0f 100644 --- a/tests/core/test_oidc/test_discovery.py +++ b/tests/core/test_oidc/test_discovery.py @@ -204,7 +204,7 @@ def _validate(metadata): if required: with self.assertRaises(ValueError) as cm: _validate(metadata) - self.assertEqual('"{}" is required'.format(key), str(cm.exception)) + self.assertEqual(f'"{key}" is required', str(cm.exception)) else: _validate(metadata) @@ -223,6 +223,6 @@ def _call_contains_invalid_value(self, key, invalid_value): with self.assertRaises(ValueError) as cm: getattr(metadata, 'validate_' + key)() self.assertEqual( - '"{}" contains invalid values'.format(key), + f'"{key}" contains invalid values', str(cm.exception) ) diff --git a/tests/django/test_oauth1/test_resource_protector.py b/tests/django/test_oauth1/test_resource_protector.py index 3466b04b..025f4ea1 100644 --- a/tests/django/test_oauth1/test_resource_protector.py +++ b/tests/django/test_oauth1/test_resource_protector.py @@ -135,7 +135,7 @@ def test_hmac_sha1_signature(self): sig = signature.hmac_sha1_signature( base_string, 'secret', 'valid-token-secret') params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param # case 1: success @@ -171,7 +171,7 @@ def test_rsa_sha1_signature(self): sig = signature.rsa_sha1_signature( base_string, read_file_path('rsa_private.pem')) params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param request = self.factory.get(url, HTTP_AUTHORIZATION=auth_header) diff --git a/tests/django/test_oauth1/test_token_credentials.py b/tests/django/test_oauth1/test_token_credentials.py index 9e0140e3..5c67b825 100644 --- a/tests/django/test_oauth1/test_token_credentials.py +++ b/tests/django/test_oauth1/test_token_credentials.py @@ -131,7 +131,7 @@ def test_hmac_sha1_signature(self): sig = signature.hmac_sha1_signature( base_string, 'secret', 'abc-secret') params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param # case 1: success @@ -170,7 +170,7 @@ def test_rsa_sha1_signature(self): sig = signature.rsa_sha1_signature( base_string, read_file_path('rsa_private.pem')) params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param request = self.factory.post(url, HTTP_AUTHORIZATION=auth_header) diff --git a/tests/django/test_oauth2/models.py b/tests/django/test_oauth2/models.py index 44ed90d6..cc2666d3 100644 --- a/tests/django/test_oauth2/models.py +++ b/tests/django/test_oauth2/models.py @@ -124,7 +124,7 @@ def get_auth_time(self): return self.auth_time -class CodeGrantMixin(object): +class CodeGrantMixin: def query_authorization_code(self, code, client): try: item = OAuth2Code.objects.get(code=code, client_id=client.client_id) diff --git a/tests/django/test_oauth2/oauth2_server.py b/tests/django/test_oauth2/oauth2_server.py index ff43908a..22697f21 100644 --- a/tests/django/test_oauth2/oauth2_server.py +++ b/tests/django/test_oauth2/oauth2_server.py @@ -19,6 +19,6 @@ def create_server(self): return AuthorizationServer(Client, OAuth2Token) def create_basic_auth(self, username, password): - text = '{}:{}'.format(username, password) + text = f'{username}:{password}' auth = to_unicode(base64.b64encode(to_bytes(text))) return 'Basic ' + auth diff --git a/tests/django/test_oauth2/test_authorization_code_grant.py b/tests/django/test_oauth2/test_authorization_code_grant.py index 81a7f715..10329859 100644 --- a/tests/django/test_oauth2/test_authorization_code_grant.py +++ b/tests/django/test_oauth2/test_authorization_code_grant.py @@ -24,7 +24,7 @@ def save_authorization_code(self, code, request): class AuthorizationCodeTest(TestCase): def create_server(self): - server = super(AuthorizationCodeTest, self).create_server() + server = super().create_server() server.register_grant(AuthorizationCodeGrant) return server diff --git a/tests/django/test_oauth2/test_client_credentials_grant.py b/tests/django/test_oauth2/test_client_credentials_grant.py index e698179f..fe658c2e 100644 --- a/tests/django/test_oauth2/test_client_credentials_grant.py +++ b/tests/django/test_oauth2/test_client_credentials_grant.py @@ -6,7 +6,7 @@ class PasswordTest(TestCase): def create_server(self): - server = super(PasswordTest, self).create_server() + server = super().create_server() server.register_grant(grants.ClientCredentialsGrant) return server diff --git a/tests/django/test_oauth2/test_implicit_grant.py b/tests/django/test_oauth2/test_implicit_grant.py index 320ac360..d2f98cc8 100644 --- a/tests/django/test_oauth2/test_implicit_grant.py +++ b/tests/django/test_oauth2/test_implicit_grant.py @@ -6,7 +6,7 @@ class ImplicitTest(TestCase): def create_server(self): - server = super(ImplicitTest, self).create_server() + server = super().create_server() server.register_grant(grants.ImplicitGrant) return server diff --git a/tests/django/test_oauth2/test_password_grant.py b/tests/django/test_oauth2/test_password_grant.py index 328e4fdd..e10165b1 100644 --- a/tests/django/test_oauth2/test_password_grant.py +++ b/tests/django/test_oauth2/test_password_grant.py @@ -19,7 +19,7 @@ def authenticate_user(self, username, password): class PasswordTest(TestCase): def create_server(self): - server = super(PasswordTest, self).create_server() + server = super().create_server() server.register_grant(PasswordGrant) return server diff --git a/tests/django/test_oauth2/test_refresh_token.py b/tests/django/test_oauth2/test_refresh_token.py index 47d261c1..63acc88d 100644 --- a/tests/django/test_oauth2/test_refresh_token.py +++ b/tests/django/test_oauth2/test_refresh_token.py @@ -29,7 +29,7 @@ def revoke_old_credential(self, credential): class RefreshTokenTest(TestCase): def create_server(self): - server = super(RefreshTokenTest, self).create_server() + server = super().create_server() server.register_grant(RefreshTokenGrant) return server diff --git a/tests/django/test_oauth2/test_revocation_endpoint.py b/tests/django/test_oauth2/test_revocation_endpoint.py index 2227f30e..1c3d73aa 100644 --- a/tests/django/test_oauth2/test_revocation_endpoint.py +++ b/tests/django/test_oauth2/test_revocation_endpoint.py @@ -9,7 +9,7 @@ class RevocationEndpointTest(TestCase): def create_server(self): - server = super(RevocationEndpointTest, self).create_server() + server = super().create_server() server.register_endpoint(RevocationEndpoint) return server diff --git a/tests/flask/cache.py b/tests/flask/cache.py index b3c77592..62cdb1d2 100644 --- a/tests/flask/cache.py +++ b/tests/flask/cache.py @@ -5,7 +5,7 @@ import pickle -class SimpleCache(object): +class SimpleCache: """A SimpleCache for testing. Copied from Werkzeug.""" def __init__(self, threshold=500, default_timeout=300): diff --git a/tests/flask/test_oauth1/test_resource_protector.py b/tests/flask/test_oauth1/test_resource_protector.py index 87c0e5c4..8b4feb3c 100644 --- a/tests/flask/test_oauth1/test_resource_protector.py +++ b/tests/flask/test_oauth1/test_resource_protector.py @@ -121,7 +121,7 @@ def test_hmac_sha1_signature(self): sig = signature.hmac_sha1_signature( base_string, 'secret', 'valid-token-secret') params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} @@ -152,7 +152,7 @@ def test_rsa_sha1_signature(self): sig = signature.rsa_sha1_signature( base_string, read_file_path('rsa_private.pem')) params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} rv = self.client.get(url, headers=headers) diff --git a/tests/flask/test_oauth1/test_temporary_credentials.py b/tests/flask/test_oauth1/test_temporary_credentials.py index 888b7fd8..79321061 100644 --- a/tests/flask/test_oauth1/test_temporary_credentials.py +++ b/tests/flask/test_oauth1/test_temporary_credentials.py @@ -201,7 +201,7 @@ def test_hmac_sha1_signature(self): ) sig = signature.hmac_sha1_signature(base_string, 'secret', None) params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} @@ -232,7 +232,7 @@ def test_rsa_sha1_signature(self): sig = signature.rsa_sha1_signature( base_string, read_file_path('rsa_private.pem')) params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} rv = self.client.post(url, headers=headers) diff --git a/tests/flask/test_oauth1/test_token_credentials.py b/tests/flask/test_oauth1/test_token_credentials.py index 3f86b909..8352b51f 100644 --- a/tests/flask/test_oauth1/test_token_credentials.py +++ b/tests/flask/test_oauth1/test_token_credentials.py @@ -155,7 +155,7 @@ def test_hmac_sha1_signature(self): sig = signature.hmac_sha1_signature( base_string, 'secret', 'abc-secret') params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} @@ -190,7 +190,7 @@ def test_rsa_sha1_signature(self): sig = signature.rsa_sha1_signature( base_string, read_file_path('rsa_private.pem')) params.append(('oauth_signature', sig)) - auth_param = ','.join(['{}="{}"'.format(k, v) for k, v in params]) + auth_param = ','.join([f'{k}="{v}"' for k, v in params]) auth_header = 'OAuth ' + auth_param headers = {'Authorization': auth_header} rv = self.client.post(url, headers=headers) diff --git a/tests/flask/test_oauth2/models.py b/tests/flask/test_oauth2/models.py index 93b4f0c9..b97e7eab 100644 --- a/tests/flask/test_oauth2/models.py +++ b/tests/flask/test_oauth2/models.py @@ -52,7 +52,7 @@ def is_refresh_token_active(self): return not self.refresh_token_revoked_at -class CodeGrantMixin(object): +class CodeGrantMixin: def query_authorization_code(self, code, client): item = AuthorizationCode.query.filter_by( code=code, client_id=client.client_id).first() diff --git a/tests/flask/test_oauth2/oauth2_server.py b/tests/flask/test_oauth2/oauth2_server.py index faa2887d..54591781 100644 --- a/tests/flask/test_oauth2/oauth2_server.py +++ b/tests/flask/test_oauth2/oauth2_server.py @@ -15,10 +15,10 @@ def token_generator(client, grant_type, user=None, scope=None): - token = '{}-{}'.format(client.client_id[0], grant_type) + token = f'{client.client_id[0]}-{grant_type}' if user: - token = '{}.{}'.format(token, user.get_user_id()) - return '{}.{}'.format(token, generate_token(32)) + token = f'{token}.{user.get_user_id()}' + return f'{token}.{generate_token(32)}' def create_authorization_server(app, lazy=False): @@ -92,6 +92,6 @@ def tearDown(self): os.environ.pop('AUTHLIB_INSECURE_TRANSPORT') def create_basic_header(self, username, password): - text = '{}:{}'.format(username, password) + text = f'{username}:{password}' auth = to_unicode(base64.b64encode(to_bytes(text))) return {'Authorization': 'Basic ' + auth} diff --git a/tests/jose/test_jwe.py b/tests/jose/test_jwe.py index 3477ea6e..27932404 100644 --- a/tests/jose/test_jwe.py +++ b/tests/jose/test_jwe.py @@ -195,7 +195,7 @@ def test_aes_jwe(self): 'A128GCM', 'A192GCM', 'A256GCM' ] for s in sizes: - alg = 'A{}KW'.format(s) + alg = f'A{s}KW' key = os.urandom(s // 8) for enc in _enc_choices: protected = {'alg': alg, 'enc': enc} @@ -220,7 +220,7 @@ def test_aes_gcm_jwe(self): 'A128GCM', 'A192GCM', 'A256GCM' ] for s in sizes: - alg = 'A{}GCMKW'.format(s) + alg = f'A{s}GCMKW' key = os.urandom(s // 8) for enc in _enc_choices: protected = {'alg': alg, 'enc': enc} diff --git a/tests/util.py b/tests/util.py index 4b7ff15f..aba66e5a 100644 --- a/tests/util.py +++ b/tests/util.py @@ -11,7 +11,7 @@ def get_file_path(name): def read_file_path(name): - with open(get_file_path(name), 'r') as f: + with open(get_file_path(name)) as f: if name.endswith('.json'): return json.load(f) return f.read() diff --git a/tox.ini b/tox.ini index db4c3083..165c1977 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,8 @@ [tox] isolated_build = True envlist = - py{37,38,39,310,311} - py{37,38,39,310,311}-{clients,flask,django,jose} + py{38,39,310,311} + py{38,39,310,311}-{clients,flask,django,jose} coverage [testenv]