From 5fbc4d7a6b04831f04ccac2810da493afcec282a Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Wed, 29 May 2024 10:25:08 +0200 Subject: [PATCH 01/31] add ruff --- pyproject.toml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c296810..5b4db51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ python = "^3.9" cryptography = ">=3.4.6" requests = "^2.25.1" -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] alabaster = "^0.7.12" black = "^24.4.2" isort = "^5.13.2" @@ -54,7 +54,27 @@ responses = "^0.13.0" sphinx = "^3.5.2" sphinx-autobuild = "^2021.3.14" coverage = "^7" +ruff = "^0.4.6" +pytest-ruff = "^0.3.2" [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.ruff.lint] +select = [ + # pycodestyle + "E", + # Pyflakes + "F", + # pyupgrade + "UP", + # flake8-bugbear + "B", + # flake8-simplify + "SIM", + # isort + "I", +] +ignore = ["E501", "I001", "SIM102"] +exclude = ["examples/*"] From d379654f075dffed13f5c3ae2c7efadfbebf5861 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Wed, 29 May 2024 12:59:13 +0200 Subject: [PATCH 02/31] automatic fixes by ruff --- src/cryptojwt/jwe/__init__.py | 2 +- src/cryptojwt/jwe/aes.py | 2 +- src/cryptojwt/jwe/jwe.py | 4 +--- src/cryptojwt/jwe/utils.py | 2 -- src/cryptojwt/jwk/__init__.py | 14 +++++++------- src/cryptojwt/jwk/ec.py | 2 +- src/cryptojwt/jwk/hmac.py | 4 ++-- src/cryptojwt/jwk/jwk.py | 2 +- src/cryptojwt/jwk/okp.py | 6 +++--- src/cryptojwt/jwk/rsa.py | 6 ++---- src/cryptojwt/jwk/x509.py | 2 +- src/cryptojwt/jws/__init__.py | 2 +- src/cryptojwt/jws/dsa.py | 8 +++----- src/cryptojwt/jws/eddsa.py | 3 --- src/cryptojwt/jws/hmac.py | 2 +- src/cryptojwt/jws/jws.py | 10 ++++------ src/cryptojwt/jws/pss.py | 2 +- src/cryptojwt/jws/utils.py | 6 ++---- src/cryptojwt/jwt.py | 6 +++--- src/cryptojwt/key_bundle.py | 18 +++++++++--------- src/cryptojwt/key_issuer.py | 14 +++++++------- src/cryptojwt/key_jar.py | 22 +++++++++------------- src/cryptojwt/simple_jwt.py | 8 +++----- src/cryptojwt/tools/jwtpeek.py | 15 +++++---------- src/cryptojwt/tools/keyconv.py | 6 +++--- src/cryptojwt/tools/keygen.py | 9 ++++----- src/cryptojwt/utils.py | 6 +++--- tests/test_02_jwk.py | 6 +----- tests/test_03_key_bundle.py | 17 ++++++++--------- tests/test_04_key_issuer.py | 26 +++++++++++++------------- tests/test_04_key_jar.py | 28 ++++++++++++++-------------- tests/test_06_jws.py | 2 -- tests/test_09_jwt.py | 2 +- tests/test_30_tools.py | 2 +- tests/test_50_argument_alias.py | 6 +++--- 35 files changed, 119 insertions(+), 153 deletions(-) diff --git a/src/cryptojwt/jwe/__init__.py b/src/cryptojwt/jwe/__init__.py index ffddcf1..c0f0d65 100644 --- a/src/cryptojwt/jwe/__init__.py +++ b/src/cryptojwt/jwe/__init__.py @@ -38,7 +38,7 @@ } -class Encrypter(object): +class Encrypter: """Abstract base class for encryption algorithms.""" def __init__(self, with_digest=False): diff --git a/src/cryptojwt/jwe/aes.py b/src/cryptojwt/jwe/aes.py index c34ab45..502902e 100644 --- a/src/cryptojwt/jwe/aes.py +++ b/src/cryptojwt/jwe/aes.py @@ -30,7 +30,7 @@ def __init__(self, key_len=32, key=None, msg_padding="PKCS7"): self.padder = PKCS7(128).padder() self.unpadder = PKCS7(128).unpadder() else: - raise Unsupported("Message padding: {}".format(msg_padding)) + raise Unsupported(f"Message padding: {msg_padding}") self.iv = None diff --git a/src/cryptojwt/jwe/jwe.py b/src/cryptojwt/jwe/jwe.py index 5935c9b..1caed85 100644 --- a/src/cryptojwt/jwe/jwe.py +++ b/src/cryptojwt/jwe/jwe.py @@ -4,11 +4,9 @@ from ..jwk.ec import ECKey from ..jwk.hmac import SYMKey from ..jwk.jwk import key_from_jwk_dict -from ..jwk.rsa import RSAKey from ..jwx import JWx from .exception import DecryptionFailed from .exception import NoSuitableDecryptionKey -from .exception import NoSuitableECDHKey from .exception import NoSuitableEncryptionKey from .exception import NotSupportedAlgorithm from .exception import WrongEncryptionAlgorithm @@ -133,7 +131,7 @@ def encrypt(self, keys=None, cek="", iv="", **kwargs): except TypeError as err: raise err else: - logger.debug("Encrypted message using key with kid={}".format(key.kid)) + logger.debug(f"Encrypted message using key with kid={key.kid}") return token # logger.error("Could not find any suitable encryption key") diff --git a/src/cryptojwt/jwe/utils.py b/src/cryptojwt/jwe/utils.py index 2ee69b9..99152d0 100644 --- a/src/cryptojwt/jwe/utils.py +++ b/src/cryptojwt/jwe/utils.py @@ -7,8 +7,6 @@ from cryptography.hazmat.primitives.hashes import SHA384 from cryptography.hazmat.primitives.hashes import SHA512 -from ..utils import b64e - LENMET = {32: (16, SHA256), 48: (24, SHA384), 64: (32, SHA512)} diff --git a/src/cryptojwt/jwk/__init__.py b/src/cryptojwt/jwk/__init__.py index e17f5a1..070b56e 100644 --- a/src/cryptojwt/jwk/__init__.py +++ b/src/cryptojwt/jwk/__init__.py @@ -14,7 +14,7 @@ USE = {"sign": "sig", "decrypt": "enc", "encrypt": "enc", "verify": "sig"} -class JWK(object): +class JWK: """ Basic JSON Web key class. Jason Web keys are described in RFC 7517 (https://tools.ietf.org/html/rfc7517). @@ -56,7 +56,7 @@ def __init__( "ECDH-ES+A192KW", "ECDH-ES+A256KW", ]: - raise UnsupportedAlgorithm("Unknown algorithm: {}".format(alg)) + raise UnsupportedAlgorithm(f"Unknown algorithm: {alg}") elif use == "sig": # The list comes from https://tools.ietf.org/html/rfc7518#page-6 # Should map against SIGNER_ALGS in cryptojwt.jws.jws @@ -79,7 +79,7 @@ def __init__( "Ed448", "none", ]: - raise UnsupportedAlgorithm("Unknown algorithm: {}".format(alg)) + raise UnsupportedAlgorithm(f"Unknown algorithm: {alg}") else: # potentially used both for encryption and signing if alg not in [ "HS256", @@ -110,7 +110,7 @@ def __init__( "ECDH-ES+A192KW", "ECDH-ES+A256KW", ]: - raise UnsupportedAlgorithm("Unknown algorithm: {}".format(alg)) + raise UnsupportedAlgorithm(f"Unknown algorithm: {alg}") self.alg = alg if isinstance(use, str): @@ -271,7 +271,7 @@ def thumbprint(self, hash_function, members=None): else: if isinstance(_val, bytes): _val = as_unicode(_val) - _se.append('"{}":{}'.format(elem, json.dumps(_val))) + _se.append(f'"{elem}":{json.dumps(_val)}') _json = "{{{}}}".format(",".join(_se)) return b64e(DIGEST_HASH[hash_function](_json)) @@ -298,7 +298,7 @@ def update(self): pass def key_len(self): - raise NotImplemented + raise NotImplementedError def pems_to_x5c(cert_chain): @@ -360,7 +360,7 @@ def certificate_fingerprint(der, hash="sha256"): def pem_hash(pem_file): - with open(pem_file, "r") as fp: + with open(pem_file) as fp: pem = fp.read() der = ssl.PEM_cert_to_DER_cert(pem) diff --git a/src/cryptojwt/jwk/ec.py b/src/cryptojwt/jwk/ec.py index 0a6757a..c5fd5f6 100644 --- a/src/cryptojwt/jwk/ec.py +++ b/src/cryptojwt/jwk/ec.py @@ -339,5 +339,5 @@ def import_ec_key(pem_data): def import_ec_key_from_cert_file(pem_file): - with open(pem_file, "r") as cert_file: + with open(pem_file) as cert_file: return import_ec_key(cert_file.read()) diff --git a/src/cryptojwt/jwk/hmac.py b/src/cryptojwt/jwk/hmac.py index f86c366..a68fac0 100644 --- a/src/cryptojwt/jwk/hmac.py +++ b/src/cryptojwt/jwk/hmac.py @@ -90,7 +90,7 @@ def appropriate_for(self, usage, alg="HS256"): else: return self.encryption_key(alg) - raise WrongUsage("This key can't be used for {}".format(usage)) + raise WrongUsage(f"This key can't be used for {usage}") def encryption_key(self, alg, **kwargs): """ @@ -121,7 +121,7 @@ def encryption_key(self, alg, **kwargs): else: raise JWKException("No support for symmetric keys > 512 bits") - logger.debug("Symmetric encryption key: {}".format(as_unicode(b64e(_enc_key)))) + logger.debug(f"Symmetric encryption key: {as_unicode(b64e(_enc_key))}") return _enc_key diff --git a/src/cryptojwt/jwk/jwk.py b/src/cryptojwt/jwk/jwk.py index 0e10a95..4c2e5db 100644 --- a/src/cryptojwt/jwk/jwk.py +++ b/src/cryptojwt/jwk/jwk.py @@ -74,7 +74,7 @@ def ensure_params(kty, provided, required): """Ensure all required parameters are present in dictionary""" if not required <= provided: missing = required - provided - raise MissingValue("Missing properties for kty={}, {}".format(kty, str(list(missing)))) + raise MissingValue(f"Missing properties for kty={kty}, {str(list(missing))}") def key_from_jwk_dict(jwk_dict, private=None): diff --git a/src/cryptojwt/jwk/okp.py b/src/cryptojwt/jwk/okp.py index 8315962..ffeeb81 100644 --- a/src/cryptojwt/jwk/okp.py +++ b/src/cryptojwt/jwk/okp.py @@ -146,7 +146,7 @@ def deserialize(self): try: self.priv_key = OKP_CRV2PRIVATE[self.crv].from_private_bytes(deser(self.d)) except KeyError: - raise UnsupportedOKPCurve("Unsupported OKP curve: {}".format(self.crv)) + raise UnsupportedOKPCurve(f"Unsupported OKP curve: {self.crv}") self.pub_key = self.priv_key.public_key() except ValueError as err: raise DeSerializationNotPossible(str(err)) @@ -154,7 +154,7 @@ def deserialize(self): try: self.pub_key = OKP_CRV2PUBLIC[self.crv].from_public_bytes(_x) except KeyError: - raise UnsupportedOKPCurve("Unsupported OKP curve: {}".format(self.crv)) + raise UnsupportedOKPCurve(f"Unsupported OKP curve: {self.crv}") def _serialize_public(self, key): self.x = b64e( @@ -376,5 +376,5 @@ def import_okp_key(pem_data): def import_okp_key_from_cert_file(pem_file): - with open(pem_file, "r") as cert_file: + with open(pem_file) as cert_file: return import_okp_key(cert_file.read()) diff --git a/src/cryptojwt/jwk/rsa.py b/src/cryptojwt/jwk/rsa.py index e4290e9..319cd7f 100644 --- a/src/cryptojwt/jwk/rsa.py +++ b/src/cryptojwt/jwk/rsa.py @@ -105,7 +105,7 @@ def import_rsa_key(pem_data): def import_rsa_key_from_cert_file(pem_file): - with open(pem_file, "r") as cert_file: + with open(pem_file) as cert_file: return import_rsa_key(cert_file.read()) @@ -284,9 +284,7 @@ def __init__( self.pub_key = self.priv_key.public_key() elif self.pub_key: self._serialize(self.pub_key) - elif has_public_key_parts: - self.deserialize() - elif has_x509_cert_chain: + elif has_public_key_parts or has_x509_cert_chain: self.deserialize() elif not self.n and not self.e: pass diff --git a/src/cryptojwt/jwk/x509.py b/src/cryptojwt/jwk/x509.py index d1fd885..87a627c 100644 --- a/src/cryptojwt/jwk/x509.py +++ b/src/cryptojwt/jwk/x509.py @@ -50,7 +50,7 @@ def import_public_key_from_pem_data(pem_data): :return: rsa.RSAPublicKey instance """ if not pem_data.startswith(PREFIX): - pem_data = bytes("{}\n{}\n{}".format(PREFIX, pem_data, POSTFIX), "utf-8") + pem_data = bytes(f"{PREFIX}\n{pem_data}\n{POSTFIX}", "utf-8") else: pem_data = bytes(pem_data, "utf-8") cert = x509.load_pem_x509_certificate(pem_data) diff --git a/src/cryptojwt/jws/__init__.py b/src/cryptojwt/jws/__init__.py index d77eb74..b3482b3 100644 --- a/src/cryptojwt/jws/__init__.py +++ b/src/cryptojwt/jws/__init__.py @@ -1,4 +1,4 @@ -class Signer(object): +class Signer: """Abstract base class for signing algorithms.""" def sign(self, msg, key): diff --git a/src/cryptojwt/jws/dsa.py b/src/cryptojwt/jws/dsa.py index 6ddedcf..8d143d4 100644 --- a/src/cryptojwt/jws/dsa.py +++ b/src/cryptojwt/jws/dsa.py @@ -1,5 +1,3 @@ -import sys - from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import ec @@ -26,7 +24,7 @@ def __init__(self, algorithm="ES256"): self.hash_algorithm = hashes.SHA512 self.curve_name = "secp521r1" else: - raise Unsupported("algorithm: {}".format(algorithm)) + raise Unsupported(f"algorithm: {algorithm}") self.algorithm = algorithm @@ -92,8 +90,8 @@ def _cross_check(self, pub_key): """ if self.curve_name != pub_key.curve.name: raise ValueError( - "The curve in private key {} and in algorithm {} don't " - "match".format(pub_key.curve.name, self.curve_name) + f"The curve in private key {pub_key.curve.name} and in algorithm {self.curve_name} don't " + "match" ) @staticmethod diff --git a/src/cryptojwt/jws/eddsa.py b/src/cryptojwt/jws/eddsa.py index 6a88f8e..97022d8 100644 --- a/src/cryptojwt/jws/eddsa.py +++ b/src/cryptojwt/jws/eddsa.py @@ -1,11 +1,8 @@ -import sys - from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives.asymmetric import ed448 from cryptography.hazmat.primitives.asymmetric import ed25519 from ..exception import BadSignature -from ..exception import Unsupported from . import Signer diff --git a/src/cryptojwt/jws/hmac.py b/src/cryptojwt/jws/hmac.py index e084e22..be48f8d 100644 --- a/src/cryptojwt/jws/hmac.py +++ b/src/cryptojwt/jws/hmac.py @@ -14,7 +14,7 @@ def __init__(self, algorithm="SHA256"): elif algorithm == "SHA512": self.algorithm = hashes.SHA512 else: - raise Unsupported("algorithm: {}".format(algorithm)) + raise Unsupported(f"algorithm: {algorithm}") def sign(self, msg, key): """ diff --git a/src/cryptojwt/jws/jws.py b/src/cryptojwt/jws/jws.py index 9306a29..4e3b983 100644 --- a/src/cryptojwt/jws/jws.py +++ b/src/cryptojwt/jws/jws.py @@ -238,7 +238,7 @@ def verify_compact_verbose(self, jws=None, keys=None, allow_none=False, sigalg=N except (BadSignature, IndexError): pass except (ValueError, TypeError) as err: - logger.warning('Exception "{}" caught'.format(err)) + logger.warning(f'Exception "{err}" caught') else: logger.debug("Verified message using key with kid=%s" % key.kid) self.msg = jwt.payload() @@ -347,13 +347,11 @@ def verify_json(self, jws, keys=None, allow_none=False, at_least_one=False): _tmp = self.verify_compact(token, keys, allow_none) except NoSuitableSigningKeys: if at_least_one is True: - logger.warning( - "Could not verify signature with headers: {}".format(all_headers) - ) + logger.warning(f"Could not verify signature with headers: {all_headers}") continue else: raise - except JWSException as err: + except JWSException: raise if _claim is None: @@ -412,7 +410,7 @@ def _is_compact_jws(self, jws): try: jwt = JWSig().unpack(jws) except Exception as err: - logger.warning("Could not parse JWS: {}".format(err)) + logger.warning(f"Could not parse JWS: {err}") return False if "alg" not in jwt.headers: diff --git a/src/cryptojwt/jws/pss.py b/src/cryptojwt/jws/pss.py index 3d3da8d..f7c22ff 100644 --- a/src/cryptojwt/jws/pss.py +++ b/src/cryptojwt/jws/pss.py @@ -21,7 +21,7 @@ def __init__(self, algorithm="SHA256"): elif algorithm == "SHA512": self.hash_algorithm = hashes.SHA512 else: - raise Unsupported("algorithm: {}".format(algorithm)) + raise Unsupported(f"algorithm: {algorithm}") def sign(self, msg, key): """ diff --git a/src/cryptojwt/jws/utils.py b/src/cryptojwt/jws/utils.py index 40ac46f..c025282 100644 --- a/src/cryptojwt/jws/utils.py +++ b/src/cryptojwt/jws/utils.py @@ -47,9 +47,7 @@ def alg2keytype(alg): return "RSA" elif alg.startswith("HS") or alg.startswith("A"): return "oct" - elif alg == "Ed25519": - return "OKP" - elif alg == "Ed448": + elif alg == "Ed25519" or alg == "Ed448": return "OKP" elif alg.startswith("ES") or alg.startswith("ECDH-ES"): return "EC" @@ -91,4 +89,4 @@ def parse_rsa_algorithm(algorithm): padding.PSS(mgf=padding.MGF1(hashes.SHA512()), salt_length=padding.PSS.MAX_LENGTH), ) else: - raise UnsupportedAlgorithm("Unknown algorithm: {}".format(algorithm)) + raise UnsupportedAlgorithm(f"Unknown algorithm: {algorithm}") diff --git a/src/cryptojwt/jwt.py b/src/cryptojwt/jwt.py index 37ee035..6116513 100755 --- a/src/cryptojwt/jwt.py +++ b/src/cryptojwt/jwt.py @@ -67,7 +67,7 @@ def pick_key(keys, use, alg="", key_type="", kid=""): if key.alg == "" and alg: if key_type == "EC": - if key.crv != "P-{}".format(alg[2:]): + if key.crv != f"P-{alg[2:]}": continue elif alg and key.alg != alg: continue @@ -209,7 +209,7 @@ def pack_key(self, issuer_id="", kid=""): keys = pick_key(self.my_keys(issuer_id, "sig"), "sig", alg=self.alg, kid=kid) if not keys: - raise NoSuitableSigningKeys("kid={}".format(kid)) + raise NoSuitableSigningKeys(f"kid={kid}") return keys[0] # Might be more then one if kid == '' @@ -225,7 +225,7 @@ def pack( aud: Optional[str] = None, iat: Optional[int] = None, jws_headers: Optional[Dict[str, str]] = None, - **kwargs + **kwargs, ) -> str: """ diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 0708d0e..82df3b5 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -375,7 +375,7 @@ def jwk_dicts_as_keys(self, keys): except KeyError: if not self.ignore_invalid_keys: raise UnknownKeyType(inst) - _error = "UnknownKeyType: {}".format(_typ) + _error = f"UnknownKeyType: {_typ}" continue except (UnsupportedECurve, UnsupportedAlgorithm) as err: if not self.ignore_invalid_keys: @@ -441,7 +441,7 @@ def _do_local_der(self, filename, keytype, keyusage=None, kid=""): key_args["priv_key"] = _key key_args["pub_key"] = _key.public_key() else: - raise NotImplementedError("No support for DER decoding of key type {}".format(_kty)) + raise NotImplementedError(f"No support for DER decoding of key type {_kty}") if not keyusage: key_args["use"] = ["enc", "sig"] @@ -506,7 +506,7 @@ def _do_remote(self, set_keys=True): raise UpdateFailed(MALFORMED.format(self.source)) if hasattr(_http_resp, "headers"): - headers = getattr(_http_resp, "headers") + headers = _http_resp.headers self.last_remote = headers.get("last-modified") or headers.get("date") elif not_modified: LOGGER.debug("%s not modified since %s", self.source, self.last_remote) @@ -646,7 +646,7 @@ def remove_keys_by_type(self, typ): :param typ: Type of key (rsa, ec, oct, ..) """ _typs = [typ.lower(), typ.upper()] - self._keys = [k for k in self._keys if not k.kty in _typs] + self._keys = [k for k in self._keys if k.kty not in _typs] def __str__(self): return str(self.jwks()) @@ -936,7 +936,7 @@ def dump_jwks(kbl, target, private=False, symmetric_too=False): try: _fp = open(target, "w") - except IOError: + except OSError: head, _ = os.path.split(target) os.makedirs(head) _fp = open(target, "w") @@ -1325,13 +1325,13 @@ def key_gen(type, **kwargs): crv = kwargs.get("crv", DEFAULT_EC_CURVE) if crv not in NIST2SEC: logging.error("Unknown curve: %s", crv) - raise ValueError("Unknown curve: {}".format(crv)) + raise ValueError(f"Unknown curve: {crv}") _key = new_ec_key(crv=crv, **kargs) elif type.upper() == "OKP": crv = kwargs.get("crv", DEFAULT_OKP_CURVE) if crv not in OKP_CRV2PUBLIC: logging.error("Unknown curve: %s", crv) - raise ValueError("Unknown curve: {}".format(crv)) + raise ValueError(f"Unknown curve: {crv}") _key = new_okp_key(crv=crv, **kargs) elif type.lower() in ["sym", "oct"]: keysize = kwargs.get("bytes", 24) @@ -1339,7 +1339,7 @@ def key_gen(type, **kwargs): _key = SYMKey(key=randomkey, **kargs) else: logging.error("Unknown key type: %s", type) - raise ValueError("Unknown key type: %s".format(type)) + raise ValueError("Unknown key type: %s".format()) return _key @@ -1374,4 +1374,4 @@ def key_by_alg(alg: str): elif alg.startswith("HS"): return key_gen("sym") - raise ValueError("Don't know who to create a key to use with '{}'".format(alg)) + raise ValueError(f"Don't know who to create a key to use with '{alg}'") diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index 08e540a..c797461 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -21,7 +21,7 @@ logger = logging.getLogger(__name__) -class KeyIssuer(object): +class KeyIssuer: """A key issuer instance contains a number of KeyBundles.""" params = { @@ -65,7 +65,7 @@ def __init__( self.spec2key = {} def __repr__(self) -> str: - return ''.format(self.name, self.key_summary()) + return f'' def __getitem__(self, item): return self.get_bundles()[item] @@ -327,7 +327,7 @@ def get(self, key_use, key_type="", kid=None, alg="", **kwargs): # if elliptic curve, have to check if I have a key of the right curve if key_type and key_type.upper() == "EC": if alg: - name = "P-{}".format(alg[2:]) # the type + name = f"P-{alg[2:]}" # the type _lst = [] for key in lst: if name != key.crv: @@ -443,9 +443,9 @@ def key_summary(self) -> str: for kb in self._bundles: for key in kb.keys(): if key.inactive_since: - key_list.append("*{}:{}:{}".format(key.kty, key.use, key.kid)) + key_list.append(f"*{key.kty}:{key.use}:{key.kid}") else: - key_list.append("{}:{}:{}".format(key.kty, key.use, key.kid)) + key_list.append(f"{key.kty}:{key.use}:{key.kid}") return ", ".join(key_list) def __iter__(self): @@ -586,7 +586,7 @@ def init_key_issuer(public_path="", private_path="", key_defs="", read_only=True if private_path: if os.path.isfile(private_path): - _jwks = open(private_path, "r").read() + _jwks = open(private_path).read() _issuer = KeyIssuer() _issuer.import_jwks(json.loads(_jwks)) if key_defs: @@ -623,7 +623,7 @@ def init_key_issuer(public_path="", private_path="", key_defs="", read_only=True fp.close() elif public_path: if os.path.isfile(public_path): - _jwks = open(public_path, "r").read() + _jwks = open(public_path).read() _issuer = KeyIssuer() _issuer.import_jwks(json.loads(_jwks)) if key_defs: diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 2bec768..e16e40c 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -24,7 +24,7 @@ logger = logging.getLogger(__name__) -class KeyJar(object): +class KeyJar: """A keyjar contains a number of KeyBundles sorted by owner/issuer""" def __init__( @@ -102,7 +102,7 @@ def items(self): def __repr__(self): issuers = self._issuer_ids() - return "".format(issuers) + return f"" @deprecated_alias(issuer="issuer_id", owner="issuer_id") def return_issuer(self, issuer_id): @@ -307,7 +307,7 @@ def match_owner(self, url): if _iss: return _iss[0] - raise KeyError("No keys for '{}' in this keyjar".format(url)) + raise KeyError(f"No keys for '{url}' in this keyjar") def __str__(self): _res = {} @@ -484,10 +484,10 @@ def _add_key( ): _issuer = self._get_issuer(issuer_id) if _issuer is None: - logger.error('Issuer "{}" not in keyjar'.format(issuer_id)) + logger.error(f'Issuer "{issuer_id}" not in keyjar') raise IssuerNotFound(issuer_id) - logger.debug("Key summary for {}: {}".format(issuer_id, _issuer.key_summary())) + logger.debug(f"Key summary for {issuer_id}: {_issuer.key_summary()}") if kid: for _key in _issuer.get(use, kid=kid, key_type=key_type): @@ -674,11 +674,7 @@ def dump( except KeyError: pass - if exclude_attributes is None: - info["issuers"] = self._dump_issuers( - exclude_issuers=exclude_issuers, exclude_attributes=exclude_attributes - ) - elif "issuers" not in exclude_attributes: + if exclude_attributes is None or "issuers" not in exclude_attributes: info["issuers"] = self._dump_issuers( exclude_issuers=exclude_issuers, exclude_attributes=exclude_attributes ) @@ -706,13 +702,13 @@ def load( :param info: A dictionary with the information :return: """ - self.ca_certs = info.get("ca_certs", None) - self.httpc_params = info.get("httpc_params", None) + self.ca_certs = info.get("ca_certs") + self.httpc_params = info.get("httpc_params") self.keybundle_cls = importer(info.get("keybundle_cls", KeyBundle)) self.remove_after = info.get("remove_after", 3600) self.spec2key = info.get("spec2key", {}) - _issuers = info.get("issuers", None) + _issuers = info.get("issuers") if _issuers is None: self._issuers = {} else: diff --git a/src/cryptojwt/simple_jwt.py b/src/cryptojwt/simple_jwt.py index fbdaf2b..bbcc456 100644 --- a/src/cryptojwt/simple_jwt.py +++ b/src/cryptojwt/simple_jwt.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) -class SimpleJWT(object): +class SimpleJWT: """ Basic JSON Web Token class that doesn't make any assumptions as to what can or should be in the payload @@ -55,9 +55,7 @@ def unpack(self, token, **kwargs): raise else: if not _ok: - raise HeaderError( - 'Expected "{}" to be "{}", was "{}"'.format(key, val, self.headers[key]) - ) + raise HeaderError(f'Expected "{key}" to be "{val}", was "{self.headers[key]}"') return self @@ -75,7 +73,7 @@ def pack(self, parts=None, headers=None): else: headers = {"alg": "none"} - logging.debug("(pack) JWT header: {}".format(headers)) + logging.debug(f"(pack) JWT header: {headers}") if not parts: return ".".join([a.decode() for a in self.b64part]) diff --git a/src/cryptojwt/tools/jwtpeek.py b/src/cryptojwt/tools/jwtpeek.py index a0f420e..aa808cf 100755 --- a/src/cryptojwt/tools/jwtpeek.py +++ b/src/cryptojwt/tools/jwtpeek.py @@ -18,7 +18,6 @@ from cryptojwt.jws import jws from cryptojwt.key_bundle import KeyBundle from cryptojwt.key_issuer import KeyIssuer -from cryptojwt.key_jar import KeyJar __author__ = "roland" @@ -53,7 +52,7 @@ def process(jwt, keys, quiet): if _jw: if not quiet: print("Encrypted JSON Web Token") - print("Headers: {}".format(_jw.jwt.headers)) + print(f"Headers: {_jw.jwt.headers}") if keys: res = _jw.decrypt(keys=keys) json_object = json.loads(res) @@ -71,17 +70,15 @@ def process(jwt, keys, quiet): print(highlight(json_str, JsonLexer(), TerminalFormatter())) else: print("Signed JSON Web Token") - print("Headers: {}".format(_jw.jwt.headers)) + print(f"Headers: {_jw.jwt.headers}") if keys: res = _jw.verify_compact(keys=keys) - print("Verified message: {}".format(res)) + print(f"Verified message: {res}") else: json_object = json.loads(_jw.jwt.part[1].decode("utf-8")) json_str = json.dumps(json_object, indent=2) print( - "Unverified message: {}".format( - highlight(json_str, JsonLexer(), TerminalFormatter()) - ) + f"Unverified message: {highlight(json_str, JsonLexer(), TerminalFormatter())}" ) @@ -127,9 +124,7 @@ def main(): _kb = KeyBundle(source=args.jwks_url) keys.extend(_kb.get()) - if not args.msg: # If nothing specified assume stdin - message = sys.stdin.read() - elif args.msg == "-": + if not args.msg or args.msg == "-": # If nothing specified assume stdin message = sys.stdin.read() else: if os.path.isfile(args.msg): diff --git a/src/cryptojwt/tools/keyconv.py b/src/cryptojwt/tools/keyconv.py index 969a2b0..5a9234d 100644 --- a/src/cryptojwt/tools/keyconv.py +++ b/src/cryptojwt/tools/keyconv.py @@ -25,7 +25,7 @@ def jwk_from_file(filename: str, private: bool = True) -> JWK: """Read JWK from file""" - with open(filename, mode="rt") as input_file: + with open(filename) as input_file: jwk_dict = json.loads(input_file.read()) return key_from_jwk_dict(jwk_dict, private=private) @@ -93,7 +93,7 @@ def pem2jwk( passphrase: Optional[str] = None, ) -> JWK: """Read PEM from filename and return JWK""" - with open(filename, "rt") as file: + with open(filename) as file: content = file.readlines() header = content[0] @@ -178,7 +178,7 @@ def output_jwk(jwk: JWK, private: bool = False, filename: Optional[str] = None) """Output JWK to file""" serialized = jwk.serialize(private=private) if filename is not None: - with open(filename, mode="wt") as file: + with open(filename, mode="w") as file: file.write(json.dumps(serialized)) else: print(json.dumps(serialized, indent=4)) diff --git a/src/cryptojwt/tools/keygen.py b/src/cryptojwt/tools/keygen.py index 3a02861..718bb62 100644 --- a/src/cryptojwt/tools/keygen.py +++ b/src/cryptojwt/tools/keygen.py @@ -11,7 +11,6 @@ from cryptojwt.jwk.okp import OKP_CRV2PUBLIC from cryptojwt.jwk.okp import new_okp_key from cryptojwt.jwk.rsa import new_rsa_key -from cryptojwt.utils import b64e DEFAULT_SYM_KEYSIZE = 32 DEFAULT_RSA_KEYSIZE = 2048 @@ -38,7 +37,7 @@ def main(): dest="rsa_exp", type=int, metavar="exponent", - help="RSA public key exponent (default {})".format(DEFAULT_RSA_EXP), + help=f"RSA public key exponent (default {DEFAULT_RSA_EXP})", default=DEFAULT_RSA_EXP, ) parser.add_argument("--kid", dest="kid", metavar="id", help="Key ID") @@ -50,12 +49,12 @@ def main(): jwk = new_rsa_key(public_exponent=args.rsa_exp, key_size=args.keysize, kid=args.kid) elif args.kty.upper() == "EC": if args.crv not in NIST2SEC: - print("Unknown curve: {0}".format(args.crv), file=sys.stderr) + print(f"Unknown curve: {args.crv}", file=sys.stderr) exit(1) jwk = new_ec_key(crv=args.crv, kid=args.kid) elif args.kty.upper() == "OKP": if args.crv not in OKP_CRV2PUBLIC: - print("Unknown curve: {0}".format(args.crv), file=sys.stderr) + print(f"Unknown curve: {args.crv}", file=sys.stderr) exit(1) jwk = new_okp_key(crv=args.crv, kid=args.kid) elif args.kty.upper() == "SYM" or args.kty.upper() == "OCT": @@ -63,7 +62,7 @@ def main(): args.keysize = DEFAULT_SYM_KEYSIZE jwk = new_sym_key(bytes=args.keysize, kid=args.kid) else: - print("Unknown key type: {}".format(args.kty), file=sys.stderr) + print(f"Unknown key type: {args.kty}", file=sys.stderr) exit(1) jwk_dict = jwk.serialize(private=True) diff --git a/src/cryptojwt/utils.py b/src/cryptojwt/utils.py index 5c13d91..47be894 100644 --- a/src/cryptojwt/utils.py +++ b/src/cryptojwt/utils.py @@ -172,7 +172,7 @@ def bytes2str_conv(item): elif isinstance(item, dict): return dict([(k, bytes2str_conv(v)) for k, v in item.items()]) - raise ValueError("Can't convert {}.".format(repr(item))) + raise ValueError(f"Can't convert {repr(item)}.") def b64encode_item(item): @@ -256,8 +256,8 @@ def rename_kwargs(func_name, kwargs, aliases): for alias, new in aliases.items(): if alias in kwargs: if new in kwargs: - raise TypeError("{} received both {} and {}".format(func_name, alias, new)) - warnings.warn("{} is deprecated; use {}".format(alias, new), DeprecationWarning) + raise TypeError(f"{func_name} received both {alias} and {new}") + warnings.warn(f"{alias} is deprecated; use {new}", DeprecationWarning) kwargs[new] = kwargs.pop(alias) diff --git a/tests/test_02_jwk.py b/tests/test_02_jwk.py index c01e85a..b26f3b0 100755 --- a/tests/test_02_jwk.py +++ b/tests/test_02_jwk.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -from __future__ import print_function import base64 import json @@ -9,11 +8,8 @@ import pytest from cryptography.hazmat.primitives.asymmetric import ec -from cryptography.hazmat.primitives.asymmetric import ed448 from cryptography.hazmat.primitives.asymmetric import ed25519 from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.hazmat.primitives.asymmetric import x448 -from cryptography.hazmat.primitives.asymmetric import x25519 from cryptojwt.exception import DeSerializationNotPossible from cryptojwt.exception import UnsupportedAlgorithm @@ -566,7 +562,7 @@ def test_jwk_conversion(): def test_str(): _j = RSAKey(alg="RS512", use="sig", n=N, e=E) - s = "{}".format(_j) + s = f"{_j}" assert s.startswith("{") and s.endswith("}") sp = s.replace("'", '"') _d = json.loads(sp) diff --git a/tests/test_03_key_bundle.py b/tests/test_03_key_bundle.py index e484192..b9a2217 100755 --- a/tests/test_03_key_bundle.py +++ b/tests/test_03_key_bundle.py @@ -15,7 +15,6 @@ from cryptojwt.jwk.ec import new_ec_key from cryptojwt.jwk.hmac import SYMKey from cryptojwt.jwk.okp import OKPKey -from cryptojwt.jwk.okp import new_okp_key from cryptojwt.jwk.rsa import RSAKey from cryptojwt.jwk.rsa import import_rsa_key_from_cert_file from cryptojwt.jwk.rsa import new_rsa_key @@ -269,7 +268,7 @@ def test_get_all(): def test_keybundle_from_local_der(): - kb = keybundle_from_local_file("{}".format(RSA0), "der", ["enc"]) + kb = keybundle_from_local_file(f"{RSA0}", "der", ["enc"]) assert len(kb) == 1 keys = kb.get("rsa") assert len(keys) == 1 @@ -279,7 +278,7 @@ def test_keybundle_from_local_der(): def test_ec_keybundle_from_local_der(): - kb = keybundle_from_local_file("{}".format(EC0), "der", ["enc"], keytype="EC") + kb = keybundle_from_local_file(f"{EC0}", "der", ["enc"], keytype="EC") assert len(kb) == 1 keys = kb.get("ec") assert len(keys) == 1 @@ -289,7 +288,7 @@ def test_ec_keybundle_from_local_der(): def test_keybundle_from_local_der_update(): - kb = keybundle_from_local_file("file://{}".format(RSA0), "der", ["enc"]) + kb = keybundle_from_local_file(f"file://{RSA0}", "der", ["enc"]) assert len(kb) == 1 keys = kb.get("rsa") assert len(keys) == 1 @@ -433,14 +432,14 @@ def test_copy(): def test_local_jwk(): _path = full_path("jwk_private_key.json") - kb = KeyBundle(source="file://{}".format(_path)) + kb = KeyBundle(source=f"file://{_path}") assert kb def test_local_jwk_update(): cache_time = 0.1 _path = full_path("jwk_private_key.json") - kb = KeyBundle(source="file://{}".format(_path), cache_time=cache_time) + kb = KeyBundle(source=f"file://{_path}", cache_time=cache_time) assert kb _ = kb.keys() last1 = kb.last_local @@ -456,7 +455,7 @@ def test_local_jwk_update(): def test_local_jwk_copy(): _path = full_path("jwk_private_key.json") - kb = KeyBundle(source="file://{}".format(_path)) + kb = KeyBundle(source=f"file://{_path}") kb2 = kb.copy() assert kb2.source == kb.source @@ -506,7 +505,7 @@ def test_update_2(): with open(fname, "w") as fp: fp.write(json.dumps(_jwks)) - kb = KeyBundle(source="file://{}".format(fname), fileformat="jwks") + kb = KeyBundle(source=f"file://{fname}", fileformat="jwks") assert len(kb) == 1 # Added one more key @@ -528,7 +527,7 @@ def test_update_mark_inactive(): with open(fname, "w") as fp: fp.write(json.dumps(_jwks)) - kb = KeyBundle(source="file://{}".format(fname), fileformat="jwks") + kb = KeyBundle(source=f"file://{fname}", fileformat="jwks") assert len(kb) == 1 # new set of keys diff --git a/tests/test_04_key_issuer.py b/tests/test_04_key_issuer.py index 6ff041f..6278c7b 100755 --- a/tests/test_04_key_issuer.py +++ b/tests/test_04_key_issuer.py @@ -208,7 +208,7 @@ def test_build_EC_keyissuer_from_file(tmpdir): assert len(key_issuer) == 2 -class TestKeyJar(object): +class TestKeyJar: def test_keyissuer_add(self): issuer = KeyIssuer() kb = keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]) @@ -480,8 +480,8 @@ def test_keyissuer_eq(): assert kj1 == kj2 -PUBLIC_FILE = "{}/public_jwks.json".format(BASEDIR) -PRIVATE_FILE = "{}/private_jwks.json".format(BASEDIR) +PUBLIC_FILE = f"{BASEDIR}/public_jwks.json" +PRIVATE_FILE = f"{BASEDIR}/private_jwks.json" KEYSPEC = [ {"type": "RSA", "use": ["sig"]}, {"type": "EC", "crv": "P-256", "use": ["sig"]}, @@ -598,17 +598,17 @@ def test_init_key_issuer_update(): OIDC_KEYS = { - "private_path": "{}/priv/jwks.json".format(BASEDIR), + "private_path": f"{BASEDIR}/priv/jwks.json", "key_defs": KEYSPEC, - "public_path": "{}/public/jwks.json".format(BASEDIR), + "public_path": f"{BASEDIR}/public/jwks.json", } def test_init_key_issuer_create_directories(): # make sure the directories are gone for _dir in ["priv", "public"]: - if os.path.isdir("{}/{}".format(BASEDIR, _dir)): - shutil.rmtree("{}/{}".format(BASEDIR, _dir)) + if os.path.isdir(f"{BASEDIR}/{_dir}"): + shutil.rmtree(f"{BASEDIR}/{_dir}") _keyissuer = init_key_issuer(**OIDC_KEYS) assert len(_keyissuer.get("sig", "RSA")) == 1 @@ -617,7 +617,7 @@ def test_init_key_issuer_create_directories(): OIDC_PUB_KEYS = { "key_defs": KEYSPEC, - "public_path": "{}/public/jwks.json".format(BASEDIR), + "public_path": f"{BASEDIR}/public/jwks.json", "read_only": False, } @@ -625,8 +625,8 @@ def test_init_key_issuer_create_directories(): def test_init_key_issuer_public_key_only(): # make sure the directories are gone for _dir in ["public"]: - if os.path.isdir("{}/{}".format(BASEDIR, _dir)): - shutil.rmtree("{}/{}".format(BASEDIR, _dir)) + if os.path.isdir(f"{BASEDIR}/{_dir}"): + shutil.rmtree(f"{BASEDIR}/{_dir}") _keyissuer = init_key_issuer(**OIDC_PUB_KEYS) assert len(_keyissuer.get("sig", "RSA")) == 1 @@ -639,7 +639,7 @@ def test_init_key_issuer_public_key_only(): OIDC_PUB_KEYS2 = { "key_defs": KEYSPEC_3, - "public_path": "{}/public/jwks.json".format(BASEDIR), + "public_path": f"{BASEDIR}/public/jwks.json", "read_only": False, } @@ -647,8 +647,8 @@ def test_init_key_issuer_public_key_only(): def test_init_key_issuer_public_key_only_with_diff(): # make sure the directories are gone for _dir in ["public"]: - if os.path.isdir("{}/{}".format(BASEDIR, _dir)): - shutil.rmtree("{}/{}".format(BASEDIR, _dir)) + if os.path.isdir(f"{BASEDIR}/{_dir}"): + shutil.rmtree(f"{BASEDIR}/{_dir}") _keyissuer = init_key_issuer(**OIDC_PUB_KEYS) assert len(_keyissuer.get("sig", "RSA")) == 1 diff --git a/tests/test_04_key_jar.py b/tests/test_04_key_jar.py index c2d9d2d..acf7485 100755 --- a/tests/test_04_key_jar.py +++ b/tests/test_04_key_jar.py @@ -215,7 +215,7 @@ def test_build_EC_keyjar_from_file(tmpdir): assert len(key_jar[""]) == 2 -class TestKeyJar(object): +class TestKeyJar: def test_keyjar_add(self): kj = KeyJar() kb = keybundle_from_local_file(RSAKEY, "der", ["ver", "sig"]) @@ -411,7 +411,7 @@ def test_provider(self): ) iss_keys = kj.get_issuer_keys("https://connect-op.heroku.com") if not iss_keys: - _msg = "{} is not available at this moment!".format(_url) + _msg = f"{_url} is not available at this moment!" warnings.warn(_msg) else: assert iss_keys[0].keys() @@ -628,7 +628,7 @@ def test_keys_by_alg_and_usage(): assert len(k) == 2 -class TestVerifyJWTKeys(object): +class TestVerifyJWTKeys: @pytest.fixture(autouse=True) def setup(self): mkey = [ @@ -789,7 +789,7 @@ def test_str(): kj = KeyJar() kj.add_kb("Alice", KeyBundle(JWK0["keys"])) - desc = "{}".format(kj) + desc = f"{kj}" _cont = json.loads(desc) assert set(_cont.keys()) == {"Alice"} @@ -803,13 +803,13 @@ def test_load_keys(): def test_find(): _path = full_path("jwk_private_key.json") - kb = KeyBundle(source="file://{}".format(_path)) + kb = KeyBundle(source=f"file://{_path}") kj = KeyJar() kj.add_kb("Alice", kb) - assert kj.find("{}".format(_path), "Alice") + assert kj.find(f"{_path}", "Alice") assert kj.find("https://example.com", "Alice") == [] - assert kj.find("{}".format(_path), "Bob") is None + assert kj.find(f"{_path}", "Bob") is None def test_get_decrypt_keys(): @@ -839,7 +839,7 @@ def test_get_decrypt_keys(): def test_update_keyjar(): _path = full_path("jwk_private_key.json") - kb = KeyBundle(source="file://{}".format(_path)) + kb = KeyBundle(source=f"file://{_path}") kj = KeyJar() kj.add_kb("Alice", kb) @@ -856,8 +856,8 @@ def test_key_summary(): assert out == "RSA::abc" -PUBLIC_FILE = "{}/public_jwks.json".format(BASEDIR) -PRIVATE_FILE = "{}/private_jwks.json".format(BASEDIR) +PUBLIC_FILE = f"{BASEDIR}/public_jwks.json" +PRIVATE_FILE = f"{BASEDIR}/private_jwks.json" KEYSPEC = [ {"type": "RSA", "use": ["sig"]}, {"type": "EC", "crv": "P-256", "use": ["sig"]}, @@ -977,17 +977,17 @@ def test_init_key_jar_update(): OIDC_KEYS = { - "private_path": "{}/priv/jwks.json".format(BASEDIR), + "private_path": f"{BASEDIR}/priv/jwks.json", "key_defs": KEYSPEC, - "public_path": "{}/public/jwks.json".format(BASEDIR), + "public_path": f"{BASEDIR}/public/jwks.json", } def test_init_key_jar_create_directories(): # make sure the directories are gone for _dir in ["priv", "public"]: - if os.path.isdir("{}/{}".format(BASEDIR, _dir)): - shutil.rmtree("{}/{}".format(BASEDIR, _dir)) + if os.path.isdir(f"{BASEDIR}/{_dir}"): + shutil.rmtree(f"{BASEDIR}/{_dir}") _keyjar = init_key_jar(**OIDC_KEYS) assert len(_keyjar.get_signing_key("RSA")) == 1 diff --git a/tests/test_06_jws.py b/tests/test_06_jws.py index 4769f3c..9f8e480 100644 --- a/tests/test_06_jws.py +++ b/tests/test_06_jws.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import json import os.path diff --git a/tests/test_09_jwt.py b/tests/test_09_jwt.py index 452ee8c..3654d42 100755 --- a/tests/test_09_jwt.py +++ b/tests/test_09_jwt.py @@ -240,7 +240,7 @@ def test_with_jti(): assert "jti" in info -class DummyMsg(object): +class DummyMsg: def __init__(self, **kwargs): for key, val in kwargs.items(): setattr(self, key, val) diff --git a/tests/test_30_tools.py b/tests/test_30_tools.py index 2eb46fe..0a6a0cd 100644 --- a/tests/test_30_tools.py +++ b/tests/test_30_tools.py @@ -10,7 +10,7 @@ def jwk_from_file(filename: str, private: bool = True) -> JWK: """Read JWK from file""" - with open(filename, mode="rt") as input_file: + with open(filename) as input_file: jwk_dict = json.loads(input_file.read()) return key_from_jwk_dict(jwk_dict, private=private) diff --git a/tests/test_50_argument_alias.py b/tests/test_50_argument_alias.py index 8831fb1..1607010 100644 --- a/tests/test_50_argument_alias.py +++ b/tests/test_50_argument_alias.py @@ -46,7 +46,7 @@ def full_path(local_file): ] -class TestVerifyJWTKeys(object): +class TestVerifyJWTKeys: @pytest.fixture(autouse=True) def setup(self): mkey = [ @@ -104,8 +104,8 @@ def test_aud(self): assert len(keys) == 1 -PUBLIC_FILE = "{}/public_jwks.json".format(BASEDIR) -PRIVATE_FILE = "{}/private_jwks.json".format(BASEDIR) +PUBLIC_FILE = f"{BASEDIR}/public_jwks.json" +PRIVATE_FILE = f"{BASEDIR}/private_jwks.json" KEYSPEC = [ {"type": "RSA", "use": ["sig"]}, {"type": "EC", "crv": "P-256", "use": ["sig"]}, From 2a5a219e2f98c287ad0ec983c041032b17de1d86 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Wed, 29 May 2024 13:17:53 +0200 Subject: [PATCH 03/31] lint --- tests/test_02_jwk.py | 22 +++++++++++++--------- tests/test_03_key_bundle.py | 21 ++++++++++----------- tests/test_04_key_issuer.py | 4 ++-- tests/test_04_key_jar.py | 9 +++------ tests/test_05_jwx.py | 3 ++- tests/test_06_jws.py | 8 ++++---- tests/test_07_jwe.py | 9 +++------ tests/test_09_jwt.py | 2 +- tests/test_31_utils.py | 6 +++--- tests/test_40_serialize.py | 2 +- 10 files changed, 42 insertions(+), 44 deletions(-) diff --git a/tests/test_02_jwk.py b/tests/test_02_jwk.py index b26f3b0..3eeddd3 100755 --- a/tests/test_02_jwk.py +++ b/tests/test_02_jwk.py @@ -68,10 +68,10 @@ def _eq(l1, l2): def test_urlsafe_base64decode(): - l = base64_to_long(N) + length = base64_to_long(N) # convert it to base64 - bys = long2intarr(l) - data = struct.pack("%sB" % len(bys), *bys) + bys = long2intarr(length) + data = struct.pack(f"{len(bys)}B", *bys) if not len(data): data = "\x00" s0 = base64.b64encode(data) @@ -81,8 +81,8 @@ def test_urlsafe_base64decode(): base64url_to_long(s0) # Not else, should not raise exception - l = base64_to_long(s0) - assert l + length = base64_to_long(s0) + assert length def test_import_rsa_key_from_cert_file(): @@ -246,7 +246,8 @@ def test_get_key(): def test_private_rsa_key_from_jwk(): keys = [] - kspec = json.loads(open(full_path("jwk_private_key.json")).read()) + with open(full_path("jwk_private_key.json")) as fp: + kspec = json.loads(fp.read()) keys.append(key_from_jwk_dict(kspec)) key = keys[0] @@ -272,7 +273,8 @@ def test_private_rsa_key_from_jwk(): def test_public_key_from_jwk(): keys = [] - kspec = json.loads(open(full_path("jwk_private_key.json")).read()) + with open(full_path("jwk_private_key.json")) as fp: + kspec = json.loads(fp.read()) keys.append(key_from_jwk_dict(kspec, private=False)) key = keys[0] @@ -288,7 +290,8 @@ def test_public_key_from_jwk(): def test_ec_private_key_from_jwk(): keys = [] - kspec = json.loads(open(full_path("jwk_private_ec_key.json")).read()) + with open(full_path("jwk_private_ec_key.json")) as fp: + kspec = json.loads(fp.read()) keys.append(key_from_jwk_dict(kspec)) key = keys[0] @@ -306,7 +309,8 @@ def test_ec_private_key_from_jwk(): def test_ec_public_key_from_jwk(): keys = [] - kspec = json.loads(open(full_path("jwk_private_ec_key.json")).read()) + with open(full_path("jwk_private_ec_key.json")) as fp: + kspec = json.loads(fp.read()) keys.append(key_from_jwk_dict(kspec, private=False)) key = keys[0] diff --git a/tests/test_03_key_bundle.py b/tests/test_03_key_bundle.py index b9a2217..cc1704c 100755 --- a/tests/test_03_key_bundle.py +++ b/tests/test_03_key_bundle.py @@ -1,4 +1,5 @@ # pylint: disable=missing-docstring,no-self-use +import contextlib import json import os import shutil @@ -408,7 +409,7 @@ def test_mark_as_inactive(): desc = {"kty": "oct", "key": "highestsupersecret", "use": "sig"} kb = KeyBundle([desc]) assert len(kb.keys()) == 1 - for k in kb.keys(): + for k in kb.keys(): # noqa kb.mark_as_inactive(k.kid) desc = {"kty": "oct", "key": "highestsupersecret", "use": "enc"} kb.add_jwk_dicts([desc]) @@ -420,7 +421,7 @@ def test_copy(): desc = {"kty": "oct", "key": "highestsupersecret", "use": "sig"} kb = KeyBundle([desc]) assert len(kb.keys()) == 1 - for k in kb.keys(): + for k in kb.keys(): # noqa kb.mark_as_inactive(k.kid) desc = {"kty": "oct", "key": "highestsupersecret", "use": "enc"} kb.add_jwk_dicts([desc]) @@ -482,7 +483,7 @@ def test_httpc_params_1(): httpc_params = {"timeout": (2, 2)} # connect, read timeouts in seconds kb = KeyBundle(source=source, httpc=requests.request, httpc_params=httpc_params) updated, _ = kb._do_remote() - assert updated == True + assert updated is True @pytest.mark.network @@ -908,7 +909,7 @@ def test_export_inactive(): desc = {"kty": "oct", "key": "highestsupersecret", "use": "sig"} kb = KeyBundle([desc]) assert len(kb.keys()) == 1 - for k in kb.keys(): + for k in kb.keys(): # noqa kb.mark_as_inactive(k.kid) desc = {"kty": "oct", "key": "highestsupersecret", "use": "enc"} kb.add_jwk_dicts([desc]) @@ -976,7 +977,7 @@ def test_remote_not_modified(): with responses.RequestsMock() as rsps: rsps.add(method="GET", url=source, json=JWKS_DICT, status=200, headers=headers) updated, _ = kb._do_remote() - assert updated == True + assert updated is True assert kb.last_remote == headers.get("Last-Modified") timeout1 = kb.time_out @@ -1019,20 +1020,18 @@ def test_ignore_errors_period(): ignore_errors_period=ignore_errors_period, ) res, _ = kb._do_remote() - assert res == True + assert res is True assert kb.ignore_errors_until is None # refetch, but fail by using a bad source kb.source = source_bad - try: + with contextlib.suppress(UpdateFailed): res, _ = kb._do_remote() - except UpdateFailed: - pass # retry should fail silently as we're in holddown res, _ = kb._do_remote() assert kb.ignore_errors_until is not None - assert res == False + assert res is False # wait until holddown time.sleep(ignore_errors_period + 1) @@ -1040,7 +1039,7 @@ def test_ignore_errors_period(): # try again kb.source = source_good res, _ = kb._do_remote() - assert res == True + assert res is True def test_ignore_invalid_keys(): diff --git a/tests/test_04_key_issuer.py b/tests/test_04_key_issuer.py index 6278c7b..a9d05bf 100755 --- a/tests/test_04_key_issuer.py +++ b/tests/test_04_key_issuer.py @@ -287,7 +287,7 @@ def test_get_enc_not_mine(self): assert issuer.get("enc", "oct") def test_dump_issuer_keys(self): - kb = keybundle_from_local_file("file://%s/jwk.json" % BASE_PATH, "jwks", ["sig"]) + kb = keybundle_from_local_file(f"file://{BASE_PATH}/jwk.json", "jwks", ["sig"]) assert len(kb) == 1 issuer = KeyIssuer() issuer.add_kb(kb) @@ -701,7 +701,7 @@ def test_localhost_url(): kb = issuer.find(url) assert len(kb) == 1 assert "verify" in kb[0].httpc_params - assert kb[0].httpc_params["verify"] == False + assert kb[0].httpc_params["verify"] is False def test_add_url(): diff --git a/tests/test_04_key_jar.py b/tests/test_04_key_jar.py index acf7485..71fadd2 100755 --- a/tests/test_04_key_jar.py +++ b/tests/test_04_key_jar.py @@ -370,7 +370,7 @@ def test_get_enc_not_mine(self): assert ks.get("enc", "oct", "http://www.example.org/") def test_dump_issuer_keys(self): - kb = keybundle_from_local_file("file://%s/jwk.json" % BASE_PATH, "jwks", ["sig"]) + kb = keybundle_from_local_file(f"file://{BASE_PATH}/jwk.json", "jwks", ["sig"]) assert len(kb) == 1 kj = KeyJar() kj.add_kb("", kb) @@ -405,14 +405,11 @@ def test_no_use(self): def test_provider(self): kj = KeyJar() _url = "https://connect-op.herokuapp.com/jwks.json" - kj.load_keys( - "https://connect-op.heroku.com", - jwks_uri=_url, - ) + kj.load_keys("https://connect-op.heroku.com", jwks_uri=_url) iss_keys = kj.get_issuer_keys("https://connect-op.heroku.com") if not iss_keys: _msg = f"{_url} is not available at this moment!" - warnings.warn(_msg) + warnings.warn(_msg, stacklevel=1) else: assert iss_keys[0].keys() diff --git a/tests/test_05_jwx.py b/tests/test_05_jwx.py index d394008..7bfe03e 100644 --- a/tests/test_05_jwx.py +++ b/tests/test_05_jwx.py @@ -50,7 +50,8 @@ def test_jws_set_jku(): def test_jwx_set_x5c(): - jwx = JWx(x5c=open(full_path("cert.pem")).read()) + with open(full_path("cert.pem")) as fp: + jwx = JWx(x5c=fp.read()) keys = jwx._get_keys() assert len(keys) assert isinstance(keys[0], RSAKey) diff --git a/tests/test_06_jws.py b/tests/test_06_jws.py index 9f8e480..9275156 100644 --- a/tests/test_06_jws.py +++ b/tests/test_06_jws.py @@ -572,7 +572,7 @@ def test_signer_ps256_fail(): except BadSignature: pass else: - assert False + raise AssertionError def test_signer_ps384(): @@ -645,11 +645,11 @@ def test_signer_eddsa_fail(): _pubkey = OKPKey().load_key(okp2.public_key()) _rj = JWS(alg="Ed25519") try: - info = _rj.verify_compact(_jwt, [_pubkey]) + _ = _rj.verify_compact(_jwt, [_pubkey]) except BadSignature: pass else: - assert False + raise AssertionError def test_no_alg_and_alg_none_same(): @@ -904,7 +904,7 @@ def test_rs256_rm_signature(): except WrongNumberOfParts: pass else: - assert False + raise AssertionError def test_pick_alg_assume_alg_from_single_key(): diff --git a/tests/test_07_jwe.py b/tests/test_07_jwe.py index 7a87efc..9f4f5e8 100644 --- a/tests/test_07_jwe.py +++ b/tests/test_07_jwe.py @@ -62,10 +62,7 @@ def str2intarr(string): return array.array("B", string).tolist() -if sys.version < "3": - to_intarr = str2intarr -else: - to_intarr = bytes2intarr +to_intarr = str2intarr if sys.version < "3" else bytes2intarr def test_jwe_09_a1(): @@ -671,9 +668,9 @@ def test_fernet_symkey(): def test_fernet_bad(): with pytest.raises(TypeError): - encrypter = FernetEncrypter(key="xyzzy") + _ = FernetEncrypter(key="xyzzy") with pytest.raises(ValueError): - encrypter = FernetEncrypter(key=os.urandom(16)) + _ = FernetEncrypter(key=os.urandom(16)) def test_fernet_bytes(): diff --git a/tests/test_09_jwt.py b/tests/test_09_jwt.py index 3654d42..1fa43db 100755 --- a/tests/test_09_jwt.py +++ b/tests/test_09_jwt.py @@ -156,7 +156,7 @@ def test_jwt_pack_and_unpack_unknown_key(): kj.add_kb(ALICE, KeyBundle()) bob = JWT(key_jar=kj, iss=BOB, allowed_sign_algs=["RS256"]) with pytest.raises(NoSuitableSigningKeys): - info = bob.unpack(_jwt) + _ = bob.unpack(_jwt) def test_jwt_pack_and_unpack_with_lifetime(): diff --git a/tests/test_31_utils.py b/tests/test_31_utils.py index d403a40..86e98a5 100644 --- a/tests/test_31_utils.py +++ b/tests/test_31_utils.py @@ -2,16 +2,16 @@ def test_check_content_type(): - assert check_content_type(content_type="application/json", mime_type="application/json") == True + assert check_content_type(content_type="application/json", mime_type="application/json") is True assert ( check_content_type( content_type="application/json; charset=utf-8", mime_type="application/json" ) - == True + is True ) assert ( check_content_type( content_type="application/html; charset=utf-8", mime_type="application/json" ) - == False + is False ) diff --git a/tests/test_40_serialize.py b/tests/test_40_serialize.py index f83b9f6..6f3ec6c 100644 --- a/tests/test_40_serialize.py +++ b/tests/test_40_serialize.py @@ -15,7 +15,7 @@ def full_path(local_file): def test_key_issuer(): - kb = keybundle_from_local_file("file://%s/jwk.json" % BASE_PATH, "jwks", ["sig"]) + kb = keybundle_from_local_file(f"file://{BASE_PATH}/jwk.json", "jwks", ["sig"]) assert len(kb) == 1 issuer = KeyIssuer() issuer.add(kb) From 9e688671fe561a0e2f8af2153175b3295e21c3ed Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Wed, 29 May 2024 13:20:21 +0200 Subject: [PATCH 04/31] lint with ruff --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7ba4551..50e03ad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,7 +41,7 @@ jobs: run: poetry install - name: Run pytest run: | - poetry run pytest -vvv -ra --cov=cryptojwt --cov-report=xml --isort --black + poetry run pytest -vvv -ra --cov=cryptojwt --cov-report=xml --isort --black --ruff - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: From dc405908a636e579f7f0467351d99beb067f1ef9 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Wed, 29 May 2024 14:13:42 +0200 Subject: [PATCH 05/31] lint --- src/cryptojwt/key_bundle.py | 41 ++++++++++++++------------------ src/cryptojwt/key_issuer.py | 43 ++++++++++++++-------------------- src/cryptojwt/tools/jwtpeek.py | 12 ++++++---- 3 files changed, 41 insertions(+), 55 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 82df3b5..6bb1fee 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -8,8 +8,7 @@ import time from datetime import datetime from functools import cmp_to_key -from typing import List -from typing import Optional +from typing import List, Optional import requests @@ -18,23 +17,19 @@ from cryptojwt.jwk.okp import OKP_CRV2PUBLIC from cryptojwt.jwk.x509 import import_private_key_from_pem_file -from .exception import JWKException -from .exception import UnknownKeyType -from .exception import UnsupportedAlgorithm -from .exception import UnsupportedECurve -from .exception import UpdateFailed -from .jwk.ec import ECKey -from .jwk.ec import new_ec_key +from .exception import ( + JWKException, + UnknownKeyType, + UnsupportedAlgorithm, + UnsupportedECurve, + UpdateFailed, +) +from .jwk.ec import ECKey, new_ec_key from .jwk.hmac import SYMKey -from .jwk.jwk import dump_jwk -from .jwk.jwk import import_jwk -from .jwk.okp import OKPKey -from .jwk.okp import new_okp_key -from .jwk.rsa import RSAKey -from .jwk.rsa import new_rsa_key -from .utils import as_unicode -from .utils import check_content_type -from .utils import httpc_params_loader +from .jwk.jwk import dump_jwk, import_jwk +from .jwk.okp import OKPKey, new_okp_key +from .jwk.rsa import RSAKey, new_rsa_key +from .utils import as_unicode, check_content_type, httpc_params_loader __author__ = "Roland Hedberg" @@ -935,15 +930,13 @@ def dump_jwks(kbl, target, private=False, symmetric_too=False): res = {"keys": keys} try: - _fp = open(target, "w") + with open(target, "w") as fp: + json.dump(res, fp) except OSError: head, _ = os.path.split(target) os.makedirs(head) - _fp = open(target, "w") - - _txt = json.dumps(res) - _fp.write(_txt) - _fp.close() + with open(target, "w") as fp: + json.dump(res, fp) def _set_kid(spec, bundle, kid_template, kid): diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index c797461..6373fa6 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -1,20 +1,14 @@ import json import logging import os -from typing import List -from typing import Optional +from typing import List, Optional from requests import request from .jwe.utils import alg2keytype as jwe_alg2keytype from .jws.utils import alg2keytype as jws_alg2keytype -from .key_bundle import KeyBundle -from .key_bundle import build_key_bundle -from .key_bundle import key_diff -from .key_bundle import update_key_bundle -from .utils import httpc_params_loader -from .utils import importer -from .utils import qualified_name +from .key_bundle import KeyBundle, build_key_bundle, key_diff, update_key_bundle +from .utils import httpc_params_loader, importer, qualified_name __author__ = "Roland Hedberg" @@ -586,7 +580,8 @@ def init_key_issuer(public_path="", private_path="", key_defs="", read_only=True if private_path: if os.path.isfile(private_path): - _jwks = open(private_path).read() + with open(private_path) as fp: + _jwks = fp.read() _issuer = KeyIssuer() _issuer.import_jwks(json.loads(_jwks)) if key_defs: @@ -599,9 +594,8 @@ def init_key_issuer(public_path="", private_path="", key_defs="", read_only=True else: _issuer.set([_kb]) jwks = _issuer.export_jwks(private=True) - fp = open(private_path, "w") - fp.write(json.dumps(jwks)) - fp.close() + with open(private_path, "w") as fp: + json.dump(jwks, fp) else: _issuer = build_keyissuer(key_defs) if not read_only: @@ -609,21 +603,20 @@ def init_key_issuer(public_path="", private_path="", key_defs="", read_only=True head, tail = os.path.split(private_path) if head and not os.path.isdir(head): os.makedirs(head) - fp = open(private_path, "w") - fp.write(json.dumps(jwks)) - fp.close() + with open(private_path, "w") as fp: + json.dump(jwks, fp) if public_path and not read_only: jwks = _issuer.export_jwks() # public part head, tail = os.path.split(public_path) if head and not os.path.isdir(head): os.makedirs(head) - fp = open(public_path, "w") - fp.write(json.dumps(jwks)) - fp.close() + with open(public_path, "w") as fp: + json.dump(jwks, fp) elif public_path: if os.path.isfile(public_path): - _jwks = open(public_path).read() + with open(public_path) as fp: + _jwks = fp.read() _issuer = KeyIssuer() _issuer.import_jwks(json.loads(_jwks)) if key_defs: @@ -636,9 +629,8 @@ def init_key_issuer(public_path="", private_path="", key_defs="", read_only=True update_key_bundle(_kb, _diff) _issuer.set([_kb]) jwks = _issuer.export_jwks() - fp = open(public_path, "w") - fp.write(json.dumps(jwks)) - fp.close() + with open(public_path, "w") as fp: + json.dump(jwks, fp) else: _issuer = build_keyissuer(key_defs) if not read_only: @@ -646,9 +638,8 @@ def init_key_issuer(public_path="", private_path="", key_defs="", read_only=True head, tail = os.path.split(public_path) if head and not os.path.isdir(head): os.makedirs(head) - fp = open(public_path, "w") - fp.write(json.dumps(_jwks)) - fp.close() + with open(public_path, "w") as fp: + json.dump(_jwks, fp) else: _issuer = build_keyissuer(key_defs) diff --git a/src/cryptojwt/tools/jwtpeek.py b/src/cryptojwt/tools/jwtpeek.py index aa808cf..9e58eb5 100755 --- a/src/cryptojwt/tools/jwtpeek.py +++ b/src/cryptojwt/tools/jwtpeek.py @@ -13,8 +13,7 @@ from cryptojwt.jwe import jwe from cryptojwt.jwk.hmac import SYMKey from cryptojwt.jwk.jwk import key_from_jwk_dict -from cryptojwt.jwk.rsa import RSAKey -from cryptojwt.jwk.rsa import import_rsa_key +from cryptojwt.jwk.rsa import RSAKey, import_rsa_key from cryptojwt.jws import jws from cryptojwt.key_bundle import KeyBundle from cryptojwt.key_issuer import KeyIssuer @@ -112,12 +111,14 @@ def main(): keys.append(SYMKey(key=args.hmac_key, kid=_kid)) if args.jwk: - _key = key_from_jwk_dict(open(args.jwk).read()) + with open(args.jwk) as fp: + _key = key_from_jwk_dict(fp.read()) keys.append(_key) if args.jwks: _iss = KeyIssuer() - _iss.import_jwks(open(args.jwks).read()) + with open(args.jwks) as fp: + _iss.import_jwks(fp.read()) keys.extend(_iss.all_keys()) if args.jwks_url: @@ -128,7 +129,8 @@ def main(): message = sys.stdin.read() else: if os.path.isfile(args.msg): - message = open(args.msg).read().strip("\n") + with open(args.msg) as fp: + message = fp.read().strip("\n") else: message = args.msg From bbc4b62e98c3429611c44b93b33b60d3e9b7e509 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Wed, 29 May 2024 14:19:53 +0200 Subject: [PATCH 06/31] lint --- src/cryptojwt/jwe/jwe.py | 5 ++--- src/cryptojwt/jwe/jwe_ec.py | 5 ++--- src/cryptojwt/jwe/jwe_hmac.py | 5 ++--- src/cryptojwt/jwt.py | 9 +++------ src/cryptojwt/key_bundle.py | 36 +++++++++++++++++++--------------- src/cryptojwt/key_issuer.py | 12 +++++++++--- src/cryptojwt/key_jar.py | 5 ++--- src/cryptojwt/simple_jwt.py | 9 +++------ src/cryptojwt/tools/jwtpeek.py | 3 ++- src/cryptojwt/utils.py | 9 +++------ 10 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/cryptojwt/jwe/jwe.py b/src/cryptojwt/jwe/jwe.py index 1caed85..e9b3518 100644 --- a/src/cryptojwt/jwe/jwe.py +++ b/src/cryptojwt/jwe/jwe.py @@ -1,3 +1,4 @@ +import contextlib import logging from ..jwk.asym import AsymmetricKey @@ -157,10 +158,8 @@ def decrypt(self, token=None, keys=None, alg=None, cek=None): else: keys = self.pick_keys(self._get_keys(), use="enc", alg=_alg) - try: + with contextlib.suppress(KeyError): keys.append(key_from_jwk_dict(_jwe.headers["jwk"])) - except KeyError: - pass if not keys and not cek: raise NoSuitableDecryptionKey(_alg) diff --git a/src/cryptojwt/jwe/jwe_ec.py b/src/cryptojwt/jwe/jwe_ec.py index bcf8105..6182c3e 100644 --- a/src/cryptojwt/jwe/jwe_ec.py +++ b/src/cryptojwt/jwe/jwe_ec.py @@ -1,3 +1,4 @@ +import contextlib import struct from cryptography.hazmat.primitives.asymmetric import ec @@ -190,10 +191,8 @@ def encrypt(self, key=None, iv="", cek="", **kwargs): _msg = as_bytes(self.msg) _args = self._dict - try: + with contextlib.suppress(KeyError): _args["kid"] = kwargs["kid"] - except KeyError: - pass if "params" in kwargs: if "apu" in kwargs["params"]: diff --git a/src/cryptojwt/jwe/jwe_hmac.py b/src/cryptojwt/jwe/jwe_hmac.py index ae5d010..655bcc0 100644 --- a/src/cryptojwt/jwe/jwe_hmac.py +++ b/src/cryptojwt/jwe/jwe_hmac.py @@ -1,3 +1,4 @@ +import contextlib import logging import zlib @@ -34,10 +35,8 @@ def encrypt(self, key, iv="", cek="", **kwargs): _msg = as_bytes(self.msg) _args = self._dict - try: + with contextlib.suppress(KeyError): _args["kid"] = kwargs["kid"] - except KeyError: - pass jwe = JWEnc(**_args) diff --git a/src/cryptojwt/jwt.py b/src/cryptojwt/jwt.py index 6116513..ca5a0fb 100755 --- a/src/cryptojwt/jwt.py +++ b/src/cryptojwt/jwt.py @@ -1,5 +1,6 @@ """Basic JSON Web Token implementation.""" +import contextlib import json import logging import time @@ -143,10 +144,8 @@ def receivers(self): def my_keys(self, issuer_id="", use="sig"): _k = self.key_jar.get(use, issuer_id=issuer_id) if issuer_id != "": - try: + with contextlib.suppress(KeyError): _k.extend(self.key_jar.get(use, issuer_id="")) - except KeyError: - pass return _k def _encrypt(self, payload, recv, cty="JWT", zip=""): @@ -442,9 +441,7 @@ def remove_jwt_parameters(arg): """ for param in JWT.jwt_parameters: - try: + with contextlib.suppress(KeyError): del arg[param] - except KeyError: - pass return arg diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 6bb1fee..9e487d8 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -1,5 +1,6 @@ """Implementation of a Key Bundle.""" +import contextlib import copy import json import logging @@ -8,7 +9,8 @@ import time from datetime import datetime from functools import cmp_to_key -from typing import List, Optional +from typing import List +from typing import Optional import requests @@ -17,19 +19,23 @@ from cryptojwt.jwk.okp import OKP_CRV2PUBLIC from cryptojwt.jwk.x509 import import_private_key_from_pem_file -from .exception import ( - JWKException, - UnknownKeyType, - UnsupportedAlgorithm, - UnsupportedECurve, - UpdateFailed, -) -from .jwk.ec import ECKey, new_ec_key +from .exception import JWKException +from .exception import UnknownKeyType +from .exception import UnsupportedAlgorithm +from .exception import UnsupportedECurve +from .exception import UpdateFailed +from .jwk.ec import ECKey +from .jwk.ec import new_ec_key from .jwk.hmac import SYMKey -from .jwk.jwk import dump_jwk, import_jwk -from .jwk.okp import OKPKey, new_okp_key -from .jwk.rsa import RSAKey, new_rsa_key -from .utils import as_unicode, check_content_type, httpc_params_loader +from .jwk.jwk import dump_jwk +from .jwk.jwk import import_jwk +from .jwk.okp import OKPKey +from .jwk.okp import new_okp_key +from .jwk.rsa import RSAKey +from .jwk.rsa import new_rsa_key +from .utils import as_unicode +from .utils import check_content_type +from .utils import httpc_params_loader __author__ = "Roland Hedberg" @@ -685,10 +691,8 @@ def remove(self, key): :param key: The key that should be removed """ - try: + with contextlib.suppress(ValueError): self._keys.remove(key) - except ValueError: - pass def __len__(self): """ diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index 6373fa6..dcba62a 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -1,14 +1,20 @@ import json import logging import os -from typing import List, Optional +from typing import List +from typing import Optional from requests import request from .jwe.utils import alg2keytype as jwe_alg2keytype from .jws.utils import alg2keytype as jws_alg2keytype -from .key_bundle import KeyBundle, build_key_bundle, key_diff, update_key_bundle -from .utils import httpc_params_loader, importer, qualified_name +from .key_bundle import KeyBundle +from .key_bundle import build_key_bundle +from .key_bundle import key_diff +from .key_bundle import update_key_bundle +from .utils import httpc_params_loader +from .utils import importer +from .utils import qualified_name __author__ = "Roland Hedberg" diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index e16e40c..17a54d5 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -1,3 +1,4 @@ +import contextlib import json import logging from typing import List @@ -669,10 +670,8 @@ def dump( if exclude_attributes: for attr in exclude_attributes: - try: + with contextlib.suppress(KeyError): del info[attr] - except KeyError: - pass if exclude_attributes is None or "issuers" not in exclude_attributes: info["issuers"] = self._dump_issuers( diff --git a/src/cryptojwt/simple_jwt.py b/src/cryptojwt/simple_jwt.py index bbcc456..36b3f30 100644 --- a/src/cryptojwt/simple_jwt.py +++ b/src/cryptojwt/simple_jwt.py @@ -1,3 +1,4 @@ +import contextlib import json import logging @@ -36,10 +37,8 @@ def unpack(self, token, **kwargs): against. """ if isinstance(token, str): - try: + with contextlib.suppress(UnicodeDecodeError): token = token.encode("utf-8") - except UnicodeDecodeError: - pass part = split_token(token) self.b64part = part @@ -98,10 +97,8 @@ def payload(self): if "cty" in self.headers and self.headers["cty"].lower() != "jwt": pass else: - try: + with contextlib.suppress(ValueError): _msg = json.loads(_msg) - except ValueError: - pass return _msg diff --git a/src/cryptojwt/tools/jwtpeek.py b/src/cryptojwt/tools/jwtpeek.py index 9e58eb5..2cab665 100755 --- a/src/cryptojwt/tools/jwtpeek.py +++ b/src/cryptojwt/tools/jwtpeek.py @@ -13,7 +13,8 @@ from cryptojwt.jwe import jwe from cryptojwt.jwk.hmac import SYMKey from cryptojwt.jwk.jwk import key_from_jwk_dict -from cryptojwt.jwk.rsa import RSAKey, import_rsa_key +from cryptojwt.jwk.rsa import RSAKey +from cryptojwt.jwk.rsa import import_rsa_key from cryptojwt.jws import jws from cryptojwt.key_bundle import KeyBundle from cryptojwt.key_issuer import KeyIssuer diff --git a/src/cryptojwt/utils.py b/src/cryptojwt/utils.py index 47be894..3babaab 100644 --- a/src/cryptojwt/utils.py +++ b/src/cryptojwt/utils.py @@ -1,4 +1,5 @@ import base64 +import contextlib import functools import importlib import json @@ -140,10 +141,8 @@ def as_bytes(s): :param s: Unicode / bytes string :return: bytes string """ - try: + with contextlib.suppress(AttributeError, UnicodeDecodeError): s = s.encode() - except (AttributeError, UnicodeDecodeError): - pass return s @@ -154,10 +153,8 @@ def as_unicode(b): :param b: byte string :return: unicode string """ - try: + with contextlib.suppress(AttributeError, UnicodeDecodeError): b = b.decode() - except (AttributeError, UnicodeDecodeError): - pass return b From cb704241f4f1b4123dae93f3e30b97feda4a4aa1 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Thu, 30 May 2024 14:48:24 +0200 Subject: [PATCH 07/31] lint B904,SIM108 --- src/cryptojwt/jwe/jwe.py | 5 +---- src/cryptojwt/jwe/jwe_ec.py | 13 +++++-------- src/cryptojwt/jwe/jwe_hmac.py | 5 +---- src/cryptojwt/jwe/jwe_rsa.py | 5 +---- src/cryptojwt/jwe/jwekey.py | 4 ++-- src/cryptojwt/jwe/utils.py | 4 ++-- src/cryptojwt/jwk/asym.py | 4 ++-- src/cryptojwt/jwk/ec.py | 8 ++++---- src/cryptojwt/jwk/hmac.py | 8 ++++---- src/cryptojwt/jwk/okp.py | 12 ++++++------ src/cryptojwt/jwk/rsa.py | 4 ++-- src/cryptojwt/jwk/wrap.py | 4 ++-- src/cryptojwt/jws/dsa.py | 4 ++-- src/cryptojwt/jws/eddsa.py | 4 ++-- src/cryptojwt/jws/jws.py | 18 ++++++------------ src/cryptojwt/jws/pss.py | 4 ++-- src/cryptojwt/jws/rsa.py | 4 ++-- src/cryptojwt/jwt.py | 11 ++--------- src/cryptojwt/jwx.py | 8 ++++---- src/cryptojwt/key_bundle.py | 15 ++++++--------- src/cryptojwt/key_issuer.py | 9 +++------ src/cryptojwt/key_jar.py | 4 ++-- src/cryptojwt/simple_jwt.py | 5 +---- src/cryptojwt/tools/jwtpeek.py | 5 +---- src/cryptojwt/utils.py | 5 +---- 25 files changed, 66 insertions(+), 106 deletions(-) diff --git a/src/cryptojwt/jwe/jwe.py b/src/cryptojwt/jwe/jwe.py index e9b3518..e8deb78 100644 --- a/src/cryptojwt/jwe/jwe.py +++ b/src/cryptojwt/jwe/jwe.py @@ -191,10 +191,7 @@ def decrypt(self, token=None, keys=None, alg=None, cek=None): return msg for key in keys: - if isinstance(key, AsymmetricKey): - _key = key.private_key() - else: - _key = key.key + _key = key.private_key() if isinstance(key, AsymmetricKey) else key.key try: msg = decrypter.decrypt(_jwe, _key) diff --git a/src/cryptojwt/jwe/jwe_ec.py b/src/cryptojwt/jwe/jwe_ec.py index 6182c3e..b4c3298 100644 --- a/src/cryptojwt/jwe/jwe_ec.py +++ b/src/cryptojwt/jwe/jwe_ec.py @@ -111,8 +111,8 @@ def enc_setup(self, msg, key=None, auth_data=b"", **kwargs): if self.alg == "ECDH-ES": try: dk_len = KEY_LEN[self.enc] - except KeyError: - raise ValueError("Unknown key length for algorithm %s" % self.enc) + except KeyError as exc: + raise ValueError("Unknown key length for algorithm %s" % self.enc) from exc cek = ecdh_derive_key(_epk, key.pub_key, apu, apv, str(self.enc).encode(), dk_len) elif self.alg in ["ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW"]: @@ -153,8 +153,8 @@ def dec_setup(self, token, key=None, **kwargs): if self.headers["alg"] == "ECDH-ES": try: dk_len = KEY_LEN[self.headers["enc"]] - except KeyError: - raise Exception("Unknown key length for algorithm") + except KeyError as exc: + raise Exception("Unknown key length for algorithm") from exc self.cek = ecdh_derive_key( key, @@ -211,10 +211,7 @@ def encrypt(self, key=None, iv="", cek="", **kwargs): return jwe.pack(parts=[iv, ctxt, tag]) def decrypt(self, token=None, **kwargs): - if isinstance(token, JWEnc): - jwe = token - else: - jwe = JWEnc().unpack(token) + jwe = token if isinstance(token, JWEnc) else JWEnc().unpack(token) if not self.cek: raise Exception("Content Encryption Key is Not Yet Set") diff --git a/src/cryptojwt/jwe/jwe_hmac.py b/src/cryptojwt/jwe/jwe_hmac.py index 655bcc0..3a1d1ed 100644 --- a/src/cryptojwt/jwe/jwe_hmac.py +++ b/src/cryptojwt/jwe/jwe_hmac.py @@ -67,10 +67,7 @@ def decrypt(self, token, key=None, cek=None): if not key and not cek: raise MissingKey("On of key or cek must be specified") - if isinstance(token, JWEnc): - jwe = token - else: - jwe = JWEnc().unpack(token) + jwe = token if isinstance(token, JWEnc) else JWEnc().unpack(token) if len(jwe) != 5: raise WrongNumberOfParts(len(jwe)) diff --git a/src/cryptojwt/jwe/jwe_rsa.py b/src/cryptojwt/jwe/jwe_rsa.py index f34b133..aa8f43e 100644 --- a/src/cryptojwt/jwe/jwe_rsa.py +++ b/src/cryptojwt/jwe/jwe_rsa.py @@ -92,10 +92,7 @@ def decrypt(self, token, key, cek=None): :param cek: Ephemeral cipher key :return: The decrypted message """ - if not isinstance(token, JWEnc): - jwe = JWEnc().unpack(token) - else: - jwe = token + jwe = JWEnc().unpack(token) if not isinstance(token, JWEnc) else token self.jwt = jwe.encrypted_key() jek = jwe.encrypted_key() diff --git a/src/cryptojwt/jwe/jwekey.py b/src/cryptojwt/jwe/jwekey.py index 31a1c8a..a88d0cf 100644 --- a/src/cryptojwt/jwe/jwekey.py +++ b/src/cryptojwt/jwe/jwekey.py @@ -29,8 +29,8 @@ def _generate_key(encalg, cek=""): except KeyError: try: _key = get_random_bytes(KEY_LEN_BYTES[encalg]) - except KeyError: - raise ValueError("Unsupported encryption algorithm %s" % encalg) + except KeyError as exc: + raise ValueError("Unsupported encryption algorithm %s" % encalg) from exc return _key diff --git a/src/cryptojwt/jwe/utils.py b/src/cryptojwt/jwe/utils.py index 99152d0..80d8324 100644 --- a/src/cryptojwt/jwe/utils.py +++ b/src/cryptojwt/jwe/utils.py @@ -18,8 +18,8 @@ def get_keys_seclen_dgst(key, iv): # Select the digest to use based on key length try: seclen, hash_method = LENMET[len(key)] - except KeyError: - raise Exception("Invalid CBC+HMAC key length: %s bytes" % len(key)) + except KeyError as exc: + raise Exception("Invalid CBC+HMAC key length: %s bytes" % len(key)) from exc # Split the key ka = key[:seclen] diff --git a/src/cryptojwt/jwk/asym.py b/src/cryptojwt/jwk/asym.py index 5ce6af9..e2b2bf5 100644 --- a/src/cryptojwt/jwk/asym.py +++ b/src/cryptojwt/jwk/asym.py @@ -38,8 +38,8 @@ def appropriate_for(self, usage, **kwargs): """ try: _use = USE[usage] - except KeyError: - raise ValueError("Unknown key usage") + except KeyError as exc: + raise ValueError("Unknown key usage") from exc else: if usage in ["sign", "decrypt"]: if not self.use or _use == self.use: diff --git a/src/cryptojwt/jwk/ec.py b/src/cryptojwt/jwk/ec.py index c5fd5f6..c2879b5 100644 --- a/src/cryptojwt/jwk/ec.py +++ b/src/cryptojwt/jwk/ec.py @@ -45,8 +45,8 @@ def ec_construct_public(num): """ try: _sec_crv = NIST2SEC[as_unicode(num["crv"])] - except KeyError: - raise UnsupportedECurve("Unsupported elliptic curve: {}".format(num["crv"])) + except KeyError as exc: + raise UnsupportedECurve("Unsupported elliptic curve: {}".format(num["crv"])) from exc ecpn = ec.EllipticCurvePublicNumbers(num["x"], num["y"], _sec_crv()) return ecpn.public_key() @@ -152,8 +152,8 @@ def deserialize(self): {"x": _x, "y": _y, "crv": self.crv, "d": _d} ) self.pub_key = self.priv_key.public_key() - except ValueError as err: - raise DeSerializationNotPossible(str(err)) + except ValueError as exc: + raise DeSerializationNotPossible(str(exc)) from exc else: self.pub_key = ec_construct_public({"x": _x, "y": _y, "crv": self.crv}) diff --git a/src/cryptojwt/jwk/hmac.py b/src/cryptojwt/jwk/hmac.py index a68fac0..dc166cb 100644 --- a/src/cryptojwt/jwk/hmac.py +++ b/src/cryptojwt/jwk/hmac.py @@ -81,8 +81,8 @@ def appropriate_for(self, usage, alg="HS256"): """ try: _use = USE[usage] - except: - raise ValueError("Unknown key usage") + except Exception as exc: + raise ValueError("Unknown key usage") from exc else: if not self.use or self.use == _use: if _use == "sig": @@ -106,8 +106,8 @@ def encryption_key(self, alg, **kwargs): try: tsize = ALG2KEYLEN[alg] - except KeyError: - raise UnsupportedAlgorithm(alg) + except KeyError as exc: + raise UnsupportedAlgorithm(alg) from exc if tsize <= 32: # SHA256 diff --git a/src/cryptojwt/jwk/okp.py b/src/cryptojwt/jwk/okp.py index ffeeb81..e51ca8b 100644 --- a/src/cryptojwt/jwk/okp.py +++ b/src/cryptojwt/jwk/okp.py @@ -145,16 +145,16 @@ def deserialize(self): if isinstance(self.d, (str, bytes)): try: self.priv_key = OKP_CRV2PRIVATE[self.crv].from_private_bytes(deser(self.d)) - except KeyError: - raise UnsupportedOKPCurve(f"Unsupported OKP curve: {self.crv}") + except KeyError as exc: + raise UnsupportedOKPCurve(f"Unsupported OKP curve: {self.crv}") from exc self.pub_key = self.priv_key.public_key() - except ValueError as err: - raise DeSerializationNotPossible(str(err)) + except ValueError as exc: + raise DeSerializationNotPossible(str(exc)) from exc else: try: self.pub_key = OKP_CRV2PUBLIC[self.crv].from_public_bytes(_x) - except KeyError: - raise UnsupportedOKPCurve(f"Unsupported OKP curve: {self.crv}") + except KeyError as exc: + raise UnsupportedOKPCurve(f"Unsupported OKP curve: {self.crv}") from exc def _serialize_public(self, key): self.x = b64e( diff --git a/src/cryptojwt/jwk/rsa.py b/src/cryptojwt/jwk/rsa.py index 319cd7f..aa4fa25 100644 --- a/src/cryptojwt/jwk/rsa.py +++ b/src/cryptojwt/jwk/rsa.py @@ -322,8 +322,8 @@ def deserialize(self): self.pub_key = self.priv_key.public_key() else: self.pub_key = rsa_construct_public(numbers) - except ValueError as err: - raise DeSerializationNotPossible("%s" % err) + except ValueError as exc: + raise DeSerializationNotPossible(str(exc)) from exc if self.x5c: _cert_chain = [] diff --git a/src/cryptojwt/jwk/wrap.py b/src/cryptojwt/jwk/wrap.py index 95aa7e8..2cbdac5 100644 --- a/src/cryptojwt/jwk/wrap.py +++ b/src/cryptojwt/jwk/wrap.py @@ -19,8 +19,8 @@ def wrap_key(key: JWK, wrapping_key: JWK, wrap_params: dict = DEFAULT_WRAP_PARAM message = json.dumps(key.serialize(private=True)).encode() try: enc_params = wrap_params[wrapping_key.kty] - except KeyError: - raise ValueError("Unsupported wrapping key type") + except KeyError as exc: + raise ValueError("Unsupported wrapping key type") from exc _jwe = JWE(msg=message, **enc_params) return _jwe.encrypt(keys=[wrapping_key], kid=wrapping_key.kid) diff --git a/src/cryptojwt/jws/dsa.py b/src/cryptojwt/jws/dsa.py index 8d143d4..536d14f 100644 --- a/src/cryptojwt/jws/dsa.py +++ b/src/cryptojwt/jws/dsa.py @@ -75,8 +75,8 @@ def verify(self, msg, sig, key): (r, s) = self._split_raw_signature(sig) asn1sig = encode_dss_signature(r, s) key.verify(asn1sig, msg, ec.ECDSA(self.hash_algorithm())) - except InvalidSignature as err: - raise BadSignature(err) + except InvalidSignature as exc: + raise BadSignature(exc) from exc else: return True diff --git a/src/cryptojwt/jws/eddsa.py b/src/cryptojwt/jws/eddsa.py index 97022d8..cf88ba5 100644 --- a/src/cryptojwt/jws/eddsa.py +++ b/src/cryptojwt/jws/eddsa.py @@ -62,7 +62,7 @@ def verify(self, msg, sig, key): try: key.verify(sig, msg) - except InvalidSignature as err: - raise BadSignature(err) + except InvalidSignature as exc: + raise BadSignature(exc) from exc else: return True diff --git a/src/cryptojwt/jws/jws.py b/src/cryptojwt/jws/jws.py index 4e3b983..1e4efd9 100644 --- a/src/cryptojwt/jws/jws.py +++ b/src/cryptojwt/jws/jws.py @@ -133,8 +133,8 @@ def sign_compact(self, keys=None, protected=None, **kwargs): # All other cases try: _signer = SIGNER_ALGS[_alg] - except KeyError: - raise UnknownAlgorithm(_alg) + except KeyError as exc: + raise UnknownAlgorithm(_alg) from exc _input = jwt.pack(parts=[self.msg]) @@ -211,10 +211,7 @@ def verify_compact_verbose(self, jws=None, keys=None, allow_none=False, sigalg=N self["alg"] = _alg - if keys: - _keys = self.pick_keys(keys) - else: - _keys = self.pick_keys(self._get_keys()) + _keys = self.pick_keys(keys) if keys else self.pick_keys(self._get_keys()) if not _keys: if "kid" in self: @@ -227,10 +224,7 @@ def verify_compact_verbose(self, jws=None, keys=None, allow_none=False, sigalg=N verifier = SIGNER_ALGS[_alg] for key in _keys: - if isinstance(key, AsymmetricKey): - _key = key.public_key() - else: - _key = key.key + _key = key.public_key() if isinstance(key, AsymmetricKey) else key.key try: if not verifier.verify(jwt.sign_input(), jwt.signature(), _key): @@ -310,8 +304,8 @@ def verify_json(self, jws, keys=None, allow_none=False, at_least_one=False): try: _payload = _jwss["payload"] - except KeyError: - raise FormatError("Missing payload") + except KeyError as exc: + raise FormatError("Missing payload") from exc try: _signs = _jwss["signatures"] diff --git a/src/cryptojwt/jws/pss.py b/src/cryptojwt/jws/pss.py index f7c22ff..65362a4 100644 --- a/src/cryptojwt/jws/pss.py +++ b/src/cryptojwt/jws/pss.py @@ -64,7 +64,7 @@ def verify(self, msg, signature, key): ), self.hash_algorithm(), ) - except InvalidSignature as err: - raise BadSignature(err) + except InvalidSignature as exc: + raise BadSignature(exc) from exc else: return True diff --git a/src/cryptojwt/jws/rsa.py b/src/cryptojwt/jws/rsa.py index 566c753..414ec14 100644 --- a/src/cryptojwt/jws/rsa.py +++ b/src/cryptojwt/jws/rsa.py @@ -42,8 +42,8 @@ def verify(self, msg, signature, key): raise TypeError("The public key must be an instance of RSAPublicKey") try: key.verify(signature, msg, self.padding, self.hash) - except InvalidSignature as err: - raise BadSignature(str(err)) + except InvalidSignature as exc: + raise BadSignature(str(exc)) from exc except AttributeError: return False else: diff --git a/src/cryptojwt/jwt.py b/src/cryptojwt/jwt.py index ca5a0fb..75cc0d9 100755 --- a/src/cryptojwt/jwt.py +++ b/src/cryptojwt/jwt.py @@ -51,10 +51,7 @@ def pick_key(keys, use, alg="", key_type="", kid=""): """ res = [] if not key_type: - if use == "sig": - key_type = jws_alg2keytype(alg) - else: - key_type = jwe_alg2keytype(alg) + key_type = jws_alg2keytype(alg) if use == "sig" else jwe_alg2keytype(alg) for key in keys: if key.use and key.use != use: @@ -263,11 +260,7 @@ def pack( issuer_id = self.iss if self.sign: - if self.alg != "none": - _key = self.pack_key(issuer_id, kid) - # _args['kid'] = _key.kid - else: - _key = None + _key = self.pack_key(issuer_id, kid) if self.alg != "none" else None jws_headers = jws_headers or {} diff --git a/src/cryptojwt/jwx.py b/src/cryptojwt/jwx.py index 7d4239d..4b78bd1 100644 --- a/src/cryptojwt/jwx.py +++ b/src/cryptojwt/jwx.py @@ -89,9 +89,9 @@ def __init__(self, msg=None, with_digest=False, httpc=None, **kwargs): try: _spec = load_x509_cert(self["x5u"], self.httpc, {}) self._jwk = RSAKey(pub_key=_spec["rsa"]).to_dict() - except Exception: + except Exception as exc: # ca_chain = load_x509_cert_chain(self["x5u"]) - raise ValueError("x5u") + raise ValueError("x5u") from exc else: self._dict[key] = _val if key in DEPRECATED and _val in DEPRECATED[key]: @@ -123,8 +123,8 @@ def __setitem__(self, key, value): def __getattr__(self, item): try: return self._dict[item] - except KeyError: - raise AttributeError(item) + except KeyError as exc: + raise AttributeError(item) from exc def keys(self): """Return all keys.""" diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 9e487d8..485d6d3 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -278,10 +278,7 @@ def __init__( if keys: self.source = None if isinstance(keys, dict): - if "keys" in keys: - initial_keys = keys["keys"] - else: - initial_keys = [keys] + initial_keys = keys["keys"] if "keys" in keys else [keys] else: initial_keys = keys self._keys = self.jwk_dicts_as_keys(initial_keys) @@ -373,9 +370,9 @@ def jwk_dicts_as_keys(self, keys): for _use in _usage: try: _key = K2C[_typ](use=_use, **inst) - except KeyError: + except KeyError as exc: if not self.ignore_invalid_keys: - raise UnknownKeyType(inst) + raise UnknownKeyType(inst) from exc _error = f"UnknownKeyType: {_typ}" continue except (UnsupportedECurve, UnsupportedAlgorithm) as err: @@ -485,7 +482,7 @@ def _do_remote(self, set_keys=True): _http_resp = self.httpc("GET", self.source, **httpc_params) except Exception as err: LOGGER.error(err) - raise UpdateFailed(REMOTE_FAILED.format(self.source, str(err))) + raise UpdateFailed(REMOTE_FAILED.format(self.source, str(err))) from err new_keys = None load_successful = _http_resp.status_code == 200 @@ -501,10 +498,10 @@ def _do_remote(self, set_keys=True): LOGGER.debug("Loaded JWKS: %s from %s", _http_resp.text, self.source) try: new_keys = self.jwk_dicts_as_keys(self.imp_jwks["keys"]) - except KeyError: + except KeyError as exc: LOGGER.error("No 'keys' keyword in JWKS") self.ignore_errors_until = time.time() + self.ignore_errors_period - raise UpdateFailed(MALFORMED.format(self.source)) + raise UpdateFailed(MALFORMED.format(self.source)) from exc if hasattr(_http_resp, "headers"): headers = _http_resp.headers diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index dcba62a..87f5ed1 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -232,8 +232,8 @@ def import_jwks(self, jwks): """ try: _keys = jwks["keys"] - except KeyError: - raise ValueError("Not a proper JWKS") + except KeyError as exc: + raise ValueError("Not a proper JWKS") from exc else: self._bundles.append( self.keybundle_cls(_keys, httpc=self.httpc, httpc_params=self.httpc_params) @@ -285,10 +285,7 @@ def get(self, key_use, key_type="", kid=None, alg="", **kwargs): :return: A possibly empty list of keys """ - if key_use in ["dec", "enc"]: - use = "enc" - else: - use = "sig" + use = "enc" if key_use in ["dec", "enc"] else "sig" if not key_type: if alg: diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 17a54d5..6ca1474 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -414,8 +414,8 @@ def import_jwks(self, jwks, issuer_id): """ try: _keys = jwks["keys"] - except KeyError: - raise ValueError("Not a proper JWKS") + except KeyError as exc: + raise ValueError("Not a proper JWKS") from exc if _keys: _issuer = self.return_issuer(issuer_id=issuer_id) diff --git a/src/cryptojwt/simple_jwt.py b/src/cryptojwt/simple_jwt.py index 36b3f30..71b6506 100644 --- a/src/cryptojwt/simple_jwt.py +++ b/src/cryptojwt/simple_jwt.py @@ -67,10 +67,7 @@ def pack(self, parts=None, headers=None): :return: """ if not headers: - if self.headers: - headers = self.headers - else: - headers = {"alg": "none"} + headers = self.headers if self.headers else {"alg": "none"} logging.debug(f"(pack) JWT header: {headers}") diff --git a/src/cryptojwt/tools/jwtpeek.py b/src/cryptojwt/tools/jwtpeek.py index 2cab665..2d56871 100755 --- a/src/cryptojwt/tools/jwtpeek.py +++ b/src/cryptojwt/tools/jwtpeek.py @@ -100,10 +100,7 @@ def main(): args = parser.parse_args() - if args.kid: - _kid = args.kid - else: - _kid = "" + _kid = args.kid if args.kid else "" keys = [] if args.rsa_file: diff --git a/src/cryptojwt/utils.py b/src/cryptojwt/utils.py index 3babaab..6802d24 100644 --- a/src/cryptojwt/utils.py +++ b/src/cryptojwt/utils.py @@ -197,10 +197,7 @@ def deser(val): :param val: The string representation of the long integer. :return: The long integer. """ - if isinstance(val, str): - _val = val.encode("utf-8") - else: - _val = val + _val = val.encode("utf-8") if isinstance(val, str) else val return base64_to_long(_val) From 05708c922a61b59a1d4523b6c3178edff0001cd3 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Thu, 30 May 2024 14:50:02 +0200 Subject: [PATCH 08/31] lint UP008 --- src/cryptojwt/jwe/jwe_ec.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptojwt/jwe/jwe_ec.py b/src/cryptojwt/jwe/jwe_ec.py index b4c3298..c8e11ed 100644 --- a/src/cryptojwt/jwe/jwe_ec.py +++ b/src/cryptojwt/jwe/jwe_ec.py @@ -203,7 +203,7 @@ def encrypt(self, key=None, iv="", cek="", **kwargs): _args["epk"] = kwargs["params"]["epk"] jwe = JWEnc(**_args) - ctxt, tag, cek = super(JWE_EC, self).enc_setup( + ctxt, tag, cek = super().enc_setup( self["enc"], _msg, auth_data=jwe.b64_encode_header(), key=cek, iv=iv ) if "encrypted_key" in kwargs: @@ -216,7 +216,7 @@ def decrypt(self, token=None, **kwargs): if not self.cek: raise Exception("Content Encryption Key is Not Yet Set") - msg = super(JWE_EC, self)._decrypt( + msg = super()._decrypt( self.headers["enc"], self.cek, self.ctxt, From e8343d3d47917eda8e9bb611a6d2381f358bb15b Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 31 May 2024 12:52:53 +0200 Subject: [PATCH 09/31] fix bare except --- src/cryptojwt/jws/hmac.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptojwt/jws/hmac.py b/src/cryptojwt/jws/hmac.py index be48f8d..775dbd2 100644 --- a/src/cryptojwt/jws/hmac.py +++ b/src/cryptojwt/jws/hmac.py @@ -44,5 +44,5 @@ def verify(self, msg, sig, key): h.update(msg) h.verify(sig) return True - except: + except Exception: return False From 2260e10f74fb519cd76811adb7a03ce5d8055eb3 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 31 May 2024 12:57:34 +0200 Subject: [PATCH 10/31] silence SIM118 --- src/cryptojwt/key_bundle.py | 12 +++++++++--- src/cryptojwt/key_issuer.py | 4 ++-- src/cryptojwt/key_jar.py | 4 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 485d6d3..4b0b3d6 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -918,12 +918,18 @@ def dump_jwks(kbl, target, private=False, symmetric_too=False): keys = [] for _bundle in kbl: if symmetric_too: - keys.extend([k.serialize(private) for k in _bundle.keys() if not k.inactive_since]) + keys.extend( + [ + k.serialize(private) + for k in _bundle.keys() # noqa: SIM118 + if not k.inactive_since + ] + ) else: keys.extend( [ k.serialize(private) - for k in _bundle.keys() + for k in _bundle.keys() # noqa: SIM118 if k.kty != "oct" and not k.inactive_since ] ) @@ -945,7 +951,7 @@ def _set_kid(spec, bundle, kid_template, kid): _keys = bundle.keys() _keys[0].kid = spec["kid"] else: - for k in bundle.keys(): + for k in bundle.keys(): # noqa: SIM118 if kid_template: k.kid = kid_template % kid kid += 1 diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index 87f5ed1..7c467c8 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -208,7 +208,7 @@ def export_jwks(self, private=False, usage=None): keys.extend( [ k.serialize(private) - for k in kb.keys() + for k in kb.keys() # noqa: SIM118 if k.inactive_since == 0 and (usage is None or (hasattr(k, "use") and k.use == usage)) ] @@ -438,7 +438,7 @@ def key_summary(self) -> str: """ key_list = [] for kb in self._bundles: - for key in kb.keys(): + for key in kb.keys(): # noqa: SIM118 if key.inactive_since: key_list.append(f"*{key.kty}:{key.use}:{key.kid}") else: diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 6ca1474..52d05ca 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -304,7 +304,7 @@ def match_owner(self, url): :param url: A URL :return: An issue entity ID that exists in the Key jar """ - _iss = [i for i in self._issuers.keys() if i.startswith(url)] + _iss = [i for i in self._issuers.keys() if i.startswith(url)] # noqa: SIM118 if _iss: return _iss[0] @@ -386,7 +386,7 @@ def export_jwks(self, private=False, issuer_id="", usage=None): keys.extend( [ k.serialize(private) - for k in kb.keys() + for k in kb.keys() # noqa: SIM118 if k.inactive_since == 0 and (usage is None or (hasattr(k, "use") and k.use == usage)) ] From 044af3cd811554a6f99e328ca3ab84040e2e43e3 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 31 May 2024 13:01:05 +0200 Subject: [PATCH 11/31] simplify loop --- src/cryptojwt/key_issuer.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index 7c467c8..ed96ab8 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -460,11 +460,7 @@ def __eq__(self, other): if k not in other: return False - for k in other.all_keys(): - if k not in self: - return False - - return True + return all(k in self for k in other.all_keys()) def rotate_keys(self, key_conf, kid_template=""): """ From d21e2a9c2046b7ae06ac2136bac601dcfa3d8ac4 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 31 May 2024 13:01:19 +0200 Subject: [PATCH 12/31] simplify --- src/cryptojwt/key_bundle.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 4b0b3d6..54b8b3e 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -277,10 +277,7 @@ def __init__( if keys: self.source = None - if isinstance(keys, dict): - initial_keys = keys["keys"] if "keys" in keys else [keys] - else: - initial_keys = keys + initial_keys = keys.get("keys", [keys]) if isinstance(keys, dict) else keys self._keys = self.jwk_dicts_as_keys(initial_keys) else: self._set_source(source, fileformat) From d96d7ae4054723ce9694346b3b7cfde671b5ed94 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 31 May 2024 13:04:02 +0200 Subject: [PATCH 13/31] simplify return any/all --- src/cryptojwt/jwk/rsa.py | 5 +---- src/cryptojwt/key_issuer.py | 5 +---- src/cryptojwt/key_jar.py | 6 +----- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/cryptojwt/jwk/rsa.py b/src/cryptojwt/jwk/rsa.py index aa4fa25..7e5b63b 100644 --- a/src/cryptojwt/jwk/rsa.py +++ b/src/cryptojwt/jwk/rsa.py @@ -208,10 +208,7 @@ def cmp_private_numbers(pn1, pn2): if not cmp_public_numbers(pn1.public_numbers, pn2.public_numbers): return False - for param in ["d", "p", "q"]: - if getattr(pn1, param) != getattr(pn2, param): - return False - return True + return all(getattr(pn1, param) == getattr(pn2, param) for param in ["d", "p", "q"]) class RSAKey(AsymmetricKey): diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index ed96ab8..a5bebc4 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -155,10 +155,7 @@ def all_keys(self): return res def __contains__(self, item): - for kb in self._bundles: - if item in kb: - return True - return False + return any(item in kb for kb in self._bundles) def items(self): _res = {} diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 52d05ca..78463fd 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -447,11 +447,7 @@ def __eq__(self, other): return False # Keys per issuer must be the same - for iss in self.owners(): - if self[iss] != other[iss]: - return False - - return True + return all(self[iss] == other[iss] for iss in self.owners()) def __delitem__(self, key): del self._issuers[key] From 0c286ec0d7caabca388c312face5fa26b27f110e Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 31 May 2024 13:08:22 +0200 Subject: [PATCH 14/31] simplify returns --- src/cryptojwt/jwk/asym.py | 5 +---- src/cryptojwt/jwk/ec.py | 4 +--- src/cryptojwt/jwk/okp.py | 4 +--- src/cryptojwt/jwk/rsa.py | 8 +------- src/cryptojwt/key_jar.py | 5 +---- src/cryptojwt/simple_jwt.py | 10 ++-------- 6 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/cryptojwt/jwk/asym.py b/src/cryptojwt/jwk/asym.py index e2b2bf5..1930248 100644 --- a/src/cryptojwt/jwk/asym.py +++ b/src/cryptojwt/jwk/asym.py @@ -58,10 +58,7 @@ def has_private_key(self): :return: True/False """ - if self.priv_key: - return True - else: - return False + return bool(self.priv_key) def public_key(self): """ diff --git a/src/cryptojwt/jwk/ec.py b/src/cryptojwt/jwk/ec.py index c2879b5..eedff4a 100644 --- a/src/cryptojwt/jwk/ec.py +++ b/src/cryptojwt/jwk/ec.py @@ -249,10 +249,8 @@ def __eq__(self, other): if other.private_key(): if cmp_keys(self.priv_key, other.priv_key, ec.EllipticCurvePrivateKey): return True - elif self.private_key(): - return False else: - return True + return not self.private_key() return False diff --git a/src/cryptojwt/jwk/okp.py b/src/cryptojwt/jwk/okp.py index e51ca8b..f58f71a 100644 --- a/src/cryptojwt/jwk/okp.py +++ b/src/cryptojwt/jwk/okp.py @@ -278,10 +278,8 @@ def __eq__(self, other): if other.private_key(): if cmp_keys(self.priv_key, other.priv_key, _private_cls): return True - elif self.private_key(): - return False else: - return True + return not self.private_key() return False diff --git a/src/cryptojwt/jwk/rsa.py b/src/cryptojwt/jwk/rsa.py index 7e5b63b..14f88c7 100644 --- a/src/cryptojwt/jwk/rsa.py +++ b/src/cryptojwt/jwk/rsa.py @@ -117,13 +117,7 @@ def rsa_eq(key1, key2): :param key2: :return: """ - pn1 = key1.public_numbers() - pn2 = key2.public_numbers() - # Check if two RSA keys are in fact the same - if pn1 == pn2: - return True - else: - return False + return key1.public_numbers() == key2.public_numbers() def x509_rsa_load(txt): diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 78463fd..d35f5f6 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -256,10 +256,7 @@ def get_issuer_keys(self, issuer_id): @deprecated_alias(issuer="issuer_id", owner="issuer_id") def __contains__(self, issuer_id): _iss = self._get_issuer(issuer_id) - if _iss is None: - return False - else: - return True + return not _iss is None @deprecated_alias(issuer="issuer_id", owner="issuer_id") def __getitem__(self, issuer_id=""): diff --git a/src/cryptojwt/simple_jwt.py b/src/cryptojwt/simple_jwt.py index 71b6506..f2c4515 100644 --- a/src/cryptojwt/simple_jwt.py +++ b/src/cryptojwt/simple_jwt.py @@ -111,15 +111,9 @@ def verify_header(self, key, val): """ if isinstance(val, list): - if self.headers[key] in val: - return True - else: - return False + return self.headers[key] in val else: - if self.headers[key] == val: - return True - else: - return False + return self.headers[key] == val def verify_headers(self, check_presence=True, **kwargs): """ From 958eb5bf1944b01527e58c96614f03881a306475 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 31 May 2024 13:09:46 +0200 Subject: [PATCH 15/31] fix return, is not --- src/cryptojwt/key_jar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index d35f5f6..813efc7 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -256,7 +256,7 @@ def get_issuer_keys(self, issuer_id): @deprecated_alias(issuer="issuer_id", owner="issuer_id") def __contains__(self, issuer_id): _iss = self._get_issuer(issuer_id) - return not _iss is None + return _iss is not None @deprecated_alias(issuer="issuer_id", owner="issuer_id") def __getitem__(self, issuer_id=""): From b61b7f1c1502aa1e9083fbae751503fe1f6c8778 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:35:01 +0200 Subject: [PATCH 16/31] do not import builtins --- src/cryptojwt/__init__.py | 7 ------- src/cryptojwt/jws/jws.py | 6 ------ 2 files changed, 13 deletions(-) diff --git a/src/cryptojwt/__init__.py b/src/cryptojwt/__init__.py index 44e5d81..abbfc1d 100644 --- a/src/cryptojwt/__init__.py +++ b/src/cryptojwt/__init__.py @@ -17,13 +17,6 @@ from .utils import b64encode_item from .utils import split_token -try: - from builtins import hex - from builtins import str - from builtins import zip -except ImportError: - pass - __version__ = pkg_resources.get_distribution("cryptojwt").version logger = logging.getLogger(__name__) diff --git a/src/cryptojwt/jws/jws.py b/src/cryptojwt/jws/jws.py index 1e4efd9..6b5fb7b 100644 --- a/src/cryptojwt/jws/jws.py +++ b/src/cryptojwt/jws/jws.py @@ -24,12 +24,6 @@ from .rsa import RSASigner from .utils import alg2keytype -try: - from builtins import object - from builtins import str -except ImportError: - pass - logger = logging.getLogger(__name__) KDESC = ["use", "kid", "kty"] From 8f9b2f7cd886f8b1c484f24ff07776e92209259b Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:36:16 +0200 Subject: [PATCH 17/31] explicit stacklevel for warn --- src/cryptojwt/jwx.py | 2 +- src/cryptojwt/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptojwt/jwx.py b/src/cryptojwt/jwx.py index 4b78bd1..ac214fb 100644 --- a/src/cryptojwt/jwx.py +++ b/src/cryptojwt/jwx.py @@ -95,7 +95,7 @@ def __init__(self, msg=None, with_digest=False, httpc=None, **kwargs): else: self._dict[key] = _val if key in DEPRECATED and _val in DEPRECATED[key]: - warnings.warn(f"{key}={_val} deprecated") + warnings.warn(f"{key}={_val} deprecated", stacklevel=1) def _set_jwk(self, val): if isinstance(val, dict): diff --git a/src/cryptojwt/utils.py b/src/cryptojwt/utils.py index 6802d24..965992c 100644 --- a/src/cryptojwt/utils.py +++ b/src/cryptojwt/utils.py @@ -251,7 +251,7 @@ def rename_kwargs(func_name, kwargs, aliases): if alias in kwargs: if new in kwargs: raise TypeError(f"{func_name} received both {alias} and {new}") - warnings.warn(f"{alias} is deprecated; use {new}", DeprecationWarning) + warnings.warn(f"{alias} is deprecated; use {new}", DeprecationWarning, stacklevel=1) kwargs[new] = kwargs.pop(alias) From 1465d4d3a9e12a978a93d1f7f81dca9957f2f207 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:39:10 +0200 Subject: [PATCH 18/31] fix unused var --- src/cryptojwt/key_bundle.py | 4 ++-- src/cryptojwt/key_issuer.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 54b8b3e..9723e69 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -826,7 +826,7 @@ def dump(self, exclude_attributes: Optional[List[str]] = None): _keys.append(_ser) res["keys"] = _keys - for attr, default in self.params.items(): + for attr in self.params: if attr in exclude_attributes: continue val = getattr(self, attr) @@ -849,7 +849,7 @@ def load(self, spec): self._keys.extend(self.jwk_dicts_as_keys(_keys)) self.last_updated = time.time() - for attr, default in self.params.items(): + for attr in self.params: val = spec.get(attr) if val: setattr(self, attr, val) diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index a5bebc4..f41e430 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -366,7 +366,7 @@ def dump(self, exclude_attributes: Optional[List[str]] = None) -> dict: exclude_attributes = [] info = {} - for attr, default in self.params.items(): + for attr in self.params: if attr in exclude_attributes: continue val = getattr(self, attr) @@ -388,7 +388,7 @@ def load(self, info): :param items: A dictionary with the information to load :return: """ - for attr, default in self.params.items(): + for attr in self.params: val = info.get(attr) if val: if attr == "keybundle_cls": From 8f9b4143e10a2705df98f2aa2c17ef0bad0e7d5f Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:40:01 +0200 Subject: [PATCH 19/31] merge isinstance param --- src/cryptojwt/jwk/jwk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptojwt/jwk/jwk.py b/src/cryptojwt/jwk/jwk.py index 4c2e5db..035e4ec 100644 --- a/src/cryptojwt/jwk/jwk.py +++ b/src/cryptojwt/jwk/jwk.py @@ -183,7 +183,7 @@ def jwk_wrap(key, use="", kid=""): :param kid: A key id :return: The Key instance """ - if isinstance(key, rsa.RSAPublicKey) or isinstance(key, rsa.RSAPrivateKey): + if isinstance(key, (rsa.RSAPublicKey, rsa.RSAPrivateKey)): kspec = RSAKey(use=use, kid=kid).load_key(key) elif isinstance(key, str): kspec = SYMKey(key=key, use=use, kid=kid) From e6384472109aa76eb32a75d4fdb674d4ee66c446 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:40:53 +0200 Subject: [PATCH 20/31] fix format --- src/cryptojwt/jws/jws.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptojwt/jws/jws.py b/src/cryptojwt/jws/jws.py index 6b5fb7b..434579a 100644 --- a/src/cryptojwt/jws/jws.py +++ b/src/cryptojwt/jws/jws.py @@ -201,7 +201,7 @@ def verify_compact_verbose(self, jws=None, keys=None, allow_none=False, sigalg=N ) if sigalg and sigalg != _alg: - raise SignerAlgError("Expected {0} got {1}".format(sigalg, jwt.headers["alg"])) + raise SignerAlgError("Expected {} got {}".format(sigalg, jwt.headers["alg"])) self["alg"] = _alg From 64ddf9289be77ffd27102caf4c4b88791a7a0f94 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:42:05 +0200 Subject: [PATCH 21/31] use yield from --- src/cryptojwt/key_issuer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index f41e430..6312940 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -443,8 +443,7 @@ def key_summary(self) -> str: return ", ".join(key_list) def __iter__(self): - for bundle in self._bundles: - yield bundle + yield from self._bundles def __eq__(self, other): if not isinstance(other, self.__class__): From 9907b2a3d00efbf1ac948262eba2110ebca68994 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:44:23 +0200 Subject: [PATCH 22/31] add imported symbols to __all__ (should be cleaned up) --- src/cryptojwt/__init__.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/cryptojwt/__init__.py b/src/cryptojwt/__init__.py index abbfc1d..d73efd7 100644 --- a/src/cryptojwt/__init__.py +++ b/src/cryptojwt/__init__.py @@ -19,6 +19,21 @@ __version__ = pkg_resources.get_distribution("cryptojwt").version +__all__ = [ + "JWE", + "JWE", + "JWK", + "JWS", + "JWT", + "KeyBundle", + "KeyJar", + "BadSyntax", + "as_unicode", + "b64d", + "b64encode_item", + "split_token", +] + logger = logging.getLogger(__name__) JWT_TYPES = ("JWT", "application/jws", "JWS", "JWE") From 788c8cb907932249b372f6621c8403a3d0436d0b Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:47:53 +0200 Subject: [PATCH 23/31] Use format specifiers instead of percent format --- src/cryptojwt/exception.py | 2 +- src/cryptojwt/jwe/jwe.py | 2 +- src/cryptojwt/jwe/jwe_ec.py | 6 +++--- src/cryptojwt/jwe/jwe_rsa.py | 4 ++-- src/cryptojwt/jwe/jwekey.py | 4 ++-- src/cryptojwt/jwe/jwenc.py | 2 +- src/cryptojwt/jwe/utils.py | 2 +- src/cryptojwt/jwk/jwk.py | 2 +- src/cryptojwt/jwk/x509.py | 4 ++-- src/cryptojwt/jws/jws.py | 16 ++++++++-------- src/cryptojwt/key_bundle.py | 6 +++--- src/cryptojwt/utils.py | 10 +++++----- 12 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/cryptojwt/exception.py b/src/cryptojwt/exception.py index 83bb1d3..63c0401 100644 --- a/src/cryptojwt/exception.py +++ b/src/cryptojwt/exception.py @@ -20,7 +20,7 @@ def __init__(self, value, msg): self.msg = msg def __str__(self): - return "%s: %r" % (self.msg, self.value) + return f"{self.msg}: {self.value!r}" class BadSignature(Invalid): diff --git a/src/cryptojwt/jwe/jwe.py b/src/cryptojwt/jwe/jwe.py index e8deb78..ad11244 100644 --- a/src/cryptojwt/jwe/jwe.py +++ b/src/cryptojwt/jwe/jwe.py @@ -199,7 +199,7 @@ def decrypt(self, token=None, keys=None, alg=None, cek=None): except (KeyError, DecryptionFailed): pass else: - logger.debug("Decrypted message using key with kid=%s" % key.kid) + logger.debug(f"Decrypted message using key with kid={key.kid}") return msg raise DecryptionFailed("No available key that could decrypt the message") diff --git a/src/cryptojwt/jwe/jwe_ec.py b/src/cryptojwt/jwe/jwe_ec.py index c8e11ed..db2d2e1 100644 --- a/src/cryptojwt/jwe/jwe_ec.py +++ b/src/cryptojwt/jwe/jwe_ec.py @@ -112,7 +112,7 @@ def enc_setup(self, msg, key=None, auth_data=b"", **kwargs): try: dk_len = KEY_LEN[self.enc] except KeyError as exc: - raise ValueError("Unknown key length for algorithm %s" % self.enc) from exc + raise ValueError(f"Unknown key length for algorithm {self.enc}") from exc cek = ecdh_derive_key(_epk, key.pub_key, apu, apv, str(self.enc).encode(), dk_len) elif self.alg in ["ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW"]: @@ -122,7 +122,7 @@ def enc_setup(self, msg, key=None, auth_data=b"", **kwargs): cek = self._generate_key(self.enc, cek=cek) encrypted_key = aes_key_wrap(kek, cek) else: - raise Exception("Unsupported algorithm %s" % self.alg) + raise Exception(f"Unsupported algorithm {self.alg}") return cek, encrypted_key, iv, params, epk @@ -174,7 +174,7 @@ def dec_setup(self, token, key=None, **kwargs): kek = ecdh_derive_key(key, epubkey.pub_key, apu, apv, str(_post).encode(), klen) self.cek = aes_key_unwrap(kek, token.encrypted_key()) else: - raise Exception("Unsupported algorithm %s" % self.headers["alg"]) + raise Exception("Unsupported algorithm {}".format(self.headers["alg"])) return self.cek diff --git a/src/cryptojwt/jwe/jwe_rsa.py b/src/cryptojwt/jwe/jwe_rsa.py index aa8f43e..51965d3 100644 --- a/src/cryptojwt/jwe/jwe_rsa.py +++ b/src/cryptojwt/jwe/jwe_rsa.py @@ -49,7 +49,7 @@ def encrypt(self, key, iv="", cek="", **kwargs): if self["zip"] == "DEF": _msg = zlib.compress(_msg) else: - raise ParameterError("Zip has unknown value: %s" % self["zip"]) + raise ParameterError("Zip has unknown value: {}".format(self["zip"])) kwarg_cek = cek or None @@ -58,7 +58,7 @@ def encrypt(self, key, iv="", cek="", **kwargs): cek = self._generate_key(_enc, cek) self["cek"] = cek - logger.debug("cek: %s, iv: %s" % ([c for c in cek], [c for c in iv])) + logger.debug(f"cek: {[c for c in cek]}, iv: {[c for c in iv]}") _encrypt = RSAEncrypter(self.with_digest).encrypt diff --git a/src/cryptojwt/jwe/jwekey.py b/src/cryptojwt/jwe/jwekey.py index a88d0cf..719e931 100644 --- a/src/cryptojwt/jwe/jwekey.py +++ b/src/cryptojwt/jwe/jwekey.py @@ -30,7 +30,7 @@ def _generate_key(encalg, cek=""): try: _key = get_random_bytes(KEY_LEN_BYTES[encalg]) except KeyError as exc: - raise ValueError("Unsupported encryption algorithm %s" % encalg) from exc + raise ValueError(f"Unsupported encryption algorithm {encalg}") from exc return _key @@ -77,7 +77,7 @@ def _decrypt(enc, key, ctxt, iv, tag, auth_data=b""): elif enc in ["A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512"]: aes = AES_CBCEncrypter(key=key) else: - raise Exception("Unsupported encryption algorithm %s" % enc) + raise Exception(f"Unsupported encryption algorithm {enc}") try: return aes.decrypt(ctxt, iv=iv, auth_data=auth_data, tag=tag) diff --git a/src/cryptojwt/jwe/jwenc.py b/src/cryptojwt/jwe/jwenc.py index 232ff0b..61ef643 100644 --- a/src/cryptojwt/jwe/jwenc.py +++ b/src/cryptojwt/jwe/jwenc.py @@ -48,7 +48,7 @@ def is_jwe(self): if "alg" in self.headers and "enc" in self.headers: for typ in ["alg", "enc"]: if self.headers[typ] not in SUPPORTED[typ]: - logger.debug("Not supported %s algorithm: %s" % (typ, self.headers[typ])) + logger.debug(f"Not supported {typ} algorithm: {self.headers[typ]}") return False else: return False diff --git a/src/cryptojwt/jwe/utils.py b/src/cryptojwt/jwe/utils.py index 80d8324..f1c44aa 100644 --- a/src/cryptojwt/jwe/utils.py +++ b/src/cryptojwt/jwe/utils.py @@ -19,7 +19,7 @@ def get_keys_seclen_dgst(key, iv): try: seclen, hash_method = LENMET[len(key)] except KeyError as exc: - raise Exception("Invalid CBC+HMAC key length: %s bytes" % len(key)) from exc + raise Exception(f"Invalid CBC+HMAC key length: {len(key)} bytes") from exc # Split the key ka = key[:seclen] diff --git a/src/cryptojwt/jwk/jwk.py b/src/cryptojwt/jwk/jwk.py index 035e4ec..47bba71 100644 --- a/src/cryptojwt/jwk/jwk.py +++ b/src/cryptojwt/jwk/jwk.py @@ -100,7 +100,7 @@ def key_from_jwk_dict(jwk_dict, private=None): if _jwk_dict["crv"] in NIST2SEC: curve = NIST2SEC[_jwk_dict["crv"]]() else: - raise UnsupportedAlgorithm("Unknown curve: %s" % (_jwk_dict["crv"])) + raise UnsupportedAlgorithm("Unknown curve: {}".format(_jwk_dict["crv"])) if _jwk_dict.get("d", None) is not None: # Ecdsa private key. diff --git a/src/cryptojwt/jwk/x509.py b/src/cryptojwt/jwk/x509.py index 87a627c..c08bd63 100644 --- a/src/cryptojwt/jwk/x509.py +++ b/src/cryptojwt/jwk/x509.py @@ -106,9 +106,9 @@ def load_x509_cert(url, httpc, spec2key, **get_args): elif isinstance(public_key, ec.EllipticCurvePublicKey): return {"ec": public_key} else: - raise Exception("HTTP Get error: %s" % r.status_code) + raise Exception(f"HTTP Get error: {r.status_code}") except Exception as err: # not a RSA key - logger.warning("Can't load key: %s" % err) + logger.warning(f"Can't load key: {err}") return [] diff --git a/src/cryptojwt/jws/jws.py b/src/cryptojwt/jws/jws.py index 434579a..686b5f8 100644 --- a/src/cryptojwt/jws/jws.py +++ b/src/cryptojwt/jws/jws.py @@ -93,10 +93,10 @@ def alg_keys(self, keys, use, protected=None): else: if "kid" in self: raise NoSuitableSigningKeys( - "No key for algorithm: %s and kid: %s" % (_alg, self["kid"]) + "No key for algorithm: {} and kid: {}".format(_alg, self["kid"]) ) else: - raise NoSuitableSigningKeys("No key for algorithm: %s" % _alg) + raise NoSuitableSigningKeys(f"No key for algorithm: {_alg}") return key, xargs, _alg @@ -137,7 +137,7 @@ def sign_compact(self, keys=None, protected=None, **kwargs): else: sig = _signer.sign(_input.encode("utf-8"), key.key) - logger.debug("Signed message using key with kid=%s" % key.kid) + logger.debug(f"Signed message using key with kid={key.kid}") return ".".join([_input, b64encode_item(sig).decode("utf-8")]) def verify_compact(self, jws=None, keys=None, allow_none=False, sigalg=None): @@ -209,11 +209,11 @@ def verify_compact_verbose(self, jws=None, keys=None, allow_none=False, sigalg=N if not _keys: if "kid" in self: - raise NoSuitableSigningKeys("No key with kid: %s" % (self["kid"])) + raise NoSuitableSigningKeys("No key with kid: {}".format(self["kid"])) elif "kid" in self.jwt.headers: - raise NoSuitableSigningKeys("No key with kid: %s" % (self.jwt.headers["kid"])) + raise NoSuitableSigningKeys("No key with kid: {}".format(self.jwt.headers["kid"])) else: - raise NoSuitableSigningKeys("No key for algorithm: %s" % _alg) + raise NoSuitableSigningKeys(f"No key for algorithm: {_alg}") verifier = SIGNER_ALGS[_alg] @@ -228,7 +228,7 @@ def verify_compact_verbose(self, jws=None, keys=None, allow_none=False, sigalg=N except (ValueError, TypeError) as err: logger.warning(f'Exception "{err}" caught') else: - logger.debug("Verified message using key with kid=%s" % key.kid) + logger.debug(f"Verified message using key with kid={key.kid}") self.msg = jwt.payload() self.key = key self._protected_headers = jwt.headers.copy() @@ -408,7 +408,7 @@ def _is_compact_jws(self, jws): jwt.headers["alg"] = "none" if jwt.headers["alg"] not in SIGNER_ALGS: - logger.debug("UnknownSignerAlg: %s" % jwt.headers["alg"]) + logger.debug("UnknownSignerAlg: {}".format(jwt.headers["alg"])) return False self.jwt = jwt diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 9723e69..c06e94e 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -1007,7 +1007,7 @@ def build_key_bundle(key_conf, kid_template=""): if "key" in spec and spec["key"]: if os.path.isfile(spec["key"]): _bundle = KeyBundle( - source="file://%s" % spec["key"], + source="file://{}".format(spec["key"]), fileformat="der", keytype=typ, keyusage=spec["use"], @@ -1018,7 +1018,7 @@ def build_key_bundle(key_conf, kid_template=""): if "key" in spec and spec["key"]: if os.path.isfile(spec["key"]): _bundle = KeyBundle( - source="file://%s" % spec["key"], + source="file://{}".format(spec["key"]), fileformat="der", keytype=typ, keyusage=spec["use"], @@ -1029,7 +1029,7 @@ def build_key_bundle(key_conf, kid_template=""): if "key" in spec and spec["key"]: if os.path.isfile(spec["key"]): _bundle = KeyBundle( - source="file://%s" % spec["key"], + source="file://{}".format(spec["key"]), fileformat="der", keytype=typ, keyusage=spec["use"], diff --git a/src/cryptojwt/utils.py b/src/cryptojwt/utils.py index 965992c..47785e0 100644 --- a/src/cryptojwt/utils.py +++ b/src/cryptojwt/utils.py @@ -20,11 +20,11 @@ def intarr2bin(arr): - return unhexlify("".join(["%02x" % byte for byte in arr])) + return unhexlify("".join([f"{byte:02x}" for byte in arr])) def intarr2long(arr): - return int("".join(["%02x" % byte for byte in arr]), 16) + return int("".join([f"{byte:02x}" for byte in arr]), 16) def intarr2str(arr): @@ -45,7 +45,7 @@ def long_to_base64(n, mlen=0): _len = mlen - len(bys) if _len: bys = [0] * _len + bys - data = struct.pack("%sB" % len(bys), *bys) + data = struct.pack(f"{len(bys)}B", *bys) if not len(data): data = b"\x00" s = base64.urlsafe_b64encode(data).rstrip(b"=") @@ -58,7 +58,7 @@ def base64_to_long(data): # urlsafe_b64decode will happily convert b64encoded data _d = base64.urlsafe_b64decode(as_bytes(data) + b"==") - return intarr2long(struct.unpack("%sB" % len(_d), _d)) + return intarr2long(struct.unpack(f"{len(_d)}B", _d)) def base64url_to_long(data): @@ -75,7 +75,7 @@ def base64url_to_long(data): # that is no '+' and '/' characters and not trailing "="s. if [e for e in [b"+", b"/", b"="] if e in _data]: raise ValueError("Not base64url encoded") - return intarr2long(struct.unpack("%sB" % len(_d), _d)) + return intarr2long(struct.unpack(f"{len(_d)}B", _d)) # ============================================================================= From 54965f29359c478ba8a321246d0ad55b7fb34884 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:49:36 +0200 Subject: [PATCH 24/31] move ruff --- .github/workflows/ruff.yml | 10 ++++++++++ .github/workflows/test.yml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ruff.yml diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 0000000..5b8f29e --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,10 @@ +name: Ruff + +on: [ push, pull_request ] + +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 50e03ad..7ba4551 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,7 +41,7 @@ jobs: run: poetry install - name: Run pytest run: | - poetry run pytest -vvv -ra --cov=cryptojwt --cov-report=xml --isort --black --ruff + poetry run pytest -vvv -ra --cov=cryptojwt --cov-report=xml --isort --black - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: From c41d1dc074546704beda40794cad8e5837d5b878 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Fri, 7 Jun 2024 11:51:00 +0200 Subject: [PATCH 25/31] no ruff --- doc/conf.py | 2 ++ 1 file changed, 2 insertions(+) mode change 100644 => 100755 doc/conf.py diff --git a/doc/conf.py b/doc/conf.py old mode 100644 new mode 100755 index 28cd920..8b9d174 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +# +# ruff: noqa # -*- coding: utf-8 -*- # # CryptoJWT documentation build configuration file, created by From d5e96f7c5e61acc198d3a6ec28f50dff1ca9bffd Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Sun, 9 Jun 2024 10:55:29 +0200 Subject: [PATCH 26/31] add depends --- .github/workflows/ruff.yml | 10 ---------- .github/workflows/test.yml | 8 +++++++- 2 files changed, 7 insertions(+), 11 deletions(-) delete mode 100644 .github/workflows/ruff.yml diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml deleted file mode 100644 index 5b8f29e..0000000 --- a/.github/workflows/ruff.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: Ruff - -on: [ push, pull_request ] - -jobs: - ruff: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: chartboost/ruff-action@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7ba4551..4f834e4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,8 +16,14 @@ jobs: do_not_skip: '["pull_request"]' cancel_others: 'true' concurrent_skipping: same_content - test: + ruff: + runs-on: ubuntu-latest needs: pre_job + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 + test: + needs: ruff if: ${{ needs.pre_job.outputs.should_skip != 'true' }} runs-on: ubuntu-latest strategy: From 1967c636880102b5390eda2a4888289251707d74 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Sun, 9 Jun 2024 10:57:11 +0200 Subject: [PATCH 27/31] use actions/setup-python@v5 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4f834e4..75eb1bd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,7 +36,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install and configure Poetry From ec78fc46d76da5658f7972686a1fe225ab4045a6 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Sun, 9 Jun 2024 10:58:05 +0200 Subject: [PATCH 28/31] use v4 --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c428cf8..c8b9942 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -39,7 +39,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -50,7 +50,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@v4 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -64,4 +64,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 From afadec8e11be6b465f2afde358190759e1a2eb45 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Sun, 9 Jun 2024 11:00:21 +0200 Subject: [PATCH 29/31] revert --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c8b9942..c428cf8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -39,7 +39,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -50,7 +50,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v4 + uses: github/codeql-action/autobuild@v3 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -64,4 +64,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@v3 From 3be27c7dcc400589bcd1a702fd4f0e532fa81e7f Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Sun, 9 Jun 2024 11:01:11 +0200 Subject: [PATCH 30/31] use v4 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 75eb1bd..6e75ae7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,6 +49,6 @@ jobs: run: | poetry run pytest -vvv -ra --cov=cryptojwt --cov-report=xml --isort --black - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} From f94b9291db3e8f7861ce32b3ac86e4e08ef9c419 Mon Sep 17 00:00:00 2001 From: Jakob Schlyter Date: Mon, 17 Jun 2024 12:39:50 +0200 Subject: [PATCH 31/31] add pre-commit --- .pre-commit-config.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..1959583 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,15 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-merge-conflict + - id: debug-statements + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-json + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.4.9 + hooks: + - id: ruff + - id: ruff-format