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

[Cheetahtemplate-discuss] calling $super($self.__class__, $self) breaks if used in parent template

Expand Messages
  • Dirk van Oosterbosch, IR labs
    Hi, this post is a sort of follow up on the recent discussion #super directive for blocks [1] and a thread I started a few months ago [2]. Back then I
    Message 1 of 4 , Nov 5, 2006
    • 0 Attachment
      Hi,

      this post is a sort of follow up on the recent discussion '#super
      directive for blocks' [1] and a thread I started a few months ago
      [2]. Back then I thought I solved it, but just now discovered I
      really didn't. It seems that I would also like a #super directive for
      *defs*.

      [1] http://www.nabble.com/-super-directive-for-blocks-tf2460570.html
      [2] http://www.nabble.com/calling-superclass--def%27s-of-templates-in-
      inheritance-chain-tf2233988.html


      Let's say I've three templates, inheriting each other, Foo, Bar and Baz.

      -----------Foo.tmpl:----------
      #extends BaseTemplate

      #def doMethod
      THIS IS FOO
      #end def doMethod

      -----------Bar.tmpl:----------
      #extends Foo

      #def doMethod
      $super($self.__class__, $self).doMethod
      THIS IS BAR
      #end def doMethod

      -----------Baz.tmpl:----------
      #extends Bar

      #def doMethod
      $super($self.__class__, $self).doMethod
      THIS IS BAZ
      #end def doMethod


      Somewhere in the templates (in Foo or in BaseTemplate) $doMethod is
      called.
      When I call Bar as my template to fill, there is no problem, and
      doMethod gives its intended result:
      THIS IS FOO
      THIS IS BAR

      But when Bar is called to be filled, things go horribly wrong. i.e.
      python goes into an infinite recursive loop in Bar. I reckon that the
      $self.__class__ in Bar is not longer interpreted as the class of the
      module of the statement (Bar), but the class of the module being
      called (Baz).
      My knowledge of python is not extensive enough to know if this is at
      all possible in python (to call super() without having to specify in
      which class we are now), but in other OO languages this seems sort of
      standard.
      So is this a problem with Cheetah or with python in general?

      And will the new #super directive fix this problem?


      best
      dirk


      -------------------------------------------------------------------------
      Using Tomcat but need to do more? Need to support web services, security?
      Get stuff done quickly with pre-integrated technology to make your job easier
      Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
      http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
      _______________________________________________
      Cheetahtemplate-discuss mailing list
      Cheetahtemplate-discuss@...
      https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
    • Mike Meyer
      ... This is wrong - it should be super(Bar, $self).doMethod. I ll get to why in a minute. ... Should be $super(Baz, $self).doMethod ... Calling doMethod on an
      Message 2 of 4 , Nov 5, 2006
      • 0 Attachment
        In <598574C1-7C45-4D7C-A0A9-C0BB430EF5A4@...>, Dirk van Oosterbosch, IR labs <labs@...> typed:
        > Hi,
        >
        > this post is a sort of follow up on the recent discussion '#super
        > directive for blocks' [1] and a thread I started a few months ago
        > [2]. Back then I thought I solved it, but just now discovered I
        > really didn't. It seems that I would also like a #super directive for
        > *defs*.
        >
        > [1] http://www.nabble.com/-super-directive-for-blocks-tf2460570.html
        > [2] http://www.nabble.com/calling-superclass--def%27s-of-templates-in-
        > inheritance-chain-tf2233988.html
        >
        >
        > Let's say I've three templates, inheriting each other, Foo, Bar and Baz.
        >
        > -----------Foo.tmpl:----------
        > #extends BaseTemplate
        >
        > #def doMethod
        > THIS IS FOO
        > #end def doMethod
        >
        > -----------Bar.tmpl:----------
        > #extends Foo
        >
        > #def doMethod
        > $super($self.__class__, $self).doMethod

        This is wrong - it should be super(Bar, $self).doMethod. I'll get to
        why in a minute.

        > THIS IS BAR
        > #end def doMethod
        >
        > -----------Baz.tmpl:----------
        > #extends Bar
        >
        > #def doMethod
        > $super($self.__class__, $self).doMethod

        Should be $super(Baz, $self).doMethod

        > THIS IS BAZ
        > #end def doMethod
        >
        >
        > Somewhere in the templates (in Foo or in BaseTemplate) $doMethod is
        > called.
        > When I call Bar as my template to fill, there is no problem, and
        > doMethod gives its intended result:
        > THIS IS FOO
        > THIS IS BAR

        Calling doMethod on an instance of bar works, because $self.__class__
        for that instance is Bar.

        > But when Bar is called to be filled, things go horribly wrong. i.e.
        > python goes into an infinite recursive loop in Bar. I reckon that the
        > $self.__class__ in Bar is not longer interpreted as the class of the
        > module of the statement (Bar), but the class of the module being
        > called (Baz).

        I'm not sure if I really understand the difference between "calling
        Bar as my template to fill" and "Bar is called to be filled", but I
        assume you tried to fill an instance of Baz. In this case,
        $self.__class__ is Baz, so the super calls (*both* of them) wind up
        invoking bar.doMethod, which as you just discovered, is a loop.

        > My knowledge of python is not extensive enough to know if this is at
        > all possible in python (to call super() without having to specify in
        > which class we are now), but in other OO languages this seems sort of
        > standard.

        It might be possible with class methods, but I'm not sure you can
        create those with Cheetah. Other OO languages that support this have a
        syntax extension for it, so the compiler will supply the appropriate
        class name for you. Sort of like they don't have to have self.

        > So is this a problem with Cheetah or with python in general?

        It's a feature of python.

        > And will the new #super directive fix this problem?

        What needs to be fixed? If you use super correctly, it'll work
        correctly.



        <mike
        --
        Mike Meyer <mwm@...> http://www.mired.org/consulting.html
        Independent Network/Unix/Perforce consultant, email for more information.

        -------------------------------------------------------------------------
        Using Tomcat but need to do more? Need to support web services, security?
        Get stuff done quickly with pre-integrated technology to make your job easier
        Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
        http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
        _______________________________________________
        Cheetahtemplate-discuss mailing list
        Cheetahtemplate-discuss@...
        https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
      • Mike Orr
        ... I let someone else answer this first since I figured they d understand it better. Mike Myers is right about how to use super. The new #super directive
        Message 3 of 4 , Nov 5, 2006
        • 0 Attachment
          On 11/5/06, Dirk van Oosterbosch, IR labs <labs@...> wrote:
          > -----------Foo.tmpl:----------
          > #extends BaseTemplate
          >
          > #def doMethod
          > THIS IS FOO
          > #end def doMethod
          >
          > -----------Bar.tmpl:----------
          > #extends Foo
          >
          > #def doMethod
          > $super($self.__class__, $self).doMethod
          > THIS IS BAR
          > #end def doMethod
          >
          > -----------Baz.tmpl:----------
          > #extends Bar
          >
          > #def doMethod
          > $super($self.__class__, $self).doMethod
          > THIS IS BAZ
          > #end def doMethod
          >
          >
          > Somewhere in the templates (in Foo or in BaseTemplate) $doMethod is
          > called.
          > When I call Bar as my template to fill, there is no problem, and
          > doMethod gives its intended result:
          > THIS IS FOO
          > THIS IS BAR
          >
          > But when Bar is called to be filled, things go horribly wrong. i.e.
          > python goes into an infinite recursive loop in Bar. I reckon that the
          > $self.__class__ in Bar is not longer interpreted as the class of the
          > module of the statement (Bar), but the class of the module being
          > called (Baz).
          > My knowledge of python is not extensive enough to know if this is at
          > all possible in python (to call super() without having to specify in
          > which class we are now), but in other OO languages this seems sort of
          > standard.
          > So is this a problem with Cheetah or with python in general?

          I let someone else answer this first since I figured they'd understand
          it better. Mike Myers is right about how to use super. The new
          #super directive will implicitly supply the correct class so you don't
          have to. I've seen Python cookbook examples defining a .super()
          method that does just what you do (self.__class__) and they apparently
          work, at least with the limited testing they've gotten. I don't know
          why Guido made super() so generic and whether it was really necessary.
          Often when he's unsure about something he'll make the minimal change
          that he's sure will work, and leave it to a future version to pretty
          it up. Other languages usually have a horrible way to call a
          superclass method: an unbound method call. Python does too:
          SuperClass.method(self, args...). The difference is, in other
          languages that's the *only* way to call a superclass method, whereas
          Python now has super() which is cleaner.

          However, Guido said at the last PyCon something I didn't understand,
          that super() is only meant for limited cases, in particular the
          "diamond case" where a class inherits from two superclasses which both
          have the same parent class. He suggested that using super() otherwise
          was wrong but didn't give a reason why. But that's just like his rant
          about "don't use a tuple as a read-only list, it's meant for bundles
          of different objects like (x, y) coordinates, not for a number of the
          same kind of objects" : the majority of Pythoneers have heard
          otherwise and will continue to do it the other way.

          As to why your self.__class__ didn't work, you hinted at the most
          likely reason. I'm not sure how you instantiated Baz but if you used
          Template(file=...), the constructor dynamically creates a new class
          and switches the instance to it, and this might throw your super()
          construct off. Otherwise, if you instantiated a precompiled template
          Baz and filled it, the instance's class *is* Baz. super() works by
          looking up the parent of the first argument. So in Baz's case it
          finds Bar.doMethod. But when Bar recurses to Foo, super() sees
          self.__class__, which is still Baz, and looks up its parent, which is
          Bar, so it calls Bar.doMethod again, Bar then recurses again like
          it's supposed to... and there's your infinite loop.

          You can use super's first argument to your advantage when you want to
          *skip* the parent's implementation and call the grandparent's instead,
          by supplying the parent as the first argument. I had to do this one
          in an application where the parent had overridden a certain method,
          but the parent's implementation was inappropriate for my subclass.

          --
          Mike Orr <sluggoster@...>

          -------------------------------------------------------------------------
          Using Tomcat but need to do more? Need to support web services, security?
          Get stuff done quickly with pre-integrated technology to make your job easier
          Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
          http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
          _______________________________________________
          Cheetahtemplate-discuss mailing list
          Cheetahtemplate-discuss@...
          https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
        • leenoori
          ... I think this thread shows exactly why the #super directive is so important. You shouldn t have to be a Python expert to use Cheetah. The #super directive
          Message 4 of 4 , Nov 6, 2006
          • 0 Attachment
            El 6/11/2006, a las 5:48, Mike Meyer escribió:

            >> $super($self.__class__, $self).doMethod
            >
            > This is wrong - it should be super(Bar, $self).doMethod.
            >
            >> $super($self.__class__, $self).doMethod
            >
            > Should be $super(Baz, $self).doMethod
            >
            > Calling doMethod on an instance of bar works, because $self.__class__
            > for that instance is Bar.
            >
            > In this case,
            > $self.__class__ is Baz, so the super calls (*both* of them) wind up
            > invoking bar.doMethod, which as you just discovered, is a loop.
            >
            >> And will the new #super directive fix this problem?
            >
            > What needs to be fixed? If you use super correctly, it'll work
            > correctly.

            I think this thread shows exactly why the #super directive is so
            important. You shouldn't have to be a Python expert to use Cheetah.
            The #super directive would allow non-programmers and non-Python
            experts to do some pretty sophisticated inheritance stuff in
            templates without having to understand the kind of nuances that Mike
            explains in his email. Cheetah should ideally shield users from
            having to know about this stuff.


            -------------------------------------------------------------------------
            Using Tomcat but need to do more? Need to support web services, security?
            Get stuff done quickly with pre-integrated technology to make your job easier
            Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
            http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
            _______________________________________________
            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.