[pypy-commit] pypy py3.5: hg merge default
arigo
pypy.commits at gmail.com
Tue Jan 24 09:54:08 EST 2017
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r89739:a0364a1c7f67
Date: 2017-01-24 15:46 +0100
http://bitbucket.org/pypy/pypy/changeset/a0364a1c7f67/
Log: hg merge default
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: cffi
-Version: 1.9.2
+Version: 1.10.0
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
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
@@ -1,11 +1,11 @@
__all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError',
'FFIError']
-from .api import FFI, CDefError, FFIError
-from .ffiplatform import VerificationError, VerificationMissing
+from .api import FFI
+from .error import CDefError, FFIError, VerificationError, VerificationMissing
-__version__ = "1.9.2"
-__version_info__ = (1, 9, 2)
+__version__ = "1.10.0"
+__version_info__ = (1, 10, 0)
# 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__
diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h
--- a/lib_pypy/cffi/_embedding.h
+++ b/lib_pypy/cffi/_embedding.h
@@ -233,7 +233,7 @@
f = PySys_GetObject((char *)"stderr");
if (f != NULL && f != Py_None) {
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
- "\ncompiled with cffi version: 1.9.2"
+ "\ncompiled with cffi version: 1.10.0"
"\n_cffi_backend module: ", f);
modules = PyImport_GetModuleDict();
mod = PyDict_GetItemString(modules, "_cffi_backend");
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
@@ -1,5 +1,7 @@
import sys, types
from .lock import allocate_lock
+from .error import CDefError
+from . import model
try:
callable
@@ -15,17 +17,6 @@
basestring = str
-class FFIError(Exception):
- pass
-
-class CDefError(Exception):
- def __str__(self):
- try:
- line = 'line %d: ' % (self.args[1].coord.line,)
- except (AttributeError, TypeError, IndexError):
- line = ''
- return '%s%s' % (line, self.args[0])
-
class FFI(object):
r'''
@@ -49,18 +40,27 @@
"""Create an FFI instance. The 'backend' argument is used to
select a non-default backend, mostly for tests.
"""
- from . import cparser, model
if backend is None:
# You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with
# _cffi_backend.so compiled.
import _cffi_backend as backend
from . import __version__
- assert backend.__version__ == __version__, \
- "version mismatch, %s != %s" % (backend.__version__, __version__)
+ if backend.__version__ != __version__:
+ # bad version! Try to be as explicit as possible.
+ if hasattr(backend, '__file__'):
+ # CPython
+ raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r. The two versions should be equal; check your installation." % (
+ __version__, __file__,
+ backend.__version__, backend.__file__))
+ else:
+ # PyPy
+ raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. This interpreter comes with a built-in '_cffi_backend' module, which is version %s. The two versions should be equal; check your installation." % (
+ __version__, __file__, backend.__version__))
# (If you insist you can also try to pass the option
# 'backend=backend_ctypes.CTypesBackend()', but don't
# rely on it! It's probably not going to work well.)
+ from . import cparser
self._backend = backend
self._lock = allocate_lock()
self._parser = cparser.Parser()
@@ -212,7 +212,7 @@
def offsetof(self, cdecl, *fields_or_indexes):
"""Return the offset of the named field inside the given
- structure or array, 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.
@@ -300,7 +300,7 @@
return self._backend.string(cdata, maxlen)
def unpack(self, cdata, length):
- """Unpack an array of C data of the given length,
+ """Unpack an array of C data of the given length,
returning a Python string/unicode/list.
If 'cdata' is a pointer to 'char', returns a byte string.
@@ -452,7 +452,6 @@
return self._backend.getwinerror(code)
def _pointer_to(self, ctype):
- from . import model
with self._lock:
return model.pointer_cache(self, ctype)
@@ -764,7 +763,6 @@
return backend.load_library(path, flags)
def _make_ffi_library(ffi, libname, flags):
- import os
backend = ffi._backend
backendlib = _load_backend_lib(backend, libname, flags)
#
@@ -802,7 +800,6 @@
if accessors_version[0] is ffi._cdef_version:
return
#
- from . import model
for key, (tp, _) in ffi._parser._declarations.items():
if not isinstance(tp, model.EnumType):
tag, name = key.split(' ', 1)
diff --git a/lib_pypy/cffi/cffi_opcode.py b/lib_pypy/cffi/cffi_opcode.py
--- a/lib_pypy/cffi/cffi_opcode.py
+++ b/lib_pypy/cffi/cffi_opcode.py
@@ -1,3 +1,4 @@
+from .error import VerificationError
class CffiOp(object):
def __init__(self, op, arg):
@@ -19,7 +20,6 @@
% (self.arg,))
return format_four_bytes(value)
if isinstance(self.arg, str):
- from .ffiplatform import VerificationError
raise VerificationError("cannot emit to Python: %r" % (self.arg,))
return format_four_bytes((self.arg << 8) | self.op)
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
@@ -1,5 +1,6 @@
import sys
-from . import api, model
+from . import model
+from .error import FFIError
COMMON_TYPES = {}
@@ -31,11 +32,11 @@
elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES:
result, quals = model.PrimitiveType(cdecl), 0
elif cdecl == 'set-unicode-needed':
- raise api.FFIError("The Windows type %r is only available after "
- "you call ffi.set_unicode()" % (commontype,))
+ raise FFIError("The Windows type %r is only available after "
+ "you call ffi.set_unicode()" % (commontype,))
else:
if commontype == cdecl:
- raise api.FFIError(
+ raise FFIError(
"Unsupported type: %r. Please look at "
"http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations "
"and file an issue if you think this type should really "
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,5 +1,6 @@
-from . import api, model
+from . import model
from .commontypes import COMMON_TYPES, resolve_common_type
+from .error import FFIError, CDefError
try:
from . import _pycparser as pycparser
except ImportError:
@@ -113,7 +114,7 @@
# grouping variant
closing = csource.find('}', endpos)
if closing < 0:
- raise api.CDefError("'extern \"Python\" {': no '}' found")
+ raise CDefError("'extern \"Python\" {': no '}' found")
if csource.find('{', endpos + 1, closing) >= 0:
raise NotImplementedError("cannot use { } inside a block "
"'extern \"Python\" { ... }'")
@@ -123,7 +124,7 @@
# non-grouping variant
semicolon = csource.find(';', endpos)
if semicolon < 0:
- raise api.CDefError("'extern \"Python\": no ';' found")
+ raise CDefError("'extern \"Python\": no ';' found")
parts.append(csource[endpos:semicolon+1])
csource = csource[semicolon+1:]
parts.append(' void __cffi_extern_python_stop;')
@@ -288,7 +289,7 @@
msg = 'cannot parse "%s"\n%s' % (line.strip(), msg)
else:
msg = 'parse error\n%s' % (msg,)
- raise api.CDefError(msg)
+ raise CDefError(msg)
def parse(self, csource, override=False, packed=False, dllexport=False):
prev_options = self._options
@@ -318,8 +319,8 @@
self._parse_decl(decl)
elif isinstance(decl, pycparser.c_ast.Typedef):
if not decl.name:
- raise api.CDefError("typedef does not declare any name",
- decl)
+ raise CDefError("typedef does not declare any name",
+ decl)
quals = 0
if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType)
and decl.type.type.names[-1] == '__dotdotdot__'):
@@ -337,8 +338,8 @@
elif decl.__class__.__name__ == 'Pragma':
pass # skip pragma, only in pycparser 2.15
else:
- raise api.CDefError("unrecognized construct", decl)
- except api.FFIError as e:
+ raise CDefError("unrecognized construct", decl)
+ except FFIError as e:
msg = self._convert_pycparser_error(e, csource)
if msg:
e.args = (e.args[0] + "\n *** Err: %s" % msg,)
@@ -348,7 +349,7 @@
if key in self._int_constants:
if self._int_constants[key] == val:
return # ignore identical double declarations
- raise api.FFIError(
+ raise FFIError(
"multiple declarations of constant: %s" % (key,))
self._int_constants[key] = val
@@ -375,7 +376,7 @@
elif value == '...':
self._declare('macro ' + key, value)
else:
- raise api.CDefError(
+ raise CDefError(
'only supports one of the following syntax:\n'
' #define %s ... (literally dot-dot-dot)\n'
' #define %s NUMBER (with NUMBER an integer'
@@ -410,8 +411,8 @@
elif isinstance(node, pycparser.c_ast.Enum):
self._get_struct_union_enum_type('enum', node)
elif not decl.name:
- raise api.CDefError("construct does not declare any variable",
- decl)
+ raise CDefError("construct does not declare any variable",
+ decl)
#
if decl.name:
tp, quals = self._get_type_and_quals(node,
@@ -438,7 +439,7 @@
self._inside_extern_python = decl.name
else:
if self._inside_extern_python !='__cffi_extern_python_stop':
- raise api.CDefError(
+ raise CDefError(
"cannot declare constants or "
"variables with 'extern \"Python\"'")
if (quals & model.Q_CONST) and not tp.is_array_type:
@@ -454,7 +455,7 @@
assert not macros
exprnode = ast.ext[-1].type.args.params[0]
if isinstance(exprnode, pycparser.c_ast.ID):
- raise api.CDefError("unknown identifier '%s'" % (exprnode.name,))
+ raise CDefError("unknown identifier '%s'" % (exprnode.name,))
return self._get_type_and_quals(exprnode.type)
def _declare(self, name, obj, included=False, quals=0):
@@ -463,7 +464,7 @@
if prevobj is obj and prevquals == quals:
return
if not self._options.get('override'):
- raise api.FFIError(
+ raise FFIError(
"multiple declarations of %s (for interactive usage, "
"try cdef(xx, override=True))" % (name,))
assert '__dotdotdot__' not in name.split()
@@ -551,7 +552,7 @@
if ident == 'void':
return model.void_type, quals
if ident == '__dotdotdot__':
- raise api.FFIError(':%d: bad usage of "..."' %
+ raise FFIError(':%d: bad usage of "..."' %
typenode.coord.line)
tp0, quals0 = resolve_common_type(self, ident)
return tp0, (quals | quals0)
@@ -583,14 +584,14 @@
return self._get_struct_union_enum_type('union', typenode, name,
nested=True), 0
#
- raise api.FFIError(":%d: bad or unsupported type declaration" %
+ raise FFIError(":%d: bad or unsupported type declaration" %
typenode.coord.line)
def _parse_function_type(self, typenode, funcname=None):
params = list(getattr(typenode.args, 'params', []))
for i, arg in enumerate(params):
if not hasattr(arg, 'type'):
- raise api.CDefError("%s arg %d: unknown type '%s'"
+ raise CDefError("%s arg %d: unknown type '%s'"
" (if you meant to use the old C syntax of giving"
" untyped arguments, it is not supported)"
% (funcname or 'in expression', i + 1,
@@ -604,7 +605,7 @@
if ellipsis:
params.pop()
if not params:
- raise api.CDefError(
+ raise CDefError(
"%s: a function with only '(...)' as argument"
" is not correct C" % (funcname or 'in expression'))
args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type))
@@ -705,7 +706,7 @@
return tp
#
if tp.fldnames is not None:
- raise api.CDefError("duplicate declaration of struct %s" % name)
+ raise CDefError("duplicate declaration of struct %s" % name)
fldnames = []
fldtypes = []
fldbitsize = []
@@ -749,7 +750,7 @@
def _make_partial(self, tp, nested):
if not isinstance(tp, model.StructOrUnion):
- raise api.CDefError("%s cannot be partial" % (tp,))
+ raise CDefError("%s cannot be partial" % (tp,))
if not tp.has_c_name() and not nested:
raise NotImplementedError("%s is partial but has no C name" %(tp,))
tp.partial = True
@@ -769,7 +770,7 @@
len(s) == 3 or (len(s) == 4 and s[1] == "\\")):
return ord(s[-2])
else:
- raise api.CDefError("invalid constant %r" % (s,))
+ raise CDefError("invalid constant %r" % (s,))
#
if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and
exprnode.op == '+'):
@@ -788,12 +789,12 @@
if partial_length_ok:
self._partial_length = True
return '...'
- raise api.FFIError(":%d: unsupported '[...]' here, cannot derive "
- "the actual array length in this context"
- % exprnode.coord.line)
+ raise FFIError(":%d: unsupported '[...]' here, cannot derive "
+ "the actual array length in this context"
+ % exprnode.coord.line)
#
- raise api.FFIError(":%d: unsupported expression: expected a "
- "simple numeric constant" % exprnode.coord.line)
+ raise FFIError(":%d: unsupported expression: expected a "
+ "simple numeric constant" % exprnode.coord.line)
def _build_enum_type(self, explicit_name, decls):
if decls is not None:
@@ -843,8 +844,8 @@
for t in typenames[:-1]:
if t not in ['int', 'short', 'long', 'signed',
'unsigned', 'char']:
- raise api.FFIError(':%d: bad usage of "..."' %
- decl.coord.line)
+ raise FFIError(':%d: bad usage of "..."' %
+ decl.coord.line)
result = model.UnknownIntegerType(decl.name)
if self._uses_new_feature is None:
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
@@ -1,14 +1,5 @@
import sys, os
-
-
-class VerificationError(Exception):
- """ An error raised when verification fails
- """
-
-class VerificationMissing(Exception):
- """ An error raised when incomplete structures are passed into
- cdef, but no verification has been done
- """
+from .error import VerificationError
LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs',
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
@@ -1,8 +1,8 @@
-import types, sys
+import types
import weakref
from .lock import allocate_lock
-
+from .error import CDefError, VerificationError, VerificationMissing
# type qualifiers
Q_CONST = 0x01
@@ -39,7 +39,6 @@
replace_with = qualify(quals, replace_with)
result = result.replace('&', replace_with)
if '$' in result:
- from .ffiplatform import VerificationError
raise VerificationError(
"cannot generate '%s' in %s: unknown type name"
% (self._get_c_name(), context))
@@ -223,9 +222,8 @@
is_raw_function = True
def build_backend_type(self, ffi, finishlist):
- from . import api
- raise api.CDefError("cannot render the type %r: it is a function "
- "type, not a pointer-to-function type" % (self,))
+ raise CDefError("cannot render the type %r: it is a function "
+ "type, not a pointer-to-function type" % (self,))
def as_function_pointer(self):
return FunctionPtrType(self.args, self.result, self.ellipsis, self.abi)
@@ -307,9 +305,8 @@
def build_backend_type(self, ffi, finishlist):
if self.length == '...':
- from . import api
- raise api.CDefError("cannot render the type %r: unknown length" %
- (self,))
+ raise CDefError("cannot render the type %r: unknown length" %
+ (self,))
self.item.get_cached_btype(ffi, finishlist) # force the item BType
BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist)
return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length)
@@ -455,13 +452,11 @@
self.completed = 2
def _verification_error(self, msg):
- from .ffiplatform import VerificationError
raise VerificationError(msg)
def check_not_partial(self):
if self.partial and self.fixedlayout is None:
- from . import ffiplatform
- raise ffiplatform.VerificationMissing(self._get_c_name())
+ raise VerificationMissing(self._get_c_name())
def build_backend_type(self, ffi, finishlist):
self.check_not_partial()
@@ -499,8 +494,7 @@
def check_not_partial(self):
if self.partial and not self.partial_resolved:
- from . import ffiplatform
- raise ffiplatform.VerificationMissing(self._get_c_name())
+ raise VerificationMissing(self._get_c_name())
def build_backend_type(self, ffi, finishlist):
self.check_not_partial()
@@ -514,7 +508,6 @@
if self.baseinttype is not None:
return self.baseinttype.get_cached_btype(ffi, finishlist)
#
- from . import api
if self.enumvalues:
smallest_value = min(self.enumvalues)
largest_value = max(self.enumvalues)
@@ -549,8 +542,8 @@
if (smallest_value >= ((-1) << (8*size2-1)) and
largest_value < (1 << (8*size2-sign))):
return btype2
- raise api.CDefError("%s values don't all fit into either 'long' "
- "or 'unsigned long'" % self._get_c_name())
+ raise CDefError("%s values don't all fit into either 'long' "
+ "or 'unsigned long'" % self._get_c_name())
def unknown_type(name, structname=None):
if structname is None:
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -1,5 +1,6 @@
import os, sys, io
from . import ffiplatform, model
+from .error import VerificationError
from .cffi_opcode import *
VERSION = "0x2601"
@@ -211,7 +212,7 @@
method = getattr(self, '_generate_cpy_%s_%s' % (kind,
step_name))
except AttributeError:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"not implemented in recompile(): %r" % name)
try:
self._current_quals = quals
@@ -354,12 +355,12 @@
included_module_name, included_source = (
ffi_to_include._assigned_source[:2])
except AttributeError:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"ffi object %r includes %r, but the latter has not "
"been prepared with set_source()" % (
self.ffi, ffi_to_include,))
if included_source is None:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"not implemented yet: ffi.include() of a Python-based "
"ffi inside a C-based ffi")
prnt(' "%s",' % (included_module_name,))
@@ -391,6 +392,10 @@
prnt()
#
# the init function
+ prnt('#ifdef __GNUC__')
+ prnt('# pragma GCC visibility push(default) /* for -fvisibility= */')
+ prnt('#endif')
+ prnt()
prnt('#ifdef PYPY_VERSION')
prnt('PyMODINIT_FUNC')
prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,))
@@ -429,6 +434,10 @@
self.module_name, version))
prnt('}')
prnt('#endif')
+ prnt()
+ prnt('#ifdef __GNUC__')
+ prnt('# pragma GCC visibility pop')
+ prnt('#endif')
def _to_py(self, x):
if isinstance(x, str):
@@ -456,12 +465,12 @@
included_module_name, included_source = (
ffi_to_include._assigned_source[:2])
except AttributeError:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"ffi object %r includes %r, but the latter has not "
"been prepared with set_source()" % (
self.ffi, ffi_to_include,))
if included_source is not None:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"not implemented yet: ffi.include() of a C-based "
"ffi inside a Python-based ffi")
prnt('from %s import ffi as _ffi%d' % (included_module_name, i))
@@ -831,7 +840,7 @@
prnt(' { %s = &p->%s; (void)tmp; }' % (
ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
fname))
- except ffiplatform.VerificationError as e:
+ except VerificationError as e:
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
prnt('}')
prnt('struct _cffi_align_%s { char x; %s y; };' % (approxname, cname))
@@ -994,7 +1003,7 @@
def _generate_cpy_const(self, is_int, name, tp=None, category='const',
check_value=None):
if (category, name) in self._seen_constants:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"duplicate declaration of %s '%s'" % (category, name))
self._seen_constants.add((category, name))
#
@@ -1093,7 +1102,7 @@
def _generate_cpy_macro_ctx(self, tp, name):
if tp == '...':
if self.target_is_python:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"cannot use the syntax '...' in '#define %s ...' when "
"using the ABI mode" % (name,))
check_value = None
@@ -1226,7 +1235,7 @@
def _generate_cpy_extern_python_ctx(self, tp, name):
if self.target_is_python:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"cannot use 'extern \"Python\"' in the ABI mode")
if tp.ellipsis:
raise NotImplementedError("a vararg function is extern \"Python\"")
@@ -1307,7 +1316,7 @@
if tp.length is None:
self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index)
elif tp.length == '...':
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"type %s badly placed: the '...' array length can only be "
"used on global arrays or on fields of structures" % (
str(tp).replace('/*...*/', '...'),))
diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py
--- a/lib_pypy/cffi/setuptools_ext.py
+++ b/lib_pypy/cffi/setuptools_ext.py
@@ -79,9 +79,10 @@
CPython itself should ignore the flag in a debugging version
(by not listing .abi3.so in the extensions it supports), but
it doesn't so far, creating troubles. That's why we check
- for "not sys.flags.debug". (http://bugs.python.org/issue28401)
+ for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent
+ of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401)
"""
- if 'py_limited_api' not in kwds and not sys.flags.debug:
+ if 'py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount'):
import setuptools
try:
setuptools_major_version = int(setuptools.__version__.partition('.')[0])
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
@@ -2,7 +2,8 @@
# DEPRECATED: implementation for ffi.verify()
#
import sys, imp
-from . import model, ffiplatform
+from . import model
+from .error import VerificationError
class VCPythonEngine(object):
@@ -155,7 +156,7 @@
self.verifier.modulefilename)
except ImportError as e:
error = "importing %r: %s" % (self.verifier.modulefilename, e)
- raise ffiplatform.VerificationError(error)
+ raise VerificationError(error)
finally:
if hasattr(sys, "setdlopenflags"):
sys.setdlopenflags(previous_flags)
@@ -185,7 +186,7 @@
def __dir__(self):
return FFILibrary._cffi_dir + list(self.__dict__)
library = FFILibrary()
- if module._cffi_setup(lst, ffiplatform.VerificationError, library):
+ if module._cffi_setup(lst, VerificationError, library):
import warnings
warnings.warn("reimporting %r might overwrite older definitions"
% (self.verifier.get_module_name()))
@@ -212,7 +213,7 @@
method = getattr(self, '_generate_cpy_%s_%s' % (kind,
step_name))
except AttributeError:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"not implemented in verify(): %r" % name)
try:
method(tp, realname)
@@ -485,7 +486,7 @@
prnt(' { %s = &p->%s; (void)tmp; }' % (
ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
fname))
- except ffiplatform.VerificationError as e:
+ except VerificationError as e:
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
prnt('}')
prnt('static PyObject *')
@@ -550,7 +551,7 @@
# check that the layout sizes and offsets match the real ones
def check(realvalue, expectedvalue, msg):
if realvalue != expectedvalue:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"%s (we have %d, but C compiler says %d)"
% (msg, expectedvalue, realvalue))
ffi = self.ffi
@@ -771,7 +772,7 @@
BItemType = self.ffi._get_cached_btype(tp.item)
length, rest = divmod(size, self.ffi.sizeof(BItemType))
if rest != 0:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"bad size: %r does not seem to be an array of %s" %
(name, tp.item))
tp = tp.resolve_length(length)
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
@@ -4,7 +4,8 @@
import sys, os
import types
-from . import model, ffiplatform
+from . import model
+from .error import VerificationError
class VGenericEngine(object):
@@ -102,7 +103,7 @@
method = getattr(self, '_generate_gen_%s_%s' % (kind,
step_name))
except AttributeError:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"not implemented in verify(): %r" % name)
try:
method(tp, realname)
@@ -281,7 +282,7 @@
prnt(' { %s = &p->%s; (void)tmp; }' % (
ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
fname))
- except ffiplatform.VerificationError as e:
+ except VerificationError as e:
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
prnt('}')
self.export_symbols.append(layoutfuncname)
@@ -344,7 +345,7 @@
# check that the layout sizes and offsets match the real ones
def check(realvalue, expectedvalue, msg):
if realvalue != expectedvalue:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"%s (we have %d, but C compiler says %d)"
% (msg, expectedvalue, realvalue))
ffi = self.ffi
@@ -498,7 +499,7 @@
error = self.ffi.string(p)
if sys.version_info >= (3,):
error = str(error, 'utf-8')
- raise ffiplatform.VerificationError(error)
+ raise VerificationError(error)
def _enum_funcname(self, prefix, name):
# "$enum_$1" => "___D_enum____D_1"
@@ -591,7 +592,7 @@
BItemType = self.ffi._get_cached_btype(tp.item)
length, rest = divmod(size, self.ffi.sizeof(BItemType))
if rest != 0:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"bad size: %r does not seem to be an array of %s" %
(name, tp.item))
tp = tp.resolve_length(length)
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
@@ -4,6 +4,7 @@
import sys, os, binascii, shutil, io
from . import __version_verifier_modules__
from . import ffiplatform
+from .error import VerificationError
if sys.version_info >= (3, 3):
import importlib.machinery
@@ -42,7 +43,7 @@
ext_package=None, tag='', force_generic_engine=False,
source_extension='.c', flags=None, relative_to=None, **kwds):
if ffi._parser._uses_new_feature:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"feature not supported with ffi.verify(), but only "
"with ffi.set_source(): %s" % (ffi._parser._uses_new_feature,))
self.ffi = ffi
@@ -83,7 +84,7 @@
which can be tweaked beforehand."""
with self.ffi._lock:
if self._has_source and file is None:
- raise ffiplatform.VerificationError(
+ raise VerificationError(
"source code already written")
self._write_source(file)
@@ -92,7 +93,7 @@
This produces a dynamic link library in 'self.modulefilename'."""
with self.ffi._lock:
if self._has_module:
- raise ffiplatform.VerificationError("module already compiled")
+ raise VerificationError("module already compiled")
if not self._has_source:
self._write_source()
self._compile_module()
diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -1216,12 +1216,16 @@
space, encoding, atom_node.get_child(i).get_value())
for i in range(atom_node.num_children())]
except error.OperationError as e:
- if not (e.match(space, space.w_UnicodeError) or
- e.match(space, space.w_ValueError)):
+ if e.match(space, space.w_UnicodeError):
+ kind = 'unicode error'
+ elif e.match(space, space.w_ValueError):
+ kind = 'value error'
+ else:
raise
# Unicode/ValueError in literal: turn into SyntaxError
- self.error(e.errorstr(space), atom_node)
- sub_strings_w = [] # please annotator
+ e.normalize_exception(space)
+ errmsg = space.str_w(space.str(e.get_w_value(space)))
+ raise self.error('(%s) %s' % (kind, errmsg), atom_node)
# Implement implicit string concatenation.
w_string = sub_strings_w[0]
for i in range(1, len(sub_strings_w)):
diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py b/pypy/interpreter/astcompiler/test/test_astbuilder.py
--- a/pypy/interpreter/astcompiler/test/test_astbuilder.py
+++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py
@@ -1398,3 +1398,9 @@
assert len(asyncwith.body) == 1
assert isinstance(asyncwith.body[0], ast.Expr)
assert isinstance(asyncwith.body[0].value, ast.Num)
+
+ def test_decode_error_in_string_literal(self):
+ input = "u'\\x'"
+ exc = py.test.raises(SyntaxError, self.get_ast, input).value
+ assert exc.msg == ("(unicode error) 'unicodeescape' codec can't decode"
+ " bytes in position 0-1: truncated \\xXX escape")
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -80,6 +80,7 @@
def errorstr(self, space, use_repr=False):
"The exception class and value, as a string."
+ self.normalize_exception(space)
w_value = self.get_w_value(space)
if space is None:
# this part NOT_RPYTHON
diff --git a/pypy/interpreter/test/test_error.py b/pypy/interpreter/test/test_error.py
--- a/pypy/interpreter/test/test_error.py
+++ b/pypy/interpreter/test/test_error.py
@@ -96,7 +96,18 @@
def test_errorstr(space):
operr = OperationError(space.w_ValueError, space.wrap("message"))
assert operr.errorstr(space) == "ValueError: message"
- assert operr.errorstr(space, use_repr=True) == "ValueError: 'message'"
+ assert operr.errorstr(space, use_repr=True) == (
+ "ValueError: ValueError('message',)")
+ operr = OperationError(space.w_ValueError, space.w_None)
+ assert operr.errorstr(space) == "ValueError"
+ operr = OperationError(space.w_ValueError,
+ space.newtuple([space.wrap(6), space.wrap(7)]))
+ assert operr.errorstr(space) == "ValueError: (6, 7)"
+ operr = OperationError(space.w_UnicodeDecodeError,
+ space.wrap(('unicodeescape', r'\\x', 0, 2, r'truncated \\xXX escape')))
+ assert operr.errorstr(space) == (
+ "UnicodeDecodeError: 'unicodeescape' codec can't decode "
+ "bytes in position 0-1: truncated \\\\xXX escape")
def test_wrap_oserror():
class FakeSpace:
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
@@ -3,7 +3,7 @@
from rpython.rlib import rdynload, clibffi
from rpython.rtyper.lltypesystem import rffi
-VERSION = "1.9.2"
+VERSION = "1.10.0"
FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
try:
diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -370,6 +370,19 @@
# bypass the method 'string' implemented in W_CTypePrimitive
return W_CType.string(self, cdataobj, maxlen)
+ def convert_to_object(self, cdata):
+ space = self.space
+ value = ord(cdata[0])
+ if value < 2:
+ return space.newbool(value != 0)
+ else:
+ raise oefmt(space.w_ValueError,
+ "got a _Bool of value %d, expected 0 or 1",
+ value)
+
+ def unpack_list_of_int_items(self, ptr, length):
+ return None
+
class W_CTypePrimitiveFloat(W_CTypePrimitive):
_attrs_ = []
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
@@ -84,6 +84,8 @@
raise oefmt(space.w_IndexError,
"initializer string is too long for '%s' (got %d "
"characters)", self.name, n)
+ if isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveBool):
+ self._must_be_string_of_zero_or_one(s)
copy_string_to_raw(llstr(s), cdata, 0, n)
if n != self.length:
cdata[n] = '\x00'
@@ -103,9 +105,16 @@
else:
raise self._convert_error("list or tuple", w_ob)
+ def _must_be_string_of_zero_or_one(self, s):
+ for c in s:
+ if ord(c) > 1:
+ raise oefmt(self.space.w_ValueError,
+ "an array of _Bool can only contain \\x00 or \\x01")
+
def string(self, cdataobj, maxlen):
space = self.space
- if isinstance(self.ctitem, ctypeprim.W_CTypePrimitive):
+ if (isinstance(self.ctitem, ctypeprim.W_CTypePrimitive) and
+ not isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveBool)):
with cdataobj as ptr:
if not ptr:
raise oefmt(space.w_RuntimeError,
@@ -285,6 +294,8 @@
if self.accept_str and space.isinstance_w(w_init, space.w_str):
# special case to optimize strings passed to a "char *" argument
value = space.bytes_w(w_init)
+ if isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveBool):
+ self._must_be_string_of_zero_or_one(value)
keepalives[i] = value
buf, buf_flag = rffi.get_nonmovingbuffer_final_null(value)
rffi.cast(rffi.CCHARPP, cdata)[0] = buf
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
@@ -1,9 +1,9 @@
# ____________________________________________________________
import sys
-assert __version__ == "1.9.2", ("This test_c.py file is for testing a version"
- " of cffi that differs from the one that we"
- " get from 'import _cffi_backend'")
+assert __version__ == "1.10.0", ("This test_c.py file is for testing a version"
+ " of cffi that differs from the one that we"
+ " get from 'import _cffi_backend'")
if sys.version_info < (3,):
type_or_class = "type"
mandatory_b_prefix = ''
@@ -885,6 +885,15 @@
py.test.raises(OverflowError, f, 128, 0)
py.test.raises(OverflowError, f, 0, 128)
+def test_call_function_0_pretend_bool_result():
+ BSignedChar = new_primitive_type("signed char")
+ BBool = new_primitive_type("_Bool")
+ BFunc0 = new_function_type((BSignedChar, BSignedChar), BBool, False)
+ f = cast(BFunc0, _testfunc(0))
+ assert f(40, -39) is True
+ assert f(40, -40) is False
+ py.test.raises(ValueError, f, 40, 2)
+
def test_call_function_1():
BInt = new_primitive_type("int")
BLong = new_primitive_type("long")
@@ -1047,6 +1056,17 @@
res = f(b"foo")
assert res == 1000 * ord(b'f')
+def test_call_function_23_bool_array():
+ # declaring the function as int(_Bool*)
+ BBool = new_primitive_type("_Bool")
+ BBoolP = new_pointer_type(BBool)
+ BInt = new_primitive_type("int")
+ BFunc23 = new_function_type((BBoolP,), BInt, False)
+ f = cast(BFunc23, _testfunc(23))
+ res = f(b"\x01\x01")
+ assert res == 1000
+ py.test.raises(ValueError, f, b"\x02\x02")
+
def test_cannot_pass_struct_with_array_of_length_0():
BInt = new_primitive_type("int")
BArray0 = new_array_type(new_pointer_type(BInt), 0)
@@ -2617,13 +2637,38 @@
py.test.raises(OverflowError, newp, BBoolP, 2)
py.test.raises(OverflowError, newp, BBoolP, -1)
BCharP = new_pointer_type(new_primitive_type("char"))
- p = newp(BCharP, b'X')
+ p = newp(BCharP, b'\x01')
q = cast(BBoolP, p)
- assert q[0] == ord(b'X')
+ assert q[0] is True
+ p = newp(BCharP, b'\x00')
+ q = cast(BBoolP, p)
+ assert q[0] is False
py.test.raises(TypeError, string, cast(BBool, False))
BDouble = new_primitive_type("double")
assert int(cast(BBool, cast(BDouble, 0.1))) == 1
assert int(cast(BBool, cast(BDouble, 0.0))) == 0
+ BBoolA = new_array_type(BBoolP, None)
+ p = newp(BBoolA, b'\x01\x00')
+ assert p[0] is True
+ assert p[1] is False
+
+def test_bool_forbidden_cases():
+ BBool = new_primitive_type("_Bool")
+ BBoolP = new_pointer_type(BBool)
+ BBoolA = new_array_type(BBoolP, None)
+ BCharP = new_pointer_type(new_primitive_type("char"))
+ p = newp(BCharP, b'X')
+ q = cast(BBoolP, p)
+ py.test.raises(ValueError, "q[0]")
+ py.test.raises(TypeError, newp, BBoolP, b'\x00')
+ assert newp(BBoolP, 0)[0] is False
+ assert newp(BBoolP, 1)[0] is True
+ py.test.raises(OverflowError, newp, BBoolP, 2)
+ py.test.raises(OverflowError, newp, BBoolP, -1)
+ py.test.raises(ValueError, newp, BBoolA, b'\x00\x01\x02')
+ py.test.raises(OverflowError, newp, BBoolA, [0, 1, 2])
+ py.test.raises(TypeError, string, newp(BBoolP, 1))
+ py.test.raises(TypeError, string, newp(BBoolA, [1]))
def test_typeoffsetof():
BChar = new_primitive_type("char")
@@ -3663,7 +3708,7 @@
("int16_t", [-2**15, 2**15-1]),
("int32_t", [-2**31, 2**31-1]),
("int64_t", [-2**63, 2**63-1]),
- ("_Bool", [0, 1]),
+ ("_Bool", [False, True]),
("float", [0.0, 10.5]),
("double", [12.34, 56.78]),
]:
@@ -3733,7 +3778,7 @@
def test_char_pointer_conversion():
import warnings
- assert __version__.startswith(("1.8", "1.9")), (
+ assert __version__.startswith(("1.8", "1.9", "1.10")), (
"consider turning the warning into an error")
BCharP = new_pointer_type(new_primitive_type("char"))
BIntP = new_pointer_type(new_primitive_type("int"))
diff --git a/pypy/module/_cffi_backend/test/test_fastpath.py b/pypy/module/_cffi_backend/test/test_fastpath.py
--- a/pypy/module/_cffi_backend/test/test_fastpath.py
+++ b/pypy/module/_cffi_backend/test/test_fastpath.py
@@ -109,9 +109,8 @@
P_BOOL = _cffi_backend.new_pointer_type(BOOL)
BOOL_ARRAY = _cffi_backend.new_array_type(P_BOOL, None)
buf = _cffi_backend.newp(BOOL_ARRAY, [1, 0])
- assert buf[0] == 1
- assert buf[1] == 0
- assert type(buf[1]) is int
+ assert buf[0] is True
+ assert buf[1] is False
raises(OverflowError, _cffi_backend.newp, BOOL_ARRAY, [2])
raises(OverflowError, _cffi_backend.newp, BOOL_ARRAY, [-1])
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py
@@ -29,7 +29,7 @@
content = open(p).read()
#
v = cffi.__version__
- assert ("version = '%s'\n" % v[:3]) in content
+ assert ("version = '%s'\n" % v[:4]) in content
assert ("release = '%s'\n" % v) in content
def test_doc_version_file():
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py
@@ -157,20 +157,21 @@
except ImportError as e:
py.test.skip(str(e))
orig_version = setuptools.__version__
+ expecting_limited_api = not hasattr(sys, 'gettotalrefcount')
try:
setuptools.__version__ = '26.0.0'
from setuptools import Extension
kwds = _set_py_limited_api(Extension, {})
- assert kwds['py_limited_api'] == True
+ assert kwds.get('py_limited_api', False) == expecting_limited_api
setuptools.__version__ = '25.0'
kwds = _set_py_limited_api(Extension, {})
- assert not kwds
+ assert kwds.get('py_limited_api', False) == False
setuptools.__version__ = 'development'
kwds = _set_py_limited_api(Extension, {})
- assert kwds['py_limited_api'] == True
+ assert kwds.get('py_limited_api', False) == expecting_limited_api
finally:
setuptools.__version__ = orig_version
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -7,6 +7,11 @@
from pypy.module.test_lib_pypy.cffi_tests.support import u, long
from pypy.module.test_lib_pypy.cffi_tests.support import FdWriteCapture, StdErrCapture
+try:
+ import importlib
+except ImportError:
+ importlib = None
+
def check_type_table(input, expected_output, included=None):
ffi = FFI()
@@ -27,6 +32,7 @@
kwds.setdefault('source_extension', '.cpp')
source = 'extern "C" {\n%s\n}' % (source,)
else:
+ # add '-Werror' to the existing 'extra_compile_args' flags
kwds['extra_compile_args'] = (kwds.get('extra_compile_args', []) +
['-Werror'])
return recompiler._verify(ffi, module_name, source, *args, **kwds)
@@ -522,6 +528,8 @@
assert os.path.exists(str(package_dir.join('mymod.c')))
package_dir.join('__init__.py').write('')
#
+ getattr(importlib, 'invalidate_caches', object)()
+ #
sys.path.insert(0, str(udir))
import test_module_name_in_package.mymod
assert test_module_name_in_package.mymod.lib.foo(10) == 42
@@ -2160,7 +2168,7 @@
return s;
}
""")
- assert lib.f().y == chr(40)
+ assert ord(lib.f().y) == 40
assert lib.f().x == 200
e = py.test.raises(NotImplementedError, lib.g, 0)
assert str(e.value) == (
@@ -2169,3 +2177,15 @@
" Such structs are only supported as return value if the function is "
"'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
"+ffibuilder.set_source() and not taking a final '...' argument)")
+
+def test_gcc_visibility_hidden():
+ if sys.platform == 'win32':
+ py.test.skip("test for gcc/clang")
+ ffi = FFI()
+ ffi.cdef("""
+ int f(int);
+ """)
+ lib = verify(ffi, "test_gcc_visibility_hidden", """
+ int f(int a) { return a + 40; }
+ """, extra_compile_args=['-fvisibility=hidden'])
+ assert lib.f(2) == 42
diff --git a/pypy/module/zipimport/interp_zipimport.py b/pypy/module/zipimport/interp_zipimport.py
--- a/pypy/module/zipimport/interp_zipimport.py
+++ b/pypy/module/zipimport/interp_zipimport.py
@@ -259,7 +259,7 @@
pass
except RZlibError as e:
# in this case, CPython raises the direct exception coming
- # from the zlib module: let's to the same
+ # from the zlib module: let's do the same
raise zlib_error(space, e.msg)
else:
if is_package:
@@ -292,7 +292,7 @@
raise oefmt(space.w_IOError, "Error reading file")
except RZlibError as e:
# in this case, CPython raises the direct exception coming
- # from the zlib module: let's to the same
+ # from the zlib module: let's do the same
raise zlib_error(space, e.msg)
def get_code(self, space, w_fullname):
@@ -428,7 +428,7 @@
space.wrap_fsdecoded(filename))
except RZlibError as e:
# in this case, CPython raises the direct exception coming
- # from the zlib module: let's to the same
+ # from the zlib module: let's do the same
raise zlib_error(space, e.msg)
prefix = name[len(filename):]
More information about the pypy-commit
mailing list