Gracefully handle pickle-errors when @staticmethod is used

pOinted out in https://github.com/freqtrade/freqtrade-strategies/issues/28
This commit is contained in:
Matthias 2019-04-16 20:25:48 +02:00
parent 16bf7aa3ab
commit 2cee716181
2 changed files with 21 additions and 6 deletions

View File

@ -157,12 +157,15 @@ class StrategyResolver(IResolver):
getfullargspec(strategy.populate_indicators).args) getfullargspec(strategy.populate_indicators).args)
strategy._buy_fun_len = len(getfullargspec(strategy.populate_buy_trend).args) strategy._buy_fun_len = len(getfullargspec(strategy.populate_buy_trend).args)
strategy._sell_fun_len = len(getfullargspec(strategy.populate_sell_trend).args) strategy._sell_fun_len = len(getfullargspec(strategy.populate_sell_trend).args)
try:
return import_strategy(strategy, config=config) return import_strategy(strategy, config=config)
except TypeError as e:
logger.warning(
f"Impossible to load strategy '{strategy}' from {_path}. Error: {e}")
except FileNotFoundError: except FileNotFoundError:
logger.warning('Path "%s" does not exist', _path.relative_to(Path.cwd())) logger.warning('Path "%s" does not exist', _path.relative_to(Path.cwd()))
raise ImportError( raise ImportError(
"Impossible to load Strategy '{}'. This class does not exist" f"Impossible to load Strategy '{strategy_name}'. This class does not exist"
" or contains Python code errors".format(strategy_name) " or contains Python code errors"
) )

View File

@ -1,17 +1,19 @@
# pragma pylint: disable=missing-docstring, protected-access, C0103 # pragma pylint: disable=missing-docstring, protected-access, C0103
import logging import logging
import warnings
from base64 import urlsafe_b64encode from base64 import urlsafe_b64encode
from os import path from os import path
from pathlib import Path from pathlib import Path
import warnings from unittest.mock import Mock
import pytest import pytest
from pandas import DataFrame from pandas import DataFrame
from freqtrade.resolvers import StrategyResolver
from freqtrade.strategy import import_strategy from freqtrade.strategy import import_strategy
from freqtrade.strategy.default_strategy import DefaultStrategy from freqtrade.strategy.default_strategy import DefaultStrategy
from freqtrade.strategy.interface import IStrategy from freqtrade.strategy.interface import IStrategy
from freqtrade.resolvers import StrategyResolver from freqtrade.tests.conftest import log_has_re
def test_import_strategy(caplog): def test_import_strategy(caplog):
@ -94,6 +96,16 @@ def test_load_not_found_strategy():
strategy._load_strategy(strategy_name='NotFoundStrategy', config={}) strategy._load_strategy(strategy_name='NotFoundStrategy', config={})
def test_load_staticmethod_importerror(mocker, caplog):
mocker.patch("freqtrade.resolvers.strategy_resolver.import_strategy", Mock(
side_effect=TypeError("can't pickle staticmethod objects")))
with pytest.raises(ImportError,
match=r"Impossible to load Strategy 'DefaultStrategy'."
r" This class does not exist or contains Python code errors"):
StrategyResolver()
assert log_has_re(r".*Error: can't pickle staticmethod objects", caplog.record_tuples)
def test_strategy(result): def test_strategy(result):
config = {'strategy': 'DefaultStrategy'} config = {'strategy': 'DefaultStrategy'}