summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vogt <michael.vogt@ubuntu.com>2011-05-26 18:01:26 +0200
committerMichael Vogt <michael.vogt@ubuntu.com>2011-05-26 18:01:26 +0200
commit19e2e0f210da3fb4cb87cfe1ddd4bbc6c61d8cd1 (patch)
tree917dd7e06549e3ac7efffdae3c8e9d02788ac81d
parente0b2560ab0fab5716187b7a1f93052373f5cbd23 (diff)
downloadpython-apt-19e2e0f210da3fb4cb87cfe1ddd4bbc6c61d8cd1.tar.gz
merge from debian, omit disable of the 0.7 API
-rw-r--r--apt/cache.py44
-rw-r--r--apt/cdrom.py7
-rw-r--r--apt/debfile.py2
-rw-r--r--apt/package.py50
-rw-r--r--apt/progress/old.py5
-rw-r--r--apt/progress/text.py5
-rw-r--r--aptsources/distinfo.py167
-rw-r--r--aptsources/sourceslist.py87
-rw-r--r--debian/changelog63
-rwxr-xr-xdebian/rules8
-rw-r--r--doc/examples/architecture.py12
-rw-r--r--doc/source/c++/api.rst60
-rw-r--r--doc/source/library/apt.package.rst31
-rw-r--r--doc/source/library/apt_pkg.rst306
-rw-r--r--doc/source/tutorials/apt-cdrom.rst2
-rw-r--r--doc/source/whatsnew/0.8.0.rst38
-rwxr-xr-xpre-build.sh4
-rw-r--r--python/acquire-item.cc10
-rw-r--r--python/acquire.cc14
-rw-r--r--python/apt_pkgmodule.cc106
-rw-r--r--python/apt_pkgmodule.h8
-rw-r--r--python/arfile.cc12
-rw-r--r--python/cache.cc265
-rw-r--r--python/cachegroup.cc188
-rw-r--r--python/configuration.cc6
-rw-r--r--python/depcache.cc12
-rw-r--r--python/generic.h16
-rw-r--r--python/indexfile.cc2
-rw-r--r--python/indexrecords.cc2
-rw-r--r--python/orderlist.cc317
-rw-r--r--python/pkgmanager.cc279
-rw-r--r--python/pkgsrcrecords.cc10
-rw-r--r--python/policy.cc2
-rw-r--r--python/progress.cc60
-rw-r--r--python/python-apt-helpers.cc2
-rw-r--r--python/python-apt.h16
-rw-r--r--python/string.cc14
-rw-r--r--python/tag.cc5
-rw-r--r--python/tarfile.cc14
-rw-r--r--setup.py3
-rw-r--r--tests/test_apt_cache.py31
-rw-r--r--tests/test_cache_invocation.py4
-rw-r--r--tests/test_configuration.py30
-rw-r--r--tests/test_group.py32
-rw-r--r--tests/test_hashes.py7
-rw-r--r--tests/test_progress.py3
46 files changed, 1964 insertions, 397 deletions
diff --git a/apt/cache.py b/apt/cache.py
index bfa41edc..be137b76 100644
--- a/apt/cache.py
+++ b/apt/cache.py
@@ -66,7 +66,11 @@ class Cache(object):
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)
if memonly:
# force apt to build its caches in memory
apt_pkg.config.set("Dir::Cache::pkgcache", "")
@@ -87,6 +91,11 @@ class Cache(object):
# recognized (LP: #320665)
apt_pkg.init_system()
self.open(progress)
+
+
+ def _inc_changes_count(self):
+ """Increase the number of changes"""
+ self._changes_count += 1
def _check_and_create_required_dirs(self, rootdir):
"""
@@ -107,7 +116,7 @@ class Cache(object):
os.makedirs(rootdir + d)
for f in files:
if not os.path.exists(rootdir + f):
- open(rootdir + f, "w")
+ open(rootdir + f, "w").close()
def _run_callbacks(self, name):
""" internal helper to run a callback """
@@ -288,6 +297,30 @@ class Cache(object):
finally:
os.close(lock)
+ def fetch_archives(self, progress=None, fetcher=None):
+ """Fetch the archives for all packages marked for install/upgrade.
+
+ You can specify either an :class:`apt.progress.base.AcquireProgress()`
+ object for the parameter *progress*, or specify an already
+ existing :class:`apt_pkg.Acquire` object for the parameter *fetcher*.
+
+ The return value of the function is undefined. If an error occured,
+ an exception of type :class:`FetchFailedException` or
+ :class:`FetchCancelledException` is raised.
+
+ .. versionadded:: 0.8.0
+ """
+ if progress is not None and fetcher is not None:
+ raise ValueError("Takes a progress or a an Acquire object")
+ if progress is None:
+ progress = apt.progress.text.AcquireProgress()
+ if fetcher is None:
+ fetcher = apt_pkg.Acquire(progress)
+
+
+ return self._fetch_archives(fetcher,
+ apt_pkg.PackageManager(self._depcache))
+
def is_virtual_package(self, pkgname):
"""Return whether the package is a virtual package."""
try:
@@ -339,6 +372,10 @@ class Cache(object):
raise_on_error=True, sources_list=None):
"""Run the equivalent of apt-get update.
+ You probably want to call open() afterwards, in order to utilise the
+ new cache. Otherwise, the old cache will be used which can lead to
+ strange bugs.
+
The first parameter *fetch_progress* may be set to an instance of
apt.progress.FetchProgress, the default is apt.progress.FetchProgress()
.
@@ -548,6 +585,7 @@ class ProblemResolver(object):
def __init__(self, cache):
self._resolver = apt_pkg.ProblemResolver(cache._depcache)
+ self._cache = cache
def clear(self, package):
"""Reset the package to the default state."""
@@ -567,11 +605,15 @@ class ProblemResolver(object):
def resolve(self):
"""Resolve dependencies, try to remove packages where needed."""
+ self._cache.cache_pre_change()
self._resolver.resolve()
+ self._cache.cache_post_change()
def resolve_by_keep(self):
"""Resolve dependencies, do not try to remove packages."""
+ self._cache.cache_pre_change()
self._resolver.resolve_by_keep()
+ self._cache.cache_post_change()
# ----------------------------- experimental interface
diff --git a/apt/cdrom.py b/apt/cdrom.py
index 01caa12f..9688de9e 100644
--- a/apt/cdrom.py
+++ b/apt/cdrom.py
@@ -79,9 +79,10 @@ class Cdrom(apt_pkg.Cdrom):
src.append(apt_pkg.config.find_file("Dir::Etc::sourcelist"))
# Check each file
for fname in src:
- for line in open(fname):
- if not line.lstrip().startswith("#") and cd_id in line:
- return True
+ with open(fname) as fobj:
+ for line in fobj:
+ if not line.lstrip().startswith("#") and cd_id in line:
+ return True
return False
if apt_pkg._COMPAT_0_7:
diff --git a/apt/debfile.py b/apt/debfile.py
index fb4312a1..d0f41def 100644
--- a/apt/debfile.py
+++ b/apt/debfile.py
@@ -64,7 +64,7 @@ class DebPackage(object):
self._installed_conflicts = set()
self._failure_string = ""
self.filename = filename
- self._debfile = apt_inst.DebFile(open(self.filename))
+ self._debfile = apt_inst.DebFile(self.filename)
control = self._debfile.control.extractdata("control")
self._sections = apt_pkg.TagSection(control)
self.pkgname = self._sections["Package"]
diff --git a/apt/package.py b/apt/package.py
index d7d5d167..14e80594 100644
--- a/apt/package.py
+++ b/apt/package.py
@@ -50,9 +50,9 @@ __all__ = ('BaseDependency', 'Dependency', 'Origin', 'Package', 'Record',
def _file_is_same(path, size, md5):
"""Return ``True`` if the file is the same."""
- if (os.path.exists(path) and os.path.getsize(path) == size and
- apt_pkg.md5sum(open(path)) == md5):
- return True
+ if os.path.exists(path) and os.path.getsize(path) == size:
+ with open(path) as fobj:
+ return apt_pkg.md5sum(fobj) == md5
class FetchError(Exception):
@@ -162,10 +162,23 @@ class Origin(object):
class Record(Mapping):
- """Represent a pkgRecord.
+ """Record in a Packages file
+
+ Represent a record as stored in a Packages file. You can use this like
+ a dictionary mapping the field names of the record to their values::
+
+ >>> record = Record("Package: python-apt\\nVersion: 0.8.0\\n\\n")
+ >>> record["Package"]
+ 'python-apt'
+ >>> record["Version"]
+ '0.8.0'
+
+ For example, to get the tasks of a package from a cache, you could do::
+
+ package.candidate.record["Tasks"].split()
+
+ Of course, you can also use the :attr:`Version.tasks` property.
- It can be accessed like a dictionary and can also give the original package
- record if accessed as a string.
"""
def __init__(self, record_str):
@@ -209,6 +222,9 @@ class Record(Mapping):
class Version(object):
"""Representation of a package version.
+ The Version class contains all information related to a
+ specific package version.
+
.. versionadded:: 0.7.9
"""
@@ -393,7 +409,11 @@ class Version(object):
@property
def record(self):
- """Return a Record() object for this version."""
+ """Return a Record() object for this version.
+
+ Return a Record() object for this version which provides access
+ to the raw attributes of the candidate version
+ """
return Record(self._records.record)
def get_dependencies(self, *types):
@@ -474,6 +494,16 @@ class Version(object):
"""
return self._records.sha256_hash
+ @property
+ def tasks(self):
+ """Get the tasks of the package.
+
+ A set of the names of the tasks this package belongs to.
+
+ .. versionadded:: 0.8.0
+ """
+ return set(self.record["Task"].split())
+
def _uris(self):
"""Return an iterator over all available urls.
@@ -994,11 +1024,8 @@ class Package(object):
"""
path = "/var/lib/dpkg/info/%s.list" % self.name
try:
- file_list = open(path, "rb")
- try:
+ with open(path, "rb") as file_list:
return file_list.read().decode("utf-8").split(u"\n")
- finally:
- file_list.close()
except EnvironmentError:
return []
@@ -1104,6 +1131,7 @@ class Package(object):
# Check if the download was canceled
if cancel_lock and cancel_lock.isSet():
return u""
+ # FIXME: python3.2: Should be closed manually
changelog_file = urllib2.urlopen(uri)
# do only get the lines that are new
changelog = u""
diff --git a/apt/progress/old.py b/apt/progress/old.py
index 4bd79f2e..364cd2ce 100644
--- a/apt/progress/old.py
+++ b/apt/progress/old.py
@@ -149,10 +149,11 @@ class TextFetchProgress(FetchProgress):
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(int(self.currentCPS)),
- apt_pkg.time_to_str(int(self.eta)))
+ 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),
diff --git a/apt/progress/text.py b/apt/progress/text.py
index d777837c..c5eec092 100644
--- a/apt/progress/text.py
+++ b/apt/progress/text.py
@@ -157,11 +157,10 @@ class AcquireProgress(base.AcquireProgress, TextProgress):
shown = False
tval = '%i%%' % percent
-
end = ""
if self.current_cps:
- eta = int(float(self.total_bytes - self.current_bytes) /
- self.current_cps)
+ eta = long(float(self.total_bytes - self.current_bytes) /
+ self.current_cps)
end = " %sB/s %s" % (apt_pkg.size_to_str(self.current_cps),
apt_pkg.time_to_str(eta))
diff --git a/aptsources/distinfo.py b/aptsources/distinfo.py
index a69f944a..249985e7 100644
--- a/aptsources/distinfo.py
+++ b/aptsources/distinfo.py
@@ -176,89 +176,90 @@ class DistInfo(object):
map_mirror_sets = {}
dist_fname = "%s/%s.info" % (base_dir, dist)
- dist_file = open(dist_fname)
- if not dist_file:
- return
- template = None
- component = None
- for line in dist_file:
- tokens = line.split(':', 1)
- if len(tokens) < 2:
- continue
- field = tokens[0].strip()
- value = tokens[1].strip()
- if field == 'ChangelogURI':
- self.changelogs_uri = _(value)
- elif field == 'MetaReleaseURI':
- self.metarelease_uri = value
- elif field == 'Suite':
- self.finish_template(template, component)
- component=None
- template = Template()
- template.name = value
- template.distribution = dist
- template.match_name = "^%s$" % value
- elif field == 'MatchName':
- template.match_name = value
- elif field == 'ParentSuite':
- template.child = True
- for nanny in self.templates:
- # look for parent and add back ref to it
- if nanny.name == value:
- template.parents.append(nanny)
- nanny.children.append(template)
- elif field == 'Available':
- template.available = apt_pkg.string_to_bool(value)
- elif field == 'Official':
- template.official = apt_pkg.string_to_bool(value)
- elif field == 'RepositoryType':
- template.type = value
- elif field == 'BaseURI' and not template.base_uri:
- template.base_uri = value
- elif field == 'BaseURI-%s' % self.arch:
- template.base_uri = value
- elif field == 'MatchURI' and not template.match_uri:
- template.match_uri = value
- elif field == 'MatchURI-%s' % self.arch:
- template.match_uri = value
- elif (field == 'MirrorsFile' or
- field == 'MirrorsFile-%s' % self.arch):
- # Make the path absolute.
- value = os.path.isabs(value) and value or \
- os.path.abspath(os.path.join(base_dir, value))
- if value not in map_mirror_sets:
- mirror_set = {}
- try:
- mirror_data = filter(match_mirror_line.match,
- [x.strip() for x in open(value)])
- except Exception:
- logging.warn("Failed to read mirror file")
- mirror_data = []
- for line in mirror_data:
- if line.startswith("#LOC:"):
- location = match_loc.sub(r"\1", line)
- continue
- (proto, hostname, dir) = split_url(line)
- if hostname in mirror_set:
- mirror_set[hostname].add_repository(proto, dir)
- else:
- mirror_set[hostname] = Mirror(
- proto, hostname, dir, location)
- map_mirror_sets[value] = mirror_set
- template.mirror_set = map_mirror_sets[value]
- elif field == 'Description':
- template.description = _(value)
- elif field == 'Component':
- if component and not template.has_component(component.name):
- template.components.append(component)
- component = Component(value)
- elif field == 'CompDescription':
- component.set_description(_(value))
- elif field == 'CompDescriptionLong':
- component.set_description_long(_(value))
- self.finish_template(template, component)
- template=None
- component=None
+ with open(dist_fname) as dist_file:
+ template = None
+ component = None
+ for line in dist_file:
+ tokens = line.split(':', 1)
+ if len(tokens) < 2:
+ continue
+ field = tokens[0].strip()
+ value = tokens[1].strip()
+ if field == 'ChangelogURI':
+ self.changelogs_uri = _(value)
+ elif field == 'MetaReleaseURI':
+ self.metarelease_uri = value
+ elif field == 'Suite':
+ self.finish_template(template, component)
+ component=None
+ template = Template()
+ template.name = value
+ template.distribution = dist
+ template.match_name = "^%s$" % value
+ elif field == 'MatchName':
+ template.match_name = value
+ elif field == 'ParentSuite':
+ template.child = True
+ for nanny in self.templates:
+ # look for parent and add back ref to it
+ if nanny.name == value:
+ template.parents.append(nanny)
+ nanny.children.append(template)
+ elif field == 'Available':
+ template.available = apt_pkg.string_to_bool(value)
+ elif field == 'Official':
+ template.official = apt_pkg.string_to_bool(value)
+ elif field == 'RepositoryType':
+ template.type = value
+ elif field == 'BaseURI' and not template.base_uri:
+ template.base_uri = value
+ elif field == 'BaseURI-%s' % self.arch:
+ template.base_uri = value
+ elif field == 'MatchURI' and not template.match_uri:
+ template.match_uri = value
+ elif field == 'MatchURI-%s' % self.arch:
+ template.match_uri = value
+ elif (field == 'MirrorsFile' or
+ field == 'MirrorsFile-%s' % self.arch):
+ # Make the path absolute.
+ value = os.path.isabs(value) and value or \
+ os.path.abspath(os.path.join(base_dir, value))
+ if value not in map_mirror_sets:
+ mirror_set = {}
+ try:
+ with open(value) as value_f:
+ mirror_data = filter(match_mirror_line.match,
+ [x.strip() for x in
+ value_f])
+ except Exception:
+ print "WARNING: Failed to read mirror file"
+ mirror_data = []
+ for line in mirror_data:
+ if line.startswith("#LOC:"):
+ location = match_loc.sub(r"\1", line)
+ continue
+ (proto, hostname, dir) = split_url(line)
+ if hostname in mirror_set:
+ mirror_set[hostname].add_repository(proto, dir)
+ else:
+ mirror_set[hostname] = Mirror(
+ proto, hostname, dir, location)
+ map_mirror_sets[value] = mirror_set
+ template.mirror_set = map_mirror_sets[value]
+ elif field == 'Description':
+ template.description = _(value)
+ elif field == 'Component':
+ if (component and not
+ template.has_component(component.name)):
+ template.components.append(component)
+ component = Component(value)
+ elif field == 'CompDescription':
+ component.set_description(_(value))
+ elif field == 'CompDescriptionLong':
+ component.set_description_long(_(value))
+ self.finish_template(template, component)
+ template=None
+ component=None
def finish_template(self, template, component):
" finish the current tempalte "
diff --git a/aptsources/sourceslist.py b/aptsources/sourceslist.py
index 04f6a5a7..b85e6947 100644
--- a/aptsources/sourceslist.py
+++ b/aptsources/sourceslist.py
@@ -1,4 +1,4 @@
-# aptsource.py - Provide an abstraction of the sources.list
+# sourceslist.py - Provide an abstraction of the sources.list
#
# Copyright (c) 2004-2009 Canonical Ltd.
# Copyright (c) 2004 Michiel Sikkes
@@ -276,6 +276,12 @@ class SourcesList(object):
yield entry
raise StopIteration
+ def __find(self, *predicates, **attrs):
+ for source in self.list:
+ if (all(getattr(source, key) == attrs[key] for key in attrs) and
+ all(predicate(source) for predicate in predicates)):
+ yield source
+
def add(self, type, uri, dist, orig_comps, comment="", pos=-1, file=None, architectures=[]):
"""
Add a new source to the sources.list.
@@ -287,39 +293,32 @@ class SourcesList(object):
# create a working copy of the component list so that
# we can modify it later
comps = orig_comps[:]
+ sources = self.__find(lambda s: set(s.architectures) == architectures,
+ disabled=False, invalid=False, type=type, uri=uri,
+ dist=dist)
# check if we have this source already in the sources.list
- for source in self.list:
- if not source.disabled and not source.invalid and \
- source.type == type and uri == source.uri and \
- source.dist == dist and \
- set(source.architectures) == architectures:
- for new_comp in comps:
- if new_comp in source.comps:
- # we have this component already, delete it
- # from the new_comps list
- del comps[comps.index(new_comp)]
- if len(comps) == 0:
- return source
- for source in self.list:
+ for source in sources:
+ for new_comp in comps:
+ if new_comp in source.comps:
+ # we have this component already, delete it
+ # from the new_comps list
+ del comps[comps.index(new_comp)]
+ if len(comps) == 0:
+ return source
+
+ sources = self.__find(lambda s: set(s.architectures) == architectures,
+ invalid=False, type=type, uri=uri, dist=dist)
+
+ for source in sources:
# if there is a repo with the same (type, uri, dist) just add the
# components
- if not source.disabled and not source.invalid and \
- source.type == type and uri == source.uri and \
- source.dist == dist and \
- set(source.architectures) == architectures:
- comps = uniq(source.comps + comps)
- source.comps = comps
- return source
- # if there is a corresponding repo which is disabled, enable it
- elif source.disabled and not source.invalid and \
- source.type == type and uri == source.uri and \
- set(source.architectures) == architectures and \
- source.dist == dist and \
- len(set(source.comps) & set(comps)) == len(comps):
+ if source.disabled and set(source.comps) == comps:
source.disabled = False
return source
+ elif not source.disabled:
+ source.comps = uniq(source.comps + comps)
+ return source
# there isn't any matching source, so create a new line and parse it
-
line = type
if architectures:
line += " [arch=%s]" % ",".join(architectures)
@@ -370,15 +369,12 @@ class SourcesList(object):
def load(self, file):
""" (re)load the current sources """
try:
- f = open(file, "r")
- lines = f.readlines()
- for line in lines:
- source = SourceEntry(line, file)
- self.list.append(source)
+ with open(file, "r") as f:
+ for line in f:
+ source = SourceEntry(line, file)
+ self.list.append(source)
except:
- logging.error("could not open file '%s'" % file)
- else:
- f.close()
+ print "could not open file '%s'" % file
def save(self):
""" save the current sources """
@@ -390,14 +386,19 @@ class SourcesList(object):
"## See sources.list(5) for more information, especialy\n"
"# Remember that you can only use http, ftp or file URIs\n"
"# CDROMs are managed through the apt-cdrom tool.\n")
- open(path, "w").write(header)
+
+ with open(path, "w") as f:
+ f.write(header)
return
- for source in self.list:
- if source.file not in files:
- files[source.file] = open(source.file, "w")
- files[source.file].write(source.str())
- for f in files:
- files[f].close()
+
+ try:
+ for source in self.list:
+ if source.file not in files:
+ files[source.file] = open(source.file, "w")
+ files[source.file].write(source.str())
+ finally:
+ for f in files:
+ files[f].close()
def check_for_relations(self, sources_list):
"""get all parent and child channels in the sources list"""
diff --git a/debian/changelog b/debian/changelog
index 11e8819d..edd0081f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,66 @@
+python-apt (0.8.0~exp4ubuntu1) oneiric; urgency=low
+
+ * Merged from debian/experimental, remaining changes:
+ - updated mirror list
+ - do not disable 0.7 compat API yet
+
+ -- Michael Vogt <michael.vogt@ubuntu.com> Tue, 24 May 2011 10:08:56 +0200
+
+python-apt (0.8.0~exp4) experimental; urgency=low
+
+ * apt_pkg: Add OrderList, wanted for mancoosi (Closes: #623485)
+ * apt_pkg: Add subclassing fun to PackageManager, for #623485 as well
+ * apt.cache: Emit change signals in ProblemResolver
+ * apt.Cache: Add a _changes_count member for later use
+
+ -- Julian Andres Klode <jak@debian.org> Fri, 29 Apr 2011 13:57:30 +0200
+
+python-apt (0.8.0~exp3) experimental; urgency=low
+
+ [ Stéphane Graber ]
+ * Update enable_component to also apply to -src entries (LP: #758732)
+
+ [ Julian Andres Klode ]
+ * apt_pkg: Add apt_pkg.Version.multi_arch and friends
+
+ -- Julian Andres Klode <jak@debian.org> Thu, 21 Apr 2011 15:33:38 +0200
+
+python-apt (0.8.0~exp2) experimental; urgency=low
+
+ * aptsources: Parse multi-arch sources.list files correctly
+ * aptsources: Allow insertion of new multi-arch entries
+ * aptsources: Various cleanup work
+ * all: Fix all instances of ResourceWarning about unclosed files
+ * tests/test_apt_cache.py: Use assertTrue() instead of assert_()
+ * apt_pkg: Raise error when parse_commandline gets empty argv (LP: #707416)
+ * apt_pkg: Fix time_to_str, time_rfc1123 to accept more correct values
+ (time_to_str accepts unsigned long, time_rfc1123 long long, y2k31-correct).
+ * apt.progress: Use long for ETA, natural type for size (LP: #377375)
+ * aptsources/sourceslist.py: s/aptsource.py/sourceslist.py/ (LP: #309603)
+ * doc/examples: Add example on how to get architecture names (LP: #194374)
+ * apt_pkg: Fix unsigned/long-vs-int issues (LP: #610820)
+ * apt.cache: Document that update() may need an open() (Closes: #622342)
+ * apt.cache: Add a fetch_archives() method (Closes: #622347)
+ * doc: Fix a minor formatting error, patch by Jakub Wilk (Closes: #608914)
+ * apt.package: Add 'tasks' to Version, improve doc (Closes: #619574)
+ * doc: Fix documentation of BaseDependency.relation (Closes: #607031)
+
+ -- Julian Andres Klode <jak@debian.org> Tue, 12 Apr 2011 15:25:38 +0200
+
+python-apt (0.8.0~exp1) experimental; urgency=low
+
+ * Disable the old-style API, and break all packages using it
+ * Add an 'is_multi_arch' attribute to apt_pkg.Cache
+ * Add apt_pkg.Group class, wrapping pkgCache::GrpIterator
+ * Change apt_pkg.Cache() so that passing None for 'progress' results in
+ no progress output
+ * Support (name, arch) tuples in apt_pkg.Cache mappings, wrapping
+ FindPkg() with two string parameters.
+ * Introduce apt_pkg.Cache.groups and apt_pkg.Cache.group_count
+ * Fix debian/rules to work correctly with tilde in version number
+
+ -- Julian Andres Klode <jak@debian.org> Tue, 05 Apr 2011 16:21:45 +0200
+
python-apt (0.7.100.3ubuntu7) oneiric; urgency=low
* data/templates/Ubuntu.info.in:
diff --git a/debian/rules b/debian/rules
index 5428375d..a85d1eb2 100755
--- a/debian/rules
+++ b/debian/rules
@@ -2,8 +2,8 @@
# Should be include-links, but that somehow fails.
export DEBVER=$(shell dpkg-parsechangelog | sed -n -e 's/^Version: //p')
export CFLAGS=-Wno-write-strings -DCOMPAT_0_7
-export PATH :=$(CURDIR)/utils:$(PATH)
-export SHELL = env PATH=$(PATH) sh
+export PATH := $(CURDIR)/utils:$(PATH)
+export pyversions := $(CURDIR)/utils/pyversions
%:
dh --with python2,python3 $@
@@ -28,14 +28,14 @@ override_dh_installdocs:
override_dh_strip:
dh_strip -p python-apt --dbg-package=python-apt-dbg
dh_strip -p python3-apt --dbg-package=python3-apt-dbg
-
+
override_dh_compress:
dh_compress -X.js -X_static/* -X _sources/* -X_sources/*/* -X.inv
# We ignore failures on hurd, since its locking is broken
override_dh_auto_test:
ifeq (,$(findstring nocheck, $(DEB_BUILD_OPTIONS)))
- set -e; for python in $(shell pyversions -r); do \
+ set -e; for python in $(shell $(pyversions) -r); do \
$$python tests/test_all.py -q || [ "$(DEB_BUILD_ARCH_OS)" = "hurd" ]; \
done;
else
diff --git a/doc/examples/architecture.py b/doc/examples/architecture.py
new file mode 100644
index 00000000..75afb2d1
--- /dev/null
+++ b/doc/examples/architecture.py
@@ -0,0 +1,12 @@
+import apt_pkg
+
+
+def main():
+ apt_pkg.init_config()
+
+ print "Native architecture:", apt_pkg.config["APT::Architecture"]
+ print "All architectures:", apt_pkg.config.value_list("APT::Architectures")
+
+
+if __name__ == '__main__':
+ main()
diff --git a/doc/source/c++/api.rst b/doc/source/c++/api.rst
index 97ab24d1..63ed1599 100644
--- a/doc/source/c++/api.rst
+++ b/doc/source/c++/api.rst
@@ -389,6 +389,38 @@ Description (pkgCache::DescIterator)
Return the :ctype:`pkgCache::DescIterator` reference contained in the
Python object *object*.
+
+Group (pkgCache::GrpIterator)
+----------------------------------
+.. versionadded:: 0.8.0
+
+.. cvar:: PyTypeObject PyGroup_Type
+
+ The type object for :class:`apt_pkg.Group` objects.
+
+.. cfunction:: int PyGroup_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Group` object, or
+ a subclass thereof.
+
+.. cfunction:: int PyGroup_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Group` object
+ and no subclass thereof.
+
+.. cfunction:: PyObject* PyGroup_FromCpp(pkgCache::GrpIterator &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Group` object from the :ctype:`pkgCache::GrpIterator`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should be
+ a PyObject of the type :cdata:`PyCache_Type`.
+
+.. cfunction:: pkgCache::GrpIterator& PyGroup_ToCpp(PyObject *object)
+
+ Return the :ctype:`pkgCache::GrpIterator` reference contained in the
+ Python object *object*.
+
Hashes (Hashes)
----------------------------------
.. cvar:: PyTypeObject PyHashes_Type
@@ -590,6 +622,34 @@ IndexFile (pkgIndexFile)
Return the :ctype:`pkgIndexFile` pointer contained in the Python object
*object*.
+OrderList (pkgOrderList)
+---------------------------
+.. cvar:: PyTypeObject PyOrderList_Type
+
+ The type object for :class:`apt_pkg.OrderList` objects.
+
+.. cfunction:: int PyOrderList_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.OrderList` object, or
+ a subclass thereof.
+
+.. cfunction:: int PyOrderList_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.OrderList` object
+ and no subclass thereof.
+
+.. cfunction:: PyObject* PyOrderList_FromCpp(pkgOrderList *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.OrderList` object from the :ctype:`pkgOrderList`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The owner must be a
+ :class:`apt_pkg.DepCache` object.
+
+.. cfunction:: pkgOrderList* PyOrderList_ToCpp(PyObject *object)
+
+ Return the :ctype:`pkgOrderList` pointer contained in the Python object
+ *object*.
PackageManager (pkgPackageManager)
----------------------------------
diff --git a/doc/source/library/apt.package.rst b/doc/source/library/apt.package.rst
index 4b143b8a..01a26973 100644
--- a/doc/source/library/apt.package.rst
+++ b/doc/source/library/apt.package.rst
@@ -34,7 +34,7 @@ Dependency Information
.. attribute:: relation
- The relation (>>,>=,==,<<,<=,)
+ The relation (>,>=,==,<,<=,)
.. attribute:: version
@@ -90,6 +90,35 @@ Origin Information
it provides a GPG-signed Release file and the GPG-key used is in the
keyring used by apt (see apt-key).
+
+
+The Record class
+-----------------
+.. autoclass:: Record
+ :members:
+
+ .. note::
+ .. versionchanged:: 0.7.100
+ This class is a subclass of :class:`collections.Mapping` when used
+ in Python 2.6 or newer.
+
+ .. describe:: record[name]
+
+ Return the value of the field with the name *name*.
+
+ .. describe:: name in record
+
+ Return whether a field *name* exists in record.
+
+ .. describe:: len(record)
+
+ The number of fields in the record
+
+ .. describe:: str(record)
+
+ Display the record as a string
+
+
Examples
---------
.. code-block:: python
diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst
index 426cb97e..81f2d408 100644
--- a/doc/source/library/apt_pkg.rst
+++ b/doc/source/library/apt_pkg.rst
@@ -40,17 +40,43 @@ Working with the cache
The constructor takes an optional argument which must be a subclass of
:class:`apt.progress.base.OpProgress`. This object will then be used to
display information during the cache opening process (or possible creation
- of the cache).
+ of the cache). It may also be ``None``, in which case no progress will
+ be emitted. If not given, progress will be printed to standard output.
+
+ .. note::
+
+ The cache supports colon-seperated name:architecture pairs. For
+ normal architectures, they are equal to a (name, architecture)
+ tuple. For the the "any" architecture behavior is different, as
+ "name:any" is equivalent to ("name:any", "any"). This is done so
+ that "name:any" matches all packages with that name which have
+ Multi-Arch: allowed set.
.. describe:: cache[pkgname]
Return the :class:`Package()` object for the package name given by
- *pkgname*.
+ *pkgname*. If *pkgname* includes a colon, the part after the colon
+ is used as the architecture.
+
+ .. describe:: cache[name, architecture]
+
+ Return the :class:`Package()` object for the package with the given
+ name and architecture.
+
+ .. versionadded: 0.8.0
.. describe:: pkgname in cache
Check whether a package with the name given by *pkgname* exists in
- the cache.
+ the cache for the native architecture. If *pkgname* includes a
+ colon, the part after the colon is used as the architecture.
+
+ .. describe:: (name, architecture) in cache
+
+ Check whether a package with the given name and architecture exists
+ in the cache.
+
+ .. versionadded: 0.8.0
.. method:: update(progress, sources [, pulse_interval]) -> bool
@@ -73,6 +99,44 @@ Working with the cache
A list of all :class:`PackageFile` objects stored in the cache.
+ .. attribute:: group_count
+
+ The number of groups in the cache.
+
+ .. versionadded: 0.8.0
+
+ .. attribute:: groups
+
+ A sequence of :class:`Group` objects, implemented as a
+ :class:`GroupList` object.
+
+ .. versionadded: 0.8.0
+
+ .. class:: GroupList
+
+ A simple sequence-like object which only provides a length and
+ an implementation of ``__getitem__`` for accessing groups at
+ a certain index. Apart from being iterable, it can be used in
+ the following ways:
+
+ .. versionadded: 0.8.0
+
+ .. describe:: list[index]
+
+ Get the :class:`Group` object for the group at the position
+ given by *index* in the GroupList *list*.
+
+ .. describe:: len(list)
+
+ Return the length of the GroupList object *list*.
+
+
+ .. attribute:: is_multi_arch
+
+ An attribute determining whether the cache supports multi-arch.
+
+ .. versionadded: 0.8.0
+
.. attribute:: package_count
The total number of packages available in the cache. This value is
@@ -358,6 +422,158 @@ Installing with :class:`PackageManager`
A constant for checking whether the the result of the call to
:meth:`do_install` is 'incomplete'.
+
+ All instances of this class also support the following methods:
+
+ .. note::
+
+ This methods are provided mainly for subclassing purposes
+ and should not be used in most programs. This class is a
+ subclass of an internal :class:`_PackageManager` which does
+ not provide that methods. As the public C++ API creates such
+ an object without those methods, you should not rely on those
+ methods to be available unless you used the constructor of
+ :class:`PackageManager` to create the object.
+
+ .. method:: configure(pkg: Package) -> bool
+
+ Notify the package manager that the :class:`Package` given
+ by *pkg* is to be configured. Must return a ``True`` value
+ or ``None`` to continue, or a value which is ``False`` if
+ evaluated as boolean to abort.
+
+ .. versionadded:: 0.8.0
+
+ .. method:: install(pkg: Package, filename: str) -> bool
+
+ Notify the package manager that the :class:`Package` given
+ by *pkg* is to be installed from the .deb located at
+ *filename*. Must return a ``True`` value or ``None`` to
+ continue, or a value which is ``False`` if evaluated as
+ boolean to abort.
+
+
+ .. versionadded:: 0.8.0
+
+ .. method:: remove(pkg: Package, purge: bool) -> bool
+
+ Notify the package manager that the :class:`Package` given
+ by *pkg* is to be removed. If *purge* is ``True``, the package
+ shall be purged. Must return a ``True`` value or ``None`` to
+ continue, or a value which is ``False`` if evaluated as boolean
+ to abort.
+
+
+ .. versionadded:: 0.8.0
+
+ .. method:: go(status_fd: int) -> bool
+
+ Start dpkg, writing status information to the file descriptor
+ given by *status_fd*. Must return a ``True`` value or ``None`` to
+ continue, or a value which is ``False`` if evaluated as boolean
+ to abort.
+
+ .. versionadded:: 0.8.0
+
+ .. method:: reset()
+
+ Reset the package manager for a new round.
+
+ .. versionadded:: 0.8.0
+
+
+Installation ordering with :class:`OrderList`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. class:: OrderList(depcache: DepCache)
+
+ Represent a :ctype:`pkgOrderList`, used for installation
+ ordering. This class provides several methods and attributes,
+ is complicated and should not be used by normal programs.
+
+ .. versionadded:: 0.8.0
+
+ This class is a sequence and supports the following operations:
+
+ .. describe:: list[index]
+
+ Get the package at the given index in the list. Negative
+ index is supported.
+
+ .. describe:: len(list)
+
+ The length of the list.
+
+ It also supports the append() method from :class:`list`:
+
+ .. method:: append(pkg: Package)
+
+ Append a new package to the end of the list. Please note that
+ you may not append a package twice, as only as much packages
+ as in the cache can be added.
+
+ The class also defines several specific attributes and methods,
+ to be described hereinafter.
+
+ .. method:: score(pkg: Package)
+
+ Return the score of the package. Packages are basically
+ ordered by descending score.
+
+ This class allows flags to be set on packages. Those flags are:
+
+ .. attribute:: FLAG_ADDED
+ .. attribute:: FLAG_ADD_PENDING
+ .. attribute:: FLAG_IMMEDIATE
+ .. attribute:: FLAG_LOOP
+ .. attribute:: FLAG_UNPACKED
+ .. attribute:: FLAG_CONFIGURED
+ .. attribute:: FLAG_REMOVED
+ .. attribute:: FLAG_STATES_MASK
+
+ Same as ``FLAG_UNPACKED | FLAG_CONFIGURED | FLAG_REMOVED``
+
+ .. attribute:: FLAG_IN_LIST
+ .. attribute:: FLAG_AFTER
+
+ The methods to work with those flags are:
+
+ .. method:: flag(pkg: Package, flag: int[, unset_flags: int])
+
+ Flag a package. Sets the flags given in *flag* and unsets
+ any flags given in *unset_flags*.
+
+ .. method:: is_flag(pkg: Package, flag: int)
+
+ Check whether the flags in *flag* are set for the package.
+
+ .. method:: wipe_flags(flags: int)
+
+ Remove the flags in *flags* from all packages.
+
+ .. method:: is_missing(pkg: Package)
+
+ Check if the package is missing (not really usable right now)
+
+ .. method:: is_now(pkg: Package)
+
+ Check if the package is flagged for any state but removal.
+
+ The following methods for ordering are provided:
+
+ .. method:: order_critical()
+
+ Order the packages for critical unpacking; that is, only
+ respect pre-dependencies.
+
+ .. method:: order_unpack()
+
+ Order the packages for unpacking, repecting Pre-Depends and
+ Conflicts.
+
+ .. method:: order_configure()
+
+ Order the packages for configuration, respecting Depends.
Improve performance with :class:`ActionGroup`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -432,6 +648,47 @@ Resolving Dependencies with :class:`ProblemResolver`
Try to resolve the problems without installing or removing packages.
+:class:`Group` of packages with the same name
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. class:: Group(cache: Cache, name: str)
+
+ .. versionadded:: 0.8.0
+
+ A collection of packages in which all packages have the same name. Groups
+ are used in multi-arch environments, where two or more packages have the
+ same name, but different architectures.
+
+ Group objects provide the following parts for sequential access:
+
+ .. describe:: group[index]
+
+ Get the package at the given **index** in the group.
+
+ .. note::
+ Groups are internally implemented using a linked list. The object
+ keeps a pointer to the current object and the first object, so
+ access to the first element, or accesses in order have a
+ complexity of O(1). Random-access complexity is ranges from
+ O(1) to O(n).
+
+ Group objects also provide special methods to find single packages:
+
+ .. method:: find_package(architecture: str) -> Package
+
+ Find a package with the groups name and the architecture given
+ in the argument *architecture*. If no such package exists, return
+ ``None``.
+
+ .. method:: find_preferred_package(prefer_nonvirtual: bool = True) -> Package
+
+ Find the preferred package. This is the package of the native
+ architecture (specified in ``APT::Architecture``) if available,
+ or the package from the first foreign architecture. If no package
+ could be found, return ``None``
+
+ If **prefer_nonvirtual** is ``True``, the preferred package
+ will be a non-virtual package, if one exists.
+
:class:`Package` information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -653,6 +910,49 @@ Example:
.. attribute:: installed_size
The size of the package (in kilobytes), when unpacked on the disk.
+
+ .. attribute:: multi_arch
+
+ The multi-arch state of the package. Can be one of the following
+ attributes.
+
+ .. attribute:: MULTI_ARCH_NONE
+
+ No multi-arch
+
+ .. attribute:: MULTI_ARCH_ALL
+
+ An ``Architecture: all`` package
+
+
+ .. attribute:: MULTI_ARCH_FOREIGN
+
+ Can satisfy dependencies of foreign-architecture
+ packages
+
+ .. attribute:: MULTI_ARCH_ALL_FOREIGN
+
+ :attr:`MULTI_ARCH_FOREIGN` for ``Architecture: all``
+ packages.
+
+ .. attribute:: MULTI_ARCH_SAME
+
+ Multiple versions from different architectures may be
+ installed in parallel, but may only satisfy dependencies
+ of packages from the same architecture
+
+ .. attribute:: MULTI_ARCH_ALLOWED
+
+ Installation in parallel and satisfying ``pkg:any``
+ style dependencies is allowed.
+
+ .. attribute:: MULTI_ARCH_ALL_ALLOWED
+
+ :attr:`MULTI_ARCH_ALLOWED` for ``Architecture: all``
+ packages.
+
+
+
.. attribute:: parent_pkg
diff --git a/doc/source/tutorials/apt-cdrom.rst b/doc/source/tutorials/apt-cdrom.rst
index 0561e082..5dd88743 100644
--- a/doc/source/tutorials/apt-cdrom.rst
+++ b/doc/source/tutorials/apt-cdrom.rst
@@ -98,7 +98,7 @@ it is a boolean argument. Afterwards you could use
location of the mount pint. ``('c',"config-file","","ConfigFile")`` shows how
to include configuration files. This option takes a parameter which points to
a configuration file which will be added to the configuration space.
-('o',"option","","ArbItem") is yet another type of option, which allows users
+``('o',"option","","ArbItem")`` is yet another type of option, which allows users
to set configuration options on the commandline.
Now we have to check whether help or version is specified, and print a message
diff --git a/doc/source/whatsnew/0.8.0.rst b/doc/source/whatsnew/0.8.0.rst
new file mode 100644
index 00000000..2eeb135e
--- /dev/null
+++ b/doc/source/whatsnew/0.8.0.rst
@@ -0,0 +1,38 @@
+What's New In python-apt 0.8
+============================
+Python-apt 0.8 is a new major release of the python bindings for the APT
+package management libraries.
+
+
+Removal of old API
+------------------
+The old API that was deprecated in 0.7.100 is no longer available. Applications
+that have not yet updated to the new API should do so.
+
+Multi-arch support
+------------------
+This version of python-apt introduces multi-arch support:
+
+ * A new class, :class:`apt_pkg.Group` has been added.
+ * :class:`apt_pkg.Cache` can now be indexed by ``(name, architecture)``
+ tuples
+
+Features for mancoosi
+----------------------
+Several new features related to ordering have been added on request
+of the mancoosi project:
+
+ * A new class :class:`apt_pkg.OrderList` has been added
+ * The :class:`apt_pkg.PackageManager` class now provides new methods
+ for registering install/remove/configure actions which can be
+ subclassed to check ordering.
+
+Other changes
+-------------
+This release of python-apt also features several other, smaller changes:
+
+ * apt_pkg.Cache() now takes None for the progress parameter, preventing
+ progress reporting.
+
+There have been various other changes, see the changelog for a complete list
+of changes.
diff --git a/pre-build.sh b/pre-build.sh
index 026a491e..a150272d 100755
--- a/pre-build.sh
+++ b/pre-build.sh
@@ -7,5 +7,5 @@ if [ -n "$https_proxy" ]; then
fi
utils/get_ubuntu_mirrors_from_lp.py > data/templates/Ubuntu.mirrors
-echo "updating Debian mirror list"
-utils/get_debian_mirrors.py > data/templates/Debian.mirrors
+#echo "updating Debian mirror list"
+#utils/get_debian_mirrors.py > data/templates/Debian.mirrors
diff --git a/python/acquire-item.cc b/python/acquire-item.cc
index 895d4a21..5e7423ab 100644
--- a/python/acquire-item.cc
+++ b/python/acquire-item.cc
@@ -65,13 +65,13 @@ static PyObject *acquireitem_get_error_text(PyObject *self, void *closure)
static PyObject *acquireitem_get_filesize(PyObject *self, void *closure)
{
pkgAcquire::Item *item = acquireitem_tocpp(self);
- return item ? Py_BuildValue("K", item->FileSize) : 0;
+ return item ? MkPyNumber(item->FileSize) : 0;
}
static PyObject *acquireitem_get_id(PyObject *self, void *closure)
{
pkgAcquire::Item *item = acquireitem_tocpp(self);
- return item ? Py_BuildValue("k", item->ID) : 0;
+ return item ? MkPyNumber(item->ID) : 0;
}
static PyObject *acquireitem_get_mode(PyObject *self, void *closure)
@@ -95,13 +95,13 @@ static PyObject *acquireitem_get_local(PyObject *self, void *closure)
static PyObject *acquireitem_get_partialsize(PyObject *self, void *closure)
{
pkgAcquire::Item *item = acquireitem_tocpp(self);
- return item ? Py_BuildValue("K", item->PartialSize) : 0;
+ return item ? MkPyNumber(item->PartialSize) : 0;
}
static PyObject *acquireitem_get_status(PyObject *self, void *closure)
{
pkgAcquire::Item *item = acquireitem_tocpp(self);
- return item ? Py_BuildValue("i", item->Status) : 0;
+ return item ? MkPyNumber(item->Status) : 0;
}
static int acquireitem_set_id(PyObject *self, PyObject *value, void *closure)
@@ -110,7 +110,7 @@ static int acquireitem_set_id(PyObject *self, PyObject *value, void *closure)
if (Itm == 0)
return -1;
if (PyLong_Check(value)) {
- Itm->ID = PyLong_AsLong(value);
+ Itm->ID = PyLong_AsUnsignedLong(value);
}
else if (PyInt_Check(value)) {
Itm->ID = PyInt_AsLong(value);
diff --git a/python/acquire.cc b/python/acquire.cc
index ab90bbdd..6169ff40 100644
--- a/python/acquire.cc
+++ b/python/acquire.cc
@@ -51,17 +51,17 @@ static PyObject *acquireworker_get_status(PyObject *self, void *closure)
static PyObject *acquireworker_get_current_size(PyObject *self, void *closure)
{
- return Py_BuildValue("k",GetCpp<pkgAcquire::Worker*>(self)->CurrentSize);
+ return MkPyNumber(GetCpp<pkgAcquire::Worker*>(self)->CurrentSize);
}
static PyObject *acquireworker_get_total_size(PyObject *self, void *closure)
{
- return Py_BuildValue("k",GetCpp<pkgAcquire::Worker*>(self)->TotalSize);
+ return MkPyNumber(GetCpp<pkgAcquire::Worker*>(self)->TotalSize);
}
static PyObject *acquireworker_get_resumepoint(PyObject *self, void *closure)
{
- return Py_BuildValue("k",GetCpp<pkgAcquire::Worker*>(self)->ResumePoint);
+ return MkPyNumber(GetCpp<pkgAcquire::Worker*>(self)->ResumePoint);
}
static PyGetSetDef acquireworker_getset[] = {
@@ -225,7 +225,7 @@ static PyObject *PkgAcquireRun(PyObject *Self,PyObject *Args)
pkgAcquire::RunResult run = fetcher->Run(pulseInterval);
- return HandleErrors(Py_BuildValue("i",run));
+ return HandleErrors(MkPyNumber(run));
}
@@ -259,15 +259,15 @@ static PyMethodDef PkgAcquireMethods[] = {
#define fetcher (GetCpp<pkgAcquire*>(Self))
static PyObject *PkgAcquireGetTotalNeeded(PyObject *Self,void*)
{
- return Py_BuildValue("L", fetcher->TotalNeeded());
+ return MkPyNumber(fetcher->TotalNeeded());
}
static PyObject *PkgAcquireGetFetchNeeded(PyObject *Self,void*)
{
- return Py_BuildValue("L", fetcher->FetchNeeded());
+ return MkPyNumber(fetcher->FetchNeeded());
}
static PyObject *PkgAcquireGetPartialPresent(PyObject *Self,void*)
{
- return Py_BuildValue("L", fetcher->PartialPresent());
+ return MkPyNumber(fetcher->PartialPresent());
}
#undef fetcher
diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc
index d1ac33e0..e8490b4e 100644
--- a/python/apt_pkgmodule.cc
+++ b/python/apt_pkgmodule.cc
@@ -24,6 +24,7 @@
#include <apt-pkg/sha256.h>
#include <apt-pkg/init.h>
#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/orderlist.h>
#include <sys/stat.h>
#include <libintl.h>
@@ -83,7 +84,7 @@ static PyObject *VersionCompare(PyObject *Self,PyObject *Args)
return 0;
}
- return Py_BuildValue("i",_system->VS->DoCmpVersion(A,A+LenA,B,B+LenB));
+ return MkPyNumber(_system->VS->DoCmpVersion(A,A+LenA,B,B+LenB));
}
static char *doc_CheckDep =
@@ -459,7 +460,7 @@ static PyObject *GetLock(PyObject *Self,PyObject *Args)
int fd = GetLock(file, errors);
- return HandleErrors(Py_BuildValue("i", fd));
+ return HandleErrors(MkPyNumber(fd));
}
static char *doc_PkgSystemLock =
@@ -732,6 +733,12 @@ static struct _PyAptPkgAPIStruct API = {
&PyVersion_Type, // version_type
&PyVersion_FromCpp, // version_tocpp
&PyVersion_ToCpp, // version_tocpp
+ &PyGroup_Type, // group_type
+ &PyGroup_FromCpp, // group_fromcpp
+ &PyGroup_ToCpp, // group_tocpp
+ &PyOrderList_Type, // orderlist_type
+ &PyOrderList_FromCpp, // orderlist_fromcpp
+ &PyOrderList_ToCpp // orderlist_tocpp
};
@@ -811,6 +818,8 @@ extern "C" void initapt_pkg()
ADDTYPE(Module,"DependencyList",&PyDependencyList_Type); // NO __new__(), internal
ADDTYPE(Module,"Package",&PyPackage_Type); // NO __new__()
ADDTYPE(Module,"Version",&PyVersion_Type); // NO __new__()
+ ADDTYPE(Module,"Group", &PyGroup_Type);
+ ADDTYPE(Module,"GroupList", &PyGroupList_Type);
/* ============================ cdrom.cc ============================ */
ADDTYPE(Module,"Cdrom",&PyCdrom_Type);
/* ========================= configuration.cc ========================= */
@@ -824,7 +833,8 @@ extern "C" void initapt_pkg()
/* ========================= metaindex.cc ========================= */
ADDTYPE(Module,"MetaIndex",&PyMetaIndex_Type); // NO __new__()
/* ========================= pkgmanager.cc ========================= */
- ADDTYPE(Module,"PackageManager",&PyPackageManager_Type);
+ ADDTYPE(Module,"_PackageManager",&PyPackageManager_Type);
+ ADDTYPE(Module,"PackageManager",&PyPackageManager2_Type);
/* ========================= pkgrecords.cc ========================= */
ADDTYPE(Module,"PackageRecords",&PyPackageRecords_Type);
/* ========================= pkgsrcrecords.cc ========================= */
@@ -838,6 +848,7 @@ extern "C" void initapt_pkg()
ADDTYPE(Module,"AcquireItemDesc",&PyAcquireItemDesc_Type);
ADDTYPE(Module,"SystemLock",&PySystemLock_Type);
ADDTYPE(Module,"FileLock",&PyFileLock_Type);
+ ADDTYPE(Module,"OrderList",&PyOrderList_Type);
// Tag file constants
PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER",
CharCharToList(TFRewritePackageOrder));
@@ -845,86 +856,110 @@ extern "C" void initapt_pkg()
PyModule_AddObject(Module,"REWRITE_SOURCE_ORDER",
CharCharToList(TFRewriteSourceOrder));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_ADDED", MkPyNumber(pkgOrderList::Added));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_ADD_PENDIG", MkPyNumber(pkgOrderList::AddPending));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_IMMEDIATE", MkPyNumber(pkgOrderList::Immediate));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_LOOP", MkPyNumber(pkgOrderList::Loop));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_UNPACKED", MkPyNumber(pkgOrderList::UnPacked));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_CONFIGURED", MkPyNumber(pkgOrderList::Configured));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_REMOVED", MkPyNumber(pkgOrderList::Removed));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_IN_LIST", MkPyNumber(pkgOrderList::InList));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_AFTER", MkPyNumber(pkgOrderList::After));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_STATES_MASK", MkPyNumber(pkgOrderList::States));
// Acquire constants.
// some constants
PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_CANCELLED",
- Py_BuildValue("i", pkgAcquire::Cancelled));
+ MkPyNumber(pkgAcquire::Cancelled));
PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_CONTINUE",
- Py_BuildValue("i", pkgAcquire::Continue));
+ MkPyNumber(pkgAcquire::Continue));
PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_FAILED",
- Py_BuildValue("i", pkgAcquire::Failed));
+ MkPyNumber(pkgAcquire::Failed));
#ifdef COMPAT_0_7
PyDict_SetItemString(PyAcquire_Type.tp_dict, "ResultCancelled",
- Py_BuildValue("i", pkgAcquire::Cancelled));
+ MkPyNumber(pkgAcquire::Cancelled));
PyDict_SetItemString(PyAcquire_Type.tp_dict, "ResultContinue",
- Py_BuildValue("i", pkgAcquire::Continue));
+ MkPyNumber(pkgAcquire::Continue));
PyDict_SetItemString(PyAcquire_Type.tp_dict, "ResultFailed",
- Py_BuildValue("i", pkgAcquire::Failed));
+ MkPyNumber(pkgAcquire::Failed));
#endif
// Dependency constants
PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DEPENDS",
- Py_BuildValue("i", pkgCache::Dep::Depends));
+ MkPyNumber(pkgCache::Dep::Depends));
PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_PREDEPENDS",
- Py_BuildValue("i", pkgCache::Dep::PreDepends));
+ MkPyNumber(pkgCache::Dep::PreDepends));
PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_SUGGESTS",
- Py_BuildValue("i", pkgCache::Dep::Suggests));
+ MkPyNumber(pkgCache::Dep::Suggests));
PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_RECOMMENDS",
- Py_BuildValue("i", pkgCache::Dep::Suggests));
+ MkPyNumber(pkgCache::Dep::Suggests));
PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_CONFLICTS",
- Py_BuildValue("i", pkgCache::Dep::Conflicts));
+ MkPyNumber(pkgCache::Dep::Conflicts));
PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_REPLACES",
- Py_BuildValue("i", pkgCache::Dep::Replaces));
+ MkPyNumber(pkgCache::Dep::Replaces));
PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_OBSOLETES",
- Py_BuildValue("i", pkgCache::Dep::Obsoletes));
+ MkPyNumber(pkgCache::Dep::Obsoletes));
PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DPKG_BREAKS",
- Py_BuildValue("i", pkgCache::Dep::DpkgBreaks));
+ MkPyNumber(pkgCache::Dep::DpkgBreaks));
PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_ENHANCES",
- Py_BuildValue("i", pkgCache::Dep::Enhances));
+ MkPyNumber(pkgCache::Dep::Enhances));
// PackageManager constants
PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_COMPLETED",
- Py_BuildValue("i", pkgPackageManager::Completed));
+ MkPyNumber(pkgPackageManager::Completed));
PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_FAILED",
- Py_BuildValue("i", pkgPackageManager::Failed));
+ MkPyNumber(pkgPackageManager::Failed));
PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_INCOMPLETE",
- Py_BuildValue("i", pkgPackageManager::Incomplete));
+ MkPyNumber(pkgPackageManager::Incomplete));
#ifdef COMPAT_0_7
PyDict_SetItemString(PyPackageManager_Type.tp_dict, "ResultCompleted",
- Py_BuildValue("i", pkgPackageManager::Completed));
+ MkPyNumber(pkgPackageManager::Completed));
PyDict_SetItemString(PyPackageManager_Type.tp_dict, "ResultFailed",
- Py_BuildValue("i", pkgPackageManager::Failed));
+ MkPyNumber(pkgPackageManager::Failed));
PyDict_SetItemString(PyPackageManager_Type.tp_dict, "ResultIncomplete",
- Py_BuildValue("i", pkgPackageManager::Incomplete));
+ MkPyNumber(pkgPackageManager::Incomplete));
#endif
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_NONE",
+ MkPyNumber(pkgCache::Version::None));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL",
+ MkPyNumber(pkgCache::Version::All));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_FOREIGN",
+ MkPyNumber(pkgCache::Version::Foreign));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_SAME",
+ MkPyNumber(pkgCache::Version::Same));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALLOWED",
+ MkPyNumber(pkgCache::Version::Allowed));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL_FOREIGN",
+ MkPyNumber(pkgCache::Version::AllForeign));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL_ALLOWED",
+ MkPyNumber(pkgCache::Version::AllAllowed));
// AcquireItem Constants.
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_IDLE",
- Py_BuildValue("i", pkgAcquire::Item::StatIdle));
+ MkPyNumber(pkgAcquire::Item::StatIdle));
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_FETCHING",
- Py_BuildValue("i", pkgAcquire::Item::StatFetching));
+ MkPyNumber(pkgAcquire::Item::StatFetching));
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_DONE",
- Py_BuildValue("i", pkgAcquire::Item::StatDone));
+ MkPyNumber(pkgAcquire::Item::StatDone));
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_TRANSIENT_NETWORK_ERROR",
- Py_BuildValue("i", pkgAcquire::Item::StatTransientNetworkError));
+ MkPyNumber(pkgAcquire::Item::StatTransientNetworkError));
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_ERROR",
- Py_BuildValue("i", pkgAcquire::Item::StatError));
+ MkPyNumber(pkgAcquire::Item::StatError));
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_AUTH_ERROR",
- Py_BuildValue("i", pkgAcquire::Item::StatAuthError));
+ MkPyNumber(pkgAcquire::Item::StatAuthError));
#ifdef COMPAT_0_7
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatIdle",
- Py_BuildValue("i", pkgAcquire::Item::StatIdle));
+ MkPyNumber(pkgAcquire::Item::StatIdle));
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatFetching",
- Py_BuildValue("i", pkgAcquire::Item::StatFetching));
+ MkPyNumber(pkgAcquire::Item::StatFetching));
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatDone",
- Py_BuildValue("i", pkgAcquire::Item::StatDone));
+ MkPyNumber(pkgAcquire::Item::StatDone));
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatError",
- Py_BuildValue("i", pkgAcquire::Item::StatError));
+ MkPyNumber(pkgAcquire::Item::StatError));
PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatAuthError",
- Py_BuildValue("i", pkgAcquire::Item::StatAuthError));
+ MkPyNumber(pkgAcquire::Item::StatAuthError));
#endif
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1
@@ -964,6 +999,7 @@ extern "C" void initapt_pkg()
PyModule_AddIntConstant(Module,"INSTSTATE_HOLD",pkgCache::State::Hold);
PyModule_AddIntConstant(Module,"INSTSTATE_HOLD_REINSTREQ",pkgCache::State::HoldReInstReq);
+
// DEPRECATED API
#ifdef COMPAT_0_7
PyModule_AddObject(Module,"RewritePackageOrder",
diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h
index da647c3f..b3534a30 100644
--- a/python/apt_pkgmodule.h
+++ b/python/apt_pkgmodule.h
@@ -70,6 +70,8 @@ extern PyTypeObject PyCache_Type;
extern PyTypeObject PyCacheFile_Type;
extern PyTypeObject PyPackageList_Type;
extern PyTypeObject PyDescription_Type;
+extern PyTypeObject PyGroup_Type;
+extern PyTypeObject PyGroupList_Type; /* internal */
extern PyTypeObject PyPackage_Type;
extern PyTypeObject PyPackageFile_Type;
extern PyTypeObject PyDependency_Type;
@@ -100,6 +102,7 @@ PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject *kwds);
// packagemanager
extern PyTypeObject PyPackageManager_Type;
+extern PyTypeObject PyPackageManager2_Type;
PyObject *GetPkgManager(PyObject *Self,PyObject *Args);
@@ -132,6 +135,7 @@ extern PyTypeObject PyAcquireItemDesc_Type;
extern PyTypeObject PyAcquireWorker_Type;
extern PyTypeObject PySystemLock_Type;
extern PyTypeObject PyFileLock_Type;
+extern PyTypeObject PyOrderList_Type;
// Functions to be exported in the public API.
@@ -149,6 +153,7 @@ extern PyTypeObject PyFileLock_Type;
# define PyDependency_ToCpp GetCpp<pkgCache::DepIterator>
# define PyDependencyList_ToCpp GetCpp<RDepListStruct> // TODO
# define PyDescription_ToCpp GetCpp<pkgCache::DescIterator>
+# define PyGroup_ToCpp GetCpp<pkgCache::GrpIterator>
# define PyHashes_ToCpp GetCpp<Hashes>
# define PyHashString_ToCpp GetCpp<HashString*>
# define PyIndexRecords_ToCpp GetCpp<indexRecords*>
@@ -156,6 +161,7 @@ extern PyTypeObject PyFileLock_Type;
# define PyPackage_ToCpp GetCpp<pkgCache::PkgIterator>
# define PyPackageFile_ToCpp GetCpp<pkgCache::PkgFileIterator>
# define PyIndexFile_ToCpp GetCpp<pkgIndexFile*>
+# define PyOrderList_ToCpp GetCpp<pkgOrderList*>
# define PyPackageList_ToCpp GetCpp<PkgListStruct> // TODO
# define PyPackageManager_ToCpp GetCpp<pkgPackageManager*>
# define PyPackageRecords_ToCpp GetCpp<PkgRecordsStruct> // TODO
@@ -186,7 +192,9 @@ PyObject* PyHashString_FromCpp(HashString* const &obj, bool Delete, PyObject *Ow
PyObject* PyIndexRecords_FromCpp(indexRecords* const &obj, bool Delete, PyObject *Owner);
PyObject* PyMetaIndex_FromCpp(metaIndex* const &obj, bool Delete, PyObject *Owner);
PyObject* PyPackage_FromCpp(pkgCache::PkgIterator const &obj, bool Delete, PyObject *Owner);
+PyObject* PyGroup_FromCpp(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner);
PyObject* PyIndexFile_FromCpp(pkgIndexFile* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyOrderList_FromCpp(pkgOrderList* const &obj, bool Delete, PyObject *Owner);
PyObject* PyPackageFile_FromCpp(pkgCache::PkgFileIterator const &obj, bool Delete, PyObject *Owner);
//PyObject* PyPackageList_FromCpp(PkgListStruct const &obj, bool Delete, PyObject *Owner);
PyObject* PyPackageManager_FromCpp(pkgPackageManager* const &obj, bool Delete, PyObject *Owner);
diff --git a/python/arfile.cc b/python/arfile.cc
index 5377ca8d..c3aa74d1 100644
--- a/python/arfile.cc
+++ b/python/arfile.cc
@@ -39,32 +39,32 @@ static PyObject *armember_get_name(PyObject *self, void *closure)
static PyObject *armember_get_mtime(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->MTime);
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->MTime);
}
static PyObject *armember_get_uid(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->UID);
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->UID);
}
static PyObject *armember_get_gid(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->GID);
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->GID);
}
static PyObject *armember_get_mode(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->Mode);
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->Mode);
}
static PyObject *armember_get_size(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->Size);
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->Size);
}
static PyObject *armember_get_start(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->Start);
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->Start);
}
static PyObject *armember_repr(PyObject *self)
diff --git a/python/cache.cc b/python/cache.cc
index 190d4f27..b263d320 100644
--- a/python/cache.cc
+++ b/python/cache.cc
@@ -39,13 +39,57 @@ const char *UntranslatedDepTypes[] =
};
/*}}}*/
-struct PkgListStruct
+
+template<typename T> struct IterListStruct
{
- pkgCache::PkgIterator Iter;
+ T Iter;
unsigned long LastIndex;
- PkgListStruct(pkgCache::PkgIterator const &I) : Iter(I), LastIndex(0) {}
- PkgListStruct() {abort();}; // G++ Bug..
+ IterListStruct(T const &I) : Iter(I), LastIndex(0) {}
+ IterListStruct() {};
+
+ bool move(unsigned long Index) {
+ if (Index < 0 || (unsigned)Index >= Count())
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return false;
+ }
+
+ if ((unsigned)Index < LastIndex)
+ {
+ LastIndex = 0;
+ Iter = Begin();
+ }
+
+ while ((unsigned)Index > LastIndex)
+ {
+ LastIndex++;
+ Iter++;
+ if (Iter.end() == true)
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ virtual unsigned Count() = 0;
+ virtual T Begin() = 0;
+
+};
+
+struct PkgListStruct : public IterListStruct<pkgCache::PkgIterator> {
+ unsigned Count() { return Iter.Cache()->HeaderP->PackageCount; }
+ pkgCache::PkgIterator Begin() { return Iter.Cache()->PkgBegin(); }
+
+ PkgListStruct(pkgCache::PkgIterator const &I) { Iter = I; }
+};
+
+struct GrpListStruct : public IterListStruct<pkgCache::GrpIterator> {
+ unsigned Count() { return Iter.Cache()->HeaderP->GroupCount; }
+ pkgCache::GrpIterator Begin() { return Iter.Cache()->GrpBegin(); }
+ GrpListStruct(pkgCache::GrpIterator const &I) { Iter = I; }
};
struct RDepListStruct
@@ -175,6 +219,16 @@ static PyMethodDef PkgCacheMethods[] =
{}
};
+static PyObject *PkgCacheGetGroupCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->GroupCount);
+}
+
+static PyObject *PkgCacheGetGroups(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return CppPyObject_NEW<GrpListStruct>(Self,&PyGroupList_Type,Cache->GrpBegin());
+}
+
static PyObject *PkgCacheGetPackages(PyObject *Self, void*) {
pkgCache *Cache = GetCpp<pkgCache *>(Self);
return CppPyObject_NEW<PkgListStruct>(Self,&PyPackageList_Type,Cache->PkgBegin());
@@ -182,31 +236,31 @@ static PyObject *PkgCacheGetPackages(PyObject *Self, void*) {
static PyObject *PkgCacheGetPackageCount(PyObject *Self, void*) {
pkgCache *Cache = GetCpp<pkgCache *>(Self);
- return Py_BuildValue("i",Cache->HeaderP->PackageCount);
+ return MkPyNumber((int)Cache->HeaderP->PackageCount);
}
static PyObject *PkgCacheGetVersionCount(PyObject *Self, void*) {
pkgCache *Cache = GetCpp<pkgCache *>(Self);
- return Py_BuildValue("i",Cache->HeaderP->VersionCount);
+ return MkPyNumber(Cache->HeaderP->VersionCount);
}
static PyObject *PkgCacheGetDependsCount(PyObject *Self, void*) {
pkgCache *Cache = GetCpp<pkgCache *>(Self);
- return Py_BuildValue("i",Cache->HeaderP->DependsCount);
+ return MkPyNumber(Cache->HeaderP->DependsCount);
}
static PyObject *PkgCacheGetPackageFileCount(PyObject *Self, void*) {
pkgCache *Cache = GetCpp<pkgCache *>(Self);
- return Py_BuildValue("i",Cache->HeaderP->PackageFileCount);
+ return MkPyNumber(Cache->HeaderP->PackageFileCount);
}
static PyObject *PkgCacheGetVerFileCount(PyObject *Self, void*) {
pkgCache *Cache = GetCpp<pkgCache *>(Self);
- return Py_BuildValue("i",Cache->HeaderP->VerFileCount);
+ return MkPyNumber(Cache->HeaderP->VerFileCount);
}
static PyObject *PkgCacheGetProvidesCount(PyObject *Self, void*) {
pkgCache *Cache = GetCpp<pkgCache *>(Self);
- return Py_BuildValue("i",Cache->HeaderP->ProvidesCount);
+ return MkPyNumber(Cache->HeaderP->ProvidesCount);
}
static PyObject *PkgCacheGetFileList(PyObject *Self, void*) {
@@ -222,11 +276,21 @@ static PyObject *PkgCacheGetFileList(PyObject *Self, void*) {
return List;
}
+static PyObject *PkgCacheGetIsMultiArch(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ PyBool_FromLong(Cache->MultiArchCache());
+}
+
static PyGetSetDef PkgCacheGetSet[] = {
{"depends_count",PkgCacheGetDependsCount,0,
"The number of apt_pkg.Dependency objects stored in the cache."},
{"file_list",PkgCacheGetFileList,0,
"A list of apt_pkg.PackageFile objects stored in the cache."},
+ {"group_count",PkgCacheGetGroupCount,0,
+ "The number of apt_pkg.Group objects stored in the cache."},
+ {"groups", PkgCacheGetGroups, 0, "A list of Group objects in the cache"},
+ {"is_multi_arch", PkgCacheGetIsMultiArch, 0,
+ "Whether the cache supports multi-arch."},
{"package_count",PkgCacheGetPackageCount,0,
"The number of apt_pkg.Package objects stored in the cache."},
{"package_file_count",PkgCacheGetPackageFileCount,0,
@@ -242,24 +306,37 @@ static PyGetSetDef PkgCacheGetSet[] = {
{}
};
+// Helper to call FindPkg(name) or FindPkg(name, architecture)
+static pkgCache::PkgIterator CacheFindPkg(PyObject *self, PyObject *arg)
+{
+ const char *name;
+ const char *architecture;
+ pkgCache *cache = GetCpp<pkgCache *>(self);
+ name = PyObject_AsString(arg);
-// Map access, operator []
-static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg)
-{
- pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ if (name != NULL)
+ return cache->FindPkg(name);
- // Get the name of the package, unicode and normal strings.
- const char *Name = PyObject_AsString(Arg);
- if (Name == NULL)
- return 0;
+ PyErr_Clear();
+ if (PyArg_ParseTuple(arg, "ss", &name, &architecture) == 0) {
+ PyErr_Clear();
+ PyErr_Format(PyExc_TypeError, "Expected a string or a pair of strings");
+ return pkgCache::PkgIterator();
+ }
+
+ return cache->FindPkg(name, architecture);
+}
- // Search for the package
- pkgCache::PkgIterator Pkg = Cache->FindPkg(Name);
+// Map access, operator []
+static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg)
+{
+ pkgCache::PkgIterator Pkg = CacheFindPkg(Self, Arg);
if (Pkg.end() == true)
{
- PyErr_SetString(PyExc_KeyError,Name);
+ if (!PyErr_Occurred())
+ PyErr_SetObject(PyExc_KeyError,Arg);
return 0;
}
@@ -269,11 +346,9 @@ static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg)
// Check whether the cache contains a package with a given name.
static int CacheContains(PyObject *Self,PyObject *Arg)
{
- // Get the name of the package, unicode and normal strings.
- const char *Name = PyObject_AsString(Arg);
- if (Name == NULL)
- return 0;
- return (GetCpp<pkgCache *>(Self)->FindPkg(Name).end() == false);
+ bool res = (CacheFindPkg(Self, Arg).end() == false);
+ PyErr_Clear();
+ return res;
}
static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
@@ -292,7 +367,11 @@ static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
pkgCacheFile *Cache = new pkgCacheFile();
- if(pyCallbackInst != 0) {
+ if (pyCallbackInst == Py_None) {
+ OpProgress Prog;
+ if (Cache->Open(Prog,false) == false)
+ return HandleErrors();
+ } else if(pyCallbackInst != 0) {
// sanity check for the progress object, see #497049
if (PyObject_HasAttrString(pyCallbackInst, "done") != true) {
PyErr_SetString(PyExc_ValueError,
@@ -342,9 +421,11 @@ static char *doc_PkgCache = "Cache([progress]) -> Cache() object.\n\n"
"apt.progress.base.OpProgress() object (or similar) which reports\n"
"progress information while the cache is being opened. If this\n"
"parameter is not supplied, the progress will be reported in simple,\n"
- "human-readable text to standard output.\n\n"
+ "human-readable text to standard output. If it is None, no output\n"
+ "will be made.\n\n"
"The cache can be used like a mapping from package names to Package\n"
- "objects (although only getting items is supported).";
+ "objects (although only getting items is supported). Instead of a name,\n"
+ "a tuple of a name and an architecture may be used.";
static PySequenceMethods CacheSeq = {0,0,0,0,0,0,0,CacheContains,0,0};
static PyMappingMethods CacheMap = {CacheMapLen,CacheMapOp,0};
PyTypeObject PyCache_Type =
@@ -418,7 +499,7 @@ PyTypeObject PyCacheFile_Type =
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
};
- /*}}}*/
+
// Package List Class /*{{{*/
// ---------------------------------------------------------------------
static Py_ssize_t PkgListLen(PyObject *Self)
@@ -429,29 +510,9 @@ static Py_ssize_t PkgListLen(PyObject *Self)
static PyObject *PkgListItem(PyObject *iSelf,Py_ssize_t Index)
{
PkgListStruct &Self = GetCpp<PkgListStruct>(iSelf);
- if (Index < 0 || (unsigned)Index >= Self.Iter.Cache()->HeaderP->PackageCount)
- {
- PyErr_SetNone(PyExc_IndexError);
- return 0;
- }
-
- if ((unsigned)Index < Self.LastIndex)
- {
- Self.LastIndex = 0;
- Self.Iter = Self.Iter.Cache()->PkgBegin();
- }
-
- while ((unsigned)Index > Self.LastIndex)
- {
- Self.LastIndex++;
- Self.Iter++;
- if (Self.Iter.end() == true)
- {
- PyErr_SetNone(PyExc_IndexError);
- return 0;
- }
- }
+ if (!Self.move(Index))
+ return 0;
return CppPyObject_NEW<pkgCache::PkgIterator>(GetOwner<PkgListStruct>(iSelf),&PyPackage_Type,
Self.Iter);
}
@@ -501,6 +562,68 @@ PyTypeObject PyPackageList_Type =
CppClear<PkgListStruct>, // tp_clear
};
+/* The same for groups */
+static Py_ssize_t GrpListLen(PyObject *Self)
+{
+ return GetCpp<GrpListStruct>(Self).Iter.Cache()->HeaderP->GroupCount;
+}
+
+static PyObject *GrpListItem(PyObject *iSelf,Py_ssize_t Index)
+{
+ GrpListStruct &Self = GetCpp<GrpListStruct>(iSelf);
+
+ if (!Self.move(Index))
+ return 0;
+ return CppPyObject_NEW<pkgCache::GrpIterator>(GetOwner<GrpListStruct>(iSelf),&PyGroup_Type,
+ Self.Iter);
+}
+
+static PySequenceMethods GrpListSeq =
+{
+ GrpListLen,
+ 0, // concat
+ 0, // repeat
+ GrpListItem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+static const char *grouplist_doc =
+ "A GroupList is an internally used structure to represent\n"
+ "the 'groups' attribute of apt_pkg.Cache objects in a more\n"
+ "efficient manner by creating Group objects only when they\n"
+ "are accessed.";
+
+PyTypeObject PyGroupList_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.GroupList", // tp_name
+ sizeof(CppPyObject<GrpListStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<GrpListStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &GrpListSeq, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ grouplist_doc, // tp_doc
+ CppTraverse<GrpListStruct>, // tp_traverse
+ CppClear<GrpListStruct>, // tp_clear
+};
+
+
#define Owner (GetOwner<pkgCache::PkgIterator>(Self))
#define MkGet(PyFunc,Ret) static PyObject *PyFunc(PyObject *Self,void*) \
{ \
@@ -514,10 +637,10 @@ MkGet(PackageGetSection,Safe_FromString(Pkg.Section()))
MkGet(PackageGetRevDependsList,CppPyObject_NEW<RDepListStruct>(Owner,
&PyDependencyList_Type, Pkg.RevDependsList()))
MkGet(PackageGetProvidesList,CreateProvides(Owner,Pkg.ProvidesList()))
-MkGet(PackageGetSelectedState,Py_BuildValue("i",Pkg->SelectedState))
-MkGet(PackageGetInstState,Py_BuildValue("i",Pkg->InstState))
-MkGet(PackageGetCurrentState,Py_BuildValue("i",Pkg->CurrentState))
-MkGet(PackageGetID,Py_BuildValue("i",Pkg->ID))
+MkGet(PackageGetSelectedState,MkPyNumber(Pkg->SelectedState))
+MkGet(PackageGetInstState,MkPyNumber(Pkg->InstState))
+MkGet(PackageGetCurrentState,MkPyNumber(Pkg->CurrentState))
+MkGet(PackageGetID,MkPyNumber(Pkg->ID))
#
MkGet(PackageGetAuto,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Auto) != 0))
MkGet(PackageGetEssential,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Essential) != 0))
@@ -714,7 +837,7 @@ static PyObject *DescriptionGetFileList(PyObject *Self,void*)
PyObject *DescFile;
PyObject *Obj;
DescFile = CppPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File());
- Obj = Py_BuildValue("Nl",DescFile,I.Index());
+ Obj = Py_BuildValue("NN",DescFile,MkPyNumber(I.Index()));
PyList_Append(List,Obj);
Py_DECREF(Obj);
}
@@ -869,7 +992,7 @@ static PyObject *VersionGetFileList(PyObject *Self, void*) {
PyObject *PkgFile;
PyObject *Obj;
PkgFile = CppPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File());
- Obj = Py_BuildValue("Nl",PkgFile,I.Index());
+ Obj = Py_BuildValue("NN",PkgFile,MkPyNumber(I.Index()));
PyList_Append(List,Obj);
Py_DECREF(Obj);
}
@@ -896,19 +1019,19 @@ static PyObject *VersionGetProvidesList(PyObject *Self, void*) {
return CreateProvides(Owner,Version_GetVer(Self).ProvidesList());
}
static PyObject *VersionGetSize(PyObject *Self, void*) {
- return Py_BuildValue("i", Version_GetVer(Self)->Size);
+ return MkPyNumber(Version_GetVer(Self)->Size);
}
static PyObject *VersionGetInstalledSize(PyObject *Self, void*) {
- return Py_BuildValue("i", Version_GetVer(Self)->InstalledSize);
+ return MkPyNumber(Version_GetVer(Self)->InstalledSize);
}
static PyObject *VersionGetHash(PyObject *Self, void*) {
- return Py_BuildValue("i", Version_GetVer(Self)->Hash);
+ return MkPyNumber(Version_GetVer(Self)->Hash);
}
static PyObject *VersionGetID(PyObject *Self, void*) {
- return Py_BuildValue("i", Version_GetVer(Self)->ID);
+ return MkPyNumber(Version_GetVer(Self)->ID);
}
static PyObject *VersionGetPriority(PyObject *Self, void*) {
- return Py_BuildValue("i",Version_GetVer(Self)->Priority);
+ return MkPyNumber(Version_GetVer(Self)->Priority);
}
static PyObject *VersionGetPriorityStr(PyObject *Self, void*) {
return Safe_FromString(Version_GetVer(Self).PriorityType());
@@ -924,6 +1047,11 @@ static PyObject *VersionGetTranslatedDescription(PyObject *Self, void*) {
Ver.TranslatedDescription());
}
+static PyObject *VersionGetMultiArch(PyObject *Self, void*)
+{
+ return MkPyNumber(Version_GetVer(Self)->MultiArch);
+}
+
#if 0 // FIXME: enable once pkgSourceList is stored somewhere
static PyObject *VersionGetIsTrusted(PyObject *Self, void*) {
else if (strcmp("IsTrusted", Name) == 0)
@@ -999,6 +1127,9 @@ static PyGetSetDef VersionGetSet[] = {
"The numeric ID of the package."},
{"installed_size",VersionGetInstalledSize,0,
"The installed size of this package version."},
+ {"multi_arch",VersionGetMultiArch,0,
+ "Multi-arch state of this package, as an integer. See\n"
+ "the various MULTI_ARCH_* members."},
{"parent_pkg",VersionGetParentPkg,0,
"The parent package of this version."},
{"priority",VersionGetPriority,0,
@@ -1118,7 +1249,7 @@ static PyObject *PackageFile_GetIndexType(PyObject *Self,void*)
static PyObject *PackageFile_GetSize(PyObject *Self,void*)
{
pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
- return Py_BuildValue("i",File->Size);
+ return MkPyNumber(File->Size);
}
static PyObject *PackageFile_GetNotSource(PyObject *Self,void*)
@@ -1135,7 +1266,7 @@ static PyObject *PackageFile_GetNotAutomatic(PyObject *Self,void*)
static PyObject *PackageFile_GetID(PyObject *Self,void*)
{
pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
- return Py_BuildValue("i",File->ID);
+ return MkPyNumber(File->ID);
}
#define S(s) (s == NULL ? "" : s)
@@ -1344,13 +1475,13 @@ static PyObject *DependencyGetDepTypeUntranslated(PyObject *Self,void*)
static PyObject *DependencyGetDepTypeEnum(PyObject *Self,void*)
{
pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
- return Py_BuildValue("i", Dep->Type);
+ return MkPyNumber(Dep->Type);
}
static PyObject *DependencyGetID(PyObject *Self,void*)
{
pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
- return Py_BuildValue("i",Dep->ID);
+ return MkPyNumber(Dep->ID);
}
static PyGetSetDef DependencyGetSet[] = {
diff --git a/python/cachegroup.cc b/python/cachegroup.cc
new file mode 100644
index 00000000..4fc6c378
--- /dev/null
+++ b/python/cachegroup.cc
@@ -0,0 +1,188 @@
+/*
+ * cachegroup.cc - Wrapper around pkgCache::GrpIterator
+ *
+ * Copyright 2011 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <Python.h>
+#include "apt_pkgmodule.h"
+#include "generic.h"
+#include <apt-pkg/pkgcache.h>
+
+struct PyGroup : CppPyObject<pkgCache::GrpIterator> {
+ pkgCache::PkgIterator current;
+ int nextIndex;
+};
+
+static PyObject *group_new(PyTypeObject *type,PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *pyCache;
+ char *name;
+ char *kwlist[] = {"cache", "name", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!s", kwlist,
+ &PyCache_Type, &pyCache,
+ &name) == 0)
+ return 0;
+
+ pkgCache *cache = GetCpp<pkgCache *>(pyCache);
+
+ pkgCache::GrpIterator grp = cache->FindGrp(name);
+
+ if (!grp.end()) {
+ return PyGroup_FromCpp(grp, true, pyCache);
+ } else {
+ PyErr_SetString(PyExc_KeyError, name);
+ return NULL;
+ }
+}
+
+static const char group_find_package_doc[] =
+ "find_package(architecture: str) -> Package\n\n"
+ "Return a package for the given architecture, or None if none exists";
+static PyObject *group_find_package(PyObject *self,PyObject *args)
+{
+ pkgCache::GrpIterator grp = GetCpp<pkgCache::GrpIterator>(self);
+ PyObject *owner = GetOwner<pkgCache::GrpIterator>(self);
+
+ char *architecture;
+ if (PyArg_ParseTuple(args, "s", &architecture) == 0)
+ return 0;
+
+ pkgCache::PkgIterator pkg = grp.FindPkg(architecture);
+
+ if (pkg.end()) {
+ Py_RETURN_NONE;
+ } else {
+ return PyPackage_FromCpp(pkg, true, owner ? owner : self);
+ }
+}
+
+static const char group_find_preferred_package_doc[] =
+ "find_preferred_package(prefer_non_virtual: bool = True) -> Package\n\n"
+ "Return a package for the best architecture, either the native one\n"
+ "or the first found one. If none exists, return None. If non_virtual\n"
+ "is True, prefer non-virtual packages over virtual ones.";
+static PyObject *group_find_preferred_package(PyObject *self,PyObject *args,
+ PyObject *kwds)
+{
+ pkgCache::GrpIterator grp = GetCpp<pkgCache::GrpIterator>(self);
+ PyObject *owner = GetOwner<pkgCache::GrpIterator>(self);
+ char nonvirtual = 1;
+ char *kwlist[] = {"prefer_non_virtual", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|b", kwlist, &nonvirtual) == 0)
+ return 0;
+ pkgCache::PkgIterator pkg = grp.FindPreferredPkg(nonvirtual);
+
+ if (pkg.end()) {
+ Py_RETURN_NONE;
+ } else {
+ return PyPackage_FromCpp(pkg, true, owner);
+ }
+}
+
+static PyMethodDef group_methods[] = {
+ {"find_package",group_find_package,METH_VARARGS,group_find_package_doc},
+ {"find_preferred_package",(PyCFunction) group_find_preferred_package,
+ METH_VARARGS|METH_KEYWORDS,group_find_preferred_package_doc},
+ {}
+};
+
+static PyObject *group_seq_item(PyObject *pySelf,Py_ssize_t index)
+{
+ PyGroup *self = static_cast<PyGroup *>(pySelf);
+ pkgCache::GrpIterator grp = GetCpp<pkgCache::GrpIterator>(self);
+ PyObject *owner = GetOwner<pkgCache::GrpIterator>(self);
+
+ if (self->nextIndex > index || self->nextIndex == 0) {
+ self->nextIndex = 1;
+ new (&self->current) pkgCache::PkgIterator(grp.PackageList());
+ }
+
+ if (self->nextIndex != index + 1) {
+ while (self->nextIndex <= index && !self->current.end()) {
+ self->current = grp.NextPkg(self->current);
+ self->nextIndex++;
+ }
+ }
+
+ if (self->current.end())
+ return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index);
+
+ return PyPackage_FromCpp(self->current, true, owner);
+}
+
+
+static PySequenceMethods group_as_sequence =
+{
+ 0,
+ 0, // concat
+ 0, // repeat
+ group_seq_item,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+
+static const char group_doc[] = "Group(cache, name)\n\n"
+ "Group of packages with the same name.\n\n"
+ "Provides access to all packages sharing a name. Can be used this\n"
+ "like a list, or by using the special find_*() methods. If you use\n"
+ "it as a sequence, make sure to access it linearly, as this uses a\n"
+ "linked list internally.";
+PyTypeObject PyGroup_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Group", // tp_name
+ sizeof(PyGroup), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::GrpIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &group_as_sequence, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ group_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ group_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ group_new, // tp_new
+};
diff --git a/python/configuration.cc b/python/configuration.cc
index 93e92efa..9000f71f 100644
--- a/python/configuration.cc
+++ b/python/configuration.cc
@@ -92,7 +92,7 @@ static PyObject *CnfFindI(PyObject *Self,PyObject *Args)
int Default = 0;
if (PyArg_ParseTuple(Args,"s|i",&Name,&Default) == 0)
return 0;
- return Py_BuildValue("i",GetSelf(Self).FindI(Name,Default));
+ return MkPyNumber(GetSelf(Self).FindI(Name,Default));
}
static const char *doc_FindB =
@@ -438,6 +438,10 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args)
return 0;
}
+ if (PySequence_Length(Pargv) < 1) {
+ PyErr_SetString(PyExc_ValueError,"argv is an empty sequence");
+ return 0;
+ }
// Convert the option list
int Length = PySequence_Length(POList);
CommandLine::Args *OList = new CommandLine::Args[Length+1];
diff --git a/python/depcache.cc b/python/depcache.cc
index 12c13a73..e6113429 100644
--- a/python/depcache.cc
+++ b/python/depcache.cc
@@ -668,22 +668,22 @@ static PyMethodDef PkgDepCacheMethods[] =
#define depcache (GetCpp<pkgDepCache *>(Self))
static PyObject *PkgDepCacheGetKeepCount(PyObject *Self,void*) {
- return Py_BuildValue("l", depcache->KeepCount());
+ return MkPyNumber(depcache->KeepCount());
}
static PyObject *PkgDepCacheGetInstCount(PyObject *Self,void*) {
- return Py_BuildValue("l", depcache->InstCount());
+ return MkPyNumber(depcache->InstCount());
}
static PyObject *PkgDepCacheGetDelCount(PyObject *Self,void*) {
- return Py_BuildValue("l", depcache->DelCount());
+ return MkPyNumber(depcache->DelCount());
}
static PyObject *PkgDepCacheGetBrokenCount(PyObject *Self,void*) {
- return Py_BuildValue("l", depcache->BrokenCount());
+ return MkPyNumber(depcache->BrokenCount());
}
static PyObject *PkgDepCacheGetUsrSize(PyObject *Self,void*) {
- return Py_BuildValue("L", depcache->UsrSize());
+ return MkPyNumber(depcache->UsrSize());
}
static PyObject *PkgDepCacheGetDebSize(PyObject *Self,void*) {
- return Py_BuildValue("L", depcache->DebSize());
+ return MkPyNumber(depcache->DebSize());
}
#undef depcache
diff --git a/python/generic.h b/python/generic.h
index ce9e5091..f9680ca5 100644
--- a/python/generic.h
+++ b/python/generic.h
@@ -57,6 +57,7 @@ typedef int Py_ssize_t;
#define PyString_Type PyUnicode_Type
#define PyInt_Check PyLong_Check
#define PyInt_AsLong PyLong_AsLong
+#define PyInt_FromLong PyLong_FromLong
// Force 0.7 compatibility to be off in Python 3 builds
#undef COMPAT_0_7
#else
@@ -231,6 +232,21 @@ PyObject *HandleErrors(PyObject *Res = 0);
const char **ListToCharChar(PyObject *List,bool NullTerm = false);
PyObject *CharCharToList(const char **List,unsigned long Size = 0);
+/* Happy number conversion, thanks to overloading */
+inline PyObject *MkPyNumber(unsigned long long o) { return PyLong_FromUnsignedLongLong(o); }
+inline PyObject *MkPyNumber(unsigned long o) { return PyLong_FromUnsignedLong(o); }
+inline PyObject *MkPyNumber(unsigned int o) { return PyLong_FromUnsignedLong(o); }
+inline PyObject *MkPyNumber(unsigned short o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(unsigned char o) { return PyInt_FromLong(o); }
+
+inline PyObject *MkPyNumber(long long o) { return PyLong_FromLongLong(o); }
+inline PyObject *MkPyNumber(long o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(int o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(short o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(char o) { return PyInt_FromLong(o); }
+
+inline PyObject *MkPyNumber(double o) { return PyFloat_FromDouble(o); }
+
# ifdef COMPAT_0_7
PyObject *_PyAptObject_getattro(PyObject *self, PyObject *attr);
# else
diff --git a/python/indexfile.cc b/python/indexfile.cc
index 037be210..bf0df516 100644
--- a/python/indexfile.cc
+++ b/python/indexfile.cc
@@ -47,7 +47,7 @@ static PyObject *IndexFileGetHasPackages(PyObject *Self,void*) {
return PyBool_FromLong((File->HasPackages()));
}
static PyObject *IndexFileGetSize(PyObject *Self,void*) {
- return Py_BuildValue("i",(File->Size()));
+ return MkPyNumber((File->Size()));
}
static PyObject *IndexFileGetIsTrusted(PyObject *Self,void*) {
return PyBool_FromLong((File->IsTrusted()));
diff --git a/python/indexrecords.cc b/python/indexrecords.cc
index d6a3263c..c7623cfd 100644
--- a/python/indexrecords.cc
+++ b/python/indexrecords.cc
@@ -63,7 +63,7 @@ static PyObject *indexrecords_lookup(PyObject *self,PyObject *args)
// Copy the HashString(), to prevent crashes and to not require the
// indexRecords object to exist.
PyObject *py_hash = PyHashString_FromCpp(new HashString(result->Hash), true, NULL);
- PyObject *value = Py_BuildValue("(Oi)",py_hash,result->Size);
+ PyObject *value = Py_BuildValue("(ON)",py_hash,MkPyNumber(result->Size));
Py_DECREF(py_hash);
return value;
}
diff --git a/python/orderlist.cc b/python/orderlist.cc
new file mode 100644
index 00000000..9fbed5f2
--- /dev/null
+++ b/python/orderlist.cc
@@ -0,0 +1,317 @@
+/*
+ * orderlist.cc - Wrapper around pkgOrderList
+ *
+ * Copyright 2011 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <Python.h>
+#include "apt_pkgmodule.h"
+#include "generic.h"
+#include <apt-pkg/orderlist.h>
+
+struct PyOrderList : CppPyObject<pkgOrderList*> {
+ pkgCache::PkgIterator current;
+ int nextIndex;
+};
+
+static PyObject *order_list_new(PyTypeObject *type,PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *pyDepCache = NULL;
+ char *kwlist[] = {"depcache", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist,
+ &PyDepCache_Type, &pyDepCache)
+ == 0)
+ return 0;
+
+ pkgDepCache *depCache = PyDepCache_ToCpp(pyDepCache);
+ return PyOrderList_FromCpp(new pkgOrderList(depCache), true,
+ pyDepCache);
+}
+
+static const char order_list_append_doc[] =
+ "append(pkg: Package)\n\n"
+ "Append a package to the end of the list.";
+static PyObject *order_list_append(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPackage = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPackage) == 0)
+ return 0;
+
+ list->push_back(PyPackage_ToCpp(pyPackage));
+ Py_RETURN_NONE;
+}
+
+static const char order_list_score_doc[] =
+ "score(pkg: Package) -> int\n\n"
+ "Return the score of the package.";
+static PyObject *order_list_score(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPackage = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPackage) == 0)
+ return 0;
+
+ return MkPyNumber(list->Score(PyPackage_ToCpp(pyPackage)));
+}
+
+static const char order_list_order_critical_doc[] =
+ "order_critical()\n\n"
+ "Order by PreDepends only (critical unpack order).";
+static PyObject *order_list_order_critical(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+
+ list->OrderCritical();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static const char order_list_order_unpack_doc[] =
+ "order_unpack()\n\n"
+ "Order the packages for unpacking (see Debian Policy).";
+static PyObject *order_list_order_unpack(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+
+ list->OrderUnpack();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static const char order_list_order_configure_doc[] =
+ "order_configure()\n\n"
+ "Order the packages for configuration (see Debian Policy).";
+static PyObject *order_list_order_configure(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+
+ list->OrderConfigure();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static bool valid_flags(unsigned int flags) {
+ return (flags & ~pkgOrderList::Added
+ & ~pkgOrderList::AddPending
+ & ~pkgOrderList::Immediate
+ & ~pkgOrderList::Loop
+ & ~pkgOrderList::UnPacked
+ & ~pkgOrderList::Configured
+ & ~pkgOrderList::Removed
+ & ~pkgOrderList::InList
+ & ~pkgOrderList::After
+ & ~pkgOrderList::States) == 0;
+}
+
+static const char order_list_flag_doc[] =
+ "flag(pkg: Package, flag: int[, unset_flags: int])\n\n"
+ "Flag the package, set flags in 'flag' and remove flags in\n"
+ "'unset_flags'.";
+static PyObject *order_list_flag(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+
+ PyObject *pyPkg = NULL;
+ unsigned int flags = 0;
+ unsigned int unset_flags = 0;
+ if (PyArg_ParseTuple(args, "O!I|I", &PyPackage_Type, &pyPkg,
+ &flags, &unset_flags) == 0)
+ return 0;
+
+ if (!valid_flags(flags))
+ return PyErr_Format(PyExc_ValueError, "flags (%u) is"
+ " not a valid combination of flags.",
+ flags);
+ if (!valid_flags(unset_flags))
+ return PyErr_Format(PyExc_ValueError, "unset_flags (%u) is"
+ " not a valid combination of flags.",
+ unset_flags);
+
+ list->Flag(PyPackage_ToCpp(pyPkg), flags, unset_flags);
+
+ Py_RETURN_NONE;
+}
+
+static const char order_list_is_flag_doc[] =
+ "is_flag(pkg: Package, flag: int)\n\n"
+ "Check if the flag(s) are set.";
+static PyObject *order_list_is_flag(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPkg = NULL;
+ unsigned int flags = 0;
+ if (PyArg_ParseTuple(args, "O!I", &PyPackage_Type, &pyPkg,
+ &flags) == 0)
+ return 0;
+
+ if (!valid_flags(flags))
+ return PyErr_Format(PyExc_ValueError, "flags (%u) is"
+ " not a valid combination of flags.",
+ flags);
+
+ return PyBool_FromLong(list->IsFlag(PyPackage_ToCpp(pyPkg), flags));
+}
+
+static const char order_list_wipe_flags_doc[] =
+ "wipe_flags(flags: int)\n\n"
+ "Remove the flags in 'flags' from all packages in this list";
+static PyObject *order_list_wipe_flags(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ unsigned int flags = 0;
+ if (PyArg_ParseTuple(args, "I", &flags) == 0)
+ return 0;
+
+ if (!valid_flags(flags))
+ return PyErr_Format(PyExc_ValueError, "flags (%u) is"
+ " not a valid combination of flags.",
+ flags);
+
+ list->WipeFlags(flags);
+ Py_RETURN_NONE;
+}
+
+static const char order_list_is_now_doc[] =
+ "is_now(pkg: Package)\n\n"
+ "Check if the package is flagged for any state but removal.";
+static PyObject *order_list_is_now(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPkg = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPkg) == 0)
+ return 0;
+
+ return PyBool_FromLong(list->IsNow(PyPackage_ToCpp(pyPkg)));
+}
+
+static const char order_list_is_missing_doc[] =
+ "is_now(pkg: Package)\n\n"
+ "Check if the package is marked for install.";
+static PyObject *order_list_is_missing(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPkg = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPkg) == 0)
+ return 0;
+
+ return PyBool_FromLong(list->IsMissing(PyPackage_ToCpp(pyPkg)));
+}
+
+
+#define METHOD(name) {#name, order_list_##name, METH_VARARGS,\
+ order_list_##name##_doc}
+
+static PyMethodDef order_list_methods[] = {
+ METHOD(append),
+ METHOD(score),
+ METHOD(order_critical),
+ METHOD(order_unpack),
+ METHOD(order_configure),
+ METHOD(flag),
+ METHOD(is_flag),
+ METHOD(is_now),
+ METHOD(is_missing),
+ METHOD(wipe_flags),
+ {}
+};
+
+static PyObject *order_list_seq_item(PyObject *self,Py_ssize_t index)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *owner = GetOwner<pkgOrderList*>(self);
+ PyObject *pycache = GetOwner<pkgOrderList*>(owner);
+ pkgCache *cache = PyCache_ToCpp(pycache);
+
+ if (index < 0 || index >= list->size())
+ return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index);
+
+ return PyPackage_FromCpp(pkgCache::PkgIterator(*cache,
+ *(list->begin() + index)),
+ true, owner);
+}
+
+Py_ssize_t order_list_seq_length(PyObject *self)
+{
+ return GetCpp<pkgOrderList*>(self)->size();
+}
+
+static PySequenceMethods order_list_as_sequence =
+{
+ order_list_seq_length, // sq_length
+ 0, // sq_concat
+ 0, // sq_repeat
+ order_list_seq_item, // sq_item
+ 0, // sq_ass_item
+ 0, // sq_contains
+ 0, // sq_inplace_concat
+ 0 // sq_inplace_repeat
+};
+
+static const char order_list_doc[] = "OrderList(depcache: DepCache)\n\n"
+ "Sequence type for packages with special ordering methods.";
+PyTypeObject PyOrderList_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.OrderList", // tp_name
+ sizeof(CppPyObject<pkgOrderList*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgOrderList*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &order_list_as_sequence, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ order_list_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ order_list_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ order_list_new, // tp_new
+};
diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc
index 95e8c27e..b7bed658 100644
--- a/python/pkgmanager.cc
+++ b/python/pkgmanager.cc
@@ -17,36 +17,10 @@
#include <apt-pkg/acquire.h>
#include <apt-pkg/init.h>
#include <apt-pkg/configuration.h>
+#include <apt-pkg/dpkgpm.h>
#include <iostream>
-static PyObject *PkgManagerNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
-{
- PyObject *Owner;
- char *kwlist[] = {"depcache",0};
- if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type,
- &Owner) == 0)
- return 0;
-
- pkgPackageManager *pm = _system->CreatePM(GetCpp<pkgDepCache*>(Owner));
-
- CppPyObject<pkgPackageManager*> *PkgManagerObj =
- CppPyObject_NEW<pkgPackageManager*>(NULL, type,pm);
-
- return PkgManagerObj;
-}
-
-#ifdef COMPAT_0_7
-PyObject *GetPkgManager(PyObject *Self,PyObject *Args)
-{
- PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPackageManager() is "
- "deprecated. Please see apt_pkg.PackageManager() for the "
- "replacement.", 1);
- return PkgManagerNew(&PyPackageManager_Type,Args,0);
-}
-#endif
-
-
static PyObject *PkgManagerGetArchives(PyObject *Self,PyObject *Args)
{
pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self);
@@ -79,7 +53,7 @@ static PyObject *PkgManagerDoInstall(PyObject *Self,PyObject *Args)
pkgPackageManager::OrderResult res = pm->DoInstall(status_fd);
- return HandleErrors(Py_BuildValue("i",res));
+ return HandleErrors(MkPyNumber(res));
}
static PyObject *PkgManagerFixMissing(PyObject *Self,PyObject *Args)
@@ -114,17 +88,16 @@ static PyMethodDef PkgManagerMethods[] =
{}
};
-
static const char *packagemanager_doc =
- "PackageManager(depcache: apt_pkg.DepCache)\n\n"
- "PackageManager objects allow the fetching of packages marked for\n"
- "installation and the installation of those packages. The parameter\n"
- "'depcache' specifies an apt_pkg.DepCache object where information\n"
- "about the package selections is retrieved from.";
+ "_PackageManager objects allow the fetching of packages marked for\n"
+ "installation and the installation of those packages.\n"
+ "This is an abstract base class that cannot be subclassed\n"
+ "in Python. The only subclass is apt_pkg.PackageManager. This\n"
+ "class is an implementation-detail and not part of the API.";
PyTypeObject PyPackageManager_Type =
{
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "apt_pkg.PackageManager", // tp_name
+ "apt_pkg._PackageManager", // tp_name
sizeof(CppPyObject<pkgPackageManager*>), // tp_basicsize
0, // tp_itemsize
// Methods
@@ -143,8 +116,7 @@ PyTypeObject PyPackageManager_Type =
_PyAptObject_getattro, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
- (Py_TPFLAGS_DEFAULT | // tp_flags
- Py_TPFLAGS_BASETYPE),
+ Py_TPFLAGS_DEFAULT, // tp_flag,
packagemanager_doc, // tp_doc
0, // tp_traverse
0, // tp_clear
@@ -162,9 +134,240 @@ PyTypeObject PyPackageManager_Type =
0, // tp_dictoffset
0, // tp_init
0, // tp_alloc
- PkgManagerNew, // tp_new
+ 0, // tp_new
+};
+
+
+struct CppPyRef {
+ PyObject *o;
+ CppPyRef(const CppPyRef &o) { Py_XINCREF(o); this->o = o; }
+ CppPyRef(PyObject *o) : o(o) {}
+ ~CppPyRef() { Py_XDECREF(o); }
+ operator PyObject *() const { return o; }
+ PyObject *operator->() const { return o; }
};
+class PyPkgManager : public pkgDPkgPM {
+ bool res(CppPyRef result) {
+ if (result == NULL) {
+ std::cerr << "Error in function: " << std::endl;
+ PyErr_Print();
+ PyErr_Clear();
+ return false;
+ }
+ return (result != NULL &&
+ (result == Py_None || PyObject_IsTrue(result) == 1));
+ }
+
+
+ PyObject *GetPyPkg(const PkgIterator &Pkg) {
+ PyObject *depcache = NULL;
+ PyObject *cache = NULL;
+
+ depcache = GetOwner<PyPkgManager*>(pyinst);
+ if (depcache != NULL && PyDepCache_Check(depcache))
+ cache = GetOwner<pkgDepCache*>(depcache);
+
+ return PyPackage_FromCpp(Pkg, true, cache);
+ }
+
+ /* Call through to Python */
+ virtual bool Install(PkgIterator Pkg,string File) {
+ return res(PyObject_CallMethod(pyinst, "install", "(NN)",
+ GetPyPkg(Pkg),
+ CppPyString(File)));
+ }
+ virtual bool Configure(PkgIterator Pkg) {
+ return res(PyObject_CallMethod(pyinst, "configure", "(N)",
+ GetPyPkg(Pkg)));
+ }
+ virtual bool Remove(PkgIterator Pkg,bool Purge = false) {
+ return res(PyObject_CallMethod(pyinst, "remove", "(NN)",
+ GetPyPkg(Pkg),
+ PyBool_FromLong(Purge)));
+ }
+ virtual bool Go(int StatusFd=-1) {
+ return res(PyObject_CallMethod(pyinst, "go", "(i)",
+ StatusFd));
+ }
+ virtual void Reset() {
+ CppPyRef(PyObject_CallMethod(pyinst, "reset", NULL));
+ }
+
+public:
+ /* Those call the protected functions from the parent class */
+ bool callInstall(PkgIterator Pkg,string File) { return pkgDPkgPM::Install(Pkg, File); }
+ bool callRemove(PkgIterator Pkg, bool Purge) { return pkgDPkgPM::Remove(Pkg, Purge); }
+ bool callGo(int StatusFd=-1) { return pkgDPkgPM::Go(StatusFd); }
+ void callReset() { return pkgDPkgPM::Reset(); }
+ bool callConfigure(PkgIterator Pkg) { return pkgDPkgPM::Configure(Pkg); }
+ pkgOrderList *getOrderList() { return pkgPackageManager::List; }
+
+ PyPkgManager(pkgDepCache *Cache) : pkgDPkgPM(Cache) {};
+ PyObject *pyinst;
+};
+
+static PyObject *PkgManagerNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"depcache",0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type,
+ &Owner) == 0)
+ return 0;
+
+ PyPkgManager *pm = new PyPkgManager(GetCpp<pkgDepCache*>(Owner));
+
+ CppPyObject<PyPkgManager*> *PkgManagerObj =
+ CppPyObject_NEW<PyPkgManager*>(NULL, type,pm);
+
+ pm->pyinst = PkgManagerObj;
+
+ return PkgManagerObj;
+}
+
+#ifdef COMPAT_0_7
+PyObject *GetPkgManager(PyObject *Self,PyObject *Args)
+{
+ PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPackageManager() is "
+ "deprecated. Please see apt_pkg.PackageManager() for the "
+ "replacement.", 1);
+ return PkgManagerNew(&PyPackageManager2_Type,Args,0);
+}
+#endif
+
+static PyObject *PkgManagerInstall(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ PyObject *pkg;
+ const char *file;
+
+ if (PyArg_ParseTuple(Args, "O!s", &PyPackage_Type,&pkg, &file) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callInstall(PyPackage_ToCpp(pkg), file)));
+}
+
+
+static PyObject *PkgManagerConfigure(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ PyObject *pkg;
+
+ if (PyArg_ParseTuple(Args, "O!", &PyPackage_Type,&pkg) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callConfigure(PyPackage_ToCpp(pkg))));
+}
+
+static PyObject *PkgManagerRemove(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ PyObject *pkg;
+ char purge;
+
+ if (PyArg_ParseTuple(Args, "O!b", &PyPackage_Type,&pkg, &purge) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callRemove(PyPackage_ToCpp(pkg), purge)));
+}
+
+static PyObject *PkgManagerGo(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ int fd;
+
+ if (PyArg_ParseTuple(Args, "i", &fd) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callGo(fd)));
+}
+
+static PyObject *PkgManagerReset(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+
+ pm->callReset();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyMethodDef PkgManager2Methods[] =
+{
+ {"install",PkgManagerInstall,METH_VARARGS,
+ "install(pkg: Package, filename: str) -> bool \n\n"
+ "Add a install action. Can be overriden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"configure",PkgManagerConfigure,METH_VARARGS,
+ "configure(pkg: Package) -> bool \n\n"
+ "Add a configure action. Can be overriden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"remove",PkgManagerRemove,METH_VARARGS,
+ "remove(pkg: Package, purge: bool) -> bool \n\n"
+ "Add a removal action. Can be overriden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"go",PkgManagerGo,METH_VARARGS,
+ "go(status_fd: int) -> bool \n\n"
+ "Start dpkg. Can be overriden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"reset",PkgManagerReset,METH_VARARGS,
+ "reset()\n\n"
+ "Reset the package manager for a new round.\n"
+ "Can be overriden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {}
+};
+
+static const char *packagemanager2_doc =
+ "PackageManager(depcache: apt_pkg.DepCache)\n\n"
+ "PackageManager objects allow the fetching of packages marked for\n"
+ "installation and the installation of those packages. The parameter\n"
+ "'depcache' specifies an apt_pkg.DepCache object where information\n"
+ "about the package selections is retrieved from.\n\n"
+ "Methods in this class can be overriden in sub classes\n"
+ "to implement behavior different from APT's dpkg implementation.";
+PyTypeObject PyPackageManager2_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.PackageManager", // tp_name
+ sizeof(CppPyObject<PyPkgManager*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<PyPkgManager*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ packagemanager2_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgManager2Methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyPackageManager_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgManagerNew, // tp_new
+};
/*}}}*/
diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc
index aad3ef7e..4c889129 100644
--- a/python/pkgsrcrecords.cc
+++ b/python/pkgsrcrecords.cc
@@ -147,9 +147,9 @@ static PyObject *PkgSrcRecordsGetFiles(PyObject *Self,void*) {
PyObject *v;
for(unsigned int i=0;i<f.size();i++) {
- v = Py_BuildValue("(siss)",
+ v = Py_BuildValue("(sNss)",
f[i].MD5Hash.c_str(),
- f[i].Size,
+ MkPyNumber(f[i].Size),
f[i].Path.c_str(),
f[i].Type.c_str());
PyList_Append(List, v);
@@ -218,8 +218,10 @@ static PyObject *PkgSrcRecordsGetBuildDepends_old(PyObject *Self,void*) {
PyObject *v;
for(unsigned int i=0;i<bd.size();i++) {
- v = Py_BuildValue("(ssii)", bd[i].Package.c_str(),
- bd[i].Version.c_str(), bd[i].Op, bd[i].Type);
+ v = Py_BuildValue("(ssNN)", bd[i].Package.c_str(),
+ bd[i].Version.c_str(),
+ MkPyNumber(bd[i].Op),
+ MkPyNumber(bd[i].Type));
PyList_Append(List, v);
Py_DECREF(v);
}
diff --git a/python/policy.cc b/python/policy.cc
index 7eccb30c..b11e4dde 100644
--- a/python/policy.cc
+++ b/python/policy.cc
@@ -45,7 +45,7 @@ PyObject *policy_get_priority(PyObject *self, PyObject *arg) {
pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
if (PyObject_TypeCheck(arg, &PyPackage_Type)) {
pkgCache::PkgIterator pkg = GetCpp<pkgCache::PkgIterator>(arg);
- return Py_BuildValue("i", policy->GetPriority(pkg));
+ return MkPyNumber(policy->GetPriority(pkg));
} else {
PyErr_SetString(PyExc_TypeError,"Argument must be of Package().");
return 0;
diff --git a/python/progress.cc b/python/progress.cc
index 5700a1b6..bd3c2ad6 100644
--- a/python/progress.cc
+++ b/python/progress.cc
@@ -92,12 +92,12 @@ void PyOpProgress::Update()
setattr(callbackInst, "op", "s", Op.c_str());
setattr(callbackInst, "subop", "s", SubOp.c_str());
setattr(callbackInst, "major_change", "b", MajorChange);
- setattr(callbackInst, "percent", "f", Percent);
+ setattr(callbackInst, "percent", "N", MkPyNumber(Percent));
#ifdef COMPAT_0_7
setattr(callbackInst, "Op", "s", Op.c_str());
setattr(callbackInst, "subOp", "s", SubOp.c_str());
setattr(callbackInst, "majorChange", "b", MajorChange);
- PyObject *arglist = Py_BuildValue("(f)", Percent);
+ PyObject *arglist = Py_BuildValue("(N)", MkPyNumber(Percent));
RunSimpleCallback("update", arglist);
#else
RunSimpleCallback("update");
@@ -156,19 +156,19 @@ void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status)
// Added object file size and object partial size to
// parameters that are passed to updateStatus.
// -- Stephan
- PyObject *arglist = Py_BuildValue("(sssikk)", Itm.URI.c_str(),
+ PyObject *arglist = Py_BuildValue("(sssNNN)", Itm.URI.c_str(),
Itm.Description.c_str(),
Itm.ShortDesc.c_str(),
- status,
- Itm.Owner->FileSize,
- Itm.Owner->PartialSize);
+ MkPyNumber(status),
+ MkPyNumber(Itm.Owner->FileSize),
+ MkPyNumber(Itm.Owner->PartialSize));
RunSimpleCallback("update_status_full", arglist);
// legacy version of the interface
- arglist = Py_BuildValue("(sssi)", Itm.URI.c_str(), Itm.Description.c_str(),
- Itm.ShortDesc.c_str(), status);
+ arglist = Py_BuildValue("(sssN)", Itm.URI.c_str(), Itm.Description.c_str(),
+ Itm.ShortDesc.c_str(), MkPyNumber(status));
if(PyObject_HasAttrString(callbackInst, "updateStatus"))
RunSimpleCallback("updateStatus", arglist);
@@ -240,11 +240,11 @@ void PyFetchProgress::Start()
pkgAcquireStatus::Start();
#ifdef COMPAT_0_7
- setattr(callbackInst, "currentCPS", "d", 0);
- setattr(callbackInst, "currentBytes", "d", 0);
- setattr(callbackInst, "currentItems", "k", 0);
- setattr(callbackInst, "totalItems", "k", 0);
- setattr(callbackInst, "totalBytes", "d", 0);
+ setattr(callbackInst, "currentCPS", "N", MkPyNumber(0));
+ setattr(callbackInst, "currentBytes", "N", MkPyNumber(0));
+ setattr(callbackInst, "currentItems", "N", MkPyNumber(0));
+ setattr(callbackInst, "totalItems", "N", MkPyNumber(0));
+ setattr(callbackInst, "totalBytes", "N", MkPyNumber(0));
#endif
RunSimpleCallback("start");
@@ -280,14 +280,14 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
return false;
}
- setattr(callbackInst, "last_bytes", "d", LastBytes);
- setattr(callbackInst, "current_cps", "d", CurrentCPS);
- setattr(callbackInst, "current_bytes", "d", CurrentBytes);
- setattr(callbackInst, "total_bytes", "d", TotalBytes);
- setattr(callbackInst, "fetched_bytes", "d", FetchedBytes);
- setattr(callbackInst, "elapsed_time", "k", ElapsedTime);
- setattr(callbackInst, "current_items", "k", CurrentItems);
- setattr(callbackInst, "total_items", "k", TotalItems);
+ setattr(callbackInst, "last_bytes", "N", MkPyNumber(LastBytes));
+ setattr(callbackInst, "current_cps", "N", MkPyNumber(CurrentCPS));
+ setattr(callbackInst, "current_bytes", "N", MkPyNumber(CurrentBytes));
+ setattr(callbackInst, "total_bytes", "N", MkPyNumber(TotalBytes));
+ setattr(callbackInst, "fetched_bytes", "N", MkPyNumber(FetchedBytes));
+ setattr(callbackInst, "elapsed_time", "N", MkPyNumber(ElapsedTime));
+ setattr(callbackInst, "current_items", "N", MkPyNumber(CurrentItems));
+ setattr(callbackInst, "total_items", "N", MkPyNumber(TotalItems));
// New style
if (!PyObject_HasAttrString(callbackInst, "updateStatus")) {
@@ -313,12 +313,12 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
return true;
}
#ifdef COMPAT_0_7
- setattr(callbackInst, "currentCPS", "d", CurrentCPS);
- setattr(callbackInst, "currentBytes", "d", CurrentBytes);
- setattr(callbackInst, "totalBytes", "d", TotalBytes);
- setattr(callbackInst, "fetchedBytes", "d", FetchedBytes);
- setattr(callbackInst, "currentItems", "k", CurrentItems);
- setattr(callbackInst, "totalItems", "k", TotalItems);
+ setattr(callbackInst, "currentCPS", "N", MkPyNumber(CurrentCPS));
+ setattr(callbackInst, "currentBytes", "N", MkPyNumber(CurrentBytes));
+ setattr(callbackInst, "totalBytes", "N", MkPyNumber(TotalBytes));
+ setattr(callbackInst, "fetchedBytes", "N", MkPyNumber(FetchedBytes));
+ setattr(callbackInst, "currentItems", "N", MkPyNumber(CurrentItems));
+ setattr(callbackInst, "totalItems", "N", MkPyNumber(TotalItems));
// Go through the list of items and add active items to the
// activeItems vector.
map<pkgAcquire::Worker *, pkgAcquire::ItemDesc *> activeItemMap;
@@ -351,11 +351,11 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
pkgAcquire::Worker *worker = iter->first;
pkgAcquire::ItemDesc *itm = iter->second;
- PyObject *itmTuple = Py_BuildValue("(ssskk)", itm->URI.c_str(),
+ PyObject *itmTuple = Py_BuildValue("(sssNN)", itm->URI.c_str(),
itm->Description.c_str(),
itm->ShortDesc.c_str(),
- worker->TotalSize,
- worker->CurrentSize);
+ MkPyNumber(worker->TotalSize),
+ MkPyNumber(worker->CurrentSize));
PyTuple_SetItem(itemsTuple, tuplePos, itmTuple);
}
diff --git a/python/python-apt-helpers.cc b/python/python-apt-helpers.cc
index 7a0f20c4..079b93cf 100644
--- a/python/python-apt-helpers.cc
+++ b/python/python-apt-helpers.cc
@@ -52,7 +52,9 @@ NEW_FROM(PyHashString_FromCpp,&PyHashString_Type,HashString*)
NEW_FROM(PyIndexRecords_FromCpp,&PyIndexRecords_Type,indexRecords*)
NEW_FROM(PyMetaIndex_FromCpp,&PyMetaIndex_Type,metaIndex*)
NEW_FROM(PyPackage_FromCpp,&PyPackage_Type,pkgCache::PkgIterator)
+NEW_FROM(PyGroup_FromCpp,&PyGroup_Type,pkgCache::GrpIterator)
NEW_FROM(PyIndexFile_FromCpp,&PyIndexFile_Type,pkgIndexFile*)
+NEW_FROM(PyOrderList_FromCpp,&PyOrderList_Type,pkgOrderList*)
NEW_FROM(PyPackageFile_FromCpp,&PyPackageFile_Type,pkgCache::PkgFileIterator)
//NEW_FROM(PyPackageList_FromCpp,&PyPackageList_Type,PkgListStruct)
NEW_FROM(PyPackageManager_FromCpp,&PyPackageManager_Type,pkgPackageManager*)
diff --git a/python/python-apt.h b/python/python-apt.h
index b9fc9212..6f2a02df 100644
--- a/python/python-apt.h
+++ b/python/python-apt.h
@@ -167,6 +167,13 @@ struct _PyAptPkgAPIStruct {
PyObject* (*version_fromcpp)(pkgCache::VerIterator const &obj, bool Delete, PyObject *Owner);
pkgCache::VerIterator& (*version_tocpp)(PyObject *self);
+ PyTypeObject *group_type;
+ PyObject* (*group_fromcpp)(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::GrpIterator& (*group_tocpp)(PyObject *self);
+
+ PyTypeObject *orderlist_type;
+ PyObject* (*orderlist_fromcpp)(pkgOrderList* const &obj, bool Delete, PyObject *Owner);
+ pkgOrderList*& (*orderlist_tocpp)(PyObject *self);
};
// Checking macros.
@@ -184,6 +191,7 @@ struct _PyAptPkgAPIStruct {
# define PyDependency_Check(op) PyObject_TypeCheck(op, &PyDependency_Type)
# define PyDependencyList_Check(op) PyObject_TypeCheck(op, &PyDependencyList_Type)
# define PyDescription_Check(op) PyObject_TypeCheck(op, &PyDescription_Type)
+# define PyGroup_Check(op) PyObject_TypeCheck(op, &PyGroup_Type)
# define PyHashes_Check(op) PyObject_TypeCheck(op, &PyHashes_Type)
# define PyHashString_Check(op) PyObject_TypeCheck(op, &PyHashString_Type)
# define PyIndexRecords_Check(op) PyObject_TypeCheck(op, &PyIndexRecords_Type)
@@ -217,12 +225,14 @@ struct _PyAptPkgAPIStruct {
# define PyDependencyList_CheckExact(op) (op->op_type == &PyDependencyList_Type)
# define PyDescription_CheckExact(op) (op->op_type == &PyDescription_Type)
# define PyHashes_CheckExact(op) (op->op_type == &PyHashes_Type)
+# define PyGroup_CheckExact(op) (op->op_type == &PyGroup_Type)
# define PyHashString_CheckExact(op) (op->op_type == &PyHashString_Type)
# define PyIndexRecords_CheckExact(op) (op->op_type == &PyIndexRecords_Type)
# define PyMetaIndex_CheckExact(op) (op->op_type == &PyMetaIndex_Type)
# define PyPackage_CheckExact(op) (op->op_type == &PyPackage_Type)
# define PyPackageFile_CheckExact(op) (op->op_type == &PyPackageFile_Type)
# define PyIndexFile_CheckExact(op) (op->op_type == &PyIndexFile_Type)
+# define PyOrderList_CheckExact(op) (op->op_type == &PyOrderList_Type)
# define PyPackageList_CheckExact(op) (op->op_type == &PyPackageList_Type)
# define PyPackageManager_CheckExact(op) (op->op_type == &PyPackageManager_Type)
# define PyPackageRecords_CheckExact(op) (op->op_type == &PyPackageRecords_Type)
@@ -260,6 +270,7 @@ static int import_apt_pkg(void) {
# define PyDependency_Type *(_PyAptPkg_API->dependency_type)
# define PyDependencyList_Type *(_PyAptPkg_API->dependencylist_type)
# define PyDescription_Type *(_PyAptPkg_API->description_type)
+# define PyGroup_Type *(_PyAptPkg_API->group_type)
# define PyHashes_Type *(_PyAptPkg_API->hashes_type)
# define PyHashString_Type *(_PyAptPkg_API->hashstring_type)
# define PyIndexRecords_Type *(_PyAptPkg_API->indexrecords_type)
@@ -267,6 +278,7 @@ static int import_apt_pkg(void) {
# define PyPackage_Type *(_PyAptPkg_API->package_type)
# define PyPackageFile_Type *(_PyAptPkg_API->packagefile_type)
# define PyIndexFile_Type *(_PyAptPkg_API->packageindexfile_type)
+# define PyOrderList_Type *(_PyAptPkg_API->orderlist_type)
# define PyPackageList_Type *(_PyAptPkg_API->packagelist_type)
# define PyPackageManager_Type *(_PyAptPkg_API->packagemanager_type)
# define PyPackageRecords_Type *(_PyAptPkg_API->packagerecords_type)
@@ -292,6 +304,7 @@ static int import_apt_pkg(void) {
# define PyDependency_ToCpp _PyAptPkg_API->dependency_tocpp
# define PyDependencyList_ToCpp _PyAptPkg_API->dependencylist_tocpp // NULL
# define PyDescription_ToCpp _PyAptPkg_API->description_tocpp
+# define PyGroup_ToCpp _PyAptPkg_API->group_tocpp
# define PyHashes_ToCpp _PyAptPkg_API->hashes_tocpp
# define PyHashString_ToCpp _PyAptPkg_API->hashstring_tocpp
# define PyIndexRecords_ToCpp _PyAptPkg_API->indexrecords_tocpp
@@ -299,6 +312,7 @@ static int import_apt_pkg(void) {
# define PyPackage_ToCpp _PyAptPkg_API->package_tocpp
# define PyPackageFile_ToCpp _PyAptPkg_API->packagefile_tocpp
# define PyIndexFile_ToCpp _PyAptPkg_API->packageindexfile_tocpp
+# define PyOrderList_ToCpp _PyAptPkg_API->orderlist_tocpp // NULL
# define PyPackageList_ToCpp _PyAptPkg_API->packagelist_tocpp // NULL
# define PyPackageManager_ToCpp _PyAptPkg_API->packagemanager_tocpp
# define PyPackageRecords_ToCpp _PyAptPkg_API->packagerecords_tocpp
@@ -324,6 +338,7 @@ static int import_apt_pkg(void) {
# define PyDependency_FromCpp _PyAptPkg_API->dependency_fromcpp
# define PyDependencyList_FromCpp _PyAptPkg_API->dependencylist_fromcpp // NULL
# define PyDescription_FromCpp _PyAptPkg_API->description_fromcpp
+# define PyGroup_FromCpp _PyAptPkg_API->group_fromcpp
# define PyHashes_FromCpp _PyAptPkg_API->hashes_fromcpp
# define PyHashString_FromCpp _PyAptPkg_API->hashstring_fromcpp
# define PyIndexRecords_FromCpp _PyAptPkg_API->indexrecords_fromcpp
@@ -331,6 +346,7 @@ static int import_apt_pkg(void) {
# define PyPackage_FromCpp _PyAptPkg_API->package_fromcpp
# define PyPackageFile_FromCpp _PyAptPkg_API->packagefile_fromcpp
# define PyIndexFile_FromCpp _PyAptPkg_API->packageindexfile_fromcpp
+# define PyOrderList_FromCpp _PyAptPkg_API->orderlist_fromcpp // NULL
# define PyPackageList_FromCpp _PyAptPkg_API->packagelist_fromcpp // NULL
# define PyPackageManager_FromCpp _PyAptPkg_API->packagemanager_fromcpp
# define PyPackageRecords_FromCpp _PyAptPkg_API->packagerecords_fromcpp
diff --git a/python/string.cc b/python/string.cc
index 6a1ce4e2..7abe2d17 100644
--- a/python/string.cc
+++ b/python/string.cc
@@ -28,11 +28,11 @@ PyObject *Python(PyObject *Self,PyObject *Args) \
return CppPyString(CFunc(Str)); \
}
-#define MkInt(Python,CFunc) \
+#define MkInt(Python,CFunc, ctype, pytype) \
PyObject *Python(PyObject *Self,PyObject *Args) \
{ \
- int Val = 0; \
- if (PyArg_ParseTuple(Args,"i",&Val) == 0) \
+ ctype Val = 0; \
+ if (PyArg_ParseTuple(Args,pytype,&Val) == 0) \
return 0; \
return CppPyString(CFunc(Val)); \
}
@@ -56,8 +56,8 @@ PyObject *StrBase64Encode(PyObject *Self,PyObject *Args) {
MkStr(StrURItoFileName,URItoFileName);
//MkFloat(StrSizeToStr,SizeToStr);
-MkInt(StrTimeToStr,TimeToStr);
-MkInt(StrTimeRFC1123,TimeRFC1123);
+MkInt(StrTimeToStr,TimeToStr, unsigned long, "k");
+MkInt(StrTimeRFC1123,TimeRFC1123, long long, "L");
/*}}}*/
// Other String functions /*{{{*/
@@ -91,7 +91,7 @@ PyObject *StrStringToBool(PyObject *Self,PyObject *Args)
char *Str = 0;
if (PyArg_ParseTuple(Args,"s",&Str) == 0)
return 0;
- return Py_BuildValue("i",StringToBool(Str));
+ return MkPyNumber(StringToBool(Str));
}
PyObject *StrStrToTime(PyObject *Self,PyObject *Args)
@@ -107,7 +107,7 @@ PyObject *StrStrToTime(PyObject *Self,PyObject *Args)
return Py_None;
}
- return Py_BuildValue("i",Result);
+ return MkPyNumber(Result);
}
PyObject *StrCheckDomainList(PyObject *Self,PyObject *Args)
diff --git a/python/tag.cc b/python/tag.cc
index 44cd06af..94554400 100644
--- a/python/tag.cc
+++ b/python/tag.cc
@@ -247,7 +247,7 @@ static PyObject *TagSecBytes(PyObject *Self,PyObject *Args)
if (PyArg_ParseTuple(Args,"") == 0)
return 0;
- return Py_BuildValue("i",GetCpp<pkgTagSection>(Self).size());
+ return MkPyNumber(GetCpp<pkgTagSection>(Self).size());
}
static PyObject *TagSecStr(PyObject *Self)
@@ -319,7 +319,8 @@ static PyObject *TagFileOffset(PyObject *Self,PyObject *Args)
{
if (PyArg_ParseTuple(Args,"") == 0)
return 0;
- return Py_BuildValue("i",((TagFileData *)Self)->Object.Offset());
+ return MkPyNumber(((TagFileData *)Self)->Object.Offset());
+
}
static char *doc_Jump =
diff --git a/python/tarfile.cc b/python/tarfile.cc
index 215d3a8c..cdfe0a7c 100644
--- a/python/tarfile.cc
+++ b/python/tarfile.cc
@@ -189,35 +189,35 @@ static PyObject *tarmember_get_linkname(PyObject *self, void *closure)
static PyObject *tarmember_get_mode(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<pkgDirStream::Item>(self).Mode);
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Mode);
}
static PyObject *tarmember_get_uid(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<pkgDirStream::Item>(self).UID);
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).UID);
}
static PyObject *tarmember_get_gid(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<pkgDirStream::Item>(self).GID);
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).GID);
}
static PyObject *tarmember_get_size(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<pkgDirStream::Item>(self).Size);
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Size);
}
static PyObject *tarmember_get_mtime(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<pkgDirStream::Item>(self).MTime);
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).MTime);
}
static PyObject *tarmember_get_major(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<pkgDirStream::Item>(self).Major);
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Major);
}
static PyObject *tarmember_get_minor(PyObject *self, void *closure)
{
- return Py_BuildValue("k", GetCpp<pkgDirStream::Item>(self).Minor);
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Minor);
}
static PyObject *tarmember_repr(PyObject *self)
diff --git a/setup.py b/setup.py
index 9c6eda60..eff78379 100644
--- a/setup.py
+++ b/setup.py
@@ -33,7 +33,8 @@ files = ['apt_pkgmodule.cc', 'acquire.cc', 'cache.cc', 'cdrom.cc',
'hashstring.cc', 'indexfile.cc', 'indexrecords.cc', 'metaindex.cc',
'pkgmanager.cc', 'pkgrecords.cc', 'pkgsrcrecords.cc', 'policy.cc',
'progress.cc', 'sourcelist.cc', 'string.cc', 'tag.cc',
- 'lock.cc', 'acquire-item.cc', 'python-apt-helpers.cc']
+ 'lock.cc', 'acquire-item.cc', 'python-apt-helpers.cc',
+ 'cachegroup.cc', 'orderlist.cc']
files = sorted(['python/' + fname for fname in files], key=lambda s: s[:-3])
apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"])
diff --git a/tests/test_apt_cache.py b/tests/test_apt_cache.py
index cccfc9c8..aaa9f601 100644
--- a/tests/test_apt_cache.py
+++ b/tests/test_apt_cache.py
@@ -48,9 +48,9 @@ class TestAptCache(unittest.TestCase):
# tons of seek operations
r = pkg.candidate.record
self.assertEqual(r['Package'], pkg.shortname)
- self.assert_('Version' in r)
- self.assert_(len(r['Description']) > 0)
- self.assert_(str(r).startswith('Package: %s\n' % pkg.shortname))
+ self.assertTrue('Version' in r)
+ self.assertTrue(len(r['Description']) > 0)
+ self.assertTrue(str(r).startswith('Package: %s\n' % pkg.shortname))
def test_get_provided_packages(self):
cache = apt.Cache()
@@ -70,7 +70,7 @@ class TestAptCache(unittest.TestCase):
def test_low_level_pkg_provides(self):
# low level cache provides list of the pkg
- cache = apt_pkg.Cache()
+ cache = apt_pkg.Cache(progress=None)
l = cache["mail-transport-agent"].provides_list
# arbitrary number, just needs to be higher enough
self.assertTrue(len(l), 5)
@@ -89,17 +89,17 @@ class TestAptCache(unittest.TestCase):
tmpdir = tempfile.mkdtemp()
dpkg_dir = os.path.join(tmpdir,"var","lib","dpkg")
os.makedirs(os.path.join(dpkg_dir,"updates"))
- open(os.path.join(dpkg_dir,"status"), "w")
+ open(os.path.join(dpkg_dir,"status"), "w").close()
apt_pkg.config.set("Dir::State::status",
os.path.join(dpkg_dir,"status"))
cache = apt.Cache()
# test empty
self.assertFalse(cache.dpkg_journal_dirty)
# that is ok, only [0-9] are dpkg jounral entries
- open(os.path.join(dpkg_dir,"updates","xxx"), "w")
+ open(os.path.join(dpkg_dir,"updates","xxx"), "w").close()
self.assertFalse(cache.dpkg_journal_dirty)
# that is a dirty journal
- open(os.path.join(dpkg_dir,"updates","000"), "w")
+ open(os.path.join(dpkg_dir,"updates","000"), "w").close()
self.assertTrue(cache.dpkg_journal_dirty)
# reset config value
apt_pkg.config.set("Dir::State::status", old_status)
@@ -121,20 +121,19 @@ class TestAptCache(unittest.TestCase):
apt_pkg.config.set("dir::etc::sourceparts", "xxx")
# main sources.list
sources_list = base_sources
- f=open(sources_list, "w")
- repo = os.path.abspath("./data/test-repo2")
- f.write("deb copy:%s /\n" % repo)
- f.close()
+ with open(sources_list, "w") as f:
+ repo = os.path.abspath("./data/test-repo2")
+ f.write("deb copy:%s /\n" % repo)
# test single sources.list fetching
sources_list = os.path.join(rootdir, "test.list")
- f=open(sources_list, "w")
- repo_dir = os.path.abspath("./data/test-repo")
- f.write("deb copy:%s /\n" % repo_dir)
- f.close()
+ with open(sources_list, "w") as f:
+ repo_dir = os.path.abspath("./data/test-repo")
+ f.write("deb copy:%s /\n" % repo_dir)
+
self.assertTrue(os.path.exists(sources_list))
# write marker to ensure listcleaner is not run
- open("./data/tmp/var/lib/apt/lists/marker", "w")
+ open("./data/tmp/var/lib/apt/lists/marker", "w").close()
# update a single sources.list
cache = apt.Cache()
diff --git a/tests/test_cache_invocation.py b/tests/test_cache_invocation.py
index 6f4014de..a89ef557 100644
--- a/tests/test_cache_invocation.py
+++ b/tests/test_cache_invocation.py
@@ -14,7 +14,7 @@ class TestCache(unittest.TestCase):
def test_wrong_invocation(self):
"""cache_invocation: Test wrong invocation."""
- apt_cache = apt_pkg.Cache(apt.progress.base.OpProgress())
+ apt_cache = apt_pkg.Cache(progress=None)
self.assertRaises(ValueError, apt_pkg.Cache, apt_cache)
self.assertRaises(ValueError, apt_pkg.Cache,
@@ -23,7 +23,7 @@ class TestCache(unittest.TestCase):
def test_proper_invocation(self):
"""cache_invocation: Test correct invocation."""
- apt_cache = apt_pkg.Cache(apt.progress.base.OpProgress())
+ apt_cache = apt_pkg.Cache(progress=None)
apt_depcache = apt_pkg.DepCache(apt_cache)
if __name__ == "__main__":
diff --git a/tests/test_configuration.py b/tests/test_configuration.py
new file mode 100644
index 00000000..80509cff
--- /dev/null
+++ b/tests/test_configuration.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2011 Julian Andres Klode <jak@debian.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of apt_pkg.Configuration"""
+import unittest
+
+import apt_pkg
+
+
+class TestConfiguration(unittest.TestCase):
+ """Test various configuration things"""
+
+ def setUp(self):
+ """Prepare the tests, create reference values..."""
+ apt_pkg.init_config()
+
+ def test_lp707416(self):
+ """configuration: Test empty arguments (LP: #707416)"""
+ self.assertRaises(ValueError, apt_pkg.parse_commandline,
+ apt_pkg.config,[], [])
+ self.assertRaises(SystemError, apt_pkg.parse_commandline,
+ apt_pkg.config,[], ["cmd", "--arg0"])
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_group.py b/tests/test_group.py
new file mode 100644
index 00000000..3c3a5b7a
--- /dev/null
+++ b/tests/test_group.py
@@ -0,0 +1,32 @@
+import unittest
+
+import apt_pkg
+
+
+class TestGroup(unittest.TestCase):
+
+ def setUp(self):
+ apt_pkg.init()
+ self.cache = apt_pkg.Cache(progress=None)
+
+ def test_pkgingroup(self):
+ """Check that each package belongs to the corresponding group"""
+ for pkg in self.cache.packages:
+ group = apt_pkg.Group(self.cache, pkg.name)
+ assert any(pkg.id == p.id for p in group)
+
+ def test_iteration(self):
+ """Check that iteration works correctly."""
+ for pkg in self.cache.packages:
+ group = apt_pkg.Group(self.cache, pkg.name)
+
+ list(group) == list(group)
+
+
+ def test_cache_groups(self):
+ """group: Iterate over all groups"""
+ assert len(list(self.cache.groups)) == self.cache.group_count
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_hashes.py b/tests/test_hashes.py
index e0aabe09..660373cb 100644
--- a/tests/test_hashes.py
+++ b/tests/test_hashes.py
@@ -82,11 +82,16 @@ class TestHashString(unittest.TestCase):
def setUp(self):
"""Prepare the test by reading the file."""
- self.hashes = apt_pkg.Hashes(open(apt_pkg.__file__))
+ self.file = open(apt_pkg.__file__)
+ self.hashes = apt_pkg.Hashes(self.file)
self.md5 = apt_pkg.HashString("MD5Sum", self.hashes.md5)
self.sha1 = apt_pkg.HashString("SHA1", self.hashes.sha1)
self.sha256 = apt_pkg.HashString("SHA256", self.hashes.sha256)
+ def tearDown(self):
+ """Cleanup, Close the file object used for the tests."""
+ self.file.close()
+
def test_md5(self):
"""hashes: Test apt_pkg.HashString().md5"""
self.assertEqual("MD5Sum:%s" % self.hashes.md5, str(self.md5))
diff --git a/tests/test_progress.py b/tests/test_progress.py
index ffab5bc0..73853dfa 100644
--- a/tests/test_progress.py
+++ b/tests/test_progress.py
@@ -34,7 +34,8 @@ class TestProgress(unittest.TestCase):
apt_pkg.config.set("Dir::state::lists", "./tmp")
# create artifical line
deb_line = "deb file:%s/data/fake-packages/ /\n" % basedir
- open("fetch_sources.list","w").write(deb_line)
+ with open("fetch_sources.list","w") as fobj:
+ fobj.write(deb_line)
apt_pkg.config.set("Dir::Etc::sourcelist", "fetch_sources.list")
def test_acquire_progress(self):