Skip to content

Commit b8c2750

Browse files
author
fdrake
committed
Avoid creating circular references between the ExpatParser and the
ContentHandler. While GC will eventually clean up, it can take longer than normal for applications that create a lot of strings (or other immutables) rather without creating many containers. This closes SF bug #535474. git-svn-id: http://svn.python.org/projects/python/trunk@26167 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 7e741e8 commit b8c2750

1 file changed

Lines changed: 38 additions & 1 deletion

File tree

Lib/xml/sax/expatreader.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,43 @@
2626
AttributesNSImpl = xmlreader.AttributesNSImpl
2727

2828
import string
29+
import weakref
30+
31+
# --- ExpatLocator
32+
33+
class ExpatLocator(xmlreader.Locator):
34+
"""Locator for use with the ExpatParser class.
35+
36+
This uses a weak reference to the parser object to avoid creating
37+
a circular reference between the parser and the content handler.
38+
"""
39+
def __init__(self, parser):
40+
self._ref = weakref.ref(parser)
41+
42+
def getColumnNumber(self):
43+
parser = self._ref()
44+
if parser is None or parser._parser is None:
45+
return None
46+
return parser._parser.ErrorColumnNumber
47+
48+
def getLineNumber(self):
49+
parser = self._ref()
50+
if parser is None or parser._parser is None:
51+
return 1
52+
return self._parser.ErrorLineNumber
53+
54+
def getPublicId(self):
55+
parser = self._ref()
56+
if parser is None:
57+
return None
58+
return parser._source.getPublicId()
59+
60+
def getSystemId(self):
61+
parser = self._ref()
62+
if parser is None:
63+
return None
64+
return parser._source.getSystemId()
65+
2966

3067
# --- ExpatParser
3168

@@ -49,7 +86,7 @@ def parse(self, source):
4986

5087
self._source = source
5188
self.reset()
52-
self._cont_handler.setDocumentLocator(self)
89+
self._cont_handler.setDocumentLocator(ExpatLocator(self))
5390
xmlreader.IncrementalParser.parse(self, source)
5491

5592
def prepareParser(self, source):

0 commit comments

Comments
 (0)