[pypy-commit] pypy py3k: merge default
pjenvey
noreply at buildbot.pypy.org
Thu May 30 21:42:06 CEST 2013
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r64670:f76c1466005a
Date: 2013-05-30 12:36 -0700
http://bitbucket.org/pypy/pypy/changeset/f76c1466005a/
Log: merge default
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
@@ -156,6 +156,9 @@
class FFILibrary(object):
_cffi_python_module = module
_cffi_ffi = self.ffi
+ _cffi_dir = []
+ def __dir__(self):
+ return FFILibrary._cffi_dir + list(self.__dict__)
library = FFILibrary()
module._cffi_setup(lst, ffiplatform.VerificationError, library)
#
@@ -701,7 +704,8 @@
return ptr[0]
def setter(library, value):
ptr[0] = value
- setattr(library.__class__, name, property(getter, setter))
+ setattr(type(library), name, property(getter, setter))
+ type(library)._cffi_dir.append(name)
# ----------
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
@@ -74,6 +74,9 @@
class FFILibrary(types.ModuleType):
_cffi_generic_module = module
_cffi_ffi = self.ffi
+ _cffi_dir = []
+ def __dir__(self):
+ return FFILibrary._cffi_dir
library = FFILibrary("")
#
# finally, call the loaded_gen_xxx() functions. This will set
@@ -168,21 +171,22 @@
newfunction = self._load_constant(False, tp, name, module)
else:
indirections = []
- if any(isinstance(type, model.StructOrUnion) for type in tp.args):
+ if any(isinstance(typ, model.StructOrUnion) for typ in tp.args):
indirect_args = []
- for i, type in enumerate(tp.args):
- if isinstance(type, model.StructOrUnion):
- type = model.PointerType(type)
- indirections.append((i, type))
- indirect_args.append(type)
+ for i, typ in enumerate(tp.args):
+ if isinstance(typ, model.StructOrUnion):
+ typ = model.PointerType(typ)
+ indirections.append((i, typ))
+ indirect_args.append(typ)
tp = model.FunctionPtrType(tuple(indirect_args),
tp.result, tp.ellipsis)
BFunc = self.ffi._get_cached_btype(tp)
wrappername = '_cffi_f_%s' % name
newfunction = module.load_function(BFunc, wrappername)
- for i, type in indirections:
- newfunction = self._make_struct_wrapper(newfunction, i, type)
+ for i, typ in indirections:
+ newfunction = self._make_struct_wrapper(newfunction, i, typ)
setattr(library, name, newfunction)
+ type(library)._cffi_dir.append(name)
def _make_struct_wrapper(self, oldfunc, i, tp):
backend = self.ffi._backend
@@ -390,6 +394,7 @@
is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
value = self._load_constant(is_int, tp, name, module)
setattr(library, name, value)
+ type(library)._cffi_dir.append(name)
# ----------
# enums
@@ -437,6 +442,7 @@
def _loaded_gen_enum(self, tp, name, module, library):
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
setattr(library, enumerator, enumvalue)
+ type(library)._cffi_dir.append(enumerator)
# ----------
# macros: for now only for integers
@@ -450,6 +456,7 @@
def _loaded_gen_macro(self, tp, name, module, library):
value = self._load_constant(True, tp, name, module)
setattr(library, name, value)
+ type(library)._cffi_dir.append(name)
# ----------
# global variables
@@ -475,6 +482,7 @@
BArray = self.ffi._get_cached_btype(tp)
value = self.ffi.cast(BArray, value)
setattr(library, name, value)
+ type(library)._cffi_dir.append(name)
return
# remove ptr=<cdata 'int *'> from the library instance, and replace
# it by a property on the class, which reads/writes into ptr[0].
@@ -486,7 +494,8 @@
return ptr[0]
def setter(library, value):
ptr[0] = value
- setattr(library.__class__, name, property(getter, setter))
+ setattr(type(library), name, property(getter, setter))
+ type(library)._cffi_dir.append(name)
cffimod_header = r'''
#include <stdio.h>
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -131,13 +131,12 @@
" struct or union ctype"))
is_union = isinstance(w_ctype, ctypestruct.W_CTypeUnion)
- maxsize = 1
alignment = 1
- offset = 0
+ boffset = 0 # this number is in *bits*, not bytes!
+ boffsetmax = 0 # the maximum value of boffset, in bits too
fields_w = space.listview(w_fields)
fields_list = []
fields_dict = {}
- prev_bit_position = 0
custom_field_pos = False
for w_field in fields_w:
@@ -161,92 +160,129 @@
"field '%s.%s' has ctype '%s' of unknown size",
w_ctype.name, fname, ftype.name)
#
+ if is_union:
+ boffset = 0 # reset each field at offset 0
+ #
+ # update the total alignment requirement, but skip it if the
+ # field is an anonymous bitfield
falign = ftype.alignof()
- if alignment < falign:
+ if alignment < falign and (fbitsize < 0 or fname != ''):
alignment = falign
#
- if foffset < 0:
+ if fbitsize < 0:
+ # not a bitfield: common case
+
+ if isinstance(ftype, ctypearray.W_CTypeArray) and ftype.length==0:
+ bs_flag = ctypestruct.W_CField.BS_EMPTY_ARRAY
+ else:
+ bs_flag = ctypestruct.W_CField.BS_REGULAR
+
# align this field to its own 'falign' by inserting padding
- offset = (offset + falign - 1) & ~(falign - 1)
+ boffset = (boffset + falign*8-1) & ~(falign*8-1)
+
+ if foffset >= 0:
+ # a forced field position: ignore the offset just computed,
+ # except to know if we must set 'custom_field_pos'
+ custom_field_pos |= (boffset != foffset * 8)
+ boffset = foffset * 8
+
+ if (fname == '' and
+ isinstance(ftype, ctypestruct.W_CTypeStructOrUnion)):
+ # a nested anonymous struct or union
+ srcfield2names = {}
+ for name, srcfld in ftype.fields_dict.items():
+ srcfield2names[srcfld] = name
+ for srcfld in ftype.fields_list:
+ fld = srcfld.make_shifted(boffset // 8)
+ fields_list.append(fld)
+ try:
+ fields_dict[srcfield2names[srcfld]] = fld
+ except KeyError:
+ pass
+ # always forbid such structures from being passed by value
+ custom_field_pos = True
+ else:
+ # a regular field
+ fld = ctypestruct.W_CField(ftype, boffset // 8, bs_flag, -1)
+ fields_list.append(fld)
+ fields_dict[fname] = fld
+
+ boffset += ftype.size * 8
+
else:
- # a forced field position: ignore the offset just computed,
- # except to know if we must set 'custom_field_pos'
- custom_field_pos |= (offset != foffset)
- offset = foffset
- #
- if fbitsize < 0 or (
- fbitsize == 8 * ftype.size and not
- isinstance(ftype, ctypeprim.W_CTypePrimitiveCharOrUniChar)):
- fbitsize = -1
- if isinstance(ftype, ctypearray.W_CTypeArray) and ftype.length == 0:
- bitshift = ctypestruct.W_CField.BS_EMPTY_ARRAY
+ # this is the case of a bitfield
+
+ if foffset >= 0:
+ raise operationerrfmt(space.w_TypeError,
+ "field '%s.%s' is a bitfield, "
+ "but a fixed offset is specified",
+ w_ctype.name, fname)
+
+ if not (isinstance(ftype, ctypeprim.W_CTypePrimitiveSigned) or
+ isinstance(ftype, ctypeprim.W_CTypePrimitiveUnsigned) or
+ isinstance(ftype,ctypeprim.W_CTypePrimitiveCharOrUniChar)):
+ raise operationerrfmt(space.w_TypeError,
+ "field '%s.%s' declared as '%s' "
+ "cannot be a bit field",
+ w_ctype.name, fname, ftype.name)
+ if fbitsize > 8 * ftype.size:
+ raise operationerrfmt(space.w_TypeError,
+ "bit field '%s.%s' is declared '%s:%d',"
+ " which exceeds the width of the type",
+ w_ctype.name, fname,
+ ftype.name, fbitsize)
+
+ # compute the starting position of the theoretical field
+ # that covers a complete 'ftype', inside of which we will
+ # locate the real bitfield
+ field_offset_bytes = boffset // 8
+ field_offset_bytes &= ~(falign - 1)
+
+ if fbitsize == 0:
+ if fname != '':
+ raise operationerrfmt(space.w_TypeError,
+ "field '%s.%s' is declared with :0",
+ w_ctype.name, fname)
+ if boffset > field_offset_bytes * 8:
+ field_offset_bytes += falign
+ assert boffset < field_offset_bytes * 8
+ boffset = field_offset_bytes * 8
else:
- bitshift = ctypestruct.W_CField.BS_REGULAR
- prev_bit_position = 0
- else:
- if (not (isinstance(ftype, ctypeprim.W_CTypePrimitiveSigned) or
- isinstance(ftype, ctypeprim.W_CTypePrimitiveUnsigned) or
- isinstance(ftype, ctypeprim.W_CTypePrimitiveChar)) or
- fbitsize == 0 or
- fbitsize > 8 * ftype.size):
- raise operationerrfmt(space.w_TypeError,
- "invalid bit field '%s'", fname)
- if prev_bit_position > 0:
- prev_field = fields_list[-1]
- assert prev_field.bitshift >= 0
- if prev_field.ctype.size != ftype.size:
- raise OperationError(space.w_NotImplementedError,
- space.wrap("consecutive bit fields should be "
- "declared with a same-sized type"))
- if prev_bit_position + fbitsize > 8 * ftype.size:
- prev_bit_position = 0
+ # Can the field start at the offset given by 'boffset'? It
+ # can if it would entirely fit into an aligned ftype field.
+ bits_already_occupied = boffset - (field_offset_bytes * 8)
+
+ if bits_already_occupied + fbitsize > 8 * ftype.size:
+ # it would not fit, we need to start at the next
+ # allowed position
+ field_offset_bytes += falign
+ assert boffset < field_offset_bytes * 8
+ boffset = field_offset_bytes * 8
+ bitshift = 0
else:
- # we can share the same field as 'prev_field'
- offset = prev_field.offset
- bitshift = prev_bit_position
- if not is_union:
- prev_bit_position += fbitsize
- #
- if (len(fname) == 0 and
- isinstance(ftype, ctypestruct.W_CTypeStructOrUnion)):
- # a nested anonymous struct or union
- srcfield2names = {}
- for name, srcfld in ftype.fields_dict.items():
- srcfield2names[srcfld] = name
- for srcfld in ftype.fields_list:
- fld = srcfld.make_shifted(offset)
+ bitshift = bits_already_occupied
+
+ fld = ctypestruct.W_CField(ftype, field_offset_bytes,
+ bitshift, fbitsize)
fields_list.append(fld)
- try:
- fields_dict[srcfield2names[srcfld]] = fld
- except KeyError:
- pass
- # always forbid such structures from being passed by value
- custom_field_pos = True
- else:
- # a regular field
- fld = ctypestruct.W_CField(ftype, offset, bitshift, fbitsize)
- fields_list.append(fld)
- fields_dict[fname] = fld
- #
- if maxsize < ftype.size:
- maxsize = ftype.size
- if not is_union:
- offset += ftype.size
+ fields_dict[fname] = fld
+
+ boffset += fbitsize
- if is_union:
- assert offset == 0
- offset = maxsize
+ if boffset > boffsetmax:
+ boffsetmax = boffset
# Like C, if the size of this structure would be zero, we compute it
# as 1 instead. But for ctypes support, we allow the manually-
# specified totalsize to be zero in this case.
+ got = (boffsetmax + 7) // 8
if totalsize < 0:
- offset = (offset + alignment - 1) & ~(alignment - 1)
- totalsize = offset or 1
- elif totalsize < offset:
+ totalsize = (got + alignment - 1) & ~(alignment - 1)
+ totalsize = totalsize or 1
+ elif totalsize < got:
raise operationerrfmt(space.w_TypeError,
"%s cannot be of size %d: there are fields at least "
- "up to %d", w_ctype.name, totalsize, offset)
+ "up to %d", w_ctype.name, totalsize, got)
if totalalignment < 0:
totalalignment = alignment
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
@@ -2757,6 +2757,35 @@
assert wr() is None
py.test.raises(RuntimeError, from_handle, cast(BCharP, 0))
+def test_bitfield_as_gcc():
+ BChar = new_primitive_type("char")
+ BShort = new_primitive_type("short")
+ BInt = new_primitive_type("int")
+ BStruct = new_struct_type("foo1")
+ complete_struct_or_union(BStruct, [('a', BChar, -1),
+ ('b', BInt, 9),
+ ('c', BChar, -1)])
+ assert typeoffsetof(BStruct, 'c') == (BChar, 3)
+ assert sizeof(BStruct) == 4
+ assert alignof(BStruct) == 4
+ #
+ BStruct = new_struct_type("foo2")
+ complete_struct_or_union(BStruct, [('a', BChar, -1),
+ ('', BShort, 9),
+ ('c', BChar, -1)])
+ assert typeoffsetof(BStruct, 'c') == (BChar, 4)
+ assert sizeof(BStruct) == 5
+ assert alignof(BStruct) == 1
+ #
+ BStruct = new_struct_type("foo2")
+ complete_struct_or_union(BStruct, [('a', BChar, -1),
+ ('', BInt, 0),
+ ('', BInt, 0),
+ ('c', BChar, -1)])
+ assert typeoffsetof(BStruct, 'c') == (BChar, 4)
+ assert sizeof(BStruct) == 5
+ assert alignof(BStruct) == 1
+
def test_version():
# this test is here mostly for PyPy
diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py
--- a/pypy/module/_minimal_curses/fficurses.py
+++ b/pypy/module/_minimal_curses/fficurses.py
@@ -11,21 +11,50 @@
from sys import platform
import os.path
-_CYGWIN = platform == 'cygwin'
-_NCURSES_CURSES = os.path.isfile("/usr/include/ncurses/curses.h")
+# We cannot trust ncurses5-config, it's broken in various ways in
+# various versions. For example it might not list -ltinfo even though
+# it's needed, or --cflags might be completely empty. On Ubuntu 10.04
+# it gives -I/usr/include/ncurses, which doesn't exist at all. Crap.
-if _CYGWIN or _NCURSES_CURSES:
- eci = ExternalCompilationInfo(
- includes = ['ncurses/curses.h', 'ncurses/term.h'],
- libraries = ['curses'],
- )
-else:
- eci = ExternalCompilationInfo(
- includes = ['curses.h', 'term.h'],
- libraries = ['curses'],
- )
+def try_cflags():
+ yield ExternalCompilationInfo(includes=['curses.h', 'term.h'])
+ yield ExternalCompilationInfo(includes=['curses.h', 'term.h'],
+ include_dirs=['/usr/include/ncurses'])
+ yield ExternalCompilationInfo(includes=['ncurses/curses.h',
+ 'ncurses/term.h'])
-rffi_platform.verify_eci(eci)
+def try_ldflags():
+ yield ExternalCompilationInfo(libraries=['curses'])
+ yield ExternalCompilationInfo(libraries=['curses', 'tinfo'])
+
+def try_tools():
+ try:
+ yield ExternalCompilationInfo.from_pkg_config("ncurses")
+ except Exception:
+ pass
+ try:
+ yield ExternalCompilationInfo.from_config_tool("ncurses5-config")
+ except Exception:
+ pass
+
+def try_eci():
+ for eci in try_tools():
+ yield eci.merge(ExternalCompilationInfo(includes=['curses.h',
+ 'term.h']))
+ for eci1 in try_cflags():
+ for eci2 in try_ldflags():
+ yield eci1.merge(eci2)
+
+def guess_eci():
+ for eci in try_eci():
+ class CConfig:
+ _compilation_info_ = eci
+ HAS = rffi_platform.Has("setupterm")
+ if rffi_platform.configure(CConfig)['HAS']:
+ return eci
+ raise ImportError("failed to guess where ncurses is installed")
+
+eci = guess_eci()
INT = rffi.INT
diff --git a/pypy/module/_multiprocessing/interp_connection.py b/pypy/module/_multiprocessing/interp_connection.py
--- a/pypy/module/_multiprocessing/interp_connection.py
+++ b/pypy/module/_multiprocessing/interp_connection.py
@@ -374,7 +374,7 @@
return space.wrap(self)
def descr_repr(self, space):
- return self._repr(space, self.handle)
+ return self._repr(space, rffi.cast(rffi.INTPTR_T, self.handle))
def is_valid(self):
return self.handle != self.INVALID_HANDLE_VALUE
diff --git a/pypy/module/_multiprocessing/test/test_connection.py b/pypy/module/_multiprocessing/test/test_connection.py
--- a/pypy/module/_multiprocessing/test/test_connection.py
+++ b/pypy/module/_multiprocessing/test/test_connection.py
@@ -67,7 +67,12 @@
assert rhandle.readable
class AppTestWinpipeConnection(BaseConnectionTest):
- spaceconfig = dict(usemodules=('_multiprocessing', 'thread', 'signal'))
+ spaceconfig = {
+ "usemodules": [
+ '_multiprocessing', 'thread', 'signal', 'struct', 'array',
+ 'itertools', '_socket', 'binascii',
+ ]
+ }
def setup_class(cls):
if sys.platform != "win32":
@@ -179,4 +184,4 @@
assert repr(c) == '<read-write Connection, handle 1>'
if hasattr(_multiprocessing, 'PipeConnection'):
c = _multiprocessing.PipeConnection(1)
- assert repr(c) == '<read-write Connection, handle 1>'
+ assert repr(c) == '<read-write PipeConnection, handle 1>'
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -1,24 +1,22 @@
+from rpython.rtyper.lltypesystem import lltype, rffi
+
from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.interpreter.argument import Arguments
-from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.function import ClassMethod, Method, StaticMethod
from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.function import (
- BuiltinFunction, Method, StaticMethod, ClassMethod)
-from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.cpyext.pyobject import (PyObject, from_ref, make_ref,
- make_typedescr, Py_DecRef)
+from pypy.interpreter.typedef import (
+ GetSetProperty, TypeDef, interp_attrproperty, interp_attrproperty_w)
from pypy.module.cpyext.api import (
- generic_cpy_call, cpython_api, PyObject, cpython_struct, METH_KEYWORDS,
- METH_O, CONST_STRING, METH_CLASS, METH_STATIC, METH_COEXIST, METH_NOARGS,
- METH_VARARGS, build_type_checkers, PyObjectFields, bootstrap_function)
-from pypy.module.cpyext.pyerrors import PyErr_Occurred
-from rpython.rlib.objectmodel import we_are_translated
+ CONST_STRING, METH_CLASS, METH_COEXIST, METH_KEYWORDS, METH_NOARGS, METH_O,
+ METH_STATIC, METH_VARARGS, PyObject, PyObjectFields, bootstrap_function,
+ build_type_checkers, cpython_api, cpython_struct, generic_cpy_call)
+from pypy.module.cpyext.pyobject import (
+ Py_DecRef, from_ref, make_ref, make_typedescr)
PyCFunction_typedef = rffi.COpaquePtr(typedef='PyCFunction')
PyCFunction = lltype.Ptr(lltype.FuncType([PyObject, PyObject], PyObject))
-PyCFunctionKwArgs = lltype.Ptr(lltype.FuncType([PyObject, PyObject, PyObject], PyObject))
+PyCFunctionKwArgs = lltype.Ptr(lltype.FuncType([PyObject, PyObject, PyObject],
+ PyObject))
PyMethodDef = cpython_struct(
'PyMethodDef',
@@ -89,9 +87,9 @@
self.name + "() takes no arguments"))
elif flags & METH_O:
if length != 1:
- raise OperationError(space.w_TypeError,
- space.wrap("%s() takes exactly one argument (%d given)" % (
- self.name, length)))
+ msg = "%s() takes exactly one argument (%d given)"
+ raise operationerrfmt(space.w_TypeError, msg,
+ self.name, length)
w_arg = space.getitem(w_args, space.wrap(0))
return generic_cpy_call(space, func, w_self, w_arg)
elif flags & METH_VARARGS:
@@ -126,9 +124,12 @@
return self.space.unwrap(self.descr_method_repr())
def descr_method_repr(self):
- return self.getrepr(self.space, "built-in method '%s' of '%s' object" % (self.name, self.w_objclass.getname(self.space)))
+ return self.getrepr(self.space,
+ "built-in method '%s' of '%s' object" %
+ (self.name, self.w_objclass.getname(self.space)))
-PyCFunction_Check, PyCFunction_CheckExact = build_type_checkers("CFunction", W_PyCFunctionObject)
+PyCFunction_Check, PyCFunction_CheckExact = build_type_checkers(
+ "CFunction", W_PyCFunctionObject)
class W_PyCClassMethodObject(W_PyCFunctionObject):
w_self = None
@@ -142,12 +143,14 @@
return self.space.unwrap(self.descr_method_repr())
def descr_method_repr(self):
- return self.getrepr(self.space, "built-in method '%s' of '%s' object" % (self.name, self.w_objclass.getname(self.space)))
+ return self.getrepr(self.space,
+ "built-in method '%s' of '%s' object" %
+ (self.name, self.w_objclass.getname(self.space)))
class W_PyCWrapperObject(W_Root):
- def __init__(self, space, pto, method_name, wrapper_func, wrapper_func_kwds,
- doc, func):
+ def __init__(self, space, pto, method_name, wrapper_func,
+ wrapper_func_kwds, doc, func):
self.space = space
self.method_name = method_name
self.wrapper_func = wrapper_func
@@ -160,7 +163,8 @@
def call(self, space, w_self, w_args, w_kw):
if self.wrapper_func is None:
assert self.wrapper_func_kwds is not None
- return self.wrapper_func_kwds(space, w_self, w_args, self.func, w_kw)
+ return self.wrapper_func_kwds(space, w_self, w_args, self.func,
+ w_kw)
if space.is_true(w_kw):
raise operationerrfmt(
space.w_TypeError,
@@ -169,8 +173,9 @@
return self.wrapper_func(space, w_self, w_args, self.func)
def descr_method_repr(self):
- return self.space.wrap("<slot wrapper '%s' of '%s' objects>" % (self.method_name,
- self.w_objclass.getname(self.space)))
+ return self.space.wrap("<slot wrapper '%s' of '%s' objects>" %
+ (self.method_name,
+ self.w_objclass.getname(self.space)))
def cwrapper_descr_call(space, w_self, __args__):
self = space.interp_w(W_PyCWrapperObject, w_self)
@@ -240,7 +245,8 @@
__get__ = interp2app(cclassmethod_descr_get),
__call__ = interp2app(cmethod_descr_call),
__name__ = interp_attrproperty('name', cls=W_PyCClassMethodObject),
- __objclass__ = interp_attrproperty_w('w_objclass', cls=W_PyCClassMethodObject),
+ __objclass__ = interp_attrproperty_w('w_objclass',
+ cls=W_PyCClassMethodObject),
__repr__ = interp2app(W_PyCClassMethodObject.descr_method_repr),
)
W_PyCClassMethodObject.typedef.acceptable_as_base_class = False
@@ -284,18 +290,19 @@
def PyDescr_NewClassMethod(space, w_type, method):
return space.wrap(W_PyCClassMethodObject(space, method, w_type))
-def PyDescr_NewWrapper(space, pto, method_name, wrapper_func, wrapper_func_kwds,
- doc, func):
+def PyDescr_NewWrapper(space, pto, method_name, wrapper_func,
+ wrapper_func_kwds, doc, func):
# not exactly the API sig
return space.wrap(W_PyCWrapperObject(space, pto, method_name,
wrapper_func, wrapper_func_kwds, doc, func))
@cpython_api([lltype.Ptr(PyMethodDef), PyObject, CONST_STRING], PyObject)
def Py_FindMethod(space, table, w_obj, name_ptr):
- """Return a bound method object for an extension type implemented in C. This
- can be useful in the implementation of a tp_getattro or
- tp_getattr handler that does not use the
- PyObject_GenericGetAttr() function."""
+ """Return a bound method object for an extension type implemented in
+ C. This can be useful in the implementation of a tp_getattro or
+ tp_getattr handler that does not use the PyObject_GenericGetAttr()
+ function.
+ """
# XXX handle __doc__
name = rffi.charp2str(name_ptr)
@@ -307,10 +314,12 @@
while True:
i = i + 1
method = methods[i]
- if not method.c_ml_name: break
+ if not method.c_ml_name:
+ break
if name == "__methods__":
- method_list_w.append(space.wrap(rffi.charp2str(method.c_ml_name)))
- elif rffi.charp2str(method.c_ml_name) == name: # XXX expensive copying
+ method_list_w.append(
+ space.wrap(rffi.charp2str(method.c_ml_name)))
+ elif rffi.charp2str(method.c_ml_name) == name: # XXX expensive copy
return space.wrap(W_PyCFunctionObject(space, method, w_obj))
if name == "__methods__":
return space.newlist(method_list_w)
diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py b/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py
--- a/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py
@@ -1,5 +1,5 @@
# Generated by pypy/tool/import_cffi.py
-import py
+import py, sys
from pypy.module.test_lib_pypy.cffi_tests import backend_tests, test_function, test_ownlib
from cffi import FFI
import _cffi_backend
@@ -37,3 +37,114 @@
assert ffi.from_handle(p) is o
assert ffi.from_handle(ffi.cast("char *", p)) is o
py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL)
+
+
+class TestBitfield:
+ def check(self, source, expected_ofs_y, expected_align, expected_size):
+ ffi = FFI()
+ ffi.cdef("struct s1 { %s };" % source)
+ ctype = ffi.typeof("struct s1")
+ # verify the information with gcc
+ if sys.platform != "win32":
+ ffi1 = FFI()
+ ffi1.cdef("""
+ static const int Gofs_y, Galign, Gsize;
+ struct s1 *try_with_value(int fieldnum, long long value);
+ """)
+ fnames = [name for name, cfield in ctype.fields
+ if name and cfield.bitsize > 0]
+ setters = ['case %d: s.%s = value; break;' % iname
+ for iname in enumerate(fnames)]
+ lib = ffi1.verify("""
+ struct s1 { %s };
+ struct sa { char a; struct s1 b; };
+ #define Gofs_y offsetof(struct s1, y)
+ #define Galign offsetof(struct sa, b)
+ #define Gsize sizeof(struct s1)
+ struct s1 *try_with_value(int fieldnum, long long value)
+ {
+ static struct s1 s;
+ memset(&s, 0, sizeof(s));
+ switch (fieldnum) { %s }
+ return &s;
+ }
+ """ % (source, ' '.join(setters)))
+ assert lib.Gofs_y == expected_ofs_y
+ assert lib.Galign == expected_align
+ assert lib.Gsize == expected_size
+ else:
+ lib = None
+ fnames = None
+ # the real test follows
+ assert ffi.offsetof("struct s1", "y") == expected_ofs_y
+ assert ffi.alignof("struct s1") == expected_align
+ assert ffi.sizeof("struct s1") == expected_size
+ # compare the actual storage of the two
+ for name, cfield in ctype.fields:
+ if cfield.bitsize < 0 or not name:
+ continue
+ if int(ffi.cast(cfield.type, -1)) == -1: # signed
+ min_value = -(1 << (cfield.bitsize-1))
+ max_value = (1 << (cfield.bitsize-1)) - 1
+ else:
+ min_value = 0
+ max_value = (1 << cfield.bitsize) - 1
+ for t in [1, 2, 4, 8, 16, 128, 2813, 89728, 981729,
+ -1,-2,-4,-8,-16,-128,-2813,-89728,-981729]:
+ if min_value <= t <= max_value:
+ self._fieldcheck(ffi, lib, fnames, name, t)
+
+ def _fieldcheck(self, ffi, lib, fnames, name, value):
+ s = ffi.new("struct s1 *")
+ setattr(s, name, value)
+ assert getattr(s, name) == value
+ raw1 = bytes(ffi.buffer(s))
+ if lib is not None:
+ t = lib.try_with_value(fnames.index(name), value)
+ raw2 = bytes(ffi.buffer(t, len(raw1)))
+ assert raw1 == raw2
+
+ def test_bitfield_basic(self):
+ self.check("int a; int b:9; int c:20; int y;", 8, 4, 12)
+ self.check("int a; short b:9; short c:7; int y;", 8, 4, 12)
+ self.check("int a; short b:9; short c:9; int y;", 8, 4, 12)
+
+ def test_bitfield_reuse_if_enough_space(self):
+ self.check("int a:2; char y;", 1, 4, 4)
+ self.check("int a:1; char b ; int c:1; char y;", 3, 4, 4)
+ self.check("int a:1; char b:8; int c:1; char y;", 3, 4, 4)
+ self.check("char a; int b:9; char y;", 3, 4, 4)
+ self.check("char a; short b:9; char y;", 4, 2, 6)
+ self.check("int a:2; char b:6; char y;", 1, 4, 4)
+ self.check("int a:2; char b:7; char y;", 2, 4, 4)
+ self.check("int a:2; short b:15; char c:2; char y;", 5, 4, 8)
+ self.check("int a:2; char b:1; char c:1; char y;", 1, 4, 4)
+
+ def test_bitfield_anonymous_no_align(self):
+ L = FFI().alignof("long long")
+ self.check("char y; int :1;", 0, 1, 2)
+ self.check("char x; int z:1; char y;", 2, 4, 4)
+ self.check("char x; int :1; char y;", 2, 1, 3)
+ self.check("char x; long long z:48; char y;", 7, L, 8)
+ self.check("char x; long long :48; char y;", 7, 1, 8)
+ self.check("char x; long long z:56; char y;", 8, L, 8 + L)
+ self.check("char x; long long :56; char y;", 8, 1, 9)
+ self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L)
+ self.check("char x; long long :57; char y;", L + 8, 1, L + 9)
+
+ def test_bitfield_zero(self):
+ L = FFI().alignof("long long")
+ self.check("char y; int :0;", 0, 1, 4)
+ self.check("char x; int :0; char y;", 4, 1, 5)
+ self.check("char x; long long :0; char y;", L, 1, L + 1)
+ self.check("short x, y; int :0; int :0;", 2, 2, 4)
+ self.check("char x; int :0; short b:1; char y;", 5, 2, 6)
+
+ def test_error_cases(self):
+ ffi = FFI()
+ py.test.raises(TypeError,
+ 'ffi.cdef("struct s1 { float x:1; };"); ffi.new("struct s1 *")')
+ py.test.raises(TypeError,
+ 'ffi.cdef("struct s2 { char x:0; };"); ffi.new("struct s2 *")')
+ py.test.raises(TypeError,
+ 'ffi.cdef("struct s3 { char x:9; };"); ffi.new("struct s3 *")')
diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py
--- a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py
@@ -1620,3 +1620,18 @@
ffi.cdef("int f(void *);")
lib = ffi.verify("int f(void *x) { return ((char*)x)[0]; }")
assert lib.f(b"foobar") == ord(b"f")
+
+def test_dir():
+ ffi = FFI()
+ ffi.cdef("""void somefunc(void);
+ extern int somevar, somearray[2];
+ static char *const sv2;
+ enum my_e { AA, BB, ... };
+ #define FOO ...""")
+ lib = ffi.verify("""void somefunc(void) { }
+ int somevar, somearray[2];
+ #define sv2 "text"
+ enum my_e { AA, BB };
+ #define FOO 42""")
+ assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray',
+ 'somefunc', 'somevar', 'sv2']
diff --git a/pypy/objspace/std/stdtypedef.py b/pypy/objspace/std/stdtypedef.py
--- a/pypy/objspace/std/stdtypedef.py
+++ b/pypy/objspace/std/stdtypedef.py
@@ -147,21 +147,12 @@
else:
plural = ''
return "unsupported operand type%s for %%s: %s" % (
- plural, ', '.join(["'%s'"] * nbargs))
+ plural, ', '.join(["'%T'"] * nbargs))
_gettypeerrormsg._annspecialcase_ = 'specialize:memo'
-def _gettypenames(space, *args_w):
- if args_w:
- typename = space.type(args_w[-1]).getname(space)
- return _gettypenames(space, *args_w[:-1]) + (typename,)
- return ()
-_gettypenames._always_inline_ = True
-
def gettypeerror(space, operatorsymbol, *args_w):
msg = _gettypeerrormsg(len(args_w))
- type_names = _gettypenames(space, *args_w)
- return operationerrfmt(space.w_TypeError, msg,
- operatorsymbol, *type_names)
+ return operationerrfmt(space.w_TypeError, msg, operatorsymbol, *args_w)
def make_perform_trampoline(prefix, exprargs, expr, miniglobals, multimethod, selfindex=0,
allow_NotImplemented_results=False):
diff --git a/rpython/translator/tool/cbuild.py b/rpython/translator/tool/cbuild.py
--- a/rpython/translator/tool/cbuild.py
+++ b/rpython/translator/tool/cbuild.py
@@ -1,5 +1,5 @@
import py
-import sys
+import sys, subprocess
from rpython.translator.platform import host
from rpython.tool.udir import udir
@@ -99,6 +99,7 @@
return platform
return self._platform
+ @classmethod
def from_compiler_flags(cls, flags):
"""Returns a new ExternalCompilationInfo instance by parsing
the string 'flags', which is in the typical Unix compiler flags
@@ -124,8 +125,8 @@
return cls(pre_include_bits=pre_include_bits,
include_dirs=include_dirs,
compile_extra=compile_extra)
- from_compiler_flags = classmethod(from_compiler_flags)
+ @classmethod
def from_linker_flags(cls, flags):
"""Returns a new ExternalCompilationInfo instance by parsing
the string 'flags', which is in the typical Unix linker flags
@@ -146,8 +147,8 @@
return cls(libraries=libraries,
library_dirs=library_dirs,
link_extra=link_extra)
- from_linker_flags = classmethod(from_linker_flags)
+ @classmethod
def from_config_tool(cls, execonfigtool):
"""Returns a new ExternalCompilationInfo instance by executing
the 'execonfigtool' with --cflags and --libs arguments."""
@@ -156,12 +157,29 @@
raise ImportError("cannot find %r" % (execonfigtool,))
# we raise ImportError to be nice to the pypy.config.pypyoption
# logic of skipping modules depending on non-installed libs
- cflags = py.process.cmdexec('"%s" --cflags' % (str(path),))
+ return cls._run_config_tool('"%s"' % (str(path),))
+
+ @classmethod
+ def from_pkg_config(cls, pkgname):
+ """Returns a new ExternalCompilationInfo instance by executing
+ 'pkg-config <pkgname>' with --cflags and --libs arguments."""
+ assert isinstance(pkgname, str)
+ try:
+ popen = subprocess.Popen(['pkg-config', pkgname, '--exists'])
+ result = popen.wait()
+ except OSError:
+ result = -1
+ if result != 0:
+ raise ImportError("failed: 'pkg-config %s --exists'" % pkgname)
+ return cls._run_config_tool('pkg-config "%s"' % pkgname)
+
+ @classmethod
+ def _run_config_tool(cls, command):
+ cflags = py.process.cmdexec('%s --cflags' % command)
eci1 = cls.from_compiler_flags(cflags)
- libs = py.process.cmdexec('"%s" --libs' % (str(path),))
+ libs = py.process.cmdexec('%s --libs' % command)
eci2 = cls.from_linker_flags(libs)
return eci1.merge(eci2)
- from_config_tool = classmethod(from_config_tool)
def _value(self):
return tuple([getattr(self, x)
diff --git a/rpython/translator/tool/test/test_cbuild.py b/rpython/translator/tool/test/test_cbuild.py
--- a/rpython/translator/tool/test/test_cbuild.py
+++ b/rpython/translator/tool/test/test_cbuild.py
@@ -127,6 +127,18 @@
ExternalCompilationInfo.from_config_tool,
'dxowqbncpqympqhe-config')
+ def test_from_pkg_config(self):
+ try:
+ cmd = ['pkg-config', 'ncurses', '--exists']
+ popen = Popen(cmd)
+ result = popen.wait()
+ except OSError:
+ result = -1
+ if result != 0:
+ py.test.skip("failed: %r" % (' '.join(cmd),))
+ eci = ExternalCompilationInfo.from_pkg_config('ncurses')
+ assert 'ncurses' in eci.libraries
+
def test_platforms(self):
from rpython.translator.platform import Platform
More information about the pypy-commit
mailing list