Skip to content

Lint with ruff to replace bandit, flake8, isort, pyupgrade #855

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions .github/workflows/lint_python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,15 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version: 3.x
check-latest: true
- run: pip install --upgrade pip setuptools wheel
- run: pip install bandit black codespell flake8 flake8-2020 flake8-bugbear
flake8-comprehensions isort mypy pytest pyupgrade safety
- run: bandit --recursive --skip B101,B105,B106,B107,B324 .
- run: pip install black codespell mypy pytest ruff safety
- run: ruff --format=github .
- run: black --check . || true
- run: codespell # --ignore-words-list="" --skip="*.css,*.js,*.lock"
- run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
- run: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=88
--show-source --statistics
- run: isort --check-only --profile black . || true
- run: pip install -r requirements-test.txt
- run: pip install --editable .
- run: mkdir --parents --verbose .mypy_cache
- run: mypy --ignore-missing-imports --install-types --non-interactive . || true
- run: pytest
- run: shopt -s globstar && pyupgrade --py37-plus **/*.py || true
- run: safety check
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
#
# The short X.Y version.

from oauthlib import __version__ as v
from oauthlib import __version__ as v # noqa: E402
version = v[:3]
# The full version, including alpha/beta/rc tags.
release = v
Expand Down
Empty file added examples/__init__.py
Empty file.
20 changes: 10 additions & 10 deletions oauthlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@
_DEBUG = False

def set_debug(debug_val):
"""Set value of debug flag
"""Set value of debug flag

:param debug_val: Value to set. Must be a bool value.
"""
global _DEBUG
_DEBUG = debug_val
"""
global _DEBUG # noqa: PLW0603
_DEBUG = debug_val

def get_debug():
"""Get debug mode value.
:return: `True` if debug mode is on, `False` otherwise
"""
return _DEBUG
"""Get debug mode value.

:return: `True` if debug mode is on, `False` otherwise
"""
return _DEBUG
5 changes: 3 additions & 2 deletions oauthlib/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'
'abcdefghijklmnopqrstuvwxyz'
'0123456789' '_.-')
'0123456789_.-')

log = logging.getLogger('oauthlib')

Expand Down Expand Up @@ -346,7 +346,8 @@ class Request:
def __init__(self, uri, http_method='GET', body=None, headers=None,
encoding='utf-8'):
# Convert to unicode using encoding if given, else assume unicode
encode = lambda x: to_unicode(x, encoding) if encoding else x
def encode(x):
return to_unicode(x, encoding) if encoding else x

self.uri = encode(uri)
self.http_method = encode(http_method)
Expand Down
5 changes: 3 additions & 2 deletions oauthlib/oauth1/rfc5849/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ def __init__(self, client_key,
:param timestamp: Use this timestamp instead of using current. (Mainly for testing)
"""
# Convert to unicode using encoding if given, else assume unicode
encode = lambda x: to_unicode(x, encoding) if encoding else x
def encode(x):
return to_unicode(x, encoding) if encoding else x

self.client_key = encode(client_key)
self.client_secret = encode(client_secret)
Expand Down Expand Up @@ -219,7 +220,7 @@ def get_oauth_params(self, request):
content_type = request.headers.get('Content-Type', None)
content_type_eligible = content_type and content_type.find('application/x-www-form-urlencoded') < 0
if request.body is not None and content_type_eligible:
params.append(('oauth_body_hash', base64.b64encode(hashlib.sha1(request.body.encode('utf-8')).digest()).decode('utf-8')))
params.append(('oauth_body_hash', base64.b64encode(hashlib.sha1(request.body.encode('utf-8')).digest()).decode('utf-8'))) # noqa: S324

return params

Expand Down
11 changes: 3 additions & 8 deletions oauthlib/oauth1/rfc5849/endpoints/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,10 @@ def _get_signature_type_and_params(self, request):
def _create_request(self, uri, http_method, body, headers):
# Only include body data from x-www-form-urlencoded requests
headers = CaseInsensitiveDict(headers or {})
if ("Content-Type" in headers and
CONTENT_TYPE_FORM_URLENCODED in headers["Content-Type"]):
if "Content-Type" in headers and CONTENT_TYPE_FORM_URLENCODED in headers["Content-Type"]: # noqa: SIM108
request = Request(uri, http_method, body, headers)
else:
request = Request(uri, http_method, '', headers)

signature_type, params, oauth_params = (
self._get_signature_type_and_params(request))

Expand Down Expand Up @@ -129,8 +127,7 @@ def _check_mandatory_parameters(self, request):
# Considerations section (`Section 4`_) before deciding on which
# method to support.
# .. _`Section 4`: https://tools.ietf.org/html/rfc5849#section-4
if (not request.signature_method in
self.request_validator.allowed_signature_methods):
if (request.signature_method not in self.request_validator.allowed_signature_methods):
raise errors.InvalidSignatureMethodError(
description="Invalid signature, {} not in {!r}.".format(
request.signature_method,
Expand Down Expand Up @@ -180,9 +177,7 @@ def _check_mandatory_parameters(self, request):

def _check_signature(self, request, is_token_request=False):
# ---- RSA Signature verification ----
if request.signature_method == SIGNATURE_RSA_SHA1 or \
request.signature_method == SIGNATURE_RSA_SHA256 or \
request.signature_method == SIGNATURE_RSA_SHA512:
if request.signature_method in {SIGNATURE_RSA_SHA1, SIGNATURE_RSA_SHA256, SIGNATURE_RSA_SHA512}:
# RSA-based signature method

# The server verifies the signature per `[RFC3447] section 8.2.2`_
Expand Down
6 changes: 3 additions & 3 deletions oauthlib/oauth1/rfc5849/signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from oauthlib.common import extract_params, safe_string_equals, urldecode

from . import utils
import contextlib

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -188,10 +189,9 @@ def base_string_uri(uri: str, host: str = None) -> str:
raise ValueError('missing host')

# NOTE: Try guessing if we're dealing with IP or hostname
try:
with contextlib.suppress(ValueError):
hostname = ipaddress.ip_address(hostname)
except ValueError:
pass


if isinstance(hostname, ipaddress.IPv6Address):
hostname = f"[{hostname}]"
Expand Down
5 changes: 3 additions & 2 deletions oauthlib/oauth1/rfc5849/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ def wrapper(params, *args, **kwargs):

def filter_oauth_params(params):
"""Removes all non oauth parameters from a dict or a list of params."""
is_oauth = lambda kv: kv[0].startswith("oauth_")
def is_oauth(kv):
return kv[0].startswith('oauth_')
if isinstance(params, dict):
return list(filter(is_oauth, list(params.items())))
else:
Expand Down Expand Up @@ -59,7 +60,7 @@ def unescape(u):
return unquote(u)


def parse_keqv_list(l):
def parse_keqv_list(l): # noqa: E741
"""A unicode-safe version of urllib2.parse_keqv_list"""
# With Python 2.6, parse_http_list handles unicode fine
return urllib2.parse_keqv_list(l)
Expand Down
8 changes: 4 additions & 4 deletions oauthlib/oauth2/rfc6749/clients/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def add_token(self, uri, http_method='GET', body=None, headers=None,

case_insensitive_token_types = {
k.lower(): v for k, v in self.token_types.items()}
if not self.token_type.lower() in case_insensitive_token_types:
if self.token_type.lower() not in case_insensitive_token_types:
raise ValueError("Unsupported token type: %s" % self.token_type)

if not (self.access_token or self.token.get('access_token')):
Expand Down Expand Up @@ -466,7 +466,7 @@ def _add_bearer_token(self, uri, http_method='GET', body=None,
return uri, headers, body

def create_code_verifier(self, length):
"""Create PKCE **code_verifier** used in computing **code_challenge**.
"""Create PKCE **code_verifier** used in computing **code_challenge**.
See `RFC7636 Section 4.1`_

:param length: REQUIRED. The length of the code_verifier.
Expand Down Expand Up @@ -530,10 +530,10 @@ def create_code_challenge(self, code_verifier, code_challenge_method=None):
"""
code_challenge = None

if code_verifier == None:
if code_verifier is None:
raise ValueError("Invalid code_verifier")

if code_challenge_method == None:
if code_challenge_method is None:
code_challenge_method = "plain"
self.code_challenge_method = code_challenge_method
code_challenge = code_verifier
Expand Down
2 changes: 1 addition & 1 deletion oauthlib/oauth2/rfc6749/clients/mobile_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class MobileApplicationClient(Client):
redirection URI, it may be exposed to the resource owner and other
applications residing on the same device.
"""

response_type = 'token'

def prepare_request_uri(self, uri, redirect_uri=None, scope=None,
Expand Down
6 changes: 3 additions & 3 deletions oauthlib/oauth2/rfc6749/clients/web_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class WebApplicationClient(Client):
browser) and capable of receiving incoming requests (via redirection)
from the authorization server.
"""

grant_type = 'authorization_code'

def __init__(self, client_id, code=None, **kwargs):
Expand Down Expand Up @@ -62,8 +62,8 @@ def prepare_request_uri(self, uri, redirect_uri=None, scope=None,
to the client. The parameter SHOULD be used for preventing
cross-site request forgery as described in `Section 10.12`_.

:param code_challenge: OPTIONAL. PKCE parameter. REQUIRED if PKCE is enforced.
A challenge derived from the code_verifier that is sent in the
:param code_challenge: OPTIONAL. PKCE parameter. REQUIRED if PKCE is enforced.
A challenge derived from the code_verifier that is sent in the
authorization request, to be verified against later.

:param code_challenge_method: OPTIONAL. PKCE parameter. A method that was used to derive code challenge.
Expand Down
4 changes: 2 additions & 2 deletions oauthlib/oauth2/rfc6749/endpoints/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ def valid_request_methods(self, valid_request_methods):
if valid_request_methods is not None:
valid_request_methods = [x.upper() for x in valid_request_methods]
self._valid_request_methods = valid_request_methods


@property
def available(self):
return self._available

@available.setter
def available(self, available):
self._available = available
self._available = available

@property
def catch_errors(self):
Expand Down
2 changes: 1 addition & 1 deletion oauthlib/oauth2/rfc6749/endpoints/introspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def create_introspect_response(self, uri, http_method='POST', body=None,
request
)
if claims is None:
return resp_headers, json.dumps(dict(active=False)), 200
return resp_headers, json.dumps({'active': False}), 200
if "active" in claims:
claims.pop("active")
return resp_headers, json.dumps(dict(active=True, **claims)), 200
Expand Down
4 changes: 2 additions & 2 deletions oauthlib/oauth2/rfc6749/endpoints/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class MetadataEndpoint(BaseEndpoint):
"""

def __init__(self, endpoints, claims={}, raise_errors=True):
assert isinstance(claims, dict)
assert isinstance(claims, dict) # noqa: S101
for endpoint in endpoints:
assert isinstance(endpoint, BaseEndpoint)
assert isinstance(endpoint, BaseEndpoint) # noqa: S101

BaseEndpoint.__init__(self)
self.raise_errors = raise_errors
Expand Down
1 change: 0 additions & 1 deletion oauthlib/oauth2/rfc6749/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ class FatalClientError(OAuth2Error):

Instead the user should be informed of the error by the provider itself.
"""
pass


class InvalidRequestFatalError(FatalClientError):
Expand Down
7 changes: 3 additions & 4 deletions oauthlib/oauth2/rfc6749/grant_types/authorization_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ def validate_authorization_request(self, request):
raise errors.MissingResponseTypeError(request=request)
# Value MUST be set to "code" or one of the OpenID authorization code including
# response_types "code token", "code id_token", "code token id_token"
elif not 'code' in request.response_type and request.response_type != 'none':
elif 'code' not in request.response_type and request.response_type != 'none':
raise errors.UnsupportedResponseTypeError(request=request)

if not self.request_validator.validate_response_type(request.client_id,
Expand All @@ -400,9 +400,8 @@ def validate_authorization_request(self, request):

# OPTIONAL. Validate PKCE request or reply with "error"/"invalid_request"
# https://tools.ietf.org/html/rfc6749#section-4.4.1
if self.request_validator.is_pkce_required(request.client_id, request) is True:
if request.code_challenge is None:
raise errors.MissingCodeChallengeError(request=request)
if self.request_validator.is_pkce_required(request.client_id, request) is True and request.code_challenge is None:
raise errors.MissingCodeChallengeError(request=request)

if request.code_challenge is not None:
request_info["code_challenge"] = request.code_challenge
Expand Down
7 changes: 2 additions & 5 deletions oauthlib/oauth2/rfc6749/grant_types/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def add_token(self, token, token_handler, request):
:type request: oauthlib.common.Request
"""
# Only add a hybrid access token on auth step if asked for
if not request.response_type in ["token", "code token", "id_token token", "code id_token token"]:
if request.response_type not in ["token", "code token", "id_token token", "code id_token token"]:
return token

token.update(token_handler.create_token(request, refresh_token=False))
Expand Down Expand Up @@ -199,10 +199,7 @@ def prepare_authorization_response(self, request, token, headers, body, status):

if request.response_type == 'none':
state = token.get('state', None)
if state:
token_items = [('state', state)]
else:
token_items = []
token_items = [('state', state)] if state else []

if request.response_mode == 'query':
headers['Location'] = add_params_to_uri(
Expand Down
9 changes: 4 additions & 5 deletions oauthlib/oauth2/rfc6749/grant_types/client_credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,10 @@ def validate_token_request(self, request):
if not self.request_validator.authenticate_client(request):
log.debug('Client authentication failed, %r.', request)
raise errors.InvalidClientError(request=request)
else:
if not hasattr(request.client, 'client_id'):
raise NotImplementedError('Authenticate client must set the '
'request.client.client_id attribute '
'in authenticate_client.')
elif not hasattr(request.client, 'client_id'):
raise NotImplementedError('Authenticate client must set the '
'request.client.client_id attribute '
'in authenticate_client.')
# Ensure client is authorized use of this grant type
self.validate_grant_type(request)

Expand Down
5 changes: 1 addition & 4 deletions oauthlib/oauth2/rfc6749/grant_types/implicit.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,7 @@ def create_token_response(self, request, token_handler):
# In OIDC implicit flow it is possible to have a request_type that does not include the access_token!
# "id_token token" - return the access token and the id token
# "id_token" - don't return the access token
if "token" in request.response_type.split():
token = token_handler.create_token(request, refresh_token=False)
else:
token = {}
token = token_handler.create_token(request, refresh_token=False) if 'token' in request.response_type.split() else {}

if request.state is not None:
token['state'] = request.state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,11 @@ def validate_token_request(self, request):
request.password, request.client, request):
raise errors.InvalidGrantError(
'Invalid credentials given.', request=request)
else:
if not hasattr(request.client, 'client_id'):
raise NotImplementedError(
'Validate user must set the '
'request.client.client_id attribute '
'in authenticate_client.')
elif not hasattr(request.client, 'client_id'):
raise NotImplementedError(
'Validate user must set the '
'request.client.client_id attribute '
'in authenticate_client.')
log.debug('Authorizing access to user %r.', request.user)

# Ensure client is authorized use of this grant type
Expand Down
Loading