def rollback(self): from trytond.cache import Cache for cache in self.cache.values(): cache.clear() for datamanager in self._datamanagers: datamanager.tpc_abort(self) Cache.rollback(self) self.connection.rollback()
def load_module_graph(graph, pool, update=None, lang=None): # Prevent to import backend when importing module from trytond.cache import Cache from trytond.ir.lang import get_parent_language if lang is None: lang = [config.get('database', 'language')] if update is None: update = [] modules_todo = [] models_to_update_history = set() # Load also parent languages lang = set(lang) for code in list(lang): while code: lang.add(code) code = get_parent_language(code) transaction = Transaction() with transaction.connection.cursor() as cursor: modules = [x.name for x in graph] module2state = dict() for sub_modules in tools.grouped_slice(modules): cursor.execute( *ir_module.select(ir_module.name, ir_module.state, where=ir_module.name.in_(list(sub_modules)))) module2state.update(cursor) modules = set(modules) for node in graph: module = node.name if module not in MODULES: continue logger.info(module) classes = pool.fill(module, modules) if update: pool.setup(classes) package_state = module2state.get(module, 'not activated') if (is_module_to_install(module, update) or (update and package_state in ('to activate', 'to upgrade'))): if package_state not in ('to activate', 'to upgrade'): if package_state == 'activated': package_state = 'to upgrade' elif package_state != 'to remove': package_state = 'to activate' for child in node: module2state[child.name] = package_state for type in list(classes.keys()): for cls in classes[type]: logger.info('%s:register %s', module, cls.__name__) cls.__register__(module) for model in classes['model']: if hasattr(model, '_history'): models_to_update_history.add(model.__name__) # Instanciate a new parser for the module tryton_parser = convert.TrytondXmlHandler( pool, module, package_state, modules, lang) for filename in node.info.get('xml', []): filename = filename.replace('/', os.sep) logger.info('%s:loading %s', module, filename) # Feed the parser with xml content: with tools.file_open(OPJ(module, filename), 'rb') as fp: tryton_parser.parse_xmlstream(fp) modules_todo.append((module, list(tryton_parser.to_delete))) load_translations(pool, node, lang) if package_state == 'to remove': continue cursor.execute(*ir_module.select( ir_module.id, where=(ir_module.name == module))) try: module_id, = cursor.fetchone() cursor.execute( *ir_module.update([ir_module.state], ['activated'], where=(ir_module.id == module_id))) except TypeError: cursor.execute(*ir_module.insert([ ir_module.create_uid, ir_module.create_date, ir_module.name, ir_module.state ], [ [0, CurrentTimestamp(), module, 'activated'], ])) module2state[module] = 'activated' # Avoid clearing cache to prevent dead lock on ir.cache table Cache.rollback(transaction) transaction.commit() # Clear transaction cache to update default_factory transaction.cache.clear() if not update: pool.setup() else: # Remove unknown models and fields Model = pool.get('ir.model') Model.clean() ModelField = pool.get('ir.model.field') ModelField.clean() transaction.commit() pool.setup_mixin(modules) for model_name in models_to_update_history: model = pool.get(model_name) if model._history: logger.info('history:update %s', model.__name__) model._update_history_table() # Vacuum : while modules_todo: (module, to_delete) = modules_todo.pop() convert.post_import(pool, module, to_delete) # Ensure cache is clear for other instances Cache.clear_all() Cache.refresh_pool(transaction) logger.info('all modules loaded')
def load_module_graph(graph, pool, update=None, lang=None): from trytond.ir.lang import get_parent_language if lang is None: lang = [config.get('database', 'language')] if update is None: update = [] modules_todo = [] models_to_update_history = set() # Load also parent languages lang = set(lang) for code in list(lang): while code: lang.add(code) code = get_parent_language(code) transaction = Transaction() with transaction.connection.cursor() as cursor: modules = [x.name for x in graph] module2state = dict() for sub_modules in tools.grouped_slice(modules): cursor.execute( *ir_module.select(ir_module.name, ir_module.state, where=ir_module.name.in_(list(sub_modules)))) module2state.update(cursor.fetchall()) modules = set(modules) for node in graph: module = node.name if module not in MODULES: continue logger.info(module) classes = pool.fill(module, modules) if update: pool.setup(classes) pool.post_init(module) package_state = module2state.get(module, 'not activated') if (is_module_to_install(module, update) or (update and package_state in ('to activate', 'to upgrade'))): if package_state not in ('to activate', 'to upgrade'): if package_state == 'activated': package_state = 'to upgrade' elif package_state != 'to remove': package_state = 'to activate' for child in node: module2state[child.name] = package_state for type in list(classes.keys()): for cls in classes[type]: logger.info('%s:register %s', module, cls.__name__) cls.__register__(module) for model in classes['model']: if hasattr(model, '_history'): models_to_update_history.add(model.__name__) # Instanciate a new parser for the module tryton_parser = convert.TrytondXmlHandler( pool, module, package_state, modules) for filename in node.info.get('xml', []): filename = filename.replace('/', os.sep) logger.info('%s:loading %s', module, filename) # Feed the parser with xml content: with tools.file_open(OPJ(module, filename), 'rb') as fp: tryton_parser.parse_xmlstream(fp) modules_todo.append((module, list(tryton_parser.to_delete))) localedir = '%s/%s' % (node.info['directory'], 'locale') lang2filenames = defaultdict(list) for filename in itertools.chain( iglob('%s/*.po' % localedir), iglob('%s/override/*.po' % localedir)): filename = filename.replace('/', os.sep) lang2 = os.path.splitext(os.path.basename(filename))[0] if lang2 not in lang: continue lang2filenames[lang2].append(filename) base_path_position = len(node.info['directory']) + 1 for language, files in lang2filenames.items(): filenames = [f[base_path_position:] for f in files] logger.info('%s:loading %s', module, ','.join(filenames)) Translation = pool.get('ir.translation') Translation.translation_import(language, module, files) if package_state == 'to remove': continue cursor.execute(*ir_module.select( ir_module.id, where=(ir_module.name == module))) try: module_id, = cursor.fetchone() cursor.execute( *ir_module.update([ir_module.state], ['activated'], where=(ir_module.id == module_id))) except TypeError: cursor.execute(*ir_module.insert([ ir_module.create_uid, ir_module.create_date, ir_module.name, ir_module.state ], [ [0, CurrentTimestamp(), module, 'activated'], ])) module2state[module] = 'activated' # Avoid clearing cache to prevent dead lock on ir.cache table Cache.rollback(transaction) transaction.commit() if not update: pool.setup() else: # Remove unknown models and fields Model = pool.get('ir.model') Model.clean() ModelField = pool.get('ir.model.field') ModelField.clean() transaction.commit() # JCA: Add update parameter to post init hooks pool.post_init(None) pool.setup_mixin(modules) for model_name in models_to_update_history: model = pool.get(model_name) if model._history: logger.info('history:update %s', model.__name__) model._update_history_table() # Vacuum : while modules_todo: (module, to_delete) = modules_todo.pop() convert.post_import(pool, module, to_delete) logger.info('all modules loaded')