Skip to content

Commit

Permalink
RFC: Add type hints (#344)
Browse files Browse the repository at this point in the history
* Add mypy to Travis and a simple type hint to _get_default_options

* Make flake8 accept unused import required by mypy

* Add typing to encode and decode, create encode_bytes in JWS to differentiate from encode in JWT

* Use Union type to describe both types of payload
  • Loading branch information
jacopofar authored and jpadilla committed Apr 8, 2018
1 parent ee2ab9f commit aed7305
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 11 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ env:
install:
- pip install -U pip
- pip install -U tox coveralls
- pip install -U mypy
script:
- tox
- mypy --ignore-missing-imports jwt
after_success:
- coveralls
23 changes: 19 additions & 4 deletions jwt/api_jws.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
import json
import warnings
from collections import Mapping
try:
# import required by mypy to perform type checking, not used for normal execution
from typing import Callable, Dict, List, Optional, Union # NOQA
except ImportError:
pass

from .algorithms import (
Algorithm, get_default_algorithms, has_crypto, requires_cryptography # NOQA
Expand Down Expand Up @@ -69,8 +74,13 @@ def get_algorithms(self):
"""
return list(self._valid_algs)

def encode(self, payload, key, algorithm='HS256', headers=None,
json_encoder=None):
def encode(self,
payload, # type: Union[Dict, bytes]
key, # type: str
algorithm='HS256', # type: str
headers=None, # type: Optional[Dict]
json_encoder=None # type: Optional[Callable]
):
segments = []

if algorithm is None:
Expand Down Expand Up @@ -117,7 +127,12 @@ def encode(self, payload, key, algorithm='HS256', headers=None,

return b'.'.join(segments)

def decode(self, jws, key='', verify=True, algorithms=None, options=None,
def decode(self,
token, # type: str
key='', # type: str
verify=True, # type: bool
algorithms=None, # type: List[str]
options=None, # type: Dict
**kwargs):

merged_options = merge_dict(self.options, options)
Expand All @@ -131,7 +146,7 @@ def decode(self, jws, key='', verify=True, algorithms=None, options=None,
DeprecationWarning
)

payload, signing_input, header, signature = self._load(jws)
payload, signing_input, header, signature = self._load(token)

if not verify:
warnings.warn('The verify parameter is deprecated. '
Expand Down
28 changes: 22 additions & 6 deletions jwt/api_jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
from calendar import timegm
from collections import Iterable, Mapping
from datetime import datetime, timedelta
try:
# import required by mypy to perform type checking, not used for normal execution
from typing import Callable, Dict, List, Optional, Union # NOQA
except ImportError:
pass

from .api_jws import PyJWS
from .algorithms import Algorithm, get_default_algorithms # NOQA
Expand All @@ -20,6 +25,7 @@ class PyJWT(PyJWS):

@staticmethod
def _get_default_options():
# type: () -> Dict[str, bool]
return {
'verify_signature': True,
'verify_exp': True,
Expand All @@ -32,8 +38,13 @@ def _get_default_options():
'require_nbf': False
}

def encode(self, payload, key, algorithm='HS256', headers=None,
json_encoder=None):
def encode(self,
payload, # type: Union[Dict, bytes]
key, # type: str
algorithm='HS256', # type: str
headers=None, # type: Optional[Dict]
json_encoder=None # type: Optional[Callable]
):
# Check that we get a mapping
if not isinstance(payload, Mapping):
raise TypeError('Expecting a mapping object, as JWT only supports '
Expand All @@ -43,7 +54,7 @@ def encode(self, payload, key, algorithm='HS256', headers=None,
for time_claim in ['exp', 'iat', 'nbf']:
# Convert datetime to a intDate value in known time-format claims
if isinstance(payload.get(time_claim), datetime):
payload[time_claim] = timegm(payload[time_claim].utctimetuple())
payload[time_claim] = timegm(payload[time_claim].utctimetuple()) # type: ignore

json_payload = json.dumps(
payload,
Expand All @@ -55,7 +66,12 @@ def encode(self, payload, key, algorithm='HS256', headers=None,
json_payload, key, algorithm, headers, json_encoder
)

def decode(self, jwt, key='', verify=True, algorithms=None, options=None,
def decode(self,
token, # type: str
key='', # type: str
verify=True, # type: bool
algorithms=None, # type: List[str]
options=None, # type: Dict
**kwargs):

if verify and not algorithms:
Expand All @@ -66,15 +82,15 @@ def decode(self, jwt, key='', verify=True, algorithms=None, options=None,
DeprecationWarning
)

payload, signing_input, header, signature = self._load(jwt)
payload, _, _, _ = self._load(token)

if options is None:
options = {'verify_signature': verify}
else:
options.setdefault('verify_signature', verify)

decoded = super(PyJWT, self).decode(
jwt, key=key, algorithms=algorithms, options=options, **kwargs
token, key=key, algorithms=algorithms, options=options, **kwargs
)

try:
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ commands =
deps =
flake8
flake8-import-order
pep8-naming
pep8-naming

0 comments on commit aed7305

Please sign in to comment.