diff --git a/docs/changelog.rst b/docs/changelog.rst index a4dafddc..3e5f1d9e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -20,6 +20,12 @@ Changelog (``--repository-url``) or via an environment variable (``TWINE_REPOSITORY_URL``). + * Generate SHA256 digest for all packages by default. + + * :feature:`171` Generate Blake2b 256 digests for packages *if* ``pyblake2`` + is installed. Users can use ``python -m pip install twine[with-blake2]`` + to have ``pyblake2`` installed with Twine. + * :release:`1.7.4 <2016-07-09>` * Correct a packaging error. diff --git a/setup.cfg b/setup.cfg index a166dd06..e2da31c6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -14,3 +14,4 @@ requires-dist = pkginfo >= 1.0 setuptools >= 0.7.0 argparse; python_version == '2.6' + pyblake2; extra == 'with-blake2' diff --git a/setup.py b/setup.py index 8581c7d2..b1df32c5 100644 --- a/setup.py +++ b/setup.py @@ -79,4 +79,9 @@ }, install_requires=install_requires, + extras_require={ + 'with-blake2': [ + 'pyblake2', + ] + }, ) diff --git a/twine/package.py b/twine/package.py index 34651439..a68249ab 100644 --- a/twine/package.py +++ b/twine/package.py @@ -20,6 +20,11 @@ import pkginfo import pkg_resources +try: + import pyblake2 +except ImportError: + pyblake2 = None + from twine.wheel import Wheel from twine.wininst import WinInst @@ -53,15 +58,24 @@ def __init__(self, filename, comment, metadata, python_version, filetype): self.signed_basefilename = self.basefilename + '.asc' self.gpg_signature = None + blake2_256_hash = None + if pyblake2 is not None: + blake2_256_hash = pyblake2.blake2b(digest_size=256 // 8) + # NOTE(sigmavirus24): We may or may not be able to use blake2 so let's + # either use the methods or lambdas to do nothing. + blake_update = getattr(blake2_256_hash, 'update', lambda *args: None) + blake_hexdigest = getattr(blake2_256_hash, 'hexdigest', lambda: None) md5_hash = hashlib.md5() sha2_hash = hashlib.sha256() with open(filename, "rb") as fp: for content in iter(lambda: fp.read(io.DEFAULT_BUFFER_SIZE), b''): md5_hash.update(content) sha2_hash.update(content) + blake_update(content) self.md5_digest = md5_hash.hexdigest() self.sha2_digest = sha2_hash.hexdigest() + self.blake2_256_digest = blake_hexdigest() @classmethod def from_filename(cls, filename, comment): @@ -117,6 +131,7 @@ def metadata_dictionary(self): "comment": self.comment, "md5_digest": self.md5_digest, "sha256_digest": self.sha256_digest, + "blake2_256_digest": self.blake2_256_digest, # PEP 314 "provides": meta.provides,