Skip to content
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

Ruff linter and formatter changes #1001

Merged
merged 26 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
bb41373
Ruff settings
gagandeepp Oct 5, 2024
4afdb5f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 5, 2024
15b1abd
ruff toml added in manifest
gagandeepp Oct 5, 2024
d99c45b
Ruff formatted files
gagandeepp Oct 5, 2024
760d589
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 5, 2024
c4eb823
Flake8 changes removed
gagandeepp Oct 5, 2024
041b475
B904 Exception fixes
gagandeepp Oct 5, 2024
b0b386f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 5, 2024
953ffc1
B028 Error code changes
gagandeepp Oct 5, 2024
080fdbc
B023 exception fixes
gagandeepp Oct 5, 2024
a86cd3f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 5, 2024
0816800
method-assign exception suppressed
gagandeepp Oct 5, 2024
88de296
method-assign exception suppressed
gagandeepp Oct 5, 2024
9662a6b
keywords removed
gagandeepp Oct 5, 2024
e3cb80d
Mypy error slienced
gagandeepp Oct 5, 2024
6f6e22b
Merge branch 'master' of https://github.com/gagandeepp/pyjwt
gagandeepp Oct 8, 2024
a267d5f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 8, 2024
7b8cd32
Code coverage fixed
gagandeepp Oct 8, 2024
9e58074
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 8, 2024
52ecfcf
Merge conflicts resolved
gagandeepp Oct 8, 2024
f601edf
Merge remote-tracking branch 'upstream/master'
gagandeepp Oct 8, 2024
19f4daf
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 8, 2024
0c12943
ruff precommit settings added
gagandeepp Oct 8, 2024
2165e4b
Merge branch 'master' of https://github.com/gagandeepp/pyjwt
gagandeepp Oct 8, 2024
be2796c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 8, 2024
3052584
Setup.cfg deleted
gagandeepp Oct 10, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ target/
.pytest_cache
.mypy_cache
pip-wheel-metadata/
.venv/
16 changes: 9 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ repos:
- id: blacken-docs
args: ["--target-version=py38"]

- repo: https://github.com/PyCQA/flake8
rev: 7.1.1
hooks:
- id: flake8
language_version: python3.9

- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
Expand Down Expand Up @@ -62,4 +56,12 @@ repos:
hooks:
- id: pyroma

...
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.6.9
hooks:
# Run the linter.
- id: ruff
args: [ --fix ]
# Run the formatter.
- id: ruff-format
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ include CHANGELOG.rst
include LICENSE
include README.rst
include SECURITY.md
include ruff.toml
include tox.ini
include jwt/py.typed
graft docs
Expand Down
34 changes: 21 additions & 13 deletions jwt/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ def from_jwk(jwk: str | JWKDict) -> bytes:
else:
raise ValueError
except ValueError:
raise InvalidKeyError("Key is not valid JSON")
raise InvalidKeyError("Key is not valid JSON") from None

if obj.get("kty") != "oct":
raise InvalidKeyError("Not an HMAC key")
Expand Down Expand Up @@ -346,7 +346,9 @@ def prepare_key(self, key: AllowedRSAKeys | str | bytes) -> AllowedRSAKeys:
try:
return cast(RSAPublicKey, load_pem_public_key(key_bytes))
except (ValueError, UnsupportedAlgorithm):
raise InvalidKeyError("Could not parse the provided public key.")
raise InvalidKeyError(
"Could not parse the provided public key."
) from None

@overload
@staticmethod
Expand Down Expand Up @@ -409,10 +411,10 @@ def from_jwk(jwk: str | JWKDict) -> AllowedRSAKeys:
else:
raise ValueError
except ValueError:
raise InvalidKeyError("Key is not valid JSON")
raise InvalidKeyError("Key is not valid JSON") from None

if obj.get("kty") != "RSA":
raise InvalidKeyError("Not an RSA key")
raise InvalidKeyError("Not an RSA key") from None

if "d" in obj and "e" in obj and "n" in obj:
# Private key
Expand All @@ -428,7 +430,7 @@ def from_jwk(jwk: str | JWKDict) -> AllowedRSAKeys:
if any_props_found and not all(props_found):
raise InvalidKeyError(
"RSA key must include all parameters if any are present besides d"
)
) from None

public_numbers = RSAPublicNumbers(
from_base64url_uint(obj["e"]),
Expand Down Expand Up @@ -520,7 +522,7 @@ def prepare_key(self, key: AllowedECKeys | str | bytes) -> AllowedECKeys:
):
raise InvalidKeyError(
"Expecting a EllipticCurvePrivateKey/EllipticCurvePublicKey. Wrong key provided for ECDSA algorithms"
)
) from None

return crypto_key

Expand Down Expand Up @@ -605,13 +607,13 @@ def from_jwk(jwk: str | JWKDict) -> AllowedECKeys:
else:
raise ValueError
except ValueError:
raise InvalidKeyError("Key is not valid JSON")
raise InvalidKeyError("Key is not valid JSON") from None

if obj.get("kty") != "EC":
raise InvalidKeyError("Not an Elliptic curve key")
raise InvalidKeyError("Not an Elliptic curve key") from None

if "x" not in obj or "y" not in obj:
raise InvalidKeyError("Not an Elliptic curve key")
raise InvalidKeyError("Not an Elliptic curve key") from None

x = base64url_decode(obj.get("x"))
y = base64url_decode(obj.get("y"))
Expand All @@ -623,17 +625,23 @@ def from_jwk(jwk: str | JWKDict) -> AllowedECKeys:
if len(x) == len(y) == 32:
curve_obj = SECP256R1()
else:
raise InvalidKeyError("Coords should be 32 bytes for curve P-256")
raise InvalidKeyError(
"Coords should be 32 bytes for curve P-256"
) from None
elif curve == "P-384":
if len(x) == len(y) == 48:
curve_obj = SECP384R1()
else:
raise InvalidKeyError("Coords should be 48 bytes for curve P-384")
raise InvalidKeyError(
"Coords should be 48 bytes for curve P-384"
) from None
elif curve == "P-521":
if len(x) == len(y) == 66:
curve_obj = SECP521R1()
else:
raise InvalidKeyError("Coords should be 66 bytes for curve P-521")
raise InvalidKeyError(
"Coords should be 66 bytes for curve P-521"
) from None
elif curve == "secp256k1":
if len(x) == len(y) == 32:
curve_obj = SECP256K1()
Expand Down Expand Up @@ -834,7 +842,7 @@ def from_jwk(jwk: str | JWKDict) -> AllowedOKPKeys:
else:
raise ValueError
except ValueError:
raise InvalidKeyError("Key is not valid JSON")
raise InvalidKeyError("Key is not valid JSON") from None

if obj.get("kty") != "OKP":
raise InvalidKeyError("Not an Octet Key Pair")
Expand Down
4 changes: 3 additions & 1 deletion jwt/api_jws.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ def decode_complete(
"and will be removed in pyjwt version 3. "
f"Unsupported kwargs: {tuple(kwargs.keys())}",
RemovedInPyjwt3Warning,
stacklevel=2,
)
if options is None:
options = {}
Expand Down Expand Up @@ -239,6 +240,7 @@ def decode(
"and will be removed in pyjwt version 3. "
f"Unsupported kwargs: {tuple(kwargs.keys())}",
RemovedInPyjwt3Warning,
stacklevel=2,
)
decoded = self.decode_complete(
jwt, key, algorithms, options, detached_payload=detached_payload
Expand Down Expand Up @@ -307,7 +309,7 @@ def _verify_signature(
try:
alg = header["alg"]
except KeyError:
raise InvalidAlgorithmError("Algorithm not specified")
raise InvalidAlgorithmError("Algorithm not specified") from None

if not alg or (algorithms is not None and alg not in algorithms):
raise InvalidAlgorithmError("The specified alg value is not allowed")
Expand Down
15 changes: 11 additions & 4 deletions jwt/api_jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ def decode_complete(
"and will be removed in pyjwt version 3. "
f"Unsupported kwargs: {tuple(kwargs.keys())}",
RemovedInPyjwt3Warning,
stacklevel=2,
)
options = dict(options or {}) # shallow-copy or initialize an empty dict
options.setdefault("verify_signature", True)
Expand All @@ -135,6 +136,7 @@ def decode_complete(
"The equivalent is setting `verify_signature` to False in the `options` dictionary. "
"This invocation has a mismatch between the kwarg and the option entry.",
category=DeprecationWarning,
stacklevel=2,
)

if not options["verify_signature"]:
Expand Down Expand Up @@ -173,7 +175,7 @@ def _decode_payload(self, decoded: dict[str, Any]) -> Any:
try:
payload = json.loads(decoded["payload"])
except ValueError as e:
raise DecodeError(f"Invalid payload string: {e}")
raise DecodeError(f"Invalid payload string: {e}") from e
if not isinstance(payload, dict):
raise DecodeError("Invalid payload string: must be a json object")
return payload
Expand Down Expand Up @@ -202,6 +204,7 @@ def decode(
"and will be removed in pyjwt version 3. "
f"Unsupported kwargs: {tuple(kwargs.keys())}",
RemovedInPyjwt3Warning,
stacklevel=2,
)
decoded = self.decode_complete(
jwt,
Expand Down Expand Up @@ -269,7 +272,9 @@ def _validate_iat(
try:
iat = int(payload["iat"])
except ValueError:
raise InvalidIssuedAtError("Issued At claim (iat) must be an integer.")
raise InvalidIssuedAtError(
"Issued At claim (iat) must be an integer."
) from None
if iat > (now + leeway):
raise ImmatureSignatureError("The token is not yet valid (iat)")

Expand All @@ -282,7 +287,7 @@ def _validate_nbf(
try:
nbf = int(payload["nbf"])
except ValueError:
raise DecodeError("Not Before claim (nbf) must be an integer.")
raise DecodeError("Not Before claim (nbf) must be an integer.") from None

if nbf > (now + leeway):
raise ImmatureSignatureError("The token is not yet valid (nbf)")
Expand All @@ -296,7 +301,9 @@ def _validate_exp(
try:
exp = int(payload["exp"])
except ValueError:
raise DecodeError("Expiration Time claim (exp) must be an integer.")
raise DecodeError(
"Expiration Time claim (exp) must be an integer."
) from None

if exp <= (now - leeway):
raise ExpiredSignatureError("Signature has expired")
Expand Down
5 changes: 4 additions & 1 deletion jwt/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ def info() -> Dict[str, Dict[str, str]]:
)
if pypy_version_info.releaselevel != "final":
implementation_version = "".join(
[implementation_version, pypy_version_info.releaselevel]
[
implementation_version,
pypy_version_info.releaselevel,
]
)
else:
implementation_version = "Unknown"
Expand Down
6 changes: 4 additions & 2 deletions jwt/jwks_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ def __init__(
if cache_keys:
# Cache signing keys
# Ignore mypy (https://github.com/python/mypy/issues/2427)
self.get_signing_key = lru_cache(maxsize=max_cached_keys)(self.get_signing_key) # type: ignore
self.get_signing_key = lru_cache(maxsize=max_cached_keys)(
self.get_signing_key
) # type: ignore

def fetch_data(self) -> Any:
jwk_set: Any = None
Expand All @@ -58,7 +60,7 @@ def fetch_data(self) -> Any:
except (URLError, TimeoutError) as e:
raise PyJWKClientConnectionError(
f'Fail to fetch data from the url, err: "{e}"'
)
) from e
else:
return jwk_set
finally:
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ profile = "black"
[tool.mypy]
allow_incomplete_defs = true
allow_untyped_defs = true
disable_error_code = [
"method-assign",
"unused-ignore",
]
ignore_missing_imports = true
no_implicit_optional = true
overrides = [
Expand Down
77 changes: 77 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Exclude a variety of commonly ignored directories.
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
]

# Same as Black.
line-length = 88
indent-width = 4

# Assume Python 3.8
target-version = "py38"

[lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
# McCabe complexity (`C901`) by default.
select = ["E4", "E7", "E9", "F", "B"]
ignore = ["E501"]

# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []

# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

[format]
# Like Black, use double quotes for strings.
quote-style = "double"

# Like Black, indent with spaces, rather than tabs.
indent-style = "space"

# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false

# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"

# Enable auto-formatting of code examples in docstrings. Markdown,
# reStructuredText code/literal blocks and doctests are all supported.
#
# This is currently disabled by default, but it is planned for this
# to be opt-out in the future.
docstring-code-format = false

# Set the line length limit used when formatting code snippets in
# docstrings.
#
# This only has an effect when the `docstring-code-format` setting is
# enabled.
docstring-code-line-length = "dynamic"
Empty file added tests/keys/jwk_empty.json
Empty file.
7 changes: 7 additions & 0 deletions tests/test_algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ def test_hmac_from_jwk_should_raise_exception_if_not_hmac_key(self):
with pytest.raises(InvalidKeyError):
algo.from_jwk(keyfile.read())

def test_hmac_from_jwk_should_raise_exception_if_empty_json(self):
algo = HMACAlgorithm(HMACAlgorithm.SHA256)

with open(key_path("jwk_empty.json")) as keyfile:
with pytest.raises(InvalidKeyError):
algo.from_jwk(keyfile.read())

@crypto_required
def test_rsa_should_parse_pem_public_key(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_api_jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def test_encode_bad_type(self, jwt):
for t in types:
pytest.raises(
TypeError,
lambda: jwt.encode(t, "secret", algorithms=["HS256"]),
lambda t=t: jwt.encode(t, "secret", algorithms=["HS256"]),
)

def test_encode_with_typ(self, jwt):
Expand Down
Loading