[Zope3-dev] Allowing views to be registered for classes rather than interfaces.

Steve Alexander steve@cat-box.net
Thu, 17 Jul 2003 13:59:41 +0300


> Tres has argued (with merit) that only interfaces designed to support 
> multiple implementations should go in a separate hierarchy.

I support Tres' argument.

I think there is value in having a separate place for interfaces that 
are meant to have a variety of implementations. We might call these 
"standard interfaces" or somethig like that. We should be careful about 
changing the contract of a "standard interface" once it has been made 
available in released software.

I don't see any harm in putting other interfaces along with their 
implementations.

An idea I was kicking around with Martijn Faassen is to have an 
automatic way of making an interface for a class.

The idea is that when you are prototyping a class, you don't want to 
keep an interface in synch with it. Rather, you just want to write and 
modify the class. However, you still want to be able to hook up views 
and adapters etc.

So, we use the common convention that names begining with an underscore 
are "private" and all other names are part of the interface.


It might look like this:

   class Foo:

       nonceInterface()

       def bar(self, arg):
           "Documentation"
           # do something

       baz = 23

       def _spoo(self):
           # do something private

       _fish = 99

The nonceInterface() class advice creates an interface called 
"Foo.interface" that defines the method bar and the attribute baz. It 
does not define _spoo or _fish because they start with an underscore. 
This is a common convention for attributes and operations that do not 
form part of the public API of an object.

 From zcml, we can refer to Foo's interface as

   <require permission="zope.View" interface=".Foo.interface" />

To make this work, and make the interface picklable, the 
nonceInterface() advice needs to do the following:

1: synthesize an interface based on the contents of the class
2: make the class implement that interface
3: inject the name 'Foo.interface' into Foo's module
4: set a class-only descriptor on Foo that gets you access to the
    interface, in the name "interface"
and maybe also...
5: set a class-only security checker on the class so that access to the
   "interface" attribute is allowed

If you want to use schemas with a nonceInterface, you can define the 
schema and then have the nonceInterface use the fields of that schema to 
override the fields gleaned from inspecting the class.

   class _IFooSchema(Interface):

       baz = IntField(title=u'for baz things')

   class Foo:

       nonceInterface(_IFooSchema)

       def bar(self, arg):
           "Documentation"
           # do something

       baz = 23


Why nonceInterface()? It is like a "nonce word".

 From Webster's Revised Unabridged Dictionary (1913) [web1913]:

   Nonce \Nonce\ (n[o^]ns), n. [For the nonce, OE. for the nones, a
      corruption of for then ones, where n. in then is a relic of
      AS. m in [eth]am, dat. of the article and demonstrative
      pronoun, E. the. See {For}, {Once}, and {The}.]
      The one or single occasion; the present call or purpose; --
      chiefly used in the phrase for the nonce.

            The miller was a stout carl for the nones. --Chaucer.

            And that he calls for drink, I 'll have prepared him A
            chalice for the nonce.                   --Shak.

      {Nonce word}, ``a word apparently employed only for the
         nonce''. --Murray (New English Dict.).

 From WordNet (r) 1.7 [wn]:

   nonce
        n : the present occasion; "for the nonce" [syn: {time being}]



--
Steve Alexander