[pypy-svn] r72506 - in pypy/trunk/pypy/module/cpyext: . include test
xoraxax at codespeak.net
xoraxax at codespeak.net
Sun Mar 21 19:30:58 CET 2010
Author: xoraxax
Date: Sun Mar 21 19:30:56 2010
New Revision: 72506
Modified:
pypy/trunk/pypy/module/cpyext/api.py
pypy/trunk/pypy/module/cpyext/include/methodobject.h
pypy/trunk/pypy/module/cpyext/methodobject.py
pypy/trunk/pypy/module/cpyext/modsupport.py
pypy/trunk/pypy/module/cpyext/object.py
pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
pypy/trunk/pypy/module/cpyext/typeobject.py
Log:
General progress: added correct allocation code respecting basesize, fix instantiation of objects, extend module support code.
Modified: pypy/trunk/pypy/module/cpyext/api.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/api.py (original)
+++ pypy/trunk/pypy/module/cpyext/api.py Sun Mar 21 19:30:56 2010
@@ -40,6 +40,10 @@
#globals().update(rffi_platform.configure(CConfig_constants))
Py_TPFLAGS_READY = (1L<<12)
Py_TPFLAGS_READYING = (1L<<13)
+METH_COEXIST = 0x0040
+METH_STATIC = 0x0020
+METH_CLASS = 0x0010
+METH_NOARGS = 0x0004
class ApiFunction:
@@ -75,7 +79,7 @@
'PyExc_Exception': ('PyObject*', 'space.w_Exception'),
'PyExc_TypeError': ('PyObject*', 'space.w_TypeError'),
'PyType_Type': ('PyTypeObject*', 'space.w_type'),
- 'PyBaseObject_Type': ('PyTypeObject*', 'space.w_object'),
+ 'PyBaseObject_Type#': ('PyTypeObject*', 'space.w_object'),
}
# It is important that these PyObjects are allocated in a raw fashion
@@ -84,8 +88,10 @@
PyObjectStruct = lltype.ForwardReference()
PyObject = lltype.Ptr(PyObjectStruct)
PyObjectFields = (("obj_refcnt", lltype.Signed), ("obj_type", PyObject))
+PyVarObjectFields = PyObjectFields + (("obj_size", Py_ssize_t), )
cpython_struct('struct _object', PyObjectFields, PyObjectStruct)
+
def configure():
for name, TYPE in rffi_platform.configure(CConfig).iteritems():
if name in TYPES:
@@ -97,13 +103,38 @@
class InvalidPointerException(Exception):
pass
+def get_padded_type(T, size):
+ fields = T._flds.copy()
+ hints = T._hints.copy()
+ hints["size"] = size
+ del hints["fieldoffsets"]
+ pad_fields = []
+ new_fields = []
+ for name in T._names:
+ new_fields.append((name, fields[name]))
+ for i in xrange(size - rffi.sizeof(T)):
+ new_fields.append(("custom%i" % (i, ), lltype.Char))
+ hints["padding"] = hints["padding"] + tuple(pad_fields)
+ return lltype.Struct(hints["c_name"], *new_fields, hints=hints)
+
def make_ref(space, w_obj, borrowed=False):
+ if w_obj is None:
+ return lltype.nullptr(PyObject.TO)
+ #raise NullPointerException("Trying to pass a NULL reference")
state = space.fromcache(State)
py_obj = state.py_objects_w2r.get(w_obj)
if py_obj is None:
+ from pypy.module.cpyext.typeobject import allocate_type_obj,\
+ W_PyCTypeObject, W_PyCObject
if space.is_w(space.type(w_obj), space.w_type):
- from pypy.module.cpyext.typeobject import allocate_type_obj
py_obj = allocate_type_obj(space, w_obj)
+ elif isinstance(w_obj, W_PyCObject):
+ w_type = space.type(w_obj)
+ assert isinstance(w_type, W_PyCTypeObject)
+ pto = w_type.pto
+ basicsize = pto._obj.c_tp_basicsize
+ T = get_padded_type(PyObject.TO, basicsize)
+ py_obj = lltype.malloc(T, None, flavor="raw")
else:
py_obj = lltype.malloc(PyObject.TO, None, flavor="raw")
py_obj.c_obj_refcnt = 1
@@ -124,6 +155,7 @@
try:
obj = state.py_objects_r2w[ptr]
except KeyError:
+ import pdb; pdb.set_trace()
raise InvalidPointerException("Got invalid reference to a PyObject")
return obj
@@ -146,8 +178,13 @@
pypy_rename = []
renamed_symbols = []
for name in export_symbols:
+ if "#" in name:
+ deref = "*"
+ else:
+ deref = ""
+ name = name.replace("#", "")
newname = name.replace('Py', 'PyPy')
- pypy_rename.append('#define %s %s' % (name, newname))
+ pypy_rename.append('#define %s %s%s' % (name, deref, newname))
renamed_symbols.append(newname)
export_symbols = renamed_symbols
pypy_rename_h = udir.join('pypy_rename.h')
@@ -188,7 +225,7 @@
global_objects = []
for name, (type, expr) in GLOBALS.iteritems():
- global_objects.append('%s %s = NULL;' % (type, name))
+ global_objects.append('%s %s = NULL;' % (type, name.replace("#", "")))
global_code = '\n'.join(global_objects)
code = (prologue +
struct_declaration_code +
@@ -216,6 +253,7 @@
# populate static data
for name, (type, expr) in GLOBALS.iteritems():
+ name = name.replace("#", "")
if rename:
name = name.replace('Py', 'PyPy')
w_obj = eval(expr)
Modified: pypy/trunk/pypy/module/cpyext/include/methodobject.h
==============================================================================
--- pypy/trunk/pypy/module/cpyext/include/methodobject.h (original)
+++ pypy/trunk/pypy/module/cpyext/include/methodobject.h Sun Mar 21 19:30:56 2010
@@ -29,6 +29,20 @@
#define METH_NOARGS 0x0004
#define METH_O 0x0008
+/* METH_CLASS and METH_STATIC are a little different; these control
+ the construction of methods for a class. These cannot be used for
+ functions in modules. */
+#define METH_CLASS 0x0010
+#define METH_STATIC 0x0020
+
+/* METH_COEXIST allows a method to be entered eventhough a slot has
+ already filled the entry. When defined, the flag allows a separate
+ method, "__contains__" for example, to coexist with a defined
+ slot like sq_contains. */
+
+#define METH_COEXIST 0x0040
+
+
#ifdef __cplusplus
}
Modified: pypy/trunk/pypy/module/cpyext/methodobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/methodobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/methodobject.py Sun Mar 21 19:30:56 2010
@@ -5,7 +5,7 @@
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import PyObject, from_ref, NullPointerException, \
- InvalidPointerException
+ InvalidPointerException, make_ref
from pypy.module.cpyext.state import State
from pypy.rlib.objectmodel import we_are_translated
@@ -19,10 +19,14 @@
def cfunction_descr_call(space, w_self, __args__):
self = space.interp_w(W_PyCFunctionObject, w_self)
args_w, kw_w = __args__.unpack()
- null = lltype.nullptr(PyObject.TO) # XXX for the moment
+ w_kw = space.newdict()
+ for key, w_value in kw_w:
+ space.setitem(w_kw, space.wrap(key), w_value)
+ args_tuple = space.newtuple([space.wrap(args_w), w_kw])
+ #null = lltype.nullptr(PyObject.TO) # XXX for the moment
# Call the C function
- result = self.ml.c_ml_meth(null, null)
+ result = self.ml.c_ml_meth(make_ref(space, self.w_self), make_ref(space, args_tuple))
try:
ret = from_ref(space, result)
except NullPointerException:
Modified: pypy/trunk/pypy/module/cpyext/modsupport.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/modsupport.py (original)
+++ pypy/trunk/pypy/module/cpyext/modsupport.py Sun Mar 21 19:30:56 2010
@@ -1,5 +1,6 @@
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import cpython_api, cpython_struct, PyObject
+from pypy.module.cpyext.api import cpython_api, cpython_struct, PyObject, \
+ METH_STATIC, METH_CLASS, METH_COEXIST
from pypy.interpreter.module import Module
from pypy.module.cpyext.methodobject import PyCFunction_NewEx
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
@@ -25,26 +26,43 @@
def Py_InitModule(space, name, methods):
modname = rffi.charp2str(name)
w_mod = PyImport_AddModule(space, modname)
- dict_w = convert_method_defs(space, methods)
+ dict_w = convert_method_defs(space, methods, None)
for key, w_value in dict_w.items():
space.setattr(w_mod, space.wrap(key), w_value)
return w_mod
-def convert_method_defs(space, methods):
+def convert_method_defs(space, methods, pto):
methods = rffi.cast(rffi.CArrayPtr(PyMethodDef), methods)
dict_w = {}
if methods:
- i = 0
+ i = -1
while True:
+ i = i + 1
method = methods[i]
if not method.c_ml_name: break
methodname = rffi.charp2str(method.c_ml_name)
flags = method.c_ml_flags
- w_function = PyCFunction_NewEx(space, method, None)
- dict_w[methodname] = w_function
- i = i + 1
+ if pto is None:
+ if flags & METH_CLASS or flags & METH_STATIC:
+ raise OperationError(space.w_ValueError,
+ "module functions cannot set METH_CLASS or METH_STATIC")
+ w_obj = PyCFunction_NewEx(space, method, None)
+ else:
+ if methodname in dict_w and not (flags & METH_COEXIST):
+ continue
+ if flags & METH_CLASS:
+ if flags & METH_STATIC:
+ raise OperationError(space.w_ValueError,
+ "method cannot be both class and static")
+ w_obj = PyDescr_NewClassMethod(pto, method)
+ elif flags & METH_STATIC:
+ w_func = PyCFunction_NewEx(space, method, None)
+ w_obj = PyStaticMethod_New(space, w_func)
+ else:
+ w_obj = PyDescr_NewMethod(space, pto, method)
+ dict_w[methodname] = w_obj
return dict_w
Modified: pypy/trunk/pypy/module/cpyext/object.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/object.py (original)
+++ pypy/trunk/pypy/module/cpyext/object.py Sun Mar 21 19:30:56 2010
@@ -3,14 +3,13 @@
from pypy.module.cpyext.typeobject import PyTypeObjectPtr, W_PyCTypeObject, W_PyCObject
from pypy.objspace.std.objectobject import W_ObjectObject
-def get_cls_for_type_object(space, w_type):
- if isinstance(w_type, W_PyCTypeObject):
- return space.allocate_instance(W_PyCObject, w_type)
- assert False, "Please add more cases in get_cls_for_type_object!"
@cpython_api([PyObject], PyObject)
def _PyObject_New(space, w_type):
- return get_cls_for_type_object(space, w_type)
+ if isinstance(w_type, W_PyCTypeObject):
+ w_pycobj = space.allocate_instance(W_PyCObject, w_type)
+ return w_pycobj
+ assert False, "Please add more cases in get_cls_for_type_object!"
@cpython_api([rffi.VOIDP_real], lltype.Void)
def PyObject_Del(space, w_obj):
Modified: pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_cpyext.py (original)
+++ pypy/trunk/pypy/module/cpyext/test/test_cpyext.py Sun Mar 21 19:30:56 2010
@@ -25,6 +25,11 @@
assert api.FUNCTIONS['Py_InitModule'].argtypes == [
rffi.CCHARP, lltype.Ptr(api.TYPES['PyMethodDef'])]
+ def test_padding(self):
+ T = api.get_padded_type(api.PyObject.TO, 42)
+ assert rffi.sizeof(T) == 42
+ print T
+
def compile_module(modname, **kwds):
eci = ExternalCompilationInfo(
export_symbols=['init%s' % (modname,)],
Modified: pypy/trunk/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/typeobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/typeobject.py Sun Mar 21 19:30:56 2010
@@ -64,7 +64,7 @@
traverseproc = P(FT([PyO, visitproc, rffi.VOIDP], rffi.INT))
PyTypeObjectFields = []
-PyTypeObjectFields.extend(PyObjectFields)
+PyTypeObjectFields.extend(PyVarObjectFields)
PyTypeObjectFields.extend([
("tp_name", rffi.CCHARP), # For printing, in format "<module>.<name>"
("tp_basicsize", Py_ssize_t), ("tp_itemsize", Py_ssize_t), # For allocation
@@ -143,9 +143,14 @@
class W_PyCTypeObject(W_TypeObject):
- pass
+ def __init__(self, space, pto):
+ self.pto = pto
+ bases_w = []
+ dict_w = convert_method_defs(space, pto.c_tp_methods, pto)
+ W_TypeObject.__init__(self, space, rffi.charp2str(pto.c_tp_name),
+ bases_w or [space.w_object], dict_w)
-class W_PyCObject(W_ObjectObject):
+class W_PyCObject(Wrappable):
pass
@unwrap_spec(ObjSpace, W_Root, W_Root)
@@ -160,12 +165,9 @@
return pto
def create_type_object(space, pto):
- bases_w = []
- dict_w = convert_method_defs(space, pto.c_tp_methods)
w_type = space.allocate_instance(W_PyCTypeObject, space.gettypeobject(W_PyCTypeObject.typedef))
- W_TypeObject.__init__(w_type, space, rffi.charp2str(pto.c_tp_name),
- bases_w or [space.w_object], dict_w)
+ w_type.__init__(space, pto)
w_type.ready()
return w_type
@@ -180,10 +182,11 @@
state.py_objects_w2r[w_obj] = pto
return 1
-W_PyCObject.typedef = TypeDef(
- 'C_object',
- #__getattrbute__ = interp2app(cobject_descr_getattribute),
- )
+W_PyCObject.typedef = W_ObjectObject.typedef
+#TypeDef(
+# 'C_object',
+# #__getattrbute__ = interp2app(cobject_descr_getattribute),
+# )
W_PyCTypeObject.typedef = TypeDef(
'C_type', W_TypeObject.typedef
More information about the Pypy-commit
mailing list