Add weakref support to sockets and re pattern objects.

This commit is contained in:
Raymond Hettinger 2004-05-31 03:09:25 +00:00
parent cb87bc8e7e
commit 027bb633b6
7 changed files with 69 additions and 5 deletions

View File

@ -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 Not all objects can be weakly referenced; those objects which can
include class instances, functions written in Python (but not in C), include class instances, functions written in Python (but not in C),
and methods (both bound and unbound). Extension types can easily methods (both bound and unbound), sets, frozensets, file objects,
be made to support weak references; see section \ref{weakref-extension}, sockets, arrays, deques, and regular expression pattern objects.
``Weak References in Extension Types,'' for more information. \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}} \begin{funcdesc}{ref}{object\optional{, callback}}

View File

@ -147,7 +147,8 @@ class _socketobject(object):
__doc__ = _realsocket.__doc__ __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): def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
if _sock is None: if _sock is None:

View File

@ -5,6 +5,7 @@ from test.test_support import verbose, run_unittest
import re import re
from sre import Scanner from sre import Scanner
import sys, os, traceback import sys, os, traceback
from weakref import proxy
# Misc tests from Tim Peters' re.doc # Misc tests from Tim Peters' re.doc
@ -15,6 +16,13 @@ import sys, os, traceback
import unittest import unittest
class ReTests(unittest.TestCase): 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): 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, 0))
self.assertEqual(re.search('x*', 'axx').span(), (0, 0)) self.assertEqual(re.search('x*', 'axx').span(), (0, 0))

View File

@ -9,6 +9,7 @@ import time
import thread, threading import thread, threading
import Queue import Queue
import sys import sys
from weakref import proxy
PORT = 50007 PORT = 50007
HOST = 'localhost' HOST = 'localhost'
@ -191,6 +192,19 @@ class SocketConnectedTest(ThreadedTCPSocketTest):
class GeneralModuleTests(unittest.TestCase): 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): def testSocketError(self):
# Testing socket module exceptions # Testing socket module exceptions
def raise_error(*args, **kwargs): def raise_error(*args, **kwargs):

View File

@ -207,6 +207,9 @@ Core and builtins
Extension modules 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 - operator.isMappingType() and operator.isSequenceType() now give
fewer false positives. fewer false positives.

View File

@ -1673,6 +1673,8 @@ _compile(PyObject* self_, PyObject* args)
Py_XINCREF(indexgroup); Py_XINCREF(indexgroup);
self->indexgroup = indexgroup; self->indexgroup = indexgroup;
self->weakreflist = NULL;
return (PyObject*) self; return (PyObject*) self;
} }
@ -1985,6 +1987,8 @@ pattern_scanner(PatternObject* pattern, PyObject* args)
static void static void
pattern_dealloc(PatternObject* self) pattern_dealloc(PatternObject* self)
{ {
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
Py_XDECREF(self->pattern); Py_XDECREF(self->pattern);
Py_XDECREF(self->groupindex); Py_XDECREF(self->groupindex);
Py_XDECREF(self->indexgroup); Py_XDECREF(self->indexgroup);
@ -2632,6 +2636,7 @@ pattern_copy(PatternObject* self, PyObject* args)
memcpy((char*) copy + offset, (char*) self + offset, memcpy((char*) copy + offset, (char*) self + offset,
sizeof(PatternObject) + self->codesize * sizeof(SRE_CODE) - offset); sizeof(PatternObject) + self->codesize * sizeof(SRE_CODE) - offset);
copy->weakreflist = NULL;
return (PyObject*) copy; return (PyObject*) copy;
#else #else
@ -2722,7 +2727,25 @@ statichere PyTypeObject Pattern_Type = {
sizeof(PatternObject), sizeof(SRE_CODE), sizeof(PatternObject), sizeof(SRE_CODE),
(destructor)pattern_dealloc, /*tp_dealloc*/ (destructor)pattern_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 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 */
}; };
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */

View File

@ -29,6 +29,7 @@ typedef struct {
/* compatibility */ /* compatibility */
PyObject* pattern; /* pattern source (or None) */ PyObject* pattern; /* pattern source (or None) */
int flags; /* flags used when compiling pattern source */ int flags; /* flags used when compiling pattern source */
PyObject *weakreflist; /* List of weak references */
/* pattern code */ /* pattern code */
int codesize; int codesize;
SRE_CODE code[1]; SRE_CODE code[1];