Hi everyone,

I think I might have found a bug in the PyPy C-API.
It seems that PyType_Type.tp_new is broken.
Here is a minimal example that reproduces the bug.

Instructions:
        Compile Foo3.c as a python extension module named Foo3.
        Set up the paths so that Test3.py can find Foo3.
        Run Test3.py

Expected result and observed result with CPython 2.7.6:
        Test3.py runs

Observed result with PyPy 2.2.1:
        Test3.py crashes.
(It gets into an infinite recursive loop where PyType_Type.tpnew and Foo3Type_Type.tp_new keep calling each other.)

Fixing this bug, or finding a workaround, would get me one step closer to getting PySide to run with PyPy.

Cheers,
Johan

#include <Python.h>

PyObject* foo3type_tp_new(PyTypeObject* metatype, PyObject* args, PyObject* 
kwds)
{
        // In a more realistic example we might do some preprocessing of args 
and kwargs here ...
    PyObject* newType = PyType_Type.tp_new(metatype, args, kwds);
        // ... and some postprocessing of newType here
        return newType;
}

PyTypeObject Foo3Type_Type = {
    PyVarObject_HEAD_INIT(0, 0)
    /*tp_name*/             "Foo3.Type",
    /*tp_basicsize*/        sizeof(PyTypeObject),
    /*tp_itemsize*/         0,
    /*tp_dealloc*/          0,
    /*tp_print*/            0,
    /*tp_getattr*/          0,
    /*tp_setattr*/          0,
    /*tp_compare*/          0,
    /*tp_repr*/             0,
    /*tp_as_number*/        0,
    /*tp_as_sequence*/      0,
    /*tp_as_mapping*/       0,
    /*tp_hash*/             0,
    /*tp_call*/             0,
    /*tp_str*/              0,
    /*tp_getattro*/         0,
    /*tp_setattro*/         0,
    /*tp_as_buffer*/        0,
    /*tp_flags*/            Py_TPFLAGS_DEFAULT,
    /*tp_doc*/              0,
    /*tp_traverse*/         0,
    /*tp_clear*/            0,
    /*tp_richcompare*/      0,
    /*tp_weaklistoffset*/   0,
    /*tp_iter*/             0,
    /*tp_iternext*/         0,
    /*tp_methods*/          0,
    /*tp_members*/          0,
    /*tp_getset*/           0,
    /*tp_base*/             0,          //  set to &PyType_Type in module init 
function (why can it not be done here?)
    /*tp_dict*/             0,
    /*tp_descr_get*/        0,
    /*tp_descr_set*/        0,
    /*tp_dictoffset*/       0,
    /*tp_init*/             0,
    /*tp_alloc*/            0,
    /*tp_new*/              foo3type_tp_new,
    /*tp_free*/             0,
    /*tp_is_gc*/            0,
    /*tp_bases*/            0,
    /*tp_mro*/              0,
    /*tp_cache*/            0,
    /*tp_subclasses*/       0,
    /*tp_weaklist*/         0
};

static PyMethodDef sbkMethods[] = {{NULL, NULL, 0, NULL}};

#ifdef _WIN32
        __declspec(dllexport) void              // PyModINIT_FUNC is broken on 
PyPy/Windows
#else
        PyMODINIT_FUNC
#endif
initFoo3(void)
{
        PyObject* mod = Py_InitModule("Foo3", sbkMethods);
        Foo3Type_Type.tp_base = &PyType_Type;
        PyType_Ready(&Foo3Type_Type);
        PyModule_AddObject(mod, "Type", (PyObject*)&Foo3Type_Type);
}
import Foo3

class X(object):
    __metaclass__ = Foo3.Type
    pass
_______________________________________________
pypy-dev mailing list
pypy-dev@python.org
https://mail.python.org/mailman/listinfo/pypy-dev

Reply via email to