2 * \file python/rpmds-py.c
7 #include <rpm/rpmtypes.h>
8 #include <rpm/rpmstring.h>
9 #include <rpm/rpmlib.h> /* rpmvercmp */
11 #include "header-py.h"
18 struct rpmdsObject_s {
20 PyObject *md_dict; /*!< to look like PyModuleObject */
27 * Split EVR into epoch, version, and release components.
28 * @param evr [epoch:]version[-release] string
29 * @retval *ep pointer to epoch
30 * @retval *vp pointer to version
31 * @retval *rp pointer to release
34 void rpmds_ParseEVR(char * evr,
40 const char *version; /* assume only version is present */
45 while (*s && risdigit(*s)) s++; /* s points to epoch terminator */
46 se = strrchr(s, '-'); /* se points to version terminator */
52 if (*epoch == '\0') epoch = "0";
54 epoch = NULL; /* XXX disable epoch compare if missing */
65 if (vp) *vp = version;
66 if (rp) *rp = release;
70 rpmds_Debug(rpmdsObject * s, PyObject * args, PyObject * kwds)
72 char * kwlist[] = {"debugLevel", NULL};
74 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &_rpmds_debug))
81 rpmds_Count(rpmdsObject * s)
83 return Py_BuildValue("i", rpmdsCount(s->ds));
87 rpmds_Ix(rpmdsObject * s)
89 return Py_BuildValue("i", rpmdsIx(s->ds));
93 rpmds_DNEVR(rpmdsObject * s)
95 return Py_BuildValue("s", rpmdsDNEVR(s->ds));
99 rpmds_N(rpmdsObject * s)
101 return Py_BuildValue("s", rpmdsN(s->ds));
105 rpmds_EVR(rpmdsObject * s)
107 return Py_BuildValue("s", rpmdsEVR(s->ds));
111 rpmds_Flags(rpmdsObject * s)
113 return Py_BuildValue("i", rpmdsFlags(s->ds));
117 rpmds_BT(rpmdsObject * s)
119 return Py_BuildValue("i", (int) rpmdsBT(s->ds));
123 rpmds_TagN(rpmdsObject * s)
125 return Py_BuildValue("i", rpmdsTagN(s->ds));
129 rpmds_Color(rpmdsObject * s)
131 return Py_BuildValue("i", rpmdsColor(s->ds));
135 rpmds_Refs(rpmdsObject * s)
137 return Py_BuildValue("i", rpmdsRefs(s->ds));
142 static int compare_values(const char *str1, const char *str2)
146 else if (str1 && !str2)
148 else if (!str1 && str2)
150 return rpmvercmp(str1, str2);
154 rpmds_compare(rpmdsObject * a, rpmdsObject * b)
156 char *aEVR = xstrdup(rpmdsEVR(a->ds));
157 const char *aE, *aV, *aR;
158 char *bEVR = xstrdup(rpmdsEVR(b->ds));
159 const char *bE, *bV, *bR;
162 /* XXX W2DO? should N be compared? */
163 rpmds_ParseEVR(aEVR, &aE, &aV, &aR);
164 rpmds_ParseEVR(bEVR, &bE, &bV, &bR);
166 rc = compare_values(aE, bE);
168 rc = compare_values(aV, bV);
170 rc = compare_values(aR, bR);
180 rpmds_richcompare(rpmdsObject * a, rpmdsObject * b, int op)
186 /* XXX map ranges overlap boolean onto '!=' python syntax. */
187 rc = rpmdsCompare(a->ds, b->ds);
188 rc = (rc < 0 ? -1 : (rc == 0 ? 1 : 0));
199 return Py_BuildValue("i", rc);
203 rpmds_iternext(rpmdsObject * s)
205 PyObject * result = NULL;
207 /* Reset loop indices on 1st entry. */
209 s->ds = rpmdsInit(s->ds);
213 /* If more to do, return a (N, EVR, Flags) tuple. */
214 if (rpmdsNext(s->ds) >= 0) {
215 const char * N = rpmdsN(s->ds);
216 const char * EVR = rpmdsEVR(s->ds);
217 rpmTag tagN = rpmdsTagN(s->ds);
218 rpmsenseFlags Flags = rpmdsFlags(s->ds);
220 if (N != NULL) N = xstrdup(N);
221 if (EVR != NULL) EVR = xstrdup(EVR);
222 result = (PyObject *) rpmds_Wrap( rpmdsSingle(tagN, N, EVR, Flags) );
230 rpmds_SetNoPromote(rpmdsObject * s, PyObject * args, PyObject * kwds)
233 char * kwlist[] = {"noPromote", NULL};
235 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetNoPromote", kwlist,
239 return Py_BuildValue("i", rpmdsSetNoPromote(s->ds, nopromote));
243 rpmds_Notify(rpmdsObject * s, PyObject * args, PyObject * kwds)
247 char * kwlist[] = {"location", "returnCode", NULL};
249 if (!PyArg_ParseTupleAndKeywords(args, kwds, "si:Notify", kwlist,
253 rpmdsNotify(s->ds, where, rc);
257 /* XXX rpmdsFind uses bsearch on s->ds, so a sort is needed. */
259 rpmds_Sort(rpmdsObject * s)
261 /* XXX sort on (N,EVR,F) here. */
266 rpmds_Find(rpmdsObject * s, PyObject * args, PyObject * kwds)
268 PyObject * to = NULL;
271 char * kwlist[] = {"element", NULL};
273 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Find", kwlist, &to))
276 /* XXX ds type check needed. */
277 o = (rpmdsObject *)to;
279 /* XXX make sure ods index is valid, real fix in lib/rpmds.c. */
280 if (rpmdsIx(o->ds) == -1) rpmdsSetIx(o->ds, 0);
282 rc = rpmdsFind(s->ds, o->ds);
283 return Py_BuildValue("i", rc);
287 rpmds_Merge(rpmdsObject * s, PyObject * args, PyObject * kwds)
289 PyObject * to = NULL;
291 char * kwlist[] = {"element", NULL};
293 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Merge", kwlist, &to))
296 /* XXX ds type check needed. */
297 o = (rpmdsObject *)to;
298 return Py_BuildValue("i", rpmdsMerge(&s->ds, o->ds));
301 rpmds_Search(rpmdsObject * s, PyObject * args, PyObject * kwds)
303 PyObject * to = NULL;
305 char * kwlist[] = {"element", NULL};
307 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Merge", kwlist, &to))
310 /* XXX ds type check needed. */
311 o = (rpmdsObject *)to;
312 return Py_BuildValue("i", rpmdsSearch(s->ds, o->ds));
316 rpmds_Rpmlib(rpmdsObject * s)
321 /* XXX check return code, permit arg (NULL uses system default). */
322 xx = rpmdsRpmlib(&ds, NULL);
324 return (PyObject *) rpmds_Wrap( ds );
330 rpmds_Compare(rpmdsObject * s, PyObject * args, PyObject * kwds)
332 PyObject * to = NULL;
334 char * kwlist[] = {"other", NULL};
336 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Compare", kwlist, &to))
339 /* XXX ds type check needed. */
340 o = (rpmdsObject *)to;
341 return Py_BuildValue("i", rpmdsCompare(s->ds, o->ds));
345 rpmds_Problem(rpmdsObject * s)
347 if (!PyArg_ParseTuple(args, ":Problem"))
353 static struct PyMethodDef rpmds_methods[] = {
354 {"Debug", (PyCFunction)rpmds_Debug, METH_VARARGS|METH_KEYWORDS,
356 {"Count", (PyCFunction)rpmds_Count, METH_NOARGS,
357 "ds.Count -> Count - Return no. of elements.\n" },
358 {"Ix", (PyCFunction)rpmds_Ix, METH_NOARGS,
359 "ds.Ix -> Ix - Return current element index.\n" },
360 {"DNEVR", (PyCFunction)rpmds_DNEVR, METH_NOARGS,
361 "ds.DNEVR -> DNEVR - Return current DNEVR.\n" },
362 {"N", (PyCFunction)rpmds_N, METH_NOARGS,
363 "ds.N -> N - Return current N.\n" },
364 {"EVR", (PyCFunction)rpmds_EVR, METH_NOARGS,
365 "ds.EVR -> EVR - Return current EVR.\n" },
366 {"Flags", (PyCFunction)rpmds_Flags, METH_NOARGS,
367 "ds.Flags -> Flags - Return current Flags.\n" },
368 {"BT", (PyCFunction)rpmds_BT, METH_NOARGS,
369 "ds.BT -> BT - Return build time.\n" },
370 {"TagN", (PyCFunction)rpmds_TagN, METH_NOARGS,
371 "ds.TagN -> TagN - Return current TagN.\n" },
372 {"Color", (PyCFunction)rpmds_Color, METH_NOARGS,
373 "ds.Color -> Color - Return current Color.\n" },
374 {"Refs", (PyCFunction)rpmds_Refs, METH_NOARGS,
375 "ds.Refs -> Refs - Return current Refs.\n" },
376 {"SetNoPromote",(PyCFunction)rpmds_SetNoPromote, METH_VARARGS|METH_KEYWORDS,
378 {"Notify", (PyCFunction)rpmds_Notify, METH_VARARGS|METH_KEYWORDS,
380 {"Sort", (PyCFunction)rpmds_Sort, METH_NOARGS,
382 {"Find", (PyCFunction)rpmds_Find, METH_VARARGS|METH_KEYWORDS,
384 {"Merge", (PyCFunction)rpmds_Merge, METH_VARARGS|METH_KEYWORDS,
386 {"Search", (PyCFunction)rpmds_Search, METH_VARARGS|METH_KEYWORDS,
387 "ds.Search(element) -> matching ds index (-1 on failure)\n\
388 - Check that element dependency range overlaps some member of ds.\n\
389 The current index in ds is positioned at overlapping member upon success.\n" },
390 {"Rpmlib", (PyCFunction)rpmds_Rpmlib, METH_NOARGS|METH_STATIC,
391 "ds.Rpmlib -> nds - Return internal rpmlib dependency set.\n"},
393 {"Compare", (PyCFunction)rpmds_Compare, METH_VARARGS|METH_KEYWORDS,
395 {"Problem", (PyCFunction)rpmds_Problem, METH_NOARGS,
398 {NULL, NULL} /* sentinel */
404 rpmds_dealloc(rpmdsObject * s)
407 s->ds = rpmdsFree(s->ds);
413 rpmds_print(rpmdsObject * s, FILE * fp, int flags)
418 s->ds = rpmdsInit(s->ds);
419 while (rpmdsNext(s->ds) >= 0)
420 fprintf(fp, "%s\n", rpmdsDNEVR(s->ds));
425 rpmds_length(rpmdsObject * s)
427 return rpmdsCount(s->ds);
431 rpmds_subscript(rpmdsObject * s, PyObject * key)
435 if (!PyInt_Check(key)) {
436 PyErr_SetString(PyExc_TypeError, "integer expected");
440 ix = (int) PyInt_AsLong(key);
441 rpmdsSetIx(s->ds, ix);
442 return Py_BuildValue("s", rpmdsDNEVR(s->ds));
445 static PyMappingMethods rpmds_as_mapping = {
446 (lenfunc) rpmds_length, /* mp_length */
447 (binaryfunc) rpmds_subscript, /* mp_subscript */
448 (objobjargproc)0, /* mp_ass_subscript */
453 static int rpmds_init(rpmdsObject * s, PyObject *args, PyObject *kwds)
461 static void rpmds_free(rpmdsObject * s)
464 fprintf(stderr, "%p -- ds %p\n", s, s->ds);
465 s->ds = rpmdsFree(s->ds);
467 PyObject_Del((PyObject *)s);
472 static PyObject * rpmds_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
474 rpmdsObject * s = (void *) PyObject_New(rpmdsObject, subtype);
475 hdrObject * ho = NULL;
476 PyObject * to = NULL;
477 rpmTag tagN = RPMTAG_REQUIRENAME;
478 rpmsenseFlags flags = 0;
479 char * kwlist[] = {"header", "tag", "flags", NULL};
481 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|Oi:rpmds_new", kwlist,
482 &hdr_Type, &ho, &to, &flags))
486 tagN = tagNumFromPyObject(to);
487 if (tagN == RPMTAG_NOT_FOUND) return NULL;
489 s->ds = rpmdsNew(hdrGetHeader(ho), tagN, 0);
491 return (PyObject *)s;
496 static char rpmds_doc[] =
499 PyTypeObject rpmds_Type = {
500 PyObject_HEAD_INIT(&PyType_Type)
502 "rpm.ds", /* tp_name */
503 sizeof(rpmdsObject), /* tp_basicsize */
506 (destructor) rpmds_dealloc, /* tp_dealloc */
507 (printfunc) rpmds_print, /* tp_print */
508 (getattrfunc)0, /* tp_getattr */
509 (setattrfunc)0, /* tp_setattr */
510 (cmpfunc) rpmds_compare, /* tp_compare */
511 (reprfunc)0, /* tp_repr */
512 0, /* tp_as_number */
513 0, /* tp_as_sequence */
514 &rpmds_as_mapping, /* tp_as_mapping */
515 (hashfunc)0, /* tp_hash */
516 (ternaryfunc)0, /* tp_call */
517 (reprfunc)0, /* tp_str */
518 PyObject_GenericGetAttr, /* tp_getattro */
519 PyObject_GenericSetAttr, /* tp_setattro */
520 0, /* tp_as_buffer */
521 Py_TPFLAGS_DEFAULT | /* tp_flags */
522 Py_TPFLAGS_HAVE_RICHCOMPARE,
523 rpmds_doc, /* tp_doc */
526 (richcmpfunc) rpmds_richcompare,/* tp_richcompare */
527 0, /* tp_weaklistoffset */
528 PyObject_SelfIter, /* tp_iter */
529 (iternextfunc) rpmds_iternext, /* tp_iternext */
530 rpmds_methods, /* tp_methods */
535 0, /* tp_descr_get */
536 0, /* tp_descr_set */
537 0, /* tp_dictoffset */
538 (initproc) rpmds_init, /* tp_init */
540 (newfunc) rpmds_new, /* tp_new */
541 (freefunc) rpmds_free, /* tp_free */
547 rpmds dsFromDs(rpmdsObject * s)
555 rpmdsObject * s = PyObject_New(rpmdsObject, &rpmds_Type);
565 rpmds_Single(PyObject * s, PyObject * args, PyObject * kwds)
567 PyObject * to = NULL;
568 rpmTag tagN = RPMTAG_PROVIDENAME;
570 const char * EVR = NULL;
571 rpmsenseFlags Flags = 0;
572 char * kwlist[] = {"to", "name", "evr", "flags", NULL};
574 if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os|si:Single", kwlist,
575 &to, &N, &EVR, &Flags))
579 tagN = tagNumFromPyObject(to);
580 if (tagN == RPMTAG_NOT_FOUND) return NULL;
582 return rpmds_Wrap( rpmdsSingle(tagN, N, EVR, Flags) );
586 hdr_dsFromHeader(PyObject * s, PyObject * args, PyObject * kwds)
588 return PyObject_Call((PyObject *) &rpmds_Type,
589 Py_BuildValue("(O)", s), kwds);
593 hdr_dsOfHeader(PyObject * s)
595 hdrObject * ho = (hdrObject *)s;
596 rpmTag tagN = RPMTAG_PROVIDENAME;
597 rpmsenseFlags Flags = RPMSENSE_EQUAL;
599 return rpmds_Wrap( rpmdsThis(hdrGetHeader(ho), tagN, Flags) );