diff --git a/CHANGELOG b/CHANGELOG index 8f7cc3b79c..de95cb0d63 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add option install module dependencies with trytond-admin * Add localhost_name and timeout as get_smtp_server uri parameters * Delete missing modules not activated when updating module list * Remove empty pages from notebook diff --git a/trytond/admin.py b/trytond/admin.py index fcc88b5ea4..7b08eec021 100644 --- a/trytond/admin.py +++ b/trytond/admin.py @@ -50,7 +50,8 @@ def run(options): lang = set() lang |= set(options.languages) pool = Pool(db_name) - pool.init(update=options.update, lang=list(lang)) + pool.init(update=options.update, lang=list(lang), + installdeps=options.installdeps) if options.update_modules_list: with Transaction().start(db_name, 0) as transaction: diff --git a/trytond/commandline.py b/trytond/commandline.py index f3f09d5037..ad070496d7 100644 --- a/trytond/commandline.py +++ b/trytond/commandline.py @@ -47,6 +47,9 @@ def get_parser_admin(): metavar='MODULE', help="update a module") parser.add_argument("--all", dest="update", action="append_const", const="ir", help="update all installed modules") + parser.add_argument("--install-dependencies", dest="installdeps", + action="store_true", + help="Install missing dependencies of updated modules") parser.add_argument("-p", "--password", dest="password", action='store_true', help="set the admin password") parser.add_argument("-m", "--update-modules-list", action="store_true", diff --git a/trytond/exceptions.py b/trytond/exceptions.py index acb37657fb..68922344e8 100644 --- a/trytond/exceptions.py +++ b/trytond/exceptions.py @@ -60,3 +60,12 @@ class ConcurrencyException(TrytonException): class RateLimitException(TrytonException): """User has sent too many requests in a given amount of time.""" + + +class MissingDependenciesException(TrytonException): + + def __init__(self, missings): + self.missings = missings + + def __str__(self): + return 'Missing dependencies: %s' % ' '.join(self.missings) diff --git a/trytond/modules/__init__.py b/trytond/modules/__init__.py index b25506fcae..5f18be4748 100644 --- a/trytond/modules/__init__.py +++ b/trytond/modules/__init__.py @@ -16,6 +16,7 @@ from sql.functions import CurrentTimestamp import trytond.tools as tools from trytond.config import config +from trytond.exceptions import MissingDependenciesException from trytond.transaction import Transaction from trytond import backend import trytond.convert as convert @@ -187,7 +188,7 @@ def create_graph(module_list): continue missings |= set((x for x in deps if x not in graph)) if missings: - raise Exception('Missing dependencies: %s' % list(missings + raise MissingDependenciesException(list(missings - set((p[0] for p in packages)))) return graph, packages, later @@ -379,10 +380,15 @@ def register_classes(): MODULES.append(module) -def load_modules(database_name, pool, update=None, lang=None): +def load_modules( + database_name, pool, update=None, lang=None, installdeps=False): res = True + if update: + update = update[:] + else: + update = [] - def _load_modules(): + def _load_modules(update): global res TableHandler = backend.get('TableHandler') transaction = Transaction() @@ -414,9 +420,15 @@ def load_modules(database_name, pool, update=None, lang=None): where=ir_module.state.in_(('activated', 'to upgrade', 'to remove')))) module_list = [name for (name,) in cursor.fetchall()] - if update: + graph = None + while graph is None: module_list += update - graph = create_graph(module_list)[0] + try: + graph = create_graph(module_list)[0] + except MissingDependenciesException as e: + if not installdeps: + raise + update += e.missings load_module_graph(graph, pool, update, lang) @@ -448,11 +460,11 @@ def load_modules(database_name, pool, update=None, lang=None): if not Transaction().connection: with Transaction().start(database_name, 0): - _load_modules() + _load_modules(update) else: with Transaction().new_transaction(), \ Transaction().set_user(0), \ Transaction().reset_context(): - _load_modules() + _load_modules(update) return res diff --git a/trytond/pool.py b/trytond/pool.py index 3b9a6eebf7..d110c770db 100644 --- a/trytond/pool.py +++ b/trytond/pool.py @@ -133,7 +133,7 @@ class Pool(object): ''' return self._locks[self.database_name] - def init(self, update=None, lang=None): + def init(self, update=None, lang=None, installdeps=False): ''' Init pool Set update to proceed to update @@ -152,7 +152,7 @@ class Pool(object): for type in self.classes.keys(): self._pool[self.database_name][type] = {} restart = not load_modules(self.database_name, self, update=update, - lang=lang) + lang=lang, installdeps=installdeps) if restart: self.init()