From cb87bc8e7ee3a2ffd83dd1b12fcfa1c01aa740aa Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 31 May 2004 00:35:52 +0000 Subject: Add weakref support to array.array and file objects. --- Include/fileobject.h | 1 + Lib/test/test_array.py | 10 ++++++++++ Lib/test/test_file.py | 15 +++++++++++++++ Modules/arraymodule.c | 9 +++++++-- Objects/fileobject.c | 7 +++++-- 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Include/fileobject.h b/Include/fileobject.h index 35b2c3df..ebbb521 100644 --- a/Include/fileobject.h +++ b/Include/fileobject.h @@ -24,6 +24,7 @@ typedef struct { int f_newlinetypes; /* Types of newlines seen */ int f_skipnextlf; /* Skip next \n */ PyObject *f_encoding; + PyObject *weakreflist; /* List of weak references */ } PyFileObject; PyAPI_DATA(PyTypeObject) PyFile_Type; diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py index 0f3e07f..d03618d 100755 --- a/Lib/test/test_array.py +++ b/Lib/test/test_array.py @@ -5,6 +5,7 @@ import unittest from test import test_support +from weakref import proxy import array, cStringIO, math tests = [] # list to accumulate all tests @@ -614,6 +615,13 @@ class BaseTest(unittest.TestCase): b = buffer(a) self.assertEqual(b[0], a.tostring()[0]) + def test_weakref(self): + s = array.array(self.typecode, self.example) + p = proxy(s) + self.assertEqual(p.tostring(), s.tostring()) + s = None + self.assertRaises(ReferenceError, len, p) + def test_bug_782369(self): import sys if hasattr(sys, "getrefcount"): @@ -624,6 +632,8 @@ class BaseTest(unittest.TestCase): b = array.array('B', range(64)) self.assertEqual(rc, sys.getrefcount(10)) + + class StringTest(BaseTest): def test_setitem(self): diff --git a/Lib/test/test_file.py b/Lib/test/test_file.py index 22db9a2..ddd0471 100644 --- a/Lib/test/test_file.py +++ b/Lib/test/test_file.py @@ -1,10 +1,25 @@ import sys import os from array import array +from weakref import proxy from test.test_support import verify, TESTFN, TestFailed from UserList import UserList +# verify weak references +f = file(TESTFN, 'w') +p = proxy(f) +p.write('teststring') +verify(f.tell(), p.tell()) +f.close() +f = None +try: + p.tell() +except ReferenceError: + pass +else: + raise TestFailed('file proxy still exists when the file is gone') + # verify expected attributes exist f = file(TESTFN, 'w') softspace = f.softspace diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index ed2ea9d..ab904bd 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -4,6 +4,7 @@ The item type is restricted to simple C types like int or float */ #include "Python.h" +#include "structmember.h" #ifdef STDC_HEADERS #include @@ -32,6 +33,7 @@ typedef struct arrayobject { char *ob_item; int allocated; struct arraydescr *ob_descr; + PyObject *weakreflist; /* List of weak references */ } arrayobject; static PyTypeObject Arraytype; @@ -442,6 +444,7 @@ newarrayobject(PyTypeObject *type, int size, struct arraydescr *descr) } op->ob_descr = descr; op->allocated = size; + op->weakreflist = NULL; return (PyObject *) op; } @@ -490,6 +493,8 @@ ins1(arrayobject *self, int where, PyObject *v) static void array_dealloc(arrayobject *op) { + if (op->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) op); if (op->ob_item != NULL) PyMem_DEL(op->ob_item); op->ob_type->tp_free((PyObject *)op); @@ -1950,12 +1955,12 @@ static PyTypeObject Arraytype = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ &array_as_buffer, /* tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ arraytype_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ array_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(arrayobject, weakreflist), /* tp_weaklistoffset */ (getiterfunc)array_iter, /* tp_iter */ 0, /* tp_iternext */ array_methods, /* tp_methods */ diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 6b7e01b..3ff3cca 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -307,6 +307,8 @@ static void drop_readahead(PyFileObject *); static void file_dealloc(PyFileObject *f) { + if (f->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) f); if (f->f_fp != NULL && f->f_close != NULL) { Py_BEGIN_ALLOW_THREADS (*f->f_close)(f->f_fp); @@ -1821,6 +1823,7 @@ file_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ((PyFileObject *)self)->f_mode = not_yet_string; Py_INCREF(Py_None); ((PyFileObject *)self)->f_encoding = Py_None; + ((PyFileObject *)self)->weakreflist = NULL; } return self; } @@ -1942,12 +1945,12 @@ PyTypeObject PyFile_Type = { /* softspace is writable: we must supply tp_setattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ file_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(PyFileObject, weakreflist), /* tp_weaklistoffset */ (getiterfunc)file_getiter, /* tp_iter */ (iternextfunc)file_iternext, /* tp_iternext */ file_methods, /* tp_methods */ -- cgit v0.12