# HG changeset patch # User Paul Boddie # Date 1203637348 -3600 # Node ID 0fef6a91098cda91110dbb050475199039b658ac # Parent 27ab716dcedb9a6e8636544bb1c407b4a67b73d8 Attempt to provide instance attribute position re-use. Added a test of subclasses. diff -r 27ab716dcedb -r 0fef6a91098c micropython/inspect.py --- a/micropython/inspect.py Tue Feb 19 00:05:22 2008 +0100 +++ b/micropython/inspect.py Fri Feb 22 00:42:28 2008 +0100 @@ -252,14 +252,17 @@ self.node = node self.bases = [] - self.instattr = set() # instance attributes + self.instattr = set() # instance attributes + self.instattr_relocated = set() # instance attributes which do not have + # the same position as those of the same + # name in some superclasses - self.all_instattr = None # cache for instance_attributes - self.all_instattr_names = None # from all_instattr - self.all_classattr = None # cache for all_class_attributes + self.all_instattr = None # cache for instance_attributes + self.all_instattr_names = None # from all_instattr + self.all_classattr = None # cache for all_class_attributes self.all_classattr_names = None # from all_classattr - self.allattr = None # cache for all_attributes - self.allattr_names = None # from allattr + self.allattr = None # cache for all_attributes + self.allattr_names = None # from allattr # Image generation details. @@ -329,25 +332,74 @@ if self.all_instattr is None: self.all_instattr = {} - instattr = set() + instattr = {} reversed_bases = self.bases[:] reversed_bases.reverse() + + # For the bases in reverse order, acquire instance attribute + # details. + for cls in reversed_bases: - instattr.update(cls.instance_attributes().keys()) + for name, attr in cls.instance_attributes().items(): + if not instattr.has_key(name): + instattr[name] = set() + instattr[name].add(attr.position) # Record instance attributes provided by this class and its bases, # along with their positions. - instattr.update(self.instattr) + for name in self.instattr: + if not instattr.has_key(name): + instattr[name] = set([-1]) # position not yet defined + + if not instattr: + self.all_instattr = {} + else: + positions = instattr.items() + instarray = [None] * len(positions) + + # Get the positions in ascending order of list size, with lists + # of the same size ordered according to their smallest position + # value. + + positions.sort(self._cmp_positions) + #print self.name, positions - for i, name in enumerate(instattr): - self.all_instattr[name] = Attr(i, None, name) + # Get the names in position order. + + held = [] + + for name, pos in positions: + pos = list(pos) + if pos[0] != -1 and instarray[pos[0]] is None: + instarray[pos[0]] = name, Attr(pos[0], None, name) + else: + if pos[0] != -1 or len(pos) > 1: + self.instattr_relocated.add(name) + held.append((name, pos)) + + for i, attr in enumerate(instarray): + if attr is None: + name, pos = held.pop() + instarray[i] = name, Attr(i, None, name) + + self.all_instattr = dict(instarray) self.all_instattr_names = self.all_instattr.keys() return self.all_instattr + def _cmp_positions(self, a, b): + name_a, list_a = a + name_b, list_b = b + if len(list_a) < len(list_b): + return -1 + elif len(list_a) > len(list_b): + return 1 + else: + return cmp(min(list_a), min(list_b)) + def all_attribute_names(self): """ diff -r 27ab716dcedb -r 0fef6a91098c tests/subclass.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/subclass.py Fri Feb 22 00:42:28 2008 +0100 @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +class A: + def __init__(self, x): + self.x = x + + def a(self): + pass + +class B(A): + def b(self): + pass + +class C(A, B): + def __init__(self, x, y): + self.x = x + self.y = y + + def a(self): + pass + +class D: + def __init__(self, y): + self.y = y + +class E(C, D): + pass + +class F(A, D): + pass + +# vim: tabstop=4 expandtab shiftwidth=4