Issue 14942: add PyType_New() - Python tracker (original) (raw)

Nick Coghlan suggested[1] exploring an easier spelling for "type(name, (), {})" in the C API. I've attached a patch that adds a function that does so: _PyType_New(). It's "private" in the patch, but only because I am reticent to expand the API without solid feedback from the more experienced devs.

Even if I didn't get the implementation quite right (I'm relatively new to the C API), the patch at least demonstrates the concept. :)

[1] http://mail.python.org/pipermail/python-ideas/2012-May/015281.html

I realised that with the addition of types.new_class(), that's fairly easy to invoke from C (no harder than any other Python function, anyway). Thus, no need to duplicate the functionality directly in the C API.

Presumably you mean something like this:

PyObject * PyType_New(PyObject *name, PyObject *bases, PyObject *ns) { PyObject *type, *args, *newtype; PyInterpreterState *interp = PyThreadState_GET()->interp; PyObject *modules = interp->modules; PyObject *builtins = PyDict_GetItemString(modules, "builtins"); _Py_IDENTIFIER(type);

if (builtins == NULL)
    return NULL;
type = _PyObject_GetAttrId(builtins, &PyId_type);
if (type == NULL)
    return NULL;
args = PyTuple_Pack(3, name, bases, ns);
if (args == NULL)
    return NULL;
newtype = PyObject_CallObject(type, args);
Py_DECREF(args);
return newtype;

}

or even:

PyObject * PyType_New(PyObject *meta, PyObject *name, PyObject *bases, PyObject *ns) { PyObject *args, *newtype;

args = PyTuple_Pack(3, name, bases, ns);
if (args == NULL)
    return NULL;
newtype = PyObject_CallObject(type, args);
Py_DECREF(args);
return newtype;

}

and called with "PyType_New(&PyTypeObject, name, bases, ns)".

If that's what you meant, I'm okay with that. Otherwise please elaborate. :)

No, I mean no new C API at all. Anyone that wants to dynamically create a new type from C in 3.3 can already just write their own code to make the appropriate types.new_class() call:

http://docs.python.org/dev/library/types#types.new_class

A simple example, ignoring refcounting:

types_mod = PyImport_ImportModule("types"); new_class = PyObject_GetAttrString(types_mod, "new_class"); new_type = PyObject_CallFunction(new_function, "s", "MyClass")

And assorted variations thereof using the different PyObject_GetAttr* and PyObject_Call* functions.