diff options
| author | Julian Andres Klode <jak@debian.org> | 2011-04-29 12:24:46 +0200 |
|---|---|---|
| committer | Julian Andres Klode <jak@debian.org> | 2011-04-29 12:24:46 +0200 |
| commit | 750f432e42c605747d86826886c29b76d19269a3 (patch) | |
| tree | 79b37b2d980c3c1d3caebd95ad9ab86d3e06d168 /python | |
| parent | 4775b948dcda187f03b765d7da2c00ea27834e9c (diff) | |
| download | python-apt-750f432e42c605747d86826886c29b76d19269a3.tar.gz | |
apt_pkg: Add subclassing fun to PackageManager, for #623485 as well
Diffstat (limited to 'python')
| -rw-r--r-- | python/apt_pkgmodule.cc | 3 | ||||
| -rw-r--r-- | python/apt_pkgmodule.h | 1 | ||||
| -rw-r--r-- | python/pkgmanager.cc | 277 |
3 files changed, 243 insertions, 38 deletions
diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc index 139ff016..e8490b4e 100644 --- a/python/apt_pkgmodule.cc +++ b/python/apt_pkgmodule.cc @@ -833,7 +833,8 @@ extern "C" void initapt_pkg() /* ========================= metaindex.cc ========================= */ ADDTYPE(Module,"MetaIndex",&PyMetaIndex_Type); // NO __new__() /* ========================= pkgmanager.cc ========================= */ - ADDTYPE(Module,"PackageManager",&PyPackageManager_Type); + ADDTYPE(Module,"_PackageManager",&PyPackageManager_Type); + ADDTYPE(Module,"PackageManager",&PyPackageManager2_Type); /* ========================= pkgrecords.cc ========================= */ ADDTYPE(Module,"PackageRecords",&PyPackageRecords_Type); /* ========================= pkgsrcrecords.cc ========================= */ diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h index 89179551..b3534a30 100644 --- a/python/apt_pkgmodule.h +++ b/python/apt_pkgmodule.h @@ -102,6 +102,7 @@ PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject *kwds); // packagemanager extern PyTypeObject PyPackageManager_Type; +extern PyTypeObject PyPackageManager2_Type; PyObject *GetPkgManager(PyObject *Self,PyObject *Args); diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc index a65c88f8..b7bed658 100644 --- a/python/pkgmanager.cc +++ b/python/pkgmanager.cc @@ -17,36 +17,10 @@ #include <apt-pkg/acquire.h> #include <apt-pkg/init.h> #include <apt-pkg/configuration.h> +#include <apt-pkg/dpkgpm.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*>(NULL, 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) { pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self); @@ -114,17 +88,16 @@ static PyMethodDef PkgManagerMethods[] = {} }; - static const char *packagemanager_doc = - "PackageManager(depcache: apt_pkg.DepCache)\n\n" - "PackageManager objects allow the fetching of packages marked for\n" - "installation and the installation of those packages. The parameter\n" - "'depcache' specifies an apt_pkg.DepCache object where information\n" - "about the package selections is retrieved from."; + "_PackageManager objects allow the fetching of packages marked for\n" + "installation and the installation of those packages.\n" + "This is an abstract base class that cannot be subclassed\n" + "in Python. The only subclass is apt_pkg.PackageManager. This\n" + "class is an implementation-detail and not part of the API."; PyTypeObject PyPackageManager_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "apt_pkg.PackageManager", // tp_name + "apt_pkg._PackageManager", // tp_name sizeof(CppPyObject<pkgPackageManager*>), // tp_basicsize 0, // tp_itemsize // Methods @@ -143,8 +116,7 @@ PyTypeObject PyPackageManager_Type = _PyAptObject_getattro, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - (Py_TPFLAGS_DEFAULT | // tp_flags - Py_TPFLAGS_BASETYPE), + Py_TPFLAGS_DEFAULT, // tp_flag, packagemanager_doc, // tp_doc 0, // tp_traverse 0, // tp_clear @@ -162,9 +134,240 @@ PyTypeObject PyPackageManager_Type = 0, // tp_dictoffset 0, // tp_init 0, // tp_alloc - PkgManagerNew, // tp_new + 0, // tp_new +}; + + +struct CppPyRef { + PyObject *o; + CppPyRef(const CppPyRef &o) { Py_XINCREF(o); this->o = o; } + CppPyRef(PyObject *o) : o(o) {} + ~CppPyRef() { Py_XDECREF(o); } + operator PyObject *() const { return o; } + PyObject *operator->() const { return o; } }; +class PyPkgManager : public pkgDPkgPM { + bool res(CppPyRef result) { + if (result == NULL) { + std::cerr << "Error in function: " << std::endl; + PyErr_Print(); + PyErr_Clear(); + return false; + } + return (result != NULL && + (result == Py_None || PyObject_IsTrue(result) == 1)); + } + + + PyObject *GetPyPkg(const PkgIterator &Pkg) { + PyObject *depcache = NULL; + PyObject *cache = NULL; + + depcache = GetOwner<PyPkgManager*>(pyinst); + if (depcache != NULL && PyDepCache_Check(depcache)) + cache = GetOwner<pkgDepCache*>(depcache); + + return PyPackage_FromCpp(Pkg, true, cache); + } + + /* Call through to Python */ + virtual bool Install(PkgIterator Pkg,string File) { + return res(PyObject_CallMethod(pyinst, "install", "(NN)", + GetPyPkg(Pkg), + CppPyString(File))); + } + virtual bool Configure(PkgIterator Pkg) { + return res(PyObject_CallMethod(pyinst, "configure", "(N)", + GetPyPkg(Pkg))); + } + virtual bool Remove(PkgIterator Pkg,bool Purge = false) { + return res(PyObject_CallMethod(pyinst, "remove", "(NN)", + GetPyPkg(Pkg), + PyBool_FromLong(Purge))); + } + virtual bool Go(int StatusFd=-1) { + return res(PyObject_CallMethod(pyinst, "go", "(i)", + StatusFd)); + } + virtual void Reset() { + CppPyRef(PyObject_CallMethod(pyinst, "reset", NULL)); + } + +public: + /* Those call the protected functions from the parent class */ + bool callInstall(PkgIterator Pkg,string File) { return pkgDPkgPM::Install(Pkg, File); } + bool callRemove(PkgIterator Pkg, bool Purge) { return pkgDPkgPM::Remove(Pkg, Purge); } + bool callGo(int StatusFd=-1) { return pkgDPkgPM::Go(StatusFd); } + void callReset() { return pkgDPkgPM::Reset(); } + bool callConfigure(PkgIterator Pkg) { return pkgDPkgPM::Configure(Pkg); } + pkgOrderList *getOrderList() { return pkgPackageManager::List; } + + PyPkgManager(pkgDepCache *Cache) : pkgDPkgPM(Cache) {}; + PyObject *pyinst; +}; + +static PyObject *PkgManagerNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) +{ + PyObject *Owner; + char *kwlist[] = {"depcache",0}; + if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type, + &Owner) == 0) + return 0; + + PyPkgManager *pm = new PyPkgManager(GetCpp<pkgDepCache*>(Owner)); + + CppPyObject<PyPkgManager*> *PkgManagerObj = + CppPyObject_NEW<PyPkgManager*>(NULL, type,pm); + + pm->pyinst = PkgManagerObj; + + return PkgManagerObj; +} + +#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(&PyPackageManager2_Type,Args,0); +} +#endif + +static PyObject *PkgManagerInstall(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp<PyPkgManager*>(Self); + PyObject *pkg; + const char *file; + + if (PyArg_ParseTuple(Args, "O!s", &PyPackage_Type,&pkg, &file) == 0) + return 0; + + return HandleErrors(PyBool_FromLong(pm->callInstall(PyPackage_ToCpp(pkg), file))); +} + + +static PyObject *PkgManagerConfigure(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp<PyPkgManager*>(Self); + PyObject *pkg; + + if (PyArg_ParseTuple(Args, "O!", &PyPackage_Type,&pkg) == 0) + return 0; + + return HandleErrors(PyBool_FromLong(pm->callConfigure(PyPackage_ToCpp(pkg)))); +} + +static PyObject *PkgManagerRemove(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp<PyPkgManager*>(Self); + PyObject *pkg; + char purge; + + if (PyArg_ParseTuple(Args, "O!b", &PyPackage_Type,&pkg, &purge) == 0) + return 0; + + return HandleErrors(PyBool_FromLong(pm->callRemove(PyPackage_ToCpp(pkg), purge))); +} + +static PyObject *PkgManagerGo(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp<PyPkgManager*>(Self); + int fd; + + if (PyArg_ParseTuple(Args, "i", &fd) == 0) + return 0; + + return HandleErrors(PyBool_FromLong(pm->callGo(fd))); +} + +static PyObject *PkgManagerReset(PyObject *Self,PyObject *Args) +{ + PyPkgManager *pm = GetCpp<PyPkgManager*>(Self); + + pm->callReset(); + Py_INCREF(Py_None); + return HandleErrors(Py_None); +} + +static PyMethodDef PkgManager2Methods[] = +{ + {"install",PkgManagerInstall,METH_VARARGS, + "install(pkg: Package, filename: str) -> bool \n\n" + "Add a install action. Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {"configure",PkgManagerConfigure,METH_VARARGS, + "configure(pkg: Package) -> bool \n\n" + "Add a configure action. Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {"remove",PkgManagerRemove,METH_VARARGS, + "remove(pkg: Package, purge: bool) -> bool \n\n" + "Add a removal action. Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {"go",PkgManagerGo,METH_VARARGS, + "go(status_fd: int) -> bool \n\n" + "Start dpkg. Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {"reset",PkgManagerReset,METH_VARARGS, + "reset()\n\n" + "Reset the package manager for a new round.\n" + "Can be overriden in subclasses.\n\n" + "New in version 0.8.0."}, + {} +}; + +static const char *packagemanager2_doc = + "PackageManager(depcache: apt_pkg.DepCache)\n\n" + "PackageManager objects allow the fetching of packages marked for\n" + "installation and the installation of those packages. The parameter\n" + "'depcache' specifies an apt_pkg.DepCache object where information\n" + "about the package selections is retrieved from.\n\n" + "Methods in this class can be overriden in sub classes\n" + "to implement behavior different from APT's dpkg implementation."; +PyTypeObject PyPackageManager2_Type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "apt_pkg.PackageManager", // tp_name + sizeof(CppPyObject<PyPkgManager*>), // tp_basicsize + 0, // tp_itemsize + // Methods + CppDeallocPtr<PyPkgManager*>, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + (Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_BASETYPE), + packagemanager2_doc, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + PkgManager2Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + &PyPackageManager_Type, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + PkgManagerNew, // tp_new +}; /*}}}*/ |
