mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	Add weakref support to array.array and file objects.
This commit is contained in:
		
							parent
							
								
									691d80532b
								
							
						
					
					
						commit
						cb87bc8e7e
					
				
					 5 changed files with 38 additions and 4 deletions
				
			
		|  | @ -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 @@ | ||||||
| 
 | 
 | ||||||
| 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 @@ def test_buffer(self): | ||||||
|         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 @@ def test_bug_782369(self): | ||||||
|                 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): | ||||||
|  |  | ||||||
|  | @ -1,10 +1,25 @@ | ||||||
| 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 @@ | ||||||
|    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 { | ||||||
| 	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) | ||||||
| 	} | 	} | ||||||
| 	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) | ||||||
| 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 = { | ||||||
| 	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 *); | ||||||
| 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) | ||||||
| 		((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 = { | ||||||
| 	/* 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 */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Raymond Hettinger
						Raymond Hettinger