diff --git a/trytond/doc/ref/tools/misc.rst b/trytond/doc/ref/tools/misc.rst index 6d627f4b46..4b0caad5a5 100644 --- a/trytond/doc/ref/tools/misc.rst +++ b/trytond/doc/ref/tools/misc.rst @@ -4,6 +4,14 @@ Miscellaneous ============= +.. function:: entry_points() + + Return a collection of entry points. + +.. function:: import_module(name) + + Import the named Tryton module. + .. function:: file_open(name[, mode[, subdir[, encoding]]]) Open the named file in subdir from the root directory. diff --git a/trytond/trytond/const.py b/trytond/trytond/const.py index 07a56ec99c..ea07c6296c 100644 --- a/trytond/trytond/const.py +++ b/trytond/trytond/const.py @@ -20,3 +20,4 @@ OPERATORS = ( '<', '>', ) +MODULES_GROUP = 'trytond.modules' diff --git a/trytond/trytond/modules/__init__.py b/trytond/trytond/modules/__init__.py index 2d3aabbf3e..f3680f651a 100644 --- a/trytond/trytond/modules/__init__.py +++ b/trytond/trytond/modules/__init__.py @@ -1,24 +1,19 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import configparser -import importlib import itertools import logging import os from collections import defaultdict from glob import iglob -try: - from backports.entry_points_selectable import entry_points -except ImportError: - from importlib.metadata import entry_points - from sql import Table from sql.functions import CurrentTimestamp import trytond.convert as convert import trytond.tools as tools from trytond.config import config +from trytond.const import MODULES_GROUP from trytond.exceptions import MissingDependenciesException from trytond.transaction import Transaction @@ -286,7 +281,7 @@ def get_modules(with_test=False): continue if os.path.isdir(OPJ(MODULES_PATH, file)): modules.add(file) - for ep in entry_points().select(group='trytond.modules'): + for ep in tools.entry_points().select(group=MODULES_GROUP): modules.add(ep.name) if with_test: modules.add('tests') @@ -313,7 +308,7 @@ def register_classes(with_test=False): MODULES.append(module_name) continue - module = importlib.import_module(f'trytond.modules.{module_name}') + module = tools.import_module(module_name) # Some modules register nothing in the Pool if hasattr(module, 'register'): module.register() diff --git a/trytond/trytond/tools/__init__.py b/trytond/trytond/tools/__init__.py index e21820f61c..21c78cedc9 100644 --- a/trytond/trytond/tools/__init__.py +++ b/trytond/trytond/tools/__init__.py @@ -14,11 +14,12 @@ except ImportError: from .decimal_ import decistmt from .misc import ( - escape_wildcard, file_open, find_dir, find_path, firstline, - get_smtp_server, grouped_slice, is_full_text, is_instance_method, likify, - lstrip_wildcard, pairwise_longest, reduce_domain, reduce_ids, - remove_forbidden_chars, resolve, rstrip_wildcard, slugify, sortable_values, - sql_pairing, strip_wildcard, unescape_wildcard) + entry_points, escape_wildcard, file_open, find_dir, find_path, firstline, + get_smtp_server, grouped_slice, import_module, is_full_text, + is_instance_method, likify, lstrip_wildcard, pairwise_longest, + reduce_domain, reduce_ids, remove_forbidden_chars, resolve, + rstrip_wildcard, slugify, sortable_values, sql_pairing, strip_wildcard, + unescape_wildcard) class ClassProperty(property): @@ -41,6 +42,7 @@ __all__ = [ cached_property, cursor_dict, decistmt, + entry_points, escape_wildcard, file_open, find_dir, @@ -48,6 +50,7 @@ __all__ = [ firstline, get_smtp_server, grouped_slice, + import_module, is_full_text, is_instance_method, likify, diff --git a/trytond/trytond/tools/misc.py b/trytond/trytond/tools/misc.py index 725b17d76c..0529ff88c8 100644 --- a/trytond/trytond/tools/misc.py +++ b/trytond/trytond/tools/misc.py @@ -20,7 +20,28 @@ from sql import Literal from sql.conditionals import Case from sql.operators import Or -from trytond.const import OPERATORS +from trytond.const import MODULES_GROUP, OPERATORS + +try: + from backports.entry_points_selectable import entry_points as _entry_points +except ImportError: + from importlib.metadata import entry_points as _entry_points +_ENTRY_POINTS = None + + +def entry_points(): + global _ENTRY_POINTS + if _ENTRY_POINTS is None: + _ENTRY_POINTS = _entry_points() + return _ENTRY_POINTS + + +def import_module(name): + try: + ep, = entry_points().select(group=MODULES_GROUP, name=name) + except ValueError: + return importlib.import_module(f'{MODULES_GROUP}.{name}') + return ep.load() def file_open(name, mode="r", subdir='modules', encoding=None): @@ -51,8 +72,7 @@ def find_path(name, subdir='modules', _test=os.path.isfile): path = secure_join(root_path, module_name, module_path) else: try: - module = importlib.import_module( - f'trytond.modules.{module_name}') + module = import_module(module_name) except ModuleNotFoundError: path = secure_join(root_path, subdir, name) else: