2 * \file python/rpmtd-py.c
5 #include "rpmsystem-py.h"
7 #include <rpm/header.h>
12 * Convert single tag data item to python object of suitable type
14 static PyObject * rpmtd_ItemAsPyobj(rpmtd td, rpmTagClass tclass)
19 case RPM_STRING_CLASS:
20 res = PyBytes_FromString(rpmtdGetString(td));
22 case RPM_NUMERIC_CLASS:
23 res = PyLong_FromLongLong(rpmtdGetNumber(td));
25 case RPM_BINARY_CLASS:
26 res = PyBytes_FromStringAndSize(td->data, td->count);
29 PyErr_SetString(PyExc_KeyError, "unknown data type");
35 PyObject *rpmtd_AsPyobj(rpmtd td)
38 int array = (rpmTagGetReturnType(td->tag) == RPM_ARRAY_RETURN_TYPE);
39 rpmTagClass tclass = rpmtdClass(td);
41 if (!array && rpmtdCount(td) < 1) {
47 res = PyList_New(rpmtdCount(td));
51 while ((ix = rpmtdNext(td)) >= 0) {
52 PyObject *item = rpmtd_ItemAsPyobj(td, tclass);
57 PyList_SET_ITEM(res, ix, item);
60 res = rpmtd_ItemAsPyobj(td, tclass);
66 struct rpmtdObject_s {
72 /* string format should never fail but do regular repr just in case it does */
73 static PyObject *rpmtd_str(rpmtdObject *s)
76 char *str = rpmtdFormat(&(s->td), RPMTD_FORMAT_STRING, NULL);
78 res = PyBytes_FromString(str);
81 res = PyObject_Repr((PyObject *)s);
86 static PyObject *rpmtd_iternext(rpmtdObject *s)
88 PyObject *next = NULL;
90 if (rpmtdNext(&(s->td)) >= 0) {
97 static PyObject *rpmtd_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
99 rpmtdObject *s = NULL;
104 headerGetFlags flags = (HEADERGET_EXT | HEADERGET_ALLOC);
105 char *kwlist[] = { "header", "tag", "raw", "noext", NULL };
107 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&|ii", kwlist,
108 hdrFromPyObject, &h, tagNumFromPyObject, &tag,
113 flags |= HEADERGET_RAW;
114 noext = 1; /* extensions with raw dont make sense */
116 if (noext) flags &= ~HEADERGET_EXT;
118 if ((s = (rpmtdObject *)subtype->tp_alloc(subtype, 0)) == NULL)
121 headerGet(h, tag, &(s->td), flags);
123 return (PyObject *) s;
126 static void rpmtd_dealloc(rpmtdObject * s)
128 rpmtdFreeData(&(s->td));
129 Py_TYPE(s)->tp_free((PyObject *)s);
132 static int rpmtd_length(rpmtdObject *s)
134 return rpmtdCount(&(s->td));
137 static PyMappingMethods rpmtd_as_mapping = {
138 (lenfunc) rpmtd_length, /* mp_length */
141 static PyMemberDef rpmtd_members[] = {
142 { "type", T_INT, offsetof(rpmtdObject, td.type), READONLY, NULL },
146 static PyObject *rpmtd_get_tag(rpmtdObject *s, void *closure)
148 return Py_BuildValue("i", rpmtdTag(&(s->td)));
151 static int rpmtd_set_tag(rpmtdObject *s, PyObject *value, void *closure)
154 if (!tagNumFromPyObject(value, &tag)) return -1;
156 if (!rpmtdSetTag(&(s->td), tag)) {
157 PyErr_SetString(PyExc_ValueError, "incompatible tag for data");
163 static PyGetSetDef rpmtd_getseters[] = {
164 { "tag", (getter)rpmtd_get_tag, (setter)rpmtd_set_tag, NULL },
168 PyTypeObject rpmtd_Type = {
169 PyVarObject_HEAD_INIT(&PyType_Type, 0)
170 "rpm.td", /* tp_name */
171 sizeof(rpmtdObject), /* tp_size */
173 (destructor) rpmtd_dealloc, /* tp_dealloc */
175 (getattrfunc)0, /* tp_getattr */
179 0, /* tp_as_number */
180 0, /* tp_as_sequence */
181 &rpmtd_as_mapping, /* tp_as_mapping */
184 (reprfunc)rpmtd_str, /* tp_str */
185 PyObject_GenericGetAttr, /* tp_getattro */
186 PyObject_GenericSetAttr, /* tp_setattro */
187 0, /* tp_as_buffer */
188 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
192 0, /* tp_richcompare */
193 0, /* tp_weaklistoffset */
194 PyObject_SelfIter, /* tp_iter */
195 (iternextfunc)rpmtd_iternext, /* tp_iternext */
197 rpmtd_members, /* tp_members */
198 rpmtd_getseters, /* tp_getset */
201 0, /* tp_descr_get */
202 0, /* tp_descr_set */
203 0, /* tp_dictoffset */
206 rpmtd_new, /* tp_new */
211 int rpmtdFromPyObject(PyObject *obj, rpmtd *td)
213 if (rpmtdObject_Check(obj)) {
214 *td = &(((rpmtdObject *)obj)->td);
217 PyErr_SetString(PyExc_TypeError, "rpm.td type expected");