summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2009-05-06 21:19:53 +0200
committerMichael Vogt <michael.vogt@ubuntu.com>2009-05-06 21:19:53 +0200
commit2c43ad2f4440571a1fadb6830f14d7a3f1ad2020 (patch)
tree76b78116acb768f6379d3425bace15cc7069bfe9
parentd9096e08b64c0e917bcfcce29f498fa47a6d7db4 (diff)
parentb285f7334fc4aa735993a057c8788876620e55cb (diff)
downloadpython-apt-2c43ad2f4440571a1fadb6830f14d7a3f1ad2020.tar.gz
* merged from debian, remaining changes:
- updated mirrors - build python2.4 - use DH_PYCENTRAL=include-links - use --install-layout=deb - pre-build.sh: update ubuntu mirrors on bzr-buildpackage * apt/package.py: Handle cases where no candidate is available, by returning None in the candidate property. (Closes: #523801) * apt/package.py: Handle cases where no candidate is available and one of the deprecated properties (e.g. candidateVersion) is requested. (Closes: #523801) * setup.py, debian/rules: Support version in setup.py again by getting the value from the variable DEBVER (defined in debian/rules), falling back to None. * Build-Depend on python-debian, use it to get version number from changelog * Depend on libjs-jquery, and remove internal copy (Closes: #521532) * apt/package.py: - Introduce Version.{uri,uris,fetch_binary()} * debian/control: - Remove mdz from Uploaders (Closes: #521477), add myself. - Update Standards-Version to 3.8.1 - Use ${binary:Version} instead of ${Source-Version} - Fix spelling error: python -> Python * debian/copyright: Switch to machine-interpretable copyright * Fix documentation building - doc/source/conf.py: Only include directories for current python version. - debian/control: Build-Depend on python-gtk2, python-vte. - setup.py: If pygtk can not be imported, do not build the documentation. * Breaks: debdelta (<< 0.28~) to avoid more problems due to the internal API changes from 0.7.9. * apt/gtk/widgets.py: - Handle older versions of python-gobject which do not ship glib * apt/package.py: Introduce the Version class - Deprecate Package.candidate*() and Package.installed*(), except for installedFiles. - Provide Version.get_source() (LP: #118788) - Provide Package.versions (Closes: #513236) * apt/progress/: New package, replaces apt.progress and apt.gtk - apt/progress/gtk2.py: Moved here from apt/gtk/widgets.py - apt/progress/__init__.py: Move here from apt/progress.py * doc/source/*: Improve the documentation - Document more attributes and functions of apt_pkg (they are all listed) * aptsources/distro.py: - use iso_3166.xml instead of iso_3166.tab - fix incorrect indent * debian/control: - add Recommends to iso-codes (for iso_3166.xml) * apt/package.py: - make sure to set the defaulttimeout back to the original value (in getChangelog(), LP: #314212) Closes: #513315 * apt/cache.py: - when setting a alternative rootdir, read the config from it as well * python/configuration.cc, python/apt_pkgmodule.cc: - add apt_pkg.ReadConfigDir() * python/cache.cc, tests/getcache_mem_corruption.py: - test if progress objects have the right methods and raise error if not (thanks to Emanuele Rocca) closes: #497049 * apt/package.py: - avoid uneeded interal references in the Package objects * aptsources/sourceslist.py: - fix bug in invalid lines detection (LP: #324614)
-rw-r--r--TODO5
-rw-r--r--apt/__init__.py18
-rw-r--r--apt/cache.py27
-rw-r--r--apt/cdrom.py2
-rw-r--r--apt/debfile.py58
-rw-r--r--apt/gtk/__init__.py0
-rw-r--r--apt/package.py743
-rw-r--r--apt/progress/__init__.py (renamed from apt/progress.py)4
-rw-r--r--apt/progress/gtk2.py (renamed from apt/gtk/widgets.py)7
-rw-r--r--aptsources/distinfo.py10
-rw-r--r--aptsources/distro.py37
-rw-r--r--aptsources/sourceslist.py31
-rw-r--r--debian/changelog92
-rw-r--r--debian/control36
-rw-r--r--debian/copyright58
-rwxr-xr-xdebian/rules7
-rw-r--r--doc/examples/acquire.py3
-rw-r--r--doc/examples/action.py1
-rwxr-xr-xdoc/examples/build-deps.py2
-rw-r--r--doc/examples/cdrom.py6
-rwxr-xr-xdoc/examples/configisc.py1
-rw-r--r--doc/examples/depcache.py3
-rw-r--r--doc/examples/desc.py1
-rwxr-xr-xdoc/examples/gui-inst.py4
-rw-r--r--doc/examples/indexfile.py1
-rw-r--r--doc/examples/inst.py3
-rw-r--r--doc/examples/metaindex.py1
-rw-r--r--doc/examples/progress.py8
-rwxr-xr-xdoc/examples/records.py6
-rwxr-xr-xdoc/examples/update.py1
-rw-r--r--doc/source/apt/package.rst14
-rw-r--r--doc/source/apt/progress.gtk2.rst (renamed from doc/source/apt/gtk.widgets.rst)6
-rw-r--r--doc/source/apt_pkg/index.rst200
-rw-r--r--doc/source/conf.py13
-rw-r--r--doc/source/examples/apt-gtk.py4
-rw-r--r--po/POTFILES.in4
-rw-r--r--python/cache.cc18
-rwxr-xr-xsetup.py18
-rw-r--r--tests/getcache_mem_corruption.py24
-rwxr-xr-xutils/get_ubuntu_mirrors.py2
40 files changed, 1016 insertions, 463 deletions
diff --git a/TODO b/TODO
index c3faedf4..a08a28af 100644
--- a/TODO
+++ b/TODO
@@ -1,8 +1,3 @@
-* apt.Package:
- - change all candidateInstalledSize() to installSize(useCandidate=True)
- same for candidateOrigin() (see downloadable for a example).
- - might be better to have "Package.candidate.{downloadable,size,etc}
-
* aptsources:
- make the distro detection in sources.list more clever by using the
origin informaton to avoid adding full uris to (unofficial/internal)
diff --git a/apt/__init__.py b/apt/__init__.py
index e3cfacbe..ae2abbf2 100644
--- a/apt/__init__.py
+++ b/apt/__init__.py
@@ -1,3 +1,21 @@
+# Copyright (c) 2005-2009 Canonical
+#
+# Author: Michael Vogt <michael.vogt@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
# import the core of apt_pkg
import apt_pkg
import sys
diff --git a/apt/cache.py b/apt/cache.py
index 01c12c94..cc425ccb 100644
--- a/apt/cache.py
+++ b/apt/cache.py
@@ -1,6 +1,6 @@
# cache.py - apt cache abstraction
#
-# Copyright (c) 2005 Canonical
+# Copyright (c) 2005-2009 Canonical
#
# Author: Michael Vogt <michael.vogt@ubuntu.com>
#
@@ -20,7 +20,6 @@
# USA
import os
-import sys
import apt_pkg
from apt import Package
@@ -53,9 +52,11 @@ class Cache(object):
apt_pkg.Config.Set("Dir::Cache::pkgcache", "")
if rootdir:
if os.path.exists(rootdir+"/etc/apt/apt.conf"):
- apt_pkg.ReadConfigFile(apt_pkg.Config, rootdir+"/etc/apt/apt.conf")
+ apt_pkg.ReadConfigFile(apt_pkg.Config,
+ rootdir + "/etc/apt/apt.conf")
if os.path.isdir(rootdir+"/etc/apt/apt.conf.d"):
- apt_pkg.ReadConfigDir(apt_pkg.Config, rootdir+"/etc/apt/apt.conf.d")
+ apt_pkg.ReadConfigDir(apt_pkg.Config,
+ rootdir + "/etc/apt/apt.conf.d")
apt_pkg.Config.Set("Dir", rootdir)
apt_pkg.Config.Set("Dir::State::status",
rootdir + "/var/lib/dpkg/status")
@@ -71,6 +72,8 @@ class Cache(object):
""" Open the package cache, after that it can be used like
a dictionary
"""
+ if progress is None:
+ progress = apt.progress.OpProgress()
self._runCallbacks("cache_pre_open")
self._cache = apt_pkg.GetCache(progress)
self._depcache = apt_pkg.GetDepCache(self._cache)
@@ -79,9 +82,7 @@ class Cache(object):
self._list.ReadMainList()
self._dict = {}
- # build the packages dict
- if progress is not None:
- progress.Op = "Building data structures"
+ progress.Op = "Building data structures"
i=last=0
size=len(self._cache.Packages)
for pkg in self._cache.Packages:
@@ -90,13 +91,11 @@ class Cache(object):
last=i
# drop stuff with no versions (cruft)
if len(pkg.VersionList) > 0:
- self._dict[pkg.Name] = Package(self._cache, self._depcache,
- self._records, self._list,
- self, pkg)
+ self._dict[pkg.Name] = Package(self, pkg)
i += 1
- if progress is not None:
- progress.done()
+
+ progress.done()
self._runCallbacks("cache_post_open")
def __getitem__(self, key):
@@ -156,7 +155,7 @@ class Cache(object):
"""Return the packages not downloadable packages in reqreinst state."""
reqreinst = set()
for pkg in self:
- if (not pkg.candidateDownloadable and
+ if (not pkg.candidate.downloadable and
(pkg._pkg.InstState == apt_pkg.InstStateReInstReq or
pkg._pkg.InstState == apt_pkg.InstStateHoldReInstReq)):
reqreinst.add(pkg.name)
@@ -450,7 +449,7 @@ if __name__ == "__main__":
print len(f)
print "Testing filtered cache (no argument)"
- f = FilteredCache(progress=OpTextProgress())
+ f = FilteredCache(progress=apt.progress.OpTextProgress())
f.cache.connect("cache_pre_change", cache_pre_changed)
f.cache.connect("cache_post_change", cache_post_changed)
f.cache.upgrade()
diff --git a/apt/cdrom.py b/apt/cdrom.py
index 61250fc4..b52762ad 100644
--- a/apt/cdrom.py
+++ b/apt/cdrom.py
@@ -1,6 +1,6 @@
# cdrom.py - CDROM handling
#
-# Copyright (c) 2005 Canonical
+# Copyright (c) 2005-2009 Canonical
# Copyright (c) 2009 Julian Andres Klode <jak@debian.org>
#
# Author: Michael Vogt <michael.vogt@ubuntu.com>
diff --git a/apt/debfile.py b/apt/debfile.py
index f24f19f4..0406a250 100644
--- a/apt/debfile.py
+++ b/apt/debfile.py
@@ -1,24 +1,21 @@
-# Copyright (c) 2005-2007 Canonical
+# Copyright (c) 2005-2009 Canonical
#
-# AUTHOR:
-# Michael Vogt <mvo@ubuntu.com>
+# Author: Michael Vogt <michael.vogt@ubuntu.com>
#
-# This file is part of GDebi
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
#
-# GDebi is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as published
-# by the Free Software Foundation; either version 2 of the License, or (at
-# your option) any later version.
-#
-# GDebi is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GDebi; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
"""Classes for working with locally available Debian packages."""
from gettext import gettext as _
import os
@@ -108,9 +105,8 @@ class DebPackage(object):
return True
continue
- inst = self._cache[depname]
- instver = inst.installedVersion
- if instver is not None and apt_pkg.CheckDep(instver, oper, ver):
+ inst = self._cache[depname].installed
+ if inst is not None and apt_pkg.CheckDep(inst.version, oper, ver):
return True
return False
@@ -163,9 +159,9 @@ class DebPackage(object):
pkg = self._cache[pkgname]
if pkg.isInstalled:
- pkgver = pkg.installedVersion
+ pkgver = pkg.installed.version
elif pkg.markedInstall:
- pkgver = pkg.candidateVersion
+ pkgver = pkg.candidate.version
else:
return False
#print "pkg: %s" % pkgname
@@ -202,7 +198,8 @@ 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, oper):
+ if self._check_single_pkg_conflict(pkg.name, ver,
+ oper):
self._installed_conflicts.add(pkg.name)
continue
if self._check_single_pkg_conflict(depname, ver, oper):
@@ -257,9 +254,9 @@ class DebPackage(object):
self._dbg(3, "replacesPkg() %s %s %s" % (pkgname, oper, ver))
pkg = self._cache[pkgname]
if pkg.isInstalled:
- pkgver = pkg.installedVersion
+ pkgver = pkg.installed.version
elif pkg.markedInstall:
- pkgver = pkg.candidateVersion
+ pkgver = pkg.candidate.version
else:
pkgver = None
for or_group in self.replaces:
@@ -296,10 +293,10 @@ class DebPackage(object):
debver = self._sections["Version"]
self._dbg(1, "debver: %s" % debver)
if pkgname in self._cache:
- if use_installed:
- cachever = self._cache[pkgname].installedVersion
+ if use_installed and self._cache[pkgname].installed:
+ cachever = self._cache[pkgname].installed.version
else:
- cachever = self._cache[pkgname].candidateVersion
+ cachever = self._cache[pkgname].candidate.version
if cachever is not None:
cmp = apt_pkg.VersionCompare(cachever, debver)
self._dbg(1, "CompareVersion(debver,instver): %s" % cmp)
@@ -366,7 +363,8 @@ 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
@@ -403,7 +401,7 @@ class DebPackage(object):
# check authentication, one authenticated origin is enough
# libapt will skip non-authenticated origins then
authenticated = False
- for origin in pkg.candidateOrigin:
+ for origin in pkg.candidate.origins:
authenticated |= origin.trusted
if not authenticated:
unauthenticated.append(pkg.name)
diff --git a/apt/gtk/__init__.py b/apt/gtk/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/apt/gtk/__init__.py
+++ /dev/null
diff --git a/apt/package.py b/apt/package.py
index f5262fff..ec88a456 100644
--- a/apt/package.py
+++ b/apt/package.py
@@ -1,6 +1,6 @@
# package.py - apt package abstraction
#
-# Copyright (c) 2005 Canonical
+# Copyright (c) 2005-2009 Canonical
#
# Author: Michael Vogt <michael.vogt@ubuntu.com>
#
@@ -21,15 +21,19 @@
"""Functionality related to packages."""
import gettext
import httplib
+import os
import sys
import re
import socket
+import subprocess
import urllib2
+import warnings
import apt_pkg
+import apt.progress
-
-__all__ = 'BaseDependency', 'Dependency', 'Origin', 'Package', 'Record'
+__all__ = ('BaseDependency', 'Dependency', 'Origin', 'Package', 'Record',
+ 'Version')
def _(string):
@@ -37,6 +41,17 @@ def _(string):
return gettext.dgettext("python-apt", string)
+def _file_is_same(path, size, md5):
+ """Return True if the file is the same."""
+ if (os.path.exists(path) and os.path.getsize(path) == size and
+ apt_pkg.md5sum(open(path)) == md5):
+ return True
+
+
+class FetchError(Exception):
+ """Raised when a file could not be fetched."""
+
+
class BaseDependency(object):
"""A single dependency.
@@ -53,6 +68,10 @@ class BaseDependency(object):
self.version = ver
self.preDepend = pre
+ def __repr__(self):
+ return ('<BaseDependency: name:%r relation:%r version:%r preDepend:%r>'
+ % (self.name, self.relation, self.version, self.preDepend))
+
class Dependency(object):
"""Represent an Or-group of dependencies.
@@ -64,6 +83,29 @@ class Dependency(object):
def __init__(self, alternatives):
self.or_dependencies = alternatives
+ def __repr__(self):
+ return repr(self.or_dependencies)
+
+
+class DeprecatedProperty(property):
+ """A property which gives DeprecationWarning on access.
+
+ This is only used for providing the properties in Package, which have been
+ replaced by the ones in Version.
+ """
+
+ def __init__(self, fget=None, fset=None, fdel=None, doc=None):
+ property.__init__(self, fget, fset, fdel, doc)
+ self.__doc__ = ':Deprecated: ' + (doc or fget.__doc__ or '')
+
+ def __get__(self, obj, type=None):
+ if obj is not None:
+ warnings.warn("Accessed deprecated property %s.%s, please see the "
+ "Version class for alternatives." %
+ ((obj.__class__.__name__ or type.__name__),
+ self.fget.func_name), DeprecationWarning, 2)
+ return property.__get__(self, obj, type)
+
class Origin(object):
"""The origin of a version.
@@ -85,17 +127,17 @@ class Origin(object):
self.site = VerFileIter.Site
self.not_automatic = VerFileIter.NotAutomatic
# check the trust
- indexfile = pkg._list.FindIndex(VerFileIter)
+ indexfile = pkg._pcache._list.FindIndex(VerFileIter)
if indexfile and indexfile.IsTrusted:
self.trusted = True
else:
self.trusted = False
def __repr__(self):
- return ("<Origin component:'%s' archive:'%s' origin:'%s' label:'%s'"
- "site:'%s' isTrusted:'%s'>") % (self.component, self.archive,
- self.origin, self.label,
- self.site, self.trusted)
+ return ("<Origin component:%r archive:%r origin:%r label:%r "
+ "site:%r isTrusted:%r>") % (self.component, self.archive,
+ self.origin, self.label,
+ self.site, self.trusted)
class Record(object):
@@ -137,6 +179,296 @@ class Record(object):
return self._rec.has_key(key)
+class Version(object):
+ """Representation of a package version.
+
+ :since: 0.7.9
+ """
+
+ def __init__(self, package, cand):
+ self.package = package
+ self._cand = cand
+
+ def __eq__(self, other):
+ return self._cand.ID == other._cand.ID
+
+ def __gt__(self, other):
+ return apt_pkg.VersionCompare(self.version, other.version) > 0
+
+ def __lt__(self, other):
+ return apt_pkg.VersionCompare(self.version, other.version) < 0
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __hash__(self):
+ return self._cand.Hash
+
+ def __repr__(self):
+ return '<Version: package:%r version:%r>' % (self.package.name,
+ self.version)
+
+ @property
+ def _records(self):
+ """Internal helper that moves the Records to the right position."""
+ if self.package._pcache._records.Lookup(self._cand.FileList[0]):
+ return self.package._pcache._records
+
+ @property
+ def installed_size(self):
+ """Return the size of the package when installed."""
+ return self._cand.InstalledSize
+
+ @property
+ def homepage(self):
+ """Return the homepage for the package."""
+ return self._records.Homepage
+
+ @property
+ def size(self):
+ """Return the size of the package."""
+ return self._cand.Size
+
+ @property
+ def architecture(self):
+ """Return the architecture of the package version."""
+ return self._cand.Arch
+
+ @property
+ def downloadable(self):
+ """Return whether the version of the package is downloadable."""
+ return bool(self._cand.Downloadable)
+
+ @property
+ def version(self):
+ """Return the version as a string."""
+ return self._cand.VerStr
+
+ @property
+ def summary(self):
+ """Return the short description (one line summary)."""
+ desc_iter = self._cand.TranslatedDescription
+ self.package._pcache._records.Lookup(desc_iter.FileList.pop(0))
+ return self.package._pcache._records.ShortDesc
+
+ @property
+ def raw_description(self):
+ """return the long description (raw)."""
+ return self._records.LongDesc
+
+ @property
+ def section(self):
+ """Return the section of the package."""
+ return self._cand.Section
+
+ @property
+ def description(self, format=True, useDots=False):
+ """Return the formatted long description.
+
+ Return the formated long description according to the Debian policy
+ (Chapter 5.6.13).
+ See http://www.debian.org/doc/debian-policy/ch-controlfields.html
+ for more information.
+ """
+ self.summary # This does the lookup for us.
+ desc = ''
+ try:
+ dsc = unicode(self.package._pcache._records.LongDesc, "utf-8")
+ except UnicodeDecodeError, err:
+ return _("Invalid unicode in description for '%s' (%s). "
+ "Please report.") % (self.package.name, err)
+
+ lines = iter(dsc.split("\n"))
+ # Skip the first line, since its a duplication of the summary
+ lines.next()
+ for raw_line in lines:
+ if raw_line.strip() == ".":
+ # The line is just line break
+ if not desc.endswith("\n"):
+ desc += "\n\n"
+ continue
+ if raw_line.startswith(" "):
+ # The line should be displayed verbatim without word wrapping
+ if not desc.endswith("\n"):
+ line = "\n%s\n" % raw_line[2:]
+ else:
+ line = "%s\n" % raw_line[2:]
+ elif raw_line.startswith(" "):
+ # The line is part of a paragraph.
+ if desc.endswith("\n") or desc == "":
+ # Skip the leading white space
+ line = raw_line[1:]
+ else:
+ line = raw_line
+ else:
+ line = raw_line
+ # Add current line to the description
+ desc += line
+ return desc
+
+ @property
+ def source_name(self):
+ """Return the name of the source package."""
+ try:
+ return self._records.SourcePkg or self.package.name
+ except IndexError:
+ return self.package.name
+
+ @property
+ def priority(self):
+ """Return the priority of the package, as string."""
+ return self._cand.PriorityStr
+
+ @property
+ def record(self):
+ """Return a Record() object for this version."""
+ return Record(self._records.Record)
+
+ @property
+ def dependencies(self):
+ """Return the dependencies of the package version."""
+ depends_list = []
+ depends = self._cand.DependsList
+ for t in ["PreDepends", "Depends"]:
+ try:
+ for depVerList in depends[t]:
+ base_deps = []
+ for depOr in depVerList:
+ base_deps.append(BaseDependency(depOr.TargetPkg.Name,
+ depOr.CompType, depOr.TargetVer,
+ (t == "PreDepends")))
+ depends_list.append(Dependency(base_deps))
+ except KeyError:
+ pass
+ return depends_list
+
+ @property
+ def origins(self):
+ """Return a list of origins for the package version."""
+ origins = []
+ for (verFileIter, index) in self._cand.FileList:
+ origins.append(Origin(self.package, verFileIter))
+ return origins
+
+ @property
+ def filename(self):
+ """Return the path to the file inside the archive."""
+ return self._records.FileName
+
+ @property
+ def md5(self):
+ """Return the md5sum of the binary."""
+ return self._records.MD5Hash
+
+ @property
+ def sha1(self):
+ """Return the sha1sum of the binary."""
+ return self._records.SHA1Hash
+
+ @property
+ def sha256(self):
+ """Return the sha1sum of the binary."""
+ return self._records.SHA256Hash
+
+ def _uris(self):
+ """Return an iterator over all available urls."""
+ for (packagefile, index) in self._cand.FileList:
+ indexfile = self.package._pcache._list.FindIndex(packagefile)
+ if indexfile:
+ yield indexfile.ArchiveURI(self._records.FileName)
+
+ @property
+ def uris(self):
+ """Return a list of all available uris for the binary."""
+ return list(self._uris())
+
+ @property
+ def uri(self):
+ """Return a single URI for the binary."""
+ return self._uris().next()
+
+ def fetch_binary(self, destdir='', progress=None):
+ """Fetch the binary version of the package.
+
+ The parameter 'destdir' specifies the directory where the package will
+ be fetched to.
+
+ The parameter 'progress' may refer to an apt.progress.FetchProgress()
+ object. If not specified or None, apt.progress.TextFetchProgress() is
+ used.
+ """
+ base = os.path.basename(self._records.FileName)
+ destfile = os.path.join(destdir, base)
+ if _file_is_same(destfile, self.size, self._records.MD5Hash):
+ print 'Ignoring already existing file:', destfile
+ return
+ acq = apt_pkg.GetAcquire(progress or apt.progress.TextFetchProgress())
+ apt_pkg.GetPkgAcqFile(acq, self.uri, self._records.MD5Hash, self.size,
+ base, destFile=destfile)
+ acq.Run()
+ for item in acq.Items:
+ if item.Status != item.StatDone:
+ raise FetchError("The item %r could not be fetched: %s" %
+ (item.DestFile, item.ErrorText))
+ return os.path.abspath(destfile)
+
+ def fetch_source(self, destdir="", progress=None, unpack=True):
+ """Get the source code of a package.
+
+ The parameter 'destdir' specifies the directory where the source will
+ be fetched to.
+
+ The parameter 'progress' may refer to an apt.progress.FetchProgress()
+ object. If not specified or None, apt.progress.TextFetchProgress() is
+ used.
+
+ The parameter 'unpack' describes whether the source should be unpacked
+ (True) or not (False). By default, it is unpacked.
+
+ If 'unpack' is True, the path to the extracted directory is returned.
+ Otherwise, the path to the .dsc file is returned.
+ """
+ src = apt_pkg.GetPkgSrcRecords()
+ acq = apt_pkg.GetAcquire(progress or apt.progress.TextFetchProgress())
+
+ dsc = None
+ src.Lookup(self.package.name)
+ try:
+ while self.version != src.Version:
+ src.Lookup(self.package.name)
+ except AttributeError:
+ raise ValueError("No source for %r" % self)
+ for md5, size, path, type in src.Files:
+ base = os.path.basename(path)
+ destfile = os.path.join(destdir, base)
+ if type == 'dsc':
+ dsc = destfile
+ if os.path.exists(base) and os.path.getsize(base) == size:
+ fobj = open(base)
+ try:
+ if apt_pkg.md5sum(fobj) == md5:
+ print 'Ignoring already existing file:', destfile
+ continue
+ finally:
+ fobj.close()
+ apt_pkg.GetPkgAcqFile(acq, src.Index.ArchiveURI(path), md5, size,
+ base, destFile=destfile)
+ acq.Run()
+
+ for item in acq.Items:
+ if item.Status != item.StatDone:
+ raise FetchError("The item %r could not be fetched: %s" %
+ (item.DestFile, item.ErrorText))
+
+ if unpack:
+ outdir = src.Package + '-' + apt_pkg.UpstreamVersion(src.Version)
+ outdir = os.path.join(destdir, outdir)
+ subprocess.check_call(["dpkg-source", "-x", dsc, outdir])
+ return os.path.abspath(outdir)
+ else:
+ return os.path.abspath(dsc)
+
+
class Package(object):
"""Representation of a package in a cache.
@@ -145,38 +477,31 @@ class Package(object):
much more.
"""
- def __init__(self, cache, depcache, records, sourcelist, pcache, pkgiter):
+ def __init__(self, pcache, pkgiter):
""" Init the Package object """
- self._cache = cache # low level cache
- self._depcache = depcache
- self._records = records
self._pkg = pkgiter
- self._list = sourcelist # sourcelist
self._pcache = pcache # python cache in cache.py
self._changelog = "" # Cached changelog
- def _lookupRecord(self, UseCandidate=True):
- """Internal helper that moves the Records to the right position.
+ def __repr__(self):
+ return '<Package: name:%r id:%r>' % (self._pkg.Name, self._pkg.ID)
- Must be called before _records is accessed.
- """
- if UseCandidate:
- ver = self._depcache.GetCandidateVer(self._pkg)
- else:
- ver = self._pkg.CurrentVer
-
- # check if we found a version
- if ver is None:
- #print "No version for: %s (Candidate: %s)" % (self._pkg.Name,
- # UseCandidate)
- return False
-
- if ver.FileList is None:
- print "No FileList for: %s " % self._pkg.Name()
- return False
- f, index = ver.FileList.pop(0)
- self._records.Lookup((f, index))
- return True
+ @property
+ def candidate(self):
+ """Return the candidate version of the package.
+
+ :since: 0.7.9"""
+ cand = self._pcache._depcache.GetCandidateVer(self._pkg)
+ if cand is not None:
+ return Version(self, cand)
+
+ @property
+ def installed(self):
+ """Return the currently installed version of the package.
+
+ :since: 0.7.9"""
+ if self._pkg.CurrentVer is not None:
+ return Version(self, self._pkg.CurrentVer)
@property
def name(self):
@@ -196,142 +521,81 @@ class Package(object):
This returns the same value as ID, which is unique."""
return self._pkg.ID
- @property
+ @DeprecatedProperty
def installedVersion(self):
- """Return the installed version as string."""
- ver = self._pkg.CurrentVer
- if ver is not None:
- return ver.VerStr
- else:
- return None
+ """Return the installed version as string.
- @property
+ Deprecated, please use installed.version instead."""
+ return getattr(self.installed, 'version', None)
+
+ @DeprecatedProperty
def candidateVersion(self):
"""Return the candidate version as string."""
- ver = self._depcache.GetCandidateVer(self._pkg)
- if ver is not None:
- return ver.VerStr
- else:
- return None
-
- def _getDependencies(self, ver):
- """Get the dependencies for a given version of a package."""
- depends_list = []
- depends = ver.DependsList
- for t in ["PreDepends", "Depends"]:
- try:
- for depVerList in depends[t]:
- base_deps = []
- for depOr in depVerList:
- base_deps.append(BaseDependency(depOr.TargetPkg.Name,
- depOr.CompType, depOr.TargetVer,
- (t == "PreDepends")))
- depends_list.append(Dependency(base_deps))
- except KeyError:
- pass
- return depends_list
+ return getattr(self.candidate, "version", None)
- @property
+ @DeprecatedProperty
def candidateDependencies(self):
"""Return a list of candidate dependencies."""
- candver = self._depcache.GetCandidateVer(self._pkg)
- if candver is None:
- return []
- return self._getDependencies(candver)
+ return getattr(self.candidate, "dependencies", None)
- @property
+ @DeprecatedProperty
def installedDependencies(self):
"""Return a list of installed dependencies."""
- ver = self._pkg.CurrentVer
- if ver is None:
- return []
- return self._getDependencies(ver)
+ return getattr(self.installed, 'dependencies', [])
- @property
+ @DeprecatedProperty
def architecture(self):
"""Return the Architecture of the package"""
- if not self._lookupRecord():
- return None
- sec = apt_pkg.ParseSection(self._records.Record)
- try:
- return sec["Architecture"]
- except KeyError:
- return None
-
- def _downloadable(self, useCandidate=True):
- """Return True if the package is downloadable."""
- if useCandidate:
- ver = self._depcache.GetCandidateVer(self._pkg)
- else:
- ver = self._pkg.CurrentVer
- if ver is None:
- return False
- return ver.Downloadable
+ return getattr(self.candidate, "architecture", None)
- @property
+ @DeprecatedProperty
def candidateDownloadable(self):
"""Return True if the candidate is downloadable."""
- return self._downloadable(True)
+ return getattr(self.candidate, "downloadable", None)
- @property
+ @DeprecatedProperty
def installedDownloadable(self):
"""Return True if the installed version is downloadable."""
- return self._downloadable(False)
+ return getattr(self.installed, 'downloadable', False)
- @property
+ @DeprecatedProperty
def sourcePackageName(self):
"""Return the source package name as string."""
- if not self._lookupRecord():
- if not self._lookupRecord(False):
+ try:
+ return self.candidate._records.SourcePkg or self._pkg.Name
+ except AttributeError:
+ try:
+ return self.installed._records.SourcePkg or self._pkg.Name
+ except AttributeError:
return self._pkg.Name
- src = self._records.SourcePkg
- if src != "":
- return src
- else:
- return self._pkg.Name
- @property
+ @DeprecatedProperty
def homepage(self):
"""Return the homepage field as string."""
- if not self._lookupRecord():
- return None
- return self._records.Homepage
+ return getattr(self.candidate, "homepage", None)
@property
def section(self):
"""Return the section of the package."""
return self._pkg.Section
- @property
+ @DeprecatedProperty
def priority(self):
"""Return the priority (of the candidate version)."""
- ver = self._depcache.GetCandidateVer(self._pkg)
- if ver:
- return ver.PriorityStr
- else:
- return None
+ return getattr(self.candidate, "priority", None)
- @property
+ @DeprecatedProperty
def installedPriority(self):
"""Return the priority (of the installed version)."""
- ver = self._depcache.GetCandidateVer(self._pkg)
- if ver:
- return ver.PriorityStr
- else:
- return None
+ return getattr(self.installed, 'priority', None)
- @property
+ @DeprecatedProperty
def summary(self):
"""Return the short description (one line summary)."""
- if not self._lookupRecord():
- return ""
- ver = self._depcache.GetCandidateVer(self._pkg)
- desc_iter = ver.TranslatedDescription
- self._records.Lookup(desc_iter.FileList.pop(0))
- return self._records.ShortDesc
+ return getattr(self.candidate, "summary", None)
- @property
- def description(self, format=True, useDots=False):
+ @DeprecatedProperty
+ def description(self):
"""Return the formatted long description.
Return the formated long description according to the Debian policy
@@ -339,105 +603,54 @@ class Package(object):
See http://www.debian.org/doc/debian-policy/ch-controlfields.html
for more information.
"""
- if not format:
- return self.rawDescription
- if not self._lookupRecord():
- return ""
- # get the translated description
- ver = self._depcache.GetCandidateVer(self._pkg)
- desc_iter = ver.TranslatedDescription
- self._records.Lookup(desc_iter.FileList.pop(0))
- desc = ""
- try:
- dsc = unicode(self._records.LongDesc, "utf-8")
- except UnicodeDecodeError, err:
- dsc = _("Invalid unicode in description for '%s' (%s). "
- "Please report.") % (self.name, err)
- lines = dsc.split("\n")
- for i in range(len(lines)):
- # Skip the first line, since its a duplication of the summary
- if i == 0:
- continue
- raw_line = lines[i]
- if raw_line.strip() == ".":
- # The line is just line break
- if not desc.endswith("\n"):
- desc += "\n"
- continue
- elif raw_line.startswith(" "):
- # The line should be displayed verbatim without word wrapping
- if not desc.endswith("\n"):
- line = "\n%s\n" % raw_line[2:]
- else:
- line = "%s\n" % raw_line[2:]
- elif raw_line.startswith(" "):
- # The line is part of a paragraph.
- if desc.endswith("\n") or desc == "":
- # Skip the leading white space
- line = raw_line[1:]
- else:
- line = raw_line
- else:
- line = raw_line
- # Use dots for lists
- if useDots:
- line = re.sub(r"^(\s*)(\*|0|o|-) ", ur"\1\u2022 ", line, 1)
- # Add current line to the description
- desc += line
- return desc
+ return getattr(self.candidate, "description", None)
- @property
+ @DeprecatedProperty
def rawDescription(self):
"""return the long description (raw)."""
- if not self._lookupRecord():
- return ""
- return self._records.LongDesc
+ return getattr(self.candidate, "raw_description", None)
- @property
+ @DeprecatedProperty
def candidateRecord(self):
"""Return the Record of the candidate version of the package."""
- if not self._lookupRecord(True):
- return None
- return Record(self._records.Record)
+ return getattr(self.candidate, "record", None)
- @property
+ @DeprecatedProperty
def installedRecord(self):
"""Return the Record of the candidate version of the package."""
- if not self._lookupRecord(False):
- return None
- return Record(self._records.Record)
+ return getattr(self.installed, 'record', '')
# depcache states
@property
def markedInstall(self):
"""Return True if the package is marked for install."""
- return self._depcache.MarkedInstall(self._pkg)
+ return self._pcache._depcache.MarkedInstall(self._pkg)
@property
def markedUpgrade(self):
"""Return True if the package is marked for upgrade."""
- return self._depcache.MarkedUpgrade(self._pkg)
+ return self._pcache._depcache.MarkedUpgrade(self._pkg)
@property
def markedDelete(self):
"""Return True if the package is marked for delete."""
- return self._depcache.MarkedDelete(self._pkg)
+ return self._pcache._depcache.MarkedDelete(self._pkg)
@property
def markedKeep(self):
"""Return True if the package is marked for keep."""
- return self._depcache.MarkedKeep(self._pkg)
+ return self._pcache._depcache.MarkedKeep(self._pkg)
@property
def markedDowngrade(self):
""" Package is marked for downgrade """
- return self._depcache.MarkedDowngrade(self._pkg)
+ return self._pcache._depcache.MarkedDowngrade(self._pkg)
@property
def markedReinstall(self):
"""Return True if the package is marked for reinstall."""
- return self._depcache.MarkedReinstall(self._pkg)
+ return self._pcache._depcache.MarkedReinstall(self._pkg)
@property
def isInstalled(self):
@@ -447,7 +660,8 @@ class Package(object):
@property
def isUpgradable(self):
"""Return True if the package is upgradable."""
- return self.isInstalled and self._depcache.IsUpgradable(self._pkg)
+ return (self.isInstalled and
+ self._pcache._depcache.IsUpgradable(self._pkg))
@property
def isAutoRemovable(self):
@@ -457,38 +671,29 @@ class Package(object):
another package, and if no packages depend on it anymore, the package
is no longer required.
"""
- return self.isInstalled and self._depcache.IsGarbage(self._pkg)
+ return self.isInstalled and self._pcache._depcache.IsGarbage(self._pkg)
# sizes
- @property
+ @DeprecatedProperty
def packageSize(self):
"""Return the size of the candidate deb package."""
- ver = self._depcache.GetCandidateVer(self._pkg)
- return ver.Size
+ return getattr(self.candidate, "size", None)
- @property
+ @DeprecatedProperty
def installedPackageSize(self):
"""Return the size of the installed deb package."""
- ver = self._pkg.CurrentVer
- return ver.Size
+ return getattr(self.installed, 'size', 0)
- @property
- def candidateInstalledSize(self, UseCandidate=True):
+ @DeprecatedProperty
+ def candidateInstalledSize(self):
"""Return the size of the candidate installed package."""
- ver = self._depcache.GetCandidateVer(self._pkg)
- if ver:
- return ver.Size
- else:
- return None
+ return getattr(self.candidate, "installed_size", None)
- @property
+ @DeprecatedProperty
def installedSize(self):
"""Return the size of the currently installed package."""
- ver = self._pkg.CurrentVer
- if ver is None:
- return 0
- return ver.InstalledSize
+ return getattr(self.installed, 'installed_size', 0)
@property
def installedFiles(self):
@@ -528,11 +733,13 @@ class Package(object):
return self._changelog
if uri is None:
- if self.candidateOrigin[0].origin == "Debian":
+ if not self.candidate:
+ pass
+ if self.candidate.origins[0].origin == "Debian":
uri = "http://packages.debian.org/changelogs/pool" \
"/%(src_section)s/%(prefix)s/%(src_pkg)s" \
"/%(src_pkg)s_%(src_ver)s/changelog"
- elif self.candidateOrigin[0].origin == "Ubuntu":
+ elif self.candidate.origins[0].origin == "Ubuntu":
uri = "http://changelogs.ubuntu.com/changelogs/pool" \
"/%(src_section)s/%(prefix)s/%(src_pkg)s" \
"/%(src_pkg)s_%(src_ver)s/changelog"
@@ -540,16 +747,16 @@ class Package(object):
return _("The list of changes is not available")
# get the src package name
- src_pkg = self.sourcePackageName
+ src_pkg = self.candidate.source_name
# assume "main" section
src_section = "main"
# use the section of the candidate as a starting point
- section = self._depcache.GetCandidateVer(self._pkg).Section
+ section = self.candidate.section
# get the source version, start with the binaries version
- bin_ver = self.candidateVersion
- src_ver = self.candidateVersion
+ bin_ver = self.candidate.version
+ src_ver = self.candidate.version
#print "bin: %s" % binver
try:
# FIXME: This try-statement is too long ...
@@ -595,7 +802,7 @@ class Package(object):
"src_ver": src_ver}
timeout = socket.getdefaulttimeout()
-
+
# FIXME: when python2.4 vanishes from the archive,
# merge this into a single try..finally block (pep 341)
try:
@@ -610,7 +817,6 @@ class Package(object):
# do only get the lines that are new
changelog = ""
regexp = "^%s \((.*)\)(.*)$" % (re.escape(src_pkg))
-
while True:
# Check if the download was canceled
if cancel_lock and cancel_lock.isSet():
@@ -619,8 +825,8 @@ class Package(object):
line_raw = changelog_file.readline()
if line_raw == "":
break
- # The changelog is encoded in utf-8, but since there isn't any
- # http header, urllib2 seems to treat it as ascii
+ # The changelog is encoded in utf-8, but since there isn't
+ # any http header, urllib2 seems to treat it as ascii
line = line_raw.decode("utf-8")
#print line.encode('utf-8')
@@ -634,8 +840,8 @@ class Package(object):
changelog_ver = match.group(1)
if changelog_ver and ":" in changelog_ver:
changelog_ver = changelog_ver.split(":", 1)[1]
- if (installed and
- apt_pkg.VersionCompare(changelog_ver, installed) <= 0):
+ if (installed and apt_pkg.VersionCompare(changelog_ver,
+ installed) <= 0):
break
# EOF (shouldn't really happen)
changelog += line
@@ -647,8 +853,8 @@ class Package(object):
except urllib2.HTTPError:
return _("The list of changes is not available yet.\n\n"
- "Please use http://launchpad.net/ubuntu/+source/%s/%s/"
- "+changelog\n"
+ "Please use http://launchpad.net/ubuntu/+source/%s/"
+ "%s/+changelog\n"
"until the changes become available or try again "
"later.") % (src_pkg, src_ver)
except (IOError, httplib.BadStatusLine):
@@ -658,23 +864,25 @@ class Package(object):
socket.setdefaulttimeout(timeout)
return self._changelog
- @property
+ @DeprecatedProperty
def candidateOrigin(self):
- """Return the Origin() of the candidate version."""
- ver = self._depcache.GetCandidateVer(self._pkg)
- if not ver:
- return None
- origins = []
- for (verFileIter, index) in ver.FileList:
- origins.append(Origin(self, verFileIter))
- return origins
+ """Return a list of Origin() objects for the candidate version."""
+ return getattr(self.candidate, "origins", None)
+
+ @property
+ def versions(self):
+ """Return a list of versions.
+
+ :since: 0.7.9
+ """
+ return [Version(self, ver) for ver in self._pkg.VersionList]
# depcache actions
def markKeep(self):
"""Mark a package for keep."""
self._pcache.cachePreChange()
- self._depcache.MarkKeep(self._pkg)
+ self._pcache._depcache.MarkKeep(self._pkg)
self._pcache.cachePostChange()
def markDelete(self, autoFix=True, purge=False):
@@ -687,10 +895,10 @@ class Package(object):
well. The default is to keep the configuration.
"""
self._pcache.cachePreChange()
- self._depcache.MarkDelete(self._pkg, purge)
+ self._pcache._depcache.MarkDelete(self._pkg, purge)
# try to fix broken stuffsta
- if autoFix and self._depcache.BrokenCount > 0:
- Fix = apt_pkg.GetPkgProblemResolver(self._depcache)
+ if autoFix and self._pcache._depcache.BrokenCount > 0:
+ Fix = apt_pkg.GetPkgProblemResolver(self._pcache._depcache)
Fix.Clear(self._pkg)
Fix.Protect(self._pkg)
Fix.Remove(self._pkg)
@@ -713,10 +921,10 @@ class Package(object):
it.
"""
self._pcache.cachePreChange()
- self._depcache.MarkInstall(self._pkg, autoInst, fromUser)
+ self._pcache._depcache.MarkInstall(self._pkg, autoInst, fromUser)
# try to fix broken stuff
- if autoFix and self._depcache.BrokenCount > 0:
- fixer = apt_pkg.GetPkgProblemResolver(self._depcache)
+ if autoFix and self._pcache._depcache.BrokenCount > 0:
+ fixer = apt_pkg.GetPkgProblemResolver(self._pcache._depcache)
fixer.Clear(self._pkg)
fixer.Protect(self._pkg)
fixer.Resolve(True)
@@ -740,7 +948,7 @@ class Package(object):
The parameter `iprogress` refers to an InstallProgress() object, as
found in apt.progress.
"""
- self._depcache.Commit(fprogress, iprogress)
+ self._pcache._depcache.Commit(fprogress, iprogress)
def _test():
@@ -749,40 +957,33 @@ def _test():
import random
import apt
apt_pkg.init()
- cache = apt_pkg.GetCache()
- depcache = apt_pkg.GetDepCache(cache)
- records = apt_pkg.GetPkgRecords(cache)
- sourcelist = apt_pkg.GetPkgSourceList()
-
- pkgiter = cache["apt-utils"]
- pkg = Package(cache, depcache, records, sourcelist, None, pkgiter)
+ progress = apt.progress.OpTextProgress()
+ cache = apt.Cache(progress)
+ pkg = cache["apt-utils"]
print "Name: %s " % pkg.name
print "ID: %s " % pkg.id
- print "Priority (Candidate): %s " % pkg.priority
- print "Priority (Installed): %s " % pkg.installedPriority
- print "Installed: %s " % pkg.installedVersion
- print "Candidate: %s " % pkg.candidateVersion
- print "CandidateDownloadable: %s" % pkg.candidateDownloadable
- print "CandidateOrigins: %s" % pkg.candidateOrigin
- print "SourcePkg: %s " % pkg.sourcePackageName
+ print "Priority (Candidate): %s " % pkg.candidate.priority
+ print "Priority (Installed): %s " % pkg.installed.priority
+ print "Installed: %s " % pkg.installed.version
+ print "Candidate: %s " % pkg.candidate.version
+ print "CandidateDownloadable: %s" % pkg.candidate.downloadable
+ print "CandidateOrigins: %s" % pkg.candidate.origins
+ print "SourcePkg: %s " % pkg.candidate.source_name
print "Section: %s " % pkg.section
- print "Summary: %s" % pkg.summary
- print "Description (formated) :\n%s" % pkg.description
- print "Description (unformated):\n%s" % pkg.rawDescription
- print "InstalledSize: %s " % pkg.installedSize
- print "PackageSize: %s " % pkg.packageSize
- print "Dependencies: %s" % pkg.installedDependencies
- for dep in pkg.candidateDependencies:
+ print "Summary: %s" % pkg.candidate.summary
+ print "Description (formated) :\n%s" % pkg.candidate.description
+ print "Description (unformated):\n%s" % pkg.candidate.raw_description
+ print "InstalledSize: %s " % pkg.candidate.installed_size
+ print "PackageSize: %s " % pkg.candidate.size
+ print "Dependencies: %s" % pkg.installed.dependencies
+ for dep in pkg.candidate.dependencies:
print ",".join("%s (%s) (%s) (%s)" % (o.name, o.version, o.relation,
o.preDepend) for o in dep.or_dependencies)
- print "arch: %s" % pkg.architecture
- print "homepage: %s" % pkg.homepage
- print "rec: ", pkg.candidateRecord
+ print "arch: %s" % pkg.candidate.architecture
+ print "homepage: %s" % pkg.candidate.homepage
+ print "rec: ", pkg.candidate.record
- # now test install/remove
- progress = apt.progress.OpTextProgress()
- cache = apt.Cache(progress)
print cache["2vcard"].getChangelog()
for i in True, False:
print "Running install on random upgradable pkgs with AutoFix: %s " % i
diff --git a/apt/progress.py b/apt/progress/__init__.py
index 51eb2426..769942ce 100644
--- a/apt/progress.py
+++ b/apt/progress/__init__.py
@@ -1,6 +1,6 @@
-# Progress.py - progress reporting classes
+# progress.py - progress reporting classes
#
-# Copyright (c) 2005 Canonical
+# Copyright (c) 2005-2009 Canonical
#
# Author: Michael Vogt <michael.vogt@ubuntu.com>
#
diff --git a/apt/gtk/widgets.py b/apt/progress/gtk2.py
index 34cc2759..f872e34f 100644
--- a/apt/gtk/widgets.py
+++ b/apt/progress/gtk2.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright (c) 2004-2005 Canonical
+# Copyright (c) 2004-2009 Canonical
#
# Authors: Michael Vogt <michael.vogt@ubuntu.com>
# Sebastian Heinlein <glatzor@ubuntu.com>
@@ -29,7 +29,10 @@ import time
import pygtk
pygtk.require('2.0')
import gtk
-import glib
+try:
+ import glib
+except ImportError:
+ import gobject as glib
import gobject
import pango
import vte
diff --git a/aptsources/distinfo.py b/aptsources/distinfo.py
index 59fa7e02..ce44e48b 100644
--- a/aptsources/distinfo.py
+++ b/aptsources/distinfo.py
@@ -1,12 +1,10 @@
-#!/usr/bin/env python
-#
# distinfo.py - provide meta information for distro repositories
#
-# Copyright (c) 2005 Gustavo Noronha Silva
-# 2006-2007 Sebastian Heinlein
+# Copyright (c) 2005 Gustavo Noronha Silva <kov@debian.org>
+# Copyright (c) 2006-2007 Sebastian Heinlein <glatzor@ubuntu.com>
#
-# Author: Gustavo Noronha Silva <kov@debian.org>
-# Sebastian Heinlein <glatzor@ubuntu.com>
+# Authors: Gustavo Noronha Silva <kov@debian.org>
+# Sebastian Heinlein <glatzor@ubuntu.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
diff --git a/aptsources/distro.py b/aptsources/distro.py
index 36ab0ff8..bbb8ba50 100644
--- a/aptsources/distro.py
+++ b/aptsources/distro.py
@@ -1,7 +1,7 @@
# distro.py - Provide a distro abstraction of the sources.list
#
-# Copyright (c) 2004-2007 Canonical Ltd.
-# 2006-2007 Sebastian Heinlein
+# Copyright (c) 2004-2009 Canonical Ltd.
+# Copyright (c) 2006-2007 Sebastian Heinlein
#
# Authors: Sebastian Heinlein <glatzor@ubuntu.com>
# Michael Vogt <mvo@debian.org>
@@ -103,22 +103,22 @@ class Distribution:
self.is_codename(source.template.name)):
#print "yeah! found a distro repo: %s" % source.line
# cdroms need do be handled differently
- if (source.uri.startswith("cdrom:") and
+ if (source.uri.startswith("cdrom:") and
source.disabled == False):
self.cdrom_sources.append(source)
cdrom_comps.extend(source.comps)
- elif (source.uri.startswith("cdrom:") and
+ elif (source.uri.startswith("cdrom:") and
source.disabled == True):
self.cdrom_sources.append(source)
- elif (source.type == self.binary_type and
+ elif (source.type == self.binary_type and
source.disabled == False):
self.main_sources.append(source)
comps.extend(source.comps)
media.append(source.uri)
- elif (source.type == self.binary_type and
+ elif (source.type == self.binary_type and
source.disabled == True):
self.disabled_sources.append(source)
- elif (source.type == self.source_type
+ elif (source.type == self.source_type
and source.disabled == False):
self.source_code_sources.append(source)
elif (source.type == self.source_type and
@@ -126,10 +126,10 @@ class Distribution:
self.disabled_sources.append(source)
if (source.invalid == False and
source.template in self.source_template.children):
- if (source.disabled == False
+ if (source.disabled == False
and source.type == self.binary_type):
self.child_sources.append(source)
- elif (source.disabled == False
+ elif (source.disabled == False
and source.type == self.source_type):
self.source_code_sources.append(source)
else:
@@ -167,15 +167,16 @@ class Distribution:
et = ElementTree(file=fname)
it = et.getiterator('iso_3166_entry')
for elm in it:
- if elm.attrib.has_key("common_name"):
+ try:
descr = elm.attrib["common_name"]
- else:
+ except KeyError:
descr = elm.attrib["name"]
- if elm.attrib.has_key("alpha_2_code"):
+ try:
code = elm.attrib["alpha_2_code"]
- else:
+ except KeyError:
code = elm.attrib["alpha_3_code"]
- self.countries[code.lower()] = gettext.dgettext('iso_3166',descr)
+ self.countries[code.lower()] = gettext.dgettext('iso_3166',
+ descr)
# try to guess the nearest mirror from the locale
self.country = None
@@ -219,14 +220,14 @@ class Distribution:
# Store all available servers:
# Name, URI, active
mirrors = []
- if (len(self.used_servers) < 1 or
- (len(self.used_servers) == 1 and
+ if (len(self.used_servers) < 1 or
+ (len(self.used_servers) == 1 and
compare_mirrors(self.used_servers[0], self.main_server))):
mirrors.append([_("Main server"), self.main_server, True])
if self.nearest_server:
mirrors.append([self._get_mirror_name(self.nearest_server),
self.nearest_server, False])
- elif (len(self.used_servers) == 1 and not
+ elif (len(self.used_servers) == 1 and not
compare_mirrors(self.used_servers[0], self.main_server)):
mirrors.append([_("Main server"), self.main_server, False])
# Only one server is used
@@ -384,7 +385,7 @@ class Distribution:
change_server_of_source(source, uri, seen_binary)
for source in self.child_sources:
# Do not change the forces server of a child source
- if (source.template.base_uri is None or
+ if (source.template.base_uri is None or
source.template.base_uri != source.uri):
change_server_of_source(source, uri, seen_binary)
for source in self.source_code_sources:
diff --git a/aptsources/sourceslist.py b/aptsources/sourceslist.py
index cb36d9df..1dfd870f 100644
--- a/aptsources/sourceslist.py
+++ b/aptsources/sourceslist.py
@@ -1,12 +1,12 @@
# aptsource.py - Provide an abstraction of the sources.list
#
-# Copyright (c) 2004-2007 Canonical Ltd.
-# 2004 Michiel Sikkes
-# 2006-2007 Sebastian Heinlein
+# Copyright (c) 2004-2009 Canonical Ltd.
+# Copyright (c) 2004 Michiel Sikkes
+# Copyright (c) 2006-2007 Sebastian Heinlein
#
-# Author: Michiel Sikkes <michiel@eyesopened.nl>
-# Michael Vogt <mvo@debian.org>
-# Sebastian Heinlein <glatzor@ubuntu.com>
+# Authors: Michiel Sikkes <michiel@eyesopened.nl>
+# Michael Vogt <mvo@debian.org>
+# Sebastian Heinlein <glatzor@ubuntu.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
@@ -219,7 +219,7 @@ class NullMatcher(object):
return True
-class SourcesList:
+class SourcesList(object):
""" represents the full sources.list + sources.list.d file """
def __init__(self,
@@ -236,9 +236,8 @@ class SourcesList:
""" update the list of known entries """
self.list = []
# read sources.list
- dir = apt_pkg.Config.FindDir("Dir::Etc")
- file = apt_pkg.Config.Find("Dir::Etc::sourcelist")
- self.load(dir+file)
+ file = apt_pkg.Config.FindFile("Dir::Etc::sourcelist")
+ self.load(file)
# read sources.list.d
partsdir = apt_pkg.Config.FindDir("Dir::Etc::sourceparts")
for file in glob.glob("%s/*.list" % partsdir):
@@ -312,11 +311,10 @@ class SourcesList:
def restoreBackup(self, backup_ext):
" restore sources.list files based on the backup extension "
- dir = apt_pkg.Config.FindDir("Dir::Etc")
- file = apt_pkg.Config.Find("Dir::Etc::sourcelist")
- if os.path.exists(dir+file+backup_ext) and \
- os.path.exists(dir+file):
- shutil.copy(dir+file+backup_ext, dir+file)
+ file = apt_pkg.Config.FindFile("Dir::Etc::sourcelist")
+ if os.path.exists(file+backup_ext) and \
+ os.path.exists(file):
+ shutil.copy(file+backup_ext, file)
# now sources.list.d
partsdir = apt_pkg.Config.FindDir("Dir::Etc::sourceparts")
for file in glob.glob("%s/*.list" % partsdir):
@@ -353,8 +351,7 @@ class SourcesList:
files = {}
# write an empty default config file if there aren't any sources
if len(self.list) == 0:
- path = "%s%s" % (apt_pkg.Config.FindDir("Dir::Etc"),
- apt_pkg.Config.Find("Dir::Etc::sourcelist"))
+ path = apt_pkg.Config.FindFile("Dir::Etc::sourcelist")
header = (
"## See sources.list(5) for more information, especialy\n"
"# Remember that you can only use http, ftp or file URIs\n"
diff --git a/debian/changelog b/debian/changelog
index a0fc52b8..94b5f37e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,95 @@
+python-apt (0.7.10.3ubuntu1) karmic; urgency=low
+
+ * merged from debian, remaining changes:
+ - updated mirrors
+ - build python2.4
+ - use DH_PYCENTRAL=include-links
+ - use --install-layout=deb
+ - pre-build.sh: update ubuntu mirrors on bzr-buildpackage
+
+ -- Michael Vogt <mvo@debian.org> Tue, 05 May 2009 12:03:27 +0200
+
+python-apt (0.7.10.3) unstable; urgency=low
+
+ * apt/package.py: Handle cases where no candidate is available, by returning
+ None in the candidate property. (Closes: #523801)
+
+ -- Julian Andres Klode <jak@debian.org> Sun, 12 Apr 2009 19:50:26 +0200
+
+python-apt (0.7.10.2) unstable; urgency=low
+
+ * apt/package.py: Handle cases where no candidate is available and
+ one of the deprecated properties (e.g. candidateVersion) is
+ requested. (Closes: #523801)
+ * setup.py, debian/rules: Support version in setup.py again by getting
+ the value from the variable DEBVER (defined in debian/rules), falling
+ back to None.
+
+ -- Julian Andres Klode <jak@debian.org> Sun, 12 Apr 2009 19:00:07 +0200
+
+python-apt (0.7.10) unstable; urgency=low
+
+ * Build-Depend on python-debian, use it to get version number from changelog
+ * Depend on libjs-jquery, and remove internal copy (Closes: #521532)
+ * apt/package.py:
+ - Introduce Version.{uri,uris,fetch_binary()}
+ * debian/control:
+ - Remove mdz from Uploaders (Closes: #521477), add myself.
+ - Update Standards-Version to 3.8.1
+ - Use ${binary:Version} instead of ${Source-Version}
+ - Fix spelling error: python -> Python
+ * debian/copyright: Switch to machine-interpretable copyright
+ * Fix documentation building
+ - doc/source/conf.py: Only include directories for current python version.
+ - debian/control: Build-Depend on python-gtk2, python-vte.
+ - setup.py: If pygtk can not be imported, do not build the documentation.
+ * Breaks: debdelta (<< 0.28~) to avoid more problems due to the internal
+ API changes from 0.7.9.
+
+ -- Julian Andres Klode <jak@debian.org> Wed, 01 Apr 2009 15:24:29 +0200
+
+python-apt (0.7.9) unstable; urgency=low
+
+ [ Julian Andres Klode ]
+ * apt/gtk/widgets.py:
+ - Handle older versions of python-gobject which do not ship glib
+ * apt/package.py: Introduce the Version class
+ - Deprecate Package.candidate*() and Package.installed*(), except for
+ installedFiles.
+ - Provide Version.get_source() (LP: #118788)
+ - Provide Package.versions (Closes: #513236)
+ * apt/progress/: New package, replaces apt.progress and apt.gtk
+ - apt/progress/gtk2.py: Moved here from apt/gtk/widgets.py
+ - apt/progress/__init__.py: Move here from apt/progress.py
+ * doc/source/*: Improve the documentation
+ - Document more attributes and functions of apt_pkg (they are all listed)
+
+ [ Michael Vogt ]
+ * aptsources/distro.py:
+ - use iso_3166.xml instead of iso_3166.tab
+ - fix incorrect indent
+ * debian/control:
+ - add Recommends to iso-codes (for iso_3166.xml)
+ * apt/package.py:
+ - make sure to set the defaulttimeout back to the
+ original value (in getChangelog(), LP: #314212)
+ Closes: #513315
+ * apt/cache.py:
+ - when setting a alternative rootdir, read the
+ config from it as well
+ * python/configuration.cc, python/apt_pkgmodule.cc:
+ - add apt_pkg.ReadConfigDir()
+ * python/cache.cc, tests/getcache_mem_corruption.py:
+ - test if progress objects have the right methods
+ and raise error if not (thanks to Emanuele Rocca)
+ closes: #497049
+ * apt/package.py:
+ - avoid uneeded interal references in the Package objects
+ * aptsources/sourceslist.py:
+ - fix bug in invalid lines detection (LP: #324614)
+
+ -- Michael Vogt <mvo@debian.org> Thu, 19 Mar 2009 13:39:21 +0100
+
python-apt (0.7.9~exp2ubuntu11) karmic; urgency=low
[ Matthias Klose ]
diff --git a/debian/control b/debian/control
index abae4b5b..57a95cd4 100644
--- a/debian/control
+++ b/debian/control
@@ -3,18 +3,32 @@ Section: python
Priority: optional
Maintainer: Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
XSBC-Original-Maintainer: APT Development Team <deity@lists.debian.org>
-Uploaders: Matt Zimmerman <mdz@debian.org>, Michael Vogt <mvo@debian.org>
-Standards-Version: 3.7.2.2
-XS-Python-Version: 2.4, all
-Build-Depends: debhelper (>= 5.0.37.1), libapt-pkg-dev (>= 0.7.20), apt-utils, python-all-dev, python-distutils-extra (>= 1.9.0), cdbs, python-central (>= 0.6.11), python-all-dbg, python-sphinx (>= 0.5), python2.4-dev, python2.4-dbg
-XS-Original-Vcs-Bzr: http://bzr.debian.org/apt/python-apt/debian-sid
-Vcs-Bzr: http://code.launchpad.net/~ubuntu-core-dev/python-apt/ubuntu
+Uploaders: Michael Vogt <mvo@debian.org>, Julian Andres Klode <jak@debian.org>
+Standards-Version: 3.8.1
+XS-Python-Version: all
+Build-Depends: apt-utils,
+ cdbs,
+ debhelper (>= 5.0.37.1),
+ libapt-pkg-dev (>= 0.7.10),
+ python-all-dbg,
+ python-all-dev,
+ python2.4-dev,
+ python2.4-dbg,
+ python-central (>= 0.5),
+ python-debian,
+ python-distutils-extra (>= 1.9.0),
+ python-gtk2,
+ python-sphinx (>= 0.5),
+ python-vte
+Vcs-Bzr: http://bzr.debian.org/apt/python-apt/debian-sid
+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
+Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, lsb-release,
+ libjs-jquery
Recommends: iso-codes
-Priority: optional
+Breaks: debdelta (<< 0.28~)
Provides: ${python:Provides}
Suggests: python-apt-dbg, python-gtk2, python-vte
XB-Python-Version: ${python:Versions}
@@ -34,10 +48,12 @@ Description: Python interface to libapt-pkg
Package: python-apt-dbg
Priority: extra
Architecture: any
-Depends: python-dbg, python-apt (= ${Source-Version}), ${shlibs:Depends}
+Section: debug
+Depends: python-dbg, python-apt (= ${binary:Version}), ${shlibs:Depends},
+ ${misc:Depends}
Description: Python interface to libapt-pkg (debug extension)
The apt_pkg Python interface will provide full access to the internal
libapt-pkg structures allowing Python programs to easily perform a
variety of functions.
.
- This package contains the extension built for the python debug interpreter.
+ This package contains the extension built for the Python debug interpreter.
diff --git a/debian/copyright b/debian/copyright
index f8463185..8599328a 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,7 +1,53 @@
-APT is free software; you can redistribute them and/or modify them under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; either version 2 of the License, or (at your option) any later
-version.
+Format-Specification: http://wiki.debian.org/Proposals/CopyrightFormat?action=recall&rev=443
-On Debian systems, a copy of the GNU General Public License can be
-found in /usr/share/common-licenses/GPL.
+Files: *
+Copyright: © 2004-2009 Canonical Ltd.
+License: GPL-2+
+
+Files: aptsources/*.py
+Copyright: © 2004-2009 Canonical Ltd.
+Copyright: © 2005 Gustavo Noronha Silva
+Copyright: © 2006-2007 Sebastian Heinlein
+License: GPL-2+
+
+Files: doc/source/*
+Copyright: © 2009 Julian Andres Klode <jak@debian.org>
+License: GPL-2+
+
+Files: utils/get_*.py
+Copyright: © 2006 Free Software Foundation Europe
+License: GPL-2+
+
+Files: po/*
+Copyright: © 2006 Canonical Ltd, and Rosetta Contributors 2006
+License: GPL-2+
+
+Files: po/de.po
+Copyright: © 2005 Michiel Sikkes <michiel@eyesopened.nl>
+License: GPL-2+
+
+Files: po/en_CA.po
+Copyright: © 2005 Adam Weinberger and the GNOME Foundation
+License: GPL-2+
+
+Files: po/fi.po
+Copyright: © 2005-2006 Timo Jyrinki
+License: GPL-2+
+
+Files: po/fr.po
+Copyright: © 2007 Hugues NAULET <hnaulet@gmail.com>
+License: GPL-2+
+
+Files: po/hu.po, po/lt.po, po/pt.po, po/ro.po, po/rw.po, po/sv.po, po/uk.po,
+ po/zh_HK.po
+Copyright: © 2005-2006 Free Software Foundation
+License: GPL-2+
+
+License: GPL-2+
+ APT is free software; you can redistribute them and/or modify them under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+ .
+ On Debian systems, a copy of the GNU General Public License can be
+ found in /usr/share/common-licenses/GPL-2.
diff --git a/debian/rules b/debian/rules
index a96e17ff..e9917843 100755
--- a/debian/rules
+++ b/debian/rules
@@ -15,6 +15,7 @@ PKG=python-apt
DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p')
DEB_COMPRESS_EXCLUDE:=.html .js _static/* _sources/* _sources/*/* .inv
DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us -uc $(DEB_BUILD_PROG_OPTS)
+export DEBVER
build/python-apt-dbg::
set -e; \
@@ -22,9 +23,6 @@ build/python-apt-dbg::
python$$i-dbg ./setup.py build; \
done
-build/python-apt::
- pydoc -w
-
install/python-apt-dbg::
for i in $(cdbs_python_build_versions); do \
python$$i-dbg ./setup.py install --root $(CURDIR)/debian/python-apt-dbg --install-layout=deb; \
@@ -33,6 +31,9 @@ install/python-apt-dbg::
! -type d ! -name '*_d.so' | xargs rm -f
find debian/python-apt-dbg -depth -empty -exec rmdir {} \;
+binary-predeb/python-apt::
+ ln -sf ../../../../javascript/jquery/jquery.js debian/python-apt/usr/share/doc/python-apt/html/_static/jquery.js
+
binary-predeb/python-apt-dbg::
rm -rf debian/python-apt-dbg/usr/share/doc/python-apt-dbg
ln -s python-apt debian/python-apt-dbg/usr/share/doc/python-apt-dbg
diff --git a/doc/examples/acquire.py b/doc/examples/acquire.py
index 58372961..41a38588 100644
--- a/doc/examples/acquire.py
+++ b/doc/examples/acquire.py
@@ -1,8 +1,7 @@
+#!/usr/bin/python
import apt
import apt_pkg
import os
-import sys
-import tempfile
def get_file(fetcher, uri, destFile):
diff --git a/doc/examples/action.py b/doc/examples/action.py
index 9b9d7dd3..8ee86eb7 100644
--- a/doc/examples/action.py
+++ b/doc/examples/action.py
@@ -3,7 +3,6 @@
import apt_pkg
import sys
-import copy
from apt.progress import OpTextProgress
from progress import TextFetchProgress
diff --git a/doc/examples/build-deps.py b/doc/examples/build-deps.py
index aeb5667c..b5ac88a2 100755
--- a/doc/examples/build-deps.py
+++ b/doc/examples/build-deps.py
@@ -32,7 +32,7 @@ if len(sys.argv) < 2:
print "need a package name as argument"
sys.exit(1)
try:
- base = cache[sys.argv[1]]
+ pkg = base = cache[sys.argv[1]]
except KeyError:
print "No package %s found" % sys.argv[1]
sys.exit(1)
diff --git a/doc/examples/cdrom.py b/doc/examples/cdrom.py
index 743220a6..408bd720 100644
--- a/doc/examples/cdrom.py
+++ b/doc/examples/cdrom.py
@@ -3,10 +3,8 @@
import apt_pkg
import sys
-import os
-import copy
-from progress import CdromProgress
+from progress import TextCdromProgress
# init
@@ -15,7 +13,7 @@ apt_pkg.init()
cdrom = apt_pkg.GetCdrom()
print cdrom
-progress = CdromProgress()
+progress = TextCdromProgress()
(res, ident) = cdrom.Ident(progress)
print "ident result is: %s (%s) " % (res, ident)
diff --git a/doc/examples/configisc.py b/doc/examples/configisc.py
index de8ec6be..8da1ad0a 100755
--- a/doc/examples/configisc.py
+++ b/doc/examples/configisc.py
@@ -10,7 +10,6 @@
import apt_pkg
import sys
-import posixpath
ConfigFile = apt_pkg.ParseCommandLine(apt_pkg.Config, [], sys.argv)
diff --git a/doc/examples/depcache.py b/doc/examples/depcache.py
index 790cc9d6..de038fe8 100644
--- a/doc/examples/depcache.py
+++ b/doc/examples/depcache.py
@@ -1,10 +1,7 @@
#!/usr/bin/python
# example how to deal with the depcache
-import apt
import apt_pkg
-import sys
-import copy
from progress import TextProgress
diff --git a/doc/examples/desc.py b/doc/examples/desc.py
index f47517cf..2febf348 100644
--- a/doc/examples/desc.py
+++ b/doc/examples/desc.py
@@ -1,3 +1,4 @@
+#!/usr/bin/python
import apt_pkg
diff --git a/doc/examples/gui-inst.py b/doc/examples/gui-inst.py
index 8138d922..68f06fc0 100755
--- a/doc/examples/gui-inst.py
+++ b/doc/examples/gui-inst.py
@@ -5,13 +5,13 @@ import pygtk
pygtk.require('2.0')
import gtk
-import apt.gtk.widgets
+import apt.progress.gtk2
if __name__ == "__main__":
win = gtk.Window()
- progress = apt.gtk.widgets.GtkAptProgress()
+ progress = apt.progress.gtk2.GtkAptProgress()
win.set_title("GtkAptProgress Demo")
win.add(progress)
progress.show()
diff --git a/doc/examples/indexfile.py b/doc/examples/indexfile.py
index 22d0b635..2f1f27f8 100644
--- a/doc/examples/indexfile.py
+++ b/doc/examples/indexfile.py
@@ -1,3 +1,4 @@
+#!/usr/bin/python
import apt_pkg
diff --git a/doc/examples/inst.py b/doc/examples/inst.py
index a3a50356..5a7fc993 100644
--- a/doc/examples/inst.py
+++ b/doc/examples/inst.py
@@ -3,9 +3,6 @@
import apt
import sys
-import os
-import copy
-import time
from apt.progress import InstallProgress
diff --git a/doc/examples/metaindex.py b/doc/examples/metaindex.py
index f00a7e01..816a3fd7 100644
--- a/doc/examples/metaindex.py
+++ b/doc/examples/metaindex.py
@@ -1,3 +1,4 @@
+#!/usr/bin/python
import apt_pkg
diff --git a/doc/examples/progress.py b/doc/examples/progress.py
index 83847598..2231001f 100644
--- a/doc/examples/progress.py
+++ b/doc/examples/progress.py
@@ -1,3 +1,5 @@
+#!/usr/bin/python
+
import sys
import time
@@ -38,7 +40,7 @@ class TextFetchProgress(apt.FetchProgress):
def pulse(self):
print "Pulse: CPS: %s/s; Bytes: %s/%s; Item: %s/%s" % (
- apt.SizeToStr(self.currentCPS), SizeToStr(self.currentBytes),
+ apt.SizeToStr(self.currentCPS), apt.SizeToStr(self.currentBytes),
apt.SizeToStr(self.totalBytes), self.currentItems, self.totalItems)
return True
@@ -79,12 +81,12 @@ class TextCdromProgress(apt.CdromProgress):
def update(self, text, step):
# check if we actually have some text to display
if text != "":
- print "Update: %s %s" % (string.strip(text), step)
+ print "Update: %s %s" % (text.strip(), step)
def askCdromName(self):
print "Please enter cd-name: ",
cd_name = sys.stdin.readline()
- return (True, string.strip(cd_name))
+ return (True, cd_name.strip())
def changeCdrom(self):
print "Please insert cdrom and press <ENTER>"
diff --git a/doc/examples/records.py b/doc/examples/records.py
index a0fc8dc4..681eac0c 100755
--- a/doc/examples/records.py
+++ b/doc/examples/records.py
@@ -5,9 +5,9 @@ import apt
cache = apt.Cache()
for pkg in cache:
- if not pkg.candidateRecord:
+ if not pkg.candidate.record:
continue
- if "Task" in pkg.candidateRecord:
+ if "Task" in pkg.candidate.record:
print "Pkg %s is part of '%s'" % (
- pkg.name, pkg.candidateRecord["Task"].split())
+ pkg.name, pkg.candidate.record["Task"].split())
#print pkg.candidateRecord
diff --git a/doc/examples/update.py b/doc/examples/update.py
index 364fa1c9..5929c9f8 100755
--- a/doc/examples/update.py
+++ b/doc/examples/update.py
@@ -1,3 +1,4 @@
+#!/usr/bin/python
import apt
import apt_pkg
import os.path
diff --git a/doc/source/apt/package.rst b/doc/source/apt/package.rst
index 1bd032ab..bb74915e 100644
--- a/doc/source/apt/package.rst
+++ b/doc/source/apt/package.rst
@@ -10,6 +10,16 @@ The Package class
.. autoclass:: Package
:members:
+ .. note::
+
+ Several methods have been deprecated in version 0.7.9 of python-apt,
+ please see the :class:`Version` class for the new alternatives.
+
+The Version class
+-----------------
+.. autoclass:: Version
+ :members:
+
Dependency Information
----------------------
@@ -88,14 +98,14 @@ Examples
cache = apt.Cache()
pkg = cache['python-apt'] # Access the Package object for python-apt
- print 'python-apt is trusted:', pkg.candidateOrigin.trusted
+ print 'python-apt is trusted:', pkg.candidate.origins[0].trusted
# Mark python-apt for install
pkg.markInstall()
print 'python-apt is marked for install:', pkg.markedInstall
- print 'python-apt is', pkg.summary #Python interface to libapt-pkg
+ print 'python-apt is (summary):', pkg.candidate.summary
# Now, really install it
cache.commit()
diff --git a/doc/source/apt/gtk.widgets.rst b/doc/source/apt/progress.gtk2.rst
index 9fa84ead..a83ab111 100644
--- a/doc/source/apt/gtk.widgets.rst
+++ b/doc/source/apt/progress.gtk2.rst
@@ -1,6 +1,6 @@
-:mod:`apt.gtk.widgets` --- GTK widgets
-======================================
-.. automodule:: apt.gtk.widgets
+:mod:`apt.progress.gtk2` --- GTK widgets
+========================================
+.. automodule:: apt.progress.gtk2
GObject progress classes
diff --git a/doc/source/apt_pkg/index.rst b/doc/source/apt_pkg/index.rst
index 1c5866a9..6e7b772e 100644
--- a/doc/source/apt_pkg/index.rst
+++ b/doc/source/apt_pkg/index.rst
@@ -34,7 +34,7 @@ Object initialization
----------------------
.. function:: GetCache([progress])
- Return a :class:`pkgCache` object. The optional parameter ``progress``
+ Return a :class:`pkgCache` object. The optional parameter *progress*
specifies an instance of :class:`apt.progress.OpProgress()` which will
display the open progress.
@@ -44,25 +44,54 @@ Object initialization
.. method:: Cdrom.Ident(progress)
- Identify the cdrom. The parameter ``progress`` refers to an
+ Identify the cdrom. The parameter *progress* refers to an
:class:`apt.progress.CdromProgress()` object.
.. method:: Cdrom.Add(progress)
- Add the cdrom to the sources.list file. The parameter ``progress``
+ Add the cdrom to the sources.list file. The parameter *progress*
refers to an :class:`apt.progress.CdromProgress()` object.
-
.. function:: GetDepCache(cache)
- Return a :class:`pkgDepCache` object. The parameter ``cache`` specifies an
+ Return a :class:`pkgDepCache` object. The parameter *cache* specifies an
instance of :class:`pkgCache` (see :func:`GetCache()`).
.. function:: GetPkgSourceList()
- Return a :class:`pkgSourceList` object.
+ Return a :class:`PkgSourceList` object.
+
+.. function:: GetPackageManager(depcache)
+
+ Return a new :class:`PkgManager` object. The parameter *depcache* specifies
+ a :class:`pkgDepCache` object as returned by :func:`GetDepCache`.
+
+.. function:: GetPkgActionGroup(depcache)
+
+ Return a new :class:`ActionGroup` object. The parameter *depcache*
+ specifies a :class:`pkgDepCache` object as returned by :func:`GetDepCache`.
+
+.. function:: GetPkgProblemResolver(depcache)
+
+ Return a new :class:`ProblemResolver` object. The parameter *depcache*
+ specifies a :class:`pkgDepCache` object as returned by :func:`GetDepCache`.
+
+.. function:: GetPkgRecords(cache)
+
+ Return a new :class:`PkgRecords` object.
+
+ The parameter *cache* refers to an :class:`pkgCache` object, as returned
+ by :func:`GetCache`.
+
+.. function:: GetPkgSrcRecords()
+
+ Return a new :class:`PkgSrcRecords` object.
+
+.. function:: newConfiguration()
+
+ Return a new :class:`Configuration` object.
The Acquire interface
@@ -70,7 +99,7 @@ The Acquire interface
.. function:: GetAcquire([progress])
Return an :class:`Acquire` object. This is a class which allows you
- to fetch files, or archive contents. The parameter ``progress`` refers to
+ to fetch files, or archive contents. The parameter *progress* refers to
an :class:`apt.progress.FetchProgress()` object.
Acquire items have multiple methods:
@@ -99,26 +128,29 @@ The Acquire interface
.. function:: GetPkgAcqFile(aquire, uri[, md5, size, descr, shortDescr, destDir, destFile])
- The parameter ``acquire`` refers to an :class:`Acquire()` object as returned
+ Create a new :class:`PkgAcqFile()` object and register it with *acquire*,
+ so it will be fetched.
+
+ The parameter *acquire* refers to an :class:`Acquire()` object as returned
by :func:`GetAcquire`. The file will be added to the Acquire queue
automatically.
- The parameter ``uri`` refers to the location of the file, any protocol
+ The parameter *uri* refers to the location of the file, any protocol
of apt is supported.
- The parameter ``md5`` refers to the md5sum of the file. This can be used
+ The parameter *md5* refers to the md5sum of the file. This can be used
for checking the file.
- The parameter ``size`` can be used to specify the size of the package,
+ The parameter *size* can be used to specify the size of the package,
which can then be used to calculate the progress and validate the download.
- The parameter ``descr`` is a descripition of the download. It may be
- used to describe the item in the progress class. ``shortDescr`` is the
+ The parameter *descr* is a descripition of the download. It may be
+ used to describe the item in the progress class. *shortDescr* is the
short form of it.
- You can use ``destDir`` to manipulate the directory where the file will
- be saved in. Together with ``destFile`` you can specify the complete target
- path.
+ You can use *destDir* to manipulate the directory where the file will
+ be saved in. Instead of *destDir*, you can also specify the full path to
+ the file using the parameter *destFile*. You can not combine both.
@@ -130,19 +162,19 @@ of the ones provides in Python's :mod:`hashlib` module.
.. function:: md5sum(object)
- Return the md5sum of the object. ``object`` may either be a string, in
+ Return the md5sum of the object. *object* may either be a string, in
which case the md5sum of the string is returned, or a :class:`file()`
object, in which case the md5sum of its contents is returned.
.. function:: sha1sum(object)
- Return the sha1sum of the object. ``object`` may either be a string, in
+ Return the sha1sum of the object. *object* may either be a string, in
which case the sha1sum of the string is returned, or a :class:`file()`
object, in which case the sha1sum of its contents is returned.
.. function:: sha256sum(object)
- Return the sha256sum of the object. ``object`` may either be a string, in
+ Return the sha256sum of the object. *object* may either be a string, in
which case the sha256sum of the string is returned, or a :class:`file()`
object, in which case the sha256sum of its contents is returned.
@@ -151,19 +183,15 @@ Other functions
.. note::
- This documentation is created automatically and should be rewritten.
+ This documentation is (in parts) created automatically, and still needs to
+ be improved.
.. autofunction:: Base64Encode
.. autofunction:: CheckDep
.. autofunction:: CheckDomainList
.. autofunction:: DeQuoteString
.. autofunction:: GetLock
-.. autofunction:: GetPackageManager
-.. autofunction:: GetPkgActionGroup
-.. autofunction:: GetPkgProblemResolver
-.. autofunction:: GetPkgRecords
-.. autofunction:: GetPkgSrcRecords
-.. autofunction:: newConfiguration
+
.. autofunction:: ParseCommandLine
.. autofunction:: ParseDepends
.. autofunction:: ParseSection
@@ -173,16 +201,108 @@ Other functions
.. autofunction:: PkgSystemUnLock
.. autofunction:: QuoteString
.. autofunction:: ReadConfigFile
+.. autofunction:: ReadConfigDir()
.. autofunction:: ReadConfigFileISC
.. autofunction:: RewriteSection
-.. autofunction:: SizeToStr
-.. autofunction:: StringToBool
-.. autofunction:: StrToTime
-.. autofunction:: TimeRFC1123
-.. autofunction:: TimeToStr
-.. autofunction:: UpstreamVersion
-.. autofunction:: URItoFileName
-.. autofunction:: VersionCompare
+
+.. function:: SizeToStr(size)
+
+ Return a string presenting the human-readable version of the integer
+ *size*. When calculating the units (k,M,G,etc.) the size is divided by the
+ factor 1000.
+
+ Example::
+
+ >>> apt_pkg.SizeToStr(10000)
+ '10.0k'
+
+.. function:: StringToBool(input)
+
+ Parse the string *input* and return one of **-1**, **0**, **1**.
+
+ .. table:: Return values
+
+ ===== =============================================
+ Value Meaning
+ ===== =============================================
+ -1 The string *input* is not recognized.
+ 0 The string *input* evaluates to **False**.
+ +1 The string *input* evaluates to **True**.
+ ===== =============================================
+
+ Example::
+
+ >>> apt_pkg.StringToBool("yes")
+ 1
+ >>> apt_pkg.StringToBool("no")
+ 0
+ >>> apt_pkg.StringToBool("not-recognized")
+ -1
+
+.. function:: StrToTime(rfc_time)
+
+ Convert the :rfc:`1123` conforming string *rfc_time* to the unix time, and
+ return the integer. This is the opposite of :func:`TimeRFC1123`.
+
+ Example::
+
+ >> apt_pkg.StrToTime('Thu, 01 Jan 1970 00:00:00 GMT')
+ 0
+
+.. function:: TimeRFC1123(seconds)
+
+ Format the unix time specified by the integer *seconds*, according to the
+ requirements of :rfc:`1123`.
+
+ Example::
+
+ >>> apt_pkg.TimeRFC1123(0)
+ 'Thu, 01 Jan 1970 00:00:00 GMT'
+
+
+.. function:: TimeToStr(seconds)
+
+ Format a given duration in a human-readable manner. The parameter *seconds*
+ refers to a number of seconds, given as an integer. The return value is a
+ string with a unit like 's' for seconds.
+
+ Example::
+
+ >>> apt_pkg.TimeToStr(3601)
+ '1h0min1s'
+
+
+
+.. function:: UpstreamVersion(version)
+
+ Return the string *version*, eliminating everything following the last
+ '-'. Thus, this should be equivalent to ``version.rsplit('-', 1)[0]``.
+
+.. function:: URItoFileName(uri)
+
+ Take a string *uri* as parameter and return a filename which can be used to
+ store the file, based on the URI.
+
+ Example::
+
+ >>> apt_pkg.URItoFileName('http://debian.org/index.html')
+ 'debian.org_index.html'
+
+
+.. function:: VersionCompare(a, b)
+
+ Compare two versions, *a* and *b*, and return an integer value which has
+ the same characteristic as the built-in :func:`cmp` function.
+
+ .. table:: Return values
+
+ ===== =============================================
+ Value Meaning
+ ===== =============================================
+ > 0 The version *a* is greater than version *b*.
+ = 0 Both versions are equal.
+ < 0 The version *a* is less than version *b*.
+ ===== =============================================
Data
@@ -256,6 +376,18 @@ Select states
Build information
^^^^^^^^^^^^^^^^^
.. data:: Date
+
+ The date on which this extension has been compiled.
+
.. data:: LibVersion
+
+ The version of the apt_pkg library. This is **not** the version of apt,
+ nor the version of python-apt.
+
.. data:: Time
+
+ The time this extension has been built.
+
.. data:: Version
+
+ The version of apt (not of python-apt).
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 8f71e3e3..40154a6f 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -23,9 +23,13 @@ import sys
# absolute, like shown here.
sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath('../..'))
+
+# Find the path to the built apt_pkg and apt_inst extensions
if os.path.exists("../../build"):
+ version = '.'.join(str(x) for x in sys.version_info[:2])
for dirname in os.listdir('../../build'):
- sys.path.insert(0, os.path.abspath('../../build/' + dirname))
+ if version in dirname:
+ sys.path.insert(0, os.path.abspath('../../build/' + dirname))
# General configuration
# ---------------------
@@ -56,10 +60,13 @@ copyright = u'2009, Julian Andres Klode <jak@debian.org>'
# |version| and |release|, also used in various other places throughout the
# built documents.
#
+from debian_bundle.changelog import Changelog
+
+changes = Changelog(open('../../debian/changelog'))
# The short X.Y version.
-version = '0.7'
+version = '.'.join(changes.full_version.split('.')[:2])
# The full version, including alpha/beta/rc tags.
-release = '0.7.9~exp2'
+release = changes.full_version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/doc/source/examples/apt-gtk.py b/doc/source/examples/apt-gtk.py
index c3bb09d5..835ea4ee 100644
--- a/doc/source/examples/apt-gtk.py
+++ b/doc/source/examples/apt-gtk.py
@@ -4,14 +4,14 @@ import pygtk
pygtk.require("2.0")
import gtk
-import apt.gtk.widgets
+import apt.progress.gtk2
def main():
"""Main function."""
win = gtk.Window()
win.connect("destroy", gtk.main_quit)
- progress = apt.gtk.widgets.GtkAptProgress()
+ progress = apt.progress.gtk2.GtkAptProgress()
win.set_title("GtkAptProgress Demo")
win.add(progress)
progress.show()
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0cf708e1..767fa3ca 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,4 +2,6 @@
[type: gettext/rfc822deb] data/templates/Ubuntu.info.in
[type: gettext/rfc822deb] data/templates/Debian.info.in
aptsources/distro.py
-apt/gtk/widgets.py \ No newline at end of file
+apt/progress/gtk2.py
+apt/package.py
+apt/debfile.py
diff --git a/python/cache.cc b/python/cache.cc
index 1c59bece..0c59f561 100644
--- a/python/cache.cc
+++ b/python/cache.cc
@@ -936,14 +936,26 @@ PyObject *TmpGetCache(PyObject *Self,PyObject *Args)
pkgCacheFile *Cache = new pkgCacheFile();
if(pyCallbackInst != 0) {
+ // sanity check for the progress object, see #497049
+ if (PyObject_HasAttrString(pyCallbackInst, "done") != true) {
+ PyErr_SetString(PyExc_ValueError,
+ "OpProgress object must implement done()");
+ return 0;
+ }
+ if (PyObject_HasAttrString(pyCallbackInst, "update") != true) {
+ PyErr_SetString(PyExc_ValueError,
+ "OpProgress object must implement update()");
+ return 0;
+ }
PyOpProgress progress;
progress.setCallbackInst(pyCallbackInst);
if (Cache->Open(progress,false) == false)
- return HandleErrors();
- } else {
+ return HandleErrors();
+ }
+ else {
OpTextProgress Prog;
if (Cache->Open(Prog,false) == false)
- return HandleErrors();
+ return HandleErrors();
}
CppOwnedPyObject<pkgCacheFile*> *CacheFileObj =
diff --git a/setup.py b/setup.py
index 1783d4cc..9ed21378 100755
--- a/setup.py
+++ b/setup.py
@@ -1,14 +1,14 @@
#! /usr/bin/env python
# $Id: setup.py,v 1.2 2002/01/08 07:13:21 jgg Exp $
-
-from distutils.core import setup, Extension
-from distutils.sysconfig import parse_makefile
-from DistUtilsExtra.command import build_extra, build_i18n
import glob
import os
import shutil
import sys
+from distutils.core import setup, Extension
+from distutils.sysconfig import parse_makefile
+from DistUtilsExtra.command import build_extra, build_i18n
+
# The apt_pkg module
files = map(lambda source: "python/"+source,
@@ -46,12 +46,12 @@ if len(sys.argv) > 1 and sys.argv[1] == "clean" and '-a' in sys.argv:
print "Not removing", dirname, "because it does not exist"
setup(name="python-apt",
- version="0.7.9",
description="Python bindings for APT",
+ version=os.environ.get('DEBVER'),
author="APT Development Team",
author_email="deity@lists.debian.org",
ext_modules=[apt_pkg, apt_inst],
- packages=['apt', 'apt.gtk', 'aptsources'],
+ packages=['apt', 'apt.progress', 'aptsources'],
data_files = [('share/python-apt/templates',
glob.glob('build/data/templates/*.info')),
('share/python-apt/templates',
@@ -64,6 +64,12 @@ setup(name="python-apt",
if (len(sys.argv) > 1 and sys.argv[1] == "build" and
sys.version_info[0] >= 2 and sys.version_info[1] >= 5):
import sphinx
+ try:
+ import pygtk
+ except ImportError:
+ print >> sys.stderr, ('W: Not building documentation because python-'
+ 'gtk2 is not available at the moment.')
+ sys.exit(0)
sphinx.main(["sphinx", "-b", "html", "-d", "build/doc/doctrees",
os.path.abspath("doc/source"), "build/doc/html"])
sphinx.main(["sphinx", "-b", "text", "-d", "build/doc/doctrees",
diff --git a/tests/getcache_mem_corruption.py b/tests/getcache_mem_corruption.py
new file mode 100644
index 00000000..42e9af00
--- /dev/null
+++ b/tests/getcache_mem_corruption.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+import apt
+import apt_pkg
+import re
+
+import unittest
+
+class TestGetCache(unittest.TestCase):
+
+ def setUp(self):
+ apt_pkg.InitConfig()
+ apt_pkg.InitSystem()
+
+ def testWrongInvocation(self):
+ # wrongly invoke GetCache() rather than GetDepCache()
+ apt_cache = apt_pkg.GetCache()
+ self.assertRaises(ValueError, apt_pkg.GetCache, apt_cache)
+
+ def testProperInvocation(self):
+ apt_cache = apt_pkg.GetCache(apt.progress.OpTextProgress())
+ apt_depcache = apt_pkg.GetDepCache(apt_cache)
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/utils/get_ubuntu_mirrors.py b/utils/get_ubuntu_mirrors.py
index 6248ece4..ddd1e369 100755
--- a/utils/get_ubuntu_mirrors.py
+++ b/utils/get_ubuntu_mirrors.py
@@ -35,7 +35,7 @@ mirrors = []
# path to the local mirror list
list_path = "../data/templates/Ubuntu.mirrors"
-req = urllib2.Request("https://wiki.ubuntu.com/Mirrors?action=raw")
+req = urllib2.Request("https://wiki.ubuntu.com/Archive?action=raw")
try:
print "Downloading mirrors list from the Ubuntu wiki..."