import StringIO
import os
import Pyana
import unittest
import sys
class StringInputStream:
leaked_streams = []
def __init__(self, string):
self.string = string.encode('utf-8')
self.leaked_streams.append(self.string)
def makeStream(self):
return StringIO.StringIO(self.string)
def __del__(self):
self.leaked_streams.remove(self.string)
class EntityResolver:
def __init__(self, mappings):
self.mappings = mappings
def resolveEntity(self, public, system):
return self.mappings[system]
class ResolveException(Exception):
pass
class RaisingResolver(EntityResolver):
def __init__(self, mappings, failOnRequest):
EntityResolver.__init__(self, mappings)
self.failOnRequest = failOnRequest
def resolveEntity(self, public, system):
if system == self.failOnRequest:
raise ResolveException
else:
return EntityResolver.resolveEntity(self, public, system)
class NoneReturningResolver(EntityResolver):
def __init__(self, mappings, failOnRequest):
EntityResolver.__init__(self, mappings)
self.failOnRequest = failOnRequest
def resolveEntity(self, public, system):
if system == self.failOnRequest:
return None
else:
return EntityResolver.resolveEntity(self, public, system)
xsl = r'''
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:include href="%(protocol)sxsl2"/>
<xsl:template match="/">
<xsl:apply-templates select="document('%(protocol)sxml2')//message"/>
</xsl:template>
</xsl:stylesheet>
'''
xsl2 = r'''
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="message">
The message is <xsl:value-of select="text()"/>
</xsl:template>
</xsl:stylesheet>
'''
xml = '<!DOCTYPE message SYSTEM "%(protocol)sdtd">\n<message>hello world</message>'
xml2 = '<messages><message>bye bye!</message></messages>'
dtd = '<!ELEMENT message (#PCDATA)>'
# using the file protocol will cause problems because the
# UNIX function realpath will be used to check to see if
# the path is actually valid
protocol = 'http://'
xsl = xsl % {'protocol' : protocol}
xml = xml % {'protocol' : protocol}
'''
mappings = {
protocol + 'xsl2' : StringInputStream(xsl2),
protocol + 'xml2': StringInputStream(xml2),
protocol + 'dtd' : StringInputStream(dtd),
'' : None # A request is made to open the NULL string
# because Xerces is attempting to load the
# XML file's schema. Whether that is a bug
# or not is still up in the air. testXSLT
# has the same problem.
}
'''
class EntityResolverTestCase(unittest.TestCase):
def check(self):
StringInputStream.leaked_streams = []
mappings = {
protocol + 'xsl2' : StringInputStream(xsl2),
protocol + 'xml2': StringInputStream(xml2),
protocol + 'dtd' : StringInputStream(dtd),
'' : None # A request is made to open the NULL string
# because Xerces is attempting to load the
# XML file's schema. Whether that is a bug
# or not is still up in the air. testXSLT
# has the same problem.
}
t = Pyana.Transformer()
t.useValidation = 1
t.setEntityResolver(EntityResolver(mappings))
assert t.transform2String(xml, xsl).strip() == \
'The message is bye bye!'
# Verify that the resolver is used for compiled
# stylesheets and source documents
t.compileStylesheet(xsl)
t.parseSource(xml) # Actually, the DTD doesn't seem to be used
# Test removing the resolver
t.setEntityResolver(None)
self.assertRaises(
Pyana.SAXError,
t.transform2String,
xml,
xsl
)
# Test RaisingResolver
t.setEntityResolver(RaisingResolver(mappings, protocol + 'dtd'))
self.assertRaises(ResolveException, t.transform2String, xml, xsl)
# As is allowed by the XSLT spec, failed document() calls
# return an empty nodeset
t.setEntityResolver(RaisingResolver(mappings, protocol + 'xml2'))
assert t.transform2String(xml, xsl) == ''
t.setEntityResolver(RaisingResolver(mappings, protocol + 'xsl2'))
self.assertRaises(ResolveException, t.transform2String, xml, xsl)
# Test NoneReturningResolver
t.setEntityResolver(NoneReturningResolver(mappings, protocol + 'dtd'))
self.assertRaises(Pyana.SAXError, t.transform2String, xml, xsl)
# As is allowed by the XSLT spec, failed document() calls
# return an empty nodeset
t.setEntityResolver(NoneReturningResolver(mappings, protocol + 'xml2'))
assert t.transform2String(xml, xsl) == ''
t.setEntityResolver(NoneReturningResolver(mappings, protocol + 'xsl2'))
self.assertRaises(
Pyana.SAXError,
t.transform2String,
xml,
xsl
)
# Previous versions of Pyana leaked streams. Verify that they are being
# cleaned up
del t
del mappings
assert StringInputStream.leaked_streams == []
def getTestSuites(type):
return unittest.TestSuite([
unittest.makeSuite(EntityResolverTestCase, type)
])
|