python: xml_parsers now store reference to a pkg object while parsing to the object
authorTomas Mlcoch <xtojaj@gmail.com>
Fri, 31 May 2013 19:55:05 +0000 (21:55 +0200)
committerTomas Mlcoch <xtojaj@gmail.com>
Fri, 31 May 2013 19:55:05 +0000 (21:55 +0200)
src/python/xml_parser-py.c

index c4f6f5c..97d52e5 100644 (file)
 #include "package-py.h"
 #include "exception-py.h"
 
+typedef struct {
+    PyObject *py_newpkgcb;
+    PyObject *py_pkgcb;
+    PyObject *py_warningcb;
+    PyObject *py_pkg;       /*!< Current processed package */
+} CbData;
+
 static int
 c_newpkgcb(cr_Package **pkg,
            const char *pkgId,
@@ -37,9 +44,16 @@ c_newpkgcb(cr_Package **pkg,
            GError **err)
 {
     PyObject *arglist, *result;
+    CbData *data = cbdata;
+
+    if (data->py_pkg) {
+        // Decref ref count on previous processed package
+        Py_DECREF(data->py_pkg);
+        data->py_pkg = NULL;
+    }
 
     arglist = Py_BuildValue("(sss)", pkgId, name, arch);
-    result = PyObject_CallObject(cbdata, arglist);
+    result = PyObject_CallObject(data->py_newpkgcb, arglist);
     Py_DECREF(arglist);
 
     if (result == NULL) {
@@ -51,12 +65,13 @@ c_newpkgcb(cr_Package **pkg,
     if (!PackageObject_Check(result) && result != Py_None) {
         PyErr_SetString(PyExc_TypeError,
             "Expected a cr_Package or None as a callback return value");
+        Py_DECREF(result);
         return CR_CB_RET_ERR;
     }
 
     *pkg = Package_FromPyObject(result);
+    data->py_pkg = result; // Store reference to current package
 
-    Py_DECREF(result);
     return CR_CB_RET_OK;
 }
 
@@ -66,10 +81,17 @@ c_pkgcb(cr_Package *pkg,
         GError **err)
 {
     PyObject *result;
+    CbData *data = cbdata;
 
     CR_UNUSED(pkg);
 
-    result = PyObject_CallObject(cbdata, NULL);
+    if (data->py_pkg) {
+        // Decref ref count on processed package
+        Py_DECREF(data->py_pkg);
+        data->py_pkg = NULL;
+    }
+
+    result = PyObject_CallObject(data->py_pkgcb, NULL);
 
     if (result == NULL) {
         // Exception raised
@@ -88,9 +110,10 @@ c_warningcb(cr_XmlParserWarningType type,
             GError **err)
 {
     PyObject *arglist, *result;
+    CbData *data = cbdata;
 
     arglist = Py_BuildValue("(is)", type, msg);
-    result = PyObject_CallObject(cbdata, arglist);
+    result = PyObject_CallObject(data->py_warningcb, arglist);
     Py_DECREF(arglist);
 
     if (result == NULL) {
@@ -110,58 +133,64 @@ py_xml_parse_primary(PyObject *self, PyObject *args)
 
     char *filename;
     int do_files;
-    PyObject *newpkgcb, *pkgcb, *warningcb;
+    PyObject *py_newpkgcb, *py_pkgcb, *py_warningcb;
+    CbData cbdata;
     GError *tmp_err = NULL;
 
     if (!PyArg_ParseTuple(args, "sOOOi:py_xml_parse_primary",
                                          &filename,
-                                         &newpkgcb,
-                                         &pkgcb,
-                                         &warningcb,
+                                         &py_newpkgcb,
+                                         &py_pkgcb,
+                                         &py_warningcb,
                                          &do_files)) {
         return NULL;
     }
 
-    if (!PyCallable_Check(newpkgcb)) {
+    if (!PyCallable_Check(py_newpkgcb)) {
         PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable");
         return NULL;
     }
 
-    if (!PyCallable_Check(pkgcb) && pkgcb != Py_None) {
+    if (!PyCallable_Check(py_pkgcb) && py_pkgcb != Py_None) {
         PyErr_SetString(PyExc_TypeError, "pkgcb must be callable or None");
         return NULL;
     }
 
-    if (!PyCallable_Check(warningcb) && warningcb != Py_None) {
+    if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) {
         PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None");
         return NULL;
     }
 
-    Py_XINCREF(newpkgcb);
-    Py_XINCREF(pkgcb);
-    Py_XINCREF(warningcb);
+    Py_XINCREF(py_newpkgcb);
+    Py_XINCREF(py_pkgcb);
+    Py_XINCREF(py_warningcb);
 
     cr_XmlParserPkgCb       ptr_c_pkgcb     = NULL;
     cr_XmlParserWarningCb   ptr_c_warningcb = NULL;
 
-    if (pkgcb != Py_None)
+    if (py_pkgcb != Py_None)
         ptr_c_pkgcb = c_pkgcb;
-    if (warningcb != Py_None)
+    if (py_warningcb != Py_None)
         ptr_c_warningcb = c_warningcb;
 
+    cbdata.py_newpkgcb  = py_newpkgcb;
+    cbdata.py_pkgcb     = py_pkgcb;
+    cbdata.py_warningcb = py_warningcb;
+    cbdata.py_pkg       = NULL;
+
     cr_xml_parse_primary(filename,
                          c_newpkgcb,
-                         newpkgcb,
+                         &cbdata,
                          ptr_c_pkgcb,
-                         pkgcb,
+                         &cbdata,
                          ptr_c_warningcb,
-                         warningcb,
+                         &cbdata,
                          do_files,
                          &tmp_err);
 
-    Py_XDECREF(newpkgcb);
-    Py_XDECREF(pkgcb);
-    Py_XDECREF(warningcb);
+    Py_XDECREF(py_newpkgcb);
+    Py_XDECREF(py_pkgcb);
+    Py_XDECREF(py_warningcb);
 
     if (tmp_err) {
         PyErr_Format(CrErr_Exception, "%s", tmp_err->message);
@@ -178,56 +207,62 @@ py_xml_parse_filelists(PyObject *self, PyObject *args)
     CR_UNUSED(self);
 
     char *filename;
-    PyObject *newpkgcb, *pkgcb, *warningcb;
+    PyObject *py_newpkgcb, *py_pkgcb, *py_warningcb;
+    CbData cbdata;
     GError *tmp_err = NULL;
 
     if (!PyArg_ParseTuple(args, "sOOO:py_xml_parse_filelists",
                                          &filename,
-                                         &newpkgcb,
-                                         &pkgcb,
-                                         &warningcb)) {
+                                         &py_newpkgcb,
+                                         &py_pkgcb,
+                                         &py_warningcb)) {
         return NULL;
     }
 
-    if (!PyCallable_Check(newpkgcb)) {
+    if (!PyCallable_Check(py_newpkgcb)) {
         PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable");
         return NULL;
     }
 
-    if (!PyCallable_Check(pkgcb) && pkgcb != Py_None) {
+    if (!PyCallable_Check(py_pkgcb) && py_pkgcb != Py_None) {
         PyErr_SetString(PyExc_TypeError, "pkgcb must be callable or None");
         return NULL;
     }
 
-    if (!PyCallable_Check(warningcb) && warningcb != Py_None) {
+    if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) {
         PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None");
         return NULL;
     }
 
-    Py_XINCREF(newpkgcb);
-    Py_XINCREF(pkgcb);
-    Py_XINCREF(warningcb);
+    Py_XINCREF(py_newpkgcb);
+    Py_XINCREF(py_pkgcb);
+    Py_XINCREF(py_warningcb);
 
     cr_XmlParserPkgCb       ptr_c_pkgcb     = NULL;
     cr_XmlParserWarningCb   ptr_c_warningcb = NULL;
 
-    if (pkgcb != Py_None)
+    if (py_pkgcb != Py_None)
         ptr_c_pkgcb = c_pkgcb;
-    if (warningcb != Py_None)
+    if (py_warningcb != Py_None)
         ptr_c_warningcb = c_warningcb;
 
+    cbdata.py_newpkgcb  = py_newpkgcb;
+    cbdata.py_pkgcb     = py_pkgcb;
+    cbdata.py_warningcb = py_warningcb;
+    cbdata.py_pkg       = NULL;
+
     cr_xml_parse_filelists(filename,
                            c_newpkgcb,
-                           newpkgcb,
+                           &cbdata,
                            ptr_c_pkgcb,
-                           pkgcb,
+                           &cbdata,
                            ptr_c_warningcb,
-                           warningcb,
+                           &cbdata,
                            &tmp_err);
 
-    Py_XDECREF(newpkgcb);
-    Py_XDECREF(pkgcb);
-    Py_XDECREF(warningcb);
+    Py_XDECREF(py_newpkgcb);
+    Py_XDECREF(py_pkgcb);
+    Py_XDECREF(py_warningcb);
 
     if (tmp_err) {
         PyErr_Format(CrErr_Exception, "%s", tmp_err->message);
@@ -244,56 +279,62 @@ py_xml_parse_other(PyObject *self, PyObject *args)
     CR_UNUSED(self);
 
     char *filename;
-    PyObject *newpkgcb, *pkgcb, *warningcb;
+    PyObject *py_newpkgcb, *py_pkgcb, *py_warningcb;
+    CbData cbdata;
     GError *tmp_err = NULL;
 
     if (!PyArg_ParseTuple(args, "sOOO:py_xml_parse_other",
                                          &filename,
-                                         &newpkgcb,
-                                         &pkgcb,
-                                         &warningcb)) {
+                                         &py_newpkgcb,
+                                         &py_pkgcb,
+                                         &py_warningcb)) {
         return NULL;
     }
 
-    if (!PyCallable_Check(newpkgcb)) {
+    if (!PyCallable_Check(py_newpkgcb)) {
         PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable");
         return NULL;
     }
 
-    if (!PyCallable_Check(pkgcb) && pkgcb != Py_None) {
+    if (!PyCallable_Check(py_pkgcb) && py_pkgcb != Py_None) {
         PyErr_SetString(PyExc_TypeError, "pkgcb must be callable or None");
         return NULL;
     }
 
-    if (!PyCallable_Check(warningcb) && warningcb != Py_None) {
+    if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) {
         PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None");
         return NULL;
     }
 
-    Py_XINCREF(newpkgcb);
-    Py_XINCREF(pkgcb);
-    Py_XINCREF(warningcb);
+    Py_XINCREF(py_newpkgcb);
+    Py_XINCREF(py_pkgcb);
+    Py_XINCREF(py_warningcb);
 
     cr_XmlParserPkgCb       ptr_c_pkgcb     = NULL;
     cr_XmlParserWarningCb   ptr_c_warningcb = NULL;
 
-    if (pkgcb != Py_None)
+    if (py_pkgcb != Py_None)
         ptr_c_pkgcb = c_pkgcb;
-    if (warningcb != Py_None)
+    if (py_warningcb != Py_None)
         ptr_c_warningcb = c_warningcb;
 
+    cbdata.py_newpkgcb  = py_newpkgcb;
+    cbdata.py_pkgcb     = py_pkgcb;
+    cbdata.py_warningcb = py_warningcb;
+    cbdata.py_pkg       = NULL;
+
     cr_xml_parse_other(filename,
                        c_newpkgcb,
-                       newpkgcb,
+                       &cbdata,
                        ptr_c_pkgcb,
-                       pkgcb,
+                       &cbdata,
                        ptr_c_warningcb,
-                       warningcb,
+                       &cbdata,
                        &tmp_err);
 
-    Py_XDECREF(newpkgcb);
-    Py_XDECREF(pkgcb);
-    Py_XDECREF(warningcb);
+    Py_XDECREF(py_newpkgcb);
+    Py_XDECREF(py_pkgcb);
+    Py_XDECREF(py_warningcb);
 
     if (tmp_err) {
         PyErr_Format(CrErr_Exception, "%s", tmp_err->message);