summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vogt <egon@bottom>2006-07-26 16:59:37 +0200
committerMichael Vogt <egon@bottom>2006-07-26 16:59:37 +0200
commit70c850f4910cfcb6a825c67f577d8bc554612044 (patch)
tree5321c9aa207b8743c7cca63e2b7b05609fbcddf7
parentf701fc174a88d8f2b418a032571ff40ed6fd56e6 (diff)
parent6fc084d34105f336fdf090e2dd45e402e25cfc57 (diff)
downloadpython-apt-70c850f4910cfcb6a825c67f577d8bc554612044.tar.gz
* merged from the auto-mark branch
-rw-r--r--TODO4
-rw-r--r--apt/cache.py144
-rw-r--r--apt/package.py97
-rw-r--r--apt/progress.py84
-rw-r--r--debian/changelog97
-rw-r--r--debian/compat1
-rw-r--r--debian/control41
-rwxr-xr-xdebian/rules26
-rw-r--r--doc/examples/acquire.py92
-rw-r--r--doc/examples/action.py3
-rw-r--r--doc/examples/all_deps.py34
-rwxr-xr-xdoc/examples/build-deps.py2
-rwxr-xr-xdoc/examples/deb_inspect.py12
-rwxr-xr-xdoc/examples/dependant-pkgs.py36
-rwxr-xr-xdoc/examples/gui-inst.py57
-rw-r--r--doc/examples/indexfile.py21
-rw-r--r--doc/examples/inst.py70
-rwxr-xr-xdoc/examples/print_uris.py22
-rw-r--r--doc/examples/progress.py17
-rw-r--r--doc/examples/sources.py6
-rw-r--r--python/acquire.cc274
-rw-r--r--python/apt_instmodule.cc38
-rw-r--r--python/apt_pkgmodule.cc7
-rw-r--r--python/apt_pkgmodule.h16
-rw-r--r--python/cache.cc27
-rw-r--r--python/cdrom.cc6
-rw-r--r--python/depcache.cc79
-rw-r--r--python/indexfile.cc92
-rw-r--r--python/makefile3
-rw-r--r--python/pkgmanager.cc135
-rw-r--r--python/pkgrecords.cc18
-rw-r--r--python/pkgrecords.h10
-rw-r--r--python/pkgsrcrecords.cc31
-rw-r--r--python/progress.cc42
-rw-r--r--python/sourcelist.cc57
-rw-r--r--python/tar.cc4
-rw-r--r--setup.py18
-rwxr-xr-xtests/memleak.py42
-rw-r--r--tests/pkgsrcrecords.py2
39 files changed, 1521 insertions, 246 deletions
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..f3f6a995
--- /dev/null
+++ b/TODO
@@ -0,0 +1,4 @@
+* apt.Package:
+ - change all candidateInstalledSize() to installSize(useCandidate=True)
+ same for candidateOrigin() (see downloadable for a example).
+ - might be better to have "Package.candidate.{downloadable,size,etc}
diff --git a/apt/cache.py b/apt/cache.py
index 973291c0..690510e3 100644
--- a/apt/cache.py
+++ b/apt/cache.py
@@ -21,8 +21,9 @@
import apt_pkg
from apt import Package
-from apt.progress import OpTextProgress
-from UserDict import UserDict
+import apt.progress
+import os
+import sys
class Cache(object):
""" Dictionary-like package cache
@@ -30,10 +31,14 @@ class Cache(object):
dictionary
"""
- def __init__(self, progress=None):
+ def __init__(self, progress=None, rootdir=None):
self._callbacks = {}
self.open(progress)
+ if rootdir:
+ apt_pkg.Config.Set("Dir", rootdir)
+ apt_pkg.Config.Set("Dir::State::status", rootdir + "/var/lib/dpkg/status")
+
def _runCallbacks(self, name):
""" internal helper to run a callback """
if self._callbacks.has_key(name):
@@ -48,6 +53,8 @@ class Cache(object):
self._cache = apt_pkg.GetCache(progress)
self._depcache = apt_pkg.GetDepCache(self._cache)
self._records = apt_pkg.GetPkgRecords(self._cache)
+ self._list = apt_pkg.GetPkgSourceList()
+ self._list.ReadMainList()
self._dict = {}
# build the packages dict
@@ -62,7 +69,8 @@ class Cache(object):
# drop stuff with no versions (cruft)
if len(pkg.VersionList) > 0:
self._dict[pkg.Name] = Package(self._cache, self._depcache,
- self._records, self, pkg)
+ self._records, self._list,
+ self, pkg)
i += 1
if progress != None:
@@ -79,11 +87,7 @@ class Cache(object):
raise StopIteration
def has_key(self, key):
- try:
- self._dict[key]
- except KeyError:
- return False
- return True
+ return self._dict.has_key(key)
def __len__(self):
return len(self._dict)
@@ -109,15 +113,102 @@ class Cache(object):
self._depcache.Upgrade(distUpgrade)
self.cachePostChange()
- def update(self, fetchProgress=None, opProgress=None):
- if(opProgress != None):
- self._cache.Update(fetchProgress, opProgress);
- else:
- self._cache.Update(fetchProgress);
+ def _runFetcher(self, fetcher):
+ # do the actual fetching
+ res = fetcher.Run()
+
+ # now check the result (this is the code from apt-get.cc)
+ failed = False
+ transient = False
+ errMsg = ""
+ for item in fetcher.Items:
+ if item.Status == item.StatDone:
+ continue
+ if item.StatIdle:
+ transient = True
+ continue
+ errMsg += "Failed to fetch %s %s\n" % (item.DescURI,item.ErrorText)
+ failed = True
+
+ # we raise a exception if the download failed
+ if failed:
+ raise IOError, errMsg
+ return res
+
+ def _fetchArchives(self, fetcher, pm):
+ """ fetch the needed archives """
+
+ # get lock
+ lockfile = apt_pkg.Config.FindDir("Dir::Cache::Archives") + "lock"
+ lock = apt_pkg.GetLock(lockfile)
+ if lock < 0:
+ raise IOError, "Failed to lock %s" % lockfile
+
+ try:
+ # this may as well throw a SystemError exception
+ if not pm.GetArchives(fetcher, self._list, self._records):
+ return False
+ # now run the fetcher, throw exception if something fails to be
+ # fetched
+ return self._runFetcher(fetcher)
+ finally:
+ os.close(lock)
+
+ def update(self, fetchProgress=None):
+ lockfile = apt_pkg.Config.FindDir("Dir::State::Lists") + "lock"
+ lock = apt_pkg.GetLock(lockfile)
+ if lock < 0:
+ raise IOError, "Failed to lock %s" % lockfile
- def commit(self, fprogress, iprogress):
+ try:
+ if fetchProgress == None:
+ fetchProgress = apt.progress.FetchProgress()
+ fetcher = apt_pkg.GetAcquire(fetchProgress)
+ # this can throw a exception
+ self._list.GetIndexes(fetcher)
+ # now run the fetcher, throw exception if something fails to be
+ # fetched
+ if self._runFetcher(fetcher) == fetcher.ResultContinue:
+ return True
+ return False
+ finally:
+ os.close(lock)
+
+ def installArchives(self, pm, installProgress):
+ installProgress.startUpdate()
+ res = installProgress.run(pm)
+ installProgress.finishUpdate()
+ return res
+
+ def commit(self, fetchProgress=None, installProgress=None):
""" Apply the marked changes to the cache """
- self._depcache.Commit(fprogress, iprogress)
+ # FIXME:
+ # use the new acquire/pkgmanager interface here,
+ # raise exceptions when a download or install fails
+ # and send proper error strings to the application.
+ # Current a failed download will just display "error"
+ # which is less than optimal!
+
+ if fetchProgress == None:
+ fetchProgress = apt.progress.FetchProgress()
+ if installProgress == None:
+ installProgress = apt.progress.InstallProgress()
+
+ pm = apt_pkg.GetPackageManager(self._depcache)
+ fetcher = apt_pkg.GetAcquire(fetchProgress)
+ while True:
+ # fetch archives first
+ res = self._fetchArchives(fetcher, pm)
+
+ # then install
+ res = self.installArchives(pm, installProgress)
+ if res == pm.ResultCompleted:
+ break
+ if res == pm.ResultFailed:
+ raise SystemError, "installArchives() failed"
+ # reload the fetcher for media swaping
+ fetcher.Shutdown()
+ return (res == pm.ResultCompleted)
# cache changes
def cachePostChange(self):
@@ -131,7 +222,7 @@ class Cache(object):
def connect(self, name, callback):
""" connect to a signal, currently only used for
- cache_{post,pre}_changed """
+ cache_{post,pre}_{changed,open} """
if not self._callbacks.has_key(name):
self._callbacks[name] = []
self._callbacks[name].append(callback)
@@ -177,11 +268,7 @@ class FilteredCache(object):
return self._filtered.keys()
def has_key(self, key):
- try:
- self._filtered[key]
- except KeyError:
- return False
- return True
+ return self._filtered.has_key(key)
def _reapplyFilter(self):
" internal helper to refilter "
@@ -228,7 +315,7 @@ def cache_post_changed():
if __name__ == "__main__":
print "Cache self test"
apt_pkg.init()
- c = Cache(OpTextProgress())
+ c = Cache(apt.progress.OpTextProgress())
c.connect("cache_pre_change", cache_pre_changed)
c.connect("cache_post_change", cache_post_changed)
print c.has_key("aptitude")
@@ -246,6 +333,17 @@ if __name__ == "__main__":
#print p.name
x = p.name
+
+ # see if fetching works
+ for d in ["/tmp/pytest", "/tmp/pytest/partial"]:
+ if not os.path.exists(d):
+ os.mkdir(d)
+ apt_pkg.Config.Set("Dir::Cache::Archives","/tmp/pytest")
+ pm = apt_pkg.GetPackageManager(c._depcache)
+ fetcher = apt_pkg.GetAcquire(apt.progress.TextFetchProgress())
+ c._fetchArchives(fetcher, pm)
+ #sys.exit(1)
+
print "Testing filtered cache (argument is old cache)"
f = FilteredCache(c)
f.cache.connect("cache_pre_change", cache_pre_changed)
diff --git a/apt/package.py b/apt/package.py
index 9749da52..0d1145ea 100644
--- a/apt/package.py
+++ b/apt/package.py
@@ -19,18 +19,22 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
-import apt_pkg, string
+import apt_pkg
+import sys
import random
+import string
+
class Package(object):
""" This class represents a package in the cache
"""
- def __init__(self, cache, depcache, records, pcache, pkgiter):
+ def __init__(self, cache, depcache, records, sourcelist, pcache, pkgiter):
""" Init the Package object """
self._cache = cache # low level cache
self._depcache = depcache
self._records = records
self._pkg = pkgiter
+ self._list = sourcelist # sourcelist
self._pcache = pcache # python cache in cache.py
pass
@@ -45,14 +49,14 @@ class Package(object):
# check if we found a version
if ver == None:
- print "No version for: %s (Candiate: %s)" % (self._pkg.Name, UseCandidate)
+ #print "No version for: %s (Candidate: %s)" % (self._pkg.Name, UseCandidate)
return False
if ver.FileList == None:
print "No FileList for: %s " % self._pkg.Name()
return False
- file, index = ver.FileList.pop(0)
- self._records.Lookup((file,index))
+ f, index = ver.FileList.pop(0)
+ self._records.Lookup((f,index))
return True
@@ -90,9 +94,29 @@ class Package(object):
return None
candidateVersion = property(candidateVersion)
+ def _downloadable(self, useCandidate=True):
+ """ helper, return if the version is downloadable """
+ if useCandidate:
+ ver = self._depcache.GetCandidateVer(self._pkg)
+ else:
+ ver = self._pkg.CurrentVer
+ if ver == None:
+ return False
+ return ver.Downloadable
+ def candidateDownloadable(self):
+ " returns if the canidate is downloadable "
+ return self._downloadable(useCandidate=True)
+ candidateDownloadable = property(candidateDownloadable)
+
+ def installedDownloadable(self):
+ " returns if the installed version is downloadable "
+ return self._downloadable(useCandidate=False)
+ installedDownloadable = property(installedDownloadable)
+
def sourcePackageName(self):
""" Return the source package name as string """
- self._lookupRecord()
+ if not self._lookupRecord():
+ return None
src = self._records.SourcePkg
if src != "":
return src
@@ -125,13 +149,15 @@ class Package(object):
def summary(self):
""" Return the short description (one line summary) """
- self._lookupRecord()
+ if not self._lookupRecord():
+ return ""
return self._records.ShortDesc
summary = property(summary)
def description(self, format=True):
""" Return the formated long description """
- self._lookupRecord()
+ if not self._lookupRecord():
+ return ""
desc = ""
for line in string.split(self._records.LongDesc, "\n"):
tmp = string.strip(line)
@@ -144,7 +170,8 @@ class Package(object):
def rawDescription(self):
""" return the long description (raw)"""
- self._lookupRecord()
+ if not self._lookupRecord():
+ return ""
return self._records.LongDesc
rawDescription = property(rawDescription)
@@ -215,12 +242,33 @@ class Package(object):
installedSize = property(installedSize)
# canidate origin
+ class Origin:
+ def __init__(self, pkg, VerFileIter):
+ self.component = VerFileIter.Component
+ self.archive = VerFileIter.Archive
+ self.origin = VerFileIter.Origin
+ self.label = VerFileIter.Label
+ self.site = VerFileIter.Site
+ # check the trust
+ indexfile = pkg._list.FindIndex(VerFileIter)
+ if indexfile and indexfile.IsTrusted:
+ self.trusted = True
+ else:
+ self.trusted = False
+ def __repr__(self):
+ return "component: '%s' archive: '%s' origin: '%s' label: '%s' " \
+ "site '%s' isTrusted: '%s'"% (self.component, self.archive,
+ self.origin, self.label,
+ self.site, self.trusted)
+
def candidateOrigin(self):
ver = self._depcache.GetCandidateVer(self._pkg)
- (VerFileIter,index) = ver.FileList.pop()
- print len(VerFileIter)
- print VerFileIter
- return VerFileIter.Component
+ if not ver:
+ return None
+ origins = []
+ for (verFileIter,index) in ver.FileList:
+ origins.append(self.Origin(self, verFileIter))
+ return origins
candidateOrigin = property(candidateOrigin)
# depcache actions
@@ -242,10 +290,12 @@ class Package(object):
Fix.InstallProtect()
Fix.Resolve()
self._pcache.cachePostChange()
- def markInstall(self, autoFix=True):
- """ mark a package for install. Run the resolver if autoFix is set """
+ def markInstall(self, autoFix=True, autoInst=True):
+ """ mark a package for install. Run the resolver if autoFix is set,
+ automatically install required dependencies if autoInst is set
+ """
self._pcache.cachePreChange()
- self._depcache.MarkInstall(self._pkg)
+ self._depcache.MarkInstall(self._pkg, autoInst)
# try to fix broken stuff
if autoFix and self._depcache.BrokenCount > 0:
fixer = apt_pkg.GetPkgProblemResolver(self._depcache)
@@ -256,9 +306,10 @@ class Package(object):
def markUpgrade(self):
""" mark a package for upgrade """
if self.isUpgradable:
- self.MarkInstall()
- # FIXME: we may want to throw a exception here
- sys.stderr.write("MarkUpgrade() called on a non-upgrable pkg")
+ self.markInstall()
+ else:
+ # FIXME: we may want to throw a exception here
+ sys.stderr.write("MarkUpgrade() called on a non-upgrable pkg: '%s'\n" %self._pkg.Name)
def commit(self, fprogress, iprogress):
""" commit the changes, need a FetchProgress and InstallProgress
@@ -274,16 +325,18 @@ if __name__ == "__main__":
cache = apt_pkg.GetCache()
depcache = apt_pkg.GetDepCache(cache)
records = apt_pkg.GetPkgRecords(cache)
+ sourcelist = apt_pkg.GetPkgSourceList()
- iter = cache["apt-utils"]
- pkg = Package(cache, depcache, records, None, iter)
+ pkgiter = cache["apt-utils"]
+ pkg = Package(cache, depcache, records, sourcelist, None, pkgiter)
print "Name: %s " % pkg.name
print "ID: %s " % pkg.id
print "Priority (Candidate): %s " % pkg.priority
print "Priority (Installed): %s " % pkg.installedPriority
print "Installed: %s " % pkg.installedVersion
print "Candidate: %s " % pkg.candidateVersion
- print "CandiateOrigin: %s" % pkg.candidateOrigin
+ print "CandidateDownloadable: %s" % pkg.candidateDownloadable
+ print "CandidateOrigins: %s" % pkg.candidateOrigin
print "SourcePkg: %s " % pkg.sourcePackageName
print "Section: %s " % pkg.section
print "Summary: %s" % pkg.summary
diff --git a/apt/progress.py b/apt/progress.py
index 86cd6594..4119067c 100644
--- a/apt/progress.py
+++ b/apt/progress.py
@@ -19,9 +19,9 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
-import sys
+import sys, apt_pkg, os, fcntl, string, re
-class OpProgress:
+class OpProgress(object):
""" Abstract class to implement reporting on cache opening
Subclass this class to implement simple Operation progress reporting
"""
@@ -62,6 +62,8 @@ class FetchProgress(object):
dlIgnored : "Ignored"}
def __init__(self):
+ self.eta = 0.0
+ self.percent = 0.0
pass
def start(self):
@@ -104,7 +106,7 @@ class TextFetchProgress(FetchProgress):
sys.stdout.flush()
return True
def stop(self):
- print "\rDone "
+ print "\rDone downloading "
def mediaChange(self, medium, drive):
""" react to media change events """
res = True;
@@ -115,7 +117,7 @@ class TextFetchProgress(FetchProgress):
res = false;
return res
-class InstallProgress:
+class DumbInstallProgress(object):
""" Report the install progress
Subclass this class to implement install progress reporting
"""
@@ -123,11 +125,85 @@ class InstallProgress:
pass
def startUpdate(self):
pass
+ def run(self, pm):
+ return pm.DoInstall()
def finishUpdate(self):
pass
def updateInterface(self):
pass
+class InstallProgress(DumbInstallProgress):
+ """ A InstallProgress that is pretty useful.
+ It supports the attributes 'percent' 'status' and callbacks
+ for the dpkg errors and conffiles and status changes
+ """
+ def __init__(self):
+ DumbInstallProgress.__init__(self)
+ (read, write) = os.pipe()
+ self.writefd=write
+ self.statusfd = os.fdopen(read, "r")
+ fcntl.fcntl(self.statusfd.fileno(), fcntl.F_SETFL,os.O_NONBLOCK)
+ self.read = ""
+ self.percent = 0.0
+ self.status = ""
+ def error(self, pkg, errormsg):
+ " called when a error is detected during the install "
+ pass
+ def conffile(self,current,new):
+ " called when a conffile question from dpkg is detected "
+ pass
+ def statusChange(self, pkg, percent, status):
+ " called when the status changed "
+ pass
+ def updateInterface(self):
+ if self.statusfd != None:
+ try:
+ while not self.read.endswith("\n"):
+ self.read += os.read(self.statusfd.fileno(),1)
+ except OSError, (errno,errstr):
+ # resource temporarly unavailable is ignored
+ if errno != 11:
+ print errstr
+ if self.read.endswith("\n"):
+ s = self.read
+ #print s
+ (status, pkg, percent, status_str) = string.split(s, ":")
+ #print "percent: %s %s" % (pkg, float(percent)/100.0)
+ if status == "pmerror":
+ self.error(pkg,status_str)
+ elif status == "pmconffile":
+ # we get a string like this:
+ # 'current-conffile' 'new-conffile' useredited distedited
+ match = re.compile("\s*\'(.*)\'\s*\'(.*)\'.*").match(status_str)
+ if match:
+ self.conffile(match.group(1), match.group(2))
+ elif status == "pmstatus":
+ if float(percent) != self.percent or \
+ status_str != self.status:
+ self.statusChange(pkg, float(percent), status_str.strip())
+ self.percent = float(percent)
+ self.status = string.strip(status_str)
+ self.read = ""
+
+ def fork(self):
+ return os.fork()
+ def waitChild(self):
+ while True:
+ (pid, res) = os.waitpid(self.child_pid,os.WNOHANG)
+ if pid == self.child_pid:
+ break
+ self.updateInterface()
+ return os.WEXITSTATUS(res)
+ def run(self, pm):
+ pid = self.fork()
+ if pid == 0:
+ # child
+ res = pm.DoInstall(self.writefd)
+ sys.exit(res)
+ self.child_pid = pid
+ res = self.waitChild()
+ return res
+
class CdromProgress:
""" Report the cdrom add progress
Subclass this class to implement cdrom add progress reporting
diff --git a/debian/changelog b/debian/changelog
index a31244bb..d9b428bd 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,96 @@
+python-apt (0.6.19) unstable; urgency=low
+
+ [ Michael Vogt ]
+ * doc/examples/print_uris.py:
+ - added a example to show how the indexfile.ArchiveURI() can be used
+ with binary packages
+
+ [ Otavio Salvador ]
+ * apt/cache.py:
+ - fix commit doc string to also cite the open related callbacks
+ - allow change of rootdir for APT database loading
+
+ --
+
+python-apt (0.6.18) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Update for the new Python policy. Closes: #373512
+
+ -- Raphael Hertzog <hertzog@debian.org> Sat, 17 Jun 2006 15:09:28 +0200
+
+python-apt (0.6.17) unstable; urgency=low
+
+ * apt/progress.py:
+ - initialize FetchProgress.eta with the correct type
+ - strip the staus str before passing it to InstallProgress.statusChanged()
+ - added InstallProgress.statusChange(pkg, percent, status)
+ - make DumbInstallProgress a new-style class
+ (thanks to kamion for the suggestions)
+ - fix various pychecker warnings
+ * apt/cache.py:
+ - return useful values on Cache.update()
+ - Release locks on failure (thanks to Colin Watson)
+ - fix various pychecker warnings
+ * apt/package.py:
+ - fix various pychecker warnings
+ - check if looupRecords succeeded
+ - fix bug in the return statement of _downloadable()
+ * apt/cache.py:
+ * python/srcrecords.cc:
+ - add "Restart" method
+ - don't run auto "Restart" before performing a Lookup
+ - fix the initalization (no need to pass a PkgCacheType to the records)
+ - added "Index" attribute
+ * python/indexfile.cc:
+ - added ArchiveURI() method
+
+ -- Michael Vogt <mvo@debian.org> Mon, 8 May 2006 22:34:58 +0200
+
+python-apt (0.6.16.2) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * debian/control:
+ + Replaces: python-apt (<< 0.6.11), instead of Conflicts which is not
+ correct here. (closes: #308586).
+
+ -- Pierre Habouzit <madcoder@debian.org> Fri, 14 Apr 2006 19:30:51 +0200
+
+python-apt (0.6.16.1) unstable; urgency=low
+
+ * memleak fixed when pkgCache objects are deallocated
+ * typos fixed (thanks to Gustavo Franco)
+ * pkgRecords.Record added to get raw record data
+ * python/cache.cc: "key" in pkgCache::VerIterator.DependsList[key] is
+ no longer locale specific but always english
+
+ -- Michael Vogt <mvo@debian.org> Wed, 22 Feb 2006 10:41:13 +0100
+
+python-apt (0.6.16) unstable; urgency=low
+
+ * added GetPkgAcqFile to queue individual file downloads with the
+ system (dosn't make use of the improved pkgAcqFile yet)
+ * added SourceList.GetIndexes()
+ * rewrote apt.cache.update() to use the improved aquire interface
+ * apt/ API change: apt.Package.candidateOrigin returns a list of origins
+ now instead of a single one
+ * apt_pkg.Cdrom.Add() returns a boolean now, CdromProgress has totalSteps
+ * added support for pkgIndexFile and added SourcesList.FindIndex()
+ * added "trusted" to the Origin class
+
+ -- Michael Vogt <michael.vogt@ubuntu.com> Thu, 5 Jan 2006 00:56:36 +0100
+
+python-apt (0.6.15) unstable; urgency=low
+
+ * rewrote cache.Commit() and make it raise proper Exception if stuff
+ goes wrong
+ * fix a invalid return from cache.commit(), fail if a download failed
+ * apt.Package.candidateOrigin returns a class now
+ * added pkgAcquire, pkgPackageManager and a example (acquire.py)
+ * tightend build-dependencies for new apt and the c++ transition
+
+ -- Michael Vogt <mvo@debian.org> Mon, 28 Nov 2005 23:48:37 +0100
+
python-apt (0.6.14) unstable; urgency=low
* doc/examples/build-deps.py:
@@ -9,9 +102,9 @@ python-apt (0.6.14) unstable; urgency=low
- always run "Restart" before performing a Lookup
* export locking via: GetLock(),PkgSystem{Lock,UnLock}
* apt/cache.py:
- - add __iter__
+ - added __iter__ to make "for pkg in apt.Cache:" stuff possible
- -- Michael Vogt <michael.vogt@ubuntu.com> Tue, 20 Sep 2005 13:24:31 +0200
+ -- Michael Vogt <mvo@debian.org> Wed, 9 Nov 2005 04:52:08 +0100
python-apt (0.6.13) unstable; urgency=low
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 00000000..7813681f
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+5 \ No newline at end of file
diff --git a/debian/control b/debian/control
index bfa67c67..f313dff5 100644
--- a/debian/control
+++ b/debian/control
@@ -3,43 +3,18 @@ Section: python
Priority: optional
Maintainer: APT Development Team <deity@lists.debian.org>
Uploaders: Matt Zimmerman <mdz@debian.org>, Michael Vogt <mvo@debian.org>
-Standards-Version: 3.6.1.1
-Build-Depends: debhelper (>= 4.2.28), libapt-pkg-dev (>= 0.6.40), apt-utils, python-dev, python2.4-dev, python2.3-dev
+Standards-Version: 3.6.2.0
+XS-Python-Version: all
+Build-Depends: debhelper (>= 5.0.37.1), libapt-pkg-dev (>= 0.6.40), apt-utils, python-all-dev, python-central
Package: python-apt
-Architecture: all
-Depends: ${python:Depends}
-Priority: optional
-Description: Python interface to libapt-pkg
- The apt-pkg Python interface will provide full access to the internal
- libapt-pkg structures allowing Python programs to easily perform a
- variety of functions, such as:
- .
- - Access to the APT configuration system
- - Access to the APT package information database
- - Parsing of Debian package control files, and other files with a
- similar structure
-
-Package: python2.3-apt
Architecture: any
-Depends: python2.3, ${shlibs:Depends}
-Conflicts: python-apt (<< 0.6.11)
-Priority: optional
-Description: Python interface to libapt-pkg
- The apt-pkg Python interface will provide full access to the internal
- libapt-pkg structures allowing Python programs to easily perform a
- variety of functions, such as:
- .
- - Access to the APT configuration system
- - Access to the APT package information database
- - Parsing of Debian package control files, and other files with a
- similar structure
-
-Package: python2.4-apt
-Architecture: any
-Depends: python2.4, ${shlibs:Depends}
-Conflicts: python-apt (<< 0.6.11)
+Depends: ${python:Depends}
Priority: optional
+Replaces: python2.3-apt (<< 0.6.18), python2.4-apt (<< 0.6.18)
+Conflicts: python2.3-apt (<< 0.6.18), python2.4-apt (<< 0.6.18)
+Provides: ${python:Provides}
+XB-Python-Version: ${python:Versions}
Description: Python interface to libapt-pkg
The apt-pkg Python interface will provide full access to the internal
libapt-pkg structures allowing Python programs to easily perform a
diff --git a/debian/rules b/debian/rules
index 0ab6fa27..ffd39a6f 100755
--- a/debian/rules
+++ b/debian/rules
@@ -6,16 +6,13 @@
# This has to be exported to make some magic below work.
export DH_OPTIONS
-# This is the debhelper compatibility version to use.
-export DH_COMPAT=3
-
DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p')
DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us -uc $(DEB_BUILD_PROG_OPTS)
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
-PYTHON=python2.3 python2.4
+PYTHON=$(shell pyversions -r debian/control)
build: build-stamp
build-stamp:
@@ -41,18 +38,6 @@ clean:
# Build architecture-independent files here.
binary-indep: DH_OPTIONS=-i
binary-indep: build
- dh_testdir
- dh_testroot
- dh_installdocs
- dh_installexamples doc/examples/*.py
- dh_installchangelogs
- dh_compress
- dh_fixperms
- dh_installdeb
- dh_python
- dh_gencontrol
- dh_md5sums
- dh_builddeb
# Build architecture-dependent files here.
binary-arch: DH_OPTIONS=-a
@@ -60,11 +45,11 @@ binary-arch: build
dh_testdir
dh_testroot
dh_clean -k
-
+
for PY in $(PYTHON); do \
- /usr/bin/$$PY setup.py install --prefix=`pwd`/debian/$${PY}-apt/usr; \
+ /usr/bin/$$PY setup.py install --prefix=`pwd`/debian/python-apt/usr; \
done
-
+
dh_installdocs
dh_installchangelogs
dh_strip
@@ -72,6 +57,7 @@ binary-arch: build
dh_fixperms
dh_installdeb
dh_shlibdeps
+ dh_pycentral
dh_python
dh_gencontrol
dh_md5sums
@@ -83,7 +69,7 @@ source diff:
arch-build:
rm -rf debian/arch-build
mkdir -p debian/arch-build/python-apt-$(DEBVER)
- baz inventory -s | xargs cp -a --parents --target=debian/arch-build/python-apt-$(DEBVER)
+ tar -c --exclude=arch-build --no-recursion -f - `bzr inventory` | (cd debian/arch-build/python-apt-$(DEBVER);tar xf -)
(cd debian/arch-build/python-apt-$(DEBVER); $(DEB_BUILD_PROG))
binary: binary-indep binary-arch
diff --git a/doc/examples/acquire.py b/doc/examples/acquire.py
new file mode 100644
index 00000000..a0790c98
--- /dev/null
+++ b/doc/examples/acquire.py
@@ -0,0 +1,92 @@
+import apt
+import apt_pkg
+import os
+import sys
+import tempfile
+
+def get_file(fetcher, uri, destFile):
+ cwd = os.getcwd()
+ # create a temp dir
+ dir = tempfile.mkdtemp()
+ os.chdir(dir)
+ # get the file
+ af = apt_pkg.GetPkgAcqFile(fetcher,
+ uri=uri,
+ descr="sample descr")
+ res = fetcher.Run()
+ if res != fetcher.ResultContinue:
+ os.rmdir(dir)
+ os.chdir(cwd)
+ return False
+ filename = os.path.basename(uri)
+ os.rename(dir+"/"+filename,destFile)
+ # cleanup
+ os.rmdir(dir)
+ os.chdir(cwd)
+ return True
+
+apt_pkg.init()
+
+#apt_pkg.Config.Set("Debug::pkgDPkgPM","1");
+#apt_pkg.Config.Set("Debug::pkgPackageManager","1");
+#apt_pkg.Config.Set("Debug::pkgDPkgProgressReporting","1");
+
+cache = apt_pkg.GetCache()
+depcache = apt_pkg.GetDepCache(cache)
+
+recs = apt_pkg.GetPkgRecords(cache)
+list = apt_pkg.GetPkgSourceList()
+list.ReadMainList()
+
+# show the amount fetch needed for a dist-upgrade
+depcache.Upgrade(True)
+progress = apt.progress.TextFetchProgress()
+fetcher = apt_pkg.GetAcquire(progress)
+pm = apt_pkg.GetPackageManager(depcache)
+pm.GetArchives(fetcher,list,recs)
+print "%s (%s)" % (apt_pkg.SizeToStr(fetcher.FetchNeeded), fetcher.FetchNeeded)
+
+for pkg in cache.Packages:
+ depcache.MarkKeep(pkg)
+
+try:
+ os.mkdir("/tmp/pyapt-test")
+ os.mkdir("/tmp/pyapt-test/partial")
+except OSError:
+ pass
+apt_pkg.Config.Set("Dir::Cache::archives","/tmp/pyapt-test")
+
+pkg = cache["3ddesktop"]
+depcache.MarkInstall(pkg)
+
+progress = apt.progress.TextFetchProgress()
+fetcher = apt_pkg.GetAcquire(progress)
+#fetcher = apt_pkg.GetAcquire()
+pm = apt_pkg.GetPackageManager(depcache)
+
+print pm
+print fetcher
+
+get_file(fetcher, "ftp://ftp.debian.org/debian/dists/README", "/tmp/lala")
+sys.exit(1)
+
+pm.GetArchives(fetcher,list,recs)
+
+for item in fetcher.Items:
+ print item
+ if item.Status == item.StatError:
+ print "Some error ocured: '%s'" % item.ErrorText
+ if item.Complete == False:
+ print "No error, still nothing downloaded (%s)" % item.ErrorText
+ print
+
+
+res = fetcher.Run()
+print "fetcher.Run() returned: %s" % res
+
+print "now runing pm.DoInstall()"
+res = pm.DoInstall(1)
+print "pm.DoInstall() returned: %s"% res
+
+
+
diff --git a/doc/examples/action.py b/doc/examples/action.py
index a794317a..adf26539 100644
--- a/doc/examples/action.py
+++ b/doc/examples/action.py
@@ -30,9 +30,6 @@ sys.exit(0)
-
-
-
iter = cache["base-config"]
print "example package iter: %s" % iter
diff --git a/doc/examples/all_deps.py b/doc/examples/all_deps.py
new file mode 100644
index 00000000..f4f1741c
--- /dev/null
+++ b/doc/examples/all_deps.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+
+import sys
+import apt
+
+
+def dependencies(cache, pkg, deps, key="Depends"):
+ #print "pkg: %s (%s)" % (pkg.name, deps)
+ candver = cache._depcache.GetCandidateVer(pkg._pkg)
+ if candver == None:
+ return deps
+ dependslist = candver.DependsList
+ if dependslist.has_key(key):
+ for depVerList in dependslist[key]:
+ for dep in depVerList:
+ if cache.has_key(dep.TargetPkg.Name):
+ if pkg.name != dep.TargetPkg.Name and not dep.TargetPkg.Name in deps:
+ deps.add(dep.TargetPkg.Name)
+ dependencies(cache, cache[dep.TargetPkg.Name], deps, key)
+ return deps
+
+
+pkgname = sys.argv[1]
+c = apt.Cache()
+pkg = c[pkgname]
+
+deps = set()
+
+deps = dependencies(c,pkg, deps, "Depends")
+print " ".join(deps)
+
+preDeps = set()
+preDeps = dependencies(c,pkg, preDeps, "PreDepends")
+print " ".join(preDeps)
diff --git a/doc/examples/build-deps.py b/doc/examples/build-deps.py
index b580f5de..65e35f3d 100755
--- a/doc/examples/build-deps.py
+++ b/doc/examples/build-deps.py
@@ -24,7 +24,7 @@ cache = apt_pkg.GetCache()
depcache = apt_pkg.GetDepCache(cache)
depcache.Init()
records = apt_pkg.GetPkgRecords(cache)
-srcrecords = apt_pkg.GetPkgSrcRecords(cache)
+srcrecords = apt_pkg.GetPkgSrcRecords()
# base package that we use for build-depends calculation
if len(sys.argv) < 2:
diff --git a/doc/examples/deb_inspect.py b/doc/examples/deb_inspect.py
index 4173c196..0befd2bb 100755
--- a/doc/examples/deb_inspect.py
+++ b/doc/examples/deb_inspect.py
@@ -4,6 +4,7 @@
import apt_pkg
import apt_inst
import sys
+import os.path
def Callback(What,Name,Link,Mode,UID,GID,Size,MTime,Major,Minor):
""" callback for debExtract """
@@ -35,5 +36,12 @@ if __name__ == "__main__":
print apt_pkg.ParseDepends(depends)
-
-
+ print "extracting archive"
+ dir = "/tmp/deb"
+ os.mkdir(dir)
+ apt_inst.debExtractArchive(open(file),dir)
+ def visit(arg, dirname, names):
+ print "%s/" % dirname
+ for file in names:
+ print "\t%s" % file
+ os.path.walk(dir, visit, None)
diff --git a/doc/examples/dependant-pkgs.py b/doc/examples/dependant-pkgs.py
new file mode 100755
index 00000000..f36936a8
--- /dev/null
+++ b/doc/examples/dependant-pkgs.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+
+import apt
+import sys
+
+pkgs = set()
+cache = apt.Cache()
+for pkg in cache:
+ candver = cache._depcache.GetCandidateVer(pkg._pkg)
+ if candver == None:
+ continue
+ dependslist = candver.DependsList
+ for dep in dependslist.keys():
+ # get the list of each dependency object
+ for depVerList in dependslist[dep]:
+ for z in depVerList:
+ # get all TargetVersions of
+ # the dependency object
+ for tpkg in z.AllTargets():
+ if sys.argv[1] == tpkg.ParentPkg.Name:
+ pkgs.add(pkg.name)
+
+main = set()
+universe = set()
+for pkg in pkgs:
+ if "universe" in cache[pkg].section:
+ universe.add(cache[pkg].sourcePackageName)
+ else:
+ main.add(cache[pkg].sourcePackageName)
+
+print "main:"
+print "\n".join(main)
+print
+
+print "universe:"
+print "\n".join(universe)
diff --git a/doc/examples/gui-inst.py b/doc/examples/gui-inst.py
index 38417e10..deb325fe 100755
--- a/doc/examples/gui-inst.py
+++ b/doc/examples/gui-inst.py
@@ -2,6 +2,7 @@
# example how to install in a custom terminal widget
# see also gnome bug: #169201
+import apt
import apt_pkg
import sys, os, fcntl
import copy
@@ -13,6 +14,7 @@ pygtk.require('2.0')
import gtk
import vte
import time
+import posix
from apt.progress import OpProgress, FetchProgress, InstallProgress
@@ -36,10 +38,12 @@ class GuiFetchProgress(gtk.Window, FetchProgress):
def stop(self):
self.hide()
def pulse(self):
- self.label.set_text("Speed: %s/s" % apt_pkg.SizeToStr(self.currentCPS))
+ FetchProgress.pulse(self)
+ self.label.set_text("Speed: %s/s" % apt_pkg.SizeToStr(self.currentCPS))
#self.progressbar.set_fraction(self.currentBytes/self.totalBytes)
while gtk.events_pending():
gtk.main_iteration()
+ return True
class TermInstallProgress(InstallProgress, gtk.Window):
def __init__(self):
@@ -50,11 +54,16 @@ class TermInstallProgress(InstallProgress, gtk.Window):
self.add(box)
self.term = vte.Terminal()
self.term.show()
+ # check for the child
+ self.reaper = vte.reaper_get()
+ self.reaper.connect("child-exited",self.child_exited)
+ self.finished = False
+
box.pack_start(self.term)
self.progressbar = gtk.ProgressBar()
self.progressbar.show()
box.pack_start(self.progressbar)
-
+
(read, write) = os.pipe()
self.writefd=write
self.status = os.fdopen(read, "r")
@@ -62,7 +71,12 @@ class TermInstallProgress(InstallProgress, gtk.Window):
print "read-fd: %s" % self.status.fileno()
print "write-fd: %s" % self.writefd
self.read = ""
-
+
+ def child_exited(self,term, pid, status):
+ print "child_exited: %s %s %s %s" % (self,term,pid,status)
+ self.apt_status = posix.WEXITSTATUS(status)
+ self.finished = True
+
def startUpdate(self):
print "start"
self.show()
@@ -84,29 +98,26 @@ class TermInstallProgress(InstallProgress, gtk.Window):
self.read = ""
while gtk.events_pending():
gtk.main_iteration()
+
def finishUpdate(self):
sys.stdin.readline()
- def fork(self):
+ def run(self, pm):
print "fork"
env = ["VTE_PTY_KEEP_FD=%s"%self.writefd]
print env
pid = self.term.forkpty(envv=env)
+ if pid == 0:
+ res = pm.DoInstall(self.writefd)
+ print res
+ sys.exit(res)
print "After fork: %s " % pid
- return pid
-
-
-# init
-apt_pkg.init()
-
-progress = OpProgress()
-cache = apt_pkg.GetCache(progress)
-print "Available packages: %s " % cache.PackageCount
+ while not self.finished:
+ self.updateInterface()
+ return self.apt_status
+cache = apt.Cache()
+print "Available packages: %s " % cache._cache.PackageCount
-# get depcache
-depcache = apt_pkg.GetDepCache(cache)
-depcache.ReadPinFile()
-depcache.Init(progress)
# update the cache
fprogress = GuiFetchProgress()
@@ -125,15 +136,15 @@ while gtk.events_pending():
gtk.main_iteration()
-iter = cache["3dchess"]
-print "\n%s"%iter
+pkg = cache["3dchess"]
+print "\n%s"%pkg.name
# install or remove, the importend thing is to keep us busy :)
-if iter.CurrentVer == None:
- depcache.MarkInstall(iter)
+if pkg.isInstalled:
+ pkg.markDelete()
else:
- depcache.MarkDelete(iter)
-depcache.Commit(fprogress, iprogress)
+ pkg.markInstall()
+cache.commit(fprogress, iprogress)
print "Exiting"
sys.exit(0)
diff --git a/doc/examples/indexfile.py b/doc/examples/indexfile.py
new file mode 100644
index 00000000..d383fd61
--- /dev/null
+++ b/doc/examples/indexfile.py
@@ -0,0 +1,21 @@
+
+import apt_pkg
+
+apt_pkg.init()
+
+sources = apt_pkg.GetPkgSourceList()
+sources.ReadMainList()
+
+cache = apt_pkg.GetCache()
+depcache = apt_pkg.GetDepCache(cache)
+pkg = cache["libimlib2"]
+cand = depcache.GetCandidateVer(pkg)
+for (f,i) in cand.FileList:
+ index = sources.FindIndex(f)
+ print index
+ if index:
+ print index.Size
+ print index.IsTrusted
+ print index.Exists
+ print index.HasPackages
+ print index.ArchiveURI("some/path")
diff --git a/doc/examples/inst.py b/doc/examples/inst.py
index fe5ec8e3..0e91c28f 100644
--- a/doc/examples/inst.py
+++ b/doc/examples/inst.py
@@ -2,60 +2,48 @@
# example how to deal with the depcache
import apt
-import apt_pkg
import sys, os
import copy
+import time
-from progress import TextFetchProgress, TextInstallProgress
-from apt.progress import OpTextProgress
+from apt.progress import InstallProgress
class TextInstallProgress(InstallProgress):
def __init__(self):
- InstallProgress.__init__(self)
- self.status = None
- def StartUpdate(self):
- print "StartUpdate: %s" % self.statusfd
- self.status = os.fdopen(self.statusfd, "r")
- print self.status
- def UpdateInterface(self):
- if self.status != None:
- s = self.status.readline()
- if s:
- print s
- def FinishUpdate(self):
- self.status.close()
-
-# init
-apt_pkg.init()
-
-progress = OpTextProgress()
-cache = apt_pkg.GetCache(progress)
-print "Available packages: %s " % cache.PackageCount
-
-# get depcache
-depcache = apt_pkg.GetDepCache(cache)
-depcache.ReadPinFile()
-depcache.Init(progress)
-
-# do something
-fprogress = TextFetchProgress()
+ apt.progress.InstallProgress.__init__(self)
+ self.last = 0.0
+ def updateInterface(self):
+ InstallProgress.updateInterface(self)
+ if self.last >= self.percent:
+ return
+ sys.stdout.write("\r[%s] %s\n" %(self.percent, self.status))
+ sys.stdout.flush()
+ self.last = self.percent
+ def conffile(self,current,new):
+ print "conffile prompt: %s %s" % (current,new)
+ def error(self, errorstr):
+ print "got dpkg error: '%s'" % errorstr
+
+cache = apt.Cache(apt.progress.OpTextProgress())
+
+fprogress = apt.progress.TextFetchProgress()
iprogress = TextInstallProgress()
-# can be used to set a custom fork method (like vte.Terminal.forkpty)
-#iprogress.fork = os.fork
-
-iter = cache["base-config"]
-print "\n%s"%iter
+pkg = cache["test-package"]
+pkg.markUpgrade()
+cache.commit(fprogress,iprogress)
+sys.exit(1)
# install or remove, the importend thing is to keep us busy :)
-if iter.CurrentVer == None:
- depcache.MarkInstall(iter)
+if pkg.isInstalled:
+ print "Going to delete %s" % pkg.name
+ pkg.markDelete()
else:
- depcache.MarkDelete(iter)
-res = depcache.Commit(fprogress, iprogress)
+ print "Going to install %s" % pkg.name
+ pkg.markInstall()
+res = cache.commit(fprogress, iprogress)
print res
-print "Exiting"
sys.exit(0)
diff --git a/doc/examples/print_uris.py b/doc/examples/print_uris.py
new file mode 100755
index 00000000..c8a64223
--- /dev/null
+++ b/doc/examples/print_uris.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+#
+# a example that prints the URIs of all upgradable packages
+#
+
+import apt
+import apt_pkg
+
+
+cache = apt.Cache()
+upgradable = filter(lambda p: p.isUpgradable, cache)
+
+
+for pkg in upgradable:
+ pkg._lookupRecord(True)
+ path = apt_pkg.ParseSection(pkg._records.Record)["Filename"]
+ cand = pkg._depcache.GetCandidateVer(pkg._pkg)
+ for (packagefile,i) in cand.FileList:
+ indexfile = cache._list.FindIndex(packagefile)
+ if indexfile:
+ uri = indexfile.ArchiveURI(path)
+ print uri
diff --git a/doc/examples/progress.py b/doc/examples/progress.py
index d820fcb2..2723c382 100644
--- a/doc/examples/progress.py
+++ b/doc/examples/progress.py
@@ -44,12 +44,16 @@ class TextFetchProgress(apt.FetchProgress):
class TextInstallProgress(apt.InstallProgress):
def __init__(self):
+ apt.InstallProgress.__init__(self)
pass
def startUpdate(self):
print "StartUpdate"
def finishUpdate(self):
print "FinishUpdate"
+ def statusChange(self, pkg, percent, status):
+ print "[%s] %s: %s" % (percent, pkg, status)
def updateInterface(self):
+ apt.InstallProgress.updateInterface(self)
# usefull to e.g. redraw a GUI
time.sleep(0.1)
@@ -70,3 +74,16 @@ class TextCdromProgress(apt.CdromProgress):
print "Please insert cdrom and press <ENTER>"
answer = sys.stdin.readline()
return True
+
+
+if __name__ == "__main__":
+ c = apt.Cache()
+ pkg = c["3dchess"]
+ if pkg.isInstalled:
+ pkg.markDelete()
+ else:
+ pkg.markInstall()
+
+ res = c.commit(TextFetchProgress(), TextInstallProgress())
+
+ print res
diff --git a/doc/examples/sources.py b/doc/examples/sources.py
index 79514621..c12c6f15 100644
--- a/doc/examples/sources.py
+++ b/doc/examples/sources.py
@@ -4,6 +4,12 @@ import apt_pkg
apt_pkg.init()
+#cache = apt_pkg.GetCache()
+#sources = apt_pkg.GetPkgSrcRecords(cache)
+
sources = apt_pkg.GetPkgSrcRecords()
+sources.Restart()
while sources.Lookup('hello'):
print sources.Package, sources.Version, sources.Maintainer, sources.Section, `sources.Binaries`
+ print sources.Files
+ print sources.Index.ArchiveURI("")
diff --git a/python/acquire.cc b/python/acquire.cc
new file mode 100644
index 00000000..65f8f2d7
--- /dev/null
+++ b/python/acquire.cc
@@ -0,0 +1,274 @@
+// Description /*{{{*/
+// $Id: acquire.cc,v 1.1 2003/06/03 03:03:23 mvo Exp $
+/* ######################################################################
+
+ Acquire - Wrapper for the acquire code
+
+ ##################################################################### */
+
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include "progress.h"
+
+#include <apt-pkg/acquire-item.h>
+
+// pkgAcquire::Item
+static PyObject *AcquireItemAttr(PyObject *Self,char *Name)
+{
+ pkgAcquire::ItemIterator &I = GetCpp<pkgAcquire::ItemIterator>(Self);
+
+ if (strcmp("ID",Name) == 0)
+ return Py_BuildValue("i",(*I)->ID);
+ else if (strcmp("Status",Name) == 0)
+ return Py_BuildValue("i",(*I)->Status);
+ else if (strcmp("Complete",Name) == 0)
+ return Py_BuildValue("i",(*I)->Complete);
+ else if (strcmp("Local",Name) == 0)
+ return Py_BuildValue("i",(*I)->Local);
+ else if (strcmp("IsTrusted",Name) == 0)
+ return Py_BuildValue("i",(*I)->IsTrusted());
+ else if (strcmp("FileSize",Name) == 0)
+ return Py_BuildValue("i",(*I)->FileSize);
+ else if (strcmp("ErrorText",Name) == 0)
+ return Safe_FromString((*I)->ErrorText.c_str());
+ else if (strcmp("DestFile",Name) == 0)
+ return Safe_FromString((*I)->DestFile.c_str());
+ else if (strcmp("DescURI",Name) == 0)
+ return Safe_FromString((*I)->DescURI().c_str());
+ // constants
+ else if (strcmp("StatIdle",Name) == 0)
+ return Py_BuildValue("i", pkgAcquire::Item::StatIdle);
+ else if (strcmp("StatFetching",Name) == 0)
+ return Py_BuildValue("i", pkgAcquire::Item::StatFetching);
+ else if (strcmp("StatDone",Name) == 0)
+ return Py_BuildValue("i", pkgAcquire::Item::StatDone);
+ else if (strcmp("StatError",Name) == 0)
+ return Py_BuildValue("i", pkgAcquire::Item::StatError);
+ else if (strcmp("StatAuthError",Name) == 0)
+ return Py_BuildValue("i", pkgAcquire::Item::StatAuthError);
+
+
+ PyErr_SetString(PyExc_AttributeError,Name);
+ return 0;
+}
+
+
+static PyObject *AcquireItemRepr(PyObject *Self)
+{
+ pkgAcquire::ItemIterator &I = GetCpp<pkgAcquire::ItemIterator>(Self);
+
+ char S[300];
+ snprintf(S,sizeof(S),"<pkgAcquire::ItemIterator object: "
+ "Status: %i Complete: %i Local: %i IsTrusted: %i "
+ "FileSize: %i DestFile:'%s' "
+ "DescURI: '%s' ID:%i ErrorText: '%s'>",
+ (*I)->Status, (*I)->Complete, (*I)->Local, (*I)->IsTrusted(),
+ (*I)->FileSize, (*I)->DestFile.c_str(), (*I)->DescURI().c_str(),
+ (*I)->ID,(*I)->ErrorText.c_str());
+ return PyString_FromString(S);
+}
+
+
+PyTypeObject AcquireItemType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgAcquire::ItemIterator", // tp_name
+ sizeof(CppOwnedPyObject<pkgAcquire::ItemIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<pkgAcquire::ItemIterator>, // tp_dealloc
+ 0, // tp_print
+ AcquireItemAttr, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ AcquireItemRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+};
+
+
+static PyObject *PkgAcquireRun(PyObject *Self,PyObject *Args)
+{
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self);
+
+ int pulseInterval = 500000;
+ if (PyArg_ParseTuple(Args, "|i", &pulseInterval) == 0)
+ return 0;
+
+ pkgAcquire::RunResult run = fetcher->Run(pulseInterval);
+
+ return HandleErrors(Py_BuildValue("i",run));
+}
+
+static PyObject *PkgAcquireShutdown(PyObject *Self,PyObject *Args)
+{
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self);
+
+ if (PyArg_ParseTuple(Args, "") == 0)
+ return 0;
+
+ fetcher->Shutdown();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyMethodDef PkgAcquireMethods[] =
+{
+ {"Run",PkgAcquireRun,METH_VARARGS,"Run the fetcher"},
+ {"Shutdown",PkgAcquireShutdown, METH_VARARGS,"Shutdown the fetcher"},
+ {}
+};
+
+
+static PyObject *AcquireAttr(PyObject *Self,char *Name)
+{
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self);
+
+ if(strcmp("TotalNeeded",Name) == 0)
+ return Py_BuildValue("d", fetcher->TotalNeeded());
+ if(strcmp("FetchNeeded",Name) == 0)
+ return Py_BuildValue("d", fetcher->FetchNeeded());
+ if(strcmp("PartialPresent",Name) == 0)
+ return Py_BuildValue("d", fetcher->PartialPresent());
+ if(strcmp("Items",Name) == 0)
+ {
+ PyObject *List = PyList_New(0);
+ for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin();
+ I != fetcher->ItemsEnd(); I++)
+ {
+ PyObject *Obj;
+ Obj = CppOwnedPyObject_NEW<pkgAcquire::ItemIterator>(Self,&AcquireItemType,I);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+
+ }
+ return List;
+ }
+ // some constants
+ if(strcmp("ResultContinue",Name) == 0)
+ return Py_BuildValue("i", pkgAcquire::Continue);
+ if(strcmp("ResultFailed",Name) == 0)
+ return Py_BuildValue("i", pkgAcquire::Failed);
+ if(strcmp("ResultCancelled",Name) == 0)
+ return Py_BuildValue("i", pkgAcquire::Cancelled);
+
+ return Py_FindMethod(PkgAcquireMethods,Self,Name);
+}
+
+
+
+
+PyTypeObject PkgAcquireType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "Acquire", // tp_name
+ sizeof(CppPyObject<pkgAcquire*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgAcquire*>, // tp_dealloc
+ 0, // tp_print
+ AcquireAttr, // 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
+};
+
+PyObject *GetAcquire(PyObject *Self,PyObject *Args)
+{
+ pkgAcquire *fetcher;
+
+ PyObject *pyFetchProgressInst = NULL;
+ if (PyArg_ParseTuple(Args,"|O",&pyFetchProgressInst) == 0)
+ return 0;
+
+ if (pyFetchProgressInst != NULL) {
+ // FIXME: memleak?
+ PyFetchProgress *progress = new PyFetchProgress();
+ progress->setCallbackInst(pyFetchProgressInst);
+ fetcher = new pkgAcquire(progress);
+ } else {
+ fetcher = new pkgAcquire();
+ }
+
+ CppPyObject<pkgAcquire*> *FetcherObj =
+ CppPyObject_NEW<pkgAcquire*>(&PkgAcquireType, fetcher);
+
+ return FetcherObj;
+}
+
+
+
+
+
+// pkgAcquireFile
+
+static PyObject *AcquireFileAttr(PyObject *Self,char *Name)
+{
+ pkgAcqFile *acqFile = GetCpp<pkgAcqFile*>(Self);
+
+ PyErr_SetString(PyExc_AttributeError,Name);
+ return 0;
+}
+
+
+
+
+PyTypeObject PkgAcquireFileType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgAcquireFile", // tp_name
+ sizeof(CppPyObject<pkgAcqFile*>),// tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgAcqFile*>, // tp_dealloc
+ 0, // tp_print
+ AcquireFileAttr, // 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
+};
+
+PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject * kwds)
+{
+ PyObject *pyfetcher;
+ char *uri, *md5, *descr, *shortDescr, *destDir, *destFile;
+ int size = 0;
+ uri = md5 = descr = shortDescr = destDir = destFile = "";
+
+ char * kwlist[] = {"owner","uri", "md5", "size", "descr", "shortDescr",
+ NULL};
+
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, "O!s|siss", kwlist,
+ &PkgAcquireType, &pyfetcher, &uri, &md5,
+ &size, &descr, &shortDescr) == 0)
+ return 0;
+
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyfetcher);
+ pkgAcqFile *af = new pkgAcqFile(fetcher, // owner
+ uri, // uri
+ md5, // md5
+ size, // size
+ descr, // descr
+ shortDescr); // short-desc
+ CppPyObject<pkgAcqFile*> *AcqFileObj = CppPyObject_NEW<pkgAcqFile*>(&PkgAcquireFileType);
+ AcqFileObj->Object = af;
+
+ return AcqFileObj;
+}
+
+
+ /*}}}*/
diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc
index 96bd029b..d672a40a 100644
--- a/python/apt_instmodule.cc
+++ b/python/apt_instmodule.cc
@@ -66,6 +66,43 @@ static PyObject *debExtractControl(PyObject *Self,PyObject *Args)
}
/*}}}*/
+// debExtractArchive - Exctract the archive /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_debExtractArchive =
+"debExtractArchve(File,rootdir) -> Bool\n"
+"Extracts the Archive into the given root dir";
+static PyObject *debExtractArchive(PyObject *Self,PyObject *Args)
+{
+ char *Rootdir = NULL;
+ PyObject *File;
+ if (PyArg_ParseTuple(Args,"O!|s",&PyFile_Type,&File,&Rootdir) == 0)
+ return 0;
+
+ // Subscope makes sure any clean up errors are properly handled.
+ bool res = false;
+ {
+ if(Rootdir != NULL)
+ {
+ chdir(Rootdir);
+ }
+
+ // Open the file and associate the .deb
+ FileFd Fd(fileno(PyFile_AsFile(File)),false);
+ debDebFile Deb(Fd);
+ if (_error->PendingError() == true)
+ return HandleErrors();
+
+ // extracts relative to the current dir
+ pkgDirStream Extract;
+ res = Deb.ExtractArchive(Extract);
+
+ if (res == false)
+ return HandleErrors();
+ }
+ return HandleErrors(Py_BuildValue("b",res));
+}
+ /*}}}*/
+
// initapt_inst - Core Module Initialization /*{{{*/
// ---------------------------------------------------------------------
/* */
@@ -73,6 +110,7 @@ static PyMethodDef methods[] =
{
// Stuff
{"debExtractControl",debExtractControl,METH_VARARGS,doc_debExtractControl},
+ {"debExtractArchive",debExtractArchive,METH_VARARGS,doc_debExtractArchive},
{"tarExtract",tarExtract,METH_VARARGS,doc_tarExtract},
{"debExtract",debExtract,METH_VARARGS,doc_debExtract},
diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc
index ce337f0f..e73628c3 100644
--- a/python/apt_pkgmodule.cc
+++ b/python/apt_pkgmodule.cc
@@ -396,6 +396,13 @@ static PyMethodDef methods[] =
// Cdrom
{"GetCdrom",GetCdrom,METH_VARARGS,"GetCdrom() -> Cdrom"},
+ // Acquire
+ {"GetAcquire",GetAcquire,METH_VARARGS,"GetAcquire() -> Acquire"},
+ {"GetPkgAcqFile",(PyCFunction)GetPkgAcqFile,METH_KEYWORDS|METH_VARARGS,"GetPkgAcquireFile() -> pkgAcquireFile"},
+
+ // PkgManager
+ {"GetPackageManager",GetPkgManager,METH_VARARGS,"GetPackageManager() -> PackageManager"},
+
{}
};
diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h
index eefa6ca7..fe7dfe88 100644
--- a/python/apt_pkgmodule.h
+++ b/python/apt_pkgmodule.h
@@ -72,11 +72,27 @@ PyObject *GetPkgProblemResolver(PyObject *Self, PyObject *Args);
extern PyTypeObject PkgCdromType;
PyObject *GetCdrom(PyObject *Self,PyObject *Args);
+// acquire
+extern PyTypeObject PkgAcquireType;
+PyObject *GetAcquire(PyObject *Self,PyObject *Args);
+PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject *kwds);
+
+// packagemanager
+extern PyTypeObject PkgManagerType;
+PyObject *GetPkgManager(PyObject *Self,PyObject *Args);
+
// PkgRecords Stuff
extern PyTypeObject PkgRecordsType;
PyObject *GetPkgRecords(PyObject *Self,PyObject *Args);
PyObject *GetPkgSrcRecords(PyObject *Self,PyObject *Args);
+
+// pkgSourceList
+extern PyTypeObject PkgSourceListType;
PyObject *GetPkgSourceList(PyObject *Self,PyObject *Args);
+// pkgSourceList
+extern PyTypeObject PackageIndexFileType;
+
+
#endif
diff --git a/python/cache.cc b/python/cache.cc
index 5c1760d4..174423c2 100644
--- a/python/cache.cc
+++ b/python/cache.cc
@@ -231,6 +231,17 @@ static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg)
return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Self,&PackageType,Pkg);
}
+// we need a special dealloc here to make sure that the CacheFile
+// is closed before deallocation the cache (otherwise we have a bad)
+// memory leak
+void PkgCacheFileDealloc(PyObject *Self)
+{
+ PyObject *CacheFilePy = GetOwner<pkgCache*>(Self);
+ pkgCacheFile *CacheF = GetCpp<pkgCacheFile*>(CacheFilePy);
+ CacheF->Close();
+ CppOwnedDealloc<pkgCache *>(Self);
+}
+
static PyMappingMethods CacheMap = {0,CacheMapOp,0};
PyTypeObject PkgCacheType =
{
@@ -240,7 +251,7 @@ PyTypeObject PkgCacheType =
sizeof(CppOwnedPyObject<pkgCache *>), // tp_basicsize
0, // tp_itemsize
// Methods
- CppOwnedDealloc<pkgCache *>, // tp_dealloc
+ PkgCacheFileDealloc, // tp_dealloc
0, // tp_print
CacheAttr, // tp_getattr
0, // tp_setattr
@@ -452,7 +463,17 @@ static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver,
// Switch/create a new dict entry
if (LastDepType != Start->Type || LastDep != 0)
{
- PyObject *Dep = PyString_FromString(Start.DepType());
+ // must be in sync with pkgCache::DepType in libapt
+ // it sucks to have it here duplicated, but we get it
+ // translated from libapt and that is certainly not what
+ // we want in a programing interface
+ const char *Types[] =
+ {
+ "", "Depends","PreDepends","Suggests",
+ "Recommends","Conflicts","Replaces",
+ "Obsoletes"
+ };
+ PyObject *Dep = PyString_FromString(Types[Start->Type]);
LastDepType = Start->Type;
LastDep = PyDict_GetItem(Dict,Dep);
if (LastDep == 0)
@@ -637,8 +658,6 @@ static PyObject *PackageFileAttr(PyObject *Self,char *Name)
return Py_BuildValue("i",(File->Flags & pkgCache::Flag::NotAutomatic) != 0);
else if (strcmp("ID",Name) == 0)
return Py_BuildValue("i",File->ID);
- /* mtime is really a cookie these days and has no meaning outside the
- list handlers */
PyErr_SetString(PyExc_AttributeError,Name);
return 0;
diff --git a/python/cdrom.cc b/python/cdrom.cc
index 13889b31..aca1be26 100644
--- a/python/cdrom.cc
+++ b/python/cdrom.cc
@@ -30,10 +30,9 @@ static PyObject *PkgCdromAdd(PyObject *Self,PyObject *Args)
PyCdromProgress progress;
progress.setCallbackInst(pyCdromProgressInst);
- Struct.cdrom.Add(&progress);
+ bool res = Struct.cdrom.Add(&progress);
- Py_INCREF(Py_None);
- return HandleErrors(Py_None);
+ return HandleErrors(Py_BuildValue("b", res));
}
static PyObject *PkgCdromIdent(PyObject *Self,PyObject *Args)
@@ -69,7 +68,6 @@ static PyObject *CdromAttr(PyObject *Self,char *Name)
{
PkgCdromStruct &Struct = GetCpp<PkgCdromStruct>(Self);
-
return Py_FindMethod(PkgCdromMethods,Self,Name);
}
diff --git a/python/depcache.cc b/python/depcache.cc
index c78d0077..60bbc1a4 100644
--- a/python/depcache.cc
+++ b/python/depcache.cc
@@ -116,17 +116,25 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args)
bool Failed = false;
for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
{
+
+ //std::cout << "looking at: " << (*I)->DestFile
+ // << " status: " << (*I)->Status << std::endl;
+
if ((*I)->Status == pkgAcquire::Item::StatDone &&
(*I)->Complete == true)
continue;
if ((*I)->Status == pkgAcquire::Item::StatIdle)
{
+ //std::cout << "transient failure" << std::endl;
+
Transient = true;
- // Failed = true;
+ //Failed = true;
continue;
}
+ //std::cout << "something is wrong!" << std::endl;
+
_error->Warning(_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
(*I)->ErrorText.c_str());
Failed = true;
@@ -135,6 +143,7 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args)
if (Transient == true && Failed == true)
{
_error->Error(_("--fix-missing and media swapping is not currently supported"));
+ Py_INCREF(Py_None);
return HandleErrors(Py_None);
}
@@ -143,27 +152,33 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args)
{
//std::cerr << "Unable to correct missing packages." << std::endl;
_error->Error("Aborting install.");
+ Py_INCREF(Py_None);
return HandleErrors(Py_None);
}
- _system->UnLock();
+ // fail if something else went wrong
+ //FIXME: make this more flexible, e.g. with a failedDl handler
+ if(Failed)
+ return Py_BuildValue("b", false);
+ _system->UnLock(true);
pkgPackageManager::OrderResult Res = iprogress.Run(PM);
- //FIXME: return usefull values here
+ //std::cout << "iprogress.Run() returned: " << (int)Res << std::endl;
+
if (Res == pkgPackageManager::Failed || _error->PendingError() == true) {
- result = Py_BuildValue("b", false);
- return result;
+ return HandleErrors(Py_BuildValue("b", false));
}
if (Res == pkgPackageManager::Completed) {
- result = Py_BuildValue("b", true);
- return result;
+ //std::cout << "iprogress.Run() returned Completed " << std::endl;
+ return Py_BuildValue("b", true);
}
+ //std::cout << "looping again, install unfinished" << std::endl;
+
// Reload the fetcher object and loop again for media swapping
Fetcher.Shutdown();
if (PM->GetArchives(&Fetcher,&List,&Recs) == false) {
- result = Py_BuildValue("b", false);
- return result;
+ return Py_BuildValue("b", false);
}
_system->Lock();
}
@@ -218,15 +233,30 @@ static PyObject *PkgDepCacheUpgrade(PyObject *Self,PyObject *Args)
if (PyArg_ParseTuple(Args,"|b",&distUpgrade) == 0)
return 0;
+ bool res;
if(distUpgrade)
- pkgDistUpgrade(*depcache);
+ res = pkgDistUpgrade(*depcache);
else
- pkgAllUpgrade(*depcache);
+ res = pkgAllUpgrade(*depcache);
Py_INCREF(Py_None);
- return HandleErrors(Py_None);
+ return HandleErrors(Py_BuildValue("b",res));
+}
+
+static PyObject *PkgDepCacheMinimizeUpgrade(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = pkgMinimizeUpgrade(*depcache);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_BuildValue("b",res));
}
+
static PyObject *PkgDepCacheReadPinFile(PyObject *Self,PyObject *Args)
{
pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
@@ -249,14 +279,15 @@ static PyObject *PkgDepCacheReadPinFile(PyObject *Self,PyObject *Args)
static PyObject *PkgDepCacheFixBroken(PyObject *Self,PyObject *Args)
{
pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
-
+
+ bool res=true;
if (PyArg_ParseTuple(Args,"") == 0)
return 0;
- pkgFixBroken(*depcache);
+ res &=pkgFixBroken(*depcache);
+ res &=pkgMinimizeUpgrade(*depcache);
- Py_INCREF(Py_None);
- return HandleErrors(Py_None);
+ return HandleErrors(Py_BuildValue("b",res));
}
@@ -339,6 +370,20 @@ static PyObject *PkgDepCacheIsUpgradable(PyObject *Self,PyObject *Args)
return HandleErrors(Py_BuildValue("b",state.Upgradable()));
}
+static PyObject *PkgDepCacheIsGarbage(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(Py_BuildValue("b",state.Garbage));
+}
+
static PyObject *PkgDepCacheIsNowBroken(PyObject *Self,PyObject *Args)
{
pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
@@ -466,6 +511,7 @@ static PyMethodDef PkgDepCacheMethods[] =
{"Upgrade",PkgDepCacheUpgrade,METH_VARARGS,"Perform Upgrade (optional boolean argument if dist-upgrade should be performed)"},
{"FixBroken",PkgDepCacheFixBroken,METH_VARARGS,"Fix broken packages"},
{"ReadPinFile",PkgDepCacheReadPinFile,METH_VARARGS,"Read the pin policy"},
+ {"MinimizeUpgrade",PkgDepCacheMinimizeUpgrade, METH_VARARGS,"Go over the entire set of packages and try to keep each package marked for upgrade. If a conflict is generated then the package is restored."},
// Manipulators
{"MarkKeep",PkgDepCacheMarkKeep,METH_VARARGS,"Mark package for keep"},
{"MarkDelete",PkgDepCacheMarkDelete,METH_VARARGS,"Mark package for delete (optional boolean argument if it should be purged)"},
@@ -475,6 +521,7 @@ static PyMethodDef PkgDepCacheMethods[] =
{"IsUpgradable",PkgDepCacheIsUpgradable,METH_VARARGS,"Is pkg upgradable"},
{"IsNowBroken",PkgDepCacheIsNowBroken,METH_VARARGS,"Is pkg is now broken"},
{"IsInstBroken",PkgDepCacheIsInstBroken,METH_VARARGS,"Is pkg broken on the current install"},
+ {"IsGarbage",PkgDepCacheIsGarbage,METH_VARARGS,"Is pkg garbage (mark-n-sweep)"},
{"MarkedInstall",PkgDepCacheMarkedInstall,METH_VARARGS,"Is pkg marked for install"},
{"MarkedUpgrade",PkgDepCacheMarkedUpgrade,METH_VARARGS,"Is pkg marked for upgrade"},
{"MarkedDelete",PkgDepCacheMarkedDelete,METH_VARARGS,"Is pkg marked for delete"},
diff --git a/python/indexfile.cc b/python/indexfile.cc
new file mode 100644
index 00000000..ef6ffc8a
--- /dev/null
+++ b/python/indexfile.cc
@@ -0,0 +1,92 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: indexfile.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $
+/* ######################################################################
+
+ pkgIndexFile - Wrapper for the pkgIndexFilefunctions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/indexfile.h>
+
+#include <Python.h>
+
+static PyObject *PackageIndexFileArchiveURI(PyObject *Self,PyObject *Args)
+{
+ pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self);
+ char *path;
+
+ if (PyArg_ParseTuple(Args, "s",&path) == 0)
+ return 0;
+
+ return HandleErrors(Safe_FromString(File->ArchiveURI(path).c_str()));
+}
+
+static PyMethodDef PackageIndexFileMethods[] =
+{
+ {"ArchiveURI",PackageIndexFileArchiveURI,METH_VARARGS,"Returns the ArchiveURI"},
+ {}
+};
+
+
+static PyObject *PackageIndexFileAttr(PyObject *Self,char *Name)
+{
+ pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self);
+ if (strcmp("Label",Name) == 0)
+ return Safe_FromString(File->GetType()->Label);
+ else if (strcmp("Describe",Name) == 0)
+ return Safe_FromString(File->Describe().c_str());
+ else if (strcmp("Exists",Name) == 0)
+ return Py_BuildValue("i",(File->Exists()));
+ else if (strcmp("HasPackages",Name) == 0)
+ return Py_BuildValue("i",(File->HasPackages()));
+ else if (strcmp("Size",Name) == 0)
+ return Py_BuildValue("i",(File->Size()));
+ else if (strcmp("IsTrusted",Name) == 0)
+ return Py_BuildValue("i",(File->IsTrusted()));
+
+ return Py_FindMethod(PackageIndexFileMethods,Self,Name);
+}
+
+static PyObject *PackageIndexFileRepr(PyObject *Self)
+{
+ pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self);
+
+ char S[300];
+ snprintf(S,sizeof(S),"<pkIndexFile object: "
+ "Label:'%s' Describe='%s' Exists='%i' "
+ "HasPackages='%i' Size='%i' "
+ "IsTrusted='%i' ArchiveURI='%s'>",
+ File->GetType()->Label, File->Describe().c_str(), File->Exists(),
+ File->HasPackages(), File->Size(),
+ File->IsTrusted(), File->ArchiveURI("").c_str());
+ return PyString_FromString(S);
+}
+
+PyTypeObject PackageIndexFileType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "pkgIndexFile", // tp_name
+ sizeof(CppOwnedPyObject<pkgIndexFile*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppOwnedDealloc<pkgIndexFile*>, // tp_dealloc
+ 0, // tp_print
+ PackageIndexFileAttr, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ PackageIndexFileRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+};
+
+
+
+
diff --git a/python/makefile b/python/makefile
index 16bfcd88..24ef3238 100644
--- a/python/makefile
+++ b/python/makefile
@@ -11,7 +11,8 @@ SLIBS = -lapt-pkg
LIB_MAKES = apt-pkg/makefile
APT_PKG_SRC = apt_pkgmodule.cc configuration.cc generic.cc tag.cc string.cc \
cache.cc pkgrecords.cc pkgsrcrecords.cc sourcelist.cc \
- depcache.cc progress.cc cdrom.cc
+ depcache.cc progress.cc cdrom.cc acquire.cc pkgmanager.cc \
+ indexfile.cc
SOURCE := $(APT_PKG_SRC)
include $(PYTHON_H) progress.h
diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc
new file mode 100644
index 00000000..bcd4c45b
--- /dev/null
+++ b/python/pkgmanager.cc
@@ -0,0 +1,135 @@
+// Description /*{{{*/
+// $Id: acquire.cc,v 1.1 2003/06/03 03:03:23 mvo Exp $
+/* ######################################################################
+
+ PkgManager - Wrapper for the pkgPackageManager code
+
+ ##################################################################### */
+
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include "pkgrecords.h"
+
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/acquire.h>
+#include <iostream>
+
+
+static PyObject *PkgManagerGetArchives(PyObject *Self,PyObject *Args)
+{
+ pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self);
+ PyObject *fetcher, *list, *recs;
+
+ if (PyArg_ParseTuple(Args, "O!O!O!",
+ &PkgAcquireType,&fetcher,
+ &PkgSourceListType, &list,
+ &PkgRecordsType, &recs) == 0)
+ return 0;
+
+ pkgAcquire *s_fetcher = GetCpp<pkgAcquire*>(fetcher);
+ pkgSourceList *s_list = GetCpp<pkgSourceList*>(list);
+ PkgRecordsStruct &s_records = GetCpp<PkgRecordsStruct>(recs);
+
+ bool res = pm->GetArchives(s_fetcher, s_list,
+ &s_records.Records);
+
+ return HandleErrors(Py_BuildValue("b",res));
+}
+
+static PyObject *PkgManagerDoInstall(PyObject *Self,PyObject *Args)
+{
+ //PkgManagerStruct &Struct = GetCpp<PkgManagerStruct>(Self);
+ pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self);
+ int status_fd = -1;
+
+ if (PyArg_ParseTuple(Args, "|i", &status_fd) == 0)
+ return 0;
+
+ pkgPackageManager::OrderResult res = pm->DoInstall(status_fd);
+
+ return HandleErrors(Py_BuildValue("i",res));
+}
+
+static PyObject *PkgManagerFixMissing(PyObject *Self,PyObject *Args)
+{
+ //PkgManagerStruct &Struct = GetCpp<PkgManagerStruct>(Self);
+ pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self);
+
+ if (PyArg_ParseTuple(Args, "") == 0)
+ return 0;
+
+ bool res = pm->FixMissing();
+
+ return HandleErrors(Py_BuildValue("b",res));
+}
+
+static PyMethodDef PkgManagerMethods[] =
+{
+ {"GetArchives",PkgManagerGetArchives,METH_VARARGS,"Load the selected archvies into the fetcher"},
+ {"DoInstall",PkgManagerDoInstall,METH_VARARGS,"Do the actual install"},
+ {"FixMissing",PkgManagerFixMissing,METH_VARARGS,"Fix the install if a pkg couldn't be downloaded"},
+ {}
+};
+
+
+static PyObject *PkgManagerAttr(PyObject *Self,char *Name)
+{
+ //PkgManagerStruct &Struct = GetCpp<PkgManagerStruct>(Self);
+ pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self);
+
+ // some constants
+ if(strcmp("ResultCompleted",Name) == 0)
+ return Py_BuildValue("i", pkgPackageManager::Completed);
+ if(strcmp("ResultFailed",Name) == 0)
+ return Py_BuildValue("i", pkgPackageManager::Failed);
+ if(strcmp("ResultIncomplete",Name) == 0)
+ return Py_BuildValue("i", pkgPackageManager::Incomplete);
+
+ return Py_FindMethod(PkgManagerMethods,Self,Name);
+}
+
+
+PyTypeObject PkgManagerType =
+{
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, // ob_size
+ "PackageManager", // tp_name
+ sizeof(CppPyObject<pkgPackageManager*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgPackageManager*>, // tp_dealloc
+ 0, // tp_print
+ PkgManagerAttr, // 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
+};
+
+#include <apt-pkg/init.h>
+#include <apt-pkg/configuration.h>
+
+PyObject *GetPkgManager(PyObject *Self,PyObject *Args)
+{
+ PyObject *Owner;
+ if (PyArg_ParseTuple(Args,"O!",&PkgDepCacheType,&Owner) == 0)
+ return 0;
+
+ pkgPackageManager *pm = _system->CreatePM(GetCpp<pkgDepCache*>(Owner));
+
+ CppPyObject<pkgPackageManager*> *PkgManagerObj =
+ CppPyObject_NEW<pkgPackageManager*>(&PkgManagerType,pm);
+
+ return PkgManagerObj;
+}
+
+
+
+
+ /*}}}*/
diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc
index 7f5aa0e2..ec78f554 100644
--- a/python/pkgrecords.cc
+++ b/python/pkgrecords.cc
@@ -10,20 +10,12 @@
// Include Files /*{{{*/
#include "generic.h"
#include "apt_pkgmodule.h"
+#include "pkgrecords.h"
-#include <apt-pkg/pkgrecords.h>
#include <Python.h>
/*}}}*/
-struct PkgRecordsStruct
-{
- pkgRecords Records;
- pkgRecords::Parser *Last;
-
- PkgRecordsStruct(pkgCache *Cache) : Records(*Cache), Last(0) {};
- PkgRecordsStruct() : Records(*(pkgCache *)0) {abort();}; // G++ Bug..
-};
// PkgRecords Class /*{{{*/
// ---------------------------------------------------------------------
@@ -54,7 +46,7 @@ static PyObject *PkgRecordsLookup(PyObject *Self,PyObject *Args)
// always return true (to make it consistent with the pkgsrcrecords object
return Py_BuildValue("i", 1);
}
-
+
static PyMethodDef PkgRecordsMethods[] =
{
{"Lookup",PkgRecordsLookup,METH_VARARGS,"Changes to a new package"},
@@ -81,6 +73,12 @@ static PyObject *PkgRecordsAttr(PyObject *Self,char *Name)
return CppPyString(Struct.Last->LongDesc());
else if (strcmp("Name",Name) == 0)
return CppPyString(Struct.Last->Name());
+ else if (strcmp("Record", Name) == 0)
+ {
+ const char *start, *stop;
+ Struct.Last->GetRec(start, stop);
+ return PyString_FromStringAndSize(start,stop-start);
+ }
}
return Py_FindMethod(PkgRecordsMethods,Self,Name);
diff --git a/python/pkgrecords.h b/python/pkgrecords.h
new file mode 100644
index 00000000..78787eab
--- /dev/null
+++ b/python/pkgrecords.h
@@ -0,0 +1,10 @@
+#include <apt-pkg/pkgrecords.h>
+
+struct PkgRecordsStruct
+{
+ pkgRecords Records;
+ pkgRecords::Parser *Last;
+
+ PkgRecordsStruct(pkgCache *Cache) : Records(*Cache), Last(0) {};
+ PkgRecordsStruct() : Records(*(pkgCache *)0) {abort();}; // G++ Bug..
+};
diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc
index 252810c7..5e04f5fc 100644
--- a/python/pkgsrcrecords.cc
+++ b/python/pkgsrcrecords.cc
@@ -43,7 +43,6 @@ static PyObject *PkgSrcRecordsLookup(PyObject *Self,PyObject *Args)
if (PyArg_ParseTuple(Args,"s",&Name) == 0)
return 0;
- Struct.Records->Restart();
Struct.Last = Struct.Records->Find(Name, false);
if (Struct.Last == 0) {
Struct.Records->Restart();
@@ -54,9 +53,25 @@ static PyObject *PkgSrcRecordsLookup(PyObject *Self,PyObject *Args)
return Py_BuildValue("i", 1);
}
+static char *doc_PkgSrcRecordsRestart = "Start Lookup from the begining";
+static PyObject *PkgSrcRecordsRestart(PyObject *Self,PyObject *Args)
+{
+ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self);
+
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Struct.Records->Restart();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
static PyMethodDef PkgSrcRecordsMethods[] =
{
{"Lookup",PkgSrcRecordsLookup,METH_VARARGS,doc_PkgSrcRecordsLookup},
+ {"Restart",PkgSrcRecordsRestart,METH_VARARGS,doc_PkgSrcRecordsRestart},
{}
};
@@ -81,8 +96,10 @@ static PyObject *PkgSrcRecordsAttr(PyObject *Self,char *Name)
*b != 0;
++b)
PyList_Append(List, CppPyString(*b));
-
return List; // todo
+ } else if (strcmp("Index",Name) == 0) {
+ const pkgIndexFile &tmp = Struct.Last->Index();
+ return CppOwnedPyObject_NEW<pkgIndexFile*>(Self,&PackageIndexFileType, (pkgIndexFile*)&tmp);
} else if (strcmp("Files",Name) == 0) {
PyObject *List = PyList_New(0);
@@ -126,10 +143,10 @@ PyTypeObject PkgSrcRecordsType =
PyObject_HEAD_INIT(&PyType_Type)
0, // ob_size
"pkgSrcRecords", // tp_name
- sizeof(CppOwnedPyObject<PkgSrcRecordsStruct>), // tp_basicsize
+ sizeof(CppPyObject<PkgSrcRecordsStruct>), // tp_basicsize
0, // tp_itemsize
// Methods
- CppOwnedDealloc<PkgSrcRecordsStruct>, // tp_dealloc
+ CppDealloc<PkgSrcRecordsStruct>, // tp_dealloc
0, // tp_print
PkgSrcRecordsAttr, // tp_getattr
0, // tp_setattr
@@ -145,11 +162,17 @@ PyTypeObject PkgSrcRecordsType =
PyObject *GetPkgSrcRecords(PyObject *Self,PyObject *Args)
{
+#if 0
PyObject *Owner;
if (PyArg_ParseTuple(Args,"O!",&PkgCacheType,&Owner) == 0)
return 0;
return HandleErrors(CppOwnedPyObject_NEW<PkgSrcRecordsStruct>(Owner,
&PkgSrcRecordsType));
+#endif
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ return HandleErrors(CppPyObject_NEW<PkgSrcRecordsStruct>(&PkgSrcRecordsType));
}
diff --git a/python/progress.cc b/python/progress.cc
index 12f9c7a8..f00058c9 100644
--- a/python/progress.cc
+++ b/python/progress.cc
@@ -218,7 +218,7 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm)
// support custom fork methods
if(PyObject_HasAttrString(callbackInst, "fork")) {
PyObject *method = PyObject_GetAttrString(callbackInst, "fork");
- //std::cerr << "custom fork found" << std::endl;
+ std::cerr << "custom fork found" << std::endl;
PyObject *arglist = Py_BuildValue("()");
PyObject *result = PyEval_CallObject(method, arglist);
Py_DECREF(arglist);
@@ -227,9 +227,11 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm)
PyErr_Print();
return pkgPackageManager::Failed;
}
- if(!PyArg_Parse(result, "i", &child_id) )
+ if(!PyArg_Parse(result, "i", &child_id) ) {
std::cerr << "custom fork() result could not be parsed?"<< std::endl;
- //std::cerr << "got: " << child_id << std::endl;
+ return pkgPackageManager::Failed;
+ }
+ std::cerr << "got pid: " << child_id << std::endl;
} else {
//std::cerr << "using build-in fork()" << std::endl;
child_id = fork();
@@ -251,15 +253,39 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm)
} else {
res = pm->DoInstall();
}
+ //std::cout << "res: " << res << std::endl;
_exit(res);
}
StartUpdate();
- while (waitpid(child_id, &ret, WNOHANG) == 0)
- UpdateInterface();
- res = (pkgPackageManager::OrderResult) WEXITSTATUS(ret);
+ if(PyObject_HasAttrString(callbackInst, "waitChild")) {
+ PyObject *method = PyObject_GetAttrString(callbackInst, "waitChild");
+ //std::cerr << "custom waitChild found" << std::endl;
+ PyObject *arglist = Py_BuildValue("(i)",child_id);
+ PyObject *result = PyEval_CallObject(method, arglist);
+ Py_DECREF(arglist);
+ if (result == NULL) {
+ std::cerr << "waitChild method invalid" << std::endl;
+ PyErr_Print();
+ return pkgPackageManager::Failed;
+ }
+ int child_res;
+ if(!PyArg_Parse(result, "i", &res) ) {
+ std::cerr << "custom waitChild() result could not be parsed?"<< std::endl;
+ return pkgPackageManager::Failed;
+ }
+ //std::cerr << "got child_res: " << res << std::endl;
+ } else {
+ //std::cerr << "using build-in waitpid()" << std::endl;
+
+ while (waitpid(child_id, &ret, WNOHANG) == 0)
+ UpdateInterface();
+
+ res = (pkgPackageManager::OrderResult) WEXITSTATUS(ret);
+ //std::cerr << "build-in waitpid() got: " << res << std::endl;
+ }
FinishUpdate();
@@ -273,6 +299,10 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm)
void PyCdromProgress::Update(string text, int current)
{
PyObject *arglist = Py_BuildValue("(si)", text.c_str(), current);
+
+ PyObject *o = Py_BuildValue("i", totalSteps);
+ PyObject_SetAttrString(callbackInst, "totalSteps", o);
+
RunSimpleCallback("update", arglist);
}
diff --git a/python/sourcelist.cc b/python/sourcelist.cc
index e2343e1c..16e51368 100644
--- a/python/sourcelist.cc
+++ b/python/sourcelist.cc
@@ -3,7 +3,7 @@
// $Id: sourcelist.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $
/* ######################################################################
- Package Records - Wrapper for the package records functions
+ SourcesList - Wrapper for the SourcesList functions
##################################################################### */
/*}}}*/
@@ -16,10 +16,7 @@
#include <Python.h>
/*}}}*/
-struct PkgSourceListStruct
-{
- pkgSourceList List;
-};
+
// PkgsourceList Class /*{{{*/
// ---------------------------------------------------------------------
@@ -27,23 +24,57 @@ struct PkgSourceListStruct
static char *doc_PkgSourceListFindIndex = "xxx";
static PyObject *PkgSourceListFindIndex(PyObject *Self,PyObject *Args)
{
- PkgSourceListStruct &Struct = GetCpp<PkgSourceListStruct>(Self);
- return Py_BuildValue("i", 1);
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+ PyObject *pyPkgFileIter;
+ PyObject *pyPkgIndexFile;
+
+ if (PyArg_ParseTuple(Args, "O!", &PackageFileType,&pyPkgFileIter) == 0)
+ return 0;
+
+ pkgCache::PkgFileIterator &i = GetCpp<pkgCache::PkgFileIterator>(pyPkgFileIter);
+ pkgIndexFile *index;
+ if(list->FindIndex(i, index))
+ {
+ pyPkgIndexFile = CppOwnedPyObject_NEW<pkgIndexFile*>(pyPkgFileIter,&PackageIndexFileType,index);
+ return pyPkgIndexFile;
+ }
+
+ //&PackageIndexFileType,&pyPkgIndexFile)
+
+ Py_INCREF(Py_None);
+ return Py_None;
}
static char *doc_PkgSourceListReadMainList = "xxx";
static PyObject *PkgSourceListReadMainList(PyObject *Self,PyObject *Args)
{
- PkgSourceListStruct &Struct = GetCpp<PkgSourceListStruct>(Self);
- Struct.List.ReadMainList();
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+ bool res = list->ReadMainList();
- return Py_None;
+ return HandleErrors(Py_BuildValue("b",res));
+}
+
+static char *doc_PkgSourceListGetIndexes = "Load the indexes into the fetcher";
+static PyObject *PkgSourceListGetIndexes(PyObject *Self,PyObject *Args)
+{
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+
+ PyObject *pyFetcher;
+
+ if (PyArg_ParseTuple(Args, "O!",&PkgAcquireType,&pyFetcher) == 0)
+ return 0;
+
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyFetcher);
+ bool res = list->GetIndexes(fetcher);
+
+ return HandleErrors(Py_BuildValue("b",res));
}
static PyMethodDef PkgSourceListMethods[] =
{
{"FindIndex",PkgSourceListFindIndex,METH_VARARGS,doc_PkgSourceListFindIndex},
{"ReadMainList",PkgSourceListReadMainList,METH_VARARGS,doc_PkgSourceListReadMainList},
+ {"GetIndexes",PkgSourceListGetIndexes,METH_VARARGS,doc_PkgSourceListReadMainList},
{}
};
@@ -56,10 +87,10 @@ PyTypeObject PkgSourceListType =
PyObject_HEAD_INIT(&PyType_Type)
0, // ob_size
"pkgSourceList", // tp_name
- sizeof(CppPyObject<PkgSourceListStruct>), // tp_basicsize
+ sizeof(CppPyObject<pkgSourceList*>), // tp_basicsize
0, // tp_itemsize
// Methods
- CppDealloc<PkgSourceListStruct>, // tp_dealloc
+ CppDealloc<pkgSourceList*>, // tp_dealloc
0, // tp_print
PkgSourceListAttr, // tp_getattr
0, // tp_setattr
@@ -73,6 +104,6 @@ PyTypeObject PkgSourceListType =
PyObject *GetPkgSourceList(PyObject *Self,PyObject *Args)
{
- return CppPyObject_NEW<PkgSourceListStruct>(&PkgSourceListType);
+ return CppPyObject_NEW<pkgSourceList*>(&PkgSourceListType,new pkgSourceList());
}
diff --git a/python/tar.cc b/python/tar.cc
index 20fb1f5f..22c0327e 100644
--- a/python/tar.cc
+++ b/python/tar.cc
@@ -88,7 +88,7 @@ bool ProcessTar::DoItem(Item &Itm,int &Fd)
// ---------------------------------------------------------------------
/* */
char *doc_tarExtract =
-"tarExtract(File,Func,Comp) -> None"
+"tarExtract(File,Func,Comp) -> None\n"
"The tar file referenced by the file object File, Func called for each\n"
"Tar member. Comp must be the string \"gzip\" (gzip is automatically invoked) \n";
PyObject *tarExtract(PyObject *Self,PyObject *Args)
@@ -128,7 +128,7 @@ PyObject *tarExtract(PyObject *Self,PyObject *Args)
// ---------------------------------------------------------------------
/* */
char *doc_debExtract =
-"debExtract(File,Func,Chunk) -> None"
+"debExtract(File,Func,Chunk) -> None\n"
"The deb referenced by the file object File is examined. The AR member\n"
"given by Chunk is treated as a tar.gz and fed through Func like\n"
"tarExtract\n";
diff --git a/setup.py b/setup.py
index f9255607..5adb0376 100644
--- a/setup.py
+++ b/setup.py
@@ -7,22 +7,18 @@ import string, glob
# The apt_pkg module
-files = string.split(parse_makefile("python/makefile")["APT_PKG_SRC"]);
-for i in range(0,len(files)):
- files[i] = "python/"+ files[i];
-apt_pkg = Extension("apt_pkg", files,
- libraries=["apt-pkg"]);
+files = map(lambda source: "python/"+source,
+ string.split(parse_makefile("python/makefile")["APT_PKG_SRC"]))
+apt_pkg = Extension("apt_pkg", files, libraries=["apt-pkg"]);
# The apt_inst module
-files = string.split(parse_makefile("python/makefile")["APT_INST_SRC"]);
-for i in range(0,len(files)):
- files[i] = "python/"+ files[i];
-apt_inst = Extension("apt_inst", files,
- libraries=["apt-pkg","apt-inst"]);
+files = map(lambda source: "python/"+source,
+ string.split(parse_makefile("python/makefile")["APT_INST_SRC"]))
+apt_inst = Extension("apt_inst", files, libraries=["apt-pkg","apt-inst"]);
setup(name="python-apt",
- version="0.6.13",
+ version="0.6.17",
description="Python bindings for APT",
author="APT Development Team",
author_email="deity@lists.debian.org",
diff --git a/tests/memleak.py b/tests/memleak.py
new file mode 100755
index 00000000..3e59cbb7
--- /dev/null
+++ b/tests/memleak.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+import apt
+import apt_pkg
+import time
+import gc
+import sys
+
+
+cache = apt.Cache()
+
+# memleak
+#for i in range(100):
+# cache.open(None)
+# print cache["apt"].name
+# time.sleep(1)
+# gc.collect()
+
+# memleak
+#for i in range(100):
+# cache = apt.Cache()
+# time.sleep(1)
+# cache = None
+# gc.collect()
+
+# no memleak, but more or less the apt.Cache.open() code
+for i in range(100):
+ cache = apt_pkg.GetCache()
+ depcache = apt_pkg.GetDepCache(cache)
+ records = apt_pkg.GetPkgRecords(cache)
+ list = apt_pkg.GetPkgSourceList()
+ list.ReadMainList()
+ dict = {}
+ for pkg in cache.Packages:
+ if len(pkg.VersionList) > 0:
+ dict[pkg.Name] = apt.Package(cache,depcache,
+ records, list, None, pkg)
+
+ print cache["apt"]
+ time.sleep(1)
+
+ gc.collect()
diff --git a/tests/pkgsrcrecords.py b/tests/pkgsrcrecords.py
index dc4881dd..28df3f7c 100644
--- a/tests/pkgsrcrecords.py
+++ b/tests/pkgsrcrecords.py
@@ -14,7 +14,7 @@ def main():
print "Running PkgSrcRecords test on all packages:"
for x in cache.Packages:
i += 1
- src = apt_pkg.GetPkgSrcRecords(cache)
+ src = apt_pkg.GetPkgSrcRecords()
if src.Lookup(x.Name):
#print src.Package
pass