Call (sub)type tp_free from destructors
[platform/upstream/rpm.git] / python / rpmmi-py.c
1 #include "rpmsystem-py.h"
2
3 #include <rpm/rpmdb.h>
4
5 #include "rpmmi-py.h"
6 #include "header-py.h"
7
8 #include "debug.h"
9
10 /** \ingroup python
11  * \class Rpmmi
12  * \brief A python rpm.mi match iterator object represents the result of a
13  *      database query.
14  *
15  * Instances of the rpm.mi object provide access to headers that match
16  * certain criteria. Typically, a primary index is accessed to find
17  * a set of headers that contain a key, and each header is returned
18  * serially.
19  *
20  * The rpm.mi class conains the following methods:
21  * - next() -> hdr              Return the next header that matches.
22  *
23  * - pattern(tag,mire,pattern)  Specify secondary match criteria.
24  *
25  * To obtain a rpm.mi object to query the database used by a transaction,
26  * the ts.match(tag,key,len) method is used.
27  *
28  * Here's an example that prints the name of all installed packages:
29  * \code
30  *      import rpm
31  *      ts = rpm.TransactionSet()
32  *      for h in ts.dbMatch():
33  *          print h['name']
34  * \endcode
35  *
36  * Here's a more typical example that uses the Name index to retrieve
37  * all installed kernel(s):
38  * \code
39  *      import rpm
40  *      ts = rpm.TransactionSet()
41  *      mi = ts.dbMatch('name', "kernel")
42  *      for h in mi:
43  *          print "%s-%s-%s" % (h['name'], h['version'], h['release'])
44  * \endcode
45  *
46  * Finally, here's an example that retrieves all packages whose name
47  * matches the glob expression "XFree*":
48  * \code
49  *      import rpm
50  *      ts = rpm.TransactionSet()
51  *      mi = ts.dbMatch()
52  *      mi.pattern('name', rpm.RPMMIRE_GLOB, "XFree*")
53  *      for h in mi:
54  *          print "%s-%s-%s" % (h['name'], h['version'], h['release'])
55  * \endcode
56  *
57  */
58
59 /** \ingroup python
60  * \name Class: Rpmmi
61  */
62
63 struct rpmmiObject_s {
64     PyObject_HEAD
65     PyObject *md_dict;          /*!< to look like PyModuleObject */
66     PyObject *ref;              /* for db/ts refcounting */
67     rpmdbMatchIterator mi;
68 } ;
69
70 static PyObject *
71 rpmmi_iternext(rpmmiObject * s)
72 {
73     Header h;
74
75     if (s->mi == NULL || (h = rpmdbNextIterator(s->mi)) == NULL) {
76         s->mi = rpmdbFreeIterator(s->mi);
77         return NULL;
78     }
79     return hdr_Wrap(&hdr_Type, h);
80 }
81
82 static PyObject *
83 rpmmi_Instance(rpmmiObject * s)
84 {
85     int rc = 0;
86
87     if (s->mi != NULL)
88         rc = rpmdbGetIteratorOffset(s->mi);
89
90     return Py_BuildValue("i", rc);
91 }
92
93 static PyObject *
94 rpmmi_Count(rpmmiObject * s)
95 {
96     int rc = 0;
97
98     if (s->mi != NULL)
99         rc = rpmdbGetIteratorCount(s->mi);
100
101     return Py_BuildValue("i", rc);
102 }
103
104 static PyObject *
105 rpmmi_Pattern(rpmmiObject * s, PyObject * args, PyObject * kwds)
106 {
107     int type;
108     char * pattern;
109     rpmTag tag;
110     char * kwlist[] = {"tag", "type", "patern", NULL};
111
112     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&is:Pattern", kwlist,
113             tagNumFromPyObject, &tag, &type, &pattern))
114         return NULL;
115
116     rpmdbSetIteratorRE(s->mi, tag, type, pattern);
117
118     Py_RETURN_NONE;
119 }
120
121 static struct PyMethodDef rpmmi_methods[] = {
122     {"instance",    (PyCFunction) rpmmi_Instance,       METH_NOARGS,
123         NULL },
124     {"count",       (PyCFunction) rpmmi_Count,          METH_NOARGS,
125         NULL },
126     {"pattern",     (PyCFunction) rpmmi_Pattern,        METH_VARARGS|METH_KEYWORDS,
127 "mi.pattern(TagN, mire_type, pattern)\n\
128 - Set a secondary match pattern on tags from retrieved header.\n" },
129     {NULL,              NULL}           /* sentinel */
130 };
131
132 static void rpmmi_dealloc(rpmmiObject * s)
133 {
134     s->mi = rpmdbFreeIterator(s->mi);
135     Py_DECREF(s->ref);
136     s->ob_type->tp_free((PyObject *)s);
137 }
138
139 static char rpmmi_doc[] =
140 "";
141
142 PyTypeObject rpmmi_Type = {
143         PyObject_HEAD_INIT(&PyType_Type)
144         0,                              /* ob_size */
145         "rpm.mi",                       /* tp_name */
146         sizeof(rpmmiObject),            /* tp_size */
147         0,                              /* tp_itemsize */
148         (destructor) rpmmi_dealloc,     /* tp_dealloc */
149         0,                              /* tp_print */
150         (getattrfunc)0,                 /* tp_getattr */
151         0,                              /* tp_setattr */
152         0,                              /* tp_compare */
153         0,                              /* tp_repr */
154         0,                              /* tp_as_number */
155         0,                              /* tp_as_sequence */
156         0,                              /* tp_as_mapping */
157         0,                              /* tp_hash */
158         0,                              /* tp_call */
159         0,                              /* tp_str */
160         PyObject_GenericGetAttr,        /* tp_getattro */
161         PyObject_GenericSetAttr,        /* tp_setattro */
162         0,                              /* tp_as_buffer */
163         Py_TPFLAGS_DEFAULT,             /* tp_flags */
164         rpmmi_doc,                      /* tp_doc */
165         0,                              /* tp_traverse */
166         0,                              /* tp_clear */
167         0,                              /* tp_richcompare */
168         0,                              /* tp_weaklistoffset */
169         PyObject_SelfIter,              /* tp_iter */
170         (iternextfunc) rpmmi_iternext,  /* tp_iternext */
171         rpmmi_methods,                  /* tp_methods */
172         0,                              /* tp_members */
173         0,                              /* tp_getset */
174         0,                              /* tp_base */
175         0,                              /* tp_dict */
176         0,                              /* tp_descr_get */
177         0,                              /* tp_descr_set */
178         0,                              /* tp_dictoffset */
179         0,                              /* tp_init */
180         0,                              /* tp_alloc */
181         0,                              /* tp_new */
182         0,                              /* tp_free */
183         0,                              /* tp_is_gc */
184 };
185
186 PyObject * rpmmi_Wrap(PyTypeObject *subtype, rpmdbMatchIterator mi, PyObject *s)
187 {
188     rpmmiObject * mio = (rpmmiObject *)subtype->tp_alloc(subtype, 0);
189     if (mio == NULL) return PyErr_NoMemory();
190
191     mio->mi = mi;
192     mio->ref = s;
193     Py_INCREF(mio->ref);
194     return (PyObject *) mio;
195 }
196