diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index bac52be23d5..064c669d7fe 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -196,6 +196,9 @@ class AST_Tests(unittest.TestCase): def test_AST_objects(self): x = ast.AST() self.assertEqual(x._fields, ()) + x.foobar = 42 + self.assertEqual(x.foobar, 42) + self.assertEqual(x.__dict__["foobar"], 42) with self.assertRaises(AttributeError): x.vararg diff --git a/Misc/NEWS b/Misc/NEWS index 7055bd3e29e..cd522dc6e5f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ What's New in Python 3.3.0 Alpha 2? Core and Builtins ----------------- +- Give the ast.AST class a __dict__. + - Issue #1469629: Allow cycles through an object's __dict__ slot to be collected. (For example if ``x.__dict__ is x``). diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 07c06dea725..2f269f47140 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -603,6 +603,11 @@ class PyTypesVisitor(PickleVisitor): def visitModule(self, mod): self.emit(""" +typedef struct { + PyObject_HEAD; + PyObject *dict; +} AST_object; + static int ast_type_init(PyObject *self, PyObject *args, PyObject *kw) { @@ -681,10 +686,15 @@ static PyMethodDef ast_type_methods[] = { {NULL} }; +static PyGetSetDef ast_type_getsets[] = { + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, + {NULL} +}; + static PyTypeObject AST_type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "_ast.AST", - sizeof(PyObject), + sizeof(AST_object), 0, 0, /* tp_dealloc */ 0, /* tp_print */ @@ -711,12 +721,12 @@ static PyTypeObject AST_type = { 0, /* tp_iternext */ ast_type_methods, /* tp_methods */ 0, /* tp_members */ - 0, /* tp_getset */ + ast_type_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof(AST_object, dict),/* tp_dictoffset */ (initproc)ast_type_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ @@ -1185,6 +1195,8 @@ def main(srcfile): p = os.path.join(SRC_DIR, str(mod.name) + "-ast.c") f = open(p, "w") f.write(auto_gen_msg) + f.write('#include \n') + f.write('\n') f.write('#include "Python.h"\n') f.write('#include "%s-ast.h"\n' % mod.name) f.write('\n') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 2603b812f08..cf73beaa158 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -1,5 +1,7 @@ /* File automatically generated by Parser/asdl_c.py. */ +#include + #include "Python.h" #include "Python-ast.h" @@ -453,6 +455,11 @@ static char *withitem_fields[]={ }; +typedef struct { + PyObject_HEAD; + PyObject *dict; +} AST_object; + static int ast_type_init(PyObject *self, PyObject *args, PyObject *kw) { @@ -531,10 +538,15 @@ static PyMethodDef ast_type_methods[] = { {NULL} }; +static PyGetSetDef ast_type_getsets[] = { + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, + {NULL} +}; + static PyTypeObject AST_type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "_ast.AST", - sizeof(PyObject), + sizeof(AST_object), 0, 0, /* tp_dealloc */ 0, /* tp_print */ @@ -561,12 +573,12 @@ static PyTypeObject AST_type = { 0, /* tp_iternext */ ast_type_methods, /* tp_methods */ 0, /* tp_members */ - 0, /* tp_getset */ + ast_type_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof(AST_object, dict),/* tp_dictoffset */ (initproc)ast_type_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */