I need a better explaination about how the formatter/text_python.py classes are supposed to work. It looks like it is a wrapper for the real formatter (like text_html), but which saves off a cached copy as a chunk of python code.
It optimizes rendering speed by either inserting dynamic calls to the formatter (when the output of that code is not the same for everybody, everytime, in any state of the wiki) or inserting pre-calculated, static text (when the output is the same, ever).
I seems though that this wrapper is affecting the order of the calls being made by the parser (such as wiki.py) and the real formatter. The result is that the real formatter is seeing nonsensible call sequences.
For example in 1.5.0 text_python's Formatter.heading() method:
def heading(self, on, depth, **kw): if on: code = [ self.__adjust_languge_state(), # <---- TYPO !!! 'request.write(%s.heading(%r, %r, **%r))' % (self.__formatter, on, depth, kw), ] return self.__insert_code(''.join(code)) else: return self.formatter.heading(on, depth, **kw)
Now I've verified that even on a page with nothing but a = Hello = in it, that the wiki parser (once it gets to the content-div) is making two calls in the order,
- formatter.heading( 1, ....)
- formatter.heading( 0, ....)
But the text_html formatter is seeing this call first,
- formatter.heading( 0, ....)
Because the text_python is intercepting the first call.
When looking at the FINAL output, generated by the bytecode, the order should be right. BUT: the opening call maybe does not happen when producing the bytecode, as it is only inserted as "source code" (and not really called at that time). It will be called, when the compiled bytecode is executed on page view. The closing call is expected to give static html, so the result of it is inserted at "compile time". Depending on how the formatter works, this is maybe a problem. Maybe FlorianFesti wants to give some more comments.
Thus the html formatter is told to close a heading before it has opened one.
So far this may have just happened to have produced sloppy but renderable html by sheer luck. What's the black magic here? -- DeronMeranda 2006-01-19 10:27:27
The black magic is that we assume that the closing heading tag does not depend on the beginning tag. This is true for HTML but might be wrong for other formatters. If there is a real world example I would suggest to make the closing heading tag dynamic, too -- FlorianFesti 2006-01-22 16:54:46
So in essence there seem to be additional unspoken requirements for all formatters:
A formatter should not assume that methods are called in any strict linear order.
No, thats wrong. Most formatters depend on linear non-stacked calls. Actually, this is just true for formatters that want to be cacheable. But the text_python.py formatter is incompatible to non-HTML markup anyway, so do not try that without "fixing" it.
A formatter class should not assume that a single formatter instance/object will be used during the generation of a page.
Doesn't make sense IMHO. A page is only of one data type. Either it is output in PDF or HTML or foo or bar but ont in some starange mixture -- FlorianFesti 2006-01-22 16:54:46
These are far-reaching requirements that restrict the kind of formatters that can be created. For example I have been seriously thinking writing a PDF formatter. However the assumption that a header always consists of three disctinct pieces (a header-start, the header-text, and a header-end) and that all three components can be generated independently in any order is absurd. A PDF writer has to draw the entire header all at once. So me-thinks this may spoil my PDF plans. -- DeronMeranda 2006-01-19 17:57:33
If your formatter has to maintain a internal stack it is obviously impossible to cache parts of a page. Simply don't use cache then. -- FlorianFesti 2006-01-22 16:54:46