# HG changeset patch # User Paul Boddie # Date 1192837004 -7200 # Node ID 3699ff87d748730259e89041125bfaf00bde0716 # Parent 63fdd990941208dbfd34b36d0498c07eadea9390 Added "vacuum" methods for removing speculatively created modules. Separated the __builtins__ module namespace from each module's own namespace. Added function parameter details to Function objects. Added convenience methods for dictionary access to objects. Added more missing node visitor methods. diff -r 63fdd9909412 -r 3699ff87d748 micropython/__init__.py --- a/micropython/__init__.py Wed Oct 17 01:31:33 2007 +0200 +++ b/micropython/__init__.py Sat Oct 20 01:36:44 2007 +0200 @@ -54,6 +54,16 @@ self.modules = {} self.loading = set() + def vacuum(self): + + "Tidy up the modules." + + for name, module in self.modules.items(): + if module.loaded: + module.vacuum() + else: + del self.modules[name] + def get_modules(self): "Return all modules known to the importer." diff -r 63fdd9909412 -r 3699ff87d748 micropython/inspect.py --- a/micropython/inspect.py Wed Oct 17 01:31:33 2007 +0200 +++ b/micropython/inspect.py Sat Oct 20 01:36:44 2007 +0200 @@ -32,7 +32,17 @@ pass -class Class: +class NamespaceDict: + + "A mix-in providing dictionary methods." + + def __getitem__(self, name): + return self.namespace[name] + + def keys(self): + return self.namespace.keys() + +class Class(NamespaceDict): "An inspected class." @@ -45,14 +55,26 @@ def add_base(self, base): self.bases.append(base) -class Function: +class Function(NamespaceDict): "An inspected function." + def __init__(self, name, argnames, has_star, has_dstar): + self.name = name + self.argnames = argnames + self.has_star = has_star + self.has_dstar = has_dstar + self.namespace = {} + +class UnresolvedName(NamespaceDict): + + "A module, class or function which was mentioned but could not be imported." + def __init__(self, name): self.name = name + self.namespace = {} -class Module(ASTVisitor): +class Module(ASTVisitor, NamespaceDict): "An inspected module." @@ -67,7 +89,6 @@ # Module namespace. self.namespace = {} - self.namespace.update(builtins_namespace) # Current expression state. @@ -94,11 +115,12 @@ self.namespace[n.value] = self.importer.add_module(self.name + "." + n.value) return processed - def default(self, node, *args): - raise InspectError, node.__class__ + def vacuum(self): + for name, value in self.namespace.items(): + if isinstance(value, Module) and not value.loaded: + del self.namespace[name] - def dispatch(self, node, *args): - return ASTVisitor.dispatch(self, node, *args) + # Namespace methods. def store(self, name, obj): if self.in_global: @@ -111,6 +133,14 @@ if self.in_init: self.classes[-1].instattr.add(name) + # Visitor methods. + + def default(self, node, *args): + raise InspectError, node.__class__ + + def dispatch(self, node, *args): + return ASTVisitor.dispatch(self, node, *args) + def NOP(self, node): return node @@ -186,23 +216,31 @@ if module is None: print "Warning:", node.modname, "not imported." - return None for name, alias in node.names: if name != "*": - self.namespace[alias or name] = attr = module.namespace[name] - if isinstance(attr, Module) and not attr.loaded: - self.importer.load(attr.name) - else: - for n in module.namespace.keys(): - self.namespace[n] = attr = module.namespace[n] + if module is not None: + self.namespace[alias or name] = attr = module.namespace[name] if isinstance(attr, Module) and not attr.loaded: self.importer.load(attr.name) + else: + self.namespace[alias or name] = UnresolvedName(name) + else: + if module is not None: + for n in module.namespace.keys(): + self.namespace[n] = attr = module.namespace[n] + if isinstance(attr, Module) and not attr.loaded: + self.importer.load(attr.name) return None def visitFunction(self, node): - self.store(node.name, Function(node.name)) + function = Function( + node.name, + node.argnames, + has_star=(node.flags & 4 != 0), + has_dstar=(node.flags & 8 != 0) + ) in_global = self.in_global self.in_global = 0 @@ -211,6 +249,8 @@ self.dispatch(node.code) self.in_init = 0 self.in_global = in_global + + self.store(node.name, function) return None def visitGetattr(self, node): @@ -218,7 +258,7 @@ if expr is not None and isinstance(expr, Module): return expr.namespace.get(node.attrname) else: - return None + return builtins_namespace.get(node.attrname) def visitIf(self, node): for test, body in node.tests: @@ -248,12 +288,16 @@ visitMul = NOP + visitMod = NOP + def visitName(self, node): name = node.name if name == "self": return Self() elif self.namespace.has_key(name): return self.namespace[name] + elif builtins_namespace.has_key(name): + return builtins_namespace[name] else: return None diff -r 63fdd9909412 -r 3699ff87d748 test.py --- a/test.py Wed Oct 17 01:31:33 2007 +0200 +++ b/test.py Sat Oct 20 01:36:44 2007 +0200 @@ -5,5 +5,6 @@ i = micropython.Importer(sys.path) m = i.load("micropython") #m = i.load_from_file("micropython/__init__.py") +i.vacuum() # vim: tabstop=4 expandtab shiftwidth=4