Commit cb87bc8e authored by Raymond Hettinger's avatar Raymond Hettinger

Add weakref support to array.array and file objects.

parent 691d8053
...@@ -24,6 +24,7 @@ typedef struct { ...@@ -24,6 +24,7 @@ typedef struct {
int f_newlinetypes; /* Types of newlines seen */ int f_newlinetypes; /* Types of newlines seen */
int f_skipnextlf; /* Skip next \n */ int f_skipnextlf; /* Skip next \n */
PyObject *f_encoding; PyObject *f_encoding;
PyObject *weakreflist; /* List of weak references */
} PyFileObject; } PyFileObject;
PyAPI_DATA(PyTypeObject) PyFile_Type; PyAPI_DATA(PyTypeObject) PyFile_Type;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import unittest import unittest
from test import test_support from test import test_support
from weakref import proxy
import array, cStringIO, math import array, cStringIO, math
tests = [] # list to accumulate all tests tests = [] # list to accumulate all tests
...@@ -614,6 +615,13 @@ class BaseTest(unittest.TestCase): ...@@ -614,6 +615,13 @@ class BaseTest(unittest.TestCase):
b = buffer(a) b = buffer(a)
self.assertEqual(b[0], a.tostring()[0]) 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): def test_bug_782369(self):
import sys import sys
if hasattr(sys, "getrefcount"): if hasattr(sys, "getrefcount"):
...@@ -624,6 +632,8 @@ class BaseTest(unittest.TestCase): ...@@ -624,6 +632,8 @@ class BaseTest(unittest.TestCase):
b = array.array('B', range(64)) b = array.array('B', range(64))
self.assertEqual(rc, sys.getrefcount(10)) self.assertEqual(rc, sys.getrefcount(10))
class StringTest(BaseTest): class StringTest(BaseTest):
def test_setitem(self): def test_setitem(self):
......
import sys import sys
import os import os
from array import array from array import array
from weakref import proxy
from test.test_support import verify, TESTFN, TestFailed from test.test_support import verify, TESTFN, TestFailed
from UserList import UserList 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 # verify expected attributes exist
f = file(TESTFN, 'w') f = file(TESTFN, 'w')
softspace = f.softspace softspace = f.softspace
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
The item type is restricted to simple C types like int or float */ The item type is restricted to simple C types like int or float */
#include "Python.h" #include "Python.h"
#include "structmember.h"
#ifdef STDC_HEADERS #ifdef STDC_HEADERS
#include <stddef.h> #include <stddef.h>
...@@ -32,6 +33,7 @@ typedef struct arrayobject { ...@@ -32,6 +33,7 @@ typedef struct arrayobject {
char *ob_item; char *ob_item;
int allocated; int allocated;
struct arraydescr *ob_descr; struct arraydescr *ob_descr;
PyObject *weakreflist; /* List of weak references */
} arrayobject; } arrayobject;
static PyTypeObject Arraytype; static PyTypeObject Arraytype;
...@@ -442,6 +444,7 @@ newarrayobject(PyTypeObject *type, int size, struct arraydescr *descr) ...@@ -442,6 +444,7 @@ newarrayobject(PyTypeObject *type, int size, struct arraydescr *descr)
} }
op->ob_descr = descr; op->ob_descr = descr;
op->allocated = size; op->allocated = size;
op->weakreflist = NULL;
return (PyObject *) op; return (PyObject *) op;
} }
...@@ -490,6 +493,8 @@ ins1(arrayobject *self, int where, PyObject *v) ...@@ -490,6 +493,8 @@ ins1(arrayobject *self, int where, PyObject *v)
static void static void
array_dealloc(arrayobject *op) array_dealloc(arrayobject *op)
{ {
if (op->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) op);
if (op->ob_item != NULL) if (op->ob_item != NULL)
PyMem_DEL(op->ob_item); PyMem_DEL(op->ob_item);
op->ob_type->tp_free((PyObject *)op); op->ob_type->tp_free((PyObject *)op);
...@@ -1950,12 +1955,12 @@ static PyTypeObject Arraytype = { ...@@ -1950,12 +1955,12 @@ static PyTypeObject Arraytype = {
PyObject_GenericGetAttr, /* tp_getattro */ PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
&array_as_buffer, /* tp_as_buffer*/ &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 */ arraytype_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
array_richcompare, /* tp_richcompare */ array_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */ offsetof(arrayobject, weakreflist), /* tp_weaklistoffset */
(getiterfunc)array_iter, /* tp_iter */ (getiterfunc)array_iter, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
array_methods, /* tp_methods */ array_methods, /* tp_methods */
......
...@@ -307,6 +307,8 @@ static void drop_readahead(PyFileObject *); ...@@ -307,6 +307,8 @@ static void drop_readahead(PyFileObject *);
static void static void
file_dealloc(PyFileObject *f) file_dealloc(PyFileObject *f)
{ {
if (f->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) f);
if (f->f_fp != NULL && f->f_close != NULL) { if (f->f_fp != NULL && f->f_close != NULL) {
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
(*f->f_close)(f->f_fp); (*f->f_close)(f->f_fp);
...@@ -1821,6 +1823,7 @@ file_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1821,6 +1823,7 @@ file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
((PyFileObject *)self)->f_mode = not_yet_string; ((PyFileObject *)self)->f_mode = not_yet_string;
Py_INCREF(Py_None); Py_INCREF(Py_None);
((PyFileObject *)self)->f_encoding = Py_None; ((PyFileObject *)self)->f_encoding = Py_None;
((PyFileObject *)self)->weakreflist = NULL;
} }
return self; return self;
} }
...@@ -1942,12 +1945,12 @@ PyTypeObject PyFile_Type = { ...@@ -1942,12 +1945,12 @@ PyTypeObject PyFile_Type = {
/* softspace is writable: we must supply tp_setattro */ /* softspace is writable: we must supply tp_setattro */
PyObject_GenericSetAttr, /* tp_setattro */ PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */ 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 */ file_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */
0, /* tp_weaklistoffset */ offsetof(PyFileObject, weakreflist), /* tp_weaklistoffset */
(getiterfunc)file_getiter, /* tp_iter */ (getiterfunc)file_getiter, /* tp_iter */
(iternextfunc)file_iternext, /* tp_iternext */ (iternextfunc)file_iternext, /* tp_iternext */
file_methods, /* tp_methods */ file_methods, /* tp_methods */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment