def test_transparentRendering(self): """ A C{transparent} element should be eliminated from the DOM and rendered as only its children. """ element = Element(loader=XMLString( '<t:transparent ' 'xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1">' 'Hello, world.' '</t:transparent>')) return self.assertFlattensTo(element, "Hello, world.")
class SimpleElement(Element): loader = XMLString( '<h1 xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" ' 't:render="name" />') def __init__(self, name): self._name = name @renderer def name(self, request, tag): return tag(self._name)
def test_missingRenderMethod(self): """ Test that flattening an L{Element} with a C{loader} which has a tag with a render directive fails with L{FlattenerError} if there is no available render method to satisfy that directive. """ element = Element(loader=XMLString(""" <p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="unknownMethod" /> """)) return self.assertFlatteningRaises(element, MissingRenderMethod)
def outerMethod(self, request, tag): return tag( InnerElement( loader=XMLString( """ <t:ignored xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="innerMethod" /> """ ) ) )
def outerMethod(self, request: Optional[IRequest], tag: Tag) -> Flattenable: return tag( InnerElement( loader=XMLString( """ <t:ignored xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="innerMethod" /> """ ) ) )
class TestFailureElement(Element): """ An L{Element} that can be used in place of L{FailureElement} to verify that L{renderElement} can render failures properly. """ loader = XMLString( '<p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1">' 'I failed.' '</p>') def __init__(self, failure, loader=None): self.failure = failure
def test_attrRendering(self): """ An Element with an attr tag renders the vaule of its attr tag as an attribute of its containing tag. """ element = Element(loader=XMLString( '<a xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1">' '<t:attr name="href">http://example.com</t:attr>' "Hello, world." "</a>")) return self.assertFlattensTo( element, b'<a href="http://example.com">Hello, world.</a>')
def test_lenientPrefixBehavior(self) -> None: """ If the parser sees a prefix it doesn't recognize on an attribute, it will pass it on through to serialization. """ theInput = ( '<hello:world hello:sample="testing" ' 'xmlns:hello="http://made-up.example.com/ns/not-real">' "This is a made-up tag.</hello:world>" ) element = Element(loader=XMLString(theInput)) self.assertFlattensTo(element, theInput.encode("utf8"))
def rstToStan(rst): html = rstToHTML(rst) # fix a bad encoding in docutils html = html.replace('encoding="unicode"', '') stan = XMLString(html).load()[0] if stan.tagName != "html": raise ValueError("Unexpected top-level HTML tag.") head, body = [x for x in stan.children if checkTag(x)] if head.tagName != "head": raise ValueError("Expected 'head' node, got '%s'" % (head.tagName)) if body.tagName != "body": raise ValueError("Expected 'body' node, got '%s'" % (body.tagName)) return body.children
class RoomsElement(Element): loader = XMLString( ('<h1 ' 'xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1"' '>Hello, <span t:render="name"></span>!</h1>')) def __init__(self, name): self.m_name = name @renderer def name(self, _request, _tag): return self.m_name
class AutomatonStatsElement(Element): """ Render some information about automatons. """ loader = XMLString(automaton_stats_template) def __init__(self, factory): self.factory = factory @renderer def main(self, request, tag): return tag(*(AutomatonElement(a) for a in self.factory.automatons))
class BravoElement(Element): loader = XMLString(root_template) def __init__(self, services): Element.__init__(self) self.services = services @renderer def title(self, request, tag): return tag("Bravo %s" % version) @renderer def service(self, request, tag): l = [] services = [] for name, service in self.services.iteritems(): factory = service.args[1] if isinstance(factory, BravoFactory): services.append(self.bravofactory(request, tags.div, factory)) else: l.append( tags.li("%s (%s)" % (name, self.services[name].__class__))) ul = tags.ul(*l) div = tags.div(*services) return tag(ul, div) def bravofactory(self, request, tag, factory): g = (tags.li(username) for username in factory.protocols) users = tags.div(tags.h3("Users"), tags.ul(*g)) world = self.world(request, tags.div, factory.world) return tag(tags.h2("Bravo world %s" % factory.name), users, world) def world(self, request, tag, world): l = [] total = (len(world.chunk_cache) + len(world.dirty_chunk_cache) + len(world._pending_chunks)) l.append(tags.li("Total chunks: %d" % total)) l.append(tags.li("Clean chunks: %d" % len(world.chunk_cache))) l.append(tags.li("Dirty chunks: %d" % len(world.dirty_chunk_cache))) l.append( tags.li("Chunks being generated: %d" % len(world._pending_chunks))) if world.permanent_cache: l.append( tags.li("Permanent cache: enabled, %d chunks" % len(world.permanent_cache))) else: l.append(tags.li("Permanent cache: disabled")) status = tags.ul(*l) return tag(tags.h3("World status"), status)
def test_transparentRendering(self) -> None: """ A C{transparent} element should be eliminated from the DOM and rendered as only its children. """ element = Element( loader=XMLString( "<t:transparent " 'xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1">' "Hello, world." "</t:transparent>" ) ) self.assertFlattensImmediately(element, b"Hello, world.")
class BravoWorldElement(Element): """ Element representing a single world. """ loader = XMLString(world_template) def __init__(self, factory, plugins): Element.__init__(self) self.factory = factory self.plugins = plugins @renderer def title(self, request, tag): return tag("World %s" % self.factory.name.title()) @renderer def user(self, request, tag): users = (tags.li(username) for username in self.factory.protocols) return tag(tags.h2("Users"), tags.ul(*users)) @renderer def status(self, request, tag): world = self.factory.world l = [] total = (len(world.chunk_cache) + len(world.dirty_chunk_cache) + len(world._pending_chunks)) l.append(tags.li("Total chunks: %d" % total)) l.append(tags.li("Clean chunks: %d" % len(world.chunk_cache))) l.append(tags.li("Dirty chunks: %d" % len(world.dirty_chunk_cache))) l.append( tags.li("Chunks being generated: %d" % len(world._pending_chunks))) if world.permanent_cache: l.append( tags.li("Permanent cache: enabled, %d chunks" % len(world.permanent_cache))) else: l.append(tags.li("Permanent cache: disabled")) status = tags.ul(*l) return tag(tags.h2("Status"), status) @renderer def plugin(self, request, tag): plugins = [] for name in self.plugins.keys(): plugins.append( tags.li( tags.a(name.title(), href='%s/%s' % (self.factory.name, name)))) return tag(tags.h2("Plugins"), tags.ul(*plugins))
def html2stan(html: Union[bytes, str]) -> Tag: """ Convert an HTML string to a Stan tree. @param html: An HTML fragment; multiple roots are allowed. @return: The fragment as a tree with a transparent root node. """ if isinstance(html, str): html = html.encode('utf8') html = _RE_CONTROL.sub(lambda m: b'\\x%02x' % ord(m.group()), html) stan: Tag = XMLString(b'<div>%s</div>' % html).load()[0] assert stan.tagName == 'div' stan.tagName = '' return stan
def test_elementContainingStaticElement(self): """ An Element which is returned by the render method of another Element is rendered properly. """ class RenderfulElement(Element): @renderer def renderMethod(self, request, tag): return tag(Element( loader=XMLString("<em>Hello, world.</em>"))) element = RenderfulElement(loader=XMLString(""" <p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="renderMethod" /> """)) return self.assertFlattensTo(element, b"<p><em>Hello, world.</em></p>")
def test_directiveRenderingOmittingTag(self): """ An Element with a render method which omits the containing tag successfully removes that tag from the output. """ class RenderfulElement(Element): @renderer def renderMethod(self, request, tag): return "Hello, world." element = RenderfulElement(loader=XMLString(""" <p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="renderMethod"> Goodbye, world. </p> """)) return self.assertFlattensTo(element, b"Hello, world.")
def test_directiveRendering(self): """ An Element with a valid render directive has that directive invoked and the result added to the output. """ renders = [] class RenderfulElement(Element): @renderer def renderMethod(self, request, tag): renders.append((self, request)) return tag("Hello, world.") element = RenderfulElement(loader=XMLString(""" <p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="renderMethod" /> """)) return self.assertFlattensTo(element, b"<p>Hello, world.</p>")
def test_deferredRendering(self): """ An Element with a render method which returns a Deferred will render correctly. """ class RenderfulElement(Element): @renderer def renderMethod(self, request, tag): return succeed("Hello, world.") element = RenderfulElement(loader=XMLString(""" <p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="renderMethod"> Goodbye, world. </p> """)) return self.assertFlattensTo(element, b"Hello, world.")
def html2stan(html): """ Convert HTML to a Stan structure. @param html: A HTML string. @type html: L{unicode} or L{bytes} """ if isinstance(html, unicode): html = html.encode("utf8") html = _control_pat.sub(lambda m: "\\x%02x" % ord(m.group()), html) html = "<div>" + html + "</div>" html = XMLString(html).load()[0].children if html and html[-1] == u"\n": del html[-1] return html
def test_roundTrip(self) -> None: """ Given a series of parsable XML strings, verify that L{twisted.web._flatten.flatten} will flatten the L{Element} back to the input when sent on a round trip. """ fragments = [ b"<p>Hello, world.</p>", b"<p><!-- hello, world --></p>", b"<p><![CDATA[Hello, world.]]></p>", b'<test1 xmlns:test2="urn:test2">' b"<test2:test3></test2:test3></test1>", b'<test1 xmlns="urn:test2"><test3></test3></test1>', b"<p>\xe2\x98\x83</p>", ] for xml in fragments: self.assertFlattensImmediately(Element(loader=XMLString(xml)), xml)
class DefaultErrorElement(Element): """ An L{ErrorElement} is an L{Element} that renders some HTML for the default rendering of an error page. """ loader = XMLString(""" <html xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="error"> <head> <title><t:slot name="code"/> <t:slot name="title"/></title> </head> <body> <h1><t:slot name="title" /></h1> <t:slot name="message" /> </body> </html> """) def __init__(self, request, response): super(DefaultErrorElement, self).__init__() self.request = request self.response = response @renderer def error(self, request, tag): """ Top-level renderer for page. """ return tag.fillSlots( code=str(self.response.code), title=RESPONSES.get(self.response.code), message=self.loadMessage(self.response.code).fillSlots( uri=self.request.uri, location=self.response.headers.getHeader('location'), method=self.request.method, ) ) def loadMessage(self, code): tag = XMLString(('<t:transparent xmlns:t="http://twistedmatrix.com/' 'ns/twisted.web.template/0.1">') + ERROR_MESSAGES.get(code, "") + '</t:transparent>').load()[0] return tag
class WorldMapElement(Element): """ Element for the WorldMap plugin. """ loader = XMLString(world_map_template) @renderer def main(self, request, tag): path = request.URLPath() l = [] for y in range(-5, 5): for x in range(-5, 5): child = path.child("%s,%s" % (x, y)) l.append(tags.img(src=str(child), height="64", width="64")) l.append(tags.br()) return tag(*l)
def test_elementUsingSlots(self): """ An Element which is returned by the render method of another Element is rendered properly. """ class RenderfulElement(Element): @renderer def renderMethod(self, request, tag): return tag.fillSlots(test2='world.') element = RenderfulElement(loader=XMLString( '<p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1"' ' t:render="renderMethod">' '<t:slot name="test1" default="Hello, " />' '<t:slot name="test2" />' '</p>' )) return self.assertFlattensTo(element, b"<p>Hello, world.</p>")
class AutomatonElement(Element): """ An automaton. """ loader = XMLString(""" <div xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1"> <h2 t:render="name" /> <ul> <li t:render="tracked" /> <li t:render="step" /> </ul> </div> """) def __init__(self, automaton): Element.__init__(self) self.automaton = automaton @renderer def name(self, request, tag): return tag(self.automaton.name) @renderer def tracked(self, request, tag): if hasattr(self.automaton, "tracked"): t = self.automaton.tracked if isinstance(t, dict): l = sum(len(i) for i in t.values()) else: l = len(t) s = "Currently tracking %d blocks" % l else: s = "<n/a>" return tag(s) @renderer def step(self, request, tag): if hasattr(self.automaton, "step"): s = "Currently processing every %f seconds" % self.automaton.step else: s = "<n/a>" return tag(s)
def test_elementUsingSlots(self) -> None: """ An Element which is returned by the render method of another Element is rendered properly. """ class RenderfulElement(Element): @renderer def renderMethod(self, request: Optional[IRequest], tag: Tag) -> Flattenable: return tag.fillSlots(test2="world.") element = RenderfulElement(loader=XMLString( '<p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1"' ' t:render="renderMethod">' '<t:slot name="test1" default="Hello, " />' '<t:slot name="test2" />' "</p>")) self.assertFlattensImmediately(element, b"<p>Hello, world.</p>")
def test_roundTrip(self): """ Given a series of parsable XML strings, verify that L{twisted.web._flatten.flatten} will flatten the L{Element} back to the input when sent on a round trip. """ fragments = [ b"<p>Hello, world.</p>", b"<p><!-- hello, world --></p>", b"<p><![CDATA[Hello, world.]]></p>", b'<test1 xmlns:test2="urn:test2">' b'<test2:test3></test2:test3></test1>', b'<test1 xmlns="urn:test2"><test3></test3></test1>', b'<p>\xe2\x98\x83</p>', ] deferreds = [ self.assertFlattensTo(Element(loader=XMLString(xml)), xml) for xml in fragments] return gatherResults(deferreds)
def test_elementContainingDynamicElement(self): """ Directives in the document factory of an Element returned from a render method of another Element are satisfied from the correct object: the "inner" Element. """ class OuterElement(Element): @renderer def outerMethod(self, request, tag): return tag(InnerElement(loader=XMLString(""" <t:ignored xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="innerMethod" /> """))) class InnerElement(Element): @renderer def innerMethod(self, request, tag): return "Hello, world." element = OuterElement(loader=XMLString(""" <p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="outerMethod" /> """)) return self.assertFlattensTo(element, b"<p>Hello, world.</p>")
class StatusResponseElement(Element): """ Render the HTML for a L{StatusResponse} """ loader = XMLString("""<html xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1" t:render="response"><head><title><t:slot name="title" /></title></head><body><h1><t:slot name="title" /></h1><p><t:slot name="description" /></p></body></html>""") def __init__(self, title, description): super(StatusResponseElement, self).__init__() self.title = title self.description = description @renderer def response(self, request, tag): """ Top-level renderer. """ return tag.fillSlots(title=self.title, description=self.description)
def test_sameLoaderTwice(self) -> None: """ Rendering the output of a loader, or even the same element, should return different output each time. """ sharedLoader = XMLString( '<p xmlns:t="http://twistedmatrix.com/ns/twisted.web.template/0.1">' '<t:transparent t:render="classCounter" /> ' '<t:transparent t:render="instanceCounter" />' "</p>" ) class DestructiveElement(Element): count = 0 instanceCount = 0 loader = sharedLoader @renderer def classCounter( self, request: Optional[IRequest], tag: Tag ) -> Flattenable: DestructiveElement.count += 1 return tag(str(DestructiveElement.count)) @renderer def instanceCounter( self, request: Optional[IRequest], tag: Tag ) -> Flattenable: self.instanceCount += 1 return tag(str(self.instanceCount)) e1 = DestructiveElement() e2 = DestructiveElement() self.assertFlattensImmediately(e1, b"<p>1 1</p>") self.assertFlattensImmediately(e1, b"<p>2 2</p>") self.assertFlattensImmediately(e2, b"<p>3 1</p>")