summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2009-01-09 21:51:09 +0100
committerJulian Andres Klode <jak@debian.org>2009-01-09 21:51:09 +0100
commit5b0beca05b84919581e44af83824c47d7a49f02b (patch)
treef4e5c41d4b348978ad8c7e6ff4468f2586f22f52
parent2aaecf61a8f464a78d62fee62941bfda7244b031 (diff)
downloadpython-apt-5b0beca05b84919581e44af83824c47d7a49f02b.tar.gz
* apt/debfile: Fix and cleanup
This fixes various problems. Most things should work now. I have also removed the get*() methods, because we have not had these methods in a stable python-apt release yet, and they are deprecated.
-rw-r--r--apt/debfile.py402
1 files changed, 198 insertions, 204 deletions
diff --git a/apt/debfile.py b/apt/debfile.py
index 49826f6b..9730be35 100644
--- a/apt/debfile.py
+++ b/apt/debfile.py
@@ -19,24 +19,25 @@
# along with GDebi; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-
-import warnings
-warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
-import apt_inst, apt_pkg
-import sys
-import os
+"""Classes for working with locally available Debian packages."""
from gettext import gettext as _
+import os
+import sys
+
+import apt_inst
+import apt_pkg
+
# Constants for comparing the local package file with the version in the cache
-(VERSION_NONE,
- VERSION_OUTDATED,
- VERSION_SAME,
- VERSION_NEWER) = range(4)
+(VERSION_NONE, VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER) = range(4)
+
class NoDebArchiveException(IOError):
- pass
+ """Exception which is raised if a file is no Debian archive."""
+
class DebPackage(object):
+ """A Debian Package (.deb file)."""
_supported_data_members = ("data.tar.gz", "data.tar.bz2", "data.tar.lzma")
@@ -56,7 +57,9 @@ class DebPackage(object):
" open given debfile "
self.filename = filename
if not apt_inst.arCheckMember(open(self.filename), "debian-binary"):
- raise NoDebArchiveException, _("This is not a valid DEB archive, missing '%s' member" % "debian-binary")
+ raise NoDebArchiveException(_("This is not a valid DEB archive, "
+ "missing '%s' member" %
+ "debian-binary"))
control = apt_inst.debExtractControl(open(self.filename))
self._sections = apt_pkg.ParseSection(control)
self.pkgname = self._sections["Package"]
@@ -66,25 +69,30 @@ class DebPackage(object):
@property
def filelist(self):
- """ return the list of files in the deb """
+ """return the list of files in the deb."""
files = []
- def extract_cb(What,Name,Link,Mode,UID,GID,Size,MTime,Major,Minor):
- #print "%s '%s','%s',%u,%u,%u,%u,%u,%u,%u"\
- # % (What,Name,Link,Mode,UID,GID,Size, MTime, Major, Minor)
- files.append(Name)
+
+ def extract_cb(what, name, *_):
+ files.append(name)
+
for member in self._supported_data_members:
if apt_inst.arCheckMember(open(self.filename), member):
try:
- apt_inst.debExtract(open(self.filename), extract_cb, member)
+ apt_inst.debExtract(open(self.filename), extract_cb,
+ member)
break
- except SystemError, e:
- return [_("List of files for '%s'could not be read" % self.filename)]
+ except SystemError:
+ return [_("List of files for '%s'could not be read" %
+ self.filename)]
return files
def _isOrGroupSatisfied(self, or_group):
- """ this function gets a 'or_group' and analyzes if
- at least one dependency of this group is already satisfied """
- self._dbg(2,"_checkOrGroup(): %s " % (or_group))
+ """Return True if at least one dependency of the or-group is satisfied.
+
+ This method gets an 'or_group' and analyzes if at least one dependency
+ of this group is already satisfied.
+ """
+ self._dbg(2, "_checkOrGroup(): %s " % (or_group))
for dep in or_group:
depname = dep[0]
@@ -92,9 +100,10 @@ class DebPackage(object):
oper = dep[2]
# check for virtual pkgs
- if not self._cache.has_key(depname):
+ if not depname in self._cache:
if self._cache.isVirtualPackage(depname):
- self._dbg(3,"_isOrGroupSatisfied(): %s is virtual dep" % depname)
+ self._dbg(3, "_isOrGroupSatisfied(): %s is virtual dep" %
+ depname)
for pkg in self._cache.getProvidingPackages(depname):
if pkg.isInstalled:
return True
@@ -102,24 +111,17 @@ class DebPackage(object):
inst = self._cache[depname]
instver = inst.installedVersion
- if instver != None and apt_pkg.CheckDep(instver,oper,ver) == True:
+ if instver is not None and apt_pkg.CheckDep(instver, oper, ver):
return True
return False
-
def _satisfyOrGroup(self, or_group):
- """ try to satisfy the or_group """
-
- or_found = False
- virtual_pkg = None
-
+ """Try to satisfy the or_group."""
for dep in or_group:
- depname = dep[0]
- ver = dep[1]
- oper = dep[2]
+ depname, ver, oper = dep
# if we don't have it in the cache, it may be virtual
- if not self._cache.has_key(depname):
+ if not depname in self._cache:
if not self._cache.isVirtualPackage(depname):
continue
providers = self._cache.getProvidingPackages(depname)
@@ -131,15 +133,15 @@ class DebPackage(object):
# now check if we can satisfy the deps with the candidate(s)
# in the cache
- cand = self._cache[depname]
- candver = self._cache._depcache.GetCandidateVer(cand._pkg)
- if not candver:
+ pkg = self._cache[depname]
+ cand = self._cache._depcache.GetCandidateVer(pkg._pkg)
+ if not cand:
continue
- if not apt_pkg.CheckDep(candver.VerStr,oper,ver):
+ if not apt_pkg.CheckDep(cand.VerStr, oper, ver):
continue
# check if we need to install it
- self._dbg(2,"Need to get: %s" % depname)
+ self._dbg(2, "Need to get: %s" % depname)
self._needPkgs.append(depname)
return True
@@ -147,36 +149,40 @@ class DebPackage(object):
or_str = ""
for dep in or_group:
or_str += dep[0]
- if dep != or_group[len(or_group)-1]:
+ if dep != or_group[-1]:
or_str += "|"
- self._failureString += _("Dependency is not satisfiable: %s\n" % or_str)
+ self._failureString += _("Dependency is not satisfiable: %s\n" %
+ or_str)
return False
def _checkSinglePkgConflict(self, pkgname, ver, oper):
- """ returns true if a pkg conflicts with a real installed/marked
- pkg """
+ """Return True if a pkg conflicts with a real installed/marked pkg."""
# FIXME: deal with conflicts against its own provides
# (e.g. Provides: ftp-server, Conflicts: ftp-server)
- self._dbg(3, "_checkSinglePkgConflict() pkg='%s' ver='%s' oper='%s'" % (pkgname, ver, oper))
- pkgver = None
- cand = self._cache[pkgname]
- if cand.isInstalled:
- pkgver = cand.installedVersion
- elif cand.markedInstall:
- pkgver = cand.candidateVersion
+ self._dbg(3, "_checkSinglePkgConflict() pkg='%s' ver='%s' oper='%s'" %
+ (pkgname, ver, oper))
+
+ pkg = self._cache[pkgname]
+ if pkg.isInstalled:
+ pkgver = pkg.installedVersion
+ elif pkg.markedInstall:
+ pkgver = pkg.candidateVersion
+ else:
+ return False
#print "pkg: %s" % pkgname
#print "ver: %s" % ver
#print "pkgver: %s " % pkgver
#print "oper: %s " % oper
- if (pkgver and apt_pkg.CheckDep(pkgver,oper,ver) and
- not self.replacesRealPkg(pkgname, oper, ver)):
- self._failureString += _("Conflicts with the installed package '%s'" % cand.name)
+ if (apt_pkg.CheckDep(pkgver, oper, ver) and not
+ self.replacesRealPkg(pkgname, oper, ver)):
+ self._failureString += _("Conflicts with the installed package "
+ "'%s'" % pkg.name)
return True
return False
def _checkConflictsOrGroup(self, or_group):
- """ check the or-group for conflicts with installed pkgs """
- self._dbg(2,"_checkConflictsOrGroup(): %s " % (or_group))
+ """Check the or-group for conflicts with installed pkgs."""
+ self._dbg(2, "_checkConflictsOrGroup(): %s " % (or_group))
or_found = False
virtual_pkg = None
@@ -187,152 +193,116 @@ class DebPackage(object):
oper = dep[2]
# check conflicts with virtual pkgs
- if not self._cache.has_key(depname):
+ if not depname in self._cache:
# FIXME: we have to check for virtual replaces here as
# well (to pass tests/gdebi-test8.deb)
if self._cache.isVirtualPackage(depname):
for pkg in self._cache.getProvidingPackages(depname):
self._dbg(3, "conflicts virtual check: %s" % pkg.name)
# P/C/R on virtal pkg, e.g. ftpd
- if self.pkgName == pkg.name:
+ if self.pkgname == pkg.name:
self._dbg(3, "conflict on self, ignoring")
continue
- if self._checkSinglePkgConflict(pkg.name,ver,oper):
+ if self._checkSinglePkgConflict(pkg.name, ver, oper):
self._installedConflicts.add(pkg.name)
continue
- if self._checkSinglePkgConflict(depname,ver,oper):
+ if self._checkSinglePkgConflict(depname, ver, oper):
self._installedConflicts.add(depname)
- return len(self._installedConflicts) != 0
-
- def getConflicts(self):
- """
- Return list of package names conflicting with this package.
-
- WARNING: This method will is deprecated. Please use the
- attribute DebPackage.depends instead.
- """
- return self.conflicts
+ return bool(self._installedConflicts)
@property
def conflicts(self):
- """
- List of package names conflicting with this package
- """
- conflicts = []
+ """List of package names conflicting with this package."""
key = "Conflicts"
- if self._sections.has_key(key):
- conflicts = apt_pkg.ParseDepends(self._sections[key])
- return conflicts
-
- def getDepends(self):
- """
- Return list of package names on which this package depends on.
-
- WARNING: This method will is deprecated. Please use the
- attribute DebPackage.depends instead.
- """
- return self.depends
+ try:
+ return apt_pkg.ParseDepends(self._sections[key])
+ except KeyError:
+ return []
@property
def depends(self):
- """
- List of package names on which this package depends on
- """
+ """List of package names on which this package depends on."""
depends = []
# find depends
- for key in ["Depends","PreDepends"]:
- if self._sections.has_key(key):
+ for key in "Depends", "PreDepends":
+ try:
depends.extend(apt_pkg.ParseDepends(self._sections[key]))
+ except KeyError:
+ pass
return depends
- def getProvides(self):
- """
- Return list of virtual packages which are provided by this package.
-
- WARNING: This method will is deprecated. Please use the
- attribute DebPackage.provides instead.
- """
- return self.provides
-
@property
def provides(self):
- """
- List of virtual packages which are provided by this package
- """
- provides = []
+ """List of virtual packages which are provided by this package."""
key = "Provides"
- if self._sections.has_key(key):
- provides = apt_pkg.ParseDepends(self._sections[key])
- return provides
-
- def getReplaces(self):
- """
- Return list of packages which are replaced by this package.
-
- WARNING: This method will is deprecated. Please use the
- attribute DebPackage.replaces instead.
- """
- return self.replaces
+ try:
+ return apt_pkg.ParseDepends(self._sections[key])
+ except KeyError:
+ return []
@property
def replaces(self):
- """
- List of packages which are replaced by this package
- """
- replaces = []
+ """List of packages which are replaced by this package."""
key = "Replaces"
- if self._sections.has_key(key):
- replaces = apt_pkg.ParseDepends(self._sections[key])
- return replaces
+ try:
+ return apt_pkg.ParseDepends(self._sections[key])
+ except KeyError:
+ return []
def replacesRealPkg(self, pkgname, oper, ver):
+ """Return True if a given non-virtual package is replaced.
+
+ Return True if the deb packages replaces a real (not virtual)
+ packages named (pkgname, oper, ver).
"""
- return True if the deb packages replaces a real (not virtual)
- packages named pkgname, oper, ver
- """
- self._dbg(3, "replacesPkg() %s %s %s" % (pkgname,oper,ver))
- pkgver = None
- cand = self._cache[pkgname]
- if cand.isInstalled:
- pkgver = cand.installedVersion
- elif cand.markedInstall:
- pkgver = cand.candidateVersion
- for or_group in self.getReplaces():
+ self._dbg(3, "replacesPkg() %s %s %s" % (pkgname, oper, ver))
+ pkg = self._cache[pkgname]
+ if pkg.isInstalled:
+ pkgver = pkg.installedVersion
+ elif pkg.markedInstall:
+ pkgver = pkg.candidateVersion
+ else:
+ pkgver = None
+ for or_group in self.replaces:
for (name, ver, oper) in or_group:
- if (name == pkgname and
- apt_pkg.CheckDep(pkgver,oper,ver)):
- self._dbg(3, "we have a replaces in our package for the conflict against '%s'" % (pkgname))
+ if (name == pkgname and apt_pkg.CheckDep(pkgver, oper, ver)):
+ self._dbg(3, "we have a replaces in our package for the "
+ "conflict against '%s'" % (pkgname))
return True
return False
def checkConflicts(self):
- """ check if the pkg conflicts with a existing or to be installed
- package. Return True if the pkg is ok """
+ """Check if there are conflicts with existing or selected packages.
+
+ Check if the package conflicts with a existing or to be installed
+ package. Return True if the pkg is OK.
+ """
res = True
- for or_group in self.getConflicts():
+ for or_group in self.conflicts:
if self._checkConflictsOrGroup(or_group):
#print "Conflicts with a exisiting pkg!"
#self._failureString = "Conflicts with a exisiting pkg!"
res = False
return res
-
def compareToVersionInCache(self, useInstalled=True):
- """ checks if the pkg is already installed or availabe in the cache
- and if so in what version, returns if the version of the deb
- is not available,older,same,newer
+ """Compare the package to the version available in the cache.
+
+ Checks if the package is already installed or availabe in the cache
+ and if so in what version, returns one of (VERSION_NONE,
+ VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER).
"""
- self._dbg(3,"compareToVersionInCache")
+ self._dbg(3, "compareToVersionInCache")
pkgname = self._sections["Package"]
debver = self._sections["Version"]
- self._dbg(1,"debver: %s" % debver)
- if self._cache.has_key(pkgname):
+ self._dbg(1, "debver: %s" % debver)
+ if pkgname in self._cache:
if useInstalled:
cachever = self._cache[pkgname].installedVersion
else:
cachever = self._cache[pkgname].candidateVersion
- if cachever != None:
- cmp = apt_pkg.VersionCompare(cachever,debver)
+ if cachever is not None:
+ cmp = apt_pkg.VersionCompare(cachever, debver)
self._dbg(1, "CompareVersion(debver,instver): %s" % cmp)
if cmp == 0:
return VERSION_SAME
@@ -343,12 +313,13 @@ class DebPackage(object):
return VERSION_NONE
def checkDeb(self):
- self._dbg(3,"checkDepends")
+ """Check if the package is installable."""
+ self._dbg(3, "checkDepends")
# check arch
arch = self._sections["Architecture"]
if arch != "all" and arch != apt_pkg.Config.Find("APT::Architecture"):
- self._dbg(1,"ERROR: Wrong architecture dude!")
+ self._dbg(1, "ERROR: Wrong architecture dude!")
self._failureString = _("Wrong architecture '%s'" % arch)
return False
@@ -366,7 +337,7 @@ class DebPackage(object):
return False
# try to satisfy the dependencies
- res = self._satisfyDepends(self.getDepends())
+ res = self._satisfyDepends(self.depends)
if not res:
return False
@@ -376,20 +347,23 @@ class DebPackage(object):
return False
if self._cache._depcache.BrokenCount > 0:
- self._failureString = _("Failed to satisfy all dependencies (broken cache)")
+ self._failureString = _("Failed to satisfy all dependencies "
+ "(broken cache)")
# clean the cache again
self._cache.clear()
return False
return True
def satisfyDependsStr(self, dependsstr):
+ """Satisfy the dependencies in the given string."""
return self._satisfyDepends(apt_pkg.ParseDepends(dependsstr))
def _satisfyDepends(self, depends):
+ """Satisfy the dependencies."""
# turn off MarkAndSweep via a action group (if available)
try:
_actiongroup = apt_pkg.GetPkgActionGroup(self._cache._depcache)
- except AttributeError, e:
+ except AttributeError:
pass
# check depends
for or_group in depends:
@@ -410,15 +384,17 @@ class DebPackage(object):
@property
def missingDeps(self):
+ """Return missing dependencies."""
self._dbg(1, "Installing: %s" % self._needPkgs)
- if self._needPkgs == None:
+ if self._needPkgs is None:
self.checkDeb()
return self._needPkgs
@property
def requiredChanges(self):
- """ gets the required changes to satisfy the depends.
- returns a tuple with (install, remove, unauthenticated)
+ """Get the changes required to satisfy the dependencies.
+
+ Returns: a tuple with (install, remove, unauthenticated)
"""
install = []
remove = []
@@ -435,83 +411,98 @@ class DebPackage(object):
unauthenticated.append(pkg.name)
if pkg.markedDelete:
remove.append(pkg.name)
- return (install,remove, unauthenticated)
-
+ return (install, remove, unauthenticated)
def _dbg(self, level, msg):
- """Write debugging output to sys.stderr.
- """
+ """Write debugging output to sys.stderr."""
if level <= self.debug:
print >> sys.stderr, msg
def install(self, installProgress=None):
- """ Install the package """
- if installProgress == None:
- res = os.system("/usr/sbin/dpkg -i %s" % self.filename)
+ """Install the package."""
+ if installProgress is None:
+ return os.system("dpkg -i %s" % self.filename)
else:
installProgress.startUpdate()
res = installProgress.run(self.filename)
installProgress.finishUpdate()
- return res
+ return res
+
class DscSrcPackage(DebPackage):
+ """A locally available source package."""
+
def __init__(self, filename=None, cache=None):
- DebPackage.__init__(self, filename, cache)
- self.depends = []
- self.conflicts = []
- self.binaries = []
- if filename != None:
+ DebPackage.__init__(self, None, cache)
+ self._depends = []
+ self._conflicts = []
+ self._binaries = []
+ if filename is not None:
self.open(filename)
- def getConflicts(self):
- return self.conflicts
- def getDepends(self):
- return self.depends
+
+ @property
+ def depends(self):
+ """Return the dependencies of the package"""
+ return self._depends
+
+ @property
+ def conflicts(self):
+ """Return the dependencies of the package"""
+ return self._conflicts
+
def open(self, file):
- depends_tags = ["Build-Depends:", "Build-Depends-Indep:"]
- conflicts_tags = ["Build-Conflicts:", "Build-Conflicts-Indep:"]
- for line in open(file):
- # check b-d and b-c
- for tag in depends_tags:
- if line.startswith(tag):
- key = line[len(tag):].strip()
- self.depends.extend(apt_pkg.ParseSrcDepends(key))
- for tag in conflicts_tags:
- if line.startswith(tag):
- key = line[len(tag):].strip()
- self.conflicts.extend(apt_pkg.ParseSrcDepends(key))
- # check binary and source and version
- if line.startswith("Source:"):
- self.pkgName = line[len("Source:"):].strip()
- if line.startswith("Binary:"):
- self.binaries = [pkg.strip() for pkg in line[len("Binary:"):].split(",")]
- if line.startswith("Version:"):
- self._sections["Version"] = line[len("Version:"):].strip()
- # we are at the end
- if line.startswith("-----BEGIN PGP SIGNATURE-"):
- break
+ """Open the package."""
+ depends_tags = ["Build-Depends", "Build-Depends-Indep"]
+ conflicts_tags = ["Build-Conflicts", "Build-Conflicts-Indep"]
+
+ fobj = open(file)
+ tagfile = apt_pkg.ParseTagFile(fobj)
+ sec = tagfile.Section
+ try:
+ while tagfile.Step() == 1:
+ for tag in depends_tags:
+ if not sec.has_key(tag):
+ continue
+ self._depends.extend(apt_pkg.ParseSrcDepends(sec[tag]))
+ for tag in conflicts_tags:
+ if not sec.has_key(tag):
+ continue
+ self._conflicts.extend(apt_pkg.ParseSrcDepends(sec[tag]))
+ if sec.has_key('Source'):
+ self.pkgname = sec['Source']
+ if sec.has_key('Binary'):
+ self.binaries = sec['Binary'].split(', ')
+ if sec.has_key('Version'):
+ self._sections['Version'] = sec['Version']
+ finally:
+ fobj.close()
+
s = _("Install Build-Dependencies for "
- "source package '%s' that builds %s\n"
- ) % (self.pkgName, " ".join(self.binaries))
+ "source package '%s' that builds %s\n") % (self.pkgname,
+ " ".join(self.binaries))
self._sections["Description"] = s
def checkDeb(self):
+ """Check if the package is installable.."""
if not self.checkConflicts():
for pkgname in self._installedConflicts:
if self._cache[pkgname]._pkg.Essential:
- raise Exception, _("A essential package would be removed")
+ raise Exception(_("A essential package would be removed"))
self._cache[pkgname].markDelete()
# FIXME: a additional run of the checkConflicts()
# after _satisfyDepends() should probably be done
return self._satisfyDepends(self.depends)
-if __name__ == "__main__":
- from cache import Cache
- from progress import DpkgInstallProgress
+
+def _test():
+ """Test function"""
+ from apt.cache import Cache
+ from apt.progress import DpkgInstallProgress
cache = Cache()
vp = "www-browser"
- print "%s virtual: %s" % (vp,cache.isVirtualPackage(vp))
+ #print "%s virtual: %s" % (vp, cache.isVirtualPackage(vp))
providers = cache.getProvidingPackages(vp)
print "Providers for %s :" % vp
for pkg in providers:
@@ -537,3 +528,6 @@ if __name__ == "__main__":
s = DscSrcPackage(cache=cache)
d = "libc6 (>= 2.3.2), libaio (>= 0.3.96) | libaio1 (>= 0.3.96)"
print s._satisfyDepends(apt_pkg.ParseDepends(d))
+
+if __name__ == "__main__":
+ _test()