# HG changeset patch # User Paul Boddie # Date 1201913602 -3600 # Node ID c6990bc3734c99f21e9d2065c2549701faa6602f # Parent 3f372b5e291a4d9e4ec6642995982dbc964a3925 Fixed global scope assignments, introducing an AtLeast class which indicates that such assignments may occur several times (since they appear in code which may be executed more than once). Changed Attr construction to fill in None for missing assignment details. diff -r 3f372b5e291a -r c6990bc3734c micropython/inspect.py --- a/micropython/inspect.py Tue Jan 29 01:01:11 2008 +0100 +++ b/micropython/inspect.py Sat Feb 02 01:53:22 2008 +0100 @@ -3,7 +3,7 @@ """ Inspect source files, obtaining details of classes and attributes. -Copyright (C) 2007 Paul Boddie +Copyright (C) 2007, 2008 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -36,7 +36,7 @@ to distinguish between certain kinds of attributes: * Class: (class|all_class|instance|all)_attributes - * Function: parameters, locals + * Function: parameters, locals, all_locals * Module: module_attributes These specific methods are useful in certain situations. @@ -58,6 +58,49 @@ pass +class AtLeast: + + "A special representation for numbers of a given value or greater." + + def __init__(self, count): + self.count = count + + def __eq__(self, other): + return 0 + + __lt__ = __le__ = __eq__ + + def __ne__(self, other): + return 1 + + def __gt__(self, other): + if isinstance(other, AtLeast): + return 0 + else: + return self.count > other + + def __ge__(self, other): + if isinstance(other, AtLeast): + return 0 + else: + return self.count >= other + + def __iadd__(self, other): + if isinstance(other, AtLeast): + self.count += other.count + else: + self.count += other + return self + + def __radd__(self, other): + if isinstance(other, AtLeast): + return AtLeast(self.count + other.count) + else: + return AtLeast(self.count + other) + + def __repr__(self): + return "AtLeast(%r)" % self.count + # Mix-ins and abstract classes. class NamespaceDict: @@ -80,19 +123,31 @@ return self.namespace.get(name, default) def __setitem__(self, name, value): + + # Use a special method to access the namespace. + if name not in self.globals: - self.namespace[name] = value + self.set(name, value) + else: + self.global_namespace.set(name, value, 1) + + def set(self, name, value, global_assignment=0): + self.namespace[name] = value - # Record the number of assignments to each name. - # NOTE: Insist on assignments with known values. + # Record the number of assignments to each name. + # NOTE: Insist on assignments with known values. - if value is not None: - if not self.assignments.has_key(name): + if value is not None: + if not self.assignments.has_key(name): + if global_assignment: + self.assignments[name] = AtLeast(1) + else: self.assignments[name] = 1 + else: + if global_assignment: + self.assignments[name] += AtLeast(1) else: self.assignments[name] += 1 - else: - self.global_namespace[name] = value def __delitem__(self, name): del self.namespace[name] @@ -213,7 +268,7 @@ self.classattr_names = self.keys() for i, name in enumerate(self.classattr_names): - self.classattr[name] = Attr(i, self, self.assignments[name], self[name]) + self.classattr[name] = Attr(i, self, self.assignments.get(name), self[name]) return self.classattr @@ -452,7 +507,7 @@ self.modattr = {} self.modattr_names = self.keys() for i, name in enumerate(self.modattr_names): - self.modattr[name] = Attr(i, self, self.assignments[name], self[name]) + self.modattr[name] = Attr(i, self, self.assignments.get(name), self[name]) return self.modattr