[IMP] refactoring: move function topological_sort to openerp.tools

This commit is contained in:
Raphael Collet 2014-08-08 10:45:17 +02:00
parent 7f82caa1a4
commit 207013c74f
3 changed files with 35 additions and 48 deletions

View File

@ -32,6 +32,7 @@ except ImportError:
import openerp
import openerp.modules.registry
from openerp.addons.base.ir.ir_qweb import AssetsBundle, QWebTemplateNotFound
from openerp.tools import topological_sort
from openerp.tools.translate import _
from openerp import http
@ -141,50 +142,6 @@ def ensure_db(redirect='/web/database/selector'):
request.session.db = db
def module_topological_sort(modules):
""" Return a list of module names sorted so that their dependencies of the
modules are listed before the module itself
modules is a dict of {module_name: dependencies}
:param modules: modules to sort
:type modules: dict
:returns: list(str)
"""
dependencies = set(itertools.chain.from_iterable(modules.itervalues()))
# incoming edge: dependency on other module (if a depends on b, a has an
# incoming edge from b, aka there's an edge from b to a)
# outgoing edge: other module depending on this one
# [Tarjan 1976], http://en.wikipedia.org/wiki/Topological_sorting#Algorithms
#L ← Empty list that will contain the sorted nodes
L = []
#S ← Set of all nodes with no outgoing edges (modules on which no other
# module depends)
S = set(module for module in modules if module not in dependencies)
visited = set()
#function visit(node n)
def visit(n):
#if n has not been visited yet then
if n not in visited:
#mark n as visited
visited.add(n)
#change: n not web module, can not be resolved, ignore
if n not in modules: return
#for each node m with an edge from m to n do (dependencies of n)
for m in modules[n]:
#visit(m)
visit(m)
#add n to L
L.append(n)
#for each node n in S do
for n in S:
#visit(n)
visit(n)
return L
def module_installed():
# Candidates module the current heuristic is the /static dir
loadable = http.addons_manifest.keys()
@ -202,7 +159,7 @@ def module_installed():
dependencies = [i['name'] for i in deps_read]
modules[module['name']] = dependencies
sorted_modules = module_topological_sort(modules)
sorted_modules = topological_sort(modules)
return sorted_modules
def module_installed_bypass_session(dbname):
@ -224,7 +181,7 @@ def module_installed_bypass_session(dbname):
modules[module['name']] = dependencies
except Exception,e:
pass
sorted_modules = module_topological_sort(modules)
sorted_modules = topological_sort(modules)
return sorted_modules
def module_boot(db=None):

View File

@ -3,7 +3,7 @@
import random
import unittest2
from ..controllers.main import module_topological_sort as sort
from openerp.tools import topological_sort
def sample(population):
return random.sample(
@ -22,7 +22,7 @@ class TestModulesLoading(unittest2.TestCase):
ms = dict(modules)
seen = set()
sorted_modules = sort(ms)
sorted_modules = topological_sort(ms)
for module in sorted_modules:
deps = ms[module]
self.assertGreaterEqual(

View File

@ -278,6 +278,36 @@ def reverse_enumerate(l):
"""
return izip(xrange(len(l)-1, -1, -1), reversed(l))
def topological_sort(elems):
""" Return a list of elements sorted so that their dependencies are listed
before them in the result.
:param elems: specifies the elements to sort with their dependencies; it is
a dictionary like `{element: dependencies}` where `dependencies` is a
collection of elements that must appear before `element`. The elements
of `dependencies` are not required to appear in `elems`; they will
simply not appear in the result.
:returns: a list with the keys of `elems` sorted according to their
specification.
"""
# the algorithm is inspired by [Tarjan 1976],
# http://en.wikipedia.org/wiki/Topological_sorting#Algorithms
result = []
visited = set()
def visit(n):
if n not in visited:
visited.add(n)
if n in elems:
# first visit all dependencies of n, then append n to result
map(visit, elems[n])
result.append(n)
map(visit, elems)
return result
class UpdateableStr(local):
""" Class that stores an updateable string (used in wizards)