aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Stubbs <jstubbs@gentoo.org>2005-04-24 16:28:51 +0000
committerJason Stubbs <jstubbs@gentoo.org>2005-04-24 16:28:51 +0000
commit8ab081659172331d6ac4ac9a943deb12a21d139e (patch)
tree8f9ee6c5f0de7e52e087dfe5ff99e4591a6c2884
parentRemoved support for --inject and --upgradeonly as well as the now unused (diff)
downloadportage-cvs-8ab081659172331d6ac4ac9a943deb12a21d139e.tar.gz
portage-cvs-8ab081659172331d6ac4ac9a943deb12a21d139e.tar.bz2
portage-cvs-8ab081659172331d6ac4ac9a943deb12a21d139e.zip
Added a class called DependSpec which handles parsing *DEPEND and SRC_URI
strings. Read-only at the moment, but will probably change later.
-rw-r--r--ChangeLog6
-rw-r--r--pym/portage_syntax.py236
2 files changed, 175 insertions, 67 deletions
diff --git a/ChangeLog b/ChangeLog
index ced4d9b..bc96270 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,12 +1,16 @@
# ChangeLog for Portage; the Gentoo Linux ports system
# Copyright 1999-2005 Gentoo Foundation; Distributed under the GPL v2
-# $Id: ChangeLog,v 1.952 2005/04/24 12:49:01 jstubbs Exp $
+# $Id: ChangeLog,v 1.953 2005/04/24 16:28:51 jstubbs Exp $
MAJOR CHANGES in 2.0.51:
1. /var/cache/edb/virtuals is no longer used at all. It's calculated now.
2. /var/cache/edb/world is now /var/lib/portage/world.
3. /etc/portage/profile/virtuals is _USER_ configs only.
+ 24 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage_syntax.py:
+ Added a class called DependSpec which handles parsing *DEPEND and SRC_URI
+ strings. Read-only at the moment, but will probably change later.
+
24 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge pym/portage.py:
Removed support for --inject and --upgradeonly as well as the now unused
digraph class.
diff --git a/pym/portage_syntax.py b/pym/portage_syntax.py
index 77906f2..f31742d 100644
--- a/pym/portage_syntax.py
+++ b/pym/portage_syntax.py
@@ -7,40 +7,40 @@ suffix_regexp = re.compile("^(alpha|beta|rc|pre|p)(\\d*)$")
suffix_value = {"pre": -2, "p": 0, "alpha": -4, "beta": -3, "rc": -1}
class CPV(object):
-
+
"""
Attributes
-
+
str category
str package
str key (cat/pkg)
str version
int revision
-
+
Methods
-
+
int __hash__()
str __repr__()
int __cmp__(CPV)
"""
-
+
def __init__(self, cpvstr):
if not isinstance(cpvstr, str):
raise ValueError(cpvstr)
self.__dict__["cpvstr"] = cpvstr
self.__dict__["hash"] = hash(cpvstr)
-
+
def __hash__(self):
return self.hash
-
+
def __repr__(self):
return self.cpvstr
-
+
def __setattr__(self, name, value):
raise Exception()
-
+
def __getattr__(self, name):
-
+
if name == "category":
myparts = self.cpvstr.split("/")
if len(myparts) >= 2:
@@ -50,7 +50,7 @@ class CPV(object):
else:
self.__dict__["category"] = None
return self.category
-
+
if name == "package":
if self.category:
myparts = self.cpvstr[len(self.category)+1:].split("-")
@@ -66,77 +66,77 @@ class CPV(object):
raise ValueError(self.cpvstr)
self.__dict__["package"] = pkgname
return self.package
-
+
if name == "key":
if self.category:
self.__dict__["key"] = self.category +"/"+ self.package
else:
self.__dict__["key"] = self.package
return self.key
-
+
if name == "version" or name == "revision":
if self.category:
myparts = self.cpvstr[len(self.category+self.package)+2:].split("-")
else:
myparts = self.cpvstr[len(self.package)+1:].split("-")
-
+
if not myparts[0]:
self.__dict__["version"] = None
self.__dict__["revision"] = None
-
+
else:
if myparts[-1][0] == "r" and myparts[-1][1:].isdigit():
self.__dict__["revision"] = int(myparts[-1][1:])
myparts = myparts[:-1]
else:
self.__dict__["revision"] = 0
-
+
for x in myparts:
if not ver_regexp.match(x):
raise ValueError(self.mycpv)
-
+
self.__dict__["version"] = "-".join(myparts)
-
+
if name == "version":
return self.version
else:
return self.revision
-
+
raise AttributeError(name)
-
+
def __cmp__(self, other):
-
+
if self.cpvstr == other.cpvstr:
return 0
-
+
if self.category and other.category and self.category != other.category:
return cmp(self.category, other.category)
-
+
if self.package and other.package and self.package != other.package:
return cmp(self.package, other.package)
-
+
if self.version != other.version:
-
+
if self.version is None:
raise ValueError(self)
-
+
if other.version is None:
raise ValueError(other)
-
+
match1 = ver_regexp.match(self.version)
match2 = ver_regexp.match(other.version)
-
+
# shortcut for cvs ebuilds (new style)
if match1.group(1) and not match2.group(1):
return 1
elif match2.group(1) and not match1.group(1):
return -1
-
+
# building lists of the version parts before the suffix
# first part is simple
list1 = [string.atoi(match1.group(2))]
list2 = [string.atoi(match2.group(2))]
-
+
# this part would greatly benefit from a fixed-length version pattern
if len(match1.group(3)) or len(match2.group(3)):
vlist1 = match1.group(3)[1:].split(".")
@@ -156,13 +156,13 @@ class CPV(object):
else:
list1.append(string.atof("0."+vlist1[i]))
list2.append(string.atof("0."+vlist2[i]))
-
+
# and now the final letter
if len(match1.group(5)):
list1.append(ord(match1.group(5)))
if len(match2.group(5)):
list2.append(ord(match2.group(5)))
-
+
for i in range(0, max(len(list1), len(list2))):
if len(list1) <= i:
return -1
@@ -170,11 +170,11 @@ class CPV(object):
return 1
elif list1[i] != list2[i]:
return list1[i] - list2[i]
-
+
# main version is equal, so now compare the _suffix part
list1 = match1.group(6).split("_")[1:]
list2 = match2.group(6).split("_")[1:]
-
+
for i in range(0, max(len(list1), len(list2))):
if len(list1) <= i:
s1 = ("p","0")
@@ -194,53 +194,53 @@ class CPV(object):
try: r2 = string.atoi(s2[1])
except ValueError: r2 = 0
return r1 - r2
-
+
return cmp(self.revision, other.revision)
class Atom(object):
-
+
"""
Attributes
-
+
bool blocks
str operator
bool glob_match
CPV cpv
-
+
Methods
int __hash__()
str __repr__()
bool match(CPV)
"""
-
+
def __init__(self, atomstr):
if not isinstance(atomstr, str):
raise ValueError(atomstr)
self.__dict__["atomstr"] = atomstr
self.__dict__["hash"] = hash(atomstr)
-
+
def __hash__(self):
return self.hash
-
+
def __repr__(self):
return self.atomstr
-
+
def __setattr__(self, name, value):
raise Exception()
-
+
def __getattr__(self, name):
-
+
if not self.__dict__.has_key("category"):
-
+
myatom = self.atomstr
-
+
if myatom[0] == "!":
self.__dict__["blocks"] = True
myatom = myatom[1:]
else:
self.__dict__["blocks"] = False
-
+
if myatom[0:2] in ["<=", ">="]:
self.__dict__["operator"] = myatom[0:2]
myatom = myatom[2:]
@@ -249,46 +249,46 @@ class Atom(object):
myatom = myatom[1:]
else:
self.__dict__["operator"] = None
-
+
if myatom[-1] == "*":
self.__dict__["glob_match"] = True
myatom = myatom[:-1]
else:
self.__dict__["glob_match"] = False
-
+
self.__dict__["cpv"] = CPV(myatom)
-
+
if self.operator != "=" and self.glob_match:
raise ValueError(self.atomstr)
-
+
if self.operator and not self.cpv.version:
raise ValueError(self.atomstr)
-
+
if not self.operator and self.cpv.version:
raise ValueError(self.atomstr)
-
+
if self.operator == "~" and self.cpv.revision:
raise ValueError(self.atomstr)
-
+
if self.glob_match and self.cpv.revision:
raise ValueError(self.atomstr)
-
+
if not self.__dict__.has_key(name):
raise AttributeError(name)
-
+
return self.__dict__[name]
-
+
def match(self, cpv):
-
+
if self.cpv.category and cpv.category and self.cpv.category != cpv.category:
return False
-
+
if self.cpv.package and cpv.package and self.cpv.package != cpv.package:
return False
-
+
if not self.operator:
return True
-
+
if self.operator == "=":
if self.glob_match and cpv.version.startswith(self.cpv.version):
return True
@@ -296,26 +296,130 @@ class Atom(object):
return False
if self.cpv.revision != cpv.revision:
return False
-
+
if self.operator == "~" and self.cpv.version == cpv.version:
return True
-
+
diff = cmp(self.cpv, cpv)
-
+
if not diff:
if self.operator == "<=" or self.operator == ">=":
return True
else:
return False
-
+
if diff > 0:
if self.operator[0] == "<":
return True
else:
return False
-
+
#if diff < 0:
if self.operator[0] == ">":
return True
#else:
return False
+
+
+class DependSpec:
+
+ def __init__(self, dependstr):
+ dependstr = " ".join(dependstr.split())
+ if not isinstance(dependstr, str):
+ raise ValueError(dependstr)
+ self.__dict__["origstr"] = dependstr
+ self.__dict__["hash"] = hash(dependstr)
+ self.__dict__["preferential"] = dependstr.startswith("||")
+ if self.preferential:
+ if dependstr[-1] != ")":
+ raise ValueError(self.dependstr)
+ dependstr = " ".join(dependstr[2:-1].split())
+ if not dependstr.startswith("("):
+ raise ValueError(self.dependstr)
+ self.__dict__["dependstr"] = " ".join(dependstr[1:])
+ else:
+ self.__dict__["dependstr"] = dependstr
+ self.__dict__["depstrlen"] = len(dependstr)
+ self.__dict__["parseidx"] = 0
+ self.__dict__["elements"] = []
+
+ def __hash__(self):
+ return self.hash
+
+ def __repr__(self):
+ return "DependSpec('" + self.origstr + "')"
+
+ def __setattr__(self, name, value):
+ raise Exception()
+
+ def __getitem__(self, index):
+ if index < len(self.elements):
+ return self.elements[index]
+ index -= len(self.elements)
+ while True:
+ use = None
+ element = ""
+ parseidx = self.parseidx
+ while parseidx < self.depstrlen:
+ c = self.dependstr[parseidx]
+ if c == "|" and not element and self.dependstr[parseidx:].startswith("||"):
+ parseidx += 2
+ (subdependstr, parseidx) = self._extract_dependstr(parseidx)
+ subdependstr = "|| (" + subdependstr + ")"
+ element = DependSpec(subdependstr)
+ break
+ if c == "(":
+ if element:
+ break
+ (subdependstr, parseidx) = self._extract_dependstr(parseidx)
+ element = DependSpec(subdependstr)
+ break
+ if c == ")":
+ raise ValueError(self.dependstr)
+ if c == " ":
+ parseidx += 1
+ if not element:
+ continue
+ if element[-1] == "?":
+ use = element[:-1]
+ if not use:
+ raise ValueError(self.dependstr)
+ element = ""
+ continue
+ break
+ element += c
+ parseidx += 1
+ self.__dict__["parseidx"] = parseidx
+ if use and not element:
+ raise ValueError(self.dependstr)
+ self.elements.append((use, element))
+ if index == 0:
+ return self.elements[-1]
+ if self.parseidx == self.depstrlen:
+ break
+ index -= 1
+ raise IndexError(index)
+
+ def _extract_dependstr(self, parseidx):
+ while self.dependstr[parseidx] != "(":
+ parseidx += 1
+ if parseidx == self.depstrlen or self.dependstr[parseidx] not in [" ", "("]:
+ raise ValueError(self.dependstr)
+ parseidx += 1
+ c = self.dependstr[parseidx]
+ subdependstr = ""
+ bracketcount = 0
+ while bracketcount or c != ")":
+ subdependstr += c
+ if c == "(":
+ bracketcount += 1
+ elif c == ")":
+ bracketcount -= 1
+ parseidx += 1
+ if parseidx == self.depstrlen:
+ break
+ c = self.dependstr[parseidx]
+ if bracketcount:
+ raise ValueError(self.dependstr)
+ parseidx += 1
+ return (subdependstr, parseidx)