/* acquire.cc - Wrapper for pkgAcquire. * * Copyright 2004-2009 Canonical Ltd * Copyright 2009 Julian Andres Klode * * 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 #include static PyObject *acquireworker_get_current_item(PyObject *self, void *closure) { pkgAcquire::Worker *worker = GetCpp(self); pkgAcquire::ItemDesc *desc = worker->CurrentItem; if (desc == NULL) { Py_RETURN_NONE; } PyObject *PyAcq = GetOwner(self); PyObject *PyItem = PyAcquireItem_FromCpp(desc->Owner, false, PyAcq); PyObject *PyDesc = PyAcquireItemDesc_FromCpp(desc, false, PyItem); Py_XDECREF(PyItem); return PyDesc; } static PyObject *acquireworker_get_status(PyObject *self, void *closure) { return CppPyString(GetCpp(self)->Status); } static PyObject *acquireworker_get_current_size(PyObject *self, void *closure) { if (GetCpp(self)->CurrentItem == nullptr) return 0; return MkPyNumber(GetCpp(self)->CurrentItem->CurrentSize); } static PyObject *acquireworker_get_total_size(PyObject *self, void *closure) { if (GetCpp(self)->CurrentItem == nullptr) return 0; return MkPyNumber(GetCpp(self)->CurrentItem->TotalSize); } static PyObject *acquireworker_get_resumepoint(PyObject *self, void *closure) { if (GetCpp(self)->CurrentItem == nullptr) return 0; return MkPyNumber(GetCpp(self)->CurrentItem->ResumePoint); } static PyGetSetDef acquireworker_getset[] = { {"current_item",acquireworker_get_current_item,0, "The item currently being fetched, as an apt_pkg.AcquireItemDesc object."}, {"status",acquireworker_get_status,0, "The status of the worker, as a string."}, {"current_size",acquireworker_get_current_size,0, "The amount of data fetched so far for the current item."}, {"total_size",acquireworker_get_total_size,0, "The total size of the item."}, {"resumepoint",acquireworker_get_resumepoint,0, "The amount of data which was already available when the download was\n" "started."}, {NULL} }; static const char *acquireworker_doc = "Represent a sub-process responsible for fetching files from\n" "remote locations. This sub-process uses 'methods' located in\n" "the directory specified by the configuration option\n" "Dir::Bin::Methods."; PyTypeObject PyAcquireWorker_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.AcquireWorker", // tp_name sizeof(CppPyObject),// tp_basicsize 0, // tp_itemsize // Methods CppDealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping 0, // tp_hash 0, // tp_call 0, // tp_str 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT| // tp_flags Py_TPFLAGS_HAVE_GC, acquireworker_doc, // tp_doc CppTraverse, // tp_traverse CppClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext 0, // tp_methods 0, // tp_members acquireworker_getset, // tp_getset }; static pkgAcquire::ItemDesc* acquireitemdesc_tocpp(PyObject *self) { pkgAcquire::ItemDesc *item = GetCpp(self); if (item == NULL) PyErr_SetString(PyExc_ValueError, "Acquire has been shutdown"); return item; } static PyObject *acquireitemdesc_get_uri(PyObject *self, void *closure) { pkgAcquire::ItemDesc *item = acquireitemdesc_tocpp(self); return item ? CppPyString(item->URI) : NULL; } static PyObject *acquireitemdesc_get_description(PyObject *self, void *closure) { pkgAcquire::ItemDesc *item = acquireitemdesc_tocpp(self); return item ? CppPyString(item->Description) : NULL; } static PyObject *acquireitemdesc_get_shortdesc(PyObject *self, void *closure) { pkgAcquire::ItemDesc *item = acquireitemdesc_tocpp(self); return item ? CppPyString(item->ShortDesc) : NULL; } static PyObject *acquireitemdesc_get_owner(CppPyObject *self, void *closure) { if (self->Owner != NULL) { Py_INCREF(self->Owner); return self->Owner; } else if (self->Object) { self->Owner = PyAcquireItem_FromCpp(self->Object->Owner, false, NULL); Py_INCREF(self->Owner); return self->Owner; } Py_RETURN_NONE; } static PyGetSetDef acquireitemdesc_getset[] = { {"uri",acquireitemdesc_get_uri,0, "The URI from which this item would be downloaded."}, {"description",acquireitemdesc_get_description,0, "A string describing the item."}, {"shortdesc",acquireitemdesc_get_shortdesc,0, "A short string describing the item (e.g. package name)."}, {"owner",(getter)acquireitemdesc_get_owner,0, "The owner of the item, an apt_pkg.AcquireItem object."}, {NULL} }; static char *acquireitemdesc_doc = "Provide the description of an item and the URI the item is\n" "fetched from. Progress classes make use of such objects to\n" "retrieve description and other information about an item."; PyTypeObject PyAcquireItemDesc_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.AcquireItemDesc", // tp_name sizeof(CppPyObject),// tp_basicsize 0, // tp_itemsize // Methods CppDealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping 0, // tp_hash 0, // tp_call 0, // tp_str 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags Py_TPFLAGS_HAVE_GC), acquireitemdesc_doc, // tp_doc CppTraverse,// tp_traverse CppClear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext 0, // tp_methods 0, // tp_members acquireitemdesc_getset, // tp_getset 0, // tp_base 0, // tp_dict 0, // tp_descr_get 0, // tp_descr_set 0, // tp_dictoffset 0, // tp_init 0, // tp_alloc 0, // tp_new }; static PyObject *PkgAcquireRun(PyObject *Self,PyObject *Args) { pkgAcquire *fetcher = GetCpp(Self); int pulseInterval = 500000; if (PyArg_ParseTuple(Args, "|i", &pulseInterval) == 0) return 0; pkgAcquire::RunResult run = fetcher->Run(pulseInterval); return HandleErrors(MkPyNumber(run)); } static PyObject *PkgAcquireShutdown(PyObject *Self,PyObject *Args) { pkgAcquire *fetcher = GetCpp(Self); if (PyArg_ParseTuple(Args, "") == 0) return 0; fetcher->Shutdown(); Py_INCREF(Py_None); return HandleErrors(Py_None); } static PyObject *PkgAcquireGetLock(PyObject *Self,PyObject *Args) { pkgAcquire *fetcher = GetCpp(Self); PyApt_Filename path; if (PyArg_ParseTuple(Args, "O&", PyApt_Filename::Converter, &path) == 0) return 0; fetcher->GetLock(path); Py_INCREF(Py_None); return HandleErrors(Py_None); } static PyMethodDef PkgAcquireMethods[] = { {"run",PkgAcquireRun,METH_VARARGS, "run() -> int\n\nRun the fetcher and return one of RESULT_CANCELLED,\n" "RESULT_CONTINUE, RESULT_FAILED.\n\n" "RESULT_CONTINUE means that all items which where queued prior to\n" "calling run() have been fetched successfully or failed transiently.\n\n" "RESULT_CANCELLED means canceled by the progress class.\n\n" "RESULT_FAILED means a generic failure."}, {"shutdown",PkgAcquireShutdown, METH_VARARGS, "shutdown()\n\n" "Shut the fetcher down, removing all items from it. Future access to\n" "queued AcquireItem objects will cause a segfault. The partial result\n" "is kept on the disk and not removed and APT might reuse it."}, {"get_lock",PkgAcquireGetLock, METH_VARARGS, "get_lock(log: str)\n\n" "Acquires a log for the given directory, using a file 'lock' in it."}, {} }; #define fetcher (GetCpp(Self)) static PyObject *PkgAcquireGetTotalNeeded(PyObject *Self,void*) { return MkPyNumber(fetcher->TotalNeeded()); } static PyObject *PkgAcquireGetFetchNeeded(PyObject *Self,void*) { return MkPyNumber(fetcher->FetchNeeded()); } static PyObject *PkgAcquireGetPartialPresent(PyObject *Self,void*) { return MkPyNumber(fetcher->PartialPresent()); } #undef fetcher static PyObject *PkgAcquireGetWorkers(PyObject *self, void *closure) { PyObject *List = PyList_New(0); pkgAcquire *Owner = GetCpp(self); PyObject *PyWorker = NULL; for (pkgAcquire::Worker *Worker = Owner->WorkersBegin(); Worker != 0; Worker = Owner->WorkerStep(Worker)) { PyWorker = PyAcquireWorker_FromCpp(Worker, false, self); PyList_Append(List, PyWorker); Py_DECREF(PyWorker); } return List; } static PyObject *PkgAcquireGetItems(PyObject *Self,void*) { pkgAcquire *fetcher = GetCpp(Self); PyObject *List = PyList_New(0); PyObject *Obj; for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin(); I != fetcher->ItemsEnd(); I++) { Obj = PyAcquireItem_FromCpp(*I, false, Self); PyList_Append(List,Obj); Py_DECREF(Obj); } return List; } static PyGetSetDef PkgAcquireGetSet[] = { {"fetch_needed",PkgAcquireGetFetchNeeded,0, "The total amount of data to be fetched (number of bytes)."}, {"items",PkgAcquireGetItems,0, "A list of all items as apt_pkg.AcquireItem objects, including already\n" "fetched ones and to be fetched ones."}, {"workers",PkgAcquireGetWorkers,0, "A list of all active workers as apt_pkg.AcquireWorker objects."}, {"partial_present",PkgAcquireGetPartialPresent,0, "The amount of data which is already available (number of bytes)."}, {"total_needed",PkgAcquireGetTotalNeeded,0, "The amount of data that needs to fetched plus the amount of data\n" "which has already been fetched (number of bytes)."}, {} }; static PyObject *PkgAcquireNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) { pkgAcquire *fetcher; PyObject *pyFetchProgressInst = NULL; char *kwlist[] = {"progress", 0}; if (PyArg_ParseTupleAndKeywords(Args,kwds,"|O",kwlist,&pyFetchProgressInst) == 0) return 0; PyFetchProgress *progress = 0; if (pyFetchProgressInst != NULL) { // FIXME: memleak? progress = new PyFetchProgress(); progress->setCallbackInst(pyFetchProgressInst); } fetcher = new pkgAcquire(); fetcher->SetLog(progress); PyObject *FetcherObj = CppPyObject_NEW(NULL, type, fetcher); if (progress != 0) progress->setPyAcquire(FetcherObj); // prepare our map of items. return HandleErrors(FetcherObj); } /** * Create a new apt_pkg.Acquire Python object from the pkgAcquire object. */ PyObject *PyAcquire_FromCpp(pkgAcquire *fetcher, bool Delete, PyObject *owner) { CppPyObject *obj = CppPyObject_NEW(owner, &PyAcquire_Type, fetcher); obj->NoDelete = (!Delete); return obj; } static char *doc_PkgAcquire = "Acquire([progress: apt.progress.base.AcquireProgress])\n\n" "Coordinate the retrieval of files via network or local file system\n" "(using 'copy:/path/to/file' style URIs). The optional argument\n" "'progress' takes an apt.progress.base.AcquireProgress object\n" "which may report progress information."; PyTypeObject PyAcquire_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "apt_pkg.Acquire", // tp_name sizeof(CppPyObject), // tp_basicsize 0, // tp_itemsize // Methods CppDeallocPtr, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr 0, // tp_compare 0, // tp_repr 0, // tp_as_number 0, // tp_as_sequence 0, // tp_as_mapping 0, // tp_hash 0, // tp_call 0, // tp_str _PyAptObject_getattro, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer (Py_TPFLAGS_DEFAULT | // tp_flags Py_TPFLAGS_BASETYPE), doc_PkgAcquire, // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext PkgAcquireMethods, // tp_methods 0, // tp_members PkgAcquireGetSet, // tp_getset 0, // tp_base 0, // tp_dict 0, // tp_descr_get 0, // tp_descr_set 0, // tp_dictoffset 0, // tp_init 0, // tp_alloc PkgAcquireNew, // tp_new };