[pypy-commit] pypy add_PyErr_SetFromErrnoWithFilenameObject_try_2: Make PyErr_SetFromErrnoWithFilenameObject work with any Python object; not just strings

Marc Abramowitz noreply at buildbot.pypy.org
Mon Mar 24 07:38:44 CET 2014


Author: Marc Abramowitz <marc at marc-abramowitz.com>
Branch: add_PyErr_SetFromErrnoWithFilenameObject_try_2
Changeset: r70225:a00eb16f44ee
Date: 2014-03-23 23:29 -0700
http://bitbucket.org/pypy/pypy/changeset/a00eb16f44ee/

Log:	Make PyErr_SetFromErrnoWithFilenameObject work with any Python
	object; not just strings

diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -165,15 +165,24 @@
     raise OperationError(w_type, w_error)
 
 @cpython_api([PyObject, PyObject], PyObject)
-def PyErr_SetFromErrnoWithFilenameObject(space, w_type, filename_object):
+def PyErr_SetFromErrnoWithFilenameObject(space, w_type, w_value):
     """Similar to PyErr_SetFromErrno(), with the additional behavior that if
-    filename_object is not NULL, it is passed to the constructor of type as a
+    w_value is not NULL, it is passed to the constructor of type as a
     third parameter.  In the case of exceptions such as IOError and OSError,
     this is used to define the filename attribute of the exception instance.
     Return value: always NULL."""
-    from pypy.module.cpyext.stringobject import PyString_AsString
-    PyErr_SetFromErrnoWithFilename(space, w_type,
-                                   PyString_AsString(space, filename_object))
+    errno = get_errno()
+    msg = os.strerror(errno)
+    if w_value:
+        w_error = space.call_function(w_type,
+                                      space.wrap(errno),
+                                      space.wrap(msg),
+                                      w_value)
+    else:
+        w_error = space.call_function(w_type,
+                                      space.wrap(errno),
+                                      space.wrap(msg))
+    raise OperationError(w_type, w_error)
 
 @cpython_api([], rffi.INT_real, error=-1)
 def PyErr_CheckSignals(space):
diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -215,7 +215,7 @@
         assert exc_info.value.errno == errno.EBADF
         assert exc_info.value.strerror == os.strerror(errno.EBADF)
 
-    def test_SetFromErrnoWithFilenameObject(self):
+    def test_SetFromErrnoWithFilenameObject__PyString(self):
         import errno, os
 
         module = self.import_extension('foo', [
@@ -234,6 +234,82 @@
         assert exc_info.value.errno == errno.EBADF
         assert exc_info.value.strerror == os.strerror(errno.EBADF)
 
+    def test_SetFromErrnoWithFilenameObject__PyInt(self):
+        import errno, os
+
+        module = self.import_extension('foo', [
+                ("set_from_errno", "METH_NOARGS",
+                 '''
+                 errno = EBADF;
+                 PyObject *intObject = PyInt_FromLong(3);
+                 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, intObject);
+                 Py_DECREF(intObject);
+                 return NULL;
+                 '''),
+                ],
+                prologue="#include <errno.h>")
+        exc_info = raises(OSError, module.set_from_errno)
+        assert exc_info.value.filename == 3
+        assert exc_info.value.errno == errno.EBADF
+        assert exc_info.value.strerror == os.strerror(errno.EBADF)
+
+    def test_SetFromErrnoWithFilenameObject__PyList(self):
+        import errno, os
+
+        module = self.import_extension('foo', [
+                ("set_from_errno", "METH_NOARGS",
+                 '''
+                 errno = EBADF;
+                 PyObject *lst = Py_BuildValue("[iis]", 1, 2, "three");
+                 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, lst);
+                 Py_DECREF(lst);
+                 return NULL;
+                 '''),
+                ],
+                prologue="#include <errno.h>")
+        exc_info = raises(OSError, module.set_from_errno)
+        assert exc_info.value.filename == [1, 2, "three"]
+        assert exc_info.value.errno == errno.EBADF
+        assert exc_info.value.strerror == os.strerror(errno.EBADF)
+
+    def test_SetFromErrnoWithFilenameObject__PyTuple(self):
+        import errno, os
+
+        module = self.import_extension('foo', [
+                ("set_from_errno", "METH_NOARGS",
+                 '''
+                 errno = EBADF;
+                 PyObject *tuple = Py_BuildValue("(iis)", 1, 2, "three");
+                 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, tuple);
+                 Py_DECREF(tuple);
+                 return NULL;
+                 '''),
+                ],
+                prologue="#include <errno.h>")
+        exc_info = raises(OSError, module.set_from_errno)
+        assert exc_info.value.filename == (1, 2, "three")
+        assert exc_info.value.errno == errno.EBADF
+        assert exc_info.value.strerror == os.strerror(errno.EBADF)
+
+    def test_SetFromErrnoWithFilenameObject__Py_None(self):
+        import errno, os
+
+        module = self.import_extension('foo', [
+                ("set_from_errno", "METH_NOARGS",
+                 '''
+                 errno = EBADF;
+                 PyObject *none = Py_BuildValue("");
+                 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, none);
+                 Py_DECREF(none);
+                 return NULL;
+                 '''),
+                ],
+                prologue="#include <errno.h>")
+        exc_info = raises(OSError, module.set_from_errno)
+        assert exc_info.value.filename is None
+        assert exc_info.value.errno == errno.EBADF
+        assert exc_info.value.strerror == os.strerror(errno.EBADF)
+
     def test_PyErr_Display(self):
         module = self.import_extension('foo', [
             ("display_error", "METH_VARARGS",


More information about the pypy-commit mailing list