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.