Recorded merge of revisions 68051 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r68051 | nick.coghlan | 2008-12-30 11:18:48 +1000 (Tue, 30 Dec 2008) | 1 line

  Issue #4701: implicitly call PyType_Ready from PyObject_Hash
........
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index c7c6393..a1b367a 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -175,6 +175,105 @@
 }
 
 
+/* Issue #4701: Check that PyObject_Hash implicitly calls
+ *   PyType_Ready if it hasn't already been called
+ */
+static PyTypeObject _HashInheritanceTester_Type = {
+	PyVarObject_HEAD_INIT(&PyType_Type, 0)
+	"hashinheritancetester",	/* Name of this type */
+	sizeof(PyObject),	/* Basic object size */
+	0,			/* Item size for varobject */
+	(destructor)PyObject_Del, /* tp_dealloc */
+	0,			/* tp_print */
+	0,			/* tp_getattr */
+	0,			/* tp_setattr */
+	0,			/* tp_compare */
+	0,			/* tp_repr */
+	0,			/* tp_as_number */
+	0,			/* tp_as_sequence */
+	0,			/* tp_as_mapping */
+	0,			/* tp_hash */
+	0,			/* tp_call */
+	0,			/* tp_str */
+	PyObject_GenericGetAttr,  /* tp_getattro */
+	0,			/* tp_setattro */
+	0,			/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT,	/* tp_flags */
+	0,			/* tp_doc */
+	0,			/* tp_traverse */
+	0,			/* tp_clear */
+	0,			/* tp_richcompare */
+	0,			/* tp_weaklistoffset */
+	0,			/* tp_iter */
+	0,			/* tp_iternext */
+	0,			/* tp_methods */
+	0,			/* tp_members */
+	0,			/* tp_getset */
+	0,			/* tp_base */
+	0,			/* tp_dict */
+	0,			/* tp_descr_get */
+	0,			/* tp_descr_set */
+	0,			/* tp_dictoffset */
+	0,			/* tp_init */
+	0,			/* tp_alloc */
+	PyType_GenericNew,		/* tp_new */
+};
+
+static PyObject*
+test_lazy_hash_inheritance(PyObject* self)
+{
+	PyTypeObject *type;
+	PyObject *obj;
+	long hash;
+
+	type = &_HashInheritanceTester_Type;
+	obj = PyObject_New(PyObject, type);
+	if (obj == NULL) {
+		PyErr_Clear();
+		PyErr_SetString(
+			TestError,
+			"test_lazy_hash_inheritance: failed to create object");
+		return NULL;
+	}
+
+	if (type->tp_dict != NULL) {
+		PyErr_SetString(
+			TestError,
+			"test_lazy_hash_inheritance: type initialised too soon");
+		Py_DECREF(obj);
+		return NULL;
+	}
+
+	hash = PyObject_Hash(obj);
+	if ((hash == -1) && PyErr_Occurred()) {
+		PyErr_Clear();
+		PyErr_SetString(
+			TestError,
+			"test_lazy_hash_inheritance: could not hash object");
+		Py_DECREF(obj);
+		return NULL;
+	}
+
+	if (type->tp_dict == NULL) {
+		PyErr_SetString(
+			TestError,
+			"test_lazy_hash_inheritance: type not initialised by hash()");
+		Py_DECREF(obj);
+		return NULL;
+	}
+
+	if (type->tp_hash != PyType_Type.tp_hash) {
+		PyErr_SetString(
+			TestError,
+			"test_lazy_hash_inheritance: unexpected hash function");
+		Py_DECREF(obj);
+		return NULL;
+	}
+
+	Py_RETURN_NONE;
+}
+
+
 /* Tests of PyLong_{As, From}{Unsigned,}Long(), and (#ifdef HAVE_LONG_LONG)
    PyLong_{As, From}{Unsigned,}LongLong().
 
@@ -1036,6 +1135,7 @@
 	{"test_config",		(PyCFunction)test_config,	 METH_NOARGS},
 	{"test_list_api",	(PyCFunction)test_list_api,	 METH_NOARGS},
 	{"test_dict_iteration",	(PyCFunction)test_dict_iteration,METH_NOARGS},
+	{"test_lazy_hash_inheritance",	(PyCFunction)test_lazy_hash_inheritance,METH_NOARGS},
 	{"test_long_api",	(PyCFunction)test_long_api,	 METH_NOARGS},
 	{"test_long_numbits",	(PyCFunction)test_long_numbits,	 METH_NOARGS},
 	{"test_k_code",		(PyCFunction)test_k_code,	 METH_NOARGS},