From: Fred Drake Date: Thu, 4 Apr 2002 17:58:53 +0000 (+0000) Subject: Avoid creating circular references between the ExpatParser and the X-Git-Tag: v2.2.1~26 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ba89194e8f7253dd30b468dde68cfc27e2c9c6fe;p=thirdparty%2FPython%2Fcpython.git 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. --- diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py index 5473b364544f..2732ab06f295 100644 --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -26,6 +26,43 @@ AttributesImpl = xmlreader.AttributesImpl AttributesNSImpl = xmlreader.AttributesNSImpl import string +import weakref + +# --- ExpatLocator + +class ExpatLocator(xmlreader.Locator): + """Locator for use with the ExpatParser class. + + This uses a weak reference to the parser object to avoid creating + a circular reference between the parser and the content handler. + """ + def __init__(self, parser): + self._ref = weakref.ref(parser) + + def getColumnNumber(self): + parser = self._ref() + if parser is None or parser._parser is None: + return None + return parser._parser.ErrorColumnNumber + + def getLineNumber(self): + parser = self._ref() + if parser is None or parser._parser is None: + return 1 + return self._parser.ErrorLineNumber + + def getPublicId(self): + parser = self._ref() + if parser is None: + return None + return parser._source.getPublicId() + + def getSystemId(self): + parser = self._ref() + if parser is None: + return None + return parser._source.getSystemId() + # --- ExpatParser @@ -49,7 +86,7 @@ class ExpatParser(xmlreader.IncrementalParser, xmlreader.Locator): self._source = source self.reset() - self._cont_handler.setDocumentLocator(self) + self._cont_handler.setDocumentLocator(ExpatLocator(self)) xmlreader.IncrementalParser.parse(self, source) def prepareParser(self, source):