Skip to content

Commit

Permalink
Raise error if error flag is not an accepted value
Browse files Browse the repository at this point in the history
  • Loading branch information
kclowes committed Jun 21, 2019
1 parent 684e61d commit 615cbad
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 46 deletions.
6 changes: 3 additions & 3 deletions docs/contracts.rst
Expand Up @@ -742,14 +742,14 @@ For example:

.. code-block:: python
>>> from web3._utils.events import EventLogErrorFlags
>>> from web3._utils.events import STRICT, IGNORE, DISCARD, WARN
>>> tx_hash = contract.functions.myFunction(12345).transact({'to':contract_address})
>>> tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
>>> returned_logs = contract.events.myEvent().processReceipt(tx_receipt, errors=EventLogErrorFlags.ignore)
>>> returned_logs = contract.events.myEvent().processReceipt(tx_receipt, errors=IGNORE)
>>> assert returned_logs[0] == tx_receipt['logs'][0]
True
>>> returned_logs = contract.events.myEvent().processReceipt(tx_receipt, errors=EventLogErrorFlags.discard)
>>> returned_logs = contract.events.myEvent().processReceipt(tx_receipt, errors=DISCARD)
>>> assert returned_logs == ()
True
Expand Down
60 changes: 23 additions & 37 deletions tests/core/contracts/test_extracting_event_data.py
Expand Up @@ -5,9 +5,11 @@
)

from web3._utils.events import (
EventLogErrorFlags,
DISCARD,
IGNORE,
STRICT,
WARN,
get_event_data,
)

Expand Down Expand Up @@ -271,46 +273,21 @@ def test_event_rich_log(


@pytest.mark.parametrize(
'errors',
'error_flag',
(
(DISCARD),
(IGNORE),
(STRICT),
(),
)
)
def test_event_processing_with_strict_error_flag(
web3,
event_contract,
indexed_event_contract,
wait_for_transaction,
errors):

txn_hash = indexed_event_contract.functions.logTwoEvents(12345).transact()
wait_for_transaction(web3, txn_hash)

event_instance = indexed_event_contract.events.LogSingleWithIndex()

event_contract_fn = event_contract.functions.logTwoEvents
dup_txn_hash = event_contract_fn(12345).transact()
dup_txn_receipt = wait_for_transaction(web3, dup_txn_hash)

with pytest.raises(ValueError, match="Expected 1 log topics. Got 0"):
event_instance.processReceipt(dup_txn_receipt, errors=errors)


@pytest.mark.parametrize(
'errors,rich_log_length',
(
(DISCARD, 0),
(IGNORE, 1),
(WARN),
('something_else'),
)
)
def test_event_processing_with_caught_errors(
web3,
event_contract,
indexed_event_contract,
wait_for_transaction,
errors,
rich_log_length):
error_flag):

emitter_fn = indexed_event_contract.functions.logTwoEvents

Expand All @@ -323,18 +300,27 @@ def test_event_processing_with_caught_errors(

event_instance = indexed_event_contract.events.LogSingleWithIndex()

returned_logs = event_instance.processReceipt(dup_txn_receipt, errors=errors)

assert len(returned_logs) == rich_log_length

if len(returned_logs) == 0:
if error_flag is DISCARD:
returned_logs = event_instance.processReceipt(dup_txn_receipt, errors=error_flag)
assert returned_logs == ()
elif len(returned_logs) == 1:
elif error_flag is IGNORE:
returned_logs = event_instance.processReceipt(dup_txn_receipt, errors=error_flag)
assert len(returned_logs) == 1
returned_log = dict(returned_logs[0])

assert repr(returned_log['errors']) == "ValueError('Expected 1 log topics. Got 0')"
del returned_log['errors']
assert returned_log == dup_txn_receipt['logs'][0]
assert is_same_address(returned_log['address'], event_contract.address)
elif error_flag is WARN:
with pytest.warns(UserWarning, match="Expected 1 log topics. Got 0"):
returned_log = event_instance.processReceipt(dup_txn_receipt, errors=error_flag)
assert len(returned_log) == 0
elif error_flag is STRICT:
with pytest.raises(ValueError, match="Expected 1 log topics. Got 0"):
event_instance.processReceipt(dup_txn_receipt, errors=error_flag)
elif error_flag is 'something_else':
with pytest.raises(AttributeError, match="Error flag must be one of:"):
returned_log = event_instance.processReceipt(dup_txn_receipt, errors=error_flag)
else:
raise Exception('Unreachable!')
14 changes: 8 additions & 6 deletions web3/_utils/events.py
Expand Up @@ -450,11 +450,13 @@ def _encode(self, value):


class EventLogErrorFlags(Enum):
STRICT = 'strict'
IGNORE = 'ignore'
DISCARD = 'discard'
Discard = 'discard'
Ignore = 'ignore'
Strict = 'strict'
Warn = 'warn'


STRICT = EventLogErrorFlags.STRICT
IGNORE = EventLogErrorFlags.IGNORE
DISCARD = EventLogErrorFlags.DISCARD
DISCARD = EventLogErrorFlags.Discard
IGNORE = EventLogErrorFlags.Ignore
STRICT = EventLogErrorFlags.Strict
WARN = EventLogErrorFlags.Warn
19 changes: 19 additions & 0 deletions web3/contract.py
Expand Up @@ -3,6 +3,7 @@
"""
import copy
import itertools
import warnings

from eth_abi import (
decode_abi,
Expand Down Expand Up @@ -65,6 +66,8 @@
DISCARD,
IGNORE,
STRICT,
WARN,
EventLogErrorFlags,
EventFilterBuilder,
get_event_data,
is_dynamic_sized_type,
Expand Down Expand Up @@ -991,8 +994,17 @@ def _get_event_abi(cls):

@combomethod
def processReceipt(self, txn_receipt, errors=STRICT):
self.check_for_valid_error_flag(errors)
return self._parse_logs(txn_receipt, errors)

def check_for_valid_error_flag(self, errors):
keys = [key.upper() for key in EventLogErrorFlags.__members__.keys()]
try:
errors.name
except AttributeError:
raise AttributeError(f'Error flag must be one of: {keys}')


@to_tuple
def _parse_logs(self, txn_receipt, errors):
for log in txn_receipt['logs']:
Expand All @@ -1007,6 +1019,13 @@ def _parse_logs(self, txn_receipt, errors):
new_log = MutableAttributeDict(log)
new_log["errors"] = e
rich_log = AttributeDict(new_log)
elif errors == WARN:
warnings.warn(
f"The log with transaction hash: {log.transactionHash} and \
logIndex: {log.logIndex} encountered the following \
error during processing: {e}. It has been discarded"
)
continue
else:
raise e
yield rich_log
Expand Down

0 comments on commit 615cbad

Please sign in to comment.