summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2011-04-29 12:24:46 +0200
committerJulian Andres Klode <jak@debian.org>2011-04-29 12:24:46 +0200
commit750f432e42c605747d86826886c29b76d19269a3 (patch)
tree79b37b2d980c3c1d3caebd95ad9ab86d3e06d168 /python
parent4775b948dcda187f03b765d7da2c00ea27834e9c (diff)
downloadpython-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.cc3
-rw-r--r--python/apt_pkgmodule.h1
-rw-r--r--python/pkgmanager.cc277
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
+};
/*}}}*/