summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt/progress/__init__.py5
-rw-r--r--doc/examples/progress.py14
-rw-r--r--po/python-apt.pot8
-rw-r--r--python/progress.cc108
4 files changed, 119 insertions, 16 deletions
diff --git a/apt/progress/__init__.py b/apt/progress/__init__.py
index 769942ce..68441cfa 100644
--- a/apt/progress/__init__.py
+++ b/apt/progress/__init__.py
@@ -107,13 +107,14 @@ class FetchProgress(object):
def stop(self):
"""Called when all files have been fetched."""
- def updateStatus(self, uri, descr, shortDescr, status):
+ def updateStatus(self, uri, descr, shortDescr, status, fileSize,
+ partialSize):
"""Called when the status of an item changes.
This happens eg. when the downloads fails or is completed.
"""
- def pulse(self):
+ def pulse(self, items):
"""Called periodically to update the user interface.
Return True to continue or False to cancel.
diff --git a/doc/examples/progress.py b/doc/examples/progress.py
index 2231001f..f7650f69 100644
--- a/doc/examples/progress.py
+++ b/doc/examples/progress.py
@@ -34,14 +34,20 @@ class TextFetchProgress(apt.FetchProgress):
def stop(self):
pass
- def updateStatus(self, uri, descr, shortDescr, status):
- print "UpdateStatus: '%s' '%s' '%s' '%i'" % (
- uri, descr, shortDescr, status)
+ def updateStatus(self, uri, descr, shortDescr, status, fileSize,
+ partialSize):
+ print "UpdateStatus: '%s' '%s' '%s' '%i' '%d/%d'" % (
+ uri, descr, shortDescr, status, partialSize, fileSize)
- def pulse(self):
+ def pulse(self, items):
print "Pulse: CPS: %s/s; Bytes: %s/%s; Item: %s/%s" % (
apt.SizeToStr(self.currentCPS), apt.SizeToStr(self.currentBytes),
apt.SizeToStr(self.totalBytes), self.currentItems, self.totalItems)
+ print "Pulse-Items: "
+ for itm in items:
+ uri, descr, shortDescr, fileSize, partialSize = itm
+ print " - '%s' '%s' '%s' '%d/%d'" % (
+ uri, descr, shortDescr, partialSize, fileSize
return True
def mediaChange(self, medium, drive):
diff --git a/po/python-apt.pot b/po/python-apt.pot
index 9c23c579..27f7e1af 100644
--- a/po/python-apt.pot
+++ b/po/python-apt.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-04-12 19:07+0200\n"
+"POT-Creation-Date: 2009-04-30 12:52+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -359,11 +359,11 @@ msgstr ""
msgid "Invalid unicode in description for '%s' (%s). Please report."
msgstr ""
-#: ../apt/package.py:745 ../apt/package.py:849
+#: ../apt/package.py:747 ../apt/package.py:851
msgid "The list of changes is not available"
msgstr ""
-#: ../apt/package.py:853
+#: ../apt/package.py:855
#, python-format
msgid ""
"The list of changes is not available yet.\n"
@@ -372,7 +372,7 @@ msgid ""
"until the changes become available or try again later."
msgstr ""
-#: ../apt/package.py:859
+#: ../apt/package.py:861
msgid ""
"Failed to download the list of changes. \n"
"Please check your Internet connection."
diff --git a/python/progress.cc b/python/progress.cc
index c5a1c138..a30ea2e7 100644
--- a/python/progress.cc
+++ b/python/progress.cc
@@ -9,10 +9,12 @@
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
+#include <map>
+#include <utility>
#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/acquire-worker.h>
#include "progress.h"
-
// generic
bool PyCallbackObj::RunSimpleCallback(const char* method_name,
PyObject *arglist,
@@ -31,14 +33,16 @@ bool PyCallbackObj::RunSimpleCallback(const char* method_name,
return false;
}
PyObject *result = PyEval_CallObject(method, arglist);
+
Py_XDECREF(arglist);
if(result == NULL) {
// exception happend
std::cerr << "Error in function " << method_name << std::endl;
PyErr_Print();
+ PyErr_Clear();
- return NULL;
+ return false;
}
if(res != NULL)
*res = result;
@@ -84,6 +88,7 @@ void PyOpProgress::Done()
// apt interface
+
bool PyFetchProgress::MediaChange(string Media, string Drive)
{
//std::cout << "MediaChange" << std::endl;
@@ -104,7 +109,17 @@ bool PyFetchProgress::MediaChange(string Media, string Drive)
void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status)
{
//std::cout << "UpdateStatus: " << Itm.URI << " " << status << std::endl;
- PyObject *arglist = Py_BuildValue("(sssi)", Itm.URI.c_str(), Itm.Description.c_str(), Itm.ShortDesc.c_str(), status);
+
+ // Added object file size and object partial size to
+ // parameters that are passed to updateStatus.
+ // -- Stephan
+ PyObject *arglist = Py_BuildValue("(sssikk)", Itm.URI.c_str(),
+ Itm.Description.c_str(),
+ Itm.ShortDesc.c_str(),
+ status,
+ Itm.Owner->FileSize,
+ Itm.Owner->PartialSize);
+
RunSimpleCallback("updateStatus", arglist);
}
@@ -141,6 +156,28 @@ void PyFetchProgress::Start()
{
//std::cout << "Start" << std::endl;
pkgAcquireStatus::Start();
+
+ // These attributes should be initialized before the first callback (start)
+ // is invoked.
+ // -- Stephan
+ PyObject *o;
+
+ o = Py_BuildValue("f", 0.0f);
+ PyObject_SetAttrString(callbackInst, "currentCPS", o);
+ Py_XDECREF(o);
+ o = Py_BuildValue("f", 0.0f);
+ PyObject_SetAttrString(callbackInst, "currentBytes", o);
+ Py_XDECREF(o);
+ o = Py_BuildValue("i", 0);
+ PyObject_SetAttrString(callbackInst, "currentItems", o);
+ Py_XDECREF(o);
+ o = Py_BuildValue("i", 0);
+ PyObject_SetAttrString(callbackInst, "totalItems", o);
+ Py_XDECREF(o);
+ o = Py_BuildValue("f", 0.0f);
+ PyObject_SetAttrString(callbackInst, "totalBytes", o);
+ Py_XDECREF(o);
+
RunSimpleCallback("start");
}
@@ -178,12 +215,71 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
PyObject_SetAttrString(callbackInst, "totalBytes", o);
Py_XDECREF(o);
- PyObject *arglist = Py_BuildValue("()");
+ // Go through the list of items and add active items to the
+ // activeItems vector.
+ map<pkgAcquire::Worker *, pkgAcquire::ItemDesc *> activeItemMap;
+
+ for(pkgAcquire::Worker *Worker = Owner->WorkersBegin();
+ Worker != 0; Worker = Owner->WorkerStep(Worker)) {
+
+ if (Worker->CurrentItem == 0) {
+ // Ignore workers with no item running
+ continue;
+ }
+ activeItemMap.insert(std::make_pair(Worker, Worker->CurrentItem));
+ }
+
+ // Create the tuple that is passed as argument to pulse().
+ // This tuple contains activeItemMap.size() item tuples.
+ PyObject *arglist;
+
+ if (((int)activeItemMap.size()) > 0) {
+ PyObject *itemsTuple = PyTuple_New((Py_ssize_t) activeItemMap.size());
+
+ // Go through activeItems, create an item tuple in the form
+ // (URI, Description, ShortDesc, FileSize, PartialSize) and
+ // add that tuple to itemsTuple.
+ map<pkgAcquire::Worker *, pkgAcquire::ItemDesc *>::iterator iter;
+ int tuplePos;
+
+ for(tuplePos = 0, iter = activeItemMap.begin();
+ iter != activeItemMap.end(); ++iter, tuplePos++) {
+ pkgAcquire::Worker *worker = iter->first;
+ pkgAcquire::ItemDesc *itm = iter->second;
+
+ PyObject *itmTuple = Py_BuildValue("(ssskk)", itm->URI.c_str(),
+ itm->Description.c_str(),
+ itm->ShortDesc.c_str(),
+ worker->TotalSize,
+ worker->CurrentSize);
+ PyTuple_SetItem(itemsTuple, tuplePos, itmTuple);
+ }
+
+ // Now our itemsTuple is ready for being passed to pulse().
+ // pulse() is going to receive a single argument, being the
+ // tuple of items, which again contains one tuple with item
+ // information per item.
+ //
+ // Python Example:
+ //
+ // class MyFetchProgress(FetchProgress):
+ // def pulse(self, items):
+ // for itm in items:
+ // uri, desc, shortdesc, filesize, partialsize = itm
+ //
+ arglist = PyTuple_Pack(1, itemsTuple);
+ }
+ else {
+ arglist = Py_BuildValue("(())");
+ }
+
PyObject *result;
- RunSimpleCallback("pulse", arglist, &result);
+ if (!RunSimpleCallback("pulse", arglist, &result)) {
+ return true;
+ }
bool res = true;
- if(!PyArg_Parse(result, "b", &res))
+ if((result == NULL) || (!PyArg_Parse(result, "b", &res)))
{
// most of the time the user who subclasses the pulse()
// method forgot to add a return {True,False} so we just