Skip to content

Commit

Permalink
add: type hints to top level functions (#218)
Browse files Browse the repository at this point in the history
* WIP: add type hints to top level functions

TODO:
- see if mypy picks up types when installing in new project
- setup mypy in CI

fixes #215

* add mypy to ci & move py.typed to correct folder?

* try and get mypy to run in CI

* run mypy in travis?

* use mypy defaults for python_version and platform

https://mypy.readthedocs.io/en/stable/config_file.html#platform-configuration

* update change log with changes
  • Loading branch information
sbdchd committed Aug 14, 2020
1 parent f3c255c commit f9066e2
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ matrix:
env: TOXENV=pypy3 CC=clang
- python: 3.8
env: TOXENV=pep8
- python: 3.8
env: TOXENV=mypy
- env: TOXENV=packaging
- python: 3.8
arch: arm64
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ include src/build_bcrypt.py
recursive-include src/_csrc *
recursive-include tests *.py

exclude requirements.txt release.py .travis.yml
exclude requirements.txt release.py .travis.yml mypy.ini

prune .travis
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Changelog
Unreleased
----------

* Add typehints for library functions

* Dropped support for Python versions less than 3.6 (2.7, 3.4, 3.5).

3.1.7
Expand Down
32 changes: 32 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[mypy]
show_column_numbers=True
pretty=True

disallow_any_unimported=True
# _bcrypt usage will result in any exprs
disallow_any_expr=False
disallow_any_decorated=True
disallow_any_explicit=True
disallow_any_generics=True
disallow_subclassing_any=True

disallow_untyped_calls=True
disallow_untyped_defs=True
disallow_incomplete_defs=True
check_untyped_defs=True
disallow_untyped_decorators=True

no_implicit_optional=True
strict_optional=True

warn_redundant_casts=True
warn_unused_ignores=True
warn_no_return=True
# _bcrypt is untyped so all calls involving it will be Any
warn_return_any=False
# keep backwards compatibility for users not using static type checking
warn_unreachable=False

strict_equality=True

ignore_missing_imports=False
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,11 @@ def run_tests(self):
author_email=__about__["__email__"],
python_requires=">=3.6",
install_requires=[CFFI_DEPENDENCY, SIX_DEPENDENCY],
extras_require={"tests": ["pytest>=3.2.1,!=3.3.0"]},
extras_require={"tests": ["pytest>=3.2.1,!=3.3.0"], "typecheck": ["mypy"]},
tests_require=["pytest>=3.2.1,!=3.3.0"],
package_dir={"": "src"},
packages=["bcrypt"],
package_data={"bcrypt": ["py.typed"]},
zip_safe=False,
classifiers=[
"Development Status :: 5 - Production/Stable",
Expand Down
18 changes: 12 additions & 6 deletions src/bcrypt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import six

from . import _bcrypt
from . import _bcrypt # type: ignore
from .__about__ import (
__author__,
__copyright__,
Expand Down Expand Up @@ -54,7 +54,7 @@
_normalize_re = re.compile(br"^\$2y\$")


def gensalt(rounds=12, prefix=b"2b"):
def gensalt(rounds: int = 12, prefix: bytes = b"2b") -> bytes:
if prefix not in (b"2a", b"2b"):
raise ValueError("Supported prefixes are b'2a' or b'2b'")

Expand All @@ -75,7 +75,7 @@ def gensalt(rounds=12, prefix=b"2b"):
)


def hashpw(password, salt):
def hashpw(password: bytes, salt: bytes) -> bytes:
if isinstance(password, six.text_type) or isinstance(salt, six.text_type):
raise TypeError("Unicode-objects must be encoded before hashing")

Expand Down Expand Up @@ -113,7 +113,7 @@ def hashpw(password, salt):
return original_salt[:4] + _bcrypt.ffi.string(hashed)[4:]


def checkpw(password, hashed_password):
def checkpw(password: bytes, hashed_password: bytes) -> bool:
if isinstance(password, six.text_type) or isinstance(
hashed_password, six.text_type
):
Expand All @@ -132,7 +132,13 @@ def checkpw(password, hashed_password):
return _bcrypt.lib.timingsafe_bcmp(ret, hashed_password, len(ret)) == 0


def kdf(password, salt, desired_key_bytes, rounds, ignore_few_rounds=False):
def kdf(
password: bytes,
salt: bytes,
desired_key_bytes: int,
rounds: int,
ignore_few_rounds: bool = False,
) -> bytes:
if isinstance(password, six.text_type) or isinstance(salt, six.text_type):
raise TypeError("Unicode-objects must be encoded before hashing")

Expand Down Expand Up @@ -167,6 +173,6 @@ def kdf(password, salt, desired_key_bytes, rounds, ignore_few_rounds=False):
return _bcrypt.ffi.buffer(key, desired_key_bytes)[:]


def _bcrypt_assert(ok):
def _bcrypt_assert(ok: bool) -> None:
if not ok:
raise SystemError("bcrypt assertion failed")
Empty file added src/bcrypt/py.typed
Empty file.
8 changes: 7 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = pypy3,py36,py37,py38,pep8,packaging
envlist = pypy3,py36,py37,py38,pep8,packaging,mypy
isolated_build = True

[testenv]
Expand All @@ -21,6 +21,12 @@ commands =
flake8 .
black --check .

[testenv:mypy]
deps =
mypy
commands =
mypy src/bcrypt

[testenv:packaging]
deps =
check-manifest
Expand Down

0 comments on commit f9066e2

Please sign in to comment.