doxygen annotations for python bindings.
authorjbj <devnull@localhost>
Fri, 12 Jan 2001 18:22:27 +0000 (18:22 +0000)
committerjbj <devnull@localhost>
Fri, 12 Jan 2001 18:22:27 +0000 (18:22 +0000)
CVS patchset: 4433
CVS date: 2001/01/12 18:22:27

Doxyfile.in
Doxyheader
python/rpmmodule.c
rpmio/rpmio.h

index 22a45c1..0d1d5a2 100644 (file)
@@ -348,6 +348,7 @@ INPUT                  = \
        ./popt/popthelp.c \
        ./popt/poptint.h \
        ./popt/poptparse.c \
+       ./python/rpmmodule.c \
        ./tools/dump.c \
        ./tools/dumpdb.c \
        ./tools/javadeps.c \
index c47a840..1355627 100644 (file)
@@ -2,6 +2,8 @@
  */
 /** \defgroup  rpmcli  RPMCLI.
  */
+/** \defgroup  python  PYTHON.
+ */
 /** \defgroup  rpmbuild        RPMBUILD.
  */
 /** \defgroup  rpmrc   RPMRC.
index 31e134f..aa8ef18 100644 (file)
@@ -1,3 +1,7 @@
+/** \ingroup python
+ * \file python/rpmmodule.c
+ */
+
 #include <alloca.h>
 #include <errno.h>
 #include <fcntl.h>
 #include "rpmmacro.h"
 #include "upgrade.h"
 
-/* from lib/misc.c */
-int rpmvercmp(const char * one, const char * two);
-
-/* Forward types */
-
-typedef struct rpmdbObject_s rpmdbObject;
-typedef struct rpmdbMIObject_s rpmdbMIObject;
-typedef struct rpmtransObject_s rpmtransObject;
-typedef struct hdrObject_s hdrObject;
+extern int _rpmio_debug;
 
-/* Prototypes */
-
-/* rpmdb functions */
-static void rpmdbDealloc(rpmdbObject * s);
-static PyObject * rpmdbFirst(rpmdbObject * s, PyObject * args);
-static PyObject * rpmdbNext(rpmdbObject * s, PyObject * args);
-static PyObject * rpmdbGetAttr(rpmdbObject * s, char * name);
-static PyObject * rpmdbByName(rpmdbObject * s, PyObject * args);
-static PyObject * rpmdbByProvides(rpmdbObject * s, PyObject * args);
-static PyObject * rpmdbByFile(rpmdbObject * s, PyObject * args);
-static int rpmdbLength(rpmdbObject * s);
-static hdrObject * rpmdbSubscript(rpmdbObject * s, PyObject * key);
-static rpmdbMIObject * py_rpmdbInitIterator (rpmdbObject * s, PyObject * args);
-
-/* rpmdbMatchIterator functions */
-static void rpmdbMIDealloc(rpmdbMIObject * s);
-static PyObject * rpmdbMIGetAttr (rpmdbObject *s, char *name);
-
-static PyObject * rpmdbMINext(rpmdbMIObject * s, PyObject * args);
-
-/* header functions */
-static void hdrDealloc(hdrObject * s);
-static PyObject * hdrGetAttr(hdrObject * s, char * name);
-static PyObject * hdrSubscript(hdrObject * s, PyObject * item);
-static PyObject * hdrKeyList(hdrObject * s, PyObject * args);
-static PyObject * hdrUnload(hdrObject * s, PyObject * args);
-static PyObject * hdrVerifyFile(hdrObject * s, PyObject * args);
-static PyObject * hdrCompressFilelist(hdrObject * s, PyObject * args);
-static PyObject * hdrExpandFilelist(hdrObject * s, PyObject * args);
-static PyObject * hdrFullFilelist(hdrObject * s, PyObject * args);
+extern int mdfile(const char *fn, unsigned char *digest);
 
 void initrpm(void);
 
-/* global module functions */
-static PyObject * doAddMacro(PyObject * self, PyObject * args);
-static PyObject * doDelMacro(PyObject * self, PyObject * args);
-static PyObject * rpmInitDB(PyObject * self, PyObject * args);
-static rpmdbObject * rpmOpenDB(PyObject * self, PyObject * args);
-static PyObject * hdrLoad(PyObject * self, PyObject * args);
-static PyObject * rpmHeaderFromPackage(PyObject * self, PyObject * args);
-static PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args);
-static PyObject * archScore(PyObject * self, PyObject * args);
-static PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args);
-static PyObject * findUpgradeSet(PyObject * self, PyObject * args);
-static PyObject * errorSetCallback (PyObject * self, PyObject * args);
-static PyObject * errorString (PyObject * self, PyObject * args);
-static PyObject * versionCompare (PyObject * self, PyObject * args);
-static PyObject * labelCompare (PyObject * self, PyObject * args);
-static PyObject * rebuildDB (PyObject * self, PyObject * args);
-/*  static PyObject * doFopen(PyObject * self, PyObject * args); */
-
-/* transaction set functions */
-static PyObject * rpmtransCreate(PyObject * self, PyObject * args);
-static PyObject * rpmtransAdd(rpmtransObject * s, PyObject * args);
-static PyObject * rpmtransRemove(rpmtransObject * s, PyObject * args);
-static PyObject * rpmtransDepCheck(rpmtransObject * s, PyObject * args);
-static PyObject * rpmtransRun(rpmtransObject * s, PyObject * args);
-static PyObject * py_rpmtransGetKeys(rpmtransObject * s, PyObject * args);
-static PyObject * rpmtransOrder(rpmtransObject * s, PyObject * args);
-static void rpmtransDealloc(PyObject * o);
-static PyObject * rpmtransGetAttr(rpmtransObject * o, char * name);
-static int rpmtransSetAttr(rpmtransObject * o, char * name,
-                          PyObject * val);
+/* from lib/misc.c */
+int rpmvercmp(const char * one, const char * two);
 
-/* signature verification */
-static PyObject * checkSig (PyObject * self, PyObject * args);
 
-/* hack to get the current header that's in the transaction set */
-static PyObject * getTsHeader (PyObject * self, PyObject * args);
+/** \ingroup python
+ */
+typedef struct rpmdbObject_s rpmdbObject;
 
-/* internal functions */
-static long tagNumFromPyObject (PyObject *item);
-static void mungeFilelist(Header h);
+/** \ingroup python
+ */
+typedef struct rpmdbMIObject_s rpmdbMIObject;
 
-/* Types */
-struct rpmdbObject_s {
-    PyObject_HEAD;
-    rpmdb db;
-    int offx;
-    int noffs;
-    int *offsets;
-} ;
+/** \ingroup python
+ */
+typedef struct rpmtransObject_s rpmtransObject;
 
-struct rpmdbMIObject_s {
-    PyObject_HEAD;
-    rpmdbObject *db;
-    rpmdbMatchIterator mi;
-} ;
+/** \ingroup python
+ */
+typedef struct hdrObject_s hdrObject;
 
-struct rpmtransObject_s {
-    PyObject_HEAD;
-    rpmdbObject * dbo;
-    rpmTransactionSet ts;
-    PyObject * keyList;                        /* keeps reference counts correct */
-    FD_t scriptFd;
-} ;
+/** \ingroup python
+ */
+static PyObject * pyrpmError;
 
+/** \ingroup python
+ * \class header
+ * \brief A python header object represents an RPM package header.
+ * 
+ * All RPM packages have headers that provide metadata for the package.
+ * Header objects can be returned by database queries or loaded from a
+ * binary package on disk.
+ * 
+ * The headerFromPackage function loads the package header from a
+ * package on disk.  It returns a tuple of a "isSource" flag and the
+ * header object.  The "isSource" flag is set to 1 if the package
+ * header was read from a source rpm or to 0 if the package header was
+ * read from a binary rpm.
+ * 
+ * For example:
+ * \code
+ *     import os, rpm
+ *  
+ *     fd = os.open("/tmp/foo-1.0-1.i386.rpm", os.O_RDONLY)
+ *     (isSource, header) = rpm.headerFromPackage(fd)
+ *     fd.close()
+ * \endcode
+ * The Python interface to the header data is quite elegant.  It
+ * presents the data in a dictionary form.  We'll take the header we
+ * just loaded and access the data within it:
+ * \code
+ *     print header[rpm.RPMTAG_NAME]
+ *     print header[rpm.RPMTAG_VERSION]
+ *     print header[rpm.RPMTAG_RELEASE]
+ * \endcode
+ * in the case of our "foor-1.0-1.i386.rpm" package, this code would
+ * output:
+\verbatim
+       foo
+       1.0
+       1
+\endverbatim
+ * You make also access the header data by string name:
+ * \code
+ *     print header['name']
+ * \endcode
+ * This method of access is a bit slower because the name must be
+ * translated into the tag number dynamically.
+ */
+
+/** \ingroup python
+ * \name Class: header
+ */
+/*@{*/
+
+/** \ingroup python
+ */
 struct hdrObject_s {
     PyObject_HEAD;
     Header h;
@@ -135,272 +114,276 @@ struct hdrObject_s {
     unsigned short * modes;
 } ;
 
-/* Data */
+/** \ingroup python
+ */
+static PyObject * hdrKeyList(hdrObject * s, PyObject * args) {
+    PyObject * list, *o;
+    HeaderIterator iter;
+    int tag, type;
 
-static PyObject * pyrpmError;
-static Header transactionSetHeader = NULL;
+    if (!PyArg_ParseTuple(args, "")) return NULL;
 
-static PyMethodDef rpmModuleMethods[] = {
-    { "TransactionSet", (PyCFunction) rpmtransCreate, METH_VARARGS, NULL },
-    { "addMacro", (PyCFunction) doAddMacro, METH_VARARGS, NULL },
-    { "delMacro", (PyCFunction) doDelMacro, METH_VARARGS, NULL },
-    { "archscore", (PyCFunction) archScore, METH_VARARGS, NULL },
-    { "findUpgradeSet", (PyCFunction) findUpgradeSet, METH_VARARGS, NULL },
-    { "headerFromPackage", (PyCFunction) rpmHeaderFromPackage, METH_VARARGS, NULL },
-    { "headerLoad", (PyCFunction) hdrLoad, METH_VARARGS, NULL },
-    { "initdb", (PyCFunction) rpmInitDB, METH_VARARGS, NULL },
-    { "opendb", (PyCFunction) rpmOpenDB, METH_VARARGS, NULL },
-    { "rebuilddb", (PyCFunction) rebuildDB, METH_VARARGS, NULL },
-    { "readHeaderListFromFD", (PyCFunction) rpmHeaderFromFD, METH_VARARGS, NULL },
-    { "readHeaderListFromFile", (PyCFunction) rpmHeaderFromFile, METH_VARARGS, NULL },
-    { "errorSetCallback", (PyCFunction) errorSetCallback, METH_VARARGS, NULL },
-    { "errorString", (PyCFunction) errorString, METH_VARARGS, NULL },
-    { "versionCompare", (PyCFunction) versionCompare, METH_VARARGS, NULL },
-    { "labelCompare", (PyCFunction) labelCompare, METH_VARARGS, NULL },
-    { "checksig", (PyCFunction) checkSig, METH_VARARGS, NULL },
-    { "getTransactionCallbackHeader", (PyCFunction) getTsHeader, METH_VARARGS, NULL },
-/*      { "Fopen", (PyCFunction) doFopen, METH_VARARGS, NULL }, */
-    { NULL }
-} ;
+    list = PyList_New(0);
 
-static PyMappingMethods hdrAsMapping = {
-       (inquiry) 0,                    /* mp_length */
-       (binaryfunc) hdrSubscript,      /* mp_subscript */
-       (objobjargproc)0,               /* mp_ass_subscript */
-};
+    iter = headerInitIterator(s->h);
+    while (headerNextIterator(iter, &tag, &type, NULL, NULL)) {
+        if (tag == HEADER_I18NTABLE) continue;
 
-static PyTypeObject hdrType = {
-       PyObject_HEAD_INIT(&PyType_Type)
-       0,                              /* ob_size */
-       "header",                       /* tp_name */
-       sizeof(hdrObject),              /* tp_size */
-       0,                              /* tp_itemsize */
-       (destructor) hdrDealloc,        /* tp_dealloc */
-       0,                              /* tp_print */
-       (getattrfunc) hdrGetAttr,       /* tp_getattr */
-       0,                              /* tp_setattr */
-       0,                              /* tp_compare */
-       0,                              /* tp_repr */
-       0,                              /* tp_as_number */
-       0,                              /* tp_as_sequence */
-       &hdrAsMapping,                  /* tp_as_mapping */
-};
+       switch (type) {
+         case RPM_BIN_TYPE:
+         case RPM_INT32_TYPE:
+         case RPM_CHAR_TYPE:
+         case RPM_INT8_TYPE:
+         case RPM_INT16_TYPE:
+         case RPM_STRING_ARRAY_TYPE:
+         case RPM_STRING_TYPE:
+           PyList_Append(list, o=PyInt_FromLong(tag));
+           Py_DECREF(o);
+       }
+    }
 
-#ifndef DYINGSOON
-static PyMappingMethods rpmdbAsMapping = {
-       (inquiry) rpmdbLength,          /* mp_length */
-       (binaryfunc) rpmdbSubscript,    /* mp_subscript */
-       (objobjargproc)0,               /* mp_ass_subscript */
-};
-#endif
+    headerFreeIterator(iter);
 
-static PyTypeObject rpmdbType = {
-       PyObject_HEAD_INIT(&PyType_Type)
-       0,                              /* ob_size */
-       "rpmdb",                        /* tp_name */
-       sizeof(rpmdbObject),            /* tp_size */
-       0,                              /* tp_itemsize */
-       (destructor) rpmdbDealloc,      /* tp_dealloc */
-       0,                              /* tp_print */
-       (getattrfunc) rpmdbGetAttr,     /* tp_getattr */
-       0,                              /* tp_setattr */
-       0,                              /* tp_compare */
-       0,                              /* tp_repr */
-       0,                              /* tp_as_number */
-       0,                              /* tp_as_sequence */
-#ifndef DYINGSOON
-       &rpmdbAsMapping,                /* tp_as_mapping */
-#else
-       0,
-#endif
-};
+    return list;
+}
 
-/* Python rpmdbMatchIterator object */
-static PyTypeObject rpmdbMIType = {
-       PyObject_HEAD_INIT(&PyType_Type)
-       0,                              /* ob_size */
-       "rpmdbMatchIterator",           /* tp_name */
-       sizeof(rpmdbMIObject),  /* tp_size */
-       0,                              /* tp_itemsize */
-       (destructor) rpmdbMIDealloc,    /* tp_dealloc */
-       0,                              /* tp_print */
-       (getattrfunc) rpmdbMIGetAttr,   /* tp_getattr */
-       0,                              /* tp_setattr */
-       0,                              /* tp_compare */
-       0,                              /* tp_repr */
-       0,                              /* tp_as_number */
-       0,                              /* tp_as_sequence */
-       0,                              /* tp_as_mapping */
-};
+/** \ingroup python
+ */
+static PyObject * hdrUnload(hdrObject * s, PyObject * args) {
+    char * buf;
+    int len;
+    PyObject * rc;
 
-static PyTypeObject rpmtransType = {
-       PyObject_HEAD_INIT(&PyType_Type)
-       0,                              /* ob_size */
-       "rpmtrans",                     /* tp_name */
-       sizeof(rpmtransObject),         /* tp_size */
-       0,                              /* tp_itemsize */
-       (destructor) rpmtransDealloc,   /* tp_dealloc */
-       0,                              /* tp_print */
-       (getattrfunc) rpmtransGetAttr,  /* tp_getattr */
-       (setattrfunc) rpmtransSetAttr,  /* tp_setattr */
-       0,                              /* tp_compare */
-       0,                              /* tp_repr */
-       0,                              /* tp_as_number */
-       0,                              /* tp_as_sequence */
-       0,                              /* tp_as_mapping */
-};
+    len = headerSizeof(s->h, 0);
+    buf = headerUnload(s->h);
 
-static struct PyMethodDef rpmdbMethods[] = {
-       {"firstkey",        (PyCFunction) rpmdbFirst,   1 },
-       {"nextkey",         (PyCFunction) rpmdbNext,    1 },
-       {"findbyfile",      (PyCFunction) rpmdbByFile, 1 },
-       {"findbyname",      (PyCFunction) rpmdbByName, 1 },
-       {"findbyprovides",  (PyCFunction) rpmdbByProvides, 1 },
-       {"match",           (PyCFunction) py_rpmdbInitIterator, 1 },
-       {NULL,          NULL}           /* sentinel */
-};
+    rc = PyString_FromStringAndSize(buf, len);
+    free(buf);
 
-static struct PyMethodDef rpmdbMIMethods[] = {
-       {"next",            (PyCFunction) rpmdbMINext,  1 },
-       {NULL,          NULL}           /* sentinel */
-};
+    return rc;
+}
 
-static struct PyMethodDef rpmtransMethods[] = {
-       {"add",         (PyCFunction) rpmtransAdd,      1 },
-       {"remove",      (PyCFunction) rpmtransRemove,   1 },
-       {"depcheck",    (PyCFunction) rpmtransDepCheck, 1 },
-       {"order",       (PyCFunction) rpmtransOrder,    1 },
-       {"run",         (PyCFunction) rpmtransRun, 1 },
-       {"getKeys",     (PyCFunction) py_rpmtransGetKeys, 1 },
-       {NULL,          NULL}           /* sentinel */
-};
+/* Returns a list of these tuple for each part which failed:
 
-static struct PyMethodDef hdrMethods[] = {
-       {"keys",        (PyCFunction) hdrKeyList,       1 },
-       {"unload",      (PyCFunction) hdrUnload,        1 },
-       {"verifyFile",  (PyCFunction) hdrVerifyFile,    1 },
-       {"expandFilelist",      (PyCFunction) hdrExpandFilelist,        1 },
-       {"compressFilelist",    (PyCFunction) hdrCompressFilelist,      1 },
-       {"fullFilelist",        (PyCFunction) hdrFullFilelist,  1 },
-       {NULL,          NULL}           /* sentinel */
-};
+       (attr_name, correctValue, currentValue)
 
-/* External functions */
-int mdfile(const char *fn, unsigned char *digest);
+       It should be passwd the file number to verify.
+*/
+/** \ingroup python
+ */
+static PyObject * hdrVerifyFile(hdrObject * s, PyObject * args) {
+    int fileNumber;
+    rpmVerifyAttrs verifyResult = 0;
+    PyObject * list, * tuple, * attrName;
+    int type, count;
+    struct stat sb;
+    char buf[2048];
+    int i;
+    time_t timeInt;
+    struct tm * timeStruct;
 
-/* Code */
+    if (!PyInt_Check(args)) {
+       PyErr_SetString(PyExc_TypeError, "integer expected");
+       return NULL;
+    }
 
-extern int _rpmio_debug;
+    fileNumber = (int) PyInt_AsLong(args);
 
-void initrpm(void) {
-    PyObject * m, * d, *o, * tag = NULL, * dict;
-    int i;
-    const struct headerSprintfExtension * extensions = rpmHeaderFormats;
-    struct headerSprintfExtension * ext;
+    if (rpmVerifyFile("", s->h, fileNumber, &verifyResult, RPMVERIFY_NONE)) {
+       Py_INCREF(Py_None);
+       return Py_None;
+    }
 
-/*      _rpmio_debug = -1; */
-    rpmReadConfigFiles(NULL, NULL);
+    list = PyList_New(0);
 
-    m = Py_InitModule("rpm", rpmModuleMethods);
-    d = PyModule_GetDict(m);
+    if (!verifyResult) return list;
 
-    pyrpmError = PyString_FromString("rpm.error");
-    PyDict_SetItemString(d, "error", pyrpmError);
-    Py_DECREF(pyrpmError);
+    if (!s->fileList) {
+       headerGetEntry(s->h, RPMTAG_OLDFILENAMES, &type, (void **) &s->fileList,
+                &count);
+    }
 
-    dict = PyDict_New();
+    lstat(s->fileList[fileNumber], &sb);
 
-    for (i = 0; i < rpmTagTableSize; i++) {
-       tag = PyInt_FromLong(rpmTagTable[i].val);
-       PyDict_SetItemString(d, (char *) rpmTagTable[i].name, tag);
-       Py_DECREF(tag);
-        PyDict_SetItem(dict, tag, o=PyString_FromString(rpmTagTable[i].name + 7));
-       Py_DECREF(o);
+    if (verifyResult & RPMVERIFY_MD5) {
+       if (!s->md5list) {
+           headerGetEntry(s->h, RPMTAG_FILEMD5S, &type, (void **) &s->md5list,
+                    &count);
+       }
+
+       if (mdfile(s->fileList[fileNumber], buf)) {
+           strcpy(buf, "(unknown)");
+       }
+
+       tuple = PyTuple_New(3);
+       attrName = PyString_FromString("checksum");
+       PyTuple_SetItem(tuple, 0, attrName);
+       PyTuple_SetItem(tuple, 1, PyString_FromString(s->md5list[fileNumber]));
+       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
+       PyList_Append(list, tuple);
+       Py_DECREF(tuple);
     }
 
-    while (extensions->name) {
-       if (extensions->type == HEADER_EXT_TAG) {
-            (const struct headerSprintfExtension *) ext = extensions;
-            PyDict_SetItemString(d, extensions->name, o=PyCObject_FromVoidPtr(ext, NULL));
-           Py_DECREF(o);
-            PyDict_SetItem(dict, tag, o=PyString_FromString(ext->name + 7));
-           Py_DECREF(o);    
-        }
-        extensions++;
+    if (verifyResult & RPMVERIFY_FILESIZE) {
+       if (!s->fileSizes) {
+           headerGetEntry(s->h, RPMTAG_FILESIZES, &type, (void **) &s->fileSizes,
+                    &count);
+
+       }
+
+       tuple = PyTuple_New(3);
+       attrName = PyString_FromString("size");
+       PyTuple_SetItem(tuple, 0, attrName);
+
+       sprintf(buf, "%d", 100);
+       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
+       sprintf(buf, "%ld", sb.st_size);
+       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
+       PyList_Append(list, tuple);
+       Py_DECREF(tuple);
     }
 
-    PyDict_SetItemString(d, "tagnames", dict);
-    Py_DECREF(dict);
+    if (verifyResult & RPMVERIFY_LINKTO) {
+       if (!s->linkList) {
+           headerGetEntry(s->h, RPMTAG_FILELINKTOS, &type, (void **) &s->linkList,
+                    &count);
+       }
 
+       i = readlink(s->fileList[fileNumber], buf, sizeof(buf));
+       if (i <= 0)
+           strcpy(buf, "(unknown)");
+       else
+           buf[i] = '\0';
 
-#define REGISTER_ENUM(val) \
-    PyDict_SetItemString(d, #val, o=PyInt_FromLong(## val)); \
-    Py_DECREF(o);
-    
-    REGISTER_ENUM(RPMFILE_STATE_NORMAL);
-    REGISTER_ENUM(RPMFILE_STATE_REPLACED);
-    REGISTER_ENUM(RPMFILE_STATE_NOTINSTALLED);
-    REGISTER_ENUM(RPMFILE_CONFIG);
-    REGISTER_ENUM(RPMFILE_MISSINGOK);
-    REGISTER_ENUM(RPMFILE_DOC);
+       tuple = PyTuple_New(3);
+       attrName = PyString_FromString("link");
+       PyTuple_SetItem(tuple, 0, attrName);
+       PyTuple_SetItem(tuple, 1, PyString_FromString(s->linkList[fileNumber]));
+       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
+       PyList_Append(list, tuple);
+       Py_DECREF(tuple);
+    }
 
-    REGISTER_ENUM(RPMDEP_SENSE_REQUIRES);
-    REGISTER_ENUM(RPMDEP_SENSE_CONFLICTS);
+    if (verifyResult & RPMVERIFY_MTIME) {
+       if (!s->mtimes) {
+           headerGetEntry(s->h, RPMTAG_FILEMTIMES, &type, (void **) &s->mtimes,
+                    &count);
+       }
 
-    REGISTER_ENUM(RPMSENSE_SERIAL);
-    REGISTER_ENUM(RPMSENSE_LESS);
-    REGISTER_ENUM(RPMSENSE_GREATER);
-    REGISTER_ENUM(RPMSENSE_EQUAL);
-    REGISTER_ENUM(RPMSENSE_PREREQ);
+       tuple = PyTuple_New(3);
+       attrName = PyString_FromString("time");
+       PyTuple_SetItem(tuple, 0, attrName);
 
-    REGISTER_ENUM(RPMTRANS_FLAG_TEST);
-    REGISTER_ENUM(RPMTRANS_FLAG_BUILD_PROBS);
-    REGISTER_ENUM(RPMTRANS_FLAG_NOSCRIPTS);
-    REGISTER_ENUM(RPMTRANS_FLAG_JUSTDB);
-    REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERS);
-    REGISTER_ENUM(RPMTRANS_FLAG_NODOCS);
-    REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES);
-    REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE);
+       timeInt = sb.st_mtime;
+       timeStruct = localtime(&timeInt);
+       strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
+       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
 
-    REGISTER_ENUM(RPMPROB_FILTER_IGNOREOS);
-    REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH);
-    REGISTER_ENUM(RPMPROB_FILTER_REPLACEPKG);
-    REGISTER_ENUM(RPMPROB_FILTER_FORCERELOCATE);
-    REGISTER_ENUM(RPMPROB_FILTER_REPLACENEWFILES);
-    REGISTER_ENUM(RPMPROB_FILTER_REPLACEOLDFILES);
-    REGISTER_ENUM(RPMPROB_FILTER_OLDPACKAGE);
-    REGISTER_ENUM(RPMPROB_FILTER_DISKSPACE);
+       timeInt = s->mtimes[fileNumber];
+       timeStruct = localtime(&timeInt);
+       strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
 
-    REGISTER_ENUM(RPMCALLBACK_INST_PROGRESS);
-    REGISTER_ENUM(RPMCALLBACK_INST_START);
-    REGISTER_ENUM(RPMCALLBACK_INST_OPEN_FILE);
-    REGISTER_ENUM(RPMCALLBACK_INST_CLOSE_FILE);
-    REGISTER_ENUM(RPMCALLBACK_TRANS_PROGRESS);
-    REGISTER_ENUM(RPMCALLBACK_TRANS_START);
-    REGISTER_ENUM(RPMCALLBACK_TRANS_STOP);
-    REGISTER_ENUM(RPMCALLBACK_UNINST_PROGRESS);
-    REGISTER_ENUM(RPMCALLBACK_UNINST_START);
-    REGISTER_ENUM(RPMCALLBACK_UNINST_STOP);
+       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
 
-    REGISTER_ENUM(RPMPROB_BADARCH);
-    REGISTER_ENUM(RPMPROB_BADOS);
-    REGISTER_ENUM(RPMPROB_PKG_INSTALLED);
-    REGISTER_ENUM(RPMPROB_BADRELOCATE);
-    REGISTER_ENUM(RPMPROB_REQUIRES);
-    REGISTER_ENUM(RPMPROB_CONFLICT);
-    REGISTER_ENUM(RPMPROB_NEW_FILE_CONFLICT);
-    REGISTER_ENUM(RPMPROB_FILE_CONFLICT);
-    REGISTER_ENUM(RPMPROB_OLDPACKAGE);
-    REGISTER_ENUM(RPMPROB_DISKSPACE);
-    REGISTER_ENUM(RPMPROB_DISKNODES);
-    REGISTER_ENUM(RPMPROB_BADPRETRANS);
+       PyList_Append(list, tuple);
+       Py_DECREF(tuple);
+    }
 
-    REGISTER_ENUM(CHECKSIG_PGP);
-    REGISTER_ENUM(CHECKSIG_GPG);
-    REGISTER_ENUM(CHECKSIG_MD5);
+    if (verifyResult & RPMVERIFY_RDEV) {
+       if (!s->rdevs) {
+           headerGetEntry(s->h, RPMTAG_FILERDEVS, &type, (void **) &s->rdevs,
+                    &count);
+       }
+
+       tuple = PyTuple_New(3);
+       attrName = PyString_FromString("device");
+
+       PyTuple_SetItem(tuple, 0, attrName);
+       sprintf(buf, "0x%-4x", s->rdevs[fileNumber]);
+       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
+       sprintf(buf, "0x%-4x", (unsigned int) sb.st_rdev);
+       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
+       PyList_Append(list, tuple);
+       Py_DECREF(tuple);
+    }
+
+    /* RPMVERIFY_USER and RPM_VERIFY_GROUP are handled wrong here, but rpmlib.a
+       doesn't do these correctly either. At least this is consisten */
+    if (verifyResult & RPMVERIFY_USER) {
+       if (!s->uids) {
+           headerGetEntry(s->h, RPMTAG_FILEUIDS, &type, (void **) &s->uids,
+                    &count);
+       }
+
+       tuple = PyTuple_New(3);
+       attrName = PyString_FromString("uid");
+       PyTuple_SetItem(tuple, 0, attrName);
+       sprintf(buf, "%d", s->uids[fileNumber]);
+       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
+       sprintf(buf, "%d", sb.st_uid);
+       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
+       PyList_Append(list, tuple);
+       Py_DECREF(tuple);
+    }
+
+    if (verifyResult & RPMVERIFY_GROUP) {
+       if (!s->gids) {
+           headerGetEntry(s->h, RPMTAG_FILEGIDS, &type, (void **) &s->gids,
+                    &count);
+       }
+
+       tuple = PyTuple_New(3);
+       attrName = PyString_FromString("gid");
+       PyTuple_SetItem(tuple, 0, attrName);
+       sprintf(buf, "%d", s->gids[fileNumber]);
+       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
+       sprintf(buf, "%d", sb.st_gid);
+       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
+       PyList_Append(list, tuple);
+       Py_DECREF(tuple);
+    }
+
+    if (verifyResult & RPMVERIFY_MODE) {
+       if (!s->modes) {
+           headerGetEntry(s->h, RPMTAG_FILEMODES, &type, (void **) &s->modes,
+                    &count);
+       }
+
+       tuple = PyTuple_New(3);
+       attrName = PyString_FromString("permissions");
+       PyTuple_SetItem(tuple, 0, attrName);
+       sprintf(buf, "0%-4o", s->modes[fileNumber]);
+       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
+       sprintf(buf, "0%-4o", sb.st_mode);
+       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
+       PyList_Append(list, tuple);
+       Py_DECREF(tuple);
+    }
+
+    return list;
+}
+
+/** \ingroup python
+ */
+static PyObject * hdrExpandFilelist(hdrObject * s, PyObject * args) {
+    expandFilelist (s->h);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+/** \ingroup python
+ */
+static PyObject * hdrCompressFilelist(hdrObject * s, PyObject * args) {
+    compressFilelist (s->h);
+
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 /* make a header with _all_ the tags we need */
+/** \ingroup python
+ */
 static void mungeFilelist(Header h)
 {
     const char ** fileNames = NULL;
@@ -422,438 +405,416 @@ static void mungeFilelist(Header h)
     free((void *)fileNames);
 }
 
-static int psGetArchScore(Header h) {
-    void * pkgArch;
-    int type, count;
+/** \ingroup python
+ */
+static PyObject * hdrFullFilelist(hdrObject * s, PyObject * args) {
+    mungeFilelist (s->h);
 
-    if (!headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count) ||
-        type == RPM_INT8_TYPE)
-       return 150;
-    else
-        return rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch);
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
-static int pkgCompareVer(void * first, void * second) {
-    struct packageInfo ** a = first;
-    struct packageInfo ** b = second;
-    int ret, score1, score2;
-
-    /* put packages w/o names at the end */
-    if (!(*a)->name) return 1;
-    if (!(*b)->name) return -1;
+/** \ingroup python
+ */
+static struct PyMethodDef hdrMethods[] = {
+       {"keys",        (PyCFunction) hdrKeyList,       1 },
+       {"unload",      (PyCFunction) hdrUnload,        1 },
+       {"verifyFile",  (PyCFunction) hdrVerifyFile,    1 },
+       {"expandFilelist",      (PyCFunction) hdrExpandFilelist,        1 },
+       {"compressFilelist",    (PyCFunction) hdrCompressFilelist,      1 },
+       {"fullFilelist",        (PyCFunction) hdrFullFilelist,  1 },
+       {NULL,          NULL}           /* sentinel */
+};
 
-    ret = xstrcasecmp((*a)->name, (*b)->name);
-    if (ret) return ret;
-    score1 = psGetArchScore((*a)->h);
-    if (!score1) return 1;
-    score2 = psGetArchScore((*b)->h);
-    if (!score2) return -1;
-    if (score1 < score2) return -1;
-    if (score1 > score2) return 1;
-    return rpmVersionCompare((*b)->h, (*a)->h);
+/** \ingroup python
+ */
+static PyObject * hdrGetAttr(hdrObject * s, char * name) {
+    return Py_FindMethod(hdrMethods, (PyObject * ) s, name);
 }
 
-static void pkgSort(struct pkgSet * psp) {
-    int i;
-    char *name;
-
-    qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
-        (void *) pkgCompareVer);
-
-    name = psp->packages[0]->name;
-    if (!name) {
-       psp->numPackages = 0;
-       return;
-    }
-    for (i = 1; i < psp->numPackages; i++) {
-       if (!psp->packages[i]->name) break;
-       if (!strcmp(psp->packages[i]->name, name))
-          psp->packages[i]->name = NULL;
-       else
-          name = psp->packages[i]->name;
-    }
-
-    qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
-        (void *) pkgCompareVer);
-
-    for (i = 0; i < psp->numPackages; i++)
-       if (!psp->packages[i]->name) break;
-    psp->numPackages = i;
+/** \ingroup python
+ */
+static void hdrDealloc(hdrObject * s) {
+    if (s->h) headerFree(s->h);
+    if (s->sigs) headerFree(s->sigs);
+    if (s->md5list) free(s->md5list);
+    if (s->fileList) free(s->fileList);
+    if (s->linkList) free(s->linkList);
+    PyMem_DEL(s);
 }
 
-static PyObject * findUpgradeSet(PyObject * self, PyObject * args) {
-    PyObject * hdrList, * result;
-    char * root = "/";
+/** \ingroup python
+ */
+static long tagNumFromPyObject (PyObject *item)
+{
+    char * str;
     int i;
-    struct pkgSet list;
-    hdrObject * hdr;
-
-    if (!PyArg_ParseTuple(args, "O|s", &hdrList, &root)) return NULL;
-
-    if (!PyList_Check(hdrList)) {
-       PyErr_SetString(PyExc_TypeError, "list of headers expected");
-       return NULL;
-    }
-
-    list.numPackages = PyList_Size(hdrList);
-    list.packages = alloca(sizeof(list.packages) * list.numPackages);
-    for (i = 0; i < list.numPackages; i++) {
-       hdr = (hdrObject *) PyList_GetItem(hdrList, i);
-       if (hdr->ob_type != &hdrType) {
-           PyErr_SetString(PyExc_TypeError, "list of headers expected");
-           return NULL;
-       }
-       list.packages[i] = alloca(sizeof(struct packageInfo));
-       list.packages[i]->h = hdr->h;
-       list.packages[i]->selected = 0;
-       list.packages[i]->data = hdr;
-
-       headerGetEntry(hdr->h, RPMTAG_NAME, NULL,
-                     (void **) &list.packages[i]->name, NULL);
-    }
-
-    pkgSort (&list);
-
-    if (ugFindUpgradePackages(&list, root)) {
-       PyErr_SetString(pyrpmError, "error during upgrade check");
-       return NULL;
-    }
-
-    result = PyList_New(0);
-    for (i = 0; i < list.numPackages; i++) {
-       if (list.packages[i]->selected) {
-           PyList_Append(result, list.packages[i]->data);
-/*         Py_DECREF(list.packages[i]->data); */
-       }
-    }
-
-    return result;
-}
-
-static PyObject * rpmInitDB(PyObject * self, PyObject * args) {
-    char *root;
-    int forWrite = 0;
-
-    if (!PyArg_ParseTuple(args, "i|s", &forWrite, &root)) return NULL;
-
-    if (rpmdbInit(root, forWrite ? O_RDWR | O_CREAT: O_RDONLY)) {
-       char * errmsg = "cannot initialize database in %s";
-       char * errstr = NULL;
-       int errsize;
-
-       errsize = strlen(errmsg) + strlen(root);
-       errstr = alloca(errsize);
-       snprintf(errstr, errsize, errmsg, root);
-       PyErr_SetString(pyrpmError, errstr);
-       return NULL;
-    }
-
-    Py_INCREF(Py_None);
-    return(Py_None);
-}
-
-static rpmdbObject * rpmOpenDB(PyObject * self, PyObject * args) {
-    rpmdbObject * o;
-    char * root = "";
-    int forWrite = 0;
-
-    if (!PyArg_ParseTuple(args, "|is", &forWrite, &root)) return NULL;
 
-    o = PyObject_NEW(rpmdbObject, &rpmdbType);
-    o->db = NULL;
-    o->offx = 0;
-    o->noffs = 0;
-    o->offsets = NULL;
-
-    if (rpmdbOpen(root, &o->db, forWrite ? O_RDWR | O_CREAT: O_RDONLY, 0644)) {
-       char * errmsg = "cannot open database in %s";
-       char * errstr = NULL;
-       int errsize;
-
-       Py_DECREF(o);
-       /* PyErr_SetString should take varargs... */
-       errsize = strlen(errmsg) + *root == '\0' ? 15 /* "/var/lib/rpm" */ : strlen(root);
-       errstr = alloca(errsize);
-       snprintf(errstr, errsize, errmsg, *root == '\0' ? "/var/lib/rpm" : root);
-       PyErr_SetString(pyrpmError, errstr);
-       return NULL;
+    if (PyInt_Check(item)) {
+       return PyInt_AsLong(item);
+    } else if (PyString_Check(item)) {
+       str = PyString_AsString(item);
+       for (i = 0; i < rpmTagTableSize; i++)
+           if (!xstrcasecmp(rpmTagTable[i].name + 7, str)) break;
+       if (i < rpmTagTableSize) return rpmTagTable[i].val;
     }
-
-    return o;
-}
-
-static PyObject * rebuildDB (PyObject * self, PyObject * args) {
-    char * root = "";
-
-    if (!PyArg_ParseTuple(args, "s", &root)) return NULL;
-
-    return Py_BuildValue("i", rpmdbRebuild(root));
+    return -1;
 }
 
-static PyObject * rpmReadHeaders (FD_t fd) {
-    PyObject * list;
-    Header header;
-    hdrObject * h;
-
-    if (!fd) {
-       PyErr_SetFromErrno(pyrpmError);
-       return NULL;
-    }
-
-    list = PyList_New(0);
-    Py_BEGIN_ALLOW_THREADS
-    header = headerRead(fd, HEADER_MAGIC_YES);
+/** \ingroup python
+ */
+static PyObject * hdrSubscript(hdrObject * s, PyObject * item) {
+    int type, count, i, tag = -1;
+    void * data;
+    PyObject * o, * metao;
+    char ** stringArray;
+    int forceArray = 0;
+    int freeData = 0;
+    char * str;
+    struct headerSprintfExtension * ext = NULL;
+    const struct headerSprintfExtension * extensions = rpmHeaderFormats;
 
-    Py_END_ALLOW_THREADS
-    while (header) {
-       compressFilelist (header);
-       providePackageNVR (header);
-       h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
-       h->h = header;
-       h->sigs = NULL;
-       h->fileList = h->linkList = h->md5list = NULL;
-       h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
-       h->modes = h->rdevs = NULL;
-       if (PyList_Append(list, (PyObject *) h)) {
-           Py_DECREF(list);
-           Py_DECREF(h);
-           return NULL;
+    if (PyCObject_Check (item))
+        ext = PyCObject_AsVoidPtr(item);
+    else
+       tag = tagNumFromPyObject (item);
+    if (tag == -1 && PyString_Check(item)) {
+       /* if we still don't have the tag, go looking for the header
+          extensions */
+       str = PyString_AsString(item);
+       while (extensions->name) {
+           if (extensions->type == HEADER_EXT_TAG
+               && !xstrcasecmp(extensions->name + 7, str)) {
+               (const struct headerSprintfExtension *) ext = extensions;
+           }
+           extensions++;
        }
-
-       Py_DECREF(h);
-
-       Py_BEGIN_ALLOW_THREADS
-       header = headerRead(fd, HEADER_MAGIC_YES);
-       Py_END_ALLOW_THREADS
     }
 
-    return list;
-}
-
-static PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args) {
-    FD_t fd;
-    int fileno;
-    PyObject * list;
-
-    if (!PyArg_ParseTuple(args, "i", &fileno)) return NULL;
-    fd = fdDup(fileno);
-
-    list = rpmReadHeaders (fd);
-    Fclose(fd);
-
-    return list;
-}
-
-
-static PyObject * hdrLoad(PyObject * self, PyObject * args) {
-    char * obj, * copy=NULL;
-    Header hdr;
-    hdrObject * h;
-    int len;
-
-    if (!PyArg_ParseTuple(args, "s#", &obj, &len)) return NULL;
-    
-    copy = malloc(len);
-    if (copy == NULL) {
-       PyErr_SetString(pyrpmError, "out of memory");
-       return NULL;
-    }
-
-    memcpy (copy, obj, len);
-
-    hdr = headerLoad(copy);
-    if (!hdr) {
-       PyErr_SetString(pyrpmError, "bad header");
-       return NULL;
-    }
-    compressFilelist (hdr);
-    providePackageNVR (hdr);
-
-    h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
-    h->h = hdr;
-    h->sigs = NULL;
-    h->fileList = h->linkList = h->md5list = NULL;
-    h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
-    h->modes = h->rdevs = NULL;
-
-    return (PyObject *) h;
-}
-
-static PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args) {
-    char * filespec;
-    FD_t fd;
-    PyObject * list;
-
-    if (!PyArg_ParseTuple(args, "s", &filespec)) return NULL;
-    fd = Fopen(filespec, "r.fdio");
-
-    if (!fd) {
-       PyErr_SetFromErrno(pyrpmError);
-       return NULL;
-    }
-
-    list = rpmReadHeaders (fd);
-    Fclose(fd);
-
-    return list;
-}
-
-static PyObject * errorCB = NULL, * errorData = NULL;
-
-static void errorcb (void)
-{
-    PyObject * result, * args = NULL;
-
-    if (errorData)
-       args = Py_BuildValue("(O)", errorData);
-
-    result = PyEval_CallObject(errorCB, args);
-    Py_XDECREF(args);
-
-    if (result == NULL) {
-       PyErr_Print();
-       PyErr_Clear();
-    }
-    Py_DECREF (result);
-}
-
-static PyObject * errorSetCallback (PyObject * self, PyObject * args) {
-    if (errorCB != NULL) {
-       Py_DECREF (errorCB);
-       errorCB = NULL;
+    if (ext) {
+        ext->u.tagFunction(s->h, &type, (const void **) &data, &count, &freeData);
+    } else {
+        if (tag == -1) {
+            PyErr_SetString(PyExc_KeyError, "unknown header tag");
+            return NULL;
+        }
+        
+        if (!rpmPackageGetEntry(NULL, s->sigs, s->h, tag, &type, &data, &count))
+       {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
     }
 
-    if (errorData != NULL) {
-       Py_DECREF (errorData);
-       errorData = NULL;
+    switch (tag) {
+      case RPMTAG_OLDFILENAMES:
+      case RPMTAG_FILESIZES:
+      case RPMTAG_FILESTATES:
+      case RPMTAG_FILEMODES:
+      case RPMTAG_FILEUIDS:
+      case RPMTAG_FILEGIDS:
+      case RPMTAG_FILERDEVS:
+      case RPMTAG_FILEMTIMES:
+      case RPMTAG_FILEMD5S:
+      case RPMTAG_FILELINKTOS:
+      case RPMTAG_FILEFLAGS:
+      case RPMTAG_ROOT:
+      case RPMTAG_FILEUSERNAME:
+      case RPMTAG_FILEGROUPNAME:
+       forceArray = 1;
+       break;
+      case RPMTAG_SUMMARY:
+      case RPMTAG_GROUP:
+      case RPMTAG_DESCRIPTION:
+       freeData = 1;
+       break;
+      default:
+        break;
     }
 
-    if (!PyArg_ParseTuple(args, "O|O", &errorCB, &errorData)) return NULL;
+    switch (type) {
+      case RPM_BIN_TYPE:
+       o = PyString_FromStringAndSize(data, count);
+       break;
 
-    /* if we're getting a void*, set the error callback to this. */
-    /* also, we can possibly decref any python callbacks we had  */
-    /* and set them to NULL.                                     */
-    if (PyCObject_Check (errorCB)) {
-       rpmErrorSetCallback (PyCObject_AsVoidPtr(errorCB));
+      case RPM_INT32_TYPE:
+       if (count != 1 || forceArray) {
+           metao = PyList_New(0);
+           for (i = 0; i < count; i++) {
+               o = PyInt_FromLong(((int *) data)[i]);
+               PyList_Append(metao, o);
+               Py_DECREF(o);
+           }
+           o = metao;
+       } else {
+           o = PyInt_FromLong(*((int *) data));
+       }
+       break;
 
-       Py_XDECREF (errorCB);
-       Py_XDECREF (errorData);
+      case RPM_CHAR_TYPE:
+      case RPM_INT8_TYPE:
+       if (count != 1 || forceArray) {
+           metao = PyList_New(0);
+           for (i = 0; i < count; i++) {
+               o = PyInt_FromLong(((char *) data)[i]);
+               PyList_Append(metao, o);
+               Py_DECREF(o);
+           }
+           o = metao;
+       } else {
+           o = PyInt_FromLong(*((char *) data));
+       }
+       break;
 
-       errorCB   = NULL;
-       errorData = NULL;
-       
-       Py_INCREF(Py_None);
-       return Py_None;
-    }
-    
-    if (!PyCallable_Check (errorCB)) {
-       PyErr_SetString(PyExc_TypeError, "parameter must be callable");
-       return NULL;
-    }
+      case RPM_INT16_TYPE:
+       if (count != 1 || forceArray) {
+           metao = PyList_New(0);
+           for (i = 0; i < count; i++) {
+               o = PyInt_FromLong(((short *) data)[i]);
+               PyList_Append(metao, o);
+               Py_DECREF(o);
+           }
+           o = metao;
+       } else {
+           o = PyInt_FromLong(*((short *) data));
+       }
+       break;
 
-    Py_INCREF (errorCB);
-    Py_XINCREF (errorData);
+      case RPM_STRING_ARRAY_TYPE:
+       stringArray = data;
 
-    return PyCObject_FromVoidPtr(rpmErrorSetCallback (errorcb), NULL);
-}
+       metao = PyList_New(0);
+       for (i = 0; i < count; i++) {
+           o = PyString_FromString(stringArray[i]);
+           PyList_Append(metao, o);
+           Py_DECREF(o);
+       }
+       free (stringArray);
+       o = metao;
+       break;
 
-static PyObject * errorString (PyObject * self, PyObject * args) {
-    return PyString_FromString(rpmErrorString ());
-}
+      case RPM_STRING_TYPE:
+       if (count != 1 || forceArray) {
+           stringArray = data;
 
-static PyObject * versionCompare (PyObject * self, PyObject * args) {
-    hdrObject * h1, * h2;
+           metao = PyList_New(0);
+           for (i=0; i < count; i++) {
+               o = PyString_FromString(stringArray[i]);
+               PyList_Append(metao, o);
+               Py_DECREF(o);
+           }
+           o = metao;
+       } else {
+           o = PyString_FromString(data);
+           if (freeData)
+               free (data);
+       }
+       break;
 
-    if (!PyArg_ParseTuple(args, "O!O!", &hdrType, &h1, &hdrType, &h2)) return NULL;
+      default:
+       PyErr_SetString(PyExc_TypeError, "unsupported type in header");
+       return NULL;
+    }
 
-    return Py_BuildValue("i", rpmVersionCompare(h1->h, h2->h));
+    return o;
 }
 
-static PyObject * labelCompare (PyObject * self, PyObject * args) {
-    char *v1, *r1, *e1, *v2, *r2, *e2;
-    int rc;
-
-    if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
-                         &e1, &v1, &r1,
-                         &e2, &v2, &r2)) return NULL;
+/** \ingroup python
+ */
+static PyMappingMethods hdrAsMapping = {
+       (inquiry) 0,                    /* mp_length */
+       (binaryfunc) hdrSubscript,      /* mp_subscript */
+       (objobjargproc)0,               /* mp_ass_subscript */
+};
 
-    if (e1 && !e2)
-       return Py_BuildValue("i", 1);
-    else if (!e1 && e2)
-       return Py_BuildValue("i", -1);
-    else if (e1 && e2) {
-       int ep1, ep2;
-       ep1 = atoi (e1);
-       ep2 = atoi (e2);
-       if (ep1 < ep2)
-           return Py_BuildValue("i", -1);
-       else if (ep1 > ep2)
-           return Py_BuildValue("i", 1);
-    }
+/** \ingroup python
+ */
+static PyTypeObject hdrType = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,                              /* ob_size */
+       "header",                       /* tp_name */
+       sizeof(hdrObject),              /* tp_size */
+       0,                              /* tp_itemsize */
+       (destructor) hdrDealloc,        /* tp_dealloc */
+       0,                              /* tp_print */
+       (getattrfunc) hdrGetAttr,       /* tp_getattr */
+       0,                              /* tp_setattr */
+       0,                              /* tp_compare */
+       0,                              /* tp_repr */
+       0,                              /* tp_as_number */
+       0,                              /* tp_as_sequence */
+       &hdrAsMapping,                  /* tp_as_mapping */
+};
 
-    rc = rpmvercmp(v1, v2);
-    if (rc)
-       return Py_BuildValue("i", rc);
+/*@}*/
 
-    return Py_BuildValue("i", rpmvercmp(r1, r2));
-}
+/** \ingroup python
+ * \class rpmdbMatchIterator
+ * \brief A python rpmdbMatchIterator object represents the result of an RPM
+ *     database query.
+ */
 
-static PyObject * rpmHeaderFromPackage(PyObject * self, PyObject * args) {
-    hdrObject * h;
-    Header header;
-    Header sigs;
-    int rc;
-    FD_t fd;
-    int rawFd;
-    int isSource = 0;
+/** \ingroup python
+ * \name Class: rpmdbMatchIterator
+ */
+/*@{*/
 
-    if (!PyArg_ParseTuple(args, "i", &rawFd)) return NULL;
-    fd = fdDup(rawFd);
+/** \ingroup python
+ */
+struct rpmdbObject_s {
+    PyObject_HEAD;
+    rpmdb db;
+    int offx;
+    int noffs;
+    int *offsets;
+} ;
 
-    rc = rpmReadPackageInfo(fd, &sigs, &header);
-    Fclose(fd);
+/** \ingroup python
+ */
+struct rpmdbMIObject_s {
+    PyObject_HEAD;
+    rpmdbObject *db;
+    rpmdbMatchIterator mi;
+} ;
 
-    switch (rc) {
-      case 0:
-       h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
-       h->h = header;
-       h->sigs = sigs;
-       h->fileList = h->linkList = h->md5list = NULL;
-       h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
-       h->modes = h->rdevs = NULL;
-       if (headerIsEntry(header, RPMTAG_SOURCEPACKAGE))
-           isSource = 1;
-       break;
+/** \ingroup python
+ */
+static PyObject *
+rpmdbMINext(rpmdbMIObject * s, PyObject * args) {
+    /* XXX assume header? */
+    Header h;
+    hdrObject * ho;
+    
 
-      case 1:
+    h = rpmdbNextIterator(s->mi);
+    if (!h) {
        Py_INCREF(Py_None);
-       h = (hdrObject *) Py_None;
-       break;
-
-      default:
-       PyErr_SetString(pyrpmError, "error reading package");
-       return NULL;
+       return Py_None;
     }
 
-    return Py_BuildValue("(Ni)", h, isSource);
+    ho = PyObject_NEW(hdrObject, &hdrType);
+    ho->h = headerLink(h);
+    ho->sigs = NULL;
+    ho->fileList = ho->linkList = ho->md5list = NULL;
+    ho->uids = ho->gids = ho->mtimes = ho->fileSizes = NULL;
+    ho->modes = ho->rdevs = NULL;
+    
+    return (PyObject *) ho;
 }
 
-/* methods for rpmdb object */
+/** \ingroup python
+ */
+static struct PyMethodDef rpmdbMIMethods[] = {
+       {"next",            (PyCFunction) rpmdbMINext,  1 },
+       {NULL,          NULL}           /* sentinel */
+};
 
-static PyObject * rpmdbGetAttr(rpmdbObject * s, char * name) {
-    return Py_FindMethod(rpmdbMethods, (PyObject * ) s, name);
+/** \ingroup python
+ */
+static PyObject * rpmdbMIGetAttr (rpmdbObject *s, char *name) {
+    return Py_FindMethod (rpmdbMIMethods, (PyObject *) s, name);
 }
 
-static void rpmdbDealloc(rpmdbObject * s) {
-    if (s->offsets) {
-       free(s->offsets);
-    }
-    if (s->db) {
-       rpmdbClose(s->db);
+/** \ingroup python
+ */
+static void rpmdbMIDealloc(rpmdbMIObject * s) {
+    if (s && s->mi) {
+       rpmdbFreeIterator(s->mi);
     }
+    Py_DECREF (s->db);
     PyMem_DEL(s);
 }
 
+/** \ingroup python
+ */
+static PyTypeObject rpmdbMIType = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,                              /* ob_size */
+       "rpmdbMatchIterator",           /* tp_name */
+       sizeof(rpmdbMIObject),  /* tp_size */
+       0,                              /* tp_itemsize */
+       (destructor) rpmdbMIDealloc,    /* tp_dealloc */
+       0,                              /* tp_print */
+       (getattrfunc) rpmdbMIGetAttr,   /* tp_getattr */
+       0,                              /* tp_setattr */
+       0,                              /* tp_compare */
+       0,                              /* tp_repr */
+       0,                              /* tp_as_number */
+       0,                              /* tp_as_sequence */
+       0,                              /* tp_as_mapping */
+};
+
+/*@}*/
+
+/** \ingroup python
+ * \class rpmdb
+ * \brief A python rpmdb object represents an RPM database.
+ * 
+ * Instances of the rpmdb object provide access to the records of a
+ * RPM database.  The records are accessed by index number.  To
+ * retrieve the header data in the RPM database, the rpmdb object is
+ * subscripted as you would access members of a list.
+ * 
+ * The rpmdb class contains the following methods:
+ * 
+ * - firstkey()        Returns the index of the first record in the database.
+ * @deprecated Legacy, use rpmdbMatchIterator instead.
+ * 
+ * - nextkey(index) Returns the index of the next record after "index" in the
+ *             database.
+ * @param index        current rpmdb location
+ * @deprecated Legacy, use rpmdbMatchIterator instead.
+ * 
+ * - findbyfile(file) Returns a list of the indexes to records that own file
+ *             "file".
+ * @param file absolute path to file
+ * 
+ * - findbyname(name) Returns a list of the indexes to records for packages
+ *             named "name".
+ * @param name package name
+ * 
+ * - findbyprovides(dep) Returns a list of the indexes to records for packages
+ *             that provide "dep".
+ * @param dep  provided dependency string
+ * 
+ * To obtain a rpmdb object, the opendb function in the rpm module
+ * must be called.  The opendb function takes two optional arguments.
+ * The first optional argument is a boolean flag that specifies if the
+ * database is to be opened for read/write access or read-only access.
+ * The second argument specifies an alternate root directory for RPM
+ * to use.
+ * 
+ * An example of opening a database and retrieving the first header in
+ * the database, then printing the name of the package that the header
+ * represents:
+ * \code
+ *     import rpm
+ *     rpmdb = rpm.opendb()
+ *     index = rpmdb.firstkey()
+ *     header = rpmdb[index]
+ *     print header[rpm.RPMTAG_NAME]
+ * \endcode
+ * To print all of the packages in the database that match a package
+ * name, the code will look like this:
+ * \code
+ *     import rpm
+ *     rpmdb = rpm.opendb()
+ *     indexes = rpmdb.findbyname("foo")
+ *     for index in indexes:
+ *         header = rpmdb[index]
+ *         print "%s-%s-%s" % (header[rpm.RPMTAG_NAME],
+ *                             header[rpm.RPMTAG_VERSION],
+ *                             header[rpm.RPMTAG_RELEASE])
+ * \endcode
+ */
+
+/** \ingroup python
+ * \name Class: rpmdb
+ */
+/*@{*/
+
+/** \ingroup python
+ */
 static PyObject * rpmdbFirst(rpmdbObject * s, PyObject * args) {
     int first;
 
@@ -891,6 +852,8 @@ static PyObject * rpmdbFirst(rpmdbObject * s, PyObject * args) {
     return Py_BuildValue("i", first);
 }
 
+/** \ingroup python
+ */
 static PyObject * rpmdbNext(rpmdbObject * s, PyObject * args) {
     int where;
 
@@ -911,6 +874,8 @@ static PyObject * rpmdbNext(rpmdbObject * s, PyObject * args) {
     return Py_BuildValue("i", where);
 }
 
+/** \ingroup python
+ */
 static PyObject * handleDbResult(rpmdbMatchIterator mi) {
     PyObject * list, *o;
 
@@ -928,22 +893,28 @@ static PyObject * handleDbResult(rpmdbMatchIterator mi) {
     return list;
 }
 
-static PyObject * rpmdbByName(rpmdbObject * s, PyObject * args) {
+/** \ingroup python
+ */
+static PyObject * rpmdbByFile(rpmdbObject * s, PyObject * args) {
     char * str;
 
     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
 
-    return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_NAME, str, 0));
+    return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_BASENAMES, str, 0));
 }
 
-static PyObject * rpmdbByFile(rpmdbObject * s, PyObject * args) {
+/** \ingroup python
+ */
+static PyObject * rpmdbByName(rpmdbObject * s, PyObject * args) {
     char * str;
 
     if (!PyArg_ParseTuple(args, "s", &str)) return NULL;
 
-    return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_BASENAMES, str, 0));
+    return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_NAME, str, 0));
 }
 
+/** \ingroup python
+ */
 static PyObject * rpmdbByProvides(rpmdbObject * s, PyObject * args) {
     char * str;
 
@@ -952,6 +923,71 @@ static PyObject * rpmdbByProvides(rpmdbObject * s, PyObject * args) {
     return handleDbResult(rpmdbInitIterator(s->db, RPMTAG_PROVIDENAME, str, 0));
 }
 
+/** \ingroup python
+ */
+static rpmdbMIObject *
+py_rpmdbInitIterator (rpmdbObject * s, PyObject * args) {
+    PyObject *index = NULL;
+    char *key = NULL;
+    int len = 0, tag = -1;
+    rpmdbMIObject * mio;
+    
+    if (!PyArg_ParseTuple(args, "|Ozi", &index, &key, &len))
+       return NULL;
+
+    if (index == NULL)
+       tag = 0;
+    else if ((tag = tagNumFromPyObject (index)) == -1) {
+       PyErr_SetString(PyExc_TypeError, "unknown tag type");
+       return NULL;
+    }
+    
+    mio = (rpmdbMIObject *) PyObject_NEW(rpmdbMIObject, &rpmdbMIType);
+    if (mio == NULL) {
+       PyErr_SetString(pyrpmError, "out of memory creating rpmdbMIObject");
+       return NULL;
+    }
+    
+    mio->mi = rpmdbInitIterator(s->db, tag, key, len);
+    mio->db = s;
+    Py_INCREF (mio->db);
+    
+    return mio;
+}
+
+/** \ingroup python
+ */
+static struct PyMethodDef rpmdbMethods[] = {
+       {"firstkey",        (PyCFunction) rpmdbFirst,   1 },
+       {"nextkey",         (PyCFunction) rpmdbNext,    1 },
+       {"findbyfile",      (PyCFunction) rpmdbByFile, 1 },
+       {"findbyname",      (PyCFunction) rpmdbByName, 1 },
+       {"findbyprovides",  (PyCFunction) rpmdbByProvides, 1 },
+       {"match",           (PyCFunction) py_rpmdbInitIterator, 1 },
+       {NULL,          NULL}           /* sentinel */
+};
+
+/** \ingroup python
+ */
+static PyObject * rpmdbGetAttr(rpmdbObject * s, char * name) {
+    return Py_FindMethod(rpmdbMethods, (PyObject * ) s, name);
+}
+
+/** \ingroup python
+ */
+static void rpmdbDealloc(rpmdbObject * s) {
+    if (s->offsets) {
+       free(s->offsets);
+    }
+    if (s->db) {
+       rpmdbClose(s->db);
+    }
+    PyMem_DEL(s);
+}
+
+#ifndef DYINGSOON
+/** \ingroup python
+ */
 static int
 rpmdbLength(rpmdbObject * s) {
     int count = 0;
@@ -969,6 +1005,8 @@ rpmdbLength(rpmdbObject * s) {
     return count;
 }
 
+/** \ingroup python
+ */
 static hdrObject *
 rpmdbSubscript(rpmdbObject * s, PyObject * key) {
     int offset;
@@ -1002,849 +1040,1039 @@ rpmdbSubscript(rpmdbObject * s, PyObject * key) {
     return h;
 }
 
-static rpmdbMIObject *
-py_rpmdbInitIterator (rpmdbObject * s, PyObject * args) {
-    PyObject *index = NULL;
-    char *key = NULL;
-    int len = 0, tag = -1;
-    rpmdbMIObject * mio;
-    
-    if (!PyArg_ParseTuple(args, "|Ozi", &index, &key, &len))
-       return NULL;
-
-    if (index == NULL)
-       tag = 0;
-    else if ((tag = tagNumFromPyObject (index)) == -1) {
-       PyErr_SetString(PyExc_TypeError, "unknown tag type");
-       return NULL;
-    }
-    
-    mio = (rpmdbMIObject *) PyObject_NEW(rpmdbMIObject, &rpmdbMIType);
-    if (mio == NULL) {
-       PyErr_SetString(pyrpmError, "out of memory creating rpmdbMIObject");
-       return NULL;
-    }
-    
-    mio->mi = rpmdbInitIterator(s->db, tag, key, len);
-    mio->db = s;
-    Py_INCREF (mio->db);
-    
-    return mio;
-}
-
-static PyObject *
-rpmdbMINext(rpmdbMIObject * s, PyObject * args) {
-    /* XXX assume header? */
-    Header h;
-    hdrObject * ho;
-    
-
-    h = rpmdbNextIterator(s->mi);
-    if (!h) {
-       Py_INCREF(Py_None);
-       return Py_None;
-    }
-
-    ho = PyObject_NEW(hdrObject, &hdrType);
-    ho->h = headerLink(h);
-    ho->sigs = NULL;
-    ho->fileList = ho->linkList = ho->md5list = NULL;
-    ho->uids = ho->gids = ho->mtimes = ho->fileSizes = NULL;
-    ho->modes = ho->rdevs = NULL;
-    
-    return (PyObject *) ho;
-}
-
-/* methods for rpmdbMatchIterator object */
-static void rpmdbMIDealloc(rpmdbMIObject * s) {
-    if (s && s->mi) {
-       rpmdbFreeIterator(s->mi);
-    }
-    Py_DECREF (s->db);
-    PyMem_DEL(s);
-}
-
-static PyObject * rpmdbMIGetAttr (rpmdbObject *s, char *name) {
-    return Py_FindMethod (rpmdbMIMethods, (PyObject *) s, name);
-}
-
-/* methods for header object */
-
-static void hdrDealloc(hdrObject * s) {
-    if (s->h) headerFree(s->h);
-    if (s->sigs) headerFree(s->sigs);
-    if (s->md5list) free(s->md5list);
-    if (s->fileList) free(s->fileList);
-    if (s->linkList) free(s->linkList);
-    PyMem_DEL(s);
-}
-
-static PyObject * hdrGetAttr(hdrObject * s, char * name) {
-    return Py_FindMethod(hdrMethods, (PyObject * ) s, name);
-}
-
-static long tagNumFromPyObject (PyObject *item)
-{
-    char * str;
-    int i;
-
-    if (PyInt_Check(item)) {
-       return PyInt_AsLong(item);
-    } else if (PyString_Check(item)) {
-       str = PyString_AsString(item);
-       for (i = 0; i < rpmTagTableSize; i++)
-           if (!xstrcasecmp(rpmTagTable[i].name + 7, str)) break;
-       if (i < rpmTagTableSize) return rpmTagTable[i].val;
-    }
-    return -1;
-}
-
-static PyObject * hdrSubscript(hdrObject * s, PyObject * item) {
-    int type, count, i, tag = -1;
-    void * data;
-    PyObject * o, * metao;
-    char ** stringArray;
-    int forceArray = 0;
-    int freeData = 0;
-    char * str;
-    struct headerSprintfExtension * ext = NULL;
-    const struct headerSprintfExtension * extensions = rpmHeaderFormats;
-
-    if (PyCObject_Check (item))
-        ext = PyCObject_AsVoidPtr(item);
-    else
-       tag = tagNumFromPyObject (item);
-    if (tag == -1 && PyString_Check(item)) {
-       /* if we still don't have the tag, go looking for the header
-          extensions */
-       str = PyString_AsString(item);
-       while (extensions->name) {
-           if (extensions->type == HEADER_EXT_TAG
-               && !xstrcasecmp(extensions->name + 7, str)) {
-               (const struct headerSprintfExtension *) ext = extensions;
-           }
-           extensions++;
-       }
-    }
-
-    if (ext) {
-        ext->u.tagFunction(s->h, &type, (const void **) &data, &count, &freeData);
-    } else {
-        if (tag == -1) {
-            PyErr_SetString(PyExc_KeyError, "unknown header tag");
-            return NULL;
-        }
-        
-        if (!rpmPackageGetEntry(NULL, s->sigs, s->h, tag, &type, &data, &count))
-       {
-            Py_INCREF(Py_None);
-            return Py_None;
-        }
-    }
+/** \ingroup python
+ */
+static PyMappingMethods rpmdbAsMapping = {
+       (inquiry) rpmdbLength,          /* mp_length */
+       (binaryfunc) rpmdbSubscript,    /* mp_subscript */
+       (objobjargproc)0,               /* mp_ass_subscript */
+};
+#endif
 
-    switch (tag) {
-      case RPMTAG_OLDFILENAMES:
-      case RPMTAG_FILESIZES:
-      case RPMTAG_FILESTATES:
-      case RPMTAG_FILEMODES:
-      case RPMTAG_FILEUIDS:
-      case RPMTAG_FILEGIDS:
-      case RPMTAG_FILERDEVS:
-      case RPMTAG_FILEMTIMES:
-      case RPMTAG_FILEMD5S:
-      case RPMTAG_FILELINKTOS:
-      case RPMTAG_FILEFLAGS:
-      case RPMTAG_ROOT:
-      case RPMTAG_FILEUSERNAME:
-      case RPMTAG_FILEGROUPNAME:
-       forceArray = 1;
-       break;
-      case RPMTAG_SUMMARY:
-      case RPMTAG_GROUP:
-      case RPMTAG_DESCRIPTION:
-       freeData = 1;
-       break;
-      default:
-        break;
-    }
+/** \ingroup python
+ */
+static PyTypeObject rpmdbType = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,                              /* ob_size */
+       "rpmdb",                        /* tp_name */
+       sizeof(rpmdbObject),            /* tp_size */
+       0,                              /* tp_itemsize */
+       (destructor) rpmdbDealloc,      /* tp_dealloc */
+       0,                              /* tp_print */
+       (getattrfunc) rpmdbGetAttr,     /* tp_getattr */
+       0,                              /* tp_setattr */
+       0,                              /* tp_compare */
+       0,                              /* tp_repr */
+       0,                              /* tp_as_number */
+       0,                              /* tp_as_sequence */
+#ifndef DYINGSOON
+       &rpmdbAsMapping,                /* tp_as_mapping */
+#else
+       0,
+#endif
+};
 
-    switch (type) {
-      case RPM_BIN_TYPE:
-       o = PyString_FromStringAndSize(data, count);
-       break;
+/*@}*/
+
+/** \ingroup python
+ * \name Class: rpmtrans
+ * \class rpmtrans
+ * \brief A python rpmtrans object represents an RPM transaction set.
+ * 
+ * The transaction set is the workhorse of RPM.  It performs the
+ * installation and upgrade of packages.  The rpmtrans object is
+ * instantiated by the TransactionSet function in the rpm module.
+ *
+ * The TransactionSet function takes two optional arguments.  The first
+ * argument is the root path, the second is an open database to perform
+ * the transaction set upon.
+ *
+ * A rpmtrans object has the following methods:
+ *
+ * - add(header,data,mode)     Add a binary package to a transaction set.
+ * @param header the header to be added
+ * @param data user data that will be passed to the transaction callback
+ *             during transaction execution
+ * @param mode         optional argument that specifies if this package should
+ *             be installed ('i'), upgraded ('u'), or if it is just
+ *             available to the transaction when computing
+ *             dependencies but no action should be performed with it
+ *             ('a').
+ *
+ * - remove
+ *
+ * - depcheck()        Perform a dependency and conflict check on the
+ *             transaction set. After headers have been added to a
+ *             transaction set, a dependency check can be performed
+ *             to make sure that all package dependencies are
+ *             satisfied.
+ * @return     None If there are no unresolved dependencies
+ *             Otherwise a list of complex tuples is returned, one tuple per
+ *             unresolved dependency, with
+ * The format of the dependency tuple is:
+ *     ((packageName, packageVersion, packageRelease),
+ *      (reqName, reqVersion),
+ *      needsFlags,
+ *      suggestedPackage,
+ *      sense)
+ *     packageName, packageVersion, packageRelease are the name,
+ *     version, and release of the package that has the unresolved
+ *     dependency or conflict.
+ *     The reqName and reqVersion are the name and version of the
+ *     requirement or conflict.
+ *     The needsFlags is a bitfield that describes the versioned
+ *     nature of a requirement or conflict.  The constants
+ *     rpm.RPMDEP_SENSE_LESS, rpm.RPMDEP_SENSE_GREATER, and
+ *     rpm.RPMDEP_SENSE_EQUAL can be logical ANDed with the needsFlags
+ *     to get versioned dependency information.
+ *     suggestedPackage is a tuple if the dependency check was aware
+ *     of a package that solves this dependency problem when the
+ *     dependency check was run.  Packages that are added to the
+ *     transaction set as "available" are examined during the
+ *     dependency check as possible dependency solvers. The tuple
+ *     contains two values, (header, suggestedName).  These are set to
+ *     the header of the suggested package and its name, respectively.
+ *     If there is no known package to solve the dependency problem,
+ *     suggestedPackage is None.
+ *     The constants rpm.RPMDEP_SENSE_CONFLICTS and
+ *     rpm.RPMDEP_SENSE_REQUIRES are set to show a dependency as a
+ *     requirement or a conflict.
+ *
+ * - run(flags,problemSetFilter,callback,data) Attempt to execute a
+ *     transaction set. After the transaction set has been populated
+ *     with install and upgrade actions, it can be executed by invoking
+ *     the run() method.
+ * @param flags - modifies the behavior of the transaction set as it is
+ *             processed.  The following values can be locical ORed
+ *             together:
+ *     - rpm.RPMTRANS_FLAG_TEST - test mode, do not modify the RPM
+ *             database, change any files, or run any package scripts
+ *     - rpm.RPMTRANS_FLAG_BUILD_PROBS - only build a list of
+ *             problems encountered when attempting to run this transaction
+ *             set
+ *     - rpm.RPMTRANS_FLAG_NOSCRIPTS - do not execute package scripts
+ *     - rpm.RPMTRANS_FLAG_JUSTDB - only make changes to the rpm
+ *             database, do not modify files.
+ *     - rpm.RPMTRANS_FLAG_NOTRIGGERS - do not run trigger scripts
+ *     - rpm.RPMTRANS_FLAG_NODOCS - do not install files marked as %doc
+ *     - rpm.RPMTRANS_FLAG_ALLFILES - create all files, even if a
+ *             file is marked %config(missingok) and an upgrade is
+ *             being performed.
+ *     - rpm.RPMTRANS_FLAG_KEEPOBSOLETE - do not remove obsoleted
+ *             packages.
+ * @param problemSetFilter - control bit(s) to ignore classes of problems,
+ *             any of
+ *     - rpm.RPMPROB_FILTER_IGNOREOS - 
+ *     - rpm.RPMPROB_FILTER_IGNOREARCH - 
+ *     - rpm.RPMPROB_FILTER_REPLACEPKG - 
+ *     - rpm.RPMPROB_FILTER_FORCERELOCATE - 
+ *     - rpm.RPMPROB_FILTER_REPLACENEWFILES - 
+ *     - rpm.RPMPROB_FILTER_REPLACEOLDFILES - 
+ *     - rpm.RPMPROB_FILTER_OLDPACKAGE - 
+ *     - rpm.RPMPROB_FILTER_DISKSPACE - 
+ */
+
+/** \ingroup python
+ * \name Class: rpmtrans
+ */
+/*@{*/
+
+/** \ingroup python
+ */
+struct rpmtransObject_s {
+    PyObject_HEAD;
+    rpmdbObject * dbo;
+    rpmTransactionSet ts;
+    PyObject * keyList;                        /* keeps reference counts correct */
+    FD_t scriptFd;
+} ;
 
-      case RPM_INT32_TYPE:
-       if (count != 1 || forceArray) {
-           metao = PyList_New(0);
-           for (i = 0; i < count; i++) {
-               o = PyInt_FromLong(((int *) data)[i]);
-               PyList_Append(metao, o);
-               Py_DECREF(o);
-           }
-           o = metao;
-       } else {
-           o = PyInt_FromLong(*((int *) data));
-       }
-       break;
+/** \ingroup python
+ */
+static PyObject * rpmtransAdd(rpmtransObject * s, PyObject * args) {
+    hdrObject * h;
+    PyObject * key;
+    char * how = NULL;
+    int isUpgrade = 0;
 
-      case RPM_CHAR_TYPE:
-      case RPM_INT8_TYPE:
-       if (count != 1 || forceArray) {
-           metao = PyList_New(0);
-           for (i = 0; i < count; i++) {
-               o = PyInt_FromLong(((char *) data)[i]);
-               PyList_Append(metao, o);
-               Py_DECREF(o);
-           }
-           o = metao;
-       } else {
-           o = PyInt_FromLong(*((char *) data));
-       }
-       break;
+    if (!PyArg_ParseTuple(args, "OO|s", &h, &key, &how)) return NULL;
+    if (h->ob_type != &hdrType) {
+       PyErr_SetString(PyExc_TypeError, "bad type for header argument");
+       return NULL;
+    }
 
-      case RPM_INT16_TYPE:
-       if (count != 1 || forceArray) {
-           metao = PyList_New(0);
-           for (i = 0; i < count; i++) {
-               o = PyInt_FromLong(((short *) data)[i]);
-               PyList_Append(metao, o);
-               Py_DECREF(o);
-           }
-           o = metao;
-       } else {
-           o = PyInt_FromLong(*((short *) data));
-       }
-       break;
+    if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
+       PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
+       return NULL;
+    } else if (how && !strcmp(how, "u"))
+       isUpgrade = 1;
 
-      case RPM_STRING_ARRAY_TYPE:
-       stringArray = data;
+    if (how && !strcmp(how, "a"))
+       rpmtransAvailablePackage(s->ts, h->h, key);
+    else
+       rpmtransAddPackage(s->ts, h->h, NULL, key, isUpgrade, NULL);
 
-       metao = PyList_New(0);
-       for (i = 0; i < count; i++) {
-           o = PyString_FromString(stringArray[i]);
-           PyList_Append(metao, o);
-           Py_DECREF(o);
-       }
-       free (stringArray);
-       o = metao;
-       break;
+    /* This should increment the usage count for me */
+    if (key) {
+       PyList_Append(s->keyList, key);
+    }
 
-      case RPM_STRING_TYPE:
-       if (count != 1 || forceArray) {
-           stringArray = data;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
-           metao = PyList_New(0);
-           for (i=0; i < count; i++) {
-               o = PyString_FromString(stringArray[i]);
-               PyList_Append(metao, o);
-               Py_DECREF(o);
+/** \ingroup python
+ */
+static PyObject * rpmtransRemove(rpmtransObject * s, PyObject * args) {
+    char * name;
+    int count;
+    rpmdbMatchIterator mi;
+    
+    if (!PyArg_ParseTuple(args, "s", &name))
+        return NULL;
+
+    /* XXX: Copied hack from ../lib/rpminstall.c, rpmErase() */
+    mi = rpmdbInitIterator(s->dbo->db, RPMDBI_LABEL, name, 0);
+    count = rpmdbGetIteratorCount(mi);
+    if (count <= 0) {
+        PyErr_SetString(pyrpmError, "package not installed");
+        return NULL;
+    } else { /* XXX: Note that we automatically choose to remove all matches */
+        Header h;
+        while ((h = rpmdbNextIterator(mi)) != NULL) {
+           unsigned int recOffset = rpmdbGetIteratorOffset(mi);
+           if (recOffset) {
+               rpmtransRemovePackage(s->ts, recOffset);
            }
-           o = metao;
-       } else {
-           o = PyString_FromString(data);
-           if (freeData)
-               free (data);
        }
-       break;
-
-      default:
-       PyErr_SetString(PyExc_TypeError, "unsupported type in header");
-       return NULL;
     }
+    rpmdbFreeIterator(mi);
 
-    return o;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
-static PyObject * hdrKeyList(hdrObject * s, PyObject * args) {
-    PyObject * list, *o;
-    HeaderIterator iter;
-    int tag, type;
+/** \ingroup python
+ */
+static PyObject * rpmtransDepCheck(rpmtransObject * s, PyObject * args) {
+    struct rpmDependencyConflict * conflicts;
+    int numConflicts;
+    PyObject * list, * cf;
+    int i;
 
     if (!PyArg_ParseTuple(args, "")) return NULL;
 
-    list = PyList_New(0);
+    rpmdepCheck(s->ts, &conflicts, &numConflicts);
+    if (numConflicts) {
+       list = PyList_New(0);
 
-    iter = headerInitIterator(s->h);
-    while (headerNextIterator(iter, &tag, &type, NULL, NULL)) {
-        if (tag == HEADER_I18NTABLE) continue;
+       for (i = 0; i < numConflicts; i++) {
+           cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
+                              conflicts[i].byVersion, conflicts[i].byRelease,
 
-       switch (type) {
-         case RPM_BIN_TYPE:
-         case RPM_INT32_TYPE:
-         case RPM_CHAR_TYPE:
-         case RPM_INT8_TYPE:
-         case RPM_INT16_TYPE:
-         case RPM_STRING_ARRAY_TYPE:
-         case RPM_STRING_TYPE:
-           PyList_Append(list, o=PyInt_FromLong(tag));
-           Py_DECREF(o);
+                              conflicts[i].needsName,
+                              conflicts[i].needsVersion,
+
+                              conflicts[i].needsFlags,
+                              conflicts[i].suggestedPackage ?
+                                  conflicts[i].suggestedPackage : Py_None,
+                              conflicts[i].sense);
+           PyList_Append(list, (PyObject *) cf);
+           Py_DECREF(cf);
        }
+
+       rpmdepFreeConflicts(conflicts, numConflicts);
+
+       return list;
     }
 
-    headerFreeIterator(iter);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
-    return list;
+/** \ingroup python
+ */
+static PyObject * rpmtransOrder(rpmtransObject * s, PyObject * args) {
+    if (!PyArg_ParseTuple(args, "")) return NULL;
+
+    rpmdepOrder(s->ts);
+
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
-static PyObject * hdrUnload(hdrObject * s, PyObject * args) {
-    char * buf;
-    int len;
-    PyObject * rc;
+/** \ingroup python
+ */
+static PyObject * py_rpmtransGetKeys(rpmtransObject * s, PyObject * args) {
+    const void **data = NULL;
+    int num, i;
+    PyObject *tuple;
 
-    len = headerSizeof(s->h, 0);
-    buf = headerUnload(s->h);
+    rpmtransGetKeys(s->ts, &data, &num);
+    if (data == NULL) {
+       Py_INCREF(Py_None);
+       return Py_None;
+    }
 
-    rc = PyString_FromStringAndSize(buf, len);
-    free(buf);
+    tuple = PyTuple_New(num);
 
-    return rc;
+    for (i = 0; i < num; i++) {
+       PyObject *obj = (PyObject *) data[i];
+       Py_INCREF(obj);
+       PyTuple_SetItem(tuple, i, obj);
+    }
+
+    free (data);
+
+    return tuple;
 }
 
-/* Returns a list of these tuple for each part which failed:
+/** \ingroup python
+ */
+struct tsCallbackType {
+    PyObject * cb;
+    PyObject * data;
+    int pythonError;
+};
 
-       (attr_name, correctValue, currentValue)
+/** \ingroup python
+ */
+static Header transactionSetHeader = NULL;
 
-       It should be passwd the file number to verify.
-*/
-static PyObject * hdrVerifyFile(hdrObject * s, PyObject * args) {
-    int fileNumber;
-    rpmVerifyAttrs verifyResult = 0;
-    PyObject * list, * tuple, * attrName;
-    int type, count;
-    struct stat sb;
-    char buf[2048];
-    int i;
-    time_t timeInt;
-    struct tm * timeStruct;
+/** \ingroup python
+ */
+static void * tsCallback(const void * hd, const rpmCallbackType what,
+                        const unsigned long amount, const unsigned long total,
+                        const void * pkgKey, rpmCallbackData data) {
+    struct tsCallbackType * cbInfo = data;
+    PyObject * args, * result;
+    int fd;
+    static FD_t fdt;
+    const Header h = (Header) hd;
 
-    if (!PyInt_Check(args)) {
-       PyErr_SetString(PyExc_TypeError, "integer expected");
+    if (cbInfo->pythonError) return NULL;
+
+    if (!pkgKey) pkgKey = Py_None;
+    transactionSetHeader = h;    
+
+    args = Py_BuildValue("(illOO)", what, amount, total, pkgKey, cbInfo->data);
+    result = PyEval_CallObject(cbInfo->cb, args);
+    Py_DECREF(args);
+
+    if (!result) {
+       cbInfo->pythonError = 1;
        return NULL;
     }
 
-    fileNumber = (int) PyInt_AsLong(args);
-
-    if (rpmVerifyFile("", s->h, fileNumber, &verifyResult, RPMVERIFY_NONE)) {
-       Py_INCREF(Py_None);
-       return Py_None;
+    if (what == RPMCALLBACK_INST_OPEN_FILE) {
+        if (!PyArg_Parse(result, "i", &fd)) {
+           cbInfo->pythonError = 1;
+           return NULL;
+       }
+       fdt = fdDup(fd);
+       
+       Py_DECREF(result);
+       return fdt;
     }
 
-    list = PyList_New(0);
-
-    if (!verifyResult) return list;
-
-    if (!s->fileList) {
-       headerGetEntry(s->h, RPMTAG_OLDFILENAMES, &type, (void **) &s->fileList,
-                &count);
+    if (what == RPMCALLBACK_INST_CLOSE_FILE) {
+       Fclose (fdt);
     }
 
-    lstat(s->fileList[fileNumber], &sb);
-
-    if (verifyResult & RPMVERIFY_MD5) {
-       if (!s->md5list) {
-           headerGetEntry(s->h, RPMTAG_FILEMD5S, &type, (void **) &s->md5list,
-                    &count);
-       }
+    Py_DECREF(result);
 
-       if (mdfile(s->fileList[fileNumber], buf)) {
-           strcpy(buf, "(unknown)");
-       }
+    return NULL;
+}
 
-       tuple = PyTuple_New(3);
-       attrName = PyString_FromString("checksum");
-       PyTuple_SetItem(tuple, 0, attrName);
-       PyTuple_SetItem(tuple, 1, PyString_FromString(s->md5list[fileNumber]));
-       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
-       PyList_Append(list, tuple);
-       Py_DECREF(tuple);
-    }
+/** \ingroup python
+ */
+static PyObject * rpmtransRun(rpmtransObject * s, PyObject * args) {
+    int flags, ignoreSet;
+    int rc, i;
+    PyObject * list, * prob;
+    rpmProblemSet probs;
+    struct tsCallbackType cbInfo;
 
-    if (verifyResult & RPMVERIFY_FILESIZE) {
-       if (!s->fileSizes) {
-           headerGetEntry(s->h, RPMTAG_FILESIZES, &type, (void **) &s->fileSizes,
-                    &count);
+    if (!PyArg_ParseTuple(args, "iiOO", &flags, &ignoreSet, &cbInfo.cb,
+                         &cbInfo.data))
+       return NULL;
 
-       }
+    cbInfo.pythonError = 0;
 
-       tuple = PyTuple_New(3);
-       attrName = PyString_FromString("size");
-       PyTuple_SetItem(tuple, 0, attrName);
+    rc = rpmRunTransactions(s->ts, tsCallback, &cbInfo, NULL, &probs, flags,
+                           ignoreSet);
 
-       sprintf(buf, "%d", 100);
-       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
-       sprintf(buf, "%ld", sb.st_size);
-       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
-       PyList_Append(list, tuple);
-       Py_DECREF(tuple);
+    if (cbInfo.pythonError) {
+       if (rc > 0)
+           rpmProblemSetFree(probs);
+       return NULL;
     }
 
-    if (verifyResult & RPMVERIFY_LINKTO) {
-       if (!s->linkList) {
-           headerGetEntry(s->h, RPMTAG_FILELINKTOS, &type, (void **) &s->linkList,
-                    &count);
-       }
-
-       i = readlink(s->fileList[fileNumber], buf, sizeof(buf));
-       if (i <= 0)
-           strcpy(buf, "(unknown)");
-       else
-           buf[i] = '\0';
+    if (rc < 0) {
+       list = PyList_New(0);
+       return list;
+    } else if (!rc) {
+       Py_INCREF(Py_None);
+       return Py_None;
+    }
 
-       tuple = PyTuple_New(3);
-       attrName = PyString_FromString("link");
-       PyTuple_SetItem(tuple, 0, attrName);
-       PyTuple_SetItem(tuple, 1, PyString_FromString(s->linkList[fileNumber]));
-       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
-       PyList_Append(list, tuple);
-       Py_DECREF(tuple);
+    list = PyList_New(0);
+    for (i = 0; i < probs->numProblems; i++) {
+       rpmProblem myprob = probs->probs + i;
+       prob = Py_BuildValue("s(isi)", rpmProblemString(myprob),
+                            myprob->type,
+                            myprob->str1,
+                            myprob->ulong1);
+       PyList_Append(list, prob);
+       Py_DECREF(prob);
     }
 
-    if (verifyResult & RPMVERIFY_MTIME) {
-       if (!s->mtimes) {
-           headerGetEntry(s->h, RPMTAG_FILEMTIMES, &type, (void **) &s->mtimes,
-                    &count);
-       }
+    rpmProblemSetFree(probs);
 
-       tuple = PyTuple_New(3);
-       attrName = PyString_FromString("time");
-       PyTuple_SetItem(tuple, 0, attrName);
+    return list;
+}
 
-       timeInt = sb.st_mtime;
-       timeStruct = localtime(&timeInt);
-       strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
-       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
+/** \ingroup python
+ */
+static struct PyMethodDef rpmtransMethods[] = {
+       {"add",         (PyCFunction) rpmtransAdd,      1 },
+       {"remove",      (PyCFunction) rpmtransRemove,   1 },
+       {"depcheck",    (PyCFunction) rpmtransDepCheck, 1 },
+       {"order",       (PyCFunction) rpmtransOrder,    1 },
+       {"getKeys",     (PyCFunction) py_rpmtransGetKeys, 1 },
+       {"run",         (PyCFunction) rpmtransRun, 1 },
+       {NULL,          NULL}           /* sentinel */
+};
 
-       timeInt = s->mtimes[fileNumber];
-       timeStruct = localtime(&timeInt);
-       strftime(buf, sizeof(buf) - 1, "%c", timeStruct);
+/** \ingroup python
+ */
+static PyObject * rpmtransGetAttr(rpmtransObject * o, char * name) {
+    return Py_FindMethod(rpmtransMethods, (PyObject *) o, name);
+}
 
-       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
+/** \ingroup python
+ */
+static void rpmtransDealloc(PyObject * o) {
+    rpmtransObject * trans = (void *) o;
 
-       PyList_Append(list, tuple);
-       Py_DECREF(tuple);
+    rpmtransFree(trans->ts);
+    if (trans->dbo) {
+       Py_DECREF(trans->dbo);
     }
+    if (trans->scriptFd) Fclose(trans->scriptFd);
+    /* this will free the keyList, and decrement the ref count of all
+       the items on the list as well :-) */
+    Py_DECREF(trans->keyList);
+    PyMem_DEL(o);
+}
 
-    if (verifyResult & RPMVERIFY_RDEV) {
-       if (!s->rdevs) {
-           headerGetEntry(s->h, RPMTAG_FILERDEVS, &type, (void **) &s->rdevs,
-                    &count);
+/** \ingroup python
+ */
+static int rpmtransSetAttr(rpmtransObject * o, char * name,
+                          PyObject * val) {
+    int i;
+
+    if (!strcmp(name, "scriptFd")) {
+       if (!PyArg_Parse(val, "i", &i)) return 0;
+       if (i < 0) {
+           PyErr_SetString(PyExc_TypeError, "bad file descriptor");
+           return -1;
+       } else {
+           o->scriptFd = fdDup(i);
+           rpmtransSetScriptFd(o->ts, o->scriptFd);
        }
+    } else {
+       PyErr_SetString(PyExc_AttributeError, name);
+       return -1;
+    }
 
-       tuple = PyTuple_New(3);
-       attrName = PyString_FromString("device");
+    return 0;
+}
 
-       PyTuple_SetItem(tuple, 0, attrName);
-       sprintf(buf, "0x%-4x", s->rdevs[fileNumber]);
-       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
-       sprintf(buf, "0x%-4x", (unsigned int) sb.st_rdev);
-       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
-       PyList_Append(list, tuple);
-       Py_DECREF(tuple);
-    }
+/** \ingroup python
+ */
+static PyTypeObject rpmtransType = {
+       PyObject_HEAD_INIT(&PyType_Type)
+       0,                              /* ob_size */
+       "rpmtrans",                     /* tp_name */
+       sizeof(rpmtransObject),         /* tp_size */
+       0,                              /* tp_itemsize */
+       (destructor) rpmtransDealloc,   /* tp_dealloc */
+       0,                              /* tp_print */
+       (getattrfunc) rpmtransGetAttr,  /* tp_getattr */
+       (setattrfunc) rpmtransSetAttr,  /* tp_setattr */
+       0,                              /* tp_compare */
+       0,                              /* tp_repr */
+       0,                              /* tp_as_number */
+       0,                              /* tp_as_sequence */
+       0,                              /* tp_as_mapping */
+};
 
-    /* RPMVERIFY_USER and RPM_VERIFY_GROUP are handled wrong here, but rpmlib.a
-       doesn't do these correctly either. At least this is consisten */
-    if (verifyResult & RPMVERIFY_USER) {
-       if (!s->uids) {
-           headerGetEntry(s->h, RPMTAG_FILEUIDS, &type, (void **) &s->uids,
-                    &count);
-       }
+/*@}*/
 
-       tuple = PyTuple_New(3);
-       attrName = PyString_FromString("uid");
-       PyTuple_SetItem(tuple, 0, attrName);
-       sprintf(buf, "%d", s->uids[fileNumber]);
-       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
-       sprintf(buf, "%d", sb.st_uid);
-       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
-       PyList_Append(list, tuple);
-       Py_DECREF(tuple);
-    }
+/** \ingroup python
+ * \name Module: rpm
+ */
+/*@{*/
 
-    if (verifyResult & RPMVERIFY_GROUP) {
-       if (!s->gids) {
-           headerGetEntry(s->h, RPMTAG_FILEGIDS, &type, (void **) &s->gids,
-                    &count);
-       }
+/** \ingroup python
+ */
+static PyObject * rpmtransCreate(PyObject * self, PyObject * args) {
+    rpmtransObject * o;
+    rpmdbObject * db = NULL;
+    char * rootPath = "/";
 
-       tuple = PyTuple_New(3);
-       attrName = PyString_FromString("gid");
-       PyTuple_SetItem(tuple, 0, attrName);
-       sprintf(buf, "%d", s->gids[fileNumber]);
-       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
-       sprintf(buf, "%d", sb.st_gid);
-       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
-       PyList_Append(list, tuple);
-       Py_DECREF(tuple);
+    if (!PyArg_ParseTuple(args, "|sO", &rootPath, &db)) return NULL;
+    if (db && db->ob_type != &rpmdbType) {
+       PyErr_SetString(PyExc_TypeError, "bad type for database argument");
+       return NULL;
     }
 
-    if (verifyResult & RPMVERIFY_MODE) {
-       if (!s->modes) {
-           headerGetEntry(s->h, RPMTAG_FILEMODES, &type, (void **) &s->modes,
-                    &count);
-       }
+    o = (void *) PyObject_NEW(rpmtransObject, &rpmtransType);
 
-       tuple = PyTuple_New(3);
-       attrName = PyString_FromString("permissions");
-       PyTuple_SetItem(tuple, 0, attrName);
-       sprintf(buf, "0%-4o", s->modes[fileNumber]);
-       PyTuple_SetItem(tuple, 1, PyString_FromString(buf));
-       sprintf(buf, "0%-4o", sb.st_mode);
-       PyTuple_SetItem(tuple, 2, PyString_FromString(buf));
-       PyList_Append(list, tuple);
-       Py_DECREF(tuple);
-    }
+    Py_XINCREF(db);
+    o->dbo = db;
+    o->scriptFd = NULL;
+    o->ts = rpmtransCreateSet(db ? db->db : NULL, rootPath);
+    o->keyList = PyList_New(0);
 
-    return list;
+    return (void *) o;
 }
 
-static PyObject * hdrCompressFilelist(hdrObject * s, PyObject * args) {
-    compressFilelist (s->h);
+/** \ingroup python
+ */
+static PyObject * doAddMacro(PyObject * self, PyObject * args) {
+    char * name, * val;
+
+    if (!PyArg_ParseTuple(args, "ss", &name, &val))
+       return NULL;
+
+    addMacro(NULL, name, NULL, val, RMIL_DEFAULT);
 
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-static PyObject * hdrExpandFilelist(hdrObject * s, PyObject * args) {
-    expandFilelist (s->h);
+/** \ingroup python
+ */
+static PyObject * doDelMacro(PyObject * self, PyObject * args) {
+    char * name;
 
-    Py_INCREF(Py_None);
-    return Py_None;
-}
+    if (!PyArg_ParseTuple(args, "s", &name))
+       return NULL;
 
-static PyObject * hdrFullFilelist(hdrObject * s, PyObject * args) {
-    mungeFilelist (s->h);
+    delMacro(NULL, name);
 
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-static PyObject * rpmtransCreate(PyObject * self, PyObject * args) {
-    rpmtransObject * o;
-    rpmdbObject * db = NULL;
-    char * rootPath = "/";
+/** \ingroup python
+ */
+static PyObject * archScore(PyObject * self, PyObject * args) {
+    char * arch;
+    int score;
 
-    if (!PyArg_ParseTuple(args, "|sO", &rootPath, &db)) return NULL;
-    if (db && db->ob_type != &rpmdbType) {
-       PyErr_SetString(PyExc_TypeError, "bad type for database argument");
+    if (!PyArg_ParseTuple(args, "s", &arch))
        return NULL;
-    }
 
-    o = (void *) PyObject_NEW(rpmtransObject, &rpmtransType);
+    score = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
 
-    Py_XINCREF(db);
-    o->dbo = db;
-    o->scriptFd = NULL;
-    o->ts = rpmtransCreateSet(db ? db->db : NULL, rootPath);
-    o->keyList = PyList_New(0);
+    return Py_BuildValue("i", score);
+}
 
-    return (void *) o;
+/** \ingroup python
+ */
+static int psGetArchScore(Header h) {
+    void * pkgArch;
+    int type, count;
+
+    if (!headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count) ||
+        type == RPM_INT8_TYPE)
+       return 150;
+    else
+        return rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch);
 }
 
-static void rpmtransDealloc(PyObject * o) {
-    rpmtransObject * trans = (void *) o;
+/** \ingroup python
+ */
+static int pkgCompareVer(void * first, void * second) {
+    struct packageInfo ** a = first;
+    struct packageInfo ** b = second;
+    int ret, score1, score2;
 
-    rpmtransFree(trans->ts);
-    if (trans->dbo) {
-       Py_DECREF(trans->dbo);
-    }
-    if (trans->scriptFd) Fclose(trans->scriptFd);
-    /* this will free the keyList, and decrement the ref count of all
-       the items on the list as well :-) */
-    Py_DECREF(trans->keyList);
-    PyMem_DEL(o);
+    /* put packages w/o names at the end */
+    if (!(*a)->name) return 1;
+    if (!(*b)->name) return -1;
+
+    ret = xstrcasecmp((*a)->name, (*b)->name);
+    if (ret) return ret;
+    score1 = psGetArchScore((*a)->h);
+    if (!score1) return 1;
+    score2 = psGetArchScore((*b)->h);
+    if (!score2) return -1;
+    if (score1 < score2) return -1;
+    if (score1 > score2) return 1;
+    return rpmVersionCompare((*b)->h, (*a)->h);
 }
 
-static PyObject * rpmtransGetAttr(rpmtransObject * o, char * name) {
-    return Py_FindMethod(rpmtransMethods, (PyObject *) o, name);
+/** \ingroup python
+ */
+static void pkgSort(struct pkgSet * psp) {
+    int i;
+    char *name;
+
+    qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
+        (void *) pkgCompareVer);
+
+    name = psp->packages[0]->name;
+    if (!name) {
+       psp->numPackages = 0;
+       return;
+    }
+    for (i = 1; i < psp->numPackages; i++) {
+       if (!psp->packages[i]->name) break;
+       if (!strcmp(psp->packages[i]->name, name))
+          psp->packages[i]->name = NULL;
+       else
+          name = psp->packages[i]->name;
+    }
+
+    qsort(psp->packages, psp->numPackages, sizeof(*psp->packages),
+        (void *) pkgCompareVer);
+
+    for (i = 0; i < psp->numPackages; i++)
+       if (!psp->packages[i]->name) break;
+    psp->numPackages = i;
 }
 
-static int rpmtransSetAttr(rpmtransObject * o, char * name,
-                          PyObject * val) {
+/** \ingroup python
+ */
+static PyObject * findUpgradeSet(PyObject * self, PyObject * args) {
+    PyObject * hdrList, * result;
+    char * root = "/";
     int i;
+    struct pkgSet list;
+    hdrObject * hdr;
 
-    if (!strcmp(name, "scriptFd")) {
-       if (!PyArg_Parse(val, "i", &i)) return 0;
-       if (i < 0) {
-           PyErr_SetString(PyExc_TypeError, "bad file descriptor");
-           return -1;
-       } else {
-           o->scriptFd = fdDup(i);
-           rpmtransSetScriptFd(o->ts, o->scriptFd);
+    if (!PyArg_ParseTuple(args, "O|s", &hdrList, &root)) return NULL;
+
+    if (!PyList_Check(hdrList)) {
+       PyErr_SetString(PyExc_TypeError, "list of headers expected");
+       return NULL;
+    }
+
+    list.numPackages = PyList_Size(hdrList);
+    list.packages = alloca(sizeof(list.packages) * list.numPackages);
+    for (i = 0; i < list.numPackages; i++) {
+       hdr = (hdrObject *) PyList_GetItem(hdrList, i);
+       if (hdr->ob_type != &hdrType) {
+           PyErr_SetString(PyExc_TypeError, "list of headers expected");
+           return NULL;
        }
-    } else {
-       PyErr_SetString(PyExc_AttributeError, name);
-       return -1;
+       list.packages[i] = alloca(sizeof(struct packageInfo));
+       list.packages[i]->h = hdr->h;
+       list.packages[i]->selected = 0;
+       list.packages[i]->data = hdr;
+
+       headerGetEntry(hdr->h, RPMTAG_NAME, NULL,
+                     (void **) &list.packages[i]->name, NULL);
     }
 
-    return 0;
+    pkgSort (&list);
+
+    if (ugFindUpgradePackages(&list, root)) {
+       PyErr_SetString(pyrpmError, "error during upgrade check");
+       return NULL;
+    }
+
+    result = PyList_New(0);
+    for (i = 0; i < list.numPackages; i++) {
+       if (list.packages[i]->selected) {
+           PyList_Append(result, list.packages[i]->data);
+/*         Py_DECREF(list.packages[i]->data); */
+       }
+    }
+
+    return result;
 }
 
-static PyObject * rpmtransAdd(rpmtransObject * s, PyObject * args) {
+/** \ingroup python
+ */
+static PyObject * rpmHeaderFromPackage(PyObject * self, PyObject * args) {
     hdrObject * h;
-    PyObject * key;
-    char * how = NULL;
-    int isUpgrade = 0;
+    Header header;
+    Header sigs;
+    int rc;
+    FD_t fd;
+    int rawFd;
+    int isSource = 0;
 
-    if (!PyArg_ParseTuple(args, "OO|s", &h, &key, &how)) return NULL;
-    if (h->ob_type != &hdrType) {
-       PyErr_SetString(PyExc_TypeError, "bad type for header argument");
+    if (!PyArg_ParseTuple(args, "i", &rawFd)) return NULL;
+    fd = fdDup(rawFd);
+
+    rc = rpmReadPackageInfo(fd, &sigs, &header);
+    Fclose(fd);
+
+    switch (rc) {
+      case 0:
+       h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
+       h->h = header;
+       h->sigs = sigs;
+       h->fileList = h->linkList = h->md5list = NULL;
+       h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
+       h->modes = h->rdevs = NULL;
+       if (headerIsEntry(header, RPMTAG_SOURCEPACKAGE))
+           isSource = 1;
+       break;
+
+      case 1:
+       Py_INCREF(Py_None);
+       h = (hdrObject *) Py_None;
+       break;
+
+      default:
+       PyErr_SetString(pyrpmError, "error reading package");
        return NULL;
     }
 
-    if (how && strcmp(how, "a") && strcmp(how, "u") && strcmp(how, "i")) {
-       PyErr_SetString(PyExc_TypeError, "how argument must be \"u\", \"a\", or \"i\"");
+    return Py_BuildValue("(Ni)", h, isSource);
+}
+
+/** \ingroup python
+ */
+static PyObject * hdrLoad(PyObject * self, PyObject * args) {
+    char * obj, * copy=NULL;
+    Header hdr;
+    hdrObject * h;
+    int len;
+
+    if (!PyArg_ParseTuple(args, "s#", &obj, &len)) return NULL;
+    
+    copy = malloc(len);
+    if (copy == NULL) {
+       PyErr_SetString(pyrpmError, "out of memory");
        return NULL;
-    } else if (how && !strcmp(how, "u"))
-       isUpgrade = 1;
+    }
 
-    if (how && !strcmp(how, "a"))
-       rpmtransAvailablePackage(s->ts, h->h, key);
-    else
-       rpmtransAddPackage(s->ts, h->h, NULL, key, isUpgrade, NULL);
+    memcpy (copy, obj, len);
 
-    /* This should increment the usage count for me */
-    if (key) {
-       PyList_Append(s->keyList, key);
+    hdr = headerLoad(copy);
+    if (!hdr) {
+       PyErr_SetString(pyrpmError, "bad header");
+       return NULL;
+    }
+    compressFilelist (hdr);
+    providePackageNVR (hdr);
+
+    h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
+    h->h = hdr;
+    h->sigs = NULL;
+    h->fileList = h->linkList = h->md5list = NULL;
+    h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
+    h->modes = h->rdevs = NULL;
+
+    return (PyObject *) h;
+}
+
+/** \ingroup python
+ */
+static PyObject * rpmInitDB(PyObject * self, PyObject * args) {
+    char *root;
+    int forWrite = 0;
+
+    if (!PyArg_ParseTuple(args, "i|s", &forWrite, &root)) return NULL;
+
+    if (rpmdbInit(root, forWrite ? O_RDWR | O_CREAT: O_RDONLY)) {
+       char * errmsg = "cannot initialize database in %s";
+       char * errstr = NULL;
+       int errsize;
+
+       errsize = strlen(errmsg) + strlen(root);
+       errstr = alloca(errsize);
+       snprintf(errstr, errsize, errmsg, root);
+       PyErr_SetString(pyrpmError, errstr);
+       return NULL;
     }
 
     Py_INCREF(Py_None);
-    return Py_None;
+    return(Py_None);
 }
 
-static PyObject * rpmtransRemove(rpmtransObject * s, PyObject * args) {
-    char * name;
-    int count;
-    rpmdbMatchIterator mi;
-    
-    if (!PyArg_ParseTuple(args, "s", &name))
-        return NULL;
+/** \ingroup python
+ */
+static rpmdbObject * rpmOpenDB(PyObject * self, PyObject * args) {
+    rpmdbObject * o;
+    char * root = "";
+    int forWrite = 0;
 
-    /* XXX: Copied hack from ../lib/rpminstall.c, rpmErase() */
-    mi = rpmdbInitIterator(s->dbo->db, RPMDBI_LABEL, name, 0);
-    count = rpmdbGetIteratorCount(mi);
-    if (count <= 0) {
-        PyErr_SetString(pyrpmError, "package not installed");
-        return NULL;
-    } else { /* XXX: Note that we automatically choose to remove all matches */
-        Header h;
-        while ((h = rpmdbNextIterator(mi)) != NULL) {
-           unsigned int recOffset = rpmdbGetIteratorOffset(mi);
-           if (recOffset) {
-               rpmtransRemovePackage(s->ts, recOffset);
-           }
-       }
-    }
-    rpmdbFreeIterator(mi);
+    if (!PyArg_ParseTuple(args, "|is", &forWrite, &root)) return NULL;
 
-    Py_INCREF(Py_None);
-    return Py_None;
-}
+    o = PyObject_NEW(rpmdbObject, &rpmdbType);
+    o->db = NULL;
+    o->offx = 0;
+    o->noffs = 0;
+    o->offsets = NULL;
 
-static PyObject * rpmtransOrder(rpmtransObject * s, PyObject * args) {
-    if (!PyArg_ParseTuple(args, "")) return NULL;
+    if (rpmdbOpen(root, &o->db, forWrite ? O_RDWR | O_CREAT: O_RDONLY, 0644)) {
+       char * errmsg = "cannot open database in %s";
+       char * errstr = NULL;
+       int errsize;
 
-    rpmdepOrder(s->ts);
+       Py_DECREF(o);
+       /* PyErr_SetString should take varargs... */
+       errsize = strlen(errmsg) + *root == '\0' ? 15 /* "/var/lib/rpm" */ : strlen(root);
+       errstr = alloca(errsize);
+       snprintf(errstr, errsize, errmsg, *root == '\0' ? "/var/lib/rpm" : root);
+       PyErr_SetString(pyrpmError, errstr);
+       return NULL;
+    }
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    return o;
 }
 
-static PyObject * rpmtransDepCheck(rpmtransObject * s, PyObject * args) {
-    struct rpmDependencyConflict * conflicts;
-    int numConflicts;
-    PyObject * list, * cf;
-    int i;
+/** \ingroup python
+ */
+static PyObject * rebuildDB (PyObject * self, PyObject * args) {
+    char * root = "";
 
-    if (!PyArg_ParseTuple(args, "")) return NULL;
+    if (!PyArg_ParseTuple(args, "s", &root)) return NULL;
 
-    rpmdepCheck(s->ts, &conflicts, &numConflicts);
-    if (numConflicts) {
-       list = PyList_New(0);
+    return Py_BuildValue("i", rpmdbRebuild(root));
+}
 
-       for (i = 0; i < numConflicts; i++) {
-           cf = Py_BuildValue("((sss)(ss)iOi)", conflicts[i].byName,
-                              conflicts[i].byVersion, conflicts[i].byRelease,
+/** \ingroup python
+ */
+static PyObject * rpmReadHeaders (FD_t fd) {
+    PyObject * list;
+    Header header;
+    hdrObject * h;
 
-                              conflicts[i].needsName,
-                              conflicts[i].needsVersion,
+    if (!fd) {
+       PyErr_SetFromErrno(pyrpmError);
+       return NULL;
+    }
 
-                              conflicts[i].needsFlags,
-                              conflicts[i].suggestedPackage ?
-                                  conflicts[i].suggestedPackage : Py_None,
-                              conflicts[i].sense);
-           PyList_Append(list, (PyObject *) cf);
-           Py_DECREF(cf);
+    list = PyList_New(0);
+    Py_BEGIN_ALLOW_THREADS
+    header = headerRead(fd, HEADER_MAGIC_YES);
+
+    Py_END_ALLOW_THREADS
+    while (header) {
+       compressFilelist (header);
+       providePackageNVR (header);
+       h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
+       h->h = header;
+       h->sigs = NULL;
+       h->fileList = h->linkList = h->md5list = NULL;
+       h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
+       h->modes = h->rdevs = NULL;
+       if (PyList_Append(list, (PyObject *) h)) {
+           Py_DECREF(list);
+           Py_DECREF(h);
+           return NULL;
        }
 
-       rpmdepFreeConflicts(conflicts, numConflicts);
+       Py_DECREF(h);
 
-       return list;
+       Py_BEGIN_ALLOW_THREADS
+       header = headerRead(fd, HEADER_MAGIC_YES);
+       Py_END_ALLOW_THREADS
     }
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    return list;
 }
 
-struct tsCallbackType {
-    PyObject * cb;
-    PyObject * data;
-    int pythonError;
-};
-
+/** \ingroup python
+ */
+static PyObject * rpmHeaderFromFD(PyObject * self, PyObject * args) {
+    FD_t fd;
+    int fileno;
+    PyObject * list;
 
+    if (!PyArg_ParseTuple(args, "i", &fileno)) return NULL;
+    fd = fdDup(fileno);
 
-static void * tsCallback(const void * hd, const rpmCallbackType what,
-                        const unsigned long amount, const unsigned long total,
-                        const void * pkgKey, rpmCallbackData data) {
-    struct tsCallbackType * cbInfo = data;
-    PyObject * args, * result;
-    int fd;
-    static FD_t fdt;
-    const Header h = (Header) hd;
+    list = rpmReadHeaders (fd);
+    Fclose(fd);
 
-    if (cbInfo->pythonError) return NULL;
+    return list;
+}
 
-    if (!pkgKey) pkgKey = Py_None;
-    transactionSetHeader = h;    
+/** \ingroup python
+ */
+static PyObject * rpmHeaderFromFile(PyObject * self, PyObject * args) {
+    char * filespec;
+    FD_t fd;
+    PyObject * list;
 
-    args = Py_BuildValue("(illOO)", what, amount, total, pkgKey, cbInfo->data);
-    result = PyEval_CallObject(cbInfo->cb, args);
-    Py_DECREF(args);
+    if (!PyArg_ParseTuple(args, "s", &filespec)) return NULL;
+    fd = Fopen(filespec, "r.fdio");
 
-    if (!result) {
-       cbInfo->pythonError = 1;
+    if (!fd) {
+       PyErr_SetFromErrno(pyrpmError);
        return NULL;
     }
 
-    if (what == RPMCALLBACK_INST_OPEN_FILE) {
-        if (!PyArg_Parse(result, "i", &fd)) {
-           cbInfo->pythonError = 1;
-           return NULL;
-       }
-       fdt = fdDup(fd);
-       
-       Py_DECREF(result);
-       return fdt;
-    }
-
-    if (what == RPMCALLBACK_INST_CLOSE_FILE) {
-       Fclose (fdt);
-    }
-
-    Py_DECREF(result);
+    list = rpmReadHeaders (fd);
+    Fclose(fd);
 
-    return NULL;
+    return list;
 }
 
-static PyObject * rpmtransRun(rpmtransObject * s, PyObject * args) {
-    int flags, ignoreSet;
-    int rc, i;
-    PyObject * list, * prob;
-    rpmProblemSet probs;
-    struct tsCallbackType cbInfo;
+/** \ingroup python
+ */
+static PyObject * errorCB = NULL, * errorData = NULL;
 
-    if (!PyArg_ParseTuple(args, "iiOO", &flags, &ignoreSet, &cbInfo.cb,
-                         &cbInfo.data))
-       return NULL;
+/** \ingroup python
+ */
+static void errorcb (void)
+{
+    PyObject * result, * args = NULL;
 
-    cbInfo.pythonError = 0;
+    if (errorData)
+       args = Py_BuildValue("(O)", errorData);
 
-    rc = rpmRunTransactions(s->ts, tsCallback, &cbInfo, NULL, &probs, flags,
-                           ignoreSet);
+    result = PyEval_CallObject(errorCB, args);
+    Py_XDECREF(args);
 
-    if (cbInfo.pythonError) {
-       if (rc > 0)
-           rpmProblemSetFree(probs);
-       return NULL;
+    if (result == NULL) {
+       PyErr_Print();
+       PyErr_Clear();
     }
+    Py_DECREF (result);
+}
 
-    if (rc < 0) {
-       list = PyList_New(0);
-       return list;
-    } else if (!rc) {
-       Py_INCREF(Py_None);
-       return Py_None;
+/** \ingroup python
+ */
+static PyObject * errorSetCallback (PyObject * self, PyObject * args) {
+    if (errorCB != NULL) {
+       Py_DECREF (errorCB);
+       errorCB = NULL;
     }
 
-    list = PyList_New(0);
-    for (i = 0; i < probs->numProblems; i++) {
-       rpmProblem myprob = probs->probs + i;
-       prob = Py_BuildValue("s(isi)", rpmProblemString(myprob),
-                            myprob->type,
-                            myprob->str1,
-                            myprob->ulong1);
-       PyList_Append(list, prob);
-       Py_DECREF(prob);
+    if (errorData != NULL) {
+       Py_DECREF (errorData);
+       errorData = NULL;
     }
 
-    rpmProblemSetFree(probs);
-
-    return list;
-}
-
-static PyObject * py_rpmtransGetKeys(rpmtransObject * s, PyObject * args) {
-    const void **data = NULL;
-    int num, i;
-    PyObject *tuple;
+    if (!PyArg_ParseTuple(args, "O|O", &errorCB, &errorData)) return NULL;
 
-    rpmtransGetKeys(s->ts, &data, &num);
-    if (data == NULL) {
-       Py_INCREF(Py_None);
-       return Py_None;
-    }
+    /* if we're getting a void*, set the error callback to this. */
+    /* also, we can possibly decref any python callbacks we had  */
+    /* and set them to NULL.                                     */
+    if (PyCObject_Check (errorCB)) {
+       rpmErrorSetCallback (PyCObject_AsVoidPtr(errorCB));
 
-    tuple = PyTuple_New(num);
+       Py_XDECREF (errorCB);
+       Py_XDECREF (errorData);
 
-    for (i = 0; i < num; i++) {
-       PyObject *obj = (PyObject *) data[i];
-       Py_INCREF(obj);
-       PyTuple_SetItem(tuple, i, obj);
+       errorCB   = NULL;
+       errorData = NULL;
+       
+       Py_INCREF(Py_None);
+       return Py_None;
+    }
+    
+    if (!PyCallable_Check (errorCB)) {
+       PyErr_SetString(PyExc_TypeError, "parameter must be callable");
+       return NULL;
     }
 
-    free (data);
+    Py_INCREF (errorCB);
+    Py_XINCREF (errorData);
 
-    return tuple;
+    return PyCObject_FromVoidPtr(rpmErrorSetCallback (errorcb), NULL);
 }
 
-static PyObject * archScore(PyObject * self, PyObject * args) {
-    char * arch;
-    int score;
+/** \ingroup python
+ */
+static PyObject * errorString (PyObject * self, PyObject * args) {
+    return PyString_FromString(rpmErrorString ());
+}
 
-    if (!PyArg_ParseTuple(args, "s", &arch))
-       return NULL;
+/** \ingroup python
+ */
+static PyObject * versionCompare (PyObject * self, PyObject * args) {
+    hdrObject * h1, * h2;
 
-    score = rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch);
+    if (!PyArg_ParseTuple(args, "O!O!", &hdrType, &h1, &hdrType, &h2)) return NULL;
 
-    return Py_BuildValue("i", score);
+    return Py_BuildValue("i", rpmVersionCompare(h1->h, h2->h));
 }
 
-static PyObject * doAddMacro(PyObject * self, PyObject * args) {
-    char * name, * val;
+/**
+ */
+static PyObject * labelCompare (PyObject * self, PyObject * args) {
+    char *v1, *r1, *e1, *v2, *r2, *e2;
+    int rc;
 
-    if (!PyArg_ParseTuple(args, "ss", &name, &val))
-       return NULL;
+    if (!PyArg_ParseTuple(args, "(zzz)(zzz)",
+                         &e1, &v1, &r1,
+                         &e2, &v2, &r2)) return NULL;
 
-    addMacro(NULL, name, NULL, val, RMIL_DEFAULT);
+    if (e1 && !e2)
+       return Py_BuildValue("i", 1);
+    else if (!e1 && e2)
+       return Py_BuildValue("i", -1);
+    else if (e1 && e2) {
+       int ep1, ep2;
+       ep1 = atoi (e1);
+       ep2 = atoi (e2);
+       if (ep1 < ep2)
+           return Py_BuildValue("i", -1);
+       else if (ep1 > ep2)
+           return Py_BuildValue("i", 1);
+    }
 
-    Py_INCREF(Py_None);
-    return Py_None;
-}
+    rc = rpmvercmp(v1, v2);
+    if (rc)
+       return Py_BuildValue("i", rc);
 
-static PyObject * doDelMacro(PyObject * self, PyObject * args) {
-    char * name;
+    return Py_BuildValue("i", rpmvercmp(r1, r2));
+}
 
-    if (!PyArg_ParseTuple(args, "s", &name))
-       return NULL;
+/** \ingroup python
+ */
+static PyObject * checkSig (PyObject * self, PyObject * args) {
+    char * filename;
+    int flags;
+    int rc = 255;
 
-    delMacro(NULL, name);
+    if (PyArg_ParseTuple(args, "si", &filename, &flags)) {
+       const char *av[2];
+       av[0] = filename;
+       av[1] = NULL;
+       rc = rpmCheckSig(flags, av);
+    }
+    return Py_BuildValue("i", rc);
+}
 
+/* hack to get the current header that's in the transaction set */
+/** \ingroup python
+ */
+static PyObject * getTsHeader (PyObject * self, PyObject * args) {
+    hdrObject * h;
+    
+    if (transactionSetHeader) {
+       h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
+       h->h = headerLink(transactionSetHeader);
+       h->sigs = NULL;
+       h->fileList = h->linkList = h->md5list = NULL;
+       h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
+       h->modes = h->rdevs = NULL;
+       return (PyObject *) h;
+    }
     Py_INCREF(Py_None);
-    return Py_None;
+    return (PyObject *) Py_None;
 }
 
+/** \ingroup python
+ */
 typedef struct FDlist_t FDlist;
 
+/** \ingroup python
+ */
 struct FDlist_t {
     FILE *f;
     FD_t fd;
@@ -1852,9 +2080,16 @@ struct FDlist_t {
     FDlist *next;
 } ;
 
+/** \ingroup python
+ */
 static FDlist *fdhead = NULL;
+
+/** \ingroup python
+ */
 static FDlist *fdtail = NULL;
 
+/** \ingroup python
+ */
 static int closeCallback(FILE * f) {
     FDlist *node, *last;
 
@@ -1884,38 +2119,9 @@ static int closeCallback(FILE * f) {
     return 0; 
 }
 
-static PyObject * checkSig (PyObject * self, PyObject * args) {
-    char * filename;
-    int flags;
-    int rc = 255;
-
-    if (PyArg_ParseTuple(args, "si", &filename, &flags)) {
-       const char *av[2];
-       av[0] = filename;
-       av[1] = NULL;
-       rc = rpmCheckSig(flags, av);
-    }
-    return Py_BuildValue("i", rc);
-}
-
-
-static PyObject * getTsHeader (PyObject * self, PyObject * args) {
-    hdrObject * h;
-    
-    if (transactionSetHeader) {
-       h = (hdrObject *) PyObject_NEW(PyObject, &hdrType);
-       h->h = headerLink(transactionSetHeader);
-       h->sigs = NULL;
-       h->fileList = h->linkList = h->md5list = NULL;
-       h->uids = h->gids = h->mtimes = h->fileSizes = NULL;
-       h->modes = h->rdevs = NULL;
-       return (PyObject *) h;
-    }
-    Py_INCREF(Py_None);
-    return (PyObject *) Py_None;
-}
-
-/* disable 
+#if 0
+/** \ingroup python
+ */
 static PyObject * doFopen(PyObject * self, PyObject * args) {
     char * path, * mode;
     FDlist *node;
@@ -1963,5 +2169,141 @@ static PyObject * doFopen(PyObject * self, PyObject * args) {
     
     return PyFile_FromFile (node->f, path, mode, closeCallback);
 }
-*/
+#endif
+
+/** \ingroup python
+ */
+static PyMethodDef rpmModuleMethods[] = {
+    { "TransactionSet", (PyCFunction) rpmtransCreate, METH_VARARGS, NULL },
+    { "addMacro", (PyCFunction) doAddMacro, METH_VARARGS, NULL },
+    { "delMacro", (PyCFunction) doDelMacro, METH_VARARGS, NULL },
+    { "archscore", (PyCFunction) archScore, METH_VARARGS, NULL },
+    { "findUpgradeSet", (PyCFunction) findUpgradeSet, METH_VARARGS, NULL },
+    { "headerFromPackage", (PyCFunction) rpmHeaderFromPackage, METH_VARARGS, NULL },
+    { "headerLoad", (PyCFunction) hdrLoad, METH_VARARGS, NULL },
+    { "initdb", (PyCFunction) rpmInitDB, METH_VARARGS, NULL },
+    { "opendb", (PyCFunction) rpmOpenDB, METH_VARARGS, NULL },
+    { "rebuilddb", (PyCFunction) rebuildDB, METH_VARARGS, NULL },
+    { "readHeaderListFromFD", (PyCFunction) rpmHeaderFromFD, METH_VARARGS, NULL },
+    { "readHeaderListFromFile", (PyCFunction) rpmHeaderFromFile, METH_VARARGS, NULL },
+    { "errorSetCallback", (PyCFunction) errorSetCallback, METH_VARARGS, NULL },
+    { "errorString", (PyCFunction) errorString, METH_VARARGS, NULL },
+    { "versionCompare", (PyCFunction) versionCompare, METH_VARARGS, NULL },
+    { "labelCompare", (PyCFunction) labelCompare, METH_VARARGS, NULL },
+    { "checksig", (PyCFunction) checkSig, METH_VARARGS, NULL },
+    { "getTransactionCallbackHeader", (PyCFunction) getTsHeader, METH_VARARGS, NULL },
+/*      { "Fopen", (PyCFunction) doFopen, METH_VARARGS, NULL }, */
+    { NULL }
+} ;
+
+/** \ingroup python
+ */
+void initrpm(void) {
+    PyObject * m, * d, *o, * tag = NULL, * dict;
+    int i;
+    const struct headerSprintfExtension * extensions = rpmHeaderFormats;
+    struct headerSprintfExtension * ext;
+
+/*      _rpmio_debug = -1; */
+    rpmReadConfigFiles(NULL, NULL);
+
+    m = Py_InitModule("rpm", rpmModuleMethods);
+    d = PyModule_GetDict(m);
+
+    pyrpmError = PyString_FromString("rpm.error");
+    PyDict_SetItemString(d, "error", pyrpmError);
+    Py_DECREF(pyrpmError);
+
+    dict = PyDict_New();
+
+    for (i = 0; i < rpmTagTableSize; i++) {
+       tag = PyInt_FromLong(rpmTagTable[i].val);
+       PyDict_SetItemString(d, (char *) rpmTagTable[i].name, tag);
+       Py_DECREF(tag);
+        PyDict_SetItem(dict, tag, o=PyString_FromString(rpmTagTable[i].name + 7));
+       Py_DECREF(o);
+    }
+
+    while (extensions->name) {
+       if (extensions->type == HEADER_EXT_TAG) {
+            (const struct headerSprintfExtension *) ext = extensions;
+            PyDict_SetItemString(d, extensions->name, o=PyCObject_FromVoidPtr(ext, NULL));
+           Py_DECREF(o);
+            PyDict_SetItem(dict, tag, o=PyString_FromString(ext->name + 7));
+           Py_DECREF(o);    
+        }
+        extensions++;
+    }
+
+    PyDict_SetItemString(d, "tagnames", dict);
+    Py_DECREF(dict);
+
+
+#define REGISTER_ENUM(val) \
+    PyDict_SetItemString(d, #val, o=PyInt_FromLong(## val)); \
+    Py_DECREF(o);
+    
+    REGISTER_ENUM(RPMFILE_STATE_NORMAL);
+    REGISTER_ENUM(RPMFILE_STATE_REPLACED);
+    REGISTER_ENUM(RPMFILE_STATE_NOTINSTALLED);
+    REGISTER_ENUM(RPMFILE_CONFIG);
+    REGISTER_ENUM(RPMFILE_MISSINGOK);
+    REGISTER_ENUM(RPMFILE_DOC);
+
+    REGISTER_ENUM(RPMDEP_SENSE_REQUIRES);
+    REGISTER_ENUM(RPMDEP_SENSE_CONFLICTS);
+
+    REGISTER_ENUM(RPMSENSE_SERIAL);
+    REGISTER_ENUM(RPMSENSE_LESS);
+    REGISTER_ENUM(RPMSENSE_GREATER);
+    REGISTER_ENUM(RPMSENSE_EQUAL);
+    REGISTER_ENUM(RPMSENSE_PREREQ);
+
+    REGISTER_ENUM(RPMTRANS_FLAG_TEST);
+    REGISTER_ENUM(RPMTRANS_FLAG_BUILD_PROBS);
+    REGISTER_ENUM(RPMTRANS_FLAG_NOSCRIPTS);
+    REGISTER_ENUM(RPMTRANS_FLAG_JUSTDB);
+    REGISTER_ENUM(RPMTRANS_FLAG_NOTRIGGERS);
+    REGISTER_ENUM(RPMTRANS_FLAG_NODOCS);
+    REGISTER_ENUM(RPMTRANS_FLAG_ALLFILES);
+    REGISTER_ENUM(RPMTRANS_FLAG_KEEPOBSOLETE);
+
+    REGISTER_ENUM(RPMPROB_FILTER_IGNOREOS);
+    REGISTER_ENUM(RPMPROB_FILTER_IGNOREARCH);
+    REGISTER_ENUM(RPMPROB_FILTER_REPLACEPKG);
+    REGISTER_ENUM(RPMPROB_FILTER_FORCERELOCATE);
+    REGISTER_ENUM(RPMPROB_FILTER_REPLACENEWFILES);
+    REGISTER_ENUM(RPMPROB_FILTER_REPLACEOLDFILES);
+    REGISTER_ENUM(RPMPROB_FILTER_OLDPACKAGE);
+    REGISTER_ENUM(RPMPROB_FILTER_DISKSPACE);
+
+    REGISTER_ENUM(RPMCALLBACK_INST_PROGRESS);
+    REGISTER_ENUM(RPMCALLBACK_INST_START);
+    REGISTER_ENUM(RPMCALLBACK_INST_OPEN_FILE);
+    REGISTER_ENUM(RPMCALLBACK_INST_CLOSE_FILE);
+    REGISTER_ENUM(RPMCALLBACK_TRANS_PROGRESS);
+    REGISTER_ENUM(RPMCALLBACK_TRANS_START);
+    REGISTER_ENUM(RPMCALLBACK_TRANS_STOP);
+    REGISTER_ENUM(RPMCALLBACK_UNINST_PROGRESS);
+    REGISTER_ENUM(RPMCALLBACK_UNINST_START);
+    REGISTER_ENUM(RPMCALLBACK_UNINST_STOP);
+
+    REGISTER_ENUM(RPMPROB_BADARCH);
+    REGISTER_ENUM(RPMPROB_BADOS);
+    REGISTER_ENUM(RPMPROB_PKG_INSTALLED);
+    REGISTER_ENUM(RPMPROB_BADRELOCATE);
+    REGISTER_ENUM(RPMPROB_REQUIRES);
+    REGISTER_ENUM(RPMPROB_CONFLICT);
+    REGISTER_ENUM(RPMPROB_NEW_FILE_CONFLICT);
+    REGISTER_ENUM(RPMPROB_FILE_CONFLICT);
+    REGISTER_ENUM(RPMPROB_OLDPACKAGE);
+    REGISTER_ENUM(RPMPROB_DISKSPACE);
+    REGISTER_ENUM(RPMPROB_DISKNODES);
+    REGISTER_ENUM(RPMPROB_BADPRETRANS);
+
+    REGISTER_ENUM(CHECKSIG_PGP);
+    REGISTER_ENUM(CHECKSIG_GPG);
+    REGISTER_ENUM(CHECKSIG_MD5);
+}
 
+/*@}*/
index 4efb077..e8896d5 100644 (file)
@@ -110,38 +110,13 @@ typedef int fdio_fflush_function_t (FD_t fd);
  * \name RPMRPC Vectors.
  */
 /*@{*/
-
-/** \ingroup rpmio
- */
 typedef int fdio_mkdir_function_t (const char * path, mode_t mode);
-
-/** \ingroup rpmrpc
- */
 typedef int fdio_chdir_function_t (const char * path);
-
-/** \ingroup rpmrpc
- */
 typedef int fdio_rmdir_function_t (const char * path);
-
-/** \ingroup rpmrpc
- */
 typedef int fdio_rename_function_t (const char * oldpath, const char * newpath);
-
-/** \ingroup rpmrpc
- */
 typedef int fdio_unlink_function_t (const char * path);
-
-
-/** \ingroup rpmrpc
- */
 typedef int fdio_stat_function_t (const char * path, struct stat * st);
-
-/** \ingroup rpmrpc
- */
 typedef int fdio_lstat_function_t (const char * path, struct stat * st);
-
-/** \ingroup rpmrpc
- */
 typedef int fdio_access_function_t (const char * path, int amode);
 /*@}*/