# HG changeset patch # User Paul Boddie # Date 1338854094 -7200 # Node ID 830194e3b6aba66ed25961c77c49010e9aa6e6a9 # Parent 6a5775a852482041a03ae000b2f86e3d518555d4 Reinstated tentative declarations of instance attributes from attribute usage that can be overridden by the declaration of class attributes for classes in the same hierarchy. Thus, "mix-in" classes whose methods employ self-based attribute accesses will not cause instance attributes to be allocated if class attributes are defined in descendant classes making use of such "mix-in" classes. diff -r 6a5775a85248 -r 830194e3b6ab micropython/data.py --- a/micropython/data.py Tue Jun 05 01:30:05 2012 +0200 +++ b/micropython/data.py Tue Jun 05 01:54:54 2012 +0200 @@ -1303,6 +1303,7 @@ self.bases = [] self.descendants = set() self.instattr = set() # instance attributes + self.instattr_tentative = set() # tentative/suspected instance attributes self.relocated = set() # attributes which do not have the same # position as those of the same name in # some superclasses @@ -1446,8 +1447,11 @@ self.bases.append(base) base.add_descendant(self) - def add_instance_attribute(self, name): - self.instattr.add(name) + def add_instance_attribute(self, name, tentative=False): + if tentative: + self.instattr_tentative.add(name) + else: + self.instattr.add(name) def add_descendant(self, cls): self.descendants.add(cls) @@ -1553,6 +1557,21 @@ "Make sure that the instance attributes are fully defined." + # Eliminate tentative instance attributes that are actually class + # attributes. + + for attrname in self.all_class_attributes().keys(): + if attrname in self.instattr_tentative: + self.instattr_tentative.remove(attrname) + + for cls in self.descendants: + for attrname in cls.class_attribute_names(): + if attrname in self.instattr_tentative: + self.instattr_tentative.remove(attrname) + + for attrname in self.instattr_tentative: + self.instattr.add(attrname) + # Cache the attributes by converting the positioned attributes into a # dictionary. diff -r 6a5775a85248 -r 830194e3b6ab micropython/inspect.py --- a/micropython/inspect.py Tue Jun 05 01:30:05 2012 +0200 +++ b/micropython/inspect.py Tue Jun 05 01:54:54 2012 +0200 @@ -327,9 +327,13 @@ cls.set(name, self.expr, 0) self.use_specific_attribute(cls.full_name(), name) - def store_instance_attr(self, name): + def store_instance_attr(self, name, tentative=False): - "Record instance attribute 'name' in the current class." + """ + Record instance attribute 'name' in the current class. If 'tentative' is + set to a true value, the instance attribute will be discarded if a class + attribute is observed. + """ if self.in_method: @@ -337,7 +341,7 @@ # Previous namespace is the class. cls = self.namespaces[-2] - cls.add_instance_attribute(name) + cls.add_instance_attribute(name, tentative) # NOTE: The instance attribute, although defined in a specific # NOTE: class, obviously appears in all descendant classes. @@ -514,6 +518,12 @@ # to be an instance. else: + + # Record any instance attributes. + + if expr.name == "self": + self.store_instance_attr(attrname, tentative=True) + attr = make_instance() # Note usage of the attribute where a local is involved.