Closed Viicos closed 1 year ago
I have an interesting issue with mypy, now that hash_alg
is typed:
jwt/algorithms.py:592: error: Argument "salt_length" to "PSS" has incompatible type "Callable[[HashAlgorithm], int]"; expected "Union[int, _MaxLength, _Auto, _DigestLength]" [arg-type]
jwt/algorithms.py:604: error: Argument "salt_length" to "PSS" has incompatible type "Callable[[HashAlgorithm], int]"; expected "Union[int, _MaxLength, _Auto, _DigestLength]" [arg-type]
This is due to the fact that hash_alg
is of type Type[HashAlgorithm]
, hence accessing the digest_size
attribute makes mypy believe that it is a property (and not a int
).
And because cryptography
is doing a weird thing (defining an abstract property in HashAlgorithm
but overriding it as a simple attribute in the hash implementations):
class HashAlgorithm(metaclass=abc.ABCMeta):
@abc.abstractproperty
def name(self) -> str:
"""
A string naming this algorithm (e.g. "sha256", "md5").
"""
@abc.abstractproperty
def digest_size(self) -> int:
"""
The size of the resulting digest in bytes.
"""
@abc.abstractproperty
def block_size(self) -> typing.Optional[int]:
"""
The internal block size of the hash function, or None if the hash
function does not use blocks internally (e.g. SHA3).
"""
class SHA256(HashAlgorithm):
name = "sha256"
digest_size = 32
block_size = 64
So this still works at runtime, but I think this is something that should be sorted out in the cryptography
package instead. As a workaround here, we can use an instance of hash_alg
instead: salt_length=self.hash_alg().digest_size
A few fixes I had while trying to fix https://github.com/jpadilla/pyjwt/issues/602.
I was also wondering if
Algorithm
could be made an abstract base class? Afaik it is not instanciated as is and this would avoid having to explicitly raiseNotImplementedError
.Regarding https://github.com/jpadilla/pyjwt/issues/602, I might have a few solutions, but that might be tricky to handle (regarding the fact that
cryptography
is optional, as stated in https://github.com/jpadilla/pyjwt/pull/605). The least that can be done:prepare_key
,sign
andverify
.Algorithm
methods, use a conditional Union including all available types, depending on the availability ofcryptography
(not sure if this will work as excepted).encode
/decode
/decode_complete
public methods.Additionally, overloads could be defined for the methods listed above:
That way type checkers could attest that for instance when using
encode(payload, key, "HS256")
, key should beUnion[str, bytes]
. Although this improves type safety, it adds a lot of boilerplate code.