detecting containers during object introspection

David C. Fox davidcfox at post.harvard.edu
Tue Jul 22 11:03:11 EDT 2003


Steven Taschuk wrote:
> Quoth David C. Fox:
>   [...]
> 
>>However, the real problem occurs if the developer makes a change like 
>>this (or even just adds a new attribute which is a non-standard 
>>container), and does increment the version number.  Because the version 
>>number was incremented, the regression test would *expect* some of the 
>>dictionary elements to change type or structure, and would simply update 
>>the standard example dictionary.  Then, any *subsequent* changes to the 
>>structure of the values in that container would go undetected (unless 
>>the developer had also updated the recursive comparison operation to 
>>take into account that the unknown object was a container).
> 
> 
> Yes, I see.  Thorny.
> 
> What if your recursive comparison operation choked on values of
> unknown types rather than falling back on the weak "have same
> type" criterion?  That way, the developer who changes the
> structure by introducing values of (e.g.) a new dict work-alike
> type would see tests fail, which would remind her to add to that
> comparison operation the necessary knowledge of the new type.
> 
> Fail safe, in other words, where "safe" means "no false positives
> from the regression test".
> 

That's one possibility.  My original reaction to it was that requiring 
developers to write comparison operations for every class whose 
instances are found in the stored dictionary seemed like overkill.  Then 
I started think about what classes actually were found there.  Many of 
them contain lists or dictionaries, and changes to the internal 
structure of those classes would cause the same problems described 
above.  Therefore, just noting that the old and new versions had an 
attribute with the same class wouldn't be sufficient.

Then, I recalled that any object instance *has* a dictionary of 
attributes: __dict__.  So, instead of writing custom comparison 
operators for each class, I should be able to define a generic 
comparison operator cmp_struct(x, y) which returns true iff

1) type(x) == type(y), and

2) one of the following is true:
    a) type(x) == type({}), and
       x.keys() and y.keys() match, and
       for each key, cmp_struct(x[key], y[key]) is true
    b) type(x) == type([]), and
       for each pair of items in x and y, cmp_struct returns true
    c) type(x) == types.InstanceType, and
       cmp_struct(x.__dict__, y.__dict__) is true
    d) type(x) is not any of the above

Thanks for your advice.  It is really nice to have someone to bounce 
ideas off of.

David





More information about the Python-list mailing list