summaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 18:07:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 18:07:41 +0000
commit76926159194e180003aa78de97e5f287bf4325a5 (patch)
tree2cea7245cdc3f66355900c820c145eba90598766 /python
parentInitial commit. (diff)
downloadpython-apt-76926159194e180003aa78de97e5f287bf4325a5.tar.xz
python-apt-76926159194e180003aa78de97e5f287bf4325a5.zip
Adding upstream version 2.7.6.upstream/2.7.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'python')
-rw-r--r--python/acquire-item.cc356
-rw-r--r--python/acquire.cc424
-rw-r--r--python/apt_instmodule.cc87
-rw-r--r--python/apt_instmodule.h29
-rw-r--r--python/apt_pkgmodule.cc1117
-rw-r--r--python/apt_pkgmodule.h214
-rw-r--r--python/arfile.cc744
-rw-r--r--python/cache.cc1600
-rw-r--r--python/cachegroup.cc188
-rw-r--r--python/cdrom.cc139
-rw-r--r--python/configuration.cc613
-rw-r--r--python/depcache.cc1169
-rw-r--r--python/generic.cc122
-rw-r--r--python/generic.h336
-rw-r--r--python/hashes.cc135
-rw-r--r--python/hashstring.cc182
-rw-r--r--python/hashstringlist.cc220
-rw-r--r--python/indexfile.cc130
-rw-r--r--python/lock.cc268
-rw-r--r--python/metaindex.cc117
-rw-r--r--python/orderlist.cc317
-rw-r--r--python/pkgmanager.cc375
-rw-r--r--python/pkgrecords.cc280
-rw-r--r--python/pkgrecords.h10
-rw-r--r--python/pkgsrcrecords.cc438
-rw-r--r--python/policy.cc243
-rw-r--r--python/progress.cc473
-rw-r--r--python/progress.h120
-rw-r--r--python/python-apt-helpers.cc69
-rw-r--r--python/python-apt.h368
-rw-r--r--python/sourcelist.cc170
-rw-r--r--python/string.cc142
-rw-r--r--python/tag.cc1063
-rw-r--r--python/tarfile.cc521
34 files changed, 12779 insertions, 0 deletions
diff --git a/python/acquire-item.cc b/python/acquire-item.cc
new file mode 100644
index 0000000..af79fd9
--- /dev/null
+++ b/python/acquire-item.cc
@@ -0,0 +1,356 @@
+/*
+ * acquire-item.cc - Wrapper around pkgAcquire::Item and pkgAcqFile.
+ *
+ * Copyright 2004-2009 Canonical Ltd.
+ * 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 "apt_pkgmodule.h"
+
+#include <apt-pkg/acquire-item.h>
+#include <map>
+
+using namespace std;
+
+inline pkgAcquire::Item *acquireitem_tocpp(PyObject *self)
+{
+ pkgAcquire::Item *itm = GetCpp<pkgAcquire::Item*>(self);
+ if (itm == 0)
+ PyErr_SetString(PyExc_ValueError, "Acquire() has been shut down or "
+ "the AcquireFile() object has been deallocated.");
+ return itm;
+}
+
+static PyObject *acquireitem_get_complete(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? PyBool_FromLong(item->Complete) : 0;
+}
+
+static PyObject *acquireitem_get_desc_uri(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? CppPyString(item->DescURI()) : 0;
+}
+
+static PyObject *acquireitem_get_destfile(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? CppPyPath(item->DestFile) : 0;
+}
+
+
+static PyObject *acquireitem_get_error_text(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? CppPyString(item->ErrorText) : 0;
+}
+
+static PyObject *acquireitem_get_filesize(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? MkPyNumber(item->FileSize) : 0;
+}
+
+static PyObject *acquireitem_get_id(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? MkPyNumber(item->ID) : 0;
+}
+
+static PyObject *acquireitem_get_active_subprocess(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+#if APT_PKG_MAJOR >= 5
+ return item ? Py_BuildValue("s", item->ActiveSubprocess.c_str()) : 0;
+#else
+ return item ? Py_BuildValue("s", item->Mode) : 0;
+#endif
+}
+
+static PyObject *acquireitem_get_mode(PyObject *self, void *closure)
+{
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "AcquireItem.mode is deprecated, use AcquireItem.active_subprocess instead.", 1) == -1)
+ return NULL;
+ return acquireitem_get_active_subprocess(self, closure);
+}
+
+static PyObject *acquireitem_get_is_trusted(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? PyBool_FromLong(item->IsTrusted()) : 0;
+}
+
+static PyObject *acquireitem_get_local(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? PyBool_FromLong(item->Local) : 0;
+}
+
+static PyObject *acquireitem_get_partialsize(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? MkPyNumber(item->PartialSize) : 0;
+}
+
+static PyObject *acquireitem_get_status(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? MkPyNumber(item->Status) : 0;
+}
+
+static int acquireitem_set_id(PyObject *self, PyObject *value, void *closure)
+{
+ pkgAcquire::Item *Itm = acquireitem_tocpp(self);
+ if (Itm == 0)
+ return -1;
+ if (PyLong_Check(value)) {
+ Itm->ID = PyLong_AsUnsignedLong(value);
+ }
+ else if (PyInt_Check(value)) {
+ Itm->ID = PyInt_AsLong(value);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "value must be integer.");
+ return -1;
+ }
+ return 0;
+}
+
+
+static PyGetSetDef acquireitem_getset[] = {
+ {"complete",acquireitem_get_complete,0,
+ "A boolean value determining whether the item has been fetched\n"
+ "completely"},
+ {"desc_uri",acquireitem_get_desc_uri,NULL,
+ "A string describing the URI from which the item is acquired."},
+ {"destfile",acquireitem_get_destfile,NULL,
+ "The path to the file where the item will be stored."},
+ {"error_text",acquireitem_get_error_text,NULL,
+ "If an error occurred, a string describing the error; empty string\n"
+ "otherwise."},
+ {"filesize",acquireitem_get_filesize,NULL,
+ "The size of the file (number of bytes). If unknown, it is set to 0."},
+ {"id",acquireitem_get_id,acquireitem_set_id,
+ "The ID of the item. An integer which can be set by progress classes."},
+ {"mode",acquireitem_get_mode,NULL,
+ "Old name for active_subprocess"},
+ {"active_subprocess",acquireitem_get_active_subprocess,NULL,
+ "The name of the active subprocess (for instance, 'gzip', 'rred' or 'gpgv')."},
+ {"is_trusted",acquireitem_get_is_trusted,NULL,
+ "Whether the item is trusted or not. Only True for packages\n"
+ "which come from a repository signed with one of the keys in\n"
+ "APT's keyring."},
+ {"local",acquireitem_get_local,NULL,
+ "Whether we are fetching a local item (copy:/) or not."},
+ {"partialsize",acquireitem_get_partialsize,NULL,
+ "The amount of data which has already been fetched (number of bytes)."},
+ {"status",acquireitem_get_status,NULL,
+ "An integer representing the item's status which can be compared\n"
+ "against one of the STAT_* constants defined in this class."},
+ {}
+};
+
+static PyObject *acquireitem_repr(PyObject *Self)
+{
+ pkgAcquire::Item *Itm = acquireitem_tocpp(Self);
+ if (Itm == 0)
+ return 0;
+
+ string repr;
+ strprintf(repr, "<%s object:"
+ "Status: %i Complete: %i Local: %i IsTrusted: %i "
+ "FileSize: %llu DestFile:'%s' "
+ "DescURI: '%s' ID:%lu ErrorText: '%s'>",
+ Self->ob_type->tp_name,
+ Itm->Status, Itm->Complete, Itm->Local, Itm->IsTrusted(),
+ Itm->FileSize, Itm->DestFile.c_str(), Itm->DescURI().c_str(),
+ Itm->ID,Itm->ErrorText.c_str());
+ // Use CppPyPath here, the string may contain a path, so we should
+ // decode it like one.
+ return CppPyPath(repr);
+}
+
+static void acquireitem_dealloc(PyObject *self)
+{
+ CppDeallocPtr<pkgAcquire::Item*>(self);
+}
+
+static const char *acquireitem_doc =
+ "Represent a single item to be fetched by an Acquire object.\n\n"
+ "It is not possible to construct instances of this class directly.\n"
+ "Prospective users should construct instances of a subclass such as\n"
+ "AcquireFile instead. It is not possible to create subclasses on the\n"
+ "Python level, only on the C++ level.";
+PyTypeObject PyAcquireItem_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.AcquireItem", // tp_name
+ sizeof(CppPyObject<pkgAcquire::Item*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ acquireitem_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ acquireitem_repr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT |
+ Py_TPFLAGS_HAVE_GC, // tp_flags
+ acquireitem_doc, // tp_doc
+ CppTraverse<pkgAcquire::Item*>, // tp_traverse
+ CppClear<pkgAcquire::Item*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ acquireitem_getset, // tp_getset
+};
+
+static PyObject *acquirefile_new(PyTypeObject *type, PyObject *Args, PyObject * kwds)
+{
+ PyObject *pyfetcher;
+ PyObject *pyhashes = nullptr;
+ HashStringList hashes;
+ const char *uri, *descr, *shortDescr;
+ PyApt_Filename destDir, destFile;
+ unsigned long long size = 0;
+ uri = descr = shortDescr = destDir = destFile = "";
+
+ char *kwlist[] = {"owner", "uri", "hash", "size", "descr", "short_descr",
+ "destdir", "destfile", NULL
+ };
+#if PY_MAJOR_VERSION >= 3
+ const char *fmt = "O!s|OKssO&O&";
+#else
+ // no "$" support to indicate that the remaining args are keyword only
+ // in py2.x :/
+ const char *fmt = "O!s|OKssO&O&";
+#endif
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, fmt, kwlist,
+ &PyAcquire_Type, &pyfetcher, &uri,
+ &pyhashes,
+ &size, &descr, &shortDescr,
+ PyApt_Filename::Converter, &destDir,
+ PyApt_Filename::Converter, &destFile) == 0)
+ return 0;
+
+ if (pyhashes == nullptr)
+ ;
+ else if (PyString_Check(pyhashes))
+ hashes = HashStringList(PyString_AsString(pyhashes));
+ else if (PyObject_TypeCheck(pyhashes, &PyHashStringList_Type))
+ hashes = GetCpp <HashStringList>(pyhashes);
+ else
+ return PyErr_SetString(PyExc_TypeError, "'hash' value must be an apt_pkg.HashStringList or a string"), nullptr;
+
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyfetcher);
+ pkgAcqFile *af = new pkgAcqFile(fetcher, // owner
+ uri, // uri
+ hashes, // hash
+ size, // size
+ descr, // descr
+ shortDescr,
+ destDir,
+ destFile); // short-desc
+ CppPyObject<pkgAcqFile*> *AcqFileObj = CppPyObject_NEW<pkgAcqFile*>(pyfetcher, type);
+ AcqFileObj->Object = af;
+ return AcqFileObj;
+}
+
+
+static char *acquirefile_doc =
+ "AcquireFile(owner, uri[, hash: Union[apt_pkg.HashStringList, str], size, descr, short_descr, destdir,"
+ "destfile])\n\n"
+ "Represent a file to be fetched. The parameter 'owner' points to\n"
+ "an apt_pkg.Acquire object and the parameter 'uri' to the source\n"
+ "location. Normally, the file will be stored in the current directory\n"
+ "using the file name given in the URI. This directory can be changed\n"
+ "by passing the name of a directory to the 'destdir' parameter. It is\n"
+ "also possible to set a path to a file using the 'destfile' parameter,\n"
+ "but both cannot be specified together.\n"
+ "\n"
+ "The parameters 'short_descr' and 'descr' can be used to specify\n"
+ "a short description and a longer description for the item. This\n"
+ "information is used by progress classes to refer to the item and\n"
+ "should be short, for example, package name as 'short_descr' and\n"
+ "and something like 'http://localhost sid/main python-apt 0.7.94.2'\n"
+ "as 'descr'."
+ "\n"
+ "The parameters 'hash' and 'size' are used to verify the resulting\n"
+ "file. The parameter 'size' is also to calculate the total amount\n"
+ "of data to be fetched and is useful for resuming a interrupted\n"
+ "download.\n\n"
+ "All parameters can be given by name (i.e. as keyword arguments).";
+
+PyTypeObject PyAcquireFile_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.AcquireFile", // tp_name
+ sizeof(CppPyObject<pkgAcqFile*>),// tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ acquireitem_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 |
+ Py_TPFLAGS_HAVE_GC,
+ acquirefile_doc, // tp_doc
+ CppTraverse<pkgAcqFile*>, // tp_traverse
+ CppClear<pkgAcqFile*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyAcquireItem_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ acquirefile_new, // tp_new
+};
+
diff --git a/python/acquire.cc b/python/acquire.cc
new file mode 100644
index 0000000..aab899f
--- /dev/null
+++ b/python/acquire.cc
@@ -0,0 +1,424 @@
+/* acquire.cc - Wrapper for pkgAcquire.
+ *
+ * Copyright 2004-2009 Canonical Ltd
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * Authors: Michael Vogt
+ * Julian Andres Klode
+ *
+ * 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 "apt_pkgmodule.h"
+#include "progress.h"
+
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/acquire-worker.h>
+
+
+static PyObject *acquireworker_get_current_item(PyObject *self, void *closure)
+{
+ pkgAcquire::Worker *worker = GetCpp<pkgAcquire::Worker*>(self);
+ pkgAcquire::ItemDesc *desc = worker->CurrentItem;
+ if (desc == NULL) {
+ Py_RETURN_NONE;
+ }
+ PyObject *PyAcq = GetOwner<pkgAcquire::Worker*>(self);
+ PyObject *PyItem = PyAcquireItem_FromCpp(desc->Owner, false, PyAcq);
+ PyObject *PyDesc = PyAcquireItemDesc_FromCpp(desc, false, PyItem);
+ Py_XDECREF(PyItem);
+ return PyDesc;
+}
+
+static PyObject *acquireworker_get_status(PyObject *self, void *closure)
+{
+ return CppPyString(GetCpp<pkgAcquire::Worker*>(self)->Status);
+}
+
+static PyObject *acquireworker_get_current_size(PyObject *self, void *closure)
+{
+ if (GetCpp<pkgAcquire::Worker*>(self)->CurrentItem == nullptr)
+ return 0;
+ return MkPyNumber(GetCpp<pkgAcquire::Worker*>(self)->CurrentItem->CurrentSize);
+}
+
+static PyObject *acquireworker_get_total_size(PyObject *self, void *closure)
+{
+ if (GetCpp<pkgAcquire::Worker*>(self)->CurrentItem == nullptr)
+ return 0;
+ return MkPyNumber(GetCpp<pkgAcquire::Worker*>(self)->CurrentItem->TotalSize);
+}
+
+static PyObject *acquireworker_get_resumepoint(PyObject *self, void *closure)
+{
+ if (GetCpp<pkgAcquire::Worker*>(self)->CurrentItem == nullptr)
+ return 0;
+ return MkPyNumber(GetCpp<pkgAcquire::Worker*>(self)->CurrentItem->ResumePoint);
+}
+
+static PyGetSetDef acquireworker_getset[] = {
+ {"current_item",acquireworker_get_current_item,0,
+ "The item currently being fetched, as an apt_pkg.AcquireItemDesc object."},
+ {"status",acquireworker_get_status,0,
+ "The status of the worker, as a string."},
+ {"current_size",acquireworker_get_current_size,0,
+ "The amount of data fetched so far for the current item."},
+ {"total_size",acquireworker_get_total_size,0,
+ "The total size of the item."},
+ {"resumepoint",acquireworker_get_resumepoint,0,
+ "The amount of data which was already available when the download was\n"
+ "started."},
+ {NULL}
+};
+
+static const char *acquireworker_doc =
+ "Represent a sub-process responsible for fetching files from\n"
+ "remote locations. This sub-process uses 'methods' located in\n"
+ "the directory specified by the configuration option\n"
+ "Dir::Bin::Methods.";
+PyTypeObject PyAcquireWorker_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.AcquireWorker", // tp_name
+ sizeof(CppPyObject<pkgAcquire::Worker*>),// tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgAcquire::Worker*>, // 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_HAVE_GC,
+ acquireworker_doc, // tp_doc
+ CppTraverse<pkgAcquire::Worker*>, // tp_traverse
+ CppClear<pkgAcquire::Worker*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ acquireworker_getset, // tp_getset
+};
+
+
+static pkgAcquire::ItemDesc* acquireitemdesc_tocpp(PyObject *self) {
+ pkgAcquire::ItemDesc *item = GetCpp<pkgAcquire::ItemDesc*>(self);
+ if (item == NULL)
+ PyErr_SetString(PyExc_ValueError, "Acquire has been shutdown");
+ return item;
+}
+
+static PyObject *acquireitemdesc_get_uri(PyObject *self, void *closure)
+{
+ pkgAcquire::ItemDesc *item = acquireitemdesc_tocpp(self);
+ return item ? CppPyString(item->URI) : NULL;
+}
+static PyObject *acquireitemdesc_get_description(PyObject *self, void *closure)
+{
+ pkgAcquire::ItemDesc *item = acquireitemdesc_tocpp(self);
+ return item ? CppPyString(item->Description) : NULL;
+}
+static PyObject *acquireitemdesc_get_shortdesc(PyObject *self, void *closure)
+{
+ pkgAcquire::ItemDesc *item = acquireitemdesc_tocpp(self);
+ return item ? CppPyString(item->ShortDesc) : NULL;
+}
+static PyObject *acquireitemdesc_get_owner(CppPyObject<pkgAcquire::ItemDesc*> *self, void *closure)
+{
+ if (self->Owner != NULL) {
+ Py_INCREF(self->Owner);
+ return self->Owner;
+ }
+ else if (self->Object) {
+ self->Owner = PyAcquireItem_FromCpp(self->Object->Owner, false, NULL);
+ Py_INCREF(self->Owner);
+ return self->Owner;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyGetSetDef acquireitemdesc_getset[] = {
+ {"uri",acquireitemdesc_get_uri,0,
+ "The URI from which this item would be downloaded."},
+ {"description",acquireitemdesc_get_description,0,
+ "A string describing the item."},
+ {"shortdesc",acquireitemdesc_get_shortdesc,0,
+ "A short string describing the item (e.g. package name)."},
+ {"owner",(getter)acquireitemdesc_get_owner,0,
+ "The owner of the item, an apt_pkg.AcquireItem object."},
+ {NULL}
+};
+
+static char *acquireitemdesc_doc =
+ "Provide the description of an item and the URI the item is\n"
+ "fetched from. Progress classes make use of such objects to\n"
+ "retrieve description and other information about an item.";
+PyTypeObject PyAcquireItemDesc_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.AcquireItemDesc", // tp_name
+ sizeof(CppPyObject<pkgAcquire::ItemDesc*>),// tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgAcquire::ItemDesc*>, // 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_HAVE_GC),
+ acquireitemdesc_doc, // tp_doc
+ CppTraverse<pkgAcquire::ItemDesc*>,// tp_traverse
+ CppClear<pkgAcquire::ItemDesc*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ acquireitemdesc_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
+ 0, // tp_new
+};
+
+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(MkPyNumber(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 PyObject *PkgAcquireGetLock(PyObject *Self,PyObject *Args)
+{
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self);
+ PyApt_Filename path;
+ if (PyArg_ParseTuple(Args, "O&", PyApt_Filename::Converter, &path) == 0)
+ return 0;
+ fetcher->GetLock(path);
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+
+
+static PyMethodDef PkgAcquireMethods[] = {
+ {"run",PkgAcquireRun,METH_VARARGS,
+ "run() -> int\n\nRun the fetcher and return one of RESULT_CANCELLED,\n"
+ "RESULT_CONTINUE, RESULT_FAILED.\n\n"
+ "RESULT_CONTINUE means that all items which where queued prior to\n"
+ "calling run() have been fetched successfully or failed transiently.\n\n"
+ "RESULT_CANCELLED means canceled by the progress class.\n\n"
+ "RESULT_FAILED means a generic failure."},
+ {"shutdown",PkgAcquireShutdown, METH_VARARGS,
+ "shutdown()\n\n"
+ "Shut the fetcher down, removing all items from it. Future access to\n"
+ "queued AcquireItem objects will cause a segfault. The partial result\n"
+ "is kept on the disk and not removed and APT might reuse it."},
+ {"get_lock",PkgAcquireGetLock, METH_VARARGS,
+ "get_lock(log: str)\n\n"
+ "Acquires a log for the given directory, using a file 'lock' in it."},
+ {}
+};
+
+#define fetcher (GetCpp<pkgAcquire*>(Self))
+static PyObject *PkgAcquireGetTotalNeeded(PyObject *Self,void*)
+{
+ return MkPyNumber(fetcher->TotalNeeded());
+}
+static PyObject *PkgAcquireGetFetchNeeded(PyObject *Self,void*)
+{
+ return MkPyNumber(fetcher->FetchNeeded());
+}
+static PyObject *PkgAcquireGetPartialPresent(PyObject *Self,void*)
+{
+ return MkPyNumber(fetcher->PartialPresent());
+}
+#undef fetcher
+
+static PyObject *PkgAcquireGetWorkers(PyObject *self, void *closure)
+{
+ PyObject *List = PyList_New(0);
+ pkgAcquire *Owner = GetCpp<pkgAcquire*>(self);
+ PyObject *PyWorker = NULL;
+ for (pkgAcquire::Worker *Worker = Owner->WorkersBegin();
+ Worker != 0; Worker = Owner->WorkerStep(Worker)) {
+ PyWorker = PyAcquireWorker_FromCpp(Worker, false, self);
+ PyList_Append(List, PyWorker);
+ Py_DECREF(PyWorker);
+ }
+ return List;
+}
+static PyObject *PkgAcquireGetItems(PyObject *Self,void*)
+{
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self);
+ PyObject *List = PyList_New(0);
+ PyObject *Obj;
+ for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin();
+ I != fetcher->ItemsEnd(); I++) {
+ Obj = PyAcquireItem_FromCpp(*I, false, Self);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyGetSetDef PkgAcquireGetSet[] = {
+ {"fetch_needed",PkgAcquireGetFetchNeeded,0,
+ "The total amount of data to be fetched (number of bytes)."},
+ {"items",PkgAcquireGetItems,0,
+ "A list of all items as apt_pkg.AcquireItem objects, including already\n"
+ "fetched ones and to be fetched ones."},
+ {"workers",PkgAcquireGetWorkers,0,
+ "A list of all active workers as apt_pkg.AcquireWorker objects."},
+ {"partial_present",PkgAcquireGetPartialPresent,0,
+ "The amount of data which is already available (number of bytes)."},
+ {"total_needed",PkgAcquireGetTotalNeeded,0,
+ "The amount of data that needs to fetched plus the amount of data\n"
+ "which has already been fetched (number of bytes)."},
+ {}
+};
+
+static PyObject *PkgAcquireNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ pkgAcquire *fetcher;
+
+ PyObject *pyFetchProgressInst = NULL;
+ char *kwlist[] = {"progress", 0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"|O",kwlist,&pyFetchProgressInst) == 0)
+ return 0;
+
+ PyFetchProgress *progress = 0;
+ if (pyFetchProgressInst != NULL) {
+ // FIXME: memleak?
+ progress = new PyFetchProgress();
+ progress->setCallbackInst(pyFetchProgressInst);
+ }
+
+ fetcher = new pkgAcquire();
+ fetcher->SetLog(progress);
+
+ PyObject *FetcherObj = CppPyObject_NEW<pkgAcquire*>(NULL, type, fetcher);
+
+ if (progress != 0)
+ progress->setPyAcquire(FetcherObj);
+ // prepare our map of items.
+ return HandleErrors(FetcherObj);
+}
+
+/**
+ * Create a new apt_pkg.Acquire Python object from the pkgAcquire object.
+ */
+PyObject *PyAcquire_FromCpp(pkgAcquire *fetcher, bool Delete, PyObject *owner) {
+ CppPyObject<pkgAcquire*> *obj = CppPyObject_NEW<pkgAcquire*>(owner, &PyAcquire_Type, fetcher);
+ obj->NoDelete = (!Delete);
+ return obj;
+}
+
+static char *doc_PkgAcquire =
+ "Acquire([progress: apt.progress.base.AcquireProgress])\n\n"
+ "Coordinate the retrieval of files via network or local file system\n"
+ "(using 'copy:/path/to/file' style URIs). The optional argument\n"
+ "'progress' takes an apt.progress.base.AcquireProgress object\n"
+ "which may report progress information.";
+
+PyTypeObject PyAcquire_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Acquire", // tp_name
+ sizeof(CppPyObject<pkgAcquire*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgAcquire*>, // 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
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ doc_PkgAcquire, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgAcquireMethods, // tp_methods
+ 0, // tp_members
+ PkgAcquireGetSet, // 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
+ PkgAcquireNew, // tp_new
+};
+
+
diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc
new file mode 100644
index 0000000..eb01074
--- /dev/null
+++ b/python/apt_instmodule.cc
@@ -0,0 +1,87 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_instmodule.cc,v 1.3 2002/01/08 06:53:04 jgg Exp $
+/* ######################################################################
+
+ apt_intmodule - Top level for the python module. Create the internal
+ structures for the module in the interpriter.
+
+ Note, this module shares state (particularly global config) with the
+ apt_pkg module.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "apt_instmodule.h"
+#include "generic.h"
+
+#include <apt-pkg/debfile.h>
+#include <apt-pkg/error.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <Python.h>
+ /*}}}*/
+
+PyObject *PyAptError;
+PyObject *PyAptWarning;
+static PyMethodDef *methods = 0;
+
+
+static const char *apt_inst_doc =
+ "Functions for working with ar/tar archives and .deb packages.\n\n"
+ "This module provides useful classes and functions to work with\n"
+ "archives, modelled after the 'TarFile' class in the 'tarfile' module.";
+#define ADDTYPE(mod,name,type) { \
+ if (PyType_Ready(type) == -1) RETURN(0); \
+ Py_INCREF(type); \
+ PyModule_AddObject(mod,name,(PyObject *)type); }
+
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "apt_inst",
+ apt_inst_doc,
+ -1,
+ methods,
+ 0,
+ 0,
+ 0,
+ 0
+};
+#define RETURN(x) return x
+#define INIT_ERROR return 0
+extern "C" PyObject * PyInit_apt_inst()
+#else
+#define INIT_ERROR return
+extern "C" void initapt_inst()
+#define RETURN(x) return
+#endif
+{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *module = PyModule_Create(&moduledef);
+#else
+ PyObject *module = Py_InitModule3("apt_inst",methods, apt_inst_doc);
+#endif
+
+ PyObject *apt_pkg = PyImport_ImportModule("apt_pkg");
+ if (apt_pkg == NULL)
+ INIT_ERROR;
+ PyAptError = PyObject_GetAttrString(apt_pkg, "Error");
+ if (PyAptError == NULL)
+ INIT_ERROR;
+ PyAptWarning = PyObject_GetAttrString(apt_pkg, "Warning");
+ if (PyAptWarning == NULL)
+ INIT_ERROR;
+
+ PyModule_AddObject(module,"Error",PyAptError);
+ PyModule_AddObject(module,"Warning",PyAptWarning);
+ ADDTYPE(module,"ArMember",&PyArMember_Type);
+ ADDTYPE(module,"ArArchive",&PyArArchive_Type);
+ ADDTYPE(module,"DebFile",&PyDebFile_Type);
+ ADDTYPE(module,"TarFile",&PyTarFile_Type);
+ ADDTYPE(module,"TarMember",&PyTarMember_Type);
+ ADDTYPE(module,"__FileFd",&PyFileFd_Type);
+ RETURN(module);
+}
diff --git a/python/apt_instmodule.h b/python/apt_instmodule.h
new file mode 100644
index 0000000..92c9800
--- /dev/null
+++ b/python/apt_instmodule.h
@@ -0,0 +1,29 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_instmodule.h,v 1.2 2002/01/08 06:53:04 jgg Exp $
+/* ######################################################################
+
+ Prototypes for the module
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef APT_INSTMODULE_H
+#define APT_INSTMODULE_H
+
+#include <Python.h>
+#include "generic.h"
+#include <apt-pkg/extracttar.h>
+
+
+extern PyTypeObject PyArMember_Type;
+extern PyTypeObject PyArArchive_Type;
+extern PyTypeObject PyDebFile_Type;
+extern PyTypeObject PyTarFile_Type;
+extern PyTypeObject PyTarMember_Type;
+extern PyTypeObject PyFileFd_Type;
+struct PyTarFileObject : public CppPyObject<ExtractTar*> {
+ int min;
+ FileFd Fd;
+};
+
+#endif
diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc
new file mode 100644
index 0000000..84b1e92
--- /dev/null
+++ b/python/apt_pkgmodule.cc
@@ -0,0 +1,1117 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_pkgmodule.cc,v 1.5 2003/07/23 02:20:24 mdz Exp $
+/* ######################################################################
+
+ apt_pkgmodule - Top level for the python module. Create the internal
+ structures for the module in the interpriter.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "apt_pkgmodule.h"
+#include "generic.h"
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/deblistparser.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/hashes.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/orderlist.h>
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/gpgv.h>
+
+#include <sys/stat.h>
+#include <libintl.h>
+#include <unistd.h>
+#include <Python.h>
+ /*}}}*/
+
+static char PyAptError_Doc[] =
+ "Exception class for most python-apt exceptions.\n"
+ "\n"
+ "This class replaces the use of :class:`SystemError` in previous versions\n"
+ "of python-apt. It inherits from :class:`SystemError`, so make sure to\n"
+ "catch this class first.\n\n"
+ ".. versionadded:: 1.1";
+
+PyObject *PyAptError;
+
+static char PyAptWarning_Doc[] =
+ "Exception class for most python-apt warnings.\n"
+ "\n"
+ ".. versionadded:: 2.7";
+
+PyObject *PyAptWarning;
+
+static char PyAptCacheMismatchError_Doc[] =
+ "Raised when passing an object from a different cache to\n"
+ ":class:`apt_pkg.DepCache` methods\n\n"
+ ".. versionadded:: 1.6.1";
+
+PyObject *PyAptCacheMismatchError;
+
+/**
+ * A Python->C->Python gettext() function.
+ *
+ * Python's gettext() ignores setlocale() which causes a strange behavior
+ * because the values received from apt-pkg respect setlocale(). We circumvent
+ * this problem by calling the C version of gettext(). This is also much
+ * faster.
+ */
+static PyObject *py_gettext(PyObject *self, PyObject *Args) {
+ const char *msg;
+ char *domain = "python-apt";
+ if (PyArg_ParseTuple(Args,"s|s:gettext",&msg, &domain) == 0)
+ return 0;
+
+ return CppPyString(dgettext(domain, msg));
+}
+
+// newConfiguration - Build a new configuration class /*{{{*/
+// ---------------------------------------------------------------------
+ /*}}}*/
+
+// Version Wrappers /*{{{*/
+// These are kind of legacy..
+static char *doc_VersionCompare =
+ "version_compare(a: str, b: str) -> int\n\n"
+ "Compare the given versions; return a strictly negative value if 'a' is \n"
+ "smaller than 'b', 0 if they are equal, and a strictly positive value if\n"
+ "'a' is larger than 'b'.";
+static PyObject *VersionCompare(PyObject *Self,PyObject *Args)
+{
+ char *A;
+ char *B;
+ Py_ssize_t LenA;
+ Py_ssize_t LenB;
+
+ if (PyArg_ParseTuple(Args,"s#s#",&A,&LenA,&B,&LenB) == 0)
+ return 0;
+
+ if (_system == 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+
+ return MkPyNumber(_system->VS->DoCmpVersion(A,A+LenA,B,B+LenB));
+}
+
+static char *doc_CheckDep =
+ "check_dep(pkg_ver: str, dep_op: str, dep_ver: str) -> bool\n\n"
+ "Check that the given requirement is fulfilled; i.e. that the version\n"
+ "string given by 'pkg_ver' matches the version string 'dep_ver' under\n"
+ "the condition specified by the operator 'dep_op' (<,<=,=,>=,>).\n\n"
+ "Return True if 'pkg_ver' matches 'dep_ver' under the\n"
+ "condition 'dep_op'; for example, this returns True:\n\n"
+ " apt_pkg.check_dep('1', '<=', '2')";
+static PyObject *CheckDep(PyObject *Self,PyObject *Args)
+{
+ char *A;
+ char *B;
+ char *OpStr;
+ unsigned int Op = 0;
+
+ if (PyArg_ParseTuple(Args,"sss",&A,&OpStr,&B) == 0)
+ return 0;
+
+ if (strcmp(OpStr, ">") == 0) OpStr = ">>";
+ if (strcmp(OpStr, "<") == 0) OpStr = "<<";
+ if (*debListParser::ConvertRelation(OpStr,Op) != 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"Bad comparison operation");
+ return 0;
+ }
+
+ if (_system == 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+
+ return PyBool_FromLong(_system->VS->CheckDep(A,Op,B));
+}
+
+
+static char *doc_UpstreamVersion =
+ "upstream_version(ver: str) -> str\n\n"
+ "Return the upstream version for the package version given by 'ver'.";
+static PyObject *UpstreamVersion(PyObject *Self,PyObject *Args)
+{
+ char *Ver;
+ if (PyArg_ParseTuple(Args,"s",&Ver) == 0)
+ return 0;
+ return CppPyString(_system->VS->UpstreamVersion(Ver));
+}
+
+static const char *doc_ParseDepends =
+"parse_depends(s: str[, strip_multi_arch : bool = True[, architecture : string]]) -> list\n"
+"\n"
+"Parse the dependencies given by 's' and return a list of lists. Each of\n"
+"these lists represents one or more options for an 'or' dependency in\n"
+"the form of '(pkg, ver, comptype)' tuples. The tuple element 'pkg'\n"
+"is the name of the package; the element 'ver' is the version, or ''\n"
+"if no version was requested. The element 'ver' is a comparison\n"
+"operator ('<', '<=', '=', '>=', or '>').\n\n"
+"If 'strip_multi_arch' is True, :any (and potentially other special values)\n"
+"will be stripped from the full package name"
+"The 'architecture' parameter may be used to specify a non-native architecture\n"
+"for the dependency parsing.";
+
+static const char *parse_src_depends_doc =
+"parse_src_depends(s: str[, strip_multi_arch : bool = True[, architecture : string]]) -> list\n"
+"\n"
+"Parse the dependencies given by 's' and return a list of lists. Each of\n"
+"these lists represents one or more options for an 'or' dependency in\n"
+"the form of '(pkg, ver, comptype)' tuples. The tuple element 'pkg'\n"
+"is the name of the package; the element 'ver' is the version, or ''\n"
+"if no version was requested. The element 'ver' is a comparison\n"
+"operator ('<', '<=', '=', '>=', or '>')."
+"\n\n"
+"Dependencies may be restricted to certain architectures and the result\n"
+"only contains those dependencies for the architecture set in the\n"
+"configuration variable APT::Architecture\n\n"
+"If 'strip_multi_arch' is True, :any (and potentially other special values)\n"
+"will be stripped from the full package name"
+"The 'architecture' parameter may be used to specify a non-native architecture\n"
+"for the dependency parsing.";
+static PyObject *RealParseDepends(PyObject *Self,PyObject *Args,PyObject *Kwds,
+ bool ParseArchFlags, bool ParseRestrictionsList,
+ std::string name, bool debStyle=false)
+{
+ std::string Package;
+ std::string Version;
+ unsigned int Op;
+ bool StripMultiArch=true;
+
+ const char *Start;
+ const char *Stop;
+ Py_ssize_t Len;
+ const char *Arch = NULL;
+ char *kwlist[] = {"s", "strip_multi_arch", "architecture", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args,Kwds,(char *)("s#|bs:" + name).c_str(), kwlist,
+ &Start, &Len, &StripMultiArch, &Arch) == 0)
+ return 0;
+ Stop = Start + Len;
+ PyObject *List = PyList_New(0);
+ PyObject *LastRow = 0;
+ while (1)
+ {
+ if (Start == Stop)
+ break;
+ if (Arch == NULL)
+ Start = debListParser::ParseDepends(Start,Stop,Package,Version,Op,
+ ParseArchFlags, StripMultiArch,
+ ParseRestrictionsList);
+ else
+ Start = debListParser::ParseDepends(Start,Stop,Package,Version,Op,
+ ParseArchFlags, StripMultiArch,
+ ParseRestrictionsList, Arch);
+
+ if (Start == 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"Problem Parsing Dependency");
+ Py_DECREF(List);
+ return 0;
+ }
+
+ if (LastRow == 0)
+ LastRow = PyList_New(0);
+
+ if (Package.empty() == false)
+ {
+ PyObject *Obj;
+ PyList_Append(LastRow,Obj = Py_BuildValue("sss",Package.c_str(),
+ Version.c_str(),
+ debStyle ? pkgCache::CompTypeDeb(Op) : pkgCache::CompType(Op)));
+ Py_DECREF(Obj);
+ }
+
+ // Group ORd deps into a single row..
+ if ((Op & pkgCache::Dep::Or) != pkgCache::Dep::Or)
+ {
+ if (PyList_Size(LastRow) != 0)
+ PyList_Append(List,LastRow);
+ Py_DECREF(LastRow);
+ LastRow = 0;
+ }
+ }
+ return List;
+}
+static PyObject *ParseDepends(PyObject *Self,PyObject *Args, PyObject *Kwds)
+{
+ return RealParseDepends(Self, Args, Kwds, false, false, "parse_depends");
+}
+static PyObject *ParseSrcDepends(PyObject *Self,PyObject *Args, PyObject *Kwds)
+{
+ return RealParseDepends(Self, Args, Kwds, true, true, "parse_src_depends");
+}
+ /*}}}*/
+// md5sum - Compute the md5sum of a file or string /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_md5sum =
+ "md5sum(object) -> str\n\n"
+ "Return the md5sum of the object. 'object' may either be a string, in\n"
+ "which case the md5sum of the string is returned, or a file() object\n"
+ "(or file descriptor), in which case the md5sum of its contents is\n"
+ "returned.";
+static PyObject *md5sum(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "apt_pkg.md5sum is deprecated, use apt_pkg.Hashes", 1) == -1)
+ return NULL;
+
+ // Digest of a string.
+ if (PyBytes_Check(Obj) != 0)
+ {
+ char *s;
+ Py_ssize_t len;
+ Hashes Sum(Hashes::MD5SUM);
+ PyBytes_AsStringAndSize(Obj, &s, &len);
+ Sum.Add((const unsigned char*)s, len);
+ return CppPyString(Sum.GetHashString(Hashes::MD5SUM).HashValue());
+ }
+
+ // Digest of a file
+ int Fd = PyObject_AsFileDescriptor(Obj);
+ if (Fd != -1)
+ {
+ Hashes Sum(Hashes::MD5SUM);
+ struct stat St;
+ if (fstat(Fd,&St) != 0 ||
+ Sum.AddFD(Fd,St.st_size) == false)
+ {
+ PyErr_SetFromErrno(PyAptError);
+ return 0;
+ }
+
+ return CppPyString(Sum.GetHashString(Hashes::MD5SUM).HashValue());
+ }
+
+ PyErr_SetString(PyExc_TypeError,"Only understand strings and files");
+ return 0;
+}
+ /*}}}*/
+// sha1sum - Compute the sha1sum of a file or string /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_sha1sum =
+ "sha1sum(object) -> str\n\n"
+ "Return the sha1sum of the object. 'object' may either be a string, in\n"
+ "which case the sha1sum of the string is returned, or a file() object\n"
+ "(or file descriptor), in which case the sha1sum of its contents is\n"
+ "returned.";
+static PyObject *sha1sum(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "apt_pkg.sha1sum is deprecated, use apt_pkg.Hashes", 1) == -1)
+ return NULL;
+
+ // Digest of a string.
+ if (PyBytes_Check(Obj) != 0)
+ {
+ char *s;
+ Py_ssize_t len;
+ Hashes Sum(Hashes::SHA1SUM);
+ PyBytes_AsStringAndSize(Obj, &s, &len);
+ Sum.Add((const unsigned char*)s, len);
+ return CppPyString(Sum.GetHashString(Hashes::SHA1SUM).HashValue());
+ }
+
+ // Digest of a file
+ int Fd = PyObject_AsFileDescriptor(Obj);
+ if (Fd != -1)
+ {
+ Hashes Sum(Hashes::SHA1SUM);
+ struct stat St;
+ if (fstat(Fd,&St) != 0 ||
+ Sum.AddFD(Fd,St.st_size) == false)
+ {
+ PyErr_SetFromErrno(PyAptError);
+ return 0;
+ }
+
+ return CppPyString(Sum.GetHashString(Hashes::SHA1SUM).HashValue());
+ }
+
+ PyErr_SetString(PyExc_TypeError,"Only understand strings and files");
+ return 0;
+}
+ /*}}}*/
+// sha256sum - Compute the sha256sum of a file or string /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_sha256sum =
+ "sha256sum(object) -> str\n\n"
+ "Return the sha256sum of the object. 'object' may either be a string, in\n"
+ "which case the sha256sum of the string is returned, or a file() object\n"
+ "(or file descriptor), in which case the sha256sum of its contents is\n"
+ "returned.";;
+static PyObject *sha256sum(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "apt_pkg.sha256sum is deprecated, use apt_pkg.Hashes", 1) == -1)
+ return NULL;
+
+ // Digest of a string.
+ if (PyBytes_Check(Obj) != 0)
+ {
+ char *s;
+ Py_ssize_t len;
+ Hashes Sum(Hashes::SHA256SUM);
+ PyBytes_AsStringAndSize(Obj, &s, &len);
+ Sum.Add((const unsigned char*)s, len);
+ return CppPyString(Sum.GetHashString(Hashes::SHA256SUM).HashValue());
+ }
+
+ // Digest of a file
+ int Fd = PyObject_AsFileDescriptor(Obj);
+ if (Fd != -1)
+ {
+ Hashes Sum(Hashes::SHA256SUM);
+ struct stat St;
+ if (fstat(Fd,&St) != 0 ||
+ Sum.AddFD(Fd,St.st_size) == false)
+ {
+ PyErr_SetFromErrno(PyAptError);
+ return 0;
+ }
+
+ return CppPyString(Sum.GetHashString(Hashes::SHA256SUM).HashValue());
+ }
+
+ PyErr_SetString(PyExc_TypeError,"Only understand strings and files");
+ return 0;
+}
+ /*}}}*/
+// sha512sum - Compute the sha512sum of a file or string /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_sha512sum =
+ "sha512sum(object) -> str\n\n"
+ "Return the sha512sum of the object. 'object' may either be a string, in\n"
+ "which case the sha512sum of the string is returned, or a file() object\n"
+ "(or file descriptor), in which case the sha512sum of its contents is\n"
+ "returned.";;
+static PyObject *sha512sum(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "apt_pkg.sha512sum is deprecated, use apt_pkg.Hashes", 1) == -1)
+ return NULL;
+
+ // Digest of a string.
+ if (PyBytes_Check(Obj) != 0)
+ {
+ char *s;
+ Py_ssize_t len;
+ Hashes Sum(Hashes::SHA512SUM);
+ PyBytes_AsStringAndSize(Obj, &s, &len);
+ Sum.Add((const unsigned char*)s, len);
+ return CppPyString(Sum.GetHashString(Hashes::SHA512SUM).HashValue());
+ }
+
+ // Digest of a file
+ int Fd = PyObject_AsFileDescriptor(Obj);
+ if (Fd != -1)
+ {
+ Hashes Sum(Hashes::SHA512SUM);
+ struct stat St;
+ if (fstat(Fd,&St) != 0 ||
+ Sum.AddFD(Fd,St.st_size) == false)
+ {
+ PyErr_SetFromErrno(PyAptError);
+ return 0;
+ }
+
+ return CppPyString(Sum.GetHashString(Hashes::SHA512SUM).HashValue());
+ }
+
+ PyErr_SetString(PyExc_TypeError,"Only understand strings and files");
+ return 0;
+}
+ /*}}}*/
+// get_architectures - return the list of architectures /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_GetArchitectures =
+ "get_architectures() -> list\n\n"
+ "Return the list of supported architectures on this system. On a \n"
+ "multiarch system this can be more than one. The main architectures\n"
+ "is the first item in the list.";;
+static PyObject *GetArchitectures(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"",&Obj) == 0)
+ return 0;
+
+ PyObject *List = PyList_New(0);
+ std::vector<std::string> arches = APT::Configuration::getArchitectures();
+ std::vector<std::string>::const_iterator I;
+ for (I = arches.begin(); I != arches.end(); I++)
+ {
+ PyList_Append(List, CppPyString(*I));
+ }
+
+ return List;
+}
+ /*}}}*/
+// init - 3 init functions /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_Init =
+"init()\n\n"
+"Shorthand for doing init_config() and init_system(). When working\n"
+"with command line arguments, first call init_config() then parse\n"
+"the command line and finally call init_system().";
+static PyObject *Init(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgInitConfig(*_config);
+ pkgInitSystem(*_config,_system);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static char *doc_InitConfig =
+"init_config()\n\n"
+"Load the default configuration and the config file.";
+static PyObject *InitConfig(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgInitConfig(*_config);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static char *doc_InitSystem =
+"init_system()\n\n"
+"Construct the apt_pkg system.";
+static PyObject *InitSystem(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgInitSystem(*_config,_system);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+ /*}}}*/
+// gpgv.cc:OpenMaybeClearSignedFile /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_OpenMaybeClearSignedFile =
+"open_maybe_clear_signed_file(file: str) -> int\n\n"
+"Open a file and ignore a PGP clear signature.\n"
+"Return a open file descriptor or a error.";
+static PyObject *PyOpenMaybeClearSignedFile(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename file;
+ char errors = false;
+ if (PyArg_ParseTuple(Args,"O&",PyApt_Filename::Converter, &file,&errors) == 0)
+ return 0;
+
+ FileFd Fd;
+ if (OpenMaybeClearSignedFile(file, Fd) == false)
+ return HandleErrors(MkPyNumber(-1));
+
+ return HandleErrors(MkPyNumber(dup(Fd.Fd())));
+}
+
+// fileutils.cc: GetLock /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_GetLock =
+"get_lock(file: str, errors: bool) -> int\n\n"
+"Create an empty file of the given name and lock it. If the locking\n"
+"succeeds, return the file descriptor of the lock file. Afterwards,\n"
+"locking the file from another process will fail and thus cause\n"
+"get_lock() to return -1 or raise an Error (if 'errors' is True).\n\n"
+"From Python 2.6 on, it is recommended to use the context manager\n"
+"provided by apt_pkg.FileLock instead using the with-statement.";
+static PyObject *GetLock(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename file;
+ char errors = false;
+ if (PyArg_ParseTuple(Args,"O&|b",PyApt_Filename::Converter, &file,&errors) == 0)
+ return 0;
+
+ int fd = GetLock(file, errors);
+
+ return HandleErrors(MkPyNumber(fd));
+}
+
+static char *doc_PkgSystemLock =
+"pkgsystem_lock() -> bool\n\n"
+"Acquire the global lock for the package system by using /var/lib/dpkg/lock-frontend\n"
+"and /var/lib/dpkg/lock to do the locking. From Python 2.6 on, the apt_pkg.SystemLock context\n"
+"manager is available and should be used instead.";
+static PyObject *PkgSystemLock(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->Lock();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSystemUnLock =
+"pkgsystem_unlock() -> bool\n\n"
+"Release the global lock for the package system.";
+static PyObject *PkgSystemUnLock(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->UnLock();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSystemLockInner =
+"pkgsystem_lock_inner() -> bool\n\n"
+"Reacquire the dpkg 'lock' lock file. Must be called only after\n"
+":meth:`pkgsystem_unlock_inner` and only around invocations of dpkg.\n"
+"\n"
+".. versionadded:: 1.7";
+static PyObject *PkgSystemLockInner(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->LockInner();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSystemUnLockInner =
+"pkgsystem_unlock_inner() -> bool\n\n"
+"Release the dpkg lock file 'lock'. To be called before manually\n"
+"invoking dpkg.\n"
+"\n"
+".. versionadded:: 1.7";
+static PyObject *PkgSystemUnLockInner(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->UnLockInner();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSystemIsLocked =
+"pkgsystem_is_locked() -> bool\n\n"
+"Check if the system is locked. Can be used to check whether the inner\n"
+"lock needs to be released or not in generic code.\n"
+"\n"
+".. versionadded:: 1.7";
+static PyObject *PkgSystemIsLocked(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->IsLocked();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+ /*}}}*/
+
+// initapt_pkg - Core Module Initialization /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static PyMethodDef methods[] =
+{
+ // Constructors
+ {"init",Init,METH_VARARGS,doc_Init},
+ {"init_config",InitConfig,METH_VARARGS,doc_InitConfig},
+ {"init_system",InitSystem,METH_VARARGS,doc_InitSystem},
+
+ // Internationalization.
+ {"gettext",py_gettext,METH_VARARGS,
+ "gettext(msg: str[, domain: str = 'python-apt']) -> str\n\n"
+ "Translate the given string. This is much faster than Python's version\n"
+ "and only does translations after setlocale() has been called."},
+
+ // Tag File
+
+ {"open_maybe_clear_signed_file",PyOpenMaybeClearSignedFile,METH_VARARGS,
+ doc_OpenMaybeClearSignedFile},
+
+ // Locking
+ {"get_lock",GetLock,METH_VARARGS,doc_GetLock},
+ {"pkgsystem_lock",PkgSystemLock,METH_VARARGS,doc_PkgSystemLock},
+ {"pkgsystem_unlock",PkgSystemUnLock,METH_VARARGS,doc_PkgSystemUnLock},
+ {"pkgsystem_lock_inner",PkgSystemLockInner,METH_VARARGS,doc_PkgSystemLockInner},
+ {"pkgsystem_unlock_inner",PkgSystemUnLockInner,METH_VARARGS,doc_PkgSystemUnLockInner},
+ {"pkgsystem_is_locked",PkgSystemIsLocked,METH_VARARGS,doc_PkgSystemIsLocked},
+
+ // Command line
+ {"read_config_file",LoadConfig,METH_VARARGS,doc_LoadConfig},
+ {"read_config_dir",LoadConfigDir,METH_VARARGS,doc_LoadConfigDir},
+ {"read_config_file_isc",LoadConfigISC,METH_VARARGS,doc_LoadConfig},
+ {"parse_commandline",ParseCommandLine,METH_VARARGS,doc_ParseCommandLine},
+
+ // Versioning
+ {"version_compare",VersionCompare,METH_VARARGS,doc_VersionCompare},
+ {"check_dep",CheckDep,METH_VARARGS,doc_CheckDep},
+ {"upstream_version",UpstreamVersion,METH_VARARGS,doc_UpstreamVersion},
+
+ // Depends
+ {"parse_depends",reinterpret_cast<PyCFunction>(static_cast<PyCFunctionWithKeywords>(ParseDepends)),METH_VARARGS|METH_KEYWORDS,doc_ParseDepends},
+ {"parse_src_depends",reinterpret_cast<PyCFunction>(static_cast<PyCFunctionWithKeywords>(ParseSrcDepends)),METH_VARARGS|METH_KEYWORDS,parse_src_depends_doc},
+
+ // Hashes
+ {"md5sum",md5sum,METH_VARARGS,doc_md5sum},
+ {"sha1sum",sha1sum,METH_VARARGS,doc_sha1sum},
+ {"sha256sum",sha256sum,METH_VARARGS,doc_sha256sum},
+ {"sha512sum",sha512sum,METH_VARARGS,doc_sha512sum},
+
+ // multiarch
+ {"get_architectures", GetArchitectures, METH_VARARGS, doc_GetArchitectures},
+
+ // Strings
+ {"check_domain_list",StrCheckDomainList,METH_VARARGS,
+ "check_domain_list(host: str, domains: str) -> bool\n\n"
+ "Check if the host given by 'host' belongs to one of the domains\n"
+ "specified in the comma separated string 'domains'. An example\n"
+ "would be:\n\n"
+ " check_domain_list('alioth.debian.org','debian.net,debian.org')\n\n"
+ "which would return True because alioth belongs to debian.org."},
+ {"quote_string",StrQuoteString,METH_VARARGS,
+ "quote_string(string: str, repl: str) -> str\n\n"
+ "Escape the string 'string', replacing any character not allowed in a URL"
+ "or specified by 'repl' with its ASCII value preceded by a percent sign"
+ "(so for example ' ' becomes '%20')."},
+ {"dequote_string",StrDeQuote,METH_VARARGS,
+ "dequote_string(string: str) -> str\n\n"
+ "Dequote the given string by replacing all HTTP encoded values such\n"
+ "as '%20' with their decoded value (in this case, ' ')."},
+ {"size_to_str",StrSizeToStr,METH_VARARGS,
+ "size_to_str(bytes: int) -> str\n\n"
+ "Return a string describing the size in a human-readable manner using\n"
+ "SI prefix and base-10 units, e.g. '1k' for 1000, '1M' for 1000000, etc."},
+ {"time_to_str",StrTimeToStr,METH_VARARGS,
+ "time_to_str(seconds: int) -> str\n\n"
+ "Return a string describing the number of seconds in a human\n"
+ "readable manner using days, hours, minutes and seconds."},
+ {"uri_to_filename",StrURItoFileName,METH_VARARGS,
+ "uri_to_filename(uri: str) -> str\n\n"
+ "Return a filename based on the given URI after replacing some\n"
+ "parts not suited for filenames (e.g. '/')."},
+ {"base64_encode",StrBase64Encode,METH_VARARGS,
+ "base64_encode(value: bytes) -> str\n\n"
+ "Encode the given bytestring into Base64. The input may not\n"
+ "contain a null byte character (use the base64 module for this)."},
+ {"string_to_bool",StrStringToBool,METH_VARARGS,
+ "string_to_bool(string: str) -> int\n\n"
+ "Return 1 if the string is a value such as 'yes', 'true', '1';\n"
+ "0 if the string is a value such as 'no', 'false', '0'; -1 if\n"
+ "the string is not recognized."},
+ {"time_rfc1123",StrTimeRFC1123,METH_VARARGS,
+ "time_rfc1123(unixtime: int) -> str\n\n"
+ "Format the given Unix time according to the requirements of\n"
+ "RFC 1123."},
+ {"str_to_time",StrStrToTime,METH_VARARGS,
+ "str_to_time(rfc_time: str) -> int\n\n"
+ "Convert the given RFC 1123 formatted string to a Unix timestamp."},
+
+ // DEPRECATED
+
+ {}
+};
+
+static struct _PyAptPkgAPIStruct API = {
+ &PyAcquire_Type, // acquire_type
+ &PyAcquire_FromCpp, // acquire_fromcpp
+ &PyAcquire_ToCpp, // acquire_tocpp
+ &PyAcquireFile_Type, // acquirefile_type
+ &PyAcquireFile_FromCpp, // acquirefile_fromcpp
+ &PyAcquireFile_ToCpp, // acquirefile_tocpp
+ &PyAcquireItem_Type, // acquireitem_type
+ &PyAcquireItem_FromCpp, // acquireitem_fromcpp
+ &PyAcquireItem_ToCpp, // acquireitem_type
+ &PyAcquireItemDesc_Type, // acquireitemdesc_type
+ &PyAcquireItemDesc_FromCpp,// acquireitemdesc_fromcpp
+ &PyAcquireItemDesc_ToCpp, // acquireitemdesc_tocpp
+ &PyAcquireWorker_Type, // acquireworker_type
+ &PyAcquireWorker_FromCpp, // acquireworker_fromcpp
+ &PyAcquireWorker_ToCpp, // acquireworker_tocpp
+ &PyActionGroup_Type, // actiongroup_type
+ &PyActionGroup_FromCpp, // actiongroup_fromcpp
+ &PyActionGroup_ToCpp, // actiongroup_tocpp
+ &PyCache_Type, // cache_type
+ &PyCache_FromCpp, // cache_fromcpp
+ &PyCache_ToCpp, // cache_tocpp
+ &PyCacheFile_Type, // cachefile_type
+ &PyCacheFile_FromCpp, // cachefile_fromcpp
+ &PyCacheFile_ToCpp, // cachefile_tocpp
+ &PyCdrom_Type, // cdrom_type
+ &PyCdrom_FromCpp, // cdrom_fromcpp
+ &PyCdrom_ToCpp, // cdrom_tocpp
+ &PyConfiguration_Type, // configuration_type
+ &PyConfiguration_FromCpp, // configuration_fromcpp
+ &PyConfiguration_ToCpp, // configuration_tocpp
+ &PyDepCache_Type, // depcache_type
+ &PyDepCache_FromCpp, // depcache_fromcpp
+ &PyDepCache_ToCpp, // depcache_tocpp
+ &PyDependency_Type, // dependency_type
+ &PyDependency_FromCpp, // dependency_fromcpp
+ &PyDependency_ToCpp, // dependency_tocpp
+ &PyDependencyList_Type, // dependencylist_type
+ 0, // FIXME: dependencylist_fromcpp
+ 0, // FIXME: dependencylist_tocpp
+ &PyDescription_Type, // description_type
+ &PyDescription_FromCpp, // description_fromcpp
+ &PyDescription_ToCpp, // description_tocpp
+ &PyHashes_Type, // hashes_type
+ &PyHashes_FromCpp, // hashes_fromcpp
+ &PyHashes_ToCpp, // hashes_tocpp
+ &PyHashString_Type, // hashstring_type
+ &PyHashString_FromCpp, // hashstring_fromcpp
+ &PyHashString_ToCpp, // hashstring_tocpp
+ &PyMetaIndex_Type, // metaindex_type
+ &PyMetaIndex_FromCpp, // metaindex_tocpp
+ &PyMetaIndex_ToCpp, // metaindex_tocpp
+ &PyPackage_Type, // package_type
+ &PyPackage_FromCpp, // package_tocpp
+ &PyPackage_ToCpp, // package_tocpp
+ &PyPackageFile_Type, // packagefile_type
+ &PyPackageFile_FromCpp, // packagefile_tocpp
+ &PyPackageFile_ToCpp, // packagefile_tocpp
+ &PyIndexFile_Type, // packageindexfile_type
+ &PyIndexFile_FromCpp, // packageindexfile_tocpp
+ &PyIndexFile_ToCpp, // packageindexfile_tocpp
+ &PyPackageList_Type, // packagelist_type
+ 0, // FIXME: packagelist_fromcpp
+ 0, // FIXME: packagelist_tocpp
+ &PyPackageManager_Type, // packagemanager_type
+ &PyPackageManager_FromCpp, // packagemanager_type
+ &PyPackageManager_ToCpp, // packagemanager_type
+ &PyPackageRecords_Type, // packagerecords_type
+ 0, // FIXME: packagerecords_fromcpp
+ 0, // FIXME: packagerecords_tocpp
+ &PyPolicy_Type, // policy_type
+ &PyPolicy_FromCpp, // policy_tocpp
+ &PyPolicy_ToCpp, // policy_tocpp
+ &PyProblemResolver_Type, // problemresolver_type
+ &PyProblemResolver_FromCpp, // problemresolver_tocpp
+ &PyProblemResolver_ToCpp, // problemresolver_tocpp
+ &PySourceList_Type, // sourcelist_type
+ &PySourceList_FromCpp, // sourcelist_tocpp
+ &PySourceList_ToCpp, // sourcelist_tocpp
+ &PySourceRecords_Type, // sourcerecords_type
+ 0, // FIXME: sourcerecords_fromcpp
+ 0, // FIXME: sourcerecords_tocpp
+ &PyTagFile_Type, // tagfile_type
+ &PyTagFile_FromCpp, // tagfile_tocpp
+ &PyTagFile_ToCpp, // tagfile_tocpp
+ &PyTagSection_Type, // tagsection_type
+ &PyTagSection_FromCpp, // tagsection_tocpp
+ &PyTagSection_ToCpp, // tagsection_tocpp
+ &PyVersion_Type, // version_type
+ &PyVersion_FromCpp, // version_tocpp
+ &PyVersion_ToCpp, // version_tocpp
+ &PyGroup_Type, // group_type
+ &PyGroup_FromCpp, // group_fromcpp
+ &PyGroup_ToCpp, // group_tocpp
+ &PyOrderList_Type, // orderlist_type
+ &PyOrderList_FromCpp, // orderlist_fromcpp
+ &PyOrderList_ToCpp, // orderlist_tocpp
+ &PySourceRecordFiles_Type, // sourcerecordfiles_type
+ 0, // FIXME: sourcerecordfiles_fromcpp
+ 0, // FIXME: sourcerecordfiles_tocpp
+};
+
+
+#define ADDTYPE(mod,name,type) { \
+ if (PyType_Ready(type) == -1) INIT_ERROR; \
+ Py_INCREF(type); \
+ PyModule_AddObject(mod,name,(PyObject *)type); }
+
+
+static const char *apt_pkg_doc =
+ "Classes and functions wrapping the apt-pkg library.\n\n"
+ "The apt_pkg module provides several classes and functions for accessing\n"
+ "the functionality provided by the apt-pkg library. Typical uses might\n"
+ "include reading APT index files and configuration files and installing\n"
+ "or removing packages.";
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "apt_pkg",
+ apt_pkg_doc,
+ -1,
+ methods,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+#define INIT_ERROR return 0
+extern "C" PyObject * PyInit_apt_pkg()
+#else
+#define INIT_ERROR return
+extern "C" void initapt_pkg()
+#endif
+{
+ // Finalize our types to add slots, etc.
+ if (PyType_Ready(&PyConfiguration_Type) == -1) INIT_ERROR;
+ if (PyType_Ready(&PyCacheFile_Type) == -1) INIT_ERROR;
+ PyAptError = PyErr_NewExceptionWithDoc("apt_pkg.Error", PyAptError_Doc, PyExc_SystemError, NULL);
+ if (PyAptError == NULL)
+ INIT_ERROR;
+ PyAptWarning = PyErr_NewExceptionWithDoc("apt_pkg.Warning", PyAptWarning_Doc, PyExc_Warning, NULL);
+ if (PyAptWarning == NULL)
+ INIT_ERROR;
+
+ PyAptCacheMismatchError = PyErr_NewExceptionWithDoc("apt_pkg.CacheMismatchError", PyAptCacheMismatchError_Doc, PyExc_ValueError, NULL);
+ if (PyAptCacheMismatchError == NULL)
+ INIT_ERROR;
+
+ // Initialize the module
+ #if PY_MAJOR_VERSION >= 3
+ PyObject *Module = PyModule_Create(&moduledef);
+ #else
+ PyObject *Module = Py_InitModule3("apt_pkg",methods, apt_pkg_doc);
+ #endif
+
+ // Global variable linked to the global configuration class
+ CppPyObject<Configuration*> *Config = CppPyObject_NEW<Configuration*>(NULL, &PyConfiguration_Type);
+ Config->Object = _config;
+ // Global configuration, should never be deleted.
+ Config->NoDelete = true;
+ PyModule_AddObject(Module,"config",Config);
+ PyModule_AddObject(Module,"Error",PyAptError);
+ PyModule_AddObject(Module,"Warning",PyAptWarning);
+ PyModule_AddObject(Module,"CacheMismatchError", PyAptCacheMismatchError);
+
+
+
+ // Add our classes.
+ /* ============================ tag.cc ============================ */
+ ADDTYPE(Module,"TagSection",&PyTagSection_Type);
+ ADDTYPE(Module,"TagFile",&PyTagFile_Type);
+ ADDTYPE(Module,"Tag",&PyTag_Type);
+ ADDTYPE(Module,"TagRewrite",&PyTagRewrite_Type);
+ ADDTYPE(Module,"TagRename",&PyTagRename_Type);
+ ADDTYPE(Module,"TagRemove",&PyTagRemove_Type);
+ /* ============================ acquire.cc ============================ */
+ ADDTYPE(Module,"Acquire",&PyAcquire_Type);
+ ADDTYPE(Module,"AcquireFile",&PyAcquireFile_Type);
+ ADDTYPE(Module,"AcquireItem",&PyAcquireItem_Type); // NO __new__()
+ ADDTYPE(Module,"AcquireWorker",&PyAcquireWorker_Type); // NO __new__()
+ /* ============================ cache.cc ============================ */
+ ADDTYPE(Module,"Cache",&PyCache_Type);
+ ADDTYPE(Module,"Dependency",&PyDependency_Type); // NO __new__()
+ ADDTYPE(Module,"Description",&PyDescription_Type); // NO __new__()
+ ADDTYPE(Module,"PackageFile",&PyPackageFile_Type); // NO __new__()
+ ADDTYPE(Module,"PackageList",&PyPackageList_Type); // NO __new__(), internal
+ ADDTYPE(Module,"DependencyList",&PyDependencyList_Type); // NO __new__(), internal
+ ADDTYPE(Module,"Package",&PyPackage_Type); // NO __new__()
+ ADDTYPE(Module,"Version",&PyVersion_Type); // NO __new__()
+ ADDTYPE(Module,"Group", &PyGroup_Type);
+ ADDTYPE(Module,"GroupList", &PyGroupList_Type);
+ /* ============================ cdrom.cc ============================ */
+ ADDTYPE(Module,"Cdrom",&PyCdrom_Type);
+ /* ========================= configuration.cc ========================= */
+ ADDTYPE(Module,"Configuration",&PyConfiguration_Type);
+ /* ========================= depcache.cc ========================= */
+ ADDTYPE(Module,"ActionGroup",&PyActionGroup_Type);
+ ADDTYPE(Module,"DepCache",&PyDepCache_Type);
+ ADDTYPE(Module,"ProblemResolver",&PyProblemResolver_Type);
+ /* ========================= indexfile.cc ========================= */
+ ADDTYPE(Module,"IndexFile",&PyIndexFile_Type); // NO __new__()
+ /* ========================= metaindex.cc ========================= */
+ ADDTYPE(Module,"MetaIndex",&PyMetaIndex_Type); // NO __new__()
+ /* ========================= pkgmanager.cc ========================= */
+ ADDTYPE(Module,"_PackageManager",&PyPackageManager_Type);
+ ADDTYPE(Module,"PackageManager",&PyPackageManager2_Type);
+ /* ========================= pkgrecords.cc ========================= */
+ ADDTYPE(Module,"PackageRecords",&PyPackageRecords_Type);
+ /* ========================= pkgsrcrecords.cc ========================= */
+ ADDTYPE(Module,"SourceRecords",&PySourceRecords_Type);
+ ADDTYPE(Module,"SourceRecordFiles",&PySourceRecordFiles_Type);
+ /* ========================= sourcelist.cc ========================= */
+ ADDTYPE(Module,"SourceList",&PySourceList_Type);
+ ADDTYPE(Module,"HashString",&PyHashString_Type);
+ ADDTYPE(Module,"Policy",&PyPolicy_Type);
+ ADDTYPE(Module,"Hashes",&PyHashes_Type);
+ ADDTYPE(Module,"AcquireItemDesc",&PyAcquireItemDesc_Type);
+ ADDTYPE(Module,"SystemLock",&PySystemLock_Type);
+ ADDTYPE(Module,"FileLock",&PyFileLock_Type);
+ ADDTYPE(Module,"OrderList",&PyOrderList_Type);
+ ADDTYPE(Module,"HashStringList",&PyHashStringList_Type);
+ // Tag file constants
+ PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER",
+ CharCharToList(TFRewritePackageOrder));
+
+ PyModule_AddObject(Module,"REWRITE_SOURCE_ORDER",
+ CharCharToList(TFRewriteSourceOrder));
+
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_ADDED", MkPyNumber(pkgOrderList::Added));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_ADD_PENDIG", MkPyNumber(pkgOrderList::AddPending));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_IMMEDIATE", MkPyNumber(pkgOrderList::Immediate));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_LOOP", MkPyNumber(pkgOrderList::Loop));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_UNPACKED", MkPyNumber(pkgOrderList::UnPacked));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_CONFIGURED", MkPyNumber(pkgOrderList::Configured));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_REMOVED", MkPyNumber(pkgOrderList::Removed));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_IN_LIST", MkPyNumber(pkgOrderList::InList));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_AFTER", MkPyNumber(pkgOrderList::After));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_STATES_MASK", MkPyNumber(pkgOrderList::States));
+
+ // Acquire constants.
+ // some constants
+ PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_CANCELLED",
+ MkPyNumber(pkgAcquire::Cancelled));
+ PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_CONTINUE",
+ MkPyNumber(pkgAcquire::Continue));
+ PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_FAILED",
+ MkPyNumber(pkgAcquire::Failed));
+ // Dependency constants
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DEPENDS",
+ MkPyNumber(pkgCache::Dep::Depends));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_PREDEPENDS",
+ MkPyNumber(pkgCache::Dep::PreDepends));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_SUGGESTS",
+ MkPyNumber(pkgCache::Dep::Suggests));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_RECOMMENDS",
+ MkPyNumber(pkgCache::Dep::Recommends));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_CONFLICTS",
+ MkPyNumber(pkgCache::Dep::Conflicts));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_REPLACES",
+ MkPyNumber(pkgCache::Dep::Replaces));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_OBSOLETES",
+ MkPyNumber(pkgCache::Dep::Obsoletes));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DPKG_BREAKS",
+ MkPyNumber(pkgCache::Dep::DpkgBreaks));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_ENHANCES",
+ MkPyNumber(pkgCache::Dep::Enhances));
+
+
+ // PackageManager constants
+ PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_COMPLETED",
+ MkPyNumber(pkgPackageManager::Completed));
+ PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_FAILED",
+ MkPyNumber(pkgPackageManager::Failed));
+ PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_INCOMPLETE",
+ MkPyNumber(pkgPackageManager::Incomplete));
+
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_NO",
+ MkPyNumber(pkgCache::Version::No));
+ // NONE is deprecated (#782802)
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_NONE",
+ MkPyNumber(pkgCache::Version::No));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL",
+ MkPyNumber(pkgCache::Version::All));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_FOREIGN",
+ MkPyNumber(pkgCache::Version::Foreign));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_SAME",
+ MkPyNumber(pkgCache::Version::Same));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALLOWED",
+ MkPyNumber(pkgCache::Version::Allowed));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL_FOREIGN",
+ MkPyNumber(pkgCache::Version::AllForeign));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL_ALLOWED",
+ MkPyNumber(pkgCache::Version::AllAllowed));
+ // AcquireItem Constants.
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_IDLE",
+ MkPyNumber(pkgAcquire::Item::StatIdle));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_FETCHING",
+ MkPyNumber(pkgAcquire::Item::StatFetching));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_DONE",
+ MkPyNumber(pkgAcquire::Item::StatDone));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_TRANSIENT_NETWORK_ERROR",
+ MkPyNumber(pkgAcquire::Item::StatTransientNetworkError));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_ERROR",
+ MkPyNumber(pkgAcquire::Item::StatError));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_AUTH_ERROR",
+ MkPyNumber(pkgAcquire::Item::StatAuthError));
+ // TagSection constants
+ PyDict_SetItemString(PyTag_Type.tp_dict, "REMOVE",
+ MkPyNumber(pkgTagSection::Tag::REMOVE));
+ PyDict_SetItemString(PyTag_Type.tp_dict, "REWRITE",
+ MkPyNumber(pkgTagSection::Tag::REWRITE));
+ PyDict_SetItemString(PyTag_Type.tp_dict, "RENAME",
+ MkPyNumber(pkgTagSection::Tag::RENAME));
+
+#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1
+ PyObject *PyCapsule = PyCapsule_New(&API, "apt_pkg._C_API", NULL);
+#else
+ PyObject *PyCapsule = PyCObject_FromVoidPtr(&API, NULL);
+#endif
+ PyModule_AddObject(Module, "_C_API", PyCapsule);
+ // Version..
+ PyModule_AddStringConstant(Module,"VERSION",(char *)pkgVersion);
+ PyModule_AddStringConstant(Module,"LIB_VERSION",(char *)pkgLibVersion);
+#ifdef DATE
+ PyModule_AddStringConstant(Module,"DATE",DATE);
+ PyModule_AddStringConstant(Module,"TIME",TIME);
+#else
+ PyModule_AddStringConstant(Module,"DATE", "Jan 1 1970");
+ PyModule_AddStringConstant(Module,"TIME", "00:00:00");
+#endif
+
+ // My constants
+ PyModule_AddIntConstant(Module,"PRI_IMPORTANT",pkgCache::State::Important);
+ PyModule_AddIntConstant(Module,"PRI_REQUIRED",pkgCache::State::Required);
+ PyModule_AddIntConstant(Module,"PRI_STANDARD",pkgCache::State::Standard);
+ PyModule_AddIntConstant(Module,"PRI_OPTIONAL",pkgCache::State::Optional);
+ PyModule_AddIntConstant(Module,"PRI_EXTRA",pkgCache::State::Extra);
+ // CurState
+ PyModule_AddIntConstant(Module,"CURSTATE_NOT_INSTALLED",pkgCache::State::NotInstalled);
+ PyModule_AddIntConstant(Module,"CURSTATE_UNPACKED",pkgCache::State::UnPacked);
+ PyModule_AddIntConstant(Module,"CURSTATE_HALF_CONFIGURED",pkgCache::State::HalfConfigured);
+ PyModule_AddIntConstant(Module,"CURSTATE_HALF_INSTALLED",pkgCache::State::HalfInstalled);
+ PyModule_AddIntConstant(Module,"CURSTATE_CONFIG_FILES",pkgCache::State::ConfigFiles);
+ PyModule_AddIntConstant(Module,"CURSTATE_INSTALLED",pkgCache::State::Installed);
+ // SelState
+ PyModule_AddIntConstant(Module,"SELSTATE_UNKNOWN",pkgCache::State::Unknown);
+ PyModule_AddIntConstant(Module,"SELSTATE_INSTALL",pkgCache::State::Install);
+ PyModule_AddIntConstant(Module,"SELSTATE_HOLD",pkgCache::State::Hold);
+ PyModule_AddIntConstant(Module,"SELSTATE_DEINSTALL",pkgCache::State::DeInstall);
+ PyModule_AddIntConstant(Module,"SELSTATE_PURGE",pkgCache::State::Purge);
+ // InstState
+ PyModule_AddIntConstant(Module,"INSTSTATE_OK",pkgCache::State::Ok);
+ PyModule_AddIntConstant(Module,"INSTSTATE_REINSTREQ",pkgCache::State::ReInstReq);
+ PyModule_AddIntConstant(Module,"INSTSTATE_HOLD",pkgCache::State::Hold);
+ PyModule_AddIntConstant(Module,"INSTSTATE_HOLD_REINSTREQ",pkgCache::State::HoldReInstReq);
+
+ #if PY_MAJOR_VERSION >= 3
+ return Module;
+ #endif
+}
+ /*}}}*/
+
diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h
new file mode 100644
index 0000000..ee92c50
--- /dev/null
+++ b/python/apt_pkgmodule.h
@@ -0,0 +1,214 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_pkgmodule.h,v 1.4 2003/07/23 02:20:24 mdz Exp $
+/* ######################################################################
+
+ Prototypes for the module
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef APT_PKGMODULE_H
+#define APT_PKGMODULE_H
+
+#include <Python.h>
+#include <apt-pkg/hashes.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/deblistparser.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/cdrom.h>
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/metaindex.h>
+#include "generic.h"
+
+// Configuration Stuff
+extern PyTypeObject PyConfiguration_Type;
+extern PyTypeObject PyVersion_Type;
+
+extern char *doc_LoadConfig;
+extern char *doc_LoadConfigISC;
+extern char *doc_LoadConfigDir;
+extern char *doc_ParseCommandLine;
+PyObject *LoadConfig(PyObject *Self,PyObject *Args);
+PyObject *LoadConfigISC(PyObject *Self,PyObject *Args);
+PyObject *LoadConfigDir(PyObject *Self,PyObject *Args);
+PyObject *ParseCommandLine(PyObject *Self,PyObject *Args);
+
+// Tag File Stuff
+extern PyTypeObject PyTagSection_Type;
+extern PyTypeObject PyTagFile_Type;
+extern PyTypeObject PyTag_Type;
+extern PyTypeObject PyTagRewrite_Type;
+extern PyTypeObject PyTagRename_Type;
+extern PyTypeObject PyTagRemove_Type;
+extern char *doc_ParseSection;
+extern char *doc_ParseTagFile;
+PyObject *ParseSection(PyObject *self,PyObject *Args);
+PyObject *ParseTagFile(PyObject *self,PyObject *Args);
+
+// String Stuff
+PyObject *StrQuoteString(PyObject *self,PyObject *Args);
+PyObject *StrDeQuote(PyObject *self,PyObject *Args);
+PyObject *StrSizeToStr(PyObject *self,PyObject *Args);
+PyObject *StrTimeToStr(PyObject *self,PyObject *Args);
+PyObject *StrURItoFileName(PyObject *self,PyObject *Args);
+PyObject *StrBase64Encode(PyObject *self,PyObject *Args);
+PyObject *StrStringToBool(PyObject *self,PyObject *Args);
+PyObject *StrTimeRFC1123(PyObject *self,PyObject *Args);
+PyObject *StrStrToTime(PyObject *self,PyObject *Args);
+PyObject *StrCheckDomainList(PyObject *Self,PyObject *Args);
+
+PyObject *PyAcquire_GetItem(PyObject *self, pkgAcquire::Item *item);
+PyObject *PyAcquire_GetItemDesc(PyObject *self, pkgAcquire::ItemDesc *item);
+bool PyAcquire_DropItem(PyObject *self, pkgAcquire::Item *item);
+
+// Cache Stuff
+extern PyTypeObject PyCache_Type;
+extern PyTypeObject PyCacheFile_Type;
+extern PyTypeObject PyPackageList_Type;
+extern PyTypeObject PyDescription_Type;
+extern PyTypeObject PyGroup_Type;
+extern PyTypeObject PyGroupList_Type; /* internal */
+extern PyTypeObject PyPackage_Type;
+extern PyTypeObject PyPackageFile_Type;
+extern PyTypeObject PyDependency_Type;
+extern PyTypeObject PyDependencyList_Type;
+PyObject *TmpGetCache(PyObject *Self,PyObject *Args);
+
+// DepCache
+extern PyTypeObject PyDepCache_Type;
+PyObject *GetDepCache(PyObject *Self,PyObject *Args);
+
+// pkgProblemResolver
+extern PyTypeObject PyProblemResolver_Type;
+PyObject *GetPkgProblemResolver(PyObject *Self, PyObject *Args);
+PyObject *GetPkgActionGroup(PyObject *Self, PyObject *Args);
+
+extern PyTypeObject PyActionGroup_Type;
+// cdrom
+extern PyTypeObject PyCdrom_Type;
+PyObject *GetCdrom(PyObject *Self,PyObject *Args);
+
+// acquire
+extern PyTypeObject PyAcquireItem_Type;
+extern PyTypeObject PyAcquire_Type;
+extern PyTypeObject PyAcquireFile_Type;
+extern char *doc_GetPkgAcqFile;
+PyObject *GetAcquire(PyObject *Self,PyObject *Args);
+PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject *kwds);
+
+// packagemanager
+extern PyTypeObject PyPackageManager_Type;
+extern PyTypeObject PyPackageManager2_Type;
+PyObject *GetPkgManager(PyObject *Self,PyObject *Args);
+
+
+// PkgRecords Stuff
+extern PyTypeObject PyPackageRecords_Type;
+extern PyTypeObject PySourceRecords_Type;
+extern PyTypeObject PySourceRecordFiles_Type;
+PyObject *GetPkgRecords(PyObject *Self,PyObject *Args);
+PyObject *GetPkgSrcRecords(PyObject *Self,PyObject *Args);
+
+// pkgSourceList
+extern PyTypeObject PySourceList_Type;
+PyObject *GetPkgSourceList(PyObject *Self,PyObject *Args);
+
+// pkgSourceList
+extern PyTypeObject PyIndexFile_Type;
+
+// metaIndex
+extern PyTypeObject PyMetaIndex_Type;
+
+// HashString
+extern PyTypeObject PyHashString_Type;
+
+extern PyTypeObject PyHashStringList_Type;
+
+
+// Policy
+extern PyTypeObject PyPolicy_Type;
+extern PyTypeObject PyHashes_Type;
+extern PyTypeObject PyAcquireItemDesc_Type;
+extern PyTypeObject PyAcquireWorker_Type;
+extern PyTypeObject PySystemLock_Type;
+extern PyTypeObject PyFileLock_Type;
+extern PyTypeObject PyOrderList_Type;
+
+// Functions to be exported in the public API.
+
+# define PyAcquire_ToCpp GetCpp<pkgAcquire*>
+# define PyAcquireFile_ToCpp GetCpp<pkgAcqFile*>
+# define PyAcquireItem_ToCpp GetCpp<pkgAcquire::Item*>
+# define PyAcquireItemDesc_ToCpp GetCpp<pkgAcquire::ItemDesc*>
+# define PyAcquireWorker_ToCpp GetCpp<pkgAcquire::Worker*>
+# define PyActionGroup_ToCpp GetCpp<pkgDepCache::ActionGroup*>
+# define PyCache_ToCpp GetCpp<pkgCache*>
+# define PyCacheFile_ToCpp GetCpp<pkgCacheFile*>
+# define PyCdrom_ToCpp GetCpp<pkgCdrom>
+# define PyConfiguration_ToCpp GetCpp<Configuration*>
+# define PyDepCache_ToCpp GetCpp<pkgDepCache*>
+# define PyDependency_ToCpp GetCpp<pkgCache::DepIterator>
+# define PyDependencyList_ToCpp GetCpp<RDepListStruct> // TODO
+# define PyDescription_ToCpp GetCpp<pkgCache::DescIterator>
+# define PyGroup_ToCpp GetCpp<pkgCache::GrpIterator>
+# define PyHashes_ToCpp GetCpp<Hashes>
+# define PyHashString_ToCpp GetCpp<HashString*>
+# define PyMetaIndex_ToCpp GetCpp<metaIndex*>
+# define PyPackage_ToCpp GetCpp<pkgCache::PkgIterator>
+# define PyPackageFile_ToCpp GetCpp<pkgCache::PkgFileIterator>
+# define PyIndexFile_ToCpp GetCpp<pkgIndexFile*>
+# define PyOrderList_ToCpp GetCpp<pkgOrderList*>
+# define PyPackageList_ToCpp GetCpp<PkgListStruct> // TODO
+# define PyPackageManager_ToCpp GetCpp<pkgPackageManager*>
+# define PyPackageRecords_ToCpp GetCpp<PkgRecordsStruct> // TODO
+# define PyPolicy_ToCpp GetCpp<pkgPolicy*>
+# define PyProblemResolver_ToCpp GetCpp<pkgProblemResolver*>
+# define PySourceList_ToCpp GetCpp<pkgSourceList*>
+# define PySourceRecords_ToCpp GetCpp<PkgSrcRecordsStruct> // TODO
+# define PyTagFile_ToCpp GetCpp<pkgTagFile>
+# define PyTagSection_ToCpp GetCpp<pkgTagSection>
+# define PyVersion_ToCpp GetCpp<pkgCache::VerIterator>
+
+PyObject* PyAcquire_FromCpp(pkgAcquire *fetcher, bool Delete, PyObject *Owner);
+PyObject* PyAcquireFile_FromCpp(pkgAcqFile* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyAcquireItem_FromCpp(pkgAcquire::Item* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyAcquireItemDesc_FromCpp(pkgAcquire::ItemDesc* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyAcquireWorker_FromCpp(pkgAcquire::Worker* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyActionGroup_FromCpp(pkgDepCache::ActionGroup* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyCache_FromCpp(pkgCache* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyCacheFile_FromCpp(pkgCacheFile* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyCdrom_FromCpp(pkgCdrom const &obj, bool Delete, PyObject *Owner);
+PyObject* PyConfiguration_FromCpp(Configuration* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyDepCache_FromCpp(pkgDepCache* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyDependency_FromCpp(pkgCache::DepIterator const &obj, bool Delete, PyObject *Owner);
+//PyObject* PyDependencyList_FromCpp(RDepListStruct const &obj, bool Delete, PyObject *Owner);
+PyObject* PyDescription_FromCpp(pkgCache::DescIterator const &obj, bool Delete, PyObject *Owner);
+PyObject* PyHashes_FromCpp(Hashes const &obj, bool Delete, PyObject *Owner);
+PyObject* PyHashString_FromCpp(HashString* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyMetaIndex_FromCpp(metaIndex* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyPackage_FromCpp(pkgCache::PkgIterator const &obj, bool Delete, PyObject *Owner);
+PyObject* PyGroup_FromCpp(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner);
+PyObject* PyIndexFile_FromCpp(pkgIndexFile* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyOrderList_FromCpp(pkgOrderList* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyPackageFile_FromCpp(pkgCache::PkgFileIterator const &obj, bool Delete, PyObject *Owner);
+//PyObject* PyPackageList_FromCpp(PkgListStruct const &obj, bool Delete, PyObject *Owner);
+PyObject* PyPackageManager_FromCpp(pkgPackageManager* const &obj, bool Delete, PyObject *Owner);
+//PyObject* PyPackageRecords_FromCpp(PkgRecordsStruct const &obj, bool Delete, PyObject *Owner);
+PyObject* PyPolicy_FromCpp(pkgPolicy* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyProblemResolver_FromCpp(pkgProblemResolver* const &obj, bool Delete, PyObject *Owner);
+PyObject* PySourceList_FromCpp(pkgSourceList* const &obj, bool Delete, PyObject *Owner);
+//PyObject* PySourceRecords_FromCpp(PkgSrcRecordsStruct const &obj, bool Delete, PyObject *Owner);
+PyObject* PyTagFile_FromCpp(pkgTagFile const &obj, bool Delete, PyObject *Owner);
+PyObject* PyTagSection_FromCpp(pkgTagSection const &obj, bool Delete, PyObject *Owner);
+PyObject* PyVersion_FromCpp(pkgCache::VerIterator const &obj, bool Delete, PyObject *Owner);
+
+#include "python-apt.h"
+#endif
+
diff --git a/python/arfile.cc b/python/arfile.cc
new file mode 100644
index 0000000..8f623b3
--- /dev/null
+++ b/python/arfile.cc
@@ -0,0 +1,744 @@
+/*
+ * arfile.cc - Wrapper around ARArchive and ARArchive::Member.
+ *
+ * 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 <Python.h>
+#include "generic.h"
+#include "apt_instmodule.h"
+#include <apt-pkg/arfile.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/configuration.h>
+#include <utime.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <array>
+
+static PyObject *armember_get_name(PyObject *self, void *closure)
+{
+ return CppPyPath(GetCpp<ARArchive::Member*>(self)->Name);
+}
+
+static PyObject *armember_get_mtime(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->MTime);
+}
+
+static PyObject *armember_get_uid(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->UID);
+}
+
+static PyObject *armember_get_gid(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->GID);
+}
+
+static PyObject *armember_get_mode(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->Mode);
+}
+
+static PyObject *armember_get_size(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->Size);
+}
+
+static PyObject *armember_get_start(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->Start);
+}
+
+static PyObject *armember_repr(PyObject *self)
+{
+ return PyString_FromFormat("<%s object: name:'%s'>",
+ self->ob_type->tp_name,
+ GetCpp<ARArchive::Member*>(self)->Name.c_str());
+}
+
+static PyGetSetDef armember_getset[] = {
+ {"gid",armember_get_gid,0,"The group id of the owner."},
+ {"mode",armember_get_mode,0,"The mode of the file."},
+ {"mtime",armember_get_mtime,0,"Last time of modification."},
+ {"name",armember_get_name,0,"The name of the file."},
+ {"size",armember_get_size,0,"The size of the files."},
+ {"start",armember_get_start,0,
+ "The offset in the archive where the file starts."},
+ {"uid",armember_get_uid,0,"The user ID of the owner."},
+ {NULL}
+};
+
+static const char *armember_doc =
+ "Represent a single file within an AR archive. For\n"
+ "Debian packages this can be e.g. control.tar.gz. This class provides\n"
+ "information about this file, such as the mode and size.";
+PyTypeObject PyArMember_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.ArMember", // tp_name
+ sizeof(CppPyObject<ARArchive::Member*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<ARArchive::Member*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ armember_repr, // 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_HAVE_GC,
+ armember_doc, // tp_doc
+ CppTraverse<ARArchive::Member*>,// tp_traverse
+ CppClear<ARArchive::Member*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ armember_getset, // tp_getset
+};
+
+
+static const char *filefd_doc=
+ "Internal helper type, representing a FileFd.";
+PyTypeObject PyFileFd_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.__FileFd" , // tp_name
+ sizeof(CppPyObject<FileFd>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<FileFd>, // 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_HAVE_GC,
+ filefd_doc, // tp_doc
+ CppTraverse<FileFd>, // tp_traverse
+ CppClear<FileFd>, // tp_clear
+};
+
+
+// We just add an inline method and should thus be ABI compatible in a way that
+// we can simply cast ARArchive instances to PyARArchiveHack.
+class PyARArchiveHack : public ARArchive
+{
+public:
+ inline Member *Members() {
+ return List;
+ }
+};
+
+struct PyArArchiveObject : public CppPyObject<PyARArchiveHack*> {
+ CppPyObject<FileFd> *Fd;
+};
+
+static const char *ararchive_getmember_doc =
+ "getmember(name: str) -> ArMember\n\n"
+ "Return an ArMember object for the member given by 'name'. Raise\n"
+ "LookupError if there is no ArMember with the given name.";
+static PyObject *ararchive_getmember(PyArArchiveObject *self, PyObject *arg)
+{
+ PyApt_Filename name;
+ CppPyObject<ARArchive::Member*> *ret;
+ if (!name.init(arg))
+ return 0;
+
+ const ARArchive::Member *member = self->Object->FindMember(name);
+ if (!member) {
+ PyErr_Format(PyExc_LookupError,"No member named '%s'",name.path);
+ return 0;
+ }
+
+ // Create our object.
+ ret = CppPyObject_NEW<ARArchive::Member*>(self,&PyArMember_Type);
+ ret->Object = const_cast<ARArchive::Member*>(member);
+ ret->NoDelete = true;
+ return ret;
+}
+
+static const char *ararchive_extractdata_doc =
+ "extractdata(name: str) -> bytes\n\n"
+ "Return the contents of the member, as a bytes object. Raise\n"
+ "LookupError if there is no ArMember with the given name.";
+static PyObject *ararchive_extractdata(PyArArchiveObject *self, PyObject *args)
+{
+ PyApt_Filename name;
+ if (PyArg_ParseTuple(args, "O&:extractdata", PyApt_Filename::Converter, &name) == 0)
+ return 0;
+ const ARArchive::Member *member = self->Object->FindMember(name);
+ if (!member) {
+ PyErr_Format(PyExc_LookupError,"No member named '%s'",name.path);
+ return 0;
+ }
+ if (member->Size > SIZE_MAX) {
+ PyErr_Format(PyExc_MemoryError,
+ "Member '%s' is too large to read into memory",name.path);
+ return 0;
+ }
+ if (!self->Fd->Object.Seek(member->Start))
+ return HandleErrors();
+
+ char* value;
+ try {
+ value = new char[member->Size];
+ } catch (std::bad_alloc&) {
+ PyErr_Format(PyExc_MemoryError,
+ "Member '%s' is too large to read into memory",name.path);
+ return 0;
+ }
+ self->Fd->Object.Read(value, member->Size, true);
+ PyObject *result = PyBytes_FromStringAndSize(value, member->Size);
+ delete[] value;
+ return result;
+}
+
+// Helper class to close the FD automatically.
+class IntFD {
+ public:
+ int fd;
+ inline operator int() { return fd; };
+ inline IntFD(int fd): fd(fd) { };
+ inline ~IntFD() { close(fd); };
+};
+
+static PyObject *_extract(FileFd &Fd, const ARArchive::Member *member,
+ const char *dir)
+{
+ if (!Fd.Seek(member->Start))
+ return HandleErrors();
+
+ std::string outfile_str = flCombine(dir,member->Name);
+ char *outfile = (char*)outfile_str.c_str();
+
+ // We are not using FileFd here, because we want to raise OSErrror with
+ // the correct errno and filename. IntFD's are closed automatically.
+ IntFD outfd(open(outfile, O_NDELAY|O_WRONLY|O_CREAT|O_TRUNC|O_APPEND,
+ member->Mode));
+ if (outfd == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+ if (fchmod(outfd, member->Mode) == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+ if (fchown(outfd, member->UID, member->GID) != 0 && errno != EPERM)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+
+ // Read 4 KiB from the file, until all of the file is read. Deallocated
+ // automatically when the function returns.
+ std::array<char, 4096> value;
+ unsigned long long size = member->Size;
+ unsigned long long read = 4096;
+ while (size > 0) {
+ if (size < read)
+ read = size;
+ if (!Fd.Read(value.data(), read, true))
+ return HandleErrors();
+ if (write(outfd, value.data(), read) != (signed long long)read)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+ size -= read;
+ }
+ utimbuf time = {static_cast<time_t>(member->MTime),
+ static_cast<time_t>(member->MTime)};
+ if (utime(outfile,&time) == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+ Py_RETURN_TRUE;
+}
+
+static const char *ararchive_extract_doc =
+ "extract(name: str[, target: str]) -> bool\n\n"
+ "Extract the member given by 'name' into the directory given\n"
+ "by 'target'. If the extraction fails, raise OSError. In case\n"
+ "of success, return True if the file owner could be set or\n"
+ "False if this was not possible. If the requested member\n"
+ "does not exist, raise LookupError.";
+static PyObject *ararchive_extract(PyArArchiveObject *self, PyObject *args)
+{
+ PyApt_Filename name;
+ PyApt_Filename target;
+
+ target = "";
+ if (PyArg_ParseTuple(args, "O&|O&:extract", PyApt_Filename::Converter, &name, PyApt_Filename::Converter, &target) == 0)
+ return 0;
+
+ const ARArchive::Member *member = self->Object->FindMember(name);
+
+ if (!member) {
+ PyErr_Format(PyExc_LookupError,"No member named '%s'",name.path);
+ return 0;
+ }
+ return _extract(self->Fd->Object, member, target);
+}
+
+static const char *ararchive_extractall_doc =
+ "extractall([target: str]) -> bool\n\n"
+ "Extract all archive contents into the directory given by 'target'. If\n"
+ "the extraction fails, raise an error. Otherwise, return True if the\n"
+ "owner could be set or False if the owner could not be changed.";
+
+static PyObject *ararchive_extractall(PyArArchiveObject *self, PyObject *args)
+{
+ PyApt_Filename target;
+ target = "";
+ if (PyArg_ParseTuple(args, "|O&:extractall", PyApt_Filename::Converter, &target) == 0)
+ return 0;
+
+ const ARArchive::Member *member = self->Object->Members();
+
+ do {
+ if (_extract(self->Fd->Object, member, target) == 0)
+ return 0;
+ } while ((member = member->Next));
+ Py_RETURN_TRUE;
+}
+
+static const char *ararchive_gettar_doc =
+ "gettar(name: str, comp: str) -> TarFile\n\n"
+ "Return a TarFile object for the member given by 'name' which will be\n"
+ "decompressed using the compression algorithm given by 'comp'.\n"
+ "This is almost equal to:\n\n"
+ " member = arfile.getmember(name)\n"
+ " tarfile = TarFile(file, member.start, member.size, 'gzip')'\n\n"
+ "It just opens a new TarFile on the given position in the stream.";
+static PyObject *ararchive_gettar(PyArArchiveObject *self, PyObject *args)
+{
+ PyApt_Filename name;
+ const char *comp;
+ if (PyArg_ParseTuple(args, "O&s:gettar", PyApt_Filename::Converter, &name, &comp) == 0)
+ return 0;
+
+ const ARArchive::Member *member = self->Object->FindMember(name);
+ if (!member) {
+ PyErr_Format(PyExc_LookupError,"No member named '%s'",name.path);
+ return 0;
+ }
+
+ PyTarFileObject *tarfile = (PyTarFileObject*)CppPyObject_NEW<ExtractTar*>(self->Fd,&PyTarFile_Type);
+ new (&tarfile->Fd) FileFd(self->Fd->Object.Fd());
+ tarfile->min = member->Start;
+ tarfile->Object = new ExtractTar(self->Fd->Object, member->Size, comp);
+ return HandleErrors(tarfile);
+}
+
+static const char *ararchive_getmembers_doc =
+ "getmembers() -> list\n\n"
+ "Return a list of all members in the archive.";
+static PyObject *ararchive_getmembers(PyArArchiveObject *self)
+{
+ PyObject *list = PyList_New(0);
+ ARArchive::Member *member = self->Object->Members();
+ do {
+ CppPyObject<ARArchive::Member*> *ret;
+ ret = CppPyObject_NEW<ARArchive::Member*>(self,&PyArMember_Type);
+ ret->Object = member;
+ ret->NoDelete = true;
+ PyList_Append(list, ret);
+ Py_DECREF(ret);
+ } while ((member = member->Next));
+ return list;
+}
+
+static const char *ararchive_getnames_doc =
+ "getnames() -> list\n\n"
+ "Return a list of the names of all members in the archive.";
+static PyObject *ararchive_getnames(PyArArchiveObject *self)
+{
+ PyObject *list = PyList_New(0);
+ ARArchive::Member *member = self->Object->Members();
+ do {
+ PyObject *item = CppPyString(member->Name);
+ PyList_Append(list, item);
+ Py_DECREF(item);
+ } while ((member = member->Next));
+ return list;
+}
+
+// Just run getmembers() and return an iterator over the list.
+static PyObject *ararchive_iter(PyArArchiveObject *self) {
+ PyObject *members = ararchive_getmembers(self);
+ PyObject *iter = PyObject_GetIter(members);
+ Py_DECREF(members);
+ return iter;
+}
+
+static PyMethodDef ararchive_methods[] = {
+ {"getmember",(PyCFunction)ararchive_getmember,METH_O,
+ ararchive_getmember_doc},
+ {"gettar",(PyCFunction)ararchive_gettar,METH_VARARGS,
+ ararchive_gettar_doc},
+ {"extractdata",(PyCFunction)ararchive_extractdata,METH_VARARGS,
+ ararchive_extractdata_doc},
+ {"extract",(PyCFunction)ararchive_extract,METH_VARARGS,
+ ararchive_extract_doc},
+ {"extractall",(PyCFunction)ararchive_extractall,METH_VARARGS,
+ ararchive_extractall_doc},
+ {"getmembers",(PyCFunction)ararchive_getmembers,METH_NOARGS,
+ ararchive_getmembers_doc},
+ {"getnames",(PyCFunction)ararchive_getnames,METH_NOARGS,
+ ararchive_getnames_doc},
+ {NULL}
+};
+
+static PyObject *ararchive_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *file;
+ PyApt_Filename filename;
+ int fileno;
+ if (PyArg_ParseTuple(args,"O:__new__",&file) == 0)
+ return 0;
+
+ PyApt_UniqueObject<PyArArchiveObject> self(NULL);
+ // We receive a filename.
+ if (filename.init(file)) {
+ self.reset((PyArArchiveObject*) CppPyObject_NEW<ARArchive*>(0,type));
+ self->Fd = CppPyObject_NEW<FileFd>(NULL, &PyFileFd_Type);
+ new (&self->Fd->Object) FileFd(filename,FileFd::ReadOnly);
+ }
+ // We receive a file object.
+ else if ((fileno = PyObject_AsFileDescriptor(file)) != -1) {
+ // Clear the error set by PyObject_AsString().
+ PyErr_Clear();
+ self.reset((PyArArchiveObject*) CppPyObject_NEW<ARArchive*>(NULL,type));
+ self->Fd = CppPyObject_NEW<FileFd>(file, &PyFileFd_Type);
+ new (&self->Fd->Object) FileFd(fileno,false);
+ }
+ else {
+ return 0;
+ }
+ self->Object = (PyARArchiveHack*)new ARArchive(self->Fd->Object);
+ if (_error->PendingError() == true)
+ return HandleErrors();
+ return self.release();
+}
+
+static int ararchive_traverse(PyObject *_self, visitproc visit, void* arg)
+{
+ PyArArchiveObject *self = (PyArArchiveObject*)_self;
+ Py_VISIT(self->Fd);
+ return CppTraverse<ARArchive*>(self, visit, arg);
+}
+
+static int ararchive_clear(PyObject *_self)
+{
+ PyArArchiveObject *self = (PyArArchiveObject*)_self;
+ Py_CLEAR(self->Fd);
+ return CppClear<ARArchive*>(self);
+}
+
+static void ararchive_dealloc(PyObject *self)
+{
+ ararchive_clear(self);
+ CppDeallocPtr<ARArchive*>(self);
+}
+
+// Return bool or -1 (exception).
+static int ararchive_contains(PyObject *self, PyObject *arg)
+{
+ PyApt_Filename name;
+ if (!name.init(arg))
+ return -1;
+ return (GetCpp<ARArchive*>(self)->FindMember(name) != 0);
+}
+
+static PySequenceMethods ararchive_as_sequence = {
+ 0,0,0,0,0,0,0,ararchive_contains,0,0
+};
+
+static PyMappingMethods ararchive_as_mapping = {
+ 0,(PyCFunction)ararchive_getmember,0
+};
+
+static const char *ararchive_doc =
+ "ArArchive(file: str/int/file)\n\n"
+ "Represent an archive in the 4.4 BSD ar format,\n"
+ "which is used for e.g. deb packages.\n\n"
+ "The parameter 'file' may be a string specifying the path of a file, or\n"
+ "a file-like object providing the fileno() method. It may also be an int\n"
+ "specifying a file descriptor (returned by e.g. os.open()).\n"
+ "The recommended way of using it is to pass in the path to the file.";
+
+PyTypeObject PyArArchive_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.ArArchive", // tp_name
+ sizeof(PyArArchiveObject), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ ararchive_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &ararchive_as_sequence, // tp_as_sequence
+ &ararchive_as_mapping, // 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_HAVE_GC,
+ ararchive_doc, // tp_doc
+ ararchive_traverse, // tp_traverse
+ ararchive_clear, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ (getiterfunc)ararchive_iter, // tp_iter
+ 0, // tp_iternext
+ ararchive_methods, // tp_methods
+ 0, // 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
+ ararchive_new // tp_new
+};
+
+/**
+ * Representation of a Debian package.
+ *
+ * This does not resemble debDebFile in apt-inst, but instead is a subclass
+ * of ArFile which adds properties for the control.tar.$compression and
+ * data.tar.$compression members which return TarFile objects. It also adds
+ * a descriptor 'version' which returns the content of 'debian-binary'.
+ *
+ * We are using it this way as it seems more natural to represent this special
+ * kind of AR archive as an AR archive with some extras.
+ */
+struct PyDebFileObject : PyArArchiveObject {
+ PyObject *data;
+ PyObject *control;
+ PyObject *debian_binary;
+};
+
+static PyObject *debfile_get_data(PyDebFileObject *self)
+{
+ return Py_INCREF(self->data), self->data;
+}
+
+static PyObject *debfile_get_control(PyDebFileObject *self)
+{
+ return Py_INCREF(self->control), self->control;
+}
+
+static PyObject *debfile_get_debian_binary(PyDebFileObject *self)
+{
+ return Py_INCREF(self->debian_binary), self->debian_binary;
+}
+
+static PyObject *_gettar(PyDebFileObject *self, const ARArchive::Member *m,
+ const char *comp)
+{
+ if (!m)
+ return 0;
+ PyTarFileObject *tarfile = (PyTarFileObject*)CppPyObject_NEW<ExtractTar*>(self->Fd,&PyTarFile_Type);
+ new (&tarfile->Fd) FileFd(self->Fd->Object.Fd());
+ tarfile->min = m->Start;
+ tarfile->Object = new ExtractTar(self->Fd->Object, m->Size, comp);
+ return tarfile;
+}
+
+/*
+ * Mostly copy-paste from APT
+ */
+static PyObject *debfile_get_tar(PyDebFileObject *self, const char *Name)
+{
+ // Get the archive member
+ const ARArchive::Member *Member = NULL;
+ const ARArchive &AR = *self->Object;
+ std::string Compressor;
+
+ std::vector<APT::Configuration::Compressor> compressor =
+ APT::Configuration::getCompressors();
+ for (std::vector<APT::Configuration::Compressor>::const_iterator c =
+ compressor.begin(); c != compressor.end(); ++c) {
+ Member = AR.FindMember(std::string(Name).append(c->Extension).c_str());
+ if (Member == NULL)
+ continue;
+ Compressor = c->Name;
+ break;
+ }
+
+ if (Member == NULL)
+ Member = AR.FindMember(std::string(Name).c_str());
+
+ if (Member == NULL) {
+ std::string ext = std::string(Name) + ".{";
+ for (std::vector<APT::Configuration::Compressor>::const_iterator c =
+ compressor.begin(); c != compressor.end(); ++c) {
+ if (!c->Extension.empty())
+ ext.append(c->Extension.substr(1));
+ }
+ ext.append("}");
+ _error->Error(("Internal error, could not locate member %s"),
+ ext.c_str());
+ return HandleErrors();
+ }
+
+ return _gettar(self, Member, Compressor.c_str());
+}
+
+
+static PyObject *debfile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyApt_UniqueObject<PyDebFileObject> self((PyDebFileObject*)ararchive_new(type, args, kwds));
+ if (self == NULL)
+ return NULL;
+
+ // DebFile
+ self->control = debfile_get_tar(self.get(), "control.tar");
+ if (self->control == NULL)
+ return NULL;
+
+ self->data = debfile_get_tar(self.get(), "data.tar");
+ if (self->data == NULL)
+ return NULL;
+
+ const ARArchive::Member *member = self->Object->FindMember("debian-binary");
+ if (!member)
+ return PyErr_Format(PyAptError, "No debian archive, missing %s",
+ "debian-binary");
+
+ if (!self->Fd->Object.Seek(member->Start))
+ return HandleErrors();
+
+ char* value = new char[member->Size];
+ self->Fd->Object.Read(value, member->Size, true);
+ self->debian_binary = PyBytes_FromStringAndSize(value, member->Size);
+ delete[] value;
+ return self.release();
+}
+
+static int debfile_traverse(PyObject *_self, visitproc visit, void* arg)
+{
+ PyDebFileObject *self = (PyDebFileObject*)_self;
+ Py_VISIT(self->data);
+ Py_VISIT(self->control);
+ Py_VISIT(self->debian_binary);
+ return PyArArchive_Type.tp_traverse(self, visit, arg);
+}
+
+static int debfile_clear(PyObject *_self) {
+ PyDebFileObject *self = (PyDebFileObject*)_self;
+ Py_CLEAR(self->data);
+ Py_CLEAR(self->control);
+ Py_CLEAR(self->debian_binary);
+ return PyArArchive_Type.tp_clear(self);
+}
+
+static void debfile_dealloc(PyObject *self) {
+ debfile_clear((PyDebFileObject *)self);
+ PyArArchive_Type.tp_dealloc(self);
+}
+
+static PyGetSetDef debfile_getset[] = {
+ {"control",(getter)debfile_get_control,0,
+ "The TarFile object associated with the control.tar.gz member."},
+ {"data",(getter)debfile_get_data,0,
+ "The TarFile object associated with the data.tar.$compression member. "
+ "All apt compression methods are supported. "
+ },
+ {"debian_binary",(getter)debfile_get_debian_binary,0,
+ "The package version, as contained in debian-binary."},
+ {NULL}
+};
+
+static const char *debfile_doc =
+ "DebFile(file: str/int/file)\n\n"
+ "A DebFile object represents a file in the .deb package format.\n\n"
+ "The parameter 'file' may be a string specifying the path of a file, or\n"
+ "a file-like object providing the fileno() method. It may also be an int\n"
+ "specifying a file descriptor (returned by e.g. os.open()).\n"
+ "The recommended way of using it is to pass in the path to the file.\n\n"
+ "It differs from ArArchive by providing the members 'control', 'data'\n"
+ "and 'version' for accessing the control.tar.gz, data.tar.$compression \n"
+ "(all apt compression methods are supported), and debian-binary members \n"
+ "in the archive.";
+
+PyTypeObject PyDebFile_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.DebFile", // tp_name
+ sizeof(PyDebFileObject), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ debfile_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_HAVE_GC,
+ debfile_doc, // tp_doc
+ debfile_traverse, // tp_traverse
+ debfile_clear, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ debfile_getset, // tp_getset
+ &PyArArchive_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ debfile_new // tp_new
+};
diff --git a/python/cache.cc b/python/cache.cc
new file mode 100644
index 0000000..81bbb96
--- /dev/null
+++ b/python/cache.cc
@@ -0,0 +1,1600 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: cache.cc,v 1.5 2003/06/03 03:03:23 mdz Exp $
+/* ######################################################################
+
+ Cache - Wrapper for the cache related functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/update.h>
+
+#include <Python.h>
+#include "progress.h"
+
+class pkgSourceList;
+
+// 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 *UntranslatedDepTypes[] =
+{
+ "", "Depends","PreDepends","Suggests",
+ "Recommends","Conflicts","Replaces",
+ "Obsoletes", "Breaks", "Enhances"
+};
+
+ /*}}}*/
+
+template<typename T> struct IterListStruct
+{
+ T Iter;
+ unsigned long LastIndex;
+
+ IterListStruct(T const &I) : Iter(I), LastIndex(0) {}
+ IterListStruct() : LastIndex(0) {};
+
+ bool move(unsigned long Index) {
+ if ((unsigned)Index >= Count())
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return false;
+ }
+
+ if ((unsigned)Index < LastIndex)
+ {
+ LastIndex = 0;
+ Iter = Begin();
+ }
+
+ while ((unsigned)Index > LastIndex)
+ {
+ LastIndex++;
+ Iter++;
+ if (Iter.end() == true)
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ virtual unsigned Count() = 0;
+ virtual T Begin() = 0;
+
+};
+
+struct PkgListStruct : public IterListStruct<pkgCache::PkgIterator> {
+ unsigned Count() { return Iter.Cache()->HeaderP->PackageCount; }
+ pkgCache::PkgIterator Begin() { return Iter.Cache()->PkgBegin(); }
+
+ PkgListStruct(pkgCache::PkgIterator const &I) { Iter = I; }
+};
+
+struct GrpListStruct : public IterListStruct<pkgCache::GrpIterator> {
+ unsigned Count() { return Iter.Cache()->HeaderP->GroupCount; }
+ pkgCache::GrpIterator Begin() { return Iter.Cache()->GrpBegin(); }
+ GrpListStruct(pkgCache::GrpIterator const &I) { Iter = I; }
+};
+
+struct RDepListStruct
+{
+ pkgCache::DepIterator Iter;
+ pkgCache::DepIterator Start;
+ unsigned long LastIndex;
+ unsigned long Len;
+
+ RDepListStruct(pkgCache::DepIterator const &I) : Iter(I), Start(I),
+ LastIndex(0)
+ {
+ Len = 0;
+ pkgCache::DepIterator D = I;
+ for (; D.end() == false; D++)
+ Len++;
+ }
+ RDepListStruct() {abort();}; // G++ Bug..
+};
+
+static PyObject *CreateProvides(PyObject *Owner,pkgCache::PrvIterator I)
+{
+ PyObject *List = PyList_New(0);
+ for (; I.end() == false; I++)
+ {
+ PyObject *Obj;
+ PyObject *Ver;
+ Ver = CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,
+ I.OwnerVer());
+ Obj = Py_BuildValue("ssN",I.ParentPkg().Name(),I.ProvideVersion(),
+ Ver);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+// Cache Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static const char *cache_update_doc =
+ "update(progress, sources: SourceList, pulse_interval: int) -> bool\n\n"
+ "Update the index files used by the cache. A call to this method\n"
+ "does not affect the current Cache object; instead, a new one\n"
+ "should be created in order to use the changed index files.\n\n"
+ "The parameter 'progress' can be used to specify an\n"
+ "apt.progress.base.AcquireProgress() object , which will report\n"
+ "progress information while the index files are being fetched.\n"
+ "The parameter 'sources', if provided, is an apt_pkg.SourcesList\n"
+ "object listing the remote repositories to be used.\n"
+ "The 'pulse_interval' parameter indicates how long (in microseconds)\n"
+ "to wait between calls to the pulse() method of the 'progress' object.\n"
+ "The default is 500000 microseconds.";
+static PyObject *PkgCacheUpdate(PyObject *Self,PyObject *Args)
+{
+ PyObject *pyFetchProgressInst = 0;
+ PyObject *pySourcesList = 0;
+ int pulseInterval = 0;
+ if (PyArg_ParseTuple(Args, "OO!|i", &pyFetchProgressInst,
+ &PySourceList_Type, &pySourcesList, &pulseInterval) == 0)
+ return 0;
+
+ PyFetchProgress progress;
+ progress.setCallbackInst(pyFetchProgressInst);
+ pkgSourceList *source = GetCpp<pkgSourceList*>(pySourcesList);
+ bool res = ListUpdate(progress, *source, pulseInterval);
+
+ PyObject *PyRes = PyBool_FromLong(res);
+ return HandleErrors(PyRes);
+}
+
+
+static PyMethodDef PkgCacheMethods[] =
+{
+ {"update",PkgCacheUpdate,METH_VARARGS,cache_update_doc},
+ {}
+};
+
+static PyObject *PkgCacheGetGroupCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->GroupCount);
+}
+
+static PyObject *PkgCacheGetGroups(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return CppPyObject_NEW<GrpListStruct>(Self,&PyGroupList_Type,Cache->GrpBegin());
+}
+
+static PyObject *PkgCacheGetPolicy(PyObject *Self, void*) {
+ PyObject *CacheFilePy = GetOwner<pkgCache*>(Self);
+ pkgCacheFile *CacheF = GetCpp<pkgCacheFile*>(CacheFilePy);
+ pkgDepCache *DepCache = (pkgDepCache *)(*CacheF);
+
+ pkgPolicy *Policy = (pkgPolicy *)&DepCache->GetPolicy();
+ CppPyObject<pkgPolicy*> *PyPolicy =
+ CppPyObject_NEW<pkgPolicy*>(Self,&PyPolicy_Type,Policy);
+ // Policy should not be deleted, it is managed by CacheFile.
+ PyPolicy->NoDelete = true;
+ return PyPolicy;
+}
+
+static PyObject *PkgCacheGetPackages(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return CppPyObject_NEW<PkgListStruct>(Self,&PyPackageList_Type,Cache->PkgBegin());
+}
+
+static PyObject *PkgCacheGetPackageCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber((int)Cache->HeaderP->PackageCount);
+}
+
+static PyObject *PkgCacheGetVersionCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->VersionCount);
+}
+static PyObject *PkgCacheGetDependsCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->DependsCount);
+}
+
+static PyObject *PkgCacheGetPackageFileCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->PackageFileCount);
+}
+
+static PyObject *PkgCacheGetVerFileCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->VerFileCount);
+}
+
+static PyObject *PkgCacheGetProvidesCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->ProvidesCount);
+}
+
+static PyObject *PkgCacheGetFileList(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ PyObject *List = PyList_New(0);
+ for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I.end() == false; I++)
+ {
+ PyObject *Obj;
+ Obj = CppPyObject_NEW<pkgCache::PkgFileIterator>(Self,&PyPackageFile_Type,I);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyObject *PkgCacheGetIsMultiArch(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return PyBool_FromLong(Cache->MultiArchCache());
+}
+
+static PyGetSetDef PkgCacheGetSet[] = {
+ {"depends_count",PkgCacheGetDependsCount,0,
+ "The number of apt_pkg.Dependency objects stored in the cache."},
+ {"file_list",PkgCacheGetFileList,0,
+ "A list of apt_pkg.PackageFile objects stored in the cache."},
+ {"group_count",PkgCacheGetGroupCount,0,
+ "The number of apt_pkg.Group objects stored in the cache."},
+ {"groups", PkgCacheGetGroups, 0, "A list of Group objects in the cache"},
+ {"policy", PkgCacheGetPolicy, 0, "The PkgPolicy for the cache"},
+ {"is_multi_arch", PkgCacheGetIsMultiArch, 0,
+ "Whether the cache supports multi-arch."},
+ {"package_count",PkgCacheGetPackageCount,0,
+ "The number of apt_pkg.Package objects stored in the cache."},
+ {"package_file_count",PkgCacheGetPackageFileCount,0,
+ "The number of apt_pkg.PackageFile objects stored in the cache."},
+ {"packages",PkgCacheGetPackages,0,
+ "A list of apt_pkg.Package objects stored in the cache."},
+ {"provides_count",PkgCacheGetProvidesCount,0,
+ "Number of Provides relations described in the cache."},
+ {"ver_file_count",PkgCacheGetVerFileCount,0,
+ "The number of (Version, PackageFile) relations."},
+ {"version_count",PkgCacheGetVersionCount,0,
+ "The number of apt_pkg.Version objects stored in the cache."},
+ {}
+};
+
+// Helper to call FindPkg(name) or FindPkg(name, architecture)
+static pkgCache::PkgIterator CacheFindPkg(PyObject *self, PyObject *arg)
+{
+ const char *name;
+ const char *architecture;
+ pkgCache *cache = GetCpp<pkgCache *>(self);
+
+ name = PyObject_AsString(arg);
+
+ if (name != NULL)
+ return cache->FindPkg(name);
+
+ PyErr_Clear();
+
+ if (PyArg_ParseTuple(arg, "ss", &name, &architecture) == 0) {
+ PyErr_Clear();
+ PyErr_Format(PyExc_TypeError, "Expected a string or a pair of strings");
+ return pkgCache::PkgIterator();
+ }
+
+ return cache->FindPkg(name, architecture);
+}
+
+// Map access, operator []
+static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg)
+{
+ pkgCache::PkgIterator Pkg = CacheFindPkg(Self, Arg);
+ if (Pkg.end() == true)
+ {
+ if (!PyErr_Occurred())
+ PyErr_SetObject(PyExc_KeyError,Arg);
+ return 0;
+ }
+
+ return CppPyObject_NEW<pkgCache::PkgIterator>(Self,&PyPackage_Type,Pkg);
+}
+
+// Check whether the cache contains a package with a given name.
+static int CacheContains(PyObject *Self,PyObject *Arg)
+{
+ bool res = (CacheFindPkg(Self, Arg).end() == false);
+ PyErr_Clear();
+ return res;
+}
+
+static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *pyCallbackInst = 0;
+ char *kwlist[] = {"progress", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, "|O", kwlist,
+ &pyCallbackInst) == 0)
+ return 0;
+
+ if (_system == 0) {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+
+ pkgCacheFile *Cache = new pkgCacheFile();
+
+ if (pyCallbackInst == Py_None) {
+ OpProgress Prog;
+ if (Cache->Open(&Prog,false) == false)
+ return HandleErrors();
+ } else if(pyCallbackInst != 0) {
+ // sanity check for the progress object, see #497049
+ if (PyObject_HasAttrString(pyCallbackInst, "done") != true) {
+ PyErr_SetString(PyExc_ValueError,
+ "OpProgress object must implement done()");
+ return 0;
+ }
+ if (PyObject_HasAttrString(pyCallbackInst, "update") != true) {
+ PyErr_SetString(PyExc_ValueError,
+ "OpProgress object must implement update()");
+ return 0;
+ }
+ PyOpProgress progress;
+ progress.setCallbackInst(pyCallbackInst);
+ if (Cache->Open(&progress,false) == false)
+ return HandleErrors();
+ }
+ else {
+ OpTextProgress Prog;
+ if (Cache->Open(&Prog,false) == false)
+ return HandleErrors();
+ }
+
+ // ensure that the states are correct (LP: #659438)
+ pkgApplyStatus(*Cache);
+
+ CppPyObject<pkgCacheFile*> *CacheFileObj =
+ CppPyObject_NEW<pkgCacheFile*>(0,&PyCacheFile_Type, Cache);
+
+ CppPyObject<pkgCache *> *CacheObj =
+ CppPyObject_NEW<pkgCache *>(CacheFileObj,type,
+ (pkgCache *)(*Cache));
+
+ // Do not delete the pointer to the pkgCache, it is managed by pkgCacheFile.
+ CacheObj->NoDelete = true;
+ Py_DECREF(CacheFileObj);
+ return CacheObj;
+}
+
+static Py_ssize_t CacheMapLen(PyObject *Self)
+{
+ return GetCpp<pkgCache*>(Self)->HeaderP->PackageCount;
+}
+
+static char *doc_PkgCache = "Cache([progress]) -> Cache() object.\n\n"
+ "The APT cache file contains a hash table mapping names of binary\n"
+ "packages to their metadata. A Cache object is the in-core\n"
+ "representation of the same. It provides access to APT’s idea of the\n"
+ "list of available packages.\n"
+ "The optional parameter *progress* can be used to specify an \n"
+ "apt.progress.base.OpProgress() object (or similar) which reports\n"
+ "progress information while the cache is being opened. If this\n"
+ "parameter is not supplied, the progress will be reported in simple,\n"
+ "human-readable text to standard output. If it is None, no output\n"
+ "will be made.\n\n"
+ "The cache can be used like a mapping from package names to Package\n"
+ "objects (although only getting items is supported). Instead of a name,\n"
+ "a tuple of a name and an architecture may be used.";
+static PySequenceMethods CacheSeq = {0,0,0,0,0,0,0,CacheContains,0,0};
+static PyMappingMethods CacheMap = {CacheMapLen,CacheMapOp,0};
+PyTypeObject PyCache_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Cache", // tp_name
+ sizeof(CppPyObject<pkgCache *>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgCache *>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &CacheSeq, // tp_as_sequence
+ &CacheMap, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ doc_PkgCache, // tp_doc
+ CppTraverse<pkgCache *>, // tp_traverse
+ CppClear<pkgCache *>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgCacheMethods, // tp_methods
+ 0, // tp_members
+ PkgCacheGetSet, // 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
+ PkgCacheNew, // tp_new
+};
+ /*}}}*/
+// PkgCacheFile Class /*{{{*/
+// ---------------------------------------------------------------------
+PyTypeObject PyCacheFile_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "pkgCacheFile", // tp_name
+ sizeof(CppPyObject<pkgCacheFile*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgCacheFile*>, // 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
+};
+
+// Package List Class /*{{{*/
+// ---------------------------------------------------------------------
+static Py_ssize_t PkgListLen(PyObject *Self)
+{
+ return GetCpp<PkgListStruct>(Self).Iter.Cache()->HeaderP->PackageCount;
+}
+
+static PyObject *PkgListItem(PyObject *iSelf,Py_ssize_t Index)
+{
+ PkgListStruct &Self = GetCpp<PkgListStruct>(iSelf);
+
+ if (!Self.move(Index))
+ return 0;
+ return CppPyObject_NEW<pkgCache::PkgIterator>(GetOwner<PkgListStruct>(iSelf),&PyPackage_Type,
+ Self.Iter);
+}
+
+static PySequenceMethods PkgListSeq =
+{
+ PkgListLen,
+ 0, // concat
+ 0, // repeat
+ PkgListItem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+static const char *packagelist_doc =
+ "A PackageList is an internally used structure to represent\n"
+ "the 'packages' attribute of apt_pkg.Cache objects in a more\n"
+ "efficient manner by creating Package objects only when they\n"
+ "are accessed.";
+
+PyTypeObject PyPackageList_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.PackageList", // tp_name
+ sizeof(CppPyObject<PkgListStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<PkgListStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &PkgListSeq, // 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 | Py_TPFLAGS_HAVE_GC, // tp_flags
+ packagelist_doc, // tp_doc
+ CppTraverse<PkgListStruct>, // tp_traverse
+ CppClear<PkgListStruct>, // tp_clear
+};
+
+/* The same for groups */
+static Py_ssize_t GrpListLen(PyObject *Self)
+{
+ return GetCpp<GrpListStruct>(Self).Iter.Cache()->HeaderP->GroupCount;
+}
+
+static PyObject *GrpListItem(PyObject *iSelf,Py_ssize_t Index)
+{
+ GrpListStruct &Self = GetCpp<GrpListStruct>(iSelf);
+
+ if (!Self.move(Index))
+ return 0;
+ return CppPyObject_NEW<pkgCache::GrpIterator>(GetOwner<GrpListStruct>(iSelf),&PyGroup_Type,
+ Self.Iter);
+}
+
+static PySequenceMethods GrpListSeq =
+{
+ GrpListLen,
+ 0, // concat
+ 0, // repeat
+ GrpListItem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+static const char *grouplist_doc =
+ "A GroupList is an internally used structure to represent\n"
+ "the 'groups' attribute of apt_pkg.Cache objects in a more\n"
+ "efficient manner by creating Group objects only when they\n"
+ "are accessed.";
+
+PyTypeObject PyGroupList_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.GroupList", // tp_name
+ sizeof(CppPyObject<GrpListStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<GrpListStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &GrpListSeq, // 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 | Py_TPFLAGS_HAVE_GC, // tp_flags
+ grouplist_doc, // tp_doc
+ CppTraverse<GrpListStruct>, // tp_traverse
+ CppClear<GrpListStruct>, // tp_clear
+};
+
+
+#define Owner (GetOwner<pkgCache::PkgIterator>(Self))
+#define MkGet(PyFunc,Ret) static PyObject *PyFunc(PyObject *Self,void*) \
+{ \
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); \
+ return Ret; \
+}
+
+MkGet(PackageGetName,CppPyString(Pkg.Name()))
+MkGet(PackageGetArch,CppPyString(Pkg.Arch()))
+MkGet(PackageGetRevDependsList,CppPyObject_NEW<RDepListStruct>(Owner,
+ &PyDependencyList_Type, Pkg.RevDependsList()))
+MkGet(PackageGetProvidesList,CreateProvides(Owner,Pkg.ProvidesList()))
+MkGet(PackageGetSelectedState,MkPyNumber(Pkg->SelectedState))
+MkGet(PackageGetInstState,MkPyNumber(Pkg->InstState))
+MkGet(PackageGetCurrentState,MkPyNumber(Pkg->CurrentState))
+MkGet(PackageGetID,MkPyNumber(Pkg->ID))
+#
+MkGet(PackageGetEssential,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Essential) != 0))
+MkGet(PackageGetImportant,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Important) != 0))
+#undef MkGet
+#undef Owner
+
+static const char PackageGetFullName_doc[] =
+ "get_fullname([pretty: bool = False]) -> str\n\n"
+ "Get the full name of the package, including the architecture. If\n"
+ "'pretty' is True, the architecture is omitted for native packages,\n"
+ "that is, and amd64 apt package on an amd64 system would give 'apt'.";
+static PyObject *PackageGetFullName(PyObject *Self,PyObject *Args,PyObject *kwds)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ char pretty = 0;
+ char *kwlist[] = {"pretty", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, "|b", kwlist,
+ &pretty) == 0)
+ return 0;
+
+
+ return CppPyString(Pkg.FullName(pretty));
+}
+
+static PyObject *PackageGetVersionList(PyObject *Self,void*)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self);
+
+ PyObject *List = PyList_New(0);
+ for (pkgCache::VerIterator I = Pkg.VersionList(); I.end() == false; I++)
+ {
+ PyObject *Obj;
+ Obj = CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,I);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyObject *PackageGetHasVersions(PyObject *Self,void*)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ return PyBool_FromLong(Pkg.VersionList().end() == false);
+}
+
+static PyObject *PackageGetHasProvides(PyObject *Self,void*)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ return PyBool_FromLong(Pkg.ProvidesList().end() == false);
+}
+
+static PyObject *PackageGetCurrentVer(PyObject *Self,void*)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self);
+ if (Pkg->CurrentVer == 0)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,
+ Pkg.CurrentVer());
+}
+
+
+static PyMethodDef PackageMethods[] =
+{
+ {"get_fullname",(PyCFunction)PackageGetFullName,METH_VARARGS|METH_KEYWORDS,
+ PackageGetFullName_doc},
+ {}
+};
+
+static PyGetSetDef PackageGetSet[] = {
+ {"name",PackageGetName,0,
+ "The name of the package."},
+ {"architecture",PackageGetArch,0, "The architecture of the package."},
+ {"rev_depends_list",PackageGetRevDependsList,0,
+ "An apt_pkg.DependencyList object of all reverse dependencies."},
+ {"provides_list",PackageGetProvidesList,0,
+ "A list of all packages providing this package. The list contains\n"
+ "tuples in the format (providesname, providesver, version)\n"
+ "where 'version' is an apt_pkg.Version object."},
+ {"selected_state",PackageGetSelectedState,0,
+ "The state of the selection, which can be compared against the constants\n"
+ "SELSTATE_DEINSTALL, SELSTATE_HOLD, SELSTATE_INSTALL, SELSTATE_PURGE,\n"
+ "SELSTATE_UNKNOWN of the apt_pkg module."},
+ {"inst_state",PackageGetInstState,0,
+ "The state of the install, which be compared against the constants\n"
+ "INSTSTATE_HOLD, INSTSTATE_HOLD_REINSTREQ, INSTSTATE_OK,\n"
+ "INSTSTATE_REINSTREQ of the apt_pkg module."},
+ {"current_state",PackageGetCurrentState,0,
+ "The current state, which can be compared against the constants\n"
+ "CURSTATE_CONFIG_FILES, CURSTATE_HALF_CONFIGURED,\n"
+ "CURSTATE_HALF_INSTALLED, CURSTATE_INSTALLED, CURSTATE_NOT_INSTALLED,\n"
+ "CURSTATE_UNPACKED of the apt_pkg module."},
+ {"id",PackageGetID,0,
+ "The numeric ID of the package"},
+ {"essential",PackageGetEssential,0,
+ "Boolean value determining whether the package is essential."},
+ {"important",PackageGetImportant,0,
+ "Boolean value determining whether the package has the 'important'\n"
+ "flag set ('Important: yes' in the Packages file). No longer used."},
+ {"version_list",PackageGetVersionList,0,
+ "A list of all apt_pkg.Version objects for this package."},
+ {"current_ver",PackageGetCurrentVer,0,
+ "The version of the package currently installed or None."},
+ {"has_versions",PackageGetHasVersions,0,
+ "Whether the package has at least one version in the cache."},
+ {"has_provides",PackageGetHasProvides,0,
+ "Whether the package is provided by at least one other package."},
+ {}
+};
+
+static PyObject *PackageRepr(PyObject *Self)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ return PyString_FromFormat("<%s object: name:'%s' id:%u>", Self->ob_type->tp_name,
+ Pkg.Name(), Pkg->ID);
+}
+
+static const char *package_doc =
+ "Represent a package. A package is uniquely identified by its name\n"
+ "and each package can have zero or more versions which can be\n"
+ "accessed via the version_list property. Packages can be installed\n"
+ "and removed by apt_pkg.DepCache.";
+
+PyTypeObject PyPackage_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Package", // tp_name
+ sizeof(CppPyObject<pkgCache::PkgIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::PkgIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ PackageRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ package_doc, // tp_doc
+ CppTraverse<pkgCache::PkgIterator>, // tp_traverse
+ CppClear<pkgCache::PkgIterator>,// tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PackageMethods, // tp_methods
+ 0, // tp_members
+ PackageGetSet, // tp_getset
+};
+
+#define Description_MkGet(PyFunc,Ret) static PyObject \
+ *PyFunc(PyObject *Self,void*) { \
+ pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); \
+ return Ret; }
+
+Description_MkGet(DescriptionGetLanguageCode,
+ CppPyString(Desc.LanguageCode()))
+Description_MkGet(DescriptionGetMd5,CppPyString(Desc.md5()))
+#undef Description_MkGet
+
+static PyObject *DescriptionGetFileList(PyObject *Self,void*)
+{
+ pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DescIterator>(Self);
+
+ /* The second value in the tuple is the index of the VF item. If the
+ user wants to request a lookup then that number will be used.
+ Maybe later it can become an object. */
+ PyObject *List = PyList_New(0);
+ for (pkgCache::DescFileIterator I = Desc.FileList(); I.end() == false; I++)
+ {
+ PyObject *DescFile;
+ PyObject *Obj;
+ DescFile = CppPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File());
+ Obj = Py_BuildValue("NN",DescFile,MkPyNumber(I.Index()));
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyGetSetDef DescriptionGetSet[] = {
+ {"language_code",DescriptionGetLanguageCode,0,
+ "The language code of the description. Empty string for untranslated\n"
+ "descriptions."},
+ {"md5",DescriptionGetMd5,0,
+ "The MD5 hash of the description."},
+ {"file_list",DescriptionGetFileList,0,
+ "A list of all apt_pkg.PackageFile objects related to this description."},
+ {}
+};
+
+static PyObject *DescriptionRepr(PyObject *Self)
+{
+ pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self);
+ return PyString_FromFormat("<%s object: language_code:'%s' md5:'%s' ",
+ Self->ob_type->tp_name, Desc.LanguageCode(),
+ Desc.md5());
+}
+
+static const char *description_doc =
+ "Represent a package description and some attributes. Needed for\n"
+ "things like translated descriptions.";
+
+PyTypeObject PyDescription_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Description", // tp_name
+ sizeof(CppPyObject<pkgCache::DescIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::DescIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ DescriptionRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ description_doc, // tp_doc
+ CppTraverse<pkgCache::DescIterator>, // tp_traverse
+ CppClear<pkgCache::DescIterator>,// tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ DescriptionGetSet, // tp_getset
+};
+ /*}}}*/
+// Version Class /*{{{*/
+// ---------------------------------------------------------------------
+
+/* This is the simple depends result, the elements are split like
+ ParseDepends does */
+static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver,
+ bool AsObj)
+{
+ PyObject *Dict = PyDict_New();
+ PyObject *LastDep = 0;
+ unsigned LastDepType = 0;
+ for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
+ {
+ pkgCache::DepIterator Start;
+ pkgCache::DepIterator End;
+ D.GlobOr(Start,End);
+
+ // Switch/create a new dict entry
+ if (LastDepType != Start->Type || LastDep != 0)
+ {
+ PyObject *Dep = CppPyString(UntranslatedDepTypes[Start->Type]);
+ LastDepType = Start->Type;
+ LastDep = PyDict_GetItem(Dict,Dep);
+ if (LastDep == 0)
+ {
+ LastDep = PyList_New(0);
+ PyDict_SetItem(Dict,Dep,LastDep);
+ Py_DECREF(LastDep);
+ }
+ Py_DECREF(Dep);
+ }
+
+ PyObject *OrGroup = PyList_New(0);
+ while (1)
+ {
+ PyObject *Obj;
+ if (AsObj == true)
+ Obj = CppPyObject_NEW<pkgCache::DepIterator>(Owner,&PyDependency_Type,
+ Start);
+ else
+ {
+ if (Start->Version == 0)
+ Obj = Py_BuildValue("sss",
+ Start.TargetPkg().Name(),
+ "",
+ Start.CompType());
+ else
+ Obj = Py_BuildValue("sss",
+ Start.TargetPkg().Name(),
+ Start.TargetVer(),
+ Start.CompType());
+ }
+ PyList_Append(OrGroup,Obj);
+ Py_DECREF(Obj);
+
+ if (Start == End)
+ break;
+ Start++;
+ }
+
+ PyList_Append(LastDep,OrGroup);
+ Py_DECREF(OrGroup);
+ }
+
+ return Dict;
+}
+
+static inline pkgCache::VerIterator Version_GetVer(PyObject *Self) {
+ return GetCpp<pkgCache::VerIterator>(Self);
+}
+
+// Version attributes.
+static PyObject *VersionGetVerStr(PyObject *Self, void*) {
+ return CppPyString(Version_GetVer(Self).VerStr());
+}
+static PyObject *VersionGetSection(PyObject *Self, void*) {
+ return CppPyString(Version_GetVer(Self).Section());
+}
+static PyObject *VersionGetArch(PyObject *Self, void*) {
+ return CppPyString(Version_GetVer(Self).Arch());
+}
+static PyObject *VersionGetFileList(PyObject *Self, void*) {
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ PyObject *List = PyList_New(0);
+ for (pkgCache::VerFileIterator I = Ver.FileList(); I.end() == false; I++)
+ {
+ PyObject *PkgFile;
+ PyObject *Obj;
+ PkgFile = CppPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File());
+ Obj = Py_BuildValue("NN",PkgFile,MkPyNumber(I.Index()));
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyObject *VersionGetDependsListStr(PyObject *Self, void*) {
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return MakeDepends(Owner,Ver,false);
+}
+static PyObject *VersionGetDependsList(PyObject *Self, void*) {
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return MakeDepends(Owner,Ver,true);
+}
+static PyObject *VersionGetParentPkg(PyObject *Self, void*) {
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return CppPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type,
+ Version_GetVer(Self).ParentPkg());
+}
+static PyObject *VersionGetProvidesList(PyObject *Self, void*) {
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return CreateProvides(Owner,Version_GetVer(Self).ProvidesList());
+}
+static PyObject *VersionGetSize(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->Size);
+}
+static PyObject *VersionGetInstalledSize(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->InstalledSize);
+}
+static PyObject *VersionGetHash(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->Hash);
+}
+static PyObject *VersionGetID(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->ID);
+}
+static PyObject *VersionGetPriority(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->Priority);
+}
+static PyObject *VersionGetPriorityStr(PyObject *Self, void*) {
+ return CppPyString(Version_GetVer(Self).PriorityType());
+}
+static PyObject *VersionGetDownloadable(PyObject *Self, void*) {
+ return PyBool_FromLong(Version_GetVer(Self).Downloadable());
+}
+static PyObject *VersionGetTranslatedDescription(PyObject *Self, void*) {
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return CppPyObject_NEW<pkgCache::DescIterator>(Owner,
+ &PyDescription_Type,
+ Ver.TranslatedDescription());
+}
+
+static PyObject *VersionGetIsSecurityUpdate(PyObject *Self, void*) {
+ return PyBool_FromLong(Version_GetVer(Self).IsSecurityUpdate());
+}
+
+static PyObject *VersionGetMultiArch(PyObject *Self, void*)
+{
+ return MkPyNumber(Version_GetVer(Self)->MultiArch);
+}
+
+#if 0 // FIXME: enable once pkgSourceList is stored somewhere
+static PyObject *VersionGetIsTrusted(PyObject *Self, void*) {
+ else if (strcmp("IsTrusted", Name) == 0)
+ {
+ pkgSourceList Sources;
+ Sources.ReadMainList();
+ for(pkgCache::VerFileIterator i = Ver.FileList(); !i.end(); i++)
+ {
+ pkgIndexFile *index;
+ if(Sources.FindIndex(i.File(), index) && !index->IsTrusted())
+ Py_RETURN_FALSE;
+ }
+ Py_RETURN_TRUE;
+ }
+}
+#endif
+
+#define NOTNULL(x) (x ? x : "")
+
+static PyObject *VersionRepr(PyObject *Self)
+{
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ return PyString_FromFormat("<%s object: Pkg:'%s' Ver:'%s' Section:'%s' "
+ " Arch:'%s' Size:%lu ISize:%lu Hash:%u ID:%u "
+ "Priority:%u>", Self->ob_type->tp_name,
+ Ver.ParentPkg().Name(), Ver.VerStr(),
+ NOTNULL(Ver.Section()), NOTNULL(Ver.Arch()),
+ (unsigned long)Ver->Size,
+ (unsigned long)Ver->InstalledSize,
+ Ver->Hash, Ver->ID, Ver->Priority);
+}
+#undef NOTNULL
+
+static PyObject *version_richcompare(PyObject *obj1, PyObject *obj2, int op)
+{
+ if (!PyVersion_Check(obj2))
+ return Py_INCREF(Py_NotImplemented), Py_NotImplemented;
+
+ const pkgCache::VerIterator &a = GetCpp<pkgCache::VerIterator>(obj1);
+ const pkgCache::VerIterator &b = GetCpp<pkgCache::VerIterator>(obj2);
+ const int comparison = _system->VS->CmpVersion(a.VerStr(), b.VerStr());
+ switch (op) {
+ case Py_LT: return PyBool_FromLong(comparison < 0);
+ case Py_LE: return PyBool_FromLong(comparison <= 0);
+ case Py_EQ: return PyBool_FromLong(comparison == 0);
+ case Py_NE: return PyBool_FromLong(comparison != 0);
+ case Py_GE: return PyBool_FromLong(comparison >= 0);
+ case Py_GT: return PyBool_FromLong(comparison > 0);
+ default: return NULL; // should not happen.
+ }
+}
+
+static PyGetSetDef VersionGetSet[] = {
+ {"arch",VersionGetArch,0,
+ "The architecture of this specific version of the package."},
+ {"depends_list",VersionGetDependsList,0,
+ "A dictionary mapping dependency types to lists (A) of lists (B) of\n"
+ "apt_pkg.Dependency objects. The lists (B) represent or dependencies\n"
+ "like 'a || b'."},
+ {"depends_list_str",VersionGetDependsListStr,0,
+ "Same as depends_list, except that the apt_pkg.Dependency objects\n"
+ "are 3-tuples of the form (name, version, operator); where operator\n"
+ "is one of '<', '<=', '=', '>=', '>'."},
+ {"downloadable",VersionGetDownloadable,0,
+ "Whether the version can be downloaded."},
+ {"file_list",VersionGetFileList,0,
+ "A list of tuples (packagefile: apt_pkg.PackageFile, index: int) for the\n"
+ "PackageFile objects related to this package. The index can be used\n"
+ "to retrieve the record of this package version."},
+ {"hash",VersionGetHash,0,
+ "The numeric hash of the version used in the internal storage."},
+ {"id",VersionGetID,0,
+ "The numeric ID of the package."},
+ {"installed_size",VersionGetInstalledSize,0,
+ "The installed size of this package version."},
+ {"multi_arch",VersionGetMultiArch,0,
+ "Multi-arch state of this package, as an integer. See\n"
+ "the various MULTI_ARCH_* members."},
+ {"parent_pkg",VersionGetParentPkg,0,
+ "The parent package of this version."},
+ {"priority",VersionGetPriority,0,
+ "The priority of the package as an integer, which can be compared to\n"
+ "the constants PRI_EXTRA, PRI_IMPORTANT, PRI_OPTIONAL, PRI_REQUIRED,\n"
+ "PRI_STANDARD of the apt_pkg module."},
+ {"priority_str",VersionGetPriorityStr,0,
+ "The priority of the package, as a string."},
+ {"provides_list",VersionGetProvidesList,0,
+ "A list of all packages provided by this version. The list contains\n"
+ "tuples in the format (providesname, providesver, version)\n"
+ "where 'version' is an apt_pkg.Version object."},
+ {"section",VersionGetSection,0,
+ "The section of this package version."},
+ {"size",VersionGetSize,0,
+ "The size of the package file."},
+ {"translated_description",VersionGetTranslatedDescription,0,
+ "An apt_pkg.Description object for the translated description if\n"
+ "available or the untranslated fallback."},
+ {"is_security_update",VersionGetIsSecurityUpdate,0,
+ "Whether this version is a security update."},
+ {"ver_str",VersionGetVerStr,0,
+ "The version string."},
+ {}
+};
+
+PyTypeObject PyVersion_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Version", // tp_name
+ sizeof(CppPyObject<pkgCache::VerIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::VerIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ VersionRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ "Version Object", // tp_doc
+ CppTraverse<pkgCache::VerIterator>, // tp_traverse
+ CppClear<pkgCache::VerIterator>,// tp_clear
+ version_richcompare, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ VersionGetSet, // tp_getset
+};
+
+ /*}}}*/
+
+// PackageFile Class /*{{{*/
+// ---------------------------------------------------------------------
+static PyObject *PackageFile_GetFileName(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyPath(File.FileName());
+}
+
+static PyObject *PackageFile_GetArchive(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Archive());
+}
+
+static PyObject *PackageFile_GetComponent(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Component());
+}
+
+static PyObject *PackageFile_GetVersion(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Version());
+}
+
+static PyObject *PackageFile_GetOrigin(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Origin());
+}
+
+static PyObject *PackageFile_GetLabel(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Label());
+}
+
+static PyObject *PackageFile_GetArchitecture(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Architecture());
+}
+
+static PyObject *PackageFile_GetCodename(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Codename());
+}
+
+static PyObject *PackageFile_GetSite(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Site());
+}
+
+static PyObject *PackageFile_GetIndexType(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.IndexType());
+}
+static PyObject *PackageFile_GetSize(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return MkPyNumber(File->Size);
+}
+
+static PyObject *PackageFile_GetNotSource(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return PyBool_FromLong((File->Flags & pkgCache::Flag::NotSource) != 0);
+}
+static PyObject *PackageFile_GetNotAutomatic(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return PyBool_FromLong((File->Flags & pkgCache::Flag::NotAutomatic) != 0);
+}
+
+static PyObject *PackageFile_GetID(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return MkPyNumber(File->ID);
+}
+
+#define S(s) (s == NULL ? "" : s)
+static PyObject *PackageFileRepr(PyObject *Self)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+
+ return PyString_FromFormat("<%s object: filename:'%s'"
+ " a=%s,c=%s,v=%s,o=%s,l=%s arch='%s' site='%s'"
+ " IndexType='%s' Size=%lu ID:%u>",
+ Self->ob_type->tp_name, File.FileName(),
+ S(File.Archive()),
+ S(File.Component()),S(File.Version()),
+ S(File.Origin()),S(File.Label()),
+ S(File.Architecture()),S(File.Site()),
+ S(File.IndexType()),File->Size,File->ID);
+}
+#undef S
+
+static PyGetSetDef PackageFileGetSet[] = {
+ {"architecture",PackageFile_GetArchitecture,0,
+ "The architecture of the package file. Unused, empty string nowadays."},
+ {"archive",PackageFile_GetArchive,0,
+ "The archive of the package file (i.e. 'Suite' in the Release file)."},
+ {"component",PackageFile_GetComponent,0,
+ "The component of this package file (e.g. 'main')."},
+ {"codename",PackageFile_GetCodename,0,
+ "The codename of this package file (e.g. squeeze-updates)."},
+ {"filename",PackageFile_GetFileName,0,
+ "The path to the file."},
+ {"id",PackageFile_GetID,0,
+ "The numeric ID of this PackageFile object."},
+ {"index_type",PackageFile_GetIndexType,0,
+ "A string describing the type of index. Known values are\n"
+ "'Debian Package Index', 'Debian Translation Index', and\n"
+ "'Debian dpkg status file'."},
+ {"label",PackageFile_GetLabel,0,
+ "The label set in the release file (e.g. 'Debian')."},
+ {"not_automatic",PackageFile_GetNotAutomatic,0,
+ "Whether the NotAutomatic flag is set in the Release file."},
+ {"not_source",PackageFile_GetNotSource,0,
+ "Whether this package file lacks an active (sources.list) source;"
+ "packages listed in such a file cannot be downloaded."},
+ {"origin",PackageFile_GetOrigin,0,
+ "The origin set in the release file."},
+ {"site",PackageFile_GetSite,0,
+ "The hostname of the location this file comes from."},
+ {"size",PackageFile_GetSize,0,
+ "The size of the file."},
+ {"version",PackageFile_GetVersion,0,
+ "The version set in the release file (e.g. '5.0.X' for lenny, where X\n"
+ "is a point release)."},
+ {}
+};
+
+static const char *packagefile_doc =
+ "A package file is an index file stored in the cache with some\n"
+ "additional pieces of information.";
+
+PyTypeObject PyPackageFile_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.PackageFile", // tp_name
+ sizeof(CppPyObject<pkgCache::PkgFileIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ CppDealloc<pkgCache::PkgFileIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ PackageFileRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ packagefile_doc, // tp_doc
+ CppTraverse<pkgCache::PkgFileIterator>, // tp_traverse
+ CppClear<pkgCache::PkgFileIterator>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ PackageFileGetSet, // tp_getset
+};
+
+// depends class
+static PyObject *DependencyRepr(PyObject *Self)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+
+ return PyString_FromFormat("<%s object: pkg:'%s' ver:'%s' comp:'%s'>",
+ Self->ob_type->tp_name, Dep.TargetPkg().Name(),
+ (Dep.TargetVer() == 0 ? "" : Dep.TargetVer()),
+ Dep.CompType());
+}
+
+static PyObject *DepAllTargets(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+
+ std::unique_ptr<pkgCache::Version *[]> Vers(Dep.AllTargets());
+ PyObject *List = PyList_New(0);
+ for (pkgCache::Version **I = Vers.get(); *I != 0; I++)
+ {
+ PyObject *Obj;
+ Obj = CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,
+ pkgCache::VerIterator(*Dep.Cache(),*I));
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyMethodDef DependencyMethods[] =
+{
+ {"all_targets",DepAllTargets,METH_VARARGS,
+ "all_targets() -> list\n\n"
+ "A list of all possible apt_pkg.Version objects which satisfy this\n"
+ "dependency."},
+ {}
+};
+
+// Dependency Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static PyObject *DependencyGetTargetVer(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ if (Dep->Version == 0)
+ return CppPyString("");
+ return CppPyString(Dep.TargetVer());
+}
+
+static PyObject *DependencyGetTargetPkg(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+ return CppPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type,
+ Dep.TargetPkg());
+}
+
+static PyObject *DependencyGetParentVer(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+ return CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,
+ Dep.ParentVer());
+}
+
+static PyObject *DependencyGetParentPkg(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+ return CppPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type,
+ Dep.ParentPkg());
+}
+
+static PyObject *DependencyGetCompType(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return CppPyString(Dep.CompType());
+}
+
+static PyObject *DependencyGetCompTypeDeb(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return CppPyString(pkgCache::CompTypeDeb(Dep->CompareOp));
+}
+
+static PyObject *DependencyGetDepType(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return CppPyString(Dep.DepType());
+}
+
+static PyObject *DependencyGetDepTypeUntranslated(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return CppPyString(UntranslatedDepTypes[Dep->Type]);
+}
+
+static PyObject *DependencyGetDepTypeEnum(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return MkPyNumber(Dep->Type);
+}
+
+static PyObject *DependencyGetID(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return MkPyNumber(Dep->ID);
+}
+
+static PyGetSetDef DependencyGetSet[] = {
+ {"comp_type",DependencyGetCompType,0,
+ "The type of comparison in mathematical notation, as a string, namely one "
+ "of:\n"
+ "'<', '<=', '=', '!=', '>=', '>', ''.\n"
+ "The empty string will be returned in case of an unversioned dependency."},
+ {"comp_type_deb",DependencyGetCompTypeDeb,0,
+ "The type of comparison in Debian notation, as a string, namely one of:\n"
+ "'<<', '<=', '=', '!=', '>=', '>>', ''.\n"
+ "The empty string will be returned in case of an unversioned dependency.\n"
+ "For details see the Debian Policy Manual on the syntax of relationship "
+ "fields:\n"
+ "https://www.debian.org/doc/debian-policy/ch-relationships.html#s-depsyntax"},
+ {"dep_type",DependencyGetDepType,0,
+ "The type of the dependency; may be translated"},
+ {"dep_type_untranslated",DependencyGetDepTypeUntranslated,0,
+ "Same as dep_type, but guaranteed to be untranslated."},
+ {"dep_type_enum",DependencyGetDepTypeEnum,0,
+ "Same as dep_type, but with a numeric value instead of a string. Can\n"
+ "be compared against the TYPE_ constants defined in this class."},
+ {"id",DependencyGetID,0,
+ "The numeric ID of this dependency object."},
+ {"parent_pkg",DependencyGetParentPkg,0,
+ "The apt_pkg.Package object of the package which depends."},
+ {"parent_ver",DependencyGetParentVer,0,
+ "The apt_pkg.Version object of the package which depends."},
+ {"target_pkg",DependencyGetTargetPkg,0,
+ "The apt_pkg.Package object of the package depended upon"},
+ {"target_ver",DependencyGetTargetVer,0,
+ "The version of the package depended upon as a string"},
+ {}
+};
+
+static const char *dependency_doc =
+ "Represent a dependency from one package version to a package,\n"
+ "and (optionally) a version relation (e.g. >= 1). Dependency\n"
+ "objects also provide useful functions like all_targets()\n"
+ "for selecting packages to satisfy the dependency.";
+
+PyTypeObject PyDependency_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Dependency", // tp_name
+ sizeof(CppPyObject<pkgCache::DepIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::DepIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ DependencyRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ dependency_doc, // tp_doc
+ CppTraverse<pkgCache::DepIterator>, // tp_traverse
+ CppClear<pkgCache::DepIterator>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ DependencyMethods, // tp_methods
+ 0, // tp_members
+ DependencyGetSet, // tp_getset
+};
+
+ /*}}}*/
+ /*}}}*/
+// Reverse Dependency List Class /*{{{*/
+// ---------------------------------------------------------------------
+static Py_ssize_t RDepListLen(PyObject *Self)
+{
+ return GetCpp<RDepListStruct>(Self).Len;
+}
+
+static PyObject *RDepListItem(PyObject *iSelf,Py_ssize_t Index)
+{
+ RDepListStruct &Self = GetCpp<RDepListStruct>(iSelf);
+ if (Index < 0 || (unsigned)Index >= Self.Len)
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return 0;
+ }
+
+ if ((unsigned)Index < Self.LastIndex)
+ {
+ Self.LastIndex = 0;
+ Self.Iter = Self.Start;
+ }
+
+ while ((unsigned)Index > Self.LastIndex)
+ {
+ Self.LastIndex++;
+ Self.Iter++;
+ if (Self.Iter.end() == true)
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return 0;
+ }
+ }
+
+ return CppPyObject_NEW<pkgCache::DepIterator>(GetOwner<RDepListStruct>(iSelf),
+ &PyDependency_Type,Self.Iter);
+}
+
+static PySequenceMethods RDepListSeq =
+{
+ RDepListLen,
+ 0, // concat
+ 0, // repeat
+ RDepListItem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+static const char *dependencylist_doc =
+ "A simple list-like type for representing multiple dependency\n"
+ "objects in an efficient manner; without having to generate\n"
+ "all Dependency objects in advance.";
+PyTypeObject PyDependencyList_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.DependencyList", // tp_name
+ sizeof(CppPyObject<RDepListStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<RDepListStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &RDepListSeq, // 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 | Py_TPFLAGS_HAVE_GC, // tp_flags
+ dependencylist_doc, // tp_doc
+ CppTraverse<RDepListStruct>, // tp_traverse
+ CppClear<RDepListStruct>, // tp_clear
+};
+
+ /*}}}*/
+
+
diff --git a/python/cachegroup.cc b/python/cachegroup.cc
new file mode 100644
index 0000000..4fc6c37
--- /dev/null
+++ b/python/cachegroup.cc
@@ -0,0 +1,188 @@
+/*
+ * cachegroup.cc - Wrapper around pkgCache::GrpIterator
+ *
+ * Copyright 2011 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 <Python.h>
+#include "apt_pkgmodule.h"
+#include "generic.h"
+#include <apt-pkg/pkgcache.h>
+
+struct PyGroup : CppPyObject<pkgCache::GrpIterator> {
+ pkgCache::PkgIterator current;
+ int nextIndex;
+};
+
+static PyObject *group_new(PyTypeObject *type,PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *pyCache;
+ char *name;
+ char *kwlist[] = {"cache", "name", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!s", kwlist,
+ &PyCache_Type, &pyCache,
+ &name) == 0)
+ return 0;
+
+ pkgCache *cache = GetCpp<pkgCache *>(pyCache);
+
+ pkgCache::GrpIterator grp = cache->FindGrp(name);
+
+ if (!grp.end()) {
+ return PyGroup_FromCpp(grp, true, pyCache);
+ } else {
+ PyErr_SetString(PyExc_KeyError, name);
+ return NULL;
+ }
+}
+
+static const char group_find_package_doc[] =
+ "find_package(architecture: str) -> Package\n\n"
+ "Return a package for the given architecture, or None if none exists";
+static PyObject *group_find_package(PyObject *self,PyObject *args)
+{
+ pkgCache::GrpIterator grp = GetCpp<pkgCache::GrpIterator>(self);
+ PyObject *owner = GetOwner<pkgCache::GrpIterator>(self);
+
+ char *architecture;
+ if (PyArg_ParseTuple(args, "s", &architecture) == 0)
+ return 0;
+
+ pkgCache::PkgIterator pkg = grp.FindPkg(architecture);
+
+ if (pkg.end()) {
+ Py_RETURN_NONE;
+ } else {
+ return PyPackage_FromCpp(pkg, true, owner ? owner : self);
+ }
+}
+
+static const char group_find_preferred_package_doc[] =
+ "find_preferred_package(prefer_non_virtual: bool = True) -> Package\n\n"
+ "Return a package for the best architecture, either the native one\n"
+ "or the first found one. If none exists, return None. If non_virtual\n"
+ "is True, prefer non-virtual packages over virtual ones.";
+static PyObject *group_find_preferred_package(PyObject *self,PyObject *args,
+ PyObject *kwds)
+{
+ pkgCache::GrpIterator grp = GetCpp<pkgCache::GrpIterator>(self);
+ PyObject *owner = GetOwner<pkgCache::GrpIterator>(self);
+ char nonvirtual = 1;
+ char *kwlist[] = {"prefer_non_virtual", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|b", kwlist, &nonvirtual) == 0)
+ return 0;
+ pkgCache::PkgIterator pkg = grp.FindPreferredPkg(nonvirtual);
+
+ if (pkg.end()) {
+ Py_RETURN_NONE;
+ } else {
+ return PyPackage_FromCpp(pkg, true, owner);
+ }
+}
+
+static PyMethodDef group_methods[] = {
+ {"find_package",group_find_package,METH_VARARGS,group_find_package_doc},
+ {"find_preferred_package",(PyCFunction) group_find_preferred_package,
+ METH_VARARGS|METH_KEYWORDS,group_find_preferred_package_doc},
+ {}
+};
+
+static PyObject *group_seq_item(PyObject *pySelf,Py_ssize_t index)
+{
+ PyGroup *self = static_cast<PyGroup *>(pySelf);
+ pkgCache::GrpIterator grp = GetCpp<pkgCache::GrpIterator>(self);
+ PyObject *owner = GetOwner<pkgCache::GrpIterator>(self);
+
+ if (self->nextIndex > index || self->nextIndex == 0) {
+ self->nextIndex = 1;
+ new (&self->current) pkgCache::PkgIterator(grp.PackageList());
+ }
+
+ if (self->nextIndex != index + 1) {
+ while (self->nextIndex <= index && !self->current.end()) {
+ self->current = grp.NextPkg(self->current);
+ self->nextIndex++;
+ }
+ }
+
+ if (self->current.end())
+ return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index);
+
+ return PyPackage_FromCpp(self->current, true, owner);
+}
+
+
+static PySequenceMethods group_as_sequence =
+{
+ 0,
+ 0, // concat
+ 0, // repeat
+ group_seq_item,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+
+static const char group_doc[] = "Group(cache, name)\n\n"
+ "Group of packages with the same name.\n\n"
+ "Provides access to all packages sharing a name. Can be used this\n"
+ "like a list, or by using the special find_*() methods. If you use\n"
+ "it as a sequence, make sure to access it linearly, as this uses a\n"
+ "linked list internally.";
+PyTypeObject PyGroup_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Group", // tp_name
+ sizeof(PyGroup), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::GrpIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &group_as_sequence, // 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
+ group_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ group_methods, // tp_methods
+ 0, // 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
+ group_new, // tp_new
+};
diff --git a/python/cdrom.cc b/python/cdrom.cc
new file mode 100644
index 0000000..392dd83
--- /dev/null
+++ b/python/cdrom.cc
@@ -0,0 +1,139 @@
+/* cdrom.cc - Wrapper for pkgCdrom.
+ *
+ * Copyright 2004-2009 Canonical Ltd.
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * Authors: Michael Vogt
+ * Julian Andres Klode
+ *
+ * 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 "apt_pkgmodule.h"
+#include "progress.h"
+
+#include <apt-pkg/cdrom.h>
+
+static char *cdrom_add_doc =
+ "add(progress: apt_pkg.CdromProgress) -> bool\n\n"
+ "Add the given CD-ROM to the sources.list. Return True on success;\n"
+ "raise an error on failure or return False.";
+static PyObject *cdrom_add(PyObject *Self,PyObject *Args)
+{
+ pkgCdrom &Cdrom = GetCpp<pkgCdrom>(Self);
+
+ PyObject *pyCdromProgressInst = 0;
+ if (PyArg_ParseTuple(Args, "O", &pyCdromProgressInst) == 0) {
+ return 0;
+ }
+
+ PyCdromProgress progress;
+ progress.setCallbackInst(pyCdromProgressInst);
+
+ bool res = Cdrom.Add(&progress);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *cdrom_ident_doc =
+ "ident(progress: apt_pkg.CdromProgress) -> str\n\n"
+ "Try to identify the CD-ROM and if successful return the hexadecimal\n"
+ "CDROM-ID (and a integer version suffix separated by -) as a\n"
+ "string. Otherwise, return None or raise an error.\n\n"
+ "The ID is created by hashing all file and directory names on the\n"
+ "CD-ROM and appending the version.";
+static PyObject *cdrom_ident(PyObject *Self,PyObject *Args)
+{
+ pkgCdrom &Cdrom = GetCpp<pkgCdrom>(Self);
+ PyObject *pyCdromProgressInst = 0;
+ if (PyArg_ParseTuple(Args, "O", &pyCdromProgressInst) == 0) {
+ return 0;
+ }
+
+ PyCdromProgress progress;
+ progress.setCallbackInst(pyCdromProgressInst);
+
+ std::string ident;
+ bool res = Cdrom.Ident(ident, &progress);
+
+ if (res)
+ return CppPyString(ident);
+ else {
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+}
+
+
+static PyMethodDef cdrom_methods[] = {
+ {"add",cdrom_add,METH_VARARGS,cdrom_add_doc},
+ {"ident",cdrom_ident,METH_VARARGS,cdrom_ident_doc},
+ {}
+};
+
+static PyObject *cdrom_new(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ return CppPyObject_NEW<pkgCdrom>(NULL, type);
+}
+
+static char *cdrom_doc =
+ "Cdrom()\n\n"
+ "Cdrom objects can be used to identify Debian installation media and to\n"
+ "add them to /etc/apt/sources.list.";
+PyTypeObject PyCdrom_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Cdrom", // tp_name
+ sizeof(CppPyObject<pkgCdrom>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCdrom>, // 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
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE,
+ cdrom_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ cdrom_methods, // tp_methods
+ 0, // 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
+ cdrom_new, // tp_new
+};
+
diff --git a/python/configuration.cc b/python/configuration.cc
new file mode 100644
index 0000000..dab2cc4
--- /dev/null
+++ b/python/configuration.cc
@@ -0,0 +1,613 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: configuration.cc,v 1.4 2003/06/03 03:22:27 mdz Exp $
+/* ######################################################################
+
+ Configuration - Binding for the configuration object.
+
+ The Configuration object can have an owner (a parent Configuration object),
+ and it always uses a pointer.
+
+ The wrapping is mostly 1:1 with the C++ code, but there are additions to
+ wrap the linked tree walking into nice flat sequence walking.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/cmndline.h>
+#include <sstream>
+#include <Python.h>
+ /*}}}*/
+
+// GetSelf - Convert PyObject to Configuration /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static inline Configuration &GetSelf(PyObject *Obj)
+{
+ return *GetCpp<Configuration*>(Obj);
+}
+ /*}}}*/
+
+// Method Wrappers /*{{{*/
+static const char *doc_Find =
+ "find(key: str[, default: str = '']) -> str\n\n"
+ "Find the value for the given key and return it. If the\n"
+ "given key does not exist, return default instead.";
+static PyObject *CnfFind(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+ return CppPyString(GetSelf(Self).Find(Name,Default));
+}
+
+static const char *doc_FindFile =
+ "find_file(key: str[, default: str = '']) -> str\n\n"
+ "Same as find(), but for filenames. In the APT configuration, there\n"
+ "is a special section Dir:: for storing filenames. find_file() locates\n"
+ "the given key and then goes up and prepends the directory names to the\n"
+ "return value. For example, for:\n"
+ "\n"
+ " apt_pkg.config['Dir'] = 'a'\n"
+ " apt_pkg.config['Dir::D'] = 'b'\n"
+ " apt_pkg.config['Dir::D::F'] = 'c'\n"
+ "\n"
+ "find_file('Dir::D::F') returns 'a/b/c'. There is also a special\n"
+ "configuration setting RootDir which will always be prepended to the\n"
+ "result (the default being ''). Thus, if RootDir is 'x', the example\n"
+ "would return 'x/a/b/c'.";
+static PyObject *CnfFindFile(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+ return CppPyPath(GetSelf(Self).FindFile(Name,Default));
+}
+
+static const char *doc_FindDir =
+ "find_dir(key: str[, default: str = '']) -> str\n\n"
+ "Same as find_file(), but for directories. The difference is\n"
+ "that this function adds a trailing slash to the result.";
+static PyObject *CnfFindDir(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+ return CppPyPath(GetSelf(Self).FindDir(Name,Default));
+}
+
+static const char *doc_FindI =
+ "find_i(key: str[, default: int = 0]) -> int\n\n"
+ "Same as find, but for integer values.";
+static PyObject *CnfFindI(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ int Default = 0;
+ if (PyArg_ParseTuple(Args,"s|i",&Name,&Default) == 0)
+ return 0;
+ return MkPyNumber(GetSelf(Self).FindI(Name,Default));
+}
+
+static const char *doc_FindB =
+ "find_i(key: str[, default: bool = False]) -> bool\n\n"
+ "Same as find, but for boolean values; returns False on unknown values.";
+static PyObject *CnfFindB(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ int Default = 0;
+ if (PyArg_ParseTuple(Args,"s|i",&Name,&Default) == 0)
+ return 0;
+ return PyBool_FromLong(GetSelf(Self).FindB(Name,(Default == 0?false:true)));
+}
+
+static const char *doc_Set =
+ "set(key: str, value: str)\n\n"
+ "Set the given key to the given value. To set int or bool values,\n"
+ "encode them using str(value) and then use find_i()/find_b()\n"
+ "to retrieve their value again.";
+static PyObject *CnfSet(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Value = 0;
+ if (PyArg_ParseTuple(Args,"ss",&Name,&Value) == 0)
+ return 0;
+
+ GetSelf(Self).Set(Name,Value);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static const char *doc_Exists =
+ "exists(key: str) -> bool\n\n"
+ "Check whether the given key exists.";
+static PyObject *CnfExists(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+ return PyBool_FromLong((int)GetSelf(Self).Exists(Name));
+}
+
+static int CnfContains(PyObject *Self,PyObject *Arg)
+{
+ return (int)GetSelf(Self).Exists(PyString_AsString(Arg));
+}
+
+static const char *doc_Clear =
+ "clear(key: str)\n\n"
+ "Remove the specified option and all sub-options.";
+static PyObject *CnfClear(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ GetSelf(Self).Clear(Name);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+// The amazing narrowing search ability!
+static const char *doc_SubTree =
+ "subtree(key: str) -> apt_pkg.Configuration\n\n"
+
+ "Return a new apt_pkg.Configuration object with the given option\n"
+ "as its root. Example:\n\n"
+ " apttree = config.subtree('APT')\n"
+ " apttree['Install-Suggests'] = config['APT::Install-Suggests']";
+static PyObject *CnfSubTree(PyObject *Self,PyObject *Args)
+{
+ char *Name;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+ const Configuration::Item *Itm = GetSelf(Self).Tree(Name);
+ if (Itm == 0)
+ {
+ PyErr_SetString(PyExc_KeyError,Name);
+ return 0;
+ }
+
+ return CppPyObject_NEW<Configuration*>(Self,&PyConfiguration_Type,
+ new Configuration(Itm));
+}
+
+// Return a list of items at a specific level
+static char *doc_List =
+ "list([root: str]) -> list\n\n"
+ "Return a list of all items at the given root, using their full\n"
+ "name. For example, in a configuration object where the options A,\n"
+ "B, and B::C are set, the following expressions evaluate to True:\n\n"
+ " conf.list() == ['A', 'B']\n"
+ " conf.list('A') == ['']\n"
+ " conf.list('B') == ['B::C']\n";
+static PyObject *CnfList(PyObject *Self,PyObject *Args)
+{
+ char *RootName = 0;
+ if (PyArg_ParseTuple(Args,"|s",&RootName) == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ const Configuration::Item *Top = GetSelf(Self).Tree(RootName);
+ if (!GetSelf(Self).Tree(0))
+ return List;
+ const Configuration::Item *Root = GetSelf(Self).Tree(0)->Parent;
+ if (Top != 0 && RootName != 0)
+ Top = Top->Child;
+ for (; Top != 0; Top = Top->Next)
+ {
+ PyObject *Obj;
+ PyList_Append(List,Obj = CppPyString(Top->FullTag(Root)));
+ Py_DECREF(Obj);
+ }
+
+ return List;
+}
+
+/* Return a list of values of items at a specific level.. This is used to
+ get out value lists */
+static char *doc_ValueList =
+ "value_list([root: str]) -> list\n\n"
+ "Same as list(), but instead of returning the keys, return the values.";
+static PyObject *CnfValueList(PyObject *Self,PyObject *Args)
+{
+ char *RootName = 0;
+ if (PyArg_ParseTuple(Args,"|s",&RootName) == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ const Configuration::Item *Top = GetSelf(Self).Tree(RootName);
+ if (Top != 0 && RootName != 0)
+ Top = Top->Child;
+ for (; Top != 0; Top = Top->Next)
+ {
+ PyObject *Obj;
+ PyList_Append(List,Obj = CppPyString(Top->Value));
+ Py_DECREF(Obj);
+ }
+
+ return List;
+}
+
+static char *doc_MyTag =
+ "my_tag() -> str\n\n"
+ "Return the tag of the root of this Configuration object. For the\n"
+ "default object, this is an empty string. For a subtree('APT') of\n"
+ "such an object, it would be 'APT' (given as an example).";
+static PyObject *CnfMyTag(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ const Configuration::Item *Top = GetSelf(Self).Tree(0);
+ if (Top == 0)
+ return Py_BuildValue("s","");
+ return CppPyString(Top->Parent->Tag);
+}
+
+static char *doc_Dump =
+ "dump() -> str\n\n"
+ "Return a string dump this Configuration object.";
+static PyObject *CnfDump(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ std::stringstream ss;
+ GetSelf(Self).Dump(ss);
+ return CppPyString(ss.str());
+}
+
+
+// Look like a mapping
+static char *doc_Keys =
+ "keys([root: str]) -> list\n\n"
+ "Return a list of all keys in the configuration object. If 'root'\n"
+ "is given, limit the list to those below the root.";
+static PyObject *CnfKeys(PyObject *Self,PyObject *Args)
+{
+ char *RootName = 0;
+ if (PyArg_ParseTuple(Args,"|s",&RootName) == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ const Configuration::Item *Top = GetSelf(Self).Tree(RootName);
+ const Configuration::Item *Stop = Top;
+ const Configuration::Item *Root = 0;
+ if (RootName == 0)
+ Stop = 0;
+ if (Top != 0 && GetSelf(Self).Tree(0))
+ Root = GetSelf(Self).Tree(0)->Parent;
+ for (; Top != 0;)
+ {
+ PyObject *Obj;
+ PyList_Append(List,Obj = CppPyString(Top->FullTag(Root)));
+ Py_DECREF(Obj);
+
+ if (Top->Child != 0)
+ {
+ Top = Top->Child;
+ continue;
+ }
+
+ while (Top != 0 && Top->Next == 0 && Top != Root &&
+ Top->Parent != Stop)
+ Top = Top->Parent;
+ if (Top != 0)
+ Top = Top->Next;
+ }
+
+ return List;
+}
+
+// Map access, operator []
+static PyObject *CnfMap(PyObject *Self,PyObject *Arg)
+{
+ if (PyString_Check(Arg) == 0)
+ {
+ PyErr_SetNone(PyExc_TypeError);
+ return 0;
+ }
+
+ if (GetSelf(Self).Exists(PyString_AsString(Arg)) == false)
+ {
+ PyErr_SetString(PyExc_KeyError,PyString_AsString(Arg));
+ return 0;
+ }
+
+ return CppPyString(GetSelf(Self).Find(PyString_AsString(Arg)));
+}
+
+// Assignment with operator []
+static int CnfMapSet(PyObject *Self,PyObject *Arg,PyObject *Val)
+{
+ if (PyString_Check(Arg) == 0 || (Val != NULL && PyString_Check(Val) == 0))
+ {
+ PyErr_SetNone(PyExc_TypeError);
+ return -1;
+ }
+
+ if (Val == NULL)
+ GetSelf(Self).Clear(PyString_AsString(Arg));
+ else
+ GetSelf(Self).Set(PyString_AsString(Arg),PyString_AsString(Val));
+ return 0;
+}
+ /*}}}*/
+// Config file loaders /*{{{*/
+char *doc_LoadConfig =
+ "read_config_file(configuration: apt_pkg.Configuration, filename: str)\n\n"
+ "Read the configuration file 'filename' and set the appropriate\n"
+ "options in the configuration object.";
+PyObject *LoadConfig(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename Name;
+ if (PyArg_ParseTuple(Args,"OO&",&Self,PyApt_Filename::Converter, &Name) == 0)
+ return 0;
+ if (PyConfiguration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (ReadConfigFile(GetSelf(Self),Name,false) == false)
+ return HandleErrors();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+char *doc_LoadConfigISC =
+ "read_config_file_isc(configuration: apt_pkg.Configuration, filename: str)\n\n"
+ "Like read_config_file(), but for configuration files like bind's\n"
+ "named.conf. They have a slightly different format than APT\n"
+ "configuration files.";
+PyObject *LoadConfigISC(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename Name;
+ if (PyArg_ParseTuple(Args,"OO&",&Self,PyApt_Filename::Converter, &Name) == 0)
+ return 0;
+ if (PyConfiguration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (ReadConfigFile(GetSelf(Self),Name,true) == false)
+ return HandleErrors();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+char *doc_LoadConfigDir =
+ "read_config_dir(configuration: apt_pkg.Configuration, dirname: str)\n\n"
+ "Read all configuration files in the dir given by 'dirname' in the\n"
+ "correct order.";
+PyObject *LoadConfigDir(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename Name;
+ if (PyArg_ParseTuple(Args,"OO&",&Self,PyApt_Filename::Converter, &Name) == 0)
+ return 0;
+ if (PyConfiguration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (ReadConfigDir(GetSelf(Self),Name,false) == false)
+ return HandleErrors();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+ /*}}}*/
+
+// ParseCommandLine - Wrapper for the command line interface /*{{{*/
+// ---------------------------------------------------------------------
+char *doc_ParseCommandLine =
+"parse_commandLine(config: Configuration, options: list, argv: list) -> list\n"
+"\n"
+"Parse the command line in 'argv' into the configuration space. The\n"
+"list 'options' contains a list of 3-tuples or 4-tuples in the form:\n"
+"\n"
+" (short_option: str, long_option: str, variable: str[, type: str])\n"
+"\n"
+"The element 'short_option' is one character, the 'long_option' element\n"
+"is the name of the long option, the element 'variable' the name of the\n"
+"configuration option the result will be stored in and type is one of\n"
+"'HasArg', 'IntLevel', 'Boolean', 'InvBoolean', 'ConfigFile',\n"
+"'ArbItem'. The default type is 'Boolean'. Read the online documentation\n"
+"in python-apt-doc and its tutorial on writing an apt-cdrom clone for more\n"
+"details.";
+PyObject *ParseCommandLine(PyObject *Self,PyObject *Args)
+{
+ PyObject *POList;
+ PyObject *Pargv;
+ if (PyArg_ParseTuple(Args,"OO!O!",&Self,
+ &PyList_Type,&POList,&PyList_Type,&Pargv) == 0)
+ return 0;
+ if (PyConfiguration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (PySequence_Length(Pargv) < 1) {
+ PyErr_SetString(PyExc_ValueError,"argv is an empty sequence");
+ return 0;
+ }
+ // Convert the option list
+ int Length = PySequence_Length(POList);
+ CommandLine::Args *OList = new CommandLine::Args[Length+1];
+ OList[Length].ShortOpt = 0;
+ OList[Length].LongOpt = 0;
+
+ for (int I = 0; I != Length; I++)
+ {
+ char *Type = 0;
+ #if PY_MAJOR_VERSION >= 3
+ if (PyArg_ParseTuple(PySequence_GetItem(POList,I),"Czs|s",
+ #else
+ if (PyArg_ParseTuple(PySequence_GetItem(POList,I),"czs|s",
+ #endif
+ &OList[I].ShortOpt,&OList[I].LongOpt,
+ &OList[I].ConfName,&Type) == 0)
+ {
+ delete [] OList;
+ return 0;
+ }
+ OList[I].Flags = 0;
+
+ // Convert the type over to flags..
+ if (Type != 0)
+ {
+ if (strcasecmp(Type,"HasArg") == 0)
+ OList[I].Flags = CommandLine::HasArg;
+ else if (strcasecmp(Type,"IntLevel") == 0)
+ OList[I].Flags = CommandLine::IntLevel;
+ else if (strcasecmp(Type,"Boolean") == 0)
+ OList[I].Flags = CommandLine::Boolean;
+ else if (strcasecmp(Type,"InvBoolean") == 0)
+ OList[I].Flags = CommandLine::InvBoolean;
+ else if (strcasecmp(Type,"ConfigFile") == 0)
+ OList[I].Flags = CommandLine::ConfigFile;
+ else if (strcasecmp(Type,"ArbItem") == 0)
+ OList[I].Flags = CommandLine::ArbItem;
+ }
+ }
+
+ // Convert the argument list into a char **
+ const char **argv = ListToCharChar(Pargv);
+ if (argv == 0)
+ {
+ delete [] OList;
+ return 0;
+ }
+
+ // Do the command line processing
+ PyObject *List = 0;
+ {
+ CommandLine CmdL(OList,&GetSelf(Self));
+ if (CmdL.Parse(PySequence_Length(Pargv),argv) == false)
+ {
+ delete [] argv;
+ delete [] OList;
+ return HandleErrors();
+ }
+
+ // Convert the file listing into a python sequence
+ for (Length = 0; CmdL.FileList[Length] != 0; Length++);
+ List = PyList_New(Length);
+ for (int I = 0; CmdL.FileList[I] != 0; I++)
+ {
+ PyList_SetItem(List,I,CppPyString(CmdL.FileList[I]));
+ }
+ }
+
+ delete [] argv;
+ delete [] OList;
+ return HandleErrors(List);
+}
+ /*}}}*/
+
+// Method table for the Configuration object
+static PyMethodDef CnfMethods[] =
+{
+ // Query
+ {"find",CnfFind,METH_VARARGS,doc_Find},
+ {"find_file",CnfFindFile,METH_VARARGS,doc_FindFile},
+ {"find_dir",CnfFindDir,METH_VARARGS,doc_FindDir},
+ {"find_i",CnfFindI,METH_VARARGS,doc_FindI},
+ {"find_b",CnfFindB,METH_VARARGS,doc_FindB},
+
+ // Others
+ {"set",CnfSet,METH_VARARGS,doc_Set},
+ {"exists",CnfExists,METH_VARARGS,doc_Exists},
+ {"subtree",CnfSubTree,METH_VARARGS,doc_SubTree},
+ {"list",CnfList,METH_VARARGS,doc_List},
+ {"value_list",CnfValueList,METH_VARARGS,doc_ValueList},
+ {"my_tag",CnfMyTag,METH_VARARGS,doc_MyTag},
+ {"clear",CnfClear,METH_VARARGS,doc_Clear},
+ {"dump",CnfDump,METH_VARARGS,doc_Dump},
+ // Python Special
+ {"keys",CnfKeys,METH_VARARGS,doc_Keys},
+ #if PY_MAJOR_VERSION < 3
+ {"has_key",CnfExists,METH_VARARGS,doc_Exists},
+ #endif
+ {"get",CnfFind,METH_VARARGS,doc_Find},
+ {}
+};
+
+static PyObject *CnfNew(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ char *kwlist[] = {NULL};
+ if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0)
+ return 0;
+ return CppPyObject_NEW<Configuration*>(NULL, type, new Configuration());
+}
+
+// Type for a Normal Configuration object
+static PySequenceMethods ConfigurationSeq = {0,0,0,0,0,0,0,CnfContains,0,0};
+static PyMappingMethods ConfigurationMap = {0,CnfMap,CnfMapSet};
+
+static const char *configuration_doc =
+ "Configuration()\n\n"
+ "Represent the configuration of APT by mapping option keys to\n"
+ "values and storing configuration parsed from files like\n"
+ "/etc/apt/apt.conf. The most important Configuration object\n"
+ "is apt_pkg.config which points to the global configuration\n"
+ "object. Other top-level Configuration objects can be created\n"
+ "by calling the constructor, but there is usually no reason to.";
+
+PyTypeObject PyConfiguration_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Configuration", // tp_name
+ sizeof(CppPyObject<Configuration*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<Configuration*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &ConfigurationSeq, // tp_as_sequence
+ &ConfigurationMap, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ configuration_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ CnfMethods, // tp_methods
+ 0, // 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
+ CnfNew, // tp_new
+};
+
diff --git a/python/depcache.cc b/python/depcache.cc
new file mode 100644
index 0000000..ed766c4
--- /dev/null
+++ b/python/depcache.cc
@@ -0,0 +1,1169 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: depcache.cc,v 1.5 2003/06/03 03:03:23 mdz Exp $
+/* ######################################################################
+
+ DepCache - Wrapper for the depcache related functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/policy.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/pkgrecords.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/upgrade.h>
+#include <Python.h>
+
+#include <iostream>
+#include "progress.h"
+
+#ifndef _
+#define _(x) (x)
+#endif
+
+
+#define VALIDATE_ITERATOR(I) do { \
+ if ((I).Cache() != &depcache->GetCache()) { \
+ PyErr_SetString(PyAptCacheMismatchError, "Object of different cache passed as argument to apt_pkg.DepCache method"); \
+ return nullptr; \
+ } \
+} while(0)
+
+
+// DepCache Class /*{{{*/
+// ---------------------------------------------------------------------
+
+
+
+static PyObject *PkgDepCacheInit(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *pyCallbackInst = 0;
+ if (PyArg_ParseTuple(Args, "|O", &pyCallbackInst) == 0)
+ return 0;
+
+ if(pyCallbackInst != 0) {
+ PyOpProgress progress;
+ progress.setCallbackInst(pyCallbackInst);
+ depcache->Init(&progress);
+ } else {
+ depcache->Init(0);
+ }
+
+ pkgApplyStatus(*depcache);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *pyInstallProgressInst = 0;
+ PyObject *pyFetchProgressInst = 0;
+ if (PyArg_ParseTuple(Args, "OO",
+ &pyFetchProgressInst, &pyInstallProgressInst) == 0) {
+ return 0;
+ }
+
+ pkgAcquire Fetcher;
+ if (Fetcher.GetLock(_config->FindDir("Dir::Cache::Archives")) == false) {
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ pkgRecords Recs(*depcache);
+ if (_error->PendingError() == true)
+ HandleErrors(Py_None);
+
+ pkgSourceList List;
+ if(!List.ReadMainList())
+ return HandleErrors(Py_None);
+
+ PyFetchProgress progress;
+ progress.setCallbackInst(pyFetchProgressInst);
+
+ pkgPackageManager *PM;
+ PM = _system->CreatePM(depcache);
+
+ Fetcher.SetLog(&progress);
+
+ if(PM->GetArchives(&Fetcher, &List, &Recs) == false ||
+ _error->PendingError() == true) {
+ std::cerr << "Error in GetArchives" << std::endl;
+ return HandleErrors();
+ }
+
+ PyInstallProgress iprogress;
+ iprogress.setCallbackInst(pyInstallProgressInst);
+
+ // Run it
+ while (1)
+ {
+ bool Transient = false;
+
+ if (Fetcher.Run() == pkgAcquire::Failed)
+ return HandleErrors();
+
+ // Print out errors
+ bool Failed = false;
+ for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+ {
+
+ if ((*I)->Status == pkgAcquire::Item::StatDone &&
+ (*I)->Complete == true)
+ continue;
+
+ if ((*I)->Status == pkgAcquire::Item::StatIdle)
+ {
+ Transient = true;
+ //Failed = true;
+ continue;
+ }
+
+ _error->Warning(_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
+ (*I)->ErrorText.c_str());
+ Failed = true;
+ }
+
+ if (Transient == true && Failed == true)
+ {
+ _error->Error(_("--fix-missing and media swapping is not currently supported"));
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ // Try to deal with missing package files
+ if (Failed == true && PM->FixMissing() == false)
+ {
+ _error->Error("Aborting install.");
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ // fail if something else went wrong
+ //FIXME: make this more flexible, e.g. with a failedDl handler
+ if(Failed)
+ Py_RETURN_FALSE;
+ _system->UnLockInner(true);
+
+ pkgPackageManager::OrderResult Res = iprogress.Run(PM);
+
+ if (Res == pkgPackageManager::Failed || _error->PendingError() == true) {
+ return HandleErrors(PyBool_FromLong(false));
+ }
+ if (Res == pkgPackageManager::Completed) {
+ Py_RETURN_TRUE;
+ }
+
+ // Reload the fetcher object and loop again for media swapping
+ Fetcher.Shutdown();
+ if (PM->GetArchives(&Fetcher,&List,&Recs) == false) {
+ Py_RETURN_FALSE;
+ }
+ _system->LockInner();
+ }
+
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheSetCandidateRelease(PyObject *Self,PyObject *Args)
+{
+ bool Success;
+ PyObject *PackageObj;
+ PyObject *VersionObj;
+ const char *target_rel;
+ std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
+ if (PyArg_ParseTuple(Args,"O!O!s",
+ &PyPackage_Type, &PackageObj,
+ &PyVersion_Type, &VersionObj,
+ &target_rel) == 0)
+ return 0;
+
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+ pkgCache::VerIterator &I = GetCpp<pkgCache::VerIterator>(VersionObj);
+ if(I.end()) {
+ return HandleErrors(PyBool_FromLong(false));
+ }
+ VALIDATE_ITERATOR(I);
+
+ Success = depcache->SetCandidateRelease(I, target_rel, Changed);
+
+ return HandleErrors(PyBool_FromLong(Success));
+}
+
+static PyObject *PkgDepCacheSetCandidateVer(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+ PyObject *PackageObj;
+ PyObject *VersionObj;
+ if (PyArg_ParseTuple(Args,"O!O!",
+ &PyPackage_Type, &PackageObj,
+ &PyVersion_Type, &VersionObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+
+ VALIDATE_ITERATOR(Pkg);
+
+ pkgCache::VerIterator &I = GetCpp<pkgCache::VerIterator>(VersionObj);
+ if(I.end()) {
+ return HandleErrors(PyBool_FromLong(false));
+ }
+ VALIDATE_ITERATOR(I);
+
+ if (I.ParentPkg() != Pkg) {
+ PyErr_SetString(PyExc_ValueError, "Version does not belong to package");
+ return nullptr;
+ }
+
+ depcache->SetCandidateVersion(I);
+
+ return HandleErrors(PyBool_FromLong(true));
+}
+
+static PyObject *PkgDepCacheGetCandidateVer(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+ PyObject *PackageObj;
+ PyObject *CandidateObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+
+ VALIDATE_ITERATOR(Pkg);
+
+ pkgDepCache::StateCache & State = (*depcache)[Pkg];
+ pkgCache::VerIterator I = State.CandidateVerIter(*depcache);
+
+ if(I.end()) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ CandidateObj = CppPyObject_NEW<pkgCache::VerIterator>(PackageObj,&PyVersion_Type,I);
+
+ return CandidateObj;
+}
+
+static PyObject *PkgDepCacheUpgrade(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ char distUpgrade=0;
+ if (PyArg_ParseTuple(Args,"|b",&distUpgrade) == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ if(distUpgrade)
+ res = APT::Upgrade::Upgrade(*depcache, 0);
+ else
+ res = APT::Upgrade::Upgrade(*depcache, APT::Upgrade::FORBID_REMOVE_PACKAGES |
+ APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES);
+ Py_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyObject *PkgDepCacheMinimizeUpgrade(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = pkgMinimizeUpgrade(*depcache);
+ Py_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+
+static PyObject *PkgDepCacheReadPinFile(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+
+ char *file=NULL;
+ if (PyArg_ParseTuple(Args,"|s",&file) == 0)
+ return 0;
+
+ if(file == NULL)
+ ReadPinFile((pkgPolicy&)depcache->GetPolicy());
+ else
+ ReadPinFile((pkgPolicy&)depcache->GetPolicy(), file);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+
+static PyObject *PkgDepCacheFixBroken(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ bool res=true;
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ res &=pkgFixBroken(*depcache);
+ res &=pkgMinimizeUpgrade(*depcache);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+
+static PyObject *PkgDepCacheMarkKeep(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ depcache->MarkKeep(Pkg);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheSetReInstall(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Self);
+
+ PyObject *PackageObj;
+ char value = 0;
+ if (PyArg_ParseTuple(Args,"O!b",&PyPackage_Type,&PackageObj, &value) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ depcache->SetReInstall(Pkg,value);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+
+static PyObject *PkgDepCacheMarkDelete(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ char purge = 0;
+ if (PyArg_ParseTuple(Args,"O!|b",&PyPackage_Type,&PackageObj, &purge) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ depcache->MarkDelete(Pkg,purge);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+
+static PyObject *PkgDepCacheMarkInstall(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ char autoInst=1;
+ char fromUser=1;
+ if (PyArg_ParseTuple(Args,"O!|bb",&PyPackage_Type,&PackageObj,
+ &autoInst, &fromUser) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+
+ Py_BEGIN_ALLOW_THREADS
+ depcache->MarkInstall(Pkg, autoInst, 0, fromUser);
+ Py_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheMarkAuto(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Self);
+
+ PyObject *PackageObj;
+ char value = 0;
+ if (PyArg_ParseTuple(Args,"O!b",&PyPackage_Type,&PackageObj, &value) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ depcache->MarkAuto(Pkg,value);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheIsUpgradable(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Upgradable()));
+}
+
+static PyObject *PkgDepCacheIsGarbage(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Garbage));
+}
+
+static PyObject *PkgDepCacheIsAutoInstalled(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Flags & pkgCache::Flag::Auto));
+}
+
+static PyObject *PkgDepCacheIsNowBroken(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.NowBroken()));
+}
+
+static PyObject *PkgDepCacheIsInstBroken(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.InstBroken()));
+}
+
+
+static PyObject *PkgDepCacheMarkedInstall(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.NewInstall()));
+}
+
+
+static PyObject *PkgDepCacheMarkedUpgrade(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Upgrade()));
+}
+
+static PyObject *PkgDepCacheMarkedDelete(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Delete()));
+}
+
+static PyObject *PkgDepCacheMarkedKeep(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Keep()));
+}
+
+static PyObject *PkgDepCacheMarkedDowngrade(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Downgrade()));
+}
+
+static PyObject *PkgDepCacheMarkedReinstall(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ bool res = state.Install() && (state.iFlags & pkgDepCache::ReInstall);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyObject *PkgDepCachePhasingApplied(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ bool res=false;
+ PyObject *PackageObj;
+
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ res = depcache->PhasingApplied(Pkg);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyMethodDef PkgDepCacheMethods[] =
+{
+ {"init",PkgDepCacheInit,METH_VARARGS,
+ "init(progress: apt.progress.base.OpProgress)\n\n"
+ "Initialize the depcache (done automatically when constructing\n"
+ "the object)."},
+ {"get_candidate_ver",PkgDepCacheGetCandidateVer,METH_VARARGS,
+ "get_candidate_ver(pkg: apt_pkg.Package) -> apt_pkg.Version\n\n"
+ "Return the candidate version for the package, normally the version\n"
+ "with the highest pin (changeable using set_candidate_ver)."},
+ {"set_candidate_ver",PkgDepCacheSetCandidateVer,METH_VARARGS,
+ "set_candidate_ver(pkg: apt_pkg.Package, ver: apt_pkg.Version) -> bool\n\n"
+ "Set the candidate version of 'pkg' to 'ver'."},
+ {"set_candidate_release",PkgDepCacheSetCandidateRelease,METH_VARARGS,
+ "set_candidate_release(pkg: apt_pkg.Package, ver: apt_pkg.Version, rel: string) -> bool\n\n"
+ "Sets not only the candidate version 'ver' for package 'pkg', "
+ "but walks also down the dependency tree and checks if it is required "
+ "to set the candidate of the dependency to a version from the given "
+ "release string 'rel', too."},
+
+ // global cache operations
+ {"upgrade",PkgDepCacheUpgrade,METH_VARARGS,
+ "upgrade([dist_upgrade: bool = True]) -> bool\n\n"
+ "Mark the packages for upgrade under the same conditions apt-get\n"
+ "upgrade does. If 'dist_upgrade' is True, also allow packages to\n"
+ "be upgraded if they require installation/removal of other packages;\n"
+ "just like apt-get dist-upgrade."},
+ {"fix_broken",PkgDepCacheFixBroken,METH_VARARGS,
+ "fix_broken() -> bool\n\n"
+ "Fix broken packages."},
+ {"read_pinfile",PkgDepCacheReadPinFile,METH_VARARGS,
+ "read_pinfile([file: str])\n\n"
+ "Read the pin policy"},
+ {"minimize_upgrade",PkgDepCacheMinimizeUpgrade, METH_VARARGS,
+ "minimize_upgrade() -> bool\n\n"
+ "Go over the entire set of packages and try to keep each package\n"
+ "marked for upgrade. If a conflict is generated then the package\n"
+ "is restored."},
+ // Policy
+ {"phasing_applied",PkgDepCachePhasingApplied,METH_VARARGS,
+ "phasing_applied(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check if the phased update is ready.\n"
+ "return false if this is a phased update that is not yet ready for us.\n"},
+ // Manipulators
+ {"mark_keep",PkgDepCacheMarkKeep,METH_VARARGS,
+ "mark_keep(pkg: apt_pkg.Package)\n\n"
+ "Mark package to be kept."},
+ {"mark_delete",PkgDepCacheMarkDelete,METH_VARARGS,
+ "mark_delete(pkg: apt_pkg.Package[, purge: bool = False])\n\n"
+ "Mark package for deletion, and if 'purge' is True also for purging."},
+ {"mark_install",PkgDepCacheMarkInstall,METH_VARARGS,
+ "mark_install(pkg: apt_pkg.Package[, auto_inst=True, from_user=True])\n\n"
+ "Mark the package for installation. The parameter 'auto_inst' controls\n"
+ "whether the dependencies of the package are marked for installation\n"
+ "as well. The parameter 'from_user' controls whether the package is\n"
+ "registered as NOT automatically installed."},
+ {"mark_auto",PkgDepCacheMarkAuto,METH_VARARGS,
+ "mark_auto(pkg: apt_pkg.Package, auto: bool)\n\n"
+ "Mark package as automatically installed (if auto=True),\n"
+ "or as not automatically installed (if auto=False)."},
+ {"set_reinstall",PkgDepCacheSetReInstall,METH_VARARGS,
+ "set_reinstall(pkg: apt_pkg.Package, reinstall: bool)\n\n"
+ "Set whether the package should be reinstalled (reinstall = True or False)."},
+ // state information
+ {"is_upgradable",PkgDepCacheIsUpgradable,METH_VARARGS,
+ "is_upgradable(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is upgradable."},
+ {"is_now_broken",PkgDepCacheIsNowBroken,METH_VARARGS,
+ "is_now_broken(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is broken, taking marked changes into account."},
+ {"is_inst_broken",PkgDepCacheIsInstBroken,METH_VARARGS,
+ "is_inst_broken(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is broken, ignoring marked changes."},
+ {"is_garbage",PkgDepCacheIsGarbage,METH_VARARGS,
+ "is_garbage(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is garbage, i.e. whether it is automatically\n"
+ "installed and the reverse dependencies are not installed anymore."},
+ {"is_auto_installed",PkgDepCacheIsAutoInstalled,METH_VARARGS,
+ "is_auto_installed(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked as automatically installed."},
+ {"marked_install",PkgDepCacheMarkedInstall,METH_VARARGS,
+ "marked_install(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for installation."},
+ {"marked_upgrade",PkgDepCacheMarkedUpgrade,METH_VARARGS,
+ "marked_upgrade(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for upgrade."},
+ {"marked_delete",PkgDepCacheMarkedDelete,METH_VARARGS,
+ "marked_delete(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for removal."},
+ {"marked_keep",PkgDepCacheMarkedKeep,METH_VARARGS,
+ "marked_keep(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package should be kept."},
+ {"marked_reinstall",PkgDepCacheMarkedReinstall,METH_VARARGS,
+ "marked_reinstall(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for re-installation."},
+ {"marked_downgrade",PkgDepCacheMarkedDowngrade,METH_VARARGS,
+ "marked_downgrade(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for downgrade."},
+ // Action
+ {"commit", PkgDepCacheCommit, METH_VARARGS,
+ "commit(acquire_progress, install_progress)\n\n"
+ "Commit all the marked changes. This method takes two arguments,\n"
+ "'acquire_progress' takes an apt.progress.base.AcquireProgress\n"
+ "object and 'install_progress' an apt.progress.base.InstallProgress\n"
+ "object."},
+ {}
+};
+
+#define depcache (GetCpp<pkgDepCache *>(Self))
+static PyObject *PkgDepCacheGetKeepCount(PyObject *Self,void*) {
+ return MkPyNumber(depcache->KeepCount());
+}
+static PyObject *PkgDepCacheGetInstCount(PyObject *Self,void*) {
+ return MkPyNumber(depcache->InstCount());
+}
+static PyObject *PkgDepCacheGetDelCount(PyObject *Self,void*) {
+ return MkPyNumber(depcache->DelCount());
+}
+static PyObject *PkgDepCacheGetBrokenCount(PyObject *Self,void*) {
+ return MkPyNumber(depcache->BrokenCount());
+}
+static PyObject *PkgDepCacheGetUsrSize(PyObject *Self,void*) {
+ return MkPyNumber(depcache->UsrSize());
+}
+static PyObject *PkgDepCacheGetDebSize(PyObject *Self,void*) {
+ return MkPyNumber(depcache->DebSize());
+}
+#undef depcache
+
+static PyObject *PkgDepCacheGetPolicy(PyObject *Self,void*) {
+ PyObject *Owner = GetOwner<pkgDepCache*>(Self);
+ pkgDepCache *DepCache = GetCpp<pkgDepCache*>(Self);
+ pkgPolicy *Policy = (pkgPolicy *)&DepCache->GetPolicy();
+ CppPyObject<pkgPolicy*> *PyPolicy =
+ CppPyObject_NEW<pkgPolicy*>(Owner,&PyPolicy_Type,Policy);
+ // Policy should not be deleted, it is managed by CacheFile.
+ PyPolicy->NoDelete = true;
+ return PyPolicy;
+}
+
+
+static PyGetSetDef PkgDepCacheGetSet[] = {
+ {"broken_count",PkgDepCacheGetBrokenCount,0,
+ "The number of packages with broken dependencies in the cache."},
+ {"deb_size",PkgDepCacheGetDebSize,0,
+ "The size of the packages which are needed for the changes to be\n"
+ "applied."},
+ {"del_count",PkgDepCacheGetDelCount,0,
+ "The number of packages marked for removal."},
+ {"inst_count",PkgDepCacheGetInstCount,0,
+ "The number of packages marked for installation."},
+ {"keep_count",PkgDepCacheGetKeepCount,0,
+ "The number of packages marked for keep."},
+ {"usr_size",PkgDepCacheGetUsrSize,0,
+ "The amount of space required for installing/removing the packages,\n"
+ "i.e. the Installed-Size of all packages marked for installation\n"
+ "minus the Installed-Size of all packages for removal."},
+ {"policy",PkgDepCacheGetPolicy,0,
+ "The apt_pkg.Policy object used by this cache."},
+ {}
+};
+
+static PyObject *PkgDepCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"cache", 0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyCache_Type,
+ &Owner) == 0)
+ return 0;
+
+
+ // the owner of the Python cache object is a cachefile object, get it
+ PyObject *CacheFilePy = GetOwner<pkgCache*>(Owner);
+ // get the pkgCacheFile from the cachefile
+ pkgCacheFile *CacheF = GetCpp<pkgCacheFile*>(CacheFilePy);
+ // and now the depcache
+ pkgDepCache *depcache = (pkgDepCache *)(*CacheF);
+
+ CppPyObject<pkgDepCache*> *DepCachePyObj;
+ DepCachePyObj = CppPyObject_NEW<pkgDepCache*>(Owner,type,depcache);
+
+ // Do not delete the underlying pointer, it is managed by the cachefile.
+ DepCachePyObj->NoDelete = true;
+
+ return HandleErrors(DepCachePyObj);
+}
+
+static char *doc_PkgDepCache = "DepCache(cache: apt_pkg.Cache)\n\n"
+ "A DepCache() holds extra information on the state of the packages.\n\n"
+ "The parameter 'cache' refers to an apt_pkg.Cache() object.";
+PyTypeObject PyDepCache_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.DepCache", // tp_name
+ sizeof(CppPyObject<pkgDepCache *>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgDepCache *>, // 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
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ doc_PkgDepCache, // tp_doc
+ CppTraverse<pkgDepCache *>, // tp_traverse
+ CppClear<pkgDepCache *>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgDepCacheMethods, // tp_methods
+ 0, // tp_members
+ PkgDepCacheGetSet, // 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
+ PkgDepCacheNew, // tp_new
+};
+
+
+
+
+ /*}}}*/
+
+#undef VALIDATE_ITERATOR
+#define VALIDATE_ITERATOR(I) (void) 0 // FIXME: Need access to depcache of pkgProblemResolver
+
+// pkgProblemResolver Class /*{{{*/
+// ---------------------------------------------------------------------
+static PyObject *PkgProblemResolverNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"depcache",0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type,
+ &Owner) == 0)
+ return 0;
+
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Owner);
+ pkgProblemResolver *fixer = new pkgProblemResolver(depcache);
+ CppPyObject<pkgProblemResolver*> *PkgProblemResolverPyObj;
+ PkgProblemResolverPyObj = CppPyObject_NEW<pkgProblemResolver*>(Owner,
+ type,
+ fixer);
+ HandleErrors(PkgProblemResolverPyObj);
+
+ return PkgProblemResolverPyObj;
+}
+
+
+static PyObject *PkgProblemResolverResolve(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+
+ char brokenFix=1;
+ if (PyArg_ParseTuple(Args,"|b",&brokenFix) == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fixer->Resolve(brokenFix);
+ Py_END_ALLOW_THREADS
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyObject *PkgProblemResolverResolveByKeep(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fixer->ResolveByKeep();
+ Py_END_ALLOW_THREADS
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyObject *PkgProblemResolverProtect(PyObject *Self,PyObject *Args)
+{
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ fixer->Protect(Pkg);
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+
+}
+static PyObject *PkgProblemResolverRemove(PyObject *Self,PyObject *Args)
+{
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ fixer->Remove(Pkg);
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgProblemResolverClear(PyObject *Self,PyObject *Args)
+{
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ fixer->Clear(Pkg);
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgProblemResolverKeepPhasedUpdates(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fixer->KeepPhasedUpdates();
+ Py_END_ALLOW_THREADS
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+
+static PyMethodDef PkgProblemResolverMethods[] =
+{
+ // config
+ {"protect", PkgProblemResolverProtect, METH_VARARGS,
+ "protect(pkg: apt_pkg.Package)\n\n"
+ "Mark the package as protected in the resolver, meaning that its\n"
+ "state will not be changed."},
+ {"remove", PkgProblemResolverRemove, METH_VARARGS,
+ "remove(pkg: apt_pkg.Package)\n\n"
+ "Mark the package for removal in the resolver."},
+ {"clear", PkgProblemResolverClear, METH_VARARGS,
+ "clear(pkg: apt_pkg.Package)\n\n"
+ "Revert the actions done by protect()/remove() on the package."},
+
+ // Actions
+ {"resolve", PkgProblemResolverResolve, METH_VARARGS,
+ "resolve([fix_broken: bool = True]) -> bool\n\n"
+ "Try to intelligently resolve problems by installing and removing\n"
+ "packages. If 'fix_broken' is True, apt will try to repair broken\n"
+ "dependencies of installed packages."},
+ {"resolve_by_keep", PkgProblemResolverResolveByKeep, METH_VARARGS,
+ "resolve_by_keep() -> bool\n\n"
+ "Try to resolve problems only by using keep."},
+ {"keep_phased_updates", PkgProblemResolverKeepPhasedUpdates, METH_VARARGS,
+ "keep_phased_updates() -> bool\n\n"
+ "Hold back upgrades to phased versions of already installed\n"
+ "packages, unless they are security updates."},
+ {}
+};
+
+static const char *problemresolver_doc =
+ "ProblemResolver(depcache: apt_pkg.DepCache)\n\n"
+ "ProblemResolver objects take care of resolving problems\n"
+ "with dependencies. They mark packages for installation/\n"
+ "removal and try to satisfy all dependencies.";
+PyTypeObject PyProblemResolver_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.ProblemResolver", // tp_name
+ sizeof(CppPyObject<pkgProblemResolver *>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgProblemResolver *>,// 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
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ problemresolver_doc, // tp_doc
+ CppTraverse<pkgProblemResolver *>, // tp_traverse
+ CppClear<pkgProblemResolver *>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgProblemResolverMethods, // tp_methods
+ 0, // 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
+ PkgProblemResolverNew, // tp_new
+};
+
+ /*}}}*/
+
+// pkgActionGroup Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static const char *actiongroup_release_doc =
+ "release()\n\n"
+ "End the scope of this action group. If this is the only action\n"
+ "group bound to the cache, this will cause any deferred cleanup\n"
+ "actions to be performed.";
+static PyObject *PkgActionGroupRelease(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache::ActionGroup *ag = GetCpp<pkgDepCache::ActionGroup*>(Self);
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+ ag->release();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static const char *actiongroup__enter__doc =
+ "__enter__() -> ActionGroup\n\n"
+ "A dummy action which just returns the object itself, so it can\n"
+ "be used as a context manager.";
+static PyObject *PkgActionGroupEnter(PyObject *Self,PyObject *Args) {
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+ Py_INCREF(Self);
+ return Self;
+}
+
+static const char *actiongroup__exit__doc =
+ "__exit__(*excinfo) -> bool\n\n"
+ "Same as release(), but for use as a context manager.";
+static PyObject *PkgActionGroupExit(PyObject *Self,PyObject *Args) {
+ pkgDepCache::ActionGroup *ag = GetCpp<pkgDepCache::ActionGroup*>(Self);
+ if (ag != NULL)
+ ag->release();
+ Py_RETURN_FALSE;
+}
+
+static PyMethodDef PkgActionGroupMethods[] =
+{
+ {"release", PkgActionGroupRelease, METH_VARARGS, actiongroup_release_doc},
+ {"__enter__", PkgActionGroupEnter, METH_VARARGS, actiongroup__enter__doc},
+ {"__exit__", PkgActionGroupExit, METH_VARARGS, actiongroup__exit__doc},
+ {}
+};
+
+static PyObject *PkgActionGroupNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"depcache", 0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type,
+ &Owner) == 0)
+ return 0;
+
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Owner);
+ pkgDepCache::ActionGroup *group = new pkgDepCache::ActionGroup(*depcache);
+ CppPyObject<pkgDepCache::ActionGroup*> *PkgActionGroupPyObj;
+ PkgActionGroupPyObj = CppPyObject_NEW<pkgDepCache::ActionGroup*>(Owner,
+ type,
+ group);
+ HandleErrors(PkgActionGroupPyObj);
+
+ return PkgActionGroupPyObj;
+
+}
+
+static char *doc_PkgActionGroup = "ActionGroup(depcache)\n\n"
+ "Create a new ActionGroup() object. The parameter *depcache* refers to an\n"
+ "apt_pkg.DepCache() object.\n\n"
+ "ActionGroups disable certain cleanup actions, so modifying many packages\n"
+ "is much faster.\n\n"
+ "ActionGroup() can also be used with the 'with' statement, but be aware\n"
+ "that the ActionGroup() is active as soon as it is created, and not just\n"
+ "when entering the context. This means you can write::\n\n"
+ " with apt_pkg.ActionGroup(depcache):\n"
+ " depcache.markInstall(pkg)\n\n"
+ "Once the block of the with statement is left, the action group is \n"
+ "automatically released from the cache.";
+
+
+PyTypeObject PyActionGroup_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.ActionGroup", // tp_name
+ sizeof(CppPyObject<pkgDepCache::ActionGroup*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgDepCache::ActionGroup*>, // 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 |
+ Py_TPFLAGS_HAVE_GC),
+ doc_PkgActionGroup, // tp_doc
+ CppTraverse<pkgDepCache::ActionGroup*>, // tp_traverse
+ CppClear<pkgDepCache::ActionGroup*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgActionGroupMethods, // tp_methods
+ 0, // 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
+ PkgActionGroupNew, // tp_new
+};
+
+
+
+ /*}}}*/
diff --git a/python/generic.cc b/python/generic.cc
new file mode 100644
index 0000000..16f1cce
--- /dev/null
+++ b/python/generic.cc
@@ -0,0 +1,122 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: generic.cc,v 1.1.1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ generic - Some handy functions to make integration a tad simpler
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+using namespace std;
+
+
+#include <apt-pkg/error.h>
+ /*}}}*/
+
+// HandleErrors - This moves errors from _error to Python Exceptions /*{{{*/
+// ---------------------------------------------------------------------
+/* We throw away all warnings and only propogate the first error. */
+PyObject *HandleErrors(PyObject *Res)
+{
+ string Err;
+ int errcnt = 0;
+ int wrncnt = 0;
+ while (_error->empty() == false)
+ {
+ string Msg;
+ bool Type = _error->PopMessage(Msg);
+ if (errcnt > 0 || wrncnt > 0)
+ Err.append(", ");
+ Err.append((Type == true ? "E:" : "W:"));
+ Err.append(Msg);
+ if (Type)
+ ++errcnt;
+ else
+ ++wrncnt;
+ }
+ if (errcnt > 0)
+ {
+ PyErr_SetString(PyAptError,Err.c_str());
+ goto err;
+ }
+ else if (wrncnt > 0)
+ {
+ if (PyErr_WarnEx(PyAptWarning, Err.c_str(), 1) == -1)
+ goto err;
+ }
+
+ return Res;
+err:
+ if (Res != 0)
+ Py_DECREF(Res);
+
+ return nullptr;
+}
+
+ /*}}}*/
+// ListToCharChar - Convert a list to an array of char char /*{{{*/
+// ---------------------------------------------------------------------
+/* Caller must free the result. 0 on error. */
+const char **ListToCharChar(PyObject *List,bool NullTerm)
+{
+ // Convert the argument list into a char **
+ int Length = PySequence_Length(List);
+ const char **Res = new const char *[Length + (NullTerm == true?1:0)];
+ for (int I = 0; I != Length; I++)
+ {
+ PyObject *Itm = PySequence_GetItem(List,I);
+ Res[I] = PyObject_AsString(Itm);
+ if (Res[I] == nullptr) {
+ delete [] Res;
+ return nullptr;
+ }
+ }
+ if (NullTerm == true)
+ Res[Length] = 0;
+ return Res;
+}
+ /*}}}*/
+// CharCharToList - Inverse of the above /*{{{*/
+// ---------------------------------------------------------------------
+/* Zero size indicates the list is Null terminated. */
+PyObject *CharCharToList(const char **List,unsigned long Size)
+{
+ if (Size == 0)
+ {
+ for (const char **I = List; *I != 0; I++)
+ Size++;
+ }
+
+ // Convert the whole configuration space into a list
+ PyObject *PList = PyList_New(Size);
+ for (unsigned long I = 0; I != Size; I++, List++)
+ PyList_SetItem(PList,I,CppPyString(*List));
+
+ return PList;
+}
+ /*}}}*/
+
+int PyApt_Filename::init(PyObject *object)
+{
+ this->object = NULL;
+ this->path = NULL;
+
+#if PY_MAJOR_VERSION < 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 2)
+ this->path = PyObject_AsString(object);
+ return this->path ? 1 : 0;
+#else
+ if (PyUnicode_Check(object)) {
+ object = PyUnicode_EncodeFSDefault(object);
+ } else if (PyBytes_Check(object)) {
+ Py_INCREF(object);
+ } else {
+ return 0;
+ }
+
+ this->object = object;
+ this->path = PyBytes_AS_STRING(this->object);
+ return 1;
+#endif
+}
diff --git a/python/generic.h b/python/generic.h
new file mode 100644
index 0000000..60f9531
--- /dev/null
+++ b/python/generic.h
@@ -0,0 +1,336 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: generic.h,v 1.4 2002/03/10 05:45:34 mdz Exp $
+/* ######################################################################
+
+ generic - Some handy functions to make integration a tad simpler
+
+ Python needs this little _HEAD tacked onto the front of the object..
+ This complicates the integration with C++. We use some templates to
+ make that quite transparent to us. It would have been nice if Python
+ internally used a page from the C++ ref counting book to hide its little
+ header from the world, but it doesn't.
+
+ The CppPyObject has the target object and the Python header, this is
+ needed to ensure proper alignment.
+ GetCpp returns the C++ object from a PyObject.
+ CppPyObject_NEW creates the Python object and then uses placement new
+ to init the C++ class.. This is good for simple situations and as an
+ example on how to do it in other more specific cases.
+ CppPyObject_Dealloc should be used in the Type as the destructor
+ function.
+ HandleErrors converts errors from the internal _error stack into Python
+ exceptions and makes sure the _error stack is empty.
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef GENERIC_H
+#define GENERIC_H
+
+#include <Python.h>
+#include <string>
+#include <iostream>
+#include <new>
+#include <langinfo.h>
+
+/**
+ * Exception class for almost all Python errors
+ */
+extern PyObject *PyAptError;
+extern PyObject *PyAptWarning;
+/**
+ * Exception class for invalidated cache objects.
+ */
+extern PyObject *PyAptCacheMismatchError;
+
+#if PYTHON_API_VERSION < 1013
+typedef int Py_ssize_t;
+#endif
+
+/* Define compatibility for Python 3.
+ *
+ * We will use the names PyString_* to refer to the default string type
+ * of the current Python version (PyString on 2.X, PyUnicode on 3.X).
+ *
+ * When we really need unicode strings, we will use PyUnicode_* directly, as
+ * long as it exists in Python 2 and Python 3.
+ *
+ * When we want bytes in Python 3, we use PyBytes*_ instead of PyString_* and
+ * define aliases from PyBytes_* to PyString_* for Python 2.
+ */
+
+#if PY_MAJOR_VERSION >= 3
+#define PyString_Check PyUnicode_Check
+#define PyString_FromString PyUnicode_FromString
+#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+#define PyString_AsString PyUnicode_AsString
+#define PyString_FromFormat PyUnicode_FromFormat
+#define PyString_Type PyUnicode_Type
+#define PyInt_Check PyLong_Check
+#define PyInt_AsLong PyLong_AsLong
+#define PyInt_FromLong PyLong_FromLong
+#endif
+
+static inline const char *PyUnicode_AsString(PyObject *op) {
+ // Convert to bytes object, using the default encoding.
+#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
+ return PyUnicode_AsUTF8(op);
+#else
+ // Use Python-internal API, there is no other way to do this
+ // without a memory leak.
+ PyObject *bytes = _PyUnicode_AsDefaultEncodedString(op, 0);
+ return bytes ? PyBytes_AS_STRING(bytes) : 0;
+#endif
+}
+
+// Convert any type of string based object to a const char.
+#if PY_MAJOR_VERSION < 3
+static inline const char *PyObject_AsString(PyObject *object) {
+ if (PyBytes_Check(object))
+ return PyBytes_AsString(object);
+ else if (PyUnicode_Check(object))
+ return PyUnicode_AsString(object);
+ else
+ PyErr_SetString(PyExc_TypeError, "Argument must be str.");
+ return 0;
+}
+#else
+static inline const char *PyObject_AsString(PyObject *object) {
+ if (PyUnicode_Check(object) == 0) {
+ PyErr_SetString(PyExc_TypeError, "Argument must be str.");
+ return 0;
+ }
+ return PyUnicode_AsString(object);
+}
+#endif
+
+template <class T> struct CppPyObject : public PyObject
+{
+ // We are only using CppPyObject and friends as dumb structs only, ie the
+ // c'tor is never called.
+ // However if T doesn't have a default c'tor C++ doesn't generate one for
+ // CppPyObject (since it can't know how it should initialize Object).
+ //
+ // This causes problems then in CppPyObject, for which C++ can't create
+ // a c'tor that calls the base class c'tor (which causes a compilation
+ // error).
+ // So basically having the c'tor here removes the need for T to have a
+ // default c'tor, which is not always desireable.
+ CppPyObject() { };
+
+ // The owner of the object. The object keeps a reference to it during its
+ // lifetime.
+ PyObject *Owner;
+
+ // Flag which causes the underlying object to not be deleted.
+ bool NoDelete;
+
+ // The underlying C++ object.
+ T Object;
+};
+
+template <class T>
+inline T &GetCpp(PyObject *Obj)
+{
+ return ((CppPyObject<T> *)Obj)->Object;
+}
+
+template <class T>
+inline PyObject *GetOwner(PyObject *Obj)
+{
+ return ((CppPyObject<T> *)Obj)->Owner;
+}
+
+
+template <class T>
+inline CppPyObject<T> *CppPyObject_NEW(PyObject *Owner,PyTypeObject *Type)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n";
+ #endif
+ CppPyObject<T> *New = (CppPyObject<T>*)Type->tp_alloc(Type, 0);
+ new (&New->Object) T;
+ New->Owner = Owner;
+ Py_XINCREF(Owner);
+ return New;
+}
+
+template <class T,class A>
+inline CppPyObject<T> *CppPyObject_NEW(PyObject *Owner, PyTypeObject *Type,A const &Arg)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n";
+ #endif
+ CppPyObject<T> *New = (CppPyObject<T>*)Type->tp_alloc(Type, 0);
+ new (&New->Object) T(Arg);
+ New->Owner = Owner;
+ Py_XINCREF(Owner);
+ return New;
+}
+
+// Traversal and Clean for objects
+template <class T>
+int CppTraverse(PyObject *self, visitproc visit, void* arg) {
+ Py_VISIT(((CppPyObject<T> *)self)->Owner);
+ return 0;
+}
+
+template <class T>
+int CppClear(PyObject *self) {
+ Py_CLEAR(((CppPyObject<T> *)self)->Owner);
+ return 0;
+}
+
+template <class T>
+void CppDealloc(PyObject *iObj)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "+ ===\n";
+ #endif
+ if (iObj->ob_type->tp_flags & Py_TPFLAGS_HAVE_GC)
+ PyObject_GC_UnTrack(iObj);
+ CppPyObject<T> *Obj = (CppPyObject<T> *)iObj;
+ if (!((CppPyObject<T>*)Obj)->NoDelete)
+ Obj->Object.~T();
+ CppClear<T>(iObj);
+ iObj->ob_type->tp_free(iObj);
+}
+
+
+template <class T>
+void CppDeallocPtr(PyObject *iObj)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "*+ ===\n";
+ #endif
+ if (iObj->ob_type->tp_flags & Py_TPFLAGS_HAVE_GC)
+ PyObject_GC_UnTrack(iObj);
+ CppPyObject<T> *Obj = (CppPyObject<T> *)iObj;
+ if (!((CppPyObject<T>*)Obj)->NoDelete) {
+ delete Obj->Object;
+ Obj->Object = NULL;
+ }
+ CppClear<T>(iObj);
+ iObj->ob_type->tp_free(iObj);
+}
+
+inline PyObject *CppPyString(const std::string &Str)
+{
+ return PyString_FromStringAndSize(Str.c_str(),Str.length());
+}
+
+inline PyObject *CppPyString(const char *Str)
+{
+ if (Str == 0)
+ return PyString_FromString("");
+ return PyString_FromString(Str);
+}
+
+inline PyObject *CppPyLocaleString(const std::string &Str)
+{
+ char const * const codeset = nl_langinfo(CODESET);
+ return PyUnicode_Decode(Str.c_str(), Str.length(), codeset, "replace");
+}
+
+#if PY_MAJOR_VERSION >= 3
+static inline PyObject *CppPyPath(const std::string &path)
+{
+ return PyUnicode_DecodeFSDefaultAndSize(path.c_str(), path.length());
+}
+
+static inline PyObject *CppPyPath(const char *path)
+{
+ if (path == nullptr)
+ path = "";
+ return PyUnicode_DecodeFSDefault(path);
+}
+#else
+template<typename T> static inline PyObject *CppPyPath(T path) {
+ return CppPyString(path);
+}
+#endif
+
+// Convert _error into Python exceptions
+PyObject *HandleErrors(PyObject *Res = 0);
+
+// Convert a list of strings to a char **
+const char **ListToCharChar(PyObject *List,bool NullTerm = false);
+PyObject *CharCharToList(const char **List,unsigned long Size = 0);
+
+/* Happy number conversion, thanks to overloading */
+inline PyObject *MkPyNumber(unsigned long long o) { return PyLong_FromUnsignedLongLong(o); }
+inline PyObject *MkPyNumber(unsigned long o) { return PyLong_FromUnsignedLong(o); }
+inline PyObject *MkPyNumber(unsigned int o) { return PyLong_FromUnsignedLong(o); }
+inline PyObject *MkPyNumber(unsigned short o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(unsigned char o) { return PyInt_FromLong(o); }
+
+inline PyObject *MkPyNumber(long long o) { return PyLong_FromLongLong(o); }
+inline PyObject *MkPyNumber(long o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(int o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(short o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(signed char o) { return PyInt_FromLong(o); }
+
+inline PyObject *MkPyNumber(double o) { return PyFloat_FromDouble(o); }
+
+# define _PyAptObject_getattro 0
+
+
+/**
+ * Magic class for file name handling
+ *
+ * This manages decoding file names from Python objects; bytes and unicode
+ * objects. On Python 2, this does the same conversion as PyObject_AsString,
+ * on Python3, it uses PyUnicode_EncodeFSDefault for unicode objects.
+ */
+class PyApt_Filename {
+public:
+ PyObject *object;
+ const char *path;
+
+ PyApt_Filename() {
+ object = NULL;
+ path = NULL;
+ }
+
+ int init(PyObject *object);
+
+ ~PyApt_Filename() {
+ Py_XDECREF(object);
+ }
+
+ static int Converter(PyObject *object, void *out) {
+ return static_cast<PyApt_Filename *>(out)->init(object);
+ }
+
+ operator const char *() {
+ return path;
+ }
+ operator const std::string() {
+ return path;
+ }
+
+ const char *operator=(const char *path) {
+ return this->path = path;
+ }
+};
+
+
+/**
+ * Basic smart pointer to hold initial objects.
+ *
+ * This is like a std::unique_ptr<PyObject, decltype(&Py_DecRef)> to some extend,
+ * but it is for initialization only, and hence will also clear out any members
+ * in case it deletes the instance (the error case).
+ */
+template <class T, bool clear=true> struct PyApt_UniqueObject {
+ T *self;
+ explicit PyApt_UniqueObject(T *self) : self(self) { }
+ ~PyApt_UniqueObject() { reset(NULL); }
+ void reset(T *newself) { if (clear && self && Py_TYPE(self)->tp_clear) Py_TYPE(self)->tp_clear(self); Py_XDECREF(self); self = newself; }
+ PyApt_UniqueObject<T> operator =(PyApt_UniqueObject<T>) = delete;
+ bool operator ==(void *other) { return self == other; }
+ T *operator ->() { return self; }
+ T *get() { return self; }
+ T *release() { T *ret = self; self = NULL; return ret; }
+};
+#endif
diff --git a/python/hashes.cc b/python/hashes.cc
new file mode 100644
index 0000000..9f3fb46
--- /dev/null
+++ b/python/hashes.cc
@@ -0,0 +1,135 @@
+/* hashes.cc - Wrapper around apt-pkg's Hashes.
+ *
+ * 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 <Python.h>
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include <apt-pkg/hashes.h>
+
+static PyObject *hashes_new(PyTypeObject *type,PyObject *args,
+ PyObject *kwds)
+{
+ return CppPyObject_NEW<Hashes>(NULL, type);
+}
+
+static int hashes_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *object = 0;
+ int Fd;
+ char *kwlist[] = {"object", NULL};
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O:__init__", kwlist,
+ &object) == 0)
+ return -1;
+ if (object == 0)
+ return 0;
+ Hashes &hashes = GetCpp<Hashes>(self);
+
+ if (PyBytes_Check(object) != 0) {
+ char *s;
+ Py_ssize_t len;
+ PyBytes_AsStringAndSize(object, &s, &len);
+ Py_BEGIN_ALLOW_THREADS
+ hashes.Add((const unsigned char*)s, len);
+ Py_END_ALLOW_THREADS
+ }
+ else if ((Fd = PyObject_AsFileDescriptor(object)) != -1) {
+ struct stat St;
+ bool err = false;
+ Py_BEGIN_ALLOW_THREADS
+ err = fstat(Fd, &St) != 0 || hashes.AddFD(Fd, St.st_size) == false;
+ Py_END_ALLOW_THREADS
+ if (err) {
+ PyErr_SetFromErrno(PyAptError);
+ return -1;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "__init__() only understand bytes and files");
+ return -1;
+ }
+ return 0;
+}
+
+static PyObject *hashes_get_hashes(PyObject *self, void*)
+{
+ auto py = CppPyObject_NEW<HashStringList>(nullptr, &PyHashStringList_Type);
+
+ py->Object = GetCpp<Hashes>(self).GetHashStringList();
+ return py;
+}
+
+
+static PyGetSetDef hashes_getset[] = {
+ {"hashes",hashes_get_hashes,0,
+ "A :class:`HashStringList` of all hashes.\n\n"
+ ".. versionadded:: 1.1"},
+ {}
+};
+
+static char *hashes_doc =
+ "Hashes([object: (bytes, file)])\n\n"
+ "Calculate hashes for the given object. It can be used to create all\n"
+ "supported hashes for a file.\n\n"
+ "The parameter *object* can be a bytestring, an object providing the\n"
+ "fileno() method, or an integer describing a file descriptor.";
+
+PyTypeObject PyHashes_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Hashes", // tp_name
+ sizeof(CppPyObject<Hashes>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<Hashes>, // 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,
+ hashes_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ hashes_getset, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ hashes_init, // tp_init
+ 0, // tp_alloc
+ hashes_new, // tp_new
+};
diff --git a/python/hashstring.cc b/python/hashstring.cc
new file mode 100644
index 0000000..01f14a0
--- /dev/null
+++ b/python/hashstring.cc
@@ -0,0 +1,182 @@
+/* hashstring.cc - Wrapper around HashString
+ *
+ * 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 <Python.h>
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include <apt-pkg/hashes.h>
+
+static PyObject *hashstring_new(PyTypeObject *type,PyObject *Args,
+ PyObject *kwds)
+{
+ char *Type = NULL;
+ char *Hash = NULL;
+ char *kwlist[] = {"type", "hash", NULL};
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, "s|s:__new__", kwlist, &Type,
+ &Hash) == 0)
+ return 0;
+ CppPyObject<HashString*> *PyObj = CppPyObject_NEW<HashString*>(NULL, type);
+ if (Hash)
+ PyObj->Object = new HashString(Type,Hash);
+ else // Type is the combined form now (i.e. type:hash)
+ PyObj->Object = new HashString(Type);
+ return PyObj;
+}
+
+static PyObject *hashstring_repr(PyObject *self)
+{
+ HashString *hash = GetCpp<HashString*>(self);
+ return PyString_FromFormat("<%s object: \"%s\">", self->ob_type->tp_name,
+ hash->toStr().c_str());
+}
+
+static PyObject *hashstring_str(PyObject *self)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ return CppPyString(hash->toStr());
+}
+
+static PyObject *hashstring_get_hashtype(PyObject *self)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ return CppPyString(hash->HashType());
+}
+
+static PyObject *hashstring_get_usable(PyObject *self)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ return PyBool_FromLong(hash->usable());
+}
+
+static PyObject *hashstring_get_hashvalue(PyObject *self)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ return CppPyString(hash->HashValue());
+}
+
+static char *hashstring_verify_file_doc =
+ "verify_file(filename: str) -> bool\n\n"
+ "Verify that the file indicated by filename matches the hash.";
+
+static PyObject *hashstring_verify_file(PyObject *self,PyObject *args)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ char *filename;
+ if (PyArg_ParseTuple(args, "s:verify_file", &filename) == 0)
+ return 0;
+ return PyBool_FromLong(hash->VerifyFile(filename));
+}
+
+static PyMethodDef hashstring_methods[] = {
+ {"verify_file",hashstring_verify_file,METH_VARARGS,
+ hashstring_verify_file_doc},
+ {NULL}
+};
+
+static PyGetSetDef hashstring_getset[] = {
+ {"hashtype",(getter)hashstring_get_hashtype,0,
+ "The type of the hash, as a string (possible: MD5Sum,SHA1,SHA256)."},
+ {"hashvalue",(getter)hashstring_get_hashvalue,0,
+ "The value of the hash, as a hexadecimal string\n"
+ "\n"
+ ".. versionadded:: 1.9.0"},
+ {"usable",(getter)hashstring_get_usable,0,
+ "True if the hashstring is a trusted hash type."},
+ {NULL}
+};
+
+static PyObject *hashstring_richcompare(PyObject *obj1, PyObject *obj2, int op)
+{
+ if (!PyObject_TypeCheck(obj1, &PyHashString_Type))
+ return PyErr_SetString(PyExc_TypeError, "Expected HashString"), nullptr;
+ if (!PyObject_TypeCheck(obj2, &PyHashString_Type))
+ return PyErr_SetString(PyExc_TypeError, "Expected HashString"), nullptr;
+
+ const HashString *a = GetCpp<HashString*>(obj1);
+ const HashString *b = GetCpp<HashString*>(obj2);
+ PyObject *result = Py_False;
+
+ switch (op) {
+ case Py_LT:
+ case Py_GT:
+ result = Py_False;
+ break;
+ case Py_LE:
+ case Py_GE:
+ case Py_EQ:
+ result = *a == *b ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = *a != *b ? Py_True : Py_False;
+ break;
+ }
+
+ Py_INCREF(result);
+ return result;
+ }
+
+static char *hashstring_doc =
+ "HashString(type, hash) OR HashString('type:hash')\n\n"
+ "Create a new HashString object. The first form allows you to specify\n"
+ "a type and a hash, and the second form a single string where type and\n"
+ "hash are separated by a colon, e.g.::\n\n"
+ " HashString('MD5Sum', '6cc1b6e6655e3555ac47e5b5fe26d04e')\n\n"
+ "Valid options for 'type' are: MD5Sum, SHA1, SHA256.";
+PyTypeObject PyHashString_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.HashString", // tp_name
+ sizeof(CppPyObject<HashString*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<HashString*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ hashstring_repr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ hashstring_str, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE,
+ hashstring_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ hashstring_richcompare, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ hashstring_methods, // tp_methods
+ 0, // tp_members
+ hashstring_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
+ hashstring_new, // tp_new
+};
diff --git a/python/hashstringlist.cc b/python/hashstringlist.cc
new file mode 100644
index 0000000..f25f502
--- /dev/null
+++ b/python/hashstringlist.cc
@@ -0,0 +1,220 @@
+/* hashstringlist.cc - Wrapper around apt-pkg's Hashes.
+ *
+ * Copyright 2015 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 <Python.h>
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include <apt-pkg/hashes.h>
+
+static PyObject *hashstringlist_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ return CppPyObject_NEW<HashStringList> (nullptr, type);
+}
+
+static int hashstringlist_init(PyObject *self, PyObject *args,
+ PyObject *kwds)
+{
+ char *kwlist[] = { NULL };
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist) == 0)
+ return -1;
+
+ return 0;
+}
+
+
+static const char hashstringlist_find_doc[] =
+ "find(type: str = \"\") -> HashString\n\n"
+ "Find a hash of the given type, or the best one, if the argument\n"
+ "is empty or not specified.";
+static PyObject *hashstringlist_find(PyObject *self, PyObject *args)
+{
+ char *type = "";
+
+ if (PyArg_ParseTuple(args, "|s", &type) == 0)
+ return 0;
+
+ const HashString *hsf = GetCpp<HashStringList>(self).find(type);
+ if (hsf == nullptr)
+ return PyErr_Format(PyExc_KeyError, "Could not find hash type %s", type);
+
+
+ return HandleErrors(PyHashString_FromCpp(new HashString(*hsf), true, nullptr));
+}
+
+static const char hashstringlist_append_doc[] =
+ "append(object: HashString)\n\n"
+ "Append the given HashString to this list.";
+static PyObject *hashstringlist_append(PyObject *self, PyObject *args)
+{
+ PyObject *o;
+
+ if (PyArg_ParseTuple(args, "O!", &PyHashString_Type, &o) == 0)
+ return 0;
+
+ GetCpp<HashStringList>(self).push_back(*PyHashString_ToCpp(o));
+ Py_RETURN_NONE;
+}
+
+static const char hashstringlist_verify_file_doc[] =
+ "verify_file(filename: str) -> bool\n\n"
+ "Verify that the file with the given name matches all hashes in\n"
+ "the list.";
+static PyObject *hashstringlist_verify_file(PyObject *self, PyObject *args)
+{
+ PyApt_Filename filename;
+
+ if (PyArg_ParseTuple(args, "O&", PyApt_Filename::Converter, &filename) == 0)
+ return 0;
+
+ bool res = GetCpp<HashStringList>(self).VerifyFile(filename);
+
+ PyObject *PyRes = PyBool_FromLong(res);
+ return HandleErrors(PyRes);
+}
+
+static PyObject *hashstringlist_get_file_size(PyObject *self, void*) {
+ return MkPyNumber(GetCpp<HashStringList>(self).FileSize());
+}
+static PyObject *hashstringlist_get_usable(PyObject *self, void*) {
+ return PyBool_FromLong(GetCpp<HashStringList>(self).usable());
+}
+
+static int hashstringlist_set_file_size(PyObject *self, PyObject *value, void *) {
+ if (PyLong_Check(value)) {
+ if (PyLong_AsUnsignedLongLong(value) == (unsigned long long) -1) {
+ return 1;
+ }
+ GetCpp<HashStringList>(self).FileSize(PyLong_AsUnsignedLongLong(value));
+ } else if (PyInt_Check(value)) {
+ if (PyInt_AsLong(value) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_OverflowError,
+ "The file_size value must be positive");
+ return 1;
+ }
+ GetCpp<HashStringList>(self).FileSize(PyInt_AsLong(value));
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "The file_size value must be an integer or long");
+ return 1;
+ }
+
+ return 0;
+}
+
+/* The same for groups */
+static Py_ssize_t hashstringlist_len(PyObject *self)
+{
+ return GetCpp <HashStringList>(self).size();
+}
+
+static PyObject *hashstringlist_getitem(PyObject *iSelf, Py_ssize_t index)
+{
+ HashStringList &self = GetCpp<HashStringList>(iSelf);
+
+ if (index < 0 || (size_t) index >= self.size())
+ return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index);
+
+ /* Copy over, safer than using a reference to the vector element */
+ HashString *hs = new HashString;
+ (*hs) = *(self.begin() + index);
+
+ return PyHashString_FromCpp(hs, true, nullptr);
+}
+
+static PySequenceMethods hashstringlist_seq_methods = {
+ hashstringlist_len,
+ 0, // concat
+ 0, // repeat
+ hashstringlist_getitem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+static PyMethodDef hashstringlist_methods[] =
+{
+ {"verify_file",hashstringlist_verify_file,METH_VARARGS,
+ hashstringlist_verify_file_doc},
+ {"find",hashstringlist_find,METH_VARARGS,
+ hashstringlist_find_doc},
+ {"append",hashstringlist_append,METH_VARARGS,
+ hashstringlist_append_doc},
+ {}
+};
+
+static PyGetSetDef hashstringlist_getset[] = {
+ {"file_size",hashstringlist_get_file_size,hashstringlist_set_file_size,
+ "If a file size is part of the list, return it, otherwise 0."},
+ {"usable",hashstringlist_get_usable,nullptr,
+ "True if at least one safe/trusted hash is in the list."},
+ {}
+};
+
+
+static char *hashstringlist_doc =
+ "HashStringList()\n\n"
+ "Manage a list of HashStrings.\n\n"
+ "The list knows which hash is the best and provides convenience\n"
+ "methods for file verification.\n\n"
+ ".. versionadded:: 1.1";
+
+PyTypeObject PyHashStringList_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.HashStringList", // tp_name
+ sizeof(CppPyObject<HashStringList>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<HashStringList>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &hashstringlist_seq_methods, // 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
+ hashstringlist_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ hashstringlist_methods, // tp_methods
+ 0, // tp_members
+ hashstringlist_getset, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ hashstringlist_init, // tp_init
+ 0, // tp_alloc
+ hashstringlist_new, // tp_new
+};
diff --git a/python/indexfile.cc b/python/indexfile.cc
new file mode 100644
index 0000000..423e2e3
--- /dev/null
+++ b/python/indexfile.cc
@@ -0,0 +1,130 @@
+// -*- 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 *IndexFileArchiveURI(PyObject *Self,PyObject *Args)
+{
+ pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self);
+ PyApt_Filename path;
+
+ if (PyArg_ParseTuple(Args, "O&", PyApt_Filename::Converter, &path) == 0)
+ return 0;
+ return HandleErrors(CppPyString(File->ArchiveURI(path).c_str()));
+}
+
+static PyMethodDef IndexFileMethods[] =
+{
+ {"archive_uri",IndexFileArchiveURI,METH_VARARGS,
+ "archive_uri(path: str) -> str\n\n"
+ "Return the URI to the given path in the archive."},
+ {}
+};
+
+#define File (GetCpp<pkgIndexFile*>(Self))
+static PyObject *IndexFileGetLabel(PyObject *Self,void*) {
+ return CppPyString(File->GetType()->Label);
+}
+static PyObject *IndexFileGetDescribe(PyObject *Self,void*) {
+ return CppPyString(File->Describe().c_str());
+}
+static PyObject *IndexFileGetExists(PyObject *Self,void*) {
+ return PyBool_FromLong((File->Exists()));
+}
+static PyObject *IndexFileGetHasPackages(PyObject *Self,void*) {
+ return PyBool_FromLong((File->HasPackages()));
+}
+static PyObject *IndexFileGetSize(PyObject *Self,void*) {
+ return MkPyNumber((File->Size()));
+}
+static PyObject *IndexFileGetIsTrusted(PyObject *Self,void*) {
+ return PyBool_FromLong((File->IsTrusted()));
+}
+#undef File
+
+#define S(x) (x ? x : "")
+static PyObject *IndexFileRepr(PyObject *Self)
+{
+ pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self);
+ return PyString_FromFormat("<pkIndexFile object: "
+ "Label:'%s' Describe='%s' Exists='%i' "
+ "HasPackages='%i' Size='%lu' "
+ "IsTrusted='%i' ArchiveURI='%s'>",
+ S(File->GetType()->Label), File->Describe().c_str(), File->Exists(),
+ File->HasPackages(), File->Size(),
+ File->IsTrusted(), File->ArchiveURI("").c_str());
+}
+#undef S
+
+static PyGetSetDef IndexFileGetSet[] = {
+ {"describe",IndexFileGetDescribe,0,
+ "A string describing the index file."},
+ {"exists",IndexFileGetExists,0,
+ "A boolean value determining whether the index file exists."},
+ {"has_packages",IndexFileGetHasPackages,0,
+ "A boolean value determining whether the index file has packages."},
+ {"is_trusted",IndexFileGetIsTrusted,0,
+ "A boolean value determining whether the file can be trusted; e.g.\n"
+ "because it is from a source with a GPG signed Release file."},
+ {"label",IndexFileGetLabel,0,
+ "The label of the index file."},
+ {"size",IndexFileGetSize,0,
+ "The size of the files, measured in bytes."},
+ {}
+};
+
+static const char *indexfile_doc =
+ "Represent an index file, i.e. package indexes, translation indexes,\n"
+ "and source indexes.";
+
+PyTypeObject PyIndexFile_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.IndexFile", // tp_name
+ sizeof(CppPyObject<pkgIndexFile*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ // Not ..Ptr, because the pointer is managed somewhere else.
+ CppDeallocPtr<pkgIndexFile*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ IndexFileRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ indexfile_doc, // tp_doc
+ CppTraverse<pkgIndexFile*>, // tp_traverse
+ CppClear<pkgIndexFile*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ IndexFileMethods, // tp_methods
+ 0, // tp_members
+ IndexFileGetSet, // tp_getset
+};
+
+
+
+
diff --git a/python/lock.cc b/python/lock.cc
new file mode 100644
index 0000000..009605e
--- /dev/null
+++ b/python/lock.cc
@@ -0,0 +1,268 @@
+/*
+ * lock.cc - Context managers for implementing locking.
+ *
+ * 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 <Python.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/pkgsystem.h>
+#include "generic.h"
+
+static PyObject *systemlock_exit(PyObject *self, PyObject *args)
+{
+
+ PyObject *exc_type = 0;
+ PyObject *exc_value = 0;
+ PyObject *traceback = 0;
+ if (!PyArg_UnpackTuple(args, "__exit__", 3, 3, &exc_type, &exc_value,
+ &traceback)) {
+ return 0;
+ }
+
+ if (_system->UnLock() == 0) {
+ // The unlock failed. If no exception happened within the suite, we
+ // will raise an error here. Otherwise, we just display the error, so
+ // Python can handle the original exception instead.
+ HandleErrors();
+ if (exc_type == Py_None)
+ return NULL;
+ else
+ PyErr_WriteUnraisable(self);
+ }
+ // Return False, as required by the context manager protocol.
+ Py_RETURN_FALSE;
+}
+
+static PyObject *systemlock_enter(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (!_system->Lock())
+ return HandleErrors();
+ Py_INCREF(self);
+ return self;
+}
+
+static PyObject *systemlock_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ if (_system == 0) {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+ return PyType_GenericNew(type,args,kwds);
+}
+
+static PyMethodDef systemlock_methods[] = {
+ {"__enter__",systemlock_enter,METH_VARARGS,"Lock the system."},
+ {"__exit__",systemlock_exit,METH_VARARGS,"Unlock the system."},
+ {NULL}
+};
+
+static char *systemlock_doc = "SystemLock()\n\n"
+ "Context manager for locking the package system. The lock is established\n"
+ "as soon as the method __enter__() is called. It is released when\n"
+ "__exit__() is called.\n\n"
+ "This should be used via the 'with' statement, for example:\n\n"
+ " with apt_pkg.SystemLock():\n"
+ " ...\n\n"
+ "Once the block is left, the lock is released automatically. The object\n"
+ "can be used multiple times:\n\n"
+ " lock = apt_pkg.SystemLock()\n"
+ " with lock:\n"
+ " ...\n"
+ " with lock:\n"
+ " ...\n\n";
+
+PyTypeObject PySystemLock_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.SystemLock", // tp_name
+ 0, // 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),
+ systemlock_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ systemlock_methods, // tp_methods
+ 0, // 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
+ systemlock_new, // tp_new
+};
+
+
+/**
+ * File Based locking.
+ *
+ * The counter is increased by every call to filelock_enter() and decreased by
+ * every call to filelock_exit(). When the counter reaches 0, the underlying
+ * file descriptor is closed.
+ *
+ * Members:
+ * @member char* filename The name of the file
+ * @member int lock_count How many times we have locked it.
+ * @member int fd The filedescriptor returned by GetLock() or 0.
+ */
+struct filelock_object {
+ PyObject_HEAD
+ char *filename;
+ int lock_count;
+ int fd;
+};
+
+static PyObject *filelock_enter(filelock_object *self, PyObject *args)
+{
+ self->lock_count++;
+ // If we have no lock yet, get a lock.
+ if (self->lock_count == 1) {
+ self->fd = GetLock(self->filename, true);
+ if (self->fd == -1) {
+ self->lock_count--;
+ return HandleErrors();
+ }
+ }
+ Py_INCREF(self);
+ return (PyObject *)self;
+}
+
+static PyObject *filelock_exit(filelock_object *self, PyObject *args)
+{
+ // Count down the lock_count, if it is less than 0, reset it to 0.
+ self->lock_count--;
+ if (self->lock_count < 0)
+ self->lock_count = 0;
+ if (self->lock_count == 0 && self->fd != 0 && close(self->fd) == -1) {
+ return PyErr_SetFromErrno(PyExc_OSError);
+ }
+ Py_RETURN_FALSE;
+}
+
+static PyObject *filelock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyApt_Filename filename;
+ char *kwlist[] = {"filename", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O&:__init__", kwlist,
+ PyApt_Filename::Converter,
+ &filename) == 0) {
+ return NULL;
+ }
+ filelock_object *self = (filelock_object *)type->tp_alloc(type, 0);
+ // Copy the string into the object.
+ self->filename = new char[strlen(filename) + 1];
+ strcpy(self->filename, filename);
+ return (PyObject *)self;
+}
+
+static void filelock_dealloc(filelock_object *self)
+{
+ delete[] self->filename;
+ ((PyObject*)self)->ob_type->tp_free(self);
+}
+
+static PyMethodDef filelock_methods[] = {
+ {"__enter__",(PyCFunction)filelock_enter,METH_VARARGS,"Lock the system."},
+ {"__exit__",(PyCFunction)filelock_exit,METH_VARARGS,"Unlock the system."},
+ {NULL}
+};
+
+static char *filelock_doc = "FileLock(filename: str)\n\n"
+ "Context manager for locking using a file. The lock is established\n"
+ "as soon as the method __enter__() is called. It is released when\n"
+ "__exit__() is called.\n\n"
+ "This should be used via the 'with' statement, for example:\n\n"
+ " with apt_pkg.FileLock(filename):\n"
+ " ...\n\n"
+ "Once the block is left, the lock is released automatically. The object\n"
+ "can be used multiple times:\n\n"
+ " lock = apt_pkg.FileLock(filename)\n"
+ " with lock:\n"
+ " ...\n"
+ " with lock:\n"
+ " ...\n\n";
+
+PyTypeObject PyFileLock_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.FileLock", // tp_name
+ sizeof(filelock_object), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ destructor(filelock_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),
+ filelock_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ filelock_methods, // tp_methods
+ 0, // 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
+ filelock_new, // tp_new
+};
diff --git a/python/metaindex.cc b/python/metaindex.cc
new file mode 100644
index 0000000..abbcb8a
--- /dev/null
+++ b/python/metaindex.cc
@@ -0,0 +1,117 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: metaindex.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $
+/* ######################################################################
+
+ metaindex - Wrapper for the metaIndex functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/metaindex.h>
+
+#include <Python.h>
+
+static PyObject *MetaIndexGetURI(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return CppPyString(meta->GetURI().c_str());
+}
+
+static PyObject *MetaIndexGetDist(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return CppPyString(meta->GetDist().c_str());
+}
+
+static PyObject *MetaIndexGetIsTrusted(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return PyBool_FromLong((meta->IsTrusted()));
+}
+
+static PyObject *MetaIndexGetType(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return CppPyString(meta->GetType());
+}
+
+static PyObject *MetaIndexGetIndexFiles(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ PyObject *List = PyList_New(0);
+ std::vector<pkgIndexFile *> *indexFiles = meta->GetIndexFiles();
+ for (std::vector<pkgIndexFile *>::const_iterator I = indexFiles->begin();
+ I != indexFiles->end(); I++)
+ {
+ CppPyObject<pkgIndexFile*> *Obj;
+ Obj = CppPyObject_NEW<pkgIndexFile*>(Self, &PyIndexFile_Type,*I);
+ // Do not delete pkgIndexFile*, they are managed by metaIndex.
+ Obj->NoDelete = true;
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyGetSetDef MetaIndexGetSet[] = {
+ {"dist",MetaIndexGetDist,0,"The distribution, as a string."},
+ {"index_files",MetaIndexGetIndexFiles,0,
+ "A list of all IndexFile objects associated with this meta index."},
+ {"is_trusted",MetaIndexGetIsTrusted,0,
+ "A boolean value determining whether the file can be trusted."},
+ {"uri",MetaIndexGetURI,0,
+ "The uri the meta index is located at."},
+ {"type",MetaIndexGetType,0,
+ "The type of the meta index."},
+ {}
+};
+
+#define S(x) (x ? x : "")
+static PyObject *MetaIndexRepr(PyObject *Self)
+{
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return PyString_FromFormat("<%s object: type='%s', uri:'%s' dist='%s' "
+ "is_trusted='%i'>", Self->ob_type->tp_name,
+ S(meta->GetType()), meta->GetURI().c_str(),
+ meta->GetDist().c_str(), meta->IsTrusted());
+}
+#undef S
+
+
+static const char *metaindex_doc =
+ "Provide information on meta-indexes (i.e. Release files), such as\n"
+ "whether they are trusted or their URI.";
+
+PyTypeObject PyMetaIndex_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.MetaIndex", // tp_name
+ sizeof(CppPyObject<metaIndex*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<metaIndex*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ MetaIndexRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ metaindex_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ MetaIndexGetSet, // tp_getset
+};
diff --git a/python/orderlist.cc b/python/orderlist.cc
new file mode 100644
index 0000000..d0ea184
--- /dev/null
+++ b/python/orderlist.cc
@@ -0,0 +1,317 @@
+/*
+ * orderlist.cc - Wrapper around pkgOrderList
+ *
+ * Copyright 2011 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 <Python.h>
+#include "apt_pkgmodule.h"
+#include "generic.h"
+#include <apt-pkg/orderlist.h>
+
+struct PyOrderList : CppPyObject<pkgOrderList*> {
+ pkgCache::PkgIterator current;
+ int nextIndex;
+};
+
+static PyObject *order_list_new(PyTypeObject *type,PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *pyDepCache = NULL;
+ char *kwlist[] = {"depcache", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist,
+ &PyDepCache_Type, &pyDepCache)
+ == 0)
+ return 0;
+
+ pkgDepCache *depCache = PyDepCache_ToCpp(pyDepCache);
+ return PyOrderList_FromCpp(new pkgOrderList(depCache), true,
+ pyDepCache);
+}
+
+static const char order_list_append_doc[] =
+ "append(pkg: Package)\n\n"
+ "Append a package to the end of the list.";
+static PyObject *order_list_append(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPackage = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPackage) == 0)
+ return 0;
+
+ list->push_back(PyPackage_ToCpp(pyPackage));
+ Py_RETURN_NONE;
+}
+
+static const char order_list_score_doc[] =
+ "score(pkg: Package) -> int\n\n"
+ "Return the score of the package.";
+static PyObject *order_list_score(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPackage = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPackage) == 0)
+ return 0;
+
+ return MkPyNumber(list->Score(PyPackage_ToCpp(pyPackage)));
+}
+
+static const char order_list_order_critical_doc[] =
+ "order_critical()\n\n"
+ "Order by PreDepends only (critical unpack order).";
+static PyObject *order_list_order_critical(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+
+ list->OrderCritical();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static const char order_list_order_unpack_doc[] =
+ "order_unpack()\n\n"
+ "Order the packages for unpacking (see Debian Policy).";
+static PyObject *order_list_order_unpack(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+
+ list->OrderUnpack();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static const char order_list_order_configure_doc[] =
+ "order_configure()\n\n"
+ "Order the packages for configuration (see Debian Policy).";
+static PyObject *order_list_order_configure(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+
+ list->OrderConfigure();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static bool valid_flags(unsigned int flags) {
+ return (flags & ~pkgOrderList::Added
+ & ~pkgOrderList::AddPending
+ & ~pkgOrderList::Immediate
+ & ~pkgOrderList::Loop
+ & ~pkgOrderList::UnPacked
+ & ~pkgOrderList::Configured
+ & ~pkgOrderList::Removed
+ & ~pkgOrderList::InList
+ & ~pkgOrderList::After
+ & ~pkgOrderList::States) == 0;
+}
+
+static const char order_list_flag_doc[] =
+ "flag(pkg: Package, flag: int[, unset_flags: int])\n\n"
+ "Flag the package, set flags in 'flag' and remove flags in\n"
+ "'unset_flags'.";
+static PyObject *order_list_flag(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+
+ PyObject *pyPkg = NULL;
+ unsigned int flags = 0;
+ unsigned int unset_flags = 0;
+ if (PyArg_ParseTuple(args, "O!I|I", &PyPackage_Type, &pyPkg,
+ &flags, &unset_flags) == 0)
+ return 0;
+
+ if (!valid_flags(flags))
+ return PyErr_Format(PyExc_ValueError, "flags (%u) is"
+ " not a valid combination of flags.",
+ flags);
+ if (!valid_flags(unset_flags))
+ return PyErr_Format(PyExc_ValueError, "unset_flags (%u) is"
+ " not a valid combination of flags.",
+ unset_flags);
+
+ list->Flag(PyPackage_ToCpp(pyPkg), flags, unset_flags);
+
+ Py_RETURN_NONE;
+}
+
+static const char order_list_is_flag_doc[] =
+ "is_flag(pkg: Package, flag: int)\n\n"
+ "Check if the flag(s) are set.";
+static PyObject *order_list_is_flag(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPkg = NULL;
+ unsigned int flags = 0;
+ if (PyArg_ParseTuple(args, "O!I", &PyPackage_Type, &pyPkg,
+ &flags) == 0)
+ return 0;
+
+ if (!valid_flags(flags))
+ return PyErr_Format(PyExc_ValueError, "flags (%u) is"
+ " not a valid combination of flags.",
+ flags);
+
+ return PyBool_FromLong(list->IsFlag(PyPackage_ToCpp(pyPkg), flags));
+}
+
+static const char order_list_wipe_flags_doc[] =
+ "wipe_flags(flags: int)\n\n"
+ "Remove the flags in 'flags' from all packages in this list";
+static PyObject *order_list_wipe_flags(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ unsigned int flags = 0;
+ if (PyArg_ParseTuple(args, "I", &flags) == 0)
+ return 0;
+
+ if (!valid_flags(flags))
+ return PyErr_Format(PyExc_ValueError, "flags (%u) is"
+ " not a valid combination of flags.",
+ flags);
+
+ list->WipeFlags(flags);
+ Py_RETURN_NONE;
+}
+
+static const char order_list_is_now_doc[] =
+ "is_now(pkg: Package)\n\n"
+ "Check if the package is flagged for any state but removal.";
+static PyObject *order_list_is_now(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPkg = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPkg) == 0)
+ return 0;
+
+ return PyBool_FromLong(list->IsNow(PyPackage_ToCpp(pyPkg)));
+}
+
+static const char order_list_is_missing_doc[] =
+ "is_now(pkg: Package)\n\n"
+ "Check if the package is marked for install.";
+static PyObject *order_list_is_missing(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPkg = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPkg) == 0)
+ return 0;
+
+ return PyBool_FromLong(list->IsMissing(PyPackage_ToCpp(pyPkg)));
+}
+
+
+#define METHOD(name) {#name, order_list_##name, METH_VARARGS,\
+ order_list_##name##_doc}
+
+static PyMethodDef order_list_methods[] = {
+ METHOD(append),
+ METHOD(score),
+ METHOD(order_critical),
+ METHOD(order_unpack),
+ METHOD(order_configure),
+ METHOD(flag),
+ METHOD(is_flag),
+ METHOD(is_now),
+ METHOD(is_missing),
+ METHOD(wipe_flags),
+ {}
+};
+
+static PyObject *order_list_seq_item(PyObject *self,Py_ssize_t index)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *owner = GetOwner<pkgOrderList*>(self);
+ PyObject *pycache = GetOwner<pkgOrderList*>(owner);
+ pkgCache *cache = PyCache_ToCpp(pycache);
+
+ if (index < 0 || index >= list->size())
+ return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index);
+
+ return PyPackage_FromCpp(pkgCache::PkgIterator(*cache,
+ *(list->begin() + index)),
+ true, owner);
+}
+
+Py_ssize_t order_list_seq_length(PyObject *self)
+{
+ return GetCpp<pkgOrderList*>(self)->size();
+}
+
+static PySequenceMethods order_list_as_sequence =
+{
+ order_list_seq_length, // sq_length
+ 0, // sq_concat
+ 0, // sq_repeat
+ order_list_seq_item, // sq_item
+ 0, // sq_ass_item
+ 0, // sq_contains
+ 0, // sq_inplace_concat
+ 0 // sq_inplace_repeat
+};
+
+static const char order_list_doc[] = "OrderList(depcache: DepCache)\n\n"
+ "Sequence type for packages with special ordering methods.";
+PyTypeObject PyOrderList_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.OrderList", // tp_name
+ sizeof(CppPyObject<pkgOrderList*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgOrderList*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &order_list_as_sequence, // 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
+ order_list_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ order_list_methods, // tp_methods
+ 0, // 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
+ order_list_new, // tp_new
+};
diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc
new file mode 100644
index 0000000..2fb8e71
--- /dev/null
+++ b/python/pkgmanager.cc
@@ -0,0 +1,375 @@
+// 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 <apt-pkg/init.h>
+#include <apt-pkg/install-progress.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/dpkgpm.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!",
+ &PyAcquire_Type,&fetcher,
+ &PySourceList_Type, &list,
+ &PyPackageRecords_Type, &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(PyBool_FromLong(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;
+
+ APT::Progress::PackageManagerProgressFd progress(status_fd);
+
+ pkgPackageManager::OrderResult res = pm->DoInstall(&progress);
+
+ return HandleErrors(MkPyNumber(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(PyBool_FromLong(res));
+}
+
+static PyMethodDef PkgManagerMethods[] =
+{
+ {"get_archives",PkgManagerGetArchives,METH_VARARGS,
+ "get_archives(fetcher: Acquire, list: SourceList, recs: PackageRecords) -> bool\n\n"
+ "Download the packages marked for installation via the Acquire object\n"
+ "'fetcher', using the information found in 'list' and 'recs'."},
+ {"do_install",PkgManagerDoInstall,METH_VARARGS,
+ "do_install(status_fd: int) -> int\n\n"
+ "Install the packages and return one of the class constants\n"
+ "RESULT_COMPLETED, RESULT_FAILED, RESULT_INCOMPLETE. The argument\n"
+ "status_fd can be used to specify a file descriptor that APT will\n"
+ "write status information on (see README.progress-reporting in the\n"
+ "apt source code for information on what will be written there)."},
+ {"fix_missing",PkgManagerFixMissing,METH_VARARGS,
+ "fix_missing() -> bool\n\n"
+ "Fix the installation if a package could not be downloaded."},
+ {}
+};
+
+static const char *packagemanager_doc =
+ "_PackageManager objects allow the fetching of packages marked for\n"
+ "installation and the installation of those packages.\n"
+ "This is an abstract base class that cannot be subclassed\n"
+ "in Python. The only subclass is apt_pkg.PackageManager. This\n"
+ "class is an implementation-detail and not part of the API.";
+PyTypeObject PyPackageManager_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg._PackageManager", // tp_name
+ sizeof(CppPyObject<pkgPackageManager*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgPackageManager*>, // 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
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flag,
+ packagemanager_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgManagerMethods, // tp_methods
+ 0, // 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
+ 0, // tp_new
+};
+
+
+struct CppPyRef {
+ PyObject *o;
+ CppPyRef(const CppPyRef &o) { Py_XINCREF(o); this->o = o; }
+ CppPyRef(PyObject *o) : o(o) {}
+ ~CppPyRef() { Py_XDECREF(o); }
+ operator PyObject *() const { return o; }
+ PyObject *operator->() const { return o; }
+};
+
+class PyPkgManager : public pkgDPkgPM {
+ bool res(CppPyRef result, const char* funcname) {
+ if (result == NULL) {
+ std::cerr << "Error in function: " << funcname << std::endl;
+ PyErr_Print();
+ PyErr_Clear();
+ return false;
+ }
+ return (result != NULL &&
+ (result == Py_None || PyObject_IsTrue(result) == 1));
+ }
+
+
+ PyObject *GetPyPkg(const PkgIterator &Pkg) {
+ PyObject *depcache = NULL;
+ PyObject *cache = NULL;
+
+ depcache = GetOwner<PyPkgManager*>(pyinst);
+ if (depcache != NULL && PyDepCache_Check(depcache))
+ cache = GetOwner<pkgDepCache*>(depcache);
+
+ return PyPackage_FromCpp(Pkg, true, cache);
+ }
+
+ /* Call through to Python */
+ virtual bool Install(PkgIterator Pkg,std::string File) {
+ return res(PyObject_CallMethod(pyinst, "install", "(NN)",
+ GetPyPkg(Pkg),
+ CppPyString(File)),
+ "install");
+ }
+ virtual bool Configure(PkgIterator Pkg) {
+ return res(PyObject_CallMethod(pyinst, "configure", "(N)",
+ GetPyPkg(Pkg)),
+ "configure");
+ }
+ virtual bool Remove(PkgIterator Pkg,bool Purge = false) {
+ return res(PyObject_CallMethod(pyinst, "remove", "(NN)",
+ GetPyPkg(Pkg),
+ PyBool_FromLong(Purge)),
+ "remove"
+ );
+ }
+ virtual bool Go(int StatusFd=-1) {
+ return res(PyObject_CallMethod(pyinst, "go", "(i)",
+ StatusFd),
+ "go");
+ }
+ virtual void Reset() {
+ Py_XDECREF(PyObject_CallMethod(pyinst, "reset", NULL));
+ }
+
+public:
+ /* Those call the protected functions from the parent class */
+ bool callInstall(PkgIterator Pkg,std::string File) { return pkgDPkgPM::Install(Pkg, File); }
+ bool callRemove(PkgIterator Pkg, bool Purge) { return pkgDPkgPM::Remove(Pkg, Purge); }
+ bool callGo(int StatusFd=-1) {
+ APT::Progress::PackageManagerProgressFd progress(StatusFd);
+ return pkgDPkgPM::Go(&progress);
+ }
+ void callReset() { return pkgDPkgPM::Reset(); }
+ bool callConfigure(PkgIterator Pkg) { return pkgDPkgPM::Configure(Pkg); }
+ pkgOrderList *getOrderList() { return pkgPackageManager::List; }
+
+ PyPkgManager(pkgDepCache *Cache) : pkgDPkgPM(Cache),pyinst(NULL) {};
+ PyObject *pyinst;
+};
+
+static PyObject *PkgManagerNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"depcache",0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type,
+ &Owner) == 0)
+ return 0;
+
+ PyPkgManager *pm = new PyPkgManager(GetCpp<pkgDepCache*>(Owner));
+
+ CppPyObject<PyPkgManager*> *PkgManagerObj =
+ CppPyObject_NEW<PyPkgManager*>(NULL, type,pm);
+
+ pm->pyinst = PkgManagerObj;
+
+ return PkgManagerObj;
+}
+
+
+static PyObject *PkgManagerInstall(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ PyObject *pkg;
+ PyApt_Filename file;
+
+ if (PyArg_ParseTuple(Args, "O!O&", &PyPackage_Type,&pkg, PyApt_Filename::Converter, &file) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callInstall(PyPackage_ToCpp(pkg), file)));
+}
+
+
+static PyObject *PkgManagerConfigure(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ PyObject *pkg;
+
+ if (PyArg_ParseTuple(Args, "O!", &PyPackage_Type,&pkg) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callConfigure(PyPackage_ToCpp(pkg))));
+}
+
+static PyObject *PkgManagerRemove(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ PyObject *pkg;
+ char purge;
+
+ if (PyArg_ParseTuple(Args, "O!b", &PyPackage_Type,&pkg, &purge) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callRemove(PyPackage_ToCpp(pkg), purge)));
+}
+
+static PyObject *PkgManagerGo(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ int fd;
+
+ if (PyArg_ParseTuple(Args, "i", &fd) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callGo(fd)));
+}
+
+static PyObject *PkgManagerReset(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+
+ pm->callReset();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyMethodDef PkgManager2Methods[] =
+{
+ {"install",PkgManagerInstall,METH_VARARGS,
+ "install(pkg: Package, filename: str) -> bool \n\n"
+ "Add a install action. Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"configure",PkgManagerConfigure,METH_VARARGS,
+ "configure(pkg: Package) -> bool \n\n"
+ "Add a configure action. Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"remove",PkgManagerRemove,METH_VARARGS,
+ "remove(pkg: Package, purge: bool) -> bool \n\n"
+ "Add a removal action. Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"go",PkgManagerGo,METH_VARARGS,
+ "go(status_fd: int) -> bool \n\n"
+ "Start dpkg. Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"reset",PkgManagerReset,METH_VARARGS,
+ "reset()\n\n"
+ "Reset the package manager for a new round.\n"
+ "Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {}
+};
+
+static const char *packagemanager2_doc =
+ "PackageManager(depcache: apt_pkg.DepCache)\n\n"
+ "PackageManager objects allow the fetching of packages marked for\n"
+ "installation and the installation of those packages. The parameter\n"
+ "'depcache' specifies an apt_pkg.DepCache object where information\n"
+ "about the package selections is retrieved from.\n\n"
+ "Methods in this class can be overridden in sub classes\n"
+ "to implement behavior different from APT's dpkg implementation.";
+PyTypeObject PyPackageManager2_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.PackageManager", // tp_name
+ sizeof(CppPyObject<PyPkgManager*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<PyPkgManager*>, // 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),
+ packagemanager2_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgManager2Methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyPackageManager_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgManagerNew, // tp_new
+};
+
+
+ /*}}}*/
diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc
new file mode 100644
index 0000000..13c2b9a
--- /dev/null
+++ b/python/pkgrecords.cc
@@ -0,0 +1,280 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: pkgrecords.cc,v 1.3 2002/02/26 01:36:15 mdz Exp $
+/* ######################################################################
+
+ Package Records - Wrapper for the package records functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include "pkgrecords.h"
+
+
+#include <Python.h>
+ /*}}}*/
+
+
+// PkgRecords Class /*{{{*/
+// ---------------------------------------------------------------------
+
+
+static PyObject *PkgRecordsLookup(PyObject *Self,PyObject *Args)
+{
+ PkgRecordsStruct &Struct = GetCpp<PkgRecordsStruct>(Self);
+
+ PyObject *PkgFObj;
+ long int Index;
+ if (PyArg_ParseTuple(Args,"(O!l)",&PyPackageFile_Type,&PkgFObj,&Index) == 0)
+ return 0;
+
+ // Get the index and check to make sure it is reasonable
+ pkgCache::PkgFileIterator &PkgF = GetCpp<pkgCache::PkgFileIterator>(PkgFObj);
+ pkgCache *Cache = PkgF.Cache();
+ if (Cache->DataEnd() <= Cache->VerFileP + Index + 1 ||
+ Cache->VerFileP[Index].File != PkgF.MapPointer())
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return 0;
+ }
+
+ // Do the lookup
+ Struct.Last = &Struct.Records.Lookup(pkgCache::VerFileIterator(*Cache,Cache->VerFileP+Index));
+
+ // always return true (to make it consistent with the pkgsrcrecords object
+ return PyBool_FromLong(1);
+}
+
+static PyMethodDef PkgRecordsMethods[] =
+{
+ {"lookup",PkgRecordsLookup,METH_VARARGS,
+ "lookup((packagefile: apt_pkg.PackageFile, index: int)) -> bool\n\n"
+ "Changes to a new package"},
+ {}
+};
+
+/**
+ * Get the PkgSrcRecordsStruct from a PyObject. If no package has been looked
+ * up, set an AttributeError using the given name.
+ */
+static inline PkgRecordsStruct &GetStruct(PyObject *Self,char *name) {
+ PkgRecordsStruct &Struct = GetCpp<PkgRecordsStruct>(Self);
+ if (Struct.Last == 0)
+ PyErr_SetString(PyExc_AttributeError,name);
+ return Struct;
+}
+
+static PyObject *PkgRecordsGetFileName(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"FileName");
+ return (Struct.Last != 0) ? CppPyPath(Struct.Last->FileName()) : 0;
+}
+static PyObject *PkgRecordsGetHashes(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"Hashes");
+ if (Struct.Last == 0)
+ return 0;
+
+ auto py = CppPyObject_NEW<HashStringList> (nullptr, &PyHashStringList_Type);
+ py->Object = Struct.Last->Hashes();
+ return py;
+}
+static PyObject *PkgRecordsGetMD5Hash(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"MD5Hash");
+ if (Struct.Last == NULL)
+ return 0;
+ auto hashes = Struct.Last->Hashes();
+ auto hash = hashes.find("md5sum");
+ if (hash == NULL)
+ return 0;
+ return CppPyString(hash->HashValue());
+}
+static PyObject *PkgRecordsGetSHA1Hash(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"SHA1Hash");
+ if (Struct.Last == NULL)
+ return 0;
+ auto hashes = Struct.Last->Hashes();
+ auto hash = hashes.find("sha1");
+ if (hash == NULL)
+ return 0;
+ return CppPyString(hash->HashValue());
+}
+static PyObject *PkgRecordsGetSHA256Hash(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"SHA256Hash");
+ if (Struct.Last == NULL)
+ return 0;
+ auto hashes = Struct.Last->Hashes();
+ auto hash = hashes.find("sha256");
+ if (hash == NULL)
+ return 0;
+ return CppPyString(hash->HashValue());
+}
+static PyObject *PkgRecordsGetSourcePkg(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"SourcePkg");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->SourcePkg()) : 0;
+}
+static PyObject *PkgRecordsGetSourceVer(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"SourceVer");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->SourceVer()) : 0;
+}
+static PyObject *PkgRecordsGetMaintainer(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"Maintainer");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Maintainer()) : 0;
+}
+static PyObject *PkgRecordsGetShortDesc(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"ShortDesc");
+ return (Struct.Last != 0) ? CppPyLocaleString(Struct.Last->ShortDesc()) : 0;
+}
+static PyObject *PkgRecordsGetLongDesc(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"LongDesc");
+ return (Struct.Last != 0) ? CppPyLocaleString(Struct.Last->LongDesc()) : 0;
+}
+static PyObject *PkgRecordsGetName(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"Name");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Name()) : 0;
+}
+static PyObject *PkgRecordsGetHomepage(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"Homepage");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Homepage()) : 0;
+}
+static PyObject *PkgRecordsGetRecord(PyObject *Self,void*) {
+ const char *start, *stop;
+ PkgRecordsStruct &Struct = GetStruct(Self,"Record");
+ if (Struct.Last == 0)
+ return 0;
+ Struct.Last->GetRec(start, stop);
+ return PyString_FromStringAndSize(start,stop-start);
+}
+static PyGetSetDef PkgRecordsGetSet[] = {
+ {"filename",PkgRecordsGetFileName,0,
+ "The filename of the package, as stored in the 'Filename' field."},
+ {"homepage",PkgRecordsGetHomepage,0,
+ "The homepage of the package, as stored in the 'Homepage' field."},
+ {"long_desc",PkgRecordsGetLongDesc,0,
+ "The long description of the packages; i.e. all lines in the\n"
+ "'Description' field except for the first one."},
+ {"hashes",PkgRecordsGetHashes,0,
+ "The hashes of the packages, as a HashStringList"},
+ {"md5_hash",PkgRecordsGetMD5Hash,0,
+ "The MD5 hash value of the package, as stored in the 'MD5Sum' field."},
+ {"maintainer",PkgRecordsGetMaintainer,0,
+ "The maintainer of the package, as stored in the 'Maintainer' field."},
+ {"name",PkgRecordsGetName,0,
+ "The name of the package, as stored in the 'Package' field."},
+ {"record",PkgRecordsGetRecord,0,
+ "The raw record, suitable for parsing by apt_pkg.TagSection."},
+ {"sha1_hash",PkgRecordsGetSHA1Hash,0,
+ "The SHA1 hash value, as stored in the 'SHA1' field."},
+ {"sha256_hash",PkgRecordsGetSHA256Hash,0,
+ "The SHA256 hash value, as stored in the 'SHA256' field."},
+ {"short_desc",PkgRecordsGetShortDesc,0,
+ "The short description of the package, i.e. the first line of the\n"
+ "'Description' field."},
+ {"source_pkg",PkgRecordsGetSourcePkg,0,
+ "The name of the source package, if different from the name of the\n"
+ "binary package. This information is retrieved from the 'Source' field."},
+ {"source_ver",PkgRecordsGetSourceVer,0,
+ "The version of the source package, if it differs from the version\n"
+ "of the binary package. Just like 'source_pkg', this information\n"
+ "is retrieved from the 'Source' field."},
+ {}
+};
+
+static int PkgRecordsContains(PyObject *Self,PyObject *Arg)
+{
+ PkgRecordsStruct &Struct = GetStruct(Self,"__contains__");
+ if (Struct.Last == nullptr)
+ return -1;
+ const char *Name = PyObject_AsString(Arg);
+
+ if (Name == nullptr)
+ return -1;
+
+ return !Struct.Last->RecordField(Name).empty();
+}
+
+static PyObject *PkgRecordsMap(PyObject *Self,PyObject *Arg)
+{
+ PkgRecordsStruct &Struct = GetStruct(Self,"__contains__");
+ if (Struct.Last == nullptr)
+ return nullptr;
+
+ const char *Name = PyObject_AsString(Arg);
+ if (Name == nullptr)
+ return nullptr;
+
+ return CppPyString(Struct.Last->RecordField(Name));
+}
+
+
+
+PySequenceMethods PkgRecordsSeqMeth = {0,0,0,0,0,0,0,PkgRecordsContains,0,0};
+PyMappingMethods PkgRecordsMapMeth = {0,PkgRecordsMap,0};
+
+static PyObject *PkgRecordsNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"cache",0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyCache_Type,
+ &Owner) == 0)
+ return 0;
+
+ return HandleErrors(CppPyObject_NEW<PkgRecordsStruct>(Owner,type,
+ GetCpp<pkgCache *>(Owner)));
+}
+
+static const char *packagerecords_doc =
+ "PackageRecords(cache: apt_pkg.Cache)\n\n"
+ "Package Records contain information about packages. Those objects\n"
+ "can be used to retrieve information such as maintainer or filename\n"
+ "of a package. They can also be used to retrieve the raw records\n"
+ "of the packages (i.e. those stanzas stored in Packages files).";
+
+PyTypeObject PyPackageRecords_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.PackageRecords", // tp_name
+ sizeof(CppPyObject<PkgRecordsStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<PkgRecordsStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &PkgRecordsSeqMeth, // tp_as_sequence
+ &PkgRecordsMapMeth, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ packagerecords_doc, // tp_doc
+ CppTraverse<PkgRecordsStruct>, // tp_traverse
+ CppClear<PkgRecordsStruct>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgRecordsMethods, // tp_methods
+ 0, // tp_members
+ PkgRecordsGetSet, // 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
+ PkgRecordsNew, // tp_new
+};
+
+ /*}}}*/
+
+
diff --git a/python/pkgrecords.h b/python/pkgrecords.h
new file mode 100644
index 0000000..1e26c8c
--- /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
new file mode 100644
index 0000000..e813c6e
--- /dev/null
+++ b/python/pkgsrcrecords.cc
@@ -0,0 +1,438 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: pkgsrcrecords.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $
+/* ######################################################################
+
+ Package Records - Wrapper for the package records functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/sourcelist.h>
+
+#include <Python.h>
+ /*}}}*/
+
+// PkgSrcRecordFiles Class /*{{{*/
+// ---------------------------------------------------------------------
+typedef pkgSrcRecords::File PkgSrcRecordFilesStruct;
+
+// compat with the old API that provided a tuple (md5,size,path,type)
+static Py_ssize_t pkgSrcRecordFiles_length(PyObject *Self) {
+ return 4;
+}
+
+// compat with the old API that provided a tuple (md5,size,path,type)
+static PyObject* pkgSrcRecordFiles_item(PyObject *Self, Py_ssize_t i) {
+ APT_IGNORE_DEPRECATED_PUSH
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ switch (i) {
+ case 0:
+ Py_INCREF(Py_None);
+ return Py_None;
+ case 1:
+ return Py_BuildValue("N", MkPyNumber(f.FileSize));
+ case 2:
+ return Py_BuildValue("s", f.Path.c_str());
+ case 3:
+ return Py_BuildValue("s", f.Type.c_str());
+ }
+
+ PyErr_Format(PyExc_IndexError, "index %d out of range, consider using the properties instead", i);
+ return NULL;
+ APT_IGNORE_DEPRECATED_POP
+}
+
+static PySequenceMethods pkgsrcrecordfiles_as_sequence = {
+ pkgSrcRecordFiles_length,0,0,pkgSrcRecordFiles_item,0,0,0,0,0,0
+};
+
+static PyObject *PkgSrcRecordFilesNew(PyTypeObject *type,PyObject *args,PyObject *kwds) {
+ char *kwlist[] = {0};
+ if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0)
+ return 0;
+
+ return HandleErrors(CppPyObject_NEW<PkgSrcRecordFilesStruct>(NULL, type));
+}
+
+static const char *sourcerecordfile_doc =
+ "SourceRecordFile()\n\n"
+ "Provide an easy way to look up the src records of a source package.\n";
+
+static PyObject *PkgSrcRecordFilesGetPath(PyObject *Self,void*) {
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ return CppPyString(f.Path.c_str());
+}
+
+static PyObject *PkgSrcRecordFilesGetType(PyObject *Self,void*) {
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ return CppPyString(f.Type.c_str());
+}
+
+static PyObject *PkgSrcRecordFilesGetSize(PyObject *Self,void*) {
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ return Py_BuildValue("N", MkPyNumber(f.FileSize));
+}
+
+static PyObject *PkgSrcRecordFilesGetHashes(PyObject *Self,void*) {
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ auto py = CppPyObject_NEW<HashStringList> (nullptr, &PyHashStringList_Type);
+ py->Object = f.Hashes;
+ return py;
+}
+
+static PyGetSetDef PkgSrcRecordFilesGetSet[] = {
+ {"path",PkgSrcRecordFilesGetPath,0,
+ "The remote path of the source package file."},
+ {"type",PkgSrcRecordFilesGetType,0,
+ "The type of the source package file."},
+ {"size",PkgSrcRecordFilesGetSize,0,
+ "The size of the source package file."},
+ {"hashes",PkgSrcRecordFilesGetHashes,0,
+ "The hashes of the source package file."},
+ {}
+};
+
+PyTypeObject PySourceRecordFiles_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.SourceRecordFiles", // tp_name
+ sizeof(CppPyObject<PkgSrcRecordFilesStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<PkgSrcRecordFilesStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &pkgsrcrecordfiles_as_sequence, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ sourcerecordfile_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ PkgSrcRecordFilesGetSet, // 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
+ PkgSrcRecordFilesNew, // tp_new
+};
+// ---------------------------------------------------------------------
+
+struct PkgSrcRecordsStruct
+{
+ pkgSourceList List;
+ pkgSrcRecords *Records;
+ pkgSrcRecords::Parser *Last;
+
+ PkgSrcRecordsStruct() : Last(0) {
+ List.ReadMainList();
+ Records = new pkgSrcRecords(List);
+ };
+ ~PkgSrcRecordsStruct() {
+ delete Records;
+ };
+};
+
+
+// PkgSrcRecords Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static char *doc_PkgSrcRecordsLookup =
+ "lookup(name: str) -> bool\n\n"
+ "Look up the source package with the given name. Each call moves\n"
+ "the position of the records parser forward. If there are no\n"
+ "more records, return None. If the lookup failed this way,\n"
+ "access to any of the attributes will result in an AttributeError.";
+static PyObject *PkgSrcRecordsLookup(PyObject *Self,PyObject *Args)
+{
+ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self);
+
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ Struct.Last = Struct.Records->Find(Name, false);
+ if (Struct.Last == 0) {
+ Struct.Records->Restart();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ return PyBool_FromLong(1);
+}
+
+static char *doc_PkgSrcRecordsRestart =
+ "restart()\n\n"
+ "Restart the lookup process. This moves the parser to the first\n"
+ "package and lookups can now be made just like on a new object.";
+static PyObject *PkgSrcRecordsRestart(PyObject *Self,PyObject *Args)
+{
+ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self);
+
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Struct.Records->Restart();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static char *doc_PkgSrcRecordsStep =
+ "step() -> bool\n\n"
+ "Go to the source package. Each call moves\n"
+ "the position of the records parser forward. If there are no\n"
+ "more records, return None. If the lookup failed this way,\n"
+ "access to any of the attributes will result in an AttributeError.";
+static PyObject *PkgSrcRecordsStep(PyObject *Self,PyObject *Args)
+{
+ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self);
+
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Struct.Last = (pkgSrcRecords::Parser*)Struct.Records->Step();
+ if (Struct.Last == 0) {
+ Struct.Records->Restart();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ return PyBool_FromLong(1);
+}
+
+static PyMethodDef PkgSrcRecordsMethods[] =
+{
+ {"lookup",PkgSrcRecordsLookup,METH_VARARGS,doc_PkgSrcRecordsLookup},
+ {"restart",PkgSrcRecordsRestart,METH_VARARGS,doc_PkgSrcRecordsRestart},
+ {"step",PkgSrcRecordsStep,METH_VARARGS,doc_PkgSrcRecordsStep},
+ {}
+};
+
+/**
+ * Get the PkgSrcRecordsStruct from a PyObject. If no package has been looked
+ * up, set an AttributeError using the given name.
+ */
+static inline PkgSrcRecordsStruct &GetStruct(PyObject *Self,char *name) {
+ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self);
+ if (Struct.Last == 0)
+ PyErr_SetString(PyExc_AttributeError,name);
+ return Struct;
+}
+
+static PyObject *PkgSrcRecordsGetPackage(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Package");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Package()) : 0;
+}
+static PyObject *PkgSrcRecordsGetVersion(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Version");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Version()) : 0;
+}
+static PyObject *PkgSrcRecordsGetMaintainer(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Maintainer");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Maintainer()) : 0;
+}
+static PyObject *PkgSrcRecordsGetSection(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Section");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Section()) : 0;
+}
+static PyObject *PkgSrcRecordsGetRecord(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Record");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->AsStr()) : 0;
+}
+static PyObject *PkgSrcRecordsGetBinaries(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Binaries");
+ if (Struct.Last == 0)
+ return 0;
+ PyObject *List = PyList_New(0);
+ for(const char **b = Struct.Last->Binaries(); *b != 0; ++b)
+ PyList_Append(List, CppPyString(*b));
+ return List; // todo
+}
+static PyObject *PkgSrcRecordsGetIndex(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Index");
+ if (Struct.Last == 0)
+ return 0;
+ const pkgIndexFile &tmp = Struct.Last->Index();
+ CppPyObject<pkgIndexFile*> *PyObj;
+ PyObj = CppPyObject_NEW<pkgIndexFile*>(Self,&PyIndexFile_Type,
+ (pkgIndexFile*)&tmp);
+ // Do not delete the pkgIndexFile*, it is managed by PkgSrcRecords::Parser.
+ PyObj->NoDelete=true;
+ return PyObj;
+}
+
+static PyObject *PkgSrcRecordsGetFiles(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Files");
+ if (Struct.Last == 0)
+ return 0;
+ PyObject *List = PyList_New(0);
+
+ std::vector<pkgSrcRecords::File> f;
+ if(!Struct.Last->Files(f))
+ return NULL; // error
+
+ PyObject *v;
+ for(unsigned int i=0;i<f.size();i++) {
+ v = CppPyObject_NEW<PkgSrcRecordFilesStruct>(Self, &PySourceRecordFiles_Type, f[i]);
+ PyList_Append(List, v);
+ Py_DECREF(v);
+ }
+ return List;
+}
+
+static PyObject *PkgSrcRecordsGetBuildDepends(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"BuildDepends");
+ if (Struct.Last == 0)
+ return 0;
+
+ PyObject *Dict = PyDict_New();
+ PyObject *Dep = 0;
+ PyObject *LastDep = 0;
+ PyObject *OrGroup = 0;
+
+ std::vector<pkgSrcRecords::Parser::BuildDepRec> bd;
+ if(!Struct.Last->BuildDepends(bd, false /* arch-only*/))
+ return NULL; // error
+
+ PyObject *v;
+ for(unsigned int i=0;i<bd.size();i++) {
+
+ Dep = CppPyString(pkgSrcRecords::Parser::BuildDepType(bd[i].Type));
+
+ LastDep = PyDict_GetItem(Dict,Dep);
+ if (LastDep == 0)
+ {
+ LastDep = PyList_New(0);
+ PyDict_SetItem(Dict,Dep,LastDep);
+ Py_DECREF(LastDep);
+ }
+ Py_DECREF(Dep);
+ OrGroup = PyList_New(0);
+ PyList_Append(LastDep, OrGroup);
+ Py_DECREF(OrGroup);
+
+ // Add at least one package to the group, add more if Or is set.
+ while (i < bd.size())
+ {
+ v = Py_BuildValue("(sss)", bd[i].Package.c_str(),
+ bd[i].Version.c_str(), pkgCache::CompType(bd[i].Op));
+ PyList_Append(OrGroup, v);
+ Py_DECREF(v);
+ if (pkgCache::Dep::Or != (bd[i].Op & pkgCache::Dep::Or))
+ break;
+ i++;
+ }
+
+ }
+ return Dict;
+}
+
+
+static PyGetSetDef PkgSrcRecordsGetSet[] = {
+ {"binaries",PkgSrcRecordsGetBinaries,0,
+ "A list of the names of the binaries produced by this source package."},
+ {"build_depends",PkgSrcRecordsGetBuildDepends,0,
+ "A dictionary describing the build-time dependencies of the package;\n"
+ "the format is the same as used for apt_pkg.Version.depends_list_str."},
+ {"files",PkgSrcRecordsGetFiles,0,
+ "A list of :class:`SourceRecordFiles` objects."},
+ {"index",PkgSrcRecordsGetIndex,0,
+ "The index file associated with this record as a list of\n"
+ "apt_pkg.IndexFile objects."},
+ {"maintainer",PkgSrcRecordsGetMaintainer,0,
+ "The maintainer of the package."},
+ {"package",PkgSrcRecordsGetPackage,0,
+ "The name of the source package."},
+ {"record",PkgSrcRecordsGetRecord,0,
+ "The raw record, suitable for parsing using apt_pkg.TagSection."},
+ {"section",PkgSrcRecordsGetSection,0,
+ "The section of the source package."},
+ {"version",PkgSrcRecordsGetVersion,0,
+ "The version of the source package."},
+ {}
+};
+
+static PyObject *PkgSrcRecordsNew(PyTypeObject *type,PyObject *args,PyObject *kwds) {
+ char *kwlist[] = {0};
+ if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0)
+ return 0;
+
+ return HandleErrors(CppPyObject_NEW<PkgSrcRecordsStruct>(NULL, type));
+}
+
+static const char *sourcerecords_doc =
+ "SourceRecords()\n\n"
+ "Provide an easy way to look up the records of source packages and\n"
+ "provide easy attributes for some widely used fields of the record.";
+
+PyTypeObject PySourceRecords_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.SourceRecords", // tp_name
+ sizeof(CppPyObject<PkgSrcRecordsStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<PkgSrcRecordsStruct>, // 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
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ sourcerecords_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgSrcRecordsMethods, // tp_methods
+ 0, // tp_members
+ PkgSrcRecordsGetSet, // 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
+ PkgSrcRecordsNew, // tp_new
+};
+
+
+ /*}}}*/
+
diff --git a/python/policy.cc b/python/policy.cc
new file mode 100644
index 0000000..037a530
--- /dev/null
+++ b/python/policy.cc
@@ -0,0 +1,243 @@
+/*
+ * policy.cc - Wrapper around pkgPolicy
+ *
+ * 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 <Python.h>
+#include "apt_pkgmodule.h"
+#include "generic.h"
+#include <apt-pkg/policy.h>
+
+static PyObject *policy_new(PyTypeObject *type,PyObject *Args,
+ PyObject *kwds) {
+ PyObject *cache;
+ char *kwlist[] = {"cache", NULL};
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, "O", kwlist, &cache) == 0)
+ return 0;
+ if (!PyObject_TypeCheck(cache, &PyCache_Type)) {
+ PyErr_SetString(PyExc_TypeError,"`cache` must be a apt_pkg.Cache().");
+ return 0;
+ }
+ pkgPolicy *policy = new pkgPolicy(GetCpp<pkgCache *>(cache));
+ return CppPyObject_NEW<pkgPolicy*>(cache,&PyPolicy_Type,policy);
+}
+
+static char *policy_get_priority_doc =
+ "get_priority(package: Union[apt_pkg.Package, apt_pkg.Version, apt_pkg.PackageFile]) -> int\n\n"
+ "Return the priority of the package.";
+
+PyObject *policy_get_priority(PyObject *self, PyObject *arg) {
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+ if (PyObject_TypeCheck(arg, &PyVersion_Type)) {
+ auto ver = GetCpp<pkgCache::VerIterator>(arg);
+ return MkPyNumber(policy->GetPriority(ver));
+ } else if (PyObject_TypeCheck(arg, &PyPackageFile_Type)) {
+ pkgCache::PkgFileIterator pkgfile = GetCpp<pkgCache::PkgFileIterator>(arg);
+ return MkPyNumber(policy->GetPriority(pkgfile));
+ } else {
+ PyErr_SetString(PyExc_TypeError,"Argument must be of Version or PackageFile.");
+ return 0;
+ }
+}
+
+
+static char *policy_set_priority_doc =
+ "set_priority(which: Union[apt_pkg.Version, apt_pkg.PackageFile], priority: int) -> None\n\n"
+ "Override priority for the given package/file. Behavior is undefined if"
+ "a preferences file is read after that, or :meth:`init_defaults` is called.";
+static PyObject *policy_set_priority(PyObject *self, PyObject *args) {
+ PyObject *which;
+ signed short priority;
+ if (PyArg_ParseTuple(args, "Oh", &which, &priority) == 0)
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+
+ if (PyObject_TypeCheck(which, &PyVersion_Type)) {
+ auto ver = GetCpp<pkgCache::VerIterator>(which);
+ policy->SetPriority(ver, priority);
+ } else if (PyObject_TypeCheck(which, &PyPackageFile_Type)) {
+ auto pkgfile = GetCpp<pkgCache::PkgFileIterator>(which);
+ policy->SetPriority(pkgfile, priority);
+ } else {
+ PyErr_SetString(PyExc_TypeError,"Argument must be of Version or PackageFile.");
+ return 0;
+ }
+
+ HandleErrors();
+ Py_RETURN_NONE;
+}
+
+static char *policy_get_candidate_ver_doc =
+ "get_match(package: apt_pkg.Package) -> Optional[apt_pkg.Version]\n\n"
+ "Get the best package for the job.";
+
+PyObject *policy_get_candidate_ver(PyObject *self, PyObject *arg) {
+ if (PyObject_TypeCheck(arg, &PyPackage_Type)) {
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+ pkgCache::PkgIterator pkg = GetCpp<pkgCache::PkgIterator>(arg);
+ pkgCache::VerIterator ver = policy->GetCandidateVer(pkg);
+ if (ver.end()) {
+ HandleErrors();
+ Py_RETURN_NONE;
+ }
+ return CppPyObject_NEW<pkgCache::VerIterator>(arg,&PyVersion_Type,
+ ver);
+ } else {
+ PyErr_SetString(PyExc_TypeError,"Argument must be of Package().");
+ return 0;
+ }
+}
+
+static char *policy_read_pinfile_doc =
+ "read_pinfile(filename: str) -> bool\n\n"
+ "Read the pin file given by filename (e.g. '/etc/apt/preferences')\n"
+ "and add it to the policy.";
+
+static PyObject *policy_read_pinfile(PyObject *self, PyObject *arg) {
+ PyApt_Filename name;
+ if (!name.init(arg))
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+
+ return PyBool_FromLong(ReadPinFile(*policy, name));
+}
+
+#if (APT_PKG_MAJOR > 4 || (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 8))
+static char *policy_read_pindir_doc =
+ "read_pindir(dirname: str) -> bool\n\n"
+ "Read the pin files in the given dir (e.g. '/etc/apt/preferences.d')\n"
+ "and add them to the policy.";
+
+static PyObject *policy_read_pindir(PyObject *self, PyObject *arg) {
+ PyApt_Filename name;
+ if (!name.init(arg))
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+
+ return PyBool_FromLong(ReadPinDir(*policy, name));
+}
+#endif
+
+static char *policy_create_pin_doc =
+ "create_pin(type: str, pkg: str, data: str, priority: int)\n\n"
+ "Create a pin for the policy. The parameter 'type' refers to one of the\n"
+ "strings 'Version', 'Release', or 'Origin'. The argument 'pkg' is the\n"
+ "name of the package. The parameter 'data' refers to the value\n"
+ "(e.g. 'unstable' for type='Release') and the other possible options.\n"
+ "The parameter 'priority' gives the priority of the pin.";
+
+static PyObject *policy_create_pin(PyObject *self, PyObject *args) {
+ pkgVersionMatch::MatchType match_type;
+ const char *type, *pkg, *data;
+ signed short priority;
+ if (PyArg_ParseTuple(args, "sssh", &type, &pkg, &data, &priority) == 0)
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+ if (strcmp(type,"Version") == 0 || strcmp(type, "version") == 0)
+ match_type = pkgVersionMatch::Version;
+ else if (strcmp(type,"Release") == 0 || strcmp(type, "release") == 0)
+ match_type = pkgVersionMatch::Release;
+ else if (strcmp(type,"Origin") == 0 || strcmp(type, "origin") == 0)
+ match_type = pkgVersionMatch::Origin;
+ else
+ match_type = pkgVersionMatch::None;
+ policy->CreatePin(match_type,pkg,data,priority);
+ HandleErrors();
+ Py_RETURN_NONE;
+}
+
+static char *policy_init_defaults_doc =
+ "init_defaults()\n\n"
+ "Initialize defaults. Needed after calling :meth:`create_pin()`\n"
+ "with an empty `pkg` argument";
+static PyObject *policy_init_defaults(PyObject *self, PyObject *args) {
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+ policy->InitDefaults();
+ HandleErrors();
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef policy_methods[] = {
+ {"get_priority",(PyCFunction)policy_get_priority,METH_O,
+ policy_get_priority_doc},
+ {"set_priority",policy_set_priority,METH_VARARGS,policy_set_priority_doc},
+ {"get_candidate_ver",(PyCFunction)policy_get_candidate_ver,METH_O,
+ policy_get_candidate_ver_doc},
+ {"read_pinfile",(PyCFunction)policy_read_pinfile,METH_O,
+ policy_read_pinfile_doc},
+#if (APT_PKG_MAJOR > 4 || (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 8))
+ {"read_pindir",(PyCFunction)policy_read_pindir,METH_O,
+ policy_read_pindir_doc},
+#endif
+ {"create_pin",policy_create_pin,METH_VARARGS,policy_create_pin_doc},
+ {"init_defaults",policy_init_defaults,METH_VARARGS,policy_init_defaults_doc},
+ {}
+};
+
+static char *policy_doc =
+ "Policy(cache)\n\n"
+ "Representation of the policy of the Cache object given by cache. This\n"
+ "provides a superset of policy-related functionality compared to the\n"
+ "DepCache class. The DepCache can be used for most purposes, but there\n"
+ "may be some cases where a special policy class is needed.";
+
+PyTypeObject PyPolicy_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Policy", // tp_name
+ sizeof(CppPyObject<pkgPolicy*>),// tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgPolicy*>, // 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 |
+ Py_TPFLAGS_HAVE_GC),
+ policy_doc, // tp_doc
+ CppTraverse<pkgPolicy*>, // tp_traverse
+ CppClear<pkgPolicy*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ policy_methods, // tp_methods
+ 0, // 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
+ policy_new, // tp_new
+};
diff --git a/python/progress.cc b/python/progress.cc
new file mode 100644
index 0000000..f4ed8e6
--- /dev/null
+++ b/python/progress.cc
@@ -0,0 +1,473 @@
+// Description /*{{{*/
+// $Id: progress.cc,v 1.5 2003/06/03 03:03:23 mvo Exp $
+/* ######################################################################
+
+ Progress - Wrapper for the progress related functions
+
+ ##################################################################### */
+#include <Python.h>
+#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 <apt-pkg/install-progress.h>
+#include "progress.h"
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+/**
+ * Set an attribute on an object, after creating the value with
+ * Py_BuildValue(fmt, arg). Afterwards, decrease its refcount and return
+ * whether setting the attribute was successful.
+ */
+template<class T>
+inline bool setattr(PyObject *object, const char *attr, const char *fmt, T arg)
+{
+ if (!object)
+ return false;
+ PyObject *value = Py_BuildValue(fmt, arg);
+ if (value == NULL)
+ return false;
+
+ int result = PyObject_SetAttrString(object, attr, value);
+ Py_DECREF(value);
+ return result != -1;
+}
+
+inline PyObject *TUPLEIZE(PyObject *op) {
+ PyObject *ret = Py_BuildValue("(O)", op);
+ Py_DECREF(op);
+ return ret;
+}
+
+// generic
+bool PyCallbackObj::RunSimpleCallback(const char* method_name,
+ PyObject *arglist,
+ PyObject **res)
+{
+ if(callbackInst == 0) {
+ Py_XDECREF(arglist);
+ return false;
+ }
+
+ PyObject *method = PyObject_GetAttrString(callbackInst,(char*) method_name);
+ if(method == NULL) {
+ Py_XDECREF(arglist);
+ if (res) {
+ Py_INCREF(Py_None);
+ *res = Py_None;
+ }
+ return false;
+ }
+
+ PyObject *result = PyObject_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 false;
+ }
+ if(res != NULL)
+ *res = result;
+ else
+ Py_XDECREF(result);
+ Py_XDECREF(method);
+
+ return true;
+}
+
+
+// OpProgress interface
+void PyOpProgress::Update()
+{
+ // Build up the argument list...
+ if(!CheckChange(0.7))
+ return;
+
+ setattr(callbackInst, "op", "s", Op.c_str());
+ setattr(callbackInst, "subop", "s", SubOp.c_str());
+ setattr(callbackInst, "major_change", "b", MajorChange);
+ setattr(callbackInst, "percent", "N", MkPyNumber(Percent));
+ RunSimpleCallback("update");
+}
+
+void PyOpProgress::Done()
+{
+ RunSimpleCallback("done");
+}
+
+
+
+// fetcher interface
+
+
+
+// apt interface
+
+PyObject *PyFetchProgress::GetDesc(pkgAcquire::ItemDesc *item) {
+ if (!pyAcquire && item->Owner && item->Owner->GetOwner()) {
+ pyAcquire = PyAcquire_FromCpp(item->Owner->GetOwner(), false, NULL);
+ }
+ PyObject *pyItem = PyAcquireItem_FromCpp(item->Owner, false, pyAcquire);
+ PyObject *pyDesc = PyAcquireItemDesc_FromCpp(item, false, pyItem);
+ Py_DECREF(pyItem);
+ return pyDesc;
+}
+
+bool PyFetchProgress::MediaChange(std::string Media, std::string Drive)
+{
+ PyCbObj_END_ALLOW_THREADS
+ PyObject *arglist = Py_BuildValue("(ss)", Media.c_str(), Drive.c_str());
+ PyObject *result = NULL;
+
+ if(PyObject_HasAttrString(callbackInst, "mediaChange"))
+ RunSimpleCallback("mediaChange", arglist, &result);
+ else
+ RunSimpleCallback("media_change", arglist, &result);
+
+ bool res = true;
+ if(!PyArg_Parse(result, "b", &res)) {
+ // no return value or None, assume false
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return false;
+ }
+
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return res;
+}
+
+void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status)
+{
+ // Added object file size and object partial size to
+ // parameters that are passed to updateStatus.
+ // -- Stephan
+ PyObject *arglist = Py_BuildValue("(sssNNN)", Itm.URI.c_str(),
+ Itm.Description.c_str(),
+ Itm.ShortDesc.c_str(),
+ MkPyNumber(status),
+ MkPyNumber(Itm.Owner->FileSize),
+ MkPyNumber(Itm.Owner->PartialSize));
+
+ RunSimpleCallback("update_status_full", arglist);
+
+ // legacy version of the interface
+
+ arglist = Py_BuildValue("(sssN)", Itm.URI.c_str(), Itm.Description.c_str(),
+ Itm.ShortDesc.c_str(), MkPyNumber(status));
+
+ if(PyObject_HasAttrString(callbackInst, "updateStatus"))
+ RunSimpleCallback("updateStatus", arglist);
+ else
+ RunSimpleCallback("update_status", arglist);
+}
+
+void PyFetchProgress::IMSHit(pkgAcquire::ItemDesc &Itm)
+{
+ PyCbObj_END_ALLOW_THREADS
+ if (PyObject_HasAttrString(callbackInst, "ims_hit"))
+ RunSimpleCallback("ims_hit", TUPLEIZE(GetDesc(&Itm)));
+ else
+ UpdateStatus(Itm, DLHit);
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyFetchProgress::Fetch(pkgAcquire::ItemDesc &Itm)
+{
+ PyCbObj_END_ALLOW_THREADS
+ if (PyObject_HasAttrString(callbackInst, "fetch"))
+ RunSimpleCallback("fetch", TUPLEIZE(GetDesc(&Itm)));
+ else
+ UpdateStatus(Itm, DLQueued);
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyFetchProgress::Done(pkgAcquire::ItemDesc &Itm)
+{
+ PyCbObj_END_ALLOW_THREADS
+ if (PyObject_HasAttrString(callbackInst, "done"))
+ RunSimpleCallback("done", TUPLEIZE(GetDesc(&Itm)));
+ else
+ UpdateStatus(Itm, DLDone);
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyFetchProgress::Fail(pkgAcquire::ItemDesc &Itm)
+{
+ PyCbObj_END_ALLOW_THREADS
+ if (PyObject_HasAttrString(callbackInst, "fail")) {
+ RunSimpleCallback("fail", TUPLEIZE(GetDesc(&Itm)));
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return;
+ }
+
+ // Ignore certain kinds of transient failures (bad code)
+ if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) {
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return;
+ }
+
+ if (Itm.Owner->Status == pkgAcquire::Item::StatDone)
+ {
+ UpdateStatus(Itm, DLIgnored);
+ }
+
+
+ if (PyObject_HasAttrString(callbackInst, "fail"))
+ RunSimpleCallback("fail", TUPLEIZE(GetDesc(&Itm)));
+ else
+ UpdateStatus(Itm, DLFailed);
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyFetchProgress::Start()
+{
+ pkgAcquireStatus::Start();
+
+
+ RunSimpleCallback("start");
+ /* After calling the start method we can safely allow
+ * other Python threads to do their work for now.
+ */
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+
+void PyFetchProgress::Stop()
+{
+ /* After the stop operation occurred no other threads
+ * are allowed. This is done so we have a matching
+ * PyCbObj_END_ALLOW_THREADS to our previous
+ * PyCbObj_BEGIN_ALLOW_THREADS (Python requires this!).
+ */
+
+ PyCbObj_END_ALLOW_THREADS
+ pkgAcquireStatus::Stop();
+ RunSimpleCallback("stop");
+}
+
+bool PyFetchProgress::Pulse(pkgAcquire * Owner)
+{
+ PyCbObj_END_ALLOW_THREADS
+ pkgAcquireStatus::Pulse(Owner);
+
+ if(callbackInst == 0) {
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return false;
+ }
+
+ setattr(callbackInst, "last_bytes", "N", MkPyNumber(LastBytes));
+ setattr(callbackInst, "current_cps", "N", MkPyNumber(CurrentCPS));
+ setattr(callbackInst, "current_bytes", "N", MkPyNumber(CurrentBytes));
+ setattr(callbackInst, "total_bytes", "N", MkPyNumber(TotalBytes));
+ setattr(callbackInst, "fetched_bytes", "N", MkPyNumber(FetchedBytes));
+ setattr(callbackInst, "elapsed_time", "N", MkPyNumber(ElapsedTime));
+ setattr(callbackInst, "current_items", "N", MkPyNumber(CurrentItems));
+ setattr(callbackInst, "total_items", "N", MkPyNumber(TotalItems));
+
+ // New style
+ if (!PyObject_HasAttrString(callbackInst, "updateStatus")) {
+ PyObject *result1;
+ bool res1 = true;
+
+ if (pyAcquire == NULL) {
+ pyAcquire = PyAcquire_FromCpp(Owner, false, NULL);
+ }
+ Py_INCREF(pyAcquire);
+
+ if (RunSimpleCallback("pulse", TUPLEIZE(pyAcquire) , &result1)) {
+ if (result1 != NULL &&
+ result1 != Py_None &&
+ PyArg_Parse(result1, "b", &res1) &&
+ res1 == false) {
+ // the user returned a explicit false here, stop
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return false;
+ }
+ }
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return true;
+ }
+ return false;
+}
+
+
+
+// install progress
+
+void PyInstallProgress::StartUpdate()
+{
+ RunSimpleCallback("start_update");
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyInstallProgress::UpdateInterface()
+{
+ PyCbObj_END_ALLOW_THREADS
+ RunSimpleCallback("update_interface");
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyInstallProgress::FinishUpdate()
+{
+ PyCbObj_END_ALLOW_THREADS
+ RunSimpleCallback("finish_update");
+}
+
+pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm)
+{
+ pkgPackageManager::OrderResult res;
+ int ret;
+ pid_t child_id;
+
+#if 0 // FIXME: this needs to be merged into apt to support medium swaping
+ res = pm->DoInstallPreFork();
+ if (res == pkgPackageManager::Failed)
+ return res;
+#endif
+
+ // support custom fork methods
+ if(PyObject_HasAttrString(callbackInst, "fork")) {
+ PyObject *method = PyObject_GetAttrString(callbackInst, "fork");
+ PyObject *arglist = Py_BuildValue("()");
+ PyObject *result = PyObject_CallObject(method, arglist);
+ Py_DECREF(arglist);
+ if (result == NULL) {
+ std::cerr << "fork method invalid" << std::endl;
+ PyErr_Print();
+ return pkgPackageManager::Failed;
+ }
+ if(!PyArg_Parse(result, "i", &child_id) ) {
+ std::cerr << "custom fork() result could not be parsed?"<< std::endl;
+ return pkgPackageManager::Failed;
+ }
+ } else {
+ child_id = fork();
+ }
+
+ PyObject *child_o = MkPyNumber(child_id);
+ PyObject_SetAttrString(callbackInst, "child_pid", child_o);
+ Py_DECREF(child_o);
+
+#if 0 // FIXME: this needs to be merged into apt to support medium swaping
+ if (child_id == 0) {
+ res = pm->DoInstallPostFork();
+ _exit(res);
+ }
+#endif
+ if (child_id == 0) {
+ PyObject *v = PyObject_GetAttrString(callbackInst, "writefd");
+ if(v) {
+ int fd = PyObject_AsFileDescriptor(v);
+
+ APT::Progress::PackageManagerProgressFd progress(fd);
+ res = pm->DoInstall(&progress);
+ } else {
+ APT::Progress::PackageManagerProgressFd progress(-1);
+ res = pm->DoInstall(&progress);
+ }
+ _exit(res);
+ }
+
+ StartUpdate();
+
+
+ PyCbObj_END_ALLOW_THREADS
+ if(PyObject_HasAttrString(callbackInst, "waitChild") ||
+ PyObject_HasAttrString(callbackInst, "wait_child")) {
+ PyObject *method;
+ if (PyObject_HasAttrString(callbackInst, "waitChild"))
+ method = PyObject_GetAttrString(callbackInst, "waitChild");
+ else
+ method = PyObject_GetAttrString(callbackInst, "wait_child");
+ PyObject *result = PyObject_CallObject(method, NULL);
+ if (result == NULL) {
+ std::cerr << "waitChild method invalid" << std::endl;
+ PyErr_Print();
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return pkgPackageManager::Failed;
+ }
+ if(!PyArg_Parse(result, "i", &res) ) {
+ std::cerr << "custom waitChild() result could not be parsed?"<< std::endl;
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return pkgPackageManager::Failed;
+ }
+ PyCbObj_BEGIN_ALLOW_THREADS
+ } else {
+ PyCbObj_BEGIN_ALLOW_THREADS
+ while (waitpid(child_id, &ret, WNOHANG) == 0) {
+ PyCbObj_END_ALLOW_THREADS
+ UpdateInterface();
+ PyCbObj_BEGIN_ALLOW_THREADS
+ }
+
+ res = (pkgPackageManager::OrderResult) WEXITSTATUS(ret);
+ }
+
+ FinishUpdate();
+
+ return res;
+}
+
+
+//-----------------------------------------------------------------------------
+// apt-cdrom interface
+
+void PyCdromProgress::Update(std::string text, int current)
+{
+ PyObject *arglist = Py_BuildValue("(si)", text.c_str(), current);
+ setattr(callbackInst, "total_steps", "i", totalSteps);
+ RunSimpleCallback("update", arglist);
+}
+
+bool PyCdromProgress::ChangeCdrom()
+{
+ PyObject *arglist = Py_BuildValue("()");
+ PyObject *result = NULL;
+ if (PyObject_HasAttrString(callbackInst, "changeCdrom"))
+ RunSimpleCallback("changeCdrom", arglist, &result);
+ else
+ RunSimpleCallback("change_cdrom", arglist, &result);
+
+ bool res = true;
+ if(!PyArg_Parse(result, "b", &res))
+ std::cerr << "ChangeCdrom: result could not be parsed" << std::endl;
+
+ return res;
+}
+
+
+bool PyCdromProgress::AskCdromName(std::string &Name)
+{
+ PyObject *arglist = Py_BuildValue("()");
+ const char *new_name;
+ bool res;
+ PyObject *result = NULL;
+
+ // Old style: (True, name) on success, (False, name) on failure.
+ if (PyObject_HasAttrString(callbackInst, "askAdromName")) {
+ RunSimpleCallback("askAdromName", arglist, &result);
+ if(!PyArg_Parse(result, "(bs)", &res, &new_name))
+ std::cerr << "AskCdromName: result could not be parsed" << std::endl;
+ // set the new name
+ Name =std:: string(new_name);
+ return res;
+ }
+ // New style: String on success, None on failure.
+ else {
+ RunSimpleCallback("ask_cdrom_name", arglist, &result);
+ if(result == Py_None)
+ return false;
+ if(!PyArg_Parse(result, "s", &new_name))
+ std::cerr << "ask_cdrom_name: result could not be parsed" << std::endl;
+ else
+ Name = std::string(new_name);
+ return true;
+ }
+}
diff --git a/python/progress.h b/python/progress.h
new file mode 100644
index 0000000..b46ac98
--- /dev/null
+++ b/python/progress.h
@@ -0,0 +1,120 @@
+// Description /*{{{*/
+// $Id: progress.h,v 1.5 2003/06/03 03:03:23 mdz Exp $
+/* ######################################################################
+
+ Progress - Wrapper for the progress related functions
+
+ ##################################################################### */
+
+#ifndef PROGRESS_H
+#define PROGRESS_H
+
+#include <apt-pkg/progress.h>
+#include <apt-pkg/acquire.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/cdrom.h>
+#include <Python.h>
+
+/* PyCbObj_BEGIN_ALLOW_THREADS and PyCbObj_END_ALLOW_THREADS are sligthly
+ * modified versions of Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS.
+ * Instead of storing the thread state in a function-local variable these
+ * use a class attribute (with the same) name, allowing blocking and
+ * unblocking from different class methods.
+ * Py_BLOCK_THREADS and Py_UNBLOCK_THREADS do not define their own
+ * local variable but use the one provided by PyCbObj_BEGIN_ALLOW_THREADS
+ * and thus are the same as Py_BLOCK_THREADS and Py_UNBLOCK_THREADS.
+ */
+#define PyCbObj_BEGIN_ALLOW_THREADS \
+ _save = PyEval_SaveThread();
+#define PyCbObj_END_ALLOW_THREADS \
+ PyEval_RestoreThread(_save); \
+ _save = NULL;
+#define PyCbObj_BLOCK_THREADS Py_BLOCK_THREADS
+#define PyCbObj_UNBLOCK_THREADS Py_UNBLOCK_THREADS
+
+class PyCallbackObj {
+ protected:
+ PyObject *callbackInst;
+ PyThreadState *_save;
+
+ public:
+ void setCallbackInst(PyObject *o) {
+ Py_INCREF(o);
+ callbackInst = o;
+ }
+
+ bool RunSimpleCallback(const char *method, PyObject *arglist=NULL,
+ PyObject **result=NULL);
+
+ PyCallbackObj() : callbackInst(0), _save(0) {};
+ ~PyCallbackObj() {Py_DECREF(callbackInst); };
+};
+
+struct PyOpProgress : public OpProgress, public PyCallbackObj
+{
+
+ virtual void Update();
+ virtual void Done();
+
+ PyOpProgress() : OpProgress(), PyCallbackObj() {};
+};
+
+
+struct PyFetchProgress : public pkgAcquireStatus, public PyCallbackObj
+{
+ protected:
+ PyObject *pyAcquire;
+ PyObject *GetDesc(pkgAcquire::ItemDesc *item);
+ public:
+ enum {
+ DLDone, DLQueued, DLFailed, DLHit, DLIgnored
+ };
+
+ void UpdateStatus(pkgAcquire::ItemDesc & Itm, int status);
+
+ virtual bool MediaChange(std::string Media, std::string Drive);
+
+ void setPyAcquire(PyObject *o) {
+ Py_CLEAR(pyAcquire);
+ Py_INCREF(o);
+ pyAcquire = o;
+ }
+
+ /* apt stuff */
+ virtual void IMSHit(pkgAcquire::ItemDesc &Itm);
+ virtual void Fetch(pkgAcquire::ItemDesc &Itm);
+ virtual void Done(pkgAcquire::ItemDesc &Itm);
+ virtual void Fail(pkgAcquire::ItemDesc &Itm);
+ virtual void Start();
+ virtual void Stop();
+
+ bool Pulse(pkgAcquire * Owner);
+ PyFetchProgress() : PyCallbackObj(), pyAcquire(0) {};
+ ~PyFetchProgress() { Py_XDECREF(pyAcquire); };
+};
+
+struct PyInstallProgress : public PyCallbackObj
+{
+ void StartUpdate();
+ void UpdateInterface();
+ void FinishUpdate();
+
+ pkgPackageManager::OrderResult Run(pkgPackageManager *pm);
+
+ PyInstallProgress() : PyCallbackObj() {};
+};
+
+struct PyCdromProgress : public pkgCdromStatus, public PyCallbackObj
+{
+ // update steps, will be called regularly as a "pulse"
+ virtual void Update(std::string text="", int current=0);
+ // ask for cdrom insert
+ virtual bool ChangeCdrom();
+ // ask for cdrom name
+ virtual bool AskCdromName(std::string &Name);
+
+ PyCdromProgress() : PyCallbackObj() {};
+};
+
+
+#endif
diff --git a/python/python-apt-helpers.cc b/python/python-apt-helpers.cc
new file mode 100644
index 0000000..bc58d93
--- /dev/null
+++ b/python/python-apt-helpers.cc
@@ -0,0 +1,69 @@
+/*
+ * python-apt.h - Common object creation functions for the public API
+ *
+ * Copyright 2010 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 "apt_pkgmodule.h"
+
+/**
+ * Short macro to be used for the generic FromCpp functions.
+ *
+ */
+#define NEW_FROM(NAME,TYPE,Cpp) \
+PyObject* NAME(Cpp const &obj, bool Delete, PyObject *Owner) \
+{ \
+ CppPyObject<Cpp> *Obj = CppPyObject_NEW<Cpp>(Owner, TYPE, obj); \
+ Obj->NoDelete = (!Delete); \
+ return Obj; \
+}
+
+// Create all those functions
+NEW_FROM(PyAcquireFile_FromCpp,&PyAcquireFile_Type,pkgAcqFile*)
+NEW_FROM(PyAcquireItem_FromCpp,&PyAcquireItem_Type,pkgAcquire::Item*)
+NEW_FROM(PyAcquireItemDesc_FromCpp,&PyAcquireItemDesc_Type,pkgAcquire::ItemDesc*)
+NEW_FROM(PyAcquireWorker_FromCpp,&PyAcquireWorker_Type,pkgAcquire::Worker*)
+NEW_FROM(PyActionGroup_FromCpp,&PyActionGroup_Type,pkgDepCache::ActionGroup*)
+NEW_FROM(PyCache_FromCpp,&PyCache_Type,pkgCache*)
+NEW_FROM(PyCacheFile_FromCpp,&PyCacheFile_Type,pkgCacheFile*)
+NEW_FROM(PyCdrom_FromCpp,&PyCdrom_Type,pkgCdrom)
+NEW_FROM(PyConfiguration_FromCpp,&PyConfiguration_Type,Configuration*)
+NEW_FROM(PyDepCache_FromCpp,&PyDepCache_Type,pkgDepCache*)
+NEW_FROM(PyDependency_FromCpp,&PyDependency_Type,pkgCache::DepIterator)
+//NEW_FROM(PyDependencyList_FromCpp,&PyDependencyList_Type,RDepListStruct)
+NEW_FROM(PyDescription_FromCpp,&PyDescription_Type,pkgCache::DescIterator)
+NEW_FROM(PyHashes_FromCpp,&PyHashes_Type,Hashes)
+NEW_FROM(PyHashString_FromCpp,&PyHashString_Type,HashString*)
+NEW_FROM(PyMetaIndex_FromCpp,&PyMetaIndex_Type,metaIndex*)
+NEW_FROM(PyPackage_FromCpp,&PyPackage_Type,pkgCache::PkgIterator)
+NEW_FROM(PyGroup_FromCpp,&PyGroup_Type,pkgCache::GrpIterator)
+NEW_FROM(PyIndexFile_FromCpp,&PyIndexFile_Type,pkgIndexFile*)
+NEW_FROM(PyOrderList_FromCpp,&PyOrderList_Type,pkgOrderList*)
+NEW_FROM(PyPackageFile_FromCpp,&PyPackageFile_Type,pkgCache::PkgFileIterator)
+//NEW_FROM(PyPackageList_FromCpp,&PyPackageList_Type,PkgListStruct)
+NEW_FROM(PyPackageManager_FromCpp,&PyPackageManager_Type,pkgPackageManager*)
+//NEW_FROM(PyPackageRecords_FromCpp,&PyPackageRecords_Type,PkgRecordsStruct)
+NEW_FROM(PyPolicy_FromCpp,&PyPolicy_Type,pkgPolicy*)
+NEW_FROM(PyProblemResolver_FromCpp,&PyProblemResolver_Type,pkgProblemResolver*)
+NEW_FROM(PySourceList_FromCpp,&PySourceList_Type,pkgSourceList*)
+//NEW_FROM(PySourceRecords_FromCpp,&PySourceRecords_Type,PkgSrcRecordsStruct)
+NEW_FROM(PyTagFile_FromCpp,&PyTagFile_Type,pkgTagFile)
+NEW_FROM(PyTagSection_FromCpp,&PyTagSection_Type,pkgTagSection)
+NEW_FROM(PyVersion_FromCpp,&PyVersion_Type,pkgCache::VerIterator)
+
+#undef NEW_FROM
diff --git a/python/python-apt.h b/python/python-apt.h
new file mode 100644
index 0000000..e3c81b0
--- /dev/null
+++ b/python/python-apt.h
@@ -0,0 +1,368 @@
+/*
+ * python-apt.h - Header file for the public interface.
+ *
+ * Copyright 2009-2010 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.
+ */
+
+#ifndef PYTHON_APT_H
+#define PYTHON_APT_H
+#include <Python.h>
+#include "generic.h"
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/deblistparser.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/cdrom.h>
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/hashes.h>
+
+typedef PyObject *ActionGroupF(pkgDepCache::ActionGroup *);
+typedef pkgDepCache::ActionGroup*& ActionGroupT(PyObject *self);
+
+struct _PyAptPkgAPIStruct {
+ // apt_pkg.Acquire (pkgAcquire*)
+ PyTypeObject *acquire_type;
+ PyObject* (*acquire_fromcpp)(pkgAcquire *acquire, bool Delete, PyObject*);
+ pkgAcquire*& (*acquire_tocpp)(PyObject *self);
+ // apt_pkg.AcquireFile
+ PyTypeObject *acquirefile_type;
+ PyObject* (*acquirefile_fromcpp)(pkgAcqFile* const &obj, bool Delete, PyObject *Owner);
+ pkgAcqFile*& (*acquirefile_tocpp)(PyObject *self);
+
+ // apt_pkg.AcquireItem
+ PyTypeObject *acquireitem_type;
+ PyObject* (*acquireitem_fromcpp)(pkgAcquire::Item* const &obj, bool Delete, PyObject *Owner);
+ pkgAcquire::Item*& (*acquireitem_tocpp)(PyObject *self);
+ // apt_pkg.AcquireItemDesc
+ PyTypeObject *acquireitemdesc_type;
+ PyObject* (*acquireitemdesc_fromcpp)(pkgAcquire::ItemDesc* const &obj, bool Delete, PyObject *Owner);
+ pkgAcquire::ItemDesc*& (*acquireitemdesc_tocpp)(PyObject *self);
+
+ PyTypeObject *acquireworker_type;
+ PyObject* (*acquireworker_fromcpp)(pkgAcquire::Worker* const &obj, bool Delete, PyObject *Owner);
+ pkgAcquire::Worker*& (*acquireworker_tocpp)(PyObject *self);
+
+ PyTypeObject *actiongroup_type;
+ PyObject* (*actiongroup_fromcpp)(pkgDepCache::ActionGroup* const &obj, bool Delete, PyObject *Owner);
+ pkgDepCache::ActionGroup*& (*actiongroup_tocpp)(PyObject *self);
+
+ PyTypeObject *cache_type;
+ PyObject* (*cache_fromcpp)(pkgCache* const &obj, bool Delete, PyObject *Owner);
+ pkgCache*& (*cache_tocpp)(PyObject *self);
+
+ PyTypeObject *cachefile_type;
+ PyObject* (*cachefile_fromcpp)(pkgCacheFile* const &obj, bool Delete, PyObject *Owner);
+ pkgCacheFile*& (*cachefile_tocpp)(PyObject *self);
+
+ PyTypeObject *cdrom_type;
+ PyObject* (*cdrom_fromcpp)(pkgCdrom const &obj, bool Delete, PyObject *Owner);
+ pkgCdrom& (*cdrom_tocpp)(PyObject *self);
+
+ PyTypeObject *configuration_type;
+ PyObject* (*configuration_fromcpp)(Configuration* const &obj, bool Delete, PyObject *Owner);
+ Configuration*& (*configuration_tocpp)(PyObject *self);
+
+ PyTypeObject *depcache_type;
+ PyObject* (*depcache_fromcpp)(pkgDepCache* const &obj, bool Delete, PyObject *Owner);
+ pkgDepCache*& (*depcache_tocpp)(PyObject *self);
+
+ PyTypeObject *dependency_type;
+ PyObject* (*dependency_fromcpp)(pkgCache::DepIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::DepIterator& (*dependency_tocpp)(PyObject *self);
+
+ PyTypeObject *dependencylist_type;
+ void *dependencylist_fromcpp; // FIXME: need dependencylist_fromcpp
+ void *dependencylist_tocpp; // FIXME: need dependencylist_tocpp
+
+ PyTypeObject *description_type;
+ PyObject* (*description_fromcpp)(pkgCache::DescIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::DescIterator& (*description_tocpp)(PyObject *self);
+
+ PyTypeObject *hashes_type;
+ PyObject* (*hashes_fromcpp)(Hashes const &obj, bool Delete, PyObject *Owner);
+ Hashes& (*hashes_tocpp)(PyObject *self);
+
+ PyTypeObject *hashstring_type;
+ PyObject* (*hashstring_fromcpp)(HashString* const &obj, bool Delete, PyObject *Owner);
+ HashString*& (*hashstring_tocpp)(PyObject *self);
+
+ PyTypeObject *metaindex_type;
+ PyObject* (*metaindex_fromcpp)(metaIndex* const &obj, bool Delete, PyObject *Owner);
+ metaIndex*& (*metaindex_tocpp)(PyObject *self);
+
+ PyTypeObject *package_type;
+ PyObject* (*package_fromcpp)(pkgCache::PkgIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::PkgIterator& (*package_tocpp)(PyObject *self);
+
+ PyTypeObject *packagefile_type;
+ PyObject* (*packagefile_fromcpp)(pkgCache::PkgFileIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::PkgFileIterator& (*packagefile_tocpp)(PyObject *self);
+
+ PyTypeObject *packageindexfile_type;
+ PyObject* (*indexfile_fromcpp)(pkgIndexFile* const &obj, bool Delete, PyObject *Owner);
+ pkgIndexFile*& (*packageindexfile_tocpp)(PyObject *self);
+
+ PyTypeObject *packagelist_type;
+ void *packagelist_fromcpp; // FIXME: need packagelist_fromcpp
+ void *packagelist_tocpp; // FIXME: need packagelist_tocpp
+
+ PyTypeObject *packagemanager_type;
+ PyObject* (*packagemanager_fromcpp)(pkgPackageManager* const &obj, bool Delete, PyObject *Owner);
+ pkgPackageManager*& (*packagemanager_tocpp)(PyObject *self);
+
+ PyTypeObject *packagerecords_type;
+ void *packagerecords_fromcpp; // FIXME: need packagerecords_fromcpp
+ void *packagerecords_tocpp; // FIXME: need packagerecords_tocpp
+
+ PyTypeObject *policy_type;
+ PyObject* (*policy_fromcpp)(pkgPolicy* const &obj, bool Delete, PyObject *Owner);
+ pkgPolicy*& (*policy_tocpp)(PyObject *self);
+
+ PyTypeObject *problemresolver_type;
+ PyObject* (*problemresolver_fromcpp)(pkgProblemResolver* const &obj, bool Delete, PyObject *Owner);
+ pkgProblemResolver*& (*problemresolver_tocpp)(PyObject *self);
+
+ PyTypeObject *sourcelist_type;
+ PyObject* (*sourcelist_fromcpp)(pkgSourceList* const &obj, bool Delete, PyObject *Owner);
+ pkgSourceList*& (*sourcelist_tocpp)(PyObject *self);
+
+ PyTypeObject *sourcerecords_type;
+ void *sourcerecords_fromcpp; // FIXME: need sourcerecords_fromcpp
+ void *sourcerecords_tocpp; // FIXME: need sourcerecords_tocpp
+
+ PyTypeObject *tagfile_type;
+ PyObject* (*tagfile_fromcpp)(pkgTagFile const &obj, bool Delete, PyObject *Owner);
+ pkgTagFile& (*tagfile_tocpp)(PyObject *self);
+
+ PyTypeObject *tagsection_type;
+ PyObject* (*tagsection_fromcpp)(pkgTagSection const &obj, bool Delete, PyObject *Owner);
+ pkgTagSection& (*tagsection_tocpp)(PyObject *self);
+
+ PyTypeObject *version_type;
+ PyObject* (*version_fromcpp)(pkgCache::VerIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::VerIterator& (*version_tocpp)(PyObject *self);
+
+ PyTypeObject *group_type;
+ PyObject* (*group_fromcpp)(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::GrpIterator& (*group_tocpp)(PyObject *self);
+
+ PyTypeObject *orderlist_type;
+ PyObject* (*orderlist_fromcpp)(pkgOrderList* const &obj, bool Delete, PyObject *Owner);
+ pkgOrderList*& (*orderlist_tocpp)(PyObject *self);
+
+ PyTypeObject *sourcerecordfiles_type;
+ void *sourcerecordfiles_fromcpp; // FIXME: need sourcerecordfiles_fromcpp
+ void *sourcerecordfiles_tocpp; // FIXME: need sourcerecordfiles_tocpp
+};
+
+// Checking macros.
+# define PyAcquire_Check(op) PyObject_TypeCheck(op, &PyAcquire_Type)
+# define PyAcquireFile_Check(op) PyObject_TypeCheck(op, &PyAcquireFile_Type)
+# define PyAcquireItem_Check(op) PyObject_TypeCheck(op, &PyAcquireItem_Type)
+# define PyAcquireItemDesc_Check(op) PyObject_TypeCheck(op, &PyAcquireItemDesc_Type)
+# define PyAcquireWorker_Check(op) PyObject_TypeCheck(op, &PyAcquireWorker_Type)
+# define PyActionGroup_Check(op) PyObject_TypeCheck(op, &PyActionGroup_Type)
+# define PyCache_Check(op) PyObject_TypeCheck(op, &PyCache_Type)
+# define PyCacheFile_Check(op) PyObject_TypeCheck(op, &PyCacheFile_Type)
+# define PyCdrom_Check(op) PyObject_TypeCheck(op, &PyCdrom_Type)
+# define PyConfiguration_Check(op) PyObject_TypeCheck(op, &PyConfiguration_Type)
+# define PyDepCache_Check(op) PyObject_TypeCheck(op, &PyDepCache_Type)
+# define PyDependency_Check(op) PyObject_TypeCheck(op, &PyDependency_Type)
+# define PyDependencyList_Check(op) PyObject_TypeCheck(op, &PyDependencyList_Type)
+# define PyDescription_Check(op) PyObject_TypeCheck(op, &PyDescription_Type)
+# define PyGroup_Check(op) PyObject_TypeCheck(op, &PyGroup_Type)
+# define PyHashes_Check(op) PyObject_TypeCheck(op, &PyHashes_Type)
+# define PyHashString_Check(op) PyObject_TypeCheck(op, &PyHashString_Type)
+# define PyIndexRecords_Check(op) PyObject_TypeCheck(op, &PyIndexRecords_Type)
+# define PyMetaIndex_Check(op) PyObject_TypeCheck(op, &PyMetaIndex_Type)
+# define PyPackage_Check(op) PyObject_TypeCheck(op, &PyPackage_Type)
+# define PyPackageFile_Check(op) PyObject_TypeCheck(op, &PyPackageFile_Type)
+# define PyIndexFile_Check(op) PyObject_TypeCheck(op, &PyIndexFile_Type)
+# define PyPackageList_Check(op) PyObject_TypeCheck(op, &PyPackageList_Type)
+# define PyPackageManager_Check(op) PyObject_TypeCheck(op, &PyPackageManager_Type)
+# define PyPackageRecords_Check(op) PyObject_TypeCheck(op, &PyPackageRecords_Type)
+# define PyPolicy_Check(op) PyObject_TypeCheck(op, &PyPolicy_Type)
+# define PyProblemResolver_Check(op) PyObject_TypeCheck(op, &PyProblemResolver_Type)
+# define PySourceList_Check(op) PyObject_TypeCheck(op, &PySourceList_Type)
+# define PySourceRecords_Check(op) PyObject_TypeCheck(op, &PySourceRecords_Type)
+# define PySourceRecordFiles_Check(op) PyObject_TypeCheck(op, &PySourceRecordFiles_Type)
+# define PyTagFile_Check(op) PyObject_TypeCheck(op, &PyTagFile_Type)
+# define PyTagSection_Check(op) PyObject_TypeCheck(op, &PyTagSection_Type)
+# define PyVersion_Check(op) PyObject_TypeCheck(op, &PyVersion_Type)
+// Exact check macros.
+# define PyAcquire_CheckExact(op) (op->op_type == &PyAcquire_Type)
+# define PyAcquireFile_CheckExact(op) (op->op_type == &PyAcquireFile_Type)
+# define PyAcquireItem_CheckExact(op) (op->op_type == &PyAcquireItem_Type)
+# define PyAcquireItemDesc_CheckExact(op) (op->op_type == &PyAcquireItemDesc_Type)
+# define PyAcquireWorker_CheckExact(op) (op->op_type == &PyAcquireWorker_Type)
+# define PyActionGroup_CheckExact(op) (op->op_type == &PyActionGroup_Type)
+# define PyCache_CheckExact(op) (op->op_type == &PyCache_Type)
+# define PyCacheFile_CheckExact(op) (op->op_type == &PyCacheFile_Type)
+# define PyCdrom_CheckExact(op) (op->op_type == &PyCdrom_Type)
+# define PyConfiguration_CheckExact(op) (op->op_type == &PyConfiguration_Type)
+# define PyDepCache_CheckExact(op) (op->op_type == &PyDepCache_Type)
+# define PyDependency_CheckExact(op) (op->op_type == &PyDependency_Type)
+# define PyDependencyList_CheckExact(op) (op->op_type == &PyDependencyList_Type)
+# define PyDescription_CheckExact(op) (op->op_type == &PyDescription_Type)
+# define PyHashes_CheckExact(op) (op->op_type == &PyHashes_Type)
+# define PyGroup_CheckExact(op) (op->op_type == &PyGroup_Type)
+# define PyHashString_CheckExact(op) (op->op_type == &PyHashString_Type)
+# define PyIndexRecords_CheckExact(op) (op->op_type == &PyIndexRecords_Type)
+# define PyMetaIndex_CheckExact(op) (op->op_type == &PyMetaIndex_Type)
+# define PyPackage_CheckExact(op) (op->op_type == &PyPackage_Type)
+# define PyPackageFile_CheckExact(op) (op->op_type == &PyPackageFile_Type)
+# define PyIndexFile_CheckExact(op) (op->op_type == &PyIndexFile_Type)
+# define PyOrderList_CheckExact(op) (op->op_type == &PyOrderList_Type)
+# define PyPackageList_CheckExact(op) (op->op_type == &PyPackageList_Type)
+# define PyPackageManager_CheckExact(op) (op->op_type == &PyPackageManager_Type)
+# define PyPackageRecords_CheckExact(op) (op->op_type == &PyPackageRecords_Type)
+# define PyPolicy_CheckExact(op) (op->op_type == &PyPolicy_Type)
+# define PyProblemResolver_CheckExact(op) (op->op_type == &PyProblemResolver_Type)
+# define PySourceList_CheckExact(op) (op->op_type == &PySourceList_Type)
+# define PySourceRecords_CheckExact(op) (op->op_type == &PySourceRecords_Type)
+# define PySourceRecordFiles_CheckExact(op) (op->op_type == &PySourceRecordFiles_Type)
+# define PyTagFile_CheckExact(op) (op->op_type == &PyTagFile_Type)
+# define PyTagSection_CheckExact(op) (op->op_type == &PyTagSection_Type)
+# define PyVersion_CheckExact(op) (op->op_type == &PyVersion_Type)
+
+# ifndef APT_PKGMODULE_H
+static struct _PyAptPkgAPIStruct *_PyAptPkg_API;
+
+static int import_apt_pkg(void) {
+# if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1
+ _PyAptPkg_API = (_PyAptPkgAPIStruct *)PyCapsule_Import("apt_pkg._C_API", 0);
+# else
+ _PyAptPkg_API = (_PyAptPkgAPIStruct *)PyCObject_Import("apt_pkg", "_C_API");
+# endif // PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1
+ return (_PyAptPkg_API != NULL) ? 0 : -1;
+}
+
+# define PyAcquire_Type *(_PyAptPkg_API->acquire_type)
+# define PyAcquireFile_Type *(_PyAptPkg_API->acquirefile_type)
+# define PyAcquireItem_Type *(_PyAptPkg_API->acquireitem_type)
+# define PyAcquireItemDesc_Type *(_PyAptPkg_API->acquireitemdesc_type)
+# define PyAcquireWorker_Type *(_PyAptPkg_API->acquireworker_type)
+# define PyActionGroup_Type *(_PyAptPkg_API->actiongroup_type)
+# define PyCache_Type *(_PyAptPkg_API->cache_type)
+# define PyCacheFile_Type *(_PyAptPkg_API->cachefile_type)
+# define PyCdrom_Type *(_PyAptPkg_API->cdrom_type)
+# define PyConfiguration_Type *(_PyAptPkg_API->configuration_type)
+# define PyDepCache_Type *(_PyAptPkg_API->depcache_type)
+# define PyDependency_Type *(_PyAptPkg_API->dependency_type)
+# define PyDependencyList_Type *(_PyAptPkg_API->dependencylist_type)
+# define PyDescription_Type *(_PyAptPkg_API->description_type)
+# define PyGroup_Type *(_PyAptPkg_API->group_type)
+# define PyHashes_Type *(_PyAptPkg_API->hashes_type)
+# define PyHashString_Type *(_PyAptPkg_API->hashstring_type)
+# define PyIndexRecords_Type *(_PyAptPkg_API->indexrecords_type)
+# define PyMetaIndex_Type *(_PyAptPkg_API->metaindex_type)
+# define PyPackage_Type *(_PyAptPkg_API->package_type)
+# define PyPackageFile_Type *(_PyAptPkg_API->packagefile_type)
+# define PyIndexFile_Type *(_PyAptPkg_API->packageindexfile_type)
+# define PyOrderList_Type *(_PyAptPkg_API->orderlist_type)
+# define PyPackageList_Type *(_PyAptPkg_API->packagelist_type)
+# define PyPackageManager_Type *(_PyAptPkg_API->packagemanager_type)
+# define PyPackageRecords_Type *(_PyAptPkg_API->packagerecords_type)
+# define PyPolicy_Type *(_PyAptPkg_API->policy_type)
+# define PyProblemResolver_Type *(_PyAptPkg_API->problemresolver_type)
+# define PySourceList_Type *(_PyAptPkg_API->sourcelist_type)
+# define PySourceRecords_Type *(_PyAptPkg_API->sourcerecords_type)
+# define PySourceRecordFiles_Type *(_PyAptPkg_API->sourcerecordfiles_type)
+# define PyTagFile_Type *(_PyAptPkg_API->tagfile_type)
+# define PyTagSection_Type *(_PyAptPkg_API->tagsection_type)
+# define PyVersion_Type *(_PyAptPkg_API->version_type)
+// Code
+# define PyAcquire_ToCpp _PyAptPkg_API->acquire_tocpp
+# define PyAcquireFile_ToCpp _PyAptPkg_API->acquirefile_tocpp
+# define PyAcquireItem_ToCpp _PyAptPkg_API->acquireitem_tocpp
+# define PyAcquireItemDesc_ToCpp _PyAptPkg_API->acquireitemdesc_tocpp
+# define PyAcquireWorker_ToCpp _PyAptPkg_API->acquireworker_tocpp
+# define PyActionGroup_ToCpp _PyAptPkg_API->actiongroup_tocpp
+# define PyCache_ToCpp _PyAptPkg_API->cache_tocpp
+# define PyCacheFile_ToCpp _PyAptPkg_API->cachefile_tocpp
+# define PyCdrom_ToCpp _PyAptPkg_API->cdrom_tocpp
+# define PyConfiguration_ToCpp _PyAptPkg_API->configuration_tocpp
+# define PyDepCache_ToCpp _PyAptPkg_API->depcache_tocpp
+# define PyDependency_ToCpp _PyAptPkg_API->dependency_tocpp
+# define PyDependencyList_ToCpp _PyAptPkg_API->dependencylist_tocpp // NULL
+# define PyDescription_ToCpp _PyAptPkg_API->description_tocpp
+# define PyGroup_ToCpp _PyAptPkg_API->group_tocpp
+# define PyHashes_ToCpp _PyAptPkg_API->hashes_tocpp
+# define PyHashString_ToCpp _PyAptPkg_API->hashstring_tocpp
+# define PyIndexRecords_ToCpp _PyAptPkg_API->indexrecords_tocpp
+# define PyMetaIndex_ToCpp _PyAptPkg_API->metaindex_tocpp
+# define PyPackage_ToCpp _PyAptPkg_API->package_tocpp
+# define PyPackageFile_ToCpp _PyAptPkg_API->packagefile_tocpp
+# define PyIndexFile_ToCpp _PyAptPkg_API->packageindexfile_tocpp
+# define PyOrderList_ToCpp _PyAptPkg_API->orderlist_tocpp // NULL
+# define PyPackageList_ToCpp _PyAptPkg_API->packagelist_tocpp // NULL
+# define PyPackageManager_ToCpp _PyAptPkg_API->packagemanager_tocpp
+# define PyPackageRecords_ToCpp _PyAptPkg_API->packagerecords_tocpp
+# define PyPolicy_ToCpp _PyAptPkg_API->policy_tocpp
+# define PyProblemResolver_ToCpp _PyAptPkg_API->problemresolver_tocpp
+# define PySourceList_ToCpp _PyAptPkg_API->sourcelist_tocpp
+# define PySourceRecords_ToCpp _PyAptPkg_API->sourcerecords_tocpp // NULL
+# define PySourceRecordFiles_ToCpp _PyAptPkg_API->sourcerecordfiles_tocpp // NULL
+# define PyTagFile_ToCpp _PyAptPkg_API->tagfile_tocpp
+# define PyTagSection_ToCpp _PyAptPkg_API->tagsection_tocpp
+# define PyVersion_ToCpp _PyAptPkg_API->version_tocpp
+// Get the C++ object
+# define PyAcquire_FromCpp _PyAptPkg_API->acquire_fromcpp
+# define PyAcquireFile_FromCpp _PyAptPkg_API->acquirefile_fromcpp
+# define PyAcquireItem_FromCpp _PyAptPkg_API->acquireitem_fromcpp
+# define PyAcquireItemDesc_FromCpp _PyAptPkg_API->acquireitemdesc_fromcpp
+# define PyAcquireWorker_FromCpp _PyAptPkg_API->acquireworker_fromcpp
+# define PyActionGroup_FromCpp _PyAptPkg_API->actiongroup_fromcpp
+# define PyCache_FromCpp _PyAptPkg_API->cache_fromcpp
+# define PyCacheFile_FromCpp _PyAptPkg_API->cachefile_fromcpp
+# define PyCdrom_FromCpp _PyAptPkg_API->cdrom_fromcpp
+# define PyConfiguration_FromCpp _PyAptPkg_API->configuration_fromcpp
+# define PyDepCache_FromCpp _PyAptPkg_API->depcache_fromcpp
+# define PyDependency_FromCpp _PyAptPkg_API->dependency_fromcpp
+# define PyDependencyList_FromCpp _PyAptPkg_API->dependencylist_fromcpp // NULL
+# define PyDescription_FromCpp _PyAptPkg_API->description_fromcpp
+# define PyGroup_FromCpp _PyAptPkg_API->group_fromcpp
+# define PyHashes_FromCpp _PyAptPkg_API->hashes_fromcpp
+# define PyHashString_FromCpp _PyAptPkg_API->hashstring_fromcpp
+# define PyIndexRecords_FromCpp _PyAptPkg_API->indexrecords_fromcpp
+# define PyMetaIndex_FromCpp _PyAptPkg_API->metaindex_fromcpp
+# define PyPackage_FromCpp _PyAptPkg_API->package_fromcpp
+# define PyPackageFile_FromCpp _PyAptPkg_API->packagefile_fromcpp
+# define PyIndexFile_FromCpp _PyAptPkg_API->packageindexfile_fromcpp
+# define PyOrderList_FromCpp _PyAptPkg_API->orderlist_fromcpp // NULL
+# define PyPackageList_FromCpp _PyAptPkg_API->packagelist_fromcpp // NULL
+# define PyPackageManager_FromCpp _PyAptPkg_API->packagemanager_fromcpp
+# define PyPackageRecords_FromCpp _PyAptPkg_API->packagerecords_fromcpp
+# define PyPolicy_FromCpp _PyAptPkg_API->policy_fromcpp
+# define PyProblemResolver_FromCpp _PyAptPkg_API->problemresolver_fromcpp
+# define PySourceList_FromCpp _PyAptPkg_API->sourcelist_fromcpp
+# define PySourceRecords_FromCpp _PyAptPkg_API->sourcerecords_fromcpp // NULL
+# define PySourceRecordFiles_FromCpp _PyAptPkg_API->sourcerecordfiles_fromcpp // NULL
+# define PyTagFile_FromCpp _PyAptPkg_API->tagfile_fromcpp
+# define PyTagSection_FromCpp _PyAptPkg_API->tagsection_fromcpp
+# define PyVersion_FromCpp _PyAptPkg_API->version_fromcpp
+# endif // APT_PKGMODULE_H
+
+#endif
+
diff --git a/python/sourcelist.cc b/python/sourcelist.cc
new file mode 100644
index 0000000..3c1d49c
--- /dev/null
+++ b/python/sourcelist.cc
@@ -0,0 +1,170 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: sourcelist.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $
+/* ######################################################################
+
+ SourcesList - Wrapper for the SourcesList functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/sourcelist.h>
+
+#include <Python.h>
+ /*}}}*/
+
+
+
+// PkgsourceList Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static char *doc_PkgSourceListFindIndex =
+ "find_index(pkgfile: apt_pkg.PackageFile) -> apt_pkg.IndexFile\n\n"
+ "Return the index file for the given package file, or None if none\n"
+ "could be found.";
+static PyObject *PkgSourceListFindIndex(PyObject *Self,PyObject *Args)
+{
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+ PyObject *pyPkgFileIter;
+ CppPyObject<pkgIndexFile*> *pyPkgIndexFile;
+
+ if (PyArg_ParseTuple(Args, "O!", &PyPackageFile_Type,&pyPkgFileIter) == 0)
+ return 0;
+
+ pkgCache::PkgFileIterator &i = GetCpp<pkgCache::PkgFileIterator>(pyPkgFileIter);
+ pkgIndexFile *index;
+ if(list->FindIndex(i, index))
+ {
+ pyPkgIndexFile = CppPyObject_NEW<pkgIndexFile*>(pyPkgFileIter,&PyIndexFile_Type,index);
+ // Do not delete the pkgIndexFile*, it is managed by pkgSourceList.
+ pyPkgIndexFile->NoDelete = true;
+ return pyPkgIndexFile;
+ }
+
+ //&PyIndexFile_Type,&pyPkgIndexFile)
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char *doc_PkgSourceListReadMainList =
+ "read_main_list() -> bool\n\n"
+ "Read /etc/apt/sources.list and similar files to populate the list\n"
+ "of indexes.";
+static PyObject *PkgSourceListReadMainList(PyObject *Self,PyObject *Args)
+{
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+ bool res = list->ReadMainList();
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSourceListGetIndexes =
+ "get_indexes(acquire: apt_pkg.Acquire[, all: bool=False]) -> bool\n\n"
+ "Add all indexes (i.e. stuff like Release files, Packages files)\n"
+ "to the Acquire object 'acquire'. If 'all' is True, all indexes\n"
+ "will be added, otherwise only changed indexes will be added.";
+static PyObject *PkgSourceListGetIndexes(PyObject *Self,PyObject *Args)
+{
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+
+ PyObject *pyFetcher;
+ char all = 0;
+ if (PyArg_ParseTuple(Args, "O!|b",&PyAcquire_Type,&pyFetcher, &all) == 0)
+ return 0;
+
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyFetcher);
+ bool res = list->GetIndexes(fetcher, all);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyMethodDef PkgSourceListMethods[] =
+{
+ {"find_index",PkgSourceListFindIndex,METH_VARARGS,doc_PkgSourceListFindIndex},
+ {"read_main_list",PkgSourceListReadMainList,METH_VARARGS,doc_PkgSourceListReadMainList},
+ {"get_indexes",PkgSourceListGetIndexes,METH_VARARGS,doc_PkgSourceListGetIndexes},
+ {}
+};
+
+static PyObject *PkgSourceListGetList(PyObject *Self,void*)
+{
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+ PyObject *List = PyList_New(0);
+ for (std::vector<metaIndex *>::const_iterator I = list->begin();
+ I != list->end(); I++)
+ {
+ CppPyObject<metaIndex*> *Obj;
+ Obj = CppPyObject_NEW<metaIndex*>(Self, &PyMetaIndex_Type,*I);
+ // Never delete metaIndex*, they are managed by the pkgSourceList.
+ Obj->NoDelete = true;
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyGetSetDef PkgSourceListGetSet[] = {
+ {"list",PkgSourceListGetList,0,"A list of MetaIndex() objects.",0},
+ {}
+};
+
+static PyObject *PkgSourceListNew(PyTypeObject *type,PyObject *args,PyObject *kwds)
+{
+ char *kwlist[] = {0};
+ if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0)
+ return 0;
+ return CppPyObject_NEW<pkgSourceList*>(NULL, type,new pkgSourceList());
+}
+
+static const char *sourcelist_doc =
+ "SourceList()\n\n"
+ "Represent the list of sources stored in /etc/apt/sources.list and\n"
+ "similar files.";
+PyTypeObject PySourceList_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.SourceList", // tp_name
+ sizeof(CppPyObject<pkgSourceList*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgSourceList*>, // 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
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ sourcelist_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgSourceListMethods, // tp_methods
+ 0, // tp_members
+ PkgSourceListGetSet, // 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
+ PkgSourceListNew, // tp_new
+};
+
diff --git a/python/string.cc b/python/string.cc
new file mode 100644
index 0000000..7cfaa70
--- /dev/null
+++ b/python/string.cc
@@ -0,0 +1,142 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: string.cc,v 1.3 2002/01/08 06:53:04 jgg Exp $
+/* ######################################################################
+
+ string - Mappings for the string functions that are worthwile for
+ Python users
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "apt_pkgmodule.h"
+#include "generic.h"
+
+#include <apt-pkg/strutl.h>
+
+#include <Python.h>
+ /*}}}*/
+
+// Templated function /*{{{*/
+/* Macro for the generic string in string out function */
+#define MkStr(Python,CFunc) \
+PyObject *Python(PyObject *Self,PyObject *Args) \
+{ \
+ char *Str = 0; \
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0) \
+ return 0; \
+ return CppPyString(CFunc(Str)); \
+}
+
+#define MkInt(Python,CFunc, ctype, pytype, ...) \
+PyObject *Python(PyObject *Self,PyObject *Args) \
+{ \
+ ctype Val = 0; \
+ if (PyArg_ParseTuple(Args,pytype,&Val) == 0) \
+ return 0; \
+ return CppPyString(CFunc(Val, ##__VA_ARGS__)); \
+}
+
+MkStr(StrDeQuote,DeQuoteString);
+
+/*
+ * Input bytes(Py3k)/str(Py2), output str.
+ */
+PyObject *StrBase64Encode(PyObject *Self,PyObject *Args) {
+ char *Str = 0;
+ #if PY_MAJOR_VERSION >= 3
+ if (PyArg_ParseTuple(Args,"y",&Str) == 0)
+ #else
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ #endif
+ return 0;
+ return CppPyString(Base64Encode(Str));
+}
+
+PyObject *StrURItoFileName(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ return 0;
+ return CppPyPath(URItoFileName(Str));
+}
+
+//MkFloat(StrSizeToStr,SizeToStr);
+MkInt(StrTimeToStr,TimeToStr, unsigned long, "k");
+MkInt(StrTimeRFC1123,TimeRFC1123, long long, "L", false);
+ /*}}}*/
+
+// Other String functions /*{{{*/
+PyObject *StrSizeToStr(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ double value;
+
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+ // In Python 3, PyInt_Check is aliased to PyLong_Check and PyInt_AsLong is
+ // aliased to PyLong_AsLong. Therefore we do the actual long checks first
+ // so that if it is a long in Python 3, the value will be converted to a
+ // double rather than a long. This avoids OverflowError regressions in
+ // Python 3. LP: #1030278
+ if (PyLong_Check(Obj))
+ value = PyLong_AsDouble(Obj);
+ else if (PyInt_Check(Obj))
+ value = PyInt_AsLong(Obj);
+ else if (PyFloat_Check(Obj))
+ value = PyFloat_AsDouble(Obj);
+ else {
+ PyErr_SetString(PyExc_TypeError,"Only understand integers and floats");
+ return 0;
+ }
+ // Check for OverflowErrors or other exceptions during conversion.
+ if (PyErr_Occurred())
+ return 0;
+ return CppPyString(SizeToStr(value));
+}
+
+PyObject *StrQuoteString(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ char *Bad = 0;
+ if (PyArg_ParseTuple(Args,"ss",&Str,&Bad) == 0)
+ return 0;
+ return CppPyString(QuoteString(Str,Bad));
+}
+
+PyObject *StrStringToBool(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ return 0;
+ return MkPyNumber(StringToBool(Str));
+}
+
+PyObject *StrStrToTime(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ return 0;
+
+ time_t Result;
+APT_IGNORE_DEPRECATED_PUSH
+ if (RFC1123StrToTime(Str,Result) == false)
+ {
+APT_IGNORE_DEPRECATED_POP
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return MkPyNumber(Result);
+}
+
+PyObject *StrCheckDomainList(PyObject *Self,PyObject *Args)
+{
+ char *Host = 0;
+ char *List = 0;
+ if (PyArg_ParseTuple(Args,"ss",&Host,&List) == 0)
+ return 0;
+ return PyBool_FromLong(CheckDomainList(Host,List));
+}
+
+ /*}}}*/
diff --git a/python/tag.cc b/python/tag.cc
new file mode 100644
index 0000000..691b67f
--- /dev/null
+++ b/python/tag.cc
@@ -0,0 +1,1063 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: tag.cc,v 1.3 2002/02/26 01:36:15 mdz Exp $
+/* ######################################################################
+
+ Tag - Binding for the RFC 822 tag file parser
+
+ Upon reflection I have make the TagSection wrapper look like a map..
+ The other option was to use a sequence (which nicely matches the internal
+ storage) but really makes no sense to a Python Programmer.. One
+ specialized lookup is provided, the FindFlag lookup - as well as the
+ usual set of duplicate things to match the C++ interface.
+
+ The TagFile interface is also slightly different, it has a built in
+ internal TagSection object that is used. Do not hold onto a reference
+ to a TagSection and let TagFile go out of scope! The underlying storage
+ for the section will go away and it will seg.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/fileutl.h>
+
+#include <stdio.h>
+#include <iostream>
+#include <Python.h>
+
+using namespace std;
+ /*}}}*/
+/* We need to keep a private copy of the data.. */
+struct TagSecData : public CppPyObject<pkgTagSection>
+{
+ char *Data;
+ bool Bytes;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *Encoding;
+#endif
+};
+
+// The owner of the TagFile is a Python file object.
+struct TagFileData : public CppPyObject<pkgTagFile>
+{
+ TagSecData *Section;
+ FileFd Fd;
+ bool Bytes;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *Encoding;
+#endif
+};
+
+// Traversal and Clean for owned objects
+int TagFileTraverse(PyObject *self, visitproc visit, void* arg) {
+ Py_VISIT(((TagFileData *)self)->Section);
+ Py_VISIT(((TagFileData *)self)->Owner);
+ return 0;
+}
+
+int TagFileClear(PyObject *self) {
+ Py_CLEAR(((TagFileData *)self)->Section);
+ Py_CLEAR(((TagFileData *)self)->Owner);
+ return 0;
+}
+
+// Helpers to return Unicode or bytes as appropriate.
+#if PY_MAJOR_VERSION < 3
+#define TagSecString_FromStringAndSize(self, v, len) \
+ PyString_FromStringAndSize((v), (len))
+#define TagSecString_FromString(self, v) CppPyString(v)
+#else
+static PyObject *TagSecString_FromStringAndSize(PyObject *self, const char *v,
+ Py_ssize_t len) {
+ TagSecData *Self = (TagSecData *)self;
+ if (Self->Bytes)
+ return PyBytes_FromStringAndSize(v, len);
+ else if (Self->Encoding)
+ return PyUnicode_Decode(v, len, PyUnicode_AsString(Self->Encoding), 0);
+ else
+ return PyUnicode_FromStringAndSize(v, len);
+}
+
+static PyObject *TagSecString_FromString(PyObject *self, const char *v) {
+ TagSecData *Self = (TagSecData *)self;
+ if (Self->Bytes)
+ return PyBytes_FromString(v);
+ else if (Self->Encoding)
+ return PyUnicode_Decode(v, strlen(v),
+ PyUnicode_AsString(Self->Encoding), 0);
+ else
+ return PyUnicode_FromString(v);
+}
+#endif
+
+
+ /*}}}*/
+// TagSecFree - Free a Tag Section /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void TagSecFree(PyObject *Obj)
+{
+ TagSecData *Self = (TagSecData *)Obj;
+ delete [] Self->Data;
+ CppDealloc<pkgTagSection>(Obj);
+}
+ /*}}}*/
+// TagFileFree - Free a Tag File /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void TagFileFree(PyObject *Obj)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << "^ ===\n";
+ #endif
+ PyObject_GC_UnTrack(Obj);
+ TagFileData *Self = (TagFileData *)Obj;
+ Py_CLEAR(Self->Section);
+ Self->Object.~pkgTagFile();
+ Self->Fd.~FileFd();
+ Py_CLEAR(Self->Owner);
+ Obj->ob_type->tp_free(Obj);
+}
+ /*}}}*/
+
+// Tag Section Wrappers /*{{{*/
+static char *doc_Find =
+ "find(name: str[, default = None]) -> str\n\n"
+ "Find the key given by 'name' and return the value. If the key can\n"
+ "not be found, return 'default'.";
+static PyObject *TagSecFind(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|z",&Name,&Default) == 0)
+ return 0;
+
+ const char *Start;
+ const char *Stop;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false)
+ {
+ if (Default == 0)
+ Py_RETURN_NONE;
+ return TagSecString_FromString(Self,Default);
+ }
+ return TagSecString_FromStringAndSize(Self,Start,Stop-Start);
+}
+
+static char *doc_FindRaw =
+ "find_raw(name: str[, default = None] -> str\n\n"
+ "Same as find(), but returns the complete 'key: value' field; instead of\n"
+ "just the value.";
+static PyObject *TagSecFindRaw(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|z",&Name,&Default) == 0)
+ return 0;
+
+ unsigned Pos;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Pos) == false)
+ {
+ if (Default == 0)
+ Py_RETURN_NONE;
+ return TagSecString_FromString(Self,Default);
+ }
+
+ const char *Start;
+ const char *Stop;
+ GetCpp<pkgTagSection>(Self).Get(Start,Stop,Pos);
+
+ return TagSecString_FromStringAndSize(Self,Start,Stop-Start);
+}
+
+static char *doc_FindFlag =
+ "find_flag(name: str) -> int\n\n"
+ "Return 1 if the key's value is 'yes' or a similar value describing\n"
+ "a boolean true. If the field does not exist, or does not have such a\n"
+ "value, return 0.";
+static PyObject *TagSecFindFlag(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ unsigned long Flag = 0;
+ if (GetCpp<pkgTagSection>(Self).FindFlag(Name,Flag,1) == false)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return PyBool_FromLong(Flag);
+}
+
+static char *doc_Write =
+ "write(file: int, order: List[str], rewrite: List[Tag]) -> None\n\n"
+ "Rewrites the section into the given file descriptor, which should be\n"
+ "a file descriptor or an object providing a fileno() method.\n"
+ "\n"
+ ".. versionadded:: 1.9.0";
+static PyObject *TagSecWrite(PyObject *Self, PyObject *Args, PyObject *kwds)
+{
+ char *kwlist[] = {"file", "order", "rewrite", nullptr};
+ PyObject *pFile;
+ PyObject *pOrder;
+ PyObject *pRewrite;
+ if (PyArg_ParseTupleAndKeywords(Args,kwds, "OO!O!",kwlist, &pFile,&PyList_Type,&pOrder, &PyList_Type, &pRewrite) == 0)
+ return nullptr;
+
+ int fileno = PyObject_AsFileDescriptor(pFile);
+ // handle invalid arguments
+ if (fileno == -1)
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Argument must be string, fd or have a fileno() method");
+ return 0;
+ }
+
+ FileFd file(fileno);
+ const char **order = ListToCharChar(pOrder,true);
+ if (order == nullptr)
+ return nullptr;
+ std::vector<pkgTagSection::Tag> rewrite;
+ for (int I = 0; I != PySequence_Length(pRewrite); I++) {
+ PyObject *item = PySequence_GetItem(pRewrite, I);
+ if (!PyObject_TypeCheck(item, &PyTag_Type))
+ return PyErr_SetString(PyExc_TypeError, "Wrong type for tag in list"), nullptr;
+ rewrite.push_back(GetCpp<pkgTagSection::Tag>(item));
+ }
+
+ return HandleErrors(PyBool_FromLong(GetCpp<pkgTagSection>(Self).Write(file, order, rewrite)));
+}
+
+
+// Map access, operator []
+static PyObject *TagSecMap(PyObject *Self,PyObject *Arg)
+{
+ const char *Name = PyObject_AsString(Arg);
+ if (Name == 0)
+ return 0;
+ const char *Start;
+ const char *Stop;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false)
+ {
+ PyErr_SetString(PyExc_KeyError,Name);
+ return 0;
+ }
+
+ return TagSecString_FromStringAndSize(Self,Start,Stop-Start);
+}
+
+// len() operation
+static Py_ssize_t TagSecLength(PyObject *Self)
+{
+ pkgTagSection &Sec = GetCpp<pkgTagSection>(Self);
+ return Sec.Count();
+}
+
+// Look like a mapping
+static char *doc_Keys =
+ "keys() -> list\n\n"
+ "Return a list of all keys.";
+static PyObject *TagSecKeys(PyObject *Self,PyObject *Args)
+{
+ pkgTagSection &Tags = GetCpp<pkgTagSection>(Self);
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ for (unsigned int I = 0; I != Tags.Count(); I++)
+ {
+ const char *Start;
+ const char *Stop;
+ Tags.Get(Start,Stop,I);
+ const char *End = Start;
+ for (; End < Stop && *End != ':'; End++);
+
+ PyObject *Obj;
+ PyList_Append(List,Obj = PyString_FromStringAndSize(Start,End-Start));
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+#if PY_MAJOR_VERSION < 3
+static char *doc_Exists =
+ "has_key(name: str) -> bool\n\n"
+ "Return True if the key given by 'name' exists, False otherwise.";
+static PyObject *TagSecExists(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ const char *Start;
+ const char *Stop;
+ return PyBool_FromLong(GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop));
+}
+#endif
+
+static int TagSecContains(PyObject *Self,PyObject *Arg)
+{
+ const char *Name = PyObject_AsString(Arg);
+ if (Name == 0)
+ return 0;
+ const char *Start;
+ const char *Stop;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false)
+ return 0;
+ return 1;
+}
+
+static char *doc_Bytes =
+ "bytes() -> int\n\n"
+ "Return the number of bytes this section is large.";
+static PyObject *TagSecBytes(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ return MkPyNumber(GetCpp<pkgTagSection>(Self).size());
+}
+
+static PyObject *TagSecStr(PyObject *Self)
+{
+ const char *Start;
+ const char *Stop;
+ GetCpp<pkgTagSection>(Self).GetSection(Start,Stop);
+ return TagSecString_FromStringAndSize(Self,Start,Stop-Start);
+}
+ /*}}}*/
+// TagFile Wrappers /*{{{*/
+static char *doc_Step =
+ "step() -> bool\n\n"
+ "Step forward in the file";
+static PyObject *TagFileStep(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ TagFileData &Obj = *(TagFileData *)Self;
+ if (Obj.Object.Step(Obj.Section->Object) == false)
+ return HandleErrors(PyBool_FromLong(0));
+
+ return HandleErrors(PyBool_FromLong(1));
+}
+
+// TagFile Wrappers /*{{{*/
+static PyObject *TagFileNext(PyObject *Self)
+{
+ TagFileData &Obj = *(TagFileData *)Self;
+ // Replace the section.
+ Py_CLEAR(Obj.Section);
+ Obj.Section = (TagSecData*)(&PyTagSection_Type)->tp_alloc(&PyTagSection_Type, 0);
+ new (&Obj.Section->Object) pkgTagSection();
+ Obj.Section->Owner = Self;
+ Py_INCREF(Obj.Section->Owner);
+ Obj.Section->Data = 0;
+ Obj.Section->Bytes = Obj.Bytes;
+#if PY_MAJOR_VERSION >= 3
+ // We don't need to incref Encoding as the previous Section object already
+ // held a reference to it.
+ Obj.Section->Encoding = Obj.Encoding;
+#endif
+ if (Obj.Object.Step(Obj.Section->Object) == false)
+ return HandleErrors(NULL);
+
+ // Bug-Debian: http://bugs.debian.org/572596
+ // Duplicate the data here and scan the duplicated section data; in order
+ // to not use any shared storage.
+ // TODO: Provide an API in apt-pkg to do this; this is really ugly.
+
+ // Fetch old section data
+ const char *Start;
+ const char *Stop;
+ Obj.Section->Object.GetSection(Start,Stop);
+ // Duplicate the data and
+ // append a \n because GetSection() will only give us a single \n
+ // but Scan() needs \n\n to work
+ Obj.Section->Data = new char[Stop-Start+2];
+
+ memcpy(Obj.Section->Data, Start, Stop - Start);
+ Obj.Section->Data[Stop-Start] = '\n';
+ Obj.Section->Data[Stop-Start+1] = '\0';
+ // Rescan it
+ if(Obj.Section->Object.Scan(Obj.Section->Data, Stop-Start+2) == false)
+ return HandleErrors(NULL);
+
+ Py_INCREF(Obj.Section);
+ return HandleErrors(Obj.Section);
+}
+
+static PyObject *TagFileIter(PyObject *Self) {
+ Py_INCREF(Self);
+ return Self;
+}
+
+static char *doc_Offset =
+ "offset() -> int\n\n"
+ "Return the current offset.";
+static PyObject *TagFileOffset(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+ return MkPyNumber(((TagFileData *)Self)->Object.Offset());
+
+}
+
+static char *doc_Jump =
+ "jump(offset: int) -> bool\n\n"
+ "Jump to the given offset; return True on success. Note that jumping to\n"
+ "an offset is not very reliable, and the 'section' attribute may point\n"
+ "to an unexpected section.";
+static PyObject *TagFileJump(PyObject *Self,PyObject *Args)
+{
+ int Offset;
+ if (PyArg_ParseTuple(Args,"i",&Offset) == 0)
+ return 0;
+
+ TagFileData &Obj = *(TagFileData *)Self;
+ if (Obj.Object.Jump(Obj.Section->Object,Offset) == false)
+ return HandleErrors(PyBool_FromLong(0));
+
+ return HandleErrors(PyBool_FromLong(1));
+}
+
+static char *doc_Close =
+ "close()\n\n"
+ "Close the file.";
+static PyObject *TagFileClose(PyObject *self, PyObject *args)
+{
+ if (args != NULL && !PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ TagFileData &Obj = *(TagFileData *) self;
+
+ Obj.Fd.Close();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *TagFileExit(PyObject *self, PyObject *args)
+{
+
+ PyObject *exc_type = 0;
+ PyObject *exc_value = 0;
+ PyObject *traceback = 0;
+ if (!PyArg_UnpackTuple(args, "__exit__", 3, 3, &exc_type, &exc_value,
+ &traceback)) {
+ return 0;
+ }
+
+ PyObject *res = TagFileClose(self, NULL);
+
+ if (res == NULL) {
+ // The close failed. If no exception happened within the suite, we
+ // will raise an error here. Otherwise, we just display the error, so
+ // Python can handle the original exception instead.
+ if (exc_type == Py_None)
+ return NULL;
+
+ PyErr_WriteUnraisable(self);
+ } else {
+ Py_DECREF(res);
+ }
+ // Return False, as required by the context manager protocol.
+ Py_RETURN_FALSE;
+}
+
+static PyObject *TagFileEnter(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ Py_INCREF(self);
+
+ return self;
+}
+
+ /*}}}*/
+// ParseSection - Parse a single section from a tag file /*{{{*/
+// ---------------------------------------------------------------------
+static PyObject *TagSecNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) {
+ char *Data;
+ Py_ssize_t Len;
+ char Bytes = 0;
+ char *kwlist[] = {"text", "bytes", 0};
+
+ // this allows reading "byte" types from python3 - but we don't
+ // make (much) use of it yet
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"s#|b",kwlist,&Data,&Len,&Bytes) == 0)
+ return 0;
+ if (memchr(Data, 0, Len) != nullptr) {
+ PyErr_SetString(PyExc_ValueError, "Input contains NUL byte");
+ return 0;
+ }
+ if (Data[Len] != 0) {
+ PyErr_SetString(PyExc_ValueError, "Input is not terminated by NUL byte");
+ return 0;
+ }
+
+ // Create the object..
+ TagSecData *New = (TagSecData*)type->tp_alloc(type, 0);
+ new (&New->Object) pkgTagSection();
+ New->Data = new char[strlen(Data)+2];
+ snprintf(New->Data,strlen(Data)+2,"%s\n",Data);
+ New->Bytes = Bytes;
+#if PY_MAJOR_VERSION >= 3
+ New->Encoding = 0;
+#endif
+
+ if (New->Object.Scan(New->Data,strlen(New->Data)) == false)
+ {
+ cerr << New->Data << endl;
+ Py_DECREF((PyObject *)New);
+ PyErr_SetString(PyExc_ValueError,"Unable to parse section data");
+ return 0;
+ }
+
+ New->Object.Trim();
+
+ return New;
+}
+
+ /*}}}*/
+// ParseTagFile - Parse a tagd file /*{{{*/
+// ---------------------------------------------------------------------
+/* This constructs the parser state. */
+
+static PyObject *TagFileNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *File = 0;
+ char Bytes = 0;
+
+ char *kwlist[] = {"file", "bytes", 0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O|b",kwlist,&File,&Bytes) == 0)
+ return 0;
+
+ // check if we got a filename or a file object
+ int fileno = -1;
+ PyApt_Filename filename;
+ if (!filename.init(File)) {
+ PyErr_Clear();
+ fileno = PyObject_AsFileDescriptor(File);
+ }
+
+ // handle invalid arguments
+ if (fileno == -1 && filename == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Argument must be string, fd or have a fileno() method");
+ return 0;
+ }
+
+ PyApt_UniqueObject<TagFileData> New((TagFileData*)type->tp_alloc(type, 0));
+ if (fileno != -1)
+ {
+#ifdef APT_HAS_GZIP
+ new (&New->Fd) FileFd();
+ New->Fd.OpenDescriptor(fileno, FileFd::ReadOnlyGzip, false);
+#else
+ new (&New->Fd) FileFd(fileno,false);
+#endif
+ }
+ else
+ {
+ // FileFd::Extension got added in this revision
+#if (APT_PKG_MAJOR > 4 || (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 12))
+ new (&New->Fd) FileFd(filename, FileFd::ReadOnly, FileFd::Extension, false);
+#else
+ new (&New->Fd) FileFd(filename, FileFd::ReadOnly, false);
+#endif
+ }
+ New->Bytes = Bytes;
+ New->Owner = File;
+ Py_INCREF(New->Owner);
+#if PY_MAJOR_VERSION >= 3
+ if (fileno != -1) {
+ New->Encoding = PyObject_GetAttr(File, PyUnicode_FromString("encoding"));
+ if (!New->Encoding)
+ PyErr_Clear();
+ if (New->Encoding && !PyUnicode_Check(New->Encoding))
+ New->Encoding = 0;
+ } else
+ New->Encoding = 0;
+ Py_XINCREF(New->Encoding);
+#endif
+ new (&New->Object) pkgTagFile(&New->Fd);
+
+ // Create the section
+ New->Section = (TagSecData*)(&PyTagSection_Type)->tp_alloc(&PyTagSection_Type, 0);
+ new (&New->Section->Object) pkgTagSection();
+ New->Section->Owner = New.get();
+ Py_INCREF(New->Section->Owner);
+ New->Section->Data = 0;
+ New->Section->Bytes = Bytes;
+#if PY_MAJOR_VERSION >= 3
+ New->Section->Encoding = New->Encoding;
+ Py_XINCREF(New->Section->Encoding);
+#endif
+
+ return HandleErrors(New.release());
+}
+ /*}}}*/
+
+// Method table for the Tag Section object
+static PyMethodDef TagSecMethods[] =
+{
+ // Query
+ {"find",TagSecFind,METH_VARARGS,doc_Find},
+ {"find_raw",TagSecFindRaw,METH_VARARGS,doc_FindRaw},
+ {"find_flag",TagSecFindFlag,METH_VARARGS,doc_FindFlag},
+ {"bytes",TagSecBytes,METH_VARARGS,doc_Bytes},
+ {"write",(PyCFunction) TagSecWrite,METH_VARARGS|METH_KEYWORDS,doc_Write},
+
+ // Python Special
+ {"keys",TagSecKeys,METH_VARARGS,doc_Keys},
+#if PY_MAJOR_VERSION < 3
+ {"has_key",TagSecExists,METH_VARARGS,doc_Exists},
+#endif
+ {"get",TagSecFind,METH_VARARGS,doc_Find},
+ {}
+};
+
+
+PySequenceMethods TagSecSeqMeth = {0,0,0,0,0,0,0,TagSecContains,0,0};
+PyMappingMethods TagSecMapMeth = {TagSecLength,TagSecMap,0};
+
+
+static char *doc_TagSec = "TagSection(text: str, [bytes: bool = False])\n\n"
+ "Provide methods to access RFC822-style header sections, like those\n"
+ "found in debian/control or Packages files.\n\n"
+ "TagSection() behave like read-only dictionaries and also provide access\n"
+ "to the functions provided by the C++ class (e.g. find).\n\n"
+ "By default, text read from files is treated as strings (binary data in\n"
+ "Python 2, Unicode strings in Python 3). Use bytes=True to cause all\n"
+ "header values read from this TagSection to be bytes even in Python 3.\n"
+ "Header names are always treated as Unicode.";
+PyTypeObject PyTagSection_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagSection", // tp_name
+ sizeof(TagSecData), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ TagSecFree, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &TagSecSeqMeth, // tp_as_sequence
+ &TagSecMapMeth, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ TagSecStr, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ doc_TagSec, // tp_doc
+ CppTraverse<pkgTagSection>, // tp_traverse
+ CppClear<pkgTagSection>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ TagSecMethods, // tp_methods
+ 0, // 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
+ TagSecNew, // tp_new
+};
+
+// Method table for the Tag File object
+static PyMethodDef TagFileMethods[] =
+{
+ // Query
+ {"step",TagFileStep,METH_VARARGS,doc_Step},
+ {"offset",TagFileOffset,METH_VARARGS,doc_Offset},
+ {"jump",TagFileJump,METH_VARARGS,doc_Jump},
+ {"close",TagFileClose,METH_VARARGS,doc_Close},
+ {"__enter__",TagFileEnter,METH_VARARGS,"Context manager entry, return self."},
+ {"__exit__",TagFileExit,METH_VARARGS,"Context manager exit, calls close."},
+
+ {}
+};
+
+// Return the current section.
+static PyObject *TagFileGetSection(PyObject *Self,void*) {
+ PyObject *Obj = ((TagFileData *)Self)->Section;
+ Py_INCREF(Obj);
+ return Obj;
+}
+
+static PyGetSetDef TagFileGetSet[] = {
+ {"section",TagFileGetSection,0,
+ "The current section, as a TagSection object.",0},
+ {}
+};
+
+
+static char *doc_TagFile = "TagFile(file, [bytes: bool = False])\n\n"
+ "TagFile() objects provide access to debian control files, which consist\n"
+ "of multiple RFC822-style sections.\n\n"
+ "To provide access to those sections, TagFile objects provide an iterator\n"
+ "which yields TagSection objects for each section.\n\n"
+ "TagFile objects also provide another API which uses a shared TagSection\n"
+ "object in the 'section' member. The functions step() and jump() can be\n"
+ "used to navigate within the file; offset() returns the current\n"
+ "position.\n\n"
+ "It is important to not mix the use of both APIs, because this can have\n"
+ "unwanted effects.\n\n"
+ "The parameter 'file' refers to an object providing a fileno() method or\n"
+ "a file descriptor (an integer).\n\n"
+ "By default, text read from files is treated as strings (binary data in\n"
+ "Python 2, Unicode strings in Python 3). Use bytes=True to cause all\n"
+ "header values read from this TagFile to be bytes even in Python 3.\n"
+ "Header names are always treated as Unicode.";
+
+// Type for a Tag File
+PyTypeObject PyTagFile_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagFile", // tp_name
+ sizeof(TagFileData), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ TagFileFree, // 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
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ doc_TagFile, // tp_doc
+ TagFileTraverse, // tp_traverse
+ TagFileClear, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ TagFileIter, // tp_iter
+ TagFileNext, // tp_iternext
+ TagFileMethods, // tp_methods
+ 0, // tp_members
+ TagFileGetSet, // 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
+ TagFileNew, // tp_new
+
+};
+
+
+// Return the current section.
+static PyObject *TagGetAction(PyObject *Self,void*) {
+ return MkPyNumber(GetCpp<pkgTagSection::Tag>(Self).Action);
+}
+
+static PyObject *TagGetName(PyObject *Self,void*) {
+ return CppPyString(GetCpp<pkgTagSection::Tag>(Self).Name);
+}
+
+static PyObject *TagGetData(PyObject *Self,void*) {
+ return CppPyString(GetCpp<pkgTagSection::Tag>(Self).Data);
+}
+
+static PyObject *PyTagRename_New(PyTypeObject *type,PyObject *Args,PyObject *kwds) {
+ char *oldName;
+ char *newName;
+ char *kwlist[] = {"old_name", "new_name", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"ss",kwlist, &oldName, &newName) == 0)
+ return nullptr;
+ if (oldName[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "Old tag name may not be empty.");
+ return nullptr;
+ }
+ if (newName[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "New tag name may not be empty.");
+ return nullptr;
+ }
+
+ auto tag = pkgTagSection::Tag::Rename(oldName, newName);
+ return CppPyObject_NEW<pkgTagSection::Tag>(nullptr, type, tag);
+}
+
+static PyObject *PyTagRewrite_New(PyTypeObject *type,PyObject *Args,PyObject *kwds) {
+ char *name;
+ char *data;
+ char *kwlist[] = {"name", "data", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"ss",kwlist, &name, &data) == 0)
+ return nullptr;
+ if (name[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "Tag name may not be empty.");
+ return nullptr;
+ }
+ if (data[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "New value may not be empty.");
+ return nullptr;
+ }
+
+ auto tag = pkgTagSection::Tag::Rewrite(name, data);
+ return CppPyObject_NEW<pkgTagSection::Tag>(nullptr, type, tag);
+}
+
+static PyObject *PyTagRemove_New(PyTypeObject *type,PyObject *Args,PyObject *kwds) {
+ char *name;
+ char *kwlist[] = {"name", nullptr};
+
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"s",kwlist, &name) == 0)
+ return nullptr;
+ if (name[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "Tag name may not be empty.");
+ return nullptr;
+ }
+
+ auto tag = pkgTagSection::Tag::Remove(name);
+ return CppPyObject_NEW<pkgTagSection::Tag>(nullptr, type, tag);
+}
+
+static PyGetSetDef TagGetSet[] = {
+ {"action",TagGetAction,0,
+ "The action to perform.",0},
+ {"name",TagGetName,0,
+ "The name of the tag to perform the action on.",0},
+ {"data",TagGetData,0,
+ "The data to write instead (for REWRITE), or the new tag name (RENAME)",0},
+ {}
+};
+
+static char doc_Tag[] = "Tag\n\n"
+ "Identify actions to be executed on a task\n"
+ "\n"
+ "This is used in conjunction with :meth:`TagSection.write` to rewrite\n"
+ "a tag section into a new one.\n"
+ "\n"
+ "This class is abstract, use one of the subclasses:\n"
+ ":class:`TagRewrite`, :class:`TagRemove`, :class:`TagRename`\n"
+ "\n"
+ ".. versionadded:: 1.1";
+
+static char doc_TagRewrite[] = "TagRewrite(name: str, data: str)\n\n"
+ "Change the value of the tag to the string passed in *data*\n"
+ "\n"
+ ".. versionadded:: 1.1";
+static char doc_TagRename[] = "TagRename(old_name: str, new_name: str)\n\n"
+ "Rename the tag *old_name* to *new_name*\n"
+ "\n"
+ ".. versionadded:: 1.1";
+
+static char doc_TagRemove[] = "TagRemove(name: str)\n\n"
+ "Remove the tag *name* from the tag section\n"
+ "\n"
+ ".. versionadded:: 1.1";
+
+
+// Type for a Tag File
+PyTypeObject PyTag_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Tag", // tp_name
+ sizeof(CppPyObject<pkgTagSection::Tag>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgTagSection::Tag>, // 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),
+ doc_Tag, // tp_doc
+ CppTraverse<pkgTagSection::Tag>, // tp_traverse
+ CppClear<pkgTagSection::Tag>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ TagGetSet, // 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
+ 0, // tp_new
+};
+
+// Type for a Tag File
+PyTypeObject PyTagRewrite_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagRewrite", // tp_name
+ sizeof(CppPyObject<pkgTagSection::Tag>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgTagSection::Tag>, // 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
+ doc_TagRewrite, // tp_doc
+ CppTraverse<pkgTagSection::Tag>, // tp_traverse
+ CppClear<pkgTagSection::Tag>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyTag_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PyTagRewrite_New, // tp_new
+};
+
+// Type for a Tag File
+PyTypeObject PyTagRemove_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagRemove", // tp_name
+ sizeof(CppPyObject<pkgTagSection::Tag>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgTagSection::Tag>, // 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
+ doc_TagRemove, // tp_doc
+ CppTraverse<pkgTagSection::Tag>, // tp_traverse
+ CppClear<pkgTagSection::Tag>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyTag_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PyTagRemove_New, // tp_new
+};
+
+// Type for a Tag File
+PyTypeObject PyTagRename_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagRename", // tp_name
+ sizeof(CppPyObject<pkgTagSection::Tag>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgTagSection::Tag>, // 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
+ doc_TagRename, // tp_doc
+ CppTraverse<pkgTagSection::Tag>, // tp_traverse
+ CppClear<pkgTagSection::Tag>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyTag_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PyTagRename_New, // tp_new
+};
diff --git a/python/tarfile.cc b/python/tarfile.cc
new file mode 100644
index 0000000..b87fa71
--- /dev/null
+++ b/python/tarfile.cc
@@ -0,0 +1,521 @@
+/*
+ * arfile.cc - Wrapper around ExtractTar which behaves like Python's tarfile.
+ *
+ * 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 "apt_instmodule.h"
+#include <apt-pkg/extracttar.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/dirstream.h>
+
+/**
+ * A subclass of pkgDirStream which calls a Python callback.
+ *
+ * This calls a Python callback in FinishedFile() with the Item as the first
+ * argument and the data as the second argument.
+ *
+ * It can also work without a callback, in which case it just sets the
+ * 'py_member' and 'py_data' members. This can be combined with setting
+ * 'member' to extract a single member into the memory.
+ */
+class PyDirStream : public pkgDirStream
+{
+
+public:
+ PyObject *callback;
+ PyObject *py_data;
+ // The requested member or NULL.
+ const char *member;
+ // Set to true if an error occurred in the Python callback, or a file
+ // was too large to read in extractdata.
+ bool error;
+ // Place where the copy of the data is stored.
+ char *copy;
+ // The size of the copy
+ size_t copy_size;
+
+ virtual bool DoItem(Item &Itm,int &Fd);
+ virtual bool FinishedFile(Item &Itm,int Fd);
+#if (APT_PKG_MAJOR >= 5)
+ virtual bool Process(Item &Itm,const unsigned char *Data,
+ unsigned long long Size,unsigned long long Pos);
+#else
+ virtual bool Process(Item &Itm,const unsigned char *Data,
+ unsigned long Size,unsigned long Pos);
+#endif
+ PyDirStream(PyObject *callback, const char *member=0) : callback(callback),
+ py_data(0), member(member), error(false), copy(0), copy_size(0)
+ {
+ Py_XINCREF(callback);
+ }
+
+ virtual ~PyDirStream() {
+ Py_XDECREF(callback);
+ Py_XDECREF(py_data);
+ delete[] copy;
+ }
+};
+
+bool PyDirStream::DoItem(Item &Itm, int &Fd)
+{
+ if (!member || strcmp(Itm.Name, member) == 0) {
+ // Allocate a new buffer if the old one is too small.
+ if (Itm.Size > SIZE_MAX)
+ goto to_large;
+ if (copy == NULL || copy_size < Itm.Size) {
+ delete[] copy;
+ copy = new (std::nothrow) char[Itm.Size];
+ if (copy == NULL)
+ goto to_large;
+ copy_size = Itm.Size;
+ }
+ Fd = -2;
+ } else {
+ Fd = -1;
+ }
+ return true;
+to_large:
+ delete[] copy;
+ copy = NULL;
+ copy_size = 0;
+ /* If we are looking for a specific member, abort reading now */
+ if (member) {
+ error = true;
+ PyErr_Format(PyExc_MemoryError,
+ "The member %s was too large to read into memory",
+ Itm.Name);
+ return false;
+ }
+ return true;
+}
+
+#if (APT_PKG_MAJOR >= 5)
+bool PyDirStream::Process(Item &Itm,const unsigned char *Data,
+ unsigned long long Size,unsigned long long Pos)
+#else
+bool PyDirStream::Process(Item &Itm,const unsigned char *Data,
+ unsigned long Size,unsigned long Pos)
+#endif
+{
+ if (copy != NULL)
+ memcpy(copy + Pos, Data,Size);
+ return true;
+}
+
+bool PyDirStream::FinishedFile(Item &Itm,int Fd)
+{
+ if (member && strcmp(Itm.Name, member) != 0)
+ // Skip non-matching Items, if a specific one is requested.
+ return true;
+
+ Py_XDECREF(py_data);
+ if (copy == NULL) {
+ Py_INCREF(Py_None);
+ py_data = Py_None;
+ } else {
+ py_data = PyBytes_FromStringAndSize(copy, Itm.Size);
+ }
+
+ if (!callback)
+ return true;
+
+ // The current member and data.
+ CppPyObject<Item> *py_member;
+ py_member = CppPyObject_NEW<Item>(0, &PyTarMember_Type);
+ // Clone our object, including the strings in it.
+ py_member->Object = Itm;
+ py_member->Object.Name = new char[strlen(Itm.Name)+1];
+ py_member->Object.LinkTarget = new char[strlen(Itm.LinkTarget)+1];
+ strcpy(py_member->Object.Name, Itm.Name);
+ strcpy(py_member->Object.LinkTarget,Itm.LinkTarget);
+ py_member->NoDelete = true;
+ error = PyObject_CallFunctionObjArgs(callback, py_member, py_data, 0) == 0;
+ // Clear the old objects and create new ones.
+ Py_XDECREF(py_member);
+ return (!error);
+}
+
+void tarmember_dealloc(PyObject *self) {
+ // We cloned those strings, delete them again.
+ delete[] GetCpp<pkgDirStream::Item>(self).Name;
+ delete[] GetCpp<pkgDirStream::Item>(self).LinkTarget;
+ CppDealloc<pkgDirStream::Item>(self);
+}
+
+// The tarfile.TarInfo interface for our TarMember class.
+static PyObject *tarmember_isblk(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::BlockDevice);
+}
+static PyObject *tarmember_ischr(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::CharDevice);
+}
+static PyObject *tarmember_isdev(PyObject *self, PyObject *args)
+{
+ pkgDirStream::Item::Type_t type = GetCpp<pkgDirStream::Item>(self).Type;
+ return PyBool_FromLong(type == pkgDirStream::Item::CharDevice ||
+ type == pkgDirStream::Item::BlockDevice ||
+ type == pkgDirStream::Item::FIFO);
+}
+
+static PyObject *tarmember_isdir(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::Directory);
+}
+
+static PyObject *tarmember_isfifo(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::FIFO);
+}
+
+static PyObject *tarmember_isfile(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::File);
+}
+static PyObject *tarmember_islnk(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::HardLink);
+}
+static PyObject *tarmember_isreg(PyObject *self, PyObject *args)
+{
+ return tarmember_isfile(self, NULL);
+}
+static PyObject *tarmember_issym(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::SymbolicLink);
+}
+
+static PyObject *tarmember_get_name(PyObject *self, void *closure)
+{
+ return CppPyPath(GetCpp<pkgDirStream::Item>(self).Name);
+}
+
+static PyObject *tarmember_get_linkname(PyObject *self, void *closure)
+{
+ return CppPyPath(GetCpp<pkgDirStream::Item>(self).LinkTarget);
+}
+
+static PyObject *tarmember_get_mode(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Mode);
+}
+
+static PyObject *tarmember_get_uid(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).UID);
+}
+static PyObject *tarmember_get_gid(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).GID);
+}
+static PyObject *tarmember_get_size(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Size);
+}
+
+static PyObject *tarmember_get_mtime(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).MTime);
+}
+
+static PyObject *tarmember_get_major(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Major);
+}
+
+static PyObject *tarmember_get_minor(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Minor);
+}
+
+static PyObject *tarmember_repr(PyObject *self)
+{
+ return PyString_FromFormat("<%s object: name:'%s'>",
+ self->ob_type->tp_name,
+ GetCpp<pkgDirStream::Item>(self).Name);
+
+}
+
+
+static PyMethodDef tarmember_methods[] = {
+ {"isblk",tarmember_isblk,METH_NOARGS,
+ "Determine whether the member is a block device."},
+ {"ischr",tarmember_ischr,METH_NOARGS,
+ "Determine whether the member is a character device."},
+ {"isdev",tarmember_isdev,METH_NOARGS,
+ "Determine whether the member is a device (block, character or FIFO)."},
+ {"isdir",tarmember_isdir,METH_NOARGS,
+ "Determine whether the member is a directory."},
+ {"isfifo",tarmember_isfifo,METH_NOARGS,
+ "Determine whether the member is a FIFO."},
+ {"isfile",tarmember_isfile,METH_NOARGS,
+ "Determine whether the member is a regular file."},
+ {"islnk",tarmember_islnk,METH_NOARGS,
+ "Determine whether the member is a hardlink."},
+ {"isreg",tarmember_isreg,METH_NOARGS,
+ "Determine whether the member is a regular file, same as isfile()."},
+ {"issym",tarmember_issym,METH_NOARGS,
+ "Determine whether the member is a symbolic link."},
+ {NULL}
+};
+
+static PyGetSetDef tarmember_getset[] = {
+ {"gid",tarmember_get_gid,0,"The owner's group ID."},
+ {"linkname",tarmember_get_linkname,0,"The target of the link."},
+ {"major",tarmember_get_major,0,"The major ID of the device."},
+ {"minor",tarmember_get_minor,0,"The minor ID of the device."},
+ {"mode",tarmember_get_mode,0,"The mode (permissions)."},
+ {"mtime",tarmember_get_mtime,0,"Last time of modification."},
+ {"name",tarmember_get_name,0,"The name of the file."},
+ {"size",tarmember_get_size,0,"The size of the file."},
+ {"uid",tarmember_get_uid,0,"The owner's user ID."},
+ {NULL}
+};
+
+static const char *tarmember_doc =
+ "Represent a single member of a 'tar' archive.\n\n"
+ "This class, which has been modelled after 'tarfile.TarInfo', represents\n"
+ "information about a given member in an archive.";
+PyTypeObject PyTarMember_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.TarMember", // tp_name
+ sizeof(CppPyObject<pkgDirStream::Item>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ tarmember_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ tarmember_repr, // 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_HAVE_GC,
+ tarmember_doc, // tp_doc
+ CppTraverse<pkgDirStream::Item>, // tp_traverse
+ CppClear<pkgDirStream::Item>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ tarmember_methods, // tp_methods
+ 0, // tp_members
+ tarmember_getset // tp_getset
+};
+
+
+
+static PyObject *tarfile_new(PyTypeObject *type,PyObject *args,PyObject *kwds)
+{
+ PyObject *file;
+ PyApt_Filename filename;
+ int fileno;
+ int min = 0;
+ int max = 0xFFFFFFFF;
+ char *comp = "gzip";
+
+ static char *kwlist[] = {"file","min","max","comp",NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O|iis", kwlist, &file, &min,
+ &max,&comp) == 0)
+ return 0;
+
+ PyApt_UniqueObject<PyTarFileObject> self((PyTarFileObject*)CppPyObject_NEW<ExtractTar*>(file,type));
+
+ // We receive a filename.
+ if (filename.init(file))
+ new (&self->Fd) FileFd((const char *) filename,FileFd::ReadOnly);
+ else if ((fileno = PyObject_AsFileDescriptor(file)) != -1) {
+ // clear the error set by PyObject_AsString().
+ PyErr_Clear();
+ new (&self->Fd) FileFd(fileno,false);
+ }
+ else {
+ return 0;
+ }
+
+ self->min = min;
+ self->Object = new ExtractTar(self->Fd,max,comp);
+ if (_error->PendingError() == true)
+ return HandleErrors(self.release());
+ return self.release();
+}
+
+static const char *tarfile_extractall_doc =
+ "extractall([rootdir: str]) -> True\n\n"
+ "Extract the archive in the current directory. The argument 'rootdir'\n"
+ "can be used to change the target directory.";
+static PyObject *tarfile_extractall(PyObject *self, PyObject *args)
+{
+ std::string cwd = SafeGetCWD();
+ PyApt_Filename rootdir;
+ if (PyArg_ParseTuple(args,"|O&:extractall", PyApt_Filename::Converter, &rootdir) == 0)
+ return 0;
+
+ if (rootdir) {
+ if (chdir(rootdir) == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, rootdir);
+ }
+
+ pkgDirStream Extract;
+
+ ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min);
+ bool res = GetCpp<ExtractTar*>(self)->Go(Extract);
+
+
+
+ if (rootdir) {
+ if (chdir(cwd.c_str()) == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError,
+ (char*)cwd.c_str());
+ }
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static const char *tarfile_go_doc =
+ "go(callback: callable[, member: str]) -> True\n\n"
+ "Go through the archive and call the callable 'callback' for each\n"
+ "member with 2 arguments. The first argument is the TarMember and\n"
+ "the second one is the data, as bytes.\n\n"
+ "The optional parameter 'member' can be used to specify the member for\n"
+ "which to call the callback. If not specified, it will be called for all\n"
+ "members. If specified and not found, LookupError will be raised.";
+static PyObject *tarfile_go(PyObject *self, PyObject *args)
+{
+ PyObject *callback;
+ PyApt_Filename member;
+ if (PyArg_ParseTuple(args,"O|O&",&callback, PyApt_Filename::Converter, &member) == 0)
+ return 0;
+ if (member && strcmp(member, "") == 0)
+ member = 0;
+ pkgDirStream Extract;
+ PyDirStream stream(callback, member);
+ ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min);
+ bool res = GetCpp<ExtractTar*>(self)->Go(stream);
+ if (stream.error)
+ return 0;
+ if (member && !stream.py_data)
+ return PyErr_Format(PyExc_LookupError, "There is no member named '%s'",
+ member.path);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static const char *tarfile_extractdata_doc =
+ "extractdata(member: str) -> bytes\n\n"
+ "Return the contents of the member, as a bytes object. Raise\n"
+ "LookupError if there is no member with the given name.";
+static PyObject *tarfile_extractdata(PyObject *self, PyObject *args)
+{
+ PyApt_Filename member;
+ if (PyArg_ParseTuple(args,"O&", PyApt_Filename::Converter, &member) == 0)
+ return 0;
+ PyDirStream stream(NULL, member);
+ ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min);
+ // Go through the stream.
+ GetCpp<ExtractTar*>(self)->Go(stream);
+
+ if (stream.error)
+ return 0;
+
+ if (!stream.py_data)
+ return PyErr_Format(PyExc_LookupError, "There is no member named '%s'",
+ member.path);
+ return Py_INCREF(stream.py_data), stream.py_data;
+}
+
+static PyMethodDef tarfile_methods[] = {
+ {"extractdata",tarfile_extractdata,METH_VARARGS,tarfile_extractdata_doc},
+ {"extractall",tarfile_extractall,METH_VARARGS,tarfile_extractall_doc},
+ {"go",tarfile_go,METH_VARARGS,tarfile_go_doc},
+ {NULL}
+};
+
+static PyObject *tarfile_repr(PyObject *self)
+{
+ return PyString_FromFormat("<%s object: %s>", self->ob_type->tp_name,
+ PyString_AsString(PyObject_Repr(GetOwner<ExtractTar*>(self))));
+}
+
+static const char *tarfile_doc =
+ "TarFile(file: str/int/file[, min: int, max: int, comp: str])\n\n"
+ "The parameter 'file' may be a string specifying the path of a file, or\n"
+ "a file-like object providing the fileno() method. It may also be an int\n"
+ "specifying a file descriptor (returned by e.g. os.open()).\n\n"
+ "The parameter 'min' describes the offset in the file where the archive\n"
+ "begins and the parameter 'max' is the size of the archive.\n\n"
+ "The compression of the archive is set by the parameter 'comp'. It can\n"
+ "be set to any program supporting the -d switch, the default being gzip.";
+PyTypeObject PyTarFile_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.TarFile", // tp_name
+ sizeof(PyTarFileObject), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<ExtractTar*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ tarfile_repr, // 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_HAVE_GC,
+ tarfile_doc, // tp_doc
+ CppTraverse<ExtractTar*>, // tp_traverse
+ CppClear<ExtractTar*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ tarfile_methods, // tp_methods
+ 0, // 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
+ tarfile_new // tp_new
+};