mirror of
https://github.com/weewx/weewx.git
synced 2026-05-19 15:25:32 -04:00
Finished a more complete explanation of how weewx tags interact with the search list.
This commit is contained in:
@@ -1171,7 +1171,7 @@ Sunrise, sunset: 06:51 19:30</pre>
|
||||
|
||||
<p>
|
||||
In the section on <em><a href="#templates">Customizing
|
||||
templates</a></em>, we have seen how you can change a template and
|
||||
templates</a></em>, we have seen how you can change a template and
|
||||
make use of the various tags available such as <span
|
||||
class="code">$day.outTemp.max</span> for the maximum outside
|
||||
temperature for the day. But, what if you want to introduce some
|
||||
@@ -1195,51 +1195,99 @@ Sunrise, sunset: 06:51 19:30</pre>
|
||||
The answer is to write a <em>search list extension</em>.
|
||||
</p>
|
||||
|
||||
<h3>How tags work</h3>
|
||||
<h3>How the search list works</h3>
|
||||
<p>
|
||||
But, before getting too deeply into extensions, it's worth
|
||||
taking a look at how <span class="code">weewx</span> tags work.
|
||||
Let's start by looking at a simple example: station altitude,
|
||||
available as the tag
|
||||
Let's start by taking a look at how the Cheetah <i>search list</i>
|
||||
works.
|
||||
</p>
|
||||
<p>
|
||||
The Cheetah template engine (which <span class="code">weewx</span>
|
||||
uses) finds tags by scanning a search list, a Python
|
||||
list of objects. For example, for a tag <span class="code">$foo</span>,
|
||||
the engine will scan down the list, trying each object in the
|
||||
list in turn. For each object, it will first try using <span
|
||||
class="code">foo</span> as an attribute, that is, it will try
|
||||
evaluating <span class="code"><i>obj</i>.foo</span>. If that
|
||||
raises an <span class="code">AttributeError</span> exception,
|
||||
then it will try <span class="code">foo</span> as a key, that is
|
||||
<span class="code"><i>obj</i>[key]</span>. If that raises a <span
|
||||
class="code">KeyError</span> exception, then it moves on to
|
||||
the next item in the list. The first match that does not raise
|
||||
an exception is used. If no match is found, Cheetah raises a <span
|
||||
class="code">NameMapper.NotFound</span> exception.
|
||||
</p>
|
||||
|
||||
<h3 id="how_tags_work">How tags work</h3>
|
||||
<p>
|
||||
Now let's take a look at how the search list interacts with <span
|
||||
class="code">weewx</span> tags. Let's start by looking at a
|
||||
simple example: station altitude, available as the tag
|
||||
</p>
|
||||
<pre class="tty">
|
||||
$station.altitude</pre>
|
||||
|
||||
<p>
|
||||
What this returns is not a raw value, say <span class="code">700</span>,
|
||||
nor even a string. Instead, it returns an instance of the class
|
||||
<span class="code"><i>ValueHelper</i></span>, a special class
|
||||
defined in module <span class="code">weewx.units</span>. When
|
||||
the Cheetah template generator encounters this tag, it
|
||||
eventually needs to convert it into a string. How it does this
|
||||
is like any other Python object: it calls the special method <span
|
||||
As we saw in the previous section, Cheetah will run down the
|
||||
search list, looking for an object with a key or attribute <span
|
||||
class="code">station</span>. In the default search list, <span
|
||||
class="code">weewx</span> includes one such object, an
|
||||
instance of the class <span class="code">weewx.cheetahgenerator.Station</span>,
|
||||
which has an attribute <span class="code">station</span>, so it
|
||||
gets a hit on this object.
|
||||
</p>
|
||||
<p>
|
||||
Cheetah will then try to evaluate the attribute <span
|
||||
class="code">altitude</span> on this object. Class <span
|
||||
class="code">Station</span> has such an attribute, so Cheetah
|
||||
evaluates it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
What this attribute returns is not a raw value, say <span
|
||||
class="code">700</span>, nor even a string. Instead, it
|
||||
returns an instance of the class <span class="code"><i>ValueHelper</i></span>,
|
||||
a special class defined in module <span class="code">weewx.units</span>.
|
||||
Internally, it holds the formats, labels, and conversion targets
|
||||
you specified in your configuration file. It's job is to make sure
|
||||
that the final output reflects these preferences. Cheetah doesn't know
|
||||
anything about this class. What it needs, when it has finished
|
||||
evaluating the expression <span class="code">$day.outTemp.max</span>
|
||||
is a <i>string</i>. In order to convert the <span class="code">ValueHelper</span>
|
||||
into a string, it does what every other Python object does when
|
||||
faced with this situation: it calls the special method <span
|
||||
class="code"><a style="text-decoration: none"
|
||||
href="https://docs.python.org/2/reference/datamodel.html#object.__str__">__str__</a></span>.
|
||||
Class <span class="code">ValueHelper</span> has a definition for
|
||||
this method, which applies any necessary unit conversions, then
|
||||
consults any formatting and labeling you may have specified, and
|
||||
then, finally, builds the string. The result is something like
|
||||
this method. Evaluating this function triggers the final steps
|
||||
in this process. Any necessary unit conversions are done, then
|
||||
formatting occurs and, finally, a label is attached. The result
|
||||
is a string something like
|
||||
</p>
|
||||
<p class="example_output">700 feet</p>
|
||||
<p>which is what Cheetah actually puts in the generated HTML
|
||||
file.
|
||||
</p>
|
||||
|
||||
<p>Now let's look at a more complicated example, say the
|
||||
maximum temperature since midnight:</p>
|
||||
<p>
|
||||
Now let's look at a more complicated example, one that uses <i>lazy
|
||||
evaluation</i>,say the maximum temperature since midnight:
|
||||
</p>
|
||||
<pre class="tty">$day.outTemp.max</pre>
|
||||
<p>
|
||||
When this is evaluated by Cheetah, it actually produces a chain
|
||||
of objects. At the top of this chain is class <span class="code">weewx.stats.TaggedStats</span>,
|
||||
an instance of which is supplied by the <em>search list</em>
|
||||
(more on this later). Internally, this instance stores the
|
||||
database to be hit, as well as a few other bookkeeping objects
|
||||
(mostly having to do with formatting and labeling).
|
||||
an instance of which is included in the default search list.
|
||||
Internally, this instance stores the database to be hit, as well
|
||||
as a few other bookkeeping objects (mostly having to do with
|
||||
formatting and labeling).
|
||||
</p>
|
||||
<p>
|
||||
This instance is examined by Cheetah to see if it has an
|
||||
attribute <span class="code">day</span>. It does, and it returns
|
||||
the next class in the chain, an instance of class <span
|
||||
class="code">weewx.stats.TimeSpanStats</span>. This instance
|
||||
stores not only the database, but also the requested time span,
|
||||
namely the time since midnight, internally.
|
||||
attribute <span class="code">day</span>. It does and, when it is
|
||||
evaluated, it returns the next class in the chain, an instance
|
||||
of <span class="code">weewx.stats.TimeSpanStats</span>. This
|
||||
instance stores not only the database, but also the requested
|
||||
time span, namely the time since midnight, internally.
|
||||
</p>
|
||||
<p>
|
||||
Cheetah then tries to find an attribute <span class="code">outTemp</span>
|
||||
@@ -1248,57 +1296,57 @@ $station.altitude</pre>
|
||||
types would be impractical!). Instead, class <span class="code">TimeSpanStats</span>
|
||||
returns an instance of the next class in the chain, <span
|
||||
class="code">weewx.stats.StatsTypeHelper</span>, which not
|
||||
only remembers the observation type, but also the database and
|
||||
the previously evaluated time span.
|
||||
only remembers what is already known, namely the database to be
|
||||
hit and the time span, but also adds the observation type, <span
|
||||
class="code">outTemp</span>, in this case.
|
||||
</p>
|
||||
<p>
|
||||
Cheetah then tries to find an attribute <span class="code">max</span>
|
||||
Cheetah then tries to evaluate an attribute <span class="code">max</span>
|
||||
of this class. Now, finally, the chain ends. The attribute <span
|
||||
class="code">max</span> triggers the actual calculation of the
|
||||
value, using all the known parameters: the time span, the
|
||||
observation type, and the type of aggregation, querying the
|
||||
database as necessary. This is an example of <em>lazy
|
||||
evaluation</em>. That is, the database is not actually hit until
|
||||
the last possible moment, after everything needed to do the
|
||||
evalation is known.
|
||||
value, using all the known parameters: the database to be hit,
|
||||
the time span of interest, the observation type, and the type of
|
||||
aggregation, querying the database as necessary. This is an
|
||||
example of lazy evaluation. That is, the database is not
|
||||
actually hit until the last possible moment, after everything
|
||||
needed to do the evalation is known.
|
||||
</p>
|
||||
<p>
|
||||
The results of the evaluation is then packaged up in, you
|
||||
guessed it, an instance of <span class="code"><i>ValueHelper</i></span>,
|
||||
which is what actually converts the value into the desired
|
||||
string.
|
||||
which does the final conversion to the desired units, formats
|
||||
the string, then adds a label. The results, something like
|
||||
</p>
|
||||
<p class="example_output">12°C</p>
|
||||
<p>
|
||||
are put in the generated HTML file. As you can see, a lot of
|
||||
machinery is hidden behind the deceptively simple expression <span
|
||||
class="code">$day.outTemp.max</span>!
|
||||
</p>
|
||||
|
||||
<h3>Search list</h3>
|
||||
<p> The Cheetah template engine (which <span class="code">weewx</span> uses) finds tags by
|
||||
scanning a <em>search
|
||||
list</em>,
|
||||
a Python list of objects. For example, for a tag <span class="code">$foo</span>, the
|
||||
engine will scan down the list, trying each object <span class="code">obj</span> in turn. First
|
||||
it tries using <span class="code">foo</span> as an attribute, that is,
|
||||
<span class="code">obj.foo</span>. If that raises an
|
||||
exception <span class="code">AttributeError</span>, then it will try
|
||||
<span class="code">foo</span> as a key, that is
|
||||
<span class="code">obj[key]</span>. If that raises a
|
||||
<span class="code">KeyError</span>, then it moves on to the next item
|
||||
in the list. The first match that does not raise an exception is
|
||||
returned. If no match is found, it raises a <span class="code">NameMapper.NotFound</span>
|
||||
exception.</p>
|
||||
<h3>
|
||||
Extending the list</h3>
|
||||
<p>Weewx comes with a number of objects already in the search list, but you can
|
||||
extend it. To do so, you should have some familiarity with Python, in
|
||||
particular, how to write new classes and member functions for them. </p>
|
||||
<p>Let's look at an example. The regular version of <span class="code">weewx</span>
|
||||
offers statistical summaries by day, week, month, and year. Suppose we
|
||||
would like to add two more: </p>
|
||||
<h3>Extending the list</h3>
|
||||
<p>
|
||||
As mentioned, <span class="code">weewx</span> comes with a
|
||||
number of objects already in the search list, but you can extend
|
||||
it. To do so, you should have some familiarity with Python, in
|
||||
particular, how to write new classes and member functions for
|
||||
them.
|
||||
</p>
|
||||
<p>
|
||||
Let's look at an example. The regular version of <span
|
||||
class="code">weewx</span> offers statistical summaries by day,
|
||||
week, month, and year. Suppose we would like to add two more:
|
||||
</p>
|
||||
<ul>
|
||||
<li>All-time statistics. This would allow us to display statistics such
|
||||
as the all-time high or low temperature seen at your station;</li>
|
||||
<li>Seven days statistics. While <span class="code">weewx</span> offers
|
||||
the tag <span class="code">$week</span>, this is statistics <em>since
|
||||
Sunday at midnight</em>. We would like to have statistics for a full
|
||||
week, that is since midnight seven days ago.</li>
|
||||
<li>All-time statistics. This would allow us to display
|
||||
statistics such as the all-time high or low temperature seen
|
||||
at your station;</li>
|
||||
<li>Seven days statistics. While <span class="code">weewx</span>
|
||||
offers the tag <span class="code">$week</span>, this is
|
||||
statistics <em>since Sunday at midnight</em>. We would like to
|
||||
have statistics for a full week, that is since midnight seven
|
||||
days ago.
|
||||
</li>
|
||||
</ul>
|
||||
<p>This example is included in the distribution as <span class="symcode">
|
||||
$BIN_ROOT</span><span class="code">/examples/xsearch.py</span>: </p>
|
||||
@@ -1371,7 +1419,9 @@ class MyXSearch(SearchList): #1
|
||||
</ul>
|
||||
</li>
|
||||
<li>The class <span class="code">TimeSpanStats</span> represents a
|
||||
statistical calculation over a time period. In our case, we will set
|
||||
statistical calculation over a time period. We have already met
|
||||
it in the introduction <i><a href="#how_tags_work">How tags work</a></i> above.
|
||||
In our case, we will set
|
||||
it up to represent the statistics over all possible times. The class
|
||||
takes 4 parameters.
|
||||
<ul>
|
||||
@@ -1437,7 +1487,7 @@ class MyXSearch(SearchList): #1
|
||||
[[SummaryByMonth]]
|
||||
...
|
||||
</pre>
|
||||
<p>Our addition has been <span class="highlight"> highlighted </span>. Note that it is in the section
|
||||
<p>Our addition has been <span class="highlight">highlighted</span>. Note that it is in the section
|
||||
<span class="code">[CheetahGenerator]</span>.
|
||||
(This section was called <span class="code">[FileGenerator]</span> in
|
||||
earlier versions of <span class="code">weewx</span>, a name which will
|
||||
|
||||
Reference in New Issue
Block a user