[Twisted-web] Re: [Nevow-commits] r3904 - server-side (fragment) nesting, and convenience descriptor generator

Matt Goodall matt at pollenation.net
Wed Jan 4 03:45:13 MST 2006


Hi all,

I really don't see any benefit in introducing a Nevow dependency on
Epsilon for this change.

In fact, the whole epsilon.descriptor module looks a little pointless to
me. All it does, AFAICT, is make something that's a property not look
like a property anymore and *maybe* adds an extra method call per
property access (I'm not sure how the standard property() is implemented
so perhaps they're the same in the end).

For those who don't want to read the changeset, but have valid comments,
here are some example uses:

Epsilon-dependent way:

    from epsilon import descriptor

    class Foo(object):
        _foo = 0
        class foo(descriptor.attribute):
            def get(self):
                return self._foo

+ Ha ha, fooled you ... I can't think of any ;-)
- Obfuscated
- Extra method call per property access ?

Normal way:

    class Foo(object):
        _foo = 0
        def getFoo(self):
            return self._foo
        foo = property(getFoo)

+ Obvious
+ Definitely no extra method call
+ Also provides a getFoo method (why do people insist on hiding them?)

Normal way but with a hidden getter method:

    class Foo(object):
        _foo = 0
        def foo():
            def get(self):
                return self._foo
            return property(get)
        foo = foo()

+ Still fairly obvious
+ Hides the foo get method without meta magic
+ Definitely no extra method call


My feelings are probably fairly obvious ;-) but what do others in the
Divmod community think?


Note: I have absolutely no objection to packages dependencies when
useful. I just don't think this qualifies as useful at all.


- Matt


Glyph Lefkowitz wrote:
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> 
> Author: glyph
> Date: Wed Jan  4 01:47:36 2006
> New Revision: 3904
> 
> Added:
>    branches/signup-config-464-9/Epsilon/epsilon/descriptor.py
>    branches/signup-config-464-9/Epsilon/epsilon/test/test_descriptor.py
> Modified:
>    branches/signup-config-464-9/Nevow/nevow/athena.py
>    branches/signup-config-464-9/Nevow/nevow/test/test_athena.py
> Log:
> server-side (fragment) nesting, and convenience descriptor generator
> 
> 
> 
> Modified: branches/signup-config-464-9/Nevow/nevow/athena.py
> ==============================================================================
> --- branches/signup-config-464-9/Nevow/nevow/athena.py	(original)
> +++ branches/signup-config-464-9/Nevow/nevow/athena.py	Wed Jan  4 01:47:36 2006
> @@ -320,7 +320,7 @@
>      def _newClientID(self):
>          return guard._sessionCookie()
>  
> -
> +from epsilon import descriptor
>  
>  class LivePage(rend.Page):
>      transportFactory = LivePageTransport
> @@ -347,6 +347,10 @@
>      # bugs.
>      TRANSPORT_IDLE_TIMEOUT = 300
>  
> +    class page(descriptor.attribute):
> +        def get(self):
> +            return self
> +
>      def __init__(self, iface=None, rootObject=None, jsModules=None, jsModuleRoot=None, *a, **kw):
>          super(LivePage, self).__init__(*a, **kw)
>  
> @@ -356,6 +360,7 @@
>              jsModules = JSPackage(jsDeps.mapping)
>          self.jsModules = jsModules
>          self.jsModuleRoot = jsModuleRoot
> +        self.liveFragmentChildren = []
>          self._includedModules = ['MochiKit', 'Divmod', 'Nevow.Athena']
>  
>  
> @@ -612,12 +617,43 @@
>  
>      jsClass = u'Nevow.Athena.Widget'
>  
> +    def __init__(self, *a, **k):
> +        super(LiveFragment, self).__init__(*a, **k)
> +        self.liveFragmentChildren = []
> +
>      def rend(self, context, data):
>          self._athenaID = self.page.addLocalObject(self)
>          context.fillSlots('athena:id', self._athenaID)
>          return super(LiveFragment, self).rend(context, data)
>  
>  
> +    def setFragmentParent(self, fragmentParent):
> +        """
> +        Sets the L{LiveFragment} (or L{LivePage}) which is the logical parent
> +        of this fragment.  This should parallel the client-side hierarchy.
> +
> +        All LiveFragments must have setFragmentParent called on them before
> +        they are rendered for the client; otherwise, they will be unable to
> +        properly hook up to the page.
> +
> +        LiveFragments should have their own setFragmentParent called before
> +        calling setFragmentParent on any of their own children.  The normal way
> +        to accomplish this is to instantiate your fragment children during the
> +        render pass.
> +
> +        If that isn't feasible, instead override setFragmentParent and
> +        instantiate your children there.
> +
> +        This architecture might seem contorted, but what it allows that is
> +        interesting is adaptation of foreign objects to LiveFragment.  Anywhere
> +        you adapt to LiveFragment, setFragmentParent is the next thing that
> +        should be called.
> +        """
> +        self.fragmentParent = fragmentParent
> +        self.page = fragmentParent.page
> +        fragmentParent.liveFragmentChildren.append(self)
> +
> +
>      def _getModuleForClass(self):
>          return jsDeps.getModuleForClass(self.jsClass)
>  
> 
> Modified: branches/signup-config-464-9/Nevow/nevow/test/test_athena.py
> ==============================================================================
> --- branches/signup-config-464-9/Nevow/nevow/test/test_athena.py	(original)
> +++ branches/signup-config-464-9/Nevow/nevow/test/test_athena.py	Wed Jan  4 01:47:36 2006
> @@ -68,3 +68,27 @@
>                  # All dependencies should be loaded before the module
>                  # that depends upon them.
>                  self.failUnless(allDeps.index(d) < allDeps.index(m))
> +
> +class TestFragment(athena.LiveFragment):
> +    pass
> +
> +class Nesting(unittest.TestCase):
> +
> +    def testFragmentNesting(self):
> +        lp = athena.LivePage()
> +        tf1 = TestFragment()
> +        tf2 = TestFragment()
> +
> +        tf1.setFragmentParent(lp)
> +        tf2.setFragmentParent(tf1)
> +
> +        self.assertEquals(lp.liveFragmentChildren, [tf1])
> +        self.assertEquals(tf1.liveFragmentChildren, [tf2])
> +        self.assertEquals(tf2.liveFragmentChildren, [])
> +        self.assertEquals(tf2.fragmentParent, tf1)
> +        self.assertEquals(tf1.fragmentParent, lp)
> +
> +        self.assertEquals(tf2.page, lp)
> +        self.assertEquals(tf1.page, lp)
> +
> +
> 
> _______________________________________________
> Nevow-commits mailing list
> Nevow-commits at divmod.org
> http://divmod.org/users/mailman.twistd/listinfo/nevow-commits

-- 
     __
    /  \__     Matt Goodall, Pollenation Internet Ltd
    \__/  \    w: http://www.pollenation.net
  __/  \__/    e: matt at pollenation.net
 /  \__/  \    t: +44 (0)113 2252500
 \__/  \__/
 /  \          Any views expressed are my own and do not necessarily
 \__/          reflect the views of my employer.



More information about the Twisted-web mailing list