Add weakref support to sockets and re pattern objects.
This commit is contained in:
parent
cb87bc8e7e
commit
027bb633b6
|
@ -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):
|
||||||
|
|
||||||
__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
|
||||||
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))
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
|
@ -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];
|
||||||
|
|
Loading…
Reference in New Issue