class TagLoaderTests(FlattenTestCase): """ Tests for L{TagLoader}. """ def setUp(self): self.loader = TagLoader(tags.i('test')) def test_interface(self): """ An instance of L{TagLoader} provides L{ITemplateLoader}. """ self.assertTrue(verifyObject(ITemplateLoader, self.loader)) def test_loadsList(self): """ L{TagLoader.load} returns a list, per L{ITemplateLoader}. """ self.assertIsInstance(self.loader.load(), list) def test_flatten(self): """ L{TagLoader} can be used in an L{Element}, and flattens as the tag used to construct the L{TagLoader} would flatten. """ e = Element(self.loader) self.assertFlattensImmediately(e, b'<i>test</i>')
class TagLoaderTests(FlattenTestCase): """ Tests for L{TagLoader}. """ def setUp(self): self.loader = TagLoader(tags.i('test')) def test_interface(self): """ An instance of L{TagLoader} provides L{ITemplateLoader}. """ self.assertTrue(verifyObject(ITemplateLoader, self.loader)) def test_loadsList(self): """ L{TagLoader.load} returns a list, per L{ITemplateLoader}. """ self.assertIsInstance(self.loader.load(), list) def test_flatten(self): """ L{TagLoader} can be used in an L{Element}, and flattens as the tag used to construct the L{TagLoader} would flatten. """ e = Element(self.loader) self.assertFlattensImmediately(e, '<i>test</i>')
class Plating(object): """ A L{Plating} is a container which can be used to generate HTML from data. Its name is derived both from tem-I{plating} and I{chrome plating}. """ CONTENT = "klein:plating:content" def __init__(self, defaults=None, tags=None, presentation_slots=frozenset()): """ """ self._defaults = {} if defaults is None else defaults self._loader = TagLoader(tags) self._presentationSlots = {self.CONTENT} | set(presentation_slots) def routed(self, routing, tags): """ """ def mydecorator(method): loader = TagLoader(tags) @modified("plating route renderer", method, routing) @bindable @inlineCallbacks def mymethod(instance, request, *args, **kw): data = yield _call(instance, method, request, *args, **kw) if _should_return_json(request): json_data = self._defaults.copy() json_data.update(data) for ignored in self._presentationSlots: json_data.pop(ignored, None) text_type = u'json' result = json_serialize(json_data) else: data[self.CONTENT] = loader.load() text_type = u'html' result = self._elementify(instance, data) request.setHeader(b'content-type', (u'text/{format}; charset=utf-8'.format( format=text_type).encode("charmap"))) returnValue(result) return method return mydecorator def _elementify(self, instance, to_fill_with): """ Convert this L{Plating} into a L{PlatedElement}. """ slot_data = self._defaults.copy() slot_data.update(to_fill_with) [loaded] = self._loader.load() loaded = loaded.clone() return PlatedElement(slot_data=slot_data, preloaded=loaded, boundInstance=instance, presentationSlots=self._presentationSlots) def widgeted(self, function): @modified("Plating.widget renderer", function) @bindable def wrapper(instance, *a, **k): data = _call(instance, function, *a, **k) return self._elementify(instance, data) function.widget = wrapper return function
class Plating(object): """ A L{Plating} is a container which can be used to generate HTML from data. Its name is derived both from tem-I{plating} and I{chrome plating}. """ CONTENT = "klein:plating:content" def __init__(self, defaults=None, tags=None, presentation_slots=()): """""" self._defaults = {} if defaults is None else defaults self._loader = TagLoader(tags) self._presentationSlots = {self.CONTENT} | set(presentation_slots) self._renderers = {} def renderMethod(self, renderer): """ Add a render method to this L{Plating} object that can be used in the top-level template. The name of the renderer to use within the template is the name of the decorated function. """ self._renderers[text_type(originalName(renderer))] = renderer return renderer def routed(self, routing, tags): """""" def mydecorator(method): loader = TagLoader(tags) @modified("plating route renderer", method, routing) @bindable @inlineCallbacks def mymethod(instance: Any, request: IRequest, *args: Any, **kw: Any) -> Any: data = yield _call(instance, method, request, *args, **kw) if _should_return_json(request): json_data = self._defaults.copy() json_data.update(data) for ignored in self._presentationSlots: json_data.pop(ignored, None) text_type = "json" ready = yield resolveDeferredObjects(json_data) result = dumps(ready) else: data[self.CONTENT] = loader.load() text_type = "html" result = self._elementify(instance, data) request.setHeader( b"content-type", ("text/{format}; charset=utf-8".format( format=text_type).encode("charmap")), ) returnValue(result) return method return mydecorator def _elementify(self, instance, to_fill_with): """ Convert this L{Plating} into a L{PlatedElement}. """ slot_data = self._defaults.copy() slot_data.update(to_fill_with) [loaded] = self._loader.load() loaded = loaded.clone() return PlatedElement( slot_data=slot_data, preloaded=loaded, renderers=self._renderers, boundInstance=instance, presentationSlots=self._presentationSlots, ) @attr.s class _Widget(object): """ Implementation of L{Plating.widgeted}. This is a L{callable} descriptor that records the instance to which its wrapped function is bound, if any. Its L{widget} method then passes that instance or L{None} and the result of invoking the function (or now bound method) to the creating L{Plating} instance's L{Plating._elementify} to construct a L{PlatedElement}. """ _plating = attr.ib(type="Plating") _function = attr.ib(type=Callable[..., Any]) _instance = attr.ib(type=object) def __call__(self, *args, **kwargs): return self._function(*args, **kwargs) def __get__(self, instance, owner=None): return self.__class__( self._plating, self._function.__get__(instance, owner), instance=instance, ) def widget(self, *args, **kwargs): """ Construct a L{PlatedElement} the rendering of this widget. """ data = self._function(*args, **kwargs) return self._plating._elementify(self._instance, data) def __getattr__(self, attr): return getattr(self._function, attr) def widgeted(self, function): """ A decorator that turns a function into a renderer for an element without a L{Klein.route}. Use this to create reusable template elements. """ return self._Widget(self, function, None)
class Plating(object): """ A L{Plating} is a container which can be used to generate HTML from data. Its name is derived both from tem-I{plating} and I{chrome plating}. """ CONTENT = "klein:plating:content" def __init__(self, defaults=None, tags=None, presentation_slots=frozenset()): """ """ self._defaults = {} if defaults is None else defaults self._loader = TagLoader(tags) self._presentation_slots = {self.CONTENT} | set(presentation_slots) def routed(self, routing, content_template): """ """ @wraps(routing) def mydecorator(method): loader = TagLoader(content_template) @routing @wraps(method) def mymethod(request, *args, **kw): data = method(request, *args, **kw) if _should_return_json(request): json_data = self._defaults.copy() json_data.update(data) for ignored in self._presentation_slots: json_data.pop(ignored, None) request.setHeader(b'content-type', b'text/json; charset=utf-8') return json_serialize(json_data) else: request.setHeader(b'content-type', b'text/html; charset=utf-8') data[self.CONTENT] = loader.load() return self._elementify(data) return method return mydecorator def _elementify(self, to_fill_with): """ """ slot_data = self._defaults.copy() slot_data.update(to_fill_with) [loaded] = self._loader.load() loaded = loaded.clone() return PlatedElement(slot_data=slot_data, preloaded=loaded) def widgeted(self, function): """ """ @wraps(function) def wrapper(*a, **k): data = function(*a, **k) return self._elementify(data) wrapper.__name__ += ".widget" function.widget = wrapper return function