[TransWarp] PROPOSAL: Get rid of binding.AutoCreated/AutoCreatable

Phillip J. Eby pje at telecommunity.com
Wed Nov 27 19:47:17 EST 2002


(Interestingly, after I wrote the first couple of paragraphs of this 
proposal, I found out that our implementation of 'AutoCreated' (really in 
'OnceClass') can cause Python 2.2.x to dump core, because of a 2.2.x 
bug.  But that's *not* the reason for this proposal, since we could work 
around the Python bug if we so chose.  This proposal is intended to remove 
what I believe are now-superfluous and overly "magical" features in 
'peak.binding'.)

When you subclass binding.AutoCreated, you get a class that, when placed 
inside another class definition, will create an instance of the AutoCreated 
subclass upon retrieval.  It is, in effect, as though you had a 
binding.New() wrapped around the nested class.

Nested classes, however, are not considered by the BDFL to be good Python 
style in situations where the contained class is merely a "helper" of the 
outer class.

Worse, there is no way you can actually have a class-defined instance 
attribute which is an AutoCreated subclass.  If you do this, you'll get a 
fresh instance of the class instead.

It seems to me that this violates the principle of "explicit is better than 
implicit", since it is not possible to tell what a nested class is going to 
actually do, without first inspecting the source code of all its base 
classes to find out if they subclass AutoCreated!

What I propose, then, is to simply get rid of binding.AutoCreated and its 
supporting metaclass machinery (OnceClass and AutoCreatable).  In places 
where we currently use nested classes to define autocreateds, we will add a 
binding.New(), as follows::

     # Before
     class Thing(binding.Component):
         class Nested(binding.AutoCreated):
             ...

     # After
     class Thing(binding.Component):
         class Nested(binding.Component):
             ...
         Nested = binding.New(Nested)

The net result is that such bindings are always explicit.  This takes a 
little more work to do, but will let us clean up some bits of cruft 
associated with the AutoCreated classes and metaclasses.

There are a few possibly negative side effects.  In the example above, 
'Nested' is no longer accessible as a class, even as a class 
attribute.  This could be worked around by giving the class and attribute 
binding different names, e.g. 'class _Nested' and 'Nested = 
binding.New(_Nested)'.  This would also be necessary for classes that you 
wished to have treated as components in themselves, otherwise they will 
consider their parent component to be the module, rather than the class 
they are contained in.

But the most common use case for a nested class that is to be auto-created, 
is when you want to build a structure of nested service components.  In 
this situation, the classes themselves aren't the components; their 
instances are.  There's really no point to accessing the classes, either, 
unless you plan to pickle the structure.  If you're pickling the structure, 
then you'll need 'config.setupModule()' anyway, and it will still do its 
normal class name mangling (e.g. '__name__ = "Thing.Nested"; 
globals()["Thing.Nested"] = Nested') when the class is created.  So, I 
don't really see a use case for *not* using 'binding.New()' to wrap a 
nested class for creation, except to save some typing.  :)

There are also some other advantages to being explicit.  One can use a 
different docstring for the binding than the class, for example, or specify 
different 'provides' configuration keys.

Anyway, as of this point, I'd like to consider AutoCreated et al to be 
"deprecated", and immediately begin standardizing PEAK not to use them any 
more.  (They also will NOT be documented in the tutorial.)  If there are no 
serious objections, I'd also like to go ahead and remove them from the code 
base.  If you're using them and can't change for some reason, please let me 
know right away.





More information about the PEAK mailing list