def test(missing): plating = Plating(tags=tags.span(slot(Plating.CONTENT))) @plating.routed(self.app.route("/"), tags.span(tags.span(render=missing))) def no(request): return {} self.get(b"/") [fe] = self.flushLoggedErrors(FlattenerError) self.assertIsInstance(fe.value.args[0], MissingRenderMethod)
def test_presentation_only_json(self): """ Slots marked as "presentation only" will not be reflected in the output. """ plating = Plating(tags=tags.span(slot("title")), presentation_slots={"title"}) @plating.routed(self.app.route("/"), tags.span(slot("data"))) def justJson(request): return {"title": "uninteresting", "data": "interesting"} request, written = self.get(b"/?json=1") self.assertEqual(json.loads(written.decode("utf-8")), {"data": "interesting"})
class FeedAggregation(object): _retrieve = attr.ib() _urls = attr.ib() _app = Klein() _planting = Plating( tags=t.html( t.head(t.title('Feed Aggregator 2.0')), t.body(slot(Plating.CONTENT)) ) ) def resource(self): return self._app.resource() @_planting.routed( _app.route('/'), t.div(render='feeds:list')(slot('item')), ) def root(self, request): def convert(feed): return feed.as_json() if request.args.get(b'json') else feed.as_html() return {'feeds': [self._retrieve(url).addCallback(convert) for url in self._urls]}
class SimpleFeedAggregation(object): application = Klein() common_page = Plating(tags=tags.html( tags.head(tags.title('Feed Aggregator 1.0')), tags.body(tags.div(slot(Plating.CONTENT))), )) def __init__(self, reactor, feed_urls): self._reactor = reactor self._feed_urls = feed_urls @defer.inlineCallbacks def retrieve_field(self, url): response = yield treq.get(url, timeout=30.0, reactor=self._reactor) if response.code != http.OK: fail_reason = http.RESPONSES[response.code] raise RuntimeError(f'Failed: {response.code} {fail_reason}') content = yield response.content() defer.returnValue(feedparser.parse(content)) @common_page.routed(application.route('/'), tags.div(render='feeds:list')(slot('item'))) def feeds(self, request): def render_feed(feed): feed_title = feed[u'feed'][u'title'] feed_link = feed[u'feed'][u'link'] return tags.table( tags.tr(tags.th(tags.a(feed_title, href=feed_link))))([ tags.tr( tags.td(tags.a(entry[u'title'], href=entry[u'link']))) for entry in feed[u'entries'] ]) return { u'feeds': [ self.retrieve_field(url).addCallback(render_feed) for url in self._feed_urls ] }
class FeedAggregation(object): _retrieve = attr.ib() _urls = attr.ib() _app = Klein() _plating = Plating(tags=t.html(t.head(t.title("Feed Aggregator 2.0")), t.body(slot(Plating.CONTENT)))) def resource(self): return self._app.resource() @_plating.routed( _app.route("/"), t.div(render="feeds:list")(slot("item")), ) def root(self, request): def convert(feed): return feed.asJSON() if request.args.get( b"json") else feed.asHTML() return { "feeds": [self._retrieve(url).addCallback(convert) for url in self._urls] }
class SlowIncrementWebService(object): application = Klein() common_page = Plating(tags=tags.html( tags.head( tags.title(slot('title')), tags.style('#amount { font-weight: bold; }' '#message { font-style: italic; }')), tags.body(tags.div(slot(Plating.CONTENT))))) def __init__(self, reactor): self._reactor = reactor @common_page.routed(application.route('/<int:amount>'), tags.div( tags.span('Hello! Your new amount is: ', id='message'), tags.span(slot('new_amount'), id='amount'), )) def slow_increment(self, request, amount): slots = { 'title': 'Slow Increment', 'new_amount': amount + 1, } return task.deferLater(self._reactor, 1.0, lambda: slots)
#!/usr/bin/python3 # -*- coding: utf-8 -*- from klein import run, route from twisted.web.template import tags, slot from klein import Klein, Plating from input_handler import handle_input app = Klein() myStyle = Plating( tags=tags.html( tags.head(tags.title(slot("pageTitle"))), tags.body(tags.h1(slot("pageTitle"), Class="titleHeading"), tags.div(slot(Plating.CONTENT))) ) ) @myStyle.routed( app.route("/input/"), tags.div()) def input(request): return {"r":['Hello, world!']} if __name__ == '__main__': app.run("localhost", 8080)
from klein.interfaces import ISession from klein.storage.memory import MemorySessionStore app = Klein() sessions = MemorySessionStore() requirer = Requirer() @requirer.prerequisite([ISession]) def procurer(request): return SessionProcurer(sessions).procureSession(request) style = Plating(tags=tags.html(tags.head(tags.title("yay")), tags.body(tags.div(slot(Plating.CONTENT))))) @requirer.require( style.routed( app.route("/", methods=["POST"]), tags.h1("u did it: ", slot("an-form-arg")), ), foo=Field.number(minimum=3, maximum=10), bar=Field.text(), ) def postHandler(foo, bar): return {"an-form-arg": foo} @requirer.require(
import json from klein import Plating from twisted.web.template import tags, slot from twisted.web.error import FlattenerError, MissingRenderMethod from klein.test.test_resource import requestMock, _render from klein.test.util import TestCase from klein import Klein page = Plating( defaults={ "title": "default title unchanged", Plating.CONTENT: "NEVER MIND THE CONTENT", }, tags=tags.html( tags.head(tags.title(slot("title"))), tags.body(tags.h1(slot("title")), tags.div(slot(Plating.CONTENT), Class="content"))), ) element = Plating( defaults={ "a": "NO VALUE FOR A", "b": "NO VALUE FOR B", }, tags=tags.div(tags.span("a: ", slot("a")), tags.span("b: ", slot("b"))), ) @element.widgeted
from random import Random from hashlib import sha256 from struct import unpack def random_from_string(string): return Random(unpack("!I", sha256(string.encode("utf-8")).digest()[:4])[0]) from twisted.web.template import tags, slot from klein import Klein, Plating app = Klein() myStyle = Plating(tags=tags.html( tags.head(tags.title(slot("pageTitle"))), tags.body(tags.h1(slot("pageTitle"), Class="titleHeading"), tags.div(slot(Plating.CONTENT)))), defaults={"pageTitle": "Places & Foods"}) @myStyle.routed( app.route("/"), tags.div( tags.h2("Sample Places:"), tags.ul([ tags.li(tags.a(href=["/places/", place])(place)) for place in ["new york", "san francisco", "shanghai"] ]), tags.h2("Sample Foods:"), tags.ul([ tags.li(tags.a(href=["/foods/", food])(food))
from klein.interfaces import ISession from klein.storage.memory import MemorySessionStore app = Klein() sessions = MemorySessionStore() requirer = Requirer() @requirer.prerequisite([ISession]) def procurer(request): return SessionProcurer(sessions).procureSession(request) style = Plating(tags=tags.html( tags.head(tags.title("yay")), tags.body(tags.div(slot(Plating.CONTENT)))) ) @style.routed( requirer.require( app.route("/", methods=["POST"]), foo=Field.integer(minimum=3, maximum=10), bar=Field.text(), ), tags.h1('u did it: ', slot("an-form-arg")) ) def postHandler(foo, bar): return {"an-form-arg": foo} @requirer.require( style.routed( app.route("/", methods=["GET"]),