[pypy-commit] pypy ufuncapi: merge default into branch
mattip
noreply at buildbot.pypy.org
Thu Jan 15 20:55:54 CET 2015
Author: mattip <matti.picus at gmail.com>
Branch: ufuncapi
Changeset: r75362:a0cbd2bf13da
Date: 2015-01-15 21:55 +0200
http://bitbucket.org/pypy/pypy/changeset/a0cbd2bf13da/
Log: merge default into branch
diff too long, truncating to 2000 out of 6448 lines
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -28,7 +28,7 @@
DEALINGS IN THE SOFTWARE.
-PyPy Copyright holders 2003-2014
+PyPy Copyright holders 2003-2015
-----------------------------------
Except when otherwise stated (look for LICENSE files or information at
diff --git a/lib-python/2.7/distutils/unixccompiler.py b/lib-python/2.7/distutils/unixccompiler.py
--- a/lib-python/2.7/distutils/unixccompiler.py
+++ b/lib-python/2.7/distutils/unixccompiler.py
@@ -58,7 +58,7 @@
executables = {'preprocessor' : None,
'compiler' : ["cc"],
'compiler_so' : ["cc"],
- 'compiler_cxx' : ["cc"],
+ 'compiler_cxx' : ["c++"], # pypy: changed, 'cc' is bogus
'linker_so' : ["cc", "-shared"],
'linker_exe' : ["cc"],
'archiver' : ["ar", "-cr"],
diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py
--- a/lib-python/2.7/subprocess.py
+++ b/lib-python/2.7/subprocess.py
@@ -1589,7 +1589,7 @@
'copyfile' in caller.f_globals):
dest_dir = sys.pypy_resolvedirof(target_executable)
src_dir = sys.pypy_resolvedirof(sys.executable)
- for libname in ['libpypy-c.so']:
+ for libname in ['libpypy-c.so', 'libpypy-c.dylib']:
dest_library = os.path.join(dest_dir, libname)
src_library = os.path.join(src_dir, libname)
if os.path.exists(src_library):
diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py
--- a/lib_pypy/_functools.py
+++ b/lib_pypy/_functools.py
@@ -9,7 +9,10 @@
of the given arguments and keywords.
"""
- def __init__(self, func, *args, **keywords):
+ def __init__(self, *args, **keywords):
+ if not args:
+ raise TypeError('__init__() takes at least 2 arguments (1 given)')
+ func, args = args[0], args[1:]
if not callable(func):
raise TypeError("the first argument must be callable")
self._func = func
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -6,3 +6,8 @@
__version__ = "0.8.6"
__version_info__ = (0, 8, 6)
+
+# The verifier module file names are based on the CRC32 of a string that
+# contains the following version number. It may be older than __version__
+# if nothing is clearly incompatible.
+__version_verifier_modules__ = "0.8.6"
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -69,6 +69,7 @@
self._function_caches = []
self._libraries = []
self._cdefsources = []
+ self._windows_unicode = None
if hasattr(backend, 'set_ffi'):
backend.set_ffi(self)
for name in backend.__dict__:
@@ -77,6 +78,7 @@
#
with self._lock:
self.BVoidP = self._get_cached_btype(model.voidp_type)
+ self.BCharA = self._get_cached_btype(model.char_array_type)
if isinstance(backend, types.ModuleType):
# _cffi_backend: attach these constants to the class
if not hasattr(FFI, 'NULL'):
@@ -189,13 +191,16 @@
cdecl = self._typeof(cdecl)
return self._backend.alignof(cdecl)
- def offsetof(self, cdecl, fieldname):
+ def offsetof(self, cdecl, *fields_or_indexes):
"""Return the offset of the named field inside the given
- structure, which must be given as a C type name.
+ structure or array, which must be given as a C type name.
+ You can give several field names in case of nested structures.
+ You can also give numeric values which correspond to array
+ items, in case of an array type.
"""
if isinstance(cdecl, basestring):
cdecl = self._typeof(cdecl)
- return self._backend.typeoffsetof(cdecl, fieldname)[1]
+ return self._typeoffsetof(cdecl, *fields_or_indexes)[1]
def new(self, cdecl, init=None):
"""Allocate an instance according to the specified C type and
@@ -264,6 +269,16 @@
"""
return self._backend.buffer(cdata, size)
+ def from_buffer(self, python_buffer):
+ """Return a <cdata 'char[]'> that points to the data of the
+ given Python object, which must support the buffer interface.
+ Note that this is not meant to be used on the built-in types str,
+ unicode, or bytearray (you can build 'char[]' arrays explicitly)
+ but only on objects containing large quantities of raw data
+ in some other format, like 'array.array' or numpy arrays.
+ """
+ return self._backend.from_buffer(self.BCharA, python_buffer)
+
def callback(self, cdecl, python_callable=None, error=None):
"""Return a callback object or a decorator making such a
callback object. 'cdecl' must name a C function pointer type.
@@ -335,9 +350,23 @@
which requires binary compatibility in the signatures.
"""
from .verifier import Verifier, _caller_dir_pycache
+ #
+ # If set_unicode(True) was called, insert the UNICODE and
+ # _UNICODE macro declarations
+ if self._windows_unicode:
+ self._apply_windows_unicode(kwargs)
+ #
+ # Set the tmpdir here, and not in Verifier.__init__: it picks
+ # up the caller's directory, which we want to be the caller of
+ # ffi.verify(), as opposed to the caller of Veritier().
tmpdir = tmpdir or _caller_dir_pycache()
+ #
+ # Make a Verifier() and use it to load the library.
self.verifier = Verifier(self, source, tmpdir, **kwargs)
lib = self.verifier.load_library()
+ #
+ # Save the loaded library for keep-alive purposes, even
+ # if the caller doesn't keep it alive itself (it should).
self._libraries.append(lib)
return lib
@@ -356,15 +385,29 @@
with self._lock:
return model.pointer_cache(self, ctype)
- def addressof(self, cdata, field=None):
+ def addressof(self, cdata, *fields_or_indexes):
"""Return the address of a <cdata 'struct-or-union'>.
- If 'field' is specified, return the address of this field.
+ If 'fields_or_indexes' are given, returns the address of that
+ field or array item in the structure or array, recursively in
+ case of nested structures.
"""
ctype = self._backend.typeof(cdata)
- ctype, offset = self._backend.typeoffsetof(ctype, field)
+ if fields_or_indexes:
+ ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes)
+ else:
+ if ctype.kind == "pointer":
+ raise TypeError("addressof(pointer)")
+ offset = 0
ctypeptr = self._pointer_to(ctype)
return self._backend.rawaddressof(ctypeptr, cdata, offset)
+ def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes):
+ ctype, offset = self._backend.typeoffsetof(ctype, field_or_index)
+ for field1 in fields_or_indexes:
+ ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1)
+ offset += offset1
+ return ctype, offset
+
def include(self, ffi_to_include):
"""Includes the typedefs, structs, unions and enums defined
in another FFI instance. Usage is similar to a #include in C,
@@ -387,6 +430,44 @@
def from_handle(self, x):
return self._backend.from_handle(x)
+ def set_unicode(self, enabled_flag):
+ """Windows: if 'enabled_flag' is True, enable the UNICODE and
+ _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR
+ to be (pointers to) wchar_t. If 'enabled_flag' is False,
+ declare these types to be (pointers to) plain 8-bit characters.
+ This is mostly for backward compatibility; you usually want True.
+ """
+ if self._windows_unicode is not None:
+ raise ValueError("set_unicode() can only be called once")
+ enabled_flag = bool(enabled_flag)
+ if enabled_flag:
+ self.cdef("typedef wchar_t TBYTE;"
+ "typedef wchar_t TCHAR;"
+ "typedef const wchar_t *LPCTSTR;"
+ "typedef const wchar_t *PCTSTR;"
+ "typedef wchar_t *LPTSTR;"
+ "typedef wchar_t *PTSTR;"
+ "typedef TBYTE *PTBYTE;"
+ "typedef TCHAR *PTCHAR;")
+ else:
+ self.cdef("typedef char TBYTE;"
+ "typedef char TCHAR;"
+ "typedef const char *LPCTSTR;"
+ "typedef const char *PCTSTR;"
+ "typedef char *LPTSTR;"
+ "typedef char *PTSTR;"
+ "typedef TBYTE *PTBYTE;"
+ "typedef TCHAR *PTCHAR;")
+ self._windows_unicode = enabled_flag
+
+ def _apply_windows_unicode(self, kwds):
+ defmacros = kwds.get('define_macros', ())
+ if not isinstance(defmacros, (list, tuple)):
+ raise TypeError("'define_macros' must be a list or tuple")
+ defmacros = list(defmacros) + [('UNICODE', '1'),
+ ('_UNICODE', '1')]
+ kwds['define_macros'] = defmacros
+
def _load_backend_lib(backend, name, flags):
if name is None:
diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py
--- a/lib_pypy/cffi/backend_ctypes.py
+++ b/lib_pypy/cffi/backend_ctypes.py
@@ -169,6 +169,7 @@
class CTypesGenericPtr(CTypesData):
__slots__ = ['_address', '_as_ctype_ptr']
_automatic_casts = False
+ kind = "pointer"
@classmethod
def _newp(cls, init):
@@ -370,10 +371,12 @@
(CTypesPrimitive, type(source).__name__))
return source
#
+ kind1 = kind
class CTypesPrimitive(CTypesGenericPrimitive):
__slots__ = ['_value']
_ctype = ctype
_reftypename = '%s &' % name
+ kind = kind1
def __init__(self, value):
self._value = value
@@ -703,12 +706,13 @@
class struct_or_union(base_ctypes_class):
pass
struct_or_union.__name__ = '%s_%s' % (kind, name)
+ kind1 = kind
#
class CTypesStructOrUnion(CTypesBaseStructOrUnion):
__slots__ = ['_blob']
_ctype = struct_or_union
_reftypename = '%s &' % (name,)
- _kind = kind
+ _kind = kind = kind1
#
CTypesStructOrUnion._fix_class()
return CTypesStructOrUnion
@@ -994,27 +998,42 @@
def getcname(self, BType, replace_with):
return BType._get_c_name(replace_with)
- def typeoffsetof(self, BType, fieldname):
- if fieldname is not None and issubclass(BType, CTypesGenericPtr):
- BType = BType._BItem
- if not issubclass(BType, CTypesBaseStructOrUnion):
- raise TypeError("expected a struct or union ctype")
- if fieldname is None:
- return (BType, 0)
- else:
+ def typeoffsetof(self, BType, fieldname, num=0):
+ if isinstance(fieldname, str):
+ if num == 0 and issubclass(BType, CTypesGenericPtr):
+ BType = BType._BItem
+ if not issubclass(BType, CTypesBaseStructOrUnion):
+ raise TypeError("expected a struct or union ctype")
BField = BType._bfield_types[fieldname]
if BField is Ellipsis:
raise TypeError("not supported for bitfields")
return (BField, BType._offsetof(fieldname))
+ elif isinstance(fieldname, (int, long)):
+ if issubclass(BType, CTypesGenericArray):
+ BType = BType._CTPtr
+ if not issubclass(BType, CTypesGenericPtr):
+ raise TypeError("expected an array or ptr ctype")
+ BItem = BType._BItem
+ offset = BItem._get_size() * fieldname
+ if offset > sys.maxsize:
+ raise OverflowError
+ return (BItem, offset)
+ else:
+ raise TypeError(type(fieldname))
- def rawaddressof(self, BTypePtr, cdata, offset):
+ def rawaddressof(self, BTypePtr, cdata, offset=None):
if isinstance(cdata, CTypesBaseStructOrUnion):
ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata))
elif isinstance(cdata, CTypesGenericPtr):
+ if offset is None or not issubclass(type(cdata)._BItem,
+ CTypesBaseStructOrUnion):
+ raise TypeError("unexpected cdata type")
+ ptr = type(cdata)._to_ctypes(cdata)
+ elif isinstance(cdata, CTypesGenericArray):
ptr = type(cdata)._to_ctypes(cdata)
else:
raise TypeError("expected a <cdata 'struct-or-union'>")
- if offset != 0:
+ if offset:
ptr = ctypes.cast(
ctypes.c_void_p(
ctypes.cast(ptr, ctypes.c_void_p).value + offset),
diff --git a/lib_pypy/cffi/commontypes.py b/lib_pypy/cffi/commontypes.py
--- a/lib_pypy/cffi/commontypes.py
+++ b/lib_pypy/cffi/commontypes.py
@@ -29,6 +29,9 @@
result = model.PointerType(resolve_common_type(result[:-2]))
elif result in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
result = model.PrimitiveType(result)
+ elif result == 'set-unicode-needed':
+ raise api.FFIError("The Windows type %r is only available after "
+ "you call ffi.set_unicode()" % (commontype,))
else:
if commontype == result:
raise api.FFIError("Unsupported type: %r. Please file a bug "
@@ -86,8 +89,6 @@
"ULONGLONG": "unsigned long long",
"WCHAR": "wchar_t",
"SHORT": "short",
- "TBYTE": "WCHAR",
- "TCHAR": "WCHAR",
"UCHAR": "unsigned char",
"UINT": "unsigned int",
"UINT8": "unsigned char",
@@ -157,14 +158,12 @@
"LPCVOID": model.const_voidp_type,
"LPCWSTR": "const WCHAR *",
- "LPCTSTR": "LPCWSTR",
"LPDWORD": "DWORD *",
"LPHANDLE": "HANDLE *",
"LPINT": "int *",
"LPLONG": "long *",
"LPSTR": "CHAR *",
"LPWSTR": "WCHAR *",
- "LPTSTR": "LPWSTR",
"LPVOID": model.voidp_type,
"LPWORD": "WORD *",
"LRESULT": "LONG_PTR",
@@ -173,7 +172,6 @@
"PBYTE": "BYTE *",
"PCHAR": "CHAR *",
"PCSTR": "const CHAR *",
- "PCTSTR": "LPCWSTR",
"PCWSTR": "const WCHAR *",
"PDWORD": "DWORD *",
"PDWORDLONG": "DWORDLONG *",
@@ -200,9 +198,6 @@
"PSIZE_T": "SIZE_T *",
"PSSIZE_T": "SSIZE_T *",
"PSTR": "CHAR *",
- "PTBYTE": "TBYTE *",
- "PTCHAR": "TCHAR *",
- "PTSTR": "LPWSTR",
"PUCHAR": "UCHAR *",
"PUHALF_PTR": "UHALF_PTR *",
"PUINT": "UINT *",
@@ -240,6 +235,15 @@
"USN": "LONGLONG",
"VOID": model.void_type,
"WPARAM": "UINT_PTR",
+
+ "TBYTE": "set-unicode-needed",
+ "TCHAR": "set-unicode-needed",
+ "LPCTSTR": "set-unicode-needed",
+ "PCTSTR": "set-unicode-needed",
+ "LPTSTR": "set-unicode-needed",
+ "PTSTR": "set-unicode-needed",
+ "PTBYTE": "set-unicode-needed",
+ "PTCHAR": "set-unicode-needed",
})
return result
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -1,4 +1,3 @@
-
from . import api, model
from .commontypes import COMMON_TYPES, resolve_common_type
try:
@@ -209,6 +208,8 @@
def _add_constants(self, key, val):
if key in self._int_constants:
+ if self._int_constants[key] == val:
+ return # ignore identical double declarations
raise api.FFIError(
"multiple declarations of constant: %s" % (key,))
self._int_constants[key] = val
@@ -228,12 +229,18 @@
pyvalue = int(int_str, 0)
self._add_constants(key, pyvalue)
+ self._declare('macro ' + key, pyvalue)
elif value == '...':
self._declare('macro ' + key, value)
else:
- raise api.CDefError('only supports the syntax "#define '
- '%s ..." (literally) or "#define '
- '%s 0x1FF" for now' % (key, key))
+ raise api.CDefError(
+ 'only supports one of the following syntax:\n'
+ ' #define %s ... (literally dot-dot-dot)\n'
+ ' #define %s NUMBER (with NUMBER an integer'
+ ' constant, decimal/hex/octal)\n'
+ 'got:\n'
+ ' #define %s %s'
+ % (key, key, key, value))
def _parse_decl(self, decl):
node = decl.type
@@ -460,6 +467,8 @@
elif kind == 'union':
tp = model.UnionType(explicit_name, None, None, None)
elif kind == 'enum':
+ if explicit_name == '__dotdotdot__':
+ raise CDefError("Enums cannot be declared with ...")
tp = self._build_enum_type(explicit_name, type.values)
else:
raise AssertionError("kind = %r" % (kind,))
@@ -532,9 +541,24 @@
def _parse_constant(self, exprnode, partial_length_ok=False):
# for now, limited to expressions that are an immediate number
- # or negative number
+ # or positive/negative number
if isinstance(exprnode, pycparser.c_ast.Constant):
- return int(exprnode.value, 0)
+ s = exprnode.value
+ if s.startswith('0'):
+ if s.startswith('0x') or s.startswith('0X'):
+ return int(s, 16)
+ return int(s, 8)
+ elif '1' <= s[0] <= '9':
+ return int(s, 10)
+ elif s[0] == "'" and s[-1] == "'" and (
+ len(s) == 3 or (len(s) == 4 and s[1] == "\\")):
+ return ord(s[-2])
+ else:
+ raise api.CDefError("invalid constant %r" % (s,))
+ #
+ if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and
+ exprnode.op == '+'):
+ return self._parse_constant(exprnode.expr)
#
if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and
exprnode.op == '-'):
diff --git a/lib_pypy/cffi/ffiplatform.py b/lib_pypy/cffi/ffiplatform.py
--- a/lib_pypy/cffi/ffiplatform.py
+++ b/lib_pypy/cffi/ffiplatform.py
@@ -11,6 +11,9 @@
"""
+LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs',
+ 'extra_objects', 'depends']
+
def get_extension(srcfilename, modname, sources=(), **kwds):
from distutils.core import Extension
allsources = [srcfilename]
diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py
--- a/lib_pypy/cffi/model.py
+++ b/lib_pypy/cffi/model.py
@@ -235,6 +235,8 @@
BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist)
return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length)
+char_array_type = ArrayType(PrimitiveType('char'), None)
+
class StructOrUnionOrEnum(BaseTypeByIdentity):
_attrs_ = ('name',)
@@ -478,7 +480,7 @@
try:
res = getattr(ffi._backend, funcname)(*args)
except NotImplementedError as e:
- raise NotImplementedError("%r: %s" % (srctype, e))
+ raise NotImplementedError("%s: %r: %s" % (funcname, srctype, e))
# note that setdefault() on WeakValueDictionary is not atomic
# and contains a rare bug (http://bugs.python.org/issue19542);
# we have to use a lock and do it ourselves
diff --git a/lib_pypy/cffi/vengine_cpy.py b/lib_pypy/cffi/vengine_cpy.py
--- a/lib_pypy/cffi/vengine_cpy.py
+++ b/lib_pypy/cffi/vengine_cpy.py
@@ -65,7 +65,7 @@
# The following two 'chained_list_constants' items contains
# the head of these two chained lists, as a string that gives the
# call to do, if any.
- self._chained_list_constants = ['0', '0']
+ self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)']
#
prnt = self._prnt
# first paste some standard set of lines that are mostly '#define'
@@ -138,15 +138,22 @@
prnt()
prnt('#endif')
- def load_library(self):
+ def load_library(self, flags=None):
# XXX review all usages of 'self' here!
# import it as a new extension module
+ if hasattr(sys, "getdlopenflags"):
+ previous_flags = sys.getdlopenflags()
try:
+ if hasattr(sys, "setdlopenflags") and flags is not None:
+ sys.setdlopenflags(flags)
module = imp.load_dynamic(self.verifier.get_module_name(),
self.verifier.modulefilename)
except ImportError as e:
error = "importing %r: %s" % (self.verifier.modulefilename, e)
raise ffiplatform.VerificationError(error)
+ finally:
+ if hasattr(sys, "setdlopenflags"):
+ sys.setdlopenflags(previous_flags)
#
# call loading_cpy_struct() to get the struct layout inferred by
# the C compiler
@@ -228,7 +235,8 @@
converter = '_cffi_to_c_int'
extraarg = ', %s' % tp.name
else:
- converter = '_cffi_to_c_%s' % (tp.name.replace(' ', '_'),)
+ converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''),
+ tp.name.replace(' ', '_'))
errvalue = '-1'
#
elif isinstance(tp, model.PointerType):
@@ -267,8 +275,8 @@
self._prnt(' if (datasize != 0) {')
self._prnt(' if (datasize < 0)')
self._prnt(' %s;' % errcode)
- self._prnt(' %s = alloca(datasize);' % (tovar,))
- self._prnt(' memset((void *)%s, 0, datasize);' % (tovar,))
+ self._prnt(' %s = alloca((size_t)datasize);' % (tovar,))
+ self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,))
self._prnt(' if (_cffi_convert_array_from_object('
'(char *)%s, _cffi_type(%d), %s) < 0)' % (
tovar, self._gettypenum(tp), fromvar))
@@ -336,7 +344,7 @@
prnt = self._prnt
numargs = len(tp.args)
if numargs == 0:
- argname = 'no_arg'
+ argname = 'noarg'
elif numargs == 1:
argname = 'arg0'
else:
@@ -386,6 +394,9 @@
prnt(' Py_END_ALLOW_THREADS')
prnt()
#
+ prnt(' (void)self; /* unused */')
+ if numargs == 0:
+ prnt(' (void)noarg; /* unused */')
if result_code:
prnt(' return %s;' %
self._convert_expr_from_c(tp.result, 'result', 'result type'))
@@ -452,6 +463,7 @@
prnt('static void %s(%s *p)' % (checkfuncname, cname))
prnt('{')
prnt(' /* only to generate compile-time warnings or errors */')
+ prnt(' (void)p;')
for fname, ftype, fbitsize in tp.enumfields():
if (isinstance(ftype, model.PrimitiveType)
and ftype.is_integer_type()) or fbitsize >= 0:
@@ -482,6 +494,8 @@
prnt(' sizeof(((%s *)0)->%s),' % (cname, fname))
prnt(' -1')
prnt(' };')
+ prnt(' (void)self; /* unused */')
+ prnt(' (void)noarg; /* unused */')
prnt(' return _cffi_get_struct_layout(nums);')
prnt(' /* the next line is not executed, but compiled */')
prnt(' %s(0);' % (checkfuncname,))
@@ -578,7 +592,8 @@
# constants, likely declared with '#define'
def _generate_cpy_const(self, is_int, name, tp=None, category='const',
- vartp=None, delayed=True, size_too=False):
+ vartp=None, delayed=True, size_too=False,
+ check_value=None):
prnt = self._prnt
funcname = '_cffi_%s_%s' % (category, name)
prnt('static int %s(PyObject *lib)' % funcname)
@@ -590,6 +605,9 @@
else:
assert category == 'const'
#
+ if check_value is not None:
+ self._check_int_constant_value(name, check_value)
+ #
if not is_int:
if category == 'var':
realexpr = '&' + name
@@ -637,6 +655,27 @@
# ----------
# enums
+ def _check_int_constant_value(self, name, value, err_prefix=''):
+ prnt = self._prnt
+ if value <= 0:
+ prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % (
+ name, name, value))
+ else:
+ prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % (
+ name, name, value))
+ prnt(' char buf[64];')
+ prnt(' if ((%s) <= 0)' % name)
+ prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % name)
+ prnt(' else')
+ prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
+ name)
+ prnt(' PyErr_Format(_cffi_VerificationError,')
+ prnt(' "%s%s has the real value %s, not %s",')
+ prnt(' "%s", "%s", buf, "%d");' % (
+ err_prefix, name, value))
+ prnt(' return -1;')
+ prnt(' }')
+
def _enum_funcname(self, prefix, name):
# "$enum_$1" => "___D_enum____D_1"
name = name.replace('$', '___D_')
@@ -653,25 +692,8 @@
prnt('static int %s(PyObject *lib)' % funcname)
prnt('{')
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
- if enumvalue < 0:
- prnt(' if ((%s) >= 0 || (long)(%s) != %dL) {' % (
- enumerator, enumerator, enumvalue))
- else:
- prnt(' if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % (
- enumerator, enumerator, enumvalue))
- prnt(' char buf[64];')
- prnt(' if ((%s) < 0)' % enumerator)
- prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % enumerator)
- prnt(' else')
- prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
- enumerator)
- prnt(' PyErr_Format(_cffi_VerificationError,')
- prnt(' "enum %s: %s has the real value %s, '
- 'not %s",')
- prnt(' "%s", "%s", buf, "%d");' % (
- name, enumerator, enumvalue))
- prnt(' return -1;')
- prnt(' }')
+ self._check_int_constant_value(enumerator, enumvalue,
+ "enum %s: " % name)
prnt(' return %s;' % self._chained_list_constants[True])
self._chained_list_constants[True] = funcname + '(lib)'
prnt('}')
@@ -695,8 +717,11 @@
# macros: for now only for integers
def _generate_cpy_macro_decl(self, tp, name):
- assert tp == '...'
- self._generate_cpy_const(True, name)
+ if tp == '...':
+ check_value = None
+ else:
+ check_value = tp # an integer
+ self._generate_cpy_const(True, name, check_value=check_value)
_generate_cpy_macro_collecttype = _generate_nothing
_generate_cpy_macro_method = _generate_nothing
@@ -783,6 +808,24 @@
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
+ typedef __int8 int_least8_t;
+ typedef __int16 int_least16_t;
+ typedef __int32 int_least32_t;
+ typedef __int64 int_least64_t;
+ typedef unsigned __int8 uint_least8_t;
+ typedef unsigned __int16 uint_least16_t;
+ typedef unsigned __int32 uint_least32_t;
+ typedef unsigned __int64 uint_least64_t;
+ typedef __int8 int_fast8_t;
+ typedef __int16 int_fast16_t;
+ typedef __int32 int_fast32_t;
+ typedef __int64 int_fast64_t;
+ typedef unsigned __int8 uint_fast8_t;
+ typedef unsigned __int16 uint_fast16_t;
+ typedef unsigned __int32 uint_fast32_t;
+ typedef unsigned __int64 uint_fast64_t;
+ typedef __int64 intmax_t;
+ typedef unsigned __int64 uintmax_t;
# else
# include <stdint.h>
# endif
@@ -828,12 +871,15 @@
PyLong_FromLongLong((long long)(x)))
#define _cffi_from_c_int(x, type) \
- (((type)-1) > 0 ? /* unsigned */ \
- (sizeof(type) < sizeof(long) ? PyInt_FromLong(x) : \
- sizeof(type) == sizeof(long) ? PyLong_FromUnsignedLong(x) : \
- PyLong_FromUnsignedLongLong(x)) \
- : (sizeof(type) <= sizeof(long) ? PyInt_FromLong(x) : \
- PyLong_FromLongLong(x)))
+ (((type)-1) > 0 ? /* unsigned */ \
+ (sizeof(type) < sizeof(long) ? \
+ PyInt_FromLong((long)x) : \
+ sizeof(type) == sizeof(long) ? \
+ PyLong_FromUnsignedLong((unsigned long)x) : \
+ PyLong_FromUnsignedLongLong((unsigned long long)x)) : \
+ (sizeof(type) <= sizeof(long) ? \
+ PyInt_FromLong((long)x) : \
+ PyLong_FromLongLong((long long)x)))
#define _cffi_to_c_int(o, type) \
(sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
@@ -844,7 +890,7 @@
: (type)_cffi_to_c_i32(o)) : \
sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
: (type)_cffi_to_c_i64(o)) : \
- (Py_FatalError("unsupported size for type " #type), 0))
+ (Py_FatalError("unsupported size for type " #type), (type)0))
#define _cffi_to_c_i8 \
((int(*)(PyObject *))_cffi_exports[1])
@@ -907,6 +953,7 @@
{
PyObject *library;
int was_alive = (_cffi_types != NULL);
+ (void)self; /* unused */
if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError,
&library))
return NULL;
diff --git a/lib_pypy/cffi/vengine_gen.py b/lib_pypy/cffi/vengine_gen.py
--- a/lib_pypy/cffi/vengine_gen.py
+++ b/lib_pypy/cffi/vengine_gen.py
@@ -58,12 +58,12 @@
modname = self.verifier.get_module_name()
prnt("void %s%s(void) { }\n" % (prefix, modname))
- def load_library(self):
+ def load_library(self, flags=0):
# import it with the CFFI backend
backend = self.ffi._backend
# needs to make a path that contains '/', on Posix
filename = os.path.join(os.curdir, self.verifier.modulefilename)
- module = backend.load_library(filename)
+ module = backend.load_library(filename, flags)
#
# call loading_gen_struct() to get the struct layout inferred by
# the C compiler
@@ -235,6 +235,7 @@
prnt('static void %s(%s *p)' % (checkfuncname, cname))
prnt('{')
prnt(' /* only to generate compile-time warnings or errors */')
+ prnt(' (void)p;')
for fname, ftype, fbitsize in tp.enumfields():
if (isinstance(ftype, model.PrimitiveType)
and ftype.is_integer_type()) or fbitsize >= 0:
@@ -354,11 +355,20 @@
# ----------
# constants, likely declared with '#define'
- def _generate_gen_const(self, is_int, name, tp=None, category='const'):
+ def _generate_gen_const(self, is_int, name, tp=None, category='const',
+ check_value=None):
prnt = self._prnt
funcname = '_cffi_%s_%s' % (category, name)
self.export_symbols.append(funcname)
- if is_int:
+ if check_value is not None:
+ assert is_int
+ assert category == 'const'
+ prnt('int %s(char *out_error)' % funcname)
+ prnt('{')
+ self._check_int_constant_value(name, check_value)
+ prnt(' return 0;')
+ prnt('}')
+ elif is_int:
assert category == 'const'
prnt('int %s(long long *out_value)' % funcname)
prnt('{')
@@ -367,6 +377,7 @@
prnt('}')
else:
assert tp is not None
+ assert check_value is None
prnt(tp.get_c_name(' %s(void)' % funcname, name),)
prnt('{')
if category == 'var':
@@ -383,9 +394,13 @@
_loading_gen_constant = _loaded_noop
- def _load_constant(self, is_int, tp, name, module):
+ def _load_constant(self, is_int, tp, name, module, check_value=None):
funcname = '_cffi_const_%s' % name
- if is_int:
+ if check_value is not None:
+ assert is_int
+ self._load_known_int_constant(module, funcname)
+ value = check_value
+ elif is_int:
BType = self.ffi._typeof_locked("long long*")[0]
BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0]
function = module.load_function(BFunc, funcname)
@@ -396,6 +411,7 @@
BLongLong = self.ffi._typeof_locked("long long")[0]
value += (1 << (8*self.ffi.sizeof(BLongLong)))
else:
+ assert check_value is None
BFunc = self.ffi._typeof_locked(tp.get_c_name('(*)(void)', name))[0]
function = module.load_function(BFunc, funcname)
value = function()
@@ -410,6 +426,36 @@
# ----------
# enums
+ def _check_int_constant_value(self, name, value):
+ prnt = self._prnt
+ if value <= 0:
+ prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % (
+ name, name, value))
+ else:
+ prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % (
+ name, name, value))
+ prnt(' char buf[64];')
+ prnt(' if ((%s) <= 0)' % name)
+ prnt(' sprintf(buf, "%%ld", (long)(%s));' % name)
+ prnt(' else')
+ prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' %
+ name)
+ prnt(' sprintf(out_error, "%s has the real value %s, not %s",')
+ prnt(' "%s", buf, "%d");' % (name[:100], value))
+ prnt(' return -1;')
+ prnt(' }')
+
+ def _load_known_int_constant(self, module, funcname):
+ BType = self.ffi._typeof_locked("char[]")[0]
+ BFunc = self.ffi._typeof_locked("int(*)(char*)")[0]
+ function = module.load_function(BFunc, funcname)
+ p = self.ffi.new(BType, 256)
+ if function(p) < 0:
+ error = self.ffi.string(p)
+ if sys.version_info >= (3,):
+ error = str(error, 'utf-8')
+ raise ffiplatform.VerificationError(error)
+
def _enum_funcname(self, prefix, name):
# "$enum_$1" => "___D_enum____D_1"
name = name.replace('$', '___D_')
@@ -427,24 +473,7 @@
prnt('int %s(char *out_error)' % funcname)
prnt('{')
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
- if enumvalue < 0:
- prnt(' if ((%s) >= 0 || (long)(%s) != %dL) {' % (
- enumerator, enumerator, enumvalue))
- else:
- prnt(' if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % (
- enumerator, enumerator, enumvalue))
- prnt(' char buf[64];')
- prnt(' if ((%s) < 0)' % enumerator)
- prnt(' sprintf(buf, "%%ld", (long)(%s));' % enumerator)
- prnt(' else')
- prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' %
- enumerator)
- prnt(' sprintf(out_error,'
- ' "%s has the real value %s, not %s",')
- prnt(' "%s", buf, "%d");' % (
- enumerator[:100], enumvalue))
- prnt(' return -1;')
- prnt(' }')
+ self._check_int_constant_value(enumerator, enumvalue)
prnt(' return 0;')
prnt('}')
prnt()
@@ -456,16 +485,8 @@
tp.enumvalues = tuple(enumvalues)
tp.partial_resolved = True
else:
- BType = self.ffi._typeof_locked("char[]")[0]
- BFunc = self.ffi._typeof_locked("int(*)(char*)")[0]
funcname = self._enum_funcname(prefix, name)
- function = module.load_function(BFunc, funcname)
- p = self.ffi.new(BType, 256)
- if function(p) < 0:
- error = self.ffi.string(p)
- if sys.version_info >= (3,):
- error = str(error, 'utf-8')
- raise ffiplatform.VerificationError(error)
+ self._load_known_int_constant(module, funcname)
def _loaded_gen_enum(self, tp, name, module, library):
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
@@ -476,13 +497,21 @@
# macros: for now only for integers
def _generate_gen_macro_decl(self, tp, name):
- assert tp == '...'
- self._generate_gen_const(True, name)
+ if tp == '...':
+ check_value = None
+ else:
+ check_value = tp # an integer
+ self._generate_gen_const(True, name, check_value=check_value)
_loading_gen_macro = _loaded_noop
def _loaded_gen_macro(self, tp, name, module, library):
- value = self._load_constant(True, tp, name, module)
+ if tp == '...':
+ check_value = None
+ else:
+ check_value = tp # an integer
+ value = self._load_constant(True, tp, name, module,
+ check_value=check_value)
setattr(library, name, value)
type(library)._cffi_dir.append(name)
@@ -565,6 +594,24 @@
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
+ typedef __int8 int_least8_t;
+ typedef __int16 int_least16_t;
+ typedef __int32 int_least32_t;
+ typedef __int64 int_least64_t;
+ typedef unsigned __int8 uint_least8_t;
+ typedef unsigned __int16 uint_least16_t;
+ typedef unsigned __int32 uint_least32_t;
+ typedef unsigned __int64 uint_least64_t;
+ typedef __int8 int_fast8_t;
+ typedef __int16 int_fast16_t;
+ typedef __int32 int_fast32_t;
+ typedef __int64 int_fast64_t;
+ typedef unsigned __int8 uint_fast8_t;
+ typedef unsigned __int16 uint_fast16_t;
+ typedef unsigned __int32 uint_fast32_t;
+ typedef unsigned __int64 uint_fast64_t;
+ typedef __int64 intmax_t;
+ typedef unsigned __int64 uintmax_t;
# else
# include <stdint.h>
# endif
diff --git a/lib_pypy/cffi/verifier.py b/lib_pypy/cffi/verifier.py
--- a/lib_pypy/cffi/verifier.py
+++ b/lib_pypy/cffi/verifier.py
@@ -1,12 +1,23 @@
-import sys, os, binascii, imp, shutil
-from . import __version__
+import sys, os, binascii, shutil
+from . import __version_verifier_modules__
from . import ffiplatform
+if sys.version_info >= (3, 3):
+ import importlib.machinery
+ def _extension_suffixes():
+ return importlib.machinery.EXTENSION_SUFFIXES[:]
+else:
+ import imp
+ def _extension_suffixes():
+ return [suffix for suffix, _, type in imp.get_suffixes()
+ if type == imp.C_EXTENSION]
+
class Verifier(object):
def __init__(self, ffi, preamble, tmpdir=None, modulename=None,
- ext_package=None, tag='', force_generic_engine=False, **kwds):
+ ext_package=None, tag='', force_generic_engine=False,
+ source_extension='.c', flags=None, relative_to=None, **kwds):
self.ffi = ffi
self.preamble = preamble
if not modulename:
@@ -14,14 +25,15 @@
vengine_class = _locate_engine_class(ffi, force_generic_engine)
self._vengine = vengine_class(self)
self._vengine.patch_extension_kwds(kwds)
- self.kwds = kwds
+ self.flags = flags
+ self.kwds = self.make_relative_to(kwds, relative_to)
#
if modulename:
if tag:
raise TypeError("can't specify both 'modulename' and 'tag'")
else:
- key = '\x00'.join([sys.version[:3], __version__, preamble,
- flattened_kwds] +
+ key = '\x00'.join([sys.version[:3], __version_verifier_modules__,
+ preamble, flattened_kwds] +
ffi._cdefsources)
if sys.version_info >= (3,):
key = key.encode('utf-8')
@@ -33,7 +45,7 @@
k1, k2)
suffix = _get_so_suffixes()[0]
self.tmpdir = tmpdir or _caller_dir_pycache()
- self.sourcefilename = os.path.join(self.tmpdir, modulename + '.c')
+ self.sourcefilename = os.path.join(self.tmpdir, modulename + source_extension)
self.modulefilename = os.path.join(self.tmpdir, modulename + suffix)
self.ext_package = ext_package
self._has_source = False
@@ -97,6 +109,20 @@
def generates_python_module(self):
return self._vengine._gen_python_module
+ def make_relative_to(self, kwds, relative_to):
+ if relative_to and os.path.dirname(relative_to):
+ dirname = os.path.dirname(relative_to)
+ kwds = kwds.copy()
+ for key in ffiplatform.LIST_OF_FILE_NAMES:
+ if key in kwds:
+ lst = kwds[key]
+ if not isinstance(lst, (list, tuple)):
+ raise TypeError("keyword '%s' should be a list or tuple"
+ % (key,))
+ lst = [os.path.join(dirname, fn) for fn in lst]
+ kwds[key] = lst
+ return kwds
+
# ----------
def _locate_module(self):
@@ -148,7 +174,10 @@
def _load_library(self):
assert self._has_module
- return self._vengine.load_library()
+ if self.flags is not None:
+ return self._vengine.load_library(self.flags)
+ else:
+ return self._vengine.load_library()
# ____________________________________________________________
@@ -181,6 +210,9 @@
def _caller_dir_pycache():
if _TMPDIR:
return _TMPDIR
+ result = os.environ.get('CFFI_TMPDIR')
+ if result:
+ return result
filename = sys._getframe(2).f_code.co_filename
return os.path.abspath(os.path.join(os.path.dirname(filename),
'__pycache__'))
@@ -222,11 +254,7 @@
pass
def _get_so_suffixes():
- suffixes = []
- for suffix, mode, type in imp.get_suffixes():
- if type == imp.C_EXTENSION:
- suffixes.append(suffix)
-
+ suffixes = _extension_suffixes()
if not suffixes:
# bah, no C_EXTENSION available. Occurs on pypy without cpyext
if sys.platform == 'win32':
diff --git a/pypy/doc/embedding.rst b/pypy/doc/embedding.rst
--- a/pypy/doc/embedding.rst
+++ b/pypy/doc/embedding.rst
@@ -30,12 +30,10 @@
Initialize threads. Only need to be called if there are any threads involved
-.. function:: long pypy_setup_home(char* home, int verbose);
+.. function:: int pypy_setup_home(char* home, int verbose);
This function searches the PyPy standard library starting from the given
- "PyPy home directory". It is not strictly necessary to execute it before
- running Python code, but without it you will not be able to import any
- non-builtin module from the standard library. The arguments are:
+ "PyPy home directory". The arguments are:
* ``home``: NULL terminated path to an executable inside the pypy directory
(can be a .so name, can be made up)
@@ -84,25 +82,36 @@
const char source[] = "print 'hello from pypy'";
- int main()
+ int main(void)
{
- int res;
+ int res;
- rpython_startup_code();
- // pypy_setup_home() is not needed in this trivial example
- res = pypy_execute_source((char*)source);
- if (res) {
- printf("Error calling pypy_execute_source!\n");
- }
- return res;
+ rpython_startup_code();
+ res = pypy_setup_home("/opt/pypy/bin/libpypy-c.so", 1);
+ if (res) {
+ printf("Error setting pypy home!\n");
+ return 1;
+ }
+
+ res = pypy_execute_source((char*)source);
+ if (res) {
+ printf("Error calling pypy_execute_source!\n");
+ }
+ return res;
}
-If we save it as ``x.c`` now, compile it and run it with::
+If we save it as ``x.c`` now, compile it and run it (on linux) with::
fijal at hermann:/opt/pypy$ gcc -o x x.c -lpypy-c -L.
fijal at hermann:/opt/pypy$ LD_LIBRARY_PATH=. ./x
hello from pypy
+on OSX it is necessary to set the rpath of the binary if one wants to link to it::
+
+ gcc -o x x.c -lpypy-c -L. -Wl,-rpath -Wl, at executable_path
+ ./x
+ hello from pypy
+
Worked!
.. note:: If the compilation fails because of missing PyPy.h header file,
diff --git a/pypy/doc/install.rst b/pypy/doc/install.rst
--- a/pypy/doc/install.rst
+++ b/pypy/doc/install.rst
@@ -38,14 +38,13 @@
and not move the binary there, else PyPy would not be able to find its
library.
-If you want to install 3rd party libraries, the most convenient way is to
-install distribute_ and pip_:
+If you want to install 3rd party libraries, the most convenient way is
+to install pip_ (unless you want to install virtualenv as explained
+below; then you can directly use pip inside virtualenvs):
.. code-block:: console
- $ curl -O http://python-distribute.org/distribute_setup.py
- $ curl -O https://raw.githubusercontent.com/pypa/pip/master/contrib/get-pip.py
- $ ./pypy-2.1/bin/pypy distribute_setup.py
+ $ curl -O https://bootstrap.pypa.io/get-pip.py
$ ./pypy-2.1/bin/pypy get-pip.py
$ ./pypy-2.1/bin/pip install pygments # for example
@@ -69,7 +68,6 @@
Note that bin/python is now a symlink to bin/pypy.
-.. _distribute: http://www.python-distribute.org/
.. _pip: http://pypi.python.org/pypi/pip
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -101,7 +101,7 @@
if space.is_none(w_path):
if verbose:
debug("Failed to find library based on pypy_find_stdlib")
- return 1
+ return rffi.cast(rffi.INT, 1)
space.startup()
space.call_function(w_pathsetter, w_path)
# import site
@@ -109,13 +109,13 @@
import_ = space.getattr(space.getbuiltinmodule('__builtin__'),
space.wrap('__import__'))
space.call_function(import_, space.wrap('site'))
- return 0
+ return rffi.cast(rffi.INT, 0)
except OperationError, e:
if verbose:
debug("OperationError:")
debug(" operror-type: " + e.w_type.getname(space))
debug(" operror-value: " + space.str_w(space.str(e.get_w_value(space))))
- return -1
+ return rffi.cast(rffi.INT, -1)
@entrypoint('main', [rffi.CCHARP], c_name='pypy_execute_source')
def pypy_execute_source(ll_source):
@@ -234,8 +234,7 @@
enable_translationmodules(config)
config.translation.suggest(check_str_without_nul=True)
- if sys.platform.startswith('linux'):
- config.translation.suggest(shared=True)
+ config.translation.suggest(shared=True)
if config.translation.thread:
config.objspace.usemodules.thread = True
diff --git a/pypy/module/__builtin__/app_io.py b/pypy/module/__builtin__/app_io.py
--- a/pypy/module/__builtin__/app_io.py
+++ b/pypy/module/__builtin__/app_io.py
@@ -86,9 +86,11 @@
def print_(*args, **kwargs):
"""The new-style print function from py3k."""
- fp = kwargs.pop("file", sys.stdout)
+ fp = kwargs.pop("file", None)
if fp is None:
- return
+ fp = sys.stdout
+ if fp is None:
+ return
def write(data):
if not isinstance(data, basestring):
data = str(data)
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -651,9 +651,12 @@
out = sys.stdout = StringIO.StringIO()
try:
pr("Hello,", "person!")
+ pr("2nd line", file=None)
+ sys.stdout = None
+ pr("nowhere")
finally:
sys.stdout = save
- assert out.getvalue() == "Hello, person!\n"
+ assert out.getvalue() == "Hello, person!\n2nd line\n"
out = StringIO.StringIO()
pr("Hello,", "person!", file=out)
assert out.getvalue() == "Hello, person!\n"
@@ -668,7 +671,6 @@
result = out.getvalue()
assert isinstance(result, unicode)
assert result == u"Hello, person!\n"
- pr("Hello", file=None) # This works.
out = StringIO.StringIO()
pr(None, file=out)
assert out.getvalue() == "None\n"
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -34,6 +34,7 @@
'newp_handle': 'handle.newp_handle',
'from_handle': 'handle.from_handle',
'_get_types': 'func._get_types',
+ 'from_buffer': 'func.from_buffer',
'string': 'func.string',
'buffer': 'cbuffer.buffer',
diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -45,8 +45,9 @@
#
cif_descr = self.getfunctype().cif_descr
if not cif_descr:
- raise OperationError(space.w_NotImplementedError,
- space.wrap("callbacks with '...'"))
+ raise oefmt(space.w_NotImplementedError,
+ "%s: callback with unsupported argument or "
+ "return type or with '...'", self.getfunctype().name)
res = clibffi.c_ffi_prep_closure(self.get_closure(), cif_descr.cif,
invoke_callback,
rffi.cast(rffi.VOIDP, self.unique_id))
@@ -98,7 +99,7 @@
def print_error(self, operr, extra_line):
space = self.space
- operr.write_unraisable(space, "callback ", self.w_callable,
+ operr.write_unraisable(space, "cffi callback ", self.w_callable,
with_traceback=True, extra_line=extra_line)
def write_error_return_value(self, ll_res):
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -440,6 +440,25 @@
return "handle to %s" % (self.space.str_w(w_repr),)
+class W_CDataFromBuffer(W_CData):
+ _attrs_ = ['buf', 'length', 'w_keepalive']
+ _immutable_fields_ = ['buf', 'length', 'w_keepalive']
+
+ def __init__(self, space, cdata, ctype, buf, w_object):
+ W_CData.__init__(self, space, cdata, ctype)
+ self.buf = buf
+ self.length = buf.getlength()
+ self.w_keepalive = w_object
+
+ def get_array_length(self):
+ return self.length
+
+ def _repr_extra(self):
+ w_repr = self.space.repr(self.w_keepalive)
+ return "buffer len %d from '%s' object" % (
+ self.length, self.space.type(self.w_keepalive).name)
+
+
W_CData.typedef = TypeDef(
'_cffi_backend.CData',
__module__ = '_cffi_backend',
diff --git a/pypy/module/_cffi_backend/ctypearray.py b/pypy/module/_cffi_backend/ctypearray.py
--- a/pypy/module/_cffi_backend/ctypearray.py
+++ b/pypy/module/_cffi_backend/ctypearray.py
@@ -107,6 +107,9 @@
return self.space.w_None
return W_CTypePtrOrArray._fget(self, attrchar)
+ def typeoffsetof_index(self, index):
+ return self.ctptr.typeoffsetof_index(index)
+
class W_CDataIter(W_Root):
_immutable_fields_ = ['ctitem', 'cdata', '_stop'] # but not '_next'
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -27,6 +27,8 @@
_immutable_fields_ = ['fargs[*]', 'ellipsis', 'cif_descr']
kind = "function"
+ cif_descr = lltype.nullptr(CIF_DESCRIPTION)
+
def __init__(self, space, fargs, fresult, ellipsis):
extra = self._compute_extra_text(fargs, fresult, ellipsis)
size = rffi.sizeof(rffi.VOIDP)
@@ -41,7 +43,17 @@
# at all. The cif is computed on every call from the actual
# types passed in. For all other functions, the cif_descr
# is computed here.
- CifDescrBuilder(fargs, fresult).rawallocate(self)
+ builder = CifDescrBuilder(fargs, fresult)
+ try:
+ builder.rawallocate(self)
+ except OperationError, e:
+ if not e.match(space, space.w_NotImplementedError):
+ raise
+ # else, eat the NotImplementedError. We will get the
+ # exception if we see an actual call
+ if self.cif_descr: # should not be True, but you never know
+ lltype.free(self.cif_descr, flavor='raw')
+ self.cif_descr = lltype.nullptr(CIF_DESCRIPTION)
def new_ctypefunc_completing_argtypes(self, args_w):
space = self.space
@@ -57,10 +69,12 @@
"argument %d passed in the variadic part needs to "
"be a cdata object (got %T)", i + 1, w_obj)
fvarargs[i] = ct
+ # xxx call instantiate() directly. It's a bit of a hack.
ctypefunc = instantiate(W_CTypeFunc)
ctypefunc.space = space
ctypefunc.fargs = fvarargs
ctypefunc.ctitem = self.ctitem
+ #ctypefunc.cif_descr = NULL --- already provided as the default
CifDescrBuilder(fvarargs, self.ctitem).rawallocate(ctypefunc)
return ctypefunc
@@ -178,8 +192,6 @@
# ____________________________________________________________
-W_CTypeFunc.cif_descr = lltype.nullptr(CIF_DESCRIPTION) # default value
-
BIG_ENDIAN = sys.byteorder == 'big'
USE_C_LIBFFI_MSVC = getattr(clibffi, 'USE_C_LIBFFI_MSVC', False)
@@ -295,18 +307,18 @@
nflat = 0
for i, cf in enumerate(ctype.fields_list):
if cf.is_bitfield():
- raise OperationError(space.w_NotImplementedError,
- space.wrap("cannot pass as argument or return value "
- "a struct with bit fields"))
+ raise oefmt(space.w_NotImplementedError,
+ "ctype '%s' not supported as argument or return value"
+ " (it is a struct with bit fields)", ctype.name)
flat = 1
ct = cf.ctype
while isinstance(ct, ctypearray.W_CTypeArray):
flat *= ct.length
ct = ct.ctitem
if flat <= 0:
- raise OperationError(space.w_NotImplementedError,
- space.wrap("cannot pass as argument or return value "
- "a struct with a zero-length array"))
+ raise oefmt(space.w_NotImplementedError,
+ "ctype '%s' not supported as argument or return value"
+ " (it is a struct with a zero-length array)", ctype.name)
nflat += flat
if USE_C_LIBFFI_MSVC and is_result_type:
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -142,12 +142,14 @@
raise oefmt(space.w_ValueError, "ctype '%s' is of unknown alignment",
self.name)
- def typeoffsetof(self, fieldname):
+ def typeoffsetof_field(self, fieldname, following):
space = self.space
- if fieldname is None:
- msg = "expected a struct or union ctype"
- else:
- msg = "expected a struct or union ctype, or a pointer to one"
+ msg = "with a field name argument, expected a struct or union ctype"
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+
+ def typeoffsetof_index(self, index):
+ space = self.space
+ msg = "with an integer argument, expected an array or pointer ctype"
raise OperationError(space.w_TypeError, space.wrap(msg))
def rawaddressof(self, cdata, offset):
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -308,24 +308,36 @@
def getcfield(self, attr):
return self.ctitem.getcfield(attr)
- def typeoffsetof(self, fieldname):
- if fieldname is None:
- return W_CTypePtrBase.typeoffsetof(self, fieldname)
- else:
- return self.ctitem.typeoffsetof(fieldname)
+ def typeoffsetof_field(self, fieldname, following):
+ if following == 0:
+ return self.ctitem.typeoffsetof_field(fieldname, -1)
+ return W_CTypePtrBase.typeoffsetof_field(self, fieldname, following)
+
+ def typeoffsetof_index(self, index):
+ space = self.space
+ ctitem = self.ctitem
+ if ctitem.size < 0:
+ raise OperationError(space.w_TypeError,
+ space.wrap("pointer to opaque"))
+ try:
+ offset = ovfcheck(index * ctitem.size)
+ except OverflowError:
+ raise OperationError(space.w_OverflowError,
+ space.wrap("array offset would overflow a ssize_t"))
+ return ctitem, offset
def rawaddressof(self, cdata, offset):
from pypy.module._cffi_backend.ctypestruct import W_CTypeStructOrUnion
space = self.space
ctype2 = cdata.ctype
if (isinstance(ctype2, W_CTypeStructOrUnion) or
- (isinstance(ctype2, W_CTypePtrOrArray) and
- isinstance(ctype2.ctitem, W_CTypeStructOrUnion))):
+ isinstance(ctype2, W_CTypePtrOrArray)):
ptrdata = rffi.ptradd(cdata._cdata, offset)
return cdataobj.W_CData(space, ptrdata, self)
else:
raise OperationError(space.w_TypeError,
- space.wrap("expected a 'cdata struct-or-union' object"))
+ space.wrap("expected a cdata struct/union/array/pointer"
+ " object"))
def _fget(self, attrchar):
if attrchar == 'i': # item
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -65,9 +65,7 @@
keepalive_until_here(ob)
return ob
- def typeoffsetof(self, fieldname):
- if fieldname is None:
- return (self, 0)
+ def typeoffsetof_field(self, fieldname, following):
self.check_complete()
space = self.space
try:
diff --git a/pypy/module/_cffi_backend/func.py b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -48,13 +48,28 @@
align = w_ctype.alignof()
return space.wrap(align)
- at unwrap_spec(w_ctype=ctypeobj.W_CType, fieldname="str_or_None")
-def typeoffsetof(space, w_ctype, fieldname):
- ctype, offset = w_ctype.typeoffsetof(fieldname)
+ at unwrap_spec(w_ctype=ctypeobj.W_CType, following=int)
+def typeoffsetof(space, w_ctype, w_field_or_index, following=0):
+ try:
+ fieldname = space.str_w(w_field_or_index)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ try:
+ index = space.int_w(w_field_or_index)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ raise OperationError(space.w_TypeError,
+ space.wrap("field name or array index expected"))
+ ctype, offset = w_ctype.typeoffsetof_index(index)
+ else:
+ ctype, offset = w_ctype.typeoffsetof_field(fieldname, following)
+ #
return space.newtuple([space.wrap(ctype), space.wrap(offset)])
@unwrap_spec(w_ctype=ctypeobj.W_CType, w_cdata=cdataobj.W_CData, offset=int)
-def rawaddressof(space, w_ctype, w_cdata, offset=0):
+def rawaddressof(space, w_ctype, w_cdata, offset):
return w_ctype.rawaddressof(w_cdata, offset)
# ____________________________________________________________
@@ -76,3 +91,32 @@
def _get_types(space):
return space.newtuple([space.gettypefor(cdataobj.W_CData),
space.gettypefor(ctypeobj.W_CType)])
+
+# ____________________________________________________________
+
+ at unwrap_spec(w_ctype=ctypeobj.W_CType)
+def from_buffer(space, w_ctype, w_x):
+ from pypy.module._cffi_backend import ctypearray, ctypeprim
+ #
+ if (not isinstance(w_ctype, ctypearray.W_CTypeArray) or
+ not isinstance(w_ctype.ctptr.ctitem, ctypeprim.W_CTypePrimitiveChar)):
+ raise oefmt(space.w_TypeError,
+ "needs 'char[]', got '%s'", w_ctype.name)
+ #
+ # xxx do we really need to implement the same mess as in CPython 2.7
+ # w.r.t. buffers and memoryviews??
+ try:
+ buf = space.readbuf_w(w_x)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ buf = space.buffer_w(w_x, space.BUF_SIMPLE)
+ try:
+ _cdata = buf.get_raw_address()
+ except ValueError:
+ raise oefmt(space.w_TypeError,
+ "from_buffer() got a '%T' object, which supports the "
+ "buffer interface but cannot be rendered as a plain "
+ "raw address on PyPy", w_x)
+ #
+ return cdataobj.W_CDataFromBuffer(space, _cdata, w_ctype, buf, w_x)
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1030,11 +1030,12 @@
BInt = new_primitive_type("int")
BArray0 = new_array_type(new_pointer_type(BInt), 0)
BStruct = new_struct_type("struct foo")
+ BStructP = new_pointer_type(BStruct)
complete_struct_or_union(BStruct, [('a', BArray0)])
- py.test.raises(NotImplementedError, new_function_type,
- (BStruct,), BInt, False)
- py.test.raises(NotImplementedError, new_function_type,
- (BInt,), BStruct, False)
+ BFunc = new_function_type((BStruct,), BInt, False)
+ py.test.raises(NotImplementedError, cast(BFunc, 123), cast(BStructP, 123))
+ BFunc2 = new_function_type((BInt,), BStruct, False)
+ py.test.raises(NotImplementedError, cast(BFunc2, 123), 123)
def test_call_function_9():
BInt = new_primitive_type("int")
@@ -1174,7 +1175,7 @@
assert sys.stderr.getvalue() == ''
assert f(10000) == -42
assert matches(sys.stderr.getvalue(), """\
-From callback <function$Zcb1 at 0x$>:
+From cffi callback <function$Zcb1 at 0x$>:
Traceback (most recent call last):
File "$", line $, in Zcb1
$
@@ -1186,7 +1187,7 @@
bigvalue = 20000
assert f(bigvalue) == -42
assert matches(sys.stderr.getvalue(), """\
-From callback <function$Zcb1 at 0x$>:
+From cffi callback <function$Zcb1 at 0x$>:
Trying to convert the result back to C:
OverflowError: integer 60000 does not fit 'short'
""")
@@ -1805,7 +1806,8 @@
new_function_type((), new_pointer_type(BFunc))
BUnion = new_union_type("union foo_u")
complete_struct_or_union(BUnion, [])
- py.test.raises(NotImplementedError, new_function_type, (), BUnion)
+ BFunc = new_function_type((), BUnion)
+ py.test.raises(NotImplementedError, cast(BFunc, 123))
py.test.raises(TypeError, new_function_type, (), BArray)
def test_struct_return_in_func():
@@ -2525,13 +2527,32 @@
('a2', BChar, -1),
('a3', BChar, -1)])
py.test.raises(TypeError, typeoffsetof, BStructPtr, None)
- assert typeoffsetof(BStruct, None) == (BStruct, 0)
+ py.test.raises(TypeError, typeoffsetof, BStruct, None)
assert typeoffsetof(BStructPtr, 'a1') == (BChar, 0)
assert typeoffsetof(BStruct, 'a1') == (BChar, 0)
assert typeoffsetof(BStructPtr, 'a2') == (BChar, 1)
assert typeoffsetof(BStruct, 'a3') == (BChar, 2)
+ assert typeoffsetof(BStructPtr, 'a2', 0) == (BChar, 1)
+ assert typeoffsetof(BStruct, u+'a3') == (BChar, 2)
+ py.test.raises(TypeError, typeoffsetof, BStructPtr, 'a2', 1)
py.test.raises(KeyError, typeoffsetof, BStructPtr, 'a4')
py.test.raises(KeyError, typeoffsetof, BStruct, 'a5')
+ py.test.raises(TypeError, typeoffsetof, BStruct, 42)
+ py.test.raises(TypeError, typeoffsetof, BChar, 'a1')
+
+def test_typeoffsetof_array():
+ BInt = new_primitive_type("int")
+ BIntP = new_pointer_type(BInt)
+ BArray = new_array_type(BIntP, None)
+ py.test.raises(TypeError, typeoffsetof, BArray, None)
+ py.test.raises(TypeError, typeoffsetof, BArray, 'a1')
+ assert typeoffsetof(BArray, 51) == (BInt, 51 * size_of_int())
+ assert typeoffsetof(BIntP, 51) == (BInt, 51 * size_of_int())
+ assert typeoffsetof(BArray, -51) == (BInt, -51 * size_of_int())
+ MAX = sys.maxsize // size_of_int()
+ assert typeoffsetof(BArray, MAX) == (BInt, MAX * size_of_int())
+ assert typeoffsetof(BIntP, MAX) == (BInt, MAX * size_of_int())
+ py.test.raises(OverflowError, typeoffsetof, BArray, MAX + 1)
def test_typeoffsetof_no_bitfield():
BInt = new_primitive_type("int")
@@ -2551,17 +2572,26 @@
assert repr(p) == "<cdata 'struct foo *' owning 3 bytes>"
s = p[0]
assert repr(s) == "<cdata 'struct foo' owning 3 bytes>"
- a = rawaddressof(BStructPtr, s)
+ a = rawaddressof(BStructPtr, s, 0)
assert repr(a).startswith("<cdata 'struct foo *' 0x")
- py.test.raises(TypeError, rawaddressof, BStruct, s)
- b = rawaddressof(BCharP, s)
+ py.test.raises(TypeError, rawaddressof, BStruct, s, 0)
+ b = rawaddressof(BCharP, s, 0)
assert b == cast(BCharP, p)
- c = rawaddressof(BStructPtr, a)
+ c = rawaddressof(BStructPtr, a, 0)
assert c == a
- py.test.raises(TypeError, rawaddressof, BStructPtr, cast(BChar, '?'))
+ py.test.raises(TypeError, rawaddressof, BStructPtr, cast(BChar, '?'), 0)
#
d = rawaddressof(BCharP, s, 1)
assert d == cast(BCharP, p) + 1
+ #
+ e = cast(BCharP, 109238)
+ f = rawaddressof(BCharP, e, 42)
+ assert f == e + 42
+ #
+ BCharA = new_array_type(BCharP, None)
+ e = newp(BCharA, 50)
+ f = rawaddressof(BCharP, e, 42)
+ assert f == e + 42
def test_newp_signed_unsigned_char():
BCharArray = new_array_type(
@@ -3195,6 +3225,20 @@
('a2', BChar, 5)],
None, -1, -1, SF_PACKED)
+def test_from_buffer():
+ import array
+ a = array.array('H', [10000, 20000, 30000])
+ BChar = new_primitive_type("char")
+ BCharP = new_pointer_type(BChar)
+ BCharA = new_array_type(BCharP, None)
+ c = from_buffer(BCharA, a)
+ assert typeof(c) is BCharA
+ assert len(c) == 6
+ assert repr(c) == "<cdata 'char[]' buffer len 6 from 'array.array' object>"
+ p = new_pointer_type(new_primitive_type("unsigned short"))
+ cast(p, c)[1] += 500
+ assert list(a) == [10000, 20500, 30000]
+
def test_version():
# this test is here mostly for PyPy
assert __version__ == "0.8.6"
diff --git a/pypy/module/_cffi_backend/test/test_c.py b/pypy/module/_cffi_backend/test/test_c.py
--- a/pypy/module/_cffi_backend/test/test_c.py
+++ b/pypy/module/_cffi_backend/test/test_c.py
@@ -30,7 +30,7 @@
class AppTestC(object):
"""Populated below, hack hack hack."""
- spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO'))
+ spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO', 'array'))
def setup_class(cls):
testfuncs_w = []
diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -565,7 +565,7 @@
# Flush the write buffer if necessary
if self.writable:
- self._writer_flush_unlocked(space)
+ self._flush_and_rewind_unlocked(space)
self._reader_reset_buf()
# Read whole blocks, and don't buffer them
diff --git a/pypy/module/_io/test/test_io.py b/pypy/module/_io/test/test_io.py
--- a/pypy/module/_io/test/test_io.py
+++ b/pypy/module/_io/test/test_io.py
@@ -362,3 +362,32 @@
f.read(1)
f.seek(-1, 1)
f.write(b'')
+
+ def test_issue1902_2(self):
+ import _io
+ with _io.open(self.tmpfile, 'w+b', 4096) as f:
+ f.write(b'\xff' * 13569)
+ f.flush()
+ f.seek(0, 0)
+
+ f.read(1)
+ f.seek(-1, 1)
+ f.write(b'\xff')
+ f.seek(1, 0)
+ f.read(4123)
+ f.seek(-4123, 1)
+
+ def test_issue1902_3(self):
+ import _io
+ buffer_size = 4096
+ with _io.open(self.tmpfile, 'w+b', buffer_size) as f:
+ f.write(b'\xff' * buffer_size * 3)
+ f.flush()
+ f.seek(0, 0)
+
+ f.read(1)
+ f.seek(-1, 1)
+ f.write(b'\xff')
+ f.seek(1, 0)
+ f.read(buffer_size * 2)
+ assert f.tell() == 1 + buffer_size * 2
diff --git a/pypy/module/micronumpy/descriptor.py b/pypy/module/micronumpy/descriptor.py
--- a/pypy/module/micronumpy/descriptor.py
+++ b/pypy/module/micronumpy/descriptor.py
@@ -394,7 +394,7 @@
alignment = space.int_w(space.getitem(w_data, space.wrap(6)))
if (w_names == space.w_None) != (w_fields == space.w_None):
- raise oefmt(space.w_ValueError, "inconsistent fields and names")
+ raise oefmt(space.w_ValueError, "inconsistent fields and names in Numpy dtype unpickling")
self.byteorder = endian
self.shape = []
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -1234,7 +1234,8 @@
d = np.dtype(('<f8', 2))
exc = raises(ValueError, "d.__setstate__((3, '|', None, ('f0', 'f1'), None, 16, 1, 0))")
- assert exc.value[0] == 'inconsistent fields and names'
+ inconsistent = 'inconsistent fields and names in Numpy dtype unpickling'
+ assert exc.value[0] == inconsistent
assert d.fields is None
assert d.shape == (2,)
assert d.subdtype is not None
@@ -1242,7 +1243,7 @@
d = np.dtype(('<f8', 2))
exc = raises(ValueError, "d.__setstate__((3, '|', None, None, {'f0': (np.dtype('float64'), 0), 'f1': (np.dtype('float64'), 8)}, 16, 1, 0))")
- assert exc.value[0] == 'inconsistent fields and names'
+ assert exc.value[0] == inconsistent
assert d.fields is None
assert d.shape == (2,)
assert d.subdtype is not None
@@ -1283,7 +1284,11 @@
from cPickle import loads, dumps
d = dtype([("x", "int32"), ("y", "int32"), ("z", "int32"), ("value", float)])
- assert d.__reduce__() == (dtype, ('V20', 0, 1), (3, '|', None, ('x', 'y', 'z', 'value'), {'y': (dtype('int32'), 4), 'x': (dtype('int32'), 0), 'z': (dtype('int32'), 8), 'value': (dtype('float64'), 12)}, 20, 1, 0))
+ assert d.__reduce__() == (dtype, ('V20', 0, 1), (3, '|', None,
+ ('x', 'y', 'z', 'value'),
+ {'y': (dtype('int32'), 4), 'x': (dtype('int32'), 0),
+ 'z': (dtype('int32'), 8), 'value': (dtype('float64'), 12),
+ }, 20, 1, 0))
new_d = loads(dumps(d))
diff --git a/pypy/module/micronumpy/tool/numready/main.py b/pypy/module/micronumpy/tool/numready/main.py
--- a/pypy/module/micronumpy/tool/numready/main.py
+++ b/pypy/module/micronumpy/tool/numready/main.py
@@ -71,6 +71,10 @@
lines = subprocess.check_output(args).splitlines()
items = SearchableSet()
for line in lines:
+ # since calling a function in "search.py" may have printed side effects,
+ # make sure the line begins with '[UT] : '
+ if not (line[:1] in KINDS.values() and line[1:4] == ' : '):
+ continue
kind, name = line.split(" : ", 1)
subitems = []
if kind == KINDS["TYPE"] and name in SPECIAL_NAMES and attr is None:
@@ -97,7 +101,15 @@
"nditer"]
def main(argv):
- cpy_items = find_numpy_items("/usr/bin/python")
+ if 'help' in argv[1]:
+ print '\nusage: python', os.path.dirname(__file__), '<path-to-pypy> [<outfile.html>] [<path-to-cpython-with-numpy>]'
+ print ' path-to-cpython-with-numpy defaults to "/usr/bin/python"\n'
+ return
+ if len(argv) < 4:
+ cpython = '/usr/bin/python'
+ else:
+ cpython = argv[3]
+ cpy_items = find_numpy_items(cpython)
pypy_items = find_numpy_items(argv[1])
ver = get_version_str(argv[1])
all_items = []
diff --git a/pypy/module/micronumpy/tool/numready/search.py b/pypy/module/micronumpy/tool/numready/search.py
--- a/pypy/module/micronumpy/tool/numready/search.py
+++ b/pypy/module/micronumpy/tool/numready/search.py
@@ -23,6 +23,15 @@
if attr is None and name.startswith("_"):
continue
subobj = getattr(obj, name)
+ if subobj is None:
+ continue
+ if isinstance(subobj, types.FunctionType):
+ try:
+ subobj()
+ except NotImplementedError:
+ continue
+ except:
+ pass
if isinstance(subobj, types.TypeType):
kind = KINDS["TYPE"]
else:
diff --git a/pypy/module/termios/__init__.py b/pypy/module/termios/__init__.py
--- a/pypy/module/termios/__init__.py
+++ b/pypy/module/termios/__init__.py
@@ -1,5 +1,7 @@
from pypy.interpreter.mixedmodule import MixedModule
+from rpython.rlib import rtermios
+
class Module(MixedModule):
"This module provides an interface to the Posix calls for tty I/O control.\n\
For a complete description of these calls, see the Posix or Unix manual\n\
@@ -23,10 +25,6 @@
'error' : 'space.fromcache(interp_termios.Cache).w_error',
}
-# XXX this is extremaly not-portable, but how to prevent this?
-
-import termios
-for i in dir(termios):
- val = getattr(termios, i)
- if i.isupper() and type(val) is int:
- Module.interpleveldefs[i] = "space.wrap(%s)" % val
+ for name in rtermios.all_constants:
+ value = getattr(rtermios, name)
+ interpleveldefs[name] = "space.wrap(%s)" % value
diff --git a/pypy/module/termios/interp_termios.py b/pypy/module/termios/interp_termios.py
--- a/pypy/module/termios/interp_termios.py
+++ b/pypy/module/termios/interp_termios.py
@@ -6,7 +6,6 @@
from pypy.interpreter.gateway import unwrap_spec
from pypy.interpreter.error import wrap_oserror, OperationError
from rpython.rlib import rtermios
-import termios
class Cache:
def __init__(self, space):
@@ -52,9 +51,9 @@
l_w = [space.wrap(i) for i in [iflag, oflag, cflag, lflag, ispeed, ospeed]]
# last one need to be chosen carefully
cc_w = [space.wrap(i) for i in cc]
- if lflag & termios.ICANON:
- cc_w[termios.VMIN] = space.wrap(ord(cc[termios.VMIN][0]))
- cc_w[termios.VTIME] = space.wrap(ord(cc[termios.VTIME][0]))
+ if lflag & rtermios.ICANON:
+ cc_w[rtermios.VMIN] = space.wrap(ord(cc[rtermios.VMIN][0]))
+ cc_w[rtermios.VTIME] = space.wrap(ord(cc[rtermios.VTIME][0]))
w_cc = space.newlist(cc_w)
l_w.append(w_cc)
return space.newlist(l_w)
@@ -63,14 +62,14 @@
def tcsendbreak(space, w_fd, duration):
fd = space.c_filedescriptor_w(w_fd)
try:
- termios.tcsendbreak(fd, duration)
+ rtermios.tcsendbreak(fd, duration)
except OSError, e:
raise convert_error(space, e)
def tcdrain(space, w_fd):
fd = space.c_filedescriptor_w(w_fd)
try:
- termios.tcdrain(fd)
+ rtermios.tcdrain(fd)
except OSError, e:
raise convert_error(space, e)
@@ -78,7 +77,7 @@
def tcflush(space, w_fd, queue):
fd = space.c_filedescriptor_w(w_fd)
try:
- termios.tcflush(fd, queue)
+ rtermios.tcflush(fd, queue)
except OSError, e:
raise convert_error(space, e)
@@ -86,6 +85,6 @@
def tcflow(space, w_fd, action):
fd = space.c_filedescriptor_w(w_fd)
try:
- termios.tcflow(fd, action)
+ rtermios.tcflow(fd, action)
except OSError, e:
raise convert_error(space, e)
diff --git a/pypy/module/termios/test/test_termios.py b/pypy/module/termios/test/test_termios.py
--- a/pypy/module/termios/test/test_termios.py
+++ b/pypy/module/termios/test/test_termios.py
@@ -136,7 +136,7 @@
val = getattr(termios, name)
if name.isupper() and type(val) is int:
d[name] = val
- assert d == self.orig_module_dict
+ assert sorted(d.items()) == sorted(self.orig_module_dict.items())
def test_error(self):
import termios, errno, os
diff --git a/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py b/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py
--- a/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py
@@ -2,7 +2,7 @@
import py
import platform
import sys, ctypes
-from cffi import FFI, CDefError
+from cffi import FFI, CDefError, FFIError
from pypy.module.test_lib_pypy.cffi_tests.support import *
SIZE_OF_INT = ctypes.sizeof(ctypes.c_int)
@@ -917,6 +917,16 @@
assert int(invalid_value) == 2
assert ffi.string(invalid_value) == "2"
+ def test_enum_char_hex_oct(self):
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef(r"enum foo{A='!', B='\'', C=0x10, D=010, E=- 0x10, F=-010};")
+ assert ffi.string(ffi.cast("enum foo", ord('!'))) == "A"
+ assert ffi.string(ffi.cast("enum foo", ord("'"))) == "B"
+ assert ffi.string(ffi.cast("enum foo", 16)) == "C"
+ assert ffi.string(ffi.cast("enum foo", 8)) == "D"
+ assert ffi.string(ffi.cast("enum foo", -16)) == "E"
+ assert ffi.string(ffi.cast("enum foo", -8)) == "F"
+
def test_array_of_struct(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a, b; };")
@@ -950,6 +960,25 @@
assert ffi.offsetof("struct foo", "b") == 4
assert ffi.offsetof("struct foo", "c") == 8
+ def test_offsetof_nested(self):
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("struct foo { int a, b, c; };"
+ "struct bar { struct foo d, e; };")
+ assert ffi.offsetof("struct bar", "e") == 12
+ py.test.raises(KeyError, ffi.offsetof, "struct bar", "e.a")
+ assert ffi.offsetof("struct bar", "e", "a") == 12
+ assert ffi.offsetof("struct bar", "e", "b") == 16
+ assert ffi.offsetof("struct bar", "e", "c") == 20
+
+ def test_offsetof_array(self):
+ ffi = FFI(backend=self.Backend())
+ assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int")
+ assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int")
+ ffi.cdef("struct bar { int a, b; int c[99]; };")
+ assert ffi.offsetof("struct bar", "c") == 2 * ffi.sizeof("int")
+ assert ffi.offsetof("struct bar", "c", 0) == 2 * ffi.sizeof("int")
+ assert ffi.offsetof("struct bar", "c", 51) == 53 * ffi.sizeof("int")
+
def test_alignof(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { char a; short b; char c; };")
@@ -1482,8 +1511,10 @@
p = ffi.new("struct foo_s *")
a = ffi.addressof(p[0])
assert repr(a).startswith("<cdata 'struct foo_s *' 0x")
+ assert a == p
py.test.raises(TypeError, ffi.addressof, p)
py.test.raises((AttributeError, TypeError), ffi.addressof, 5)
+ py.test.raises(TypeError, ffi.addressof, ffi.cast("int", 5))
More information about the pypy-commit
mailing list