Copy templates when creating userdir

This commit is contained in:
Matthias 2019-11-01 13:28:35 +01:00
parent 258d4bd6ae
commit fd45ebd0e9
4 changed files with 66 additions and 4 deletions

View File

@ -1,8 +1,10 @@
import logging import logging
from typing import Any, Dict, Optional import shutil
from pathlib import Path from pathlib import Path
from typing import Any, Dict, Optional
from freqtrade import OperationalException from freqtrade import OperationalException
from freqtrade.constants import USER_DATA_FILES
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -48,3 +50,22 @@ def create_userdata_dir(directory: str, create_dir=False) -> Path:
if not subfolder.is_dir(): if not subfolder.is_dir():
subfolder.mkdir(parents=False) subfolder.mkdir(parents=False)
return folder return folder
def copy_sample_files(directory: Path) -> None:
"""
Copy files from templates to User data directory.
:param directory: Directory to copy data to
"""
if not directory.is_dir():
raise OperationalException(f"Directory `{directory}` does not exist.")
sourcedir = Path(__file__).parents[1] / "templates"
for source, target in USER_DATA_FILES.items():
targetdir = directory / target
if not targetdir.is_dir():
raise OperationalException(f"Directory `{targetdir}` does not exist.")
targetfile = targetdir / source
if targetfile.exists():
logger.warning(f"File `{targetfile}` exists already, not deploying sample file.")
continue
shutil.copy(str(sourcedir / source), str(targetfile))

View File

@ -22,6 +22,14 @@ AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList', 'PrecisionFilter', 'P
DRY_RUN_WALLET = 999.9 DRY_RUN_WALLET = 999.9
MATH_CLOSE_PREC = 1e-14 # Precision used for float comparisons MATH_CLOSE_PREC = 1e-14 # Precision used for float comparisons
# Soure files with destination directories
USER_DATA_FILES = {
'sample_strategy.py': 'strategies',
'sample_hyperopt_advanced.py': 'hyperopts',
'sample_hyperopt_loss.py': 'hyperopts',
'sample_hyperopt.py': 'hyperopts',
}
TIMEFRAMES = [ TIMEFRAMES = [
'1m', '3m', '5m', '15m', '30m', '1m', '3m', '5m', '15m', '30m',
'1h', '2h', '4h', '6h', '8h', '12h', '1h', '2h', '4h', '6h', '8h', '12h',

View File

@ -11,7 +11,7 @@ from tabulate import tabulate
from freqtrade import OperationalException from freqtrade import OperationalException
from freqtrade.configuration import Configuration, TimeRange, remove_credentials from freqtrade.configuration import Configuration, TimeRange, remove_credentials
from freqtrade.configuration.directory_operations import create_userdata_dir from freqtrade.configuration.directory_operations import create_userdata_dir, copy_sample_files
from freqtrade.data.history import (convert_trades_to_ohlcv, from freqtrade.data.history import (convert_trades_to_ohlcv,
refresh_backtest_ohlcv_data, refresh_backtest_ohlcv_data,
refresh_backtest_trades_data) refresh_backtest_trades_data)
@ -81,7 +81,8 @@ def start_create_userdir(args: Dict[str, Any]) -> None:
:return: None :return: None
""" """
if "user_data_dir" in args and args["user_data_dir"]: if "user_data_dir" in args and args["user_data_dir"]:
create_userdata_dir(args["user_data_dir"], create_dir=True) userdir = create_userdata_dir(args["user_data_dir"], create_dir=True)
copy_sample_files(userdir)
else: else:
logger.warning("`create-userdir` requires --userdir to be set.") logger.warning("`create-userdir` requires --userdir to be set.")
sys.exit(1) sys.exit(1)

View File

@ -18,7 +18,7 @@ from freqtrade.configuration.deprecated_settings import (
check_conflicting_settings, process_deprecated_setting, check_conflicting_settings, process_deprecated_setting,
process_temporary_deprecated_settings) process_temporary_deprecated_settings)
from freqtrade.configuration.directory_operations import (create_datadir, from freqtrade.configuration.directory_operations import (create_datadir,
create_userdata_dir) create_userdata_dir, copy_sample_files)
from freqtrade.configuration.load_config import load_config_file from freqtrade.configuration.load_config import load_config_file
from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL from freqtrade.constants import DEFAULT_DB_DRYRUN_URL, DEFAULT_DB_PROD_URL
from freqtrade.loggers import _set_loggers from freqtrade.loggers import _set_loggers
@ -709,6 +709,38 @@ def test_create_userdata_dir_exists_exception(mocker, default_conf, caplog) -> N
assert md.call_count == 0 assert md.call_count == 0
def test_copy_sample_files(mocker, default_conf, caplog) -> None:
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
copymock = mocker.patch('shutil.copy', MagicMock())
copy_sample_files(Path('/tmp/bar'))
assert copymock.call_count == 4
assert copymock.call_args_list[0][0][1] == '/tmp/bar/strategies/sample_strategy.py'
assert copymock.call_args_list[1][0][1] == '/tmp/bar/hyperopts/sample_hyperopt_advanced.py'
assert copymock.call_args_list[2][0][1] == '/tmp/bar/hyperopts/sample_hyperopt_loss.py'
assert copymock.call_args_list[3][0][1] == '/tmp/bar/hyperopts/sample_hyperopt.py'
def test_copy_sample_files_errors(mocker, default_conf, caplog) -> None:
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
mocker.patch('shutil.copy', MagicMock())
with pytest.raises(OperationalException,
match=r"Directory `.{1,2}tmp.{1,2}bar` does not exist\."):
copy_sample_files(Path('/tmp/bar'))
mocker.patch.object(Path, "is_dir", MagicMock(side_effect=[True, False]))
with pytest.raises(OperationalException,
match=r"Directory `.{1,2}tmp.{1,2}bar.{1,2}strategies` does not exist\."):
copy_sample_files(Path('/tmp/bar'))
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
mocker.patch.object(Path, "exists", MagicMock(return_value=True))
copy_sample_files(Path('/tmp/bar'))
assert log_has_re(r"File `.*` exists already, not deploying sample.*", caplog)
def test_validate_tsl(default_conf): def test_validate_tsl(default_conf):
default_conf['stoploss'] = 0.0 default_conf['stoploss'] = 0.0
with pytest.raises(OperationalException, match='The config stoploss needs to be different ' with pytest.raises(OperationalException, match='The config stoploss needs to be different '