add: type hints to top level functions (#218)
* 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 https://github.com/pyca/bcrypt/issues/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
This commit is contained in:
parent
f3c255ca15
commit
f9066e2be5
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
32
mypy.ini
Normal file
32
mypy.ini
Normal file
@ -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
setup.py
3
setup.py
@ -208,10 +208,11 @@ setup(
|
||||
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",
|
||||
|
||||
@ -22,7 +22,7 @@ import warnings
|
||||
|
||||
import six
|
||||
|
||||
from . import _bcrypt
|
||||
from . import _bcrypt # type: ignore
|
||||
from .__about__ import (
|
||||
__author__,
|
||||
__copyright__,
|
||||
@ -54,7 +54,7 @@ __all__ = [
|
||||
_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'")
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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
|
||||
):
|
||||
@ -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")
|
||||
|
||||
@ -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")
|
||||
|
||||
0
src/bcrypt/py.typed
Normal file
0
src/bcrypt/py.typed
Normal file
8
tox.ini
8
tox.ini
@ -1,5 +1,5 @@
|
||||
[tox]
|
||||
envlist = pypy3,py36,py37,py38,pep8,packaging
|
||||
envlist = pypy3,py36,py37,py38,pep8,packaging,mypy
|
||||
isolated_build = True
|
||||
|
||||
[testenv]
|
||||
@ -21,6 +21,12 @@ commands =
|
||||
flake8 .
|
||||
black --check .
|
||||
|
||||
[testenv:mypy]
|
||||
deps =
|
||||
mypy
|
||||
commands =
|
||||
mypy src/bcrypt
|
||||
|
||||
[testenv:packaging]
|
||||
deps =
|
||||
check-manifest
|
||||
|
||||
Loading…
Reference in New Issue
Block a user