diff options
| author | Julian Andres Klode <jak@debian.org> | 2010-01-15 15:22:12 +0100 |
|---|---|---|
| committer | Julian Andres Klode <jak@debian.org> | 2010-01-15 15:22:12 +0100 |
| commit | 7bfefb84523645fe24d0e5603d56c23cf410328e (patch) | |
| tree | 3965ce6e2e968a2facd5efa2e3ea4fb34c4140ff /python | |
| parent | 71aad7e28bbaf1ee8efdad77ebfb4e4c0fd0ec26 (diff) | |
| parent | 52cca77b8179a7f625673f19cb132686c0d416c9 (diff) | |
| download | python-apt-7bfefb84523645fe24d0e5603d56c23cf410328e.tar.gz | |
Merge debian-experimental.
Diffstat (limited to 'python')
32 files changed, 6016 insertions, 1553 deletions
diff --git a/python/acquire-item.cc b/python/acquire-item.cc new file mode 100644 index 00000000..1fb66080 --- /dev/null +++ b/python/acquire-item.cc @@ -0,0 +1,361 @@ +/* + * 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; + + + +struct PyAcquireItems { + CppOwnedPyObject<pkgAcqFile*> *file; + CppOwnedPyObject<pkgAcquire::Item*> *item; + CppOwnedPyObject<pkgAcquire::ItemDesc*> *desc; +}; + +typedef map<pkgAcquire::Item*,PyAcquireItems> item_map; + +// Keep a vector to PyAcquireItemObject pointers, so we can set the Object +// pointers to NULL when deallocating the main object (mostly AcquireFile). +struct PyAcquireObject : public CppPyObject<pkgAcquire*> { + item_map items; +}; + +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 ? CppPyString(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 ? Py_BuildValue("i", item->FileSize) : 0; +} + +static PyObject *acquireitem_get_id(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? Py_BuildValue("k", item->ID) : 0; +} + +static PyObject *acquireitem_get_mode(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? Py_BuildValue("s", item->Mode) : 0; +} + +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_status(PyObject *self, void *closure) +{ + pkgAcquire::Item *item = acquireitem_tocpp(self); + return item ? Py_BuildValue("i", 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_AsLong(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}, + {"desc_uri",acquireitem_get_desc_uri}, + {"destfile",acquireitem_get_destfile}, + {"error_text",acquireitem_get_error_text}, + {"filesize",acquireitem_get_filesize}, + {"id",acquireitem_get_id,acquireitem_set_id}, + {"mode",acquireitem_get_mode}, + {"is_trusted",acquireitem_get_is_trusted}, + {"local",acquireitem_get_local}, + {"status",acquireitem_get_status}, +#ifdef COMPAT_0_7 + {"Complete",acquireitem_get_complete}, + {"DescURI",acquireitem_get_desc_uri}, + {"DestFile",acquireitem_get_destfile}, + {"ErrorText",acquireitem_get_error_text}, + {"FileSize",acquireitem_get_filesize}, + {"ID",acquireitem_get_id}, + {"IsTrusted",acquireitem_get_is_trusted}, + {"Local",acquireitem_get_local}, + {"Status",acquireitem_get_status}, +#endif + {} +}; + +static PyObject *acquireitem_repr(PyObject *Self) +{ + pkgAcquire::Item *Itm = acquireitem_tocpp(Self); + if (Itm == 0) + return 0; + + return PyString_FromFormat("<%s object: " + "Status: %i Complete: %i Local: %i IsTrusted: %i " + "FileSize: %lu 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()); +} + +static void acquireitem_dealloc(PyObject *self) +{ + pkgAcquire::Item *item = PyAcquireItem_ToCpp(self); + PyAcquireObject *Owner = (PyAcquireObject *)GetOwner<pkgAcquire::Item*>(self); + PyAcquireItems item_struct = Owner->items[item]; + // TODO: Unregister the object in the owner. + if (!((CppOwnedPyObject<pkgAcquire::Item*>*)self)->NoDelete) { + if (item_struct.file != 0 && item_struct.file != self) + item_struct.file->Object = 0; + if (item_struct.item != 0 && item_struct.item != self) { + item_struct.item->Object = 0; + Py_DECREF(item_struct.item); + } + if (item_struct.desc != 0) { + item_struct.desc->Object = 0; + Py_DECREF(item_struct.desc); + } + Owner->items.erase(item); + } + else { + if (item_struct.file == self) + item_struct.file = 0; + if (item_struct.item == self) + item_struct.item = 0; + } + + CppOwnedDeallocPtr<pkgAcquire::Item*>(self); +} + +PyTypeObject PyAcquireItem_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.AcquireItem", // tp_name + sizeof(CppOwnedPyObject<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 + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "AcquireItem Object", // 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 + acquireitem_getset, // tp_getset +}; + +static PyObject *acquirefile_new(PyTypeObject *type, PyObject *Args, PyObject * kwds) +{ + PyObject *pyfetcher; + char *uri, *md5, *descr, *shortDescr, *destDir, *destFile; + int size = 0; + uri = md5 = descr = shortDescr = destDir = destFile = ""; + + char *kwlist[] = {"owner","uri", "md5", "size", "descr", "short_descr", + "destdir", "destfile", NULL + }; + + if (PyArg_ParseTupleAndKeywords(Args, kwds, "O!s|sissss", kwlist, + &PyAcquire_Type, &pyfetcher, &uri, &md5, + &size, &descr, &shortDescr, &destDir, &destFile) == 0) + return 0; + + pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyfetcher); + pkgAcqFile *af = new pkgAcqFile(fetcher, // owner + uri, // uri + md5, // md5 + size, // size + descr, // descr + shortDescr, + destDir, + destFile); // short-desc + CppOwnedPyObject<pkgAcqFile*> *AcqFileObj = CppOwnedPyObject_NEW<pkgAcqFile*>(pyfetcher, type); + AcqFileObj->Object = af; + + + ((PyAcquireObject *)pyfetcher)->items[af].file = AcqFileObj; + return AcqFileObj; +} + + +static char *acquirefile_doc = + "AcquireFile(owner, uri[, md5, size, descr, short_descr, destdir," + "destfile]) -> New AcquireFile() object\n\n" + "The parameter *owner* refers to an apt_pkg.Acquire() object. You can use\n" + "*destdir* OR *destfile* to specify the destination directory/file."; + +PyTypeObject PyAcquireFile_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.AcquireFile", // tp_name + sizeof(CppOwnedPyObject<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 + CppOwnedTraverse<pkgAcqFile*>, // tp_traverse + CppOwnedClear<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 +}; + +#ifdef COMPAT_0_7 +char *doc_GetPkgAcqFile = + "GetPkgAcqFile(pkgAquire, uri[, md5, size, descr, shortDescr, destDir, destFile]) -> PkgAcqFile\n"; +PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject * kwds) +{ + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPkgAcqFile() is " + "deprecated. Please see apt_pkg.AcquireFile() for the " + "replacement", 1); + PyObject *pyfetcher; + char *uri, *md5, *descr, *shortDescr, *destDir, *destFile; + int size = 0; + uri = md5 = descr = shortDescr = destDir = destFile = ""; + + char * kwlist[] = {"owner","uri", "md5", "size", "descr", "shortDescr", + "destDir", "destFile", NULL + }; + + if (PyArg_ParseTupleAndKeywords(Args, kwds, "O!s|sissss", kwlist, + &PyAcquire_Type, &pyfetcher, &uri, &md5, + &size, &descr, &shortDescr, &destDir, &destFile) == 0) + return 0; + + pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyfetcher); + pkgAcqFile *af = new pkgAcqFile(fetcher, // owner + uri, // uri + md5, // md5 + size, // size + descr, // descr + shortDescr, + destDir, + destFile); // short-desc + CppPyObject<pkgAcqFile*> *AcqFileObj = CppPyObject_NEW<pkgAcqFile*>(&PyAcquireFile_Type); + AcqFileObj->Object = af; + AcqFileObj->NoDelete = true; + + return AcqFileObj; +} +#endif diff --git a/python/acquire.cc b/python/acquire.cc index 1ecf55a5..ef8b10b6 100644 --- a/python/acquire.cc +++ b/python/acquire.cc @@ -1,278 +1,439 @@ -// Description /*{{{*/ -// $Id: acquire.cc,v 1.1 2003/06/03 03:03:23 mvo Exp $ -/* ###################################################################### - - Acquire - Wrapper for the acquire code - - ##################################################################### */ +/* 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> - -// pkgAcquire::Item -static PyObject *AcquireItemAttr(PyObject *Self,char *Name) -{ - pkgAcquire::ItemIterator &I = GetCpp<pkgAcquire::ItemIterator>(Self); - - if (strcmp("ID",Name) == 0) - return Py_BuildValue("i",(*I)->ID); - else if (strcmp("Status",Name) == 0) - return Py_BuildValue("i",(*I)->Status); - else if (strcmp("Complete",Name) == 0) - return Py_BuildValue("i",(*I)->Complete); - else if (strcmp("Local",Name) == 0) - return Py_BuildValue("i",(*I)->Local); - else if (strcmp("IsTrusted",Name) == 0) - return Py_BuildValue("i",(*I)->IsTrusted()); - else if (strcmp("FileSize",Name) == 0) - return Py_BuildValue("i",(*I)->FileSize); - else if (strcmp("ErrorText",Name) == 0) - return Safe_FromString((*I)->ErrorText.c_str()); - else if (strcmp("DestFile",Name) == 0) - return Safe_FromString((*I)->DestFile.c_str()); - else if (strcmp("DescURI",Name) == 0) - return Safe_FromString((*I)->DescURI().c_str()); - // constants - else if (strcmp("StatIdle",Name) == 0) - return Py_BuildValue("i", pkgAcquire::Item::StatIdle); - else if (strcmp("StatFetching",Name) == 0) - return Py_BuildValue("i", pkgAcquire::Item::StatFetching); - else if (strcmp("StatDone",Name) == 0) - return Py_BuildValue("i", pkgAcquire::Item::StatDone); - else if (strcmp("StatError",Name) == 0) - return Py_BuildValue("i", pkgAcquire::Item::StatError); - else if (strcmp("StatAuthError",Name) == 0) - return Py_BuildValue("i", pkgAcquire::Item::StatAuthError); - - - PyErr_SetString(PyExc_AttributeError,Name); - return 0; -} +#include <apt-pkg/acquire-worker.h> -static PyObject *AcquireItemRepr(PyObject *Self) -{ - pkgAcquire::ItemIterator &I = GetCpp<pkgAcquire::ItemIterator>(Self); - - char S[300]; - snprintf(S,sizeof(S),"<pkgAcquire::ItemIterator object: " - "Status: %i Complete: %i Local: %i IsTrusted: %i " - "FileSize: %i DestFile:'%s' " - "DescURI: '%s' ID:%i ErrorText: '%s'>", - (*I)->Status, (*I)->Complete, (*I)->Local, (*I)->IsTrusted(), - (*I)->FileSize, (*I)->DestFile.c_str(), (*I)->DescURI().c_str(), - (*I)->ID,(*I)->ErrorText.c_str()); - return PyString_FromString(S); -} +typedef CppOwnedPyObject<pkgAcquire::Worker*> PyAcquireWorkerObject; +struct PyAcquireItems { + CppOwnedPyObject<pkgAcqFile*> *file; + CppOwnedPyObject<pkgAcquire::Item*> *item; + CppOwnedPyObject<pkgAcquire::ItemDesc*> *desc; +}; +typedef map<pkgAcquire::Item*,PyAcquireItems> item_map; +typedef map<pkgAcquire::Worker*,PyAcquireWorkerObject*> worker_map; -PyTypeObject AcquireItemType = -{ - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgAcquire::ItemIterator", // tp_name - sizeof(CppOwnedPyObject<pkgAcquire::ItemIterator>), // tp_basicsize - 0, // tp_itemsize - // Methods - CppOwnedDealloc<pkgAcquire::ItemIterator>, // tp_dealloc - 0, // tp_print - AcquireItemAttr, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - AcquireItemRepr, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash +// Keep a vector to PyAcquireItemObject pointers, so we can set the Object +// pointers to NULL when deallocating the main object (mostly AcquireFile). +struct PyAcquireObject : public CppPyObject<pkgAcquire*> { + item_map items; + worker_map workers; }; -static PyObject *PkgAcquireRun(PyObject *Self,PyObject *Args) +static PyObject *acquireworker_get_current_item(PyObject *self, void *closure) { - 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(Py_BuildValue("i",run)); + pkgAcquire::Worker *worker = GetCpp<pkgAcquire::Worker*>(self); + + if (worker->CurrentItem == NULL) { + Py_RETURN_NONE; + } + + PyObject *PyAcquire = GetOwner<pkgAcquire::Worker*>(self); + + if (PyAcquire) + return PyAcquire_GetItemDesc(PyAcquire, worker->CurrentItem); + else { + PyObject *PyItem = PyAcquireItem_FromCpp(worker->CurrentItem->Owner); + PyObject *ret = PyAcquireItemDesc_FromCpp(worker->CurrentItem,false, + PyItem); + Py_DECREF(PyItem); + return ret; + } } -static PyObject *PkgAcquireShutdown(PyObject *Self,PyObject *Args) +static PyObject *acquireworker_get_status(PyObject *self, void *closure) { - pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self); - - if (PyArg_ParseTuple(Args, "") == 0) - return 0; - - fetcher->Shutdown(); - - Py_INCREF(Py_None); - return HandleErrors(Py_None); + return CppPyString(GetCpp<pkgAcquire::Worker*>(self)->Status); } -static PyMethodDef PkgAcquireMethods[] = +static PyObject *acquireworker_get_current_size(PyObject *self, void *closure) { - {"Run",PkgAcquireRun,METH_VARARGS,"Run the fetcher"}, - {"Shutdown",PkgAcquireShutdown, METH_VARARGS,"Shutdown the fetcher"}, - {} -}; - + return Py_BuildValue("k",GetCpp<pkgAcquire::Worker*>(self)->CurrentSize); +} -static PyObject *AcquireAttr(PyObject *Self,char *Name) +static PyObject *acquireworker_get_total_size(PyObject *self, void *closure) { - pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self); - - if(strcmp("TotalNeeded",Name) == 0) - return Py_BuildValue("d", fetcher->TotalNeeded()); - if(strcmp("FetchNeeded",Name) == 0) - return Py_BuildValue("d", fetcher->FetchNeeded()); - if(strcmp("PartialPresent",Name) == 0) - return Py_BuildValue("d", fetcher->PartialPresent()); - if(strcmp("Items",Name) == 0) - { - PyObject *List = PyList_New(0); - for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin(); - I != fetcher->ItemsEnd(); I++) - { - PyObject *Obj; - Obj = CppOwnedPyObject_NEW<pkgAcquire::ItemIterator>(Self,&AcquireItemType,I); - PyList_Append(List,Obj); - Py_DECREF(Obj); - - } - return List; - } - // some constants - if(strcmp("ResultContinue",Name) == 0) - return Py_BuildValue("i", pkgAcquire::Continue); - if(strcmp("ResultFailed",Name) == 0) - return Py_BuildValue("i", pkgAcquire::Failed); - if(strcmp("ResultCancelled",Name) == 0) - return Py_BuildValue("i", pkgAcquire::Cancelled); - - return Py_FindMethod(PkgAcquireMethods,Self,Name); + return Py_BuildValue("k",GetCpp<pkgAcquire::Worker*>(self)->TotalSize); } +static PyObject *acquireworker_get_resumepoint(PyObject *self, void *closure) +{ + return Py_BuildValue("k",GetCpp<pkgAcquire::Worker*>(self)->ResumePoint); +} +static PyGetSetDef acquireworker_getset[] = { + {"current_item",acquireworker_get_current_item}, + {"status",acquireworker_get_status}, + {"current_size",acquireworker_get_current_size}, + {"total_size",acquireworker_get_total_size}, + {"resumepoint",acquireworker_get_resumepoint}, + {NULL} +}; -PyTypeObject PkgAcquireType = -{ - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "Acquire", // tp_name - sizeof(CppPyObject<pkgAcquire*>), // tp_basicsize - 0, // tp_itemsize - // Methods - CppDealloc<pkgAcquire*>, // tp_dealloc - 0, // tp_print - AcquireAttr, // 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 +PyTypeObject PyAcquireWorker_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.AcquireWorker", // tp_name + sizeof(CppOwnedPyObject<pkgAcquire::Worker*>),// tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDealloc<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, + 0, // tp_doc + CppOwnedTraverse<pkgAcquire::Worker*>, // tp_traverse + CppOwnedClear<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 }; -PyObject *GetAcquire(PyObject *Self,PyObject *Args) +static PyObject *acquireitemdesc_get_uri(PyObject *self, void *closure) +{ + return CppPyString(GetCpp<pkgAcquire::ItemDesc*>(self)->URI); +} +static PyObject *acquireitemdesc_get_description(PyObject *self, void *closure) +{ + return CppPyString(GetCpp<pkgAcquire::ItemDesc*>(self)->Description); +} +static PyObject *acquireitemdesc_get_shortdesc(PyObject *self, void *closure) +{ + return CppPyString(GetCpp<pkgAcquire::ItemDesc*>(self)->ShortDesc); +} +static PyObject *acquireitemdesc_get_owner(CppOwnedPyObject<pkgAcquire::ItemDesc*> *self, void *closure) { - pkgAcquire *fetcher; + if (self->Owner != NULL) { + Py_INCREF(self->Owner); + return self->Owner; + } + else if (self->Object) { + self->Owner = PyAcquireItem_FromCpp(self->Object->Owner); + Py_INCREF(self->Owner); + return self->Owner; + } + Py_RETURN_NONE; +} + +static PyGetSetDef acquireitemdesc_getset[] = { + {"uri",acquireitemdesc_get_uri,0,"The URI from which to download this item."}, + {"description",acquireitemdesc_get_description}, + {"shortdesc",acquireitemdesc_get_shortdesc}, + {"owner",(getter)acquireitemdesc_get_owner}, + {NULL} +}; - PyObject *pyFetchProgressInst = NULL; - if (PyArg_ParseTuple(Args,"|O",&pyFetchProgressInst) == 0) - return 0; +static char *acquireitemdesc_doc = + "Represent an AcquireItemDesc"; + +PyTypeObject PyAcquireItemDesc_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.AcquireItemDesc", // tp_name + sizeof(CppOwnedPyObject<pkgAcquire::ItemDesc*>),// tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDealloc<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 + CppOwnedTraverse<pkgAcquire::ItemDesc*>,// tp_traverse + CppOwnedClear<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 +}; - if (pyFetchProgressInst != NULL) { - // FIXME: memleak? - PyFetchProgress *progress = new PyFetchProgress(); - progress->setCallbackInst(pyFetchProgressInst); - fetcher = new pkgAcquire(progress); - } else { - fetcher = new pkgAcquire(); - } - CppPyObject<pkgAcquire*> *FetcherObj = - CppPyObject_NEW<pkgAcquire*>(&PkgAcquireType, fetcher); +// Acquire - return FetcherObj; +PyObject *PyAcquire_GetItem(PyObject *self, pkgAcquire::Item *item) +{ + PyAcquireItems &item_struct = ((PyAcquireObject *)self)->items[item]; + if (! item_struct.item) { + item_struct.item = PyAcquireItem_FromCpp(item,false,self); + } + Py_INCREF(item_struct.item); + return item_struct.item; } +PyObject *PyAcquire_GetItemDesc(PyObject *self, pkgAcquire::ItemDesc *item) +{ + PyAcquireItems &item_struct = ((PyAcquireObject *)self)->items[item->Owner]; + if (! item_struct.item) + item_struct.item = PyAcquireItem_FromCpp(item->Owner,false,self); + if (! item_struct.desc) + item_struct.desc = PyAcquireItemDesc_FromCpp(item,false, + item_struct.item); + Py_INCREF(item_struct.desc); + return item_struct.desc; +} +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); -// pkgAcquireFile + return HandleErrors(Py_BuildValue("i",run)); +} -static PyObject *AcquireFileAttr(PyObject *Self,char *Name) +static PyObject *PkgAcquireShutdown(PyObject *Self,PyObject *Args) { - pkgAcqFile *acqFile = GetCpp<pkgAcqFile*>(Self); - - PyErr_SetString(PyExc_AttributeError,Name); - return 0; + pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self); + + if (PyArg_ParseTuple(Args, "") == 0) + return 0; + + fetcher->Shutdown(); + + // TODO: Delete all objects here + item_map &items = ((PyAcquireObject *)Self)->items; + for (item_map::iterator I = items.begin(); I != items.end(); I++) { + if ((*I).second.file) + (*I).second.file->Object = NULL; + if ((*I).second.item) { + (*I).second.item->Object = NULL; + Py_DECREF((*I).second.item); + } + if ((*I).second.desc) { + (*I).second.desc->Object = NULL; + Py_DECREF((*I).second.desc); + } + } + items.clear(); + Py_INCREF(Py_None); + return HandleErrors(Py_None); } +static PyMethodDef PkgAcquireMethods[] = { + {"run",PkgAcquireRun,METH_VARARGS,"Run the fetcher"}, + {"shutdown",PkgAcquireShutdown, METH_VARARGS,"Shutdown the fetcher"}, +#ifdef COMPAT_0_7 + {"Run",PkgAcquireRun,METH_VARARGS,"Run the fetcher"}, + {"Shutdown",PkgAcquireShutdown, METH_VARARGS,"Shutdown the fetcher"}, +#endif + {} +}; +#define fetcher (GetCpp<pkgAcquire*>(Self)) +static PyObject *PkgAcquireGetTotalNeeded(PyObject *Self,void*) +{ + return Py_BuildValue("d", fetcher->TotalNeeded()); +} +static PyObject *PkgAcquireGetFetchNeeded(PyObject *Self,void*) +{ + return Py_BuildValue("d", fetcher->FetchNeeded()); +} +static PyObject *PkgAcquireGetPartialPresent(PyObject *Self,void*) +{ + return Py_BuildValue("d", fetcher->PartialPresent()); +} +#undef fetcher - -PyTypeObject PkgAcquireFileType = +static PyObject *PkgAcquireGetWorkers(PyObject *self, void *closure) +{ + PyObject *List = PyList_New(0); + pkgAcquire *Owner = GetCpp<pkgAcquire*>(self); + CppOwnedPyObject<pkgAcquire::Worker*> *PyWorker = NULL; + for (pkgAcquire::Worker *Worker = Owner->WorkersBegin(); + Worker != 0; Worker = Owner->WorkerStep(Worker)) { + PyWorker = CppOwnedPyObject_NEW<pkgAcquire::Worker*>(self,&PyAcquireWorker_Type, Worker); + PyWorker->NoDelete = true; + PyList_Append(List, PyWorker); + Py_DECREF(PyWorker); + } + return List; +} +static PyObject *PkgAcquireGetItems(PyObject *Self,void*) { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgAcquireFile", // tp_name - sizeof(CppPyObject<pkgAcqFile*>),// tp_basicsize - 0, // tp_itemsize - // Methods - CppDealloc<pkgAcqFile*>, // tp_dealloc - 0, // tp_print - AcquireFileAttr, // 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 + pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self); + PyObject *List = PyList_New(0); + PyObject *Obj; + for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin(); + I != fetcher->ItemsEnd(); I++) { + Obj = PyAcquire_GetItem(Self, *I); + PyList_Append(List,Obj); + Py_DECREF(Obj); + } + return List; +} + +static PyGetSetDef PkgAcquireGetSet[] = { + {"fetch_needed",PkgAcquireGetFetchNeeded}, + {"items",PkgAcquireGetItems}, + {"workers",PkgAcquireGetWorkers}, + {"partial_present",PkgAcquireGetPartialPresent}, + {"total_needed",PkgAcquireGetTotalNeeded}, +#ifdef COMPAT_0_7 + {"FetchNeeded",PkgAcquireGetFetchNeeded}, + {"Items",PkgAcquireGetItems}, + {"PartialPresent",PkgAcquireGetPartialPresent}, + {"TotalNeeded",PkgAcquireGetTotalNeeded}, +#endif + {} }; -char *doc_GetPkgAcqFile = -"GetPkgAcqFile(pkgAquire, uri[, md5, size, descr, shortDescr, destDir, destFile]) -> PkgAcqFile\n"; -PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject * kwds) +static PyObject *PkgAcquireNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) { - PyObject *pyfetcher; - char *uri, *md5, *descr, *shortDescr, *destDir, *destFile; - int size = 0; - uri = md5 = descr = shortDescr = destDir = destFile = ""; - - char * kwlist[] = {"owner","uri", "md5", "size", "descr", "shortDescr", - "destDir", "destFile", NULL}; - - if (PyArg_ParseTupleAndKeywords(Args, kwds, "O!s|sissss", kwlist, - &PkgAcquireType, &pyfetcher, &uri, &md5, - &size, &descr, &shortDescr, &destDir, &destFile) == 0) - return 0; - - pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyfetcher); - pkgAcqFile *af = new pkgAcqFile(fetcher, // owner - uri, // uri - md5, // md5 - size, // size - descr, // descr - shortDescr, - destDir, - destFile); // short-desc - CppPyObject<pkgAcqFile*> *AcqFileObj = CppPyObject_NEW<pkgAcqFile*>(&PkgAcquireFileType); - AcqFileObj->Object = af; - - return AcqFileObj; + 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(progress); + } + else { + fetcher = new pkgAcquire(); + } + + PyAcquireObject *FetcherObj = (PyAcquireObject *) + CppPyObject_NEW<pkgAcquire*>(type, fetcher); + + if (progress != 0) + progress->setPyAcquire(FetcherObj); + // prepare our map of items. + new (&FetcherObj->items) item_map(); + new (&FetcherObj->workers) worker_map(); + return FetcherObj; } +static char *doc_PkgAcquire = + "Acquire(progress: apt_pkg.AcquireProgress) -> Acquire() object.\n\n" + "Create a new acquire object. The parameter *progress* can be used to\n" + "specify an apt_pkg.AcquireProgress() object, which will display the\n" + "progress of the fetching."; + +PyTypeObject PyAcquire_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Acquire", // tp_name + sizeof(PyAcquireObject), // 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 + 0, // 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 +}; + +#ifdef COMPAT_0_7 +PyObject *GetAcquire(PyObject *Self,PyObject *Args) +{ + PyErr_WarnEx(PyExc_DeprecationWarning,"apt_pkg.GetAcquire() is deprecated." + " Please see apt_pkg.Acquire() for the replacement.", 1); + return PkgAcquireNew(&PyAcquire_Type,Args,0); +} +#endif - /*}}}*/ diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc index 48868d86..2721509e 100644 --- a/python/apt_instmodule.cc +++ b/python/apt_instmodule.cc @@ -23,26 +23,31 @@ #include <Python.h> /*}}}*/ +#ifdef COMPAT_0_7 + // debExtractControl - Exctract an arbitary control member /*{{{*/ // --------------------------------------------------------------------- /* This is a common operation so this function will stay, but others that expose the full range of the apt-inst .deb processing will join it some day. */ static char *doc_debExtractControl = -"debExtractControl(File[,Member]) -> String\n" +"deb_extract_control(file[,member]) -> String\n" "Returns the indicated file from the control tar. The default is 'control'\n"; static PyObject *debExtractControl(PyObject *Self,PyObject *Args) { char *Member = "control"; PyObject *File; - if (PyArg_ParseTuple(Args,"O!|s",&PyFile_Type,&File,&Member) == 0) + if (PyArg_ParseTuple(Args,"O|s",&File,&Member) == 0) return 0; // Subscope makes sure any clean up errors are properly handled. PyObject *Res = 0; { // Open the file and associate the .deb - FileFd Fd(fileno(PyFile_AsFile(File)),false); + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; + FileFd Fd(fileno,false); debDebFile Deb(Fd); if (_error->PendingError() == true) return HandleErrors(); @@ -69,14 +74,14 @@ static PyObject *debExtractControl(PyObject *Self,PyObject *Args) // debExtractArchive - Exctract the archive /*{{{*/ // --------------------------------------------------------------------- static char *doc_debExtractArchive = -"debExtractArchve(File,rootdir) -> Bool\n" +"deb_extract_archive(File,rootdir) -> Bool\n" "Extracts the Archive into the given root dir"; static PyObject *debExtractArchive(PyObject *Self,PyObject *Args) { char *Rootdir = NULL; char cwd[512]; PyObject *File; - if (PyArg_ParseTuple(Args,"O!|s",&PyFile_Type,&File,&Rootdir) == 0) + if (PyArg_ParseTuple(Args,"O|s",&File,&Rootdir) == 0) return 0; // Subscope makes sure any clean up errors are properly handled. @@ -89,7 +94,10 @@ static PyObject *debExtractArchive(PyObject *Self,PyObject *Args) } // Open the file and associate the .deb - FileFd Fd(fileno(PyFile_AsFile(File)),false); + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; + FileFd Fd(fileno,false); debDebFile Deb(Fd); if (_error->PendingError() == true) { if (Rootdir != NULL) @@ -112,17 +120,20 @@ static PyObject *debExtractArchive(PyObject *Self,PyObject *Args) // arFindMember - Find member in AR archive /*{{{*/ // --------------------------------------------------------------------- static char *doc_arCheckMember = -"arCheckMember(File, membername) -> Bool\n"; +"ar_check_member(file, membername) -> Bool\n"; static PyObject *arCheckMember(PyObject *Self,PyObject *Args) { char *Member = NULL; bool res = false; PyObject *File; - if (PyArg_ParseTuple(Args,"O!s",&PyFile_Type,&File,&Member) == 0) + if (PyArg_ParseTuple(Args,"Os",&File,&Member) == 0) return 0; // Open the file and associate the .deb - FileFd Fd(fileno(PyFile_AsFile(File)),false); + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; + FileFd Fd(fileno,false); ARArchive AR(Fd); if (_error->PendingError() == true) return HandleErrors(Py_BuildValue("b",res)); @@ -145,16 +156,56 @@ static PyMethodDef methods[] = // access to deb files {"debExtractControl",debExtractControl,METH_VARARGS,doc_debExtractControl}, {"debExtractArchive",debExtractArchive,METH_VARARGS,doc_debExtractArchive}, - + // access to tar streams {"tarExtract",tarExtract,METH_VARARGS,doc_tarExtract}, {"debExtract",debExtract,METH_VARARGS,doc_debExtract}, - {} }; - +#else +static PyMethodDef *methods = 0; +#endif // defined(COMPAT_0_7) + + +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 +extern "C" PyObject * PyInit_apt_inst() +#else extern "C" void initapt_inst() +#define RETURN(x) +#endif { - Py_InitModule("apt_inst",methods); +#if PY_MAJOR_VERSION >= 3 + PyObject *module = PyModule_Create(&moduledef); +#else + PyObject *module = Py_InitModule3("apt_inst",methods, apt_inst_doc); +#endif + + 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); + RETURN(module); } - /*}}}*/ diff --git a/python/apt_instmodule.h b/python/apt_instmodule.h index 45ba5f85..2b07261b 100644 --- a/python/apt_instmodule.h +++ b/python/apt_instmodule.h @@ -11,10 +11,25 @@ #define APT_INSTMODULE_H #include <Python.h> +#include "generic.h" +#include <apt-pkg/extracttar.h> +#ifdef COMPAT_0_7 PyObject *debExtract(PyObject *Self,PyObject *Args); extern char *doc_debExtract; PyObject *tarExtract(PyObject *Self,PyObject *Args); extern char *doc_tarExtract; +#endif + +extern PyTypeObject PyArMember_Type; +extern PyTypeObject PyArArchive_Type; +extern PyTypeObject PyDebFile_Type; +extern PyTypeObject PyTarFile_Type; +extern PyTypeObject PyTarMember_Type; + +struct PyTarFileObject : public CppOwnedPyObject<ExtractTar*> { + int min; + FileFd Fd; +}; #endif diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index bfa1227e..f20b0c87 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -13,6 +13,8 @@ #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> @@ -24,17 +26,39 @@ #include <apt-pkg/pkgsystem.h> #include <sys/stat.h> +#include <libintl.h> #include <unistd.h> #include <Python.h> /*}}}*/ +/** + * 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 PyString_FromString(dgettext(domain, msg)); +} + // newConfiguration - Build a new configuration class /*{{{*/ // --------------------------------------------------------------------- +#ifdef COMPAT_0_7 static char *doc_newConfiguration = "Construct a configuration instance"; static PyObject *newConfiguration(PyObject *self,PyObject *args) { - return CppPyObject_NEW<Configuration>(&ConfigurationType); + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.newConfiguration() is " + "deprecated. Use apt_pkg.Configuration() instead.", 1); + return CppOwnedPyObject_NEW<Configuration*>(NULL, &PyConfiguration_Type, new Configuration()); } +#endif /*}}}*/ // Version Wrappers /*{{{*/ @@ -100,9 +124,11 @@ static char *doc_ParseDepends = "The resulting tuples are (Pkg,Ver,Operation). Each anded dependency is a\n" "list of or'd dependencies\n" "Source depends are evaluated against the curernt arch and only those that\n" -"Match are returned."; +"Match are returned.\n\n" +"apt_pkg.Parse{,Src}Depends() are old forms which return >>,<< instead of >,<"; static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, - bool ParseArchFlags) + bool ParseArchFlags, string name, + bool debStyle=false) { string Package; string Version; @@ -112,7 +138,7 @@ static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, const char *Stop; int Len; - if (PyArg_ParseTuple(Args,"s#",&Start,&Len) == 0) + if (PyArg_ParseTuple(Args,(char *)("s#:" + name).c_str(),&Start,&Len) == 0) return 0; Stop = Start + Len; PyObject *List = PyList_New(0); @@ -139,7 +165,7 @@ static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, PyObject *Obj; PyList_Append(LastRow,Obj = Py_BuildValue("sss",Package.c_str(), Version.c_str(), - pkgCache::CompTypeDeb(Op))); + debStyle ? pkgCache::CompTypeDeb(Op) : pkgCache::CompType(Op))); Py_DECREF(Obj); } @@ -156,12 +182,22 @@ static PyObject *RealParseDepends(PyObject *Self,PyObject *Args, } static PyObject *ParseDepends(PyObject *Self,PyObject *Args) { - return RealParseDepends(Self,Args,false); + return RealParseDepends(Self, Args, false, "parse_depends"); } static PyObject *ParseSrcDepends(PyObject *Self,PyObject *Args) { - return RealParseDepends(Self,Args,true); + return RealParseDepends(Self, Args, true, "parse_src_depends"); +} +#ifdef COMPAT_0_7 +static PyObject *ParseDepends_old(PyObject *Self,PyObject *Args) +{ + return RealParseDepends(Self, Args, false, "ParseDepends", true); } +static PyObject *ParseSrcDepends_old(PyObject *Self,PyObject *Args) +{ + return RealParseDepends(Self, Args, true, "ParseSrcDepends", true); +} +#endif /*}}}*/ // md5sum - Compute the md5sum of a file or string /*{{{*/ // --------------------------------------------------------------------- @@ -173,21 +209,21 @@ static PyObject *md5sum(PyObject *Self,PyObject *Args) return 0; // Digest of a string. - if (PyString_Check(Obj) != 0) + if (PyBytes_Check(Obj) != 0) { char *s; Py_ssize_t len; MD5Summation Sum; - PyString_AsStringAndSize(Obj, &s, &len); + PyBytes_AsStringAndSize(Obj, &s, &len); Sum.Add((const unsigned char*)s, len); return CppPyString(Sum.Result().Value()); } // Digest of a file - if (PyFile_Check(Obj) != 0) + int Fd = PyObject_AsFileDescriptor(Obj); + if (Fd != -1) { MD5Summation Sum; - int Fd = fileno(PyFile_AsFile(Obj)); struct stat St; if (fstat(Fd,&St) != 0 || Sum.AddFD(Fd,St.st_size) == false) @@ -213,21 +249,21 @@ static PyObject *sha1sum(PyObject *Self,PyObject *Args) return 0; // Digest of a string. - if (PyString_Check(Obj) != 0) + if (PyBytes_Check(Obj) != 0) { char *s; Py_ssize_t len; SHA1Summation Sum; - PyString_AsStringAndSize(Obj, &s, &len); + PyBytes_AsStringAndSize(Obj, &s, &len); Sum.Add((const unsigned char*)s, len); return CppPyString(Sum.Result().Value()); } // Digest of a file - if (PyFile_Check(Obj) != 0) + int Fd = PyObject_AsFileDescriptor(Obj); + if (Fd != -1) { SHA1Summation Sum; - int Fd = fileno(PyFile_AsFile(Obj)); struct stat St; if (fstat(Fd,&St) != 0 || Sum.AddFD(Fd,St.st_size) == false) @@ -253,21 +289,21 @@ static PyObject *sha256sum(PyObject *Self,PyObject *Args) return 0; // Digest of a string. - if (PyString_Check(Obj) != 0) + if (PyBytes_Check(Obj) != 0) { char *s; Py_ssize_t len; SHA256Summation Sum; - PyString_AsStringAndSize(Obj, &s, &len); + PyBytes_AsStringAndSize(Obj, &s, &len); Sum.Add((const unsigned char*)s, len); return CppPyString(Sum.Result().Value()); } // Digest of a file - if (PyFile_Check(Obj) != 0) + int Fd = PyObject_AsFileDescriptor(Obj); + if (Fd != -1) { SHA256Summation Sum; - int Fd = fileno(PyFile_AsFile(Obj)); struct stat St; if (fstat(Fd,&St) != 0 || Sum.AddFD(Fd,St.st_size) == false) @@ -385,42 +421,82 @@ static PyObject *PkgSystemUnLock(PyObject *Self,PyObject *Args) static PyMethodDef methods[] = { // Constructors - {"newConfiguration",newConfiguration,METH_VARARGS,doc_newConfiguration}, {"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. Much Faster than Python's version and only\n" + "does translations after setlocale() has been called."}, + + // Tag File + {"rewrite_section",RewriteSection,METH_VARARGS,doc_RewriteSection}, + + // Locking + {"get_lock",GetLock,METH_VARARGS,doc_GetLock}, + {"pkgsystem_lock",PkgSystemLock,METH_VARARGS,doc_PkgSystemLock}, + {"pkgsystem_unlock",PkgSystemUnLock,METH_VARARGS,doc_PkgSystemUnLock}, + + // 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",ParseDepends,METH_VARARGS,doc_ParseDepends}, + {"parse_src_depends",ParseSrcDepends,METH_VARARGS,doc_ParseDepends}, + + // Stuff + {"md5sum",md5sum,METH_VARARGS,doc_md5sum}, + {"sha1sum",sha1sum,METH_VARARGS,doc_sha1sum}, + {"sha256sum",sha256sum,METH_VARARGS,doc_sha256sum}, + + // Strings + {"check_domain_list",StrCheckDomainList,METH_VARARGS,"CheckDomainList(String,String) -> Bool"}, + {"quote_string",StrQuoteString,METH_VARARGS,"QuoteString(String,String) -> String"}, + {"dequote_string",StrDeQuote,METH_VARARGS,"DeQuoteString(String) -> String"}, + {"size_to_str",StrSizeToStr,METH_VARARGS,"SizeToStr(int) -> String"}, + {"time_to_str",StrTimeToStr,METH_VARARGS,"TimeToStr(int) -> String"}, + {"uri_to_filename",StrURItoFileName,METH_VARARGS,"URItoFileName(String) -> String"}, + {"base64_encode",StrBase64Encode,METH_VARARGS,"Base64Encode(String) -> String"}, + {"string_to_bool",StrStringToBool,METH_VARARGS,"StringToBool(String) -> int"}, + {"time_rfc1123",StrTimeRFC1123,METH_VARARGS,"TimeRFC1123(int) -> String"}, + {"str_to_time",StrStrToTime,METH_VARARGS,"StrToTime(String) -> Int"}, + + // DEPRECATED + #ifdef COMPAT_0_7 + {"newConfiguration",newConfiguration,METH_VARARGS,doc_newConfiguration}, {"InitConfig",InitConfig,METH_VARARGS,doc_InitConfig}, {"InitSystem",InitSystem,METH_VARARGS,doc_InitSystem}, - // Tag File {"ParseSection",ParseSection,METH_VARARGS,doc_ParseSection}, {"ParseTagFile",ParseTagFile,METH_VARARGS,doc_ParseTagFile}, {"RewriteSection",RewriteSection,METH_VARARGS,doc_RewriteSection}, - // Locking {"GetLock",GetLock,METH_VARARGS,doc_GetLock}, {"PkgSystemLock",PkgSystemLock,METH_VARARGS,doc_PkgSystemLock}, {"PkgSystemUnLock",PkgSystemUnLock,METH_VARARGS,doc_PkgSystemUnLock}, - // Command line {"ReadConfigFile",LoadConfig,METH_VARARGS,doc_LoadConfig}, {"ReadConfigDir",LoadConfigDir,METH_VARARGS,doc_LoadConfigDir}, {"ReadConfigFileISC",LoadConfigISC,METH_VARARGS,doc_LoadConfig}, {"ParseCommandLine",ParseCommandLine,METH_VARARGS,doc_ParseCommandLine}, - // Versioning {"VersionCompare",VersionCompare,METH_VARARGS,doc_VersionCompare}, {"CheckDep",CheckDep,METH_VARARGS,doc_CheckDep}, {"UpstreamVersion",UpstreamVersion,METH_VARARGS,doc_UpstreamVersion}, - // Depends - {"ParseDepends",ParseDepends,METH_VARARGS,doc_ParseDepends}, - {"ParseSrcDepends",ParseSrcDepends,METH_VARARGS,doc_ParseDepends}, + {"ParseDepends",ParseDepends_old,METH_VARARGS,doc_ParseDepends}, + {"ParseSrcDepends",ParseSrcDepends_old,METH_VARARGS,doc_ParseDepends}, - // Stuff - {"md5sum",md5sum,METH_VARARGS,doc_md5sum}, - {"sha1sum",sha1sum,METH_VARARGS,doc_sha1sum}, - {"sha256sum",sha256sum,METH_VARARGS,doc_sha256sum}, - - // Strings {"CheckDomainList",StrCheckDomainList,METH_VARARGS,"CheckDomainList(String,String) -> Bool"}, {"QuoteString",StrQuoteString,METH_VARARGS,"QuoteString(String,String) -> String"}, {"DeQuoteString",StrDeQuote,METH_VARARGS,"DeQuoteString(String) -> String"}, @@ -432,104 +508,314 @@ static PyMethodDef methods[] = {"TimeRFC1123",StrTimeRFC1123,METH_VARARGS,"TimeRFC1123(int) -> String"}, {"StrToTime",StrStrToTime,METH_VARARGS,"StrToTime(String) -> Int"}, - // Cache {"GetCache",TmpGetCache,METH_VARARGS,"GetCache() -> PkgCache"}, {"GetDepCache",GetDepCache,METH_VARARGS,"GetDepCache(Cache) -> DepCache"}, {"GetPkgRecords",GetPkgRecords,METH_VARARGS,"GetPkgRecords(Cache) -> PkgRecords"}, {"GetPkgSrcRecords",GetPkgSrcRecords,METH_VARARGS,"GetPkgSrcRecords() -> PkgSrcRecords"}, {"GetPkgSourceList",GetPkgSourceList,METH_VARARGS,"GetPkgSourceList() -> PkgSourceList"}, - - // misc {"GetPkgProblemResolver",GetPkgProblemResolver,METH_VARARGS,"GetDepProblemResolver(DepCache) -> PkgProblemResolver"}, {"GetPkgActionGroup",GetPkgActionGroup,METH_VARARGS,"GetPkgActionGroup(DepCache) -> PkgActionGroup"}, - - // Cdrom {"GetCdrom",GetCdrom,METH_VARARGS,"GetCdrom() -> Cdrom"}, - - // Acquire {"GetAcquire",GetAcquire,METH_VARARGS,"GetAcquire() -> Acquire"}, {"GetPkgAcqFile",(PyCFunction)GetPkgAcqFile,METH_KEYWORDS|METH_VARARGS, doc_GetPkgAcqFile}, - - // PkgManager {"GetPackageManager",GetPkgManager,METH_VARARGS,"GetPackageManager(DepCache) -> PackageManager"}, + #endif {} }; -static void AddStr(PyObject *Dict,const char *Itm,const char *Str) -{ - PyObject *Obj = PyString_FromString(Str); - PyDict_SetItemString(Dict,(char *)Itm,Obj); - Py_DECREF(Obj); -} +static struct _PyAptPkgAPIStruct API = { + &PyAcquire_Type, // acquire_type + &PyAcquireFile_Type, // acquirefile_type + &PyAcquireItem_Type, // acquireitem_type + &PyAcquireItemDesc_Type, // acquireitemdesc_type + &PyAcquireWorker_Type, // acquireworker_type + &PyActionGroup_Type, // actiongroup_type + &PyCache_Type, // cache_type + &PyCacheFile_Type, // cachefile_type + &PyCdrom_Type, // cdrom_type + &PyConfiguration_Type, // configuration_type + &PyDepCache_Type, // depcache_type + &PyDependency_Type, // dependency_type + &PyDependencyList_Type, // dependencylist_type + &PyDescription_Type, // description_type + &PyHashes_Type, // hashes_type + &PyHashString_Type, // hashstring_type + &PyIndexRecords_Type, // indexrecords_type + &PyMetaIndex_Type, // metaindex_type + &PyPackage_Type, // package_type + &PyPackageFile_Type, // packagefile_type + &PyPackageIndexFile_Type, // packageindexfile_type + &PyPackageList_Type, // packagelist_type + &PyPackageManager_Type, // packagemanager_type + &PyPackageRecords_Type, // packagerecords_type + &PyPolicy_Type, // policy_type + &PyProblemResolver_Type, // problemresolver_type + &PySourceList_Type, // sourcelist_type + &PySourceRecords_Type, // sourcerecords_type + &PyTagFile_Type, // tagfile_type + &PyTagSection_Type, // tagsection_type + &PyVersion_Type, // version_type +}; -static void AddInt(PyObject *Dict,const char *Itm,unsigned long I) -{ - PyObject *Obj = Py_BuildValue("i",I); - PyDict_SetItemString(Dict,(char *)Itm,Obj); - Py_DECREF(Obj); -} +#define ADDTYPE(mod,name,type) { \ + if (PyType_Ready(type) == -1) INIT_ERROR; \ + Py_INCREF(type); \ + PyModule_AddObject(mod,name,(PyObject *)type); } + + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "apt_pkg", + "Classes and functions wrapping the apt-pkg library.\n\n" + "The apt_pkg module provides...", + -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; + + // Initialize the module + #if PY_MAJOR_VERSION >= 3 + PyObject *Module = PyModule_Create(&moduledef); + #else PyObject *Module = Py_InitModule("apt_pkg",methods); - PyObject *Dict = PyModule_GetDict(Module); + #endif // Global variable linked to the global configuration class - CppPyObject<Configuration *> *Config = CppPyObject_NEW<Configuration *>(&ConfigurationPtrType); + CppOwnedPyObject<Configuration*> *Config = CppOwnedPyObject_NEW<Configuration*>(NULL, &PyConfiguration_Type); Config->Object = _config; - PyDict_SetItemString(Dict,"Config",Config); - Py_DECREF(Config); - + // Global configuration, should never be deleted. + Config->NoDelete = true; + PyModule_AddObject(Module,"config",Config); + #ifdef COMPAT_0_7 + Py_INCREF(Config); + PyModule_AddObject(Module,"Config",Config); + #endif + + + + + // Add our classes. + /* ============================ tag.cc ============================ */ + ADDTYPE(Module,"TagSection",&PyTagSection_Type); + ADDTYPE(Module,"TagFile",&PyTagFile_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__() + /* ============================ 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,"PackageIndexFile",&PyPackageIndexFile_Type); // NO __new__() + /* ========================= metaindex.cc ========================= */ + ADDTYPE(Module,"MetaIndex",&PyMetaIndex_Type); // NO __new__() + /* ========================= pkgmanager.cc ========================= */ + ADDTYPE(Module,"PackageManager",&PyPackageManager_Type); + /* ========================= pkgrecords.cc ========================= */ + ADDTYPE(Module,"PackageRecords",&PyPackageRecords_Type); + /* ========================= pkgsrcrecords.cc ========================= */ + ADDTYPE(Module,"SourceRecords",&PySourceRecords_Type); + /* ========================= sourcelist.cc ========================= */ + ADDTYPE(Module,"SourceList",&PySourceList_Type); + ADDTYPE(Module,"IndexRecords",&PyIndexRecords_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); // Tag file constants - PyObject *Obj; - PyDict_SetItemString(Dict,"RewritePackageOrder", - Obj = CharCharToList(TFRewritePackageOrder)); - Py_DECREF(Obj); - PyDict_SetItemString(Dict,"RewriteSourceOrder", - Obj = CharCharToList(TFRewriteSourceOrder)); - Py_DECREF(Obj); - + PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER", + CharCharToList(TFRewritePackageOrder)); + + PyModule_AddObject(Module,"REWRITE_SOURCE_ORDER", + CharCharToList(TFRewriteSourceOrder)); + + + // Acquire constants. + // some constants + PyDict_SetItemString(PyAcquire_Type.tp_dict, "result_cancelled", + Py_BuildValue("i", pkgAcquire::Cancelled)); + PyDict_SetItemString(PyAcquire_Type.tp_dict, "result_continue", + Py_BuildValue("i", pkgAcquire::Continue)); + PyDict_SetItemString(PyAcquire_Type.tp_dict, "result_failed", + Py_BuildValue("i", pkgAcquire::Failed)); +#ifdef COMPAT_0_7 + PyDict_SetItemString(PyAcquire_Type.tp_dict, "ResultCancelled", + Py_BuildValue("i", pkgAcquire::Cancelled)); + PyDict_SetItemString(PyAcquire_Type.tp_dict, "ResultContinue", + Py_BuildValue("i", pkgAcquire::Continue)); + PyDict_SetItemString(PyAcquire_Type.tp_dict, "ResultFailed", + Py_BuildValue("i", pkgAcquire::Failed)); +#endif + // Dependency constants + PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DEPENDS", + Py_BuildValue("i", pkgCache::Dep::Depends)); + PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_PREDEPENDS", + Py_BuildValue("i", pkgCache::Dep::PreDepends)); + PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_SUGGESTS", + Py_BuildValue("i", pkgCache::Dep::Suggests)); + PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_RECOMMENDS", + Py_BuildValue("i", pkgCache::Dep::Suggests)); + PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_CONFLICTS", + Py_BuildValue("i", pkgCache::Dep::Conflicts)); + PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_REPLACES", + Py_BuildValue("i", pkgCache::Dep::Replaces)); + PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_OBSOLETES", + Py_BuildValue("i", pkgCache::Dep::Obsoletes)); + PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DPKG_BREAKS", + Py_BuildValue("i", pkgCache::Dep::DpkgBreaks)); + PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_ENHANCES", + Py_BuildValue("i", pkgCache::Dep::Enhances)); + + + // PackageManager constants + PyDict_SetItemString(PyPackageManager_Type.tp_dict, "result_completed", + Py_BuildValue("i", pkgPackageManager::Completed)); + PyDict_SetItemString(PyPackageManager_Type.tp_dict, "result_failed", + Py_BuildValue("i", pkgPackageManager::Failed)); + PyDict_SetItemString(PyPackageManager_Type.tp_dict, "result_incomplete", + Py_BuildValue("i", pkgPackageManager::Incomplete)); + +#ifdef COMPAT_0_7 + PyDict_SetItemString(PyPackageManager_Type.tp_dict, "ResultCompleted", + Py_BuildValue("i", pkgPackageManager::Completed)); + PyDict_SetItemString(PyPackageManager_Type.tp_dict, "ResultFailed", + Py_BuildValue("i", pkgPackageManager::Failed)); + PyDict_SetItemString(PyPackageManager_Type.tp_dict, "ResultIncomplete", + Py_BuildValue("i", pkgPackageManager::Incomplete)); +#endif + + // AcquireItem Constants. + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_idle", + Py_BuildValue("i", pkgAcquire::Item::StatIdle)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_fetching", + Py_BuildValue("i", pkgAcquire::Item::StatFetching)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_done", + Py_BuildValue("i", pkgAcquire::Item::StatDone)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_error", + Py_BuildValue("i", pkgAcquire::Item::StatError)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "stat_auth_error", + Py_BuildValue("i", pkgAcquire::Item::StatAuthError)); + +#ifdef COMPAT_0_7 + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatIdle", + Py_BuildValue("i", pkgAcquire::Item::StatIdle)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatFetching", + Py_BuildValue("i", pkgAcquire::Item::StatFetching)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatDone", + Py_BuildValue("i", pkgAcquire::Item::StatDone)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatError", + Py_BuildValue("i", pkgAcquire::Item::StatError)); + PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "StatAuthError", + Py_BuildValue("i", pkgAcquire::Item::StatAuthError)); +#endif + +#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.. - AddStr(Dict,"Version",pkgVersion); - AddStr(Dict,"LibVersion",pkgLibVersion); - AddStr(Dict,"Date",__DATE__); - AddStr(Dict,"Time",__TIME__); + PyModule_AddStringConstant(Module,"VERSION",(char *)pkgVersion); + PyModule_AddStringConstant(Module,"LIB_VERSION",(char *)pkgLibVersion); + PyModule_AddStringConstant(Module,"DATE",__DATE__); + PyModule_AddStringConstant(Module,"TIME",__TIME__); // My constants - AddInt(Dict,"DepDepends",pkgCache::Dep::Depends); - AddInt(Dict,"DepPreDepends",pkgCache::Dep::PreDepends); - AddInt(Dict,"DepSuggests",pkgCache::Dep::Suggests); - AddInt(Dict,"DepRecommends",pkgCache::Dep::Recommends); - AddInt(Dict,"DepConflicts",pkgCache::Dep::Conflicts); - AddInt(Dict,"DepReplaces",pkgCache::Dep::Replaces); - AddInt(Dict,"DepObsoletes",pkgCache::Dep::Obsoletes); - AddInt(Dict,"DepDpkgBreaks",pkgCache::Dep::DpkgBreaks); - AddInt(Dict,"DepEnhances",pkgCache::Dep::Enhances); - - AddInt(Dict,"PriImportant",pkgCache::State::Important); - AddInt(Dict,"PriRequired",pkgCache::State::Required); - AddInt(Dict,"PriStandard",pkgCache::State::Standard); - AddInt(Dict,"PriOptional",pkgCache::State::Optional); - AddInt(Dict,"PriExtra",pkgCache::State::Extra); - - AddInt(Dict,"CurStateNotInstalled",pkgCache::State::NotInstalled); - AddInt(Dict,"CurStateUnPacked",pkgCache::State::UnPacked); - AddInt(Dict,"CurStateHalfConfigured",pkgCache::State::HalfConfigured); - AddInt(Dict,"CurStateHalfInstalled",pkgCache::State::HalfInstalled); - AddInt(Dict,"CurStateConfigFiles",pkgCache::State::ConfigFiles); - AddInt(Dict,"CurStateInstalled",pkgCache::State::Installed); - - AddInt(Dict,"SelStateUnknown",pkgCache::State::Unknown); - AddInt(Dict,"SelStateInstall",pkgCache::State::Install); - AddInt(Dict,"SelStateHold",pkgCache::State::Hold); - AddInt(Dict,"SelStateDeInstall",pkgCache::State::DeInstall); - AddInt(Dict,"SelStatePurge",pkgCache::State::Purge); - - AddInt(Dict,"InstStateOk",pkgCache::State::Ok); - AddInt(Dict,"InstStateReInstReq",pkgCache::State::ReInstReq); - AddInt(Dict,"InstStateHold",pkgCache::State::Hold); - AddInt(Dict,"InstStateHoldReInstReq",pkgCache::State::HoldReInstReq); + 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); + + // DEPRECATED API + #ifdef COMPAT_0_7 + PyModule_AddObject(Module,"RewritePackageOrder", + CharCharToList(TFRewritePackageOrder)); + PyModule_AddObject(Module,"RewriteSourceOrder", + CharCharToList(TFRewriteSourceOrder)); + PyModule_AddStringConstant(Module,"LibVersion",(char *)pkgLibVersion); + PyModule_AddStringConstant(Module,"Date",__DATE__); + PyModule_AddStringConstant(Module,"Time",__TIME__); + PyModule_AddIntConstant(Module,"PriImportant",pkgCache::State::Important); + PyModule_AddIntConstant(Module,"PriRequired",pkgCache::State::Required); + PyModule_AddIntConstant(Module,"PriStandard",pkgCache::State::Standard); + PyModule_AddIntConstant(Module,"PriOptional",pkgCache::State::Optional); + PyModule_AddIntConstant(Module,"PriExtra",pkgCache::State::Extra); + PyModule_AddIntConstant(Module,"CurStateNotInstalled",pkgCache::State::NotInstalled); + PyModule_AddIntConstant(Module,"CurStateUnPacked",pkgCache::State::UnPacked); + PyModule_AddIntConstant(Module,"CurStateHalfConfigured",pkgCache::State::HalfConfigured); + PyModule_AddIntConstant(Module,"CurStateHalfInstalled",pkgCache::State::HalfInstalled); + PyModule_AddIntConstant(Module,"CurStateConfigFiles",pkgCache::State::ConfigFiles); + PyModule_AddIntConstant(Module,"CurStateInstalled",pkgCache::State::Installed); + PyModule_AddIntConstant(Module,"SelStateUnknown",pkgCache::State::Unknown); + PyModule_AddIntConstant(Module,"SelStateInstall",pkgCache::State::Install); + PyModule_AddIntConstant(Module,"SelStateHold",pkgCache::State::Hold); + PyModule_AddIntConstant(Module,"SelStateDeInstall",pkgCache::State::DeInstall); + PyModule_AddIntConstant(Module,"SelStatePurge",pkgCache::State::Purge); + PyModule_AddIntConstant(Module,"InstStateOk",pkgCache::State::Ok); + PyModule_AddIntConstant(Module,"InstStateReInstReq",pkgCache::State::ReInstReq); + PyModule_AddIntConstant(Module,"InstStateHold",pkgCache::State::Hold); + PyModule_AddIntConstant(Module,"InstStateHoldReInstReq",pkgCache::State::HoldReInstReq); + PyModule_AddIntConstant(Module,"_COMPAT_0_7",1); + #else + PyModule_AddIntConstant(Module,"_COMPAT_0_7",0); + #endif + #if PY_MAJOR_VERSION >= 3 + return Module; + #endif } /*}}}*/ diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index e047bcd8..97ba05a7 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -11,15 +11,13 @@ #define APT_PKGMODULE_H #include <Python.h> +#include <apt-pkg/hashes.h> +#include <apt-pkg/acquire-item.h> // Configuration Stuff -#define Configuration_Check(op) ((op)->ob_type == &ConfigurationType || \ - (op)->ob_type == &ConfigurationPtrType || \ - (op)->ob_type == &ConfigurationSubType) -extern PyTypeObject ConfigurationType; -extern PyTypeObject ConfigurationPtrType; -extern PyTypeObject ConfigurationSubType; -extern PyTypeObject VersionType; +#define Configuration_Check(op) ((op)->ob_type == &PyConfiguration_Type) +extern PyTypeObject PyConfiguration_Type; +extern PyTypeObject PyVersion_Type; extern char *doc_LoadConfig; extern char *doc_LoadConfigISC; @@ -31,8 +29,8 @@ PyObject *LoadConfigDir(PyObject *Self,PyObject *Args); PyObject *ParseCommandLine(PyObject *Self,PyObject *Args); // Tag File Stuff -extern PyTypeObject TagSecType; -extern PyTypeObject TagFileType; +extern PyTypeObject PyTagSection_Type; +extern PyTypeObject PyTagFile_Type; extern char *doc_ParseSection; extern char *doc_ParseTagFile; extern char *doc_RewriteSection; @@ -52,54 +50,77 @@ 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 PkgCacheType; -extern PyTypeObject PkgCacheFileType; -extern PyTypeObject PkgListType; -extern PyTypeObject PackageType; -extern PyTypeObject PackageFileType; -extern PyTypeObject DependencyType; -extern PyTypeObject RDepListType; +extern PyTypeObject PyCache_Type; +extern PyTypeObject PyCacheFile_Type; +extern PyTypeObject PyPackageList_Type; +extern PyTypeObject PyDescription_Type; +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 PkgDepCacheType; +extern PyTypeObject PyDepCache_Type; PyObject *GetDepCache(PyObject *Self,PyObject *Args); // pkgProblemResolver -extern PyTypeObject PkgProblemResolverType; +extern PyTypeObject PyProblemResolver_Type; PyObject *GetPkgProblemResolver(PyObject *Self, PyObject *Args); PyObject *GetPkgActionGroup(PyObject *Self, PyObject *Args); +extern PyTypeObject PyActionGroup_Type; // cdrom -extern PyTypeObject PkgCdromType; +extern PyTypeObject PyCdrom_Type; PyObject *GetCdrom(PyObject *Self,PyObject *Args); // acquire -extern PyTypeObject PkgAcquireType; +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 PkgManagerType; +extern PyTypeObject PyPackageManager_Type; PyObject *GetPkgManager(PyObject *Self,PyObject *Args); // PkgRecords Stuff -extern PyTypeObject PkgRecordsType; +extern PyTypeObject PyPackageRecords_Type; +extern PyTypeObject PySourceRecords_Type; PyObject *GetPkgRecords(PyObject *Self,PyObject *Args); PyObject *GetPkgSrcRecords(PyObject *Self,PyObject *Args); // pkgSourceList -extern PyTypeObject PkgSourceListType; +extern PyTypeObject PySourceList_Type; PyObject *GetPkgSourceList(PyObject *Self,PyObject *Args); // pkgSourceList -extern PyTypeObject PackageIndexFileType; +extern PyTypeObject PyPackageIndexFile_Type; // metaIndex -extern PyTypeObject MetaIndexType; - - +extern PyTypeObject PyMetaIndex_Type; + +// HashString +extern PyTypeObject PyHashString_Type; + +// IndexRecord +extern PyTypeObject PyIndexRecords_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; +#include "python-apt.h" #endif + diff --git a/python/arfile.cc b/python/arfile.cc new file mode 100644 index 00000000..1abb738f --- /dev/null +++ b/python/arfile.cc @@ -0,0 +1,646 @@ +/* + * 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/sptr.h> +#include <utime.h> + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +static PyObject *armember_get_name(PyObject *self, void *closure) +{ + return CppPyString(GetCpp<ARArchive::Member*>(self)->Name); +} + +static PyObject *armember_get_mtime(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->MTime); +} + +static PyObject *armember_get_uid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->UID); +} + +static PyObject *armember_get_gid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->GID); +} + +static PyObject *armember_get_mode(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->Mode); +} + +static PyObject *armember_get_size(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<ARArchive::Member*>(self)->Size); +} + +static PyObject *armember_get_start(PyObject *self, void *closure) +{ + return Py_BuildValue("k", 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 = + "An ArMember object represents 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(CppOwnedPyObject<ARArchive::Member*>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDeallocPtr<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 + CppOwnedTraverse<ARArchive::Member*>,// tp_traverse + CppOwnedClear<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 +}; + +// 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 CppOwnedPyObject<PyARArchiveHack*> { + FileFd Fd; +}; + +static const char *ararchive_getmember_doc = + "getmember(name: str) -> ArMember\n\n" + "Return a 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) +{ + const char *name; + CppOwnedPyObject<ARArchive::Member*> *ret; + if (! (name = PyObject_AsString(arg))) + return 0; + + const ARArchive::Member *member = self->Object->FindMember(name); + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + + // Create our object. + ret = CppOwnedPyObject_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) +{ + char *name = 0; + if (PyArg_ParseTuple(args, "s:extractdata", &name) == 0) + return 0; + const ARArchive::Member *member = self->Object->FindMember(name); + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + if (!self->Fd.Seek(member->Start)) + return HandleErrors(); + + char* value = new char[member->Size]; + self->Fd.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(); + + 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. + SPtrArray<char> value = new char[4096]; + unsigned long size = member->Size; + unsigned long read = 4096; + while (size > 0) { + if (size < read) + read = size; + if (!Fd.Read(value, read, true)) + return HandleErrors(); + if (write(outfd, value, read) != (signed)read) + return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile); + size -= read; + } + utimbuf time = {member->MTime, 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 by target.\n" + "If the extraction failed, an error is raised. Otherwise, the method\n" + "returns True if the owner could be set or False if the owner could not\n" + "be changed. It may also raise LookupError if there is member with\n" + "the given name."; +static PyObject *ararchive_extract(PyArArchiveObject *self, PyObject *args) +{ + char *name = 0; + char *target = ""; + if (PyArg_ParseTuple(args, "s|s:extract", &name, &target) == 0) + return 0; + + const ARArchive::Member *member = self->Object->FindMember(name); + + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + return _extract(self->Fd, member, target); +} + +static const char *ararchive_extractall_doc = + "extract([target: str]) -> bool\n\n" + "Extract all into the directory given by target.\n" + "If the extraction failed, an error is raised. Otherwise, the method\n" + "returns True if the owner could be set or False if the owner could not\n" + "be changed."; + +static PyObject *ararchive_extractall(PyArArchiveObject *self, PyObject *args) +{ + char *target = ""; + if (PyArg_ParseTuple(args, "|s:extractall", &target) == 0) + return 0; + + const ARArchive::Member *member = self->Object->Members(); + + do { + if (_extract(self->Fd, 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) +{ + const char *name; + const char *comp; + if (PyArg_ParseTuple(args, "ss:gettar", &name, &comp) == 0) + return 0; + + const ARArchive::Member *member = self->Object->FindMember(name); + if (!member) { + PyErr_Format(PyExc_LookupError,"No member named '%s'",name); + return 0; + } + + PyTarFileObject *tarfile = (PyTarFileObject*)CppOwnedPyObject_NEW<ExtractTar*>(self,&PyTarFile_Type); + new (&tarfile->Fd) FileFd(self->Fd); + tarfile->min = member->Start; + tarfile->Object = new ExtractTar(self->Fd, member->Size, comp); + return HandleErrors(tarfile); +} + +static const char *ararchive_getmembers_doc = + "getmembers() -> list\n\n" + "Return a list of all members in the AR archive."; +static PyObject *ararchive_getmembers(PyArArchiveObject *self) +{ + PyObject *list = PyList_New(0); + ARArchive::Member *member = self->Object->Members(); + do { + CppOwnedPyObject<ARArchive::Member*> *ret; + ret = CppOwnedPyObject_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 AR 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; + PyArArchiveObject *self; + char *filename = 0; + int fileno; + if (PyArg_ParseTuple(args,"O:__new__",&file) == 0) + return 0; + + // We receive a filename. + if ((filename = (char*)PyObject_AsString(file))) { + self = (PyArArchiveObject *)CppOwnedPyObject_NEW<ARArchive*>(0,type); + new (&self->Fd) 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 = (PyArArchiveObject *)CppOwnedPyObject_NEW<ARArchive*>(file,type); + new (&self->Fd) FileFd(fileno,false); + } + else { + return 0; + } + self->Object = (PyARArchiveHack*)new ARArchive(self->Fd); + if (_error->PendingError() == true) + return HandleErrors(); + return self; +} + +static void ararchive_dealloc(PyObject *self) +{ + ((PyArArchiveObject *)(self))->Fd.~FileFd(); + CppOwnedDeallocPtr<ARArchive*>(self); +} + +// Return bool or -1 (exception). +static int ararchive_contains(PyObject *self, PyObject *arg) +{ + const char *name = PyObject_AsString(arg); + if (!name) + 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" + "An ArArchive object represents 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 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 + CppOwnedTraverse<ARArchive*>, // tp_traverse + CppOwnedClear<ARArchive*>, // 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.{lzma,bz2,gz} and + * data.tar.{lzma,bz2,gz} 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*)CppOwnedPyObject_NEW<ExtractTar*>(self,&PyTarFile_Type); + new (&tarfile->Fd) FileFd(self->Fd); + tarfile->min = m->Start; + tarfile->Object = new ExtractTar(self->Fd, m->Size, comp); + return tarfile; +} + + + +static PyObject *debfile_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyDebFileObject *self = (PyDebFileObject*)ararchive_new(type, args, kwds); + + // DebFile + self->control = _gettar(self, self->Object->FindMember("control.tar.gz"), + "gzip"); + if (!self->control) + return PyErr_Format(PyExc_SystemError, "No debian archive, missing %s", + "control.tar.gz"); + + self->data = _gettar(self, self->Object->FindMember("data.tar.gz"), + "gzip"); + if (!self->data) + self->data = _gettar(self, self->Object->FindMember("data.tar.bz2"), + "bzip2"); + if (!self->data) + self->data = _gettar(self, self->Object->FindMember("data.tar.lzma"), + "lzma"); + if (!self->data) + return PyErr_Format(PyExc_SystemError, "No debian archive, missing %s", + "data.tar.gz or data.tar.bz2 or data.tar.lzma"); + + + const ARArchive::Member *member = self->Object->FindMember("debian-binary"); + if (!member) + return PyErr_Format(PyExc_SystemError, "No debian archive, missing %s", + "debian-binary"); + + if (!self->Fd.Seek(member->Start)) + return HandleErrors(); + + char* value = new char[member->Size]; + self->Fd.Read(value, member->Size, true); + self->debian_binary = PyBytes_FromStringAndSize(value, member->Size); + delete[] value; + return self; +} + +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.{gz,bz2,lzma} member."}, + {"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 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.{gz,bz2,lzma}\n" + ",debian-binary members 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 index 023cf041..6bbf0766 100644 --- a/python/cache.cc +++ b/python/cache.cc @@ -73,7 +73,7 @@ static PyObject *CreateProvides(PyObject *Owner,pkgCache::PrvIterator I) { PyObject *Obj; PyObject *Ver; - Ver = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType, + Ver = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type, I.OwnerVer()); Obj = Py_BuildValue("ssN",I.ParentPkg().Name(),I.ProvideVersion(), Ver); @@ -87,9 +87,6 @@ static PyObject *CreateProvides(PyObject *Owner,pkgCache::PrvIterator I) // --------------------------------------------------------------------- static PyObject *PkgCacheUpdate(PyObject *Self,PyObject *Args) { - PyObject *CacheFilePy = GetOwner<pkgCache*>(Self); - pkgCacheFile *Cache = GetCpp<pkgCacheFile*>(CacheFilePy); - PyObject *pyFetchProgressInst = 0; PyObject *pySourcesList = 0; int pulseInterval = 0; @@ -105,8 +102,11 @@ static PyObject *PkgCacheUpdate(PyObject *Self,PyObject *Args) return HandleErrors(PyRes); } +#ifdef COMPAT_0_7 static PyObject *PkgCacheClose(PyObject *Self,PyObject *Args) { + PyErr_WarnEx(PyExc_DeprecationWarning, "Cache.Close() is deprecated, " + "because it causes segfaults. Delete the Cache instead.", 1); PyObject *CacheFilePy = GetOwner<pkgCache*>(Self); pkgCacheFile *Cache = GetCpp<pkgCacheFile*>(CacheFilePy); Cache->Close(); @@ -117,6 +117,9 @@ static PyObject *PkgCacheClose(PyObject *Self,PyObject *Args) static PyObject *PkgCacheOpen(PyObject *Self,PyObject *Args) { + PyErr_WarnEx(PyExc_DeprecationWarning, "Cache.Open() is deprecated, " + "because it causes memory leaks. Create a new Cache instead.", + 1); PyObject *CacheFilePy = GetOwner<pkgCache*>(Self); pkgCacheFile *Cache = GetCpp<pkgCacheFile*>(CacheFilePy); @@ -144,63 +147,102 @@ static PyObject *PkgCacheOpen(PyObject *Self,PyObject *Args) Py_INCREF(Py_None); return HandleErrors(Py_None); } - +#endif static PyMethodDef PkgCacheMethods[] = { + {"update",PkgCacheUpdate,METH_VARARGS,"Update the cache"}, +#ifdef COMPAT_0_7 {"Update",PkgCacheUpdate,METH_VARARGS,"Update the cache"}, {"Open", PkgCacheOpen, METH_VARARGS,"Open the cache"}, {"Close", PkgCacheClose, METH_VARARGS,"Close the cache"}, +#endif {} }; -static PyObject *CacheAttr(PyObject *Self,char *Name) -{ +static PyObject *PkgCacheGetPackages(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return CppOwnedPyObject_NEW<PkgListStruct>(Self,&PyPackageList_Type,Cache->PkgBegin()); +} + +static PyObject *PkgCacheGetPackageCount(PyObject *Self, void*) { pkgCache *Cache = GetCpp<pkgCache *>(Self); + return Py_BuildValue("i",Cache->HeaderP->PackageCount); +} + +static PyObject *PkgCacheGetVersionCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return Py_BuildValue("i",Cache->HeaderP->VersionCount); +} +static PyObject *PkgCacheGetDependsCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return Py_BuildValue("i",Cache->HeaderP->DependsCount); +} - if (strcmp("Packages",Name) == 0) - return CppOwnedPyObject_NEW<PkgListStruct>(Self,&PkgListType,Cache->PkgBegin()); - else if (strcmp("PackageCount",Name) == 0) - return Py_BuildValue("i",Cache->HeaderP->PackageCount); - else if (strcmp("VersionCount",Name) == 0) - return Py_BuildValue("i",Cache->HeaderP->VersionCount); - else if (strcmp("DependsCount",Name) == 0) - return Py_BuildValue("i",Cache->HeaderP->DependsCount); - else if (strcmp("PackageFileCount",Name) == 0) - return Py_BuildValue("i",Cache->HeaderP->PackageFileCount); - else if (strcmp("VerFileCount",Name) == 0) - return Py_BuildValue("i",Cache->HeaderP->VerFileCount); - else if (strcmp("ProvidesCount",Name) == 0) - return Py_BuildValue("i",Cache->HeaderP->ProvidesCount); - else if (strcmp("FileList",Name) == 0) +static PyObject *PkgCacheGetPackageFileCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return Py_BuildValue("i",Cache->HeaderP->PackageFileCount); +} + +static PyObject *PkgCacheGetVerFileCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return Py_BuildValue("i",Cache->HeaderP->VerFileCount); +} + +static PyObject *PkgCacheGetProvidesCount(PyObject *Self, void*) { + pkgCache *Cache = GetCpp<pkgCache *>(Self); + return Py_BuildValue("i",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 *List = PyList_New(0); - for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I.end() == false; I++) - { - PyObject *Obj; - Obj = CppOwnedPyObject_NEW<pkgCache::PkgFileIterator>(Self,&PackageFileType,I); - PyList_Append(List,Obj); - Py_DECREF(Obj); - } - return List; + PyObject *Obj; + Obj = CppOwnedPyObject_NEW<pkgCache::PkgFileIterator>(Self,&PyPackageFile_Type,I); + PyList_Append(List,Obj); + Py_DECREF(Obj); } - - return Py_FindMethod(PkgCacheMethods,Self,Name); + return List; } +static PyGetSetDef PkgCacheGetSet[] = { + {"depends_count",PkgCacheGetDependsCount}, + {"file_list",PkgCacheGetFileList}, + {"package_count",PkgCacheGetPackageCount}, + {"package_file_count",PkgCacheGetPackageFileCount}, + {"packages",PkgCacheGetPackages}, + {"provides_count",PkgCacheGetProvidesCount}, + {"ver_file_count",PkgCacheGetVerFileCount}, + {"version_count",PkgCacheGetVersionCount}, +#ifdef COMPAT_0_7 + {"DependsCount",PkgCacheGetDependsCount}, + {"FileList",PkgCacheGetFileList}, + {"PackageCount",PkgCacheGetPackageCount}, + {"PackageFileCount",PkgCacheGetPackageFileCount}, + {"Packages",PkgCacheGetPackages}, + {"ProvidesCount",PkgCacheGetProvidesCount}, + {"VerFileCount",PkgCacheGetVerFileCount}, + {"VersionCount",PkgCacheGetVersionCount}, +#endif + {} +}; + + + // Map access, operator [] static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) { pkgCache *Cache = GetCpp<pkgCache *>(Self); - if (PyString_Check(Arg) == 0) - { - PyErr_SetNone(PyExc_TypeError); + // Get the name of the package, unicode and normal strings. + const char *Name = PyObject_AsString(Arg); + if (Name == NULL) return 0; - } + // Search for the package - const char *Name = PyString_AsString(Arg); pkgCache::PkgIterator Pkg = Cache->FindPkg(Name); if (Pkg.end() == true) { @@ -208,32 +250,79 @@ static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg) return 0; } - return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Self,&PackageType,Pkg); + return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Self,&PyPackage_Type,Pkg); } -// we need a special dealloc here to make sure that the CacheFile -// is closed before deallocation the cache (otherwise we have a bad) -// memory leak -void PkgCacheFileDealloc(PyObject *Self) +static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) { - PyObject *CacheFilePy = GetOwner<pkgCache*>(Self); - pkgCacheFile *CacheF = GetCpp<pkgCacheFile*>(CacheFilePy); - CacheF->Close(); - CppOwnedDealloc<pkgCache *>(Self); + 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 != 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(); + } + + CppOwnedPyObject<pkgCacheFile*> *CacheFileObj = + CppOwnedPyObject_NEW<pkgCacheFile*>(0,&PyCacheFile_Type, Cache); + + CppOwnedPyObject<pkgCache *> *CacheObj = + CppOwnedPyObject_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 char *doc_PkgCache = "Cache([progress]) -> Cache() object.\n\n" + "The cache provides access to the packages and other stuff.\n\n" + "The optional parameter *progress* can be used to specify an \n" + "apt.progress.OpProgress() object (or similar) which displays\n" + "the opening progress.\n\n" + "If not specified, the progress is displayed in simple text form."; + static PyMappingMethods CacheMap = {0,CacheMapOp,0}; -PyTypeObject PkgCacheType = +PyTypeObject PyCache_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgCache", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Cache", // tp_name sizeof(CppOwnedPyObject<pkgCache *>), // tp_basicsize 0, // tp_itemsize // Methods - PkgCacheFileDealloc, // tp_dealloc + CppOwnedDeallocPtr<pkgCache *>, // tp_dealloc 0, // tp_print - CacheAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr @@ -241,19 +330,44 @@ PyTypeObject PkgCacheType = 0, // tp_as_sequence &CacheMap, // 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_PkgCache, // tp_doc + CppOwnedTraverse<pkgCache *>, // tp_traverse + CppOwnedClear<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 PkgCacheFileType = +PyTypeObject PyCacheFile_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size + PyVarObject_HEAD_INIT(&PyType_Type, 0) "pkgCacheFile", // tp_name sizeof(CppOwnedPyObject<pkgCacheFile*>), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc<pkgCacheFile*>, // tp_dealloc + CppOwnedDeallocPtr<pkgCacheFile*>, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -263,6 +377,12 @@ PyTypeObject PkgCacheFileType = 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 /*{{{*/ @@ -298,7 +418,7 @@ static PyObject *PkgListItem(PyObject *iSelf,Py_ssize_t Index) } } - return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(GetOwner<PkgListStruct>(iSelf),&PackageType, + return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(GetOwner<PkgListStruct>(iSelf),&PyPackage_Type, Self.Iter); } @@ -313,11 +433,10 @@ static PySequenceMethods PkgListSeq = 0 // assign slice }; -PyTypeObject PkgListType = +PyTypeObject PyPackageList_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgCache::PkgIterator", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.PackageList", // tp_name sizeof(CppOwnedPyObject<PkgListStruct>), // tp_basicsize 0, // tp_itemsize // Methods @@ -331,89 +450,120 @@ PyTypeObject PkgListType = &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 + 0, // tp_doc + CppOwnedTraverse<PkgListStruct>, // tp_traverse + CppOwnedClear<PkgListStruct>, // tp_clear }; - /*}}}*/ -// Package Class /*{{{*/ -// --------------------------------------------------------------------- -static PyObject *PackageAttr(PyObject *Self,char *Name) +#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,PyString_FromString(Pkg.Name())) +MkGet(PackageGetSection,Safe_FromString(Pkg.Section())) +MkGet(PackageGetRevDependsList,CppOwnedPyObject_NEW<RDepListStruct>(Owner, + &PyDependencyList_Type, Pkg.RevDependsList())) +MkGet(PackageGetProvidesList,CreateProvides(Owner,Pkg.ProvidesList())) +MkGet(PackageGetSelectedState,Py_BuildValue("i",Pkg->SelectedState)) +MkGet(PackageGetInstState,Py_BuildValue("i",Pkg->InstState)) +MkGet(PackageGetCurrentState,Py_BuildValue("i",Pkg->CurrentState)) +MkGet(PackageGetID,Py_BuildValue("i",Pkg->ID)) +# +MkGet(PackageGetAuto,Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Auto) != 0)) +MkGet(PackageGetEssential,Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Essential) != 0)) +MkGet(PackageGetImportant,Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Important) != 0)) +#undef MkGet +#undef Owner + +static PyObject *PackageGetVersionList(PyObject *Self,void*) { pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self); - if (strcmp("Name",Name) == 0) - return PyString_FromString(Pkg.Name()); - else if (strcmp("VersionList",Name) == 0) + PyObject *List = PyList_New(0); + for (pkgCache::VerIterator I = Pkg.VersionList(); I.end() == false; I++) { - PyObject *List = PyList_New(0); - for (pkgCache::VerIterator I = Pkg.VersionList(); I.end() == false; I++) - { - PyObject *Obj; - Obj = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType,I); - PyList_Append(List,Obj); - Py_DECREF(Obj); - } - return List; + PyObject *Obj; + Obj = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,I); + PyList_Append(List,Obj); + Py_DECREF(Obj); } - else if (strcmp("CurrentVer",Name) == 0) + return List; +} +static PyObject *PackageGetCurrentVer(PyObject *Self,void*) +{ + pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self); + if (Pkg->CurrentVer == 0) { - if (Pkg->CurrentVer == 0) - { - Py_INCREF(Py_None); - return Py_None; - } - - return CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType, - Pkg.CurrentVer()); + Py_INCREF(Py_None); + return Py_None; } - else if (strcmp("Section",Name) == 0) - return Safe_FromString(Pkg.Section()); - else if (strcmp("RevDependsList",Name) == 0) - return CppOwnedPyObject_NEW<RDepListStruct>(Owner,&RDepListType, - Pkg.RevDependsList()); - else if (strcmp("ProvidesList",Name) == 0) - return CreateProvides(Owner,Pkg.ProvidesList()); - else if (strcmp("SelectedState",Name) == 0) - return Py_BuildValue("i",Pkg->SelectedState); - else if (strcmp("InstState",Name) == 0) - return Py_BuildValue("i",Pkg->InstState); - else if (strcmp("CurrentState",Name) == 0) - return Py_BuildValue("i",Pkg->CurrentState); - else if (strcmp("ID",Name) == 0) - return Py_BuildValue("i",Pkg->ID); - else if (strcmp("Auto",Name) == 0) - return Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Auto) != 0); - else if (strcmp("Essential",Name) == 0) - return Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Essential) != 0); - else if (strcmp("Important",Name) == 0) - return Py_BuildValue("i",(Pkg->Flags & pkgCache::Flag::Important) != 0); - - PyErr_SetString(PyExc_AttributeError,Name); - return 0; + return CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type, + Pkg.CurrentVer()); } +static PyGetSetDef PackageGetSet[] = { + {"name",PackageGetName}, + {"section",PackageGetSection}, + {"rev_depends_list",PackageGetRevDependsList}, + {"provides_list",PackageGetProvidesList}, + {"selected_state",PackageGetSelectedState}, + {"inst_state",PackageGetInstState}, + {"current_state",PackageGetCurrentState}, + {"id",PackageGetID}, + {"auto",PackageGetAuto}, + {"essential",PackageGetEssential}, + {"important",PackageGetImportant}, + {"version_list",PackageGetVersionList}, + {"current_ver",PackageGetCurrentVer}, + #ifdef COMPAT_0_7 + {"Name",PackageGetName}, + {"Section",PackageGetSection}, + {"RevDependsList",PackageGetRevDependsList}, + {"ProvidesList",PackageGetProvidesList}, + {"SelectedState",PackageGetSelectedState}, + {"InstState",PackageGetInstState}, + {"CurrentState",PackageGetCurrentState}, + {"ID",PackageGetID}, + {"Auto",PackageGetAuto}, + {"Essential",PackageGetEssential}, + {"Important",PackageGetImportant}, + {"VersionList",PackageGetVersionList}, + {"CurrentVer",PackageGetCurrentVer}, + #endif + {} +}; + static PyObject *PackageRepr(PyObject *Self) { pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); - char S[300]; - snprintf(S,sizeof(S),"<pkgCache::Package object: Name:'%s' Section: '%s'" - " ID:%u Flags:0x%lX>", - Pkg.Name(),Pkg.Section(),Pkg->ID,Pkg->Flags); - return PyString_FromString(S); + return PyString_FromFormat("<%s object: name:'%s' section: " + "'%s' id:%u>", Self->ob_type->tp_name, + Pkg.Name(), (Pkg.Section() ? Pkg.Section() : ""), + Pkg->ID); } -PyTypeObject PackageType = +PyTypeObject PyPackage_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgCache::Package", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Package", // tp_name sizeof(CppOwnedPyObject<pkgCache::PkgIterator>), // tp_basicsize 0, // tp_itemsize // Methods CppOwnedDealloc<pkgCache::PkgIterator>, // tp_dealloc 0, // tp_print - PackageAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare PackageRepr, // tp_repr @@ -421,62 +571,84 @@ PyTypeObject PackageType = 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 | Py_TPFLAGS_HAVE_GC, // tp_flags + "Package Object", // tp_doc + CppOwnedTraverse<pkgCache::PkgIterator>, // tp_traverse + CppOwnedClear<pkgCache::PkgIterator>,// tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + PackageGetSet, // tp_getset }; - /*}}}*/ -// Description Class /*{{{*/ -// --------------------------------------------------------------------- -static PyObject *DescriptionAttr(PyObject *Self,char *Name) + +#define Description_MkGet(PyFunc,Ret) static PyObject \ + *PyFunc(PyObject *Self,void*) { \ + pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); \ + return Ret; } + +Description_MkGet(DescriptionGetLanguageCode, + PyString_FromString(Desc.LanguageCode())) +Description_MkGet(DescriptionGetMd5,Safe_FromString(Desc.md5())) +#undef Description_MkGet + +static PyObject *DescriptionGetFileList(PyObject *Self,void*) { pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); PyObject *Owner = GetOwner<pkgCache::DescIterator>(Self); - if (strcmp("LanguageCode",Name) == 0) - return PyString_FromString(Desc.LanguageCode()); - else if (strcmp("md5",Name) == 0) - return Safe_FromString(Desc.md5()); - else if (strcmp("FileList",Name) == 0) + /* 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++) { - /* 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 = CppOwnedPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PackageFileType,I.File()); - Obj = Py_BuildValue("Nl",DescFile,I.Index()); - PyList_Append(List,Obj); - Py_DECREF(Obj); - } - return List; + PyObject *DescFile; + PyObject *Obj; + DescFile = CppOwnedPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File()); + Obj = Py_BuildValue("Nl",DescFile,I.Index()); + PyList_Append(List,Obj); + Py_DECREF(Obj); } - PyErr_SetString(PyExc_AttributeError,Name); - return 0; + return List; } +static PyGetSetDef DescriptionGetSet[] = { + {"language_code",DescriptionGetLanguageCode}, + {"md5",DescriptionGetMd5}, + {"file_list",DescriptionGetFileList}, + #ifdef COMPAT_0_7 + {"LanguageCode",DescriptionGetLanguageCode}, + {"FileList",DescriptionGetFileList}, + #endif + {} +}; + static PyObject *DescriptionRepr(PyObject *Self) { pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); - - char S[300]; - snprintf(S,sizeof(S), - "<pkgCache::Description object: language_code:'%s' md5:'%s' ", - Desc.LanguageCode(), Desc.md5()); - return PyString_FromString(S); + return PyString_FromFormat("<%s object: language_code:'%s' md5:'%s' ", + Self->ob_type->tp_name, Desc.LanguageCode(), + Desc.md5()); } -PyTypeObject DescriptionType = +PyTypeObject PyDescription_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgCache::DescIterator", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Description", // tp_name sizeof(CppOwnedPyObject<pkgCache::DescIterator>), // tp_basicsize 0, // tp_itemsize // Methods CppOwnedDealloc<pkgCache::DescIterator>, // tp_dealloc 0, // tp_print - DescriptionAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare DescriptionRepr, // tp_repr @@ -484,6 +656,22 @@ PyTypeObject DescriptionType = 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 | Py_TPFLAGS_HAVE_GC, // tp_flags + "apt_pkg.Description Object", // tp_doc + CppOwnedTraverse<pkgCache::DescIterator>, // tp_traverse + CppOwnedClear<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 /*{{{*/ @@ -523,7 +711,7 @@ static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver, { PyObject *Obj; if (AsObj == true) - Obj = CppOwnedPyObject_NEW<pkgCache::DepIterator>(Owner,&DependencyType, + Obj = CppOwnedPyObject_NEW<pkgCache::DepIterator>(Owner,&PyDependency_Type, Start); else { @@ -553,63 +741,86 @@ static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver, return Dict; } -static PyObject *VersionAttr(PyObject *Self,char *Name) -{ +static inline pkgCache::VerIterator Version_GetVer(PyObject *Self) { + return GetCpp<pkgCache::VerIterator>(Self); +} + +// Version attributes. +static PyObject *VersionGetVerStr(PyObject *Self, void*) { + return PyString_FromString(Version_GetVer(Self).VerStr()); +} +static PyObject *VersionGetSection(PyObject *Self, void*) { + return Safe_FromString(Version_GetVer(Self).Section()); +} +static PyObject *VersionGetArch(PyObject *Self, void*) { + return Safe_FromString(Version_GetVer(Self).Arch()); +} +static PyObject *VersionGetFileList(PyObject *Self, void*) { pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self); - - if (strcmp("VerStr",Name) == 0) - return PyString_FromString(Ver.VerStr()); - else if (strcmp("Section",Name) == 0) - return Safe_FromString(Ver.Section()); - else if (strcmp("Arch",Name) == 0) - return Safe_FromString(Ver.Arch()); - else if (strcmp("FileList",Name) == 0) + PyObject *List = PyList_New(0); + for (pkgCache::VerFileIterator I = Ver.FileList(); I.end() == false; I++) { - /* 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::VerFileIterator I = Ver.FileList(); I.end() == false; I++) - { - PyObject *PkgFile; - PyObject *Obj; - PkgFile = CppOwnedPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PackageFileType,I.File()); - Obj = Py_BuildValue("Nl",PkgFile,I.Index()); - PyList_Append(List,Obj); - Py_DECREF(Obj); - } - return List; - } - else if (strcmp("DependsListStr",Name) == 0) - return MakeDepends(Owner,Ver,false); - else if (strcmp("DependsList",Name) == 0) - return MakeDepends(Owner,Ver,true); - else if (strcmp("ParentPkg",Name) == 0) - return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType, - Ver.ParentPkg()); - else if (strcmp("ProvidesList",Name) == 0) - return CreateProvides(Owner,Ver.ProvidesList()); - else if (strcmp("Size",Name) == 0) - return Py_BuildValue("i",Ver->Size); - else if (strcmp("InstalledSize",Name) == 0) - return Py_BuildValue("i",Ver->InstalledSize); - else if (strcmp("Hash",Name) == 0) - return Py_BuildValue("i",Ver->Hash); - else if (strcmp("ID",Name) == 0) - return Py_BuildValue("i",Ver->ID); - else if (strcmp("Priority",Name) == 0) - return Py_BuildValue("i",Ver->Priority); - else if (strcmp("PriorityStr",Name) == 0) - return Safe_FromString(Ver.PriorityType()); - else if (strcmp("Downloadable", Name) == 0) - return Py_BuildValue("b", Ver.Downloadable()); - else if (strcmp("TranslatedDescription", Name) == 0) { - return CppOwnedPyObject_NEW<pkgCache::DescIterator>(Owner, - &DescriptionType, - Ver.TranslatedDescription()); + PyObject *PkgFile; + PyObject *Obj; + PkgFile = CppOwnedPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File()); + Obj = Py_BuildValue("Nl",PkgFile,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 CppOwnedPyObject_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 Py_BuildValue("i", Version_GetVer(Self)->Size); +} +static PyObject *VersionGetInstalledSize(PyObject *Self, void*) { + return Py_BuildValue("i", Version_GetVer(Self)->InstalledSize); +} +static PyObject *VersionGetHash(PyObject *Self, void*) { + return Py_BuildValue("i", Version_GetVer(Self)->Hash); +} +static PyObject *VersionGetID(PyObject *Self, void*) { + return Py_BuildValue("i", Version_GetVer(Self)->ID); +} +static PyObject *VersionGetPriority(PyObject *Self, void*) { + return Py_BuildValue("i",Version_GetVer(Self)->Priority); +} +static PyObject *VersionGetPriorityStr(PyObject *Self, void*) { + return Safe_FromString(Version_GetVer(Self).PriorityType()); +} +static PyObject *VersionGetDownloadable(PyObject *Self, void*) { + return Py_BuildValue("b",Version_GetVer(Self).Downloadable()); +} +static PyObject *VersionGetTranslatedDescription(PyObject *Self, void*) { + pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self); + return CppOwnedPyObject_NEW<pkgCache::DescIterator>(Owner, + &PyDescription_Type, + Ver.TranslatedDescription()); +} + #if 0 // FIXME: enable once pkgSourceList is stored somewhere +static PyObject *VersionGetIsTrusted(PyObject *Self, void*) { else if (strcmp("IsTrusted", Name) == 0) { pkgSourceList Sources; @@ -622,37 +833,73 @@ static PyObject *VersionAttr(PyObject *Self,char *Name) } return Py_BuildValue("b", true); } +} #endif - PyErr_SetString(PyExc_AttributeError,Name); - return 0; -} +#define NOTNULL(x) (x ? x : "") static PyObject *VersionRepr(PyObject *Self) { pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self); - - char S[300]; - snprintf(S,sizeof(S),"<pkgCache::Version object: Pkg:'%s' Ver:'%s' " - "Section:'%s' Arch:'%s' Size:%lu ISize:%lu Hash:%u " - "ID:%u Priority:%u>", - Ver.ParentPkg().Name(),Ver.VerStr(),Ver.Section(),Ver.Arch(), - (unsigned long)Ver->Size,(unsigned long)Ver->InstalledSize, - Ver->Hash,Ver->ID,Ver->Priority); - return PyString_FromString(S); + 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 PyGetSetDef VersionGetSet[] = { + {"arch",VersionGetArch}, + {"depends_list",VersionGetDependsList}, + {"depends_list_str",VersionGetDependsListStr}, + {"downloadable",VersionGetDownloadable}, + {"file_list",VersionGetFileList}, + {"hash",VersionGetHash}, + {"id",VersionGetID}, + {"installed_size",VersionGetInstalledSize}, + {"parent_pkg",VersionGetParentPkg}, + {"priority",VersionGetPriority}, + {"priority_str",VersionGetPriorityStr}, + {"provides_list",VersionGetProvidesList}, + {"section",VersionGetSection}, + {"size",VersionGetSize}, + {"translated_description",VersionGetTranslatedDescription}, + {"ver_str",VersionGetVerStr}, +#ifdef COMPAT_0_7 + {"Arch",VersionGetArch}, + {"DependsList",VersionGetDependsList}, + {"DependsListStr",VersionGetDependsListStr}, + {"Downloadable",VersionGetDownloadable}, + {"FileList",VersionGetFileList}, + {"Hash",VersionGetHash}, + {"ID",VersionGetID}, + {"InstalledSize",VersionGetInstalledSize}, + {"ParentPkg",VersionGetParentPkg}, + {"Priority",VersionGetPriority}, + {"PriorityStr",VersionGetPriorityStr}, + {"ProvidesList",VersionGetProvidesList}, + {"Section",VersionGetSection}, + {"Size",VersionGetSize}, + {"TranslationDescription",VersionGetTranslatedDescription}, + {"VerStr",VersionGetVerStr}, +#endif + {} +}; -PyTypeObject VersionType = +PyTypeObject PyVersion_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgCache::VerIterator", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Version", // tp_name sizeof(CppOwnedPyObject<pkgCache::VerIterator>), // tp_basicsize 0, // tp_itemsize // Methods CppOwnedDealloc<pkgCache::VerIterator>, // tp_dealloc 0, // tp_print - VersionAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare VersionRepr, // tp_repr @@ -660,96 +907,195 @@ PyTypeObject VersionType = 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 | Py_TPFLAGS_HAVE_GC, // tp_flags + "Version Object", // tp_doc + CppOwnedTraverse<pkgCache::VerIterator>, // tp_traverse + CppOwnedClear<pkgCache::VerIterator>,// tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + VersionGetSet, // tp_getset }; /*}}}*/ // PackageFile Class /*{{{*/ // --------------------------------------------------------------------- -static PyObject *PackageFileAttr(PyObject *Self,char *Name) -{ - pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); -// PyObject *Owner = GetOwner<pkgCache::PkgFileIterator>(Self); - - if (strcmp("FileName",Name) == 0) - return Safe_FromString(File.FileName()); - else if (strcmp("Archive",Name) == 0) - return Safe_FromString(File.Archive()); - else if (strcmp("Component",Name) == 0) - return Safe_FromString(File.Component()); - else if (strcmp("Version",Name) == 0) - return Safe_FromString(File.Version()); - else if (strcmp("Origin",Name) == 0) - return Safe_FromString(File.Origin()); - else if (strcmp("Label",Name) == 0) - return Safe_FromString(File.Label()); - else if (strcmp("Architecture",Name) == 0) - return Safe_FromString(File.Architecture()); - else if (strcmp("Site",Name) == 0) - return Safe_FromString(File.Site()); - else if (strcmp("IndexType",Name) == 0) - return Safe_FromString(File.IndexType()); - else if (strcmp("Size",Name) == 0) - return Py_BuildValue("i",File->Size); - else if (strcmp("NotSource",Name) == 0) - return Py_BuildValue("i",(File->Flags & pkgCache::Flag::NotSource) != 0); - else if (strcmp("NotAutomatic",Name) == 0) - return Py_BuildValue("i",(File->Flags & pkgCache::Flag::NotAutomatic) != 0); - else if (strcmp("ID",Name) == 0) - return Py_BuildValue("i",File->ID); - - PyErr_SetString(PyExc_AttributeError,Name); - return 0; +static PyObject *PackageFile_GetFileName(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Safe_FromString(File.FileName()); } -static PyObject *PackageFileRepr(PyObject *Self) +static PyObject *PackageFile_GetArchive(PyObject *Self,void*) { - pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Safe_FromString(File.Archive()); +} - char S[300]; - snprintf(S,sizeof(S),"<pkgCache::PackageFile object: " - "File:'%s' a=%s,c=%s,v=%s,o=%s,l=%s " - "Arch='%s' Site='%s' IndexType='%s' Size=%lu " - "Flags=0x%lX ID:%u>", - File.FileName(),File.Archive(),File.Component(),File.Version(), - File.Origin(),File.Label(),File.Architecture(),File.Site(), - File.IndexType(),File->Size,File->Flags,File->ID); - return PyString_FromString(S); +static PyObject *PackageFile_GetComponent(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Safe_FromString(File.Component()); } -PyTypeObject PackageFileType = +static PyObject *PackageFile_GetVersion(PyObject *Self,void*) { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgCache::PkgFileIterator", // tp_name - sizeof(CppOwnedPyObject<pkgCache::PkgFileIterator>), // tp_basicsize - 0, // tp_itemsize - // Methods - CppOwnedDealloc<pkgCache::PkgFileIterator>, // tp_dealloc - 0, // tp_print - PackageFileAttr, // 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 + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Safe_FromString(File.Version()); +} + +static PyObject *PackageFile_GetOrigin(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Safe_FromString(File.Origin()); +} + +static PyObject *PackageFile_GetLabel(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Safe_FromString(File.Label()); +} + +static PyObject *PackageFile_GetArchitecture(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Safe_FromString(File.Architecture()); +} + +static PyObject *PackageFile_GetSite(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Safe_FromString(File.Site()); +} + +static PyObject *PackageFile_GetIndexType(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Safe_FromString(File.IndexType()); +} +static PyObject *PackageFile_GetSize(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Py_BuildValue("i",File->Size); +} + +static PyObject *PackageFile_GetNotSource(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Py_BuildValue("i",(File->Flags & pkgCache::Flag::NotSource) != 0); +} +static PyObject *PackageFile_GetNotAutomatic(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Py_BuildValue("i",(File->Flags & pkgCache::Flag::NotSource) != 0); +} + +static PyObject *PackageFile_GetID(PyObject *Self,void*) +{ + pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self); + return Py_BuildValue("i",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[] = { + {(char*)"architecture",PackageFile_GetArchitecture}, + {(char*)"archive",PackageFile_GetArchive}, + {(char*)"component",PackageFile_GetComponent}, + {(char*)"filename",PackageFile_GetFileName}, + {(char*)"id",PackageFile_GetID}, + {(char*)"index_type",PackageFile_GetIndexType}, + {(char*)"label",PackageFile_GetLabel}, + {(char*)"not_automatic",PackageFile_GetNotAutomatic}, + {(char*)"not_source",PackageFile_GetNotSource}, + {(char*)"origin",PackageFile_GetOrigin}, + {(char*)"site",PackageFile_GetSite}, + {(char*)"size",PackageFile_GetSize}, + {(char*)"version",PackageFile_GetVersion}, + #ifdef COMPAT_0_7 + {"Architecture",PackageFile_GetArchitecture}, + {"Archive",PackageFile_GetArchive}, + {"Component",PackageFile_GetComponent}, + {"FileName",PackageFile_GetFileName}, + {"ID",PackageFile_GetID}, + {"IndexType",PackageFile_GetIndexType}, + {"Label",PackageFile_GetLabel}, + {"NotAutomatic",PackageFile_GetNotAutomatic}, + {"NotSource",PackageFile_GetNotSource}, + {"Origin",PackageFile_GetOrigin}, + {"Site",PackageFile_GetSite}, + {"Size",PackageFile_GetSize}, + {"Version",PackageFile_GetVersion}, + #endif + {} }; +PyTypeObject PyPackageFile_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.PackageFile", // tp_name + sizeof(CppOwnedPyObject<pkgCache::PkgFileIterator>), // tp_basicsize + 0, // tp_itemsize + CppOwnedDealloc<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 + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags + "apt_pkg.PackageFile Object", // tp_doc + CppOwnedTraverse<pkgCache::PkgFileIterator>, // tp_traverse + CppOwnedClear<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); - char S[300]; - snprintf(S,sizeof(S),"<pkgCache::Dependency object: " - "Pkg:'%s' Ver:'%s' Comp:'%s'>", - Dep.TargetPkg().Name(), - (Dep.TargetVer() == 0?"":Dep.TargetVer()), - Dep.CompType()); - return PyString_FromString(S); + 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 *DepSmartTargetPkg(PyObject *Self,PyObject *Args) @@ -767,7 +1113,7 @@ static PyObject *DepSmartTargetPkg(PyObject *Self,PyObject *Args) return Py_None; } - return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType,P); + return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type,P); } static PyObject *DepAllTargets(PyObject *Self,PyObject *Args) @@ -783,7 +1129,7 @@ static PyObject *DepAllTargets(PyObject *Self,PyObject *Args) for (pkgCache::Version **I = Vers; *I != 0; I++) { PyObject *Obj; - Obj = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType, + Obj = CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type, pkgCache::VerIterator(*Dep.Cache(),*I)); PyList_Append(List,Obj); Py_DECREF(Obj); @@ -793,65 +1139,136 @@ static PyObject *DepAllTargets(PyObject *Self,PyObject *Args) static PyMethodDef DependencyMethods[] = { + {"smart_target_pkg",DepSmartTargetPkg,METH_VARARGS,"Returns the natural Target or None"}, + {"all_targets",DepAllTargets,METH_VARARGS,"Returns all possible Versions that match this dependency"}, +#ifdef COMPAT_0_7 {"SmartTargetPkg",DepSmartTargetPkg,METH_VARARGS,"Returns the natural Target or None"}, {"AllTargets",DepAllTargets,METH_VARARGS,"Returns all possible Versions that match this dependency"}, +#endif {} }; // Dependency Class /*{{{*/ // --------------------------------------------------------------------- -static PyObject *DependencyAttr(PyObject *Self,char *Name) +static PyObject *DependencyGetTargetVer(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + if (Dep->Version == 0) + return PyString_FromString(""); + return PyString_FromString(Dep.TargetVer()); +} + +static PyObject *DependencyGetTargetPkg(PyObject *Self,void*) { pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self); + return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type, + Dep.TargetPkg()); +} - if (strcmp("TargetVer",Name) == 0) - { - if (Dep->Version == 0) - return PyString_FromString(""); - return PyString_FromString(Dep.TargetVer()); - } - else if (strcmp("TargetPkg",Name) == 0) - return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType, - Dep.TargetPkg()); - else if (strcmp("ParentVer",Name) == 0) - return CppOwnedPyObject_NEW<pkgCache::VerIterator>(Owner,&VersionType, - Dep.ParentVer()); - else if (strcmp("ParentPkg",Name) == 0) - return CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PackageType, Dep.ParentPkg()); - else if (strcmp("CompType",Name) == 0) - return PyString_FromString(Dep.CompType()); - else if (strcmp("DepType",Name) == 0) - return PyString_FromString(Dep.DepType()); - else if (strcmp("UntranslatedDepType",Name) == 0) - return PyString_FromString(UntranslatedDepTypes[Dep->Type]); - else if (strcmp("DepTypeEnum",Name) == 0) - return Py_BuildValue("i", Dep->Type); - else if (strcmp("ID",Name) == 0) - return Py_BuildValue("i",Dep->ID); - - return Py_FindMethod(DependencyMethods,Self,Name); -} - -PyTypeObject DependencyType = -{ - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgCache::DepIterator", // tp_name +static PyObject *DependencyGetParentVer(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self); + return CppOwnedPyObject_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 CppOwnedPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type, + Dep.ParentPkg()); +} + +static PyObject *DependencyGetCompType(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return PyString_FromString(Dep.CompType()); +} + +static PyObject *DependencyGetDepType(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return PyString_FromString(Dep.DepType()); +} + +static PyObject *DependencyGetDepTypeUntranslated(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return PyString_FromString(UntranslatedDepTypes[Dep->Type]); +} + +static PyObject *DependencyGetDepTypeEnum(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return Py_BuildValue("i", Dep->Type); +} + +static PyObject *DependencyGetID(PyObject *Self,void*) +{ + pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self); + return Py_BuildValue("i",Dep->ID); +} + +static PyGetSetDef DependencyGetSet[] = { + {"comp_type",DependencyGetCompType}, + {"dep_type",DependencyGetDepType}, + {"dep_type_untranslated",DependencyGetDepTypeUntranslated}, + {"dep_type_enum",DependencyGetDepTypeEnum}, + {"id",DependencyGetID}, + {"parent_pkg",DependencyGetParentPkg}, + {"parent_ver",DependencyGetParentVer}, + {"target_pkg",DependencyGetTargetPkg}, + {"target_ver",DependencyGetTargetVer}, +#ifdef COMPAT_0_7 + {"CompType",DependencyGetCompType}, + {"DepType",DependencyGetDepType}, + {"ID",DependencyGetID}, + {"ParentPkg",DependencyGetParentPkg}, + {"ParentVer",DependencyGetParentVer}, + {"TargetPkg",DependencyGetTargetPkg}, + {"TargetVer",DependencyGetTargetVer}, +#endif + {} +}; + + +PyTypeObject PyDependency_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Dependency", // tp_name sizeof(CppOwnedPyObject<pkgCache::DepIterator>), // tp_basicsize 0, // tp_itemsize // Methods CppOwnedDealloc<pkgCache::DepIterator>, // tp_dealloc 0, // tp_print - DependencyAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare - DependencyRepr, // tp_repr + DependencyRepr, // 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 | Py_TPFLAGS_HAVE_GC, // tp_flags + "Dependency Object", // tp_doc + CppOwnedTraverse<pkgCache::DepIterator>, // tp_traverse + CppOwnedClear<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 }; /*}}}*/ @@ -890,7 +1307,7 @@ static PyObject *RDepListItem(PyObject *iSelf,Py_ssize_t Index) } return CppOwnedPyObject_NEW<pkgCache::DepIterator>(GetOwner<RDepListStruct>(iSelf), - &DependencyType,Self.Iter); + &PyDependency_Type,Self.Iter); } static PySequenceMethods RDepListSeq = @@ -904,11 +1321,10 @@ static PySequenceMethods RDepListSeq = 0 // assign slice }; -PyTypeObject RDepListType = +PyTypeObject PyDependencyList_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgCache::DepIterator", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.DependencyList", // tp_name sizeof(CppOwnedPyObject<RDepListStruct>), // tp_basicsize 0, // tp_itemsize // Methods @@ -922,55 +1338,25 @@ PyTypeObject RDepListType = &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 Object", // tp_doc + CppOwnedTraverse<RDepListStruct>, // tp_traverse + CppOwnedClear<RDepListStruct>, // tp_clear }; /*}}}*/ - +#ifdef COMPAT_0_7 PyObject *TmpGetCache(PyObject *Self,PyObject *Args) { - PyObject *pyCallbackInst = 0; - if (PyArg_ParseTuple(Args, "|O", &pyCallbackInst) == 0) - return 0; - - if (_system == 0) { - PyErr_SetString(PyExc_ValueError,"_system not initialized"); - return 0; - } - - pkgCacheFile *Cache = new pkgCacheFile(); - - 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(); - } - - CppOwnedPyObject<pkgCacheFile*> *CacheFileObj = - CppOwnedPyObject_NEW<pkgCacheFile*>(0,&PkgCacheFileType, Cache); - - CppOwnedPyObject<pkgCache *> *CacheObj = - CppOwnedPyObject_NEW<pkgCache *>(CacheFileObj,&PkgCacheType, - (pkgCache *)(*Cache)); - - //Py_DECREF(CacheFileObj); - return CacheObj; + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetCache() is deprecated. " + "Please see apt_pkg.Cache() for the replacement.", 1); + return PkgCacheNew(&PyCache_Type,Args,0); } +#endif diff --git a/python/cdrom.cc b/python/cdrom.cc index 0831548e..4195c9cb 100644 --- a/python/cdrom.cc +++ b/python/cdrom.cc @@ -1,10 +1,26 @@ -// Description /*{{{*/ -// $Id: cdrom.cc,v 1.1 2003/06/03 03:03:23 mvo Exp $ -/* ###################################################################### - - Cdrom - Wrapper for the apt-cdrom support - - ##################################################################### */ +/* 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" @@ -12,99 +28,142 @@ #include <apt-pkg/cdrom.h> - -struct PkgCdromStruct +static char *cdrom_add_doc = + "add(progress: apt_pkg.CdromProgress) -> bool\n\n" + "Add the given CD-ROM to the sources.list. Returns True on success, may\n" + "raise an error on failure or return False."; +static PyObject *cdrom_add(PyObject *Self,PyObject *Args) { - pkgCdrom cdrom; -}; + pkgCdrom &Cdrom = GetCpp<pkgCdrom>(Self); -static PyObject *PkgCdromAdd(PyObject *Self,PyObject *Args) -{ - PkgCdromStruct &Struct = GetCpp<PkgCdromStruct>(Self); + PyObject *pyCdromProgressInst = 0; + if (PyArg_ParseTuple(Args, "O", &pyCdromProgressInst) == 0) { + return 0; + } - PyObject *pyCdromProgressInst = 0; - if (PyArg_ParseTuple(Args, "O", &pyCdromProgressInst) == 0) { - return 0; - } + PyCdromProgress progress; + progress.setCallbackInst(pyCdromProgressInst); - PyCdromProgress progress; - progress.setCallbackInst(pyCdromProgressInst); + bool res = Cdrom.Add(&progress); - bool res = Struct.cdrom.Add(&progress); + return HandleErrors(PyBool_FromLong(res)); +} - return HandleErrors(Py_BuildValue("b", 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 identity as a\n" + "string. Otherwise, return None or raise an error."; +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); + + string ident; + bool res = Cdrom.Ident(ident, &progress); + + if (res) + return CppPyString(ident); + else { + Py_INCREF(Py_None); + return HandleErrors(Py_None); + } } -static PyObject *PkgCdromIdent(PyObject *Self,PyObject *Args) +#ifdef COMPAT_0_7 +static PyObject *cdrom_ident_old(PyObject *Self,PyObject *Args) { - PkgCdromStruct &Struct = GetCpp<PkgCdromStruct>(Self); + pkgCdrom &Cdrom = GetCpp<pkgCdrom>(Self); - PyObject *pyCdromProgressInst = 0; - if (PyArg_ParseTuple(Args, "O", &pyCdromProgressInst) == 0) { - return 0; - } + PyObject *pyCdromProgressInst = 0; + if (PyArg_ParseTuple(Args, "O", &pyCdromProgressInst) == 0) { + return 0; + } - PyCdromProgress progress; - progress.setCallbackInst(pyCdromProgressInst); + PyCdromProgress progress; + progress.setCallbackInst(pyCdromProgressInst); - string ident; - bool res = Struct.cdrom.Ident(ident, &progress); + string ident; + bool res = Cdrom.Ident(ident, &progress); - PyObject *result = Py_BuildValue("(bs)", res, ident.c_str()); + PyObject *result = Py_BuildValue("(bs)", res, ident.c_str()); - return HandleErrors(result); + return HandleErrors(result); } - - -static PyMethodDef PkgCdromMethods[] = -{ - {"Add",PkgCdromAdd,METH_VARARGS,"Add a cdrom"}, - {"Ident",PkgCdromIdent,METH_VARARGS,"Ident a cdrom"}, - {} +#endif + +static PyMethodDef cdrom_methods[] = { + {"add",cdrom_add,METH_VARARGS,cdrom_add_doc}, + {"ident",cdrom_ident,METH_VARARGS,cdrom_ident_doc}, +#ifdef COMPAT_0_7 + {"Add",cdrom_add,METH_VARARGS,"Add(progress) -> Add a cdrom"}, + {"Ident",cdrom_ident_old,METH_VARARGS,"Ident(progress) -> Ident a cdrom"}, +#endif + {} }; - -static PyObject *CdromAttr(PyObject *Self,char *Name) +static PyObject *cdrom_new(PyTypeObject *type,PyObject *Args,PyObject *kwds) { - PkgCdromStruct &Struct = GetCpp<PkgCdromStruct>(Self); - - return Py_FindMethod(PkgCdromMethods,Self,Name); + return CppPyObject_NEW<pkgCdrom>(type); } - - - -PyTypeObject PkgCdromType = -{ - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "Cdrom", // tp_name - sizeof(CppOwnedPyObject<PkgCdromStruct>), // tp_basicsize - 0, // tp_itemsize - // Methods - CppOwnedDealloc<PkgCdromStruct>, // tp_dealloc - 0, // tp_print - CdromAttr, // 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 +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 + 0, // 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 }; +#ifdef COMPAT_0_7 PyObject *GetCdrom(PyObject *Self,PyObject *Args) { - pkgCdrom *cdrom = new pkgCdrom(); - - CppOwnedPyObject<pkgCdrom> *CdromObj = - CppOwnedPyObject_NEW<pkgCdrom>(0,&PkgCdromType, *cdrom); - - return CdromObj; + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetCdrom() is deprecated. " + "Please see apt_pkg.Cdrom() for the replacement.", 1); + return cdrom_new(&PyCdrom_Type,Args,0); } - - - - - /*}}}*/ +#endif diff --git a/python/configuration.cc b/python/configuration.cc index 21f70bc1..b2367c3e 100644 --- a/python/configuration.cc +++ b/python/configuration.cc @@ -5,11 +5,8 @@ Configuration - Binding for the configuration object. - There are three seperate classes.. - Configuration - A stand alone configuration instance - ConfigurationPtr - A pointer to a configuration instance, used only - for the global instance (_config) - ConfigurationSub - A subtree - has a reference to its owner. + 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. @@ -25,33 +22,13 @@ #include <Python.h> /*}}}*/ -/* If we create a sub tree then it is of this type, the Owner is used - to manage reference counting. */ -struct SubConfiguration : public CppPyObject<Configuration> -{ - PyObject *Owner; -}; - - /*}}}*/ -// CnfSubFree - Free a sub configuration /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void CnfSubFree(PyObject *Obj) -{ - SubConfiguration *Self = (SubConfiguration *)Obj; - Py_DECREF(Self->Owner); - CppDealloc<Configuration>(Obj); -} - /*}}}*/ // GetSelf - Convert PyObject to Configuration /*{{{*/ // --------------------------------------------------------------------- /* */ static inline Configuration &GetSelf(PyObject *Obj) { - if (Obj->ob_type == &ConfigurationPtrType) - return *GetCpp<Configuration *>(Obj); - return GetCpp<Configuration>(Obj); + return *GetCpp<Configuration*>(Obj); } /*}}}*/ @@ -128,6 +105,11 @@ static PyObject *CnfExists(PyObject *Self,PyObject *Args) return Py_BuildValue("i",(int)GetSelf(Self).Exists(Name)); } +static int CnfContains(PyObject *Self,PyObject *Arg) +{ + return (int)GetSelf(Self).Exists(PyString_AsString(Arg)); +} + static char *doc_Clear = "Clear(Name) -> None"; static PyObject *CnfClear(PyObject *Self,PyObject *Args) { @@ -155,12 +137,8 @@ static PyObject *CnfSubTree(PyObject *Self,PyObject *Args) return 0; } - // Create a new sub configuration. - SubConfiguration *New = PyObject_NEW(SubConfiguration,&ConfigurationSubType); - new (&New->Object) Configuration(Itm); - New->Owner = Self; - Py_INCREF(Self); - return New; + return CppOwnedPyObject_NEW<Configuration*>(Self,&PyConfiguration_Type, + new Configuration(Itm)); } // Return a list of items at a specific level @@ -174,6 +152,8 @@ static PyObject *CnfList(PyObject *Self,PyObject *Args) // 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; @@ -238,7 +218,7 @@ static PyObject *CnfKeys(PyObject *Self,PyObject *Args) const Configuration::Item *Root = 0; if (RootName == 0) Stop = 0; - if (Top != 0) + if (Top != 0 && GetSelf(Self).Tree(0)) Root = GetSelf(Self).Tree(0)->Parent; for (; Top != 0;) { @@ -383,7 +363,11 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) 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) { @@ -448,13 +432,26 @@ PyObject *ParseCommandLine(PyObject *Self,PyObject *Args) 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}, +#ifdef COMPAT_0_7 {"Find",CnfFind,METH_VARARGS,doc_Find}, {"FindFile",CnfFindFile,METH_VARARGS,doc_FindFile}, {"FindDir",CnfFindDir,METH_VARARGS,doc_FindDir}, {"FindI",CnfFindI,METH_VARARGS,doc_FindI}, {"FindB",CnfFindB,METH_VARARGS,doc_FindB}, - - // Others {"Set",CnfSet,METH_VARARGS,doc_Set}, {"Exists",CnfExists,METH_VARARGS,doc_Exists}, {"SubTree",CnfSubTree,METH_VARARGS,doc_SubTree}, @@ -462,81 +459,67 @@ static PyMethodDef CnfMethods[] = {"ValueList",CnfValueList,METH_VARARGS,doc_ValueList}, {"MyTag",CnfMyTag,METH_VARARGS,doc_MyTag}, {"Clear",CnfClear,METH_VARARGS,doc_Clear}, - +#endif // 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}, {} }; -// CnfGetAttr - Get an attribute - variable/method /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static PyObject *CnfGetAttr(PyObject *Self,char *Name) -{ - return Py_FindMethod(CnfMethods,Self,Name); +static PyObject *CnfNew(PyTypeObject *type, PyObject *args, PyObject *kwds) { + char *kwlist[] = {NULL}; + if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0) + return 0; + return CppOwnedPyObject_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}; -PyTypeObject ConfigurationType = -{ - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "Configuration", // tp_name - sizeof(CppPyObject<Configuration>), // tp_basicsize - 0, // tp_itemsize - // Methods - CppDealloc<Configuration>, // tp_dealloc - 0, // tp_print - CnfGetAttr, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - &ConfigurationMap, // tp_as_mapping - 0, // tp_hash -}; - -PyTypeObject ConfigurationPtrType = -{ - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "ConfigurationPtr", // tp_name - sizeof(CppPyObject<Configuration *>), // tp_basicsize - 0, // tp_itemsize - // Methods - (destructor)PyObject_Free, // tp_dealloc - 0, // tp_print - CnfGetAttr, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - &ConfigurationMap, // tp_as_mapping - 0, // tp_hash -}; - -PyTypeObject ConfigurationSubType = +PyTypeObject PyConfiguration_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "ConfigurationSub", // tp_name - sizeof(SubConfiguration), // tp_basicsize + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.Configuration", // tp_name + sizeof(CppOwnedPyObject<Configuration*>), // tp_basicsize 0, // tp_itemsize // Methods - CnfSubFree, // tp_dealloc + CppOwnedDeallocPtr<Configuration*>, // tp_dealloc 0, // tp_print - CnfGetAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number - 0, // tp_as_sequence + &ConfigurationSeq, // tp_as_sequence &ConfigurationMap, // 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), + "Configuration Object", // 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 index 7edb7b59..e78b9f4e 100644 --- a/python/depcache.cc +++ b/python/depcache.cc @@ -62,8 +62,6 @@ static PyObject *PkgDepCacheInit(PyObject *Self,PyObject *Args) static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args) { - PyObject *result; - pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *pyInstallProgressInst = 0; @@ -192,11 +190,10 @@ static PyObject *PkgDepCacheSetCandidateVer(PyObject *Self,PyObject *Args) PyObject *PackageObj; PyObject *VersionObj; if (PyArg_ParseTuple(Args,"O!O!", - &PackageType, &PackageObj, - &VersionType, &VersionObj) == 0) + &PyPackage_Type, &PackageObj, + &PyVersion_Type, &VersionObj) == 0) return 0; - pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); pkgCache::VerIterator &I = GetCpp<pkgCache::VerIterator>(VersionObj); if(I.end()) { return HandleErrors(Py_BuildValue("b",false)); @@ -211,7 +208,7 @@ static PyObject *PkgDepCacheGetCandidateVer(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; PyObject *CandidateObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -222,7 +219,7 @@ static PyObject *PkgDepCacheGetCandidateVer(PyObject *Self,PyObject *Args) Py_INCREF(Py_None); return Py_None; } - CandidateObj = CppOwnedPyObject_NEW<pkgCache::VerIterator>(PackageObj,&VersionType,I); + CandidateObj = CppOwnedPyObject_NEW<pkgCache::VerIterator>(PackageObj,&PyVersion_Type,I); return CandidateObj; } @@ -303,7 +300,7 @@ static PyObject *PkgDepCacheMarkKeep(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache*>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -319,7 +316,7 @@ static PyObject *PkgDepCacheSetReInstall(PyObject *Self,PyObject *Args) PyObject *PackageObj; char value = 0; - if (PyArg_ParseTuple(Args,"O!b",&PackageType,&PackageObj, &value) == 0) + if (PyArg_ParseTuple(Args,"O!b",&PyPackage_Type,&PackageObj, &value) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -336,7 +333,7 @@ static PyObject *PkgDepCacheMarkDelete(PyObject *Self,PyObject *Args) PyObject *PackageObj; char purge = 0; - if (PyArg_ParseTuple(Args,"O!|b",&PackageType,&PackageObj, &purge) == 0) + if (PyArg_ParseTuple(Args,"O!|b",&PyPackage_Type,&PackageObj, &purge) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -354,7 +351,7 @@ static PyObject *PkgDepCacheMarkInstall(PyObject *Self,PyObject *Args) PyObject *PackageObj; char autoInst=1; char fromUser=1; - if (PyArg_ParseTuple(Args,"O!|bb",&PackageType,&PackageObj, + if (PyArg_ParseTuple(Args,"O!|bb",&PyPackage_Type,&PackageObj, &autoInst, &fromUser) == 0) return 0; @@ -367,12 +364,29 @@ static PyObject *PkgDepCacheMarkInstall(PyObject *Self,PyObject *Args) 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); + 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!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -386,7 +400,7 @@ static PyObject *PkgDepCacheIsGarbage(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -400,7 +414,7 @@ static PyObject *PkgDepCacheIsAutoInstalled(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -414,7 +428,7 @@ static PyObject *PkgDepCacheIsNowBroken(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -428,7 +442,7 @@ static PyObject *PkgDepCacheIsInstBroken(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -443,7 +457,7 @@ static PyObject *PkgDepCacheMarkedInstall(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -458,7 +472,7 @@ static PyObject *PkgDepCacheMarkedUpgrade(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -472,7 +486,7 @@ static PyObject *PkgDepCacheMarkedDelete(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -486,7 +500,7 @@ static PyObject *PkgDepCacheMarkedKeep(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -500,7 +514,7 @@ static PyObject *PkgDepCacheMarkedDowngrade(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -514,7 +528,7 @@ static PyObject *PkgDepCacheMarkedReinstall(PyObject *Self,PyObject *Args) pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); @@ -528,21 +542,48 @@ static PyObject *PkgDepCacheMarkedReinstall(PyObject *Self,PyObject *Args) static PyMethodDef PkgDepCacheMethods[] = { + {"init",PkgDepCacheInit,METH_VARARGS,"Init the depcache (done on construct automatically)"}, + {"get_candidate_ver",PkgDepCacheGetCandidateVer,METH_VARARGS,"Get candidate version"}, + {"set_candidate_ver",PkgDepCacheSetCandidateVer,METH_VARARGS,"Set candidate version"}, + + // global cache operations + {"upgrade",PkgDepCacheUpgrade,METH_VARARGS,"Perform Upgrade (optional boolean argument if dist-upgrade should be performed)"}, + {"fix_broken",PkgDepCacheFixBroken,METH_VARARGS,"Fix broken packages"}, + {"read_pinfile",PkgDepCacheReadPinFile,METH_VARARGS,"Read the pin policy"}, + {"minimize_upgrade",PkgDepCacheMinimizeUpgrade, METH_VARARGS,"Go over the entire set of packages and try to keep each package marked for upgrade. If a conflict is generated then the package is restored."}, + // Manipulators + {"mark_keep",PkgDepCacheMarkKeep,METH_VARARGS,"Mark package for keep"}, + {"mark_delete",PkgDepCacheMarkDelete,METH_VARARGS,"Mark package for delete (optional boolean argument if it should be purged)"}, + {"mark_install",PkgDepCacheMarkInstall,METH_VARARGS,"Mark package for Install"}, + {"mark_auto",PkgDepCacheMarkAuto,METH_VARARGS,"mark_auto(pkg: apt_pkg.Package, auto: bool)\n\nMark package as automatically installed."}, + {"set_reinstall",PkgDepCacheSetReInstall,METH_VARARGS,"Set if the package should be reinstalled"}, + // state information + {"is_upgradable",PkgDepCacheIsUpgradable,METH_VARARGS,"Is pkg upgradable"}, + {"is_now_broken",PkgDepCacheIsNowBroken,METH_VARARGS,"Is pkg is now broken"}, + {"is_inst_broken",PkgDepCacheIsInstBroken,METH_VARARGS,"Is pkg broken on the current install"}, + {"is_garbage",PkgDepCacheIsGarbage,METH_VARARGS,"Is pkg garbage (mark-n-sweep)"}, + {"is_auto_installed",PkgDepCacheIsAutoInstalled,METH_VARARGS,"Is pkg marked as auto installed"}, + {"marked_install",PkgDepCacheMarkedInstall,METH_VARARGS,"Is pkg marked for install"}, + {"marked_upgrade",PkgDepCacheMarkedUpgrade,METH_VARARGS,"Is pkg marked for upgrade"}, + {"marked_delete",PkgDepCacheMarkedDelete,METH_VARARGS,"Is pkg marked for delete"}, + {"marked_keep",PkgDepCacheMarkedKeep,METH_VARARGS,"Is pkg marked for keep"}, + {"marked_reinstall",PkgDepCacheMarkedReinstall,METH_VARARGS,"Is pkg marked for reinstall"}, + {"marked_downgrade",PkgDepCacheMarkedDowngrade,METH_VARARGS,"Is pkg marked for downgrade"}, + + // Action + {"commit", PkgDepCacheCommit, METH_VARARGS, "Commit pending changes"}, +#ifdef COMPAT_0_7 {"Init",PkgDepCacheInit,METH_VARARGS,"Init the depcache (done on construct automatically)"}, {"GetCandidateVer",PkgDepCacheGetCandidateVer,METH_VARARGS,"Get candidate version"}, {"SetCandidateVer",PkgDepCacheSetCandidateVer,METH_VARARGS,"Set candidate version"}, - - // global cache operations {"Upgrade",PkgDepCacheUpgrade,METH_VARARGS,"Perform Upgrade (optional boolean argument if dist-upgrade should be performed)"}, {"FixBroken",PkgDepCacheFixBroken,METH_VARARGS,"Fix broken packages"}, {"ReadPinFile",PkgDepCacheReadPinFile,METH_VARARGS,"Read the pin policy"}, {"MinimizeUpgrade",PkgDepCacheMinimizeUpgrade, METH_VARARGS,"Go over the entire set of packages and try to keep each package marked for upgrade. If a conflict is generated then the package is restored."}, - // Manipulators {"MarkKeep",PkgDepCacheMarkKeep,METH_VARARGS,"Mark package for keep"}, {"MarkDelete",PkgDepCacheMarkDelete,METH_VARARGS,"Mark package for delete (optional boolean argument if it should be purged)"}, {"MarkInstall",PkgDepCacheMarkInstall,METH_VARARGS,"Mark package for Install"}, {"SetReInstall",PkgDepCacheSetReInstall,METH_VARARGS,"Set if the package should be reinstalled"}, - // state information {"IsUpgradable",PkgDepCacheIsUpgradable,METH_VARARGS,"Is pkg upgradable"}, {"IsNowBroken",PkgDepCacheIsNowBroken,METH_VARARGS,"Is pkg is now broken"}, {"IsInstBroken",PkgDepCacheIsInstBroken,METH_VARARGS,"Is pkg broken on the current install"}, @@ -554,82 +595,144 @@ static PyMethodDef PkgDepCacheMethods[] = {"MarkedKeep",PkgDepCacheMarkedKeep,METH_VARARGS,"Is pkg marked for keep"}, {"MarkedReinstall",PkgDepCacheMarkedReinstall,METH_VARARGS,"Is pkg marked for reinstall"}, {"MarkedDowngrade",PkgDepCacheMarkedDowngrade,METH_VARARGS,"Is pkg marked for downgrade"}, - - // Action {"Commit", PkgDepCacheCommit, METH_VARARGS, "Commit pending changes"}, +#endif {} }; +#define depcache (GetCpp<pkgDepCache *>(Self)) +static PyObject *PkgDepCacheGetKeepCount(PyObject *Self,void*) { + return Py_BuildValue("l", depcache->KeepCount()); +} +static PyObject *PkgDepCacheGetInstCount(PyObject *Self,void*) { + return Py_BuildValue("l", depcache->InstCount()); +} +static PyObject *PkgDepCacheGetDelCount(PyObject *Self,void*) { + return Py_BuildValue("l", depcache->DelCount()); +} +static PyObject *PkgDepCacheGetBrokenCount(PyObject *Self,void*) { + return Py_BuildValue("l", depcache->BrokenCount()); +} +static PyObject *PkgDepCacheGetUsrSize(PyObject *Self,void*) { + return Py_BuildValue("d", depcache->UsrSize()); +} +static PyObject *PkgDepCacheGetDebSize(PyObject *Self,void*) { + return Py_BuildValue("d", 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(); + CppOwnedPyObject<pkgPolicy*> *PyPolicy = + CppOwnedPyObject_NEW<pkgPolicy*>(Owner,&PyPolicy_Type,Policy); + // Policy should not be deleted, it is managed by CacheFile. + PyPolicy->NoDelete = true; + return PyPolicy; +} -static PyObject *DepCacheAttr(PyObject *Self,char *Name) -{ - pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self); - // size querries - if(strcmp("KeepCount",Name) == 0) - return Py_BuildValue("l", depcache->KeepCount()); - else if(strcmp("InstCount",Name) == 0) - return Py_BuildValue("l", depcache->InstCount()); - else if(strcmp("DelCount",Name) == 0) - return Py_BuildValue("l", depcache->DelCount()); - else if(strcmp("BrokenCount",Name) == 0) - return Py_BuildValue("l", depcache->BrokenCount()); - else if(strcmp("UsrSize",Name) == 0) - return Py_BuildValue("d", depcache->UsrSize()); - else if(strcmp("DebSize",Name) == 0) - return Py_BuildValue("d", depcache->DebSize()); +static PyGetSetDef PkgDepCacheGetSet[] = { + {"broken_count",PkgDepCacheGetBrokenCount}, + {"deb_size",PkgDepCacheGetDebSize}, + {"del_count",PkgDepCacheGetDelCount}, + {"inst_count",PkgDepCacheGetInstCount}, + {"keep_count",PkgDepCacheGetKeepCount}, + {"usr_size",PkgDepCacheGetUsrSize}, + {"policy",PkgDepCacheGetPolicy}, + #ifdef COMPAT_0_7 + {"BrokenCount",PkgDepCacheGetBrokenCount}, + {"DebSize",PkgDepCacheGetDebSize}, + {"DelCount",PkgDepCacheGetDelCount}, + {"InstCount",PkgDepCacheGetInstCount}, + {"KeepCount",PkgDepCacheGetKeepCount}, + {"UsrSize",PkgDepCacheGetUsrSize}, + #endif + {} +}; +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; - return Py_FindMethod(PkgDepCacheMethods,Self,Name); -} + // 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); + + CppOwnedPyObject<pkgDepCache*> *DepCachePyObj; + DepCachePyObj = CppOwnedPyObject_NEW<pkgDepCache*>(Owner,type,depcache); + // Do not delete the underlying pointer, it is managed by the cachefile. + DepCachePyObj->NoDelete = true; + return HandleErrors(DepCachePyObj); +} -PyTypeObject PkgDepCacheType = +static char *doc_PkgDepCache = "DepCache(cache) -> DepCache() object\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 = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgDepCache", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.DepCache", // tp_name sizeof(CppOwnedPyObject<pkgDepCache *>), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc<pkgDepCache *>, // tp_dealloc + CppOwnedDeallocPtr<pkgDepCache *>, // tp_dealloc 0, // tp_print - DepCacheAttr, // tp_getattr + 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_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_PkgDepCache, // tp_doc + CppOwnedTraverse<pkgDepCache *>, // tp_traverse + CppOwnedClear<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 }; - +#ifdef COMPAT_0_7 PyObject *GetDepCache(PyObject *Self,PyObject *Args) { - PyObject *Owner; - if (PyArg_ParseTuple(Args,"O!",&PkgCacheType,&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); - - CppOwnedPyObject<pkgDepCache*> *DepCachePyObj; - DepCachePyObj = CppOwnedPyObject_NEW<pkgDepCache*>(Owner, - &PkgDepCacheType, - depcache); - HandleErrors(DepCachePyObj); - - return DepCachePyObj; + PyErr_WarnEx(PyExc_DeprecationWarning,"apt_pkg.GetDepCache() is deprecated" + ". Please see apt_pkg.DepCache() for the replacement.",1); + return PkgDepCacheNew(&PyDepCache_Type,Args,0); } - +#endif @@ -638,26 +741,33 @@ PyObject *GetDepCache(PyObject *Self,PyObject *Args) // pkgProblemResolver Class /*{{{*/ // --------------------------------------------------------------------- - - -PyObject *GetPkgProblemResolver(PyObject *Self,PyObject *Args) +static PyObject *PkgProblemResolverNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) { PyObject *Owner; - if (PyArg_ParseTuple(Args,"O!",&PkgDepCacheType,&Owner) == 0) + 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); CppOwnedPyObject<pkgProblemResolver*> *PkgProblemResolverPyObj; PkgProblemResolverPyObj = CppOwnedPyObject_NEW<pkgProblemResolver*>(Owner, - &PkgProblemResolverType, + type, fixer); HandleErrors(PkgProblemResolverPyObj); return PkgProblemResolverPyObj; - } +#ifdef COMPAT_0_7 +PyObject *GetPkgProblemResolver(PyObject *Self,PyObject *Args) { + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPkgProblemResolver() is" + " deprecated. Please see apt_pkg.ProblemResolver() for the " + "replacement.", 1); + return PkgProblemResolverNew(&PyProblemResolver_Type,Args,0); +} +#endif static PyObject *PkgProblemResolverResolve(PyObject *Self,PyObject *Args) { @@ -693,7 +803,7 @@ static PyObject *PkgProblemResolverProtect(PyObject *Self,PyObject *Args) { pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); fixer->Protect(Pkg); @@ -705,7 +815,7 @@ static PyObject *PkgProblemResolverRemove(PyObject *Self,PyObject *Args) { pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); fixer->Remove(Pkg); @@ -717,7 +827,7 @@ static PyObject *PkgProblemResolverClear(PyObject *Self,PyObject *Args) { pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); PyObject *PackageObj; - if (PyArg_ParseTuple(Args,"O!",&PackageType,&PackageObj) == 0) + if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0) return 0; pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj); fixer->Clear(Pkg); @@ -738,37 +848,35 @@ static PyObject *PkgProblemResolverInstallProtect(PyObject *Self,PyObject *Args) static PyMethodDef PkgProblemResolverMethods[] = { // config + {"protect", PkgProblemResolverProtect, METH_VARARGS, "protect(PkgIterator)"}, + {"remove", PkgProblemResolverRemove, METH_VARARGS, "remove(PkgIterator)"}, + {"clear", PkgProblemResolverClear, METH_VARARGS, "clear(PkgIterator)"}, + {"install_protect", PkgProblemResolverInstallProtect, METH_VARARGS, "install_protect()"}, + + // Actions + {"resolve", PkgProblemResolverResolve, METH_VARARGS, "Try to intelligently resolve problems by installing and removing packages"}, + {"resolve_by_keep", PkgProblemResolverResolveByKeep, METH_VARARGS, "Try to resolv problems only by using keep"}, + #ifdef COMPAT_0_7 {"Protect", PkgProblemResolverProtect, METH_VARARGS, "Protect(PkgIterator)"}, {"Remove", PkgProblemResolverRemove, METH_VARARGS, "Remove(PkgIterator)"}, {"Clear", PkgProblemResolverClear, METH_VARARGS, "Clear(PkgIterator)"}, {"InstallProtect", PkgProblemResolverInstallProtect, METH_VARARGS, "ProtectInstalled()"}, - - // Actions {"Resolve", PkgProblemResolverResolve, METH_VARARGS, "Try to intelligently resolve problems by installing and removing packages"}, {"ResolveByKeep", PkgProblemResolverResolveByKeep, METH_VARARGS, "Try to resolv problems only by using keep"}, + #endif {} }; - -static PyObject *ProblemResolverAttr(PyObject *Self,char *Name) -{ - pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self); - - return Py_FindMethod(PkgProblemResolverMethods,Self,Name); -} - - -PyTypeObject PkgProblemResolverType = +PyTypeObject PyProblemResolver_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgProblemResolver", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.ProblemResolver", // tp_name sizeof(CppOwnedPyObject<pkgProblemResolver *>), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc<pkgProblemResolver *>, // tp_dealloc + CppOwnedDeallocPtr<pkgProblemResolver *>,// tp_dealloc 0, // tp_print - ProblemResolverAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr @@ -776,6 +884,32 @@ PyTypeObject PkgProblemResolverType = 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), + "ProblemResolver Object", // tp_doc + CppOwnedTraverse<pkgProblemResolver *>, // tp_traverse + CppOwnedClear<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 }; /*}}}*/ @@ -797,7 +931,6 @@ static PyObject *PkgActionGroupRelease(PyObject *Self,PyObject *Args) static PyObject *PkgActionGroupEnter(PyObject *Self,PyObject *Args) { if (PyArg_ParseTuple(Args,"") == 0) return 0; - Py_INCREF(Self); return Self; } static PyObject *PkgActionGroupExit(PyObject *Self,PyObject *Args) { @@ -806,35 +939,60 @@ static PyObject *PkgActionGroupExit(PyObject *Self,PyObject *Args) { Py_RETURN_FALSE; } - static PyMethodDef PkgActionGroupMethods[] = { {"release", PkgActionGroupRelease, METH_VARARGS, "release()"}, - {"__enter__", PkgActionGroupEnter, METH_VARARGS, "__enter__() -> self"}, - {"__exit__", PkgActionGroupExit, METH_VARARGS, "__exit__()"}, + {"__exit__", PkgActionGroupExit, METH_VARARGS, "__exit__(...) -> " + "Release the action group, for 'with' statement."}, + {"__enter__", PkgActionGroupEnter, METH_VARARGS, "__enter__() -> " + "Enter, for the 'with' statement. Does nothing."}, {} }; - -static PyObject *ActionGroupAttr(PyObject *Self,char *Name) +static PyObject *PkgActionGroupNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) { - pkgDepCache::ActionGroup *ag = GetCpp<pkgDepCache::ActionGroup*>(Self); + PyObject *Owner; + char *kwlist[] = {"depcache", 0}; + if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type, + &Owner) == 0) + return 0; - return Py_FindMethod(PkgActionGroupMethods,Self,Name); -} + pkgDepCache *depcache = GetCpp<pkgDepCache*>(Owner); + pkgDepCache::ActionGroup *group = new pkgDepCache::ActionGroup(*depcache); + CppOwnedPyObject<pkgDepCache::ActionGroup*> *PkgActionGroupPyObj; + PkgActionGroupPyObj = CppOwnedPyObject_NEW<pkgDepCache::ActionGroup*>(Owner, + type, + group); + HandleErrors(PkgActionGroupPyObj); + + return PkgActionGroupPyObj; +} -PyTypeObject PkgActionGroupType = +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 = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgActionGroup", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.ActionGroup", // tp_name sizeof(CppOwnedPyObject<pkgDepCache::ActionGroup*>), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc<pkgDepCache::ActionGroup*>, // tp_dealloc + CppOwnedDeallocPtr<pkgDepCache::ActionGroup*>, // tp_dealloc 0, // tp_print - ActionGroupAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr @@ -842,25 +1000,43 @@ PyTypeObject PkgActionGroupType = 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 + CppOwnedTraverse<pkgDepCache::ActionGroup*>, // tp_traverse + CppOwnedClear<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 }; +#ifdef COMPAT_0_7 PyObject *GetPkgActionGroup(PyObject *Self,PyObject *Args) { - PyObject *Owner; - if (PyArg_ParseTuple(Args,"O!",&PkgDepCacheType,&Owner) == 0) - return 0; - - pkgDepCache *depcache = GetCpp<pkgDepCache*>(Owner); - pkgDepCache::ActionGroup *group = new pkgDepCache::ActionGroup(*depcache); - CppOwnedPyObject<pkgDepCache::ActionGroup*> *PkgActionGroupPyObj; - PkgActionGroupPyObj = CppOwnedPyObject_NEW<pkgDepCache::ActionGroup*>(Owner, - &PkgActionGroupType, - group); - HandleErrors(PkgActionGroupPyObj); - - return PkgActionGroupPyObj; - + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPkgActionGroup() is " + "deprecated. Please see apt_pkg.ActionGroup() for the " + "replacement.", 1); + return PkgActionGroupNew(&PyActionGroup_Type,Args,0); } +#endif /*}}}*/ diff --git a/python/generic.cc b/python/generic.cc index 7309d978..51439a1b 100644 --- a/python/generic.cc +++ b/python/generic.cc @@ -25,8 +25,9 @@ PyObject *HandleErrors(PyObject *Res) return Res; } - if (Res != 0) + if (Res != 0) { Py_DECREF(Res); + } string Err; int errcnt = 0; diff --git a/python/generic.h b/python/generic.h index d2fcf42a..d5d6e9fb 100644 --- a/python/generic.h +++ b/python/generic.h @@ -29,12 +29,81 @@ #include <Python.h> #include <string> +#include <iostream> #include <new> #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 +// Force 0.7 compatibility to be off in Python 3 builds +#undef COMPAT_0_7 +#else +// Compatibility for Python 2.5 and previous. +#if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 5) +#define PyBytes_Check PyString_Check +#define PyBytes_AS_STRING PyString_AS_STRING +#define PyBytes_AsString PyString_AsString +#define PyBytes_AsStringAndSize PyString_AsStringAndSize +#define PyBytes_FromStringAndSize PyString_FromStringAndSize +#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, +#endif +#endif + +// Hacks to make Python 2.4 build. +#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4 +#define PyErr_WarnEx(cat,msg,stacklevel) PyErr_Warn(cat,msg) +#endif + + +static inline const char *PyUnicode_AsString(PyObject *op) { + // Convert to bytes object, using the default encoding. + PyObject *bytes = PyUnicode_AsEncodedString(op,0,0); + return bytes ? PyBytes_AS_STRING(bytes) : 0; +} + +// 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 @@ -48,6 +117,11 @@ template <class T> struct CppPyObject : public PyObject // So basically having the c'tor here removes the need for T to have a // default c'tor, which is not always desireable. CppPyObject() { }; + + // Flag which causes the underlying object to not be deleted. + bool NoDelete; + + // The underlying C++ object. T Object; }; @@ -72,7 +146,10 @@ inline PyObject *GetOwner(PyObject *Obj) template <class T> inline CppPyObject<T> *CppPyObject_NEW(PyTypeObject *Type) { - CppPyObject<T> *New = PyObject_NEW(CppPyObject<T>,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; return New; } @@ -80,7 +157,10 @@ inline CppPyObject<T> *CppPyObject_NEW(PyTypeObject *Type) template <class T,class A> inline CppPyObject<T> *CppPyObject_NEW(PyTypeObject *Type,A const &Arg) { - CppPyObject<T> *New = PyObject_NEW(CppPyObject<T>,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(Arg); return New; } @@ -89,10 +169,13 @@ template <class T> inline CppOwnedPyObject<T> *CppOwnedPyObject_NEW(PyObject *Owner, PyTypeObject *Type) { - CppOwnedPyObject<T> *New = PyObject_NEW(CppOwnedPyObject<T>,Type); + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n"; + #endif + CppOwnedPyObject<T> *New = (CppOwnedPyObject<T>*)Type->tp_alloc(Type, 0); new (&New->Object) T; New->Owner = Owner; - Py_INCREF(Owner); + Py_XINCREF(Owner); return New; } @@ -100,31 +183,78 @@ template <class T,class A> inline CppOwnedPyObject<T> *CppOwnedPyObject_NEW(PyObject *Owner, PyTypeObject *Type,A const &Arg) { - CppOwnedPyObject<T> *New = PyObject_NEW(CppOwnedPyObject<T>,Type); + #ifdef ALLOC_DEBUG + std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n"; + #endif + CppOwnedPyObject<T> *New = (CppOwnedPyObject<T>*)Type->tp_alloc(Type, 0); new (&New->Object) T(Arg); New->Owner = Owner; - if (Owner != 0) - Py_INCREF(Owner); + Py_XINCREF(Owner); return New; } +// Traversal and Clean for owned objects +template <class T> +int CppOwnedTraverse(PyObject *self, visitproc visit, void* arg) { + Py_VISIT(((CppOwnedPyObject<T> *)self)->Owner); + return 0; +} + +template <class T> +int CppOwnedClear(PyObject *self) { + Py_CLEAR(((CppOwnedPyObject<T> *)self)->Owner); + return 0; +} + // Generic Dealloc type functions template <class T> void CppDealloc(PyObject *Obj) { - GetCpp<T>(Obj).~T(); - PyObject_DEL(Obj); + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << " ===\n"; + #endif + if (!((CppPyObject<T>*)Obj)->NoDelete) + GetCpp<T>(Obj).~T(); + Obj->ob_type->tp_free(Obj); } template <class T> void CppOwnedDealloc(PyObject *iObj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "+ ===\n"; + #endif + CppOwnedPyObject<T> *Obj = (CppOwnedPyObject<T> *)iObj; + if (!((CppPyObject<T>*)Obj)->NoDelete) + Obj->Object.~T(); + CppOwnedClear<T>(iObj); + iObj->ob_type->tp_free(iObj); +} + +// Pointer deallocation +// Generic Dealloc type functions +template <class T> +void CppDeallocPtr(PyObject *Obj) +{ + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << "* ===\n"; + #endif + if (!((CppPyObject<T>*)Obj)->NoDelete) + delete GetCpp<T>(Obj); + Obj->ob_type->tp_free(Obj); +} + +template <class T> +void CppOwnedDeallocPtr(PyObject *iObj) +{ + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "*+ ===\n"; + #endif CppOwnedPyObject<T> *Obj = (CppOwnedPyObject<T> *)iObj; - Obj->Object.~T(); - if (Obj->Owner != 0) { - Py_DECREF(Obj->Owner); - } - PyObject_DEL(Obj); + if (!((CppPyObject<T>*)Obj)->NoDelete) + delete Obj->Object; + CppOwnedClear<T>(iObj); + iObj->ob_type->tp_free(iObj); } inline PyObject *CppPyString(std::string Str) diff --git a/python/hashes.cc b/python/hashes.cc new file mode 100644 index 00000000..0086c17a --- /dev/null +++ b/python/hashes.cc @@ -0,0 +1,136 @@ +/* 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>(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); + hashes.Add((const unsigned char*)s, len); + } + else if ((Fd = PyObject_AsFileDescriptor(object)) != -1) { + struct stat St; + if (fstat(Fd, &St) != 0 || hashes.AddFD(Fd, St.st_size) == false) { + PyErr_SetFromErrno(PyExc_SystemError); + return -1; + } + } + else { + PyErr_SetString(PyExc_TypeError, + "__init__() only understand strings and files"); + return -1; + } + return 0; +} + +static PyObject *hashes_get_md5(PyObject *self, void*) +{ + return CppPyString(GetCpp<Hashes>(self).MD5.Result().Value()); +} + +static PyObject *hashes_get_sha1(PyObject *self, void*) +{ + return CppPyString(GetCpp<Hashes>(self).SHA1.Result().Value()); +} + +static PyObject *hashes_get_sha256(PyObject *self, void*) +{ + return CppPyString(GetCpp<Hashes>(self).SHA256.Result().Value()); +} + +static PyGetSetDef hashes_getset[] = { + {"md5",hashes_get_md5,0,"The MD5Sum of the file as a string."}, + {"sha1",hashes_get_sha1,0,"The SHA1Sum of the file as a string."}, + {"sha256",hashes_get_sha256,0,"The SHA256Sum of the file as a string."}, + {} +}; + +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 bytes (3.X) / str (2.X) object, or an\n" + "object providing the fileno() method or an integer describing a file\n" + "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 00000000..90c80e4c --- /dev/null +++ b/python/hashstring.cc @@ -0,0 +1,134 @@ +/* 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*>(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) +{ + HashString *hash = GetCpp<HashString*>(self); + return CppPyString(hash->toStr()); +} + +static PyObject *hashstring_get_hashtype(PyObject *self) +{ + HashString *hash = GetCpp<HashString*>(self); + return CppPyString(hash->HashType()); +} + +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) +{ + 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)."}, + {NULL} +}; + +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 seperated 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 + 0, // 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/indexfile.cc b/python/indexfile.cc index 107eae27..a6f8904e 100644 --- a/python/indexfile.cc +++ b/python/indexfile.cc @@ -22,69 +22,105 @@ static PyObject *PackageIndexFileArchiveURI(PyObject *Self,PyObject *Args) if (PyArg_ParseTuple(Args, "s",&path) == 0) return 0; - return HandleErrors(Safe_FromString(File->ArchiveURI(path).c_str())); } static PyMethodDef PackageIndexFileMethods[] = { + {"archive_uri",PackageIndexFileArchiveURI,METH_VARARGS,"Returns the ArchiveURI"}, + #ifdef COMPAT_0_7 {"ArchiveURI",PackageIndexFileArchiveURI,METH_VARARGS,"Returns the ArchiveURI"}, + #endif {} }; - -static PyObject *PackageIndexFileAttr(PyObject *Self,char *Name) -{ - pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self); - if (strcmp("Label",Name) == 0) - return Safe_FromString(File->GetType()->Label); - else if (strcmp("Describe",Name) == 0) - return Safe_FromString(File->Describe().c_str()); - else if (strcmp("Exists",Name) == 0) - return Py_BuildValue("i",(File->Exists())); - else if (strcmp("HasPackages",Name) == 0) - return Py_BuildValue("i",(File->HasPackages())); - else if (strcmp("Size",Name) == 0) - return Py_BuildValue("i",(File->Size())); - else if (strcmp("IsTrusted",Name) == 0) - return Py_BuildValue("i",(File->IsTrusted())); - - return Py_FindMethod(PackageIndexFileMethods,Self,Name); +#define File (GetCpp<pkgIndexFile*>(Self)) +static PyObject *PackageIndexFileGetLabel(PyObject *Self,void*) { + return Safe_FromString(File->GetType()->Label); +} +static PyObject *PackageIndexFileGetDescribe(PyObject *Self,void*) { + return Safe_FromString(File->Describe().c_str()); } +static PyObject *PackageIndexFileGetExists(PyObject *Self,void*) { + return Py_BuildValue("i",(File->Exists())); +} +static PyObject *PackageIndexFileGetHasPackages(PyObject *Self,void*) { + return Py_BuildValue("i",(File->HasPackages())); +} +static PyObject *PackageIndexFileGetSize(PyObject *Self,void*) { + return Py_BuildValue("i",(File->Size())); +} +static PyObject *PackageIndexFileGetIsTrusted(PyObject *Self,void*) { + return Py_BuildValue("i",(File->IsTrusted())); +} +#undef File +#define S(x) (x ? x : "") static PyObject *PackageIndexFileRepr(PyObject *Self) { pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self); - - char S[1024]; - snprintf(S,sizeof(S),"<pkIndexFile object: " + return PyString_FromFormat("<pkIndexFile object: " "Label:'%s' Describe='%s' Exists='%i' " - "HasPackages='%i' Size='%i' " + "HasPackages='%i' Size='%lu' " "IsTrusted='%i' ArchiveURI='%s'>", - File->GetType()->Label, File->Describe().c_str(), File->Exists(), + S(File->GetType()->Label), File->Describe().c_str(), File->Exists(), File->HasPackages(), File->Size(), File->IsTrusted(), File->ArchiveURI("").c_str()); - return PyString_FromString(S); } +#undef S + +static PyGetSetDef PackageIndexFileGetSet[] = { + {"describe",PackageIndexFileGetDescribe}, + {"exists",PackageIndexFileGetExists}, + {"has_packages",PackageIndexFileGetHasPackages}, + {"is_trusted",PackageIndexFileGetIsTrusted}, + {"label",PackageIndexFileGetLabel}, + {"size",PackageIndexFileGetSize}, + #ifdef COMPAT_0_7 + {"Describe",PackageIndexFileGetDescribe}, + {"Exists",PackageIndexFileGetExists}, + {"HasPackages",PackageIndexFileGetHasPackages}, + {"IsTrusted",PackageIndexFileGetIsTrusted}, + {"Label",PackageIndexFileGetLabel}, + {"Size",PackageIndexFileGetSize}, + #endif + {} +}; -PyTypeObject PackageIndexFileType = +PyTypeObject PyPackageIndexFile_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgIndexFile", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.PackageIndexFile", // tp_name sizeof(CppOwnedPyObject<pkgIndexFile*>), // tp_basicsize 0, // tp_itemsize // Methods - CppOwnedDealloc<pkgIndexFile*>, // tp_dealloc + // Not ..Ptr, because the pointer is managed somewhere else. + CppOwnedDeallocPtr<pkgIndexFile*>, // tp_dealloc 0, // tp_print - PackageIndexFileAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare - PackageIndexFileRepr, // tp_repr + PackageIndexFileRepr, // tp_repr 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping + 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 | Py_TPFLAGS_HAVE_GC, // tp_flags + "IndexFile Object", // tp_doc + CppOwnedTraverse<pkgIndexFile*>, // tp_traverse + CppOwnedClear<pkgIndexFile*>, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + PackageIndexFileMethods, // tp_methods + 0, // tp_members + PackageIndexFileGetSet, // tp_getset }; diff --git a/python/indexrecords.cc b/python/indexrecords.cc new file mode 100644 index 00000000..9ab052f6 --- /dev/null +++ b/python/indexrecords.cc @@ -0,0 +1,127 @@ +/* + * indexrecords.cc - Wrapper around indexRecords + * + * 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/indexrecords.h> + +static PyObject *IndexRecords_NEW(PyTypeObject *type,PyObject *Args, + PyObject *kwds) +{ + char * kwlist[] = {NULL}; + if (PyArg_ParseTupleAndKeywords(Args, kwds, "", kwlist) == 0) + return 0; + indexRecords *records = new indexRecords(); + CppPyObject<indexRecords*> *New = CppPyObject_NEW<indexRecords*>(type, + records); + return New; +} + +static PyObject *IndexRecords_Load(PyObject *self,PyObject *args) +{ + const char *filename; + if (PyArg_ParseTuple(args, "s", &filename) == 0) + return 0; + indexRecords *records = GetCpp<indexRecords*>(self); + return HandleErrors(Py_BuildValue("i", records->Load(filename))); +} + +static char *IndexRecords_Lookup_doc = "lookup(metakey)\n\n" + "Lookup the filename given by metakey, return a tuple (hash, size).\n" + "The hash part is a HashString() object."; +static PyObject *IndexRecords_Lookup(PyObject *self,PyObject *args) +{ + const char *keyname; + if (PyArg_ParseTuple(args, "s", &keyname) == 0) + return 0; + indexRecords *records = GetCpp<indexRecords*>(self); + const indexRecords::checkSum *result = records->Lookup(keyname); + if (result == 0) { + PyErr_SetString(PyExc_KeyError,keyname); + return 0; + } + // Copy the HashString(), to prevent crashes and to not require the + // indexRecords object to exist. + PyObject *py_hash = PyHashString_FromCpp(new HashString(result->Hash)); + PyObject *value = Py_BuildValue("(Oi)",py_hash,result->Size); + Py_DECREF(py_hash); + return value; +} + +static PyObject *IndexRecords_GetDist(PyObject *self) +{ + indexRecords *records = GetCpp<indexRecords*>(self); + return HandleErrors(PyString_FromString(records->GetDist().c_str())); +} + +static PyMethodDef IndexRecords_Methods[] = { + {"load",IndexRecords_Load,METH_VARARGS, + "load(filename: str)\n\nLoad the file given by filename."}, + {"get_dist",(PyCFunction)IndexRecords_GetDist,METH_NOARGS, + "get_dist() -> str\n\nReturn a distribution set in the release file."}, + {"lookup",IndexRecords_Lookup,METH_VARARGS,IndexRecords_Lookup_doc}, + {} +}; + +static char *IndexRecords_doc = "IndexRecords()\n\n" + "Representation of a release file."; +PyTypeObject PyIndexRecords_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.IndexRecords", // tp_name + sizeof(CppPyObject<indexRecords*>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDeallocPtr<indexRecords*>, // 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), + IndexRecords_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + IndexRecords_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 + IndexRecords_NEW, // tp_new +}; diff --git a/python/lock.cc b/python/lock.cc new file mode 100644 index 00000000..d4d45734 --- /dev/null +++ b/python/lock.cc @@ -0,0 +1,265 @@ +/* + * 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 <apt-pkg/init.h> +#include <apt-pkg/error.h> +#include <Python.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, e.g.::\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) +{ + char *filename = 0; + char *kwlist[] = {"filename", NULL}; + if (PyArg_ParseTupleAndKeywords(args, kwds, "s:__init__", kwlist, + &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 = "SystemLock(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, e.g.::\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/makefile b/python/makefile deleted file mode 100644 index 3e6458f4..00000000 --- a/python/makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -*- make -*- -BASE=.. -SUBDIR=python - -# Bring in the default rules -include ../buildlib/defaults.mak - -# The apt_pkg module -MODULE=apt_pkg -SLIBS = -lapt-pkg -LIB_MAKES = apt-pkg/makefile -APT_PKG_SRC = apt_pkgmodule.cc configuration.cc generic.cc tag.cc string.cc \ - cache.cc pkgrecords.cc pkgsrcrecords.cc sourcelist.cc \ - depcache.cc progress.cc cdrom.cc acquire.cc pkgmanager.cc \ - indexfile.cc metaindex.cc -SOURCE := $(APT_PKG_SRC) -include $(PYTHON_H) progress.h - -# The apt_int module.. -MODULE=apt_inst -SLIBS = -lapt-inst -lapt-pkg -LIB_MAKES = apt-inst/makefile -APT_INST_SRC = apt_instmodule.cc tar.cc generic.cc -SOURCE := $(APT_INST_SRC) -include $(PYTHON_H) - diff --git a/python/metaindex.cc b/python/metaindex.cc index efbc38af..4e059f0c 100644 --- a/python/metaindex.cc +++ b/python/metaindex.cc @@ -1,13 +1,13 @@ // -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ +// Description /*{{{*/ // $Id: metaindex.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $ /* ###################################################################### metaindex - Wrapper for the metaIndex functions ##################################################################### */ - /*}}}*/ -// Include Files /*{{{*/ + /*}}}*/ +// Include Files /*{{{*/ #include "generic.h" #include "apt_pkgmodule.h" @@ -15,67 +15,94 @@ #include <Python.h> +static PyObject *MetaIndexGetURI(PyObject *Self,void*) { + metaIndex *meta = GetCpp<metaIndex*>(Self); + return Safe_FromString(meta->GetURI().c_str()); +} -static PyObject *MetaIndexAttr(PyObject *Self,char *Name) -{ - metaIndex *meta = GetCpp<metaIndex*>(Self); - if (strcmp("URI",Name) == 0) - return Safe_FromString(meta->GetURI().c_str()); - else if (strcmp("Dist",Name) == 0) - return Safe_FromString(meta->GetDist().c_str()); - else if (strcmp("IsTrusted",Name) == 0) - return Py_BuildValue("i",(meta->IsTrusted())); - else if (strcmp("IndexFiles",Name) == 0) - { - PyObject *List = PyList_New(0); - vector<pkgIndexFile *> *indexFiles = meta->GetIndexFiles(); - for (vector<pkgIndexFile *>::const_iterator I = indexFiles->begin(); - I != indexFiles->end(); I++) - { - PyObject *Obj; - Obj = CppPyObject_NEW<pkgIndexFile*>(&PackageIndexFileType,*I); - PyList_Append(List,Obj); - } - return List; - } +static PyObject *MetaIndexGetDist(PyObject *Self,void*) { + metaIndex *meta = GetCpp<metaIndex*>(Self); + return Safe_FromString(meta->GetDist().c_str()); +} - PyErr_SetString(PyExc_AttributeError,Name); - return 0; +static PyObject *MetaIndexGetIsTrusted(PyObject *Self,void*) { + metaIndex *meta = GetCpp<metaIndex*>(Self); + return Py_BuildValue("i",(meta->IsTrusted())); } -static PyObject *MetaIndexRepr(PyObject *Self) -{ - metaIndex *meta = GetCpp<metaIndex*>(Self); +static PyObject *MetaIndexGetIndexFiles(PyObject *Self,void*) { + metaIndex *meta = GetCpp<metaIndex*>(Self); + PyObject *List = PyList_New(0); + vector<pkgIndexFile *> *indexFiles = meta->GetIndexFiles(); + for (vector<pkgIndexFile *>::const_iterator I = indexFiles->begin(); + I != indexFiles->end(); I++) + { + CppOwnedPyObject<pkgIndexFile*> *Obj; + Obj = CppOwnedPyObject_NEW<pkgIndexFile*>(Self, &PyPackageIndexFile_Type,*I); + // Do not delete pkgIndexFile*, they are managed by metaIndex. + Obj->NoDelete = true; + PyList_Append(List,Obj); + Py_DECREF(Obj); + } + return List; +} - char S[1024]; - snprintf(S,sizeof(S),"<metaIndex object: " - "Type='%s', URI:'%s' Dist='%s' IsTrusted='%i'>", - meta->GetType(), meta->GetURI().c_str(), meta->GetDist().c_str(), - meta->IsTrusted()); +static PyGetSetDef MetaIndexGetSet[] = { + {"dist",MetaIndexGetDist}, + {"index_files",MetaIndexGetIndexFiles}, + {"is_trusted",MetaIndexGetIsTrusted}, + {"uri",MetaIndexGetURI}, + #ifdef COMPAT_0_7 + {"Dist",MetaIndexGetDist}, + {"IndexFiles",MetaIndexGetIndexFiles}, + {"IsTrusted",MetaIndexGetIsTrusted}, + {"URI",MetaIndexGetURI}, + #endif + {} +}; - return PyString_FromString(S); +#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 -PyTypeObject MetaIndexType = +PyTypeObject PyMetaIndex_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "metaIndex", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.MetaIndex", // tp_name sizeof(CppOwnedPyObject<metaIndex*>), // tp_basicsize - 0, // tp_itemsize + 0, // tp_itemsize // Methods - CppOwnedDealloc<metaIndex*>, // tp_dealloc - 0, // tp_print - MetaIndexAttr, // 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 + CppOwnedDeallocPtr<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 + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "apt_pkg.MetaIndex Object", // 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/pkgmanager.cc b/python/pkgmanager.cc index 0eaa28cd..58f2aaec 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -15,8 +15,37 @@ #include <apt-pkg/sourcelist.h> #include <apt-pkg/error.h> #include <apt-pkg/acquire.h> +#include <apt-pkg/init.h> +#include <apt-pkg/configuration.h> + #include <iostream> +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; + + pkgPackageManager *pm = _system->CreatePM(GetCpp<pkgDepCache*>(Owner)); + + CppPyObject<pkgPackageManager*> *PkgManagerObj = + CppPyObject_NEW<pkgPackageManager*>(type,pm); + + return PkgManagerObj; +} + +#ifdef COMPAT_0_7 +PyObject *GetPkgManager(PyObject *Self,PyObject *Args) +{ + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPackageManager() is " + "deprecated. Please see apt_pkg.PackageManager() for the " + "replacement.", 1); + return PkgManagerNew(&PyPackageManager_Type,Args,0); +} +#endif + static PyObject *PkgManagerGetArchives(PyObject *Self,PyObject *Args) { @@ -24,9 +53,9 @@ static PyObject *PkgManagerGetArchives(PyObject *Self,PyObject *Args) PyObject *fetcher, *list, *recs; if (PyArg_ParseTuple(Args, "O!O!O!", - &PkgAcquireType,&fetcher, - &PkgSourceListType, &list, - &PkgRecordsType, &recs) == 0) + &PyAcquire_Type,&fetcher, + &PySourceList_Type, &list, + &PyPackageRecords_Type, &recs) == 0) return 0; pkgAcquire *s_fetcher = GetCpp<pkgAcquire*>(fetcher); @@ -68,68 +97,62 @@ static PyObject *PkgManagerFixMissing(PyObject *Self,PyObject *Args) static PyMethodDef PkgManagerMethods[] = { + {"get_archives",PkgManagerGetArchives,METH_VARARGS,"Load the selected archives into the fetcher"}, + {"do_install",PkgManagerDoInstall,METH_VARARGS,"Do the actual install"}, + {"fix_missing",PkgManagerFixMissing,METH_VARARGS,"Fix the install if a pkg couldn't be downloaded"}, +#ifdef COMPAT_0_7 {"GetArchives",PkgManagerGetArchives,METH_VARARGS,"Load the selected archives into the fetcher"}, {"DoInstall",PkgManagerDoInstall,METH_VARARGS,"Do the actual install"}, {"FixMissing",PkgManagerFixMissing,METH_VARARGS,"Fix the install if a pkg couldn't be downloaded"}, +#endif {} }; -static PyObject *PkgManagerAttr(PyObject *Self,char *Name) -{ - //PkgManagerStruct &Struct = GetCpp<PkgManagerStruct>(Self); - pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self); - - // some constants - if(strcmp("ResultCompleted",Name) == 0) - return Py_BuildValue("i", pkgPackageManager::Completed); - if(strcmp("ResultFailed",Name) == 0) - return Py_BuildValue("i", pkgPackageManager::Failed); - if(strcmp("ResultIncomplete",Name) == 0) - return Py_BuildValue("i", pkgPackageManager::Incomplete); - - return Py_FindMethod(PkgManagerMethods,Self,Name); -} - - -PyTypeObject PkgManagerType = +PyTypeObject PyPackageManager_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "PackageManager", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.PackageManager", // tp_name sizeof(CppPyObject<pkgPackageManager*>), // tp_basicsize 0, // tp_itemsize // Methods - CppDealloc<pkgPackageManager*>, // tp_dealloc + CppDeallocPtr<pkgPackageManager*>, // tp_dealloc 0, // tp_print - PkgManagerAttr, // tp_getattr + 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_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), + "PackageManager Object", // 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 + PkgManagerNew, // tp_new }; -#include <apt-pkg/init.h> -#include <apt-pkg/configuration.h> - -PyObject *GetPkgManager(PyObject *Self,PyObject *Args) -{ - PyObject *Owner; - if (PyArg_ParseTuple(Args,"O!",&PkgDepCacheType,&Owner) == 0) - return 0; - - pkgPackageManager *pm = _system->CreatePM(GetCpp<pkgDepCache*>(Owner)); - - CppPyObject<pkgPackageManager*> *PkgManagerObj = - CppPyObject_NEW<pkgPackageManager*>(&PkgManagerType,pm); - - return PkgManagerObj; -} - - /*}}}*/ diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc index 5359ee6f..d34ba0d2 100644 --- a/python/pkgrecords.cc +++ b/python/pkgrecords.cc @@ -27,7 +27,7 @@ static PyObject *PkgRecordsLookup(PyObject *Self,PyObject *Args) PyObject *PkgFObj; long int Index; - if (PyArg_ParseTuple(Args,"(O!l)",&PackageFileType,&PkgFObj,&Index) == 0) + if (PyArg_ParseTuple(Args,"(O!l)",&PyPackageFile_Type,&PkgFObj,&Index) == 0) return 0; // Get the index and check to make sure it is reasonable @@ -49,59 +49,128 @@ static PyObject *PkgRecordsLookup(PyObject *Self,PyObject *Args) static PyMethodDef PkgRecordsMethods[] = { + {"lookup",PkgRecordsLookup,METH_VARARGS,"Changes to a new package"}, + #ifdef COMPAT_0_7 {"Lookup",PkgRecordsLookup,METH_VARARGS,"Changes to a new package"}, + #endif {} }; -static PyObject *PkgRecordsAttr(PyObject *Self,char *Name) -{ +/** + * 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; +} - if (Struct.Last != 0) - { - if (strcmp("FileName",Name) == 0) - return CppPyString(Struct.Last->FileName()); - else if (strcmp("MD5Hash",Name) == 0) - return CppPyString(Struct.Last->MD5Hash()); - else if (strcmp("SHA1Hash",Name) == 0) - return CppPyString(Struct.Last->SHA1Hash()); - else if (strcmp("SHA256Hash",Name) == 0) - return CppPyString(Struct.Last->SHA256Hash()); - else if (strcmp("SourcePkg",Name) == 0) - return CppPyString(Struct.Last->SourcePkg()); - else if (strcmp("SourceVer",Name) == 0) - return CppPyString(Struct.Last->SourceVer()); - else if (strcmp("Maintainer",Name) == 0) - return CppPyString(Struct.Last->Maintainer()); - else if (strcmp("ShortDesc",Name) == 0) - return CppPyString(Struct.Last->ShortDesc()); - else if (strcmp("LongDesc",Name) == 0) - return CppPyString(Struct.Last->LongDesc()); - else if (strcmp("Name",Name) == 0) - return CppPyString(Struct.Last->Name()); - else if (strcmp("Homepage",Name) == 0) - return CppPyString(Struct.Last->Homepage()); - else if (strcmp("Record", Name) == 0) - { - const char *start, *stop; - Struct.Last->GetRec(start, stop); - return PyString_FromStringAndSize(start,stop-start); - } - } +static PyObject *PkgRecordsGetFileName(PyObject *Self,void*) { + PkgRecordsStruct &Struct = GetStruct(Self,"FileName"); + return (Struct.Last != 0) ? CppPyString(Struct.Last->FileName()) : 0; +} +static PyObject *PkgRecordsGetMD5Hash(PyObject *Self,void*) { + PkgRecordsStruct &Struct = GetStruct(Self,"MD5Hash"); + return (Struct.Last != 0) ? CppPyString(Struct.Last->MD5Hash()) : 0; +} +static PyObject *PkgRecordsGetSHA1Hash(PyObject *Self,void*) { + PkgRecordsStruct &Struct = GetStruct(Self,"SHA1Hash"); + return (Struct.Last != 0) ? CppPyString(Struct.Last->SHA1Hash()) : 0; +} +static PyObject *PkgRecordsGetSHA256Hash(PyObject *Self,void*) { + PkgRecordsStruct &Struct = GetStruct(Self,"SHA256Hash"); + return (Struct.Last != 0) ? CppPyString(Struct.Last->SHA256Hash()) : 0; +} +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) ? CppPyString(Struct.Last->ShortDesc()) : 0; +} +static PyObject *PkgRecordsGetLongDesc(PyObject *Self,void*) { + PkgRecordsStruct &Struct = GetStruct(Self,"LongDesc"); + return (Struct.Last != 0) ? CppPyString(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}, + {"homepage",PkgRecordsGetHomepage}, + {"long_desc",PkgRecordsGetLongDesc}, + {"md5_hash",PkgRecordsGetMD5Hash}, + {"maintainer",PkgRecordsGetMaintainer}, + {"name",PkgRecordsGetName}, + {"record",PkgRecordsGetRecord}, + {"sha1_hash",PkgRecordsGetSHA1Hash}, + {"sha256_hash",PkgRecordsGetSHA256Hash}, + {"short_desc",PkgRecordsGetShortDesc}, + {"source_pkg",PkgRecordsGetSourcePkg}, + {"source_ver",PkgRecordsGetSourceVer}, +#ifdef COMPAT_0_7 + {"FileName",PkgRecordsGetFileName}, + {"Homepage",PkgRecordsGetHomepage}, + {"LongDesc",PkgRecordsGetLongDesc}, + {"MD5Hash",PkgRecordsGetMD5Hash}, + {"Maintainer",PkgRecordsGetMaintainer}, + {"Name",PkgRecordsGetName}, + {"Record",PkgRecordsGetRecord}, + {"SHA1Hash",PkgRecordsGetSHA1Hash}, + {"SHA256Hash",PkgRecordsGetSHA256Hash}, + {"ShortDesc",PkgRecordsGetShortDesc}, + {"SourcePkg",PkgRecordsGetSourcePkg}, + {"SourceVer",PkgRecordsGetSourceVer}, +#endif + {} +}; + +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 Py_FindMethod(PkgRecordsMethods,Self,Name); + return HandleErrors(CppOwnedPyObject_NEW<PkgRecordsStruct>(Owner,type, + GetCpp<pkgCache *>(Owner))); } -PyTypeObject PkgRecordsType = + +PyTypeObject PyPackageRecords_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgRecords", // tp_name + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.PackageRecords", // tp_name sizeof(CppOwnedPyObject<PkgRecordsStruct>), // tp_basicsize 0, // tp_itemsize // Methods CppOwnedDealloc<PkgRecordsStruct>, // tp_dealloc 0, // tp_print - PkgRecordsAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr @@ -109,17 +178,43 @@ PyTypeObject PkgRecordsType = 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), + "Records Object", // tp_doc + CppOwnedTraverse<PkgRecordsStruct>, // tp_traverse + CppOwnedClear<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 }; /*}}}*/ + +#ifdef COMPAT_0_7 PyObject *GetPkgRecords(PyObject *Self,PyObject *Args) { - PyObject *Owner; - if (PyArg_ParseTuple(Args,"O!",&PkgCacheType,&Owner) == 0) - return 0; - - return HandleErrors(CppOwnedPyObject_NEW<PkgRecordsStruct>(Owner,&PkgRecordsType, - GetCpp<pkgCache *>(Owner))); + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPkgRecords() is " + "deprecated. Please see apt_pkg.Records() for the " + "replacement.", 1); + return PkgRecordsNew(&PyPackageRecords_Type,Args,0); } - +#endif diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc index 36493e7b..086ec8d5 100644 --- a/python/pkgsrcrecords.cc +++ b/python/pkgsrcrecords.cc @@ -58,7 +58,6 @@ static PyObject *PkgSrcRecordsRestart(PyObject *Self,PyObject *Args) { PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self); - char *Name = 0; if (PyArg_ParseTuple(Args,"") == 0) return 0; @@ -70,87 +69,202 @@ static PyObject *PkgSrcRecordsRestart(PyObject *Self,PyObject *Args) static PyMethodDef PkgSrcRecordsMethods[] = { + {"lookup",PkgSrcRecordsLookup,METH_VARARGS,doc_PkgSrcRecordsLookup}, + {"restart",PkgSrcRecordsRestart,METH_VARARGS,doc_PkgSrcRecordsRestart}, +#ifdef COMPAT_0_7 {"Lookup",PkgSrcRecordsLookup,METH_VARARGS,doc_PkgSrcRecordsLookup}, {"Restart",PkgSrcRecordsRestart,METH_VARARGS,doc_PkgSrcRecordsRestart}, +#endif {} }; -static PyObject *PkgSrcRecordsAttr(PyObject *Self,char *Name) -{ +/** + * 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; +} - if (Struct.Last != 0) - { - if (strcmp("Package",Name) == 0) - return CppPyString(Struct.Last->Package()); - else if (strcmp("Version",Name) == 0) - return CppPyString(Struct.Last->Version()); - else if (strcmp("Maintainer",Name) == 0) - return CppPyString(Struct.Last->Maintainer()); - else if (strcmp("Section",Name) == 0) - return CppPyString(Struct.Last->Section()); - else if (strcmp("Record",Name) == 0) - return CppPyString(Struct.Last->AsStr()); - else if (strcmp("Binaries",Name) == 0) { - PyObject *List = PyList_New(0); - - for(const char **b = Struct.Last->Binaries(); - *b != 0; - ++b) - PyList_Append(List, CppPyString(*b)); - return List; // todo - } else if (strcmp("Index",Name) == 0) { - const pkgIndexFile &tmp = Struct.Last->Index(); - return CppOwnedPyObject_NEW<pkgIndexFile*>(Self,&PackageIndexFileType, (pkgIndexFile*)&tmp); - } else if (strcmp("Files",Name) == 0) { - PyObject *List = PyList_New(0); - - vector<pkgSrcRecords::File> f; - if(!Struct.Last->Files(f)) - return NULL; // error - - PyObject *v; - for(unsigned int i=0;i<f.size();i++) { - v = Py_BuildValue("(siss)", - f[i].MD5Hash.c_str(), - f[i].Size, - f[i].Path.c_str(), - f[i].Type.c_str()); - PyList_Append(List, v); - Py_DECREF(v); +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(); + CppOwnedPyObject<pkgIndexFile*> *PyObj; + PyObj = CppOwnedPyObject_NEW<pkgIndexFile*>(Self,&PyPackageIndexFile_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); + + vector<pkgSrcRecords::File> f; + if(!Struct.Last->Files(f)) + return NULL; // error + + PyObject *v; + for(unsigned int i=0;i<f.size();i++) { + v = Py_BuildValue("(siss)", + f[i].MD5Hash.c_str(), + f[i].Size, + f[i].Path.c_str(), + f[i].Type.c_str()); + 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; + + 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 = PyString_FromString(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); } - return List; - } else if (strcmp("BuildDepends",Name) == 0) { - PyObject *List = PyList_New(0); - - 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++) { - v = Py_BuildValue("(ssii)", bd[i].Package.c_str(), - bd[i].Version.c_str(), bd[i].Op, bd[i].Type); - PyList_Append(List, v); + 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 (1) + { + 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); - } - return List; - } + if (pkgCache::Dep::Or != (bd[i].Op & pkgCache::Dep::Or) || i == bd.size()) + break; + i++; + } + } + return Dict; +} + +#ifdef COMPAT_0_7 +static PyObject *PkgSrcRecordsGetBuildDepends_old(PyObject *Self,void*) { + PkgSrcRecordsStruct &Struct = GetStruct(Self,"BuildDepends"); + if (Struct.Last == 0) + return 0; + PyObject *List = PyList_New(0); + + 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++) { + v = Py_BuildValue("(ssii)", bd[i].Package.c_str(), + bd[i].Version.c_str(), bd[i].Op, bd[i].Type); + PyList_Append(List, v); + Py_DECREF(v); + } + return List; +} +#endif + +static PyGetSetDef PkgSrcRecordsGetSet[] = { + {"binaries",PkgSrcRecordsGetBinaries}, + {"build_depends",PkgSrcRecordsGetBuildDepends}, + {"files",PkgSrcRecordsGetFiles}, + {"index",PkgSrcRecordsGetIndex}, + {"maintainer",PkgSrcRecordsGetMaintainer}, + {"package",PkgSrcRecordsGetPackage}, + {"record",PkgSrcRecordsGetRecord}, + {"section",PkgSrcRecordsGetSection}, + {"version",PkgSrcRecordsGetVersion}, +#ifdef COMPAT_0_7 + {"Binaries",PkgSrcRecordsGetBinaries}, + {"BuildDepends",PkgSrcRecordsGetBuildDepends_old,0,"Deprecated function and deprecated output format."}, + {"Files",PkgSrcRecordsGetFiles}, + {"Index",PkgSrcRecordsGetIndex}, + {"Maintainer",PkgSrcRecordsGetMaintainer}, + {"Package",PkgSrcRecordsGetPackage}, + {"Record",PkgSrcRecordsGetRecord}, + {"Section",PkgSrcRecordsGetSection}, + {"Version",PkgSrcRecordsGetVersion}, +#endif + {} +}; - return Py_FindMethod(PkgSrcRecordsMethods,Self,Name); +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>(type)); } -PyTypeObject PkgSrcRecordsType = + +PyTypeObject PySourceRecords_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgSrcRecords", // tp_name + 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 - PkgSrcRecordsAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr @@ -158,23 +272,44 @@ PyTypeObject PkgSrcRecordsType = 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), + "SourceRecords Object", // 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 }; /*}}}*/ +#ifdef COMPAT_0_7 PyObject *GetPkgSrcRecords(PyObject *Self,PyObject *Args) { -#if 0 - PyObject *Owner; - if (PyArg_ParseTuple(Args,"O!",&PkgCacheType,&Owner) == 0) - return 0; - - return HandleErrors(CppOwnedPyObject_NEW<PkgSrcRecordsStruct>(Owner, - &PkgSrcRecordsType)); -#endif + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPkgSrcRecords() is " + "deprecated. Please see apt_pkg.SourceRecords() for the " + "replacement.", 1); if (PyArg_ParseTuple(Args,"") == 0) return 0; - return HandleErrors(CppPyObject_NEW<PkgSrcRecordsStruct>(&PkgSrcRecordsType)); + return HandleErrors(CppPyObject_NEW<PkgSrcRecordsStruct>(&PySourceRecords_Type)); } - +#endif diff --git a/python/policy.cc b/python/policy.cc new file mode 100644 index 00000000..faf53b38 --- /dev/null +++ b/python/policy.cc @@ -0,0 +1,205 @@ +/* + * 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 CppOwnedPyObject_NEW<pkgPolicy*>(cache,&PyPolicy_Type,policy); +} + +static char *Policy_GetPriority_doc = "get_priority(package: apt_pkg.Package)" + " -> int\n\n" + "Return the priority of the package."; + +PyObject *Policy_GetPriority(PyObject *self, PyObject *arg) { + pkgPolicy *policy = GetCpp<pkgPolicy *>(self); + if (PyObject_TypeCheck(arg, &PyPackage_Type)) { + pkgCache::PkgIterator pkg = GetCpp<pkgCache::PkgIterator>(arg); + return Py_BuildValue("i", policy->GetPriority(pkg)); + } else { + PyErr_SetString(PyExc_TypeError,"Argument must be of Package()."); + return 0; + } +} + +static char *Policy_GetCandidateVer_doc = "get_match(package: apt_pkg.Package)" + " -> apt_pkg.Version\n\n" + "Get the best package for the job."; + +PyObject *Policy_GetCandidateVer(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); + return CppOwnedPyObject_NEW<pkgCache::VerIterator>(arg,&PyVersion_Type, + ver); + } else { + PyErr_SetString(PyExc_TypeError,"Argument must be of Package()."); + return 0; + } +} + +static char *Policy_GetMatch_doc = "get_match(package: apt_pkg.Package) -> " + "apt_pkg.Version\n\n" + "Return a matching version for the given package."; + +static PyObject *Policy_GetMatch(PyObject *self, PyObject *arg) { + if (PyObject_TypeCheck(arg, &PyPackage_Type) == 0) { + PyErr_SetString(PyExc_TypeError,"Argument must be of Package()."); + return 0; + } + pkgPolicy *policy = GetCpp<pkgPolicy *>(self); + pkgCache::PkgIterator pkg = GetCpp<pkgCache::PkgIterator>(arg); + pkgCache::VerIterator ver = policy->GetMatch(pkg); + return CppOwnedPyObject_NEW<pkgCache::VerIterator>(arg,&PyVersion_Type,ver); +} + +static char *Policy_ReadPinFile_doc = "read_pinfile(filename: str) -> bool\n\n" + "Read the pin file given by filename (e.g. '/etc/apt/preferences') and\n" + "add it to the policy."; + +static PyObject *Policy_ReadPinFile(PyObject *self, PyObject *arg) { + if (!PyString_Check(arg)) + return 0; + pkgPolicy *policy = GetCpp<pkgPolicy *>(self); + + return PyBool_FromLong(ReadPinFile(*policy, PyString_AsString(arg))); +} + +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 8) +static char *Policy_ReadPinDir_doc = "read_pindir(dirname: str) -> bool\n\n" + "Read the pin files in the given dir (e.g. '/etc/apt/preferences.d') and\n" + "add them to the policy."; + +static PyObject *Policy_ReadPinDir(PyObject *self, PyObject *arg) { + if (!PyString_Check(arg)) + return 0; + pkgPolicy *policy = GetCpp<pkgPolicy *>(self); + + return PyBool_FromLong(ReadPinDir(*policy, PyString_AsString(arg))); +} +#endif + +static char *Policy_CreatePin_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" + "following strings: 'Version', 'Release', 'Origin'. The argument 'pkg'\n" + "is the 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_CreatePin(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; + if (strcmp(type,"Release") == 0 || strcmp(type, "release") == 0) + match_type = pkgVersionMatch::Release; + 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 PyMethodDef Policy_Methods[] = { + {"get_priority",(PyCFunction)Policy_GetPriority,METH_O, + Policy_GetPriority_doc}, + {"get_candidate_ver",(PyCFunction)Policy_GetCandidateVer,METH_O, + Policy_GetCandidateVer_doc}, + {"read_pinfile",(PyCFunction)Policy_ReadPinFile,METH_O, + Policy_ReadPinFile_doc}, +#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 8) + {"read_pindir",(PyCFunction)Policy_ReadPinDir,METH_O, + Policy_ReadPinFile_doc}, +#endif + {"create_pin",Policy_CreatePin,METH_VARARGS,Policy_CreatePin_doc}, + {"get_match",(PyCFunction)Policy_GetMatch,METH_O, Policy_GetMatch_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(CppOwnedPyObject<pkgPolicy*>),// tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDeallocPtr<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 + CppOwnedTraverse<pkgPolicy*>, // tp_traverse + CppOwnedClear<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 index 82967687..30f62763 100644 --- a/python/progress.cc +++ b/python/progress.cc @@ -13,8 +13,33 @@ #include <utility> #include <apt-pkg/acquire-item.h> #include <apt-pkg/acquire-worker.h> -#include "generic.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); + + 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, @@ -36,8 +61,8 @@ bool PyCallbackObj::RunSimpleCallback(const char* method_name, } return false; } - PyObject *result = PyEval_CallObject(method, arglist); - + + PyObject *result = PyObject_CallObject(method, arglist); Py_XDECREF(arglist); if(result == NULL) { @@ -61,26 +86,25 @@ bool PyCallbackObj::RunSimpleCallback(const char* method_name, // OpProgress interface void PyOpProgress::Update() { - PyObject *o; - o = Py_BuildValue("s", Op.c_str()); - PyObject_SetAttrString(callbackInst, "op", o); - Py_XDECREF(o); - o = Py_BuildValue("s", SubOp.c_str()); - PyObject_SetAttrString(callbackInst, "subOp", o); - Py_XDECREF(o); - o = Py_BuildValue("b", MajorChange); - PyObject_SetAttrString(callbackInst, "majorChange", o); - Py_XDECREF(o); - - // CheckChange takes a time delta argument how often we - // should run update - for interactive UIs it makes sense - // to run ~25/sec - if(CheckChange(0.04)) - { - PyObject *arglist = Py_BuildValue("(f)", Percent); - RunSimpleCallback("update", arglist); - } -}; + // 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); +#ifdef COMPAT_0_7 + setattr(callbackInst, "Op", "s", Op.c_str()); + setattr(callbackInst, "subOp", "s", SubOp.c_str()); + setattr(callbackInst, "majorChange", "b", MajorChange); + PyObject *arglist = Py_BuildValue("(f)", Percent); + RunSimpleCallback("update", arglist); +#else + setattr(callbackInst, "percent", "f", Percent); + RunSimpleCallback("update"); +#endif +} void PyOpProgress::Done() { @@ -101,7 +125,8 @@ bool PyFetchProgress::MediaChange(string Media, string Drive) //std::cout << "MediaChange" << std::endl; PyObject *arglist = Py_BuildValue("(ss)", Media.c_str(), Drive.c_str()); PyObject *result; - RunSimpleCallback("mediaChange", arglist, &result); + if(! RunSimpleCallback("media_change", arglist, &result)) + RunSimpleCallback("mediaChange", arglist, &result); bool res = true; if(!PyArg_Parse(result, "b", &res)) { @@ -116,14 +141,12 @@ bool PyFetchProgress::MediaChange(string Media, string Drive) void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status) { //std::cout << "UpdateStatus: " << Itm.URI << " " << status << std::endl; - // Added object file size and object partial size to // parameters that are passed to updateStatus. // -- Stephan - PyCbObj_END_ALLOW_THREADS - PyObject *arglist = Py_BuildValue("(sssikk)", Itm.URI.c_str(), - Itm.Description.c_str(), - Itm.ShortDesc.c_str(), + PyObject *arglist = Py_BuildValue("(sssikk)", Itm.URI.c_str(), + Itm.Description.c_str(), + Itm.ShortDesc.c_str(), status, Itm.Owner->FileSize, Itm.Owner->PartialSize); @@ -131,32 +154,52 @@ void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status) RunSimpleCallback("update_status_full", arglist); // legacy version of the interface - arglist = Py_BuildValue("(sssi)", Itm.URI.c_str(), - Itm.Description.c_str(), - Itm.ShortDesc.c_str(), - status); - RunSimpleCallback("updateStatus", arglist); - PyCbObj_BEGIN_ALLOW_THREADS + arglist = Py_BuildValue("(sssi)", Itm.URI.c_str(), Itm.Description.c_str(), + Itm.ShortDesc.c_str(), status); + + if(!RunSimpleCallback("update_status", arglist)) + RunSimpleCallback("updateStatus", arglist); } void PyFetchProgress::IMSHit(pkgAcquire::ItemDesc &Itm) { - UpdateStatus(Itm, DLHit); + PyCbObj_END_ALLOW_THREADS + if (PyObject_HasAttrString(callbackInst, "ims_hit")) + RunSimpleCallback("ims_hit", TUPLEIZE(PyAcquire_GetItemDesc(pyAcquire, &Itm))); + else + UpdateStatus(Itm, DLHit); + PyCbObj_BEGIN_ALLOW_THREADS } void PyFetchProgress::Fetch(pkgAcquire::ItemDesc &Itm) { - UpdateStatus(Itm, DLQueued); + PyCbObj_END_ALLOW_THREADS + if (PyObject_HasAttrString(callbackInst, "fetch")) + RunSimpleCallback("fetch", TUPLEIZE(PyAcquire_GetItemDesc(pyAcquire, &Itm))); + else + UpdateStatus(Itm, DLQueued); + PyCbObj_BEGIN_ALLOW_THREADS } void PyFetchProgress::Done(pkgAcquire::ItemDesc &Itm) { - UpdateStatus(Itm, DLDone); + PyCbObj_END_ALLOW_THREADS + if (PyObject_HasAttrString(callbackInst, "done")) + RunSimpleCallback("done", TUPLEIZE(PyAcquire_GetItemDesc(pyAcquire, &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(PyAcquire_GetItemDesc(pyAcquire, &Itm))); + return; + } + // Ignore certain kinds of transient failures (bad code) if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) return; @@ -166,7 +209,12 @@ void PyFetchProgress::Fail(pkgAcquire::ItemDesc &Itm) UpdateStatus(Itm, DLIgnored); } - UpdateStatus(Itm, DLFailed); + + if (PyObject_HasAttrString(callbackInst, "fail")) + RunSimpleCallback("fail", TUPLEIZE(PyAcquire_GetItemDesc(pyAcquire, &Itm))); + else + UpdateStatus(Itm, DLFailed); + PyCbObj_BEGIN_ALLOW_THREADS } void PyFetchProgress::Start() @@ -174,26 +222,13 @@ void PyFetchProgress::Start() //std::cout << "Start" << std::endl; pkgAcquireStatus::Start(); - // These attributes should be initialized before the first callback (start) - // is invoked. - // -- Stephan - PyObject *o; - - o = Py_BuildValue("f", 0.0f); - PyObject_SetAttrString(callbackInst, "currentCPS", o); - Py_XDECREF(o); - o = Py_BuildValue("f", 0.0f); - PyObject_SetAttrString(callbackInst, "currentBytes", o); - Py_XDECREF(o); - o = Py_BuildValue("i", 0); - PyObject_SetAttrString(callbackInst, "currentItems", o); - Py_XDECREF(o); - o = Py_BuildValue("i", 0); - PyObject_SetAttrString(callbackInst, "totalItems", o); - Py_XDECREF(o); - o = Py_BuildValue("f", 0.0f); - PyObject_SetAttrString(callbackInst, "totalBytes", o); - Py_XDECREF(o); +#ifdef COMPAT_0_7 + setattr(callbackInst, "currentCPS", "d", 0); + setattr(callbackInst, "currentBytes", "d", 0); + setattr(callbackInst, "currentItems", "k", 0); + setattr(callbackInst, "totalItems", "k", 0); + setattr(callbackInst, "totalBytes", "d", 0); +#endif RunSimpleCallback("start"); /* After calling the start method we can safely allow @@ -206,10 +241,11 @@ void PyFetchProgress::Start() void PyFetchProgress::Stop() { /* After the stop operation occured no other threads - * are allowed. This is done so we have a matching + * 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 //std::cout << "Stop" << std::endl; pkgAcquireStatus::Stop(); @@ -225,28 +261,52 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) if(callbackInst == 0) return false; - // set stats - PyObject *o; - o = Py_BuildValue("f", CurrentCPS); - PyObject_SetAttrString(callbackInst, "currentCPS", o); - Py_XDECREF(o); - o = Py_BuildValue("f", CurrentBytes); - PyObject_SetAttrString(callbackInst, "currentBytes", o); - Py_XDECREF(o); - o = Py_BuildValue("i", CurrentItems); - PyObject_SetAttrString(callbackInst, "currentItems", o); - Py_XDECREF(o); - o = Py_BuildValue("i", TotalItems); - PyObject_SetAttrString(callbackInst, "totalItems", o); - Py_XDECREF(o); - o = Py_BuildValue("f", TotalBytes); - PyObject_SetAttrString(callbackInst, "totalBytes", o); - Py_XDECREF(o); + setattr(callbackInst, "last_bytes", "d", LastBytes); + setattr(callbackInst, "current_cps", "d", CurrentCPS); + setattr(callbackInst, "current_bytes", "d", CurrentBytes); + setattr(callbackInst, "total_bytes", "d", TotalBytes); + setattr(callbackInst, "fetched_bytes", "d", FetchedBytes); + setattr(callbackInst, "elapsed_time", "k", ElapsedTime); + setattr(callbackInst, "current_items", "k", CurrentItems); + setattr(callbackInst, "total_items", "k", TotalItems); +#ifdef COMPAT_0_7 + setattr(callbackInst, "currentCPS", "d", CurrentCPS); + setattr(callbackInst, "currentBytes", "d", CurrentBytes); + setattr(callbackInst, "totalBytes", "d", TotalBytes); + setattr(callbackInst, "fetchedBytes", "d", FetchedBytes); + setattr(callbackInst, "currentItems", "k", CurrentItems); + setattr(callbackInst, "totalItems", "k", TotalItems); +#endif + + // New style +#ifdef COMPAT_0_7 + if (!PyObject_HasAttrString(callbackInst, "updateStatus")) { +#else + { +#endif + PyObject *result1; + bool res1 = true; + + Py_INCREF(pyAcquire); + + if (RunSimpleCallback("pulse", TUPLEIZE(pyAcquire) , &result1)) { + if (result1 != NULL && 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; + + + } +#ifdef COMPAT_0_7 // Go through the list of items and add active items to the // activeItems vector. map<pkgAcquire::Worker *, pkgAcquire::ItemDesc *> activeItemMap; - + for(pkgAcquire::Worker *Worker = Owner->WorkersBegin(); Worker != 0; Worker = Owner->WorkerStep(Worker)) { @@ -256,7 +316,7 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) } activeItemMap.insert(std::make_pair(Worker, Worker->CurrentItem)); } - + // Create the tuple that is passed as argument to pulse(). // This tuple contains activeItemMap.size() item tuples. PyObject *arglist; @@ -270,8 +330,8 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) map<pkgAcquire::Worker *, pkgAcquire::ItemDesc *>::iterator iter; int tuplePos; - for(tuplePos = 0, iter = activeItemMap.begin(); - iter != activeItemMap.end(); ++iter, tuplePos++) { + for(tuplePos = 0, iter = activeItemMap.begin(); + iter != activeItemMap.end(); ++iter, tuplePos++) { pkgAcquire::Worker *worker = iter->first; pkgAcquire::ItemDesc *itm = iter->second; @@ -304,13 +364,15 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) PyObject *result; bool res = true; - RunSimpleCallback("pulse_items", arglist, &result); - if (result != NULL && PyArg_Parse(result, "b", &res) && res == false) { - // the user returned a explicit false here, stop - PyCbObj_BEGIN_ALLOW_THREADS - return false; + if (RunSimpleCallback("pulse_items", arglist, &result)) { + if (result != NULL && PyArg_Parse(result, "b", &res) && res == false) { + // the user returned a explicit false here, stop + PyCbObj_BEGIN_ALLOW_THREADS + return false; + } } + arglist = Py_BuildValue("()"); if (!RunSimpleCallback("pulse", arglist, &result)) { PyCbObj_BEGIN_ALLOW_THREADS @@ -319,7 +381,7 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) if((result == NULL) || (!PyArg_Parse(result, "b", &res))) { - // most of the time the user who subclasses the pulse() + // most of the time the user who subclasses the pulse() // method forgot to add a return {True,False} so we just // assume he wants a True PyCbObj_BEGIN_ALLOW_THREADS @@ -329,6 +391,7 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) PyCbObj_BEGIN_ALLOW_THREADS // fetching can be canceld by returning false return res; +#endif } @@ -337,26 +400,28 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner) void PyInstallProgress::StartUpdate() { - RunSimpleCallback("startUpdate"); + if (!RunSimpleCallback("start_update")) + RunSimpleCallback("startUpdate"); PyCbObj_BEGIN_ALLOW_THREADS } void PyInstallProgress::UpdateInterface() { PyCbObj_END_ALLOW_THREADS - RunSimpleCallback("updateInterface"); + if (!RunSimpleCallback("update_interface")) + RunSimpleCallback("updateInterface"); PyCbObj_BEGIN_ALLOW_THREADS } void PyInstallProgress::FinishUpdate() { PyCbObj_END_ALLOW_THREADS - RunSimpleCallback("finishUpdate"); + if (!RunSimpleCallback("finish_update")) + RunSimpleCallback("finishUpdate"); } pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) { - void *dummy; pkgPackageManager::OrderResult res; int ret; pid_t child_id; @@ -372,7 +437,7 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) PyObject *method = PyObject_GetAttrString(callbackInst, "fork"); std::cerr << "custom fork found" << std::endl; PyObject *arglist = Py_BuildValue("()"); - PyObject *result = PyEval_CallObject(method, arglist); + PyObject *result = PyObject_CallObject(method, arglist); Py_DECREF(arglist); if (result == NULL) { std::cerr << "fork method invalid" << std::endl; @@ -411,19 +476,24 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) StartUpdate(); + PyCbObj_END_ALLOW_THREADS - if(PyObject_HasAttrString(callbackInst, "waitChild")) { - PyObject *method = PyObject_GetAttrString(callbackInst, "waitChild"); + if(PyObject_HasAttrString(callbackInst, "waitChild") || + PyObject_HasAttrString(callbackInst, "wait_child")) { + PyObject *method; + if (PyObject_HasAttrString(callbackInst, "wait_child")) + method = PyObject_GetAttrString(callbackInst, "wait_child"); + else + method = PyObject_GetAttrString(callbackInst, "waitChild"); //std::cerr << "custom waitChild found" << std::endl; PyObject *arglist = Py_BuildValue("(i)",child_id); - PyObject *result = PyEval_CallObject(method, arglist); + PyObject *result = PyObject_CallObject(method, arglist); Py_DECREF(arglist); if (result == NULL) { std::cerr << "waitChild method invalid" << std::endl; PyErr_Print(); return pkgPackageManager::Failed; } - int child_res; if(!PyArg_Parse(result, "i", &res) ) { std::cerr << "custom waitChild() result could not be parsed?"<< std::endl; PyCbObj_BEGIN_ALLOW_THREADS @@ -456,11 +526,10 @@ pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm) void PyCdromProgress::Update(string text, int current) { PyObject *arglist = Py_BuildValue("(si)", text.c_str(), current); - - PyObject *o = Py_BuildValue("i", totalSteps); - PyObject_SetAttrString(callbackInst, "totalSteps", o); - Py_XDECREF(o); - + setattr(callbackInst, "total_steps", "i", totalSteps); + #ifdef COMPAT_0_7 + setattr(callbackInst, "totalSteps", "i", totalSteps); + #endif RunSimpleCallback("update", arglist); } @@ -468,7 +537,8 @@ bool PyCdromProgress::ChangeCdrom() { PyObject *arglist = Py_BuildValue("()"); PyObject *result; - RunSimpleCallback("changeCdrom", arglist, &result); + if(!RunSimpleCallback("change_cdrom", arglist, &result)) + RunSimpleCallback("changeCdrom", arglist, &result); bool res = true; if(!PyArg_Parse(result, "b", &res)) @@ -481,18 +551,28 @@ bool PyCdromProgress::ChangeCdrom() bool PyCdromProgress::AskCdromName(string &Name) { PyObject *arglist = Py_BuildValue("()"); - PyObject *result; - RunSimpleCallback("askCdromName", arglist, &result); - const char *new_name; bool res; - if(!PyArg_Parse(result, "(bs)", &res, &new_name)) - std::cerr << "AskCdromName: result could not be parsed" << std::endl; - - //std::cerr << "got: " << res << " " << "name: " << new_name << std::endl; - - // set the new name - Name = string(new_name); + PyObject *result; - return res; + // New style: String on success, None on failure. + if (RunSimpleCallback("ask_cdrom_name", arglist, &result)) { + if(result == Py_None) + return false; + if(!PyArg_Parse(result, "s", &new_name)) + std::cerr << "AskCdromName: result could not be parsed" << std::endl; + else + Name = string(new_name); + return true; + } + // Old style: (True, name) on success, (False, name) on failure. + else { + RunSimpleCallback("askCdromName", 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 = string(new_name); + + return res; + } } diff --git a/python/progress.h b/python/progress.h index 29243bfc..80cb2785 100644 --- a/python/progress.h +++ b/python/progress.h @@ -18,7 +18,7 @@ /* 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 + * 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 @@ -62,6 +62,9 @@ struct PyOpProgress : public OpProgress, public PyCallbackObj struct PyFetchProgress : public pkgAcquireStatus, public PyCallbackObj { + protected: + PyObject *pyAcquire; + public: enum { DLDone, DLQueued, DLFailed, DLHit, DLIgnored }; @@ -70,6 +73,10 @@ struct PyFetchProgress : public pkgAcquireStatus, public PyCallbackObj virtual bool MediaChange(string Media, string Drive); + void setPyAcquire(PyObject *o) { + pyAcquire = o; + } + /* apt stuff */ virtual void IMSHit(pkgAcquire::ItemDesc &Itm); virtual void Fetch(pkgAcquire::ItemDesc &Itm); diff --git a/python/python-apt.h b/python/python-apt.h new file mode 100644 index 00000000..08242c08 --- /dev/null +++ b/python/python-apt.h @@ -0,0 +1,271 @@ +/* + * python-apt.h - Header file for the public interface. + * + * 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. + */ + +#ifndef PYTHON_APT_H +#define PYTHON_APT_H +#include <Python.h> +#include "generic.h" + +struct _PyAptPkgAPIStruct { + PyTypeObject *acquire_type; + PyTypeObject *acquirefile_type; + PyTypeObject *acquireitem_type; + PyTypeObject *acquireitemdesc_type; + PyTypeObject *acquireworker_type; + PyTypeObject *actiongroup_type; + PyTypeObject *cache_type; + PyTypeObject *cachefile_type; + PyTypeObject *cdrom_type; + PyTypeObject *configuration_type; + PyTypeObject *depcache_type; + PyTypeObject *dependency_type; + PyTypeObject *dependencylist_type; + PyTypeObject *description_type; + PyTypeObject *hashes_type; + PyTypeObject *hashstring_type; + PyTypeObject *indexrecords_type; + PyTypeObject *metaindex_type; + PyTypeObject *package_type; + PyTypeObject *packagefile_type; + PyTypeObject *packageindexfile_type; + PyTypeObject *packagelist_type; + PyTypeObject *packagemanager_type; + PyTypeObject *packagerecords_type; + PyTypeObject *policy_type; + PyTypeObject *problemresolver_type; + PyTypeObject *sourcelist_type; + PyTypeObject *sourcerecords_type; + PyTypeObject *tagfile_type; + PyTypeObject *tagsection_type; + PyTypeObject *version_type; +}; + +# ifndef APT_PKGMODULE_H +# 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 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 PyPackageIndexFile_Type *(_PyAptPkg_API->packageindexfile_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 PyTagFile_Type *(_PyAptPkg_API->tagfile_type) +# define PyTagSection_Type *(_PyAptPkg_API->tagsection_type) +# define PyVersion_Type *(_PyAptPkg_API->version_type) + +// Creating + +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); + return (_PyAptPkg_API != NULL) ? 0 : -1; +# else + + PyObject *module = PyImport_ImportModule("apt_pkg"); + + if (module == NULL) { + return -1; + } + if (module != NULL) { + PyObject *c_api_object = PyObject_GetAttrString(module, "_C_API"); + if (c_api_object == NULL) + return -1; + if (PyCObject_Check(c_api_object)) + _PyAptPkg_API = (struct _PyAptPkgAPIStruct *)PyCObject_AsVoidPtr(c_api_object); + Py_DECREF(c_api_object); + } + return 0; +# endif // PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1 +} +# endif // APT_PKGMODULE_H + +// 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 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 PyPackageIndexFile_Check(op) PyObject_TypeCheck(op, &PyPackageIndexFile_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 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 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 PyPackageIndexFile_CheckExact(op) (op->op_type == &PyPackageIndexFile_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 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) + +// Get the underlying C++ reference or pointer from the Python object. +# 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> // NOT EXPORTED +# define PyDescription_ToCpp GetCpp<pkgCache::DescIterator> +# define PyHashes_ToCpp GetCpp<Hashes> +# define PyHashString_ToCpp GetCpp<HashString*> +# define PyIndexRecords_ToCpp GetCpp<indexRecords*> +# define PyMetaIndex_ToCpp GetCpp<metaIndex*> +# define PyPackage_ToCpp GetCpp<pkgCache::PkgIterator> +# define PyPackageFile_ToCpp GetCpp<pkgCache::PkgFileIterator> +# define PyPackageIndexFile_ToCpp GetCpp<pkgIndexFile*> +//# define PyPackageList_ToCpp GetCpp<PkgListStruct> // NOT EXPORTED. +# define PyPackageManager_ToCpp GetCpp<pkgPackageManager*> +//# define PyPackageRecords_ToCpp GetCpp<PkgRecordsStruct> // NOT EXPORTED +# define PyPolicy_ToCpp GetCpp<pkgPolicy*> +# define PyProblemResolver_ToCpp GetCpp<pkgProblemResolver*> +# define PySourceList_ToCpp GetCpp<pkgSourceList*> +//# define PySourceRecords_ToCpp GetCpp<PkgSrcRecordsStruct> // NOT EXPORTED +# define PyTagFile_ToCpp GetCpp<pkgTagFile> +# define PyTagSection_ToCpp GetCpp<pkgTagSection> +# define PyVersion_ToCpp GetCpp<pkgCache::VerIterator> + +// Python object creation, using two inline template functions and one variadic +// macro per type. +template<class Cpp> +inline CppPyObject<Cpp> *FromCpp(PyTypeObject *pytype, Cpp obj, + bool Delete=false) +{ + CppPyObject<Cpp> *Obj = CppPyObject_NEW<Cpp>(pytype, obj); + Obj->NoDelete = (!Delete); + return Obj; +} + +template<class Cpp> +inline CppOwnedPyObject<Cpp> *FromCppOwned(PyTypeObject *pytype, Cpp const &obj, + bool Delete=false, PyObject *Owner=NULL) +{ + CppOwnedPyObject<Cpp> *Obj = CppOwnedPyObject_NEW<Cpp>(Owner, pytype, obj); + Obj->NoDelete = (!Delete); + return Obj; +} + +# define PyAcquire_FromCpp(...) FromCpp<pkgAcquire*>(&PyAcquire_Type, ##__VA_ARGS__) +# define PyAcquireFile_FromCpp(...) FromCppOwned<pkgAcqFile*>(&PyAcquireFile_Type, ##__VA_ARGS__) +# define PyAcquireItem_FromCpp(...) FromCppOwned<pkgAcquire::Item*>(&PyAcquireItem_Type,##__VA_ARGS__) +# define PyAcquireItemDesc_FromCpp(...) FromCppOwned<pkgAcquire::ItemDesc*>(&PyAcquireItemDesc_Type,##__VA_ARGS__) +# define PyAcquireWorker_FromCpp(...) FromCppOwned<pkgAcquire::Worker*>(&PyAcquireWorker_Type,##__VA_ARGS__) +# define PyActionGroup_FromCpp(...) FromCppOwned<pkgDepCache::ActionGroup*>(&PyActionGroup_Type,##__VA_ARGS__) +# define PyCache_FromCpp(...) FromCppOwned<pkgCache*>(&PyCache_Type,##__VA_ARGS__) +# define PyCacheFile_FromCpp(...) FromCpp<pkgCacheFile*>(&PyCacheFile_Type,##__VA_ARGS__) +# define PyCdrom_FromCpp(...) FromCpp<pkgCdrom>(&PyCdrom_Type,##__VA_ARGS__) +# define PyConfiguration_FromCpp(...) FromCppOwned<Configuration*>(&PyConfiguration_Type, ##__VA_ARGS__) +# define PyDepCache_FromCpp(...) FromCppOwned<pkgDepCache*>(&PyDepCache_Type,##__VA_ARGS__) +# define PyDependency_FromCpp(...) FromCppOwned<pkgCache::DepIterator>(&PyDependency_Type,##__VA_ARGS__) +//# define PyDependencyList_FromCpp(...) FromCppOwned<RDepListStruct>(&PyDependencyList_Type,##__VA_ARGS__) +# define PyDescription_FromCpp(...) FromCppOwned<pkgCache::DescIterator>(&PyDescription_Type,##__VA_ARGS__) +# define PyHashes_FromCpp(...) FromCpp<Hashes>(&PyHashes_Type,##__VA_ARGS__) +# define PyHashString_FromCpp(...) FromCpp<HashString*>(&PyHashString_Type,##__VA_ARGS__) +# define PyIndexRecords_FromCpp(...) FromCpp<indexRecords*>(&PyIndexRecords_Type,##__VA_ARGS__) +# define PyMetaIndex_FromCpp(...) FromCppOwned<metaIndex*>(&PyMetaIndex_Type,##__VA_ARGS__) +# define PyPackage_FromCpp(...) FromCppOwned<pkgCache::PkgIterator>(&PyPackage_Type,##__VA_ARGS__) +# define PyPackageIndexFile_FromCpp(...) FromCppOwned<pkgIndexFile*>(&PyPackageIndexFile_Type,##__VA_ARGS__) +# define PyPackageFile_FromCpp(...) FromCppOwned<pkgCache::PkgFileIterator>(&PyPackageFile_Type,##__VA_ARGS__) +//# define PyPackageList_FromCpp(...) FromCppOwned<PkgListStruct>(&PyPackageList_Type,##__VA_ARGS__) +# define PyPackageManager_FromCpp(...) FromCpp<pkgPackageManager*>(&PyPackageManager_Type,##__VA_ARGS__) +//# define PyPackageRecords_FromCpp(...) FromCppOwned<PkgRecordsStruct>(&PyPackageRecords_Type,##__VA_ARGS__) +# define PyPolicy_FromCpp(...) FromCppOwned<pkgPolicy*>(&PyPolicy_Type,##__VA_ARGS__) +# define PyProblemResolver_FromCpp(...) FromCppOwned<pkgProblemResolver*>(&PyProblemResolver_Type,##__VA_ARGS__) +# define PySourceList_FromCpp(...) FromCpp<pkgSourceList*>(&PySourceList_Type,##__VA_ARGS__) +//# define PySourceRecords_FromCpp(...) FromCpp<PkgSrcRecordsStruct>(&PySourceRecords_Type,##__VA_ARGS__) +# define PyTagFile_FromCpp(...) FromCppOwned<pkgTagFile>(&PyTagFile_Type,##__VA_ARGS__) +# define PyTagSection_FromCpp(...) FromCppOwned<pkgTagSection>(&PyTagSection_Type,##__VA_ARGS__) +# define PyVersion_FromCpp(...) FromCppOwned<pkgCache::VerIterator>(&PyVersion_Type,##__VA_ARGS__) +#endif diff --git a/python/sourcelist.cc b/python/sourcelist.cc index 5dcaf86b..e86f7fd3 100644 --- a/python/sourcelist.cc +++ b/python/sourcelist.cc @@ -26,20 +26,22 @@ static PyObject *PkgSourceListFindIndex(PyObject *Self,PyObject *Args) { pkgSourceList *list = GetCpp<pkgSourceList*>(Self); PyObject *pyPkgFileIter; - PyObject *pyPkgIndexFile; + CppOwnedPyObject<pkgIndexFile*> *pyPkgIndexFile; - if (PyArg_ParseTuple(Args, "O!", &PackageFileType,&pyPkgFileIter) == 0) + 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 = CppOwnedPyObject_NEW<pkgIndexFile*>(pyPkgFileIter,&PackageIndexFileType,index); + pyPkgIndexFile = CppOwnedPyObject_NEW<pkgIndexFile*>(pyPkgFileIter,&PyPackageIndexFile_Type,index); + // Do not delete the pkgIndexFile*, it is managed by pkgSourceList. + pyPkgIndexFile->NoDelete = true; return pyPkgIndexFile; } - //&PackageIndexFileType,&pyPkgIndexFile) + //&PyPackageIndexFile_Type,&pyPkgIndexFile) Py_INCREF(Py_None); return Py_None; @@ -61,7 +63,7 @@ static PyObject *PkgSourceListGetIndexes(PyObject *Self,PyObject *Args) PyObject *pyFetcher; char all = 0; - if (PyArg_ParseTuple(Args, "O!|b",&PkgAcquireType,&pyFetcher, &all) == 0) + if (PyArg_ParseTuple(Args, "O!|b",&PyAcquire_Type,&pyFetcher, &all) == 0) return 0; pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyFetcher); @@ -72,41 +74,60 @@ static PyObject *PkgSourceListGetIndexes(PyObject *Self,PyObject *Args) 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}, +#ifdef COMPAT_0_7 {"FindIndex",PkgSourceListFindIndex,METH_VARARGS,doc_PkgSourceListFindIndex}, {"ReadMainList",PkgSourceListReadMainList,METH_VARARGS,doc_PkgSourceListReadMainList}, - {"GetIndexes",PkgSourceListGetIndexes,METH_VARARGS,doc_PkgSourceListReadMainList}, + {"GetIndexes",PkgSourceListGetIndexes,METH_VARARGS,doc_PkgSourceListGetIndexes}, +#endif {} }; -static PyObject *PkgSourceListAttr(PyObject *Self,char *Name) +static PyObject *PkgSourceListGetList(PyObject *Self,void*) { pkgSourceList *list = GetCpp<pkgSourceList*>(Self); - - if (strcmp("List",Name) == 0) + PyObject *List = PyList_New(0); + for (vector<metaIndex *>::const_iterator I = list->begin(); + I != list->end(); I++) { - PyObject *List = PyList_New(0); - for (vector<metaIndex *>::const_iterator I = list->begin(); - I != list->end(); I++) - { - PyObject *Obj; - Obj = CppPyObject_NEW<metaIndex*>(&MetaIndexType,*I); - PyList_Append(List,Obj); - } - return List; + CppOwnedPyObject<metaIndex*> *Obj; + Obj = CppOwnedPyObject_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 Py_FindMethod(PkgSourceListMethods,Self,Name); + return List; } -PyTypeObject PkgSourceListType = + +static PyGetSetDef PkgSourceListGetSet[] = { + {"list",PkgSourceListGetList,0,"A list of MetaIndex() objects.",0}, +#ifdef COMPAT_0_7 + {"List",PkgSourceListGetList,0,"A list of MetaIndex() objects.",0}, +#endif + {} +}; + +static PyObject *PkgSourceListNew(PyTypeObject *type,PyObject *args,PyObject *kwds) { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "pkgSourceList", // tp_name + char *kwlist[] = {0}; + if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0) + return 0; + return CppPyObject_NEW<pkgSourceList*>(type,new pkgSourceList()); +} + +PyTypeObject PySourceList_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.SourceList", // tp_name sizeof(CppPyObject<pkgSourceList*>), // tp_basicsize 0, // tp_itemsize // Methods - CppDealloc<pkgSourceList*>, // tp_dealloc + CppDeallocPtr<pkgSourceList*>, // tp_dealloc 0, // tp_print - PkgSourceListAttr, // tp_getattr + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr @@ -114,10 +135,39 @@ PyTypeObject PkgSourceListType = 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), + "pkgSourceList Object", // 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 }; +#ifdef COMPAT_0_7 PyObject *GetPkgSourceList(PyObject *Self,PyObject *Args) { - return CppPyObject_NEW<pkgSourceList*>(&PkgSourceListType,new pkgSourceList()); + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.GetPkgSourceList() is " + "deprecated. Please see apt_pkg.SourceList() for the " + "replacement.", 1); + return PkgSourceListNew(&PySourceList_Type,Args,0); } - +#endif diff --git a/python/string.cc b/python/string.cc index 8168ea5b..b95ee3eb 100644 --- a/python/string.cc +++ b/python/string.cc @@ -38,7 +38,21 @@ PyObject *Python(PyObject *Self,PyObject *Args) \ } MkStr(StrDeQuote,DeQuoteString); -MkStr(StrBase64Encode,Base64Encode); + +/* + * 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)); +} + MkStr(StrURItoFileName,URItoFileName); //MkFloat(StrSizeToStr,SizeToStr); diff --git a/python/tag.cc b/python/tag.cc index 6fe97ed5..b1a3e520 100644 --- a/python/tag.cc +++ b/python/tag.cc @@ -34,19 +34,32 @@ using namespace std; /*}}}*/ /* We need to keep a private copy of the data.. */ -struct TagSecData : public CppPyObject<pkgTagSection> +struct TagSecData : public CppOwnedPyObject<pkgTagSection> { char *Data; }; -struct TagFileData : public PyObject +// The owner of the TagFile is a Python file object. +struct TagFileData : public CppOwnedPyObject<pkgTagFile> { - pkgTagFile Object; - PyObject *File; TagSecData *Section; FileFd Fd; }; +// 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; +} + + /*}}}*/ // TagSecFree - Free a Tag Section /*{{{*/ // --------------------------------------------------------------------- @@ -55,7 +68,7 @@ void TagSecFree(PyObject *Obj) { TagSecData *Self = (TagSecData *)Obj; delete [] Self->Data; - CppDealloc<pkgTagSection>(Obj); + CppOwnedDealloc<pkgTagSection>(Obj); } /*}}}*/ // TagFileFree - Free a Tag File /*{{{*/ @@ -63,12 +76,15 @@ void TagSecFree(PyObject *Obj) /* */ void TagFileFree(PyObject *Obj) { + #ifdef ALLOC_DEBUG + std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << "^ ===\n"; + #endif TagFileData *Self = (TagFileData *)Obj; - Py_DECREF((PyObject *)Self->Section); + Py_CLEAR(Self->Section); Self->Object.~pkgTagFile(); Self->Fd.~FileFd(); - Py_DECREF(Self->File); - PyObject_DEL(Obj); + Py_CLEAR(Self->Owner); + Obj->ob_type->tp_free(Obj); } /*}}}*/ @@ -183,6 +199,7 @@ static PyObject *TagSecKeys(PyObject *Self,PyObject *Args) return List; } +#if PY_MAJOR_VERSION < 3 static char *doc_Exists = "Exists(Name) -> integer"; static PyObject *TagSecExists(PyObject *Self,PyObject *Args) { @@ -196,6 +213,19 @@ static PyObject *TagSecExists(PyObject *Self,PyObject *Args) return Py_BuildValue("i",0); return Py_BuildValue("i",1); } +#endif + +static int TagSecContains(PyObject *Self,PyObject *Arg) +{ + if (PyString_Check(Arg) == 0) + return 0; + const char *Name = PyString_AsString(Arg); + const char *Start; + const char *Stop; + if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false) + return 0; + return 1; +} static char *doc_Bytes = "Bytes() -> integer"; static PyObject *TagSecBytes(PyObject *Self,PyObject *Args) @@ -252,15 +282,14 @@ static PyObject *TagFileJump(PyObject *Self,PyObject *Args) /*}}}*/ // ParseSection - Parse a single section from a tag file /*{{{*/ // --------------------------------------------------------------------- -char *doc_ParseSection ="ParseSection(Text) -> SectionObject"; -PyObject *ParseSection(PyObject *self,PyObject *Args) -{ +static PyObject *TagSecNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) { char *Data; - if (PyArg_ParseTuple(Args,"s",&Data) == 0) + char *kwlist[] = {"text", 0}; + if (PyArg_ParseTupleAndKeywords(Args,kwds,"s",kwlist,&Data) == 0) return 0; // Create the object.. - TagSecData *New = PyObject_NEW(TagSecData,&TagSecType); + 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); @@ -277,30 +306,56 @@ PyObject *ParseSection(PyObject *self,PyObject *Args) return New; } + +#ifdef COMPAT_0_7 +char *doc_ParseSection ="ParseSection(Text) -> TagSection() object. Deprecated."; +PyObject *ParseSection(PyObject *self,PyObject *Args) +{ + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.ParseSection() is " + "deprecated. Please see apt_pkg.TagSection() for the " + "replacement.", 1); + return TagSecNew(&PyTagSection_Type,Args,0); +} +#endif /*}}}*/ // ParseTagFile - Parse a tagd file /*{{{*/ // --------------------------------------------------------------------- /* This constructs the parser state. */ -char *doc_ParseTagFile = "ParseTagFile(File) -> TagFile"; -PyObject *ParseTagFile(PyObject *self,PyObject *Args) + +static PyObject *TagFileNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) { PyObject *File; - if (PyArg_ParseTuple(Args,"O!",&PyFile_Type,&File) == 0) + char *kwlist[] = {"file", 0}; + if (PyArg_ParseTupleAndKeywords(Args,kwds,"O",kwlist,&File) == 0) + return 0; + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) return 0; - TagFileData *New = PyObject_NEW(TagFileData,&TagFileType); - new (&New->Fd) FileFd(fileno(PyFile_AsFile(File)),false); - New->File = File; - Py_INCREF(New->File); + TagFileData *New = (TagFileData*)type->tp_alloc(type, 0); + new (&New->Fd) FileFd(fileno,false); + New->Owner = File; + Py_INCREF(New->Owner); new (&New->Object) pkgTagFile(&New->Fd); // Create the section - New->Section = PyObject_NEW(TagSecData,&TagSecType); + New->Section = (TagSecData*)(&PyTagSection_Type)->tp_alloc(&PyTagSection_Type, 0); new (&New->Section->Object) pkgTagSection(); + New->Section->Owner = New; + Py_INCREF(New->Section->Owner); New->Section->Data = 0; return HandleErrors(New); } +#ifdef COMPAT_0_7 +char *doc_ParseTagFile = "ParseTagFile(File) -> TagFile() object. Deprecated."; +PyObject *ParseTagFile(PyObject *self,PyObject *Args) { + PyErr_WarnEx(PyExc_DeprecationWarning, "apt_pkg.ParseTagFile() is " + "deprecated. Please see apt_pkg.TagFile() for the " + "replacement.", 1); + return TagFileNew(&PyTagFile_Type,Args,0); +} +#endif /*}}}*/ // RewriteSection - Rewrite a section.. /*{{{*/ // --------------------------------------------------------------------- @@ -326,7 +381,7 @@ PyObject *RewriteSection(PyObject *self,PyObject *Args) PyObject *Section; PyObject *Order; PyObject *Rewrite; - if (PyArg_ParseTuple(Args,"O!O!O!",&TagSecType,&Section, + if (PyArg_ParseTuple(Args,"O!O!O!",&PyTagSection_Type,&Section, &PyList_Type,&Order,&PyList_Type,&Rewrite) == 0) return 0; @@ -377,93 +432,164 @@ PyObject *RewriteSection(PyObject *self,PyObject *Args) 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}, +#ifdef COMPAT_0_7 {"Find",TagSecFind,METH_VARARGS,doc_Find}, {"FindRaw",TagSecFindRaw,METH_VARARGS,doc_FindRaw}, {"FindFlag",TagSecFindFlag,METH_VARARGS,doc_FindFlag}, {"Bytes",TagSecBytes,METH_VARARGS,doc_Bytes}, +#endif // 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}, {} }; -// TagSecGetAttr - Get an attribute - variable/method /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static PyObject *TagSecGetAttr(PyObject *Self,char *Name) -{ - return Py_FindMethod(TagSecMethods,Self,Name); -} - /*}}}*/ -// Type for a Tag Section + +PySequenceMethods TagSecSeqMeth = {0,0,0,0,0,0,0,TagSecContains,0,0}; PyMappingMethods TagSecMapMeth = {TagSecLength,TagSecMap,0}; -PyTypeObject TagSecType = + + +static char *doc_TagSec = "TagSection(text) -> Create a new object.\n\n" + "TagSection() objects provide methods to access rfc822-style formatted\n" + "header sections, like those 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)"; +PyTypeObject PyTagSection_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "TagSection", // tp_name + 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 - TagSecGetAttr, // tp_getattr + 0, // tp_print + 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number - 0, // tp_as_sequence + &TagSecSeqMeth, // tp_as_sequence &TagSecMapMeth, // tp_as_mapping 0, // tp_hash - 0, // tp_call - TagSecStr, // tp_str + 0, // tp_call + TagSecStr, // 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_TagSec, // tp_doc + CppOwnedTraverse<pkgTagSection>, // tp_traverse + CppOwnedClear<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}, +#ifdef COMPAT_0_7 {"Step",TagFileStep,METH_VARARGS,doc_Step}, {"Offset",TagFileOffset,METH_VARARGS,doc_Offset}, {"Jump",TagFileJump,METH_VARARGS,doc_Jump}, +#endif {} }; -// TagFileGetAttr - Get an attribute - variable/method /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static PyObject *TagFileGetAttr(PyObject *Self,char *Name) -{ - if (strcmp("Section",Name) == 0) - { - PyObject *Obj = ((TagFileData *)Self)->Section; - Py_INCREF(Obj); - return Obj; - } - - return Py_FindMethod(TagFileMethods,Self,Name); +// 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,"Return a TagSection.",0}, +#ifdef COMPAT_0_7 + {"Section",TagFileGetSection,0,"Return a TagSection.",0}, +#endif + {} +}; + +static char *doc_TagFile = "TagFile(file) -> TagFile() object. \n\n" + "TagFile() objects provide access to debian control files, which consists\n" + "of multiple RFC822-like formatted sections.\n\n" + "A file may consists of multiple sections, and you can use Step() to move\n" + "forward. The current TagSection() is available via the attribute section" + ".\n\n" + "The parameter *file* refers to an object providing a fileno() method or\n" + "a file descriptor (an integer)"; + // Type for a Tag File -PyTypeObject TagFileType = +PyTypeObject PyTagFile_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, // ob_size - "TagFile", // tp_name + 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 - TagFileGetAttr, // tp_getattr + 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_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_TagFile, // tp_doc + TagFileTraverse, // tp_traverse + TagFileClear, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // 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 + }; diff --git a/python/tar.cc b/python/tar.cc index e5aaee6f..b994d4e7 100644 --- a/python/tar.cc +++ b/python/tar.cc @@ -4,10 +4,13 @@ /* ###################################################################### Tar Inteface + * THIS FILE IS COMPLETELY DEPRECATED, AND NOT USED ANYMORE IF BUILT * + * WITHOUT COMPATIBILITY. * ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ +#ifdef COMPAT_0_7 #include "generic.h" #include <apt-pkg/extracttar.h> @@ -72,8 +75,12 @@ bool ProcessTar::DoItem(Item &Itm,int &Fd) case Item::FIFO: Type = "FIFO"; break; + + default: + return false; } + if (PyObject_CallFunction(Function,"sssiiiiiii",Type,Itm.Name, Itm.LinkTarget,Itm.Mode,Itm.UID,Itm.GID,Itm.Size, Itm.MTime,Itm.Major,Itm.Minor) == 0) @@ -97,8 +104,7 @@ PyObject *tarExtract(PyObject *Self,PyObject *Args) PyObject *Function; char *Comp; - if (PyArg_ParseTuple(Args,"O!Os",&PyFile_Type,&File, - &Function,&Comp) == 0) + if (PyArg_ParseTuple(Args,"OOs",&File, &Function,&Comp) == 0) return 0; if (PyCallable_Check(Function) == 0) @@ -109,7 +115,11 @@ PyObject *tarExtract(PyObject *Self,PyObject *Args) { // Open the file and associate the tar - FileFd Fd(fileno(PyFile_AsFile(File)),false); + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; + + FileFd Fd(fileno,false); ExtractTar Tar(Fd,0xFFFFFFFF,Comp); if (_error->PendingError() == true) return HandleErrors(); @@ -139,8 +149,7 @@ PyObject *debExtract(PyObject *Self,PyObject *Args) char *Chunk; const char *Comp = "gzip"; - if (PyArg_ParseTuple(Args,"O!Os",&PyFile_Type,&File, - &Function,&Chunk) == 0) + if (PyArg_ParseTuple(Args,"OOs",&File,&Function,&Chunk) == 0) return 0; if (PyCallable_Check(Function) == 0) @@ -149,10 +158,13 @@ PyObject *debExtract(PyObject *Self,PyObject *Args) return 0; } + int fileno = PyObject_AsFileDescriptor(File); + if (fileno == -1) + return 0; { // Open the file and associate the tar // Open the file and associate the .deb - FileFd Fd(fileno(PyFile_AsFile(File)),false); + FileFd Fd(fileno,false); debDebFile Deb(Fd); if (_error->PendingError() == true) return HandleErrors(); @@ -180,3 +192,4 @@ PyObject *debExtract(PyObject *Self,PyObject *Args) return HandleErrors(Py_None); } /*}}}*/ +#endif // defined(COMPAT_0_7) diff --git a/python/tarfile.cc b/python/tarfile.cc new file mode 100644 index 00000000..9c3797fb --- /dev/null +++ b/python/tarfile.cc @@ -0,0 +1,469 @@ +/* + * 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; + // The current member and data. + CppOwnedPyObject<Item*> *py_member; + PyObject *py_data; + // The requested member or NULL. + const char *member; + // Set to true if an error occured in the Python callback. + bool error; + // Place where the copy of the data is stored. + char *copy; + + virtual bool DoItem(Item &Itm,int &Fd); + virtual bool FinishedFile(Item &Itm,int Fd); + virtual bool Process(Item &Itm,const unsigned char *Data, + unsigned long Size,unsigned long Pos); + + PyDirStream(PyObject *callback, const char *member=0) : callback(callback), + py_member(0), py_data(0), member(member), error(false), copy(0) + { + Py_XINCREF(callback); + } + + virtual ~PyDirStream() { + Py_XDECREF(callback); + Py_XDECREF(py_member); + Py_XDECREF(py_data); + delete[] copy; + } +}; + +bool PyDirStream::DoItem(Item &Itm, int &Fd) +{ + if (!member || strcmp(Itm.Name, member) == 0) { + delete[] copy; + copy = new char[Itm.Size]; + Fd = -2; + } + return true; +} + +bool PyDirStream::Process(Item &Itm,const unsigned char *Data, + unsigned long Size,unsigned long Pos) +{ + 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; + + // Clear the old objects and create new ones. + Py_XDECREF(py_member); + Py_XDECREF(py_data); + py_member = CppOwnedPyObject_NEW<Item*>(0, &PyTarMember_Type, &Itm); + py_member->NoDelete = true; + py_data = PyBytes_FromStringAndSize(copy, Itm.Size); + + if (!callback) + return true; + error = PyObject_CallFunctionObjArgs(callback, py_member, py_data, 0) == 0; + return (!error); +} + +// 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 PyString_FromString(GetCpp<pkgDirStream::Item*>(self)->Name); +} + +static PyObject *tarmember_get_linkname(PyObject *self, void *closure) +{ + return Safe_FromString(GetCpp<pkgDirStream::Item*>(self)->LinkTarget); +} + +static PyObject *tarmember_get_mode(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<pkgDirStream::Item*>(self)->Mode); +} + +static PyObject *tarmember_get_uid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<pkgDirStream::Item*>(self)->UID); +} +static PyObject *tarmember_get_gid(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<pkgDirStream::Item*>(self)->GID); +} +static PyObject *tarmember_get_size(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<pkgDirStream::Item*>(self)->Size); +} + +static PyObject *tarmember_get_mtime(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<pkgDirStream::Item*>(self)->MTime); +} + +static PyObject *tarmember_get_major(PyObject *self, void *closure) +{ + return Py_BuildValue("k", GetCpp<pkgDirStream::Item*>(self)->Major); +} + +static PyObject *tarmember_get_minor(PyObject *self, void *closure) +{ + return Py_BuildValue("k", 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(CppOwnedPyObject<pkgDirStream::Item*>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppOwnedDealloc<pkgDirStream::Item*>, // 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 + CppOwnedTraverse<pkgDirStream::Item*>, // tp_traverse + CppOwnedClear<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; + PyTarFileObject *self; + char *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; + + self = (PyTarFileObject*)CppOwnedPyObject_NEW<ExtractTar*>(file,type); + + // We receive a filename. + if ((filename = (char*)PyObject_AsString(file))) + new (&self->Fd) FileFd(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 { + Py_DECREF(self); + return 0; + } + + self->min = min; + self->Object = new ExtractTar(self->Fd,max,comp); + if (_error->PendingError() == true) + return HandleErrors(self); + return self; +} + +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) +{ + string cwd = SafeGetCWD(); + char *rootdir = 0; + if (PyArg_ParseTuple(args,"|s:extractall",&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 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; + char *member = 0; + if (PyArg_ParseTuple(args,"O|s",&callback,&member) == 0) + return 0; + if (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); + 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) +{ + const char *member; + if (PyArg_ParseTuple(args,"s",&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.py_data) + return PyErr_Format(PyExc_LookupError, "There is no member named '%s'", + member); + if (stream.error) { + return 0; + } + 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 + CppOwnedDealloc<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 + CppOwnedTraverse<ExtractTar*>, // tp_traverse + CppOwnedClear<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 +}; |
