On Thu, 15 Oct 2009, David Malcolm wrote:
diff --git a/python/rpmds-py.c b/python/rpmds-py.c
index f45c908..1b091f9 100644
--- a/python/rpmds-py.c
+++ b/python/rpmds-py.c
@@ -473,7 +473,10 @@ PyTypeObject rpmds_Type = {
        PyObject_GenericSetAttr,        /* tp_setattro */
        0,                              /* tp_as_buffer */
        Py_TPFLAGS_DEFAULT |            /* tp_flags */
+#if PY_MAJOR_VERSION < 3
+            /* FIXME: doublecheck this flag */
            Py_TPFLAGS_HAVE_RICHCOMPARE |
+#endif

Py_TPFLAGS_HAVE_RICHCOMPARE is included in Py_TPFLAGS_DEFAULT for any remotely recent Python 2.x versions, so it's simply unnecessary. Removed...

diff --git a/python/rpmfd-py.c b/python/rpmfd-py.c
index 97cd100..837cea5 100644
--- a/python/rpmfd-py.c
+++ b/python/rpmfd-py.c
@@ -9,12 +9,15 @@ int rpmFdFromPyObject(PyObject *obj, FD_t *fdp)

    if (PyInt_Check(obj)) {
        fd = fdDup(PyInt_AsLong(obj));
+/* FIXME: still need to port this block to Py3k */
+#if PY_MAJOR_VERSION < 3
    } else if (PyFile_Check(obj)) {
        FILE *fp = PyFile_AsFile(obj);
        fd = fdDup(fileno(fp));
    } else {
        PyErr_SetString(PyExc_TypeError, "integer or file object expected");
        return 0;
+#endif

Turns out Python has a nice way to deal with this: PyObject_AsFileDescriptor(). Using it not only avoids the 2.x vs 3.x incompatibility but it also makes it work with any file-like object implementing .fileno() method (including rpm.fd itself), and it even reduces code :) Fixed in HEAD.

    }
    if (Ferror(fd)) {
        PyErr_SetString(PyExc_IOError, Fstrerror(fd));
@@ -51,12 +54,28 @@ static PyObject *rpmfd_new(PyTypeObject *subtype,
                                     &fo, &mode, &flags))
        return NULL;

-    if (PyString_Check(fo)) {
+#if PY_MAJOR_VERSION >= 3
+    /* Handle py3k unicode objects by decoding using default FS encoding */
+    if (PyUnicode_Check(fo)) {
+       PyObject *fs_encoded_bytes = NULL;
+       if (PyUnicode_FSConverter(fo, &fs_encoded_bytes)) {
        char *m = rstrscat(NULL, mode, ".", flags, NULL);
        Py_BEGIN_ALLOW_THREADS
-       fd = Fopen(PyString_AsString(fo), m);
+       fd = Fopen(PyBytes_AsString(fo), m);
        Py_END_ALLOW_THREADS
        free(m);
+       Py_DECREF(fs_encoded_bytes);
+      } else {
+       return NULL;
+      }
+#else
+    if (PyBytes_Check(fo)) {
+       char *m = rstrscat(NULL, mode, ".", flags, NULL);
+       Py_BEGIN_ALLOW_THREADS
+       fd = Fopen(PyBytes_AsString(fo), m);
+       Py_END_ALLOW_THREADS
+       free(m);
+#endif
    } else if (!rpmFdFromPyObject(fo, &fd)) {
        return NULL;
    }

Oh grumble... damn encodings. But ok I guess there's no way around it.
Just makes me wonder what to do with file names from headers, since we have no clue of their encoding.

diff --git a/python/rpmmodule.c b/python/rpmmodule.c
index e0aeddc..c281db1 100644
--- a/python/rpmmodule.c
+++ b/python/rpmmodule.c
@@ -64,6 +64,8 @@ static PyObject * setLogFile (PyObject * self, PyObject * 
args, PyObject *kwds)
    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:logSetFile", kwlist, &fop))
        return NULL;

+/* FIXME: still need to port this block to Py3k */
+#if PY_MAJOR_VERSION < 3
    if (fop) {
        if (!PyFile_Check(fop)) {
            PyErr_SetString(PyExc_TypeError, "requires file object");
@@ -71,6 +73,7 @@ static PyObject * setLogFile (PyObject * self, PyObject * 
args, PyObject *kwds)
        }
        fp = PyFile_AsFile(fop);
    }
+#endif

I changed this to use PyObject_AsFileDescriptor() so it at least compiles, although it gets a bit murky, need to check that it still works...


    (void) rpmlogSetFile(fp);

diff --git a/python/rpmts-py.c b/python/rpmts-py.c
index cc0ed00..3633d61 100644
--- a/python/rpmts-py.c
+++ b/python/rpmts-py.c
@@ -159,7 +159,14 @@ static void die(PyObject *cb)
        PyErr_Print();
    }
    if ((r = PyObject_Repr(cb)) != NULL) {
+#if PY_MAJOR_VERSION >= 3
+       /* FIXME: this is making assumptions about the encoding of stderr.*/
+       PyObject *utf8_bytes = PyUnicode_AsUTF8String(r);
+        pyfn = PyBytes_AsString(utf8_bytes);
+       Py_XDECREF(utf8_bytes);
+#else
        pyfn = PyString_AsString(r);
+#endif
    }
    fprintf(stderr, _("error: python callback %s failed, aborting!\n"),
                      pyfn ? pyfn : "???");

Hmm. Dunno if it's worth the trouble dealing with Repr encoding and all, this is afterall the last S.O.S. before sinking, plain "Fatal error in transaction callback, by the time you read this I am already dead" would be just as well.

        - Panu -
_______________________________________________
Rpm-maint mailing list
[email protected]
http://lists.rpm.org/mailman/listinfo/rpm-maint

Reply via email to