[ZPT] Truncating strings
Shane Hathaway
shane at zope.com
Wed Oct 22 22:47:58 EDT 2003
On Tue, 21 Oct 2003, Ian Bicking wrote:
> [I think tal:format would imply structure] But the current access to
> these sorts of functions through the modules variable is painful at
> best. And it seems like the functions in PythonScripts.standard are a
> little sparse.
Once again, this would be beautifully simple with subpath prefixes.
Behold:
<span tal:content="var/fmt:truncate/10"></span>
I keep trying to tell everyone why this is so great. Does anyone listen?
:-)
If the syntax looks a little magical, here is what's going on. First, the
path expression visits the name "var" and keeps its value in a temporary
variable. It then looks at the next element of the path expression,
"fmt:truncate". Normally, the path expression would look for an attribute
or item by that name, but since the name has a colon, the path expression
machinery takes a different route, knowing that colons mean it should use
a prefix implementation instead of traversing the normal way. It finds a
prefix implementation named "fmt" in the registry of prefixes. It
probably finds the implementation in the global registry.
Then the path expression machinery says to the "fmt" prefix
implementation, "please traverse from the object I'm giving you, to the
name 'truncate', and return what you got". The "fmt" prefix
implementation knows about a function called 'truncate' and calls it.
The 'truncate' function doesn't actually truncate yet, though, because we
haven't looked at the number 10 yet, so we don't know how much to
truncate. Instead, this truncate function returns an object which, when
traversed, will actually do the truncating.
So the path expression machinery gets the truncator object and continues
traversal. The next element in the path is the string "10". That string
doesn't have a colon, so the machinery uses the default traversal. It
looks for an attribute called "10"... nope, no such attribute. Then it
looks for an item called "10". The truncator has a __getitem__ method
that truncates to the specified number of characters, returning a string.
The path expression gets this truncated string back, and finally, the path
expression returns the truncated string.
Alternatively, the truncate function could use some trick to consume the
next element of the path, rather than return a truncator object. This is
probably faster, but not as elegant: now the truncate function is tightly
bound to path expressions. Originally, it didn't care whether a path
expression or some other thing called it. OTOH, the truncate function is
trivial, so it's probably better to ignore elegance in this case.
Expedience wins.
Now, consider the oddness and slight magic of Zope's default traverser.
Even in Zope 3, the default traverser looks for an attribute, then if it
finds no attribute, it looks for an item. This leads to several
unanswerable questions. If both attribute access and item access fail,
should it raise an AttributeError, a KeyError, or something else? How do
you force the path expression to look for an item of a dictionary called
"key"? (You can't--since dictionaries have an attribute called "key", the
lookup always stops at attribute access.) If the thing you're looking up
is a method, how do you call the method once you have the attribute? How
do you pass arguments? How do you apply operations other and attribute or
item access, such as looking up an adapter?
Subpath prefixes are aimed squarely at solving the default traversal
problem. Subpath prefixes let you use traversers other than the default.
They provide a good answer for all of the questions above: if you want to
traverse in some way other than the default, just use a prefix. Then be
imaginative about the kind of traversal you could do. (But stop before
you write something that's Turing-complete [1]. ;-) )
In any case, I hope this rambling has made the ideas behind subpath
prefixes clearer. They solve many problems I encounter daily.
[1] http://en.wikipedia.org/wiki/Turing-complete
Shane
More information about the ZPT
mailing list