diff --git a/Doc/lib/libweakref.tex b/Doc/lib/libweakref.tex index c8d82a88957..f2ba80b03ed 100644 --- a/Doc/lib/libweakref.tex +++ b/Doc/lib/libweakref.tex @@ -48,9 +48,23 @@ by the \module{weakref} module for the benefit of advanced uses. Not all objects can be weakly referenced; those objects which can include class instances, functions written in Python (but not in C), -and methods (both bound and unbound). Extension types can easily -be made to support weak references; see section \ref{weakref-extension}, -``Weak References in Extension Types,'' for more information. +methods (both bound and unbound), sets, frozensets, file objects, +sockets, arrays, deques, and regular expression pattern objects. +\versionchanged[Added support for files, sockets, arrays, and patterns]{2.4} + +Several builtin types such as \class{list} and \class{dict} do not +directly support weak references but can add support through subclassing: + +\begin{verbatim} +class Dict(dict): + pass + +obj = Dict(red=1, green=2, blue=3) # this object is weak referencable +\end{verbatim} + +Extension types can easily be made to support weak references; see section +\ref{weakref-extension}, ``Weak References in Extension Types,'' for more +information. \begin{funcdesc}{ref}{object\optional{, callback}} diff --git a/Lib/socket.py b/Lib/socket.py index 39d511962b2..e97ce5979f5 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -147,7 +147,8 @@ class _socketobject(object): __doc__ = _realsocket.__doc__ - __slots__ = ["_sock", "send", "recv", "sendto", "recvfrom"] + __slots__ = ["_sock", "send", "recv", "sendto", "recvfrom", + "__weakref__"] def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None): if _sock is None: diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 2363ce5ee6e..c7afdc59a2a 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -5,6 +5,7 @@ from test.test_support import verbose, run_unittest import re from sre import Scanner import sys, os, traceback +from weakref import proxy # Misc tests from Tim Peters' re.doc @@ -15,6 +16,13 @@ import sys, os, traceback import unittest class ReTests(unittest.TestCase): + + def test_weakref(self): + s = 'QabbbcR' + x = re.compile('ab+c') + y = proxy(x) + self.assertEqual(x.findall('QabbbcR'), y.findall('QabbbcR')) + def test_search_star_plus(self): self.assertEqual(re.search('x*', 'axx').span(0), (0, 0)) self.assertEqual(re.search('x*', 'axx').span(), (0, 0)) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index f7bf041ebd0..6e2f80c407b 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -9,6 +9,7 @@ import time import thread, threading import Queue import sys +from weakref import proxy PORT = 50007 HOST = 'localhost' @@ -191,6 +192,19 @@ class SocketConnectedTest(ThreadedTCPSocketTest): class GeneralModuleTests(unittest.TestCase): + def test_weakref(self): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + p = proxy(s) + self.assertEqual(p.fileno(), s.fileno()) + s.close() + s = None + try: + p.fileno() + except ReferenceError: + pass + else: + self.fail('Socket proxy still exists') + def testSocketError(self): # Testing socket module exceptions def raise_error(*args, **kwargs): diff --git a/Misc/NEWS b/Misc/NEWS index 7215483a329..032f76ec5bd 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -207,6 +207,9 @@ Core and builtins Extension modules ----------------- +- the weakref module now supports additional objects: array.array, + sre.pattern_objects, file objects, and sockets. + - operator.isMappingType() and operator.isSequenceType() now give fewer false positives. diff --git a/Modules/_sre.c b/Modules/_sre.c index 45139bc0023..4be33d04ca8 100644 --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -1673,6 +1673,8 @@ _compile(PyObject* self_, PyObject* args) Py_XINCREF(indexgroup); self->indexgroup = indexgroup; + self->weakreflist = NULL; + return (PyObject*) self; } @@ -1985,6 +1987,8 @@ pattern_scanner(PatternObject* pattern, PyObject* args) static void pattern_dealloc(PatternObject* self) { + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *) self); Py_XDECREF(self->pattern); Py_XDECREF(self->groupindex); Py_XDECREF(self->indexgroup); @@ -2632,6 +2636,7 @@ pattern_copy(PatternObject* self, PyObject* args) memcpy((char*) copy + offset, (char*) self + offset, sizeof(PatternObject) + self->codesize * sizeof(SRE_CODE) - offset); + copy->weakreflist = NULL; return (PyObject*) copy; #else @@ -2722,7 +2727,25 @@ statichere PyTypeObject Pattern_Type = { sizeof(PatternObject), sizeof(SRE_CODE), (destructor)pattern_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ - (getattrfunc)pattern_getattr /*tp_getattr*/ + (getattrfunc)pattern_getattr, /*tp_getattr*/ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + offsetof(PatternObject, weakreflist), /* tp_weaklistoffset */ }; /* -------------------------------------------------------------------- */ diff --git a/Modules/sre.h b/Modules/sre.h index 45028024665..b07d2108052 100644 --- a/Modules/sre.h +++ b/Modules/sre.h @@ -29,6 +29,7 @@ typedef struct { /* compatibility */ PyObject* pattern; /* pattern source (or None) */ int flags; /* flags used when compiling pattern source */ + PyObject *weakreflist; /* List of weak references */ /* pattern code */ int codesize; SRE_CODE code[1];