ruff format: Update tests/ base directory

This commit is contained in:
Matthias 2024-05-12 15:35:47 +02:00
parent 53947732a0
commit 23427bec08
7 changed files with 4084 additions and 3233 deletions

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ from tests.conftest import CURRENT_TEST_STRATEGY
# Parse common command-line-arguments. Used for all tools # Parse common command-line-arguments. Used for all tools
def test_parse_args_none() -> None: def test_parse_args_none() -> None:
arguments = Arguments(['trade']) arguments = Arguments(["trade"])
assert isinstance(arguments, Arguments) assert isinstance(arguments, Arguments)
x = arguments.get_parsed_arg() x = arguments.get_parsed_arg()
assert isinstance(x, dict) assert isinstance(x, dict)
@ -20,265 +20,278 @@ def test_parse_args_none() -> None:
def test_parse_args_defaults(mocker) -> None: def test_parse_args_defaults(mocker) -> None:
mocker.patch.object(Path, 'is_file', MagicMock(side_effect=[False, True])) mocker.patch.object(Path, "is_file", MagicMock(side_effect=[False, True]))
args = Arguments(['trade']).get_parsed_arg() args = Arguments(["trade"]).get_parsed_arg()
assert args['config'] == ['config.json'] assert args["config"] == ["config.json"]
assert args['strategy_path'] is None assert args["strategy_path"] is None
assert args['datadir'] is None assert args["datadir"] is None
assert args['verbosity'] == 0 assert args["verbosity"] == 0
def test_parse_args_default_userdatadir(mocker) -> None: def test_parse_args_default_userdatadir(mocker) -> None:
mocker.patch.object(Path, 'is_file', MagicMock(return_value=True)) mocker.patch.object(Path, "is_file", MagicMock(return_value=True))
args = Arguments(['trade']).get_parsed_arg() args = Arguments(["trade"]).get_parsed_arg()
# configuration defaults to user_data if that is available. # configuration defaults to user_data if that is available.
assert args['config'] == [str(Path('user_data/config.json'))] assert args["config"] == [str(Path("user_data/config.json"))]
assert args['strategy_path'] is None assert args["strategy_path"] is None
assert args['datadir'] is None assert args["datadir"] is None
assert args['verbosity'] == 0 assert args["verbosity"] == 0
def test_parse_args_userdatadir(mocker) -> None: def test_parse_args_userdatadir(mocker) -> None:
mocker.patch.object(Path, 'is_file', MagicMock(return_value=True)) mocker.patch.object(Path, "is_file", MagicMock(return_value=True))
args = Arguments(['trade', '--user-data-dir', 'user_data']).get_parsed_arg() args = Arguments(["trade", "--user-data-dir", "user_data"]).get_parsed_arg()
# configuration defaults to user_data if that is available. # configuration defaults to user_data if that is available.
assert args['config'] == [str(Path('user_data/config.json'))] assert args["config"] == [str(Path("user_data/config.json"))]
assert args['strategy_path'] is None assert args["strategy_path"] is None
assert args['datadir'] is None assert args["datadir"] is None
assert args['verbosity'] == 0 assert args["verbosity"] == 0
def test_parse_args_config() -> None: def test_parse_args_config() -> None:
args = Arguments(['trade', '-c', '/dev/null']).get_parsed_arg() args = Arguments(["trade", "-c", "/dev/null"]).get_parsed_arg()
assert args['config'] == ['/dev/null'] assert args["config"] == ["/dev/null"]
args = Arguments(['trade', '--config', '/dev/null']).get_parsed_arg() args = Arguments(["trade", "--config", "/dev/null"]).get_parsed_arg()
assert args['config'] == ['/dev/null'] assert args["config"] == ["/dev/null"]
args = Arguments(['trade', '--config', '/dev/null', args = Arguments(
'--config', '/dev/zero'],).get_parsed_arg() ["trade", "--config", "/dev/null", "--config", "/dev/zero"],
assert args['config'] == ['/dev/null', '/dev/zero'] ).get_parsed_arg()
assert args["config"] == ["/dev/null", "/dev/zero"]
def test_parse_args_db_url() -> None: def test_parse_args_db_url() -> None:
args = Arguments(['trade', '--db-url', 'sqlite:///test.sqlite']).get_parsed_arg() args = Arguments(["trade", "--db-url", "sqlite:///test.sqlite"]).get_parsed_arg()
assert args['db_url'] == 'sqlite:///test.sqlite' assert args["db_url"] == "sqlite:///test.sqlite"
def test_parse_args_verbose() -> None: def test_parse_args_verbose() -> None:
args = Arguments(['trade', '-v']).get_parsed_arg() args = Arguments(["trade", "-v"]).get_parsed_arg()
assert args['verbosity'] == 1 assert args["verbosity"] == 1
args = Arguments(['trade', '--verbose']).get_parsed_arg() args = Arguments(["trade", "--verbose"]).get_parsed_arg()
assert args['verbosity'] == 1 assert args["verbosity"] == 1
def test_common_scripts_options() -> None: def test_common_scripts_options() -> None:
args = Arguments(['download-data', '-p', 'ETH/BTC', 'XRP/BTC']).get_parsed_arg() args = Arguments(["download-data", "-p", "ETH/BTC", "XRP/BTC"]).get_parsed_arg()
assert args['pairs'] == ['ETH/BTC', 'XRP/BTC'] assert args["pairs"] == ["ETH/BTC", "XRP/BTC"]
assert 'func' in args assert "func" in args
def test_parse_args_version() -> None: def test_parse_args_version() -> None:
with pytest.raises(SystemExit, match=r'0'): with pytest.raises(SystemExit, match=r"0"):
Arguments(['--version']).get_parsed_arg() Arguments(["--version"]).get_parsed_arg()
def test_parse_args_invalid() -> None: def test_parse_args_invalid() -> None:
with pytest.raises(SystemExit, match=r'2'): with pytest.raises(SystemExit, match=r"2"):
Arguments(['-c']).get_parsed_arg() Arguments(["-c"]).get_parsed_arg()
def test_parse_args_strategy() -> None: def test_parse_args_strategy() -> None:
args = Arguments(['trade', '--strategy', 'SomeStrategy']).get_parsed_arg() args = Arguments(["trade", "--strategy", "SomeStrategy"]).get_parsed_arg()
assert args['strategy'] == 'SomeStrategy' assert args["strategy"] == "SomeStrategy"
def test_parse_args_strategy_invalid() -> None: def test_parse_args_strategy_invalid() -> None:
with pytest.raises(SystemExit, match=r'2'): with pytest.raises(SystemExit, match=r"2"):
Arguments(['--strategy']).get_parsed_arg() Arguments(["--strategy"]).get_parsed_arg()
def test_parse_args_strategy_path() -> None: def test_parse_args_strategy_path() -> None:
args = Arguments(['trade', '--strategy-path', '/some/path']).get_parsed_arg() args = Arguments(["trade", "--strategy-path", "/some/path"]).get_parsed_arg()
assert args['strategy_path'] == '/some/path' assert args["strategy_path"] == "/some/path"
def test_parse_args_strategy_path_invalid() -> None: def test_parse_args_strategy_path_invalid() -> None:
with pytest.raises(SystemExit, match=r'2'): with pytest.raises(SystemExit, match=r"2"):
Arguments(['--strategy-path']).get_parsed_arg() Arguments(["--strategy-path"]).get_parsed_arg()
def test_parse_args_backtesting_invalid() -> None: def test_parse_args_backtesting_invalid() -> None:
with pytest.raises(SystemExit, match=r'2'): with pytest.raises(SystemExit, match=r"2"):
Arguments(['backtesting --timeframe']).get_parsed_arg() Arguments(["backtesting --timeframe"]).get_parsed_arg()
with pytest.raises(SystemExit, match=r'2'): with pytest.raises(SystemExit, match=r"2"):
Arguments(['backtesting --timeframe', 'abc']).get_parsed_arg() Arguments(["backtesting --timeframe", "abc"]).get_parsed_arg()
def test_parse_args_backtesting_custom() -> None: def test_parse_args_backtesting_custom() -> None:
args = [ args = [
'backtesting', "backtesting",
'-c', 'test_conf.json', "-c",
'--timeframe', '1m', "test_conf.json",
'--strategy-list', "--timeframe",
"1m",
"--strategy-list",
CURRENT_TEST_STRATEGY, CURRENT_TEST_STRATEGY,
'SampleStrategy' "SampleStrategy",
] ]
call_args = Arguments(args).get_parsed_arg() call_args = Arguments(args).get_parsed_arg()
assert call_args['config'] == ['test_conf.json'] assert call_args["config"] == ["test_conf.json"]
assert call_args['verbosity'] == 0 assert call_args["verbosity"] == 0
assert call_args['command'] == 'backtesting' assert call_args["command"] == "backtesting"
assert call_args['func'] is not None assert call_args["func"] is not None
assert call_args['timeframe'] == '1m' assert call_args["timeframe"] == "1m"
assert isinstance(call_args['strategy_list'], list) assert isinstance(call_args["strategy_list"], list)
assert len(call_args['strategy_list']) == 2 assert len(call_args["strategy_list"]) == 2
def test_parse_args_hyperopt_custom() -> None: def test_parse_args_hyperopt_custom() -> None:
args = [ args = ["hyperopt", "-c", "test_conf.json", "--epochs", "20", "--spaces", "buy"]
'hyperopt',
'-c', 'test_conf.json',
'--epochs', '20',
'--spaces', 'buy'
]
call_args = Arguments(args).get_parsed_arg() call_args = Arguments(args).get_parsed_arg()
assert call_args['config'] == ['test_conf.json'] assert call_args["config"] == ["test_conf.json"]
assert call_args['epochs'] == 20 assert call_args["epochs"] == 20
assert call_args['verbosity'] == 0 assert call_args["verbosity"] == 0
assert call_args['command'] == 'hyperopt' assert call_args["command"] == "hyperopt"
assert call_args['spaces'] == ['buy'] assert call_args["spaces"] == ["buy"]
assert call_args['func'] is not None assert call_args["func"] is not None
assert callable(call_args['func']) assert callable(call_args["func"])
def test_download_data_options() -> None: def test_download_data_options() -> None:
args = [ args = [
'download-data', "download-data",
'--datadir', 'datadir/directory', "--datadir",
'--pairs-file', 'file_with_pairs', "datadir/directory",
'--days', '30', "--pairs-file",
'--exchange', 'binance' "file_with_pairs",
"--days",
"30",
"--exchange",
"binance",
] ]
pargs = Arguments(args).get_parsed_arg() pargs = Arguments(args).get_parsed_arg()
assert pargs['pairs_file'] == 'file_with_pairs' assert pargs["pairs_file"] == "file_with_pairs"
assert pargs['datadir'] == 'datadir/directory' assert pargs["datadir"] == "datadir/directory"
assert pargs['days'] == 30 assert pargs["days"] == 30
assert pargs['exchange'] == 'binance' assert pargs["exchange"] == "binance"
def test_plot_dataframe_options() -> None: def test_plot_dataframe_options() -> None:
args = [ args = [
'plot-dataframe', "plot-dataframe",
'-c', 'tests/testdata/testconfigs/main_test_config.json', "-c",
'--indicators1', 'sma10', 'sma100', "tests/testdata/testconfigs/main_test_config.json",
'--indicators2', 'macd', 'fastd', 'fastk', "--indicators1",
'--plot-limit', '30', "sma10",
'-p', 'UNITTEST/BTC', "sma100",
"--indicators2",
"macd",
"fastd",
"fastk",
"--plot-limit",
"30",
"-p",
"UNITTEST/BTC",
] ]
pargs = Arguments(args).get_parsed_arg() pargs = Arguments(args).get_parsed_arg()
assert pargs['indicators1'] == ['sma10', 'sma100'] assert pargs["indicators1"] == ["sma10", "sma100"]
assert pargs['indicators2'] == ['macd', 'fastd', 'fastk'] assert pargs["indicators2"] == ["macd", "fastd", "fastk"]
assert pargs['plot_limit'] == 30 assert pargs["plot_limit"] == 30
assert pargs['pairs'] == ['UNITTEST/BTC'] assert pargs["pairs"] == ["UNITTEST/BTC"]
@pytest.mark.parametrize('auto_open_arg', [True, False]) @pytest.mark.parametrize("auto_open_arg", [True, False])
def test_plot_profit_options(auto_open_arg: bool) -> None: def test_plot_profit_options(auto_open_arg: bool) -> None:
args = [ args = [
'plot-profit', "plot-profit",
'-p', 'UNITTEST/BTC', "-p",
'--trade-source', 'DB', "UNITTEST/BTC",
'--db-url', 'sqlite:///whatever.sqlite', "--trade-source",
"DB",
"--db-url",
"sqlite:///whatever.sqlite",
] ]
if auto_open_arg: if auto_open_arg:
args.append('--auto-open') args.append("--auto-open")
pargs = Arguments(args).get_parsed_arg() pargs = Arguments(args).get_parsed_arg()
assert pargs['trade_source'] == 'DB' assert pargs["trade_source"] == "DB"
assert pargs['pairs'] == ['UNITTEST/BTC'] assert pargs["pairs"] == ["UNITTEST/BTC"]
assert pargs['db_url'] == 'sqlite:///whatever.sqlite' assert pargs["db_url"] == "sqlite:///whatever.sqlite"
assert pargs['plot_auto_open'] == auto_open_arg assert pargs["plot_auto_open"] == auto_open_arg
def test_config_notallowed(mocker) -> None: def test_config_notallowed(mocker) -> None:
mocker.patch.object(Path, 'is_file', MagicMock(return_value=False)) mocker.patch.object(Path, "is_file", MagicMock(return_value=False))
args = [ args = [
'create-userdir', "create-userdir",
] ]
pargs = Arguments(args).get_parsed_arg() pargs = Arguments(args).get_parsed_arg()
assert 'config' not in pargs assert "config" not in pargs
# When file exists: # When file exists:
mocker.patch.object(Path, 'is_file', MagicMock(return_value=True)) mocker.patch.object(Path, "is_file", MagicMock(return_value=True))
args = [ args = [
'create-userdir', "create-userdir",
] ]
pargs = Arguments(args).get_parsed_arg() pargs = Arguments(args).get_parsed_arg()
# config is not added even if it exists, since create-userdir is in the notallowed list # config is not added even if it exists, since create-userdir is in the notallowed list
assert 'config' not in pargs assert "config" not in pargs
def test_config_notrequired(mocker) -> None: def test_config_notrequired(mocker) -> None:
mocker.patch.object(Path, 'is_file', MagicMock(return_value=False)) mocker.patch.object(Path, "is_file", MagicMock(return_value=False))
args = [ args = [
'download-data', "download-data",
] ]
pargs = Arguments(args).get_parsed_arg() pargs = Arguments(args).get_parsed_arg()
assert pargs['config'] is None assert pargs["config"] is None
# When file exists: # When file exists:
mocker.patch.object(Path, 'is_file', MagicMock(side_effect=[False, True])) mocker.patch.object(Path, "is_file", MagicMock(side_effect=[False, True]))
args = [ args = [
'download-data', "download-data",
] ]
pargs = Arguments(args).get_parsed_arg() pargs = Arguments(args).get_parsed_arg()
# config is added if it exists # config is added if it exists
assert pargs['config'] == ['config.json'] assert pargs["config"] == ["config.json"]
def test_check_int_positive() -> None: def test_check_int_positive() -> None:
assert check_int_positive('3') == 3 assert check_int_positive("3") == 3
assert check_int_positive('1') == 1 assert check_int_positive("1") == 1
assert check_int_positive('100') == 100 assert check_int_positive("100") == 100
with pytest.raises(argparse.ArgumentTypeError): with pytest.raises(argparse.ArgumentTypeError):
check_int_positive('-2') check_int_positive("-2")
with pytest.raises(argparse.ArgumentTypeError): with pytest.raises(argparse.ArgumentTypeError):
check_int_positive('0') check_int_positive("0")
with pytest.raises(argparse.ArgumentTypeError): with pytest.raises(argparse.ArgumentTypeError):
check_int_positive(0) check_int_positive(0)
with pytest.raises(argparse.ArgumentTypeError): with pytest.raises(argparse.ArgumentTypeError):
check_int_positive('3.5') check_int_positive("3.5")
with pytest.raises(argparse.ArgumentTypeError): with pytest.raises(argparse.ArgumentTypeError):
check_int_positive('DeadBeef') check_int_positive("DeadBeef")
def test_check_int_nonzero() -> None: def test_check_int_nonzero() -> None:
assert check_int_nonzero('3') == 3 assert check_int_nonzero("3") == 3
assert check_int_nonzero('1') == 1 assert check_int_nonzero("1") == 1
assert check_int_nonzero('100') == 100 assert check_int_nonzero("100") == 100
assert check_int_nonzero('-2') == -2 assert check_int_nonzero("-2") == -2
with pytest.raises(argparse.ArgumentTypeError): with pytest.raises(argparse.ArgumentTypeError):
check_int_nonzero('0') check_int_nonzero("0")
with pytest.raises(argparse.ArgumentTypeError): with pytest.raises(argparse.ArgumentTypeError):
check_int_nonzero(0) check_int_nonzero(0)
with pytest.raises(argparse.ArgumentTypeError): with pytest.raises(argparse.ArgumentTypeError):
check_int_nonzero('3.5') check_int_nonzero("3.5")
with pytest.raises(argparse.ArgumentTypeError): with pytest.raises(argparse.ArgumentTypeError):
check_int_nonzero('DeadBeef') check_int_nonzero("DeadBeef")

File diff suppressed because it is too large Load Diff

View File

@ -17,93 +17,100 @@ from tests.conftest import log_has, log_has_re
def test_create_datadir(mocker, default_conf, caplog) -> None: def test_create_datadir(mocker, default_conf, caplog) -> None:
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False)) mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
md = mocker.patch.object(Path, 'mkdir', MagicMock()) md = mocker.patch.object(Path, "mkdir", MagicMock())
create_datadir(default_conf, '/foo/bar') create_datadir(default_conf, "/foo/bar")
assert md.call_args[1]['parents'] is True assert md.call_args[1]["parents"] is True
assert log_has('Created data directory: /foo/bar', caplog) assert log_has("Created data directory: /foo/bar", caplog)
def test_create_userdata_dir(mocker, default_conf, caplog) -> None: def test_create_userdata_dir(mocker, default_conf, caplog) -> None:
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False)) mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
md = mocker.patch.object(Path, 'mkdir', MagicMock()) md = mocker.patch.object(Path, "mkdir", MagicMock())
x = create_userdata_dir('/tmp/bar', create_dir=True) x = create_userdata_dir("/tmp/bar", create_dir=True)
assert md.call_count == 10 assert md.call_count == 10
assert md.call_args[1]['parents'] is False assert md.call_args[1]["parents"] is False
assert log_has(f'Created user-data directory: {Path("/tmp/bar")}', caplog) assert log_has(f'Created user-data directory: {Path("/tmp/bar")}', caplog)
assert isinstance(x, Path) assert isinstance(x, Path)
assert str(x) == str(Path("/tmp/bar")) assert str(x) == str(Path("/tmp/bar"))
def test_create_userdata_dir_and_chown(mocker, tmp_path, caplog) -> None: def test_create_userdata_dir_and_chown(mocker, tmp_path, caplog) -> None:
sp_mock = mocker.patch('subprocess.check_output') sp_mock = mocker.patch("subprocess.check_output")
path = tmp_path / 'bar' path = tmp_path / "bar"
assert not path.is_dir() assert not path.is_dir()
x = create_userdata_dir(str(path), create_dir=True) x = create_userdata_dir(str(path), create_dir=True)
assert sp_mock.call_count == 0 assert sp_mock.call_count == 0
assert log_has(f'Created user-data directory: {path}', caplog) assert log_has(f"Created user-data directory: {path}", caplog)
assert isinstance(x, Path) assert isinstance(x, Path)
assert path.is_dir() assert path.is_dir()
assert (path / 'data').is_dir() assert (path / "data").is_dir()
os.environ['FT_APP_ENV'] = 'docker' os.environ["FT_APP_ENV"] = "docker"
chown_user_directory(path / 'data') chown_user_directory(path / "data")
assert sp_mock.call_count == 1 assert sp_mock.call_count == 1
del os.environ['FT_APP_ENV'] del os.environ["FT_APP_ENV"]
def test_create_userdata_dir_exists(mocker, default_conf, caplog) -> None: def test_create_userdata_dir_exists(mocker, default_conf, caplog) -> None:
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True)) mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
md = mocker.patch.object(Path, 'mkdir', MagicMock()) md = mocker.patch.object(Path, "mkdir", MagicMock())
create_userdata_dir('/tmp/bar') create_userdata_dir("/tmp/bar")
assert md.call_count == 0 assert md.call_count == 0
def test_create_userdata_dir_exists_exception(mocker, default_conf, caplog) -> None: def test_create_userdata_dir_exists_exception(mocker, default_conf, caplog) -> None:
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False)) mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
md = mocker.patch.object(Path, 'mkdir', MagicMock()) md = mocker.patch.object(Path, "mkdir", MagicMock())
with pytest.raises(OperationalException, with pytest.raises(
match=r'Directory `.{1,2}tmp.{1,2}bar` does not exist.*'): OperationalException, match=r"Directory `.{1,2}tmp.{1,2}bar` does not exist.*"
create_userdata_dir('/tmp/bar', create_dir=False) ):
create_userdata_dir("/tmp/bar", create_dir=False)
assert md.call_count == 0 assert md.call_count == 0
def test_copy_sample_files(mocker, default_conf, caplog) -> None: def test_copy_sample_files(mocker, default_conf, caplog) -> None:
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True)) mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
mocker.patch.object(Path, "exists", MagicMock(return_value=False)) mocker.patch.object(Path, "exists", MagicMock(return_value=False))
copymock = mocker.patch('shutil.copy', MagicMock()) copymock = mocker.patch("shutil.copy", MagicMock())
copy_sample_files(Path('/tmp/bar')) copy_sample_files(Path("/tmp/bar"))
assert copymock.call_count == 3 assert copymock.call_count == 3
assert copymock.call_args_list[0][0][1] == str( assert copymock.call_args_list[0][0][1] == str(
Path('/tmp/bar') / 'strategies/sample_strategy.py') Path("/tmp/bar") / "strategies/sample_strategy.py"
)
assert copymock.call_args_list[1][0][1] == str( assert copymock.call_args_list[1][0][1] == str(
Path('/tmp/bar') / 'hyperopts/sample_hyperopt_loss.py') Path("/tmp/bar") / "hyperopts/sample_hyperopt_loss.py"
)
assert copymock.call_args_list[2][0][1] == str( assert copymock.call_args_list[2][0][1] == str(
Path('/tmp/bar') / 'notebooks/strategy_analysis_example.ipynb') Path("/tmp/bar") / "notebooks/strategy_analysis_example.ipynb"
)
def test_copy_sample_files_errors(mocker, default_conf, caplog) -> None: 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, "is_dir", MagicMock(return_value=False))
mocker.patch.object(Path, "exists", MagicMock(return_value=False)) mocker.patch.object(Path, "exists", MagicMock(return_value=False))
mocker.patch('shutil.copy', MagicMock()) mocker.patch("shutil.copy", MagicMock())
with pytest.raises(OperationalException, with pytest.raises(
match=r"Directory `.{1,2}tmp.{1,2}bar` does not exist\."): OperationalException, match=r"Directory `.{1,2}tmp.{1,2}bar` does not exist\."
copy_sample_files(Path('/tmp/bar')) ):
copy_sample_files(Path("/tmp/bar"))
mocker.patch.object(Path, "is_dir", MagicMock(side_effect=[True, False])) mocker.patch.object(Path, "is_dir", MagicMock(side_effect=[True, False]))
with pytest.raises(OperationalException, with pytest.raises(
match=r"Directory `.{1,2}tmp.{1,2}bar.{1,2}strategies` does not exist\."): OperationalException,
copy_sample_files(Path('/tmp/bar')) 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, "is_dir", MagicMock(return_value=True))
mocker.patch.object(Path, "exists", MagicMock(return_value=True)) mocker.patch.object(Path, "exists", MagicMock(return_value=True))
copy_sample_files(Path('/tmp/bar')) copy_sample_files(Path("/tmp/bar"))
assert log_has_re(r"File `.*` exists already, not deploying sample file\.", caplog) assert log_has_re(r"File `.*` exists already, not deploying sample file\.", caplog)
caplog.clear() caplog.clear()
copy_sample_files(Path('/tmp/bar'), overwrite=True) copy_sample_files(Path("/tmp/bar"), overwrite=True)
assert log_has_re(r"File `.*` exists already, overwriting\.", caplog) assert log_has_re(r"File `.*` exists already, overwriting\.", caplog)

View File

@ -19,42 +19,42 @@ from freqtrade.loggers.set_log_levels import (
def test_set_loggers() -> None: def test_set_loggers() -> None:
# Reset Logging to Debug, otherwise this fails randomly as it's set globally # Reset Logging to Debug, otherwise this fails randomly as it's set globally
logging.getLogger('requests').setLevel(logging.DEBUG) logging.getLogger("requests").setLevel(logging.DEBUG)
logging.getLogger("urllib3").setLevel(logging.DEBUG) logging.getLogger("urllib3").setLevel(logging.DEBUG)
logging.getLogger('ccxt.base.exchange').setLevel(logging.DEBUG) logging.getLogger("ccxt.base.exchange").setLevel(logging.DEBUG)
logging.getLogger('telegram').setLevel(logging.DEBUG) logging.getLogger("telegram").setLevel(logging.DEBUG)
previous_value1 = logging.getLogger('requests').level previous_value1 = logging.getLogger("requests").level
previous_value2 = logging.getLogger('ccxt.base.exchange').level previous_value2 = logging.getLogger("ccxt.base.exchange").level
previous_value3 = logging.getLogger('telegram').level previous_value3 = logging.getLogger("telegram").level
set_loggers() set_loggers()
value1 = logging.getLogger('requests').level value1 = logging.getLogger("requests").level
assert previous_value1 is not value1 assert previous_value1 is not value1
assert value1 is logging.INFO assert value1 is logging.INFO
value2 = logging.getLogger('ccxt.base.exchange').level value2 = logging.getLogger("ccxt.base.exchange").level
assert previous_value2 is not value2 assert previous_value2 is not value2
assert value2 is logging.INFO assert value2 is logging.INFO
value3 = logging.getLogger('telegram').level value3 = logging.getLogger("telegram").level
assert previous_value3 is not value3 assert previous_value3 is not value3
assert value3 is logging.INFO assert value3 is logging.INFO
set_loggers(verbosity=2) set_loggers(verbosity=2)
assert logging.getLogger('requests').level is logging.DEBUG assert logging.getLogger("requests").level is logging.DEBUG
assert logging.getLogger('ccxt.base.exchange').level is logging.INFO assert logging.getLogger("ccxt.base.exchange").level is logging.INFO
assert logging.getLogger('telegram').level is logging.INFO assert logging.getLogger("telegram").level is logging.INFO
assert logging.getLogger('werkzeug').level is logging.INFO assert logging.getLogger("werkzeug").level is logging.INFO
set_loggers(verbosity=3, api_verbosity='error') set_loggers(verbosity=3, api_verbosity="error")
assert logging.getLogger('requests').level is logging.DEBUG assert logging.getLogger("requests").level is logging.DEBUG
assert logging.getLogger('ccxt.base.exchange').level is logging.DEBUG assert logging.getLogger("ccxt.base.exchange").level is logging.DEBUG
assert logging.getLogger('telegram').level is logging.INFO assert logging.getLogger("telegram").level is logging.INFO
assert logging.getLogger('werkzeug').level is logging.ERROR assert logging.getLogger("werkzeug").level is logging.ERROR
@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows") @pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
@ -63,9 +63,10 @@ def test_set_loggers_syslog():
orig_handlers = logger.handlers orig_handlers = logger.handlers
logger.handlers = [] logger.handlers = []
config = {'verbosity': 2, config = {
'logfile': 'syslog:/dev/log', "verbosity": 2,
} "logfile": "syslog:/dev/log",
}
setup_logging_pre() setup_logging_pre()
setup_logging(config) setup_logging(config)
@ -85,10 +86,11 @@ def test_set_loggers_Filehandler(tmp_path):
logger = logging.getLogger() logger = logging.getLogger()
orig_handlers = logger.handlers orig_handlers = logger.handlers
logger.handlers = [] logger.handlers = []
logfile = tmp_path / 'ft_logfile.log' logfile = tmp_path / "ft_logfile.log"
config = {'verbosity': 2, config = {
'logfile': str(logfile), "verbosity": 2,
} "logfile": str(logfile),
}
setup_logging_pre() setup_logging_pre()
setup_logging(config) setup_logging(config)
@ -111,9 +113,10 @@ def test_set_loggers_journald(mocker):
orig_handlers = logger.handlers orig_handlers = logger.handlers
logger.handlers = [] logger.handlers = []
config = {'verbosity': 2, config = {
'logfile': 'journald', "verbosity": 2,
} "logfile": "journald",
}
setup_logging_pre() setup_logging_pre()
setup_logging(config) setup_logging(config)
@ -129,11 +132,11 @@ def test_set_loggers_journald_importerror(import_fails):
orig_handlers = logger.handlers orig_handlers = logger.handlers
logger.handlers = [] logger.handlers = []
config = {'verbosity': 2, config = {
'logfile': 'journald', "verbosity": 2,
} "logfile": "journald",
with pytest.raises(OperationalException, }
match=r'You need the cysystemd python package.*'): with pytest.raises(OperationalException, match=r"You need the cysystemd python package.*"):
setup_logging(config) setup_logging(config)
logger.handlers = orig_handlers logger.handlers = orig_handlers
@ -141,16 +144,16 @@ def test_set_loggers_journald_importerror(import_fails):
def test_reduce_verbosity(): def test_reduce_verbosity():
setup_logging_pre() setup_logging_pre()
reduce_verbosity_for_bias_tester() reduce_verbosity_for_bias_tester()
prior_level = logging.getLogger('freqtrade').getEffectiveLevel() prior_level = logging.getLogger("freqtrade").getEffectiveLevel()
assert logging.getLogger('freqtrade.resolvers').getEffectiveLevel() == logging.WARNING assert logging.getLogger("freqtrade.resolvers").getEffectiveLevel() == logging.WARNING
assert logging.getLogger('freqtrade.strategy.hyper').getEffectiveLevel() == logging.WARNING assert logging.getLogger("freqtrade.strategy.hyper").getEffectiveLevel() == logging.WARNING
# base level wasn't changed # base level wasn't changed
assert logging.getLogger('freqtrade').getEffectiveLevel() == prior_level assert logging.getLogger("freqtrade").getEffectiveLevel() == prior_level
restore_verbosity_for_bias_tester() restore_verbosity_for_bias_tester()
assert logging.getLogger('freqtrade.resolvers').getEffectiveLevel() == prior_level assert logging.getLogger("freqtrade.resolvers").getEffectiveLevel() == prior_level
assert logging.getLogger('freqtrade.strategy.hyper').getEffectiveLevel() == prior_level assert logging.getLogger("freqtrade.strategy.hyper").getEffectiveLevel() == prior_level
assert logging.getLogger('freqtrade').getEffectiveLevel() == prior_level assert logging.getLogger("freqtrade").getEffectiveLevel() == prior_level
# base level wasn't changed # base level wasn't changed

View File

@ -18,41 +18,34 @@ if sys.version_info < (3, 9):
def test_strategy_updater_start(user_dir, capsys) -> None: def test_strategy_updater_start(user_dir, capsys) -> None:
# Effective test without mocks. # Effective test without mocks.
teststrats = Path(__file__).parent / 'strategy/strats' teststrats = Path(__file__).parent / "strategy/strats"
tmpdirp = Path(user_dir) / "strategies" tmpdirp = Path(user_dir) / "strategies"
tmpdirp.mkdir(parents=True, exist_ok=True) tmpdirp.mkdir(parents=True, exist_ok=True)
shutil.copy(teststrats / 'strategy_test_v2.py', tmpdirp) shutil.copy(teststrats / "strategy_test_v2.py", tmpdirp)
old_code = (teststrats / 'strategy_test_v2.py').read_text() old_code = (teststrats / "strategy_test_v2.py").read_text()
args = [ args = ["strategy-updater", "--userdir", str(user_dir), "--strategy-list", "StrategyTestV2"]
"strategy-updater",
"--userdir",
str(user_dir),
"--strategy-list",
"StrategyTestV2"
]
pargs = get_args(args) pargs = get_args(args)
pargs['config'] = None pargs["config"] = None
start_strategy_update(pargs) start_strategy_update(pargs)
assert Path(user_dir / "strategies_orig_updater").exists() assert Path(user_dir / "strategies_orig_updater").exists()
# Backup file exists # Backup file exists
assert Path(user_dir / "strategies_orig_updater" / 'strategy_test_v2.py').exists() assert Path(user_dir / "strategies_orig_updater" / "strategy_test_v2.py").exists()
# updated file exists # updated file exists
new_file = tmpdirp / 'strategy_test_v2.py' new_file = tmpdirp / "strategy_test_v2.py"
assert new_file.exists() assert new_file.exists()
new_code = new_file.read_text() new_code = new_file.read_text()
assert 'INTERFACE_VERSION = 3' in new_code assert "INTERFACE_VERSION = 3" in new_code
assert 'INTERFACE_VERSION = 2' in old_code assert "INTERFACE_VERSION = 2" in old_code
captured = capsys.readouterr() captured = capsys.readouterr()
assert 'Conversion of strategy_test_v2.py started.' in captured.out assert "Conversion of strategy_test_v2.py started." in captured.out
assert re.search(r'Conversion of strategy_test_v2\.py took .* seconds', captured.out) assert re.search(r"Conversion of strategy_test_v2\.py took .* seconds", captured.out)
def test_strategy_updater_methods(default_conf, caplog) -> None: def test_strategy_updater_methods(default_conf, caplog) -> None:
instance_strategy_updater = StrategyUpdater() instance_strategy_updater = StrategyUpdater()
modified_code1 = instance_strategy_updater.update_code(""" modified_code1 = instance_strategy_updater.update_code("""
class testClass(IStrategy): class testClass(IStrategy):

View File

@ -8,61 +8,61 @@ from freqtrade.exceptions import OperationalException
def test_parse_timerange_incorrect(): def test_parse_timerange_incorrect():
timerange = TimeRange.parse_timerange("")
timerange = TimeRange.parse_timerange('')
assert timerange == TimeRange(None, None, 0, 0) assert timerange == TimeRange(None, None, 0, 0)
timerange = TimeRange.parse_timerange('20100522-') timerange = TimeRange.parse_timerange("20100522-")
assert TimeRange('date', None, 1274486400, 0) == timerange assert TimeRange("date", None, 1274486400, 0) == timerange
assert timerange.timerange_str == '20100522-' assert timerange.timerange_str == "20100522-"
timerange = TimeRange.parse_timerange('-20100522') timerange = TimeRange.parse_timerange("-20100522")
assert TimeRange(None, 'date', 0, 1274486400) == timerange assert TimeRange(None, "date", 0, 1274486400) == timerange
assert timerange.timerange_str == '-20100522' assert timerange.timerange_str == "-20100522"
timerange = TimeRange.parse_timerange('20100522-20150730') timerange = TimeRange.parse_timerange("20100522-20150730")
assert timerange == TimeRange('date', 'date', 1274486400, 1438214400) assert timerange == TimeRange("date", "date", 1274486400, 1438214400)
assert timerange.timerange_str == '20100522-20150730' assert timerange.timerange_str == "20100522-20150730"
assert timerange.start_fmt == '2010-05-22 00:00:00' assert timerange.start_fmt == "2010-05-22 00:00:00"
assert timerange.stop_fmt == '2015-07-30 00:00:00' assert timerange.stop_fmt == "2015-07-30 00:00:00"
# Added test for unix timestamp - BTC genesis date # Added test for unix timestamp - BTC genesis date
assert TimeRange('date', None, 1231006505, 0) == TimeRange.parse_timerange('1231006505-') assert TimeRange("date", None, 1231006505, 0) == TimeRange.parse_timerange("1231006505-")
assert TimeRange(None, 'date', 0, 1233360000) == TimeRange.parse_timerange('-1233360000') assert TimeRange(None, "date", 0, 1233360000) == TimeRange.parse_timerange("-1233360000")
timerange = TimeRange.parse_timerange('1231006505-1233360000') timerange = TimeRange.parse_timerange("1231006505-1233360000")
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange assert TimeRange("date", "date", 1231006505, 1233360000) == timerange
assert isinstance(timerange.startdt, datetime) assert isinstance(timerange.startdt, datetime)
assert isinstance(timerange.stopdt, datetime) assert isinstance(timerange.stopdt, datetime)
assert timerange.startdt == datetime.fromtimestamp(1231006505, tz=timezone.utc) assert timerange.startdt == datetime.fromtimestamp(1231006505, tz=timezone.utc)
assert timerange.stopdt == datetime.fromtimestamp(1233360000, tz=timezone.utc) assert timerange.stopdt == datetime.fromtimestamp(1233360000, tz=timezone.utc)
assert timerange.timerange_str == '20090103-20090131' assert timerange.timerange_str == "20090103-20090131"
timerange = TimeRange.parse_timerange('1231006505000-1233360000000') timerange = TimeRange.parse_timerange("1231006505000-1233360000000")
assert TimeRange('date', 'date', 1231006505, 1233360000) == timerange assert TimeRange("date", "date", 1231006505, 1233360000) == timerange
timerange = TimeRange.parse_timerange('1231006505000-') timerange = TimeRange.parse_timerange("1231006505000-")
assert TimeRange('date', None, 1231006505, 0) == timerange assert TimeRange("date", None, 1231006505, 0) == timerange
timerange = TimeRange.parse_timerange('-1231006505000') timerange = TimeRange.parse_timerange("-1231006505000")
assert TimeRange(None, 'date', 0, 1231006505) == timerange assert TimeRange(None, "date", 0, 1231006505) == timerange
with pytest.raises(OperationalException, match=r'Incorrect syntax.*'): with pytest.raises(OperationalException, match=r"Incorrect syntax.*"):
TimeRange.parse_timerange('-') TimeRange.parse_timerange("-")
with pytest.raises(OperationalException, with pytest.raises(
match=r'Start date is after stop date for timerange.*'): OperationalException, match=r"Start date is after stop date for timerange.*"
TimeRange.parse_timerange('20100523-20100522') ):
TimeRange.parse_timerange("20100523-20100522")
def test_subtract_start(): def test_subtract_start():
x = TimeRange('date', 'date', 1274486400, 1438214400) x = TimeRange("date", "date", 1274486400, 1438214400)
x.subtract_start(300) x.subtract_start(300)
assert x.startts == 1274486400 - 300 assert x.startts == 1274486400 - 300
# Do nothing if no startdate exists # Do nothing if no startdate exists
x = TimeRange(None, 'date', 0, 1438214400) x = TimeRange(None, "date", 0, 1438214400)
x.subtract_start(300) x.subtract_start(300)
assert not x.startts assert not x.startts
assert not x.startdt assert not x.startdt
x = TimeRange('date', None, 1274486400, 0) x = TimeRange("date", None, 1274486400, 0)
x.subtract_start(300) x.subtract_start(300)
assert x.startts == 1274486400 - 300 assert x.startts == 1274486400 - 300
@ -70,17 +70,17 @@ def test_subtract_start():
def test_adjust_start_if_necessary(): def test_adjust_start_if_necessary():
min_date = datetime(2017, 11, 14, 21, 15, 00, tzinfo=timezone.utc) min_date = datetime(2017, 11, 14, 21, 15, 00, tzinfo=timezone.utc)
x = TimeRange('date', 'date', 1510694100, 1510780500) x = TimeRange("date", "date", 1510694100, 1510780500)
# Adjust by 20 candles - min_date == startts # Adjust by 20 candles - min_date == startts
x.adjust_start_if_necessary(300, 20, min_date) x.adjust_start_if_necessary(300, 20, min_date)
assert x.startts == 1510694100 + (20 * 300) assert x.startts == 1510694100 + (20 * 300)
x = TimeRange('date', 'date', 1510700100, 1510780500) x = TimeRange("date", "date", 1510700100, 1510780500)
# Do nothing, startup is set and different min_date # Do nothing, startup is set and different min_date
x.adjust_start_if_necessary(300, 20, min_date) x.adjust_start_if_necessary(300, 20, min_date)
assert x.startts == 1510694100 + (20 * 300) assert x.startts == 1510694100 + (20 * 300)
x = TimeRange(None, 'date', 0, 1510780500) x = TimeRange(None, "date", 0, 1510780500)
# Adjust by 20 candles = 20 * 5m # Adjust by 20 candles = 20 * 5m
x.adjust_start_if_necessary(300, 20, min_date) x.adjust_start_if_necessary(300, 20, min_date)
assert x.startts == 1510694100 + (20 * 300) assert x.startts == 1510694100 + (20 * 300)