From e829a5822f25e957fa837ef52868508eb3c7505e Mon Sep 17 00:00:00 2001 From: René 'Necoro' Neumann Date: Mon, 15 Sep 2008 08:43:06 +0200 Subject: New dependency handling. Should fix some bugs. --- portato/backend/package.py | 28 +-------- portato/dependency.py | 140 ++++++++++++++++++++------------------------ portato/gui/windows/main.py | 56 ++++++++---------- 3 files changed, 88 insertions(+), 136 deletions(-) diff --git a/portato/backend/package.py b/portato/backend/package.py index e4b2082..c9f87ac 100644 --- a/portato/backend/package.py +++ b/portato/backend/package.py @@ -180,34 +180,8 @@ class Package (_Package): deps = paren_reduce(deps) tree = DependencyTree() + tree.parse(deps) - def add (tree, deps): - it = iter(deps) - for dep in it: - if hasattr(dep, "__iter__"): - debug("Following dep is an unsupposed list: %s", dep) - assert(len(dep) == 1) - dep = dep[0] - if dep.endswith("?"): - ntree = tree.add_flag(dep[:-1]) - n = it.next() - if not hasattr(n, "__iter__"): - n = (n,) - add(ntree, n) - - elif dep == "||": - n = it.next() # skip - if not hasattr(n, "__iter__"): - n = [n] - else: - n = list(n) - - tree.add_or(n) - - else: - tree.add(dep) - - add(tree, deps) return tree # diff --git a/portato/dependency.py b/portato/dependency.py index ef06e41..1f1c5e1 100644 --- a/portato/dependency.py +++ b/portato/dependency.py @@ -17,6 +17,7 @@ Provides classes for the presentation of dependencies. from __future__ import absolute_import, with_statement __docformat__ = "restructuredtext" +from collections import defaultdict from .helper import debug from .backend import system @@ -69,66 +70,6 @@ class Dependency (object): satisfied = property(is_satisfied) -class OrDependency (Dependency): - """ - Dependency representing an "or". - - :note: Order is important. ``|| ( a b )`` != ``|| ( b a )`` - - :IVariables: - - dep : tuple(`Dependency`,...) - The dependencies. The tuple and the dependencies are immutable. - """ - - def __init__ (self, deps): - """ - Creates an or-dependency out of a list (or tuple) of deps. - - :param deps: The or'ed dependencies. - :type deps: iter - """ - - _dep = [] - for dep in deps: - if not hasattr(dep, "__iter__"): - assert not dep.endswith("?") - _dep.append(Dependency(dep)) - else: - _dep.append(AllOfDependency(dep)) - - self._dep = tuple(_dep) - - def __str__ (self): - return "<|| %s>" % str(self.dep) - - __repr__ = __str__ - -class AllOfDependency (Dependency): - """ - Dependency representing a set of packages inside "or". - If the or is: ``|| (a ( b c ) )`` the `AllOfDependency` would be the ``( b c )``. - - :IVariables: - - dep : tuple(`Dependency`,...) - The dependencies . The tuple and the deps are immutable. - """ - - def __init__ (self, deps): - """ - Creates an or-dependency out of a list (or tuple) of deps. - - :param deps: The dependencies. - :type deps: iter - """ - - self._dep = tuple(Dependency(dep) for dep in deps) - - def __str__ (self): - return "" % str(self.dep) - - __repr__ = __str__ class DependencyTree (object): @@ -147,8 +88,15 @@ class DependencyTree (object): def __init__ (self): self.deps = set() - self.flags = {} + self.flags = defaultdict(UseDependency) + self._ors = [] + self._subs = [] + def is_empty (self): + return not (self.deps or self.flags or self._ors or self._subs) + + empty = property(is_empty) + def add (self, dep, *moredeps): """ Adds one or more normal dependencies to the tree. @@ -166,14 +114,13 @@ class DependencyTree (object): for dep in moredeps: self.deps.add(Dependency(dep)) - def add_or (self, orlist): - """ - Adds a list of dependencies, which are or'ed. + def add_or (self): + o = OrDependency() + self._ors.append(o) + return o - :param orlist: the dependency list - :type orlist: iter - """ - self.deps.add(OrDependency(orlist)) + def add_sub (self): + return self def add_flag (self, flag): """ @@ -183,16 +130,53 @@ class DependencyTree (object): :param flag: the new flag :rtype: `DependencyTree` """ - if not flag in self.flags: - self.flags[flag] = DependencyTree() - return self.get_flag_tree(flag) + return self.flags[flag] # it's a defaultdict + + def parse (self, deps): + it = iter(deps) + for dep in it: + if dep[-1] == "?": + ntree = self.add_flag(dep[:-1]) + n = it.next() + if not hasattr(n, "__iter__"): + n = [n] + ntree.parse(n) + + elif dep == "||": + n = it.next() # skip + if not hasattr(n, "__iter__"): + n = [n] + + self.add_or().parse(n) + + elif isinstance(dep, list): + self.add_sub().parse(dep) + + else: + self.add(dep) - def get_flag_tree (self, flag): - """ - Returns the sub-tree of a specific tree. + def get_list(self, l): + for d in l[:]: + if d.is_empty(): + l.remove(d) + else: + yield d - :raises KeyError: if the flag is not (yet) in this tree - :rtype: `DependencyTree` - """ - return self.flags[flag] + def get_ors (self): + return self.get_list(self._ors) + + def get_subs (self): + return self.get_list(self._subs) + + ors = property(get_ors) + subs = property(get_subs) + +class OrDependency (DependencyTree): + def add_sub (self): + s = DependencyTree() + self._subs.append(s) + return s + +class UseDependency (DependencyTree): + pass diff --git a/portato/gui/windows/main.py b/portato/gui/windows/main.py index fca4535..eaed760 100644 --- a/portato/gui/windows/main.py +++ b/portato/gui/windows/main.py @@ -23,7 +23,7 @@ from collections import defaultdict # our backend stuff from ...backend import flags, system # must be the first to avoid circular deps -from ... import get_listener, plugin, dependency +from ... import get_listener, plugin from ...helper import debug, warning, error, info, unique_array from ...session import Session from ...constants import CONFIG_LOCATION, VERSION, APP_ICON, ICON_DIR @@ -208,17 +208,24 @@ class PackageTable: def fill_dep_list(self): store = self.depList.get_model() + + def sort_key (x): + split = system.split_cpv(x.dep) + + if split is None: # split_cpv returns None if this is only a CP; we assume there are only valid deps + return x.dep + else: + return "/".join(split[0:2]) + + def get_icon (dep): + if dep.satisfied: + return self.icons["installed"] + elif dep.dep[0] == "!": + return self.icons["block"] + else: + return None def add (tree, it): - - def get_icon (dep): - if dep.satisfied: - return self.icons["installed"] - elif dep.dep[0] == "!": - return self.icons["block"] - else: - return None - # useflags for use, usetree in tree.flags.iteritems(): if use[0] == "!": @@ -229,30 +236,17 @@ class PackageTable: add(usetree, useit) # ORs - ordeps = (dep for dep in tree.deps if isinstance(dep, dependency.OrDependency)) - - for ordep in ordeps: + for ortree in tree.ors: orit = store.append(it, [self.icons["or"], _("One of the following")]) + add(ortree, orit) - for dep in ordep.dep: - if isinstance(dep, dependency.AllOfDependency): # a list inside or - allit = store.append(orit, [None, _("All of the following")]) - for adep in dep.dep: - store.append(allit, [get_icon(adep), adep.dep]) - else: - store.append(orit, [get_icon(dep), dep.dep]) - - # normal - def sort_key (x): - split = system.split_cpv(x.dep) + # Sub (all of) + for subtree in tree.subs: + allit = store.append(it, [None, _("All of the following")]) + add(subtree, allit) - if split is None: # split_cpv returns None if this is only a CP; we assume there are only valid deps - return x.dep - else: - return "/".join(split[0:2]) - - ndeps = [dep for dep in tree.deps if not isinstance(dep, dependency.OrDependency)] - ndeps.sort(key = sort_key) + # normal + ndeps = sorted(tree.deps, key = sort_key) for dep in ndeps: store.append(it, [get_icon(dep), dep.dep]) -- cgit v1.2.3-70-g09d2