Imported Upstream version 4.14.1
[platform/upstream/rpm.git] / python / rpmmi-py.c
1 #include "rpmsystem-py.h"
2
3 #include <rpm/rpmdb.h>
4 #include <rpm/header.h>
5
6 #include "rpmmi-py.h"
7 #include "header-py.h"
8
9 /** \ingroup python
10  * \class Rpmmi
11  * \brief A python rpm.mi match iterator object represents the result of a
12  *      database query.
13  *
14  * Instances of the rpm.mi object provide access to headers that match
15  * certain criteria. Typically, a primary index is accessed to find
16  * a set of headers that contain a key, and each header is returned
17  * serially.
18  *
19  * The rpm.mi class conains the following methods:
20  * - next() -> hdr              Return the next header that matches.
21  *
22  * - pattern(tag,mire,pattern)  Specify secondary match criteria.
23  *
24  * To obtain a rpm.mi object to query the database used by a transaction,
25  * the ts.match(tag,key,len) method is used.
26  *
27  * Here's an example that prints the name of all installed packages:
28  * \code
29  *      import rpm
30  *      ts = rpm.TransactionSet()
31  *      for h in ts.dbMatch():
32  *          print h['name']
33  * \endcode
34  *
35  * Here's a more typical example that uses the Name index to retrieve
36  * all installed kernel(s):
37  * \code
38  *      import rpm
39  *      ts = rpm.TransactionSet()
40  *      mi = ts.dbMatch('name', 'kernel')
41  *      for h in mi:
42  *          print '%s-%s-%s' % (h['name'], h['version'], h['release'])
43  * \endcode
44  *
45  * Finally, here's an example that retrieves all packages whose name
46  * matches the glob expression 'XFree*':
47  * \code
48  *      import rpm
49  *      ts = rpm.TransactionSet()
50  *      mi = ts.dbMatch()
51  *      mi.pattern('name', rpm.RPMMIRE_GLOB, 'XFree*')
52  *      for h in mi:
53  *          print '%s-%s-%s' % (h['name'], h['version'], h['release'])
54  * \endcode
55  *
56  */
57
58 /** \ingroup python
59  * \name Class: Rpmmi
60  */
61
62 struct rpmmiObject_s {
63     PyObject_HEAD
64     PyObject *md_dict;          /*!< to look like PyModuleObject */
65     PyObject *ref;              /* for db/ts refcounting */
66     rpmdbMatchIterator mi;
67 } ;
68
69 static PyObject *
70 rpmmi_iternext(rpmmiObject * s)
71 {
72     Header h;
73
74     if (s->mi == NULL || (h = rpmdbNextIterator(s->mi)) == NULL) {
75         s->mi = rpmdbFreeIterator(s->mi);
76         return NULL;
77     }
78     headerLink(h);
79     return hdr_Wrap(&hdr_Type, h);
80 }
81
82 static PyObject *
83 rpmmi_Instance(rpmmiObject * s, PyObject * unused)
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, PyObject * unused)
95 {
96     DEPRECATED_METHOD("use len(mi) instead");
97     return Py_BuildValue("i", PyMapping_Size((PyObject *)s));
98 }
99
100 static PyObject *
101 rpmmi_Pattern(rpmmiObject * s, PyObject * args, PyObject * kwds)
102 {
103     int type;
104     const char * pattern;
105     rpmTagVal tag;
106     char * kwlist[] = {"tag", "type", "patern", NULL};
107
108     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&is:Pattern", kwlist,
109             tagNumFromPyObject, &tag, &type, &pattern))
110         return NULL;
111
112     rpmdbSetIteratorRE(s->mi, tag, type, pattern);
113
114     Py_RETURN_NONE;
115 }
116
117 static struct PyMethodDef rpmmi_methods[] = {
118     {"instance",    (PyCFunction) rpmmi_Instance,       METH_NOARGS,
119      "mi.instance() -- Return the number (db key) of the current header."},
120     {"count",       (PyCFunction) rpmmi_Count,          METH_NOARGS,
121 "Deprecated, use len(mi) instead.\n" },
122     {"pattern",     (PyCFunction) rpmmi_Pattern,        METH_VARARGS|METH_KEYWORDS,
123 "mi.pattern(TagN, mire_type, pattern)\n\
124 - Set a secondary match pattern on tags from retrieved header.\n" },
125     {NULL,              NULL}           /* sentinel */
126 };
127
128 static void rpmmi_dealloc(rpmmiObject * s)
129 {
130     s->mi = rpmdbFreeIterator(s->mi);
131     Py_DECREF(s->ref);
132     Py_TYPE(s)->tp_free((PyObject *)s);
133 }
134
135 static Py_ssize_t rpmmi_length(rpmmiObject * s)
136 {
137     return s->mi ? rpmdbGetIteratorCount(s->mi) : 0;
138 }
139
140 static int rpmmi_bool(rpmmiObject *s)
141 {
142     return (s->mi != NULL);
143 }
144
145 PyMappingMethods rpmmi_as_mapping = {
146     (lenfunc) rpmmi_length,             /* mp_length */
147     0,
148 };
149
150 static PyNumberMethods rpmmi_as_number = {
151         0, /* nb_add */
152         0, /* nb_subtract */
153         0, /* nb_multiply */
154 #if PY_MAJOR_VERSION < 3
155         0, /* nb_divide */
156 #endif
157         0, /* nb_remainder */
158         0, /* nb_divmod */
159         0, /* nb_power */
160         0, /* nb_negative */
161         0, /* nb_positive */
162         0, /* nb_absolute */
163         (inquiry)rpmmi_bool, /* nb_bool/nonzero */
164 };
165
166 static char rpmmi_doc[] =
167   "rpm.mi match iterator object represents the result of a\n"
168   "     database query.\n"
169   "\n"
170   "Instances of the rpm.mi object provide access to headers that match\n"
171   "certain criteria. Typically, a primary index is accessed to find\n"
172   "a set of headers that contain a key, and each header is returned\n"
173   "serially.\n"
174   "\n"
175   "To obtain a rpm.mi object to query the database used by a transaction,\n"
176   "the ts.match(tag,key,len) method is used.\n"
177   "\n"
178   "Here's an example that prints the name of all installed packages:\n"
179   "     import rpm\n"
180   "     ts = rpm.TransactionSet()\n"
181   "     for h in ts.dbMatch():\n"
182   "         print h['name']\n"
183   "\n"
184   "Here's a more typical example that uses the Name index to retrieve\n"
185   "all installed kernel(s):\n"
186   "     import rpm\n"
187   "     ts = rpm.TransactionSet()\n"
188   "     mi = ts.dbMatch('name', 'kernel')\n"
189   "     for h in mi:\n"
190   "         print '%s-%s-%s' % (h['name'], h['version'], h['release'])\n"
191   "\n"
192   "Finally, here's an example that retrieves all packages whose name\n"
193   "matches the glob expression 'XFree*':\n"
194   "     import rpm\n"
195   "     ts = rpm.TransactionSet()\n"
196   "     mi = ts.dbMatch()\n"
197   "     mi.pattern('name', rpm.RPMMIRE_GLOB, 'XFree*')\n"
198   "     for h in mi:\n"
199   "         print '%s-%s-%s' % (h['name'], h['version'], h['release'])\n"
200 ;
201
202 PyTypeObject rpmmi_Type = {
203         PyVarObject_HEAD_INIT(&PyType_Type, 0)
204         "rpm.mi",                       /* tp_name */
205         sizeof(rpmmiObject),            /* tp_size */
206         0,                              /* tp_itemsize */
207         (destructor) rpmmi_dealloc,     /* tp_dealloc */
208         0,                              /* tp_print */
209         (getattrfunc)0,                 /* tp_getattr */
210         0,                              /* tp_setattr */
211         0,                              /* tp_compare */
212         0,                              /* tp_repr */
213         &rpmmi_as_number,               /* tp_as_number */
214         0,                              /* tp_as_sequence */
215         &rpmmi_as_mapping,              /* tp_as_mapping */
216         0,                              /* tp_hash */
217         0,                              /* tp_call */
218         0,                              /* tp_str */
219         PyObject_GenericGetAttr,        /* tp_getattro */
220         PyObject_GenericSetAttr,        /* tp_setattro */
221         0,                              /* tp_as_buffer */
222         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
223         rpmmi_doc,                      /* tp_doc */
224         0,                              /* tp_traverse */
225         0,                              /* tp_clear */
226         0,                              /* tp_richcompare */
227         0,                              /* tp_weaklistoffset */
228         PyObject_SelfIter,              /* tp_iter */
229         (iternextfunc) rpmmi_iternext,  /* tp_iternext */
230         rpmmi_methods,                  /* tp_methods */
231         0,                              /* tp_members */
232         0,                              /* tp_getset */
233         0,                              /* tp_base */
234         0,                              /* tp_dict */
235         0,                              /* tp_descr_get */
236         0,                              /* tp_descr_set */
237         0,                              /* tp_dictoffset */
238         0,                              /* tp_init */
239         0,                              /* tp_alloc */
240         0,                              /* tp_new */
241         0,                              /* tp_free */
242         0,                              /* tp_is_gc */
243 };
244
245 PyObject * rpmmi_Wrap(PyTypeObject *subtype, rpmdbMatchIterator mi, PyObject *s)
246 {
247     rpmmiObject * mio = (rpmmiObject *)subtype->tp_alloc(subtype, 0);
248     if (mio == NULL) return NULL;
249
250     mio->mi = mi;
251     mio->ref = s;
252     Py_INCREF(mio->ref);
253     return (PyObject *) mio;
254 }
255