From 10efac5378f8b4a132fc57769a6d1456e9a5a3d4 Mon Sep 17 00:00:00 2001 From: xymy Date: Mon, 16 Mar 2020 13:56:07 +0800 Subject: [PATCH] Fix classmethod hash_dir --- xycrypto/hashes.py | 27 ++++++++++++++++----------- xycrypto/hmac.py | 24 +++++++++++++----------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/xycrypto/hashes.py b/xycrypto/hashes.py index 484f576..81bd37c 100644 --- a/xycrypto/hashes.py +++ b/xycrypto/hashes.py @@ -1,7 +1,6 @@ import abc import functools import hashlib -import itertools import os __all__ = [ @@ -86,18 +85,24 @@ def hash_file(cls, filepath, **kwargs): def hash_dir(cls, dirpath, **kwargs): """Return hash of data from directory.""" - with os.scandir(dirpath) as it: - result = itertools.repeat(0) - for entry in it: - if entry.is_dir(): - value = cls.hash_dir(entry, **kwargs) - else: - value = cls.hash_file(entry, **kwargs) - result = bytes(x ^ y for x, y in zip(result, value)) - if not isinstance(result, bytes): - raise RuntimeError('empty directory') + try: + digest_size = getattr(cls, 'digest_size') + except AttributeError: + digest_size = getattr(cls(**kwargs), 'digest_size') + + def _hash_dir(cls, dirpath, **kwargs): + result = b'\x00' * digest_size + with os.scandir(dirpath) as it: + for entry in it: + if entry.is_dir(): + value = cls.hash_dir(entry, **kwargs) + else: + value = cls.hash_file(entry, **kwargs) + result = bytes(x ^ y for x, y in zip(result, value)) return result + return _hash_dir(cls, dirpath, **kwargs) + @classmethod def hash_fs(cls, path, **kwargs): """Return hash of data from filesystems.""" diff --git a/xycrypto/hmac.py b/xycrypto/hmac.py index ad9b9dc..d6020f2 100644 --- a/xycrypto/hmac.py +++ b/xycrypto/hmac.py @@ -1,5 +1,4 @@ import functools -import itertools import os from hmac import compare_digest @@ -102,18 +101,21 @@ def hash_file(cls, hash_cls, key, filepath, **kwargs): def hash_dir(cls, hash_cls, key, dirpath, **kwargs): """Return hash of data from directory.""" - with os.scandir(dirpath) as it: - result = itertools.repeat(0) - for entry in it: - if entry.is_dir(): - value = cls.hash_dir(hash_cls, key, entry, **kwargs) - else: - value = cls.hash_file(hash_cls, key, entry, **kwargs) - result = bytes(x ^ y for x, y in zip(result, value)) - if not isinstance(result, bytes): - raise RuntimeError('empty directory') + digest_size = getattr(cls(hash_cls, key, **kwargs), 'digest_size') + + def _hash_dir(cls, hash_cls, key, dirpath, **kwargs): + result = b'\x00' * digest_size + with os.scandir(dirpath) as it: + for entry in it: + if entry.is_dir(): + value = cls.hash_dir(hash_cls, key, entry, **kwargs) + else: + value = cls.hash_file(hash_cls, key, entry, **kwargs) + result = bytes(x ^ y for x, y in zip(result, value)) return result + return _hash_dir(cls, hash_cls, key, dirpath, **kwargs) + @classmethod def hash_fs(cls, hash_cls, key, path, **kwargs): """Return hash of data from filesystems."""