/
niceSOFT
/
createrepo_c
Обзор
Документация
Войти
/
niceSOFT
/
createrepo_c
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/python/xml_parser-py.c
986 строк
28 KB
Daniel Alley
Add NULL checks for PyLong_FromVoidPtr in xml_parser callbacks
17 июл 2026, 10:09
17 июл 2026, 10:09
5cf41fe
Код
Авторство
О чём код?
/* createrepo_c - Library of routines for manipulation with repodata * Copyright (C) 2013 Tomas Mlcoch * * 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 <assert.h> #include <stddef.h> #include "src/createrepo_c.h" #include "xml_parser-py.h" #include "typeconversion.h" #include "package-py.h" #include "repomd-py.h" #include "updateinfo-py.h" #include "exception-py.h" typedef struct { PyObject *py_newpkgcb; PyObject *py_pkgcb; PyObject *py_warningcb; PyObject *py_pkgs; /*!< Current processed package */ } CbData; static int c_newpkgcb(cr_Package **pkg, const char *pkgId, const char *name, const char *arch, void *cbdata, GError **err) { PyObject *arglist, *result; CbData *data = cbdata; arglist = Py_BuildValue("(sss)", pkgId, name, arch); if (!arglist) { PyErr_ToGError(err); return CR_CB_RET_ERR; } result = PyObject_CallObject(data->py_newpkgcb, arglist); Py_DECREF(arglist); if (result == NULL) { // Exception raised PyErr_ToGError(err); return CR_CB_RET_ERR; } 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; } if (result == Py_None) { *pkg = NULL; } else { *pkg = Package_FromPyObject(result); if (data->py_pkgcb != Py_None) { // Store reference to the python pkg (result) only if we will need it later PyObject *keyFromPtr = PyLong_FromVoidPtr(*pkg); if (!keyFromPtr) { Py_DECREF(result); PyErr_ToGError(err); return CR_CB_RET_ERR; } PyDict_SetItem(data->py_pkgs, keyFromPtr, result); Py_DECREF(keyFromPtr); } } if (Py_REFCNT(result) == 1) { *pkg = NULL; } Py_DECREF(result); return CR_CB_RET_OK; } static int c_pkgcb(cr_Package *pkg, void *cbdata, GError **err) { // destroys "pkg" PyObject *arglist, *result, *py_pkg; CbData *data = cbdata; PyObject *keyFromPtr = PyLong_FromVoidPtr(pkg); if (!keyFromPtr) { PyErr_ToGError(err); return CR_CB_RET_ERR; } py_pkg = PyDict_GetItem(data->py_pkgs, keyFromPtr); if (py_pkg) { arglist = Py_BuildValue("(O)", py_pkg); if (!arglist) { Py_DECREF(keyFromPtr); PyErr_ToGError(err); return CR_CB_RET_ERR; } result = PyObject_CallObject(data->py_pkgcb, arglist); PyDict_DelItem(data->py_pkgs, keyFromPtr); } else { // The package was not provided by user in c_newpkgcb, // create new python package object PyObject *new_py_pkg = Object_FromPackage(pkg, 1); if (!new_py_pkg) { Py_DECREF(keyFromPtr); PyErr_ToGError(err); return CR_CB_RET_ERR; } arglist = Py_BuildValue("(O)", new_py_pkg); Py_DECREF(new_py_pkg); if (!arglist) { Py_DECREF(keyFromPtr); PyErr_ToGError(err); return CR_CB_RET_ERR; } result = PyObject_CallObject(data->py_pkgcb, arglist); } Py_DECREF(arglist); Py_DECREF(keyFromPtr); if (result == NULL) { // Exception raised PyErr_ToGError(err); return CR_CB_RET_ERR; } Py_DECREF(result); return CR_CB_RET_OK; } static int c_warningcb(cr_XmlParserWarningType type, char *msg, void *cbdata, GError **err) { PyObject *arglist, *result; CbData *data = cbdata; arglist = Py_BuildValue("(is)", type, msg); if (!arglist) { PyErr_ToGError(err); return CR_CB_RET_ERR; } result = PyObject_CallObject(data->py_warningcb, arglist); Py_DECREF(arglist); if (result == NULL) { // Exception raised PyErr_ToGError(err); return CR_CB_RET_ERR; } Py_DECREF(result); return CR_CB_RET_OK; } PyObject * py_xml_parse_primary(G_GNUC_UNUSED PyObject *self, PyObject *args) { char *filename; int do_files; PyObject *py_newpkgcb, *py_pkgcb, *py_warningcb; CbData cbdata; GError *tmp_err = NULL; if (!PyArg_ParseTuple(args, "sOOOi:py_xml_parse_primary", &filename, &py_newpkgcb, &py_pkgcb, &py_warningcb, &do_files)) { return NULL; } if (!PyCallable_Check(py_newpkgcb) && py_newpkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_pkgcb) && py_pkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "pkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) { PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None"); return NULL; } if (py_newpkgcb == Py_None && py_pkgcb == Py_None) { PyErr_SetString(PyExc_ValueError, "both pkgcb and newpkgcb cannot be None"); return NULL; } Py_XINCREF(py_newpkgcb); Py_XINCREF(py_pkgcb); Py_XINCREF(py_warningcb); cr_XmlParserNewPkgCb ptr_c_newpkgcb = NULL; cr_XmlParserPkgCb ptr_c_pkgcb = NULL; cr_XmlParserWarningCb ptr_c_warningcb = NULL; if (py_newpkgcb != Py_None) ptr_c_newpkgcb = c_newpkgcb; if (py_pkgcb != Py_None) ptr_c_pkgcb = c_pkgcb; 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_pkgs = PyDict_New(); cr_xml_parse_primary(filename, ptr_c_newpkgcb, &cbdata, ptr_c_pkgcb, &cbdata, ptr_c_warningcb, &cbdata, do_files, &tmp_err); Py_XDECREF(py_newpkgcb); Py_XDECREF(py_pkgcb); Py_XDECREF(py_warningcb); Py_XDECREF(cbdata.py_pkgs); if (tmp_err) { nice_exception(&tmp_err, NULL); return NULL; } Py_RETURN_NONE; } PyObject * py_xml_parse_primary_snippet(G_GNUC_UNUSED PyObject *self, PyObject *args) { char *target; int do_files; PyObject *py_newpkgcb, *py_pkgcb, *py_warningcb; CbData cbdata; GError *tmp_err = NULL; if (!PyArg_ParseTuple(args, "sOOOi:py_xml_parse_primary_snippet", &target, &py_newpkgcb, &py_pkgcb, &py_warningcb, &do_files)) { return NULL; } if (!PyCallable_Check(py_newpkgcb) && py_newpkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_pkgcb) && py_pkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "pkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) { PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None"); return NULL; } if (py_newpkgcb == Py_None && py_pkgcb == Py_None) { PyErr_SetString(PyExc_ValueError, "both pkgcb and newpkgcb cannot be None"); return NULL; } Py_XINCREF(py_newpkgcb); Py_XINCREF(py_pkgcb); Py_XINCREF(py_warningcb); cr_XmlParserNewPkgCb ptr_c_newpkgcb = NULL; cr_XmlParserPkgCb ptr_c_pkgcb = NULL; cr_XmlParserWarningCb ptr_c_warningcb = NULL; if (py_newpkgcb != Py_None) ptr_c_newpkgcb = c_newpkgcb; if (py_pkgcb != Py_None) ptr_c_pkgcb = c_pkgcb; 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_pkgs = PyDict_New(); cr_xml_parse_primary_snippet(target, ptr_c_newpkgcb, &cbdata, ptr_c_pkgcb, &cbdata, ptr_c_warningcb, &cbdata, do_files, &tmp_err); Py_XDECREF(py_newpkgcb); Py_XDECREF(py_pkgcb); Py_XDECREF(py_warningcb); Py_XDECREF(cbdata.py_pkgs); if (tmp_err) { nice_exception(&tmp_err, NULL); return NULL; } Py_RETURN_NONE; } PyObject * py_xml_parse_filelists(G_GNUC_UNUSED PyObject *self, PyObject *args) { char *filename; PyObject *py_newpkgcb, *py_pkgcb, *py_warningcb; CbData cbdata; GError *tmp_err = NULL; if (!PyArg_ParseTuple(args, "sOOO:py_xml_parse_filelists", &filename, &py_newpkgcb, &py_pkgcb, &py_warningcb)) { return NULL; } if (!PyCallable_Check(py_newpkgcb) && py_newpkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_pkgcb) && py_pkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "pkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) { PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None"); return NULL; } if (py_newpkgcb == Py_None && py_pkgcb == Py_None) { PyErr_SetString(PyExc_ValueError, "both pkgcb and newpkgcb cannot be None"); return NULL; } Py_XINCREF(py_newpkgcb); Py_XINCREF(py_pkgcb); Py_XINCREF(py_warningcb); cr_XmlParserNewPkgCb ptr_c_newpkgcb = NULL; cr_XmlParserPkgCb ptr_c_pkgcb = NULL; cr_XmlParserWarningCb ptr_c_warningcb = NULL; if (py_newpkgcb != Py_None) ptr_c_newpkgcb = c_newpkgcb; if (py_pkgcb != Py_None) ptr_c_pkgcb = c_pkgcb; 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_pkgs = PyDict_New(); cr_xml_parse_filelists(filename, ptr_c_newpkgcb, &cbdata, ptr_c_pkgcb, &cbdata, ptr_c_warningcb, &cbdata, &tmp_err); Py_XDECREF(py_newpkgcb); Py_XDECREF(py_pkgcb); Py_XDECREF(py_warningcb); Py_XDECREF(cbdata.py_pkgs); if (tmp_err) { nice_exception(&tmp_err, NULL); return NULL; } Py_RETURN_NONE; } PyObject * py_xml_parse_filelists_snippet(G_GNUC_UNUSED PyObject *self, PyObject *args) { char *target; PyObject *py_newpkgcb, *py_pkgcb, *py_warningcb; CbData cbdata; GError *tmp_err = NULL; if (!PyArg_ParseTuple(args, "sOOO:py_xml_parse_filelists_snippet", &target, &py_newpkgcb, &py_pkgcb, &py_warningcb)) { return NULL; } if (!PyCallable_Check(py_newpkgcb) && py_newpkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_pkgcb) && py_pkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "pkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) { PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None"); return NULL; } if (py_newpkgcb == Py_None && py_pkgcb == Py_None) { PyErr_SetString(PyExc_ValueError, "both pkgcb and newpkgcb cannot be None"); return NULL; } Py_XINCREF(py_newpkgcb); Py_XINCREF(py_pkgcb); Py_XINCREF(py_warningcb); cr_XmlParserNewPkgCb ptr_c_newpkgcb = NULL; cr_XmlParserPkgCb ptr_c_pkgcb = NULL; cr_XmlParserWarningCb ptr_c_warningcb = NULL; if (py_newpkgcb != Py_None) ptr_c_newpkgcb = c_newpkgcb; if (py_pkgcb != Py_None) ptr_c_pkgcb = c_pkgcb; 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_pkgs = PyDict_New(); cr_xml_parse_filelists_snippet(target, ptr_c_newpkgcb, &cbdata, ptr_c_pkgcb, &cbdata, ptr_c_warningcb, &cbdata, &tmp_err); Py_XDECREF(py_newpkgcb); Py_XDECREF(py_pkgcb); Py_XDECREF(py_warningcb); Py_XDECREF(cbdata.py_pkgs); if (tmp_err) { nice_exception(&tmp_err, NULL); return NULL; } Py_RETURN_NONE; } PyObject * py_xml_parse_other(G_GNUC_UNUSED PyObject *self, PyObject *args) { char *filename; PyObject *py_newpkgcb, *py_pkgcb, *py_warningcb; CbData cbdata; GError *tmp_err = NULL; if (!PyArg_ParseTuple(args, "sOOO:py_xml_parse_other", &filename, &py_newpkgcb, &py_pkgcb, &py_warningcb)) { return NULL; } if (!PyCallable_Check(py_newpkgcb) && py_newpkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_pkgcb) && py_pkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "pkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) { PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None"); return NULL; } if (py_newpkgcb == Py_None && py_pkgcb == Py_None) { PyErr_SetString(PyExc_ValueError, "both pkgcb and newpkgcb cannot be None"); return NULL; } Py_XINCREF(py_newpkgcb); Py_XINCREF(py_pkgcb); Py_XINCREF(py_warningcb); cr_XmlParserNewPkgCb ptr_c_newpkgcb = NULL; cr_XmlParserPkgCb ptr_c_pkgcb = NULL; cr_XmlParserWarningCb ptr_c_warningcb = NULL; if (py_newpkgcb != Py_None) ptr_c_newpkgcb = c_newpkgcb; if (py_pkgcb != Py_None) ptr_c_pkgcb = c_pkgcb; 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_pkgs = PyDict_New(); cr_xml_parse_other(filename, ptr_c_newpkgcb, &cbdata, ptr_c_pkgcb, &cbdata, ptr_c_warningcb, &cbdata, &tmp_err); Py_XDECREF(py_newpkgcb); Py_XDECREF(py_pkgcb); Py_XDECREF(py_warningcb); Py_XDECREF(cbdata.py_pkgs); if (tmp_err) { nice_exception(&tmp_err, NULL); return NULL; } Py_RETURN_NONE; } PyObject * py_xml_parse_other_snippet(G_GNUC_UNUSED PyObject *self, PyObject *args) { char *target; PyObject *py_newpkgcb, *py_pkgcb, *py_warningcb; CbData cbdata; GError *tmp_err = NULL; if (!PyArg_ParseTuple(args, "sOOO:py_xml_parse_other_snippet", &target, &py_newpkgcb, &py_pkgcb, &py_warningcb)) { return NULL; } if (!PyCallable_Check(py_newpkgcb) && py_newpkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_pkgcb) && py_pkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "pkgcb must be callable or None"); return NULL; } if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) { PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None"); return NULL; } if (py_newpkgcb == Py_None && py_pkgcb == Py_None) { PyErr_SetString(PyExc_ValueError, "both pkgcb and newpkgcb cannot be None"); return NULL; } Py_XINCREF(py_newpkgcb); Py_XINCREF(py_pkgcb); Py_XINCREF(py_warningcb); cr_XmlParserNewPkgCb ptr_c_newpkgcb = NULL; cr_XmlParserPkgCb ptr_c_pkgcb = NULL; cr_XmlParserWarningCb ptr_c_warningcb = NULL; if (py_newpkgcb != Py_None) ptr_c_newpkgcb = c_newpkgcb; if (py_pkgcb != Py_None) ptr_c_pkgcb = c_pkgcb; 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_pkgs = PyDict_New(); cr_xml_parse_other_snippet(target, ptr_c_newpkgcb, &cbdata, ptr_c_pkgcb, &cbdata, ptr_c_warningcb, &cbdata, &tmp_err); Py_XDECREF(py_newpkgcb); Py_XDECREF(py_pkgcb); Py_XDECREF(py_warningcb); Py_XDECREF(cbdata.py_pkgs); if (tmp_err) { nice_exception(&tmp_err, NULL); return NULL; } Py_RETURN_NONE; } PyObject * py_xml_parse_repomd(G_GNUC_UNUSED PyObject *self, PyObject *args) { char *filename; PyObject *py_repomd, *py_warningcb; CbData cbdata; cr_Repomd *repomd; GError *tmp_err = NULL; if (!PyArg_ParseTuple(args, "sO!O:py_xml_parse_repomd", &filename, &Repomd_Type, &py_repomd, &py_warningcb)) { return NULL; } if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) { PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None"); return NULL; } Py_XINCREF(py_repomd); Py_XINCREF(py_warningcb); cr_XmlParserWarningCb ptr_c_warningcb = NULL; if (py_warningcb != Py_None) ptr_c_warningcb = c_warningcb; cbdata.py_newpkgcb = NULL; cbdata.py_pkgcb = NULL; cbdata.py_warningcb = py_warningcb; cbdata.py_pkgs = NULL; repomd = Repomd_FromPyObject(py_repomd); cr_xml_parse_repomd(filename, repomd, ptr_c_warningcb, &cbdata, &tmp_err); Py_XDECREF(py_repomd); Py_XDECREF(py_warningcb); if (tmp_err) { nice_exception(&tmp_err, NULL); return NULL; } Py_RETURN_NONE; } PyObject * py_xml_parse_updateinfo(G_GNUC_UNUSED PyObject *self, PyObject *args) { char *filename; PyObject *py_updateinfo, *py_warningcb; CbData cbdata; cr_UpdateInfo *updateinfo; GError *tmp_err = NULL; if (!PyArg_ParseTuple(args, "sO!O:py_xml_parse_updateinfo", &filename, &UpdateInfo_Type, &py_updateinfo, &py_warningcb)) { return NULL; } if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) { PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None"); return NULL; } Py_XINCREF(py_updateinfo); Py_XINCREF(py_warningcb); cr_XmlParserWarningCb ptr_c_warningcb = NULL; if (py_warningcb != Py_None) ptr_c_warningcb = c_warningcb; cbdata.py_newpkgcb = NULL; cbdata.py_pkgcb = NULL; cbdata.py_warningcb = py_warningcb; cbdata.py_pkgs = NULL; updateinfo = UpdateInfo_FromPyObject(py_updateinfo); cr_xml_parse_updateinfo(filename, updateinfo, ptr_c_warningcb, &cbdata, &tmp_err); Py_XDECREF(py_updateinfo); Py_XDECREF(py_warningcb); if (tmp_err) { nice_exception(&tmp_err, NULL); return NULL; } Py_RETURN_NONE; } typedef struct { PyObject_HEAD cr_PkgIterator *pkg_iterator; CbData *cbdata; } _PkgIteratorObject; cr_PkgIterator * PkgIterator_FromPyObject(PyObject *o) { if (!PkgIteratorObject_Check(o)) { PyErr_SetString(PyExc_TypeError, "Expected a createrepo_c.PkgIterator object."); return NULL; } return ((_PkgIteratorObject *)o)->pkg_iterator; } PyObject * Object_FromPkgIterator(cr_PkgIterator *pkg_iterator) { if (!pkg_iterator) { PyErr_SetString(PyExc_ValueError, "Expected a cr_PkgIterator pointer not NULL."); return NULL; } PyObject *py_pkg_iterator = PyObject_CallObject((PyObject *)&PkgIterator_Type, NULL); if (!py_pkg_iterator) return NULL; ((_PkgIteratorObject *)py_pkg_iterator)->pkg_iterator = pkg_iterator; return py_pkg_iterator; } static int check_PkgIteratorStatus(const _PkgIteratorObject *self) { assert(self != NULL); assert(PkgIteratorObject_Check(self)); if (self->pkg_iterator == NULL) { PyErr_SetString(CrErr_Exception, "Improper createrepo_c PkgIterator object."); return -1; } return 0; } /* Function on the type */ static PyObject * pkg_iterator_new(PyTypeObject *type, G_GNUC_UNUSED PyObject *args, G_GNUC_UNUSED PyObject *kwds) { _PkgIteratorObject *self = (_PkgIteratorObject *)type->tp_alloc(type, 0); if (self) { self->pkg_iterator = NULL; self->cbdata = g_malloc0(sizeof(CbData)); } return (PyObject *)self; } PyDoc_STRVAR(pkg_iterator_init__doc__, "PkgIterator object\n\n" ".. method:: __init__()\n\n" " Default constructor\n"); static int pkg_iterator_init(_PkgIteratorObject *self, PyObject *args, PyObject *kwargs) { char *primary_path; char *filelists_path; char *other_path; PyObject *py_newpkgcb, *py_warningcb; GError *tmp_err = NULL; static char *kwlist[] = {"primary", "filelists", "other", "newpkgcb", "warningcb", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szzOO:pkg_iterator_init", kwlist, &primary_path, &filelists_path, &other_path, &py_newpkgcb, &py_warningcb)) { return -1; } if (!primary_path) { PyErr_SetString(PyExc_TypeError, "primary file path must be provided"); return -1; } if (!PyCallable_Check(py_newpkgcb) && py_newpkgcb != Py_None) { PyErr_SetString(PyExc_TypeError, "newpkgcb must be callable or None"); return -1; } if (!PyCallable_Check(py_warningcb) && py_warningcb != Py_None) { PyErr_SetString(PyExc_TypeError, "warningcb must be callable or None"); return -1; } if (self->pkg_iterator) { // reinitialization by __init__() cr_PkgIterator_free(self->pkg_iterator, &tmp_err); self->pkg_iterator = NULL; Py_XDECREF(self->cbdata->py_newpkgcb); Py_XDECREF(self->cbdata->py_warningcb); Py_XDECREF(self->cbdata->py_pkgs); self->cbdata->py_newpkgcb = NULL; self->cbdata->py_warningcb = NULL; self->cbdata->py_pkgs = NULL; } if (tmp_err) { nice_exception(&tmp_err, NULL); return -1; } Py_XINCREF(py_newpkgcb); Py_XINCREF(py_warningcb); cr_XmlParserNewPkgCb ptr_c_newpkgcb = NULL; cr_XmlParserWarningCb ptr_c_warningcb = NULL; if (py_newpkgcb != Py_None) ptr_c_newpkgcb = c_newpkgcb; if (py_warningcb != Py_None) ptr_c_warningcb = c_warningcb; self->cbdata->py_newpkgcb = py_newpkgcb; self->cbdata->py_pkgcb = NULL; self->cbdata->py_warningcb = py_warningcb; self->cbdata->py_pkgs = PyDict_New(); self->pkg_iterator = cr_PkgIterator_new( primary_path, filelists_path, other_path, ptr_c_newpkgcb, self->cbdata, ptr_c_warningcb, self->cbdata, &tmp_err); if (tmp_err) { nice_exception(&tmp_err, NULL); return -1; } if (self->pkg_iterator == NULL) { PyErr_SetString(CrErr_Exception, "PkgIterator initialization failed"); return -1; } return 0; } static void pkg_iterator_dealloc(_PkgIteratorObject *self) { GError *tmp_err = NULL; if (self->pkg_iterator) { cr_PkgIterator_free(self->pkg_iterator, &tmp_err); } if (self->cbdata) { Py_XDECREF(self->cbdata->py_newpkgcb); Py_XDECREF(self->cbdata->py_warningcb); Py_XDECREF(self->cbdata->py_pkgs); free(self->cbdata); } freefunc free_func = PyType_GetSlot(Py_TYPE(self), Py_tp_free); free_func(self); } static PyObject * pkg_iterator_next_package(PyObject *PyObject_self) { _PkgIteratorObject *self = (_PkgIteratorObject *) PyObject_self; cr_Package *pkg; GError *tmp_err = NULL; if (check_PkgIteratorStatus(self)) { return NULL; } pkg = cr_PkgIterator_parse_next(self->pkg_iterator, &tmp_err); if (tmp_err) { cr_package_free(pkg); nice_exception(&tmp_err, NULL); return NULL; } if (!pkg) { assert(cr_PkgIterator_is_finished(self->pkg_iterator)); PyErr_SetNone(PyExc_StopIteration); return NULL; } PyObject *keyFromPtr = PyLong_FromVoidPtr(pkg); if (!keyFromPtr) { cr_package_free(pkg); return NULL; } PyObject *py_pkg = PyDict_GetItem(self->cbdata->py_pkgs, keyFromPtr); if (py_pkg) { // Remove pkg from PyDict but keep one reference so its not freed if the // user doesn't have any references to the package Py_XINCREF(py_pkg); PyDict_DelItem(self->cbdata->py_pkgs, keyFromPtr); } else { // The package was not provided by user in c_newpkgcb, // create new python package object py_pkg = Object_FromPackage(pkg, 1); } Py_DECREF(keyFromPtr); return py_pkg; } static PyObject * pkg_iterator_is_finished(_PkgIteratorObject *self, G_GNUC_UNUSED void *nothing) { if (check_PkgIteratorStatus(self)) return NULL; if (cr_PkgIterator_is_finished (self->pkg_iterator)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } PyDoc_STRVAR(pkg_iterator_is_finished__doc__, "Whether the package iterator has been consumed. \n\n" ".. method:: is_finished()\n\n" " Whether the iterator is consumed.\n"); static struct PyMethodDef pkg_iterator_methods[] = { {"is_finished", (PyCFunction) pkg_iterator_is_finished, METH_NOARGS, pkg_iterator_is_finished__doc__}, {NULL, NULL, 0, NULL} /* sentinel */ }; /* Object */ PyTypeObject PkgIterator_Type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "createrepo_c.PkgIterator", .tp_basicsize = sizeof(_PkgIteratorObject), .tp_dealloc = (destructor) pkg_iterator_dealloc, .tp_repr = 0, // (reprfunc) pkg_iterator_repr, .tp_str = 0, //(reprfunc) pkg_iterator_str, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_doc = pkg_iterator_init__doc__, .tp_iter = PyObject_SelfIter, .tp_iternext = pkg_iterator_next_package, .tp_methods = pkg_iterator_methods, .tp_init = (initproc) pkg_iterator_init, .tp_new = pkg_iterator_new, };