Remove EGG_MODULES to rely only on imported module path

This commit is contained in:
Cédric Krier
2023-10-12 01:30:18 +02:00
parent 058b8988a0
commit 80e19a25eb
7 changed files with 59 additions and 108 deletions
+2 -2
View File
@@ -33,7 +33,7 @@ if options.coroutine:
from gevent import monkey
monkey.patch_all()
from trytond.modules import get_module_info, get_module_list
from trytond.modules import get_module_info, get_modules
from trytond.pool import Pool
# Import trytond things after it is configured
from trytond.wsgi import app
@@ -67,7 +67,7 @@ with commandline.pidfile(options):
else:
ssl_args = {}
if options.dev and not options.coroutine:
for module in get_module_list():
for module in get_modules():
info = get_module_info(module)
for ext in ['xml',
'fodt', 'odt', 'fodp', 'odp', 'fods', 'ods', 'fodg', 'odg',
+2 -2
View File
@@ -25,8 +25,8 @@ def database_completer(parsed_args, **kwargs):
def module_completer(**kwargs):
from trytond.modules import get_module_list
return get_module_list()
from trytond.modules import get_modules
return get_modules()
def language_completer(**kwargs):
+1 -1
View File
@@ -239,7 +239,7 @@ class Lang(DeactivableMixin, ModelSQL, ModelView):
modules = Module.search([
('state', '=', 'activated'),
])
modules = [m.name for m in modules]
modules = {m.name for m in modules}
for node in create_graph(modules):
load_translations(pool, node, codes)
+2 -2
View File
@@ -10,7 +10,7 @@ from trytond.exceptions import UserError
from trytond.i18n import gettext
from trytond.model import ModelSQL, ModelView, Unique, fields, sequence_ordered
from trytond.model.exceptions import AccessError
from trytond.modules import get_module_info, get_module_list
from trytond.modules import get_module_info, get_modules
from trytond.pool import Pool
from trytond.pyson import Eval
from trytond.rpc import RPC
@@ -243,7 +243,7 @@ class Module(ModelSQL, ModelView):
"Update the list of available modules"
pool = Pool()
Dependency = pool.get('ir.module.dependency')
module_names = get_module_list(with_test=Pool.test)
module_names = get_modules(with_test=Pool.test)
for sub_module_names in grouped_slice(module_names):
cls.delete(cls.search([
('state', '!=', 'activated'),
+2 -2
View File
@@ -221,9 +221,9 @@ class View(ModelSQL, ModelView):
@property
def _module_index(self):
from trytond.modules import create_graph, get_module_list
from trytond.modules import create_graph, get_modules
if self.__class__.__module_index is None:
graph = create_graph(get_module_list(with_test=Pool.test))
graph = create_graph(get_modules(with_test=Pool.test))
modules = [m.name for m in graph]
self.__class__.__module_index = {
m: i for i, m in enumerate(reversed(modules))}
+29 -62
View File
@@ -5,10 +5,13 @@ import importlib
import itertools
import logging
import os
import sys
from collections import defaultdict
from glob import iglob
from importlib.machinery import SOURCE_SUFFIXES, FileFinder, SourceFileLoader
try:
import pkg_resources
except ImportError:
pkg_resources = None
from sql import Table
from sql.functions import CurrentTimestamp
@@ -45,40 +48,6 @@ def update_egg_modules():
update_egg_modules()
def import_module(name, fullname=None):
if fullname is None:
fullname = 'trytond.modules.' + name
try:
module = importlib.import_module(fullname)
except ImportError:
if name not in EGG_MODULES:
raise
ep = EGG_MODULES[name]
# Can not use ep.load because modules are declared in an importable
# path and it can not import submodule.
path = os.path.join(
ep.dist.location, *ep.module_name.split('.')[:-1])
if not os.path.isdir(path):
# Find module in path
for path in sys.path:
path = os.path.join(
path, *ep.module_name.split('.')[:-1])
if os.path.isdir(os.path.join(path, name)):
break
else:
# When testing modules from setuptools location is the
# module directory
path = os.path.dirname(ep.dist.location)
spec = FileFinder(
path, (SourceFileLoader, SOURCE_SUFFIXES)
).find_spec(fullname)
if spec.loader:
module = spec.loader.load_module()
else:
raise
return module
def get_module_info(name):
"Return the content of the tryton.cfg"
module_config = configparser.ConfigParser()
@@ -139,20 +108,19 @@ class Node(list):
super(Node, self).append(node)
def create_graph(module_list):
module_list = set(module_list)
def create_graph(modules):
all_deps = set()
graph = Graph()
for module in module_list:
for module in modules:
info = get_module_info(module)
deps = info.get('depends', []) + [
d for d in info.get('extras_depend', []) if d in module_list]
d for d in info.get('extras_depend', []) if d in modules]
node = graph.add(module, deps)
assert node.info is None
node.info = info
all_deps.update(deps)
missing = all_deps - module_list
missing = all_deps - modules
if missing:
raise MissingDependenciesException(list(missing))
return graph
@@ -323,8 +291,8 @@ def load_module_graph(graph, pool, update=None, lang=None):
logger.info('all modules loaded')
def get_module_list(with_test=False):
module_list = set()
def get_modules(with_test=False):
modules = {'ir', 'res'}
if os.path.exists(MODULES_PATH) and os.path.isdir(MODULES_PATH):
for file in os.listdir(MODULES_PATH):
if file.startswith('.'):
@@ -332,14 +300,13 @@ def get_module_list(with_test=False):
if file == '__pycache__':
continue
if os.path.isdir(OPJ(MODULES_PATH, file)):
module_list.add(file)
update_egg_modules()
module_list.update(EGG_MODULES.keys())
module_list.add('ir')
module_list.add('res')
modules.add(file)
if pkg_resources:
for ep in pkg_resources.iter_entry_points('trytond.modules'):
modules.add(ep.name)
if with_test:
module_list.add('tests')
return list(module_list)
modules.add('tests')
return modules
def register_classes(with_test=False):
@@ -354,19 +321,19 @@ def register_classes(with_test=False):
import trytond.tests
trytond.tests.register()
for node in create_graph(get_module_list(with_test=with_test)):
module = node.name
logger.info('%s:registering classes', module)
for node in create_graph(get_modules(with_test=with_test)):
module_name = node.name
logger.info('%s:registering classes', module_name)
if module in ('ir', 'res', 'tests'):
MODULES.append(module)
if module_name in ('ir', 'res', 'tests'):
MODULES.append(module_name)
continue
the_module = import_module(module)
module = importlib.import_module(f'trytond.modules.{module_name}')
# Some modules register nothing in the Pool
if hasattr(the_module, 'register'):
the_module.register()
MODULES.append(module)
if hasattr(module, 'register'):
module.register()
MODULES.append(module_name)
def load_modules(
@@ -392,12 +359,12 @@ def load_modules(
cursor.execute(*ir_module.select(ir_module.name,
where=ir_module.state.in_(('activated', 'to upgrade',
'to remove'))))
module_list = [name for (name,) in cursor]
modules = {name for (name,) in cursor}
graph = None
while graph is None:
module_list += update
modules.update(update)
try:
graph = create_graph(module_list)
graph = create_graph(modules)
except MissingDependenciesException as e:
if not activatedeps:
raise
+21 -37
View File
@@ -8,7 +8,6 @@ import importlib
import io
import os
import re
import sys
import types
import unicodedata
import warnings
@@ -32,7 +31,6 @@ def file_open(name, mode="r", subdir='modules', encoding=None):
def find_path(name, subdir='modules', _test=os.path.isfile):
"Return path from the root directory, using subdir folder"
from trytond.modules import EGG_MODULES
root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def secure_join(root, *paths):
@@ -43,45 +41,31 @@ def find_path(name, subdir='modules', _test=os.path.isfile):
raise IOError("Permission denied: %s" % name)
return path
egg_name = False
if subdir == 'modules':
module_name = name.split(os.sep)[0]
if module_name in EGG_MODULES:
epoint = EGG_MODULES[module_name]
location = os.path.dirname(epoint.load().__file__)
mod_path = os.path.join(location,
*epoint.module_name.split('.')[:-1])
mod_path = os.path.abspath(mod_path)
egg_name = secure_join(mod_path, name)
if not _test(egg_name):
# Find module in path
for path in sys.path:
mod_path = os.path.join(path,
*epoint.module_name.split('.')[:-1])
mod_path = os.path.abspath(mod_path)
egg_name = secure_join(mod_path, name)
if _test(egg_name):
break
if not _test(egg_name):
# When testing modules from setuptools location is the
# module directory
egg_name = secure_join(
os.path.dirname(location), name)
if subdir:
if (subdir == 'modules'
and (name.startswith('ir' + os.sep)
or name.startswith('res' + os.sep)
or name.startswith('tests' + os.sep))):
name = secure_join(root_path, name)
if subdir == 'modules':
try:
module_name, module_path = name.split(os.sep, 1)
except ValueError:
module_name, module_path = name, None
if module_name in {'ir', 'res', 'tests'}:
path = secure_join(root_path, module_name, module_path)
else:
try:
module = importlib.import_module(
f'trytond.modules.{module_name}')
except ModuleNotFoundError:
path = secure_join(root_path, subdir, name)
else:
path = os.path.dirname(module.__file__)
if module_path:
path = secure_join(path, module_path)
else:
name = secure_join(root_path, subdir, name)
path = secure_join(root_path, subdir, name)
else:
name = secure_join(root_path, name)
path = secure_join(root_path, name)
for path in [name, egg_name]:
if path and _test(path):
return path
if _test(path):
return path
else:
raise FileNotFoundError("No such file or directory: %r" % name)