Skip to content

Commit

Permalink
Merge pull request #13 from carver/lazy-auto-backend
Browse files Browse the repository at this point in the history
Auto import with no backend is now supported
  • Loading branch information
carver committed Apr 2, 2018
2 parents 7452abb + 99d647e commit 300d528
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 9 deletions.
8 changes: 4 additions & 4 deletions eth_hash/auto.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from eth_hash.backends.auto import (
AutoBackend,
)
from eth_hash.main import (
Keccak256,
)
from eth_hash.utils import (
auto_choose_backend,
)

keccak = Keccak256(auto_choose_backend())
keccak = Keccak256(AutoBackend())
16 changes: 16 additions & 0 deletions eth_hash/backends/auto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from eth_hash.utils import (
auto_choose_backend,
)


class AutoBackend:
_backend = None

@property
def backend(self):
if self._backend is None:
self._backend = auto_choose_backend()
return self._backend

def __getattr__(self, attr):
return getattr(self.backend, attr)
21 changes: 18 additions & 3 deletions eth_hash/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,25 @@

class Keccak256:
def __init__(self, backend):
self.hasher = backend.keccak256
self.preimage = backend.preimage
self._backend = backend
self.hasher = self._hasher_first_run
self.preimage = self._preimage_first_run

assert self.hasher(b'') == b"\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';\x7b\xfa\xd8\x04]\x85\xa4p" # noqa: E501
def _hasher_first_run(self, preimage):
'''
Invoke the backend on-demand, and check an expected hash result,
then replace this first run with the new hasher method.
This is a bit of a hacky way to minimize overhead on hash calls after this first one.
'''
new_hasher = self._backend.keccak256
assert new_hasher(b'') == b"\xc5\xd2F\x01\x86\xf7#<\x92~}\xb2\xdc\xc7\x03\xc0\xe5\x00\xb6S\xca\x82';\x7b\xfa\xd8\x04]\x85\xa4p" # noqa: E501
self.hasher = new_hasher
return new_hasher(preimage)

def _preimage_first_run(self, data):
new_preimage = self._backend.preimage
self.preimage = new_preimage
return new_preimage(data)

def __call__(self, preimage: Union[bytes, bytearray]) -> bytes:
if not isinstance(preimage, (bytes, bytearray)):
Expand Down
16 changes: 14 additions & 2 deletions tests/core/test_import.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import pytest


def test_import_auto():
from eth_hash.auto import keccak # noqa: F401


def test_import_auto_empty_crash():
from eth_hash.auto import keccak
with pytest.raises(ImportError, match="None of these hashing backends are installed"):
keccak(b'')


def test_import():
import eth_hash # noqa: F401

Expand All @@ -13,9 +23,10 @@ def test_import():
],
)
def test_load_by_env(monkeypatch, backend):
from eth_hash.auto import keccak
monkeypatch.setenv('ETH_HASH_BACKEND', backend)
with pytest.raises(ImportError) as excinfo:
from eth_hash.auto import keccak # noqa: F401
keccak(b'triggered')
expected_msg = (
"The backend specified in ETH_HASH_BACKEND, '{0}', is not installed. "
"Install with `pip install eth-hash[{0}]`.".format(backend)
Expand All @@ -24,10 +35,11 @@ def test_load_by_env(monkeypatch, backend):


def test_load_unavailable_backend_by_env(monkeypatch):
from eth_hash.auto import keccak
backend = 'this-backend-will-never-exist'
monkeypatch.setenv('ETH_HASH_BACKEND', backend)
with pytest.raises(ValueError) as excinfo:
from eth_hash.auto import keccak # noqa: F401
keccak(b'triggered')
expected_msg = (
"The backend specified in ETH_HASH_BACKEND, '{0}', is not supported. "
"Choose one of".format(backend)
Expand Down

0 comments on commit 300d528

Please sign in to comment.