# HG changeset patch # User Paul Boddie # Date 1214061803 -7200 # Node ID 7b78ddb23be648e1799342739b7a1ff6410285b2 # Parent de8cd27e721d58cd12225a287116b49c23b5d7df Added support for the detection of module attribute assignment. Added some more tests of module assignment. Introduced better system path initialisation based on the program being inspected. diff -r de8cd27e721d -r 7b78ddb23be6 docs/rationale.txt --- a/docs/rationale.txt Mon Jun 16 01:56:46 2008 +0200 +++ b/docs/rationale.txt Sat Jun 21 17:23:23 2008 +0200 @@ -7,8 +7,9 @@ Motivations * Run Python programs in "small" devices - * Small programs - * Few executed instructions + * Small programs plus few executed instructions + * Avoid expensive library code + (small footprint, lots of executed instructions) Python's flexibility comes at a cost @@ -17,6 +18,13 @@ * Difficult to predict eventual behaviour before execution * Difficult to generate optimisations when compiling +Not all things are dynamic/equal in Python + + * Locals, modules and classes are special in some way + * Locals don't tend to change unilaterally + * Modules usually retain their identity + * Classes differ from objects (despite metaclasses) + Attribute access * Must do a full lookup every time: @@ -34,7 +42,7 @@ Consequences of revised attribute access - * Cannot extend the range of attributes on objects + * Cannot extend the range of attributes on objects of existing classes * Further optimisations: * Restriction: attempt to control modification of attributes * Result: further optimisation of accesses diff -r de8cd27e721d -r 7b78ddb23be6 micropython/inspect.py --- a/micropython/inspect.py Mon Jun 16 01:56:46 2008 +0200 +++ b/micropython/inspect.py Sat Jun 21 17:23:23 2008 +0200 @@ -173,9 +173,26 @@ self.all_objects.add(obj) + def store_module_attr(self, name, module): + + """ + Record module attribute 'name' in the given 'module' using the current + expression. + """ + + if isinstance(self.expr, Attr): + assigned_value = self.expr.value + else: + assigned_value = self.expr + + module.set(name, assigned_value, 0) + def store_class_attr(self, name): - "Record class attribute 'name' in the current class." + """ + Record class attribute 'name' in the current class using the current + expression. + """ if self.in_method and self.namespaces[-2].has_key(name): @@ -300,9 +317,13 @@ def visitAssAttr(self, node): expr = self.dispatch(node.expr) - if isinstance(expr, Attr) and expr.name == "self": - if not self.store_class_attr(node.attrname): - self.store_instance_attr(node.attrname) + if isinstance(expr, Attr): + if expr.name == "self": + if not self.store_class_attr(node.attrname): + self.store_instance_attr(node.attrname) + elif isinstance(expr.value, Module): + self.store_module_attr(node.attrname, expr.value) + print "Warning: attribute %r of module %r set outside the module." % (node.attrname, expr.value.name) return None def visitAssList(self, node): diff -r de8cd27e721d -r 7b78ddb23be6 test.py --- a/test.py Mon Jun 16 01:56:46 2008 +0200 +++ b/test.py Sat Jun 21 17:23:23 2008 +0200 @@ -4,6 +4,7 @@ from micropython.rsvp import raw import rsvp import sys +import os code = None @@ -32,7 +33,15 @@ if __name__ == "__main__": args = sys.argv[2:] - i = micropython.Importer(sys.path, "-v" in args) + path = sys.path[:] + + if len(sys.argv) > 1: + program = os.path.abspath(sys.argv[1]) + path.append(os.path.split(program)[0]) + else: + program = None + + i = micropython.Importer(path, "-v" in args) if "-omax" in args: requested_optimisations = i.supported_optimisations @@ -45,11 +54,12 @@ try: builtins = i.load_from_file("lib/builtins.py", "__builtins__") - if len(sys.argv) < 2: + if program is None: + print "Loading module micropython ..." m = i.load("micropython") - #m = i.load_from_file("micropython/__init__.py") else: - m = i.load_from_file(sys.argv[1]) + print "Loading program", program, "..." + m = i.load_from_file(program) except micropython.ProcessingError, exc: print repr(exc) else: diff -r de8cd27e721d -r 7b78ddb23be6 tests/failure/imported.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/failure/imported.py Sat Jun 21 17:23:23 2008 +0200 @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +attr = 123 +a = 10 + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r de8cd27e721d -r 7b78ddb23be6 tests/failure/importer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/failure/importer.py Sat Jun 21 17:23:23 2008 +0200 @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +import imported + +imported.attr = 456 # detected with warning + +m = imported +imported.a = 9 # detected with warning +m.a = 8 # detected with warning (m is always imported) + +imported.x = 1 # detected with warning (despite no collision) + +n = None +n = imported +n.y = 2 # not detected due to reassignment of n +n.y = 3 # not detected due to reassignment of n + +# vim: tabstop=4 expandtab shiftwidth=4