diff --git a/simplekv/crypt.py b/simplekv/crypt.py index 3a2a9cc4..60df6208 100644 --- a/simplekv/crypt.py +++ b/simplekv/crypt.py @@ -21,8 +21,8 @@ def __init__(self, hm, source): '(too small)') def read(self, n=None): - if '' == self.buffer or 0 == n: - return '' + if b'' == self.buffer or 0 == n: + return b'' new_read = self.source.read(n) if n is not None else self.source.read() finished = (n is None or len(new_read) != n) @@ -94,11 +94,6 @@ def __init__(self, secret_key, decorated_store, hashfunc=hashlib.sha256): self.__hashfunc = hashfunc self.__secret_key = bytes(secret_key) - @property - def hmac_digestsize(self): - # returns, in bytes, the size of the digest - return self.hmac_mixin_hashfunc().digestsize - def __new_hmac(self, key, msg=None): if not msg: msg = b'' @@ -130,7 +125,7 @@ def get_file(self, key, file): if isinstance(file, str): try: f = open(file, 'wb') - except OSError as e: + except (OSError, IOError) as e: raise IOError('Error opening %s for writing: %r' % ( file, e )) diff --git a/tests/test_hmac.py b/tests/test_hmac.py index 9ace6c19..a26fa922 100644 --- a/tests/test_hmac.py +++ b/tests/test_hmac.py @@ -39,10 +39,27 @@ def create_reader(self, stored_blob, secret_key, hashfunc): def chunk_sizes(self, value): return [10 ** n for n in xrange(2, 8)] + def test_close(self, create_reader): + reader = create_reader() + assert not reader.source.closed + reader.close() + assert reader.source.closed + + def test_close_via_context(self, create_reader): + reader = create_reader() + assert not reader.source.closed + with reader as r: + assert r is reader + assert reader.source.closed + def test_reading_limit_0(self, create_reader): reader = create_reader() - assert reader.read(0) == '' - assert reader.read(0) == '' + data = reader.read(0) + assert isinstance(data, bytes) + assert len(data) == 0 + data = reader.read(0) + assert isinstance(data, bytes) + assert len(data) == 0 def test_reading_with_limit(self, secret_key, hashfunc, value, create_reader, chunk_sizes): @@ -100,6 +117,7 @@ def test_unbounded_read(self, value, create_reader): # this only works with dicts, as we access the internal structures to # manipulate values class HMACDec(object): + @pytest.fixture def hmacstore(self, secret_key, store): return HMACDecorator(secret_key, store) @@ -111,6 +129,32 @@ def test_get_fails_on_manipulation(self, hmacstore, key, value): with pytest.raises(VerificationException): hmacstore.get(key) + def test_copy_raises_not_implemented(self, store): + with pytest.raises(NotImplementedError): + HMACDecorator(b'secret', store).copy(u'src', u'dest') + + def test_put_file_obj(self, key, value, hmacstore): + hmacstore.put_file(key, BytesIO(value)) + assert hmacstore.get(key) == value + + def test_put_file_str(self, key, value, hmacstore): + with tempfile.NamedTemporaryFile(mode='wb', delete=False) as f: + f.write(value) + hmacstore.put_file(key, f.name) + assert hmacstore.get(key) == value + + def test_get_file_obj(self, key, value, hmacstore): + hmacstore.put(key, value) + b = BytesIO() + hmacstore.get_file(key, b) + assert b.getvalue() == value + + def test_get_file_non_writable_target(self, key, value, hmacstore): + hmacstore.put(key, value) + path = '/tmp/this/file/does/not/exist' + with pytest.raises(IOError, match='Error opening {} for writing'.format(path)): + hmacstore.get_file(key, path) + def test_get_file_fails_on_manipulation(self, hmacstore, key, value): hmacstore.put(key, value) hmacstore.d[key] += b('a')