# HG changeset patch # User Paul Boddie # Date 1340145843 -7200 # Node ID 1b42eee2b7499784889dc0158439d4b570bba342 # Parent ea25b91e1adc9867c719b58219303b6517dcbed2 Changed attribute usage recording to apply only to function and class definition locals. diff -r ea25b91e1adc -r 1b42eee2b749 docs/concepts.txt --- a/docs/concepts.txt Tue Jun 19 00:29:57 2012 +0200 +++ b/docs/concepts.txt Wed Jun 20 00:44:03 2012 +0200 @@ -45,6 +45,58 @@ See rejected.txt for complicating mechanisms which could be applied to mitigate the effects of these restrictions on optimisations. +Attribute Usage Observations +============================ + +Within a scope, a name may be used in conjunction with attribute names in +order to access attributes on objects referenced by the name. However, such +observations can only be regarded as reliable if the object referenced is not +changed independently by some other mechanism or activity. + +With conventional functions and methods, any locally defined names can be +considered private to that scope and thus immune to independent modification, +at least within reasonable features of the language. Although stack +modification may be possible, it seems appropriate to reject such features, +especially since they lend themselves to unmaintainable programs. + +For names defined during the initialisation of a class, since the class itself +cannot be referenced by name until its declaration has been completely +evaluated, no independent modification can occur from outside the class scope. + +For names defined during the initialisation of a module, global declarations +in functions permit the rebinding of global variables and since functions may +be invoked during module initialisation, independent modification can +potentially occur if any functions are called. + +Module globals can be accessed from other modules that can refer to a module +by its name. Initially, an import is required to make a module available for +modification, but there is no restriction on whether a module has been +completely imported (and thus defined) before an import statement can make it +available to other modules. Consider the following package root definition: + + # Module test: + def f(): + import test.modifier + x = 123 + f() + + # Module test.modifier: + import test + test.x = 456 + +Here, an import of test will initially set x to 123, but then the function f +will be invoked and cause the test.modifier module to be imported. Since the +test module is already being imported, the import statement will not try to +perform the import operation again, but it will make the partially defined +module available for access. Thus, the test.modifier module will then set x to +456, and independent modification of the test namespace will have been +performed. + +In conclusion, module globals cannot therefore be regarded as immune to +operations that would disrupt usage observations. Consequently, only locals +and class definition "locals" can be reliably employed in attribute usage +observations. + Contexts and Values =================== diff -r ea25b91e1adc -r 1b42eee2b749 micropython/inspect.py --- a/micropython/inspect.py Tue Jun 19 00:29:57 2012 +0200 +++ b/micropython/inspect.py Wed Jun 20 00:44:03 2012 +0200 @@ -582,9 +582,11 @@ where such attributes are inferred from the usage. """ - # Access to attribute via a local. + # Access to attribute via a local in functions or classes but not + # modules (since module-level locals are globals that can be modified + # independently of the namespace). - if expr.parent is self.get_namespace(): + if expr.parent is self.get_namespace() and not self.get_namespace() is self: # NOTE: Revisiting of nodes may occur for loops. diff -r ea25b91e1adc -r 1b42eee2b749 tests/attribute_access_type_restriction_global_reassigned.py --- a/tests/attribute_access_type_restriction_global_reassigned.py Tue Jun 19 00:29:57 2012 +0200 +++ b/tests/attribute_access_type_restriction_global_reassigned.py Wed Jun 20 00:44:03 2012 +0200 @@ -36,11 +36,12 @@ obj = d if obj.f(): + obj.g() change_global() - x = obj.g() + x = obj.f() else: x = 2 -result_3 = x +result_4 = x # vim: tabstop=4 expandtab shiftwidth=4