Permalink
7821 lines (6902 sloc) 238 KB
/* Type object implementation */
#include "Python.h"
#include "internal/pystate.h"
#include "frameobject.h"
#include "structmember.h"
#include <ctype.h>
/*[clinic input]
class type "PyTypeObject *" "&PyType_Type"
class object "PyObject *" "&PyBaseObject_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b94608d231c434b]*/
#include "clinic/typeobject.c.h"
/* Support type attribute cache */
/* The cache can keep references to the names alive for longer than
they normally would. This is why the maximum size is limited to
MCACHE_MAX_ATTR_SIZE, since it might be a problem if very large
strings are used as attribute names. */
#define MCACHE_MAX_ATTR_SIZE 100
#define MCACHE_SIZE_EXP 12
#define MCACHE_HASH(version, name_hash) \
(((unsigned int)(version) ^ (unsigned int)(name_hash)) \
& ((1 << MCACHE_SIZE_EXP) - 1))
#define MCACHE_HASH_METHOD(type, name) \
MCACHE_HASH((type)->tp_version_tag, \
((PyASCIIObject *)(name))->hash)
#define MCACHE_CACHEABLE_NAME(name) \
PyUnicode_CheckExact(name) && \
PyUnicode_IS_READY(name) && \
PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE
struct method_cache_entry {
unsigned int version;
PyObject *name; /* reference to exactly a str or None */
PyObject *value; /* borrowed */
};
static struct method_cache_entry method_cache[1 << MCACHE_SIZE_EXP];
static unsigned int next_version_tag = 0;
#define MCACHE_STATS 0
#if MCACHE_STATS
static size_t method_cache_hits = 0;
static size_t method_cache_misses = 0;
static size_t method_cache_collisions = 0;
#endif
/* alphabetical order */
_Py_IDENTIFIER(__abstractmethods__);
_Py_IDENTIFIER(__class__);
_Py_IDENTIFIER(__class_getitem__);
_Py_IDENTIFIER(__delitem__);
_Py_IDENTIFIER(__dict__);
_Py_IDENTIFIER(__doc__);
_Py_IDENTIFIER(__getattribute__);
_Py_IDENTIFIER(__getitem__);
_Py_IDENTIFIER(__hash__);
_Py_IDENTIFIER(__init_subclass__);
_Py_IDENTIFIER(__len__);
_Py_IDENTIFIER(__module__);
_Py_IDENTIFIER(__name__);
_Py_IDENTIFIER(__new__);
_Py_IDENTIFIER(__set_name__);
_Py_IDENTIFIER(__setitem__);
_Py_IDENTIFIER(builtins);
static PyObject *
slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static void
clear_slotdefs(void);
/*
* finds the beginning of the docstring's introspection signature.
* if present, returns a pointer pointing to the first '('.
* otherwise returns NULL.
*
* doesn't guarantee that the signature is valid, only that it
* has a valid prefix. (the signature must also pass skip_signature.)
*/
static const char *
find_signature(const char *name, const char *doc)
{
const char *dot;
size_t length;
if (!doc)
return NULL;
assert(name != NULL);
/* for dotted names like classes, only use the last component */
dot = strrchr(name, '.');
if (dot)
name = dot + 1;
length = strlen(name);
if (strncmp(doc, name, length))
return NULL;
doc += length;
if (*doc != '(')
return NULL;
return doc;
}
#define SIGNATURE_END_MARKER ")\n--\n\n"
#define SIGNATURE_END_MARKER_LENGTH 6
/*
* skips past the end of the docstring's instrospection signature.
* (assumes doc starts with a valid signature prefix.)
*/
static const char *
skip_signature(const char *doc)
{
while (*doc) {
if ((*doc == *SIGNATURE_END_MARKER) &&
!strncmp(doc, SIGNATURE_END_MARKER, SIGNATURE_END_MARKER_LENGTH))
return doc + SIGNATURE_END_MARKER_LENGTH;
if ((*doc == '\n') && (doc[1] == '\n'))
return NULL;
doc++;
}
return NULL;
}
#ifndef NDEBUG
static int
_PyType_CheckConsistency(PyTypeObject *type)
{
if (!(type->tp_flags & Py_TPFLAGS_READY)) {
/* don't check types before PyType_Ready() */
return 1;
}
assert(!(type->tp_flags & Py_TPFLAGS_READYING));
assert(type->tp_mro != NULL && PyTuple_Check(type->tp_mro));
assert(type->tp_dict != NULL);
return 1;
}
#endif
static const char *
_PyType_DocWithoutSignature(const char *name, const char *internal_doc)
{
const char *doc = find_signature(name, internal_doc);
if (doc) {
doc = skip_signature(doc);
if (doc)
return doc;
}
return internal_doc;
}
PyObject *
_PyType_GetDocFromInternalDoc(const char *name, const char *internal_doc)
{
const char *doc = _PyType_DocWithoutSignature(name, internal_doc);
if (!doc || *doc == '\0') {
Py_RETURN_NONE;
}
return PyUnicode_FromString(doc);
}
PyObject *
_PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_doc)
{
const char *start = find_signature(name, internal_doc);
const char *end;
if (start)
end = skip_signature(start);
else
end = NULL;
if (!end) {
Py_RETURN_NONE;
}
/* back "end" up until it points just past the final ')' */
end -= SIGNATURE_END_MARKER_LENGTH - 1;
assert((end - start) >= 2); /* should be "()" at least */
assert(end[-1] == ')');
assert(end[0] == '\n');
return PyUnicode_FromStringAndSize(start, end - start);
}
unsigned int
PyType_ClearCache(void)
{
Py_ssize_t i;
unsigned int cur_version_tag = next_version_tag - 1;
#if MCACHE_STATS
size_t total = method_cache_hits + method_cache_collisions + method_cache_misses;
fprintf(stderr, "-- Method cache hits = %zd (%d%%)\n",
method_cache_hits, (int) (100.0 * method_cache_hits / total));
fprintf(stderr, "-- Method cache true misses = %zd (%d%%)\n",
method_cache_misses, (int) (100.0 * method_cache_misses / total));
fprintf(stderr, "-- Method cache collisions = %zd (%d%%)\n",
method_cache_collisions, (int) (100.0 * method_cache_collisions / total));
fprintf(stderr, "-- Method cache size = %zd KiB\n",
sizeof(method_cache) / 1024);
#endif
for (i = 0; i < (1 << MCACHE_SIZE_EXP); i++) {
method_cache[i].version = 0;
Py_CLEAR(method_cache[i].name);
method_cache[i].value = NULL;
}
next_version_tag = 0;
/* mark all version tags as invalid */
PyType_Modified(&PyBaseObject_Type);
return cur_version_tag;
}
void
_PyType_Fini(void)
{
PyType_ClearCache();
clear_slotdefs();
}
void
PyType_Modified(PyTypeObject *type)
{
/* Invalidate any cached data for the specified type and all
subclasses. This function is called after the base
classes, mro, or attributes of the type are altered.
Invariants:
- Py_TPFLAGS_VALID_VERSION_TAG is never set if
Py_TPFLAGS_HAVE_VERSION_TAG is not set (e.g. on type
objects coming from non-recompiled extension modules)
- before Py_TPFLAGS_VALID_VERSION_TAG can be set on a type,
it must first be set on all super types.
This function clears the Py_TPFLAGS_VALID_VERSION_TAG of a
type (so it must first clear it on all subclasses). The
tp_version_tag value is meaningless unless this flag is set.
We don't assign new version tags eagerly, but only as
needed.
*/
PyObject *raw, *ref;
Py_ssize_t i;
if (!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
return;
raw = type->tp_subclasses;
if (raw != NULL) {
assert(PyDict_CheckExact(raw));
i = 0;
while (PyDict_Next(raw, &i, NULL, &ref)) {
assert(PyWeakref_CheckRef(ref));
ref = PyWeakref_GET_OBJECT(ref);
if (ref != Py_None) {
PyType_Modified((PyTypeObject *)ref);
}
}
}
type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
}
static void
type_mro_modified(PyTypeObject *type, PyObject *bases) {
/*
Check that all base classes or elements of the MRO of type are
able to be cached. This function is called after the base
classes or mro of the type are altered.
Unset HAVE_VERSION_TAG and VALID_VERSION_TAG if the type
has a custom MRO that includes a type which is not officially
super type.
Called from mro_internal, which will subsequently be called on
each subclass when their mro is recursively updated.
*/
Py_ssize_t i, n;
int clear = 0;
if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
return;
n = PyTuple_GET_SIZE(bases);
for (i = 0; i < n; i++) {
PyObject *b = PyTuple_GET_ITEM(bases, i);
PyTypeObject *cls;
assert(PyType_Check(b));
cls = (PyTypeObject *)b;
if (!PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) ||
!PyType_IsSubtype(type, cls)) {
clear = 1;
break;
}
}
if (clear)
type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG|
Py_TPFLAGS_VALID_VERSION_TAG);
}
static int
assign_version_tag(PyTypeObject *type)
{
/* Ensure that the tp_version_tag is valid and set
Py_TPFLAGS_VALID_VERSION_TAG. To respect the invariant, this
must first be done on all super classes. Return 0 if this
cannot be done, 1 if Py_TPFLAGS_VALID_VERSION_TAG.
*/
Py_ssize_t i, n;
PyObject *bases;
if (PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
return 1;
if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
return 0;
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
return 0;
type->tp_version_tag = next_version_tag++;
/* for stress-testing: next_version_tag &= 0xFF; */
if (type->tp_version_tag == 0) {
/* wrap-around or just starting Python - clear the whole
cache by filling names with references to Py_None.
Values are also set to NULL for added protection, as they
are borrowed reference */
for (i = 0; i < (1 << MCACHE_SIZE_EXP); i++) {
method_cache[i].value = NULL;
Py_INCREF(Py_None);
Py_XSETREF(method_cache[i].name, Py_None);
}
/* mark all version tags as invalid */
PyType_Modified(&PyBaseObject_Type);
return 1;
}
bases = type->tp_bases;
n = PyTuple_GET_SIZE(bases);
for (i = 0; i < n; i++) {
PyObject *b = PyTuple_GET_ITEM(bases, i);
assert(PyType_Check(b));
if (!assign_version_tag((PyTypeObject *)b))
return 0;
}
type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;
return 1;
}
static PyMemberDef type_members[] = {
{"__basicsize__", T_PYSSIZET, offsetof(PyTypeObject,tp_basicsize),READONLY},
{"__itemsize__", T_PYSSIZET, offsetof(PyTypeObject, tp_itemsize), READONLY},
{"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY},
{"__weakrefoffset__", T_LONG,
offsetof(PyTypeObject, tp_weaklistoffset), READONLY},
{"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY},
{"__dictoffset__", T_LONG,
offsetof(PyTypeObject, tp_dictoffset), READONLY},
{"__mro__", T_OBJECT, offsetof(PyTypeObject, tp_mro), READONLY},
{0}
};
static int
check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *name)
{
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
PyErr_Format(PyExc_TypeError,
"can't set %s.%s", type->tp_name, name);
return 0;
}
if (!value) {
PyErr_Format(PyExc_TypeError,
"can't delete %s.%s", type->tp_name, name);
return 0;
}
return 1;
}
const char *
_PyType_Name(PyTypeObject *type)
{
const char *s = strrchr(type->tp_name, '.');
if (s == NULL) {
s = type->tp_name;
}
else {
s++;
}
return s;
}
static PyObject *
type_name(PyTypeObject *type, void *context)
{
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
PyHeapTypeObject* et = (PyHeapTypeObject*)type;
Py_INCREF(et->ht_name);
return et->ht_name;
}
else {
return PyUnicode_FromString(_PyType_Name(type));
}
}
static PyObject *
type_qualname(PyTypeObject *type, void *context)
{
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
PyHeapTypeObject* et = (PyHeapTypeObject*)type;
Py_INCREF(et->ht_qualname);
return et->ht_qualname;
}
else {
return PyUnicode_FromString(_PyType_Name(type));
}
}
static int
type_set_name(PyTypeObject *type, PyObject *value, void *context)
{
const char *tp_name;
Py_ssize_t name_size;
if (!check_set_special_type_attr(type, value, "__name__"))
return -1;
if (!PyUnicode_Check(value)) {
PyErr_Format(PyExc_TypeError,
"can only assign string to %s.__name__, not '%s'",
type->tp_name, Py_TYPE(value)->tp_name);
return -1;
}
tp_name = PyUnicode_AsUTF8AndSize(value, &name_size);
if (tp_name == NULL)
return -1;
if (strlen(tp_name) != (size_t)name_size) {
PyErr_SetString(PyExc_ValueError,
"type name must not contain null characters");
return -1;
}
type->tp_name = tp_name;
Py_INCREF(value);
Py_SETREF(((PyHeapTypeObject*)type)->ht_name, value);
return 0;
}
static int
type_set_qualname(PyTypeObject *type, PyObject *value, void *context)
{
PyHeapTypeObject* et;
if (!check_set_special_type_attr(type, value, "__qualname__"))
return -1;
if (!PyUnicode_Check(value)) {
PyErr_Format(PyExc_TypeError,
"can only assign string to %s.__qualname__, not '%s'",
type->tp_name, Py_TYPE(value)->tp_name);
return -1;
}
et = (PyHeapTypeObject*)type;
Py_INCREF(value);
Py_SETREF(et->ht_qualname, value);
return 0;
}
static PyObject *
type_module(PyTypeObject *type, void *context)
{
PyObject *mod;
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
mod = _PyDict_GetItemId(type->tp_dict, &PyId___module__);
if (mod == NULL) {
PyErr_Format(PyExc_AttributeError, "__module__");
return NULL;
}
Py_INCREF(mod);
}
else {
const char *s = strrchr(type->tp_name, '.');
if (s != NULL) {
mod = PyUnicode_FromStringAndSize(
type->tp_name, (Py_ssize_t)(s - type->tp_name));
if (mod != NULL)
PyUnicode_InternInPlace(&mod);
}
else {
mod = _PyUnicode_FromId(&PyId_builtins);
Py_XINCREF(mod);
}
}
return mod;
}
static int
type_set_module(PyTypeObject *type, PyObject *value, void *context)
{
if (!check_set_special_type_attr(type, value, "__module__"))
return -1;
PyType_Modified(type);
return _PyDict_SetItemId(type->tp_dict, &PyId___module__, value);
}
static PyObject *
type_abstractmethods(PyTypeObject *type, void *context)
{
PyObject *mod = NULL;
/* type itself has an __abstractmethods__ descriptor (this). Don't return
that. */
if (type != &PyType_Type)
mod = _PyDict_GetItemId(type->tp_dict, &PyId___abstractmethods__);
if (!mod) {
PyObject *message = _PyUnicode_FromId(&PyId___abstractmethods__);
if (message)
PyErr_SetObject(PyExc_AttributeError, message);
return NULL;
}
Py_INCREF(mod);
return mod;
}
static int
type_set_abstractmethods(PyTypeObject *type, PyObject *value, void *context)
{
/* __abstractmethods__ should only be set once on a type, in
abc.ABCMeta.__new__, so this function doesn't do anything
special to update subclasses.
*/
int abstract, res;
if (value != NULL) {
abstract = PyObject_IsTrue(value);
if (abstract < 0)
return -1;
res = _PyDict_SetItemId(type->tp_dict, &PyId___abstractmethods__, value);
}
else {
abstract = 0;
res = _PyDict_DelItemId(type->tp_dict, &PyId___abstractmethods__);
if (res && PyErr_ExceptionMatches(PyExc_KeyError)) {
PyObject *message = _PyUnicode_FromId(&PyId___abstractmethods__);
if (message)
PyErr_SetObject(PyExc_AttributeError, message);
return -1;
}
}
if (res == 0) {
PyType_Modified(type);
if (abstract)
type->tp_flags |= Py_TPFLAGS_IS_ABSTRACT;
else
type->tp_flags &= ~Py_TPFLAGS_IS_ABSTRACT;
}
return res;
}
static PyObject *
type_get_bases(PyTypeObject *type, void *context)
{
Py_INCREF(type->tp_bases);
return type->tp_bases;
}
static PyTypeObject *best_base(PyObject *);
static int mro_internal(PyTypeObject *, PyObject **);
static int type_is_subtype_base_chain(PyTypeObject *, PyTypeObject *);
static int compatible_for_assignment(PyTypeObject *, PyTypeObject *, const char *);
static int add_subclass(PyTypeObject*, PyTypeObject*);
static int add_all_subclasses(PyTypeObject *type, PyObject *bases);
static void remove_subclass(PyTypeObject *, PyTypeObject *);
static void remove_all_subclasses(PyTypeObject *type, PyObject *bases);
static void update_all_slots(PyTypeObject *);
typedef int (*update_callback)(PyTypeObject *, void *);
static int update_subclasses(PyTypeObject *type, PyObject *name,
update_callback callback, void *data);
static int recurse_down_subclasses(PyTypeObject *type, PyObject *name,
update_callback callback, void *data);
static int
mro_hierarchy(PyTypeObject *type, PyObject *temp)
{
int res;
PyObject *new_mro, *old_mro;
PyObject *tuple;
PyObject *subclasses;
Py_ssize_t i, n;
res = mro_internal(type, &old_mro);
if (res <= 0)
/* error / reentrance */
return res;
new_mro = type->tp_mro;
if (old_mro != NULL)
tuple = PyTuple_Pack(3, type, new_mro, old_mro);
else
tuple = PyTuple_Pack(2, type, new_mro);
if (tuple != NULL)
res = PyList_Append(temp, tuple);
else
res = -1;
Py_XDECREF(tuple);
if (res < 0) {
type->tp_mro = old_mro;
Py_DECREF(new_mro);
return -1;
}
Py_XDECREF(old_mro);
/* Obtain a copy of subclasses list to iterate over.
Otherwise type->tp_subclasses might be altered
in the middle of the loop, for example, through a custom mro(),
by invoking type_set_bases on some subclass of the type
which in turn calls remove_subclass/add_subclass on this type.
Finally, this makes things simple avoiding the need to deal
with dictionary iterators and weak references.
*/
subclasses = type___subclasses___impl(type);
if (subclasses == NULL)
return -1;
n = PyList_GET_SIZE(subclasses);
for (i = 0; i < n; i++) {
PyTypeObject *subclass;
subclass = (PyTypeObject *)PyList_GET_ITEM(subclasses, i);
res = mro_hierarchy(subclass, temp);
if (res < 0)
break;
}
Py_DECREF(subclasses);
return res;
}
static int
type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context)
{
int res = 0;
PyObject *temp;
PyObject *old_bases;
PyTypeObject *new_base, *old_base;
Py_ssize_t i;
if (!check_set_special_type_attr(type, new_bases, "__bases__"))
return -1;
if (!PyTuple_Check(new_bases)) {
PyErr_Format(PyExc_TypeError,
"can only assign tuple to %s.__bases__, not %s",
type->tp_name, Py_TYPE(new_bases)->tp_name);
return -1;
}
if (PyTuple_GET_SIZE(new_bases) == 0) {
PyErr_Format(PyExc_TypeError,
"can only assign non-empty tuple to %s.__bases__, not ()",
type->tp_name);
return -1;
}
for (i = 0; i < PyTuple_GET_SIZE(new_bases); i++) {
PyObject *ob;
PyTypeObject *base;
ob = PyTuple_GET_ITEM(new_bases, i);
if (!PyType_Check(ob)) {
PyErr_Format(PyExc_TypeError,
"%s.__bases__ must be tuple of classes, not '%s'",
type->tp_name, Py_TYPE(ob)->tp_name);
return -1;
}
base = (PyTypeObject*)ob;
if (PyType_IsSubtype(base, type) ||
/* In case of reentering here again through a custom mro()
the above check is not enough since it relies on
base->tp_mro which would gonna be updated inside
mro_internal only upon returning from the mro().
However, base->tp_base has already been assigned (see
below), which in turn may cause an inheritance cycle
through tp_base chain. And this is definitely
not what you want to ever happen. */
(base->tp_mro != NULL && type_is_subtype_base_chain(base, type))) {
PyErr_SetString(PyExc_TypeError,
"a __bases__ item causes an inheritance cycle");
return -1;
}
}
new_base = best_base(new_bases);
if (new_base == NULL)
return -1;
if (!compatible_for_assignment(type->tp_base, new_base, "__bases__"))
return -1;
Py_INCREF(new_bases);
Py_INCREF(new_base);
old_bases = type->tp_bases;
old_base = type->tp_base;
type->tp_bases = new_bases;
type->tp_base = new_base;
temp = PyList_New(0);
if (temp == NULL)
goto bail;
if (mro_hierarchy(type, temp) < 0)
goto undo;
Py_DECREF(temp);
/* Take no action in case if type->tp_bases has been replaced
through reentrance. */
if (type->tp_bases == new_bases) {
/* any base that was in __bases__ but now isn't, we
need to remove |type| from its tp_subclasses.
conversely, any class now in __bases__ that wasn't
needs to have |type| added to its subclasses. */
/* for now, sod that: just remove from all old_bases,
add to all new_bases */
remove_all_subclasses(type, old_bases);
res = add_all_subclasses(type, new_bases);
update_all_slots(type);
}
Py_DECREF(old_bases);
Py_DECREF(old_base);
assert(_PyType_CheckConsistency(type));
return res;
undo:
for (i = PyList_GET_SIZE(temp) - 1; i >= 0; i--) {
PyTypeObject *cls;
PyObject *new_mro, *old_mro = NULL;
PyArg_UnpackTuple(PyList_GET_ITEM(temp, i),
"", 2, 3, &cls, &new_mro, &old_mro);
/* Do not rollback if cls has a newer version of MRO. */
if (cls->tp_mro == new_mro) {
Py_XINCREF(old_mro);
cls->tp_mro = old_mro;
Py_DECREF(new_mro);
}
}
Py_DECREF(temp);
bail:
if (type->tp_bases == new_bases) {
assert(type->tp_base == new_base);
type->tp_bases = old_bases;
type->tp_base = old_base;
Py_DECREF(new_bases);
Py_DECREF(new_base);
}
else {
Py_DECREF(old_bases);
Py_DECREF(old_base);
}
assert(_PyType_CheckConsistency(type));
return -1;
}
static PyObject *
type_dict(PyTypeObject *type, void *context)
{
if (type->tp_dict == NULL) {
Py_RETURN_NONE;
}
return PyDictProxy_New(type->tp_dict);
}
static PyObject *
type_get_doc(PyTypeObject *type, void *context)
{
PyObject *result;
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) && type->tp_doc != NULL) {
return _PyType_GetDocFromInternalDoc(type->tp_name, type->tp_doc);
}
result = _PyDict_GetItemId(type->tp_dict, &PyId___doc__);
if (result == NULL) {
result = Py_None;
Py_INCREF(result);
}
else if (Py_TYPE(result)->tp_descr_get) {
result = Py_TYPE(result)->tp_descr_get(result, NULL,
(PyObject *)type);
}
else {
Py_INCREF(result);
}
return result;
}
static PyObject *
type_get_text_signature(PyTypeObject *type, void *context)
{
return _PyType_GetTextSignatureFromInternalDoc(type->tp_name, type->tp_doc);
}
static int
type_set_doc(PyTypeObject *type, PyObject *value, void *context)
{
if (!check_set_special_type_attr(type, value, "__doc__"))
return -1;
PyType_Modified(type);
return _PyDict_SetItemId(type->tp_dict, &PyId___doc__, value);
}
/*[clinic input]
type.__instancecheck__ -> bool
instance: object
/
Check if an object is an instance.
[clinic start generated code]*/
static int
type___instancecheck___impl(PyTypeObject *self, PyObject *instance)
/*[clinic end generated code: output=08b6bf5f591c3618 input=cdbfeaee82c01a0f]*/
{
return _PyObject_RealIsInstance(instance, (PyObject *)self);
}
/*[clinic input]
type.__subclasscheck__ -> bool
subclass: object
/
Check if a class is a subclass.
[clinic start generated code]*/
static int
type___subclasscheck___impl(PyTypeObject *self, PyObject *subclass)
/*[clinic end generated code: output=97a4e51694500941 input=071b2ca9e03355f4]*/
{
return _PyObject_RealIsSubclass(subclass, (PyObject *)self);
}
static PyGetSetDef type_getsets[] = {
{"__name__", (getter)type_name, (setter)type_set_name, NULL},
{"__qualname__", (getter)type_qualname, (setter)type_set_qualname, NULL},
{"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL},
{"__module__", (getter)type_module, (setter)type_set_module, NULL},
{"__abstractmethods__", (getter)type_abstractmethods,
(setter)type_set_abstractmethods, NULL},
{"__dict__", (getter)type_dict, NULL, NULL},
{"__doc__", (getter)type_get_doc, (setter)type_set_doc, NULL},
{"__text_signature__", (getter)type_get_text_signature, NULL, NULL},
{0}
};
static PyObject *
type_repr(PyTypeObject *type)
{
PyObject *mod, *name, *rtn;
mod = type_module(type, NULL);
if (mod == NULL)
PyErr_Clear();
else if (!PyUnicode_Check(mod)) {
Py_DECREF(mod);
mod = NULL;
}
name = type_qualname(type, NULL);
if (name == NULL) {
Py_XDECREF(mod);
return NULL;
}
if (mod != NULL && !_PyUnicode_EqualToASCIIId(mod, &PyId_builtins))
rtn = PyUnicode_FromFormat("<class '%U.%U'>", mod, name);
else
rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);
Py_XDECREF(mod);
Py_DECREF(name);
return rtn;
}
static PyObject *
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *obj;
if (type->tp_new == NULL) {
PyErr_Format(PyExc_TypeError,
"cannot create '%.100s' instances",
type->tp_name);
return NULL;
}
#ifdef Py_DEBUG
/* type_call() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
#endif
obj = type->tp_new(type, args, kwds);
obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL);
if (obj == NULL)
return NULL;
/* Ugly exception: when the call was type(something),
don't call tp_init on the result. */
if (type == &PyType_Type &&
PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
(kwds == NULL ||
(PyDict_Check(kwds) && PyDict_GET_SIZE(kwds) == 0)))
return obj;
/* If the returned object is not an instance of type,
it won't be initialized. */
if (!PyType_IsSubtype(Py_TYPE(obj), type))
return obj;
type = Py_TYPE(obj);
if (type->tp_init != NULL) {
int res = type->tp_init(obj, args, kwds);
if (res < 0) {
assert(PyErr_Occurred());
Py_DECREF(obj);
obj = NULL;
}
else {
assert(!PyErr_Occurred());
}
}
return obj;
}
PyObject *
PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
{
PyObject *obj;
const size_t size = _PyObject_VAR_SIZE(type, nitems+1);
/* note that we need to add one, for the sentinel */
if (PyType_IS_GC(type))
obj = _PyObject_GC_Malloc(size);
else
obj = (PyObject *)PyObject_MALLOC(size);
if (obj == NULL)
return PyErr_NoMemory();
memset(obj, '\0', size);
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
Py_INCREF(type);
if (type->tp_itemsize == 0)
(void)PyObject_INIT(obj, type);
else
(void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems);
if (PyType_IS_GC(type))
_PyObject_GC_TRACK(obj);
return obj;
}
PyObject *
PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
return type->tp_alloc(type, 0);
}
/* Helpers for subtyping */
static int
traverse_slots(PyTypeObject *type, PyObject *self, visitproc visit, void *arg)
{
Py_ssize_t i, n;
PyMemberDef *mp;
n = Py_SIZE(type);
mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type);
for (i = 0; i < n; i++, mp++) {
if (mp->type == T_OBJECT_EX) {
char *addr = (char *)self + mp->offset;
PyObject *obj = *(PyObject **)addr;
if (obj != NULL) {
int err = visit(obj, arg);
if (err)
return err;
}
}
}
return 0;
}
static int
subtype_traverse(PyObject *self, visitproc visit, void *arg)
{
PyTypeObject *type, *base;
traverseproc basetraverse;
/* Find the nearest base with a different tp_traverse,
and traverse slots while we're at it */
type = Py_TYPE(self);
base = type;
while ((basetraverse = base->tp_traverse) == subtype_traverse) {
if (Py_SIZE(base)) {
int err = traverse_slots(base, self, visit, arg);
if (err)
return err;
}
base = base->tp_base;
assert(base);
}
if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr && *dictptr)
Py_VISIT(*dictptr);
}
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
/* For a heaptype, the instances count as references
to the type. Traverse the type so the collector
can find cycles involving this link. */
Py_VISIT(type);
if (basetraverse)
return basetraverse(self, visit, arg);
return 0;
}
static void
clear_slots(PyTypeObject *type, PyObject *self)
{
Py_ssize_t i, n;
PyMemberDef *mp;
n = Py_SIZE(type);
mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type);
for (i = 0; i < n; i++, mp++) {
if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) {
char *addr = (char *)self + mp->offset;
PyObject *obj = *(PyObject **)addr;
if (obj != NULL) {
*(PyObject **)addr = NULL;
Py_DECREF(obj);
}
}
}
}
static int
subtype_clear(PyObject *self)
{
PyTypeObject *type, *base;
inquiry baseclear;
/* Find the nearest base with a different tp_clear
and clear slots while we're at it */
type = Py_TYPE(self);
base = type;
while ((baseclear = base->tp_clear) == subtype_clear) {
if (Py_SIZE(base))
clear_slots(base, self);
base = base->tp_base;
assert(base);
}
/* Clear the instance dict (if any), to break cycles involving only
__dict__ slots (as in the case 'self.__dict__ is self'). */
if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr && *dictptr)
Py_CLEAR(*dictptr);
}
if (baseclear)
return baseclear(self);
return 0;
}
static void
subtype_dealloc(PyObject *self)
{
PyTypeObject *type, *base;
destructor basedealloc;
PyThreadState *tstate = PyThreadState_GET();
int has_finalizer;
/* Extract the type; we expect it to be a heap type */
type = Py_TYPE(self);
assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
/* Test whether the type has GC exactly once */
if (!PyType_IS_GC(type)) {
/* It's really rare to find a dynamic type that doesn't have
GC; it can only happen when deriving from 'object' and not
adding any slots or instance variables. This allows
certain simplifications: there's no need to call
clear_slots(), or DECREF the dict, or clear weakrefs. */
/* Maybe call finalizer; exit early if resurrected */
if (type->tp_finalize) {
if (PyObject_CallFinalizerFromDealloc(self) < 0)
return;
}
if (type->tp_del) {
type->tp_del(self);
if (self->ob_refcnt > 0)
return;
}
/* Find the nearest base with a different tp_dealloc */
base = type;
while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
assert(Py_SIZE(base) == 0);
base = base->tp_base;
assert(base);
}
/* Extract the type again; tp_del may have changed it */
type = Py_TYPE(self);
/* Call the base tp_dealloc() */
assert(basedealloc);
basedealloc(self);
/* Can't reference self beyond this point */
Py_DECREF(type);
/* Done */
return;
}
/* We get here only if the type has GC */
/* UnTrack and re-Track around the trashcan macro, alas */
/* See explanation at end of function for full disclosure */
PyObject_GC_UnTrack(self);
++_PyRuntime.gc.trash_delete_nesting;
++ tstate->trash_delete_nesting;
Py_TRASHCAN_SAFE_BEGIN(self);
--_PyRuntime.gc.trash_delete_nesting;
-- tstate->trash_delete_nesting;
/* Find the nearest base with a different tp_dealloc */
base = type;
while ((/*basedealloc =*/ base->tp_dealloc) == subtype_dealloc) {
base = base->tp_base;
assert(base);
}
has_finalizer = type->tp_finalize || type->tp_del;
if (type->tp_finalize) {
_PyObject_GC_TRACK(self);
if (PyObject_CallFinalizerFromDealloc(self) < 0) {
/* Resurrected */
goto endlabel;
}
_PyObject_GC_UNTRACK(self);
}
/*
If we added a weaklist, we clear it. Do this *before* calling tp_del,
clearing slots, or clearing the instance dict.
GC tracking must be off at this point. weakref callbacks (if any, and
whether directly here or indirectly in something we call) may trigger GC,
and if self is tracked at that point, it will look like trash to GC and GC
will try to delete self again.
*/
if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
PyObject_ClearWeakRefs(self);
if (type->tp_del) {
_PyObject_GC_TRACK(self);
type->tp_del(self);
if (self->ob_refcnt > 0) {
/* Resurrected */
goto endlabel;
}
_PyObject_GC_UNTRACK(self);
}
if (has_finalizer) {
/* New weakrefs could be created during the finalizer call.
If this occurs, clear them out without calling their
finalizers since they might rely on part of the object
being finalized that has already been destroyed. */
if (type->tp_weaklistoffset && !base->tp_weaklistoffset) {
/* Modeled after GET_WEAKREFS_LISTPTR() */
PyWeakReference **list = (PyWeakReference **) \
PyObject_GET_WEAKREFS_LISTPTR(self);
while (*list)
_PyWeakref_ClearRef(*list);
}
}
/* Clear slots up to the nearest base with a different tp_dealloc */
base = type;
while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
if (Py_SIZE(base))
clear_slots(base, self);
base = base->tp_base;
assert(base);
}
/* If we added a dict, DECREF it */
if (type->tp_dictoffset && !base->tp_dictoffset) {
PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr != NULL) {
PyObject *dict = *dictptr;
if (dict != NULL) {
Py_DECREF(dict);
*dictptr = NULL;
}
}
}
/* Extract the type again; tp_del may have changed it */
type = Py_TYPE(self);
/* Call the base tp_dealloc(); first retrack self if
* basedealloc knows about gc.
*/
if (PyType_IS_GC(base))
_PyObject_GC_TRACK(self);
assert(basedealloc);
basedealloc(self);
/* Can't reference self beyond this point. It's possible tp_del switched
our type from a HEAPTYPE to a non-HEAPTYPE, so be careful about
reference counting. */
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
Py_DECREF(type);
endlabel:
++_PyRuntime.gc.trash_delete_nesting;
++ tstate->trash_delete_nesting;
Py_TRASHCAN_SAFE_END(self);
--_PyRuntime.gc.trash_delete_nesting;
-- tstate->trash_delete_nesting;
/* Explanation of the weirdness around the trashcan macros:
Q. What do the trashcan macros do?
A. Read the comment titled "Trashcan mechanism" in object.h.
For one, this explains why there must be a call to GC-untrack
before the trashcan begin macro. Without understanding the
trashcan code, the answers to the following questions don't make
sense.
Q. Why do we GC-untrack before the trashcan and then immediately
GC-track again afterward?
A. In the case that the base class is GC-aware, the base class
probably GC-untracks the object. If it does that using the
UNTRACK macro, this will crash when the object is already
untracked. Because we don't know what the base class does, the
only safe thing is to make sure the object is tracked when we
call the base class dealloc. But... The trashcan begin macro
requires that the object is *untracked* before it is called. So
the dance becomes:
GC untrack
trashcan begin
GC track
Q. Why did the last question say "immediately GC-track again"?
It's nowhere near immediately.
A. Because the code *used* to re-track immediately. Bad Idea.
self has a refcount of 0, and if gc ever gets its hands on it
(which can happen if any weakref callback gets invoked), it
looks like trash to gc too, and gc also tries to delete self
then. But we're already deleting self. Double deallocation is
a subtle disaster.
Q. Why the bizarre (net-zero) manipulation of
_PyRuntime.trash_delete_nesting around the trashcan macros?
A. Some base classes (e.g. list) also use the trashcan mechanism.
The following scenario used to be possible:
- suppose the trashcan level is one below the trashcan limit
- subtype_dealloc() is called
- the trashcan limit is not yet reached, so the trashcan level
is incremented and the code between trashcan begin and end is
executed
- this destroys much of the object's contents, including its
slots and __dict__
- basedealloc() is called; this is really list_dealloc(), or
some other type which also uses the trashcan macros
- the trashcan limit is now reached, so the object is put on the
trashcan's to-be-deleted-later list
- basedealloc() returns
- subtype_dealloc() decrefs the object's type
- subtype_dealloc() returns
- later, the trashcan code starts deleting the objects from its
to-be-deleted-later list
- subtype_dealloc() is called *AGAIN* for the same object
- at the very least (if the destroyed slots and __dict__ don't
cause problems) the object's type gets decref'ed a second
time, which is *BAD*!!!
The remedy is to make sure that if the code between trashcan
begin and end in subtype_dealloc() is called, the code between
trashcan begin and end in basedealloc() will also be called.
This is done by decrementing the level after passing into the
trashcan block, and incrementing it just before leaving the
block.
But now it's possible that a chain of objects consisting solely
of objects whose deallocator is subtype_dealloc() will defeat
the trashcan mechanism completely: the decremented level means
that the effective level never reaches the limit. Therefore, we
*increment* the level *before* entering the trashcan block, and
matchingly decrement it after leaving. This means the trashcan
code will trigger a little early, but that's no big deal.
Q. Are there any live examples of code in need of all this
complexity?
A. Yes. See SF bug 668433 for code that crashed (when Python was
compiled in debug mode) before the trashcan level manipulations
were added. For more discussion, see SF patches 581742, 575073
and bug 574207.
*/
}
static PyTypeObject *solid_base(PyTypeObject *type);
/* type test with subclassing support */
static int
type_is_subtype_base_chain(PyTypeObject *a, PyTypeObject *b)
{
do {
if (a == b)
return 1;
a = a->tp_base;
} while (a != NULL);
return (b == &PyBaseObject_Type);
}
int
PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)
{
PyObject *mro;
mro = a->tp_mro;
if (mro != NULL) {
/* Deal with multiple inheritance without recursion
by walking the MRO tuple */
Py_ssize_t i, n;
assert(PyTuple_Check(mro));
n = PyTuple_GET_SIZE(mro);
for (i = 0; i < n; i++) {
if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b)
return 1;
}
return 0;
}
else
/* a is not completely initilized yet; follow tp_base */
return type_is_subtype_base_chain(a, b);
}
/* Routines to do a method lookup in the type without looking in the
instance dictionary (so we can't use PyObject_GetAttr) but still
binding it to the instance.
Variants:
- _PyObject_LookupSpecial() returns NULL without raising an exception
when the _PyType_Lookup() call fails;
- lookup_maybe_method() and lookup_method() are internal routines similar
to _PyObject_LookupSpecial(), but can return unbound PyFunction
to avoid temporary method object. Pass self as first argument when
unbound == 1.
*/
PyObject *
_PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid)
{
PyObject *res;
res = _PyType_LookupId(Py_TYPE(self), attrid);
if (res != NULL) {
descrgetfunc f;
if ((f = Py_TYPE(res)->tp_descr_get) == NULL)
Py_INCREF(res);
else
res = f(res, self, (PyObject *)(Py_TYPE(self)));
}
return res;
}
static PyObject *
lookup_maybe_method(PyObject *self, _Py_Identifier *attrid, int *unbound)
{
PyObject *res = _PyType_LookupId(Py_TYPE(self), attrid);
if (res == NULL) {
return NULL;
}
if (PyFunction_Check(res)) {
/* Avoid temporary PyMethodObject */
*unbound = 1;
Py_INCREF(res);
}
else {
*unbound = 0;
descrgetfunc f = Py_TYPE(res)->tp_descr_get;
if (f == NULL) {
Py_INCREF(res);
}
else {
res = f(res, self, (PyObject *)(Py_TYPE(self)));
}
}
return res;
}
static PyObject *
lookup_method(PyObject *self, _Py_Identifier *attrid, int *unbound)
{
PyObject *res = lookup_maybe_method(self, attrid, unbound);
if (res == NULL && !PyErr_Occurred()) {
PyErr_SetObject(PyExc_AttributeError, attrid->object);
}
return res;
}
static PyObject*
call_unbound(int unbound, PyObject *func, PyObject *self,
PyObject **args, Py_ssize_t nargs)
{
if (unbound) {
return _PyObject_FastCall_Prepend(func, self, args, nargs);
}
else {
return _PyObject_FastCall(func, args, nargs);
}
}
static PyObject*
call_unbound_noarg(int unbound, PyObject *func, PyObject *self)
{
if (unbound) {
PyObject *args[1] = {self};
return _PyObject_FastCall(func, args, 1);
}
else {
return _PyObject_CallNoArg(func);
}
}
/* A variation of PyObject_CallMethod* that uses lookup_maybe_method()
instead of PyObject_GetAttrString(). */
static PyObject *
call_method(PyObject *obj, _Py_Identifier *name,
PyObject **args, Py_ssize_t nargs)
{
int unbound;
PyObject *func, *retval;
func = lookup_method(obj, name, &unbound);
if (func == NULL) {
return NULL;
}
retval = call_unbound(unbound, func, obj, args, nargs);
Py_DECREF(func);
return retval;
}
/* Clone of call_method() that returns NotImplemented when the lookup fails. */
static PyObject *
call_maybe(PyObject *obj, _Py_Identifier *name,
PyObject **args, Py_ssize_t nargs)
{
int unbound;
PyObject *func, *retval;
func = lookup_maybe_method(obj, name, &unbound);
if (func == NULL) {
if (!PyErr_Occurred())
Py_RETURN_NOTIMPLEMENTED;
return NULL;
}
retval = call_unbound(unbound, func, obj, args, nargs);
Py_DECREF(func);
return retval;
}
/*
Method resolution order algorithm C3 described in
"A Monotonic Superclass Linearization for Dylan",
by Kim Barrett, Bob Cassel, Paul Haahr,
David A. Moon, Keith Playford, and P. Tucker Withington.
(OOPSLA 1996)
Some notes about the rules implied by C3:
No duplicate bases.
It isn't legal to repeat a class in a list of base classes.
The next three properties are the 3 constraints in "C3".
Local precedence order.
If A precedes B in C's MRO, then A will precede B in the MRO of all
subclasses of C.
Monotonicity.
The MRO of a class must be an extension without reordering of the
MRO of each of its superclasses.
Extended Precedence Graph (EPG).
Linearization is consistent if there is a path in the EPG from
each class to all its successors in the linearization. See
the paper for definition of EPG.
*/
static int
tail_contains(PyObject *tuple, int whence, PyObject *o)
{
Py_ssize_t j, size;
size = PyTuple_GET_SIZE(tuple);
for (j = whence+1; j < size; j++) {
if (PyTuple_GET_ITEM(tuple, j) == o)
return 1;
}
return 0;
}
static PyObject *
class_name(PyObject *cls)
{
PyObject *name = _PyObject_GetAttrId(cls, &PyId___name__);
if (name == NULL) {
PyErr_Clear();
name = PyObject_Repr(cls);
}
if (name == NULL)
return NULL;
if (!PyUnicode_Check(name)) {
Py_DECREF(name);
return NULL;
}
return name;
}
static int
check_duplicates(PyObject *tuple)
{
Py_ssize_t i, j, n;
/* Let's use a quadratic time algorithm,
assuming that the bases tuples is short.
*/
n = PyTuple_GET_SIZE(tuple);
for (i = 0; i < n; i++) {
PyObject *o = PyTuple_GET_ITEM(tuple, i);
for (j = i + 1; j < n; j++) {
if (PyTuple_GET_ITEM(tuple, j) == o) {
o = class_name(o);
if (o != NULL) {
PyErr_Format(PyExc_TypeError,
"duplicate base class %U",
o);
Py_DECREF(o);
} else {
PyErr_SetString(PyExc_TypeError,
"duplicate base class");
}
return -1;
}
}
}
return 0;
}
/* Raise a TypeError for an MRO order disagreement.
It's hard to produce a good error message. In the absence of better
insight into error reporting, report the classes that were candidates
to be put next into the MRO. There is some conflict between the
order in which they should be put in the MRO, but it's hard to
diagnose what constraint can't be satisfied.
*/
static void
set_mro_error(PyObject **to_merge, Py_ssize_t to_merge_size, int *remain)
{
Py_ssize_t i, n, off;
char buf[1000];
PyObject *k, *v;
PyObject *set = PyDict_New();
if (!set) return;
for (i = 0; i < to_merge_size; i++) {
PyObject *L = to_merge[i];
if (remain[i] < PyTuple_GET_SIZE(L)) {
PyObject *c = PyTuple_GET_ITEM(L, remain[i]);
if (PyDict_SetItem(set, c, Py_None) < 0) {
Py_DECREF(set);
return;
}
}
}
n = PyDict_GET_SIZE(set);
off = PyOS_snprintf(buf, sizeof(buf), "Cannot create a \
consistent method resolution\norder (MRO) for bases");
i = 0;
while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) {
PyObject *name = class_name(k);
const char *name_str;
if (name != NULL) {
name_str = PyUnicode_AsUTF8(name);
if (name_str == NULL)
name_str = "?";
} else
name_str = "?";
off += PyOS_snprintf(buf + off, sizeof(buf) - off, " %s", name_str);
Py_XDECREF(name);
if (--n && (size_t)(off+1) < sizeof(buf)) {
buf[off++] = ',';
buf[off] = '\0';
}
}
PyErr_SetString(PyExc_TypeError, buf);
Py_DECREF(set);
}
static int
pmerge(PyObject *acc, PyObject **to_merge, Py_ssize_t to_merge_size)
{
int res = 0;
Py_ssize_t i, j, empty_cnt;
int *remain;
/* remain stores an index into each sublist of to_merge.
remain[i] is the index of the next base in to_merge[i]
that is not included in acc.
*/
remain = PyMem_New(int, to_merge_size);
if (remain == NULL) {
PyErr_NoMemory();
return -1;
}
for (i = 0; i < to_merge_size; i++)
remain[i] = 0;
again:
empty_cnt = 0;
for (i = 0; i < to_merge_size; i++) {
PyObject *candidate;
PyObject *cur_tuple = to_merge[i];
if (remain[i] >= PyTuple_GET_SIZE(cur_tuple)) {
empty_cnt++;
continue;
}
/* Choose next candidate for MRO.
The input sequences alone can determine the choice.
If not, choose the class which appears in the MRO
of the earliest direct superclass of the new class.
*/
candidate = PyTuple_GET_ITEM(cur_tuple, remain[i]);
for (j = 0; j < to_merge_size; j++) {
PyObject *j_lst = to_merge[j];
if (tail_contains(j_lst, remain[j], candidate))
goto skip; /* continue outer loop */
}
res = PyList_Append(acc, candidate);
if (res < 0)
goto out;
for (j = 0; j < to_merge_size; j++) {
PyObject *j_lst = to_merge[j];
if (remain[j] < PyTuple_GET_SIZE(j_lst) &&
PyTuple_GET_ITEM(j_lst, remain[j]) == candidate) {
remain[j]++;
}
}
goto again;
skip: ;
}
if (empty_cnt != to_merge_size) {
set_mro_error(to_merge, to_merge_size, remain);
res = -1;
}
out:
PyMem_Del(remain);
return res;
}
static PyObject *
mro_implementation(PyTypeObject *type)
{
PyObject *result;
PyObject *bases;
PyObject **to_merge;
Py_ssize_t i, n;
if (type->tp_dict == NULL) {
if (PyType_Ready(type) < 0)
return NULL;
}
bases = type->tp_bases;
assert(PyTuple_Check(bases));
n = PyTuple_GET_SIZE(bases);
for (i = 0; i < n; i++) {
PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i);
if (base->tp_mro == NULL) {
PyErr_Format(PyExc_TypeError,
"Cannot extend an incomplete type '%.100s'",
base->tp_name);
return NULL;
}
assert(PyTuple_Check(base->tp_mro));
}
if (n == 1) {
/* Fast path: if there is a single base, constructing the MRO
* is trivial.
*/
PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0);
Py_ssize_t k = PyTuple_GET_SIZE(base->tp_mro);
result = PyTuple_New(k + 1);
if (result == NULL) {
return NULL;
}
Py_INCREF(type);
PyTuple_SET_ITEM(result, 0, (PyObject *) type);
for (i = 0; i < k; i++) {
PyObject *cls = PyTuple_GET_ITEM(base->tp_mro, i);
Py_INCREF(cls);
PyTuple_SET_ITEM(result, i + 1, cls);
}
return result;
}
/* This is just a basic sanity check. */
if (check_duplicates(bases) < 0) {
return NULL;
}
/* Find a superclass linearization that honors the constraints
of the explicit tuples of bases and the constraints implied by
each base class.
to_merge is an array of tuples, where each tuple is a superclass
linearization implied by a base class. The last element of
to_merge is the declared tuple of bases.
*/
to_merge = PyMem_New(PyObject *, n + 1);
if (to_merge == NULL) {
PyErr_NoMemory();
return NULL;
}
for (i = 0; i < n; i++) {
PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, i);
to_merge[i] = base->tp_mro;
}
to_merge[n] = bases;
result = PyList_New(1);
if (result == NULL) {
PyMem_Del(to_merge);
return NULL;
}
Py_INCREF(type);
PyList_SET_ITEM(result, 0, (PyObject *)type);
if (pmerge(result, to_merge, n + 1) < 0) {
Py_CLEAR(result);
}
PyMem_Del(to_merge);
return result;
}
/*[clinic input]
type.mro
Return a type's method resolution order.
[clinic start generated code]*/
static PyObject *
type_mro_impl(PyTypeObject *self)
/*[clinic end generated code: output=bffc4a39b5b57027 input=28414f4e156db28d]*/
{
PyObject *seq;
seq = mro_implementation(self);
if (seq != NULL && !PyList_Check(seq)) {
Py_SETREF(seq, PySequence_List(seq));
}
return seq;
}
static int
mro_check(PyTypeObject *type, PyObject *mro)
{
PyTypeObject *solid;
Py_ssize_t i, n;
solid = solid_base(type);
n = PyTuple_GET_SIZE(mro);
for (i = 0; i < n; i++) {
PyTypeObject *base;
PyObject *tmp;
tmp = PyTuple_GET_ITEM(mro, i);
if (!PyType_Check(tmp)) {
PyErr_Format(
PyExc_TypeError,
"mro() returned a non-class ('%.500s')",
Py_TYPE(tmp)->tp_name);
return -1;
}
base = (PyTypeObject*)tmp;
if (!PyType_IsSubtype(solid, solid_base(base))) {
PyErr_Format(
PyExc_TypeError,
"mro() returned base with unsuitable layout ('%.500s')",
base->tp_name);
return -1;
}
}
return 0;
}
/* Lookups an mcls.mro method, invokes it and checks the result (if needed,
in case of a custom mro() implementation).
Keep in mind that during execution of this function type->tp_mro
can be replaced due to possible reentrance (for example,
through type_set_bases):
- when looking up the mcls.mro attribute (it could be
a user-provided descriptor);
- from inside a custom mro() itself;
- through a finalizer of the return value of mro().
*/
static PyObject *
mro_invoke(PyTypeObject *type)
{
PyObject *mro_result;
PyObject *new_mro;
int custom = (Py_TYPE(type) != &PyType_Type);
if (custom) {
_Py_IDENTIFIER(mro);
int unbound;
PyObject *mro_meth = lookup_method((PyObject *)type, &PyId_mro,
&unbound);
if (mro_meth == NULL)
return NULL;
mro_result = call_unbound_noarg(unbound, mro_meth, (PyObject *)type);
Py_DECREF(mro_meth);
}
else {
mro_result = mro_implementation(type);
}
if (mro_result == NULL)
return NULL;
new_mro = PySequence_Tuple(mro_result);
Py_DECREF(mro_result);
if (new_mro == NULL)
return NULL;
if (custom && mro_check(type, new_mro) < 0) {
Py_DECREF(new_mro);
return NULL;
}
return new_mro;
}
/* Calculates and assigns a new MRO to type->tp_mro.
Return values and invariants:
- Returns 1 if a new MRO value has been set to type->tp_mro due to
this call of mro_internal (no tricky reentrancy and no errors).
In case if p_old_mro argument is not NULL, a previous value
of type->tp_mro is put there, and the ownership of this
reference is transferred to a caller.
Otherwise, the previous value (if any) is decref'ed.
- Returns 0 in case when type->tp_mro gets changed because of
reentering here through a custom mro() (see a comment to mro_invoke).
In this case, a refcount of an old type->tp_mro is adjusted
somewhere deeper in the call stack (by the innermost mro_internal
or its caller) and may become zero upon returning from here.
This also implies that the whole hierarchy of subclasses of the type
has seen the new value and updated their MRO accordingly.
- Returns -1 in case of an error.
*/
static int
mro_internal(PyTypeObject *type, PyObject **p_old_mro)
{
PyObject *new_mro, *old_mro;
int reent;
/* Keep a reference to be able to do a reentrancy check below.
Don't let old_mro be GC'ed and its address be reused for
another object, like (suddenly!) a new tp_mro. */
old_mro = type->tp_mro;
Py_XINCREF(old_mro);
new_mro = mro_invoke(type); /* might cause reentrance */
reent = (type->tp_mro != old_mro);
Py_XDECREF(old_mro);
if (new_mro == NULL)
return -1;
if (reent) {
Py_DECREF(new_mro);
return 0;
}
type->tp_mro = new_mro;
type_mro_modified(type, type->tp_mro);
/* corner case: the super class might have been hidden
from the custom MRO */
type_mro_modified(type, type->tp_bases);
PyType_Modified(type);
if (p_old_mro != NULL)
*p_old_mro = old_mro; /* transfer the ownership */
else
Py_XDECREF(old_mro);
return 1;
}
/* Calculate the best base amongst multiple base classes.
This is the first one that's on the path to the "solid base". */
static PyTypeObject *
best_base(PyObject *bases)
{
Py_ssize_t i, n;
PyTypeObject *base, *winner, *candidate, *base_i;
PyObject *base_proto;
assert(PyTuple_Check(bases));
n = PyTuple_GET_SIZE(bases);
assert(n > 0);
base = NULL;
winner = NULL;
for (i = 0; i < n; i++) {
base_proto = PyTuple_GET_ITEM(bases, i);
if (!PyType_Check(base_proto)) {
PyErr_SetString(
PyExc_TypeError,
"bases must be types");
return NULL;
}
base_i = (PyTypeObject *)base_proto;
if (base_i->tp_dict == NULL) {
if (PyType_Ready(base_i) < 0)
return NULL;
}
if (!PyType_HasFeature(base_i, Py_TPFLAGS_BASETYPE)) {
PyErr_Format(PyExc_TypeError,
"type '%.100s' is not an acceptable base type",
base_i->tp_name);
return NULL;
}
candidate = solid_base(base_i);
if (winner == NULL) {
winner = candidate;
base = base_i;
}
else if (PyType_IsSubtype(winner, candidate))
;
else if (PyType_IsSubtype(candidate, winner)) {
winner = candidate;
base = base_i;
}
else {
PyErr_SetString(
PyExc_TypeError,
"multiple bases have "
"instance lay-out conflict");
return NULL;
}
}
assert (base != NULL);
return base;
}
static int
extra_ivars(PyTypeObject *type, PyTypeObject *base)
{
size_t t_size = type->tp_basicsize;
size_t b_size = base->tp_basicsize;
assert(t_size >= b_size); /* Else type smaller than base! */
if (type->tp_itemsize || base->tp_itemsize) {
/* If itemsize is involved, stricter rules */
return t_size != b_size ||
type->tp_itemsize != base->tp_itemsize;
}
if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 &&
type->tp_weaklistoffset + sizeof(PyObject *) == t_size &&
type->tp_flags & Py_TPFLAGS_HEAPTYPE)
t_size -= sizeof(PyObject *);
if (type->tp_dictoffset && base->tp_dictoffset == 0 &&
type->tp_dictoffset + sizeof(PyObject *) == t_size &&
type->tp_flags & Py_TPFLAGS_HEAPTYPE)
t_size -= sizeof(PyObject *);
return t_size != b_size;
}
static PyTypeObject *
solid_base(PyTypeObject *type)
{
PyTypeObject *base;
if (type->tp_base)
base = solid_base(type->tp_base);
else
base = &PyBaseObject_Type;
if (extra_ivars(type, base))
return type;
else
return base;
}
static void object_dealloc(PyObject *);
static int object_init(PyObject *, PyObject *, PyObject *);
static int update_slot(PyTypeObject *, PyObject *);
static void fixup_slot_dispatchers(PyTypeObject *);
static int set_names(PyTypeObject *);
static int init_subclass(PyTypeObject *, PyObject *);
/*
* Helpers for __dict__ descriptor. We don't want to expose the dicts
* inherited from various builtin types. The builtin base usually provides
* its own __dict__ descriptor, so we use that when we can.
*/
static PyTypeObject *
get_builtin_base_with_dict(PyTypeObject *type)
{
while (type->tp_base != NULL) {
if (type->tp_dictoffset != 0 &&
!(type->tp_flags & Py_TPFLAGS_HEAPTYPE))
return type;
type = type->tp_base;
}
return NULL;
}
static PyObject *
get_dict_descriptor(PyTypeObject *type)
{
PyObject *descr;
descr = _PyType_LookupId(type, &PyId___dict__);
if (descr == NULL || !PyDescr_IsData(descr))
return NULL;
return descr;
}
static void
raise_dict_descr_error(PyObject *obj)
{
PyErr_Format(PyExc_TypeError,
"this __dict__ descriptor does not support "
"'%.200s' objects", Py_TYPE(obj)->tp_name);
}
static PyObject *
subtype_dict(PyObject *obj, void *context)
{
PyTypeObject *base;
base = get_builtin_base_with_dict(Py_TYPE(obj));
if (base != NULL) {
descrgetfunc func;
PyObject *descr = get_dict_descriptor(base);
if (descr == NULL) {
raise_dict_descr_error(obj);
return NULL;
}
func = Py_TYPE(descr)->tp_descr_get;
if (func == NULL) {
raise_dict_descr_error(obj);
return NULL;
}
return func(descr, obj, (PyObject *)(Py_TYPE(obj)));
}
return PyObject_GenericGetDict(obj, context);
}
static int
subtype_setdict(PyObject *obj, PyObject *value, void *context)
{
PyObject **dictptr;
PyTypeObject *base;
base = get_builtin_base_with_dict(Py_TYPE(obj));
if (base != NULL) {
descrsetfunc func;
PyObject *descr = get_dict_descriptor(base);
if (descr == NULL) {
raise_dict_descr_error(obj);
return -1;
}
func = Py_TYPE(descr)->tp_descr_set;
if (func == NULL) {
raise_dict_descr_error(obj);
return -1;
}
return func(descr, obj, value);
}
/* Almost like PyObject_GenericSetDict, but allow __dict__ to be deleted. */
dictptr = _PyObject_GetDictPtr(obj);
if (dictptr == NULL) {
PyErr_SetString(PyExc_AttributeError,
"This object has no __dict__");
return -1;
}
if (value != NULL && !PyDict_Check(value)) {
PyErr_Format(PyExc_TypeError,
"__dict__ must be set to a dictionary, "
"not a '%.200s'", Py_TYPE(value)->tp_name);
return -1;
}
Py_XINCREF(value);
Py_XSETREF(*dictptr, value);
return 0;
}
static PyObject *
subtype_getweakref(PyObject *obj, void *context)
{
PyObject **weaklistptr;
PyObject *result;
if (Py_TYPE(obj)->tp_weaklistoffset == 0) {
PyErr_SetString(PyExc_AttributeError,
"This object has no __weakref__");
return NULL;
}
assert(Py_TYPE(obj)->tp_weaklistoffset > 0);
assert(Py_TYPE(obj)->tp_weaklistoffset + sizeof(PyObject *) <=
(size_t)(Py_TYPE(obj)->tp_basicsize));
weaklistptr = (PyObject **)
((char *)obj + Py_TYPE(obj)->tp_weaklistoffset);
if (*weaklistptr == NULL)
result = Py_None;
else
result = *weaklistptr;
Py_INCREF(result);
return result;
}
/* Three variants on the subtype_getsets list. */
static PyGetSetDef subtype_getsets_full[] = {
{"__dict__", subtype_dict, subtype_setdict,
PyDoc_STR("dictionary for instance variables (if defined)")},
{"__weakref__", subtype_getweakref, NULL,
PyDoc_STR("list of weak references to the object (if defined)")},
{0}
};
static PyGetSetDef subtype_getsets_dict_only[] = {
{"__dict__", subtype_dict, subtype_setdict,
PyDoc_STR("dictionary for instance variables (if defined)")},
{0}
};
static PyGetSetDef subtype_getsets_weakref_only[] = {
{"__weakref__", subtype_getweakref, NULL,
PyDoc_STR("list of weak references to the object (if defined)")},
{0}
};
static int
valid_identifier(PyObject *s)
{
if (!PyUnicode_Check(s)) {
PyErr_Format(PyExc_TypeError,
"__slots__ items must be strings, not '%.200s'",
Py_TYPE(s)->tp_name);
return 0;
}
if (!PyUnicode_IsIdentifier(s)) {
PyErr_SetString(PyExc_TypeError,
"__slots__ must be identifiers");
return 0;
}
return 1;
}
/* Forward */
static int
object_init(PyObject *self, PyObject *args, PyObject *kwds);
static int
type_init(PyObject *cls, PyObject *args, PyObject *kwds)
{
int res;
assert(args != NULL && PyTuple_Check(args));
assert(kwds == NULL || PyDict_Check(kwds));
if (kwds != NULL && PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
PyDict_Check(kwds) && PyDict_GET_SIZE(kwds) != 0) {
PyErr_SetString(PyExc_TypeError,
"type.__init__() takes no keyword arguments");
return -1;
}
if (args != NULL && PyTuple_Check(args) &&
(PyTuple_GET_SIZE(args) != 1 && PyTuple_GET_SIZE(args) != 3)) {
PyErr_SetString(PyExc_TypeError,
"type.__init__() takes 1 or 3 arguments");
return -1;
}
/* Call object.__init__(self) now. */
/* XXX Could call super(type, cls).__init__() but what's the point? */
args = PyTuple_GetSlice(args, 0, 0);
res = object_init(cls, args, NULL);
Py_DECREF(args);
return res;
}
unsigned long
PyType_GetFlags(PyTypeObject *type)
{
return type->tp_flags;
}
/* Determine the most derived metatype. */
PyTypeObject *
_PyType_CalculateMetaclass(PyTypeObject *metatype, PyObject *bases)
{
Py_ssize_t i, nbases;
PyTypeObject *winner;
PyObject *tmp;
PyTypeObject *tmptype;
/* Determine the proper metatype to deal with this,
and check for metatype conflicts while we're at it.
Note that if some other metatype wins to contract,
it's possible that its instances are not types. */
nbases = PyTuple_GET_SIZE(bases);
winner = metatype;
for (i = 0; i < nbases; i++) {
tmp = PyTuple_GET_ITEM(bases, i);
tmptype = Py_TYPE(tmp);
if (PyType_IsSubtype(winner, tmptype))
continue;
if (PyType_IsSubtype(tmptype, winner)) {
winner = tmptype;
continue;
}
/* else: */
PyErr_SetString(PyExc_TypeError,
"metaclass conflict: "
"the metaclass of a derived class "
"must be a (non-strict) subclass "
"of the metaclasses of all its bases");
return NULL;
}
return winner;
}
static PyObject *
type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
{
PyObject *name, *bases = NULL, *orig_dict, *dict = NULL;
PyObject *qualname, *slots = NULL, *tmp, *newslots, *cell;
PyTypeObject *type = NULL, *base, *tmptype, *winner;
PyHeapTypeObject *et;
PyMemberDef *mp;
Py_ssize_t i, nbases, nslots, slotoffset, name_size;
int j, may_add_dict, may_add_weak, add_dict, add_weak;
_Py_IDENTIFIER(__qualname__);
_Py_IDENTIFIER(__slots__);
_Py_IDENTIFIER(__classcell__);
assert(args != NULL && PyTuple_Check(args));
assert(kwds == NULL || PyDict_Check(kwds));
/* Special case: type(x) should return x->ob_type */
/* We only want type itself to accept the one-argument form (#27157)
Note: We don't call PyType_CheckExact as that also allows subclasses */
if (metatype == &PyType_Type) {
const Py_ssize_t nargs = PyTuple_GET_SIZE(args);
const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_GET_SIZE(kwds);
if (nargs == 1 && nkwds == 0) {
PyObject *x = PyTuple_GET_ITEM(args, 0);
Py_INCREF(Py_TYPE(x));
return (PyObject *) Py_TYPE(x);
}
/* SF bug 475327 -- if that didn't trigger, we need 3
arguments. but PyArg_ParseTuple below may give
a msg saying type() needs exactly 3. */
if (nargs != 3) {
PyErr_SetString(PyExc_TypeError,
"type() takes 1 or 3 arguments");
return NULL;
}
}
/* Check arguments: (name, bases, dict) */
if (!PyArg_ParseTuple(args, "UO!O!:type.__new__", &name, &PyTuple_Type,
&bases, &PyDict_Type, &orig_dict))
return NULL;
/* Adjust for empty tuple bases */
nbases = PyTuple_GET_SIZE(bases);
if (nbases == 0) {
base = &PyBaseObject_Type;
bases = PyTuple_Pack(1, base);
if (bases == NULL)
return NULL;
nbases = 1;
}
else {
_Py_IDENTIFIER(__mro_entries__);
for (i = 0; i < nbases; i++) {
tmp = PyTuple_GET_ITEM(bases, i);
if (PyType_Check(tmp)) {
continue;
}
if (_PyObject_LookupAttrId(tmp, &PyId___mro_entries__, &tmp) < 0) {
return NULL;
}
if (tmp != NULL) {
PyErr_SetString(PyExc_TypeError,
"type() doesn't support MRO entry resolution; "
"use types.new_class()");
Py_DECREF(tmp);
return NULL;
}
}
/* Search the bases for the proper metatype to deal with this: */
winner = _PyType_CalculateMetaclass(metatype, bases);
if (winner == NULL) {
return NULL;
}
if (winner != metatype) {
if (winner->tp_new != type_new) /* Pass it to the winner */
return winner->tp_new(winner, args, kwds);
metatype = winner;
}
/* Calculate best base, and check that all bases are type objects */
base = best_base(bases);
if (base == NULL) {
return NULL;
}
Py_INCREF(bases);
}
/* Use "goto error" from this point on as we now own the reference to "bases". */
dict = PyDict_Copy(orig_dict);
if (dict == NULL)
goto error;
/* Check for a __slots__ sequence variable in dict, and count it */
slots = _PyDict_GetItemId(dict, &PyId___slots__);
nslots = 0;
add_dict = 0;
add_weak = 0;
may_add_dict = base->tp_dictoffset == 0;
may_add_weak = base->tp_weaklistoffset == 0 && base->tp_itemsize == 0;
if (slots == NULL) {
if (may_add_dict) {
add_dict++;
}
if (may_add_weak) {
add_weak++;
}
}
else {
/* Have slots */
/* Make it into a tuple */
if (PyUnicode_Check(slots))
slots = PyTuple_Pack(1, slots);
else
slots = PySequence_Tuple(slots);
if (slots == NULL)
goto error;
assert(PyTuple_Check(slots));
/* Are slots allowed? */
nslots = PyTuple_GET_SIZE(slots);
if (nslots > 0 && base->tp_itemsize != 0) {
PyErr_Format(PyExc_TypeError,
"nonempty __slots__ "
"not supported for subtype of '%s'",
base->tp_name);
goto error;
}
/* Check for valid slot names and two special cases */
for (i = 0; i < nslots; i++) {
PyObject *tmp = PyTuple_GET_ITEM(slots, i);
if (!valid_identifier(tmp))
goto error;
assert(PyUnicode_Check(tmp));
if (_PyUnicode_EqualToASCIIId(tmp, &PyId___dict__)) {
if (!may_add_dict || add_dict) {
PyErr_SetString(PyExc_TypeError,
"__dict__ slot disallowed: "
"we already got one");
goto error;
}
add_dict++;
}
if (_PyUnicode_EqualToASCIIString(tmp, "__weakref__")) {
if (!may_add_weak || add_weak) {
PyErr_SetString(PyExc_TypeError,
"__weakref__ slot disallowed: "
"either we already got one, "
"or __itemsize__ != 0");
goto error;
}
add_weak++;
}
}
/* Copy slots into a list, mangle names and sort them.
Sorted names are needed for __class__ assignment.
Convert them back to tuple at the end.
*/
newslots = PyList_New(nslots - add_dict - add_weak);
if (newslots == NULL)
goto error;
for (i = j = 0; i < nslots; i++) {
tmp = PyTuple_GET_ITEM(slots, i);
if ((add_dict &&
_PyUnicode_EqualToASCIIId(tmp, &PyId___dict__)) ||
(add_weak &&
_PyUnicode_EqualToASCIIString(tmp, "__weakref__")))
continue;
tmp =_Py_Mangle(name, tmp);
if (!tmp) {
Py_DECREF(newslots);
goto error;
}
PyList_SET_ITEM(newslots, j, tmp);
if (PyDict_GetItem(dict, tmp)) {
/* CPython inserts __qualname__ and __classcell__ (when needed)
into the namespace when creating a class. They will be deleted
below so won't act as class variables. */
if (!_PyUnicode_EqualToASCIIId(tmp, &PyId___qualname__) &&
!_PyUnicode_EqualToASCIIId(tmp, &PyId___classcell__)) {
PyErr_Format(PyExc_ValueError,
"%R in __slots__ conflicts with class variable",
tmp);
Py_DECREF(newslots);
goto error;
}
}
j++;
}
assert(j == nslots - add_dict - add_weak);
nslots = j;
Py_CLEAR(slots);
if (PyList_Sort(newslots) == -1) {
Py_DECREF(newslots);
goto error;
}
slots = PyList_AsTuple(newslots);
Py_DECREF(newslots);
if (slots == NULL)
goto error;
/* Secondary bases may provide weakrefs or dict */
if (nbases > 1 &&
((may_add_dict && !add_dict) ||
(may_add_weak && !add_weak))) {
for (i = 0; i < nbases; i++) {
tmp = PyTuple_GET_ITEM(bases, i);
if (tmp == (PyObject *)base)
continue; /* Skip primary base */
assert(PyType_Check(tmp));
tmptype = (PyTypeObject *)tmp;
if (may_add_dict && !add_dict &&
tmptype->tp_dictoffset != 0)
add_dict++;
if (may_add_weak && !add_weak &&
tmptype->tp_weaklistoffset != 0)
add_weak++;
if (may_add_dict && !add_dict)
continue;
if (may_add_weak && !add_weak)
continue;
/* Nothing more to check */
break;
}
}
}
/* Allocate the type object */
type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots);
if (type == NULL)
goto error;
/* Keep name and slots alive in the extended type object */
et = (PyHeapTypeObject *)type;
Py_INCREF(name);
et->ht_name = name;
et->ht_slots = slots;
slots = NULL;
/* Initialize tp_flags */
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE |
Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_FINALIZE;
if (base->tp_flags & Py_TPFLAGS_HAVE_GC)
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
/* Initialize essential fields */
type->tp_as_async = &et->as_async;
type->tp_as_number = &et->as_number;
type->tp_as_sequence = &et->as_sequence;
type->tp_as_mapping = &et->as_mapping;
type->tp_as_buffer = &et->as_buffer;
type->tp_name = PyUnicode_AsUTF8AndSize(name, &name_size);
if (!type->tp_name)
goto error;
if (strlen(type->tp_name) != (size_t)name_size) {
PyErr_SetString(PyExc_ValueError,
"type name must not contain null characters");
goto error;
}
/* Set tp_base and tp_bases */
type->tp_bases = bases;
bases = NULL;
Py_INCREF(base);
type->tp_base = base;
/* Initialize tp_dict from passed-in dict */
Py_INCREF(dict);
type->tp_dict = dict;
/* Set __module__ in the dict */
if (_PyDict_GetItemId(dict, &PyId___module__) == NULL) {
tmp = PyEval_GetGlobals();
if (tmp != NULL) {
tmp = _PyDict_GetItemId(tmp, &PyId___name__);
if (tmp != NULL) {
if (_PyDict_SetItemId(dict, &PyId___module__,
tmp) < 0)
goto error;
}
}
}
/* Set ht_qualname to dict['__qualname__'] if available, else to
__name__. The __qualname__ accessor will look for ht_qualname.
*/
qualname = _PyDict_GetItemId(dict, &PyId___qualname__);
if (qualname != NULL) {
if (!PyUnicode_Check(qualname)) {
PyErr_Format(PyExc_TypeError,
"type __qualname__ must be a str, not %s",
Py_TYPE(qualname)->tp_name);
goto error;
}
}
et->ht_qualname = qualname ? qualname : et->ht_name;
Py_INCREF(et->ht_qualname);
if (qualname != NULL && _PyDict_DelItemId(dict, &PyId___qualname__) < 0)
goto error;
/* Set tp_doc to a copy of dict['__doc__'], if the latter is there
and is a string. The __doc__ accessor will first look for tp_doc;
if that fails, it will still look into __dict__.
*/
{
PyObject *doc = _PyDict_GetItemId(dict, &PyId___doc__);
if (doc != NULL && PyUnicode_Check(doc)) {
Py_ssize_t len;
const char *doc_str;
char *tp_doc;
doc_str = PyUnicode_AsUTF8(doc);
if (doc_str == NULL)
goto error;
/* Silently truncate the docstring if it contains null bytes. */
len = strlen(doc_str);
tp_doc = (char *)PyObject_MALLOC(len + 1);
if (tp_doc == NULL) {
PyErr_NoMemory();
goto error;
}
memcpy(tp_doc, doc_str, len + 1);
type->tp_doc = tp_doc;
}
}
/* Special-case __new__: if it's a plain function,
make it a static function */
tmp = _PyDict_GetItemId(dict, &PyId___new__);
if (tmp != NULL && PyFunction_Check(tmp)) {
tmp = PyStaticMethod_New(tmp);
if (tmp == NULL)
goto error;
if (_PyDict_SetItemId(dict, &PyId___new__, tmp) < 0) {
Py_DECREF(tmp);
goto error;
}
Py_DECREF(tmp);
}
/* Special-case __init_subclass__ and __class_getitem__:
if they are plain functions, make them classmethods */
tmp = _PyDict_GetItemId(dict, &PyId___init_subclass__);
if (tmp != NULL && PyFunction_Check(tmp)) {
tmp = PyClassMethod_New(tmp);
if (tmp == NULL)
goto error;
if (_PyDict_SetItemId(dict, &PyId___init_subclass__, tmp) < 0) {
Py_DECREF(tmp);
goto error;
}
Py_DECREF(tmp);
}
tmp = _PyDict_GetItemId(dict, &PyId___class_getitem__);
if (tmp != NULL && PyFunction_Check(tmp)) {
tmp = PyClassMethod_New(tmp);
if (tmp == NULL)
goto error;
if (_PyDict_SetItemId(dict, &PyId___class_getitem__, tmp) < 0) {
Py_DECREF(tmp);
goto error;
}
Py_DECREF(tmp);
}
/* Add descriptors for custom slots from __slots__, or for __dict__ */
mp = PyHeapType_GET_MEMBERS(et);
slotoffset = base->tp_basicsize;
if (et->ht_slots != NULL) {
for (i = 0; i < nslots; i++, mp++) {
mp->name = PyUnicode_AsUTF8(
PyTuple_GET_ITEM(et->ht_slots, i));
if (mp->name == NULL)
goto error;
mp->type = T_OBJECT_EX;
mp->offset = slotoffset;
/* __dict__ and __weakref__ are already filtered out */
assert(strcmp(mp->name, "__dict__") != 0);
assert(strcmp(mp->name, "__weakref__") != 0);
slotoffset += sizeof(PyObject *);
}
}
if (add_dict) {
if (base->tp_itemsize)
type->tp_dictoffset = -(long)sizeof(PyObject *);
else
type->tp_dictoffset = slotoffset;
slotoffset += sizeof(PyObject *);
}
if (add_weak) {
assert(!base->tp_itemsize);
type->tp_weaklistoffset = slotoffset;
slotoffset += sizeof(PyObject *);
}
type->tp_basicsize = slotoffset;
type->tp_itemsize = base->tp_itemsize;
type->tp_members = PyHeapType_GET_MEMBERS(et);
if (type->tp_weaklistoffset && type->tp_dictoffset)
type->tp_getset = subtype_getsets_full;
else if (type->tp_weaklistoffset && !type->tp_dictoffset)
type->tp_getset = subtype_getsets_weakref_only;
else if (!type->tp_weaklistoffset && type->tp_dictoffset)
type->tp_getset = subtype_getsets_dict_only;
else
type->tp_getset = NULL;
/* Special case some slots */
if (type->tp_dictoffset != 0 || nslots > 0) {
if (base->tp_getattr == NULL && base->tp_getattro == NULL)
type->tp_getattro = PyObject_GenericGetAttr;
if (base->tp_setattr == NULL && base->tp_setattro == NULL)
type->tp_setattro = PyObject_GenericSetAttr;
}
type->tp_dealloc = subtype_dealloc;
/* Enable GC unless this class is not adding new instance variables and
the base class did not use GC. */
if ((base->tp_flags & Py_TPFLAGS_HAVE_GC) ||
type->tp_basicsize > base->tp_basicsize)
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
/* Always override allocation strategy to use regular heap */
type->tp_alloc = PyType_GenericAlloc;
if (type->tp_flags & Py_TPFLAGS_HAVE_GC) {
type->tp_free = PyObject_GC_Del;
type->tp_traverse = subtype_traverse;
type->tp_clear = subtype_clear;
}
else
type->tp_free = PyObject_Del;
/* store type in class' cell if one is supplied */
cell = _PyDict_GetItemId(dict, &PyId___classcell__);
if (cell != NULL) {
/* At least one method requires a reference to its defining class */
if (!PyCell_Check(cell)) {
PyErr_Format(PyExc_TypeError,
"__classcell__ must be a nonlocal cell, not %.200R",
Py_TYPE(cell));
goto error;
}
PyCell_Set(cell, (PyObject *) type);
_PyDict_DelItemId(dict, &PyId___classcell__);
PyErr_Clear();
}
/* Initialize the rest */
if (PyType_Ready(type) < 0)
goto error;
/* Put the proper slots in place */
fixup_slot_dispatchers(type);
if (type->tp_dictoffset) {
et->ht_cached_keys = _PyDict_NewKeysForClass();
}
if (set_names(type) < 0)
goto error;
if (init_subclass(type, kwds) < 0)
goto error;
Py_DECREF(dict);
return (PyObject *)type;
error:
Py_XDECREF(dict);
Py_XDECREF(bases);
Py_XDECREF(slots);
Py_XDECREF(type);
return NULL;
}
static const short slotoffsets[] = {
-1, /* invalid slot */
#include "typeslots.inc"
};
PyObject *
PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
{
PyHeapTypeObject *res = (PyHeapTypeObject*)PyType_GenericAlloc(&PyType_Type, 0);
PyTypeObject *type, *base;
PyObject *modname;
char *s;
char *res_start = (char*)res;
PyType_Slot *slot;
/* Set the type name and qualname */
s = strrchr(spec->name, '.');
if (s == NULL)
s = (char*)spec->name;
else
s++;
if (res == NULL)
return NULL;
type = &res->ht_type;
/* The flags must be initialized early, before the GC traverses us */
type->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE;
res->ht_name = PyUnicode_FromString(s);
if (!res->ht_name)
goto fail;
res->ht_qualname = res->ht_name;
Py_INCREF(res->ht_qualname);
type->tp_name = spec->name;
if (!type->tp_name)
goto fail;
/* Adjust for empty tuple bases */
if (!bases) {
base = &PyBaseObject_Type;
/* See whether Py_tp_base(s) was specified */
for (slot = spec->slots; slot->slot; slot++) {
if (slot->slot == Py_tp_base)
base = slot->pfunc;
else if (slot->slot == Py_tp_bases) {
bases = slot->pfunc;
Py_INCREF(bases);
}
}
if (!bases)
bases = PyTuple_Pack(1, base);
if (!bases)
goto fail;
}
else
Py_INCREF(bases);
/* Calculate best base, and check that all bases are type objects */
base = best_base(bases);
if (base == NULL) {
goto fail;
}
if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
PyErr_Format(PyExc_TypeError,
"type '%.100s' is not an acceptable base type",
base->tp_name);
goto fail;
}
/* Initialize essential fields */
type->tp_as_async = &res->as_async;
type->tp_as_number = &res->as_number;
type->tp_as_sequence = &res->as_sequence;
type->tp_as_mapping = &res->as_mapping;
type->tp_as_buffer = &res->as_buffer;
/* Set tp_base and tp_bases */
type->tp_bases = bases;
bases = NULL;
Py_INCREF(base);
type->tp_base = base;
type->tp_basicsize = spec->basicsize;
type->tp_itemsize = spec->itemsize;
for (slot = spec->slots; slot->slot; slot++) {
if (slot->slot < 0
|| (size_t)slot->slot >= Py_ARRAY_LENGTH(slotoffsets)) {
PyErr_SetString(PyExc_RuntimeError, "invalid slot offset");
goto fail;
}
if (slot->slot == Py_tp_base || slot->slot == Py_tp_bases)
/* Processed above */
continue;
*(void**)(res_start + slotoffsets[slot->slot]) = slot->pfunc;
/* need to make a copy of the docstring slot, which usually
points to a static string literal */
if (slot->slot == Py_tp_doc) {
const char *old_doc = _PyType_DocWithoutSignature(type->tp_name, slot->pfunc);
size_t len = strlen(old_doc)+1;
char *tp_doc = PyObject_MALLOC(len);
if (tp_doc == NULL) {
PyErr_NoMemory();
goto fail;
}
memcpy(tp_doc, old_doc, len);
type->tp_doc = tp_doc;
}
}
if (type->tp_dealloc == NULL) {
/* It's a heap type, so needs the heap types' dealloc.
subtype_dealloc will call the base type's tp_dealloc, if
necessary. */
type->tp_dealloc = subtype_dealloc;
}
if (PyType_Ready(type) < 0)
goto fail;
if (type->tp_dictoffset) {
res->ht_cached_keys = _PyDict_NewKeysForClass();
}
/* Set type.__module__ */
s = strrchr(spec->name, '.');
if (s != NULL) {
int err;
modname = PyUnicode_FromStringAndSize(
spec->name, (Py_ssize_t)(s - spec->name));
if (modname == NULL) {
goto fail;
}
err = _PyDict_SetItemId(type->tp_dict, &PyId___module__, modname);
Py_DECREF(modname);
if (err != 0)
goto fail;
} else {
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"builtin type %.200s has no __module__ attribute",
spec->name))
goto fail;
}
return (PyObject*)res;
fail:
Py_DECREF(res);
return NULL;
}
PyObject *
PyType_FromSpec(PyType_Spec *spec)
{
return PyType_FromSpecWithBases(spec, NULL);
}
void *
PyType_GetSlot(PyTypeObject *type, int slot)
{
if (!PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) || slot < 0) {
PyErr_BadInternalCall();
return NULL;
}
if ((size_t)slot >= Py_ARRAY_LENGTH(slotoffsets)) {
/* Extension module requesting slot from a future version */
return NULL;
}
return *(void**)(((char*)type) + slotoffsets[slot]);
}
/* Internal API to look for a name through the MRO, bypassing the method cache.
This returns a borrowed reference, and might set an exception.
'error' is set to: -1: error with exception; 1: error without exception; 0: ok */
static PyObject *
find_name_in_mro(PyTypeObject *type, PyObject *name, int *error)
{
Py_ssize_t i, n;
PyObject *mro, *res, *base, *dict;
Py_hash_t hash;
if (!PyUnicode_CheckExact(name) ||
(hash = ((PyASCIIObject *) name)->hash) == -1)
{
hash = PyObject_Hash(name);
if (hash == -1) {
*error = -1;
return NULL;
}
}
/* Look in tp_dict of types in MRO */
mro = type->tp_mro;
if (mro == NULL) {
if ((type->tp_flags & Py_TPFLAGS_READYING) == 0) {
if (PyType_Ready(type) < 0) {
*error = -1;
return NULL;
}
mro = type->tp_mro;
}
if (mro == NULL) {
*error = 1;
return NULL;
}
}
res = NULL;
/* Keep a strong reference to mro because type->tp_mro can be replaced
during dict lookup, e.g. when comparing to non-string keys. */
Py_INCREF(mro);
assert(PyTuple_Check(mro));
n = PyTuple_GET_SIZE(mro);
for (i = 0; i < n; i++) {
base = PyTuple_GET_ITEM(mro, i);
assert(PyType_Check(base));
dict = ((PyTypeObject *)base)->tp_dict;
assert(dict && PyDict_Check(dict));
res = _PyDict_GetItem_KnownHash(dict, name, hash);
if (res != NULL)
break;
if (PyErr_Occurred()) {
*error = -1;
goto done;
}
}
*error = 0;
done:
Py_DECREF(mro);
return res;
}
/* Internal API to look for a name through the MRO.
This returns a borrowed reference, and doesn't set an exception! */
PyObject *
_PyType_Lookup(PyTypeObject *type, PyObject *name)
{
PyObject *res;
int error;
unsigned int h;
if (MCACHE_CACHEABLE_NAME(name) &&
PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) {
/* fast path */
h = MCACHE_HASH_METHOD(type, name);
if (method_cache[h].version == type->tp_version_tag &&
method_cache[h].name == name) {
#if MCACHE_STATS
method_cache_hits++;
#endif
return method_cache[h].value;
}
}
/* We may end up clearing live exceptions below, so make sure it's ours. */
assert(!PyErr_Occurred());
res = find_name_in_mro(type, name, &error);
/* Only put NULL results into cache if there was no error. */
if (error) {
/* It's not ideal to clear the error condition,
but this function is documented as not setting
an exception, and I don't want to change that.
E.g., when PyType_Ready() can't proceed, it won't
set the "ready" flag, so future attempts to ready
the same type will call it again -- hopefully
in a context that propagates the exception out.
*/
if (error == -1) {
PyErr_Clear();
}
return NULL;
}
if (MCACHE_CACHEABLE_NAME(name) && assign_version_tag(type)) {
h = MCACHE_HASH_METHOD(type, name);
method_cache[h].version = type->tp_version_tag;
method_cache[h].value = res; /* borrowed */
Py_INCREF(name);
assert(((PyASCIIObject *)(name))->hash != -1);
#if MCACHE_STATS
if (method_cache[h].name != Py_None && method_cache[h].name != name)
method_cache_collisions++;
else
method_cache_misses++;
#endif
Py_SETREF(method_cache[h].name, name);
}
return res;
}
PyObject *
_PyType_LookupId(PyTypeObject *type, struct _Py_Identifier *name)
{
PyObject *oname;
oname = _PyUnicode_FromId(name); /* borrowed */
if (oname == NULL)
return NULL;
return _PyType_Lookup(type, oname);
}
/* This is similar to PyObject_GenericGetAttr(),
but uses _PyType_Lookup() instead of just looking in type->tp_dict. */
static PyObject *
type_getattro(PyTypeObject *type, PyObject *name)
{
PyTypeObject *metatype = Py_TYPE(type);
PyObject *meta_attribute, *attribute;
descrgetfunc meta_get;
if (!PyUnicode_Check(name)) {
PyErr_Format(PyExc_TypeError,
"attribute name must be string, not '%.200s'",
name->ob_type->tp_name);
return NULL;
}
/* Initialize this type (we'll assume the metatype is initialized) */
if (type->tp_dict == NULL) {
if (PyType_Ready(type) < 0)
return NULL;
}
/* No readable descriptor found yet */
meta_get = NULL;
/* Look for the attribute in the metatype */
meta_attribute = _PyType_Lookup(metatype, name);
if (meta_attribute != NULL) {
meta_get = Py_TYPE(meta_attribute)->tp_descr_get;
if (meta_get != NULL && PyDescr_IsData(meta_attribute)) {
/* Data descriptors implement tp_descr_set to intercept
* writes. Assume the attribute is not overridden in
* type's tp_dict (and bases): call the descriptor now.
*/
return meta_get(meta_attribute, (PyObject *)type,
(PyObject *)metatype);
}
Py_INCREF(meta_attribute);
}
/* No data descriptor found on metatype. Look in tp_dict of this
* type and its bases */
attribute = _PyType_Lookup(type, name);
if (attribute != NULL) {
/* Implement descriptor functionality, if any */
descrgetfunc local_get = Py_TYPE(attribute)->tp_descr_get;
Py_XDECREF(meta_attribute);
if (local_get != NULL) {
/* NULL 2nd argument indicates the descriptor was
* found on the target object itself (or a base) */
return local_get(attribute, (PyObject *)NULL,
(PyObject *)type);
}
Py_INCREF(attribute);
return attribute;
}
/* No attribute found in local __dict__ (or bases): use the
* descriptor from the metatype, if any */
if (meta_get != NULL) {
PyObject *res;
res = meta_get(meta_attribute, (PyObject *)type,
(PyObject *)metatype);
Py_DECREF(meta_attribute);
return res;
}
/* If an ordinary attribute was found on the metatype, return it now */
if (meta_attribute != NULL) {
return meta_attribute;
}
/* Give up */
PyErr_Format(PyExc_AttributeError,
"type object '%.50s' has no attribute '%U'",
type->tp_name, name);
return NULL;
}
static int
type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
{
int res;
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
PyErr_Format(
PyExc_TypeError,
"can't set attributes of built-in/extension type '%s'",
type->tp_name);
return -1;
}
if (PyUnicode_Check(name)) {
if (PyUnicode_CheckExact(name)) {
if (PyUnicode_READY(name) == -1)
return -1;
Py_INCREF(name);
}
else {
name = _PyUnicode_Copy(name);
if (name == NULL)
return -1;
}
PyUnicode_InternInPlace(&name);
if (!PyUnicode_CHECK_INTERNED(name)) {
PyErr_SetString(PyExc_MemoryError,
"Out of memory interning an attribute name");
Py_DECREF(name);
return -1;
}
}
else {
/* Will fail in _PyObject_GenericSetAttrWithDict. */
Py_INCREF(name);
}
res = _PyObject_GenericSetAttrWithDict((PyObject *)type, name, value, NULL);
if (res == 0) {
res = update_slot(type, name);
assert(_PyType_CheckConsistency(type));
}
Py_DECREF(name);
return res;
}
extern void
_PyDictKeys_DecRef(PyDictKeysObject *keys);
static void
type_dealloc(PyTypeObject *type)
{
PyHeapTypeObject *et;
PyObject *tp, *val, *tb;
/* Assert this is a heap-allocated type object */
assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
_PyObject_GC_UNTRACK(type);
PyErr_Fetch(&tp, &val, &tb);
remove_all_subclasses(type, type->tp_bases);
PyErr_Restore(tp, val, tb);
PyObject_ClearWeakRefs((PyObject *)type);
et = (PyHeapTypeObject *)type;
Py_XDECREF(type->tp_base);
Py_XDECREF(type->tp_dict);
Py_XDECREF(type->tp_bases);
Py_XDECREF(type->tp_mro);
Py_XDECREF(type->tp_cache);
Py_XDECREF(type->tp_subclasses);
/* A type's tp_doc is heap allocated, unlike the tp_doc slots
* of most other objects. It's okay to cast it to char *.
*/
PyObject_Free((char *)type->tp_doc);
Py_XDECREF(et->ht_name);
Py_XDECREF(et->ht_qualname);
Py_XDECREF(et->ht_slots);
if (et->ht_cached_keys)
_PyDictKeys_DecRef(et->ht_cached_keys);
Py_TYPE(type)->tp_free((PyObject *)type);
}
/*[clinic input]
type.__subclasses__
Return a list of immediate subclasses.
[clinic start generated code]*/
static PyObject *
type___subclasses___impl(PyTypeObject *self)
/*[clinic end generated code: output=eb5eb54485942819 input=5af66132436f9a7b]*/
{
PyObject *list, *raw, *ref;
Py_ssize_t i;
list = PyList_New(0);
if (list == NULL)
return NULL;
raw = self->tp_subclasses;
if (raw == NULL)
return list;
assert(PyDict_CheckExact(raw));
i = 0;
while (PyDict_Next(raw, &i, NULL, &ref)) {
assert(PyWeakref_CheckRef(ref));
ref = PyWeakref_GET_OBJECT(ref);
if (ref != Py_None) {
if (PyList_Append(list, ref) < 0) {
Py_DECREF(list);
return NULL;
}
}
}
return list;
}
static PyObject *
type_prepare(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
PyObject *kwnames)
{
return PyDict_New();
}
/*
Merge the __dict__ of aclass into dict, and recursively also all
the __dict__s of aclass's base classes. The order of merging isn't
defined, as it's expected that only the final set of dict keys is
interesting.
Return 0 on success, -1 on error.
*/
static int
merge_class_dict(PyObject *dict, PyObject *aclass)
{
PyObject *classdict;
PyObject *bases;
_Py_IDENTIFIER(__bases__);
assert(PyDict_Check(dict));
assert(aclass);
/* Merge in the type's dict (if any). */
classdict = _PyObject_GetAttrId(aclass, &PyId___dict__);
if (classdict == NULL)
PyErr_Clear();
else {
int status = PyDict_Update(dict, classdict);
Py_DECREF(classdict);
if (status < 0)
return -1;
}
/* Recursively merge in the base types' (if any) dicts. */
bases = _PyObject_GetAttrId(aclass, &PyId___bases__);
if (bases == NULL)
PyErr_Clear();
else {
/* We have no guarantee that bases is a real tuple */
Py_ssize_t i, n;
n = PySequence_Size(bases); /* This better be right */
if (n < 0)
PyErr_Clear();
else {
for (i = 0; i < n; i++) {
int status;
PyObject *base = PySequence_GetItem(bases, i);
if (base == NULL) {
Py_DECREF(bases);
return -1;
}
status = merge_class_dict(dict, base);
Py_DECREF(base);
if (status < 0) {
Py_DECREF(bases);
return -1;
}
}
}
Py_DECREF(bases);
}
return 0;
}
/* __dir__ for type objects: returns __dict__ and __bases__.
We deliberately don't suck up its __class__, as methods belonging to the
metaclass would probably be more confusing than helpful.
*/
/*[clinic input]
type.__dir__
Specialized __dir__ implementation for types.
[clinic start generated code]*/
static PyObject *
type___dir___impl(PyTypeObject *self)
/*[clinic end generated code: output=69d02fe92c0f15fa input=7733befbec645968]*/
{
PyObject *result = NULL;
PyObject *dict = PyDict_New();
if (dict != NULL && merge_class_dict(dict, (PyObject *)self) == 0)
result = PyDict_Keys(dict);
Py_XDECREF(dict);
return result;
}
/*[clinic input]
type.__sizeof__
Return memory consumption of the type object.
[clinic start generated code]*/
static PyObject *
type___sizeof___impl(PyTypeObject *self)
/*[clinic end generated code: output=766f4f16cd3b1854 input=99398f24b9cf45d6]*/
{
Py_ssize_t size;
if (self->tp_flags & Py_TPFLAGS_HEAPTYPE) {
PyHeapTypeObject* et = (PyHeapTypeObject*)self;
size = sizeof(PyHeapTypeObject);
if (et->ht_cached_keys)
size += _PyDict_KeysSize(et->ht_cached_keys);
}
else
size = sizeof(PyTypeObject);
return PyLong_FromSsize_t(size);
}
static PyMethodDef type_methods[] = {
TYPE_MRO_METHODDEF
TYPE___SUBCLASSES___METHODDEF
{"__prepare__", (PyCFunction)type_prepare,
METH_FASTCALL | METH_KEYWORDS | METH_CLASS,
PyDoc_STR("__prepare__() -> dict\n"
"used to create the namespace for the class statement")},
TYPE___INSTANCECHECK___METHODDEF
TYPE___SUBCLASSCHECK___METHODDEF
TYPE___DIR___METHODDEF
TYPE___SIZEOF___METHODDEF
{0}
};
PyDoc_STRVAR(type_doc,
/* this text signature cannot be accurate yet. will fix. --larry */
"type(object_or_name, bases, dict)\n"
"type(object) -> the object's type\n"
"type(name, bases, dict) -> a new type");
static int
type_traverse(PyTypeObject *type, visitproc visit, void *arg)
{
/* Because of type_is_gc(), the collector only calls this
for heaptypes. */
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
char msg[200];
sprintf(msg, "type_traverse() called for non-heap type '%.100s'",
type->tp_name);
Py_FatalError(msg);
}
Py_VISIT(type->tp_dict);
Py_VISIT(type->tp_cache);
Py_VISIT(type->tp_mro);
Py_VISIT(type->tp_bases);
Py_VISIT(type->tp_base);
/* There's no need to visit type->tp_subclasses or
((PyHeapTypeObject *)type)->ht_slots, because they can't be involved
in cycles; tp_subclasses is a list of weak references,
and slots is a tuple of strings. */
return 0;
}
static int
type_clear(PyTypeObject *type)
{
PyDictKeysObject *cached_keys;
/* Because of type_is_gc(), the collector only calls this
for heaptypes. */
assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
/* We need to invalidate the method cache carefully before clearing
the dict, so that other objects caught in a reference cycle
don't start calling destroyed methods.
Otherwise, the only field we need to clear is tp_mro, which is
part of a hard cycle (its first element is the class itself) that
won't be broken otherwise (it's a tuple and tuples don't have a
tp_clear handler). None of the other fields need to be
cleared, and here's why:
tp_cache:
Not used; if it were, it would be a dict.
tp_bases, tp_base:
If these are involved in a cycle, there must be at least
one other, mutable object in the cycle, e.g. a base
class's dict; the cycle will be broken that way.
tp_subclasses:
A dict of weak references can't be part of a cycle; and
dicts have their own tp_clear.
slots (in PyHeapTypeObject):
A tuple of strings can't be part of a cycle.
*/
PyType_Modified(type);
cached_keys = ((PyHeapTypeObject *)type)->ht_cached_keys;
if (cached_keys != NULL) {
((PyHeapTypeObject *)type)->ht_cached_keys = NULL;
_PyDictKeys_DecRef(cached_keys);
}
if (type->tp_dict)
PyDict_Clear(type->tp_dict);
Py_CLEAR(type->tp_mro);
return 0;
}
static int
type_is_gc(PyTypeObject *type)
{
return type->tp_flags & Py_TPFLAGS_HEAPTYPE;
}
PyTypeObject PyType_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"type", /* tp_name */
sizeof(PyHeapTypeObject), /* tp_basicsize */
sizeof(PyMemberDef), /* tp_itemsize */
(destructor)type_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc)type_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
(ternaryfunc)type_call, /* tp_call */
0, /* tp_str */
(getattrofunc)type_getattro, /* tp_getattro */
(setattrofunc)type_setattro, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */
type_doc, /* tp_doc */
(traverseproc)type_traverse, /* tp_traverse */
(inquiry)type_clear, /* tp_clear */
0, /* tp_richcompare */
offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
type_methods, /* tp_methods */
type_members, /* tp_members */
type_getsets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */
type_init, /* tp_init */
0, /* tp_alloc */
type_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
(inquiry)type_is_gc, /* tp_is_gc */
};
/* The base type of all types (eventually)... except itself. */
/* You may wonder why object.__new__() only complains about arguments
when object.__init__() is not overridden, and vice versa.
Consider the use cases:
1. When neither is overridden, we want to hear complaints about
excess (i.e., any) arguments, since their presence could
indicate there's a bug.
2. When defining an Immutable type, we are likely to override only
__new__(), since __init__() is called too late to initialize an
Immutable object. Since __new__() defines the signature for the
type, it would be a pain to have to override __init__() just to
stop it from complaining about excess arguments.
3. When defining a Mutable type, we are likely to override only
__init__(). So here the converse reasoning applies: we don't
want to have to override __new__() just to stop it from
complaining.
4. When __init__() is overridden, and the subclass __init__() calls
object.__init__(), the latter should complain about excess
arguments; ditto for __new__().
Use cases 2 and 3 make it unattractive to unconditionally check for
excess arguments. The best solution that addresses all four use
cases is as follows: __init__() complains about excess arguments
unless __new__() is overridden and __init__() is not overridden
(IOW, if __init__() is overridden or __new__() is not overridden);
symmetrically, __new__() complains about excess arguments unless
__init__() is overridden and __new__() is not overridden
(IOW, if __new__() is overridden or __init__() is not overridden).
However, for backwards compatibility, this breaks too much code.
Therefore, in 2.6, we'll *warn* about excess arguments when both
methods are overridden; for all other cases we'll use the above
rules.
*/
/* Forward */
static PyObject *
object_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static int
excess_args(PyObject *args, PyObject *kwds)
{
return PyTuple_GET_SIZE(args) ||
(kwds && PyDict_Check(kwds) && PyDict_GET_SIZE(kwds));
}
static int
object_init(PyObject *self, PyObject *args, PyObject *kwds)
{
PyTypeObject *type = Py_TYPE(self);
if (excess_args(args, kwds)) {
if (type->tp_init != object_init) {
PyErr_SetString(PyExc_TypeError, "object.__init__() takes no arguments");
return -1;
}
if (type->tp_new == object_new) {
PyErr_Format(PyExc_TypeError, "%.200s().__init__() takes no arguments",
type->tp_name);
return -1;
}
}
return 0;
}
static PyObject *
object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
if (excess_args(args, kwds)) {
if (type->tp_new != object_new) {
PyErr_SetString(PyExc_TypeError, "object.__new__() takes no arguments");
return NULL;
}
if (type->tp_init == object_init) {
PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments",
type->tp_name);
return NULL;
}
}
if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) {
PyObject *abstract_methods = NULL;
PyObject *builtins;
PyObject *sorted;
PyObject *sorted_methods = NULL;
PyObject *joined = NULL;
PyObject *comma;
_Py_static_string(comma_id, ", ");
_Py_IDENTIFIER(sorted);
/* Compute ", ".join(sorted(type.__abstractmethods__))
into joined. */
abstract_methods = type_abstractmethods(type, NULL);
if (abstract_methods == NULL)
goto error;
builtins = PyEval_GetBuiltins();
if (builtins == NULL)
goto error;
sorted = _PyDict_GetItemId(builtins, &PyId_sorted);
if (sorted == NULL)
goto error;
sorted_methods = PyObject_CallFunctionObjArgs(sorted,
abstract_methods,
NULL);
if (sorted_methods == NULL)
goto error;
comma = _PyUnicode_FromId(&comma_id);
if (comma == NULL)
goto error;
joined = PyUnicode_Join(comma, sorted_methods);
if (joined == NULL)
goto error;
PyErr_Format(PyExc_TypeError,
"Can't instantiate abstract class %s "
"with abstract methods %U",
type->tp_name,
joined);