Convert resolvers to classmethods
This commit is contained in:
		| @@ -14,6 +14,7 @@ class ExchangeResolver(IResolver): | |||||||
|     """ |     """ | ||||||
|     This class contains all the logic to load a custom exchange class |     This class contains all the logic to load a custom exchange class | ||||||
|     """ |     """ | ||||||
|  |     object_type = Exchange | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def load_exchange(exchange_name: str, config: dict, validate: bool = True) -> Exchange: |     def load_exchange(exchange_name: str, config: dict, validate: bool = True) -> Exchange: | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ class HyperOptResolver(IResolver): | |||||||
|     """ |     """ | ||||||
|     This class contains all the logic to load custom hyperopt class |     This class contains all the logic to load custom hyperopt class | ||||||
|     """ |     """ | ||||||
|  |     object_type = IHyperOpt | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def load_hyperopt(config: Dict) -> IHyperOpt: |     def load_hyperopt(config: Dict) -> IHyperOpt: | ||||||
| @@ -59,12 +60,13 @@ class HyperOptResolver(IResolver): | |||||||
|         """ |         """ | ||||||
|         current_path = Path(__file__).parent.parent.joinpath('optimize').resolve() |         current_path = Path(__file__).parent.parent.joinpath('optimize').resolve() | ||||||
|  |  | ||||||
|         abs_paths = IResolver.build_search_paths(config, current_path=current_path, |         abs_paths = HyperOptResolver.build_search_paths(config, current_path=current_path, | ||||||
|                                                         user_subdir=USERPATH_HYPEROPTS, |                                                         user_subdir=USERPATH_HYPEROPTS, | ||||||
|                                                         extra_dir=extra_dir) |                                                         extra_dir=extra_dir) | ||||||
|  |  | ||||||
|         hyperopt = IResolver._load_object(paths=abs_paths, object_type=IHyperOpt, |         hyperopt = HyperOptResolver._load_object(paths=abs_paths, | ||||||
|                                           object_name=hyperopt_name, kwargs={'config': config}) |                                                  object_name=hyperopt_name, | ||||||
|  |                                                  kwargs={'config': config}) | ||||||
|         if hyperopt: |         if hyperopt: | ||||||
|             return hyperopt |             return hyperopt | ||||||
|         raise OperationalException( |         raise OperationalException( | ||||||
| @@ -77,6 +79,7 @@ class HyperOptLossResolver(IResolver): | |||||||
|     """ |     """ | ||||||
|     This class contains all the logic to load custom hyperopt loss class |     This class contains all the logic to load custom hyperopt loss class | ||||||
|     """ |     """ | ||||||
|  |     object_type = IHyperOptLoss | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def load_hyperoptloss(config: Dict) -> IHyperOptLoss: |     def load_hyperoptloss(config: Dict) -> IHyperOptLoss: | ||||||
| @@ -113,11 +116,11 @@ class HyperOptLossResolver(IResolver): | |||||||
|         """ |         """ | ||||||
|         current_path = Path(__file__).parent.parent.joinpath('optimize').resolve() |         current_path = Path(__file__).parent.parent.joinpath('optimize').resolve() | ||||||
|  |  | ||||||
|         abs_paths = IResolver.build_search_paths(config, current_path=current_path, |         abs_paths = HyperOptLossResolver.build_search_paths(config, current_path=current_path, | ||||||
|                                                             user_subdir=USERPATH_HYPEROPTS, |                                                             user_subdir=USERPATH_HYPEROPTS, | ||||||
|                                                             extra_dir=extra_dir) |                                                             extra_dir=extra_dir) | ||||||
|  |  | ||||||
|         hyperoptloss = IResolver._load_object(paths=abs_paths, object_type=IHyperOptLoss, |         hyperoptloss = HyperOptLossResolver._load_object(paths=abs_paths, | ||||||
|                                                          object_name=hyper_loss_name) |                                                          object_name=hyper_loss_name) | ||||||
|         if hyperoptloss: |         if hyperoptloss: | ||||||
|             return hyperoptloss |             return hyperoptloss | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ import importlib.util | |||||||
| import inspect | import inspect | ||||||
| import logging | import logging | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
| from typing import Any, List, Optional, Tuple, Union, Generator | from typing import Any, Generator, List, Optional, Tuple, Type, Union | ||||||
|  |  | ||||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -16,6 +16,8 @@ class IResolver: | |||||||
|     """ |     """ | ||||||
|     This class contains all the logic to load custom classes |     This class contains all the logic to load custom classes | ||||||
|     """ |     """ | ||||||
|  |     # Childclasses need to override this | ||||||
|  |     object_type: Type[Any] | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def build_search_paths(config, current_path: Path, user_subdir: Optional[str] = None, |     def build_search_paths(config, current_path: Path, user_subdir: Optional[str] = None, | ||||||
| @@ -32,12 +34,11 @@ class IResolver: | |||||||
|  |  | ||||||
|         return abs_paths |         return abs_paths | ||||||
|  |  | ||||||
|     @staticmethod |     @classmethod | ||||||
|     def _get_valid_object(object_type, module_path: Path, |     def _get_valid_object(cls, module_path: Path, | ||||||
|                           object_name: str) -> Generator[Any, None, None]: |                           object_name: str) -> Generator[Any, None, None]: | ||||||
|         """ |         """ | ||||||
|         Generator returning objects with matching object_type and object_name in the path given. |         Generator returning objects with matching object_type and object_name in the path given. | ||||||
|         :param object_type: object_type (class) |  | ||||||
|         :param module_path: absolute path to the module |         :param module_path: absolute path to the module | ||||||
|         :param object_name: Class name of the object |         :param object_name: Class name of the object | ||||||
|         :return: generator containing matching objects |         :return: generator containing matching objects | ||||||
| @@ -55,19 +56,21 @@ class IResolver: | |||||||
|  |  | ||||||
|         valid_objects_gen = ( |         valid_objects_gen = ( | ||||||
|             obj for name, obj in inspect.getmembers(module, inspect.isclass) |             obj for name, obj in inspect.getmembers(module, inspect.isclass) | ||||||
|             if object_name == name and object_type in obj.__bases__ |             if object_name == name and cls.object_type in obj.__bases__ | ||||||
|         ) |         ) | ||||||
|         return valid_objects_gen |         return valid_objects_gen | ||||||
|  |  | ||||||
|     @staticmethod |     @classmethod | ||||||
|     def _search_object(directory: Path, object_type, object_name: str, |     def _search_object(cls, directory: Path, object_name: str, | ||||||
|                        kwargs: dict = {}) -> Union[Tuple[Any, Path], Tuple[None, None]]: |                        kwargs: dict = {}) -> Union[Tuple[Any, Path], Tuple[None, None]]: | ||||||
|         """ |         """ | ||||||
|         Search for the objectname in the given directory |         Search for the objectname in the given directory | ||||||
|         :param directory: relative or absolute directory path |         :param directory: relative or absolute directory path | ||||||
|  |         :param object_name: ClassName of the object to load | ||||||
|         :return: object instance |         :return: object instance | ||||||
|         """ |         """ | ||||||
|         logger.debug("Searching for %s %s in '%s'", object_type.__name__, object_name, directory) |         logger.debug("Searching for %s %s in '%s'", | ||||||
|  |                      cls.object_type.__name__, object_name, directory) | ||||||
|         for entry in directory.iterdir(): |         for entry in directory.iterdir(): | ||||||
|             # Only consider python files |             # Only consider python files | ||||||
|             if not str(entry).endswith('.py'): |             if not str(entry).endswith('.py'): | ||||||
| @@ -75,14 +78,14 @@ class IResolver: | |||||||
|                 continue |                 continue | ||||||
|             module_path = entry.resolve() |             module_path = entry.resolve() | ||||||
|  |  | ||||||
|             obj = next(IResolver._get_valid_object(object_type, module_path, object_name), None) |             obj = next(cls._get_valid_object(module_path, object_name), None) | ||||||
|  |  | ||||||
|             if obj: |             if obj: | ||||||
|                 return (obj(**kwargs), module_path) |                 return (obj(**kwargs), module_path) | ||||||
|         return (None, None) |         return (None, None) | ||||||
|  |  | ||||||
|     @staticmethod |     @classmethod | ||||||
|     def _load_object(paths: List[Path], object_type, object_name: str, |     def _load_object(cls, paths: List[Path], object_name: str, | ||||||
|                      kwargs: dict = {}) -> Optional[Any]: |                      kwargs: dict = {}) -> Optional[Any]: | ||||||
|         """ |         """ | ||||||
|         Try to load object from path list. |         Try to load object from path list. | ||||||
| @@ -90,13 +93,12 @@ class IResolver: | |||||||
|  |  | ||||||
|         for _path in paths: |         for _path in paths: | ||||||
|             try: |             try: | ||||||
|                 (module, module_path) = IResolver._search_object(directory=_path, |                 (module, module_path) = cls._search_object(directory=_path, | ||||||
|                                                                  object_type=object_type, |  | ||||||
|                                                            object_name=object_name, |                                                            object_name=object_name, | ||||||
|                                                            kwargs=kwargs) |                                                            kwargs=kwargs) | ||||||
|                 if module: |                 if module: | ||||||
|                     logger.info( |                     logger.info( | ||||||
|                         f"Using resolved {object_type.__name__.lower()[1:]} {object_name} " |                         f"Using resolved {cls.object_type.__name__.lower()[1:]} {object_name} " | ||||||
|                         f"from '{module_path}'...") |                         f"from '{module_path}'...") | ||||||
|                     return module |                     return module | ||||||
|             except FileNotFoundError: |             except FileNotFoundError: | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ class PairListResolver(IResolver): | |||||||
|     """ |     """ | ||||||
|     This class contains all the logic to load custom PairList class |     This class contains all the logic to load custom PairList class | ||||||
|     """ |     """ | ||||||
|  |     object_type = IPairList | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def load_pairlist(pairlist_name: str, exchange, pairlistmanager, |     def load_pairlist(pairlist_name: str, exchange, pairlistmanager, | ||||||
| @@ -53,8 +54,9 @@ class PairListResolver(IResolver): | |||||||
|         abs_paths = IResolver.build_search_paths(config, current_path=current_path, |         abs_paths = IResolver.build_search_paths(config, current_path=current_path, | ||||||
|                                                  user_subdir=None, extra_dir=None) |                                                  user_subdir=None, extra_dir=None) | ||||||
|  |  | ||||||
|         pairlist = IResolver._load_object(paths=abs_paths, object_type=IPairList, |         pairlist = PairListResolver._load_object(paths=abs_paths, | ||||||
|                                           object_name=pairlist_name, kwargs=kwargs) |                                                  object_name=pairlist_name, | ||||||
|  |                                                  kwargs=kwargs) | ||||||
|         if pairlist: |         if pairlist: | ||||||
|             return pairlist |             return pairlist | ||||||
|         raise OperationalException( |         raise OperationalException( | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ class StrategyResolver(IResolver): | |||||||
|     """ |     """ | ||||||
|     This class contains the logic to load custom strategy class |     This class contains the logic to load custom strategy class | ||||||
|     """ |     """ | ||||||
|  |     object_type = IStrategy | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def load_strategy(config: Optional[Dict] = None) -> IStrategy: |     def load_strategy(config: Optional[Dict] = None) -> IStrategy: | ||||||
| @@ -134,7 +135,7 @@ class StrategyResolver(IResolver): | |||||||
|         """ |         """ | ||||||
|         current_path = Path(__file__).parent.parent.joinpath('strategy').resolve() |         current_path = Path(__file__).parent.parent.joinpath('strategy').resolve() | ||||||
|  |  | ||||||
|         abs_paths = IResolver.build_search_paths(config, current_path=current_path, |         abs_paths = StrategyResolver.build_search_paths(config, current_path=current_path, | ||||||
|                                                         user_subdir=constants.USERPATH_STRATEGY, |                                                         user_subdir=constants.USERPATH_STRATEGY, | ||||||
|                                                         extra_dir=extra_dir) |                                                         extra_dir=extra_dir) | ||||||
|  |  | ||||||
| @@ -154,8 +155,9 @@ class StrategyResolver(IResolver): | |||||||
|                 # register temp path with the bot |                 # register temp path with the bot | ||||||
|                 abs_paths.insert(0, temp.resolve()) |                 abs_paths.insert(0, temp.resolve()) | ||||||
|  |  | ||||||
|         strategy = IResolver._load_object(paths=abs_paths, object_type=IStrategy, |         strategy = StrategyResolver._load_object(paths=abs_paths, | ||||||
|                                           object_name=strategy_name, kwargs={'config': config}) |                                                  object_name=strategy_name, | ||||||
|  |                                                  kwargs={'config': config}) | ||||||
|         if strategy: |         if strategy: | ||||||
|             strategy._populate_fun_len = len(getfullargspec(strategy.populate_indicators).args) |             strategy._populate_fun_len = len(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) | ||||||
|   | |||||||
| @@ -20,7 +20,6 @@ def test_search_strategy(): | |||||||
|  |  | ||||||
|     s, _ = StrategyResolver._search_object( |     s, _ = StrategyResolver._search_object( | ||||||
|         directory=default_location, |         directory=default_location, | ||||||
|         object_type=IStrategy, |  | ||||||
|         kwargs={'config': default_config}, |         kwargs={'config': default_config}, | ||||||
|         object_name='DefaultStrategy' |         object_name='DefaultStrategy' | ||||||
|     ) |     ) | ||||||
| @@ -28,7 +27,6 @@ def test_search_strategy(): | |||||||
|  |  | ||||||
|     s, _ = StrategyResolver._search_object( |     s, _ = StrategyResolver._search_object( | ||||||
|         directory=default_location, |         directory=default_location, | ||||||
|         object_type=IStrategy, |  | ||||||
|         kwargs={'config': default_config}, |         kwargs={'config': default_config}, | ||||||
|         object_name='NotFoundStrategy' |         object_name='NotFoundStrategy' | ||||||
|     ) |     ) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user