On Fri, Aug 28, 2009 at 9:41 PM, Johannes Dollinger
<johannes.dollin...@einfallsreich.net> wrote:
>
> The proposal and motivation are essentially the same as in the last
> thread [1] and the ticket description [2]. I put it on the 1.2 feature
> list.
> I tried to split my patch into smaller, more readable commits here:  
> http://github.com/emulbreh/django/tree/master
> I haven't converted defaulttags, loadertags and django.templatetags.*
> yet to show that it's (mostly) backwards compatible (see below). It
> would be useful to decide on some questions in the "API Design .."
> section below first.
>
> I'll summarize the core ideas again as well as problems and pending
> design decisions.
>
> Concepts: Expressions and TokenStream
> =================================
> Variable and FilterExpression will be deprecated as they require the
> caller to know the length of the expression in advance.

I'm not sure I follow this assertion. I have no problem believing
FilterExpression can be made cleaner, but Variable takes an expression
like 'article.section', plus a context, and resolves it into a string.
In itself, it seems like a well built and stable piece of API.

> This makes
> whitespace handling cumbersome and some syntactical constructs really
> hard to parse (e.g., the {% url ... %} parser is broken by design).

Saying {% url %} is "broken by design" doesn't accurately represent
the problem - it was a victim of inadequate tag building tools, and
now can't be fixed due to backwards-compatibility guarantees.

> Variable vs FilterExpression
> ======================
> I could only find documentation for Variable. If the internally used
> Parser.compile_filter() is indeed undocumented there is no official
> way to use FilterExpression in custom tags. If that means that
> FilterExpression.resolve() behaviour doesn't have to be backwards
> compatible, that would help a lot ..

As best as I can make out, you are correct. FilterExpression appears
to be an internal, so isn't covered by our backwards compatibility
guarantees. However, Variable is documented API.

> 1.) Currently `Variable("unresolvable")` and
> `FilterExpression("unresolvable", p)` resolve differently: Variable
> raises VariableDoesNotExist and FilterExpression returns
> TEMPLATE_STRING_IF_INVALID. Except when `ignore_failures=True` is
> given. But `FilterExpression("foo|cut:unresolvable", p)` will again
> raise VariableDoesNotExist - regardless of `ignore_failures=True`.
>
> My Expression implementation unifies these behaviours: If any part of
> an expression is unresolvable a LookupError will be raised.
> `ignore_failures` will be deprecated but there's a resolve_safe()
> method on the Expression base class that reads:
>
>     def resolve_safe(self, context, default=None):
>         try:
>             return self.resolve(context)
>         except LookupError:
>             return default
>
> This would be a small backwards incompatible change. I have one
> failing test (exception02) because the ExtendsNode implementation
> depends on the current FilterExpression behaviour.

It's either backwards compatible or it isn't. Backwards compatibility
is a requirement, not an optional extra.

> 2.) Currently `Variable("a._hidden")` works - but
> `FilterExpression("a._hidden", p)` raises a TemplateSyntaxError. This
> would be unified: lookup parts may not start with an underscore. If
> it's not acceptable to break bc here leading underscores might simply
> be allowed.

I'm inclined to say this is a bug with FilterExpression. Underscored
variables shouldn't ever be exposed.

> 3.) Numeric literals ending with "." are currently treated as
> Variables. The following test (ifequal-numeric07) succeds because
> `ignore_failures=True` in IfEqualNode suppresses the inevitable
> VariableDoesNotExist exception and then compares None to 2: ('{%
> ifequal x 2. %}yes{% endifequal %}', {'x': 2}, ''). My current
> implementation raises a TemplateSyntaxError as soon as it encounters a
> numeric literal with a trailing dot. This could easily be made
> backwards compatible if it's considered worth it.

Sorry, but this one can't change. "2." is a tested format for handling
floats; the fact that this is inconvenient to your parser is
irrelevant.

> Tags
> =====
> * {% url ... %}, {% ssi ... %} currently accept unquoted literal
> strings. This will continue to work but the preferred syntax will use
> properly quoted strings. This may one day allow for viewnames and ssi
> paths that come from expressions.

At this point, this sort of fix can't happen until v2.0. It's would be
a major change at this point. It's nice to know that the template
parsing tools will handle it when the time comes, but I would expect
that to be true of _any_ rework of the parser.

> * {% if not %} would fail with my current implementation. This is
> fixable. But I'm not sure it's worth it: not/and/or should be keywords
> in the context of boolean expressions.

I'm unclear what you're proposing here. {% if not %} is a well
documented API, so it can't be deprecated.

****

There is a lot more work that requires a review here - not the least
of which is a large patch. I also know you've been working on this for
a long time - judging by the mailing list, at least a year, possibly
longer.

I don't want to sound dismissive of the work you're done here, but
your comments in this post haven't inspired me to go looking deeper.
You've been a little cavalier with the term "backwards incompatible"
on a couple of occasions, which is something that simply isn't
acceptable in something as prominent and well documented as Django's
template language.

There are bugs in the template system. Many of these are caused by
inconsistent handling of parsing, especially of variables. If you can
point at something that you think is a bug (such as the handlng of
foo._attrib), then it's no longer covered by backwards compatibility.
However, you don't get that accommodation simply because something
doesn't fit into your nice new parsing scheme.

Now, some of this might just be a misunderstanding on my part -
especially with regards to what is partially implemented, what you
intend to fix, and what you think can't (or shouldn't) be fixed.
You've spent a lot of time describing your new parsing API, but not a
lot of time describing why the new API is required. To that end, I'm
not entirely sure how much of this patch is intended to cover the "fix
the inconsistencies in the template system" problem, and how much is
intended to fix the "make template tags easier to write" problem. If
you're proposing a major rework of internals with the goal of fixing
bugs, explaining exactly what is broken and how it is broken is an
important part of your proposal. If the goal is to improve the
usability of the public API, explaining the use cases you're trying to
make easier is important.

I'm also intrigued to know how this proposal intersects with Mike
Malone's patch to introduce template caching (#6262).

Please don't let this discourage you - I am keen to see improvements
in the template system. However, any widespread changes are going to
get _very_ thorough investigation, and before I invest the time
tearing down the code, I want to make sure the fundamentals
underpinning the patch are well understood and well founded.

Yours,
Russ Magee %-)

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to