diff options
| author | Julian Andres Klode <jak@debian.org> | 2009-01-09 21:51:09 +0100 |
|---|---|---|
| committer | Julian Andres Klode <jak@debian.org> | 2009-01-09 21:51:09 +0100 |
| commit | 5b0beca05b84919581e44af83824c47d7a49f02b (patch) | |
| tree | f4e5c41d4b348978ad8c7e6ff4468f2586f22f52 | |
| parent | 2aaecf61a8f464a78d62fee62941bfda7244b031 (diff) | |
| download | python-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.py | 402 |
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() |
