diff options
author | R. Tyler Ballance <tyler@monkeypox.org> | 2009-11-16 21:09:13 -0800 |
---|---|---|
committer | R. Tyler Ballance <tyler@monkeypox.org> | 2009-11-16 21:09:13 -0800 |
commit | d9ce7916e309e2393d824e249f512d2629e5e181 (patch) | |
tree | 6b7ad5cd6292f6e017e048fbeb4551facbabd174 /docs/devel_guide_src/cache.tex | |
parent | e43765a679b84c52df875e9629d303e304af50a1 (diff) | |
download | python-cheetah-docs.tar.gz |
Revert "Delete the "old" docs directory to make way for fancy smancy sphinx"docs
This reverts commit 5dc95cfcd015628665d3672e56d0551943b5db6b.
Diffstat (limited to 'docs/devel_guide_src/cache.tex')
-rwxr-xr-x | docs/devel_guide_src/cache.tex | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/docs/devel_guide_src/cache.tex b/docs/devel_guide_src/cache.tex new file mode 100755 index 0000000..043b8cf --- /dev/null +++ b/docs/devel_guide_src/cache.tex @@ -0,0 +1,365 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Caching placeholders and \#cache} +\label{cache} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Dynamic placeholder -- no cache} +\label{cache.dynamic} + +The template: +\begin{verbatim} +Dynamic variable: $voom +\end{verbatim} + +The command line and the output: +\begin{verbatim} +% voom='Voom!' python x.py --env +Dynamic variable: Voom! +\end{verbatim} + +The generated code: +\begin{verbatim} +write('Dynamic variable: ') +write(filter(VFS(SL,"voom",1))) # generated from '$voom' at line 1, col 20. +write('\n') +\end{verbatim} + +Just what we expected, like any other dynamic placeholder. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Static placeholder} +\label{cache.static} + +The template: +\begin{verbatim} +Cached variable: $*voom +\end{verbatim} + +The command line and output: +\begin{verbatim} +% voom='Voom!' python x.py --env +Cached variable: Voom! +\end{verbatim} + +The generated code, with line numbers: +\begin{verbatim} + 1 write('Cached variable: ') + 2 ## START CACHE REGION: at line, col (1, 19) in the source. + 3 RECACHE = True + 4 if not self._cacheData.has_key('19760169'): + 5 pass + 6 else: + 7 RECACHE = False + 8 if RECACHE: + 9 orig_trans = trans +10 trans = cacheCollector = DummyTransaction() +11 write = cacheCollector.response().write +12 write(filter(VFS(SL,"voom",1))) # generated from '$*voom' at line 1, + # col 19. +13 trans = orig_trans +14 write = trans.response().write +15 self._cacheData['19760169'] = cacheCollector.response().getvalue() +16 del cacheCollector +17 write(self._cacheData['19760169']) +18 ## END CACHE REGION + +19 write('\n') +\end{verbatim} + +That one little star generated a whole lotta code. First, instead of an +ordinary \code{VFS} lookup (searchList) lookup, it converted the +placeholder to a lookup in the \code{.\_cacheData} dictionary. Cheetah also +generated a unique key (\code{'19760169'}) for our cached item -- this is its +cache ID. + +Second, Cheetah put a pair of if-blocks before the \code{write}. The first +(lines 3-7) determine whether the cache value is missing or out of date, and +sets local variable \code{RECACHE} true or false. +This stanza may look unnecessarily verbose -- lines 3-7 could be eliminated if +line 8 was changed to +\begin{verbatim} +if not self._cacheData.has_key('19760169'): +\end{verbatim} +-- but this model is expandable for some of the cache features we'll see below. + +The second if-block, lines 8-16, do the cache updating if necessary. +Clearly, the programmer is trying to stick as close to normal (dynamic) +workflow as possible. Remember that \code{write}, even though it looks like a +local function, is actually a method of a file-like object. So we create a +temporary file-like object to divert the \code{write} object into, then read +the result and stuff it into the cache. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Timed-refresh placeholder} +\label{cache.timed} + +The template: +\begin{verbatim} +Timed cache: $*.5m*voom +\end{verbatim} + +The command line and the output: +\begin{verbatim} +% voom='Voom!' python x.py --env +Timed cache: Voom! +\end{verbatim} + +The generated method's docstring: +\begin{verbatim} +""" +This is the main method generated by Cheetah +This cache will be refreshed every 30.0 seconds. +""" +\end{verbatim} + +The generated code: +\begin{verbatim} + 1 write('Timed cache: ') + 2 ## START CACHE REGION: at line, col (1, 15) in the source. + 3 RECACHE = True + 4 if not self._cacheData.has_key('55048032'): + 5 self.__cache55048032__refreshTime = currentTime() + 30.0 + 6 elif currentTime() > self.__cache55048032__refreshTime: + 7 self.__cache55048032__refreshTime = currentTime() + 30.0 + 8 else: + 9 RECACHE = False +10 if RECACHE: +11 orig_trans = trans +12 trans = cacheCollector = DummyTransaction() +13 write = cacheCollector.response().write +14 write(filter(VFS(SL,"voom",1))) # generated from '$*.5m*voom' at + # line 1, col 15. +15 trans = orig_trans +16 write = trans.response().write +17 self._cacheData['55048032'] = cacheCollector.response().getvalue() +18 del cacheCollector +19 write(self._cacheData['55048032']) +20 ## END CACHE REGION + +21 write('\n') +\end{verbatim} + +This code is identical to the static cache example except for the docstring +and the first if-block. (OK, so the cache ID is different and the comment on +line 14 is different too. Big deal.) + +Each timed-refresh cache item has a corrsponding private attribute +\code{.\_\_cache\#\#\#\#\#\#\#\#\_\_refreshTime} giving the refresh time +in ticks (=seconds since January 1, 1970). The first if-block (lines 3-9) +checks whether the cache value is missing or its update time has passed, and if +so, sets \code{RECACHE} to true and also schedules another refresh at the next +interval. + +The method docstring reminds the user how often the cache will be refreshed. +This information is unfortunately not as robust as it could be. Each +timed-cache placeholder blindly generates a line in the docstring. If all +refreshes are at the same interval, there will be multiple identical lines +in the docstring. If the refreshes are at different intervals, you get a +situation like this: +\begin{verbatim} +""" +This is the main method generated by Cheetah +This cache will be refreshed every 30.0 seconds. +This cache will be refreshed every 60.0 seconds. +This cache will be refreshed every 120.0 seconds. +""" +\end{verbatim} +The docstring tells only that ``something'' will be refreshed every 60.0 +seconds, but doesn't reveal {\em which} placeholder that is. Only if you +know the relative order of the placeholders in the template can you figure +that out. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{Timed-refresh placeholder with braces} +\label{cache.timed.braces} + +This example is the same but with the long placeholder syntax. It's here +because it's a Cheetah FAQ whether to put the cache interval inside or outside +the braces. (It's also here so I can look it up because I frequently forget.) +The answer is: outside. The braces go around only the placeholder name (and +perhaps some output-filter arguments.) + +The template: +\begin{verbatim} +Timed with {}: $*.5m*{voom} +\end{verbatim} + +The output: +\begin{verbatim} +Timed with {}: Voom! +\end{verbatim} + +The generated code differs only in the comment. Inside the cache-refresh +if-block: +\begin{verbatim} +write(filter(VFS(SL,"voom",1))) # generated from '$*.5m*{voom}' at line 1, + #col 17. +\end{verbatim} + +If you try to do it this way: +\begin{verbatim} +Timed with {}: ${*.5m*voom} ## Wrong! +\end{verbatim} +you get: +\begin{verbatim} +Timed with {}: ${*.5m*voom} +\end{verbatim} +\verb+${+ is not a valid placeholder, so it gets treated as ordinary text. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{\#cache} +\label{cache.directive} + +The template: +\begin{verbatim} +#cache +This is a cached region. $voom +#end cache +\end{verbatim} + +The output: +\begin{verbatim} +This is a cached region. Voom! +\end{verbatim} + +The generated code: +\begin{verbatim} + 1 ## START CACHE REGION: at line, col (1, 1) in the source. + 2 RECACHE = True + 3 if not self._cacheData.has_key('23711421'): + 4 pass + 5 else: + 6 RECACHE = False + 7 if RECACHE: + 8 orig_trans = trans + 9 trans = cacheCollector = DummyTransaction() +10 write = cacheCollector.response().write +11 write('This is a cached region. ') +12 write(filter(VFS(SL,"voom",1))) # generated from '$voom' at line 2, + # col 27. +13 write('\n') +14 trans = orig_trans +15 write = trans.response().write +16 self._cacheData['23711421'] = cacheCollector.response().getvalue() +17 del cacheCollector +18 write(self._cacheData['23711421']) +19 ## END CACHE REGION +\end{verbatim} + +This is the same as the \code{\$*voom} example, except that the plain text +around the placeholder is inside the second if-block. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{\#cache with timer and id} +\label{cache.directive.timer} + +The template: +\begin{verbatim} +#cache timer='.5m', id='cache1' +This is a cached region. $voom +#end cache +\end{verbatim} + +The output: +\begin{verbatim} +This is a cached region. Voom! +\end{verbatim} + +The generated code is the same as the previous example except the first +if-block: +\begin{verbatim} +RECACHE = True +if not self._cacheData.has_key('13925129'): + self._cacheIndex['cache1'] = '13925129' + self.__cache13925129__refreshTime = currentTime() + 30.0 +elif currentTime() > self.__cache13925129__refreshTime: + self.__cache13925129__refreshTime = currentTime() + 30.0 +else: + RECACHE = False +\end{verbatim} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\subsection{\#cache with test: expression and method conditions} +\label{cache.directive.test} + +The template: +\begin{verbatim} +#cache test=$isDBUpdated +This is a cached region. $voom +#end cache +\end{verbatim} + +(Analysis postponed: bug in Cheetah produces invalid Python.) + +%The output: +%\begin{verbatim} +%\end{verbatim} + +%The generated code: +%\begin{verbatim} +%\end{verbatim} + + +The template: +\begin{verbatim} +#cache id='cache1', test=($isDBUpdated or $someOtherCondition) +This is a cached region. $voom +#end cache +\end{verbatim} + +The output: +\begin{verbatim} +This is a cached region. Voom! +\end{verbatim} + +The first if-block in the generated code: +\begin{verbatim} +RECACHE = True +if not self._cacheData.has_key('36798144'): + self._cacheIndex['cache1'] = '36798144' +elif (VFS(SL,"isDBUpdated",1) or VFS(SL,"someOtherCondition",1)): + RECACHE = True +else: + RECACHE = False +\end{verbatim} +The second if-block is the same as in the previous example. If you leave +out the \code{()} around the test expression, the result is the same, although +it may be harder for the template maintainer to read. + +You can even combine arguments, although this is of questionable value. + +The template: +\begin{verbatim} +#cache id='cache1', timer='30m', test=$isDBUpdated or $someOtherCondition +This is a cached region. $voom +#end cache +\end{verbatim} + +The output: +\begin{verbatim} +This is a cached region. Voom! +\end{verbatim} + +The first if-block: +\begin{verbatim} +RECACHE = True +if not self._cacheData.has_key('88939345'): + self._cacheIndex['cache1'] = '88939345' + self.__cache88939345__refreshTime = currentTime() + 1800.0 +elif currentTime() > self.__cache88939345__refreshTime: + self.__cache88939345__refreshTime = currentTime() + 1800.0 +elif VFS(SL,"isDBUpdated",1) or VFS(SL,"someOtherCondition",1): + RECACHE = True +else: + RECACHE = False +\end{verbatim} + +We are planning to add a \code{'varyBy'} keyword argument in the future that +will allow separate cache instances to be created for a variety of conditions, +such as different query string parameters or browser types. This is inspired by +ASP.net's varyByParam and varyByBrowser output caching keywords. Since this is +not implemented yet, I cannot provide examples here. + +% Local Variables: +% TeX-master: "devel_guide" +% End: |