summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRené 'Necoro' Neumann <necoro@necoro.net>2008-09-15 08:43:06 +0200
committerRené 'Necoro' Neumann <necoro@necoro.net>2008-09-15 08:43:06 +0200
commite829a5822f25e957fa837ef52868508eb3c7505e (patch)
treec59cdd5b46857d34f543ac6f0a0b0ee08326c641
parent839d5c95803272546a0348743f09a8da56bc006a (diff)
downloadportato-e829a5822f25e957fa837ef52868508eb3c7505e.tar.gz
portato-e829a5822f25e957fa837ef52868508eb3c7505e.tar.bz2
portato-e829a5822f25e957fa837ef52868508eb3c7505e.zip
New dependency handling. Should fix some bugs.
-rw-r--r--portato/backend/package.py28
-rw-r--r--portato/dependency.py140
-rw-r--r--portato/gui/windows/main.py56
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<string>
- """
-
- _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<string>
- """
-
- self._dep = tuple(Dependency(dep) for dep in deps)
-
- def __str__ (self):
- return "<ALL %s>" % 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<string>
- """
- 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])