From 1ddee37628b8aac48a8f1fc51af4575b5570589b Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Wed, 30 Sep 2009 12:45:07 +0300 Subject: [PATCH] Add beginnings of rpmtd wrappings to python - unlike other types, store the C-level td structure directly in the python object, this lets us selectively expose some members directly, avoids having to deal with rpmtd allocation separately and as leaves the reference counting to python as rpmtd's aren't refcounted on C-level --- python/rpmmodule.c | 6 ++- python/rpmtd-py.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++ python/rpmtd-py.h | 5 +++ 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/python/rpmmodule.c b/python/rpmmodule.c index 3748e87..d034ddf 100644 --- a/python/rpmmodule.c +++ b/python/rpmmodule.c @@ -12,6 +12,7 @@ #include "rpmmi-py.h" #include "rpmps-py.h" #include "rpmmacro-py.h" +#include "rpmtd-py.h" #include "rpmte-py.h" #include "rpmts-py.h" #include "spec-py.h" @@ -203,7 +204,7 @@ void init_rpm(void) if (PyType_Ready(&rpmfi_Type) < 0) return; if (PyType_Ready(&rpmmi_Type) < 0) return; if (PyType_Ready(&rpmps_Type) < 0) return; - + if (PyType_Ready(&rpmtd_Type) < 0) return; if (PyType_Ready(&rpmte_Type) < 0) return; if (PyType_Ready(&rpmts_Type) < 0) return; if (PyType_Ready(&spec_Type) < 0) return; @@ -242,6 +243,9 @@ void init_rpm(void) Py_INCREF(&rpmps_Type); PyModule_AddObject(m, "ps", (PyObject *) &rpmps_Type); + Py_INCREF(&rpmtd_Type); + PyModule_AddObject(m, "td", (PyObject *) &rpmtd_Type); + Py_INCREF(&rpmte_Type); PyModule_AddObject(m, "te", (PyObject *) &rpmte_Type); diff --git a/python/rpmtd-py.c b/python/rpmtd-py.c index cf8c92e..aeb5a7a 100644 --- a/python/rpmtd-py.c +++ b/python/rpmtd-py.c @@ -3,8 +3,11 @@ */ #include "rpmsystem-py.h" +#include #include +#include #include "rpmtd-py.h" +#include "header-py.h" /* * Convert single tag data item to python object of suitable type @@ -51,3 +54,118 @@ PyObject *rpmtd_AsPyobj(rpmtd td) } return res; } + +struct rpmtdObject_s { + PyObject_HEAD + PyObject *md_dict; + struct rpmtd_s td; +}; + +/* string format should never fail but do regular repr just in case it does */ +static PyObject *rpmtd_str(rpmtdObject *s) +{ + PyObject *res = NULL; + char *str = rpmtdFormat(&(s->td), RPMTD_FORMAT_STRING, NULL); + if (str) { + res = PyString_FromString(str); + free(str); + } else { + res = PyObject_Repr((PyObject *)s); + } + return res; +} + +static PyObject *rpmtd_iternext(rpmtdObject *s) +{ + PyObject *next = NULL; + + if (rpmtdNext(&(s->td)) >= 0) { + Py_INCREF(s); + next = (PyObject*) s; + } + return next; +} + +static PyObject *rpmtd_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds) +{ + rpmtdObject *s = NULL; + Header h = NULL; + rpmTag tag; + char *kwlist[] = { "header", "tag", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&", kwlist, + hdrFromPyObject, &h, tagNumFromPyObject, &tag)) + return NULL; + + if ((s = (rpmtdObject *)subtype->tp_alloc(subtype, 0)) == NULL) + return PyErr_NoMemory(); + + headerGet(h, tag, &(s->td), HEADERGET_EXT); + + return (PyObject *) s; +} + +static void rpmtd_dealloc(rpmtdObject * s) +{ + rpmtdFreeData(&(s->td)); + s->ob_type->tp_free((PyObject *)s); +} + +static int rpmtd_length(rpmtdObject *s) +{ + return rpmtdCount(&(s->td)); +} + +static PyMappingMethods rpmtd_as_mapping = { + (lenfunc) rpmtd_length, /* mp_length */ +}; + +static PyMemberDef rpmtd_members[] = { + { "tag", T_INT, offsetof(rpmtdObject, td.tag), READONLY, NULL }, + { "type", T_INT, offsetof(rpmtdObject, td.type), READONLY, NULL }, + { NULL } +}; + +PyTypeObject rpmtd_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "rpm.td", /* tp_name */ + sizeof(rpmtdObject), /* tp_size */ + 0, /* tp_itemsize */ + (destructor) rpmtd_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + &rpmtd_as_mapping, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc)rpmtd_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)rpmtd_iternext, /* tp_iternext */ + 0, /* tp_methods */ + &rpmtd_members, /* tp_members */ + 0, /* 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 */ + rpmtd_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; diff --git a/python/rpmtd-py.h b/python/rpmtd-py.h index 39469f2..ac93b3a 100644 --- a/python/rpmtd-py.h +++ b/python/rpmtd-py.h @@ -1,5 +1,10 @@ #ifndef H_RPMTD_PY #define H_RPMTD_PY +typedef struct rpmtdObject_s rpmtdObject; + +extern PyTypeObject rpmtd_Type; + PyObject * rpmtd_AsPyobj(rpmtd td); + #endif -- 2.7.4