Merge pull request #3097 from freqtrade/parse_config_error
Improve config parse error handling
This commit is contained in:
commit
65f19fde40
@ -1,13 +1,15 @@
|
||||
"""
|
||||
This module contain functions to load the configuration file
|
||||
"""
|
||||
import rapidjson
|
||||
import logging
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
||||
from freqtrade.exceptions import OperationalException
|
||||
import rapidjson
|
||||
|
||||
from freqtrade.exceptions import OperationalException
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -15,6 +17,26 @@ logger = logging.getLogger(__name__)
|
||||
CONFIG_PARSE_MODE = rapidjson.PM_COMMENTS | rapidjson.PM_TRAILING_COMMAS
|
||||
|
||||
|
||||
def log_config_error_range(path: str, errmsg: str) -> str:
|
||||
"""
|
||||
Parses configuration file and prints range around error
|
||||
"""
|
||||
if path != '-':
|
||||
offsetlist = re.findall(r'(?<=Parse\serror\sat\soffset\s)\d+', errmsg)
|
||||
if offsetlist:
|
||||
offset = int(offsetlist[0])
|
||||
text = Path(path).read_text()
|
||||
# Fetch an offset of 80 characters around the error line
|
||||
subtext = text[offset-min(80, offset):offset+80]
|
||||
segments = subtext.split('\n')
|
||||
if len(segments) > 3:
|
||||
# Remove first and last lines, to avoid odd truncations
|
||||
return '\n'.join(segments[1:-1])
|
||||
else:
|
||||
return subtext
|
||||
return ''
|
||||
|
||||
|
||||
def load_config_file(path: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Loads a config file from the given path
|
||||
@ -29,5 +51,12 @@ def load_config_file(path: str) -> Dict[str, Any]:
|
||||
raise OperationalException(
|
||||
f'Config file "{path}" not found!'
|
||||
' Please create a config file or check whether it exists.')
|
||||
except rapidjson.JSONDecodeError as e:
|
||||
err_range = log_config_error_range(path, str(e))
|
||||
raise OperationalException(
|
||||
f'{e}\n'
|
||||
f'Please verify the following segment of your configuration:\n{err_range}'
|
||||
if err_range else 'Please verify your configuration file for syntax errors.'
|
||||
)
|
||||
|
||||
return config
|
||||
|
@ -18,7 +18,7 @@ from freqtrade.configuration.config_validation import validate_config_schema
|
||||
from freqtrade.configuration.deprecated_settings import (
|
||||
check_conflicting_settings, process_deprecated_setting,
|
||||
process_temporary_deprecated_settings)
|
||||
from freqtrade.configuration.load_config import load_config_file
|
||||
from freqtrade.configuration.load_config import load_config_file, log_config_error_range
|
||||
from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL
|
||||
from freqtrade.exceptions import OperationalException
|
||||
from freqtrade.loggers import _set_loggers, setup_logging
|
||||
@ -66,6 +66,30 @@ def test_load_config_file(default_conf, mocker, caplog) -> None:
|
||||
assert validated_conf.items() >= default_conf.items()
|
||||
|
||||
|
||||
def test_load_config_file_error(default_conf, mocker, caplog) -> None:
|
||||
del default_conf['user_data_dir']
|
||||
filedata = json.dumps(default_conf).replace(
|
||||
'"stake_amount": 0.001,', '"stake_amount": .001,')
|
||||
mocker.patch('freqtrade.configuration.load_config.open', mocker.mock_open(read_data=filedata))
|
||||
mocker.patch.object(Path, "read_text", MagicMock(return_value=filedata))
|
||||
|
||||
with pytest.raises(OperationalException, match=f".*Please verify the following segment.*"):
|
||||
load_config_file('somefile')
|
||||
|
||||
|
||||
def test_load_config_file_error_range(default_conf, mocker, caplog) -> None:
|
||||
del default_conf['user_data_dir']
|
||||
filedata = json.dumps(default_conf).replace(
|
||||
'"stake_amount": 0.001,', '"stake_amount": .001,')
|
||||
mocker.patch.object(Path, "read_text", MagicMock(return_value=filedata))
|
||||
|
||||
x = log_config_error_range('somefile', 'Parse error at offset 64: Invalid value.')
|
||||
assert isinstance(x, str)
|
||||
assert (x == '{"max_open_trades": 1, "stake_currency": "BTC", '
|
||||
'"stake_amount": .001, "fiat_display_currency": "USD", '
|
||||
'"ticker_interval": "5m", "dry_run": true, ')
|
||||
|
||||
|
||||
def test__args_to_config(caplog):
|
||||
|
||||
arg_list = ['trade', '--strategy-path', 'TestTest']
|
||||
|
Loading…
Reference in New Issue
Block a user