mahmoud / ashes Goto Github PK
View Code? Open in Web Editor NEW⚱️ Lightweight, self-contained templating for Python 2 and 3, a la Dust templates
Home Page: http://ashes.readthedocs.org
License: Other
⚱️ Lightweight, self-contained templating for Python 2 and 3, a la Dust templates
Home Page: http://ashes.readthedocs.org
License: Other
It took a bit more trial & error to figure out my issues with the TemplateLoaders.
I'd suggest switching the library to use a "BaseTemplateLoader" class , which has full inline documentation for whatever methods and arguments are supported, and then having the 2 other classes inherit from it. Basically, implement the Loaders the same way the AshesEnv is implemented -- but with a bit more docs.
The 'BaseAshesEnv' could also use some more docs around load/load_all/init. .
I've been having trouble trying to ensure some 'global' variables will always be available to templates. When using partials and context / kwargs, they are lost.
The javascript version supports this through an implementation detail -- javascript just-so-happens to have global variables, and will look there. The docs/wiki of the LinkedIn fork mentions this quite a bit.
It would be great if the AshesEnv class and/or render commands would support a globals dict.
Dust has a convenient @select helper statement to handle different cases in code flow. Ashes currently doesn't support it. Can that feature be added?
Looks like the newest code has not been published on PyPi. Published ashes 0.4.0 is 1149 lines long while the one in github is 1495 lines.
Hopefully this will fix a bug where the {@eq} operator isn't working correctly. :-)
I was about to write an iterate
helper, but then noticed you had one in the source already (!)
I couldn't find any docs for it (aside from the source code) and I'm not sure what (if any) javascript implementations it is compatible with (there are several in the "issues" section of the active dust.js linkedin fork)
It would be great if this library's docs did 2 things:
see also - #22
LinkedIn has forked Dust.js because the original developer/maintainer isn't responsive.
Given the number of improvements LinkedIn have made, it might be better to compare your compatibility to their fork.
In templates, it seems ashes hardcodes the delimiter to be opening and closing curly brackets. It think it would be a small but useful feature to have any arbitrary string as opening and closing delimiter.
I.e. if I have a template file:
Hello, {[(world)]}
I think it would be useful to do:
ashes --template mytmplt.txt -M '{ "world": "People" }' --opening-delimeter '{[(' --closing-delimiter ')]}'
And get
Hello, People
i have a novel idea for a feature, but it might not be possible. i wanted to "ask first" before trying to build it.
we use the dust
format for user customizable templates. they're heavily sanitized and processed after submission, but are still User Generated Content. dust.js handles client side, ashes handles server side rendering.
performance is a bit of a concern. ashes is good enough for now, but we could do quite a bit better if we were able to cache the templates somehow. A decent chunk of the time is spent compiling the templates.
Since this is for user customization, we can't recycle the AshesEnv across requests. Because of the way Ashes builds templates, neither the env not the templates can be serialized ( pickle doesn't like the render functions, probably doesn't like a lot more ).
In order to support cachable templates, I see a few opportunities:
• cache the _gen_python string. This would save about 65% of building the template ( the 100% baseline is Template._get_render_func )
• cache the AST. This would save about 45% of time loading the template, but might be easier.
My general concerns before moving forward, are that I'm not sure if this is 'legal' or not. Could there be anything in the AST / python template that is specific to the current envelope or process ?
i don't think so. looking at the output of both, they seem doable -- but I don't have experience with the various filters and other advanced Dust techniques. we just it with basic dict/string/list.
https://github.com/linkedin/dustjs/wiki/Dust-Tutorial#more-on-dust-output-and-dust-filters
{Preserve all new lines, whitespace, and braces
} - Available with 2.3.3 release
It would be great to do this:
{>"tab-navs.dust" activeTab="topic"/}
{>"base-layout.dust" pageClass="page-home" noSidebar="on"/}
This works:
{>"{filename}.html"/}
This doesn't work:
{>"subfolder/{filename}.html"/}
Looks for "subfolder/" instead
I've fixed this in my local copy and will submit a pull request shortly.
I've been playing around with 'consumption tracking' of ashes templates for a while, but haven't figured out a good approach yet. I figured I should post here and perhaps someone else has been working on this task as well...
What I would like to accomplish: tracking what objects/assets are accessed/consumed in our templates via ashes. We render in ashes and dust, so this would allow for passing the data structure for a given template through a "sieve" when rendering any templates client-side (i.e. Ashes can potentially reduce a 100k json payload to the 15k that will be used) and also help tailor the data population.
I originally tried to do this via the data objects passed in to ashes, but that can't handle alternate logic comparisons.
I imagine I can't be alone in having tried to optimize this bit... right?
I noticed that missing parameters are rendered as empty strings.
>>> ashes_env.register_source('hello', 'Hello, {name}!')
<Template name='hello'>
>>> ashes_env.render('hello', {})
'Hello, !'
It would be nice if it was possible to opt-in to errors. My use case is that I want to test that I am not passing the wrong parameters for a template.
Thanks in advance, I like the library.
I'm very new to this library and the first question I have in mind (you may find it trivial): is there any flexible way to extend the list of features from https://github.com/mahmoud/ashes#compatibility?
More specifically, I am thinking about a way to inject external functions. If comfortable with the context, something similar to the Jinja filters. E.g.:
context.register_feature('virtual_name', feature_function_name)
And use the feature as virtual_name
inside the template.
Is this currently possible or on the roadmap?
Thanks,
Mircea
Reminder, as requested. :-)
i just did an update and 0.7.6 jumped to 15.0.0 on PyPi
same thing on the github tag.
there's no changelog or explanation for this numbering (which is odd).
Code
ashesenv.render('template.dust', { 'count': 10 })
Template
{@gt key=count value=0}
expected
{:else}
unexpected
{/gt}
{@gt key=count value=1}
expected
{:else}
unexpected
{/gt}
{@gt key=count value=2}
expected
{:else}
unexpected
{/gt}
Output
expected
expected
unexpected
Apologies if I've missed this in the docs but what are my options for calling plain old python functions directly from the templates? Is this easy/possible?
The equivalent of something like: { get_current_username() }
Opened on behalf of @jvanasco, based on a comment on #4:
"I'd love to see the @contextDump
helper extension. debugging is possible , but a bit of a pain , without it."
I'm curious, what aspects of @contextDump
are most useful for you? Just seeing the rendering context/model (whatever it's called, the dictionary of data passed in)? Or do you want to see the codegen'd code and everything, like LinkedIn's apparently supports with key="full" and so forth. Personally I feel the latter is a bit overkill, but could see some simpler functionality as convenient.
It would be great if the bottle
code were isolated away (or controlled by an environment variable)
These lines are what I'm referring to.
https://github.com/mahmoud/ashes/blob/master/ashes.py#L2129-L2176
It would be nice if the bottle import could be split out to another file, or at least suppressed with an environment variable. We have bottle
installed in our virtualenv for some specific services in a deployment (unrelated to an ashes process); having a dozen uswgi workers (re)start with an unnecessary 5.5MB load and memory hit is a bit annoying.
AshesEnv.load_all
only returns the templates; it does not register them into the environment.
BaseAshesEnv.load_all
actually loads the templates. it has a kwarg do_register=True
, which then runs this bit:
if do_register:
for t in tmpls:
self.register(t)
I'd suggest changing AshesEnv.load_all
to have the same functionality OR update the docstring to note that it doesn't actually load templates into the environment -- it just fetches them.
Code:
ashesenv.register_source('url', '{q|u}')
ashesenv.render('url', {'q': u'中文'})
Output:
KeyError: u'\u4e2d'
Trying to template a nested list as follows:
{#.}
row{~n}
{#.}
{.}{~n}
{/.}
{/.}
Given data of say: [[1,2], [3,4]]
You'd expect:
row
1
2
row
3
4
as output, but instead, this happens:
Traceback (most recent call last):
...
File ".../local/lib/python2.7/site-packages/ashes.py", line 1906, in render
return tmpl.render(model, self)
File ".../local/lib/python2.7/site-packages/ashes.py", line 1780, in render
self.render_chunk(chunk, Context.wrap(env, model)).end()
File ".../local/lib/python2.7/site-packages/ashes.py", line 1787, in render_chunk
return self.render_func(chunk, context)
File "<string>", line 11, in render
File "<string>", line 4, in body_0
File ".../local/lib/python2.7/site-packages/ashes.py", line 1572, in section
head.pop('$len', None)
TypeError: pop() takes at most 1 argument (2 given)
The linkedin fork introduced two extensions to the language: https://github.com/linkedin/dustjs/wiki/Dust-Tutorial
{@idx}{.}{/idx}
, however it's a primitive)it would be great if ashes supported them.
in the example below, kwargs do not transfer from parent to child.
01_parent.dust
<!-- 01_parent.dust -->
<h1>01_parent</h1>
{>"02_child.dust" animal="dog" name="bear"/}
<!-- /01_parent.dust -->
02_child.dust
<!-- 02_child.dust -->
<h1>02_child</h1>
animal={animal}
name={name}
<!-- /02_child.dust -->
here's the same thing in javascript using the dust library
var parent = '<!-- 01_parent_dust --><h1>01_parent</h1>{>"02_child_dust" animal="dog" name="bear"/}<!-- /01_parent_dust -->';
var child = '<!-- 02_child_dust --><h1>02_child</h1>animal={animal} name={name}<!-- /02_child_dust -->';
dust.loadSource(dust.compile(parent, '01_parent_dust'));
dust.loadSource(dust.compile(child, '02_child_dust'));
dust.render("01_parent_dust", {}, function(err, out) {
console.log(out);
});
i'm not sure how/where to fix this.
Your comment: "A quick example (which will work again soon):", are you referring to ashes.load throwing this error "TypeError: load() takes exactly 2 arguments (3 given)"? At least that is the behavior I am seeing. "ashes.load('app.dust', 'tmpl')" triggers the error.
Have you integrated ashes into any simple web frameworks such as bottle.py, web.py, etc? I started down the path of writing an adaptor for bottle.py extending the BaseTemplate API. No success so far but so I wanted to check with you on the question above.
FYI, bottle.py template API info: https://bottle.readthedocs.org/en/latest/api.html#templates
Thanks man!
~marc
I noticed this small peculiarity while going through the code.
https://github.com/mahmoud/ashes/blob/master/ashes.py#L1750
https://github.com/mahmoud/ashes/blob/master/ashes.py#L2082
path
, which is an arg, is submitted in a different position as a kwarg. This is valid Python, but one of those odd behavioral things that is usually unknown to junior developers. I just wanted to suggest making it the first argument.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.