[pypy-svn] r73325 - in pypy/branch/cpython-extension/pypy/module/cpyext: . test
xoraxax at codespeak.net
xoraxax at codespeak.net
Sat Apr 3 04:53:43 CEST 2010
Author: xoraxax
Date: Sat Apr 3 04:53:40 2010
New Revision: 73325
Modified:
pypy/branch/cpython-extension/pypy/module/cpyext/api.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_typeobject.py
pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
Log:
Extended slots logic to cope with subclassing.
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/api.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/api.py Sat Apr 3 04:53:40 2010
@@ -372,7 +372,8 @@
def bootstrap_types(space):
from pypy.module.cpyext.pyobject import make_ref
- from pypy.module.cpyext.typeobject import PyTypeObjectPtr, PyPyType_Ready
+ from pypy.module.cpyext.typeobject import PyTypeObjectPtr, PyPyType_Ready, \
+ inherit_slots
# bootstrap this damn cycle
type_pto = make_ref(space, space.w_type)
type_pto = rffi.cast(PyTypeObjectPtr, type_pto)
@@ -385,6 +386,7 @@
PyPyType_Ready(space, type_pto, space.w_type)
type_pto.c_tp_bases = make_ref(space, space.newtuple([space.w_object]))
object_pto.c_tp_bases = make_ref(space, space.newtuple([]))
+ inherit_slots(space, type_pto, space.w_object)
#_____________________________________________________
# Build the bridge DLL, Allow extension DLLs to call
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_typeobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_typeobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_typeobject.py Sat Apr 3 04:53:40 2010
@@ -15,6 +15,7 @@
print "Obj has type", type(obj)
assert type(obj) is module.fooType
print "type of obj has type", type(type(obj))
+ print "type of type of obj has type", type(type(type(obj)))
obj2 = obj.copy()
assert module.new().name == "Foo Example"
c = module.fooType.copy
@@ -66,10 +67,9 @@
a = module.fooType
assert "cannot create" in raises(TypeError, "a()").value.message
- skip("In Progress")
class bar(module.fooType):
pass
+ assert "cannot create" in raises(TypeError, "bar()").value.message
fuu = module.FuuType
fuu_inst = fuu(u"abc")
- assert "cannot create" in raises(TypeError, "bar()").value.message
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py Sat Apr 3 04:53:40 2010
@@ -18,6 +18,7 @@
Py_TPFLAGS_HAVE_CLASS
from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
from pypy.interpreter.module import Module
+from pypy.interpreter.function import FunctionWithFixedCode, StaticMethod
from pypy.module.cpyext import structmemberdefs
from pypy.module.cpyext.modsupport import convert_method_defs
from pypy.module.cpyext.state import State
@@ -25,11 +26,11 @@
from pypy.module.cpyext.pyobject import Py_IncRef, Py_DecRef, _Py_Dealloc
from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr, PyTypeObject, \
- PyGetSetDef, PyMemberDef
+ PyGetSetDef, PyMemberDef, newfunc
from pypy.module.cpyext.slotdefs import slotdefs
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.rlib.rstring import rsplit
-from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.objectmodel import we_are_translated, specialize
WARN_ABOUT_MISSING_SLOT_FUNCTIONS = False
@@ -100,7 +101,7 @@
def update_all_slots(space, w_obj, pto):
# XXX fill slots in pto
state = space.fromcache(State)
- for method_name, slot_name, slot_func, _, _, doc in slotdefs:
+ for method_name, slot_name, slot_func, _, _, _ in slotdefs:
w_descr = space.lookup(w_obj, method_name)
if w_descr is None:
# XXX special case iternext
@@ -109,12 +110,14 @@
if WARN_ABOUT_MISSING_SLOT_FUNCTIONS:
os.write(2, method_name + " defined by the type but no slot function defined!\n")
continue
- if not we_are_translated() and method_name == "__new__" and "bar" in repr(w_obj):
- import pdb; pdb.set_trace()
slot_func_helper = llhelper(slot_func.api_func.functype,
slot_func.api_func.get_wrapper(space))
- # XXX special case wrapper-functions and use a "specific" slot func,
- # XXX special case tp_new
+ # XXX special case wrapper-functions and use a "specific" slot func
+
+ # the special case of __new__ in CPython works a bit differently, hopefully
+ # this matches the semantics
+ if method_name == "__new__" and not pto.c_tp_new:
+ continue
if len(slot_name) == 1:
setattr(pto, slot_name[0], slot_func_helper)
else:
@@ -146,11 +149,38 @@
continue
dict_w[method_name] = PyDescr_NewWrapper(space, pto, method_name, wrapper_func,
wrapper_func_kwds, doc, func_voidp)
+ if pto.c_tp_new:
+ add_tp_new_wrapper(space, dict_w, pto)
+
+ at cpython_api([PyObject, PyObject, PyObject], PyObject, external=False)
+def tp_new_wrapper(space, w_self, w_args, w_kwds): # XXX untested code
+ args_w = space.listview(w_args)[:]
+ args_w.insert(0, w_self)
+ w_args_new = space.newlist(args_w)
+ return space.call(space.lookup(space.w_type, space.wrap("__new__")), w_args_new, w_kwds)
+
+ at specialize.memo()
+def get_new_method_def(space):
+ from pypy.module.cpyext.modsupport import PyMethodDef
+ ptr = llmemory.malloc(Ptr(PyMethodDef), flavor="raw")
+ ptr.c_ml_name = rffi.str2charp("__new__")
+ ptr.c_ml_meth = llhelper(tp_new_wrapper.api_func.functype,
+ tp_new_wrapper.get_wrapper(space))
+ ptr.c_ml_flags = METH_VARARGS | METH_KEYWORDS
+ ptr.c_ml_doc = rffi.str2charp("T.__new__(S, ...) -> a new object with type S, a subtype of T")
+ return ptr
+
+def add_tp_new_wrapper(space, dict_w, pto):
+ if "__new__" in dict_w:
+ return
+ pyo = rffi.cast(PyObject, pto)
+ dict_w["__new__"] = PyCFunction_NewEx(space, get_new_method_def(space),
+ from_ref(space, pyo))
def inherit_special(space, pto, base_pto):
- # XXX copy basicsize and flags in a magical way
+ # XXX missing: copy basicsize and flags in a magical way
flags = rffi.cast(lltype.Signed, pto.c_tp_flags)
- if flags & Py_TPFLAGS_HAVE_CLASS:
+ if True or flags & Py_TPFLAGS_HAVE_CLASS: # XXX i do not understand this check
base_object_pyo = make_ref(space, space.w_object, steal=True)
base_object_pto = rffi.cast(PyTypeObjectPtr, base_object_pyo)
if base_pto != base_object_pto or \
@@ -161,7 +191,7 @@
class W_PyCTypeObject(W_TypeObject):
def __init__(self, space, pto):
- bases_w = [] # XXX fill
+ bases_w = space.fixedview(from_ref(space, pto.c_tp_bases))
dict_w = {}
add_operators(space, dict_w, pto)
@@ -179,7 +209,7 @@
class __extend__(W_Root):
__metaclass__ = extendabletype
- __slots__ = ("_pyolifeline", )
+ __slots__ = ("_pyolifeline", ) # hint for the annotator
_pyolifeline = None
def set_pyolifeline(self, lifeline):
self._pyolifeline = lifeline
@@ -261,20 +291,18 @@
@cpython_api([PyObject], lltype.Void, external=False)
def subtype_dealloc(space, obj):
pto = rffi.cast(PyTypeObjectPtr, obj.c_ob_type)
- assert pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE
base = pto
this_func_ptr = llhelper(subtype_dealloc.api_func.functype,
subtype_dealloc.api_func.get_wrapper(space))
- ref_of_object_type = rffi.cast(PyTypeObjectPtr,
- make_ref(space, space.w_object, steal=True))
while base.c_tp_dealloc == this_func_ptr:
base = base.c_tp_base
assert base
dealloc = base.c_tp_dealloc
# XXX call tp_del if necessary
generic_cpy_call(space, dealloc, obj)
- pto = rffi.cast(PyObject, pto)
- Py_DecRef(space, pto)
+ if pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE:
+ pto = rffi.cast(PyObject, pto)
+ Py_DecRef(space, pto)
@cpython_api([PyObject], lltype.Void, external=False)
@@ -302,7 +330,7 @@
obj_pto_voidp = rffi.cast(rffi.VOIDP_real, obj_pto)
generic_cpy_call(space, type_pto.c_tp_free, obj_pto_voidp)
pto = rffi.cast(PyObject, type_pto)
- Py_DecRef(space, pto)
+ Py_DecRef(space, pto) # XXX duplicate decref? (see above)
def allocate_type_obj(space, w_type):
@@ -362,6 +390,10 @@
elif pto.c_tp_base:
pto.c_tp_basicsize = pto.c_tp_base.c_tp_basicsize
+ # will be filled later on with the correct value
+ # may not be 0
+ if space.is_w(w_type, space.w_object):
+ pto.c_tp_new = rffi.cast(newfunc, 1)
update_all_slots(space, w_type, pto)
return pto
@@ -369,6 +401,19 @@
def PyType_Ready(space, pto):
return PyPyType_Ready(space, pto, None)
+def inherit_slots(space, pto, w_base):
+ # XXX missing: nearly everything
+ base_pyo = make_ref(space, w_base)
+ try:
+ base = rffi.cast(PyTypeObjectPtr, base_pyo)
+ if not pto.c_tp_dealloc:
+ pto.c_tp_dealloc = base.c_tp_dealloc
+ # XXX check for correct GC flags!
+ if not pto.c_tp_free:
+ pto.c_tp_free = base.c_tp_free
+ finally:
+ Py_DecRef(space, base_pyo)
+
def PyPyType_Ready(space, pto, w_obj):
try:
pto.c_tp_dict = lltype.nullptr(PyObject.TO) # not supported
@@ -396,10 +441,13 @@
pto.c_tp_bases = make_ref(space, bases)
if w_obj is None:
PyPyType_Register(space, pto)
- # missing:
if base:
inherit_special(space, pto, base)
- # inherit_slots, setting __doc__ if not defined and tp_doc defined
+ if pto.c_tp_bases: # this is false while bootstrapping
+ for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)):
+ inherit_slots(space, pto, w_base)
+ # missing:
+ # setting __doc__ if not defined and tp_doc defined
# inheriting tp_as_* slots
# unsupported:
# tp_mro, tp_subclasses
More information about the Pypy-commit
mailing list