Skip to content

Commit b8cace5

Browse files
authored
Update typing syntax and usage for Python 3.6+ (#535)
Now that Python 2 is not supported, can move away from type comments to type annotation 🎉. The typing module is always available, so remove the guards. Specify the supported Python in the mypy configuration. Move other mypy configurations to one place. This way, whether tox is used or not, the same mypy errors appear. Distribute and install PEP-561 compliant py.typed file. When PyJWT is a imported as a library, this tells mypy to use the provided type annotations rather than going through typeshed. This way, the types are always up to date when running mypy. Remove outdated ignores since dropping Python 2.
1 parent 3ab6583 commit b8cace5

File tree

6 files changed

+37
-38
lines changed

6 files changed

+37
-38
lines changed

jwt/api_jws.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import binascii
22
import json
33
from collections.abc import Mapping
4+
from typing import Dict, List, Optional, Type, Union
45

56
from .algorithms import requires_cryptography # NOQA
67
from .algorithms import Algorithm, get_default_algorithms, has_crypto
@@ -12,12 +13,6 @@
1213
)
1314
from .utils import base64url_decode, base64url_encode, force_bytes, merge_dict
1415

15-
try:
16-
# import required by mypy to perform type checking, not used for normal execution
17-
from typing import Callable, Dict, List, Optional, Type, Union # NOQA
18-
except ImportError:
19-
pass
20-
2116

2217
class PyJWS:
2318
header_typ = "JWT"
@@ -79,11 +74,11 @@ def get_algorithms(self):
7974

8075
def encode(
8176
self,
82-
payload, # type: Union[Dict, bytes]
83-
key, # type: str
84-
algorithm="HS256", # type: str
85-
headers=None, # type: Optional[Dict]
86-
json_encoder=None, # type: Optional[Type[json.JSONEncoder]]
77+
payload: Union[Dict, bytes],
78+
key: str,
79+
algorithm: str = "HS256",
80+
headers: Optional[Dict] = None,
81+
json_encoder: Optional[Type[json.JSONEncoder]] = None,
8782
):
8883
segments = []
8984

@@ -131,11 +126,11 @@ def encode(
131126

132127
def decode(
133128
self,
134-
jwt, # type: str
135-
key="", # type: str
136-
algorithms=None, # type: List[str]
137-
options=None, # type: Dict
138-
complete=False, # type: bool
129+
jwt: str,
130+
key: str = "",
131+
algorithms: List[str] = None,
132+
options: Dict = None,
133+
complete: bool = False,
139134
**kwargs
140135
):
141136

jwt/api_jwt.py

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from calendar import timegm
33
from collections.abc import Iterable, Mapping
44
from datetime import datetime, timedelta
5+
from typing import Any, Dict, List, Optional, Type, Union
56

67
from .algorithms import Algorithm, get_default_algorithms # NOQA
78
from .api_jws import PyJWS
@@ -16,19 +17,12 @@
1617
)
1718
from .utils import merge_dict
1819

19-
try:
20-
# import required by mypy to perform type checking, not used for normal execution
21-
from typing import Any, Callable, Dict, List, Optional, Type, Union # NOQA
22-
except ImportError:
23-
pass
24-
2520

2621
class PyJWT(PyJWS):
2722
header_type = "JWT"
2823

2924
@staticmethod
30-
def _get_default_options():
31-
# type: () -> Dict[str, Union[bool, List[str]]]
25+
def _get_default_options() -> Dict[str, Union[bool, List[str]]]:
3226
return {
3327
"verify_signature": True,
3428
"verify_exp": True,
@@ -41,11 +35,11 @@ def _get_default_options():
4135

4236
def encode(
4337
self,
44-
payload, # type: Union[Dict, bytes]
45-
key, # type: str
46-
algorithm="HS256", # type: str
47-
headers=None, # type: Optional[Dict]
48-
json_encoder=None, # type: Optional[Type[json.JSONEncoder]]
38+
payload: Union[Dict, bytes],
39+
key: str,
40+
algorithm: str = "HS256",
41+
headers: Optional[Dict] = None,
42+
json_encoder: Optional[Type[json.JSONEncoder]] = None,
4943
):
5044
# Check that we get a mapping
5145
if not isinstance(payload, Mapping):
@@ -60,7 +54,7 @@ def encode(
6054
if isinstance(payload.get(time_claim), datetime):
6155
payload[time_claim] = timegm(
6256
payload[time_claim].utctimetuple()
63-
) # type: ignore
57+
)
6458

6559
json_payload = json.dumps(
6660
payload, separators=(",", ":"), cls=json_encoder
@@ -72,13 +66,13 @@ def encode(
7266

7367
def decode(
7468
self,
75-
jwt, # type: str
76-
key="", # type: str
77-
algorithms=None, # type: List[str]
78-
options=None, # type: Dict
79-
complete=False, # type: bool
69+
jwt: str,
70+
key: str = "",
71+
algorithms: List[str] = None,
72+
options: Dict = None,
73+
complete: bool = False,
8074
**kwargs
81-
): # type: (...) -> Dict[str, Any]
75+
) -> Dict[str, Any]:
8276

8377
if options is None:
8478
options = {"verify_signature": True}

jwt/help.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from . import __version__ as pyjwt_version
66

77
try:
8-
import cryptography # type: ignore
8+
import cryptography
99
except ImportError:
1010
cryptography = None # type: ignore
1111

jwt/py.typed

Whitespace-only changes.

setup.cfg

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,14 @@ classifiers =
3030
Topic :: Utilities
3131

3232
[options]
33+
zip_safe = false
34+
include_package_data = true
3335
python_requires = >=3.6
3436
packages = find:
3537

38+
[options.package_data]
39+
* = py.typed
40+
3641
[options.extras_require]
3742
docs =
3843
sphinx
@@ -61,3 +66,8 @@ jwks-client =
6166
exclude =
6267
tests
6368
tests.*
69+
70+
[mypy]
71+
python_version = 3.6
72+
ignore_missing_imports = true
73+
warn_unused_ignores = true

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ commands =
5656
[testenv:typing]
5757
basepython = python3.8
5858
extras = dev
59-
commands = mypy --ignore-missing-imports jwt
59+
commands = mypy jwt
6060

6161

6262
[testenv:lint]

0 commit comments

Comments
 (0)