use jsonschema regex pattern for whitelist format and enhance validation error messages (closes #120)

This commit is contained in:
gcarq 2017-11-20 19:37:25 +01:00
parent d88cc084e6
commit cd5afd6ff4
2 changed files with 44 additions and 6 deletions

View File

@ -6,7 +6,8 @@ import os
import time
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 freqtrade import __version__
@ -58,8 +59,14 @@ def load_config(path: str) -> Dict:
if 'internals' not in conf:
conf['internals'] = {}
logger.info('Validating configuration ...')
try:
validate(conf, CONF_SCHEMA)
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:
@ -218,7 +225,10 @@ CONF_SCHEMA = {
'secret': {'type': 'string'},
'pair_whitelist': {
'type': 'array',
'items': {'type': 'string'},
'items': {
'type': 'string',
'pattern': '^[0-9A-Z]+_[0-9A-Z]+$'
},
'uniqueItems': True
}
},

View File

@ -1,12 +1,15 @@
# pragma pylint: disable=missing-docstring,C0103
import time
import json
import os
import time
from argparse import Namespace
from copy import deepcopy
from unittest.mock import MagicMock
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():
@ -119,3 +122,28 @@ def test_start_backtesting(mocker):
main_call_args = pytest_mock.call_args[0][0]
assert main_call_args[0] == '-s'
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')