############################################################################## # # Copyright (c) 2004 TINY SPRL. (http://tiny.be) # # $Id: __init__.py 1308 2005-09-08 18:02:01Z pinky $ # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsability of assessing all potential # consequences resulting from its eventual inadequacies and bugs # End users who are looking for a ready-to-use solution with commercial # garantees and support are strongly adviced to contact a Free Software # Service Company # # This program is Free Software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## import os, sys, imp import itertools from sets import Set import osv import sql_db import tools import netsvc logger = netsvc.Logger() opj = os.path.join ad = tools.config['addons_path'] sys.path.insert(1,ad) class Graph(dict): def addNode(self, name, deps): max_depth, father = 0, None for n in [Node(x, self) for x in deps]: if n.depth >= max_depth: father = n max_depth = n.depth if father: father.addChild(name) else: Node(name, self) def __iter__(self): base = [n for n in self.values() if n.depth==0] return itertools.chain(iter(base), *map(iter, base)) class Singleton(object): def __new__(cls, name, graph): if name in graph: inst = graph[name] else: inst = object.__new__(cls) inst.name = name graph[name] = inst return inst class Node(Singleton): def __init__(self, name, graph): self.graph = graph if not hasattr(self, 'childs'): self.childs = [] if not hasattr(self, 'depth'): self.depth = 0 def addChild(self, name): node = Node(name, self.graph) node.depth = self.depth + 1 if node not in self.childs: self.childs.append(node) for attr in ('init', 'update', 'demo'): if hasattr(self, attr): setattr(node, attr, True) self.childs.sort(lambda x,y: cmp(x.name, y.name)) def hasChild(self, name): return Node(name, self.graph) in self.childs or \ bool([c for c in self.childs if c.hasChild(name)]) def __setattr__(self, name, value): super(Singleton, self).__setattr__(name, value) if name in ('init', 'update', 'demo'): tools.config[name][self.name] = 1 for child in self.childs: setattr(child, name, value) if name == 'depth': for child in self.childs: setattr(child, name, value + 1) def __iter__(self): return itertools.chain(iter(self.childs), *map(iter, self.childs)) def __str__(self): return self._pprint() def _pprint(self, depth=0): s = '%s\n' % self.name for c in self.childs: s += '%s`-> %s' % (' ' * depth, c._pprint(depth+1)) return s def create_graph(): graph = Graph() packages = [] for i in os.listdir(ad): terp_file = opj(ad, i, '__terp__.py') if os.path.isfile(terp_file): info = eval(file(terp_file).read()) if info.get('active', True): packages.append((i, info.get('depends', []), info)) current,later = Set([p for p, dep, data in packages]), Set() while packages and current > later: package, deps, datas = packages[0] # if all dependencies of 'package' are already in the graph, add 'package' in the graph if reduce(lambda x,y: x and y in graph, deps, True): later.clear() current.remove(package) graph.addNode(package, deps) node = Node(package, graph) node.datas = datas for kind in ('init', 'demo', 'update'): if package in tools.config[kind] or 'all' in tools.config[kind]: setattr(node, kind, True) else: later.add(package) packages.append((package, deps, datas)) packages = packages[1:] for package in later: logger.notifyChannel('init', netsvc.LOG_ERROR, 'addon:%s:Unmet dependency' % package) return graph def load_modules(graph): package_todo = [] for package in graph: m = package.name logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s' % m) sys.stdout.flush() imp.load_module(m, *imp.find_module(m)) idref = {} if hasattr(package, 'init') or hasattr(package, 'update'): for kind in ('init', 'update'): for xml in package.datas.get('%s_xml' % kind, []): mode = 'update' if hasattr(package, 'init'): mode = 'init' logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s:loading %s' % (m, xml)) tools.convert_xml_import(m, tools.file_open(opj(m, xml)).read(), idref, mode=mode) if hasattr(package, 'demo'): for xml in package.datas.get('demo_xml', []): logger.notifyChannel('init', netsvc.LOG_INFO, 'addon:%s:loading %s' % (m, xml)) tools.convert_xml_import(m, tools.file_open(opj(m, xml)).read(), idref) package_todo.append(package.name) pool=osv.osv.osv_pools cr=sql_db.db.cursor() pool.get('ir.model.data')._process_end(cr, 1, package_todo) cr.commit() cr.close() def main(): g = create_graph() load_modules(g) main()