<br><br><div class="gmail_quote">On Wed, Mar 16, 2011 at 1:47 PM, Robert Kern <span dir="ltr"><<a href="mailto:robert.kern@gmail.com">robert.kern@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">On 3/16/11 12:13 PM, Ian Bicking wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I'll note this general problem is also present in any of the declarative ORMs,<br>
which use silly hacks to tell descriptors their name. Like you have:<br>
<br>
class Table(ORM):<br>
name = StringColumn()<br>
<br>
Another case where I've noticed a problem is any kind of descriptor that needs<br>
its own storage; the name of the property gives a possible stable namespace for<br>
the value, but without the name you either have to pass in a name or the storage<br>
area becomes volatile. For instance, a read-only descriptor:<br>
<a href="http://svn.colorstudy.com/home/ianb/recipes/setonce.py" target="_blank">http://svn.colorstudy.com/home/ianb/recipes/setonce.py</a><br>
<br>
You can solve this in, e.g., the ORM class by doing things when a class is<br>
created -- but it requires very specific cooperation between the class and the<br>
descriptor. Everyone really does it different ways.<br>
<br>
One could imagine an extension of the descriptor protocol, where on class<br>
creation you called something like attr.__addtoclass__(cls, name) (for all<br>
attributes of the class that define that method) -- which if you just want the<br>
name you'd simply save that name in your object and return self.<br>
</blockquote>
<br></div>
If we were to extend the descriptor protocol, I think it would be better to extend it by providing __get_ex__(self, instance, owner, name), __set_ex__(self, instance, name, value), etc. methods that would be called in preference over the current __get__() and __set__() methods. This allows descriptor objects to be reused.<br>
<br>
We do this reasonably often with the Traits package (which overrides __getattribute__() to essentially implement this __get_ex__()/__set_ex__() protocol by different names). For example, we have a complicated trait for specifying colors:<br>
<br>
ColorTrait = Trait("black", Tuple, List, Str, color_table)<br>
<br>
It would be nice to simply reuse this object everywhere:<br>
<br>
class Figure(HasTraits):<br>
background = ColorTrait<br>
foreground = ColorTrait<br></blockquote><div><br>As I was thinking of __addtoclass__ it would address this, though at class instantiation time instead of attribute access time. Specifically it would be like there was a fixup stage that would look like:<br>
<br>def fixup(cls):<br> for class_instance in cls.__mro__:<br> for name, value in class_instance.__dict__.items():<br> method = getattr(value, '__addtoclass__', None)<br> if method is not None:<br>
new_value = method(cls, name)<br> if new_value is not value:<br> setattr(cls, name, new_value)<br><br>If ColorTrait returns a new instance when __addtoclass__ is called, then it can, and all of its instances will be class-specific (and not shared with subclasses).<br>
<br> Ian<br><br></div></div>