summaryrefslogtreecommitdiff
path: root/apt
diff options
context:
space:
mode:
Diffstat (limited to 'apt')
-rw-r--r--apt/__init__.py16
-rw-r--r--apt/auth.py56
-rw-r--r--apt/cache.py327
-rw-r--r--apt/cdrom.py6
-rw-r--r--apt/debfile.py247
-rw-r--r--apt/deprecation.py106
-rw-r--r--apt/package.py505
-rw-r--r--apt/progress/__init__.py14
-rw-r--r--apt/progress/base.py7
-rw-r--r--apt/progress/gtk2.py519
-rw-r--r--apt/progress/old.py259
-rw-r--r--apt/progress/text.py26
-rw-r--r--apt/utils.py13
13 files changed, 588 insertions, 1513 deletions
diff --git a/apt/__init__.py b/apt/__init__.py
index 677a625b..b8d291e3 100644
--- a/apt/__init__.py
+++ b/apt/__init__.py
@@ -18,20 +18,20 @@
# USA
# import the core of apt_pkg
"""High-Level Interface for working with apt."""
+from __future__ import print_function
+
import apt_pkg
# import some fancy classes
from apt.package import Package
from apt.cache import Cache, ProblemResolver
+Cache # pyflakes
+ProblemResolver # pyflakes
from apt.cdrom import Cdrom
-if apt_pkg._COMPAT_0_7:
- from apt.progress.old import (OpProgress, FetchProgress, InstallProgress,
- CdromProgress)
- from apt_pkg import (size_to_str as SizeToStr, time_to_str as TimeToStr,
- version_compare as VersionCompare)
-
-# init the package system
-apt_pkg.init()
+# init the package system, but do not re-initialize config
+if "APT" not in apt_pkg.config:
+ apt_pkg.init_config()
+apt_pkg.init_system()
__all__ = ['Cache', 'Cdrom', 'Package']
diff --git a/apt/auth.py b/apt/auth.py
index c1b8da2a..74fea10b 100644
--- a/apt/auth.py
+++ b/apt/auth.py
@@ -24,7 +24,8 @@
# USA
"""Handle GnuPG keys used to trust signed repositories."""
-import atexit
+from __future__ import print_function
+
import os
import os.path
import shutil
@@ -68,7 +69,8 @@ def _call_apt_key_script(*args, **kwargs):
# configuration from the chroot to the apt-key script by using
# a temporary APT_CONFIG file. The apt-key script uses apt-config
# shell internally
- conf = tempfile.NamedTemporaryFile(prefix="apt-key", suffix=".conf")
+ conf = tempfile.NamedTemporaryFile(
+ prefix="apt-key", suffix=".conf")
conf.write(apt_pkg.config.dump().encode("UTF-8"))
conf.flush()
env["APT_CONFIG"] = conf.name
@@ -79,17 +81,18 @@ def _call_apt_key_script(*args, **kwargs):
content = kwargs.get("stdin", None)
# py2 needs this encoded, py3.3 will crash if it is
- if isinstance(content, unicode) and sys.version_info[:2] < (3, 3):
+ if sys.version_info.major < 3 and isinstance(content, unicode):
content = content.encode("utf-8")
output, stderr = proc.communicate(content)
if proc.returncode:
- raise AptKeyError("The apt-key script failed with return code %s:\n"
- "%s\n"
- "stdout: %s\n"
- "stderr: %s" % (proc.returncode, " ".join(cmd),
- output,stderr))
+ raise AptKeyError(
+ "The apt-key script failed with return code %s:\n"
+ "%s\n"
+ "stdout: %s\n"
+ "stderr: %s" % (
+ proc.returncode, " ".join(cmd), output, stderr))
elif stderr:
sys.stderr.write(stderr) # Forward stderr
@@ -98,6 +101,7 @@ def _call_apt_key_script(*args, **kwargs):
if conf is not None:
conf.close()
+
def add_key_from_file(filename):
"""Import a GnuPG key file to trust repositores signed by it.
@@ -110,6 +114,7 @@ def add_key_from_file(filename):
raise AptKeyError("Key file cannot be accessed: %s" % filename)
_call_apt_key_script("add", filename)
+
def add_key_from_keyserver(keyid, keyserver):
"""Import a GnuPG key file to trust repositores signed by it.
@@ -126,8 +131,9 @@ def add_key_from_keyserver(keyid, keyserver):
finally:
shutil.rmtree(tmp_keyring_dir)
+
def _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir):
- if len(keyid) < 160/8:
+ if len(keyid) < (160 / 8):
raise AptKeyError("Only long keyids (v4, 160bit) are supported")
# create a temp keyring dir
tmp_secret_keyring = os.path.join(tmp_keyring_dir, "secring.gpg")
@@ -137,17 +143,23 @@ def _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir):
"gpg",
"--no-default-keyring", "--no-options",
"--homedir", tmp_keyring_dir,
- ]
+ ]
# download the key to a temp keyring first
res = subprocess.call(gpg_default_options + [
"--secret-keyring", tmp_secret_keyring,
"--keyring", tmp_keyring,
"--keyserver", keyserver,
"--recv", keyid,
- ])
+ ])
if res != 0:
raise AptKeyError("recv from '%s' failed for '%s'" % (
keyserver, keyid))
+ # FIXME:
+ # - with gnupg 1.4.18 the downloaded key is actually checked(!),
+ # i.e. gnupg will not import anything that the server sends
+ # into the keyring, so the below checks are now redundant *if*
+ # gnupg 1.4.18 is used
+
# now export again using the long key id (to ensure that there is
# really only this one key in our keyring) and not someone MITM us
tmp_export_keyring = os.path.join(tmp_keyring_dir, "export-keyring.gpg")
@@ -155,7 +167,7 @@ def _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir):
"--keyring", tmp_keyring,
"--output", tmp_export_keyring,
"--export", keyid,
- ])
+ ])
if res != 0:
raise AptKeyError("export of '%s' failed", keyid)
# now verify the fingerprint, this is probably redundant as we
@@ -167,10 +179,10 @@ def _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir):
"--fingerprint",
"--batch",
"--with-colons",
- ],
- stdout=subprocess.PIPE,
- universal_newlines=True).communicate()[0]
- got_fingerprint=None
+ ],
+ stdout=subprocess.PIPE,
+ universal_newlines=True).communicate()[0]
+ got_fingerprint = None
for line in output.splitlines():
if line.startswith("fpr:"):
got_fingerprint = line.split(":")[9]
@@ -180,12 +192,15 @@ def _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir):
# what gnupg is using)
signing_key_fingerprint = keyid.replace("0x", "").upper()
if got_fingerprint != signing_key_fingerprint:
+ # make the error match what gnupg >= 1.4.18 will output when
+ # it checks the key itself before importing it
raise AptKeyError(
- "Fingerprints do not match, not importing: '%s' != '%s'" % (
- signing_key_fingerprint, got_fingerprint))
+ "recv from '%s' failed for '%s'" % (
+ keyserver, signing_key_fingerprint))
# finally add it
add_key_from_file(tmp_export_keyring)
+
def add_key(content):
"""Import a GnuPG key to trust repositores signed by it.
@@ -195,6 +210,7 @@ def add_key(content):
_call_apt_key_script("adv", "--quiet", "--batch",
"--import", "-", stdin=content)
+
def remove_key(fingerprint):
"""Remove a GnuPG key to no longer trust repositores signed by it.
@@ -203,6 +219,7 @@ def remove_key(fingerprint):
"""
_call_apt_key_script("rm", fingerprint)
+
def export_key(fingerprint):
"""Return the GnuPG key in text format.
@@ -211,6 +228,7 @@ def export_key(fingerprint):
"""
return _call_apt_key_script("export", fingerprint)
+
def update():
"""Update the local keyring with the archive keyring and remove from
the local keyring the archive keys which are no longer valid. The
@@ -219,6 +237,7 @@ def update():
"""
return _call_apt_key_script("update")
+
def net_update():
"""Work similar to the update command above, but get the archive
keyring from an URI instead and validate it against a master key.
@@ -229,6 +248,7 @@ def net_update():
"""
return _call_apt_key_script("net-update")
+
def list_keys():
"""Returns a list of TrustedKey instances for each key which is
used to trust repositories.
diff --git a/apt/cache.py b/apt/cache.py
index 9842cb2a..74bbe71f 100644
--- a/apt/cache.py
+++ b/apt/cache.py
@@ -19,15 +19,15 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
+from __future__ import print_function
+
import fnmatch
import os
+import warnings
import weakref
import apt_pkg
from apt import Package
-from apt_pkg import gettext as _
-from apt.deprecation import (AttributeDeprecatedBy, function_deprecated_by,
- deprecated_args)
import apt.progress.text
@@ -42,6 +42,7 @@ class FetchFailedException(IOError):
class LockFailedException(IOError):
"""Exception that is thrown when locking fails."""
+
class CacheClosedException(Exception):
"""Exception that is thrown when the cache is used after close()."""
@@ -55,14 +56,21 @@ class Cache(object):
list of available packages.
The cache can be used like a mapping from package names to Package
- objects (although only getting items is supported).
+ objects (although only getting items is supported).
Keyword arguments:
- progress -- a OpProgress object
- rootdir -- a alternative root directory. if that is given
- the system sources.list and system lists/ files are
- not read, only files relative to the given rootdir
- memonly -- build the cache in memory only
+ progress -- a OpProgress object,
+ rootdir -- an alternative root directory. if that is given the system
+ sources.list and system lists/files are not read, only file relative
+ to the given rootdir,
+ memonly -- build the cache in memory only.
+
+
+ .. versionchanged:: 1.0
+
+ The cache now supports package names with special architecture
+ qualifiers such as :all and :native. It does not export them
+ in :meth:`keys()`, though, to keep :meth:`keys()` a unique set.
"""
def __init__(self, progress=None, rootdir=None, memonly=False):
@@ -71,30 +79,30 @@ class Cache(object):
self._records = None
self._list = None
self._callbacks = {}
+ self._callbacks2 = {}
self._weakref = weakref.WeakValueDictionary()
- self._set = set()
- self._fullnameset = set()
self._changes_count = -1
self._sorted_set = None
-
- self.connect("cache_post_open", self._inc_changes_count)
- self.connect("cache_post_change", self._inc_changes_count)
+
+ self.connect("cache_post_open", "_inc_changes_count")
+ self.connect("cache_post_change", "_inc_changes_count")
if memonly:
# force apt to build its caches in memory
apt_pkg.config.set("Dir::Cache::pkgcache", "")
if rootdir:
- if os.path.exists(rootdir+"/etc/apt/apt.conf"):
+ rootdir = os.path.abspath(rootdir)
+ if os.path.exists(rootdir + "/etc/apt/apt.conf"):
apt_pkg.read_config_file(apt_pkg.config,
- rootdir + "/etc/apt/apt.conf")
- if os.path.isdir(rootdir+"/etc/apt/apt.conf.d"):
+ rootdir + "/etc/apt/apt.conf")
+ if os.path.isdir(rootdir + "/etc/apt/apt.conf.d"):
apt_pkg.read_config_dir(apt_pkg.config,
- rootdir + "/etc/apt/apt.conf.d")
+ rootdir + "/etc/apt/apt.conf.d")
apt_pkg.config.set("Dir", rootdir)
apt_pkg.config.set("Dir::State::status",
rootdir + "/var/lib/dpkg/status")
# also set dpkg to the rootdir path so that its called for the
# --print-foreign-architectures call
- apt_pkg.config.set("Dir::bin::dpkg",
+ apt_pkg.config.set("Dir::bin::dpkg",
os.path.join(rootdir, "usr", "bin", "dpkg"))
# create required dirs/files when run with special rootdir
# automatically
@@ -103,7 +111,6 @@ class Cache(object):
# recognized (LP: #320665)
apt_pkg.init_system()
self.open(progress)
-
def _inc_changes_count(self):
"""Increase the number of changes"""
@@ -116,12 +123,12 @@ class Cache(object):
"""
files = ["/var/lib/dpkg/status",
"/etc/apt/sources.list",
- ]
+ ]
dirs = ["/var/lib/dpkg",
"/etc/apt/",
"/var/cache/apt/archives/partial",
"/var/lib/apt/lists/partial",
- ]
+ ]
for d in dirs:
if not os.path.exists(rootdir + d):
#print "creating: ", rootdir + d
@@ -134,7 +141,14 @@ class Cache(object):
""" internal helper to run a callback """
if name in self._callbacks:
for callback in self._callbacks[name]:
- callback()
+ if callback == '_inc_changes_count':
+ self._inc_changes_count()
+ else:
+ callback()
+
+ if name in self._callbacks2:
+ for callback, args, kwds in self._callbacks2[name]:
+ callback(self, *args, **kwds)
def open(self, progress=None):
""" Open the package cache, after that it can be used like
@@ -152,28 +166,11 @@ class Cache(object):
self._records = apt_pkg.PackageRecords(self._cache)
self._list = apt_pkg.SourceList()
self._list.read_main_list()
- self._set.clear()
- self._fullnameset.clear()
self._sorted_set = None
self._weakref.clear()
self._have_multi_arch = len(apt_pkg.get_architectures()) > 1
- progress.op = _("Building data structures")
- i = last = 0
- size = len(self._cache.packages)
- for pkg in self._cache.packages:
- if progress is not None and last+100 < i:
- progress.update(i/float(size)*100)
- last = i
- # drop stuff with no versions (cruft)
- if pkg.has_versions:
- self._set.add(pkg.get_fullname(pretty=True))
- if self._have_multi_arch:
- self._fullnameset.add(pkg.get_fullname(pretty=False))
-
- i += 1
-
progress.done()
self._run_callbacks("cache_post_open")
@@ -196,37 +193,58 @@ class Cache(object):
try:
return self._weakref[key]
except KeyError:
- if key in self._set or key in self._fullnameset:
- key = str(key)
- pkg = self._weakref[key] = Package(self, self._cache[key])
- return pkg
- else:
+ key = str(key)
+ try:
+ rawpkg = self._cache[key]
+ except KeyError:
+ raise KeyError('The cache has no package named %r' % key)
+
+ # It might be excluded due to not having a version or something
+ if not self.__is_real_pkg(rawpkg):
raise KeyError('The cache has no package named %r' % key)
+ # Check if we already know the package using the normalized name
+ name = rawpkg.get_fullname(pretty=False)
+ try:
+ return self._weakref[name]
+ except KeyError:
+ pkg = Package(self, rawpkg)
+ self._weakref[key] = self._weakref[name] = pkg
+
+ return pkg
+
def __iter__(self):
# 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:
+ for pkgname in self.keys():
yield self[pkgname]
raise StopIteration
+ def __is_real_pkg(self, rawpkg):
+ """Check if the apt_pkg.Package provided is a real package."""
+ return rawpkg.has_versions
+
def has_key(self, key):
- return (key in self._set or key in self._fullnameset)
+ return key in self
def __contains__(self, key):
- return (key in self._set or key in self._fullnameset)
+ try:
+ return self.__is_real_pkg(self._cache[key])
+ except KeyError:
+ return False
def __len__(self):
- return len(self._set)
+ return len(self.keys())
def keys(self):
- return list(self._set)
+ if self._sorted_set is None:
+ self._sorted_set = sorted(p.get_fullname(pretty=True)
+ for p in self._cache.packages
+ if self.__is_real_pkg(p))
+ return list(self._sorted_set) # We need a copy here, caller may modify
def get_changes(self):
""" Get the marked changes """
@@ -242,7 +260,6 @@ class Cache(object):
changes.append(package)
return changes
- @deprecated_args
def upgrade(self, dist_upgrade=False):
"""Upgrade all packages.
@@ -258,7 +275,8 @@ class Cache(object):
def required_download(self):
"""Get the size of the packages that are required to download."""
if self._records is None:
- raise CacheClosedException("Cache object used after close() called")
+ raise CacheClosedException(
+ "Cache object used after close() called")
pm = apt_pkg.PackageManager(self._depcache)
fetcher = apt_pkg.Acquire()
pm.get_archives(fetcher, self._list, self._records)
@@ -288,16 +306,14 @@ class Cache(object):
# now check the result (this is the code from apt-get.cc)
failed = False
- transient = False
err_msg = ""
for item in fetcher.items:
if item.status == item.STAT_DONE:
continue
if item.STAT_IDLE:
- transient = True
continue
err_msg += "Failed to fetch %s %s\n" % (item.desc_uri,
- item.error_text)
+ item.error_text)
failed = True
# we raise a exception if the download failed or it was cancelt
@@ -310,7 +326,8 @@ class Cache(object):
def _fetch_archives(self, fetcher, pm):
""" fetch the needed archives """
if self._records is None:
- raise CacheClosedException("Cache object used after close() called")
+ raise CacheClosedException(
+ "Cache object used after close() called")
# get lock
lockfile = apt_pkg.config.find_dir("Dir::Cache::Archives") + "lock"
@@ -348,7 +365,6 @@ class Cache(object):
if fetcher is None:
fetcher = apt_pkg.Acquire(progress)
-
return self._fetch_archives(fetcher,
apt_pkg.PackageManager(self._depcache))
@@ -361,12 +377,12 @@ class Cache(object):
else:
return bool(pkg.has_provides and not pkg.has_versions)
- def get_providing_packages(self, pkgname, candidate_only=True,
+ 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.
+ specified name.
If 'candidate_only' is False, return all packages with at
least one version providing the virtual package. Otherwise,
@@ -377,7 +393,7 @@ class Cache(object):
packages providing pkgname, even if pkgname is not itself
a virtual pkg.
"""
-
+
providers = set()
get_candidate_ver = self._depcache.get_candidate_ver
try:
@@ -398,7 +414,6 @@ class Cache(object):
providers.add(package)
return list(providers)
- @deprecated_args
def update(self, fetch_progress=None, pulse_interval=0,
raise_on_error=True, sources_list=None):
"""Run the equivalent of apt-get update.
@@ -411,7 +426,7 @@ class Cache(object):
apt.progress.FetchProgress, the default is apt.progress.FetchProgress()
.
sources_list -- Update a alternative sources.list than the default.
- Note that the sources.list.d directory is ignored in this case
+ Note that the sources.list.d directory is ignored in this case
"""
lockfile = apt_pkg.config.find_dir("Dir::State::Lists") + "lock"
lock = apt_pkg.get_lock(lockfile)
@@ -423,7 +438,8 @@ class Cache(object):
old_sources_list = apt_pkg.config.find("Dir::Etc::sourcelist")
old_sources_list_d = apt_pkg.config.find("Dir::Etc::sourceparts")
old_cleanup = apt_pkg.config.find("APT::List-Cleanup")
- apt_pkg.config.set("Dir::Etc::sourcelist", os.path.abspath(sources_list))
+ apt_pkg.config.set("Dir::Etc::sourcelist",
+ os.path.abspath(sources_list))
apt_pkg.config.set("Dir::Etc::sourceparts", "xxx")
apt_pkg.config.set("APT::List-Cleanup", "0")
slist = apt_pkg.SourceList()
@@ -450,7 +466,6 @@ class Cache(object):
apt_pkg.config.set("Dir::Etc::sourceparts", old_sources_list_d)
apt_pkg.config.set("APT::List-Cleanup", old_cleanup)
- @deprecated_args
def install_archives(self, pm, install_progress):
"""
The first parameter *pm* refers to an object returned by
@@ -471,7 +486,6 @@ class Cache(object):
install_progress.finish_update()
return res
- @deprecated_args
def commit(self, fetch_progress=None, install_progress=None):
"""Apply the marked changes to the cache.
@@ -531,12 +545,40 @@ class Cache(object):
self._run_callbacks("cache_pre_change")
def connect(self, name, callback):
- """ connect to a signal, currently only used for
- cache_{post,pre}_{changed,open} """
- if not name in self._callbacks:
+ """Connect to a signal.
+
+ .. deprecated:: 1.0
+
+ Please use connect2() instead, as this function is very
+ likely to cause a memory leak.
+ """
+ if callback != '_inc_changes_count':
+ warnings.warn("connect() likely causes a reference"
+ " cycle, use connect2() instead", RuntimeWarning, 2)
+ if name not in self._callbacks:
self._callbacks[name] = []
self._callbacks[name].append(callback)
+ def connect2(self, name, callback, *args, **kwds):
+ """Connect to a signal.
+
+ The callback will be passed the cache as an argument, and
+ any arguments passed to this function. Make sure that, if you
+ pass a method of a class as your callback, your class does not
+ contain a reference to the cache.
+
+ Cyclic references to the cache can cause issues if the Cache object
+ is replaced by a new one, because the cache keeps a lot of objects and
+ tens of open file descriptors.
+
+ currently only used for cache_{post,pre}_{changed,open}.
+
+ .. versionadded:: 1.0
+ """
+ if name not in self._callbacks2:
+ self._callbacks2[name] = []
+ self._callbacks2[name].append((callback, args, kwds))
+
def actiongroup(self):
"""Return an `ActionGroup` object for the current cache.
@@ -561,9 +603,9 @@ class Cache(object):
@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
+ fix the system if dpkg got interrupted is to run
'dpkg --configure -a' as root.
"""
dpkg_status_dir = os.path.dirname(
@@ -593,20 +635,6 @@ class Cache(object):
"""Return the number of packages marked as keep."""
return self._depcache.keep_count
- if apt_pkg._COMPAT_0_7:
- _runCallbacks = function_deprecated_by(_run_callbacks)
- getChanges = function_deprecated_by(get_changes)
- requiredDownload = AttributeDeprecatedBy('required_download')
- additionalRequiredSpace = AttributeDeprecatedBy('required_space')
- reqReinstallPkgs = AttributeDeprecatedBy('req_reinstall_pkgs')
- _runFetcher = function_deprecated_by(_run_fetcher)
- _fetchArchives = function_deprecated_by(_fetch_archives)
- isVirtualPackage = function_deprecated_by(is_virtual_package)
- getProvidingPackages = function_deprecated_by(get_providing_packages)
- installArchives = function_deprecated_by(install_archives)
- cachePostChange = function_deprecated_by(cache_post_change)
- cachePreChange = function_deprecated_by(cache_pre_change)
-
class ProblemResolver(object):
"""Resolve problems due to dependencies and conflicts.
@@ -670,6 +698,38 @@ class MarkedChangesFilter(Filter):
return False
+class _FilteredCacheHelper(object):
+ """Helper class for FilteredCache to break a reference cycle."""
+
+ def __init__(self, cache):
+ # Do not keep a reference to the cache, or you have a cycle!
+
+ self._filtered = {}
+ self._filters = {}
+ cache.connect2("cache_post_change", self.filter_cache_post_change)
+ cache.connect2("cache_post_open", self.filter_cache_post_change)
+
+ def _reapply_filter(self, cache):
+ " internal helper to refilter "
+ # Do not keep a reference to the cache, or you have a cycle!
+ self._filtered = {}
+ for pkg in cache:
+ for f in self._filters:
+ if f.apply(pkg):
+ self._filtered[pkg.name] = 1
+ break
+
+ def set_filter(self, filter):
+ """Set the current active filter."""
+ self._filters = []
+ self._filters.append(filter)
+
+ def filter_cache_post_change(self, cache):
+ """Called internally if the cache changes, emit a signal then."""
+ # Do not keep a reference to the cache, or you have a cycle!
+ self._reapply_filter(cache)
+
+
class FilteredCache(object):
""" A package cache that is filtered.
@@ -681,99 +741,74 @@ class FilteredCache(object):
self.cache = Cache(progress)
else:
self.cache = cache
- self.cache.connect("cache_post_change", self.filter_cache_post_change)
- self.cache.connect("cache_post_open", self.filter_cache_post_change)
- self._filtered = {}
- self._filters = []
+ self._helper = _FilteredCacheHelper(self.cache)
def __len__(self):
- return len(self._filtered)
+ return len(self._helper._filtered)
def __getitem__(self, key):
return self.cache[key]
def __iter__(self):
- for pkgname in self._filtered:
+ for pkgname in self._helper._filtered:
yield self.cache[pkgname]
def keys(self):
- return self._filtered.keys()
+ return self._helper._filtered.keys()
def has_key(self, key):
- return (key in self._filtered)
+ return key in self
def __contains__(self, key):
- return (key in self._filtered)
-
- def _reapply_filter(self):
- " internal helper to refilter "
- self._filtered = {}
- for pkg in self.cache:
- for f in self._filters:
- if f.apply(pkg):
- self._filtered[pkg.name] = 1
- break
+ try:
+ # Normalize package name for multi arch
+ return self.cache[key].name in self._helper._filtered
+ except KeyError:
+ return False
def set_filter(self, filter):
"""Set the current active filter."""
- self._filters = []
- self._filters.append(filter)
- #self._reapplyFilter()
- # force a cache-change event that will result in a refiltering
+ self._helper.set_filter(filter)
self.cache.cache_post_change()
def filter_cache_post_change(self):
"""Called internally if the cache changes, emit a signal then."""
- #print "filterCachePostChange()"
- self._reapply_filter()
-
-
-# def connect(self, name, callback):
-# self.cache.connect(name, callback)
+ self._helper.filter_cache_post_change(self.cache)
def __getattr__(self, key):
"""we try to look exactly like a real cache."""
- #print "getattr: %s " % key
return getattr(self.cache, key)
- if apt_pkg._COMPAT_0_7:
- _reapplyFilter = function_deprecated_by(_reapply_filter)
- setFilter = function_deprecated_by(set_filter)
- filterCachePostChange = function_deprecated_by(\
- filter_cache_post_change)
-
-def cache_pre_changed():
- print "cache pre changed"
+def cache_pre_changed(cache):
+ print("cache pre changed")
-def cache_post_changed():
- print "cache post changed"
+def cache_post_changed(cache):
+ print("cache post changed")
def _test():
"""Internal test code."""
- print "Cache self test"
+ print("Cache self test")
apt_pkg.init()
cache = Cache(apt.progress.text.OpProgress())
- cache.connect("cache_pre_change", cache_pre_changed)
- cache.connect("cache_post_change", cache_post_changed)
- print ("aptitude" in cache)
+ cache.connect2("cache_pre_change", cache_pre_changed)
+ cache.connect2("cache_post_change", cache_post_changed)
+ print(("aptitude" in cache))
pkg = cache["aptitude"]
- print pkg.name
- print len(cache)
+ print(pkg.name)
+ print(len(cache))
for pkgname in cache.keys():
assert cache[pkgname].name == pkgname
cache.upgrade()
changes = cache.get_changes()
- print len(changes)
+ print(len(changes))
for pkg in changes:
assert pkg.name
-
-
# see if fetching works
for dirname in ["/tmp/pytest", "/tmp/pytest/partial"]:
if not os.path.exists(dirname):
@@ -784,28 +819,28 @@ def _test():
cache._fetch_archives(fetcher, pm)
#sys.exit(1)
- print "Testing filtered cache (argument is old cache)"
+ print("Testing filtered cache (argument is old cache)")
filtered = FilteredCache(cache)
- filtered.cache.connect("cache_pre_change", cache_pre_changed)
- filtered.cache.connect("cache_post_change", cache_post_changed)
+ filtered.cache.connect2("cache_pre_change", cache_pre_changed)
+ filtered.cache.connect2("cache_post_change", cache_post_changed)
filtered.cache.upgrade()
filtered.set_filter(MarkedChangesFilter())
- print len(filtered)
+ print(len(filtered))
for pkgname in filtered.keys():
assert pkgname == filtered[pkg].name
- print len(filtered)
+ print(len(filtered))
- print "Testing filtered cache (no argument)"
+ print("Testing filtered cache (no argument)")
filtered = FilteredCache(progress=apt.progress.base.OpProgress())
- filtered.cache.connect("cache_pre_change", cache_pre_changed)
- filtered.cache.connect("cache_post_change", cache_post_changed)
+ filtered.cache.connect2("cache_pre_change", cache_pre_changed)
+ filtered.cache.connect2("cache_post_change", cache_post_changed)
filtered.cache.upgrade()
filtered.set_filter(MarkedChangesFilter())
- print len(filtered)
+ print(len(filtered))
for pkgname in filtered.keys():
assert pkgname == filtered[pkgname].name
- print len(filtered)
+ print(len(filtered))
if __name__ == '__main__':
_test()
diff --git a/apt/cdrom.py b/apt/cdrom.py
index 9688de9e..35a0b180 100644
--- a/apt/cdrom.py
+++ b/apt/cdrom.py
@@ -20,10 +20,11 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
"""Classes related to cdrom handling."""
+from __future__ import print_function
+
import glob
import apt_pkg
-from apt.deprecation import AttributeDeprecatedBy
from apt.progress.base import CdromProgress
@@ -84,6 +85,3 @@ class Cdrom(apt_pkg.Cdrom):
if not line.lstrip().startswith("#") and cd_id in line:
return True
return False
-
- if apt_pkg._COMPAT_0_7:
- inSourcesList = AttributeDeprecatedBy('in_sources_list')
diff --git a/apt/debfile.py b/apt/debfile.py
index adf9b348..3f4bca4b 100644
--- a/apt/debfile.py
+++ b/apt/debfile.py
@@ -17,6 +17,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
"""Classes for working with locally available Debian packages."""
+from __future__ import print_function
+
import apt
import apt_inst
import apt_pkg
@@ -25,19 +27,21 @@ import os
import sys
from apt_pkg import gettext as _
-from StringIO import StringIO
+from io import BytesIO
+
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_NONE,
+ VERSION_OUTDATED,
+ VERSION_SAME,
VERSION_NEWER) = range(4)
debug = 0
@@ -68,7 +72,7 @@ class DebPackage(object):
self._sections = apt_pkg.TagSection(control)
self.pkgname = self._sections["Package"]
self._check_was_run = False
-
+
def __getitem__(self, key):
return self._sections[key]
@@ -91,29 +95,31 @@ class DebPackage(object):
""" return the list of files in control.tar.gt """
control = []
try:
- self._debfile.control.go(lambda item, data: control.append(item.name))
+ self._debfile.control.go(
+ lambda item, data: control.append(item.name))
except SystemError:
return [_("List of control files for '%s' could not be read") %
self.filename]
return sorted(control)
-
# helper that will return a pkgname with a multiarch suffix if needed
- def _maybe_append_multiarch_suffix(self, pkgname,
+ def _maybe_append_multiarch_suffix(self, pkgname,
in_conflict_checking=False):
# trivial cases
+ if ":" in pkgname:
+ return pkgname
if not self._multiarch:
return pkgname
elif self._cache.is_virtual_package(pkgname):
return pkgname
- elif (pkgname in self._cache and
+ elif (pkgname in self._cache and
self._cache[pkgname].candidate and
self._cache[pkgname].candidate.architecture == "all"):
return pkgname
# now do the real multiarch checking
multiarch_pkgname = "%s:%s" % (pkgname, self._multiarch)
# the upper layers will handle this
- if not multiarch_pkgname in self._cache:
+ if multiarch_pkgname not in self._cache:
return multiarch_pkgname
# now check the multiarch state
cand = self._cache[multiarch_pkgname].candidate._cand
@@ -124,8 +130,8 @@ class DebPackage(object):
return pkgname
# for conflicts we need a special case here, any not multiarch enabled
# package has a implicit conflict
- if (in_conflict_checking and
- not (cand.multi_arch & cand.MULTI_ARCH_SAME)):
+ if (in_conflict_checking and
+ not (cand.multi_arch & cand.MULTI_ARCH_SAME)):
return pkgname
return multiarch_pkgname
@@ -146,9 +152,11 @@ class DebPackage(object):
depname = self._maybe_append_multiarch_suffix(depname)
# check for virtual pkgs
- if not depname in self._cache:
+ if depname not in self._cache:
if self._cache.is_virtual_package(depname):
- self._dbg(3, "_is_or_group_satisfied(): %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
@@ -161,13 +169,15 @@ class DebPackage(object):
# 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
+ # 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))
+ self._dbg(
+ 3, "found installed '%s' that provides '%s'" % (
+ ppkg.name, depname))
return True
return False
@@ -180,7 +190,7 @@ class DebPackage(object):
depname = self._maybe_append_multiarch_suffix(depname)
# if we don't have it in the cache, it may be virtual
- if not depname in self._cache:
+ if depname not in self._cache:
if not self._cache.is_virtual_package(depname):
continue
providers = self._cache.get_providing_packages(depname)
@@ -210,16 +220,19 @@ class DebPackage(object):
or_str += dep[0]
if ver and oper:
or_str += " (%s %s)" % (dep[2], dep[1])
- if dep != or_group[len(or_group)-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, "_check_single_pkg_conflict() 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
@@ -232,7 +245,7 @@ class DebPackage(object):
#print "pkgver: %s " % pkgver
#print "oper: %s " % oper
if (apt_pkg.check_dep(pkgver, oper, ver) and not
- self.replaces_real_pkg(pkgname, oper, ver)):
+ self.replaces_real_pkg(pkgname, oper, ver)):
self._failure_string += _("Conflicts with the installed package "
"'%s'") % pkg.name
self._dbg(3, "conflicts with installed pkg '%s'" % pkg.name)
@@ -253,7 +266,7 @@ class DebPackage(object):
depname, in_conflict_checking=True)
# check conflicts with virtual pkgs
- if not depname in self._cache:
+ if depname not in self._cache:
# FIXME: we have to check for virtual replaces here as
# well (to pass tests/gdebi-test8.deb)
if self._cache.is_virtual_package(depname):
@@ -263,8 +276,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):
@@ -276,7 +289,7 @@ class DebPackage(object):
"""List of package names conflicting with this package."""
key = "Conflicts"
try:
- return apt_pkg.parse_depends(self._sections[key])
+ return apt_pkg.parse_depends(self._sections[key], False)
except KeyError:
return []
@@ -287,7 +300,8 @@ class DebPackage(object):
# find depends
for key in "Depends", "Pre-Depends":
try:
- depends.extend(apt_pkg.parse_depends(self._sections[key]))
+ depends.extend(
+ apt_pkg.parse_depends(self._sections[key], False))
except KeyError:
pass
return depends
@@ -297,7 +311,7 @@ class DebPackage(object):
"""List of virtual packages which are provided by this package."""
key = "Provides"
try:
- return apt_pkg.parse_depends(self._sections[key])
+ return apt_pkg.parse_depends(self._sections[key], False)
except KeyError:
return []
@@ -306,7 +320,7 @@ class DebPackage(object):
"""List of packages which are replaced by this package."""
key = "Replaces"
try:
- return apt_pkg.parse_depends(self._sections[key])
+ return apt_pkg.parse_depends(self._sections[key], False)
except KeyError:
return []
@@ -347,22 +361,22 @@ class DebPackage(object):
return res
def check_breaks_existing_packages(self):
- """
- check if installing the package would break exsisting
+ """
+ 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)
+ steps = max(int(size / 50), 1)
debver = self._sections["Version"]
debarch = self._sections["Architecture"]
# store what we provide so that we can later check against that
- provides = [ x[0][0] for x in self.provides]
+ 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 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
@@ -371,14 +385,21 @@ class DebPackage(object):
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):
+ 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}
+ # 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
@@ -386,25 +407,41 @@ class DebPackage(object):
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 and c_or.target_pkg.architecture == debarch:
- 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 }
+ if (c_or.target_pkg.name == self.pkgname and
+ c_or.target_pkg.architecture == debarch):
+ 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 and
- self.pkgname != pkg.name):
- 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.pkgname != pkg.name):
+ 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()
@@ -419,6 +456,11 @@ class DebPackage(object):
"""
self._dbg(3, "compare_to_version_in_cache")
pkgname = self._sections["Package"]
+ architecture = self._sections["Architecture"]
+
+ # Arch qualify the package name
+ pkgname = ":".join([pkgname, architecture])
+
debver = self._sections["Version"]
self._dbg(1, "debver: %s" % debver)
if pkgname in self._cache:
@@ -439,19 +481,19 @@ class DebPackage(object):
return self.VERSION_OUTDATED
return self.VERSION_NONE
- def check(self):
+ def check(self, allow_downgrade=False):
"""Check if the package is installable."""
self._dbg(3, "check")
self._check_was_run = True
# check arch
- if not "Architecture" in self._sections:
+ if "Architecture" not 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"):
+ if arch != "all" and arch != apt_pkg.config.find("APT::Architecture"):
if arch in apt_pkg.get_architectures():
self._multiarch = arch
self.pkgname = "%s:%s" % (self.pkgname, self._multiarch)
@@ -462,10 +504,12 @@ class DebPackage(object):
return False
# check version
- if self.compare_to_version_in_cache() == self.VERSION_OUTDATED:
+ if (not allow_downgrade and
+ 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")
+ self._failure_string = _(
+ "A later version is already installed")
return False
# FIXME: this sort of error handling sux
@@ -475,7 +519,7 @@ class DebPackage(object):
if not self.check_conflicts():
return False
- # check if installing it would break anything on the
+ # check if installing it would break anything on the
# current system
if not self.check_breaks_existing_packages():
return False
@@ -499,19 +543,18 @@ class DebPackage(object):
def satisfy_depends_str(self, dependsstr):
"""Satisfy the dependencies in the given string."""
- return self._satisfy_depends(apt_pkg.parse_depends(dependsstr))
+ return self._satisfy_depends(apt_pkg.parse_depends(dependsstr, False))
def _satisfy_depends(self, depends):
"""Satisfy the dependencies."""
# turn off MarkAndSweep via a action group (if available)
try:
_actiongroup = apt_pkg.ActionGroup(self._cache._depcache)
+ _actiongroup # pyflakes
except AttributeError:
pass
# 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)
if not self._is_or_group_satisfied(or_group):
if not self._satisfy_or_group(or_group):
return False
@@ -530,7 +573,8 @@ class DebPackage(object):
"""Return missing dependencies."""
self._dbg(1, "Installing: %s" % self._need_pkgs)
if not self._check_was_run:
- raise AttributeError("property only available after check() was run")
+ raise AttributeError(
+ "property only available after check() was run")
return self._need_pkgs
@property
@@ -543,7 +587,8 @@ class DebPackage(object):
remove = []
unauthenticated = []
if not self._check_was_run:
- raise AttributeError("property only available after check() was run")
+ raise AttributeError(
+ "property only available after check() was run")
for pkg in self._cache:
if pkg.marked_install or pkg.marked_upgrade:
install.append(pkg.name)
@@ -562,7 +607,7 @@ class DebPackage(object):
def to_hex(in_data):
hex = ""
for (i, c) in enumerate(in_data):
- if i%80 == 0:
+ if i % 80 == 0:
hex += "\n"
hex += "%2.2x " % ord(c)
return hex
@@ -585,20 +630,20 @@ class DebPackage(object):
else:
s += chr(b)
return s
-
+
def _get_content(self, part, name, auto_decompress=True, auto_hex=True):
if name.startswith("./"):
name = name[2:]
data = part.extractdata(name)
# check for zip content
if name.endswith(".gz") and auto_decompress:
- io = StringIO(data)
+ io = BytesIO(data)
gz = gzip.GzipFile(fileobj=io)
- data = _("Automatically decompressed:\n\n")
+ data = _("Automatically decompressed:\n\n").encode("utf-8")
data += gz.read()
# auto-convert to hex
try:
- data = unicode(data, "utf-8")
+ data = data.decode("utf-8")
except Exception:
new_data = _("Automatically converted to printable ascii:\n")
new_data += self.to_strish(data)
@@ -622,7 +667,7 @@ class DebPackage(object):
def _dbg(self, level, msg):
"""Write debugging output to sys.stderr."""
if level <= self.debug:
- print >> sys.stderr, msg
+ print(msg, file=sys.stderr)
def install(self, install_progress=None):
"""Install the package."""
@@ -640,6 +685,7 @@ class DebPackage(object):
install_progress.finishUpdate()
return res
+
class DscSrcPackage(DebPackage):
"""A locally available source package."""
@@ -664,28 +710,42 @@ class DscSrcPackage(DebPackage):
"""Return the dependencies of the package"""
return self._conflicts
+ @property
+ def filelist(self):
+ """Return the list of files associated with this dsc file"""
+ # Files stanza looks like (hash, size, filename, ...)
+ return self._sections['Files'].split()[2::3]
+
def open(self, file):
"""Open the package."""
depends_tags = ["Build-Depends", "Build-Depends-Indep"]
conflicts_tags = ["Build-Conflicts", "Build-Conflicts-Indep"]
- fobj = open(file)
+ fd = apt_pkg.open_maybe_clear_signed_file(file)
+ fobj = os.fdopen(fd)
tagfile = apt_pkg.TagFile(fobj)
try:
for sec in tagfile:
+ # we only care about the stanza with the "Format:" tag, the
+ # rest is gpg signature noise. we should probably have
+ # bindings for apts OpenMaybeClearsignedFile()
+ if "Format" not in sec:
+ continue
for tag in depends_tags:
- if not tag in sec:
+ if tag not in sec:
continue
self._depends.extend(apt_pkg.parse_src_depends(sec[tag]))
for tag in conflicts_tags:
- if not tag in sec:
+ if tag not in sec:
continue
self._conflicts.extend(apt_pkg.parse_src_depends(sec[tag]))
if 'Source' in sec:
self.pkgname = sec['Source']
if 'Binary' in sec:
- self.binaries = sec['Binary'].split(', ')
- if 'Version' in sec:
- self._sections['Version'] = sec['Version']
+ self.binaries = [b.strip() for b in
+ sec['Binary'].split(',')]
+ for tag in sec.keys():
+ if tag in sec:
+ self._sections[tag] = sec[tag]
finally:
del tagfile
fobj.close()
@@ -695,7 +755,7 @@ class DscSrcPackage(DebPackage):
" ".join(self.binaries))
self._sections["Description"] = s
self._check_was_run = False
-
+
def check(self):
"""Check if the package is installable.."""
if not self.check_conflicts():
@@ -709,6 +769,7 @@ class DscSrcPackage(DebPackage):
# after _satisfy_depends() should probably be done
return self._satisfy_depends(self.depends)
+
def _test():
"""Test function"""
from apt.cache import Cache
@@ -717,25 +778,25 @@ def _test():
cache = Cache()
vp = "www-browser"
- print "%s virtual: %s" % (vp, cache.is_virtual_package(vp))
+ print("%s virtual: %s" % (vp, cache.is_virtual_package(vp)))
providers = cache.get_providing_packages(vp)
- print "Providers for %s :" % vp
+ print("Providers for %s :" % vp)
for pkg in providers:
- print " %s" % pkg.name
+ print(" %s" % pkg.name)
d = DebPackage(sys.argv[1], cache)
- print "Deb: %s" % d.pkgname
+ print("Deb: %s" % d.pkgname)
if not d.check():
- print "can't be satified"
- print d._failure_string
- print "missing deps: %s" % d.missing_deps
- print d.required_changes
+ print("can't be satified")
+ print(d._failure_string)
+ print("missing deps: %s" % d.missing_deps)
+ print(d.required_changes)
- print d.filelist
+ print(d.filelist)
- print "Installing ..."
+ print("Installing ...")
ret = d.install(InstallProgress())
- print ret
+ print(ret)
#s = DscSrcPackage(cache, "../tests/3ddesktop_0.2.9-6.dsc")
#s.check_dep()
@@ -744,7 +805,7 @@ def _test():
s = DscSrcPackage(cache=cache)
d = "libc6 (>= 2.3.2), libaio (>= 0.3.96) | libaio1 (>= 0.3.96)"
- print s._satisfy_depends(apt_pkg.parse_depends(d))
+ print(s._satisfy_depends(apt_pkg.parse_depends(d, False)))
if __name__ == "__main__":
_test()
diff --git a/apt/deprecation.py b/apt/deprecation.py
deleted file mode 100644
index 0f39ad63..00000000
--- a/apt/deprecation.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# deprecation.py - Module providing classes and functions for deprecation.
-#
-# Copyright (c) 2009 Julian Andres Klode <jak@debian.org>
-# Copyright (c) 2009 Ben Finney <ben+debian@benfinney.id.au>
-#
-# 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
-"""Classes and functions for deprecating features.
-
-This is used for internal purposes only and not part of the official API. Do
-not use it for anything outside the apt package.
-"""
-import re
-import operator
-import warnings
-
-import apt_pkg
-
-__all__ = []
-
-
-class AttributeDeprecatedBy(object):
- """Property acting as a proxy for a new attribute.
-
- When accessed, the property issues a DeprecationWarning and (on get) calls
- attrgetter() for the attribute 'attribute' on the current object or (on
- set) uses setattr to set the value of the wrapped attribute.
- """
-
- def __init__(self, attribute):
- """Initialize the property."""
- self.attribute = attribute
- self.__doc__ = 'Deprecated, please use \'%s\' instead' % attribute
- self.getter = operator.attrgetter(attribute)
-
- def __get__(self, obj, type_=None):
- """Issue a DeprecationWarning and return the requested value."""
- if obj is None:
- return getattr(type_, self.attribute, self)
- warnings.warn(self.__doc__, DeprecationWarning, stacklevel=2)
- return self.getter(obj or type_)
-
- def __set__(self, obj, value):
- """Issue a DeprecationWarning and set the requested value."""
- warnings.warn(self.__doc__, DeprecationWarning, stacklevel=2)
- setattr(obj, self.attribute, value)
-
-
-def function_deprecated_by(func, convert_names=True):
- """Return a function that warns it is deprecated by another function.
-
- Returns a new function that warns it is deprecated by function 'func',
- then acts as a pass-through wrapper for 'func'.
-
- This function also converts all keyword argument names from mixedCase to
- lowercase_with_underscores, but only if 'convert_names' is True (default).
- """
- warning = 'Deprecated, please use \'%s()\' instead' % func.__name__
-
- def deprecated_function(*args, **kwds):
- """Wrapper around a deprecated function."""
- warnings.warn(warning, DeprecationWarning, stacklevel=2)
- if convert_names:
- for key in kwds.keys():
- kwds[re.sub('([A-Z])', '_\\1', key).lower()] = kwds.pop(key)
- return func(*args, **kwds)
- return deprecated_function
-
-
-def deprecated_args(func):
- """A function with deprecated arguments.
-
- Similar to function_deprecated_by() but warns on every deprecated argument
- instead of function calls.
- """
- if not apt_pkg._COMPAT_0_7:
- return func
-
- def deprecated_function(*args, **kwds):
- """Wrapper around a function with deprecated arguments."""
- for key in kwds.keys():
- new_key = re.sub('([A-Z])', '_\\1', key).lower()
- if new_key != key:
- warnings.warn("Deprecated parameter %r" % key)
- kwds[new_key] = kwds.pop(key)
- return func(*args, **kwds)
-
- # Wrap the function completely (same as functools.wraps)
- # pylint: disable-msg=W0622
- deprecated_function.__name__ = func.__name__
- deprecated_function.__doc__ = func.__doc__
- deprecated_function.__module__ = func.__module__
- deprecated_function.__dict__.update(func.__dict__)
- return deprecated_function
diff --git a/apt/package.py b/apt/package.py
index dbaab320..57c89b35 100644
--- a/apt/package.py
+++ b/apt/package.py
@@ -19,34 +19,35 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
"""Functionality related to packages."""
-import httplib
+from __future__ import print_function
+
+
import os
import sys
import re
import socket
import subprocess
-import urllib2
-import warnings
-try:
- from collections import Mapping, Sequence
-except ImportError:
- # (for Python < 2.6) pylint: disable-msg=C0103
- Sequence = Mapping = object
try:
- from collections import Sequence
+ from http.client import BadStatusLine
+ from urllib.error import HTTPError
+ from urllib.request import urlopen
except ImportError:
- Sequence = object
+ from httplib import BadStatusLine
+ from urllib2 import HTTPError, urlopen
+
+from collections import Mapping, Sequence
import apt_pkg
import apt.progress.text
from apt_pkg import gettext as _
-from apt.deprecation import (function_deprecated_by, AttributeDeprecatedBy,
- deprecated_args)
__all__ = ('BaseDependency', 'Dependency', 'Origin', 'Package', 'Record',
'Version', 'VersionList')
+if sys.version_info.major >= 3:
+ unicode = str
+
def _file_is_same(path, size, md5):
"""Return ``True`` if the file is the same."""
@@ -60,38 +61,77 @@ class FetchError(Exception):
class BaseDependency(object):
- """A single dependency.
-
- Attributes defined here:
- name - The name of the dependency
- relation - The relation (>,>=,==,<,<=,)
- version - The version depended on
- rawtype - The type of the dependendy (e.g. 'Recommends')
- pre_depend - Boolean value whether this is a pre-dependency.
- """
+ """A single dependency."""
class __dstr(str):
- """Helper to make > match >> and < match <<"""
+ """Compare helper for compatibility with old third-party code.
+
+ Old third-party code might still compare the relation with the
+ previously used relations (<<,<=,==,!=,>=,>>,) instead of the curently
+ used ones (<,<=,=,!=,>=,>,). This compare helper lets < match to <<,
+ > match to >> and = match to ==.
+ """
def __eq__(self, other):
- return str.__eq__(self, other) or str.__eq__(2 * self, other)
+ if str.__eq__(self, other):
+ return True
+ elif str.__eq__(self, '<'):
+ return str.__eq__('<<', other)
+ elif str.__eq__(self, '>'):
+ return str.__eq__('>>', other)
+ elif str.__eq__(self, '='):
+ return str.__eq__('==', other)
+ else:
+ return False
def __ne__(self, other):
- return str.__eq__(self, other) and str.__ne__(2 * self, other)
+ return not self.__eq__(other)
- def __init__(self, name, rel, ver, pre, rawtype=None):
- self.name = name
- self.relation = len(rel) == 1 and self.__dstr(rel) or rel
- self.version = ver
- self.pre_depend = pre
- self.rawtype = rawtype
+ def __init__(self, dep):
+ self._dep = dep # apt_pkg.Dependency
- def __repr__(self):
- return ('<BaseDependency: name:%r relation:%r version:%r preDepend:%r>'
- % (self.name, self.relation, self.version, self.pre_depend))
+ @property
+ def name(self):
+ """The name of the target package."""
+ return self._dep.target_pkg.name
+
+ @property
+ def relation(self):
+ """The relation (<, <=, !=, =, >=, >, ).
+
+ Note that the empty string is a valid string as well, if no version
+ is specified.
+ """
+ return self.__dstr(self._dep.comp_type)
- if apt_pkg._COMPAT_0_7:
- preDepend = AttributeDeprecatedBy('pre_depend')
+ @property
+ def version(self):
+ """The target version or an empty string.
+
+ Note that the version is only an empty string in case of an unversioned
+ dependency. In this case the relation is also an empty string.
+ """
+ return self._dep.target_ver
+
+ @property
+ def rawtype(self):
+ """Type of the dependency.
+
+ This should be one of 'Breaks', 'Conflicts', 'Depends', 'Enhances',
+ 'PreDepends', 'Recommends', 'Replaces', 'Suggests'.
+
+ Additional types might be added in the future.
+ """
+ return self._dep.dep_type_untranslated
+
+ @property
+ def pre_depend(self):
+ """Whether this is a PreDepends."""
+ return self._dep.dep_type_untranslated == 'PreDepends'
+
+ def __repr__(self):
+ return ('<BaseDependency: name:%r relation:%r version:%r rawtype:%r>'
+ % (self.name, self.relation, self.version, self.rawtype))
class Dependency(list):
@@ -99,34 +139,29 @@ class Dependency(list):
Attributes defined here:
or_dependencies - The possible choices
+ rawtype - The type of the dependencies in the Or-group
"""
- def __init__(self, alternatives):
- super(Dependency, self).__init__()
- self.extend(alternatives)
+ def __init__(self, base_deps, rawtype):
+ super(Dependency, self).__init__(base_deps)
+ self._rawtype = rawtype
@property
def or_dependencies(self):
return self
-class DeprecatedProperty(property):
- """A property which gives DeprecationWarning on access.
+ @property
+ def rawtype(self):
+ """Type of the Or-group of dependency.
- This is only used for providing the properties in Package, which have been
- replaced by the ones in Version.
- """
+ This should be one of 'Breaks', 'Conflicts', 'Depends', 'Enhances',
+ 'PreDepends', 'Recommends', 'Replaces', 'Suggests'.
- def __init__(self, fget=None, fset=None, fdel=None, doc=None):
- property.__init__(self, fget, fset, fdel, doc)
- self.__doc__ = (doc or fget.__doc__ or '')
+ Additional types might be added in the future.
- 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.__name__), DeprecationWarning, 2)
- return property.__get__(self, obj, type_)
+ .. versionadded:: 1.0.0
+ """
+ return self._rawtype
class Origin(object):
@@ -356,14 +391,14 @@ class Version(object):
try:
if not isinstance(dsc, unicode):
# Only convert where needed (i.e. Python 2.X)
- dsc = unicode(dsc, "utf-8")
+ dsc = dsc.decode("utf-8")
except UnicodeDecodeError as err:
return _("Invalid unicode in description for '%s' (%s). "
- "Please report.") % (self.package.name, err)
+ "Please report.") % (self.package.name, err)
lines = iter(dsc.split("\n"))
# Skip the first line, since its a duplication of the summary
- lines.next()
+ next(lines)
for raw_line in lines:
if raw_line.strip() == ".":
# The line is just line break
@@ -417,7 +452,7 @@ class Version(object):
"""
priority = 0
policy = self.package._pcache._depcache.policy
- for (packagefile, _) in self._cand.file_list:
+ for (packagefile, _unused) in self._cand.file_list:
priority = max(priority, policy.get_priority(packagefile))
return priority
@@ -431,7 +466,14 @@ class Version(object):
return Record(self._records.record)
def get_dependencies(self, *types):
- """Return a list of Dependency objects for the given types."""
+ """Return a list of Dependency objects for the given types.
+
+ Multiple types can be specified. Possible types are:
+ 'Breaks', 'Conflicts', 'Depends', 'Enhances', 'PreDepends',
+ 'Recommends', 'Replaces', 'Suggests'
+
+ Additional types might be added in the future.
+ """
depends_list = []
depends = self._cand.depends_list
for type_ in types:
@@ -439,11 +481,8 @@ class Version(object):
for dep_ver_list in depends[type_]:
base_deps = []
for dep_or in dep_ver_list:
- base_deps.append(BaseDependency(dep_or.target_pkg.name,
- dep_or.comp_type, dep_or.target_ver,
- (type_ == "PreDepends"),
- rawtype=type_))
- depends_list.append(Dependency(base_deps))
+ base_deps.append(BaseDependency(dep_or))
+ depends_list.append(Dependency(base_deps, type_))
except KeyError:
pass
return depends_list
@@ -452,7 +491,7 @@ class Version(object):
def provides(self):
""" Return a list of names that this version provides."""
return [p[0] for p in self._cand.provides_list]
-
+
@property
def enhances(self):
"""Return the list of enhances for the package version."""
@@ -477,7 +516,7 @@ class Version(object):
def origins(self):
"""Return a list of origins for the package version."""
origins = []
- for (packagefile, _) in self._cand.file_list:
+ for (packagefile, _unused) in self._cand.file_list:
origins.append(Origin(self.package, packagefile))
return origins
@@ -528,7 +567,7 @@ class Version(object):
.. versionadded:: 0.7.10
"""
- for (packagefile, _) in self._cand.file_list:
+ for (packagefile, _unused) in self._cand.file_list:
indexfile = self.package._pcache._list.find_index(packagefile)
if indexfile:
yield indexfile.archive_uri(self._records.filename)
@@ -548,7 +587,7 @@ class Version(object):
.. versionadded:: 0.7.10
"""
try:
- return iter(self._uris()).next()
+ return next(iter(self._uris()))
except StopIteration:
return None
@@ -567,7 +606,7 @@ class Version(object):
base = os.path.basename(self._records.filename)
destfile = os.path.join(destdir, base)
if _file_is_same(destfile, self.size, self._records.md5_hash):
- print('Ignoring already existing file: %s' % destfile)
+ print(('Ignoring already existing file: %s' % destfile))
return os.path.abspath(destfile)
acq = apt_pkg.Acquire(progress or apt.progress.text.AcquireProgress())
acqfile = apt_pkg.AcquireFile(acq, self.uri, self._records.md5_hash,
@@ -616,7 +655,7 @@ class Version(object):
if type_ == 'dsc':
dsc = destfile
if _file_is_same(destfile, size, md5):
- print('Ignoring already existing file: %s' % destfile)
+ print(('Ignoring already existing file: %s' % destfile))
continue
files.append(apt_pkg.AcquireFile(acq, src.index.archive_uri(path),
md5, size, base, destfile=destfile))
@@ -625,7 +664,7 @@ class Version(object):
for item in acq.items:
if item.status != item.STAT_DONE:
raise FetchError("The item %r could not be fetched: %s" %
- (item.destfile, item.error_text))
+ (item.destfile, item.error_text))
if unpack:
outdir = src.package + '-' + apt_pkg.upstream_version(src.version)
@@ -657,8 +696,8 @@ class VersionList(Sequence):
"""
def __init__(self, package, slice_=None):
- self._package = package # apt.package.Package()
- self._versions = package._pkg.version_list # [apt_pkg.Version(), ...]
+ self._package = package # apt.package.Package()
+ self._versions = package._pkg.version_list # [apt_pkg.Version(), ...]
if slice_:
self._versions = self._versions[slice_]
@@ -683,7 +722,7 @@ class VersionList(Sequence):
return (Version(self._package, ver) for ver in self._versions)
def __contains__(self, item):
- if isinstance(item, Version): # Sequence interface
+ if isinstance(item, Version): # Sequence interface
item = item.version
# Dictionary interface.
for ver in self._versions:
@@ -726,8 +765,8 @@ class Package(object):
self._changelog = "" # Cached changelog
def __repr__(self):
- return '<Package: name:%r architecture=%r id:%r>' % (self._pkg.name,
- self._pkg.architecture, self._pkg.id)
+ return '<Package: name:%r architecture=%r id:%r>' % (
+ self._pkg.name, self._pkg.architecture, self._pkg.id)
def __lt__(self, other):
return self.name < other.name
@@ -769,6 +808,7 @@ class Package(object):
as :attr:`shortname`
.. versionchanged:: 0.7.100.3
+
As part of multi-arch, this field now may include architecture
information.
"""
@@ -806,36 +846,6 @@ class Package(object):
"""Return True if the package is an essential part of the system."""
return self._pkg.essential
- @DeprecatedProperty
- def installedVersion(self): #pylint: disable-msg=C0103
- """Return the installed version as string.
-
- .. deprecated:: 0.7.9"""
- return getattr(self.installed, 'version', None)
-
- @DeprecatedProperty
- def candidateVersion(self): #pylint: disable-msg=C0103
- """Return the candidate version as string.
-
- .. deprecated:: 0.7.9"""
- return getattr(self.candidate, "version", None)
-
- @DeprecatedProperty
- def candidateDependencies(self): #pylint: disable-msg=C0103
- """Return a list of candidate dependencies.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.candidate, "dependencies", None)
-
- @DeprecatedProperty
- def installedDependencies(self): #pylint: disable-msg=C0103
- """Return a list of installed dependencies.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.installed, 'dependencies', [])
-
def architecture(self):
"""Return the Architecture of the package.
@@ -846,107 +856,11 @@ class Package(object):
"""
return self._pkg.architecture
- @DeprecatedProperty
- def candidateDownloadable(self): #pylint: disable-msg=C0103
- """Return ``True`` if the candidate is downloadable.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.candidate, "downloadable", None)
-
- @DeprecatedProperty
- def installedDownloadable(self): #pylint: disable-msg=C0103
- """Return ``True`` if the installed version is downloadable.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.installed, 'downloadable', False)
-
- @DeprecatedProperty
- def sourcePackageName(self): #pylint: disable-msg=C0103
- """Return the source package name as string.
-
- .. deprecated:: 0.7.9
- """
- try:
- return self.candidate._records.source_pkg or self._pkg.name
- except AttributeError:
- try:
- return self.installed._records.source_pkg or self._pkg.name
- except AttributeError:
- return self._pkg.name
-
- @DeprecatedProperty
- def homepage(self):
- """Return the homepage field as string.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.candidate, "homepage", None)
-
@property
def section(self):
"""Return the section of the package."""
return self._pkg.section
- @DeprecatedProperty
- def priority(self):
- """Return the priority (of the candidate version).
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.candidate, "priority", None)
-
- @DeprecatedProperty
- def installedPriority(self): #pylint: disable-msg=C0103
- """Return the priority (of the installed version).
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.installed, 'priority', None)
-
- @DeprecatedProperty
- def summary(self):
- """Return the short description (one line summary).
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.candidate, "summary", None)
-
- @DeprecatedProperty
- def description(self):
- """Return the formatted long description.
-
- Return the formatted 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.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.candidate, "description", None)
-
- @DeprecatedProperty
- def rawDescription(self): #pylint: disable-msg=C0103
- """return the long description (raw).
-
- .. deprecated:: 0.7.9"""
- return getattr(self.candidate, "raw_description", None)
-
- @DeprecatedProperty
- def candidateRecord(self): #pylint: disable-msg=C0103
- """Return the Record of the candidate version of the package.
-
- .. deprecated:: 0.7.9"""
- return getattr(self.candidate, "record", None)
-
- @DeprecatedProperty
- def installedRecord(self): #pylint: disable-msg=C0103
- """Return the Record of the candidate version of the package.
-
- .. deprecated:: 0.7.9"""
- return getattr(self.installed, 'record', '')
-
# depcache states
@property
@@ -1007,39 +921,6 @@ class Package(object):
return self._pcache._depcache.is_auto_installed(self._pkg)
# sizes
- @DeprecatedProperty
- def packageSize(self): #pylint: disable-msg=C0103
- """Return the size of the candidate deb package.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.candidate, "size", None)
-
- @DeprecatedProperty
- def installedPackageSize(self): #pylint: disable-msg=C0103
- """Return the size of the installed deb package.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.installed, 'size', 0)
-
- @DeprecatedProperty
- def candidateInstalledSize(self): #pylint: disable-msg=C0103
- """Return the size of the candidate installed package.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.candidate, "installed_size", None)
-
- @DeprecatedProperty
- def installedSize(self): #pylint: disable-msg=C0103
- """Return the size of the currently installed package.
-
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.installed, 'installed_size', 0)
-
@property
def installed_files(self):
"""Return a list of files installed by the package.
@@ -1047,7 +928,7 @@ class Package(object):
Return a list of unicode names of the files which have
been installed by this package
"""
- for name in self.shortname, self.fullname:
+ for name in self.name, self.fullname:
path = "/var/lib/dpkg/info/%s.list" % name
try:
with open(path, "rb") as file_list:
@@ -1100,10 +981,10 @@ class Package(object):
src_section = "main"
# use the section of the candidate as a starting point
section = self.candidate.section
-
+
# get the source version
src_ver = self.candidate.source_version
-
+
try:
# try to get the source version of the pkg, this differs
# for some (e.g. libnspr4 on ubuntu)
@@ -1160,7 +1041,7 @@ class Package(object):
if cancel_lock and cancel_lock.isSet():
return u""
# FIXME: python3.2: Should be closed manually
- changelog_file = urllib2.urlopen(uri)
+ changelog_file = urlopen(uri)
# do only get the lines that are new
changelog = u""
regexp = "^%s \((.*)\)(.*)$" % (re.escape(src_pkg))
@@ -1189,7 +1070,7 @@ class Package(object):
changelog_ver = changelog_ver.split(":", 1)[1]
if (installed and apt_pkg.version_compare(
- changelog_ver, installed) <= 0):
+ changelog_ver, installed) <= 0):
break
# EOF (shouldn't really happen)
changelog += line
@@ -1201,29 +1082,25 @@ class Package(object):
changelog = changelog.decode("utf-8")
self._changelog = changelog
- except urllib2.HTTPError:
- res = _("The list of changes is not available yet.\n\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 HTTPError:
+ if self.candidate.origins[0].origin == "Ubuntu":
+ res = _("The list of changes is not available yet.\n\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)
+ else:
+ res = _("The list of changes is not available")
return res if isinstance(res, unicode) else res.decode("utf-8")
- except (IOError, httplib.BadStatusLine):
+ except (IOError, BadStatusLine):
res = _("Failed to download the list of changes. \nPlease "
- "check your Internet connection.")
+ "check your Internet connection.")
return res if isinstance(res, unicode) else res.decode("utf-8")
finally:
socket.setdefaulttimeout(timeout)
return self._changelog
- @DeprecatedProperty
- def candidateOrigin(self): #pylint: disable-msg=C0103
- """Return a list of `Origin()` objects for the candidate version.
-
- .. deprecated:: 0.7.9
- """
- return getattr(self.candidate, "origins", None)
-
@property
def versions(self):
"""Return a VersionList() object for all available versions.
@@ -1242,6 +1119,11 @@ class Package(object):
"""Return True if the installed package is broken."""
return self._pcache._depcache.is_now_broken(self._pkg)
+ @property
+ def has_config_files(self):
+ """Checks whether the package is is the config-files state."""
+ return self. _pkg.current_state == apt_pkg.CURSTATE_CONFIG_FILES
+
# depcache actions
def mark_keep(self):
@@ -1250,7 +1132,6 @@ class Package(object):
self._pcache._depcache.mark_keep(self._pkg)
self._pcache.cache_post_change()
- @deprecated_args
def mark_delete(self, auto_fix=True, purge=False):
"""Mark a package for deletion.
@@ -1272,7 +1153,6 @@ class Package(object):
fix.resolve()
self._pcache.cache_post_change()
- @deprecated_args
def mark_install(self, auto_fix=True, auto_inst=True, from_user=True):
"""Mark a package for install.
@@ -1297,11 +1177,12 @@ class Package(object):
fixer.resolve(True)
self._pcache.cache_post_change()
- def mark_upgrade(self):
+ def mark_upgrade(self, from_user=True):
"""Mark a package for upgrade."""
if self.is_upgradable:
- from_user = not self._pcache._depcache.is_auto_installed(self._pkg)
+ auto = self.is_auto_installed
self.mark_install(from_user=from_user)
+ self.mark_auto(auto)
else:
# FIXME: we may want to throw a exception here
sys.stderr.write(("MarkUpgrade() called on a non-upgrable pkg: "
@@ -1328,103 +1209,61 @@ class Package(object):
self._pcache._depcache.commit(fprogress, iprogress)
- if not apt_pkg._COMPAT_0_7:
- del installedVersion
- del candidateVersion
- del candidateDependencies
- del installedDependencies
- del architecture
- del candidateDownloadable
- del installedDownloadable
- del sourcePackageName
- del homepage
- del priority
- del installedPriority
- del summary
- del description
- del rawDescription
- del candidateRecord
- del installedRecord
- del packageSize
- del installedPackageSize
- del candidateInstalledSize
- del installedSize
- del candidateOrigin
- else:
- markedInstalled = AttributeDeprecatedBy('marked_installed')
- markedInstall = AttributeDeprecatedBy('marked_install')
- markedUpgrade = AttributeDeprecatedBy('marked_upgrade')
- markedDelete = AttributeDeprecatedBy('marked_delete')
- markedKeep = AttributeDeprecatedBy('marked_keep')
- markedDowngrade = AttributeDeprecatedBy('marked_downgrade')
- markedReinstall = AttributeDeprecatedBy('marked_reinstall')
- isInstalled = AttributeDeprecatedBy('is_installed')
- isUpgradable = AttributeDeprecatedBy('is_upgradable')
- isAutoRemovable = AttributeDeprecatedBy('is_auto_removable')
- installedFiles = AttributeDeprecatedBy('installed_files')
- getChangelog = function_deprecated_by(get_changelog)
- markDelete = function_deprecated_by(mark_delete)
- markInstall = function_deprecated_by(mark_install)
- markKeep = function_deprecated_by(mark_keep)
- markUpgrade = function_deprecated_by(mark_upgrade)
-
-
def _test():
"""Self-test."""
- print "Self-test for the Package modul"
+ print("Self-test for the Package modul")
import random
apt_pkg.init()
progress = apt.progress.text.OpProgress()
cache = apt.Cache(progress)
pkg = cache["apt-utils"]
- print "Name: %s " % pkg.name
- print "ID: %s " % pkg.id
- 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.candidate.summary
- print "Description (formatted) :\n%s" % pkg.candidate.description
- print "Description (unformatted):\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
- print "Recommends: %s" % pkg.installed.recommends
+ print("Name: %s " % pkg.name)
+ print("ID: %s " % pkg.id)
+ 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.candidate.summary)
+ print("Description (formatted) :\n%s" % pkg.candidate.description)
+ print("Description (unformatted):\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)
+ print("Recommends: %s" % pkg.installed.recommends)
for dep in pkg.candidate.dependencies:
- print ",".join("%s (%s) (%s) (%s)" % (o.name, o.version, o.relation,
- o.pre_depend) for o in dep.or_dependencies)
- print "arch: %s" % pkg.candidate.architecture
- print "homepage: %s" % pkg.candidate.homepage
- print "rec: ", pkg.candidate.record
-
+ print(",".join("%s (%s) (%s) (%s)" % (o.name, o.version, o.relation,
+ o.pre_depend) for o in dep.or_dependencies))
+ print("arch: %s" % pkg.candidate.architecture)
+ print("homepage: %s" % pkg.candidate.homepage)
+ print("rec: ", pkg.candidate.record)
- print cache["2vcard"].get_changelog()
+ print(cache["2vcard"].get_changelog())
for i in True, False:
- print "Running install on random upgradable pkgs with AutoFix: %s " % i
+ print("Running install on random upgradable pkgs with AutoFix: ", i)
for pkg in cache:
if pkg.is_upgradable:
if random.randint(0, 1) == 1:
pkg.mark_install(i)
- print "Broken: %s " % cache._depcache.broken_count
- print "InstCount: %s " % cache._depcache.inst_count
+ print("Broken: %s " % cache._depcache.broken_count)
+ print("InstCount: %s " % cache._depcache.inst_count)
- print
+ print()
# get a new cache
for i in True, False:
- print "Randomly remove some packages with AutoFix: %s" % i
+ print("Randomly remove some packages with AutoFix: %s" % i)
cache = apt.Cache(progress)
for name in cache.keys():
if random.randint(0, 1) == 1:
try:
cache[name].mark_delete(i)
except SystemError:
- print "Error trying to remove: %s " % name
- print "Broken: %s " % cache._depcache.broken_count
- print "DelCount: %s " % cache._depcache.del_count
+ print("Error trying to remove: %s " % name)
+ print("Broken: %s " % cache._depcache.broken_count)
+ print("DelCount: %s " % cache._depcache.del_count)
# self-test
if __name__ == "__main__":
diff --git a/apt/progress/__init__.py b/apt/progress/__init__.py
index 10c11021..1ae94d06 100644
--- a/apt/progress/__init__.py
+++ b/apt/progress/__init__.py
@@ -19,17 +19,11 @@
"""Progress reporting.
This package provides progress reporting for the python-apt package. The module
-'base' provides classes with no output, the module 'gtk2' provides classes for
-GTK+ applications, and the module 'text' provides classes for terminals, etc.
+'base' provides classes with no output, and the module 'text' provides classes
+for terminals, etc.
"""
-import apt_pkg
-
-__all__ = []
+from __future__ import print_function
-if apt_pkg._COMPAT_0_7:
- from apt.progress.old import (CdromProgress, DpkgInstallProgress,
- DumbInstallProgress, FetchProgress,
- InstallProgress, OpProgress,
- OpTextProgress, TextFetchProgress)
+__all__ = []
diff --git a/apt/progress/base.py b/apt/progress/base.py
index 2c80ae29..95eca9ec 100644
--- a/apt/progress/base.py
+++ b/apt/progress/base.py
@@ -22,6 +22,8 @@
Custom progress classes should inherit from these classes. They can also be
used as dummy progress classes which simply do nothing.
"""
+from __future__ import print_function
+
import errno
import fcntl
import os
@@ -217,7 +219,7 @@ class InstallProgress(object):
except IOError as err:
# resource temporarly unavailable is ignored
if err.errno != errno.EAGAIN and err.errno != errno.EWOULDBLOCK:
- print err.strerror
+ print(err.strerror)
return
pkgname = status = status_str = percent = base = ""
@@ -269,7 +271,8 @@ class InstallProgress(object):
try:
select.select([self.status_stream], [], [],
self.select_timeout)
- except select.error as (errno_, _errstr):
+ except select.error as error:
+ (errno_, _errstr) = error.args
if errno_ != errno.EINTR:
raise
diff --git a/apt/progress/gtk2.py b/apt/progress/gtk2.py
deleted file mode 100644
index c2635ca0..00000000
--- a/apt/progress/gtk2.py
+++ /dev/null
@@ -1,519 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2004-2009 Canonical
-#
-# Authors: Michael Vogt <michael.vogt@ubuntu.com>
-# Sebastian Heinlein <glatzor@ubuntu.com>
-# Julian Andres Klode <jak@debian.org>
-#
-# 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
-"""GObject-powered progress classes and a GTK+ status widget."""
-
-import pygtk
-pygtk.require('2.0')
-import gtk
-try:
- import glib
-except ImportError:
- import gobject as glib
-import gobject
-import pango
-import time
-import vte
-
-import apt_pkg
-from apt_pkg import gettext as _
-from apt.deprecation import function_deprecated_by, AttributeDeprecatedBy
-from apt.progress import base
-
-if apt_pkg._COMPAT_0_7:
- from apt.progress import old
-
-
-__all__ = ['GAcquireProgress', 'GInstallProgress', 'GOpProgress',
- 'GtkAptProgress']
-
-
-def mksig(params=(), run=gobject.SIGNAL_RUN_FIRST, rettype=gobject.TYPE_NONE):
- """Simplified Create a gobject signal.
-
- This allows us to write signals easier, because we just need to define the
- type of the parameters (in most cases).
-
- ``params`` is a tuple which defines the types of the arguments.
- """
- return (run, rettype, params)
-
-
-class GOpProgress(gobject.GObject, base.OpProgress):
- """Operation progress with GObject signals.
-
- Signals:
-
- * status-changed(str: operation, int: percent)
- * status-started() - Not Implemented yet
- * status-finished()
-
- """
-
- __gsignals__ = {"status-changed": mksig((str, int)),
- "status-started": mksig(),
- "status-finished": mksig()}
-
- def __init__(self):
- base.OpProgress.__init__(self)
- gobject.GObject.__init__(self)
- self._context = glib.main_context_default()
-
- def update(self, percent=None):
- """Called to update the percentage done"""
- base.OpProgress.update(self, percent)
- self.emit("status-changed", self.op, self.percent)
- while self._context.pending():
- self._context.iteration()
-
- def done(self):
- """Called when all operation have finished."""
- base.OpProgress.done(self)
- self.emit("status-finished")
-
- if apt_pkg._COMPAT_0_7:
- subOp = AttributeDeprecatedBy('subop')
- Op = AttributeDeprecatedBy('op')
-
-
-class GInstallProgress(gobject.GObject, base.InstallProgress):
- """Installation progress with GObject signals.
-
- Signals:
-
- * status-changed(str: status, int: percent)
- * status-started()
- * status-finished()
- * status-timeout()
- * status-error()
- * status-conffile()
-
- """
- # Seconds until a maintainer script will be regarded as hanging
- INSTALL_TIMEOUT = 5 * 60
-
- __gsignals__ = {"status-changed": mksig((str, int)),
- "status-started": mksig(),
- "status-timeout": mksig(),
- "status-error": mksig(),
- "status-conffile": mksig(),
- "status-finished": mksig()}
-
- def __init__(self, term):
- base.InstallProgress.__init__(self)
- gobject.GObject.__init__(self)
- self.finished = False
- self.apt_status = -1
- self.time_last_update = time.time()
- self.term = term
- self.term.connect("child-exited", self.child_exited)
- self.env = ["VTE_PTY_KEEP_FD=%s" % self.writefd,
- "DEBIAN_FRONTEND=gnome",
- "APT_LISTCHANGES_FRONTEND=gtk"]
- self._context = glib.main_context_default()
-
- def child_exited(self, term):
- """Called when a child process exits"""
- self.apt_status = term.get_child_exit_status()
- self.finished = True
-
- def error(self, pkg, errormsg):
- """Called when an error happens.
-
- Emits: status-error()
- """
- self.emit("status-error")
-
- def conffile(self, current, new):
- """Called during conffile.
-
- Emits: status-conffile()
- """
- self.emit("status-conffile")
-
- def start_update(self):
- """Called when the update starts.
-
- Emits: status-started()
- """
- self.emit("status-started")
-
- def run(self, obj):
- """Run."""
- self.finished = False
- return base.InstallProgress.run(self, obj)
-
- def finish_update(self):
- """Called when the update finished.
-
- Emits: status-finished()
- """
- self.emit("status-finished")
-
- def processing(self, pkg, stage):
- """Called when entering a new stage in dpkg."""
- # We have no percentage or alike, send -1 to let the bar pulse.
- self.emit("status-changed", ("Installing %s...") % pkg, -1)
-
- def status_change(self, pkg, percent, status):
- """Called when the status changed.
-
- Emits: status-changed(status, percent)
- """
- self.time_last_update = time.time()
- self.emit("status-changed", status, percent)
-
- def update_interface(self):
- """Called periodically to update the interface.
-
- Emits: status-timeout() [When a timeout happens]
- """
- base.InstallProgress.update_interface(self)
- while self._context.pending():
- self._context.iteration()
- if self.time_last_update + self.INSTALL_TIMEOUT < time.time():
- self.emit("status-timeout")
-
- def fork(self):
- """Fork the process."""
- return self.term.forkpty(envv=self.env)
-
- def wait_child(self):
- """Wait for the child process to exit."""
- while not self.finished:
- self.update_interface()
- time.sleep(0.02)
- return self.apt_status
-
- if apt_pkg._COMPAT_0_7:
- updateInterface = function_deprecated_by(update_interface)
- startUpdate = function_deprecated_by(start_update)
- finishUpdate = function_deprecated_by(finish_update)
- statusChange = function_deprecated_by(status_change)
- waitChild = function_deprecated_by(wait_child)
- childExited = function_deprecated_by(child_exited)
-
-
-GDpkgInstallProgress = GInstallProgress
-
-
-class GAcquireProgress(gobject.GObject, base.AcquireProgress):
- """A Fetch Progress with GObject signals.
-
- Signals:
-
- * status-changed(str: description, int: percent)
- * status-started()
- * status-finished()
-
- DEPRECATED.
- """
-
- __gsignals__ = {"status-changed": mksig((str, int)),
- "status-started": mksig(),
- "status-finished": mksig()}
-
- def __init__(self):
- base.AcquireProgress.__init__(self)
- gobject.GObject.__init__(self)
- self._continue = True
- self._context = glib.main_context_default()
-
- def start(self):
- base.AcquireProgress.start(self)
- self.emit("status-started")
-
- def stop(self):
- base.AcquireProgress.stop(self)
- self.emit("status-finished")
-
- def cancel(self):
- self._continue = False
-
- def pulse(self, owner):
- base.AcquireProgress.pulse(self, owner)
- current_item = self.current_items + 1
- if current_item > self.total_items:
- current_item = self.total_items
- if self.current_cps > 0:
- text = (_("Downloading file %(current)li of %(total)li with "
- "%(speed)s/s") % \
- {"current": current_item,
- "total": self.total_items,
- "speed": apt_pkg.size_to_str(self.current_cps)})
- else:
- text = (_("Downloading file %(current)li of %(total)li") % \
- {"current": current_item,
- "total": self.total_items})
-
- percent = (((self.current_bytes + self.current_items) * 100.0) /
- float(self.total_bytes + self.total_items))
- self.emit("status-changed", text, percent)
- while self._context.pending():
- self._context.iteration()
- return self._continue
-
-if apt_pkg._COMPAT_0_7:
-
- class GFetchProgress(gobject.GObject, old.FetchProgress):
- """A Fetch Progress with GObject signals.
-
- Signals:
-
- * status-changed(str: description, int: percent)
- * status-started()
- * status-finished()
-
- DEPRECATED.
- """
-
- __gsignals__ = {"status-changed": mksig((str, int)),
- "status-started": mksig(),
- "status-finished": mksig()}
-
- def __init__(self):
- old.FetchProgress.__init__(self)
- gobject.GObject.__init__(self)
- self._continue = True
- self._context = glib.main_context_default()
-
- def start(self):
- self.emit("status-started")
-
- def stop(self):
- self.emit("status-finished")
-
- def cancel(self):
- self._continue = False
-
- def pulse(self):
- old.FetchProgress.pulse(self)
- current_item = self.currentItems + 1
- if current_item > self.totalItems:
- current_item = self.totalItems
- if self.current_cps > 0:
- text = (_("Downloading file %(current)li of %(total)li with "
- "%(speed)s/s") % \
- {"current": current_item,
- "total": self.totalItems,
- "speed": apt_pkg.size_to_str(self.currentCPS)})
- else:
- text = (_("Downloading file %(current)li of %(total)li") % \
- {"current": current_item,
- "total": self.totalItems})
- self.emit("status-changed", text, self.percent)
- while self._context.pending():
- self._context.iteration()
- return self._continue
-
-
-class GtkAptProgress(gtk.VBox):
- """Graphical progress for installation/fetch/operations.
-
- This widget provides a progress bar, a terminal and a status bar for
- showing the progress of package manipulation tasks.
- """
-
- def __init__(self):
- gtk.VBox.__init__(self)
- self.set_spacing(6)
- # Setup some child widgets
- self._expander = gtk.Expander(_("Details"))
- self._terminal = vte.Terminal()
- #self._terminal.set_font_from_string("monospace 10")
- self._expander.add(self._terminal)
- self._progressbar = gtk.ProgressBar()
- # Setup the always italic status label
- self._label = gtk.Label()
- attr_list = pango.AttrList()
- attr_list.insert(pango.AttrStyle(pango.STYLE_ITALIC, 0, -1))
- self._label.set_attributes(attr_list)
- self._label.set_ellipsize(pango.ELLIPSIZE_END)
- self._label.set_alignment(0, 0)
- # add child widgets
- self.pack_start(self._progressbar, False)
- self.pack_start(self._label, False)
- self.pack_start(self._expander, False)
- # Setup the internal progress handlers
- self._progress_open = GOpProgress()
- self._progress_open.connect("status-changed", self._on_status_changed)
- self._progress_open.connect("status-started", self._on_status_started)
- self._progress_open.connect("status-finished",
- self._on_status_finished)
- self._progress_acquire = GAcquireProgress()
- self._progress_acquire.connect("status-changed",
- self._on_status_changed)
- self._progress_acquire.connect("status-started",
- self._on_status_started)
- self._progress_acquire.connect("status-finished",
- self._on_status_finished)
-
- self._progress_fetch = None
- self._progress_install = GInstallProgress(self._terminal)
- self._progress_install.connect("status-changed",
- self._on_status_changed)
- self._progress_install.connect("status-started",
- self._on_status_started)
- self._progress_install.connect("status-finished",
- self._on_status_finished)
- self._progress_install.connect("status-timeout",
- self._on_status_timeout)
- self._progress_install.connect("status-error",
- self._on_status_timeout)
- self._progress_install.connect("status-conffile",
- self._on_status_timeout)
-
- def clear(self):
- """Reset all status information."""
- self._label.set_label("")
- self._progressbar.set_fraction(0)
- self._expander.set_expanded(False)
-
- @property
- def open(self):
- """Return the cache opening progress handler."""
- return self._progress_open
-
- @property
- def install(self):
- """Return the install progress handler."""
- return self._progress_install
-
- @property
- def dpkg_install(self):
- """Return the install progress handler for dpkg."""
- return self._progress_install
-
- if apt_pkg._COMPAT_0_7:
-
- @property
- def fetch(self):
- """Return the fetch progress handler."""
- if self._progress_fetch is None:
- self._progress_fetch = GFetchProgress()
- self._progress_fetch.connect("status-changed",
- self._on_status_changed)
- self._progress_fetch.connect("status-started",
- self._on_status_started)
- self._progress_fetch.connect("status-finished",
- self._on_status_finished)
- return self._progress_fetch
-
- @property
- def acquire(self):
- """Return the acquire progress handler."""
- return self._progress_acquire
-
- def _on_status_started(self, progress):
- """Called when something starts."""
- self._on_status_changed(progress, _("Starting..."), 0)
- while gtk.events_pending():
- gtk.main_iteration()
-
- def _on_status_finished(self, progress):
- """Called when something finished."""
- self._on_status_changed(progress, _("Complete"), 100)
- while gtk.events_pending():
- gtk.main_iteration()
-
- def _on_status_changed(self, progress, status, percent):
- """Called when the status changed."""
- self._label.set_text(status)
- if percent is None or percent == -1:
- self._progressbar.pulse()
- else:
- self._progressbar.set_fraction(percent/100.0)
- while gtk.events_pending():
- gtk.main_iteration()
-
- def _on_status_timeout(self, progress):
- """Called when timeout happens."""
- self._expander.set_expanded(True)
- while gtk.events_pending():
- gtk.main_iteration()
-
- def cancel_download(self):
- """Cancel a currently running download."""
- self._progress_fetch.cancel()
-
- def show_terminal(self, expanded=False):
- """Show the expander for the terminal.
-
- Show an expander with a terminal widget which provides a way
- to interact with dpkg
- """
- self._expander.show()
- self._terminal.show()
- self._expander.set_expanded(expanded)
- while gtk.events_pending():
- gtk.main_iteration()
-
- def hide_terminal(self):
- """Hide the expander with the terminal widget."""
- self._expander.hide()
- while gtk.events_pending():
- gtk.main_iteration()
-
- def show(self):
- """Show the Box"""
- gtk.HBox.show(self)
- self._label.show()
- self._progressbar.show()
- while gtk.events_pending():
- gtk.main_iteration()
-
-
-def _test():
- """Test function"""
- import sys
-
- import apt
- from apt.debfile import DebPackage
-
- win = gtk.Window()
- apt_progress = GtkAptProgress()
- win.set_title("GtkAptProgress Demo")
- win.add(apt_progress)
- apt_progress.show()
- win.show()
- cache = apt.cache.Cache(apt_progress.open)
- pkg = cache["xterm"]
- if pkg.is_installed:
- pkg.mark_delete()
- else:
- pkg.mark_install()
- apt_progress.show_terminal(True)
- try:
- cache.commit(apt_progress.acquire, apt_progress.install)
- except Exception as exc:
- print >> sys.stderr, "Exception happened:", exc
- if len(sys.argv) > 1:
- deb = DebPackage(sys.argv[1], cache)
- deb.install(apt_progress.dpkg_install)
- win.connect("destroy", gtk.main_quit)
- gtk.main()
-
-
-if __name__ == "__main__":
- _test()
-
-# vim: ts=4 et sts=4
diff --git a/apt/progress/old.py b/apt/progress/old.py
deleted file mode 100644
index 364cd2ce..00000000
--- a/apt/progress/old.py
+++ /dev/null
@@ -1,259 +0,0 @@
-# progress.py - progress reporting classes
-#
-# 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
-# pylint: disable-msg = C0103
-"""Deprecated progress reporting classes.
-
-This module provides classes for compatibility with python-apt 0.7. They are
-completely deprecated and should not be used anymore.
-"""
-
-
-import os
-import sys
-
-import apt_pkg
-from apt.deprecation import AttributeDeprecatedBy, function_deprecated_by
-import warnings
-from apt.progress import base, text
-
-__all__ = []
-
-
-class OpProgress(base.OpProgress):
- """Abstract class to implement reporting on cache opening."""
-
- def __init__(self):
- base.OpProgress.__init__(self)
- warnings.warn("apt.progress.OpProgress is deprecated.",
- DeprecationWarning, stacklevel=2)
-
- subOp = AttributeDeprecatedBy('subop')
- Op = AttributeDeprecatedBy('op')
-
-
-class OpTextProgress(OpProgress, text.OpProgress):
- """A simple text based cache open reporting class."""
-
- def __init__(self):
- text.OpProgress.__init__(self)
- warnings.warn("apt.progress.OpTextProgress is deprecated.",
- DeprecationWarning, stacklevel=2)
-
-
-class FetchProgress(object):
- """Report the download/fetching progress."""
-
- # download status constants
- (dlDone, dlQueued, dlFailed, dlHit, dlIgnored) = range(5)
- dlStatusStr = {dlDone: "Done", dlQueued: "Queued", dlFailed: "Failed",
- dlHit: "Hit", dlIgnored: "Ignored"}
-
- def __init__(self):
- self.eta = 0.0
- self.percent = 0.0
- # Make checking easier
- self.currentBytes = 0
- self.currentItems = 0
- self.totalBytes = 0
- self.totalItems = 0
- self.currentCPS = 0
- warnings.warn("apt.progress.FetchProgress is deprecated.",
- DeprecationWarning, stacklevel=2)
-
- def start(self):
- """Called when the fetching starts."""
-
- def stop(self):
- """Called when all files have been fetched."""
-
- def updateStatus(self, uri, descr, short_descr, status):
- """Called when the status of an item changes.
-
- This happens eg. when the downloads fails or is completed.
- """
-
- def update_status_full(self, uri, descr, short_descr, status, file_size,
- partial_size):
- """Called when the status of an item changes.
-
- This happens eg. when the downloads fails or is completed. This
- version include information on current filesize and partial size
- """
-
- def pulse(self):
- """Called periodically to update the user interface.
-
- Return True to continue or False to cancel.
- """
- self.percent = (((self.currentBytes + self.currentItems) * 100.0) /
- float(self.totalBytes + self.totalItems))
- if self.currentCPS > 0:
- self.eta = ((self.totalBytes - self.currentBytes) /
- float(self.currentCPS))
- return True
-
- def pulse_items(self, items):
- """Called periodically to update the user interface.
- This function includes details about the items being fetched
- Return True to continue or False to cancel.
-
- """
- self.percent = (((self.currentBytes + self.currentItems) * 100.0) /
- float(self.totalBytes + self.totalItems))
- if self.currentCPS > 0:
- self.eta = ((self.totalBytes - self.currentBytes) /
- float(self.currentCPS))
- return True
-
- def mediaChange(self, medium, drive):
- """react to media change events."""
-
-
-class TextFetchProgress(FetchProgress):
- """ Ready to use progress object for terminal windows """
-
- def __init__(self):
- FetchProgress.__init__(self)
- self.items = {}
-
- def updateStatus(self, uri, descr, short_descr, status):
- """Called when the status of an item changes.
-
- This happens eg. when the downloads fails or is completed.
- """
- if status != self.dlQueued:
- print "\r%s %s" % (self.dlStatusStr[status], descr)
- self.items[uri] = status
-
- def pulse(self):
- """Called periodically to update the user interface.
-
- Return True to continue or False to cancel.
- """
- FetchProgress.pulse(self)
-
- if self.currentCPS > 0:
- s = "[%2.f%%] %sB/s %s" % (self.percent,
- apt_pkg.size_to_str(self.currentCPS),
- apt_pkg.time_to_str(long(self.eta)))
- else:
- s = "%2.f%% [Working]" % (self.percent)
- print "\r%s" % (s),
- sys.stdout.flush()
- return True
-
- def stop(self):
- """Called when all files have been fetched."""
- print "\rDone downloading "
-
- def mediaChange(self, medium, drive):
- """react to media change events."""
- print ("Media change: please insert the disc labeled "
- "'%s' in the drive '%s' and press enter") % (medium, drive)
-
- return raw_input() not in ('c', 'C')
-
-
-class CdromProgress(object):
- """Report the cdrom add progress."""
-
- def __init__(self):
- warnings.warn("apt.progress.CdromProgress is deprecated.",
- DeprecationWarning, stacklevel=2)
-
- def askCdromName(self):
- """Ask for a cdrom name"""
-
- def changeCdrom(self):
- """Change cdrom"""
-
- def update(self, text, current):
- """Update."""
-
-
-class DumbInstallProgress(base.InstallProgress):
- """Report the install progress."""
-
- def __init__(self):
- base.InstallProgress.__init__(self)
- warnings.warn("apt.progress.*InstallProgress are deprecated.",
- DeprecationWarning, stacklevel=2)
-
- def updateInterface(self):
- # *_stream were not available in the old progress reporting classes,
- # create the attributes if they do not exist yet; as they are used
- # in base.InstallProgress.update_interface().
- if hasattr(self, "writefd") and not hasattr(self, "write_stream"):
- self.write_stream = os.fdopen(self.writefd, "w")
- if hasattr(self, "statusfd") and not hasattr(self, "status_stream"):
- self.status_stream = os.fdopen(self.statusfd, "r")
- return base.InstallProgress.update_interface(self)
-
- def update_interface(self):
- return self.updateInterface()
-
- def startUpdate(self):
- return base.InstallProgress.start_update(self)
-
- def start_update(self):
- return self.startUpdate()
-
- def finishUpdate(self):
- return base.InstallProgress.finish_update(self)
-
- def finish_update(self):
- return self.finishUpdate()
-
-
-class InstallProgress(DumbInstallProgress, base.InstallProgress):
- """An InstallProgress that is pretty useful.
-
- It supports the attributes 'percent' 'status' and callbacks for the dpkg
- errors and conffiles and status changes.
- """
-
- selectTimeout = AttributeDeprecatedBy('select_timeout')
-
- def statusChange(self, pkg, percent, status):
- return base.InstallProgress.status_change(self, pkg, percent, status)
-
- def status_change(self, pkg, percent, status):
- return self.statusChange(pkg, percent, status)
-
- def waitChild(self):
- return base.InstallProgress.wait_child(self)
-
- def wait_child(self):
- return self.waitChild()
-
-
-class DpkgInstallProgress(InstallProgress):
- """Progress handler for a local Debian package installation."""
-
- debfile = ""
- debname = ""
-
- def run(self, debfile):
- """Start installing the given Debian package."""
- # Deprecated stuff
- self.debfile = debfile
- self.debname = os.path.basename(debfile).split("_")[0]
- return base.InstallProgress.run(self, debfile)
diff --git a/apt/progress/text.py b/apt/progress/text.py
index c5eec092..d1f87539 100644
--- a/apt/progress/text.py
+++ b/apt/progress/text.py
@@ -15,6 +15,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
"""Progress reporting for text interfaces."""
+from __future__ import print_function
+
import os
import sys
@@ -23,6 +25,11 @@ from apt.progress import base
__all__ = ['AcquireProgress', 'CdromProgress', 'OpProgress']
+if sys.version_info.major < 3:
+ input = raw_input
+else:
+ long = int
+
def _(msg):
"""Translate the message, also try apt if translation is missing."""
@@ -47,7 +54,7 @@ class TextProgress(object):
# Fill remaining stuff with whitespace
if self._width > len(msg):
self._file.write((self._width - len(msg)) * ' ')
- elif maximize: # Needed for OpProgress.
+ elif maximize: # Needed for OpProgress.
self._width = max(self._width, len(msg))
if newline:
self._file.write("\n")
@@ -91,7 +98,7 @@ class AcquireProgress(base.AcquireProgress, TextProgress):
base.AcquireProgress.__init__(self)
self._signal = None
self._width = 80
- self._id = 1
+ self._id = long(1)
def start(self):
"""Start an Acquire progress.
@@ -104,7 +111,7 @@ class AcquireProgress(base.AcquireProgress, TextProgress):
self._signal = signal.signal(signal.SIGWINCH, self._winch)
# Get the window size.
self._winch()
- self._id = 1L
+ self._id = long(1)
def _winch(self, *dummy):
"""Signal handler for window resize signals."""
@@ -114,7 +121,7 @@ class AcquireProgress(base.AcquireProgress, TextProgress):
import struct
buf = fcntl.ioctl(self._file, termios.TIOCGWINSZ, 8 * ' ')
dummy, col, dummy, dummy = struct.unpack('hhhh', buf)
- self._width = col - 1 # 1 for the cursor
+ self._width = col - 1 # 1 for the cursor
def ims_hit(self, item):
"""Called when an item is update (e.g. not modified on the server)."""
@@ -188,8 +195,9 @@ class AcquireProgress(base.AcquireProgress, TextProgress):
# Add the total size and percent
if worker.total_size and not worker.current_item.owner.complete:
- val += "/%sB %i%%" % (apt_pkg.size_to_str(worker.total_size),
- worker.current_size*100.0/worker.total_size)
+ val += "/%sB %i%%" % (
+ apt_pkg.size_to_str(worker.total_size),
+ worker.current_size * 100.0 / worker.total_size)
val += ']'
@@ -214,7 +222,7 @@ class AcquireProgress(base.AcquireProgress, TextProgress):
self._write(_("Media change: please insert the disc labeled\n"
" '%s'\n"
"in the drive '%s' and press enter\n") % (medium, drive))
- return raw_input() not in ('c', 'C')
+ return input() not in ('c', 'C')
def stop(self):
"""Invoked when the Acquire process stops running."""
@@ -239,7 +247,7 @@ class CdromProgress(base.CdromProgress, TextProgress):
self._write(_("Please provide a name for this Disc, such as "
"'Debian 2.1r1 Disk 1'"), False)
try:
- return raw_input(":")
+ return input(":")
except KeyboardInterrupt:
return
@@ -255,6 +263,6 @@ class CdromProgress(base.CdromProgress, TextProgress):
self._write(_("Please insert a Disc in the drive and press enter"),
False)
try:
- return (raw_input() == '')
+ return (input() == '')
except KeyboardInterrupt:
return False
diff --git a/apt/utils.py b/apt/utils.py
index 08140258..948aac92 100644
--- a/apt/utils.py
+++ b/apt/utils.py
@@ -16,6 +16,7 @@
# 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.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+from __future__ import print_function
import os.path
@@ -32,7 +33,7 @@ def get_maintenance_end_date(release_date, m_months):
years = m_months // 12
months = m_months % 12
support_end_year = (release_date.year + years +
- (release_date.month + months)//12)
+ (release_date.month + months) // 12)
support_end_month = (release_date.month + months) % 12
# special case: this happens when e.g. doing 2010-06 + 18 months
if support_end_month == 0:
@@ -49,7 +50,7 @@ def get_release_date_from_release_file(path):
return None
tag = apt_pkg.TagFile(open(path))
section = next(tag)
- if not "Date" in section:
+ if "Date" not in section:
return None
date = section["Date"]
return apt_pkg.str_to_time(date)
@@ -69,8 +70,8 @@ def get_release_filename_for_pkg(cache, pkgname, label, release):
for ver_file, _index in aver.file_list:
#print verFile
if (ver_file.origin == label and
- ver_file.label == label and
- ver_file.archive == release):
+ ver_file.label == label and
+ ver_file.archive == release):
ver = aver
if not ver:
return None
@@ -78,8 +79,8 @@ def get_release_filename_for_pkg(cache, pkgname, label, release):
for metaindex in cache._list.list:
for m in metaindex.index_files:
if (indexfile and
- indexfile.describe == m.describe and
- indexfile.is_trusted):
+ indexfile.describe == m.describe and
+ indexfile.is_trusted):
dirname = apt_pkg.config.find_dir("Dir::State::lists")
name = (apt_pkg.uri_to_filename(metaindex.uri) +
"dists_%s_Release" % metaindex.dist)