use jsonschema regex pattern for whitelist format and enhance validation error messages (closes #120)
This commit is contained in:
parent
d88cc084e6
commit
cd5afd6ff4
@ -6,7 +6,8 @@ import os
|
|||||||
import time
|
import time
|
||||||
from typing import Any, Callable, List, Dict
|
from typing import Any, Callable, List, Dict
|
||||||
|
|
||||||
from jsonschema import validate
|
from jsonschema import validate, Draft4Validator
|
||||||
|
from jsonschema.exceptions import best_match, ValidationError
|
||||||
from wrapt import synchronized
|
from wrapt import synchronized
|
||||||
|
|
||||||
from freqtrade import __version__
|
from freqtrade import __version__
|
||||||
@ -58,8 +59,14 @@ def load_config(path: str) -> Dict:
|
|||||||
if 'internals' not in conf:
|
if 'internals' not in conf:
|
||||||
conf['internals'] = {}
|
conf['internals'] = {}
|
||||||
logger.info('Validating configuration ...')
|
logger.info('Validating configuration ...')
|
||||||
|
try:
|
||||||
validate(conf, CONF_SCHEMA)
|
validate(conf, CONF_SCHEMA)
|
||||||
return conf
|
return conf
|
||||||
|
except ValidationError:
|
||||||
|
logger.fatal('Configuration is not valid! See config.json.example')
|
||||||
|
raise ValidationError(
|
||||||
|
best_match(Draft4Validator(CONF_SCHEMA).iter_errors(conf)).message
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def throttle(func: Callable[..., Any], min_secs: float, *args, **kwargs) -> Any:
|
def throttle(func: Callable[..., Any], min_secs: float, *args, **kwargs) -> Any:
|
||||||
@ -218,7 +225,10 @@ CONF_SCHEMA = {
|
|||||||
'secret': {'type': 'string'},
|
'secret': {'type': 'string'},
|
||||||
'pair_whitelist': {
|
'pair_whitelist': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'items': {'type': 'string'},
|
'items': {
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[0-9A-Z]+_[0-9A-Z]+$'
|
||||||
|
},
|
||||||
'uniqueItems': True
|
'uniqueItems': True
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
# pragma pylint: disable=missing-docstring,C0103
|
# pragma pylint: disable=missing-docstring,C0103
|
||||||
import time
|
import json
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
|
from copy import deepcopy
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from jsonschema import ValidationError
|
||||||
|
|
||||||
from freqtrade.misc import throttle, parse_args, start_backtesting
|
from freqtrade.misc import throttle, parse_args, start_backtesting, load_config
|
||||||
|
|
||||||
|
|
||||||
def test_throttle():
|
def test_throttle():
|
||||||
@ -119,3 +122,28 @@ def test_start_backtesting(mocker):
|
|||||||
main_call_args = pytest_mock.call_args[0][0]
|
main_call_args = pytest_mock.call_args[0][0]
|
||||||
assert main_call_args[0] == '-s'
|
assert main_call_args[0] == '-s'
|
||||||
assert main_call_args[1].endswith(os.path.join('freqtrade', 'tests', 'test_backtesting.py'))
|
assert main_call_args[1].endswith(os.path.join('freqtrade', 'tests', 'test_backtesting.py'))
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_config(default_conf, mocker):
|
||||||
|
file_mock = mocker.patch('freqtrade.misc.open', mocker.mock_open(
|
||||||
|
read_data=json.dumps(default_conf)
|
||||||
|
))
|
||||||
|
validated_conf = load_config('somefile')
|
||||||
|
assert file_mock.call_count == 1
|
||||||
|
assert validated_conf.items() >= default_conf.items()
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_config_invalid_pair(default_conf, mocker):
|
||||||
|
conf = deepcopy(default_conf)
|
||||||
|
conf['exchange']['pair_whitelist'].append('BTC-ETH')
|
||||||
|
mocker.patch('freqtrade.misc.open', mocker.mock_open(read_data=json.dumps(conf)))
|
||||||
|
with pytest.raises(ValidationError, match=r'.*does not match.*'):
|
||||||
|
load_config('somefile')
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_config_missing_attributes(default_conf, mocker):
|
||||||
|
conf = deepcopy(default_conf)
|
||||||
|
conf.pop('exchange')
|
||||||
|
mocker.patch('freqtrade.misc.open', mocker.mock_open(read_data=json.dumps(conf)))
|
||||||
|
with pytest.raises(ValidationError, match=r'.*\'exchange\' is a required property.*'):
|
||||||
|
load_config('somefile')
|
||||||
|
Loading…
Reference in New Issue
Block a user