]> granicus.if.org Git - python/commitdiff
Add weakref support to array.array and file objects.
authorRaymond Hettinger <python@rcn.com>
Mon, 31 May 2004 00:35:52 +0000 (00:35 +0000)
committerRaymond Hettinger <python@rcn.com>
Mon, 31 May 2004 00:35:52 +0000 (00:35 +0000)
Include/fileobject.h
Lib/test/test_array.py
Lib/test/test_file.py
Modules/arraymodule.c
Objects/fileobject.c

index 35b2c3dffcc638c086f76933c07a767720ff72e2..ebbb521d17be986a7e049c5195f2e26270209f82 100644 (file)
@@ -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;
index 0f3e07f17298fd978fde2f2b7e1175da87e858e9..d03618d04fa79c86385b9784870ade215a6e94f4 100755 (executable)
@@ -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):
index 22db9a2920489506ff8128c82a94842715fb664b..ddd0471e1ef6add07d9ac004344a0471fde53995 100644 (file)
@@ -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
index ed2ea9d1688183427005a81b87c0f3ab70a2c5a2..ab904bdce5ac9e837155526404f932d6444d8de9 100644 (file)
@@ -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 <stddef.h>
@@ -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 */
index 6b7e01b91c8583c6946c888e83d802cd40c909e1..3ff3ccad91ccba7eb5c0c35f3ff6e8b0dfebc5c1 100644 (file)
@@ -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 */