rpm  5.4.10
rpmds-py.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmio.h>
8 #include <rpmiotypes.h> /* XXX fnpyKey */
9 #include <rpmtypes.h>
10 #include <rpmtag.h>
11 
12 #include "header-py.h"
13 #include "rpmds-py.h"
14 
15 #include "debug.h"
16 
17 /*@access rpmds @*/
18 
26 static
27 void rpmds_ParseEVR(char * evr,
28  /*@exposed@*/ /*@out@*/ const char ** ep,
29  /*@exposed@*/ /*@out@*/ const char ** vp,
30  /*@exposed@*/ /*@out@*/ const char ** rp)
31  /*@modifies *ep, *vp, *rp @*/
32  /*@requires maxSet(ep) >= 0 /\ maxSet(vp) >= 0 /\ maxSet(rp) >= 0 @*/
33 {
34  const char *epoch;
35  const char *version; /* assume only version is present */
36  const char *release;
37  char *s, *se;
38 
39  s = evr;
40  while (*s && xisdigit(*s)) s++; /* s points to epoch terminator */
41  se = strrchr(s, '-'); /* se points to version terminator */
42 
43  if (*s == ':') {
44  epoch = evr;
45  *s++ = '\0';
46  version = s;
47  /*@-branchstate@*/
48  if (*epoch == '\0') epoch = "0";
49  /*@=branchstate@*/
50  } else {
51  epoch = NULL; /* XXX disable epoch compare if missing */
52  version = evr;
53  }
54  if (se) {
55 /*@-boundswrite@*/
56  *se++ = '\0';
57 /*@=boundswrite@*/
58  release = se;
59  } else {
60  release = NULL;
61  }
62 
63  if (ep) *ep = epoch;
64  if (vp) *vp = version;
65  if (rp) *rp = release;
66 }
67 
70 static int compare_values(const char *str1, const char *str2)
71 {
72  if (!str1 && !str2)
73  return 0;
74  else if (str1 && !str2)
75  return 1;
76  else if (!str1 && str2)
77  return -1;
78  return rpmvercmp(str1, str2);
79 }
80 
81 static int
83  /*@*/
84 {
85  char *aEVR = xstrdup(rpmdsEVR(a->ds));
86  const char *aE, *aV, *aR;
87  char *bEVR = xstrdup(rpmdsEVR(b->ds));
88  const char *bE, *bV, *bR;
89  int rc;
90 
91  /* XXX W2DO? should N be compared? */
92  rpmds_ParseEVR(aEVR, &aE, &aV, &aR);
93  rpmds_ParseEVR(bEVR, &bE, &bV, &bR);
94 
95  rc = compare_values(aE, bE);
96  if (!rc) {
97  rc = compare_values(aV, bV);
98  if (!rc)
99  rc = compare_values(aR, bR);
100  }
101 
102  aEVR = _free(aEVR);
103  bEVR = _free(bEVR);
104 
105  return rc;
106 }
107 
108 static PyObject *
110  /*@*/
111 {
112  int rc;
113 
114  switch (op) {
115  case Py_NE:
116  /* XXX map ranges overlap boolean onto '!=' python syntax. */
117  rc = rpmdsCompare(a->ds, b->ds);
118  rc = (rc < 0 ? -1 : (rc == 0 ? 1 : 0));
119  break;
120  case Py_LT:
121  case Py_LE:
122  case Py_GT:
123  case Py_GE:
124  case Py_EQ:
125  /*@fallthrough@*/
126  default:
127  rc = -1;
128  break;
129  }
130  return Py_BuildValue("i", rc);
131 }
132 
133 static PyObject *
135  /*@*/
136 {
137  Py_INCREF(s);
138  return (PyObject *)s;
139 }
140 
141 /*@null@*/
142 static PyObject *
144  /*@modifies s @*/
145 {
146  PyObject * result = NULL;
147 
148  /* Reset loop indices on 1st entry. */
149  if (!s->active) {
150  s->ds = rpmdsInit(s->ds);
151  s->active = 1;
152  }
153 
154  /* If more to do, return a (N, EVR, Flags) tuple. */
155  if (rpmdsNext(s->ds) >= 0) {
156  const char * N = rpmdsN(s->ds);
157  const char * EVR = rpmdsEVR(s->ds);
158  rpmTag tagN = rpmdsTagN(s->ds);
159  rpmsenseFlags Flags = rpmdsFlags(s->ds);
160 
161 /*@-branchstate@*/
162  if (N != NULL) N = xstrdup(N);
163  if (EVR != NULL) EVR = xstrdup(EVR);
164 /*@=branchstate@*/
165  result = (PyObject *)rpmds_Wrap( rpmdsSingle(tagN, N, EVR, Flags) );
166  } else
167  s->active = 0;
168 
169  return result;
170 }
171 
176 
177 /*@null@*/
178 static PyObject *
180  /*@globals _Py_NoneStruct @*/
181  /*@modifies s, _Py_NoneStruct @*/
182 {
183  PyObject * result;
184 
185  result = rpmds_iternext(s);
186 
187  if (result == NULL) {
188  Py_INCREF(Py_None);
189  return Py_None;
190  }
191  return result;
192 }
193 
194 /*@null@*/
195 static PyObject *
196 rpmds_Debug(/*@unused@*/ rpmdsObject * s, PyObject * args,
197  PyObject * kwds)
198  /*@globals _Py_NoneStruct @*/
199  /*@modifies _Py_NoneStruct @*/
200 {
201  char * kwlist[] = {"debugLevel", NULL};
202 
203  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &_rpmds_debug))
204  return NULL;
205 
206  Py_INCREF(Py_None);
207  return Py_None;
208 }
209 
210 /*@null@*/
211 static PyObject *
213  /*@*/
214 {
215  return Py_BuildValue("i", rpmdsCount(s->ds));
216 }
217 
218 /*@null@*/
219 static PyObject *
221  /*@*/
222 {
223  return Py_BuildValue("i", rpmdsIx(s->ds));
224 }
225 
226 /*@null@*/
227 static PyObject *
229  /*@*/
230 {
231  return Py_BuildValue("s", rpmdsDNEVR(s->ds));
232 }
233 
234 /*@null@*/
235 static PyObject *
237  /*@*/
238 {
239  return Py_BuildValue("s", rpmdsN(s->ds));
240 }
241 
242 /*@null@*/
243 static PyObject *
245  /*@*/
246 {
247  return Py_BuildValue("s", rpmdsEVR(s->ds));
248 }
249 
250 /*@null@*/
251 static PyObject *
253  /*@*/
254 {
255  return Py_BuildValue("i", rpmdsFlags(s->ds));
256 }
257 
258 /*@null@*/
259 static PyObject *
261  /*@*/
262 {
263  return Py_BuildValue("i", (int) rpmdsBT(s->ds));
264 }
265 
266 /*@null@*/
267 static PyObject *
269  /*@*/
270 {
271  return Py_BuildValue("i", rpmdsTagN(s->ds));
272 }
273 
274 /*@null@*/
275 static PyObject *
277  /*@*/
278 {
279  return Py_BuildValue("i", rpmdsColor(s->ds));
280 }
281 
282 /*@null@*/
283 static PyObject *
285  /*@*/
286 {
287  return Py_BuildValue("i", rpmdsRefs(s->ds));
288 }
289 
290 /*@null@*/
291 static PyObject *
293  /*@*/
294 {
295  return Py_BuildValue("i", rpmdsResult(s->ds));
296 }
297 /*@null@*/
298 static PyObject *
299 rpmds_SetNoPromote(rpmdsObject * s, PyObject * args, PyObject * kwds)
300  /*@modifies s @*/
301 {
302  int nopromote;
303  char * kwlist[] = {"noPromote", NULL};
304 
305  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:SetNoPromote", kwlist,
306  &nopromote))
307  return NULL;
308 
309  return Py_BuildValue("i", rpmdsSetNoPromote(s->ds, nopromote));
310 }
311 
312 /*@null@*/
313 static PyObject *
314 rpmds_Notify(rpmdsObject * s, PyObject * args, PyObject * kwds)
315  /*@globals _Py_NoneStruct @*/
316  /*@modifies _Py_NoneStruct @*/
317 {
318  const char * where;
319  int rc;
320  char * kwlist[] = {"location", "returnCode", NULL};
321 
322  if (!PyArg_ParseTupleAndKeywords(args, kwds, "si:Notify", kwlist,
323  &where, &rc))
324  return NULL;
325 
326  rpmdsNotify(s->ds, where, rc);
327  Py_INCREF(Py_None);
328  return Py_None;
329 }
330 
331 /* XXX rpmdsFind uses bsearch on s->ds, so a sort is needed. */
332 /*@null@*/
333 static PyObject *
335  /*@globals _Py_NoneStruct @*/
336  /*@modifies _Py_NoneStruct @*/
337 {
338  rpmds nds = NULL;
339 
340  if (rpmdsMerge(&nds, s->ds) >= 0) {
341  (void)rpmdsFree(s->ds);
342  s->ds = NULL;
343  s->ds = nds;
344  }
345  Py_INCREF(Py_None);
346  return Py_None;
347 }
348 
349 /*@null@*/
350 static PyObject *
351 rpmds_Find(rpmdsObject * s, PyObject * args, PyObject * kwds)
352  /*@modifies s @*/
353 {
354  PyObject * to = NULL;
355  rpmdsObject * o;
356  char * kwlist[] = {"element", NULL};
357 
358  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Find", kwlist, &to))
359  return NULL;
360 
361  /* XXX ds type check needed. */
362  o = (rpmdsObject *)to;
363 
364  /* XXX make sure ods index is valid, real fix in lib/rpmds.c. */
365  if (rpmdsIx(o->ds) == -1) rpmdsSetIx(o->ds, 0);
366 
367  return Py_BuildValue("i", rpmdsFind(s->ds, o->ds));
368 }
369 
370 /*@null@*/
371 static PyObject *
372 rpmds_Merge(rpmdsObject * s, PyObject * args, PyObject * kwds)
373  /*@modifies s @*/
374 {
375  PyObject * to = NULL;
376  rpmdsObject * o;
377  char * kwlist[] = {"element", NULL};
378 
379  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Merge", kwlist, &to))
380  return NULL;
381 
382  /* XXX ds type check needed. */
383  o = (rpmdsObject *)to;
384  return Py_BuildValue("i", rpmdsMerge(&s->ds, o->ds));
385 }
386 
387 /*@null@*/
388 static PyObject *
389 rpmds_Search(rpmdsObject * s, PyObject * args, PyObject * kwds)
390  /*@modifies s @*/
391 {
392  PyObject * to = NULL;
393  rpmdsObject * o;
394  char * kwlist[] = {"element", NULL};
395 
396  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Merge", kwlist, &to))
397  return NULL;
398 
399  /* XXX ds type check needed. */
400  o = (rpmdsObject *)to;
401  return Py_BuildValue("i", rpmdsSearch(s->ds, o->ds));
402 }
403 
404 static PyObject *
406  /*@*/
407 {
408  rpmds ds = NULL;
409  int xx;
410 
411  /* XXX check return code, permit arg (NULL uses system default). */
412  xx = rpmdsCpuinfo(&ds, NULL);
413 
414  return (PyObject *) rpmds_Wrap( ds );
415 }
416 
417 static PyObject *
419  /*@*/
420 {
421  rpmds ds = NULL;
422  int xx;
423 
424  /* XXX check return code, permit arg (NULL uses system default). */
425  xx = rpmdsRpmlib(&ds, NULL);
426 
427  return (PyObject *) rpmds_Wrap( ds );
428 }
429 
430 static PyObject *
432  /*@*/
433 {
434  rpmPRCO PRCO = rpmdsNewPRCO(NULL);
435  rpmds P = NULL;
436  int xx;
437 
438  /* XXX check return code, permit arg (NULL uses system default). */
439  xx = rpmdsSysinfo(PRCO, NULL);
440  P = rpmdsLink(rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME), "rpmds_Sysinfo");
441  PRCO = rpmdsFreePRCO(PRCO);
442 
443  return (PyObject *) rpmds_Wrap( P );
444 }
445 
446 static PyObject *
448  /*@*/
449 {
450  rpmds ds = NULL;
451  int xx;
452 
453  /* XXX check return code, permit arg (NULL uses system default). */
454  xx = rpmdsGetconf(&ds, NULL);
455 
456  return (PyObject *) rpmds_Wrap( ds );
457 }
458 
459 static PyObject *
461  /*@*/
462 {
463  rpmPRCO PRCO = rpmdsNewPRCO(NULL);
464  rpmds P = NULL;
465  int xx;
466 
467  /* XXX check return code, permit arg (NULL uses system default). */
468  xx = rpmdsLdconfig(PRCO, NULL);
469 
470  P = rpmdsLink(rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME), "rpmds_Ldconfig");
471  PRCO = rpmdsFreePRCO(PRCO);
472  return (PyObject *) rpmds_Wrap( P );
473 }
474 
475 static PyObject *
477  /*@*/
478 {
479  rpmds ds = NULL;
480  int xx;
481 
482  /* XXX check return code, permit arg (NULL uses system default). */
483  xx = rpmdsUname(&ds, NULL);
484 
485  return (PyObject *) rpmds_Wrap( ds );
486 }
487 
488 #ifdef NOTYET
489 static PyObject *
490 rpmds_Compare(rpmdsObject * s, PyObject * args, PyObject * kwds)
491  /*@modifies s @*/
492 {
493  PyObject * to = NULL;
494  rpmdsObject * o;
495  char * kwlist[] = {"other", NULL};
496 
497  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Compare", kwlist, &to))
498  return NULL;
499 
500  /* XXX ds type check needed. */
501  o = (rpmdsObject *)to;
502  return Py_BuildValue("i", rpmdsCompare(s->ds, o->ds));
503 }
504 
505 /*@null@*/
506 static PyObject *
507 rpmds_Problem(rpmdsObject * s)
508  /*@*/
509 {
510  if (!PyArg_ParseTuple(args, ":Problem"))
511  return NULL;
512  Py_INCREF(Py_None);
513  return Py_None;
514 }
515 #endif
516 
519 /*@-fullinitblock@*/
520 /*@unchecked@*/ /*@observer@*/
521 static struct PyMethodDef rpmds_methods[] = {
522  {"Debug", (PyCFunction)rpmds_Debug, METH_VARARGS|METH_KEYWORDS,
523  NULL},
524  {"Count", (PyCFunction)rpmds_Count, METH_NOARGS,
525  "ds.Count -> Count - Return no. of elements.\n" },
526  {"Ix", (PyCFunction)rpmds_Ix, METH_NOARGS,
527  "ds.Ix -> Ix - Return current element index.\n" },
528  {"DNEVR", (PyCFunction)rpmds_DNEVR, METH_NOARGS,
529  "ds.DNEVR -> DNEVR - Return current DNEVR.\n" },
530  {"N", (PyCFunction)rpmds_N, METH_NOARGS,
531  "ds.N -> N - Return current N.\n" },
532  {"EVR", (PyCFunction)rpmds_EVR, METH_NOARGS,
533  "ds.EVR -> EVR - Return current EVR.\n" },
534  {"Flags", (PyCFunction)rpmds_Flags, METH_NOARGS,
535  "ds.Flags -> Flags - Return current Flags.\n" },
536  {"BT", (PyCFunction)rpmds_BT, METH_NOARGS,
537  "ds.BT -> BT - Return build time.\n" },
538  {"TagN", (PyCFunction)rpmds_TagN, METH_NOARGS,
539  "ds.TagN -> TagN - Return current TagN.\n" },
540  {"Color", (PyCFunction)rpmds_Color, METH_NOARGS,
541  "ds.Color -> Color - Return current Color.\n" },
542  {"Refs", (PyCFunction)rpmds_Refs, METH_NOARGS,
543  "ds.Refs -> Refs - Return current Refs.\n" },
544  {"Result", (PyCFunction)rpmds_Result, METH_NOARGS,
545  "ds.Result -> Result - Return current Result.\n" },
546  {"next", (PyCFunction)rpmds_Next, METH_NOARGS,
547 "ds.next() -> (N, EVR, Flags)\n\
548 - Retrieve next dependency triple.\n" },
549  {"SetNoPromote",(PyCFunction)rpmds_SetNoPromote, METH_VARARGS|METH_KEYWORDS,
550  NULL},
551  {"Notify", (PyCFunction)rpmds_Notify, METH_VARARGS|METH_KEYWORDS,
552  NULL},
553  {"Sort", (PyCFunction)rpmds_Sort, METH_NOARGS,
554 "ds.Sort() -> None\n\
555 - Sort the (N,EVR,Flags) elements in ds\n" },
556  {"Find", (PyCFunction)rpmds_Find, METH_VARARGS|METH_KEYWORDS,
557 "ds.Find(element) -> matching ds index (-1 on failure)\n\
558 - Check for an exactly matching element in ds.\n\
559 The current index in ds is positioned at matching member upon success.\n" },
560  {"Merge", (PyCFunction)rpmds_Merge, METH_VARARGS|METH_KEYWORDS,
561 "ds.Merge(elements) -> 0 on success\n\
562 - Merge elements into ds, maintaining (N,EVR,Flags) sort order.\n" },
563  {"Search", (PyCFunction)rpmds_Search, METH_VARARGS|METH_KEYWORDS,
564 "ds.Search(element) -> matching ds index (-1 on failure)\n\
565 - Check that element dependency range overlaps some member of ds.\n\
566 The current index in ds is positioned at overlapping member upon success.\n" },
567  {"Cpuinfo", (PyCFunction)rpmds_Cpuinfo, METH_NOARGS|METH_STATIC,
568  "ds.Cpuinfo -> nds - Return /proc/cpuinfo dependency set.\n"},
569  {"Rpmlib", (PyCFunction)rpmds_Rpmlib, METH_NOARGS|METH_STATIC,
570  "ds.Rpmlib -> nds - Return internal rpmlib dependency set.\n"},
571  {"Sysinfo", (PyCFunction)rpmds_Sysinfo, METH_NOARGS|METH_STATIC,
572  "ds.Sysinfo -> nds - Return /etc/rpm/sysinfo dependency set.\n"},
573  {"Getconf", (PyCFunction)rpmds_Getconf, METH_NOARGS|METH_STATIC,
574  "ds.Getconf -> nds - Return getconf(1) dependency set.\n"},
575  {"Ldconfig", (PyCFunction)rpmds_Ldconfig, METH_NOARGS|METH_STATIC,
576  "ds.Ldconfig -> nds - Return /etc/ld.so.cache dependency set.\n"},
577  {"Uname", (PyCFunction)rpmds_Uname, METH_NOARGS|METH_STATIC,
578  "ds.Uname -> nds - Return uname(2) dependency set.\n"},
579 #ifdef NOTYET
580  {"Compare", (PyCFunction)rpmds_Compare, METH_VARARGS|METH_KEYWORDS,
581  NULL},
582  {"Problem", (PyCFunction)rpmds_Problem, METH_NOARGS,
583  NULL},
584 #endif
585  {NULL, NULL} /* sentinel */
586 };
587 /*@=fullinitblock@*/
588 
589 /* ---------- */
590 
591 static void
593  /*@modifies s @*/
594 {
595  if (s) {
596  (void)rpmdsFree(s->ds);
597  s->ds = NULL;
598  PyObject_Del(s);
599  }
600 }
601 
602 static int
603 rpmds_print(rpmdsObject * s, FILE * fp, /*@unused@*/ int flags)
604  /*@globals fileSystem @*/
605  /*@modifies s, fp, fileSystem @*/
606 {
607  if (!(s && s->ds))
608  return -1;
609 
610  s->ds = rpmdsInit(s->ds);
611  while (rpmdsNext(s->ds) >= 0)
612  fprintf(fp, "%s\n", rpmdsDNEVR(s->ds));
613  return 0;
614 }
615 
616 static PyObject * rpmds_getattro(PyObject * o, PyObject * n)
617  /*@*/
618 {
619  return PyObject_GenericGetAttr(o, n);
620 }
621 
622 static int rpmds_setattro(PyObject * o, PyObject * n, PyObject * v)
623  /*@*/
624 {
625  return PyObject_GenericSetAttr(o, n, v);
626 }
627 
628 static int
630  /*@*/
631 {
632  return rpmdsCount(s->ds);
633 }
634 
635 /*@null@*/
636 static PyObject *
637 rpmds_subscript(rpmdsObject * s, PyObject * key)
638  /*@modifies s @*/
639 {
640  int ix;
641 
642  if (!PyInt_Check(key)) {
643  PyErr_SetString(PyExc_TypeError, "integer expected");
644  return NULL;
645  }
646 
647  ix = (int) PyInt_AsLong(key);
648  /* XXX make sure that DNEVR exists. */
649  rpmdsSetIx(s->ds, ix-1);
650  (void) rpmdsNext(s->ds);
651  return Py_BuildValue("s", rpmdsDNEVR(s->ds));
652 }
653 
654 static PyMappingMethods rpmds_as_mapping = {
655  (lenfunc) rpmds_length, /* mp_length */
656  (binaryfunc) rpmds_subscript, /* mp_subscript */
657  (objobjargproc)0, /* mp_ass_subscript */
658 };
659 
662 static int rpmds_init(rpmdsObject * s, PyObject *args, PyObject *kwds)
663  /*@globals rpmGlobalMacroContext @*/
664  /*@modifies s, rpmGlobalMacroContext @*/
665 {
666  hdrObject * ho = NULL;
667  PyObject * to = NULL;
668  rpmTag tagN = RPMTAG_REQUIRENAME;
669  rpmsenseFlags flags = 0;
670  char * kwlist[] = {"header", "tag", "flags", NULL};
671 
672 if (_rpmds_debug < 0)
673 fprintf(stderr, "*** rpmds_init(%p,%p,%p)\n", s, args, kwds);
674 
675  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|Oi:rpmds_init", kwlist,
676  &hdr_Type, &ho, &to, &flags))
677  return -1;
678 
679  if (to != NULL) {
680  tagN = tagNumFromPyObject(to);
681  if (tagN == (rpmTag)0xffffffff) {
682  PyErr_SetString(PyExc_KeyError, "unknown header tag");
683  return -1;
684  }
685  }
686  s->ds = rpmdsNew(hdrGetHeader(ho), tagN, flags);
687  s->active = 0;
688 
689  return 0;
690 }
691 
694 static void rpmds_free(/*@only@*/ rpmdsObject * s)
695  /*@modifies s @*/
696 {
697 if (_rpmds_debug)
698 fprintf(stderr, "%p -- ds %p\n", s, s->ds);
699  (void)rpmdsFree(s->ds);
700  s->ds = NULL;
701 
702  PyObject_Del((PyObject *)s);
703 }
704 
707 static PyObject * rpmds_alloc(PyTypeObject * subtype, int nitems)
708  /*@*/
709 {
710  PyObject * s = PyType_GenericAlloc(subtype, nitems);
711 
712 if (_rpmds_debug < 0)
713 fprintf(stderr, "*** rpmds_alloc(%p,%d) ret %p\n", subtype, nitems, s);
714  return s;
715 }
716 
719 /*@null@*/
720 static PyObject * rpmds_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
721  /*@globals rpmGlobalMacroContext @*/
722  /*@modifies rpmGlobalMacroContext @*/
723 {
724  rpmdsObject * s = (void *) PyObject_New(rpmdsObject, subtype);
725 
726  /* Perform additional initialization. */
727  if (rpmds_init(s, args, kwds) < 0) {
728  rpmds_free(s);
729  return NULL;
730  }
731 
732 if (_rpmds_debug)
733 fprintf(stderr, "%p ++ ds %p\n", s, s->ds);
734 
735  return (PyObject *)s;
736 }
737 
740 /*@unchecked@*/ /*@observer@*/
741 static char rpmds_doc[] =
742 "";
743 
744 /*@-fullinitblock@*/
745 PyTypeObject rpmds_Type = {
746  PyObject_HEAD_INIT(&PyType_Type)
747  0, /* ob_size */
748  "rpm.ds", /* tp_name */
749  sizeof(rpmdsObject), /* tp_basicsize */
750  0, /* tp_itemsize */
751  /* methods */
752  (destructor) rpmds_dealloc, /* tp_dealloc */
753  (printfunc) rpmds_print, /* tp_print */
754  (getattrfunc)0, /* tp_getattr */
755  (setattrfunc)0, /* tp_setattr */
756  (cmpfunc) rpmds_compare, /* tp_compare */
757  (reprfunc)0, /* tp_repr */
758  0, /* tp_as_number */
759  0, /* tp_as_sequence */
760  &rpmds_as_mapping, /* tp_as_mapping */
761  (hashfunc)0, /* tp_hash */
762  (ternaryfunc)0, /* tp_call */
763  (reprfunc)0, /* tp_str */
764  (getattrofunc) rpmds_getattro, /* tp_getattro */
765  (setattrofunc) rpmds_setattro, /* tp_setattro */
766  0, /* tp_as_buffer */
767  Py_TPFLAGS_DEFAULT | /* tp_flags */
768  Py_TPFLAGS_HAVE_RICHCOMPARE,
769  rpmds_doc, /* tp_doc */
770 #if Py_TPFLAGS_HAVE_ITER
771  0, /* tp_traverse */
772  0, /* tp_clear */
773  (richcmpfunc) rpmds_richcompare,/* tp_richcompare */
774  0, /* tp_weaklistoffset */
775  (getiterfunc) rpmds_iter, /* tp_iter */
776  (iternextfunc) rpmds_iternext, /* tp_iternext */
777  rpmds_methods, /* tp_methods */
778  0, /* tp_members */
779  0, /* tp_getset */
780  0, /* tp_base */
781  0, /* tp_dict */
782  0, /* tp_descr_get */
783  0, /* tp_descr_set */
784  0, /* tp_dictoffset */
785  (initproc) rpmds_init, /* tp_init */
786  (allocfunc) rpmds_alloc, /* tp_alloc */
787  (newfunc) rpmds_new, /* tp_new */
788  (freefunc) rpmds_free, /* tp_free */
789  0, /* tp_is_gc */
790 #endif
791 };
792 /*@=fullinitblock@*/
793 
794 /* ---------- */
795 
797 {
798  return s->ds;
799 }
800 
801 rpmdsObject *
803 {
804  rpmdsObject * s = PyObject_New(rpmdsObject, &rpmds_Type);
805 
806  if (s == NULL)
807  return NULL;
808  s->ds = ds;
809  s->active = 0;
810  return s;
811 }
812 
813 
814 rpmdsObject *
815 rpmds_Single(/*@unused@*/ PyObject * s, PyObject * args, PyObject * kwds)
816 {
817  PyObject * to = NULL;
818  rpmTag tagN = RPMTAG_PROVIDENAME;
819  const char * N;
820  const char * EVR = NULL;
821  rpmsenseFlags Flags = 0;
822  char * kwlist[] = {"to", "name", "evr", "flags", NULL};
823 
824  if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os|si:Single", kwlist,
825  &to, &N, &EVR, &Flags))
826  return NULL;
827 
828  if (to != NULL) {
829  tagN = tagNumFromPyObject(to);
830  if (tagN == (rpmTag)0xffffffff) {
831  PyErr_SetString(PyExc_KeyError, "unknown header tag");
832  return NULL;
833  }
834  }
835  if (N != NULL) N = xstrdup(N);
836  if (EVR != NULL) EVR = xstrdup(EVR);
837  return rpmds_Wrap( rpmdsSingle(tagN, N, EVR, Flags) );
838 }
839 
840 rpmdsObject *
841 hdr_dsFromHeader(PyObject * s, PyObject * args, PyObject * kwds)
842 {
843  hdrObject * ho = (hdrObject *)s;
844  PyObject * to = NULL;
845  rpmTag tagN = RPMTAG_REQUIRENAME;
846  int flags = 0;
847  char * kwlist[] = {"to", "flags", NULL};
848 
849  if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:dsFromHeader", kwlist,
850  &to, &flags))
851  return NULL;
852 
853  if (to != NULL) {
854  tagN = tagNumFromPyObject(to);
855  if (tagN == (rpmTag)0xffffffff) {
856  PyErr_SetString(PyExc_KeyError, "unknown header tag");
857  return NULL;
858  }
859  }
860  return rpmds_Wrap( rpmdsNew(hdrGetHeader(ho), tagN, flags) );
861 }
862 
863 rpmdsObject *
864 hdr_dsOfHeader(PyObject * s)
865 {
866  hdrObject * ho = (hdrObject *)s;
867  int tagN = RPMTAG_PROVIDENAME;
868  int Flags = RPMSENSE_EQUAL;
869 
870  return rpmds_Wrap( rpmdsThis(hdrGetHeader(ho), tagN, Flags) );
871 }