diff options
| author | Michael Vogt <mvo@debian.org> | 2005-10-21 21:07:38 +0000 |
|---|---|---|
| committer | Michael Vogt <mvo@debian.org> | 2005-10-21 21:07:38 +0000 |
| commit | f701fc174a88d8f2b418a032571ff40ed6fd56e6 (patch) | |
| tree | d2a0ebed225e24207c952430390a51d3628a03fb | |
| parent | 76bf6920764c1a9a67586d23743f31311b66b811 (diff) | |
| parent | bd6df1d8419eb3403e64191681b32fbd1f3accac (diff) | |
| download | python-apt-f701fc174a88d8f2b418a032571ff40ed6fd56e6.tar.gz | |
* merged with apt--mvo
Patches applied:
* michael.vogt@ubuntu.com--2005/python-apt--mvo--0--patch-77
* merged with the progress reporting code
* michael.vogt@ubuntu.com--2005/python-apt--mvo--0--patch-78
* progress interface fully working now, commit interface too
* michael.vogt@ubuntu.com--2005/python-apt--mvo--0--patch-79
* fix a crasher in the install interface
* michael.vogt@ubuntu.com--2005/python-apt--progress-reporting--0--base-0
tag of michael.vogt@ubuntu.com--2005/python-apt--mvo--0--patch-43
* michael.vogt@ubuntu.com--2005/python-apt--progress-reporting--0--patch-1
* support the apt--progress-reporting--0 branch (using "InstallProgress.statusfd)
* michael.vogt@ubuntu.com--2005/python-apt--progress-reporting--0--patch-2
* support for update reporting via vte/progress bars added, including a evil "pass-me-my-file-descriptor" hack
* michael.vogt@ubuntu.com--2005/python-apt--progress-reporting--0--patch-3
* merged with python-apt--mvo
* michael.vogt@ubuntu.com--2005/python-apt--progress-reporting--0--patch-4
* merged from python-apt--mvo
* michael.vogt@ubuntu.com--2005/python-apt--progress-reporting--0--patch-5
* better support new python-apt, added example for gui-inst with support for VTE_PTY_KEEP_FD
* michael.vogt@ubuntu.com--2005/python-apt--progress-reporting--0--patch-6
* removed the fdsend stuff again, libvte will be patched instead
| -rw-r--r-- | apt/progress.py | 58 | ||||
| -rwxr-xr-x[-rw-r--r--] | doc/examples/gui-inst.py | 54 | ||||
| -rw-r--r-- | doc/examples/inst.py | 16 | ||||
| -rw-r--r-- | python/apt_pkgmodule.cc | 3 | ||||
| -rw-r--r-- | python/depcache.cc | 41 | ||||
| -rw-r--r-- | python/makefile | 1 | ||||
| -rw-r--r-- | python/progress.cc | 26 | ||||
| -rw-r--r-- | python/progress.h | 6 | ||||
| -rw-r--r-- | setup.py | 1 |
9 files changed, 154 insertions, 52 deletions
diff --git a/apt/progress.py b/apt/progress.py index 6fd2977a..86cd6594 100644 --- a/apt/progress.py +++ b/apt/progress.py @@ -44,10 +44,23 @@ class OpTextProgress(OpProgress): -class FetchProgress: +class FetchProgress(object): """ Report the download/fetching progress Subclass this class to implement fetch progress reporting """ + + # download status constants + dlDone = 0 + dlQueued = 1 + dlFailed = 2 + dlHit = 3 + dlIgnored = 4 + dlStatusStr = {dlDone : "Done", + dlQueued : "Queued", + dlFailed : "Failed", + dlHit : "Hit", + dlIgnored : "Ignored"} + def __init__(self): pass @@ -61,13 +74,46 @@ class FetchProgress: pass def pulse(self): - """ called periodically (to update the gui) """ + """ called periodically (to update the gui), importend to + return True to continue or False to cancel + """ + self.percent = ((self.currentBytes + self.currentItems)*100.0)/float(self.totalBytes+self.totalItems) + if self.currentCPS > 0: + self.eta = (self.totalBytes-self.currentBytes)/float(self.currentCPS) return True - def mediaChange(self, medium, drive): pass - +class TextFetchProgress(FetchProgress): + """ Ready to use progress object for terminal windows """ + def __init__(self): + self.items = {} + def updateStatus(self, uri, descr, shortDescr, status): + if status != self.dlQueued: + print "\r%s %s" % (self.dlStatusStr[status], descr) + self.items[uri] = status + def pulse(self): + FetchProgress.pulse(self) + if self.currentCPS > 0: + s = "[%2.f%%] %sB/s %s" % (self.percent, + apt_pkg.SizeToStr(int(self.currentCPS)), + apt_pkg.TimeToStr(int(self.eta))) + else: + s = "%2.f%% [Working]" % (self.percent) + print "\r%s" % (s), + sys.stdout.flush() + return True + def stop(self): + print "\rDone " + def mediaChange(self, medium, drive): + """ react to media change events """ + res = True; + print "Media change: please insert the disc labeled \ + '%s' in the drive '%s' and press enter" % (medium,drive) + s = sys.stdin.readline() + if(s == 'c' or s == 'C'): + res = false; + return res class InstallProgress: """ Report the install progress @@ -82,7 +128,6 @@ class InstallProgress: def updateInterface(self): pass - class CdromProgress: """ Report the cdrom add progress Subclass this class to implement cdrom add progress reporting @@ -105,3 +150,6 @@ if __name__ == "__main__": cache = apt_pkg.GetCache(progress) depcache = apt_pkg.GetDepCache(cache) depcache.Init(progress) + + fprogress = TextFetchProgress() + cache.Update(fprogress) diff --git a/doc/examples/gui-inst.py b/doc/examples/gui-inst.py index b2f64e91..38417e10 100644..100755 --- a/doc/examples/gui-inst.py +++ b/doc/examples/gui-inst.py @@ -3,8 +3,10 @@ # see also gnome bug: #169201 import apt_pkg -import sys, os +import sys, os, fcntl import copy +import string +import fcntl import pygtk pygtk.require('2.0') @@ -28,13 +30,14 @@ class GuiFetchProgress(gtk.Window, FetchProgress): self.vbox.pack_start(self.label) self.resize(300,100) def start(self): - self.progress.set_fraction(0) + print "start" + self.progress.set_fraction(0.0) self.show() def stop(self): self.hide() def pulse(self): self.label.set_text("Speed: %s/s" % apt_pkg.SizeToStr(self.currentCPS)) - self.progress.set_fraction(self.currentBytes/self.totalBytes) + #self.progressbar.set_fraction(self.currentBytes/self.totalBytes) while gtk.events_pending(): gtk.main_iteration() @@ -42,21 +45,54 @@ class TermInstallProgress(InstallProgress, gtk.Window): def __init__(self): gtk.Window.__init__(self) self.show() + box = gtk.VBox() + box.show() + self.add(box) self.term = vte.Terminal() self.term.show() - self.add(self.term) - def start(self): - self.progress.set_fraction(0) + 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") + fcntl.fcntl(self.status.fileno(), fcntl.F_SETFL,os.O_NONBLOCK) + print "read-fd: %s" % self.status.fileno() + print "write-fd: %s" % self.writefd + self.read = "" + + def startUpdate(self): + print "start" self.show() - def stop(self): - self.hide() def updateInterface(self): + if self.status != None: + try: + self.read += os.read(self.status.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) + self.progressbar.set_fraction(float(percent)/100.0) + self.progressbar.set_text(string.strip(status_str)) + self.read = "" while gtk.events_pending(): gtk.main_iteration() def finishUpdate(self): sys.stdin.readline() def fork(self): - return self.term.forkpty() + print "fork" + env = ["VTE_PTY_KEEP_FD=%s"%self.writefd] + print env + pid = self.term.forkpty(envv=env) + print "After fork: %s " % pid + return pid # init diff --git a/doc/examples/inst.py b/doc/examples/inst.py index b25cf542..fe5ec8e3 100644 --- a/doc/examples/inst.py +++ b/doc/examples/inst.py @@ -1,6 +1,7 @@ #!/usr/bin/python # example how to deal with the depcache +import apt import apt_pkg import sys, os import copy @@ -8,6 +9,21 @@ import copy from progress import TextFetchProgress, TextInstallProgress from apt.progress import OpTextProgress +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() diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 9a3aac37..ce337f0f 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -449,14 +449,13 @@ extern "C" void initapt_pkg() AddInt(Dict,"DepConflicts",pkgCache::Dep::Conflicts); AddInt(Dict,"DepReplaces",pkgCache::Dep::Replaces); AddInt(Dict,"DepObsoletes",pkgCache::Dep::Obsoletes); - + AddInt(Dict,"PriImportant",pkgCache::State::Important); AddInt(Dict,"PriRequired",pkgCache::State::Required); AddInt(Dict,"PriStandard",pkgCache::State::Standard); AddInt(Dict,"PriOptional",pkgCache::State::Optional); AddInt(Dict,"PriExtra",pkgCache::State::Extra); - } /*}}}*/ diff --git a/python/depcache.cc b/python/depcache.cc index 418ddd14..c78d0077 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -27,6 +27,9 @@ #include <iostream> #include "progress.h" +#ifndef _ +#define _(x) (x) +#endif @@ -96,7 +99,7 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) return HandleErrors(); } - std::cout << "PM created" << std::endl; + //std::cout << "PM created" << std::endl; PyInstallProgress iprogress; iprogress.setCallbackInst(pyInstallProgressInst); @@ -124,15 +127,16 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) continue; } - //FIXME: report this error somehow -// fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(), -// (*I)->ErrorText.c_str()); + _error->Warning(_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(), + (*I)->ErrorText.c_str()); Failed = true; } -#if 0 // check that stuff if (Transient == true && Failed == true) - return Py_None; /*_error->Error(_("--fix-missing and media swapping is not currently supported"));*/ + { + _error->Error(_("--fix-missing and media swapping is not currently supported")); + return HandleErrors(Py_None); + } // Try to deal with missing package files if (Failed == true && PM->FixMissing() == false) @@ -141,7 +145,6 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) _error->Error("Aborting install."); return HandleErrors(Py_None); } -#endif _system->UnLock(); @@ -164,29 +167,7 @@ static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) } _system->Lock(); } - - - -#if 0 - if (Fetcher.Run() == pkgAcquire::Failed) - return HandleErrors(Py_None); - - std::cout << "Fetcher was run" << std::endl; - - // FIXME: incomplete, see apt-get.cc - _system->UnLock(); - - pkgPackageManager::OrderResult Res = PM->DoInstall(); - if (Res == pkgPackageManager::Failed || _error->PendingError() == true) - return Py_None/*false;*/; - if (Res == pkgPackageManager::Completed) - return Py_None /*true;*/; - - _system->Lock(); -#endif - - // FIXME: open the cache here again - + return HandleErrors(Py_None); } diff --git a/python/makefile b/python/makefile index 273096a7..16bfcd88 100644 --- a/python/makefile +++ b/python/makefile @@ -22,3 +22,4 @@ LIB_MAKES = apt-inst/makefile APT_INST_SRC = apt_instmodule.cc tar.cc generic.cc SOURCE := $(APT_INST_SRC) include $(PYTHON_H) + diff --git a/python/progress.cc b/python/progress.cc index f79090f7..12f9c7a8 100644 --- a/python/progress.cc +++ b/python/progress.cc @@ -9,8 +9,10 @@ #include <iostream> #include <sys/types.h> #include <sys/wait.h> +#include <apt-pkg/acquire-item.h> #include "progress.h" + // generic bool PyCallbackObj::RunSimpleCallback(const char* method_name, PyObject *arglist, @@ -74,9 +76,6 @@ void PyOpProgress::Done() // fetcher interface -enum { - DLDone, DLQueued, DLFailed, DLHit -}; // apt interface @@ -121,6 +120,15 @@ void PyFetchProgress::Done(pkgAcquire::ItemDesc &Itm) void PyFetchProgress::Fail(pkgAcquire::ItemDesc &Itm) { + // Ignore certain kinds of transient failures (bad code) + if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) + return; + + if (Itm.Owner->Status == pkgAcquire::Item::StatDone) + { + UpdateStatus(Itm, DLIgnored); + } + UpdateStatus(Itm, DLFailed); } @@ -220,7 +228,7 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) return pkgPackageManager::Failed; } if(!PyArg_Parse(result, "i", &child_id) ) - std::cerr << "result could not be parsed?"<< std::endl; + std::cerr << "custom fork() result could not be parsed?"<< std::endl; //std::cerr << "got: " << child_id << std::endl; } else { //std::cerr << "using build-in fork()" << std::endl; @@ -235,10 +243,18 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) } #endif if (child_id == 0) { - res = pm->DoInstall(); + PyObject *v = PyObject_GetAttrString(callbackInst, "writefd"); + if(v) { + int fd = PyObject_AsFileDescriptor(v); + cout << "got fd: " << fd << endl; + res = pm->DoInstall(fd); + } else { + res = pm->DoInstall(); + } _exit(res); } + StartUpdate(); while (waitpid(child_id, &ret, WNOHANG) == 0) UpdateInterface(); diff --git a/python/progress.h b/python/progress.h index f116c811..f04bd683 100644 --- a/python/progress.h +++ b/python/progress.h @@ -15,6 +15,7 @@ #include <apt-pkg/cdrom.h> #include <Python.h> + class PyCallbackObj { protected: PyObject *callbackInst; @@ -44,6 +45,10 @@ struct PyOpProgress : public OpProgress, public PyCallbackObj struct PyFetchProgress : public pkgAcquireStatus, public PyCallbackObj { + enum { + DLDone, DLQueued, DLFailed, DLHit, DLIgnored + }; + void UpdateStatus(pkgAcquire::ItemDesc & Itm, int status); virtual bool MediaChange(string Media, string Drive); @@ -58,7 +63,6 @@ struct PyFetchProgress : public pkgAcquireStatus, public PyCallbackObj bool Pulse(pkgAcquire * Owner); PyFetchProgress() : PyCallbackObj() {}; - }; struct PyInstallProgress : public PyCallbackObj @@ -20,6 +20,7 @@ for i in range(0,len(files)): apt_inst = Extension("apt_inst", files, libraries=["apt-pkg","apt-inst"]); + setup(name="python-apt", version="0.6.13", description="Python bindings for APT", |
