Update to PEP 227 (static scoping)

Fredrik Lundh fredrik at pythonware.com
Wed Feb 21 15:45:00 EST 2001


Jeremy wrote:

>     - A function that contains a nested function with free variables
>       and also uses exec that does not specify a namespace, e.g.
>           def f():
>               exec foo
>               def g():
>                   ...
>       "exec foo in ns" should be legal, although the current CVS code
>       base does not yet allow it.
>
>     - A function like the one above, except that is uses import *
>       instead of exec.

Note that in real life, "free" means "global or builtin".  For example,
this common Tkinter pattern will no longer compile:

import sys
def makeui():
    from Tkinter import *
    def callback():
        print "bye"
        sys.exit(1)
    Button(command=callback).pack()

# gives an error on line two (the first def statement)

If you have 2.1a2 installed, the following script will check for exec
and import problems.  Run it from the top of your development tree,
and let us know what you find...  (running it on the 2.0 source tree
is also somewhat entertaining ;-)

#
# look for exec/import scope problems

import os
import fnmatch
import string, traceback

class GlobDirectoryWalker:
    # a forward iterator that traverses a directory tree

    def __init__(self, directory, pattern="*"):
        self.stack = [directory]
        self.pattern = pattern
        self.files = []
        self.index = 0

    def __getitem__(self, index):
        while 1:
            try:
                file = self.files[self.index]
                self.index = self.index + 1
            except IndexError:
                # pop next directory from stack
                self.directory = self.stack.pop()
                self.files = os.listdir(self.directory)
                self.index = 0
            else:
                # got a filename
                fullname = os.path.join(self.directory, file)
                if os.path.isdir(fullname) and not os.path.islink(fullname):
                    self.stack.append(fullname)
                if fnmatch.fnmatch(file, self.pattern):
                    return fullname

count = 0
for file in GlobDirectoryWalker(".", "*.py"):
    try:
        # print file, "..."
        count = count + 1
        print count, "\r",
        compile(open(file).read() + "\n", file, "exec")
    except SyntaxError, v:
        v = str(v)
        if string.find(v, "nested scope") > 0:
            print "-" * 68
            print file
            traceback.print_exc()
print count, "files checked"

# Cheers /F





More information about the Python-list mailing list