Skip to content

Commit 26a63fc

Browse files
Ruff linter and formatter changes (#1001)
* Ruff settings * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * ruff toml added in manifest * Ruff formatted files * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Flake8 changes removed * B904 Exception fixes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * B028 Error code changes * B023 exception fixes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * method-assign exception suppressed * method-assign exception suppressed * keywords removed * Mypy error slienced * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Code coverage fixed * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Merge conflicts resolved * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * ruff precommit settings added * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Setup.cfg deleted --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 8910f56 commit 26a63fc

File tree

13 files changed

+143
-29
lines changed

13 files changed

+143
-29
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,4 @@ target/
6262
.pytest_cache
6363
.mypy_cache
6464
pip-wheel-metadata/
65+
.venv/

.pre-commit-config.yaml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@ repos:
1111
- id: blacken-docs
1212
args: ["--target-version=py38"]
1313

14-
- repo: https://github.com/PyCQA/flake8
15-
rev: 7.1.1
16-
hooks:
17-
- id: flake8
18-
language_version: python3.9
19-
2014
- repo: https://github.com/PyCQA/isort
2115
rev: 5.13.2
2216
hooks:
@@ -62,4 +56,12 @@ repos:
6256
hooks:
6357
- id: pyroma
6458

65-
...
59+
- repo: https://github.com/astral-sh/ruff-pre-commit
60+
# Ruff version.
61+
rev: v0.6.9
62+
hooks:
63+
# Run the linter.
64+
- id: ruff
65+
args: [ --fix ]
66+
# Run the formatter.
67+
- id: ruff-format

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ include CHANGELOG.rst
66
include LICENSE
77
include README.rst
88
include SECURITY.md
9+
include ruff.toml
910
include tox.ini
1011
include jwt/py.typed
1112
graft docs

jwt/algorithms.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def from_jwk(jwk: str | JWKDict) -> bytes:
297297
else:
298298
raise ValueError
299299
except ValueError:
300-
raise InvalidKeyError("Key is not valid JSON")
300+
raise InvalidKeyError("Key is not valid JSON") from None
301301

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

351353
@overload
352354
@staticmethod
@@ -409,10 +411,10 @@ def from_jwk(jwk: str | JWKDict) -> AllowedRSAKeys:
409411
else:
410412
raise ValueError
411413
except ValueError:
412-
raise InvalidKeyError("Key is not valid JSON")
414+
raise InvalidKeyError("Key is not valid JSON") from None
413415

414416
if obj.get("kty") != "RSA":
415-
raise InvalidKeyError("Not an RSA key")
417+
raise InvalidKeyError("Not an RSA key") from None
416418

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

433435
public_numbers = RSAPublicNumbers(
434436
from_base64url_uint(obj["e"]),
@@ -520,7 +522,7 @@ def prepare_key(self, key: AllowedECKeys | str | bytes) -> AllowedECKeys:
520522
):
521523
raise InvalidKeyError(
522524
"Expecting a EllipticCurvePrivateKey/EllipticCurvePublicKey. Wrong key provided for ECDSA algorithms"
523-
)
525+
) from None
524526

525527
return crypto_key
526528

@@ -605,13 +607,13 @@ def from_jwk(jwk: str | JWKDict) -> AllowedECKeys:
605607
else:
606608
raise ValueError
607609
except ValueError:
608-
raise InvalidKeyError("Key is not valid JSON")
610+
raise InvalidKeyError("Key is not valid JSON") from None
609611

610612
if obj.get("kty") != "EC":
611-
raise InvalidKeyError("Not an Elliptic curve key")
613+
raise InvalidKeyError("Not an Elliptic curve key") from None
612614

613615
if "x" not in obj or "y" not in obj:
614-
raise InvalidKeyError("Not an Elliptic curve key")
616+
raise InvalidKeyError("Not an Elliptic curve key") from None
615617

616618
x = base64url_decode(obj.get("x"))
617619
y = base64url_decode(obj.get("y"))
@@ -623,17 +625,23 @@ def from_jwk(jwk: str | JWKDict) -> AllowedECKeys:
623625
if len(x) == len(y) == 32:
624626
curve_obj = SECP256R1()
625627
else:
626-
raise InvalidKeyError("Coords should be 32 bytes for curve P-256")
628+
raise InvalidKeyError(
629+
"Coords should be 32 bytes for curve P-256"
630+
) from None
627631
elif curve == "P-384":
628632
if len(x) == len(y) == 48:
629633
curve_obj = SECP384R1()
630634
else:
631-
raise InvalidKeyError("Coords should be 48 bytes for curve P-384")
635+
raise InvalidKeyError(
636+
"Coords should be 48 bytes for curve P-384"
637+
) from None
632638
elif curve == "P-521":
633639
if len(x) == len(y) == 66:
634640
curve_obj = SECP521R1()
635641
else:
636-
raise InvalidKeyError("Coords should be 66 bytes for curve P-521")
642+
raise InvalidKeyError(
643+
"Coords should be 66 bytes for curve P-521"
644+
) from None
637645
elif curve == "secp256k1":
638646
if len(x) == len(y) == 32:
639647
curve_obj = SECP256K1()
@@ -834,7 +842,7 @@ def from_jwk(jwk: str | JWKDict) -> AllowedOKPKeys:
834842
else:
835843
raise ValueError
836844
except ValueError:
837-
raise InvalidKeyError("Key is not valid JSON")
845+
raise InvalidKeyError("Key is not valid JSON") from None
838846

839847
if obj.get("kty") != "OKP":
840848
raise InvalidKeyError("Not an Octet Key Pair")

jwt/api_jws.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ def decode_complete(
194194
"and will be removed in pyjwt version 3. "
195195
f"Unsupported kwargs: {tuple(kwargs.keys())}",
196196
RemovedInPyjwt3Warning,
197+
stacklevel=2,
197198
)
198199
if options is None:
199200
options = {}
@@ -239,6 +240,7 @@ def decode(
239240
"and will be removed in pyjwt version 3. "
240241
f"Unsupported kwargs: {tuple(kwargs.keys())}",
241242
RemovedInPyjwt3Warning,
243+
stacklevel=2,
242244
)
243245
decoded = self.decode_complete(
244246
jwt, key, algorithms, options, detached_payload=detached_payload
@@ -307,7 +309,7 @@ def _verify_signature(
307309
try:
308310
alg = header["alg"]
309311
except KeyError:
310-
raise InvalidAlgorithmError("Algorithm not specified")
312+
raise InvalidAlgorithmError("Algorithm not specified") from None
311313

312314
if not alg or (algorithms is not None and alg not in algorithms):
313315
raise InvalidAlgorithmError("The specified alg value is not allowed")

jwt/api_jwt.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ def decode_complete(
122122
"and will be removed in pyjwt version 3. "
123123
f"Unsupported kwargs: {tuple(kwargs.keys())}",
124124
RemovedInPyjwt3Warning,
125+
stacklevel=2,
125126
)
126127
options = dict(options or {}) # shallow-copy or initialize an empty dict
127128
options.setdefault("verify_signature", True)
@@ -135,6 +136,7 @@ def decode_complete(
135136
"The equivalent is setting `verify_signature` to False in the `options` dictionary. "
136137
"This invocation has a mismatch between the kwarg and the option entry.",
137138
category=DeprecationWarning,
139+
stacklevel=2,
138140
)
139141

140142
if not options["verify_signature"]:
@@ -173,7 +175,7 @@ def _decode_payload(self, decoded: dict[str, Any]) -> Any:
173175
try:
174176
payload = json.loads(decoded["payload"])
175177
except ValueError as e:
176-
raise DecodeError(f"Invalid payload string: {e}")
178+
raise DecodeError(f"Invalid payload string: {e}") from e
177179
if not isinstance(payload, dict):
178180
raise DecodeError("Invalid payload string: must be a json object")
179181
return payload
@@ -202,6 +204,7 @@ def decode(
202204
"and will be removed in pyjwt version 3. "
203205
f"Unsupported kwargs: {tuple(kwargs.keys())}",
204206
RemovedInPyjwt3Warning,
207+
stacklevel=2,
205208
)
206209
decoded = self.decode_complete(
207210
jwt,
@@ -269,7 +272,9 @@ def _validate_iat(
269272
try:
270273
iat = int(payload["iat"])
271274
except ValueError:
272-
raise InvalidIssuedAtError("Issued At claim (iat) must be an integer.")
275+
raise InvalidIssuedAtError(
276+
"Issued At claim (iat) must be an integer."
277+
) from None
273278
if iat > (now + leeway):
274279
raise ImmatureSignatureError("The token is not yet valid (iat)")
275280

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

287292
if nbf > (now + leeway):
288293
raise ImmatureSignatureError("The token is not yet valid (nbf)")
@@ -296,7 +301,9 @@ def _validate_exp(
296301
try:
297302
exp = int(payload["exp"])
298303
except ValueError:
299-
raise DecodeError("Expiration Time claim (exp) must be an integer.")
304+
raise DecodeError(
305+
"Expiration Time claim (exp) must be an integer."
306+
) from None
300307

301308
if exp <= (now - leeway):
302309
raise ExpiredSignatureError("Signature has expired")

jwt/help.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ def info() -> Dict[str, Dict[str, str]]:
3939
)
4040
if pypy_version_info.releaselevel != "final":
4141
implementation_version = "".join(
42-
[implementation_version, pypy_version_info.releaselevel]
42+
[
43+
implementation_version,
44+
pypy_version_info.releaselevel,
45+
]
4346
)
4447
else:
4548
implementation_version = "Unknown"

jwt/jwks_client.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ def __init__(
4545
if cache_keys:
4646
# Cache signing keys
4747
# Ignore mypy (https://github.com/python/mypy/issues/2427)
48-
self.get_signing_key = lru_cache(maxsize=max_cached_keys)(self.get_signing_key) # type: ignore
48+
self.get_signing_key = lru_cache(maxsize=max_cached_keys)(
49+
self.get_signing_key
50+
) # type: ignore
4951

5052
def fetch_data(self) -> Any:
5153
jwk_set: Any = None
@@ -58,7 +60,7 @@ def fetch_data(self) -> Any:
5860
except (URLError, TimeoutError) as e:
5961
raise PyJWKClientConnectionError(
6062
f'Fail to fetch data from the url, err: "{e}"'
61-
)
63+
) from e
6264
else:
6365
return jwk_set
6466
finally:

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ profile = "black"
100100
[tool.mypy]
101101
allow_incomplete_defs = true
102102
allow_untyped_defs = true
103+
disable_error_code = [
104+
"method-assign",
105+
"unused-ignore",
106+
]
103107
ignore_missing_imports = true
104108
no_implicit_optional = true
105109
overrides = [

ruff.toml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Exclude a variety of commonly ignored directories.
2+
exclude = [
3+
".bzr",
4+
".direnv",
5+
".eggs",
6+
".git",
7+
".git-rewrite",
8+
".hg",
9+
".ipynb_checkpoints",
10+
".mypy_cache",
11+
".nox",
12+
".pants.d",
13+
".pyenv",
14+
".pytest_cache",
15+
".pytype",
16+
".ruff_cache",
17+
".svn",
18+
".tox",
19+
".venv",
20+
".vscode",
21+
"__pypackages__",
22+
"_build",
23+
"buck-out",
24+
"build",
25+
"dist",
26+
"node_modules",
27+
"site-packages",
28+
"venv",
29+
]
30+
31+
# Same as Black.
32+
line-length = 88
33+
indent-width = 4
34+
35+
# Assume Python 3.8
36+
target-version = "py38"
37+
38+
[lint]
39+
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
40+
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
41+
# McCabe complexity (`C901`) by default.
42+
select = ["E4", "E7", "E9", "F", "B"]
43+
ignore = ["E501"]
44+
45+
# Allow fix for all enabled rules (when `--fix`) is provided.
46+
fixable = ["ALL"]
47+
unfixable = []
48+
49+
# Allow unused variables when underscore-prefixed.
50+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
51+
52+
[format]
53+
# Like Black, use double quotes for strings.
54+
quote-style = "double"
55+
56+
# Like Black, indent with spaces, rather than tabs.
57+
indent-style = "space"
58+
59+
# Like Black, respect magic trailing commas.
60+
skip-magic-trailing-comma = false
61+
62+
# Like Black, automatically detect the appropriate line ending.
63+
line-ending = "auto"
64+
65+
# Enable auto-formatting of code examples in docstrings. Markdown,
66+
# reStructuredText code/literal blocks and doctests are all supported.
67+
#
68+
# This is currently disabled by default, but it is planned for this
69+
# to be opt-out in the future.
70+
docstring-code-format = false
71+
72+
# Set the line length limit used when formatting code snippets in
73+
# docstrings.
74+
#
75+
# This only has an effect when the `docstring-code-format` setting is
76+
# enabled.
77+
docstring-code-line-length = "dynamic"

0 commit comments

Comments
 (0)