Loading ...
Sorry, an error occurred while loading the content.

[Cheetahtemplate-discuss] Re: errorCatcher replacement

Expand Messages
  • Tavis Rudd
    Hi Keith, I m interested in hearing more. I have to admit that although I wrote the ErrorCatcher stuff (at Chuck s request) I ve never found a need to use it.
    Message 1 of 3 , Nov 25, 2003
    • 0 Attachment
      Hi Keith,
      I'm interested in hearing more. I have to admit that although I wrote the
      ErrorCatcher stuff (at Chuck's request) I've never found a need to use it.

      Can you summarize your issues with ErrorCatcher, the advantages of your
      alternative, and how it works?

      Cheers,
      Tavis

      On Tuesday 25 November 2003 01:17, Keith Devens wrote:
      > Hey Tavis,
      >
      > If I came up with a way to replace the mess that is errorCatcher that has
      > almost no overhead, can do everything errorCatcher can do and a little
      > more, and is far simpler, would you be interested? I've already got the
      > code that enables this done except for making the modification to the
      > template compiler that this would take and it seems to work great. I think
      > the biggest part of this modification would be just removing all the
      > errorCatcher code that's there now.
      >
      > I'm not asking rhetorically, since if you're on the cusp of releasing 1.0
      > and don't want to make any major changes I'll understand. On the other
      > hand, if you are interested, I'd like to try to get most of the rest of the
      > code done over Thanksgiving. I have yet to explore fully how the template
      > compiler works, so that's the major hurdle.
      >
      > Of course, my solution might be bad, or not in keeping with how you want
      > Cheetah to work, etc. And, I suppose I could wind up being wrong about how
      > easy it is to integrate this with Cheetah (though I can't imagine how, but
      > it's still a possibility). But, disclaimers aside, would you be interested
      > in considering such a relatively large change? If so, let me know, and I'll
      > start explaining and sending some code your way so you can judge whether
      > the change makes sense. Keep in mind that this should require no change in
      > template syntax, and I'd have to check, but I think we could even get away
      > with leaving Python code that uses Cheetah.Template with errorCatchers
      > unchanged.
      >
      > Thanks.
      >
      > Keith



      -------------------------------------------------------
      This SF.net email is sponsored by: SF.net Giveback Program.
      Does SourceForge.net help you be more productive? Does it
      help you create better code? SHARE THE LOVE, and help us help
      YOU! Click Here: http://sourceforge.net/donate/
      _______________________________________________
      Cheetahtemplate-discuss mailing list
      Cheetahtemplate-discuss@...
      https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
    • Keith Devens
      ... Sure. One of the reasons I e-mailed you personally rather than sending something to the list is because if my idea was dumb and you shot it down, you d be
      Message 2 of 3 , Nov 25, 2003
      • 0 Attachment
        > Can you summarize your issues with ErrorCatcher, the advantages of your
        > alternative, and how it works?

        Sure. One of the reasons I e-mailed you personally rather than sending
        something to the list is because if my idea was dumb and you shot it down,
        you'd be the only one I'd look dumb in front of :) No problem though.

        As I understand it, the sole purpose of an errorCatcher is to prevent
        unfilled placeholders from throwing exceptions, which is about the worst and
        least useful thing that can happen. Much better to have "$variable", or even
        nothing show up than have one (possibly minor) piece of your display logic
        kill your entire page. There's also an errorCatcher that does some logging
        of errors (ListErrors)... it's easy for my scheme to do this as well.

        So, the way I see it, the same purpose can be served by an object appended
        to the end of your search list that can respond to anything (has special
        methods like __getattr__, __call__, etc.), and it can return whatever you
        want when __str__ is called, the same as what happens when warn() is called
        on an errorCatcher. Here's essentially the object I'm currently using:

        class RememberErrorObject:
        def __init__(self, name = None):
        self.name = name
        def __getitem__(self, name):
        if not self.name:
        return self.__class__('$' + name)
        self.name += '.' + name
        return self
        def __str__(self):
        return self.name

        Real simple, you get the idea. It cheats a little, always uses '$' as the
        placeholder value, doesn't support __call__ yet, etc. It was just for a
        proof-of-concept, but it works, and you can try it out right now in your
        Template instantiation without having to modify anything else.

        Like so:
        e = RememberErrorObject()
        t = Template(file=TEMPLATE_DIR+'/testingcheetah.tmpl', searchList=[e])

        Now, for reference, here's what Cheetah generates when an errorCatcher is in
        effect:

        write(filter(self.__errorCatcher2(localsDict=locals()),
        rawExpr='@variable')) # from line 10, col 1.

        And here's __errorCatcher2:

        def __errorCatcher2(self, localsDict={}):
        """
        Generated from @variable at line, col (10, 1).
        """
        try:
        return eval('''VFS(SL + [globals(), __builtin__], "variable",
        True)''', globals(), localsDict)
        except self._errorCatcher.exceptions(), e:
        return self._errorCatcher.warn(exc_val=e, code= 'VFS(SL +
        [globals(), __builtin__], "variable", True)' , rawCode= '@variable' ,
        lineCol=(10, 1))

        So, that takes into account what the actual placeholder was ("@variable"),
        and it makes some extra information available such as the "lineCol".

        Here's what a normal placeholder substitution looks like when no
        errorCatcher is in effect:

        write(filter(VFS(SL + [globals(),__builtin__],"variable",True),
        rawExpr='@variable')) # from line 10, col 1.

        Given my slightly more complete, and simpler, errorObject that can be used
        once the template code generation is modified:

        class ErrorObject:
        def __init__(self):
        self.placeholder = {'name': '', 'lineCol':(0,0)}
        def __getitem__(self, name):
        return self
        def __str__(self):
        return self.placeholder['name']
        def __call__(self, name, lineCol):
        self.placeholder['name'] = name
        self.placeholder['lineCol'] = lineCol
        return self

        We can modify the placeholder substitution to be something like:

        e = errorCatcher() #at the beginning
        #...
        write(filter(VFS(SL + [globals(),
        __builtin__,e('@variable',(10,1))],"variable",True), rawExpr='@variable')) #
        from line 10, col 1.

        And that's pretty much it. I'd probably have to wind up replacing __call__
        with a fill() method so that e('@variable',(10,1)) would have to be
        e.fill('@variable',(10,1)), which would allow us to save __call__ for
        placeholders that either don't use NameMapper syntax or do a method call
        directly on a placeholder.

        Note also that this allows errorCatcher output to go through the filter, so
        there's no need to have the HTML-specific hack of something that looks like:
        ====< $foo could not be found >====
        in the case of BigEcho.

        I also did a proof of concept that allows logging just as ListErrors does,
        but there's enough mangled code in this e-mail for now :)

        So, I don't think there's that much overhead with this system (basically,
        a function call to e.fill() to keep track of the placeholder name and
        "lineCol", and an extra item on the search list), and assuming there's no
        problem with it, it seems like it could even be on by default, which might
        make things easier for people. Finally, I think you should still be able to
        do things like:

        t = Template(file=TEMPLATE_DIR+'/testingcheetah.tmpl', errorCatcher='Echo')

        and the entire ErrorCatcher hierarchy could essentially be left intact... I
        just called mine ErrorObject to avoid name clashes for now. The main thing
        that would have to be changed is the code generation, but again, that seems
        like it would mostly be removing the old ErrorCatcher system of one method
        definition per placeholder.

        The main, and possibly significant, drawback of this scheme is that if your
        placeholder is something like $variable.foo, and an earlier object in the
        searchList does have $variable, but $variable doesn't have foo in it, you
        can still get an exception. This may be a showstopper, and if it is that's
        ok. Though, I'd like to see what I'd have to change to make Cheetah back up
        upon not finding foo and try again on an object later in the search list.
        This *may* be desireable behavior anyway. Anyone have ideas about this?

        I'm sorry for how long this e-mail was, as well as for all the mangled code.
        Aside from what I noted in the preceding paragraph, do you see any problems
        I overlooked?

        Thanks for your patience.

        Keith

        P.S. The following is unnecessary for understanding the modification I want
        to make, but explains some of my motivation. Don't feel obligated to read
        it... :)

        The original reason I started with this is the following: I'm porting my CMS
        to mod_python + Cheetah, and one of my requirements for MVC separation is to
        not have to have any code know ahead of time what variables are in the
        template. Rather, the template should be able to "request" data from the
        CMS, and as long as the CMS has some method available to provide that data
        (the data is requested by name), it can be automatically loaded, then
        cached, etc. When I was working with Smarty, I wrote a template precompiler
        that parsed out all applicable variable references and dynamically wrote out
        some code that would notify the CMS of what variables it needed. Such a hack
        wasn't necessary with Cheetah because through the searchList and through
        Python's operator overloading, I could have searchList variables request
        data from the CMS when it was requested by the template.

        AFAIK this is similar to how Movable Type handles things. Template designers
        can just use whatever MT variables the system provides, and when MT fills
        the template *it* figures out how to give you the data you need.

        So, the point is, if data wasn't available in the CMS, the template should
        just spit back out the placeholder value, which is essentially what the
        errorCatcher does, and that led me to the scheme outlined above.



        -------------------------------------------------------
        This SF.net email is sponsored by: SF.net Giveback Program.
        Does SourceForge.net help you be more productive? Does it
        help you create better code? SHARE THE LOVE, and help us help
        YOU! Click Here: http://sourceforge.net/donate/
        _______________________________________________
        Cheetahtemplate-discuss mailing list
        Cheetahtemplate-discuss@...
        https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
      • Keith Devens
        ... your ... up ... Turns out it was a piece of cake, and worked exactly as I expected: Python code: e = RememberErrorObject() namespace1 =
        Message 3 of 3 , Nov 26, 2003
        • 0 Attachment
          Just wanted to give an update:

          > The main, and possibly significant, drawback of this scheme is that if
          your
          > placeholder is something like $variable.foo, and an earlier object in the
          > searchList does have $variable, but $variable doesn't have foo in it, you
          > can still get an exception. This may be a showstopper, and if it is that's
          > ok. Though, I'd like to see what I'd have to change to make Cheetah back
          up
          > upon not finding foo and try again on an object later in the search list.
          > This *may* be desireable behavior anyway. Anyone have ideas about this?

          Turns out it was a piece of cake, and worked exactly as I expected:

          Python code:
          e = RememberErrorObject()
          namespace1 = {'parent':{'child1':'foo'}}
          namespace2 = {'parent':{'child2':'bar'}}
          namespace3 = {'parent':{'child3':'baz'}}
          t = Template(file=TEMPLATE_DIR+'/testingcheetah.tmpl',
          searchList=[namespace1, namespace2, namespace3, e])

          Template:
          $parent.child1
          $parent.child2
          $parent.child3
          $parent.child4

          Gives:
          foo
          bar
          baz
          $parent.child4

          The only change required was on line 252 of NameMapper.py (v 1.26)
          from: "except NotFoundInNamespace:"
          to: "except (NotFoundInNamespace, NotFound):"

          Essentially, that's what was happening *anyway* for "first level" keys in
          objects in the search list, but not for subsequent levels, for in
          _valueForName you have this code:

          if passNamespace:
          try:
          binding = valueForKey(obj, firstKey)
          except NotFound:
          raise NotFoundInNamespace
          else:
          binding = valueForKey(obj, firstKey)

          and passNamespace is true on the first call to _valueForName, but not for
          nested calls. I assume this was done intentionally, but why?

          Thanks.

          Keith



          -------------------------------------------------------
          This SF.net email is sponsored by: SF.net Giveback Program.
          Does SourceForge.net help you be more productive? Does it
          help you create better code? SHARE THE LOVE, and help us help
          YOU! Click Here: http://sourceforge.net/donate/
          _______________________________________________
          Cheetahtemplate-discuss mailing list
          Cheetahtemplate-discuss@...
          https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
        Your message has been successfully submitted and would be delivered to recipients shortly.