Merge pull request #1772 from freqtrade/fix/staticmethod_import

Gracefully handle pickle-errors when @staticmethod is used
This commit is contained in:
Misagh 2019-04-17 17:24:56 +02:00 committed by GitHub
commit f5ef8f5bc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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'}