Accept rpm.fd() types file objects everywhere in python bindings
authorPanu Matilainen <pmatilai@redhat.com>
Thu, 15 Oct 2009 07:11:37 +0000 (10:11 +0300)
committerPanu Matilainen <pmatilai@redhat.com>
Thu, 15 Oct 2009 07:11:37 +0000 (10:11 +0300)
- turn rpmfdFromPyObject() into a python-level object converter, add
  a separate C-level getter for the fd pointer itself
- take advantage of python refcounting to handle differences between
  native vs converted rpm.fd in callers so we can simply decref the
  rpmfdFromPyObject() result without having to worry whether it was
  converted or not (ie should we close it or not)

python/header-py.c
python/rpmfd-py.c
python/rpmfd-py.h
python/rpmts-py.c

index 5ca920e..e51ef0b 100644 (file)
@@ -272,19 +272,20 @@ static PyObject * hdrWrite(hdrObject *s, PyObject *args, PyObject *kwds)
 {
     char *kwlist[] = { "file", "magic", NULL };
     int magic = 1;
-    FD_t fd = NULL;
+    rpmfdObject *fdo = NULL;
     int rc;
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist,
-                                    rpmFdFromPyObject, &fd, &magic))
+                                    rpmfdFromPyObject, &fdo, &magic))
        return NULL;
 
     Py_BEGIN_ALLOW_THREADS;
-    rc = headerWrite(fd, s->h, magic ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
+    rc = headerWrite(rpmfdGetFd(fdo), s->h,
+                    magic ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
     Py_END_ALLOW_THREADS;
 
     if (rc) PyErr_SetFromErrno(PyExc_IOError);
-    Fclose(fd); /* avoid messing up errno wrt above */
+    Py_XDECREF(fdo); /* avoid messing up errno with file close  */
     if (rc) return NULL;
 
     Py_RETURN_NONE;
@@ -359,8 +360,8 @@ static struct PyMethodDef hdr_methods[] = {
 static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
 {
     PyObject *obj = NULL;
+    rpmfdObject *fdo = NULL;
     Header h = NULL;
-    FD_t fd = NULL;
     char *kwlist[] = { "obj", NULL };
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &obj)) {
@@ -373,11 +374,11 @@ static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
        h = headerCopy(((hdrObject*) obj)->h);
     } else if (PyString_Check(obj)) {
        h = headerCopyLoad(PyString_AsString(obj));
-    } else if (rpmFdFromPyObject(obj, &fd)) {
+    } else if (rpmfdFromPyObject(obj, &fdo)) {
        Py_BEGIN_ALLOW_THREADS;
-       h = headerRead(fd, HEADER_MAGIC_YES);
-       Fclose(fd);
+       h = headerRead(rpmfdGetFd(fdo), HEADER_MAGIC_YES);
        Py_END_ALLOW_THREADS;
+       Py_XDECREF(fdo);
     } else {
        PyErr_SetString(PyExc_TypeError, "header, blob or file expected");
        return NULL;
index 8b4f2b1..8458410 100644 (file)
@@ -3,25 +3,36 @@
 #include <rpm/rpmstring.h>
 #include "rpmfd-py.h"
 
-int rpmFdFromPyObject(PyObject *obj, FD_t *fdp)
+struct rpmfdObject_s {
+    PyObject_HEAD
+    PyObject *md_dict;
+    FD_t fd;
+};
+
+FD_t rpmfdGetFd(rpmfdObject *fdo)
 {
-    FD_t fd = NULL;
+    return fdo->fd;
+}
 
-    if (PyInt_Check(obj)) {
-       fd = fdDup(PyInt_AsLong(obj));
-    } else if (PyFile_Check(obj)) {
-       FILE *fp = PyFile_AsFile(obj);
-       fd = fdDup(fileno(fp));
+int rpmfdFromPyObject(PyObject *obj, rpmfdObject **fdop)
+{
+    rpmfdObject *fdo = NULL;
+
+    if (rpmfdObject_Check(obj)) {
+       Py_INCREF(obj);
+       fdo = (rpmfdObject *) obj;
     } else {
-       PyErr_SetString(PyExc_TypeError, "integer or file object expected");
-       return 0;
+       fdo = (rpmfdObject *) PyObject_Call((PyObject *)&rpmfd_Type,
+                                           Py_BuildValue("(O)", obj), NULL);
     }
-    if (Ferror(fd)) {
-       PyErr_SetString(PyExc_IOError, Fstrerror(fd));
-       if (fd) Fclose(fd);
+    if (fdo == NULL) return 0;
+
+    if (Ferror(fdo->fd)) {
+       Py_DECREF(fdo);
+       PyErr_SetString(PyExc_IOError, Fstrerror(fdo->fd));
        return 0;
     }
-    *fdp = fd;
+    *fdop = fdo;
     return 1;
 }
 
@@ -31,12 +42,6 @@ static PyObject *err_closed(void)
     return NULL;
 }
 
-struct rpmfdObject_s {
-    PyObject_HEAD
-    PyObject *md_dict;
-    FD_t fd;
-};
-
 static PyObject *rpmfd_new(PyTypeObject *subtype, 
                           PyObject *args, PyObject *kwds)
 {
@@ -57,7 +62,13 @@ static PyObject *rpmfd_new(PyTypeObject *subtype,
        fd = Fopen(PyString_AsString(fo), m);
        Py_END_ALLOW_THREADS 
        free(m);
-    } else if (!rpmFdFromPyObject(fo, &fd)) {
+    } else if (PyInt_Check(fo)) {
+       fd = fdDup(PyInt_AsLong(fo));
+    } else if (PyFile_Check(fo)) {
+       FILE *fp = PyFile_AsFile(fo);
+       fd = fdDup(fileno(fp));
+    } else {
+       PyErr_SetString(PyExc_TypeError, "path or file object expected");
        return NULL;
     }
 
index 3e2a9ca..b84e174 100644 (file)
@@ -7,7 +7,11 @@ typedef struct rpmfdObject_s rpmfdObject;
 
 extern PyTypeObject rpmfd_Type;
 
-int rpmFdFromPyObject(PyObject *obj, FD_t *fdp);
+#define rpmfdObject_Check(v)   ((v)->ob_type == &rpmfd_Type)
+
+FD_t rpmfdGetFd(rpmfdObject *fdo);
+
+int rpmfdFromPyObject(PyObject *obj, rpmfdObject **fdop);
 
 
 #endif
index 0ac6a5c..e228736 100644 (file)
 struct rpmtsObject_s {
     PyObject_HEAD
     PyObject *md_dict;         /*!< to look like PyModuleObject */
+    rpmfdObject *scriptFd;
     rpmts      ts;
-    FD_t scriptFd;
     rpmtsi tsi;
 };
 
@@ -337,17 +337,17 @@ static PyObject *
 rpmts_HdrFromFdno(rpmtsObject * s, PyObject *arg)
 {
     PyObject *ho = NULL;
+    rpmfdObject *fdo = NULL;
     Header h;
-    FD_t fd;
     rpmRC rpmrc;
 
-    if (!PyArg_Parse(arg, "O&:HdrFromFdno", rpmFdFromPyObject, &fd))
+    if (!PyArg_Parse(arg, "O&:HdrFromFdno", rpmfdFromPyObject, &fdo))
        return NULL;
 
     Py_BEGIN_ALLOW_THREADS;
-    rpmrc = rpmReadPackageFile(s->ts, fd, "rpmts_HdrFromFdno", &h);
+    rpmrc = rpmReadPackageFile(s->ts, rpmfdGetFd(fdo), "rpmts_HdrFromFdno", &h);
     Py_END_ALLOW_THREADS;
-    Fclose(fd);
+    Py_XDECREF(fdo);
 
     if (rpmrc == RPMRC_OK) {
        ho = hdr_Wrap(&hdr_Type, h);
@@ -676,8 +676,7 @@ static void rpmts_dealloc(rpmtsObject * s)
 {
 
     s->ts = rpmtsFree(s->ts);
-
-    if (s->scriptFd) Fclose(s->scriptFd);
+    Py_XDECREF(s->scriptFd);
     s->ob_type->tp_free((PyObject *)s);
 }
 
@@ -722,11 +721,14 @@ static PyObject *rpmts_get_rootDir(rpmtsObject *s, void *closure)
 
 static int rpmts_set_scriptFd(rpmtsObject *s, PyObject *value, void *closure)
 {
+    rpmfdObject *fdo = NULL;
     int rc = 0;
-    if (PyArg_Parse(value, "O&", rpmFdFromPyObject, &s->scriptFd)) {
-       rpmtsSetScriptFd(s->ts, s->scriptFd);
+    if (PyArg_Parse(value, "O&", rpmfdFromPyObject, &fdo)) {
+       Py_XDECREF(s->scriptFd);
+       s->scriptFd = fdo;
+       rpmtsSetScriptFd(s->ts, rpmfdGetFd(s->scriptFd));
     } else if (value == Py_None) {
-       Fclose(s->scriptFd);
+       Py_XDECREF(s->scriptFd);
        s->scriptFd = NULL;
        rpmtsSetScriptFd(s->ts, NULL);
     } else {