diff options
| author | Michael Vogt <michael.vogt@ubuntu.com> | 2010-07-28 11:09:00 +0200 |
|---|---|---|
| committer | Michael Vogt <michael.vogt@ubuntu.com> | 2010-07-28 11:09:00 +0200 |
| commit | cee5d33d44130ce8ceb7b563f7b97f2bf9a3ca5c (patch) | |
| tree | 8157a049457a566f6ac5b2e665cba01629aadd58 | |
| parent | 3b4330920da718d2dbb2a4a94577c07eaa58a8c5 (diff) | |
| parent | d642c9ea22f5705acfcba79493f48293626771c3 (diff) | |
| download | python-apt-cee5d33d44130ce8ceb7b563f7b97f2bf9a3ca5c.tar.gz | |
merged from the debian-sid bzr branch
31 files changed, 854 insertions, 185 deletions
diff --git a/apt/__init__.py b/apt/__init__.py index a8a8b8fc..677a625b 100644 --- a/apt/__init__.py +++ b/apt/__init__.py @@ -16,7 +16,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA - # import the core of apt_pkg """High-Level Interface for working with apt.""" import apt_pkg diff --git a/apt/cache.py b/apt/cache.py index 8e07e4d0..f64b489a 100644 --- a/apt/cache.py +++ b/apt/cache.py @@ -19,6 +19,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA +import fnmatch import os import weakref @@ -64,6 +65,7 @@ class Cache(object): self._callbacks = {} self._weakref = weakref.WeakValueDictionary() self._set = set() + self._sorted_set = None if memonly: # force apt to build its caches in memory apt_pkg.config.set("Dir::Cache::pkgcache", "") @@ -118,6 +120,7 @@ class Cache(object): """ if progress is None: progress = apt.progress.base.OpProgress() + self.op_progress = progress self._run_callbacks("cache_pre_open") self._cache = apt_pkg.Cache(progress) @@ -126,6 +129,7 @@ class Cache(object): self._list = apt_pkg.SourceList() self._list.read_main_list() self._set.clear() + self._sorted_set = None self._weakref.clear() progress.op = _("Building data structures") @@ -157,7 +161,15 @@ class Cache(object): raise KeyError('The cache has no package named %r' % key) def __iter__(self): - for pkgname in self._set: + # We iterate sorted over package names here. With this we read the + # package lists linearly if we need to access the package records, + # instead of having to do thousands of random seeks; the latter + # is disastrous if we use compressed package indexes, and slower than + # necessary for uncompressed indexes. + if self._sorted_set is None: + self._sorted_set = sorted(self._set) + + for pkgname in self._sorted_set: yield self[pkgname] raise StopIteration @@ -277,21 +289,28 @@ class Cache(object): else: return bool(pkg.has_provides and not pkg.has_versions) - def get_providing_packages(self, virtual, candidate_only=True): - """Return a list of all packages providing a virtual package. + def get_providing_packages(self, pkgname, candidate_only=True, + include_nonvirtual=False): + """Return a list of all packages providing a package. Return a list of packages which provide the virtual package of the - specified name. If 'candidate_only' is False, return all packages - with at least one version providing the virtual package. Otherwise, - return only those packages where the candidate version provides - the virtual package. + specified name. + + If 'candidate_only' is False, return all packages with at + least one version providing the virtual package. Otherwise, + return only those packages where the candidate version + provides the virtual package. + + If 'include_nonvirtual' is True then it will search for all + packages providing pkgname, even if pkgname is not itself + a virtual pkg. """ providers = set() get_candidate_ver = self._depcache.get_candidate_ver try: - vp = self._cache[virtual] - if vp.has_versions: + vp = self._cache[pkgname] + if vp.has_versions and not include_nonvirtual: return list(providers) except KeyError: return list(providers) @@ -445,6 +464,21 @@ class Cache(object): return apt_pkg.ActionGroup(self._depcache) @property + def dpkg_journal_dirty(self): + """Return True if the dpkg was interrupted + + All dpkg operations will fail until this is fixed, the action to + fix the system if dpkg got interrupted is to run + 'dpkg --configure -a' as root. + """ + dpkg_status_dir = os.path.dirname( + apt_pkg.config.find_file("Dir::State::status")) + for f in os.listdir(os.path.join(dpkg_status_dir, "updates")): + if fnmatch.fnmatch(f, "[0-9]*"): + return True + return False + + @property def broken_count(self): """Return the number of packages with broken dependencies.""" return self._depcache.broken_count diff --git a/apt/debfile.py b/apt/debfile.py index ccaa25e4..ea83c5b3 100644 --- a/apt/debfile.py +++ b/apt/debfile.py @@ -1,4 +1,4 @@ -# Copyright (c) 2005-2009 Canonical +# Copyright (c) 2005-2010 Canonical # # Author: Michael Vogt <michael.vogt@ubuntu.com> # @@ -17,47 +17,53 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA """Classes for working with locally available Debian packages.""" +import apt +import apt_inst +import apt_pkg +import gzip import os import sys -import apt_inst -import apt_pkg from apt_pkg import gettext as _ - - -# Constants for comparing the local package file with the version in the cache -(VERSION_NONE, VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER) = range(4) - +from StringIO import StringIO class NoDebArchiveException(IOError): """Exception which is raised if a file is no Debian archive.""" - class DebPackage(object): """A Debian Package (.deb file).""" + # Constants for comparing the local package file with the version + # in the cache + (VERSION_NONE, + VERSION_OUTDATED, + VERSION_SAME, + VERSION_NEWER) = range(4) + _supported_data_members = ("data.tar.gz", "data.tar.bz2", "data.tar.lzma") debug = 0 def __init__(self, filename=None, cache=None): + if cache is None: + cache = apt.Cache() self._cache = cache - self._need_pkgs = [] self._debfile = None self.pkgname = "" - self.filename = filename self._sections = {} - self._installed_conflicts = set() - self._failure_string = "" if filename: self.open(filename) def open(self, filename): - " open given debfile " + """ open given debfile """ + self._need_pkgs = [] + self._installed_conflicts = set() + self._failure_string = "" self.filename = filename - self._debfile = apt_inst.DebFile(self.filename) + self._debfile = apt_inst.DebFile(open(self.filename)) control = self._debfile.control.extractdata("control") - self._sections = apt_pkg.TagSection(control) + # hm, 'replace' is probably better but python2.6 test fail with that + self._sections = apt_pkg.TagSection(control.decode("UTF-8", 'ignore')) self.pkgname = self._sections["Package"] def __getitem__(self, key): @@ -90,20 +96,35 @@ class DebPackage(object): # check for virtual pkgs if not depname in self._cache: if self._cache.is_virtual_package(depname): - self._dbg(3, "_isOrGroupSatisfied(): %s is virtual dep" % - depname) + self._dbg(3, "_is_or_group_satisfied(): %s is virtual dep" % depname) for pkg in self._cache.get_providing_packages(depname): if pkg.is_installed: return True continue - + # check real dependency inst = self._cache[depname].installed if inst is not None and apt_pkg.check_dep(inst.version, oper, ver): return True + + # if no real dependency is installed, check if there is + # a package installed that provides this dependency + # (e.g. scrollkeeper dependecies are provided by rarian-compat) + # but only do that if there is no version required in the + # dependency (we do not supprot versionized dependencies) + if not oper: + for ppkg in self._cache.get_providing_packages( + depname, include_nonvirtual=True): + if ppkg.is_installed: + self._dbg(3, "found installed '%s' that provides '%s'" % (ppkg.name, depname)) + return True return False def _satisfy_or_group(self, or_group): """Try to satisfy the or_group.""" + + or_found = False + virtual_pkg = None + for dep in or_group: depname, ver, oper = dep @@ -136,19 +157,18 @@ class DebPackage(object): or_str = "" for dep in or_group: or_str += dep[0] - if dep != or_group[-1]: + if ver and oper: + or_str += " (%s %s)" % (dep[2], dep[1]) + if dep != or_group[len(or_group)-1]: or_str += "|" - self._failure_string += _("Dependency is not satisfiable: %s\n" % - or_str) + self._failure_string += _("Dependency is not satisfiable: %s\n") % or_str return False def _check_single_pkg_conflict(self, pkgname, ver, oper): """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)) - + self._dbg(3, "_check_single_pkg_conflict() pkg='%s' ver='%s' oper='%s'" % (pkgname, ver, oper)) pkg = self._cache[pkgname] if pkg.is_installed: pkgver = pkg.installed.version @@ -163,7 +183,7 @@ class DebPackage(object): if (apt_pkg.check_dep(pkgver, oper, ver) and not self.replaces_real_pkg(pkgname, oper, ver)): self._failure_string += _("Conflicts with the installed package " - "'%s'" % pkg.name) + "'%s'") % pkg.name return True return False @@ -171,6 +191,9 @@ class DebPackage(object): """Check the or-group for conflicts with installed pkgs.""" self._dbg(2, "_check_conflicts_or_group(): %s " % (or_group)) + or_found = False + virtual_pkg = None + for dep in or_group: depname = dep[0] ver = dep[1] @@ -187,7 +210,7 @@ class DebPackage(object): if self.pkgname == pkg.name: self._dbg(3, "conflict on self, ignoring") continue - if self._check_single_pkg_conflict(pkg.name, ver, + if self._check_single_pkg_conflict(pkg.name, ver, oper): self._installed_conflicts.add(pkg.name) continue @@ -209,7 +232,7 @@ class DebPackage(object): """List of package names on which this package depends on.""" depends = [] # find depends - for key in "Depends", "PreDepends": + for key in "Depends", "Pre-Depends": try: depends.extend(apt_pkg.parse_depends(self._sections[key])) except KeyError: @@ -240,7 +263,7 @@ class DebPackage(object): 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)) + self._dbg(3, "replaces_real_pkg() %s %s %s" % (pkgname, oper, ver)) pkg = self._cache[pkgname] if pkg.is_installed: pkgver = pkg.installed.version @@ -270,6 +293,68 @@ class DebPackage(object): res = False return res + def check_breaks_existing_packages(self): + """ + check if installing the package would break exsisting + package on the system, e.g. system has: + smc depends on smc-data (= 1.4) + and user tries to installs smc-data 1.6 + """ + # show progress information as this step may take some time + size = float(len(self._cache)) + steps = max(int(size/50), 1) + debver = self._sections["Version"] + # store what we provide so that we can later check against that + provides = [ x[0][0] for x in self.provides] + for (i, pkg) in enumerate(self._cache): + if i%steps == 0: + self._cache.op_progress.update(float(i)/size*100.0) + if not pkg.is_installed: + continue + # check if the exising dependencies are still satisfied + # with the package + ver = pkg._pkg.current_ver + for dep_or in pkg.installed.dependencies: + for dep in dep_or.or_dependencies: + if dep.name == self.pkgname: + if not apt_pkg.check_dep(debver, dep.relation, dep.version): + self._dbg(2, "would break (depends) %s" % pkg.name) + # TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation + self._failure_string += _("Breaks existing package '%(pkgname)s' dependency %(depname)s (%(deprelation)s %(depversion)s)") % { + 'pkgname' : pkg.name, + 'depname' : dep.name, + 'deprelation' : dep.relation, + 'depversion' : dep.version} + self._cache.op_progress.done() + return False + # now check if there are conflicts against this package on + # the existing system + if "Conflicts" in ver.depends_list: + for conflicts_ver_list in ver.depends_list["Conflicts"]: + for c_or in conflicts_ver_list: + if c_or.target_pkg.name == self.pkgname: + if apt_pkg.check_dep(debver, c_or.comp_type, c_or.target_ver): + self._dbg(2, "would break (conflicts) %s" % pkg.name) + # TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation + self._failure_string += _("Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s %(targetver)s)") % { + 'pkgname' : pkg.name, + 'targetpkg' : c_or.target_pkg.name, + 'comptype' : c_or.comp_type, + 'targetver' : c_or.target_ver } + self._cache.op_progress.done() + return False + if c_or.target_pkg.name in provides: + self._dbg(2, "would break (conflicts) %s" % provides) + self._failure_string += _("Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But the '%(debfile)s' provides it via: '%(provides)s'") % { + 'provides' : ",".join(provides), + 'debfile' : self.filename, + 'targetpkg' : c_or.target_pkg.name, + 'pkgname' : pkg.name } + self._cache.op_progress.done() + return False + self._cache.op_progress.done() + return True + def compare_to_version_in_cache(self, use_installed=True): """Compare the package to the version available in the cache. @@ -277,42 +362,49 @@ class DebPackage(object): and if so in what version, returns one of (VERSION_NONE, VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER). """ - self._dbg(3, "compareToVersionInCache") + self._dbg(3, "compare_to_version_in_cache") pkgname = self._sections["Package"] debver = self._sections["Version"] self._dbg(1, "debver: %s" % debver) if pkgname in self._cache: if use_installed and self._cache[pkgname].installed: cachever = self._cache[pkgname].installed.version - else: + elif not use_installed and self._cache[pkgname].candidate: cachever = self._cache[pkgname].candidate.version + else: + return self.VERSION_NONE if cachever is not None: - cmpres = apt_pkg.version_compare(cachever, debver) - self._dbg(1, "CompareVersion(debver,instver): %s" % cmpres) - if cmpres == 0: - return VERSION_SAME - elif cmpres < 0: - return VERSION_NEWER - elif cmpres > 0: - return VERSION_OUTDATED - return VERSION_NONE + cmp = apt_pkg.version_compare(cachever, debver) + self._dbg(1, "CompareVersion(debver,instver): %s" % cmp) + if cmp == 0: + return self.VERSION_SAME + elif cmp < 0: + return self.VERSION_NEWER + elif cmp > 0: + return self.VERSION_OUTDATED + return self.VERSION_NONE def check(self): """Check if the package is installable.""" self._dbg(3, "check_depends") # check arch + if not "Architecture" in self._sections: + self._dbg(1, "ERROR: no architecture field") + self._failure_string = _("No Architecture field in the package") + return False arch = self._sections["Architecture"] if arch != "all" and arch != apt_pkg.config.find("APT::Architecture"): self._dbg(1, "ERROR: Wrong architecture dude!") - self._failure_string = _("Wrong architecture '%s'" % arch) + self._failure_string = _("Wrong architecture '%s'") % arch return False # check version - if self.compare_to_version_in_cache() == VERSION_OUTDATED: - # the deb is older than the installed - self._failure_string = _("A later version is already installed") - return False + if self.compare_to_version_in_cache() == self.VERSION_OUTDATED: + if self._cache[self.pkgname].installed: + # the deb is older than the installed + self._failure_string = _("A later version is already installed") + return False # FIXME: this sort of error handling sux self._failure_string = "" @@ -321,6 +413,11 @@ class DebPackage(object): if not self.check_conflicts(): return False + # check if installing it would break anything on the + # current system + if not self.check_breaks_existing_packages(): + return False + # try to satisfy the dependencies if not self._satisfy_depends(self.depends): return False @@ -332,7 +429,7 @@ class DebPackage(object): if self._cache._depcache.broken_count > 0: self._failure_string = _("Failed to satisfy all dependencies " - "(broken cache)") + "(broken cache)") # clean the cache again self._cache.clear() return False @@ -352,17 +449,16 @@ class DebPackage(object): # check depends for or_group in depends: #print "or_group: %s" % or_group - #print "or_group satified: %s" % self._is_or_group_satisfied( - # or_group) + #print "or_group satified: %s" % self._is_or_group_satisfied(or_group) if not self._is_or_group_satisfied(or_group): if not self._satisfy_or_group(or_group): return False # now try it out in the cache for pkg in self._need_pkgs: try: - self._cache[pkg].mark_install(fromUser=False) - except SystemError: - self._failure_string = _("Cannot install '%s'" % pkg) + self._cache[pkg].mark_install(from_user=False) + except SystemError, e: + self._failure_string = _("Cannot install '%s'") % pkg self._cache.clear() return False return True @@ -398,6 +494,77 @@ class DebPackage(object): remove.append(pkg.name) return (install, remove, unauthenticated) + @property + def control_filelist(self): + """ return the list of files in control.tar.gt """ + try: + from debian.debfile import DebFile + except: + raise Exception(_("Python-debian module not available")) + content = [] + for name in DebFile(self.filename).control: + if name and name != ".": + content.append(name) + return sorted(content) + + @staticmethod + def to_hex(self, in_data): + hex = "" + for (i, c) in enumerate(in_data): + if i%80 == 0: + hex += "\n" + hex += "%2.2x " % ord(c) + return hex + + @staticmethod + def to_strish(self, in_data): + s = "" + for c in in_data: + if ord(c) < 10 or ord(c) > 127: + s += " " + else: + s += c + return s + + def _get_content(self, part, name, auto_decompress=True, auto_hex=True): + data = part.get_content(name) + # check for zip content + if name.endswith(".gz") and auto_decompress: + io = StringIO(data) + gz = gzip.GzipFile(fileobj=io) + data = _("Automatically decompressed:\n\n") + data += gz.read() + # auto-convert to hex + try: + data = unicode(data, "utf-8") + except Exception, e: + new_data = _("Automatically converted to printable ascii:\n") + new_data += self.to_strish(data) + return new_data + return data + + def control_content(self, name): + """ return the content of a specific control.tar.gz file """ + try: + from debian.debfile import DebFile + except: + raise Exception(_("Python-debian module not available")) + control = DebFile(self.filename).control + if name in control: + return self._get_content(control, name) + return "" + + def data_content(self, name): + """ return the content of a specific control.tar.gz file """ + try: + from debian.debfile import DebFile + except: + raise Exception(_("Python-debian module not available")) + data = DebFile(self.filename).data + if name in data: + return self._get_content(data, name) + return "" + def _dbg(self, level, msg): """Write debugging output to sys.stderr.""" if level <= self.debug: @@ -419,18 +586,18 @@ class DebPackage(object): install_progress.finishUpdate() return res - class DscSrcPackage(DebPackage): """A locally available source package.""" def __init__(self, filename=None, cache=None): DebPackage.__init__(self, None, cache) + self.filename = filename self._depends = [] self._conflicts = [] self.pkgname = "" self.binaries = [] - if filename is not None: - self.open(filename) + if self.filename is not None: + self.open(self.filename) @property def depends(self): @@ -446,7 +613,6 @@ class DscSrcPackage(DebPackage): """Open the package.""" depends_tags = ["Build-Depends", "Build-Depends-Indep"] conflicts_tags = ["Build-Conflicts", "Build-Conflicts-Indep"] - fobj = open(file) tagfile = apt_pkg.TagFile(fobj) try: @@ -481,11 +647,10 @@ class DscSrcPackage(DebPackage): if self._cache[pkgname]._pkg.essential: raise Exception(_("An essential package would be removed")) self._cache[pkgname].mark_delete() - # FIXME: a additional run of the checkConflicts() - # after _satisfyDepends() should probably be done + # FIXME: a additional run of the check_conflicts() + # after _satisfy_depends() should probably be done return self._satisfy_depends(self.depends) - def _test(): """Test function""" from apt.cache import Cache @@ -494,7 +659,7 @@ def _test(): cache = Cache() vp = "www-browser" - #print "%s virtual: %s" % (vp, cache.isVirtualPackage(vp)) + print "%s virtual: %s" % (vp, cache.is_virtual_package(vp)) providers = cache.get_providing_packages(vp) print "Providers for %s :" % vp for pkg in providers: @@ -508,6 +673,8 @@ def _test(): print "missing deps: %s" % d.missing_deps print d.required_changes + print d.filelist + print "Installing ..." ret = d.install(DpkgInstallProgress()) print ret diff --git a/debian/changelog b/debian/changelog index 9fe79188..d95f87e5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,75 @@ +python-apt (0.7.96.1ubuntu1) maverick; urgency=low + + [ Julian Andres Klode ] + * python/tag.cc: + - Support gzip compression for control files (Closes: #383617), + requires APT (>> 0.7.26~exp10) to work. + * doc/conf.py: + - Correctly handle non-digit characters in version (ignore everything + after them). + * python/apt_pkgmodule.cc: + - Bind pkgAcquire::Item::StatTransientNetworkError (Closes: #589010) + + [ Michael Vogt ] + * merge from debian-sid bzr branch, remaining changes: + - do not build for python2.5 + + -- Michael Vogt <michael.vogt@ubuntu.com> Wed, 28 Jul 2010 10:54:25 +0200 + +python-apt (0.7.96.1) unstable; urgency=low + + * tests/test_debfile.py: + - properly setup fixture data to make debfile test pass + (closes: #588796) + + -- Michael Vogt <mvo@debian.org> Mon, 12 Jul 2010 14:14:51 +0200 + +python-apt (0.7.96) unstable; urgency=low + + [ Michael Vogt ] + * data/templates/gNewSense.info.in, + data/templates/gNewSense.mirrors: + - add gNewSense template and mirrors, thanks to Karl Goetz + * data/templates/Ubuntu.info.in, + data/templates/Ubuntu.mirrors: + - updated for Ubuntu maverick + * doc/source/conf.py: + - do not fail on non-digits in the version number + * utils/get_debian_mirrors.py: + - ignore mirrors without a county + * apt/cache.py: + - add new "dpkg_journal_dirty" property that can be used to + detect a interrupted dpkg (the famous + "E: dpkg was interrupted, you must manually run 'dpkg --configure -a'") + * merged lp:~kiwinote/python-apt/merge-gdebi-changes, this port the + DebPackage class fixes from gdebi into python-apt so that gdebi can + use the class from python-apt directly + * apt/debfile.py: + - check if the debfiles provides are in conflict with the systems + packages + - fix py3 compatibility + * tests/test_debs/*.deb, tests/test_debfile.py: + - add automatic test based on the test debs from gdebi + * python/progress.cc: + - deal with missing return value from the acquire progress in pulse() + + [ Martin Pitt ] + * tests/test_apt_cache.py: Test accessing the record of all packages during + iteration. This both ensures that it's well-formatted and structured, and + also that accessing it does not take an inordinate amount of time. This + exposes a severe performance problem when using gzip compressed package + indexes. + * apt/cache.py: When iterating over the cache, do so sorted by package name. + With this we read the the package lists linearly if we need to access the + package records, instead of having to do thousands of random seeks; the + latter is disastrous if we use compressed package indexes, and slower than + necessary for uncompressed indexes. + + [ Julian Andres Klode ] + * Re-enable Python 3 support for latest python-default changes (hack). + + -- Michael Vogt <mvo@debian.org> Mon, 12 Jul 2010 08:58:42 +0200 + python-apt (0.7.95ubuntu2) maverick; urgency=low * apt/utils.py: @@ -751,6 +823,9 @@ python-apt (0.7.11.0) unstable; urgency=low (LP: #372224) * python/progress.cc: - fix crash in RunSimpleCallback() + * apt/cache.py: + - when the cache is run with a alternative rootdir, create + required dirs/files automatically -- Michael Vogt <mvo@debian.org> Mon, 20 Jul 2009 15:35:27 +0200 @@ -1026,7 +1101,7 @@ python-apt (0.7.9~exp2) experimental; urgency=low * Merge Ben Finney's do not use has_key() (Closes: #481878) * Do not use deprecated form of raise statement (Closes: #494259) * Add support for PkgRecords.SHA256Hash (Closes: #456113) - + [ Michael Vogt ] * apt/package.py: - fix bug in candidateInstalledSize property @@ -1036,7 +1111,7 @@ python-apt (0.7.9~exp2) experimental; urgency=low - only add nearest_server and server to the mirrors if they are defined - -- Julian Andres Klode <jak@debian.org> Sun, 11 Jan 2009 20:01:59 +0100 + -- Michael Vogt <mvo@debian.org> Fri, 16 Jan 2009 11:28:17 +0100 python-apt (0.7.9~exp1) experimental; urgency=low @@ -1227,7 +1302,7 @@ python-apt (0.7.7.1) unstable; urgency=low * aptsources/distinfo.py: - fix template matching for arch specific code (LP: #244093) - -- Michael Vogt <michael.vogt@ubuntu.com> Fri, 25 Jul 2008 18:34:28 +0200 + -- Michael Vogt <mvo@debian.org> Fri, 25 Jul 2008 18:13:53 +0200 python-apt (0.7.7ubuntu2) intrepid; urgency=low @@ -1266,7 +1341,7 @@ python-apt (0.7.7) unstable; urgency=low [ Michael Vogt ] * python/apt_pkgmodule.cc: - fix bug in hashsum calculation when the original string - contains \0 charackters (thanks to Celso Providelo and + contains \0 charackters (thanks to Celso Providelo and Ryan Hass for the test-case) LP: #243630 * tests/test_hashsums.py: - add tests for the hashsum code @@ -1346,14 +1421,14 @@ python-apt (0.7.5) unstable; urgency=low - export the Homepage field * python/tar.cc: - fix .lzma extraction (thanks to bigjools) - * python/sourcelist.cc: - - support GetIndexes() GetAll argument to implement - something like --print-uris - * python/apt_pkgmodule.cc: - - add InstState{Ok,ReInstReq,Hold,HoldReInstReq} constants - * apt/cache.py: - - add reqReinstallPkgs property that lists all packages in - ReInstReq or HoldReInstReq + * python/sourcelist.cc: + - support GetIndexes() GetAll argument to implement + something like --print-uris + * python/apt_pkgmodule.cc: + - add InstState{Ok,ReInstReq,Hold,HoldReInstReq} constants + * apt/cache.py: + - add reqReinstallPkgs property that lists all packages in + ReInstReq or HoldReInstReq -- Michael Vogt <mvo@debian.org> Tue, 19 Feb 2008 21:06:36 +0100 diff --git a/debian/control b/debian/control index b553dee7..65f72367 100644 --- a/debian/control +++ b/debian/control @@ -9,8 +9,8 @@ XS-Python-Version: all Build-Depends: apt-utils, debhelper (>= 7.3.5), libapt-pkg-dev (>= 0.7.22~), - python-all-dbg, python-all-dev, + python-all-dbg, python-central (>= 0.5), python-distutils-extra (>= 2.0), python-sphinx (>= 0.5) @@ -19,8 +19,8 @@ Vcs-Browser: http://bzr.debian.org/loggerhead/apt/python-apt/debian-sid/changes Package: python-apt Architecture: any -Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, lsb-release -Recommends: iso-codes +Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends} +Recommends: lsb-release, iso-codes, python2.6 Breaks: debdelta (<< 0.28~), packagekit-backend-apt (<= 0.4.8-0ubuntu4) Provides: ${python:Provides} Suggests: python-apt-dbg, python-gtk2, python-vte, python-apt-doc diff --git a/debian/rules b/debian/rules index cc1cabee..f7cca130 100755 --- a/debian/rules +++ b/debian/rules @@ -3,6 +3,8 @@ export DH_PYCENTRAL=nomove export DEBVER=$(shell dpkg-parsechangelog | sed -n -e 's/^Version: //p') export CFLAGS=-Wno-write-strings -DCOMPAT_0_7 +export PATH :=$(CURDIR)/utils:$(PATH) +export SHELL = env PATH=$(PATH) sh %: dh --with python-central $@ @@ -20,7 +22,7 @@ override_dh_installdocs: override_dh_strip: dh_strip --dbg-package=python-apt-dbg - + override_dh_compress: dh_compress -X.js -X_static/* -X _sources/* -X_sources/*/* -X.inv diff --git a/doc/source/conf.py b/doc/source/conf.py index 05490da7..18c8642e 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -78,8 +78,13 @@ except KeyError: release = p2.communicate()[0] # Handle the alpha release scheme -release_raw = release.split("~")[0].split(".")[2] -if release_raw.isdigit() and int(release_raw) >= 90: +release_raw = "0" +for c in release.split("~")[0].split(".")[2]: + if not c.isdigit(): + break + release_raw += c + +if int(release_raw) >= 90: version_s = release.split("~")[0].split(".")[:3] # Set the version to 0.X.100 if the release is 0.X.9Y (0.7.90 => 0.7.100) # Use diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst index dd958959..b91790db 100644 --- a/doc/source/library/apt_pkg.rst +++ b/doc/source/library/apt_pkg.rst @@ -1381,6 +1381,10 @@ installation. The item is yet to be fetched. + .. attribute:: STAT_TRANSIENT_NETWORK_ERROR + + There was a network error. + .. class:: AcquireFile(owner, uri[, md5, size, descr, short_descr, destdir, destfile]) diff --git a/po/python-apt.pot b/po/python-apt.pot index b7168e6e..0d683700 100644 --- a/po/python-apt.pot +++ b/po/python-apt.pot @@ -8,10 +8,11 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-08-21 15:34+0200\n" +"POT-Creation-Date: 2010-07-12 09:45+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" @@ -24,236 +25,266 @@ msgstr "" #. Description #: ../data/templates/Ubuntu.info.in:13 -msgid "Ubuntu 9.04 'Jaunty Jackalope'" +msgid "Ubuntu 10.10 'Maverick Meerkat'" msgstr "" #. Description #: ../data/templates/Ubuntu.info.in:31 -msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'" +msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'" msgstr "" #. Description #: ../data/templates/Ubuntu.info.in:74 -msgid "Ubuntu 8.10 'Intrepid Ibex'" +msgid "Ubuntu 10.04 'Lucid Lynx'" msgstr "" #. Description #: ../data/templates/Ubuntu.info.in:92 +msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:135 +msgid "Ubuntu 9.10 'Karmic Koala'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:153 +msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:196 +msgid "Ubuntu 9.04 'Jaunty Jackalope'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:214 +msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:257 +msgid "Ubuntu 8.10 'Intrepid Ibex'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:275 msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:136 +#: ../data/templates/Ubuntu.info.in:319 msgid "Ubuntu 8.04 'Hardy Heron'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:154 +#: ../data/templates/Ubuntu.info.in:337 msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:191 +#: ../data/templates/Ubuntu.info.in:382 msgid "Ubuntu 7.10 'Gutsy Gibbon'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:209 +#: ../data/templates/Ubuntu.info.in:400 msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:244 +#: ../data/templates/Ubuntu.info.in:445 msgid "Ubuntu 7.04 'Feisty Fawn'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:262 +#: ../data/templates/Ubuntu.info.in:463 msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:296 +#: ../data/templates/Ubuntu.info.in:505 msgid "Ubuntu 6.10 'Edgy Eft'" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:301 +#: ../data/templates/Ubuntu.info.in:510 msgid "Community-maintained" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:307 +#: ../data/templates/Ubuntu.info.in:516 msgid "Restricted software" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:314 +#: ../data/templates/Ubuntu.info.in:523 msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:348 +#: ../data/templates/Ubuntu.info.in:565 msgid "Ubuntu 6.06 LTS 'Dapper Drake'" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:351 +#: ../data/templates/Ubuntu.info.in:568 msgid "Canonical-supported Open Source software" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:353 +#: ../data/templates/Ubuntu.info.in:570 msgid "Community-maintained (universe)" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:354 +#: ../data/templates/Ubuntu.info.in:571 msgid "Community-maintained Open Source software" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:356 +#: ../data/templates/Ubuntu.info.in:573 msgid "Non-free drivers" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:357 +#: ../data/templates/Ubuntu.info.in:574 msgid "Proprietary drivers for devices" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:359 +#: ../data/templates/Ubuntu.info.in:576 msgid "Restricted software (Multiverse)" msgstr "" #. CompDescriptionLong -#: ../data/templates/Ubuntu.info.in:360 +#: ../data/templates/Ubuntu.info.in:577 msgid "Software restricted by copyright or legal issues" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:366 +#: ../data/templates/Ubuntu.info.in:583 msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:378 +#: ../data/templates/Ubuntu.info.in:599 msgid "Important security updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:383 +#: ../data/templates/Ubuntu.info.in:604 msgid "Recommended updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:388 +#: ../data/templates/Ubuntu.info.in:609 msgid "Pre-released updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:393 +#: ../data/templates/Ubuntu.info.in:614 msgid "Unsupported updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:400 +#: ../data/templates/Ubuntu.info.in:625 msgid "Ubuntu 5.10 'Breezy Badger'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:414 +#: ../data/templates/Ubuntu.info.in:639 msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:426 +#: ../data/templates/Ubuntu.info.in:655 msgid "Ubuntu 5.10 Security Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:431 +#: ../data/templates/Ubuntu.info.in:660 msgid "Ubuntu 5.10 Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:436 +#: ../data/templates/Ubuntu.info.in:665 msgid "Ubuntu 5.10 Backports" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:443 +#: ../data/templates/Ubuntu.info.in:676 msgid "Ubuntu 5.04 'Hoary Hedgehog'" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:457 +#: ../data/templates/Ubuntu.info.in:690 msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:460 ../data/templates/Debian.info.in:123 +#: ../data/templates/Ubuntu.info.in:693 ../data/templates/Debian.info.in:149 msgid "Officially supported" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:469 +#: ../data/templates/Ubuntu.info.in:706 msgid "Ubuntu 5.04 Security Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:474 +#: ../data/templates/Ubuntu.info.in:711 msgid "Ubuntu 5.04 Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:479 +#: ../data/templates/Ubuntu.info.in:716 msgid "Ubuntu 5.04 Backports" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:485 +#: ../data/templates/Ubuntu.info.in:722 msgid "Ubuntu 4.10 'Warty Warthog'" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:491 +#: ../data/templates/Ubuntu.info.in:728 msgid "Community-maintained (Universe)" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:493 +#: ../data/templates/Ubuntu.info.in:730 msgid "Non-free (Multiverse)" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:499 +#: ../data/templates/Ubuntu.info.in:736 msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:502 +#: ../data/templates/Ubuntu.info.in:739 msgid "No longer officially supported" msgstr "" #. CompDescription -#: ../data/templates/Ubuntu.info.in:504 +#: ../data/templates/Ubuntu.info.in:741 msgid "Restricted copyright" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:511 +#: ../data/templates/Ubuntu.info.in:748 msgid "Ubuntu 4.10 Security Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:516 +#: ../data/templates/Ubuntu.info.in:753 msgid "Ubuntu 4.10 Updates" msgstr "" #. Description -#: ../data/templates/Ubuntu.info.in:521 +#: ../data/templates/Ubuntu.info.in:758 msgid "Ubuntu 4.10 Backports" msgstr "" @@ -265,56 +296,61 @@ msgstr "" #. Description #: ../data/templates/Debian.info.in:8 -msgid "Debian 5.0 'Lenny' " +msgid "Debian 6.0 'Squeeze' " msgstr "" #. Description #: ../data/templates/Debian.info.in:33 -msgid "Debian 4.0 'Etch'" +msgid "Debian 5.0 'Lenny' " msgstr "" #. Description #: ../data/templates/Debian.info.in:58 +msgid "Debian 4.0 'Etch'" +msgstr "" + +#. Description +#: ../data/templates/Debian.info.in:83 msgid "Debian 3.1 'Sarge'" msgstr "" #. Description -#: ../data/templates/Debian.info.in:69 +#: ../data/templates/Debian.info.in:94 msgid "Proposed updates" msgstr "" #. Description -#: ../data/templates/Debian.info.in:76 +#: ../data/templates/Debian.info.in:101 msgid "Security updates" msgstr "" #. Description -#: ../data/templates/Debian.info.in:83 +#: ../data/templates/Debian.info.in:108 msgid "Debian current stable release" msgstr "" #. Description -#: ../data/templates/Debian.info.in:96 +#: ../data/templates/Debian.info.in:121 msgid "Debian testing" msgstr "" #. Description -#: ../data/templates/Debian.info.in:121 +#: ../data/templates/Debian.info.in:147 msgid "Debian 'Sid' (unstable)" msgstr "" #. CompDescription -#: ../data/templates/Debian.info.in:125 +#: ../data/templates/Debian.info.in:151 msgid "DFSG-compatible Software with Non-Free Dependencies" msgstr "" #. CompDescription -#: ../data/templates/Debian.info.in:127 +#: ../data/templates/Debian.info.in:153 msgid "Non-DFSG-compatible Software" msgstr "" #. TRANSLATORS: %s is a country -#: ../aptsources/distro.py:207 ../aptsources/distro.py:422 +#: ../aptsources/distro.py:208 ../aptsources/distro.py:423 #, python-format msgid "Server for %s" msgstr "" @@ -322,48 +358,48 @@ msgstr "" #. More than one server is used. Since we don't handle this case #. in the user interface we set "custom servers" to true and #. append a list of all used servers -#: ../aptsources/distro.py:225 ../aptsources/distro.py:231 -#: ../aptsources/distro.py:247 +#: ../aptsources/distro.py:226 ../aptsources/distro.py:232 +#: ../aptsources/distro.py:248 msgid "Main server" msgstr "" -#: ../aptsources/distro.py:251 +#: ../aptsources/distro.py:252 msgid "Custom servers" msgstr "" -#: ../apt/gtk/widgets.py:243 +#: ../apt/progress/gtk2.py:260 ../apt/progress/gtk2.py:316 #, python-format msgid "Downloading file %(current)li of %(total)li with %(speed)s/s" msgstr "" -#: ../apt/gtk/widgets.py:249 +#: ../apt/progress/gtk2.py:266 ../apt/progress/gtk2.py:322 #, python-format msgid "Downloading file %(current)li of %(total)li" msgstr "" #. Setup some child widgets -#: ../apt/gtk/widgets.py:269 +#: ../apt/progress/gtk2.py:342 msgid "Details" msgstr "" -#: ../apt/gtk/widgets.py:351 +#: ../apt/progress/gtk2.py:430 msgid "Starting..." msgstr "" -#: ../apt/gtk/widgets.py:357 +#: ../apt/progress/gtk2.py:436 msgid "Complete" msgstr "" -#: ../apt/package.py:315 +#: ../apt/package.py:342 #, python-format msgid "Invalid unicode in description for '%s' (%s). Please report." msgstr "" -#: ../apt/package.py:878 ../apt/package.py:982 +#: ../apt/package.py:1007 ../apt/package.py:1112 msgid "The list of changes is not available" msgstr "" -#: ../apt/package.py:986 +#: ../apt/package.py:1118 #, python-format msgid "" "The list of changes is not available yet.\n" @@ -372,56 +408,143 @@ msgid "" "until the changes become available or try again later." msgstr "" -#: ../apt/package.py:992 +#: ../apt/package.py:1125 msgid "" "Failed to download the list of changes. \n" "Please check your Internet connection." msgstr "" -#: ../apt/debfile.py:56 -#, python-format -msgid "This is not a valid DEB archive, missing '%s' member" -msgstr "" - -#: ../apt/debfile.py:81 +#: ../apt/debfile.py:79 #, python-format msgid "List of files for '%s' could not be read" msgstr "" -#: ../apt/debfile.py:149 +#: ../apt/debfile.py:164 #, python-format msgid "Dependency is not satisfiable: %s\n" msgstr "" -#: ../apt/debfile.py:173 +#: ../apt/debfile.py:185 #, python-format msgid "Conflicts with the installed package '%s'" msgstr "" -#: ../apt/debfile.py:319 +#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation +#: ../apt/debfile.py:323 +#, python-format +msgid "" +"Breaks existing package '%(pkgname)s' dependency %(depname)s " +"(%(deprelation)s %(depversion)s)" +msgstr "" + +#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation +#: ../apt/debfile.py:339 +#, python-format +msgid "" +"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s " +"%(targetver)s)" +msgstr "" + +#: ../apt/debfile.py:348 +#, python-format +msgid "" +"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But " +"the '%(debfile)s' provides it via: '%(provides)s'" +msgstr "" + +#: ../apt/debfile.py:394 +msgid "No Architecture field in the package" +msgstr "" + +#: ../apt/debfile.py:399 #, python-format msgid "Wrong architecture '%s'" msgstr "" #. the deb is older than the installed -#: ../apt/debfile.py:325 +#: ../apt/debfile.py:406 msgid "A later version is already installed" msgstr "" -#: ../apt/debfile.py:345 +#: ../apt/debfile.py:431 msgid "Failed to satisfy all dependencies (broken cache)" msgstr "" -#: ../apt/debfile.py:376 +#: ../apt/debfile.py:461 #, python-format msgid "Cannot install '%s'" msgstr "" -#: ../apt/debfile.py:484 +#: ../apt/debfile.py:503 ../apt/debfile.py:551 ../apt/debfile.py:562 +msgid "Python-debian module not available" +msgstr "" + +#: ../apt/debfile.py:535 +msgid "" +"Automatically decompressed:\n" +"\n" +msgstr "" + +#: ../apt/debfile.py:541 +msgid "Automatically converted to printable ascii:\n" +msgstr "" + +#: ../apt/debfile.py:638 #, python-format msgid "Install Build-Dependencies for source package '%s' that builds %s\n" msgstr "" -#: ../apt/debfile.py:494 +#: ../apt/debfile.py:648 msgid "An essential package would be removed" msgstr "" + +#: ../apt/progress/text.py:81 +#, python-format +msgid "%c%s... Done" +msgstr "" + +#: ../apt/progress/text.py:120 +msgid "Hit " +msgstr "" + +#: ../apt/progress/text.py:129 +msgid "Ign " +msgstr "" + +#: ../apt/progress/text.py:131 +msgid "Err " +msgstr "" + +#: ../apt/progress/text.py:142 +msgid "Get:" +msgstr "" + +#: ../apt/progress/text.py:202 +msgid " [Working]" +msgstr "" + +#: ../apt/progress/text.py:213 +#, python-format +msgid "" +"Media change: please insert the disc labeled\n" +" '%s'\n" +"in the drive '%s' and press enter\n" +msgstr "" + +#. Trick for getting a translation from apt +#: ../apt/progress/text.py:222 +#, python-format +msgid "Fetched %sB in %s (%sB/s)\n" +msgstr "" + +#: ../apt/progress/text.py:238 +msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'" +msgstr "" + +#: ../apt/progress/text.py:254 +msgid "Please insert a Disc in the drive and press enter" +msgstr "" + +#: ../apt/cache.py:135 +msgid "Building data structures" +msgstr "" diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index a1e9ada0..cacbf77a 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -905,6 +905,8 @@ extern "C" void initapt_pkg() Py_BuildValue("i", pkgAcquire::Item::StatFetching)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_DONE", Py_BuildValue("i", pkgAcquire::Item::StatDone)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_TRANSIENT_NETWORK_ERROR", + Py_BuildValue("i", pkgAcquire::Item::StatTransientNetworkError)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_ERROR", Py_BuildValue("i", pkgAcquire::Item::StatError)); PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_AUTH_ERROR", diff --git a/python/progress.cc b/python/progress.cc index 9002b3eb..437309cf 100644 --- a/python/progress.cc +++ b/python/progress.cc @@ -300,7 +300,10 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) Py_INCREF(pyAcquire); if (RunSimpleCallback("pulse", TUPLEIZE(pyAcquire) , &result1)) { - if (result1 != NULL && PyArg_Parse(result1, "b", &res1) && res1 == false) { + if (result1 != NULL && + result1 != Py_None && + PyArg_Parse(result1, "b", &res1) && + res1 == false) { // the user returned a explicit false here, stop PyCbObj_BEGIN_ALLOW_THREADS return false; diff --git a/python/tag.cc b/python/tag.cc index 9fe12a1a..97039bc4 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -393,7 +393,12 @@ static PyObject *TagFileNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) return 0; TagFileData *New = (TagFileData*)type->tp_alloc(type, 0); +#ifdef APT_HAS_GZIP + new (&New->Fd) FileFd(); + New->Fd.OpenDescriptor(fileno, FileFd::ReadOnlyGzip, false); +#else new (&New->Fd) FileFd(fileno,false); +#endif New->Owner = File; Py_INCREF(New->Owner); new (&New->Object) pkgTagFile(&New->Fd); diff --git a/tests/data/fake-packages/Packages b/tests/data/fake-packages/Packages new file mode 100644 index 00000000..9fbab957 --- /dev/null +++ b/tests/data/fake-packages/Packages @@ -0,0 +1,21 @@ +Package: 2vcard +Priority: optional +Section: universe/utils +Installed-Size: 108 +Maintainer: Arvind Autar <Autar022@planet.nl> +Architecture: amd64 +Version: 0.5-1ubuntu1 +Filename: pool/universe/2/2vcard/2vcard_0.5-1ubuntu1_amd64.deb +Size: 14164 +MD5sum: 105ea91f0a75417d0f9e8e9624513b2a +SHA1: d55beee01c08efc33cd131e106330dca72ee14be +SHA256: 4a72edaf87cdb826e5508b85311fcf0bec9b7e019a55740ded7feb1b9e197f11 +Description: A little perl script to convert an adressbook to VCARD file format + 2vcard is a little perl script that you can use to convert the popular vcard + file format. Currently 2vcard can only convert adressbooks and alias files from + the following formats: abook,eudora,juno,ldif,mutt,mh and pine. + . + The VCARD format is used by gnomecard, for example, which is turn is used by + the balsa email client. +Bugs: mailto:ubuntu-users@lists.ubuntu.com +Origin: Ubuntu diff --git a/tests/data/fake-packages/Packages.gz b/tests/data/fake-packages/Packages.gz Binary files differnew file mode 100644 index 00000000..506bc8d4 --- /dev/null +++ b/tests/data/fake-packages/Packages.gz diff --git a/tests/data/test_debs/gdebi-test1.deb b/tests/data/test_debs/gdebi-test1.deb Binary files differnew file mode 100644 index 00000000..ea9991ac --- /dev/null +++ b/tests/data/test_debs/gdebi-test1.deb diff --git a/tests/data/test_debs/gdebi-test10.deb b/tests/data/test_debs/gdebi-test10.deb Binary files differnew file mode 100644 index 00000000..ca43ace6 --- /dev/null +++ b/tests/data/test_debs/gdebi-test10.deb diff --git a/tests/data/test_debs/gdebi-test2.deb b/tests/data/test_debs/gdebi-test2.deb Binary files differnew file mode 100644 index 00000000..307ac689 --- /dev/null +++ b/tests/data/test_debs/gdebi-test2.deb diff --git a/tests/data/test_debs/gdebi-test3.deb b/tests/data/test_debs/gdebi-test3.deb Binary files differnew file mode 100644 index 00000000..436b9258 --- /dev/null +++ b/tests/data/test_debs/gdebi-test3.deb diff --git a/tests/data/test_debs/gdebi-test4.deb b/tests/data/test_debs/gdebi-test4.deb Binary files differnew file mode 100644 index 00000000..9eb92d1b --- /dev/null +++ b/tests/data/test_debs/gdebi-test4.deb diff --git a/tests/data/test_debs/gdebi-test5.deb b/tests/data/test_debs/gdebi-test5.deb Binary files differnew file mode 100644 index 00000000..0c98c03f --- /dev/null +++ b/tests/data/test_debs/gdebi-test5.deb diff --git a/tests/data/test_debs/gdebi-test6.deb b/tests/data/test_debs/gdebi-test6.deb Binary files differnew file mode 100644 index 00000000..8ceacadc --- /dev/null +++ b/tests/data/test_debs/gdebi-test6.deb diff --git a/tests/data/test_debs/gdebi-test7.deb b/tests/data/test_debs/gdebi-test7.deb Binary files differnew file mode 100644 index 00000000..c0414990 --- /dev/null +++ b/tests/data/test_debs/gdebi-test7.deb diff --git a/tests/data/test_debs/gdebi-test8.deb b/tests/data/test_debs/gdebi-test8.deb Binary files differnew file mode 100644 index 00000000..439f8ca7 --- /dev/null +++ b/tests/data/test_debs/gdebi-test8.deb diff --git a/tests/data/test_debs/gdebi-test9.deb b/tests/data/test_debs/gdebi-test9.deb Binary files differnew file mode 100644 index 00000000..9901d906 --- /dev/null +++ b/tests/data/test_debs/gdebi-test9.deb diff --git a/tests/data/test_debs/var/lib/dpkg/status b/tests/data/test_debs/var/lib/dpkg/status new file mode 100644 index 00000000..f0c48151 --- /dev/null +++ b/tests/data/test_debs/var/lib/dpkg/status @@ -0,0 +1,53 @@ +Package: apt +Status: install ok installed +Priority: important +Section: admin +Installed-Size: 5456 +Maintainer: APT Development Team <deity@lists.debian.org> +Architecture: i386 +Version: 0.7.25.3 +Replaces: libapt-pkg-dev (<< 0.3.7), libapt-pkg-doc (<< 0.3.7) +Provides: libapt-pkg-libc6.10-6-4.8 +Description: Advanced front-end for dpkg + This is Debian's next generation front-end for the dpkg package manager. + It provides the apt-get utility and APT dselect method that provides a + simpler, safer way to install and upgrade packages. + . + APT features complete installation ordering, multiple source capability + and several other unique features, see the Users Guide in apt-doc. + +Package: postfix +Status: install ok installed +Priority: extra +Section: mail +Installed-Size: 3488 +Maintainer: LaMont Jones <lamont@debian.org> +Architecture: i386 +Version: 2.7.0-1 +Replaces: mail-transport-agent, postfix-tls +Provides: default-mta, mail-transport-agent, postfix-tls +Recommends: python +Conflicts: libnss-db (<< 2.2-3), mail-transport-agent, postfix-tls, smail +Description: High-performance mail transport agent + Postfix is Wietse Venema's mail transport agent that started life as an + alternative to the widely-used Sendmail program. Postfix attempts to + be fast, easy to administer, and secure, while at the same time being + sendmail compatible enough to not upset existing users. Thus, the outside + has a sendmail-ish flavor, but the inside is completely different. + +Package: debconf +Status: install ok installed +Priority: important +Section: admin +Installed-Size: 924 +Maintainer: Debconf Developers <debconf-devel@lists.alioth.debian.org> +Architecture: all +Version: 1.5.28 +Replaces: debconf-tiny +Provides: debconf-2.0 +Recommends: apt-utils (>= 0.5.1) +Conflicts: apt (<< 0.3.12.1), cdebconf (<< 0.96), debconf-tiny, debconf-utils (<< 1.3.22), dialog (<< 0.9b-20020814-1), menu (<= 2.1.3-1), whiptail (<< 0.51.4-11), whiptail-utf8 (<= 0.50.17-13) +Description: Debian configuration management system + Debconf is a configuration management system for debian packages. Packages + use Debconf to ask questions when they are installed. +Python-Version: 2.6, 3.1 diff --git a/tests/test_all.py b/tests/test_all.py index d561a9ae..d6370747 100644 --- a/tests/test_all.py +++ b/tests/test_all.py @@ -9,21 +9,29 @@ import os import unittest import sys -if __name__ == '__main__': - sys.stderr.write("[tests] Running on %s\n" % sys.version.replace("\n", "")) - os.chdir(os.path.dirname(__file__)) +def get_library_dir(): # Find the path to the built apt_pkg and apt_inst extensions - if os.path.exists("../build"): - from distutils.util import get_platform - from distutils.sysconfig import get_python_version - # Set the path to the build directory. - plat_specifier = ".%s-%s" % (get_platform(), get_python_version()) - if sys.version_info[0] >= 3 or sys.version_info[1] >= 6: - library_dir = "../build/lib%s%s" % (plat_specifier, + if not os.path.exists("../build"): + return None + from distutils.util import get_platform + from distutils.sysconfig import get_python_version + # Set the path to the build directory. + plat_specifier = ".%s-%s" % (get_platform(), get_python_version()) + if sys.version_info[0] >= 3 or sys.version_info[1] >= 6: + library_dir = "../build/lib%s%s" % (plat_specifier, (sys.pydebug and "-pydebug" or "")) - else: - library_dir = "../build/lib%s%s" % ((sys.pydebug and "_d" or ""), + else: + library_dir = "../build/lib%s%s" % ((sys.pydebug and "_d" or ""), plat_specifier) + return os.path.abspath(library_dir) + +if __name__ == '__main__': + sys.stderr.write("[tests] Running on %s\n" % sys.version.replace("\n", "")) + dirname = os.path.dirname(__file__) + if dirname: + os.chdir(dirname) + library_dir = get_library_dir() + if library_dir: sys.path.insert(0, os.path.abspath(library_dir)) for path in os.listdir('.'): diff --git a/tests/test_apt_cache.py b/tests/test_apt_cache.py index fdcf482d..a43e92d2 100644 --- a/tests/test_apt_cache.py +++ b/tests/test_apt_cache.py @@ -6,9 +6,15 @@ # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. """Unit tests for verifying the correctness of check_dep, etc in apt_pkg.""" +import os +import tempfile import unittest +import sys +sys.path.insert(0, "..") + import apt +import apt_pkg class TestAptCache(unittest.TestCase): @@ -30,5 +36,52 @@ class TestAptCache(unittest.TestCase): self.assertTrue(isinstance(dep.relation, str)) self.assertTrue(dep.pre_depend in (True, False)) + # accessing record should take a reasonable time; in + # particular, when using compressed indexes, it should not use + # tons of seek operations + r = pkg.candidate.record + self.assertEqual(r['Package'], pkg.name) + self.assert_('Version' in r) + self.assert_(len(r['Description']) > 0) + self.assert_(str(r).startswith('Package: %s\n' % pkg.name)) + + def test_get_provided_packages(self): + cache = apt.Cache() + # a true virtual pkg + l = cache.get_providing_packages("mail-transport-agent") + self.assertTrue(len(l) > 0) + # this is a not virtual (transitional) package provided by another + l = cache.get_providing_packages("scrollkeeper") + self.assertEqual(l, []) + # now inlcude nonvirtual packages in the search (rarian-compat + # provides scrollkeeper) + l = cache.get_providing_packages("scrollkeeper", + include_nonvirtual=True) + self.assertTrue(len(l), 1) + + + def test_dpkg_journal_dirty(self): + # backup old value + old_status = apt_pkg.config.find_file("Dir::State::status") + # create tmp env + tmpdir = tempfile.mkdtemp() + dpkg_dir = os.path.join(tmpdir,"var","lib","dpkg") + os.makedirs(os.path.join(dpkg_dir,"updates")) + open(os.path.join(dpkg_dir,"status"), "w") + apt_pkg.config.set("Dir::State::status", + os.path.join(dpkg_dir,"status")) + cache = apt.Cache() + # test empty + self.assertFalse(cache.dpkg_journal_dirty) + # that is ok, only [0-9] are dpkg jounral entries + open(os.path.join(dpkg_dir,"updates","xxx"), "w") + self.assertFalse(cache.dpkg_journal_dirty) + # that is a dirty journal + open(os.path.join(dpkg_dir,"updates","000"), "w") + self.assertTrue(cache.dpkg_journal_dirty) + # reset config value + apt_pkg.config.set("Dir::State::status", old_status) + + if __name__ == "__main__": unittest.main() diff --git a/tests/test_aptsources.py b/tests/test_aptsources.py index 767f5244..3ef20f64 100644 --- a/tests/test_aptsources.py +++ b/tests/test_aptsources.py @@ -98,7 +98,7 @@ class TestAptSources(unittest.TestCase): apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list.testDistribution") sources = aptsources.sourceslist.SourcesList(True, self.templates) - distro = aptsources.distro.get_distro() + distro = aptsources.distro.get_distro(id="Ubuntu") distro.get_sources(sources) # test if all suits of the current distro were detected correctly dist_templates = set() @@ -111,7 +111,7 @@ class TestAptSources(unittest.TestCase): apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list.testDistribution") sources = aptsources.sourceslist.SourcesList(True, self.templates) - distro = aptsources.distro.get_distro() + distro = aptsources.distro.get_distro(id="Ubuntu") distro.get_sources(sources) # test if all suits of the current distro were detected correctly dist_templates = set() diff --git a/tests/test_debfile.py b/tests/test_debfile.py new file mode 100644 index 00000000..bb9fd62c --- /dev/null +++ b/tests/test_debfile.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# +# Copyright (C) 2010 Michael Vogt <mvo@ubuntu.com> +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of DebPackage in apt.debfile.""" +import os +import logging +import unittest + +from test_all import get_library_dir +import sys +sys.path.insert(0, get_library_dir()) +import apt_pkg +import apt.debfile + +class TestDebfilee(unittest.TestCase): + """ test the apt cache """ + + TEST_DEBS = [ + # conflicts with apt + ('gdebi-test1.deb', False), + # impossible dependency + ('gdebi-test2.deb', False), + # or-group (impossible-dependency|apt) + ('gdebi-test3.deb', True), + # Conflicts: apt (<= 0.1) + ('gdebi-test4.deb', True), + # Conflicts: apt (>= 0.1) + ('gdebi-test5.deb', False), + # invalid unicode in descr + ('gdebi-test6.deb', True), + # provides/conflicts against "foobarbaz" + ('gdebi-test7.deb', True), + # provides/conflicts/replaces against "mail-transport-agent" + # (should fails if mail-transport-agent is installed) + ('gdebi-test8.deb', False), + # provides/conflicts against real pkg + ('gdebi-test9.deb', True), + # provides debconf-tiny and the real debconf conflicts with + ('gdebi-test10.deb', False), + ] + + def setUp(self): + apt_pkg.init_config() + apt_pkg.config.set("APT::Architecture","i386") + apt_pkg.config.set("Dir::State::status", + "./data/test_debs/var/lib/dpkg/status") + apt_pkg.init_system() + self.cache = apt.Cache() + + def testDebFile(self): + deb = apt.debfile.DebPackage(cache=self.cache) + for (filename, expected_res) in self.TEST_DEBS: + logging.debug("testing %s, expecting %s" % (filename, expected_res)) + deb.open(os.path.join("data", "test_debs", filename)) + res = deb.check() + self.assertEqual(res, expected_res, + "Unexpected result for package '%s' (got %s wanted %s)\n%s" % ( + filename, res, expected_res, deb._failure_string)) + +if __name__ == "__main__": + #logging.basicConfig(level=logging.DEBUG) + unittest.main() diff --git a/tests/test_progress.py b/tests/test_progress.py new file mode 100644 index 00000000..ffab5bc0 --- /dev/null +++ b/tests/test_progress.py @@ -0,0 +1,47 @@ +#!/usr/bin/python +# +# Copyright (C) 2010 Michael Vogt <mvo@ubuntu.com> +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +"""Unit tests for verifying the correctness of apt.progress""" +import unittest + +import apt +import apt_pkg +import os + +class TestAcquireProgress(apt.progress.base.AcquireProgress): + def pulse(self, owner): + self.pulsed = True + # there should be a return value here, either (True,False) + # but often this is forgoten (and causes odd error messages) + # so the lib supports it. we test the lack of support value here + +class TestProgress(unittest.TestCase): + + def setUp(self): + basedir = os.path.abspath(os.path.dirname(__file__)) + # setup apt_pkg config + apt_pkg.init() + apt_pkg.config.set("APT::Architecture", "amd64") + apt_pkg.config.set("Dir::Etc", basedir) + apt_pkg.config.set("Dir::Etc::sourceparts", "/xxx") + # setup lists dir + if not os.path.exists("./tmp/partial"): + os.makedirs("./tmp/partial") + apt_pkg.config.set("Dir::state::lists", "./tmp") + # create artifical line + deb_line = "deb file:%s/data/fake-packages/ /\n" % basedir + open("fetch_sources.list","w").write(deb_line) + apt_pkg.config.set("Dir::Etc::sourcelist", "fetch_sources.list") + + def test_acquire_progress(self): + progress = TestAcquireProgress() + cache = apt.Cache() + res = cache.update(progress) + self.assertTrue(progress.pulsed) + +if __name__ == "__main__": + unittest.main() diff --git a/utils/pyversions b/utils/pyversions new file mode 100755 index 00000000..3accad3f --- /dev/null +++ b/utils/pyversions @@ -0,0 +1,2 @@ +#!/bin/sh +(/usr/bin/pyversions "$@"; /usr/bin/py3versions "$@"; ) | tr '\n' ' ' |
