Commit bfabab77 authored by Raymond Hettinger's avatar Raymond Hettinger

Add weakref support to sockets and re pattern objects.

parent d7640d59
...@@ -48,9 +48,23 @@ by the \module{weakref} module for the benefit of advanced uses. ...@@ -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}}
......
...@@ -147,7 +147,8 @@ class _socketobject(object): ...@@ -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:
......
...@@ -5,6 +5,7 @@ from test.test_support import verbose, run_unittest ...@@ -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 ...@@ -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))
......
...@@ -9,6 +9,7 @@ import time ...@@ -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): ...@@ -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):
......
...@@ -207,6 +207,9 @@ Core and builtins ...@@ -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.
......
...@@ -1673,6 +1673,8 @@ _compile(PyObject* self_, PyObject* args) ...@@ -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) ...@@ -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) ...@@ -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 = { ...@@ -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 */
}; };
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
......
...@@ -29,6 +29,7 @@ typedef struct { ...@@ -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];
......
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