# HG changeset patch # User Paul Boddie # Date 1200697915 -3600 # Node ID eb64b7d28fbe1a2d8e96558e96937619c6123987 # Parent 4f83a4f9373acb62cf138a52b07c3863d8a2c77b Fixed Const.__repr__ and visitConst. Added a global namespace reference to NamespaceDict, supporting assignment tracking for globals below the module level. Introduced support for local imports. diff -r 4f83a4f9373a -r eb64b7d28fbe micropython/inspect.py --- a/micropython/inspect.py Fri Jan 18 00:55:11 2008 +0100 +++ b/micropython/inspect.py Sat Jan 19 00:11:55 2008 +0100 @@ -64,9 +64,10 @@ "A mix-in providing dictionary methods." - def __init__(self): + def __init__(self, global_namespace=None): self.namespace = {} self.globals = set() + self.global_namespace = global_namespace # Number of assignments per name. @@ -83,11 +84,15 @@ self.namespace[name] = value # Record the number of assignments to each name. + # NOTE: Insist on assignments with known values. - if not self.assignments.has_key(name): - self.assignments[name] = 1 - else: - self.assignments[name] += 1 + if value is not None: + if not self.assignments.has_key(name): + self.assignments[name] = 1 + else: + self.assignments[name] += 1 + else: + self.global_namespace[name] = value def __delitem__(self, name): del self.namespace[name] @@ -146,7 +151,7 @@ self.location = None def __repr__(self): - return "Const(%r, location=%d)" % (self.value, self.location) + return "Const(%r, location=%r)" % (self.value, self.location) def __eq__(self, other): return self.value == other.value @@ -158,8 +163,8 @@ "An inspected class." - def __init__(self, name, parent_name, node=None): - NamespaceDict.__init__(self) + def __init__(self, name, parent_name, global_namespace=None, node=None): + NamespaceDict.__init__(self, global_namespace) self.name = name self.parent_name = parent_name self.node = node @@ -300,8 +305,8 @@ "An inspected function." - def __init__(self, name, parent_name, argnames, has_star, has_dstar, node=None): - NamespaceDict.__init__(self) + def __init__(self, name, parent_name, argnames, has_star, has_dstar, global_namespace=None, node=None): + NamespaceDict.__init__(self, global_namespace) self.name = name self.parent_name = parent_name self.argnames = argnames @@ -371,8 +376,8 @@ "A module, class or function which was mentioned but could not be imported." - def __init__(self, name, parent_name): - NamespaceDict.__init__(self) + def __init__(self, name, parent_name, global_namespace=None): + NamespaceDict.__init__(self, global_namespace) self.name = name self.parent_name = parent_name @@ -390,7 +395,7 @@ "An inspected module's core details." def __init__(self, name): - NamespaceDict.__init__(self) + NamespaceDict.__init__(self, self) self.name = name # Module attributes. @@ -603,7 +608,7 @@ if self.namespaces: print "Class %r in %r is not global: ignored." % (node.name, self) else: - cls = Class(node.name, self.get_parent().full_name(), node) + cls = Class(node.name, self.get_parent().full_name(), self, node) for base in node.bases: base_ref = self.dispatch(base) if base_ref is None: @@ -629,6 +634,7 @@ def visitConst(self, node): const = Const(node.value) self.constant_values[node.value] = const + return const visitContinue = NOP @@ -659,21 +665,23 @@ if module is None: print "Warning:", node.modname, "not imported." - # NOTE: This could produce local names instead of globals where import - # NOTE: is used within functions. - for name, alias in node.names: if name != "*": if module is not None and module.namespace.has_key(name): - self[alias or name] = attr = module[name] + attr = module[name] + self.store(alias or name, attr) if isinstance(attr, Module) and not attr.loaded: self.importer.load(attr.name) + + # Support the import of names from missing modules. + else: - self[alias or name] = UnresolvedName(name, node.modname) + self.store(alias or name, UnresolvedName(name, node.modname, self)) else: if module is not None: for n in module.namespace.keys(): - self[n] = attr = module[n] + attr = module[n] + self.store(n, attr) if isinstance(attr, Module) and not attr.loaded: self.importer.load(attr.name) @@ -686,6 +694,7 @@ node.argnames, (node.flags & 4 != 0), (node.flags & 8 != 0), + self, node ) @@ -722,7 +731,7 @@ if isinstance(expr, Module): return expr.namespace.get(node.attrname) elif isinstance(expr, UnresolvedName): - return UnresolvedName(node.attrname, expr.full_name()) + return UnresolvedName(node.attrname, expr.full_name(), self) return builtins.get(node.attrname) def visitGlobal(self, node): @@ -745,14 +754,11 @@ if self.importer is None: raise InspectError, "Please use the micropython.Importer class for code which uses the 'import' statement." - # NOTE: This could produce local names instead of globals where import - # NOTE: is used within functions. - for name, alias in node.names: if alias is not None: - self[alias] = self.importer.load(name, 1) or UnresolvedName(None, name) + self.store(alias, self.importer.load(name, 1) or UnresolvedName(None, name, self)) else: - self[name.split(".")[0]] = self.importer.load(name) or UnresolvedName(None, name.split(".")[0]) + self.store(name.split(".")[0], self.importer.load(name) or UnresolvedName(None, name.split(".")[0], self)) return None @@ -884,10 +890,10 @@ 'bool', 'buffer', 'complex', 'dict', 'file', 'float', 'int', 'list', 'long', 'object', 'slice', 'str', 'tuple', 'type', 'unicode', 'xrange']: - self[key] = Class(key, self.full_name()) + self[key] = Class(key, self.full_name(), self) for key in ['id', 'len']: - self[key] = Function(key, self.full_name(), ['arg'], 0, 0) + self[key] = Function(key, self.full_name(), ['arg'], 0, 0, self) builtins = Builtins()