summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vogt <mvo@debian.org>2005-10-21 21:07:38 +0000
committerMichael Vogt <mvo@debian.org>2005-10-21 21:07:38 +0000
commitf701fc174a88d8f2b418a032571ff40ed6fd56e6 (patch)
treed2a0ebed225e24207c952430390a51d3628a03fb
parent76bf6920764c1a9a67586d23743f31311b66b811 (diff)
parentbd6df1d8419eb3403e64191681b32fbd1f3accac (diff)
downloadpython-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.py58
-rwxr-xr-x[-rw-r--r--]doc/examples/gui-inst.py54
-rw-r--r--doc/examples/inst.py16
-rw-r--r--python/apt_pkgmodule.cc3
-rw-r--r--python/depcache.cc41
-rw-r--r--python/makefile1
-rw-r--r--python/progress.cc26
-rw-r--r--python/progress.h6
-rw-r--r--setup.py1
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
diff --git a/setup.py b/setup.py
index fe9d3ce1..f9255607 100644
--- a/setup.py
+++ b/setup.py
@@ -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",