Skip to content

Commit ce07798

Browse files
authored
Merge pull request #163 from jschlyter/ruff
Lint with ruff
2 parents 69b064b + 16ffca5 commit ce07798

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+389
-470
lines changed

Diff for: .github/workflows/test.yml

+8-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@ jobs:
1616
do_not_skip: '["pull_request"]'
1717
cancel_others: 'true'
1818
concurrent_skipping: same_content
19-
test:
19+
ruff:
20+
runs-on: ubuntu-latest
2021
needs: pre_job
22+
steps:
23+
- uses: actions/checkout@v4
24+
- uses: chartboost/ruff-action@v1
25+
test:
26+
needs: ruff
2127
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
2228
runs-on: ubuntu-latest
2329
strategy:
@@ -43,6 +49,6 @@ jobs:
4349
run: |
4450
poetry run pytest -vvv -ra --cov=cryptojwt --cov-report=xml --isort --black
4551
- name: Upload coverage to Codecov
46-
uses: codecov/codecov-action@v3
52+
uses: codecov/codecov-action@v4
4753
with:
4854
token: ${{ secrets.CODECOV_TOKEN }}

Diff for: .pre-commit-config.yaml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.6.0
4+
hooks:
5+
- id: check-merge-conflict
6+
- id: debug-statements
7+
- id: trailing-whitespace
8+
- id: end-of-file-fixer
9+
- id: check-yaml
10+
- id: check-json
11+
- repo: https://github.com/astral-sh/ruff-pre-commit
12+
rev: v0.4.9
13+
hooks:
14+
- id: ruff
15+
- id: ruff-format

Diff for: doc/conf.py

100644100755
+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#!/usr/bin/env python3
2+
#
3+
# ruff: noqa
24
# -*- coding: utf-8 -*-
35
#
46
# CryptoJWT documentation build configuration file, created by

Diff for: pyproject.toml

+21-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ python = "^3.9"
4242
cryptography = ">=3.4.6"
4343
requests = "^2.25.1"
4444

45-
[tool.poetry.dev-dependencies]
45+
[tool.poetry.group.dev.dependencies]
4646
alabaster = "^0.7.12"
4747
black = "^24.4.2"
4848
isort = "^5.13.2"
@@ -54,7 +54,27 @@ responses = "^0.13.0"
5454
sphinx = "^3.5.2"
5555
sphinx-autobuild = "^2021.3.14"
5656
coverage = "^7"
57+
ruff = "^0.4.6"
58+
pytest-ruff = "^0.3.2"
5759

5860
[build-system]
5961
requires = ["poetry-core>=1.0.0"]
6062
build-backend = "poetry.core.masonry.api"
63+
64+
[tool.ruff.lint]
65+
select = [
66+
# pycodestyle
67+
"E",
68+
# Pyflakes
69+
"F",
70+
# pyupgrade
71+
"UP",
72+
# flake8-bugbear
73+
"B",
74+
# flake8-simplify
75+
"SIM",
76+
# isort
77+
"I",
78+
]
79+
ignore = ["E501", "I001", "SIM102"]
80+
exclude = ["examples/*"]

Diff for: src/cryptojwt/__init__.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,23 @@
1616
from .utils import b64encode_item
1717
from .utils import split_token
1818

19-
try:
20-
from builtins import hex
21-
from builtins import str
22-
from builtins import zip
23-
except ImportError:
24-
pass
25-
2619
__version__ = version("cryptojwt")
2720

21+
__all__ = [
22+
"JWE",
23+
"JWE",
24+
"JWK",
25+
"JWS",
26+
"JWT",
27+
"KeyBundle",
28+
"KeyJar",
29+
"BadSyntax",
30+
"as_unicode",
31+
"b64d",
32+
"b64encode_item",
33+
"split_token",
34+
]
35+
2836
logger = logging.getLogger(__name__)
2937

3038
JWT_TYPES = ("JWT", "application/jws", "JWS", "JWE")

Diff for: src/cryptojwt/exception.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def __init__(self, value, msg):
2020
self.msg = msg
2121

2222
def __str__(self):
23-
return "%s: %r" % (self.msg, self.value)
23+
return f"{self.msg}: {self.value!r}"
2424

2525

2626
class BadSignature(Invalid):

Diff for: src/cryptojwt/jwe/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
}
3939

4040

41-
class Encrypter(object):
41+
class Encrypter:
4242
"""Abstract base class for encryption algorithms."""
4343

4444
def __init__(self, with_digest=False):

Diff for: src/cryptojwt/jwe/aes.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(self, key_len=32, key=None, msg_padding="PKCS7"):
3030
self.padder = PKCS7(128).padder()
3131
self.unpadder = PKCS7(128).unpadder()
3232
else:
33-
raise Unsupported("Message padding: {}".format(msg_padding))
33+
raise Unsupported(f"Message padding: {msg_padding}")
3434

3535
self.iv = None
3636

Diff for: src/cryptojwt/jwe/jwe.py

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1+
import contextlib
12
import logging
23

34
from ..jwk.asym import AsymmetricKey
45
from ..jwk.ec import ECKey
56
from ..jwk.hmac import SYMKey
67
from ..jwk.jwk import key_from_jwk_dict
7-
from ..jwk.rsa import RSAKey
88
from ..jwx import JWx
99
from .exception import DecryptionFailed
1010
from .exception import NoSuitableDecryptionKey
11-
from .exception import NoSuitableECDHKey
1211
from .exception import NoSuitableEncryptionKey
1312
from .exception import NotSupportedAlgorithm
1413
from .exception import WrongEncryptionAlgorithm
@@ -133,7 +132,7 @@ def encrypt(self, keys=None, cek="", iv="", **kwargs):
133132
except TypeError as err:
134133
raise err
135134
else:
136-
logger.debug("Encrypted message using key with kid={}".format(key.kid))
135+
logger.debug(f"Encrypted message using key with kid={key.kid}")
137136
return token
138137

139138
# logger.error("Could not find any suitable encryption key")
@@ -159,10 +158,8 @@ def decrypt(self, token=None, keys=None, alg=None, cek=None):
159158
else:
160159
keys = self.pick_keys(self._get_keys(), use="enc", alg=_alg)
161160

162-
try:
161+
with contextlib.suppress(KeyError):
163162
keys.append(key_from_jwk_dict(_jwe.headers["jwk"]))
164-
except KeyError:
165-
pass
166163

167164
if not keys and not cek:
168165
raise NoSuitableDecryptionKey(_alg)
@@ -194,18 +191,15 @@ def decrypt(self, token=None, keys=None, alg=None, cek=None):
194191
return msg
195192

196193
for key in keys:
197-
if isinstance(key, AsymmetricKey):
198-
_key = key.private_key()
199-
else:
200-
_key = key.key
194+
_key = key.private_key() if isinstance(key, AsymmetricKey) else key.key
201195

202196
try:
203197
msg = decrypter.decrypt(_jwe, _key)
204198
self["cek"] = decrypter.cek if "cek" in decrypter else None
205199
except (KeyError, DecryptionFailed):
206200
pass
207201
else:
208-
logger.debug("Decrypted message using key with kid=%s" % key.kid)
202+
logger.debug(f"Decrypted message using key with kid={key.kid}")
209203
return msg
210204

211205
raise DecryptionFailed("No available key that could decrypt the message")

Diff for: src/cryptojwt/jwe/jwe_ec.py

+11-15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import contextlib
12
import struct
23

34
from cryptography.hazmat.primitives.asymmetric import ec
@@ -110,8 +111,8 @@ def enc_setup(self, msg, key=None, auth_data=b"", **kwargs):
110111
if self.alg == "ECDH-ES":
111112
try:
112113
dk_len = KEY_LEN[self.enc]
113-
except KeyError:
114-
raise ValueError("Unknown key length for algorithm %s" % self.enc)
114+
except KeyError as exc:
115+
raise ValueError(f"Unknown key length for algorithm {self.enc}") from exc
115116

116117
cek = ecdh_derive_key(_epk, key.pub_key, apu, apv, str(self.enc).encode(), dk_len)
117118
elif self.alg in ["ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW"]:
@@ -121,7 +122,7 @@ def enc_setup(self, msg, key=None, auth_data=b"", **kwargs):
121122
cek = self._generate_key(self.enc, cek=cek)
122123
encrypted_key = aes_key_wrap(kek, cek)
123124
else:
124-
raise Exception("Unsupported algorithm %s" % self.alg)
125+
raise Exception(f"Unsupported algorithm {self.alg}")
125126

126127
return cek, encrypted_key, iv, params, epk
127128

@@ -152,8 +153,8 @@ def dec_setup(self, token, key=None, **kwargs):
152153
if self.headers["alg"] == "ECDH-ES":
153154
try:
154155
dk_len = KEY_LEN[self.headers["enc"]]
155-
except KeyError:
156-
raise Exception("Unknown key length for algorithm")
156+
except KeyError as exc:
157+
raise Exception("Unknown key length for algorithm") from exc
157158

158159
self.cek = ecdh_derive_key(
159160
key,
@@ -173,7 +174,7 @@ def dec_setup(self, token, key=None, **kwargs):
173174
kek = ecdh_derive_key(key, epubkey.pub_key, apu, apv, str(_post).encode(), klen)
174175
self.cek = aes_key_unwrap(kek, token.encrypted_key())
175176
else:
176-
raise Exception("Unsupported algorithm %s" % self.headers["alg"])
177+
raise Exception("Unsupported algorithm {}".format(self.headers["alg"]))
177178

178179
return self.cek
179180

@@ -190,10 +191,8 @@ def encrypt(self, key=None, iv="", cek="", **kwargs):
190191
_msg = as_bytes(self.msg)
191192

192193
_args = self._dict
193-
try:
194+
with contextlib.suppress(KeyError):
194195
_args["kid"] = kwargs["kid"]
195-
except KeyError:
196-
pass
197196

198197
if "params" in kwargs:
199198
if "apu" in kwargs["params"]:
@@ -204,23 +203,20 @@ def encrypt(self, key=None, iv="", cek="", **kwargs):
204203
_args["epk"] = kwargs["params"]["epk"]
205204

206205
jwe = JWEnc(**_args)
207-
ctxt, tag, cek = super(JWE_EC, self).enc_setup(
206+
ctxt, tag, cek = super().enc_setup(
208207
self["enc"], _msg, auth_data=jwe.b64_encode_header(), key=cek, iv=iv
209208
)
210209
if "encrypted_key" in kwargs:
211210
return jwe.pack(parts=[kwargs["encrypted_key"], iv, ctxt, tag])
212211
return jwe.pack(parts=[iv, ctxt, tag])
213212

214213
def decrypt(self, token=None, **kwargs):
215-
if isinstance(token, JWEnc):
216-
jwe = token
217-
else:
218-
jwe = JWEnc().unpack(token)
214+
jwe = token if isinstance(token, JWEnc) else JWEnc().unpack(token)
219215

220216
if not self.cek:
221217
raise Exception("Content Encryption Key is Not Yet Set")
222218

223-
msg = super(JWE_EC, self)._decrypt(
219+
msg = super()._decrypt(
224220
self.headers["enc"],
225221
self.cek,
226222
self.ctxt,

Diff for: src/cryptojwt/jwe/jwe_hmac.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import contextlib
12
import logging
23
import zlib
34

@@ -34,10 +35,8 @@ def encrypt(self, key, iv="", cek="", **kwargs):
3435
_msg = as_bytes(self.msg)
3536

3637
_args = self._dict
37-
try:
38+
with contextlib.suppress(KeyError):
3839
_args["kid"] = kwargs["kid"]
39-
except KeyError:
40-
pass
4140

4241
jwe = JWEnc(**_args)
4342

@@ -68,10 +67,7 @@ def decrypt(self, token, key=None, cek=None):
6867
if not key and not cek:
6968
raise MissingKey("On of key or cek must be specified")
7069

71-
if isinstance(token, JWEnc):
72-
jwe = token
73-
else:
74-
jwe = JWEnc().unpack(token)
70+
jwe = token if isinstance(token, JWEnc) else JWEnc().unpack(token)
7571

7672
if len(jwe) != 5:
7773
raise WrongNumberOfParts(len(jwe))

Diff for: src/cryptojwt/jwe/jwe_rsa.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def encrypt(self, key, iv="", cek="", **kwargs):
4949
if self["zip"] == "DEF":
5050
_msg = zlib.compress(_msg)
5151
else:
52-
raise ParameterError("Zip has unknown value: %s" % self["zip"])
52+
raise ParameterError("Zip has unknown value: {}".format(self["zip"]))
5353

5454
kwarg_cek = cek or None
5555

@@ -58,7 +58,7 @@ def encrypt(self, key, iv="", cek="", **kwargs):
5858
cek = self._generate_key(_enc, cek)
5959
self["cek"] = cek
6060

61-
logger.debug("cek: %s, iv: %s" % ([c for c in cek], [c for c in iv]))
61+
logger.debug(f"cek: {[c for c in cek]}, iv: {[c for c in iv]}")
6262

6363
_encrypt = RSAEncrypter(self.with_digest).encrypt
6464

@@ -92,10 +92,7 @@ def decrypt(self, token, key, cek=None):
9292
:param cek: Ephemeral cipher key
9393
:return: The decrypted message
9494
"""
95-
if not isinstance(token, JWEnc):
96-
jwe = JWEnc().unpack(token)
97-
else:
98-
jwe = token
95+
jwe = JWEnc().unpack(token) if not isinstance(token, JWEnc) else token
9996

10097
self.jwt = jwe.encrypted_key()
10198
jek = jwe.encrypted_key()

Diff for: src/cryptojwt/jwe/jwekey.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ def _generate_key(encalg, cek=""):
2929
except KeyError:
3030
try:
3131
_key = get_random_bytes(KEY_LEN_BYTES[encalg])
32-
except KeyError:
33-
raise ValueError("Unsupported encryption algorithm %s" % encalg)
32+
except KeyError as exc:
33+
raise ValueError(f"Unsupported encryption algorithm {encalg}") from exc
3434

3535
return _key
3636

@@ -77,7 +77,7 @@ def _decrypt(enc, key, ctxt, iv, tag, auth_data=b""):
7777
elif enc in ["A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"]:
7878
aes = AES_CBCEncrypter(key=key)
7979
else:
80-
raise Exception("Unsupported encryption algorithm %s" % enc)
80+
raise Exception(f"Unsupported encryption algorithm {enc}")
8181

8282
try:
8383
return aes.decrypt(ctxt, iv=iv, auth_data=auth_data, tag=tag)

Diff for: src/cryptojwt/jwe/jwenc.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def is_jwe(self):
4848
if "alg" in self.headers and "enc" in self.headers:
4949
for typ in ["alg", "enc"]:
5050
if self.headers[typ] not in SUPPORTED[typ]:
51-
logger.debug("Not supported %s algorithm: %s" % (typ, self.headers[typ]))
51+
logger.debug(f"Not supported {typ} algorithm: {self.headers[typ]}")
5252
return False
5353
else:
5454
return False

Diff for: src/cryptojwt/jwe/utils.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
from cryptography.hazmat.primitives.hashes import SHA384
88
from cryptography.hazmat.primitives.hashes import SHA512
99

10-
from ..utils import b64e
11-
1210
LENMET = {32: (16, SHA256), 48: (24, SHA384), 64: (32, SHA512)}
1311

1412

@@ -20,8 +18,8 @@ def get_keys_seclen_dgst(key, iv):
2018
# Select the digest to use based on key length
2119
try:
2220
seclen, hash_method = LENMET[len(key)]
23-
except KeyError:
24-
raise Exception("Invalid CBC+HMAC key length: %s bytes" % len(key))
21+
except KeyError as exc:
22+
raise Exception(f"Invalid CBC+HMAC key length: {len(key)} bytes") from exc
2523

2624
# Split the key
2725
ka = key[:seclen]

0 commit comments

Comments
 (0)