[pypy-svn] r73399 - in pypy/branch/cpython-extension/pypy/module/cpyext: . include test
fijal at codespeak.net
fijal at codespeak.net
Mon Apr 5 03:32:56 CEST 2010
Author: fijal
Date: Mon Apr 5 03:32:54 2010
New Revision: 73399
Added:
pypy/branch/cpython-extension/pypy/module/cpyext/include/mysnprintf.c
pypy/branch/cpython-extension/pypy/module/cpyext/include/pythonrun.c
pypy/branch/cpython-extension/pypy/module/cpyext/misc.py (contents, props changed)
Modified:
pypy/branch/cpython-extension/pypy/module/cpyext/__init__.py
pypy/branch/cpython-extension/pypy/module/cpyext/api.py
pypy/branch/cpython-extension/pypy/module/cpyext/include/Python.h
pypy/branch/cpython-extension/pypy/module/cpyext/include/pythonrun.h
pypy/branch/cpython-extension/pypy/module/cpyext/modsupport.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_pyerrors.py
Log:
include more stuff from CPython. I believe I should test it while I'm at
adding it...
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/__init__.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/__init__.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/__init__.py Mon Apr 5 03:32:54 2010
@@ -51,6 +51,7 @@
import pypy.module.cpyext.mapping
import pypy.module.cpyext.iterator
import pypy.module.cpyext.unicodeobject
+import pypy.module.cpyext.misc
# now that all rffi_platform.Struct types are registered, configure them
api.configure_types()
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/api.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/api.py Mon Apr 5 03:32:54 2010
@@ -556,7 +556,9 @@
include_dir / "pyerrors.c",
include_dir / "modsupport.c",
include_dir / "getargs.c",
- include_dir / "stringobject.c"],
+ include_dir / "stringobject.c",
+ include_dir / "mysnprintf.c",
+ include_dir / "pythonrun.c"],
separate_module_sources = [code],
export_symbols=export_symbols_eci,
**kwds
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/include/Python.h
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/include/Python.h (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/include/Python.h Mon Apr 5 03:32:54 2010
@@ -12,6 +12,7 @@
#define SIZEOF_VOID_P sizeof(void *)
#define WITH_DOC_STRINGS
#define HAVE_UNICODE
+#define INT_MAX (1 << (8 * sizeof(int) - 1))
/* Compat stuff */
#ifndef _WIN32
@@ -56,6 +57,7 @@
#include <assert.h>
#include <locale.h>
#include <ctype.h>
+#include <stdlib.h>
#include "boolobject.h"
#include "floatobject.h"
Added: pypy/branch/cpython-extension/pypy/module/cpyext/include/mysnprintf.c
==============================================================================
--- (empty file)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/include/mysnprintf.c Mon Apr 5 03:32:54 2010
@@ -0,0 +1,105 @@
+#include "Python.h"
+#include <ctype.h>
+
+/* snprintf() wrappers. If the platform has vsnprintf, we use it, else we
+ emulate it in a half-hearted way. Even if the platform has it, we wrap
+ it because platforms differ in what vsnprintf does in case the buffer
+ is too small: C99 behavior is to return the number of characters that
+ would have been written had the buffer not been too small, and to set
+ the last byte of the buffer to \0. At least MS _vsnprintf returns a
+ negative value instead, and fills the entire buffer with non-\0 data.
+
+ The wrappers ensure that str[size-1] is always \0 upon return.
+
+ PyOS_snprintf and PyOS_vsnprintf never write more than size bytes
+ (including the trailing '\0') into str.
+
+ If the platform doesn't have vsnprintf, and the buffer size needed to
+ avoid truncation exceeds size by more than 512, Python aborts with a
+ Py_FatalError.
+
+ Return value (rv):
+
+ When 0 <= rv < size, the output conversion was unexceptional, and
+ rv characters were written to str (excluding a trailing \0 byte at
+ str[rv]).
+
+ When rv >= size, output conversion was truncated, and a buffer of
+ size rv+1 would have been needed to avoid truncation. str[size-1]
+ is \0 in this case.
+
+ When rv < 0, "something bad happened". str[size-1] is \0 in this
+ case too, but the rest of str is unreliable. It could be that
+ an error in format codes was detected by libc, or on platforms
+ with a non-C99 vsnprintf simply that the buffer wasn't big enough
+ to avoid truncation, or on platforms without any vsnprintf that
+ PyMem_Malloc couldn't obtain space for a temp buffer.
+
+ CAUTION: Unlike C99, str != NULL and size > 0 are required.
+*/
+
+int
+PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
+{
+ int len; /* # bytes written, excluding \0 */
+#ifdef HAVE_SNPRINTF
+#define _PyOS_vsnprintf_EXTRA_SPACE 1
+#else
+#define _PyOS_vsnprintf_EXTRA_SPACE 512
+ char *buffer;
+#endif
+ assert(str != NULL);
+ assert(size > 0);
+ assert(format != NULL);
+ /* We take a size_t as input but return an int. Sanity check
+ * our input so that it won't cause an overflow in the
+ * vsnprintf return value or the buffer malloc size. */
+ if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
+ len = -666;
+ goto Done;
+ }
+
+#ifdef HAVE_SNPRINTF
+ len = vsnprintf(str, size, format, va);
+#else
+ /* Emulate it. */
+ buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
+ if (buffer == NULL) {
+ len = -666;
+ goto Done;
+ }
+
+ len = vsprintf(buffer, format, va);
+ if (len < 0)
+ /* ignore the error */;
+
+ else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
+ Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
+
+ else {
+ const size_t to_copy = (size_t)len < size ?
+ (size_t)len : size - 1;
+ assert(to_copy < size);
+ memcpy(str, buffer, to_copy);
+ str[to_copy] = '\0';
+ }
+ PyMem_FREE(buffer);
+#endif
+Done:
+ if (size > 0)
+ str[size-1] = '\0';
+ return len;
+#undef _PyOS_vsnprintf_EXTRA_SPACE
+}
+
+int
+PyOS_snprintf(char *str, size_t size, const char *format, ...)
+{
+ int rc;
+ va_list va;
+
+ va_start(va, format);
+ rc = PyOS_vsnprintf(str, size, format, va);
+ va_end(va);
+ return rc;
+}
Added: pypy/branch/cpython-extension/pypy/module/cpyext/include/pythonrun.c
==============================================================================
--- (empty file)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/include/pythonrun.c Mon Apr 5 03:32:54 2010
@@ -0,0 +1,31 @@
+
+#include "Python.h"
+
+void
+Py_FatalError(const char *msg)
+{
+ fprintf(stderr, "Fatal Python error: %s\n", msg);
+ fflush(stderr); /* it helps in Windows debug build */
+
+#ifdef MS_WINDOWS
+ {
+ size_t len = strlen(msg);
+ WCHAR* buffer;
+ size_t i;
+
+ /* Convert the message to wchar_t. This uses a simple one-to-one
+ conversion, assuming that the this error message actually uses ASCII
+ only. If this ceases to be true, we will have to convert. */
+ buffer = alloca( (len+1) * (sizeof *buffer));
+ for( i=0; i<=len; ++i)
+ buffer[i] = msg[i];
+ OutputDebugStringW(L"Fatal Python error: ");
+ OutputDebugStringW(buffer);
+ OutputDebugStringW(L"\n");
+ }
+#ifdef _DEBUG
+ DebugBreak();
+#endif
+#endif /* MS_WINDOWS */
+ abort();
+}
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/include/pythonrun.h
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/include/pythonrun.h (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/include/pythonrun.h Mon Apr 5 03:32:54 2010
@@ -6,6 +6,7 @@
extern "C" {
#endif
+ void Py_FatalError(const char *msg);
#ifdef __cplusplus
}
Added: pypy/branch/cpython-extension/pypy/module/cpyext/misc.py
==============================================================================
--- (empty file)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/misc.py Mon Apr 5 03:32:54 2010
@@ -0,0 +1,14 @@
+
+from pypy.module.cpyext.api import cpython_api_c
+
+ at cpython_api_c()
+def Py_FatalError():
+ pass
+
+ at cpython_api_c()
+def PyOS_snprintf():
+ pass
+
+ at cpython_api_c()
+def PyOS_vsnprintf():
+ pass
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/modsupport.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/modsupport.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/modsupport.py Mon Apr 5 03:32:54 2010
@@ -1,12 +1,16 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import cpython_api, cpython_struct, \
- METH_STATIC, METH_CLASS, METH_COEXIST, CANNOT_FAIL
+ METH_STATIC, METH_CLASS, METH_COEXIST, CANNOT_FAIL, cpython_api_c
from pypy.module.cpyext.pyobject import PyObject, register_container
from pypy.interpreter.module import Module
from pypy.module.cpyext.methodobject import W_PyCFunctionObject, PyCFunction_NewEx, PyDescr_NewMethod, PyMethodDef, PyCFunction
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.interpreter.error import OperationError
+ at cpython_api_c()
+def PyModule_AddObject():
+ pass
+
def PyImport_AddModule(space, name):
w_name = space.wrap(name)
w_mod = space.wrap(Module(space, w_name))
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_pyerrors.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_pyerrors.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_pyerrors.py Mon Apr 5 03:32:54 2010
@@ -1,7 +1,9 @@
from pypy.module.cpyext.state import State
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
-from pypy.rpython.lltypesystem import rffi
+from pypy.rpython.lltypesystem import rffi, ll2ctypes
+
+from pypy.interpreter.gateway import interp2app
class TestExceptions(BaseApiTest):
def test_GivenExceptionMatches(self, space, api):
@@ -55,6 +57,17 @@
class AppTestFetch(AppTestCpythonExtensionBase):
+ def setup_class(cls):
+ AppTestCpythonExtensionBase.setup_class.im_func(cls)
+ space = cls.space
+
+ def set_errno(num):
+ import pdb
+ pdb.set_trace()
+ ll2ctypes.TLS.errno = num
+
+ cls.w_set_errno = space.wrap(interp2app(set_errno, unwrap_spec=[int]))
+
def test_occurred(self):
module = self.import_extension('foo', [
("check_error", "METH_NOARGS",
@@ -78,13 +91,12 @@
module = self.import_extension('foo', [
("set_from_errno", "METH_NOARGS",
'''
- int close(int);
- close(-1);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
'''),
])
try:
+ self.set_errno(errno.EBADF)
module.set_from_errno()
except OSError, e:
assert e.errno == errno.EBADF
More information about the Pypy-commit
mailing list