Skip to content
50 changes: 50 additions & 0 deletions third_party/3/jwt/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from typing import Mapping, Any, Optional, Union

from . import algorithms

def decode(jwt: Union[str, bytes], key: Union[str, bytes] = ...,
verify: bool = ..., algorithms: Optional[Any] = ...,
options: Optional[Mapping[Any, Any]] = ...,
**kwargs: Any) -> Mapping[str, Any]: ...

def encode(payload: Mapping[str, Any], key: Union[str, bytes],
algorithm: str = ..., headers: Optional[Mapping[str, Any]] = ...,
json_encoder: Optional[Any] = ...) -> bytes: ...

def register_algorithm(alg_id: str,
alg_obj: algorithms.Algorithm) -> None: ...

def unregister_algorithm(alg_id: str) -> None: ...

class InvalidTokenError(Exception): pass

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove the blank lines between the various exception classes too (but keep them between this block and the functions and non-exception definitions).

class DecodeError(InvalidTokenError): pass

class ExpiredSignatureError(InvalidTokenError): pass

class InvalidAudienceError(InvalidTokenError): pass

class InvalidIssuerError(InvalidTokenError): pass

class InvalidIssuedAtError(InvalidTokenError): pass

class ImmatureSignatureError(InvalidTokenError): pass

class InvalidKeyError(Exception): pass

class InvalidAlgorithmError(InvalidTokenError): pass

class MissingRequiredClaimError(InvalidTokenError): ...

# Compatibility aliases (deprecated)
ExpiredSignature = ExpiredSignatureError
InvalidAudience = InvalidAudienceError
InvalidIssuer = InvalidIssuerError

# These aren't actually documented, but the package
# exports them in __init__.py, so we should at least
# make sure that mypy doesn't raise spurious errors
# if they're used.
get_unverified_header = ... # type: Any
PyJWT = ... # type: Any
PyJWS = ... # type: Any
3 changes: 3 additions & 0 deletions third_party/3/jwt/algorithms.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from typing import Any

class Algorithm: Any # type: ignore
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just makes the class body be Any. You need to write class Algorithm(Any): ... to inherit from Any.

Empty file.
8 changes: 8 additions & 0 deletions third_party/3/jwt/contrib/algorithms/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from typing import Callable, Any, Union
from hashlib import _DataType

# In reality, _HashAlg is a function of the type
# that hashlib.sha256/384/512 are, but there doesn't
# seem to be a consistent exportable name that we can reference
# for that, so we'll just say it's a Callable here.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just say from hashlib import _Hash, just like you are importing _DataType from there. In order to export it, you could write from hashlib import _Hash as _HashAlg. (In the future, once PEP 544 is in, I suppose _Hash would become a protocol.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so this is what I'd tried originally, but I get the error Module 'hashlib' has no attribute '_Hash'.

I noticed that in the Python 2 stubs, this type is called _hash, so I also tried importing that name--just in case my mypy is somehow using the python 2 stubs--but that doesn't work either.

Any ideas?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These stubs are in stdlib/3 so they should only use the Python 3 version. When you switch to what I suggested does it still fail?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh. You need to merge/rebase. The situation in hashlib apparently changed since you last pulled from upstream.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, I got an email notification where you said you were able to reproduce my bug and were debugging it, but visiting this page now, I'm not seeing it--did you manage to make any progress?

I'll try to test my stub in the context of the typeshed repo itself and see if that helps--so far I have been writing it in my own independent repository because I need unit tests to make sure the annotations align with the example snippets in pyJWT's own documentation, but I understand from #862 that those tests wouldn't be useful as a contribution to this repository, so I've kept them separate. But this also means I've mostly been testing the stubs from my repository, which doesn't have the intermediary 3 directory that might make mypy happy.

Will try to get this working on my end soon! Sorry for the delay.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I found out I was wrong and deleted that comment, replacing it instead with "You need to merge/rebase", but I never sent that comment out. :-( So the upshot is that yes, I debugged it, and the solution is to merge from upstream.

_HashAlg = Callable[[_DataType], Any]
10 changes: 10 additions & 0 deletions third_party/3/jwt/contrib/algorithms/py_ecdsa.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import Any
from jwt.algorithms import Algorithm

from . import _HashAlg

class ECAlgorithm(Algorithm):
SHA256 = ... # type: _HashAlg
SHA384 = ... # type: _HashAlg
SHA512 = ... # type: _HashAlg
def __init__(self, hash_alg: _HashAlg) -> None: ...
10 changes: 10 additions & 0 deletions third_party/3/jwt/contrib/algorithms/pycrypto.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import Any
from jwt.algorithms import Algorithm

from . import _HashAlg

class RSAAlgorithm(Algorithm):
SHA256 = ... # type: _HashAlg
SHA384 = ... # type: _HashAlg
SHA512 = ... # type: _HashAlg
def __init__(self, hash_alg: _HashAlg) -> None: ...