1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
# This module defines package relationships.
# It exports two special "version" values: Virtual and Any.
# A Virtual version never matches a versioned conflict or dependency.
# An Any version always matches a versioned conflict or dependency.
# Copyright (C) 1998 Richard Braakman
#
# This program is free software. It is distributed 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, you can find it on the World Wide
# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301, USA.
import string
import version
# The two special "version" values. All empty lists are unique,
# so these statements initialize them to unique values.
Virtual = []
Any = []
# The basic relationship: a single package name.
# Its name is stored in the name attribute.
class SimpleRelation:
def __init__(self, package):
self.name = package
def __str__(self):
return self.name
def __repr__(self):
return 'SimpleRelation(' + `self.name` + ')'
def satisfied(self, packagename, version):
return packagename == self.name
def satisfied_by(self, packages):
if packages.has_key(self.name):
return self.name
return None
def packagenames(self):
return [self.name]
# A package name with a version check.
# The package name is stored in the name attribute.
# The relation is stored as a string in the relationstring attribute,
# and as a comparison function in the relation attribute.
# The version to compare to is stored in the version attribute.
class VersionedRelation:
def __init__(self, package, relation, version):
self.name = package
self.version = version
self.relationstring = relation
if relation == '<' or relation == '<=':
self.relation = lessthan
elif relation == '>' or relation == '>=':
self.relation = greaterthan
elif relation == '=':
self.relation = equalversion
elif relation == '>>':
self.relation = strictgreater
elif relation == '<<':
self.relation = strictless
else:
raise ValueError, 'relation: ' + relation
def __str__(self):
return '%s (%s %s)' % (self.name, self.relationstring, self.version)
def __repr__(self):
return 'VersionedRelation(' + `self.name` + ', ' + \
`self.relationstring` + ', ' + `self.version` + ')'
# version can be the special values Virtual or Any, in addition
# to a normal Version instance.
def satisfied(self, packagename, version):
if packagename != self.name or version is Virtual:
return 0
if version is Any:
return 1
return self.relation(version, self.version)
def satisfied_by(self, packages):
version = packages.get(self.name)
if version is not None and self.satisfied(self.name, version):
return self.name
return None
def packagenames(self):
return [self.name]
# Relations joined with the "alternatives" operator, i.e. foo | bar.
# This class just stores the joined relations as a sequence.
class AltRelation:
def __init__(self, relationlist):
self.relations = relationlist
def __str__(self):
return string.join(map(str, self.relations), ' | ')
def __repr__(self):
return 'AltRelation(' + `self.relations` + ')'
def satisfied(self, packagename, version):
for rel in self.relations:
if rel.satisfied(packagename, version):
return 1
return 0
def satisfied_by(self, packages):
rv = []
for rel in self.relations:
sb = rel.satisfied_by(packages)
if sb is not None and rv.count(sb) == 0:
rv.append(sb)
if len(rv) > 0:
return rv
return None
def packagenames(self):
return reduce(lambda x, y: x + y.packagenames(), self.relations, [])
def parsealt(str):
i = string.find(str, '(')
if i == -1:
return SimpleRelation(string.strip(str))
packagename = string.strip(str[:i])
j = string.find(str, ')')
relver = string.strip(str[i+1:j])
if relver[1] == '<' or relver[1] == '=' or relver[1] == '>':
return VersionedRelation(packagename, relver[:2],
version.make(string.strip(relver[2:])))
else:
return VersionedRelation(packagename, relver[:1],
version.make(string.strip(relver[1:])))
def parse(str):
alts = map(parsealt, string.split(str, '|'))
if len(alts) > 1:
return AltRelation(alts)
return alts[0]
# Possible values for the relation attribute
def strictless(x, y):
return x < y
def lessthan(x, y):
return x <= y
def equalversion(x, y):
return x.equals(y)
def greaterthan(x, y):
return x >= y
def strictgreater(x, y):
return x > y
|