diff options
| -rw-r--r-- | c/call_python.c | 22 | ||||
| -rw-r--r-- | testing/cffi0/test_function.py | 32 | ||||
| -rw-r--r-- | testing/cffi1/test_recompiler.py | 12 | ||||
| -rw-r--r-- | testing/support.py | 37 |
4 files changed, 51 insertions, 52 deletions
diff --git a/c/call_python.c b/c/call_python.c index 8545ea8..4db966a 100644 --- a/c/call_python.c +++ b/c/call_python.c @@ -90,29 +90,21 @@ static void _cffi_call_python(struct _cffi_externpy_s *externpy, char *args) at least 8 bytes in size. */ save_errno(); - { -#ifdef WITH_THREAD - PyGILState_STATE state = PyGILState_Ensure(); -#endif if (externpy->reserved1 == NULL) { /* not initialized! */ - PyObject *f = PySys_GetObject("stderr"); - if (f != NULL) { - PyFile_WriteString("extern \"Python\": function ", f); - PyFile_WriteString(externpy->name, f); - PyFile_WriteString("() called, but no code was attached " - "to it yet with @ffi.def_extern(). " - "Returning 0.\n", f); - } + fprintf(stderr, "extern \"Python\": function %s() called, " + "but no code was attached to it yet with " + "@ffi.def_extern(). Returning 0.\n", externpy->name); memset(args, 0, externpy->size_of_result); } else { +#ifdef WITH_THREAD + PyGILState_STATE state = PyGILState_Ensure(); +#endif general_invoke_callback(0, args, args, externpy->reserved1); - } - #ifdef WITH_THREAD - PyGILState_Release(state); + PyGILState_Release(state); #endif } restore_errno(); diff --git a/testing/cffi0/test_function.py b/testing/cffi0/test_function.py index b4c98e7..8fdcc86 100644 --- a/testing/cffi0/test_function.py +++ b/testing/cffi0/test_function.py @@ -4,6 +4,7 @@ import math, os, sys import ctypes.util from cffi.backend_ctypes import CTypesBackend from testing.udir import udir +from testing.support import FdWriteCapture try: from StringIO import StringIO @@ -11,29 +12,6 @@ except ImportError: from io import StringIO -class FdWriteCapture(object): - """xxx limited to capture at most 512 bytes of output, according - to the Posix manual.""" - - def __init__(self, capture_fd): - self.capture_fd = capture_fd - - def __enter__(self): - self.read_fd, self.write_fd = os.pipe() - self.copy_fd = os.dup(self.capture_fd) - os.dup2(self.write_fd, self.capture_fd) - return self - - def __exit__(self, *args): - os.dup2(self.copy_fd, self.capture_fd) - os.close(self.copy_fd) - os.close(self.write_fd) - self._value = os.read(self.read_fd, 512) - os.close(self.read_fd) - - def getvalue(self): - return self._value - lib_m = 'm' if sys.platform == 'win32': #there is a small chance this fails on Mingw via environ $CC @@ -135,7 +113,7 @@ class TestFunction(object): """) ffi.C = ffi.dlopen(None) ffi.C.fputs # fetch before capturing, for easier debugging - with FdWriteCapture(2) as fd: + with FdWriteCapture() as fd: ffi.C.fputs(b"hello\n", ffi.C.stderr) ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() @@ -151,7 +129,7 @@ class TestFunction(object): """) ffi.C = ffi.dlopen(None) ffi.C.fputs # fetch before capturing, for easier debugging - with FdWriteCapture(2) as fd: + with FdWriteCapture() as fd: ffi.C.fputs(b"hello\n", ffi.C.stderr) ffi.C.fputs(b" world\n", ffi.C.stderr) res = fd.getvalue() @@ -166,7 +144,7 @@ class TestFunction(object): void *stderr; """) ffi.C = ffi.dlopen(None) - with FdWriteCapture(2) as fd: + with FdWriteCapture() as fd: ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n") ffi.C.fprintf(ffi.C.stderr, b"hello, %s!\n", ffi.new("char[]", b"world")) @@ -228,7 +206,7 @@ class TestFunction(object): fptr = ffi.cast("int(*)(const char *txt, void *)", ffi.C.fputs) assert fptr == ffi.C.fputs assert repr(fptr).startswith("<cdata 'int(*)(char *, void *)' 0x") - with FdWriteCapture(2) as fd: + with FdWriteCapture() as fd: fptr(b"world\n", ffi.C.stderr) res = fd.getvalue() assert res == b'world\n' diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py index ee77c5c..81c43ef 100644 --- a/testing/cffi1/test_recompiler.py +++ b/testing/cffi1/test_recompiler.py @@ -4,7 +4,7 @@ from cffi import FFI, VerificationError, FFIError from cffi import recompiler from testing.udir import udir from testing.support import u -from StringIO import StringIO +from testing.support import FdWriteCapture, StdErrCapture def check_type_table(input, expected_output, included=None): @@ -1486,14 +1486,6 @@ def test_win32_calling_convention_3(): pt = ptr_call2(ffi.addressof(lib, 'cb2')) assert (pt.x, pt.y) == (99*500*999, -99*500*999) -class StdErrCapture(object): - def __enter__(self): - self.old_stderr = sys.stderr - sys.stderr = f = StringIO() - return f - def __exit__(self, *args): - sys.stderr = self.old_stderr - def test_extern_python_1(): ffi = FFI() ffi.cdef(""" @@ -1506,7 +1498,7 @@ def test_extern_python_1(): """) lib = verify(ffi, 'test_extern_python_1', "") assert ffi.typeof(lib.bar) == ffi.typeof("int(*)(int, int)") - with StdErrCapture() as f: + with FdWriteCapture() as f: res = lib.bar(4, 5) assert res == 0 assert f.getvalue() == ( diff --git a/testing/support.py b/testing/support.py index 17c56cd..17ee621 100644 --- a/testing/support.py +++ b/testing/support.py @@ -17,3 +17,40 @@ else: u = "" unicode = str long = int + + +class StdErrCapture(object): + """Capture writes to sys.stderr (not to the underlying file descriptor).""" + def __enter__(self): + import StringIO + self.old_stderr = sys.stderr + sys.stderr = f = StringIO.StringIO() + return f + def __exit__(self, *args): + sys.stderr = self.old_stderr + + +class FdWriteCapture(object): + """xxx limited to capture at most 512 bytes of output, according + to the Posix manual.""" + + def __init__(self, capture_fd=2): # stderr by default + self.capture_fd = capture_fd + + def __enter__(self): + import os + self.read_fd, self.write_fd = os.pipe() + self.copy_fd = os.dup(self.capture_fd) + os.dup2(self.write_fd, self.capture_fd) + return self + + def __exit__(self, *args): + import os + os.dup2(self.copy_fd, self.capture_fd) + os.close(self.copy_fd) + os.close(self.write_fd) + self._value = os.read(self.read_fd, 512) + os.close(self.read_fd) + + def getvalue(self): + return self._value |
