Introduce equivalence classes for gas speed names

pull/2445/head
David Núñez 2020-11-18 22:57:04 +01:00
parent 1b5de0a266
commit 71ad8c2c31
2 changed files with 64 additions and 3 deletions

View File

@ -14,12 +14,14 @@
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from abc import ABC, abstractmethod
from difflib import get_close_matches
from typing import Optional
import requests
from constant_sorrow.constants import SLOW, MEDIUM, FAST, FASTEST
from web3 import Web3
from web3.gas_strategies.rpc import rpc_gas_price_strategy
from web3.types import Wei, TxParams
@ -54,6 +56,13 @@ class EthereumGasPriceDatafeed(Datafeed):
_speed_names = NotImplemented
_default_speed = NotImplemented
_speed_equivalence_classes = {
SLOW: ('slow', 'safeLow', 'low'),
MEDIUM: ('medium', 'standard', 'average'),
FAST: ('fast', 'high'),
FASTEST: ('fastest', )
}
@abstractmethod
def _parse_gas_prices(self):
return NotImplementedError
@ -72,6 +81,22 @@ class EthereumGasPriceDatafeed(Datafeed):
return gas_price
return gas_price_strategy
@classmethod
def get_canonical_speed(cls, speed: str):
for canonical_speed, speed_names in cls._speed_equivalence_classes.items():
if speed.lower() in map(str.lower, speed_names):
return canonical_speed
else:
all_speed_names = [name for names in cls._speed_equivalence_classes.values() for name in names]
suggestion = get_close_matches(speed, all_speed_names, n=1)
if not suggestion:
message = f"'{speed}' is not a valid speed name."
else:
suggestion = suggestion.pop()
message = f"'{speed}' is not a valid speed name. Did you mean '{suggestion}'?"
raise LookupError(message)
class EtherchainGasPriceDatafeed(EthereumGasPriceDatafeed):
"""Gas price datafeed from Etherchain"""

View File

@ -18,14 +18,15 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
from unittest.mock import patch
import pytest
from constant_sorrow.constants import SLOW, MEDIUM, FAST, FASTEST
from requests.exceptions import ConnectionError
from web3 import Web3
from nucypher.utilities.datafeeds import (
EtherchainGasPriceDatafeed,
Datafeed,
UpvestGasPriceDatafeed
)
UpvestGasPriceDatafeed,
EthereumGasPriceDatafeed)
from nucypher.utilities.gas_strategies import datafeed_fallback_gas_price_strategy
etherchain_json = {
@ -76,6 +77,41 @@ def test_probe_datafeed(mocker):
assert feed._raw_data == json
def test_canonical_speed_names():
# Valid speed names, grouped in equivalence classes
speed_equivalence_classes = {
SLOW: ('slow', 'SLOW', 'Slow',
'safeLow', 'safelow', 'SafeLow', 'SAFELOW',
'low', 'LOW', 'Low'),
MEDIUM: ('medium', 'MEDIUM', 'Medium',
'standard', 'STANDARD', 'Standard',
'average', 'AVERAGE', 'Average'),
FAST: ('fast', 'FAST', 'Fast',
'high', 'HIGH', 'High'),
FASTEST: ('fastest', 'FASTEST', 'Fastest')
}
for canonical_speed, equivalence_class in speed_equivalence_classes.items():
for speed_name in equivalence_class:
assert canonical_speed == EthereumGasPriceDatafeed.get_canonical_speed(speed_name)
# Invalid speed names, but that are somewhat similar to a valid one so we can give a suggestion
similarities = (
('hihg', 'high'),
('zlow', 'low'),
)
for wrong_name, suggestion in similarities:
message = f"'{wrong_name}' is not a valid speed name. Did you mean '{suggestion}'?"
with pytest.raises(LookupError, match=message):
EthereumGasPriceDatafeed.get_canonical_speed(wrong_name)
# Utterly wrong speed names. Shame on you.
wrong_name = "🙈"
with pytest.raises(LookupError, match=f"'{wrong_name}' is not a valid speed name."):
EthereumGasPriceDatafeed.get_canonical_speed(wrong_name)
def test_etherchain():
feed = EtherchainGasPriceDatafeed()