Author: brett.cannon Date: Sat Aug 19 01:55:41 2006 New Revision: 51392 Added: python/branches/bcannon-objcap/Lib/test/test_objcap.py (contents, props changed) python/branches/bcannon-objcap/Modules/objcapmodule.c (contents, props changed) Modified: python/branches/bcannon-objcap/Lib/test/test_descr.py python/branches/bcannon-objcap/Objects/typeobject.c python/branches/bcannon-objcap/setup.py Log: Introduce objcap module to store removed abilities. Begin with moving object.__subclasses__(). Modified: python/branches/bcannon-objcap/Lib/test/test_descr.py ============================================================================== --- python/branches/bcannon-objcap/Lib/test/test_descr.py (original) +++ python/branches/bcannon-objcap/Lib/test/test_descr.py Sat Aug 19 01:55:41 2006 @@ -3595,7 +3595,6 @@ vereq(e.meth(), 1) vereq(d.a, 2) vereq(e.a, 2) - vereq(C2.__subclasses__(), [D]) # stuff that shouldn't: class L(list): Added: python/branches/bcannon-objcap/Lib/test/test_objcap.py ============================================================================== --- (empty file) +++ python/branches/bcannon-objcap/Lib/test/test_objcap.py Sat Aug 19 01:55:41 2006 @@ -0,0 +1,33 @@ +import objcap +import unittest +from test import test_support + +class TestClass(object): + pass + +class ObjectSubclasses(unittest.TestCase): + + """Test object.__subclasses__() move.""" + + def test_removal(self): + # Make sure __subclasses__ is no longer on 'object'. + self.failUnless(not hasattr(object, '__subclasses__')) + + def test_argument(self): + # Make sure only proper arguments are accepted. + self.failUnlessRaises(TypeError, objcap.subclasses, object()) + + def test_result(self): + # Check return values. + self.failUnlessEqual(objcap.subclasses(TestClass), []) + self.failUnless(objcap.subclasses(object)) + + +def test_main(): + test_support.run_unittest( + ObjectSubclasses + ) + + +if __name__ == '__main__': + test_main() Added: python/branches/bcannon-objcap/Modules/objcapmodule.c ============================================================================== --- (empty file) +++ python/branches/bcannon-objcap/Modules/objcapmodule.c Sat Aug 19 01:55:41 2006 @@ -0,0 +1,70 @@ +/* + Store changes done to implement object-capabilities. +*/ + +#include "Python.h" + +PyDoc_STRVAR(module_doc, +"XXX Placeholder for code removed for object-capabilities reasons.\n\ +"); + + +/* + Return the subclasses of a class. + + Moved so that object does not expose *all* new-style classes to *every* + interpreter. Otherwise would invert direction of knowledge about + inheritance tree. +*/ +static PyObject * +object_subclasses(PyObject* self, PyTypeObject *type) +{ + PyObject *list, *raw, *ref; + Py_ssize_t i, n; + + if (!PyType_Check(type)) { + PyErr_SetString(PyExc_TypeError, + "argument must be a type or subclass thereof"); + return NULL; + } + list = PyList_New(0); + if (list == NULL) + return NULL; + raw = type->tp_subclasses; + if (raw == NULL) + return list; + assert(PyList_Check(raw)); + n = PyList_GET_SIZE(raw); + for (i = 0; i < n; i++) { + ref = PyList_GET_ITEM(raw, i); + 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; +} + +PyDoc_STRVAR(object_subclass_doc, +"subclasses(object) -> return a list of subclasses.\n\ +Originally object.__subclasses__()."); + + +static PyMethodDef module_methods[] = { + {"subclasses", (PyCFunction)object_subclasses, METH_O, "XXX"}, + {NULL, NULL} +}; + +PyMODINIT_FUNC +initobjcap(void) +{ + PyObject *module; + + module = Py_InitModule3("objcap", module_methods, module_doc); + if (!module) + return; +} Modified: python/branches/bcannon-objcap/Objects/typeobject.c ============================================================================== --- python/branches/bcannon-objcap/Objects/typeobject.c (original) +++ python/branches/bcannon-objcap/Objects/typeobject.c Sat Aug 19 01:55:41 2006 @@ -2151,39 +2151,10 @@ type->ob_type->tp_free((PyObject *)type); } -static PyObject * -type_subclasses(PyTypeObject *type, PyObject *args_ignored) -{ - PyObject *list, *raw, *ref; - Py_ssize_t i, n; - - list = PyList_New(0); - if (list == NULL) - return NULL; - raw = type->tp_subclasses; - if (raw == NULL) - return list; - assert(PyList_Check(raw)); - n = PyList_GET_SIZE(raw); - for (i = 0; i < n; i++) { - ref = PyList_GET_ITEM(raw, i); - 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 PyMethodDef type_methods[] = { {"mro", (PyCFunction)mro_external, METH_NOARGS, PyDoc_STR("mro() -> list\nreturn a type's method resolution order")}, - {"__subclasses__", (PyCFunction)type_subclasses, METH_NOARGS, - PyDoc_STR("__subclasses__() -> list of immediate subclasses")}, {0} }; Modified: python/branches/bcannon-objcap/setup.py ============================================================================== --- python/branches/bcannon-objcap/setup.py (original) +++ python/branches/bcannon-objcap/setup.py Sat Aug 19 01:55:41 2006 @@ -349,6 +349,8 @@ # Some modules that are normally always on: exts.append( Extension('_weakref', ['_weakref.c']) ) + exts.append(Extension('objcap', ['objcapmodule.c'])) + # array objects exts.append( Extension('array', ['arraymodule.c']) ) # complex math library functions