Hi, as some of you might have seen from the checkins, I'm trying to complete Andreas's work of bringing the Zope 3 ZPT engine to Zope 2. Andreas has done a great job dealing with the very non-trivial unicode and persistency-compabitibility issues already. I've taken over since to fix up Five accordingly (which is basically done) and make everything else work again (also nearly done). Hanno Schlichting from the Plone crowd has helped me a lot there by running 3rd party software like the CMF (which uses the PageTemplate implementation for filesystem-based templates) against our branch and pointing out backward compatibility issues (which could be fixed with his help). So far it's looking good. There are many subtle differences between the two implementations that make progress slow. Right now I've hit three minor problems (I'm sure there are more, but this is what I have on my plate right for now) regarding some incompatibilities between the Zope 2 and Zope 3 implementations. I've sketched out the problems next to their corresponding (failing) unit tests (look for the XXX comments): http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag... http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag... All three require some effort in order to provide full backward compatibility. Thus I thought I run these by you, let you read what I think about them and hopefully get some feedback on how to proceed. Silence is treated as consent with what I propose in the comments. Philipp P.S.: For those of you who want to try this out or help, check out the 'ajung-zpt-end-game' branch of Zope 2 (which will automatically pull the corresponding Five branch as well).
Philipp von Weitershausen wrote:
http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag... http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag...
I meant http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag... http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag... instead.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Re: Empty path elements: Zope2 uses them at the beginning of a path to indicate traversal from the root. -1 to dropping that case (it is the one which makes '/foo/bar' behave orthagonally). Havinng blank elements work as no-ops also makes them behave predictably: this is what command shells (sane ones, anyway) do with them. E.g.: $ ls /path/to//foo yiels the same results as: $ ls /path/to/foo So -0 to dropping the current blank traversal behavior at all. Therefore, +0 to modifying Z3's version to allow the same behavior (I think Zope2's version is more correct). Re: calling primitive types which are at the end of a path expression. They should be called, as should any other callable at the end of a path expression; anything else is a hard-to-explain bit of special case hackery. The ZPT spec has *always* read so. +1 to fixing both / either Z2 or Z3 to make this uniformly so. BBB be damned in this case, as the behavior (not calling the primitiive type) is contrary to spec. Tres. - -- =================================================================== Tres Seaver +1 202-558-7113 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFEcSxN+gerLs4ltQ4RAvnxAKCeLS5DxZo6f1PAikJ5Gp9IWAxy7QCgvxSe z3WxK2p0Opb6jPRzl/S3VZ4= =Dj/N -----END PGP SIGNATURE-----
Tres Seaver wrote:
Zope2 uses them at the beginning of a path to indicate traversal from the root. -1 to dropping that case (it is the one which makes '/foo/bar' behave orthagonally).
Yeah, I'm actually about -10 to this ;-) ...think about trying to explain why: context.restrictedTraverse('/plonesite/folder/document').absolute_url() ...works, while the following barfs at you: tal:attributes="href /plonesite/folder/document/absolue_url" ...which would mean you could no longer use Zope 2's catalog uids as paths for traversal, which would be a shame :-/
Havinng blank elements work as no-ops also makes them behave predictably: this is what command shells (sane ones, anyway) do with them. E.g.:
$ ls /path/to//foo
yiels the same results as:
$ ls /path/to/foo
So -0 to dropping the current blank traversal behavior at all.
Then again, I'm +0.1 on dropping empty path elements anywhere but the start of the path... cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Tres Seaver wrote:
Re: Empty path elements:
Zope2 uses them at the beginning of a path to indicate traversal from the root.
Sure, in restrictedTraverse and the like. But not in TALES expressions. While you can start a TALES expression on a /, the empty path element at the beginning stands for the global namespace. Hence, path:foo/bar and path:/foo/bar are identical. Specially, you still have to write root/bla or /root/bla to traverse from the root object.
-1 to dropping that case (it is the one which makes '/foo/bar' behave orthagonally). Havinng blank elements work as no-ops also makes them behave predictably: this is what command shells (sane ones, anyway) do with them. E.g.:
$ ls /path/to//foo
yiels the same results as:
$ ls /path/to/foo
So -0 to dropping the current blank traversal behavior at all. Therefore, +0 to modifying Z3's version to allow the same behavior (I think Zope2's version is more correct).
I would tend to agree, however, Fred must've had a reason when he added the check for empty path elements in zope.tales.expressions: 26551 srichter class SubPathExpr(object): 12874 philikon 9658 matth def __init__(self, path, traverser, engine): 9637 matth self._traverser = traverser 9658 matth self._engine = engine 10598 stevea 9637 matth # Parse path 9658 matth compiledpath = [] 9658 matth currentpath = [] 9658 matth for element in str(path).strip().split('/'): 26722 fdrake if not element: 26722 fdrake raise engine.getCompilerError()( 26722 fdrake 'Path element may not be empty in %r' % path) r26722 unfortunately doesn't have a log message that might hint at the reason. It does feature an extensive test (testEmptyPathSegmentRaisesCompilerError) for this change though. Perhaps Fred can shed some light on this issue? (CCing him)
Re: calling primitive types which are at the end of a path expression.
They should be called, as should any other callable at the end of a path expression; anything else is a hard-to-explain bit of special case hackery. The ZPT spec has *always* read so. +1 to fixing both / either Z2 or Z3 to make this uniformly so. BBB be damned in this case, as the behavior (not calling the primitiive type) is contrary to spec.
Right. Basically, we'd be fixing a bug because the current Zope 2 behaviour is contradicting spec. Too bad this behaviour is documented in a test... oh well, tests can have bugs, too. I will fix the test in Zope 2.10 to work with Zope 3's (correct) behaviour. I should probalby also fix Zope 2.9's behaviour if we consider this a bug?!? Philipp
Tres, I've thought about this some more and chatted with Fred. Here's what I think:
Zope2 uses them at the beginning of a path to indicate traversal from the root.
Sure, in restrictedTraverse and the like. But not in TALES expressions. While you can start a TALES expression on a /, the empty path element at the beginning stands for the global namespace. Hence, path:foo/bar and path:/foo/bar are identical. Specially, you still have to write root/bla or /root/bla to traverse from the root object.
Since /foo/bar is like foo/bar as I pointed out above, there's no use case currently to support /foo/bar.
-1 to dropping that case (it is the one which makes '/foo/bar' behave orthagonally). Havinng blank elements work as no-ops also makes them behave predictably: this is what command shells (sane ones, anyway) do with them. E.g.:
$ ls /path/to//foo
yiels the same results as:
$ ls /path/to/foo
So -0 to dropping the current blank traversal behavior at all. Therefore, +0 to modifying Z3's version to allow the same behavior (I think Zope2's version is more correct).
Parallels like this (traversing from root, normalizing empty elements) sure sound nice, they don't work as expected even in Zope 2.9. The root case has been discussed above. The empty elements case works differently, too. foo//bar will yield the traversal elements ['foo', '', 'bar'] and you'll get a KeyError: ''. Zope 2.9 does NOT normalize like a shell. So, even though Chris Withers and you like the parallels to a Unix shell, they're not even reality as of Zope 2.9. Moreover, I see no use case for empty path elements currently. Yes, Zope 2 has a unit test that tests them and the CMF happens to use them by mistake because it compiles even empty filter expressions for actions. But those are no use cases. The CMF case (it's a GenericSetup case now, I think) is just plain misguided usage of TALES expressions. It should not even try to compile an empty expression string. My tendency is to fix CMF which (apart from that one unit test in Zope 2) seems to be the only place where empty path elements occur (and even there not deliberately but accidentally). Philipp
Philipp von Weitershausen wrote:
So, even though Chris Withers and you like the parallels to a Unix shell, they're not even reality as of Zope 2.9.
Sorry, you're completely right and I'm mistaken, my apologies. In TALES you always start from an object, so I'm +1 on banning empty segments in all places in a path :-) cheers, Chris -- Simplistix - Content Management, Zope & Python Consulting - http://www.simplistix.co.uk
Previously Tres Seaver wrote:
Zope2 uses them at the beginning of a path to indicate traversal from the root. -1 to dropping that case (it is the one which makes '/foo/bar' behave orthagonally). Havinng blank elements work as no-ops also makes them behave predictably: this is what command shells (sane ones, anyway) do with them. E.g.:
$ ls /path/to//foo
yiels the same results as:
$ ls /path/to/foo
That actually does not need to be true and POSIX does not dictate that. There have been some discussions to use // as a marker for a different kind of traversal for some filesystems. Wichert. -- Wichert Akkerman <wichert@wiggy.net> It is simple to make things. http://www.wiggy.net/ It is hard to make things simple.
On Mon, May 22, 2006 at 03:41:21AM +0200, Philipp von Weitershausen wrote:
Philipp von Weitershausen wrote:
http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag... http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag...
I meant
http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag... http://svn.zope.org/Zope/branches/ajung-zpt-end-game/lib/python/Products/Pag...
instead.
Re. one of your questions: # there are ways to make code compatible with 2.9 and 2.10: # Add a nocall: before the python: expression (if that's # possible?!?). Yes, it's possible. This works fine in 2.9: <p tal:define="blah nocall:python:int" tal:content="python:blah('1')+2"> </p> -- Paul Winkler http://www.slinkp.com
On 5/22/06, Philipp von Weitershausen <philipp@weitershausen.de> wrote:
Silence is treated as consent with what I propose in the comments.
... ;-) -- Lennart Regebro, Nuxeo http://www.nuxeo.com/ CPS Content Management http://www.cps-project.org/
participants (6)
-
Chris Withers -
Lennart Regebro -
Paul Winkler -
Philipp von Weitershausen -
Tres Seaver -
Wichert Akkerman