Skip to content

Commit

Permalink
Update the hashlib brain hash.digest & hash.hexdigest met…
Browse files Browse the repository at this point in the history
…hods. (#1827)

* Add the ``length`` parameter to ``hash.digest`` & ``hash.hexdigest`` in the ``hashlib`` brain.

* Move content in Changelog to a different section.

Refs pylint-dev/pylint#4039
  • Loading branch information
mbyrnepr2 authored and Pierre-Sassoulas committed Oct 19, 2022
1 parent db46a70 commit fccbc97
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 38 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Expand Up @@ -20,6 +20,10 @@ What's New in astroid 2.12.12?
==============================
Release date: TBA

* Add the ``length`` parameter to ``hash.digest`` & ``hash.hexdigest`` in the ``hashlib`` brain.

Refs PyCQA/pylint#4039



What's New in astroid 2.12.11?
Expand Down
104 changes: 71 additions & 33 deletions astroid/brain/brain_hashlib.py
Expand Up @@ -10,48 +10,86 @@

def _hashlib_transform():
maybe_usedforsecurity = ", usedforsecurity=True" if PY39_PLUS else ""
signature = f"value=''{maybe_usedforsecurity}"
init_signature = f"value=''{maybe_usedforsecurity}"
digest_signature = "self"
shake_digest_signature = "self, length"

template = """
class %(name)s(object):
def __init__(self, %(signature)s): pass
def digest(self):
return %(digest)s
def copy(self):
return self
def update(self, value): pass
def hexdigest(self):
return ''
@property
def name(self):
return %(name)r
@property
def block_size(self):
return 1
@property
def digest_size(self):
return 1
class %(name)s:
def __init__(self, %(init_signature)s): pass
def digest(%(digest_signature)s):
return %(digest)s
def copy(self):
return self
def update(self, value): pass
def hexdigest(%(digest_signature)s):
return ''
@property
def name(self):
return %(name)r
@property
def block_size(self):
return 1
@property
def digest_size(self):
return 1
"""

algorithms_with_signature = dict.fromkeys(
["md5", "sha1", "sha224", "sha256", "sha384", "sha512"], signature
[
"md5",
"sha1",
"sha224",
"sha256",
"sha384",
"sha512",
"sha3_224",
"sha3_256",
"sha3_384",
"sha3_512",
],
(init_signature, digest_signature),
)

blake2b_signature = (
"data=b'', *, digest_size=64, key=b'', salt=b'', "
"person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, "
f"node_depth=0, inner_size=0, last_node=False{maybe_usedforsecurity}"
)

blake2s_signature = (
"data=b'', *, digest_size=32, key=b'', salt=b'', "
"person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, "
f"node_depth=0, inner_size=0, last_node=False{maybe_usedforsecurity}"
)
blake2b_signature = f"data=b'', *, digest_size=64, key=b'', salt=b'', \
person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \
node_depth=0, inner_size=0, last_node=False{maybe_usedforsecurity}"
blake2s_signature = f"data=b'', *, digest_size=32, key=b'', salt=b'', \
person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \
node_depth=0, inner_size=0, last_node=False{maybe_usedforsecurity}"
new_algorithms = dict.fromkeys(
["sha3_224", "sha3_256", "sha3_384", "sha3_512", "shake_128", "shake_256"],
signature,

shake_algorithms = dict.fromkeys(
["shake_128", "shake_256"],
(init_signature, shake_digest_signature),
)
algorithms_with_signature.update(new_algorithms)
algorithms_with_signature.update(shake_algorithms)

algorithms_with_signature.update(
{"blake2b": blake2b_signature, "blake2s": blake2s_signature}
{
"blake2b": (blake2b_signature, digest_signature),
"blake2s": (blake2s_signature, digest_signature),
}
)

classes = "".join(
template % {"name": hashfunc, "digest": 'b""', "signature": signature}
for hashfunc, signature in algorithms_with_signature.items()
template
% {
"name": hashfunc,
"digest": 'b""',
"init_signature": init_signature,
"digest_signature": digest_signature,
}
for hashfunc, (
init_signature,
digest_signature,
) in algorithms_with_signature.items()
)

return parse(classes)


Expand Down
30 changes: 25 additions & 5 deletions tests/unittest_brain.py
Expand Up @@ -83,24 +83,44 @@ def _assert_hashlib_class(self, class_obj: ClassDef) -> None:
len(class_obj["__init__"].args.defaults), 2 if PY39_PLUS else 1
)
self.assertEqual(len(class_obj["update"].args.args), 2)
self.assertEqual(len(class_obj["digest"].args.args), 1)
self.assertEqual(len(class_obj["hexdigest"].args.args), 1)

def test_hashlib(self) -> None:
"""Tests that brain extensions for hashlib work."""
hashlib_module = MANAGER.ast_from_module_name("hashlib")
for class_name in ("md5", "sha1"):
for class_name in (
"md5",
"sha1",
"sha224",
"sha256",
"sha384",
"sha512",
"sha3_224",
"sha3_256",
"sha3_384",
"sha3_512",
):
class_obj = hashlib_module[class_name]
self._assert_hashlib_class(class_obj)
self.assertEqual(len(class_obj["digest"].args.args), 1)
self.assertEqual(len(class_obj["hexdigest"].args.args), 1)

def test_hashlib_py36(self) -> None:
def test_shake(self) -> None:
"""Tests that the brain extensions for the hashlib shake algorithms work."""
hashlib_module = MANAGER.ast_from_module_name("hashlib")
for class_name in ("sha3_224", "sha3_512", "shake_128"):
for class_name in ("shake_128", "shake_256"):
class_obj = hashlib_module[class_name]
self._assert_hashlib_class(class_obj)
self.assertEqual(len(class_obj["digest"].args.args), 2)
self.assertEqual(len(class_obj["hexdigest"].args.args), 2)

def test_blake2(self) -> None:
"""Tests that the brain extensions for the hashlib blake2 hash functions work."""
hashlib_module = MANAGER.ast_from_module_name("hashlib")
for class_name in ("blake2b", "blake2s"):
class_obj = hashlib_module[class_name]
self.assertEqual(len(class_obj["__init__"].args.args), 2)
self.assertEqual(len(class_obj["digest"].args.args), 1)
self.assertEqual(len(class_obj["hexdigest"].args.args), 1)


class CollectionsDequeTests(unittest.TestCase):
Expand Down

0 comments on commit fccbc97

Please sign in to comment.