summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/acquireprogress.cc198
-rw-r--r--python/apt_pkgmodule.cc2
-rw-r--r--python/apt_pkgmodule.h2
-rw-r--r--python/opprogress.cc173
-rw-r--r--python/progress.cc14
5 files changed, 387 insertions, 2 deletions
diff --git a/python/acquireprogress.cc b/python/acquireprogress.cc
new file mode 100644
index 00000000..ac3b8fd9
--- /dev/null
+++ b/python/acquireprogress.cc
@@ -0,0 +1,198 @@
+/* acquireprogress.cc - Base class for FetchProgress classes.
+ *
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "generic.h"
+#include <Python.h>
+#include <structmember.h>
+
+typedef struct {
+ PyObject_HEAD
+ double last_bytes;
+ double current_cps;
+ double current_bytes;
+ double total_bytes;
+ double fetched_bytes;
+ unsigned long elapsed_time;
+ unsigned long total_items;
+ unsigned long current_items;
+} PyAcquireProgressObject;
+
+
+// DUMMY IMPLEMENTATIONS.
+static char *acquireprogress_media_change_doc =
+ "media_change(media: str, drive: str) -> bool\n\n"
+ "Invoked when the user should be prompted to change the inserted\n"
+ "removable media.\n\n"
+ "This method should not return until the user has confirmed to the user\n"
+ "interface that the media change is complete.\n\n"
+ ":param:media The name of the media type that should be changed.\n"
+ ":param:drive The identifying name of the drive whose media should be\n"
+ " changed.\n\n"
+ "Return True if the user confirms the media change, False if it is\n"
+ "cancelled.";
+static PyObject *acquireprogress_media_change(PyObject *self, PyObject *args)
+{
+ Py_RETURN_FALSE;
+}
+
+static char *acquireprogress_ims_hit_doc = "ims_hit(item: AcquireItemDesc)\n\n"
+ "Invoked when an item is confirmed to be up-to-date. For instance,\n"
+ "when an HTTP download is informed that the file on the server was\n"
+ "not modified.";
+static PyObject *acquireprogress_ims_hit(PyObject *self, PyObject *arg)
+{
+ // TODO: Add type check.
+ Py_RETURN_NONE;
+}
+
+static char *acquireprogress_fetch_doc = "fetch(item: AcquireItemDesc)\n\n"
+ "Invoked when some of an item's data is fetched.";
+static PyObject *acquireprogress_fetch(PyObject *self, PyObject *args)
+{
+ // TODO: Add type check.
+ Py_RETURN_NONE;
+}
+
+static char *acquireprogress_done_doc = "done(item: AcquireItemDesc)\n\n"
+ "Invoked when an item is successfully and completely fetched.";
+static PyObject *acquireprogress_done(PyObject *self, PyObject *args)
+{
+ // TODO: Add type check.
+ Py_RETURN_NONE;
+}
+
+static char *acquireprogress_fail_doc = "fail(item: AcquireItemDesc)\n\n"
+ "Invoked when the process of fetching an item encounters a fatal error.";
+static PyObject *acquireprogress_fail(PyObject *self, PyObject *args)
+{
+ // TODO: Add type check.
+ Py_RETURN_NONE;
+}
+
+static char *acquireprogress_pulse_doc = "pulse(owner: Acquire) -> bool\n\n"
+ "Periodically invoked while the Acquire process is underway.\n\n"
+ "Return False if the user asked to cancel the whole Acquire process.";
+static PyObject *acquireprogress_pulse(PyObject *self, PyObject *args)
+{
+ // TODO: Add type check.
+ Py_RETURN_TRUE;
+}
+
+static char *acquireprogress_start_doc = "start()\n\n"
+ "Invoked when the Acquire process starts running.";
+static PyObject *acquireprogress_start(PyObject *self, PyObject *args)
+{
+ Py_RETURN_NONE;
+}
+
+static char *acquireprogress_stop_doc = "stop()\n\n"
+ "Invoked when the Acquire process stops running.";
+static PyObject *acquireprogress_stop(PyObject *self, PyObject *args)
+{
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef acquireprogress_methods[] = {
+ {"media_change", acquireprogress_media_change, METH_VARARGS,
+ acquireprogress_media_change_doc},
+ {"ims_hit",acquireprogress_ims_hit,METH_VARARGS,
+ acquireprogress_ims_hit_doc},
+ {"fetch",acquireprogress_fetch,METH_VARARGS,acquireprogress_fetch_doc},
+ {"done",acquireprogress_done,METH_VARARGS,acquireprogress_done_doc},
+ {"fail",acquireprogress_fail,METH_VARARGS,acquireprogress_fail_doc},
+ {"pulse",acquireprogress_pulse,METH_VARARGS,acquireprogress_pulse_doc},
+ {"start",acquireprogress_start,METH_NOARGS,acquireprogress_start_doc},
+ {"stop",acquireprogress_stop,METH_NOARGS,acquireprogress_stop_doc},
+ {NULL}
+};
+
+static PyMemberDef acquireprogress_members[] = {
+ {"last_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, last_bytes), 0,
+ "The number of bytes fetched as of the previous call to pulse(),\n"
+ "including local items."},
+ {"current_cps", T_DOUBLE, offsetof(PyAcquireProgressObject, current_cps), 0,
+ "The current rate of download, in bytes per second."},
+ {"current_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, current_bytes),
+ 0, "The number of bytes fetched."},
+ {"total_bytes", T_DOUBLE, offsetof(PyAcquireProgressObject, total_bytes), 0,
+ "The total number of bytes that need to be fetched. This member is\n"
+ "inaccurate, as new items might be enqueued while the download is\n"
+ "in progress!"},
+ {"fetched_bytes", T_DOUBLE,offsetof(PyAcquireProgressObject, fetched_bytes),
+ 0, "The total number of bytes accounted for by items that were\n"
+ "successfully fetched."},
+ {"elapsed_time", T_ULONG, offsetof(PyAcquireProgressObject, elapsed_time),0,
+ "The amount of time that has elapsed since the download started."},
+ {"total_items", T_ULONG, offsetof(PyAcquireProgressObject, total_items),0,
+ "The total number of items that need to be fetched. This member is\n"
+ "inaccurate, as new items might be enqueued while the download is\n"
+ "in progress!"},
+ {"current_items", T_ULONG, offsetof(PyAcquireProgressObject, current_items),
+ 0, "The number of items that have been successfully downloaded."},
+ {NULL}
+};
+
+static char *acquireprogress_doc = "AcquireProgress()\n\n"
+ "A monitor object for downloads controlled by the Acquire class. This is\n"
+ "an mostly abstract class. You should subclass it and implement the\n"
+ "methods to get something useful.";
+
+PyTypeObject PyAcquireProgress_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.AcquireProgress", // tp_name
+ sizeof(PyAcquireProgressObject), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ 0, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE,
+ acquireprogress_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ acquireprogress_methods, // tp_methods
+ acquireprogress_members, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PyType_GenericNew, // tp_new
+};
diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc
index bc2f4258..4f948847 100644
--- a/python/apt_pkgmodule.cc
+++ b/python/apt_pkgmodule.cc
@@ -621,6 +621,8 @@ extern "C" void initapt_pkg()
ADDTYPE(Module,"HashString",&PyHashString_Type);
ADDTYPE(Module,"Policy",&PyPolicy_Type);
ADDTYPE(Module,"Hashes",&PyHashes_Type);
+ ADDTYPE(Module,"OpProgress",&PyOpProgress_Type);
+ ADDTYPE(Module,"AcquireProgress",&PyAcquireProgress_Type);
// Tag file constants
PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER",
CharCharToList(TFRewritePackageOrder));
diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h
index 97be5d5c..34bc2ae5 100644
--- a/python/apt_pkgmodule.h
+++ b/python/apt_pkgmodule.h
@@ -112,6 +112,8 @@ extern PyTypeObject PyIndexRecords_Type;
// Policy
extern PyTypeObject PyPolicy_Type;
extern PyTypeObject PyHashes_Type;
+extern PyTypeObject PyOpProgress_Type;
+extern PyTypeObject PyAcquireProgress_Type;
#include "python-apt.h"
#endif
diff --git a/python/opprogress.cc b/python/opprogress.cc
new file mode 100644
index 00000000..450e290a
--- /dev/null
+++ b/python/opprogress.cc
@@ -0,0 +1,173 @@
+/* op-progress.cc - Base class for OpProgress classes.
+ *
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "generic.h"
+#include <Python.h>
+#include <structmember.h>
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *op;
+ PyObject *subop;
+ int major_change;
+ float percent;
+} PyOpProgressObject;
+
+static PyObject *opprogress_update(PyObject *Self, PyObject *args)
+{
+ Py_RETURN_NONE;
+}
+
+static PyObject *opprogress_done(PyObject *Self, PyObject *args)
+{
+ Py_RETURN_NONE;
+}
+
+static PyObject *opprogress_get_op(PyOpProgressObject *self, void *closure)
+{
+ return self->op;
+}
+
+static int opprogress_set_op(PyOpProgressObject *self, PyObject *value,
+ void *closure)
+{
+ if (value == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Cannot delete 'op'");
+ return -1;
+ }
+ if (!PyString_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,"'op' must be a string.");
+ return -1;
+ }
+ Py_DECREF(self->op);
+ Py_INCREF(value);
+
+ self->op = value;
+ return 0;
+}
+
+static PyObject *opprogress_get_subop(PyOpProgressObject *self, void *closure)
+{
+ return self->subop;
+}
+
+static int opprogress_set_subop(PyOpProgressObject *self, PyObject *value,
+ void *closure)
+{
+ if (value == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Cannot delete 'subop'.");
+ return -1;
+ }
+ if (!PyString_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,"'subop' must be a string.");
+ return -1;
+ }
+ Py_DECREF(self->subop);
+ Py_INCREF(value);
+ self->subop = value;
+ return 0;
+}
+
+static PyMethodDef opprogress_methods[] = {
+ {"update",opprogress_update,METH_NOARGS,"update()\n\nCalled periodically."},
+ {"done",opprogress_done,METH_NOARGS,"update()\n\nCalled when done."},
+ {NULL},
+};
+
+static PyMemberDef opprogress_members[] = {
+ {"major_change", T_INT, offsetof(PyOpProgressObject, major_change), 0,
+ "Boolean value indicating whether the change is a major change."},
+ {"percent", T_FLOAT, offsetof(PyOpProgressObject, percent), 0,
+ "Percentage of completion (float value)."},
+ {NULL}
+};
+
+static PyGetSetDef opprogress_getset[] = {
+ {"op", (getter)opprogress_get_op, (setter)opprogress_set_op,
+ "Description of the current operation"},
+ {"subop", (getter)opprogress_get_subop, (setter)opprogress_set_subop,
+ "Description of the current sub-operation"},
+ {NULL},
+};
+
+static void opprogress_dealloc(PyObject *self)
+{
+ Py_XDECREF(((PyOpProgressObject *)self)->op);
+ Py_XDECREF(((PyOpProgressObject *)self)->subop);
+ self->ob_type->tp_free(self);
+}
+
+static PyObject *opprogress_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyOpProgressObject *res = (PyOpProgressObject *)type->tp_alloc(type, 0);
+ res->op = PyString_FromString("");
+ res->subop = PyString_FromString("");
+ return (PyObject *)res;
+}
+
+static char *opprogress_doc = "OpProgress()\n\n"
+ "A base class for writing custom operation progress classes. Subclasses\n"
+ "should override all the methods (and call the parent ones) but shall\n"
+ "not override any of the inherited descriptors because they may be\n"
+ "ignored.";
+
+PyTypeObject PyOpProgress_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.OpProgress", // tp_name
+ sizeof(PyOpProgressObject), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ opprogress_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE,
+ opprogress_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ opprogress_methods, // tp_methods
+ opprogress_members, // tp_members
+ opprogress_getset, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ opprogress_new, // tp_new
+};
diff --git a/python/progress.cc b/python/progress.cc
index 44f27b0c..b1845f0a 100644
--- a/python/progress.cc
+++ b/python/progress.cc
@@ -15,6 +15,7 @@
#include <apt-pkg/acquire-worker.h>
#include "progress.h"
#include "generic.h"
+#include "apt_pkgmodule.h"
// generic
bool PyCallbackObj::RunSimpleCallback(const char* method_name,
@@ -75,11 +76,20 @@ void PyOpProgress::Update()
PyObject_SetAttrString(callbackInst, "majorChange", o);
Py_XDECREF(o);
+
+
// Build up the argument list...
if(CheckChange(0.05))
{
- PyObject *arglist = Py_BuildValue("(f)", Percent);
- RunSimpleCallback("update", arglist);
+ if (PyObject_TypeCheck(callbackInst, &PyOpProgress_Type)) {
+ o = Py_BuildValue("f", Percent);
+ PyObject_SetAttrString(callbackInst, "percent", o);
+ RunSimpleCallback("update");
+ Py_XDECREF(o);
+ } else {
+ PyObject *arglist = Py_BuildValue("(f)", Percent);
+ RunSimpleCallback("update", arglist);
+ }
}
};