Conversion of Cheetah Generator to Jinja Generator for template inheritance.

206 views
Skip to first unread message

Chris Davies-Barnard

unread,
Feb 5, 2016, 1:13:21 PM2/5/16
to weewx-development
Evening all, 

I'm trying to convert Cheetah Generator to a Jinja version so I can use template inheritance in my skin.   I have got so far and I can render simple templates e.g.   (obj1 will make more sense further down)

<div id="content">
  <p>{{ month_name }}</p>

  <p>{{ obj1.station.location }}</p>
</div>

But I'm stuck converting the objects into dictionaries.  I have modified getSearchList so it now looks like this:

def _getSearchList(self, encoding, timespan, default_binding):
  """Get the complete search list to be used by Jinja."""

  # Get the basic search list
  timespan_start_tt = time.localtime(timespan.start)
  #JINJA: Changed to we return a dictionary not a list
  searchList = self.outputted_dict
  searchList['month_name'] = time.strftime("%b", timespan_start_tt)
  searchList['year_name'] = timespan_start_tt[0]
  searchList['encoding'] = encoding
  # Bind to the default_binding:
  db_lookup = self.db_binder.bind_default(default_binding)

  # Then add the V3.X style search list extensions
  count = 0
  for obj in self.search_list_objs:
    searchList["obj"+str(count)] = obj.get_extension_list(timespan, db_lookup)
   count += 1
 
  pprint(searchList)

and the final pprint line returns the following where the numbers are temp additions to show what I am after but with obj0 etc being descriptive.   

{'obj0': <weewx.jinjagenerator.Almanac object at 0x112c943d0>,

 'obj1': <weewx.jinjagenerator.Station object at 0x113045990>,

   'obj2': <weewx.tags.TimeBinder object at 0x113045e90>,

   'obj3': <weewx.jinjagenerator.UnitInfo object at 0x113045a50>,

   'obj4': <weewx.jinjagenerator.Extras object at 0x113045bd0>,

 'SummaryByMonth': [],

 'SummaryByYear': [],

 'encoding': 'html_entities',

 'month_name': 'May',

 'year_name': 2015
}


I guess it might be that I need to change something further down in the SearchList class so that dictionaries are returned and not objects.

Anyway,  look forward to hearing from you!!

Thanks

Chris

Thomas Keffer

unread,
Feb 5, 2016, 4:45:19 PM2/5/16
to Chris Davies-Barnard, weewx-development
I'm not following what you mean by "converting the objects into dictionaries." Which objects? Do you mean the results of a dot notation expression like obj1.station.location? If so, remember that most dot expressions return instances of  ValueHelpers, not simple dictionaries. ValueHelpers support unit conversion and formatting.

Or, maybe you mean something else.

In any case, Cheetah supports inheritance.

-tk


Chris Davies-Barnard

unread,
Feb 5, 2016, 6:58:34 PM2/5/16
to weewx-development
Ok, ignore me. It's been a long week and a few variations on google search and I think I have found what I'm looking for.

http://www.cheetahtemplate.org/docs/users_guide_html_multipage/inheritanceEtc.block.html

Thanks again for the response.

Thomas Keffer

unread,
Feb 5, 2016, 7:06:53 PM2/5/16
to Chris Davies-Barnard, weewx-development
It's really a shame that the team that developed Cheetah has abandoned it. It's really a remarkable library, full of pleasant surprises. Every time I dig into it, I discover something new.

-tk

Chris Davies-Barnard

unread,
Feb 6, 2016, 2:12:43 AM2/6/16
to weewx-development
Agreed and on speed tests it's really one of the fastest. Django is miserably slow by comparison - my main work site is now Django. Maybe a talented scientist with a history of developing excellent weather programs that use it should take up its development? ;)

The reason I was looking is that I have written three little extensions but actually embedding them into the different pages is just loooong. So was I hoping to create some basic block snippets that could then either be inherited or extended. I must admit I was surprised when it appeared Cheetah didn't do it.

Chris

mwall

unread,
Feb 6, 2016, 8:17:17 AM2/6/16
to weewx-development

could you explain a bit more about what you're trying to do?

there is a related challenge with the cmon and forecast extensions.  each extension should provide a fully functional skin that shows what it does. ideally you could just plop that into some other report.  in practice things are a bit more complicated, and it would be nice to come up with a pattern that simplifies everything.

for example, the forecast extension defines a $forecast variable that provides access to massive amounts of forecast data.  that is fine for little stuff such as injecting the predicted high temperature or cloud cover.  but there are aggregate displays of forecast data (table, strip) that one should not have to duplicate. see http://sailing.mit.edu/weather/forecast.html for an example.

my approach is to distribute an include file in the skin, for example forecast_table.inc and forecast_strip.inc.  so if you want a forecast table in your report, just include the forecast_table.inc file.  similarly for the strip charts.  (i recently figured out how to include them multiple times so you can do it for any number of forecasts)

that's fine for weewx-generated pages, but i don't know how that would integrate with web pages from other content management systems.

one integration approach is to have weewx spit out a lower level file, such as a realtime (cumulus) or customdata (weather display) or arbitrary json file that is then read in by some php or javascript.  that is how steel series gauges works.

m

Chris Davies-Barnard

unread,
Feb 6, 2016, 2:53:15 PM2/6/16
to weewx-development
Hi Matt,

So as you will be aware I have written a couple of extensions recently and am working on a third but to add them to my skin I would need to bootstrap all the extension skins and then add the appropriate links to all other files.   This to me seems a bit long winded.

What I would like is a base.html.tmpl with declared blocks that can be extended by each page in the main weewx skin and extension skins.  

I guess this would also work with template-snippets so if you wanted to put a forecast on a page or a wunderground sticker you could just include it once and it would appear on all pages.

I don't feel I'm explaining myself well but it makes total sense to me having done a lot of web development with a variety of CMS.

Chris

mwall

unread,
Feb 6, 2016, 4:11:28 PM2/6/16
to weewx-development
try this on for size:

there are two types of skin extensions: (1) those that result in comprehensive/standalone report, and (2) those that are a component that can be used in another report.

for example, the ForecastVariables search list extension is an example of (2) - it provides the $forecast variable that can be used in other templates.

the cmon extension is an example of (1) - it is a standalone report that displays information about computer health.

however, the boundary between (1) and (2) is not really this well-defined.  for example, the exfoliation skin includes a 'station' page that is basically the skin part of the cmon extension, it uses $forecast to embed individual values, and it includes forecast_table.inc to display extensive forecast data.

each weewx extension should stand on its own (easier to test, install, and maintain; less chance of one extension breaking another), but it should be easy to make compound extensions, e.g., embed the space station extension into the index.html of any other weewx report.

i guess what i'm looking for is some kind of standard/pattern for embedding the output from one extension into another.

so far the best i've got is the .inc files (e.g., forecast_table.inc and forecast_strip.inc)

but it still feels like i'm fiddling with sticks when i'd like to be working with pre-fab assemblies.

m

Chris Davies-Barnard

unread,
Feb 6, 2016, 4:36:13 PM2/6/16
to weewx-development
Ok,  I'm with you.... So....  What we need is....

1)   A Base Template that all other pages and extensions inherit.   Anyone making a standalone extension can just inherit the base template and put their output in the content block.  See http://docs.makotemplates.org/en/latest/defs.html#using-blocks for ideas.

2) An inc folder that contains extensionname.inc files that can be included in the base template and therefore would be rendered into all pages automatically or into specific pages by overriding certain blocks.  Much like the Django templating system.

I'm also wondering whether we could use the template system to populate/render a CSS file from a template using colors specified in skin.conf?

Thoughts?

Chris

PS:  Currently looking at Mako as an alternative to Cheetah and Jinja.









On Friday, 5 February 2016 18:13:21 UTC, Chris Davies-Barnard wrote:

Chris Davies-Barnard

unread,
Feb 7, 2016, 6:55:00 AM2/7/16
to weewx-development
Hi,  

So I've been running three sequential attempts at improving the templating using Cheetah, Jinja and Mako and in all three instances I'm hitting a brick wall.

  1. Jinja:  I got this working pretty quickly with blocks and inherited templates but soon ran into issues with the current, week and yearly stats and their value helpers.  Don't know enough about the internal workings of Weewx to get past this point.
  2. Mako:  As above.
  3. Cheetah:   I cannot for the life of me figure out how to get extended templates to work  The documentation says:

4.6 Object-Oriented Documents

Because Cheetah documents are actually class definitions, templates may inherit from one another in a natural way, using regular Python semantics. For instance, consider this template, FrogBase.tmpl:

#def title
This document has not defined its title
#end def
#def htTitle
$title
#end def
<HTML><HEAD>
<TITLE>$title</TITLE>
</
HEAD><BODY>
<H1>$htTitle</H1>
$body
</
BODY></HTML>

And its subclassed document, Frog1.tmpl:

#from FrogBase import FrogBase
#extends FrogBase
#def title
The Frog Page
#end def
#def htTitle
The <IMG SRC="Frog.png"> page
#end def
#def body
... lots of info about frogs ...
#end def

This is a classic use of inheritance. The parent ``template'' is simply an abstract superclass. Each document specializes the output of its parent. For instance, here the parent defines $htTitle so that by default it's identical to whatever the$title is, but it can also be customized.


but I cannot get it to work and where as Jinja/Mako are well documented Cheetah is not.

Feeling Defeated....

Chris



On Friday, 5 February 2016 18:13:21 UTC, Chris Davies-Barnard wrote:
Message has been deleted

Radar

unread,
Feb 7, 2016, 9:13:46 AM2/7/16
to weewx-development
i don't know python but this is how i got it to work
cheetah -c FrogBase.tmpl
cheetah -c Frog1.tmpl
python Frog1.py

to test it with weewx 3.3.1 i did
renamed index.html.tmpl index.tmpl
cheetah -c index.tmpl
mv index.py to weewx/bin
made a file call it index.html.tmpl
#from index import index
#extends index
#def Tren_arrow($t)
  .... etc ....
#end def

that worked for me but remder i don't know python it is trail and lots of errors

Chris Davies-Barnard

unread,
Feb 7, 2016, 1:47:21 PM2/7/16
to weewx-development
Thanks Radar,

I was hoping it was going to be a bit simpler.   I have made some progress and am now thinking about how to fit it into Weewx.

Chris

Chris Davies

unread,
Feb 9, 2016, 12:56:36 PM2/9/16
to Thomas Keffer, weewx-development
Hi Tom,

Thank you (as always) for the wise and knowledgable response.   I don't know why I didn't see the Cheetah inheritance when I looked.    

Can we do template snippets in Cheetah e.g. Create a header segment that we can share/import across all pages?

Going back to Jinja (Python 3 compatible ;))  At the moment I have to give the station instance an arbitrary key so I can pass it back as a dictionary which means I'm looking at obj2.station... rather than just station....   Maybe I'm looking at it the wrong way and I can pass a list instead - I'll do some reading.

Thanks again and have a good weekend.

Chris



Sent from my iPad

mwall

unread,
Feb 9, 2016, 1:07:10 PM2/9/16
to weewx-development, tke...@gmail.com
On Tuesday, February 9, 2016 at 12:56:36 PM UTC-5, Chris Davies-Barnard wrote:
Can we do template snippets in Cheetah e.g. Create a header segment that we can share/import across all pages?

use the #include directive.

in file 'header.inc':

<div class='header'>
This is the header
</div>

in file 'footer.inc':

<div class='footer'>
This is the footer
</div>

in file a.html.tmpl:

#include "header.inc"
<p>this is the middle bit for a</p>
#include "footer.inc"

in file b.html.tmpl:

#include "header.inc"
<p>this is the middle bit for b</p>
#include "footer.inc"

other than a path bug in the early 2.x versions, this has worked flawlessly in weewx for a few years now.

m

Thomas Keffer

unread,
Feb 9, 2016, 1:11:47 PM2/9/16
to mwall, weewx-development
This seems a heck of a lot simpler than compiling templates.

-tk

mwall

unread,
Feb 9, 2016, 1:15:27 PM2/9/16
to weewx-development, mw...@users.sourceforge.net
On Tuesday, February 9, 2016 at 1:11:47 PM UTC-5, Tom Keffer wrote:
This seems a heck of a lot simpler than compiling templates.

you can even parameterize the inclusions.  for example, if you define a file forecast_table.inc that uses a variable $forecast_source that indicates which forecast to display, then you can include the file multiple times like this:

#set global $forecast_source = 'NWS'
#include "forecast_table.inc"
#set global $forecast_source = 'WU'
#include "forecast_table.inc"

the 'global' is necessary to make the 'set' apply across file scope.

you can even do c/c++ style inclusion guards, if necessary.

m
Message has been deleted

Chris Davies-Barnard

unread,
Feb 9, 2016, 2:44:51 PM2/9/16
to weewx-development
Well now I feel really stupid! 

But in fairness to myself I actually made this same step/conclusion today.  But only after getting the python module imports to work on the fly and I still need to figure out how to use those dynamic imports to render templates.   I think I made the mistake of using extend when I first tried the non compiled import rather than include.   Having spent a few months developing the new school site (http://compu2learn.uk/)  in Django I got myself confused!

For now with the time I have available, this basic include seems a lot easier.  So, finally I can get my template sorted and use it for adding extensions easily.  



On Friday, 5 February 2016 18:13:21 UTC, Chris Davies-Barnard wrote:
Reply all
Reply to author
Forward
0 new messages