X Tutup
Skip to content

Commit cb87bc8

Browse files
committed
Add weakref support to array.array and file objects.
1 parent 691d805 commit cb87bc8

File tree

5 files changed

+38
-4
lines changed

5 files changed

+38
-4
lines changed

Include/fileobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ typedef struct {
2424
int f_newlinetypes; /* Types of newlines seen */
2525
int f_skipnextlf; /* Skip next \n */
2626
PyObject *f_encoding;
27+
PyObject *weakreflist; /* List of weak references */
2728
} PyFileObject;
2829

2930
PyAPI_DATA(PyTypeObject) PyFile_Type;

Lib/test/test_array.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import unittest
77
from test import test_support
8+
from weakref import proxy
89
import array, cStringIO, math
910

1011
tests = [] # list to accumulate all tests
@@ -614,6 +615,13 @@ def test_buffer(self):
614615
b = buffer(a)
615616
self.assertEqual(b[0], a.tostring()[0])
616617

618+
def test_weakref(self):
619+
s = array.array(self.typecode, self.example)
620+
p = proxy(s)
621+
self.assertEqual(p.tostring(), s.tostring())
622+
s = None
623+
self.assertRaises(ReferenceError, len, p)
624+
617625
def test_bug_782369(self):
618626
import sys
619627
if hasattr(sys, "getrefcount"):
@@ -624,6 +632,8 @@ def test_bug_782369(self):
624632
b = array.array('B', range(64))
625633
self.assertEqual(rc, sys.getrefcount(10))
626634

635+
636+
627637
class StringTest(BaseTest):
628638

629639
def test_setitem(self):

Lib/test/test_file.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
11
import sys
22
import os
33
from array import array
4+
from weakref import proxy
45

56
from test.test_support import verify, TESTFN, TestFailed
67
from UserList import UserList
78

9+
# verify weak references
10+
f = file(TESTFN, 'w')
11+
p = proxy(f)
12+
p.write('teststring')
13+
verify(f.tell(), p.tell())
14+
f.close()
15+
f = None
16+
try:
17+
p.tell()
18+
except ReferenceError:
19+
pass
20+
else:
21+
raise TestFailed('file proxy still exists when the file is gone')
22+
823
# verify expected attributes exist
924
f = file(TESTFN, 'w')
1025
softspace = f.softspace

Modules/arraymodule.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
The item type is restricted to simple C types like int or float */
55

66
#include "Python.h"
7+
#include "structmember.h"
78

89
#ifdef STDC_HEADERS
910
#include <stddef.h>
@@ -32,6 +33,7 @@ typedef struct arrayobject {
3233
char *ob_item;
3334
int allocated;
3435
struct arraydescr *ob_descr;
36+
PyObject *weakreflist; /* List of weak references */
3537
} arrayobject;
3638

3739
static PyTypeObject Arraytype;
@@ -442,6 +444,7 @@ newarrayobject(PyTypeObject *type, int size, struct arraydescr *descr)
442444
}
443445
op->ob_descr = descr;
444446
op->allocated = size;
447+
op->weakreflist = NULL;
445448
return (PyObject *) op;
446449
}
447450

@@ -490,6 +493,8 @@ ins1(arrayobject *self, int where, PyObject *v)
490493
static void
491494
array_dealloc(arrayobject *op)
492495
{
496+
if (op->weakreflist != NULL)
497+
PyObject_ClearWeakRefs((PyObject *) op);
493498
if (op->ob_item != NULL)
494499
PyMem_DEL(op->ob_item);
495500
op->ob_type->tp_free((PyObject *)op);
@@ -1950,12 +1955,12 @@ static PyTypeObject Arraytype = {
19501955
PyObject_GenericGetAttr, /* tp_getattro */
19511956
0, /* tp_setattro */
19521957
&array_as_buffer, /* tp_as_buffer*/
1953-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
1958+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
19541959
arraytype_doc, /* tp_doc */
19551960
0, /* tp_traverse */
19561961
0, /* tp_clear */
19571962
array_richcompare, /* tp_richcompare */
1958-
0, /* tp_weaklistoffset */
1963+
offsetof(arrayobject, weakreflist), /* tp_weaklistoffset */
19591964
(getiterfunc)array_iter, /* tp_iter */
19601965
0, /* tp_iternext */
19611966
array_methods, /* tp_methods */

Objects/fileobject.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@ static void drop_readahead(PyFileObject *);
307307
static void
308308
file_dealloc(PyFileObject *f)
309309
{
310+
if (f->weakreflist != NULL)
311+
PyObject_ClearWeakRefs((PyObject *) f);
310312
if (f->f_fp != NULL && f->f_close != NULL) {
311313
Py_BEGIN_ALLOW_THREADS
312314
(*f->f_close)(f->f_fp);
@@ -1821,6 +1823,7 @@ file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
18211823
((PyFileObject *)self)->f_mode = not_yet_string;
18221824
Py_INCREF(Py_None);
18231825
((PyFileObject *)self)->f_encoding = Py_None;
1826+
((PyFileObject *)self)->weakreflist = NULL;
18241827
}
18251828
return self;
18261829
}
@@ -1942,12 +1945,12 @@ PyTypeObject PyFile_Type = {
19421945
/* softspace is writable: we must supply tp_setattro */
19431946
PyObject_GenericSetAttr, /* tp_setattro */
19441947
0, /* tp_as_buffer */
1945-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
1948+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
19461949
file_doc, /* tp_doc */
19471950
0, /* tp_traverse */
19481951
0, /* tp_clear */
19491952
0, /* tp_richcompare */
1950-
0, /* tp_weaklistoffset */
1953+
offsetof(PyFileObject, weakreflist), /* tp_weaklistoffset */
19511954
(getiterfunc)file_getiter, /* tp_iter */
19521955
(iternextfunc)file_iternext, /* tp_iternext */
19531956
file_methods, /* tp_methods */

0 commit comments

Comments
 (0)
X Tutup