Turn of globals in a function?

Ron_Adam radam2 at tampabay.rr.com
Thu Mar 31 19:31:40 CEST 2005


On Thu, 31 Mar 2005 16:28:15 +1200, Greg Ewing
<greg at cosc.canterbury.ac.nz> wrote:

>Oren Tirosh wrote:
>> def noglobals(f):
>> .   import new
>> .   return new.function(
>> .       f.func_code, 
>> .       {'__builtins__':__builtins__},
>> .       f.func_name, 
>> .       f.func_defaults, 
>> .       f.func_closure
>> .   )
>
>Be aware that this will render the function incapable
>of seeing *any* globals at all, including other
>functions and classes defined in the same module --
>which you may find rather inconvenient!


Developing this idea further... 

This allows a programmer to specify what globals to allow read and or
writes.


Cheers, 
Ron


#---start---
# useglobals.py

"""
A function to specify what globals and builtins
a function may access.
Author: Ronald Adam
"""

def useglobals(rw_globals=None, r_globals=None, builtins=True):
    #import dis
    import sys
    write_list = []
    read_list = []
    if rw_globals != None:
        rw_globals = rw_globals.replace(' ','')        
        write_list = rw_globals.split(',')
    if r_globals != None:
        r_globals = r_globals.replace(' ','')
        read_list = r_globals.split(',')
    if builtins == True:
        read_list.extend(dir(__builtins__))
    elif builtins != None:
        builtins = builtins.replace(' ','')
        read_list.extend(builtins.split(','))
    # Add own name to read list.
    read_list.append(sys._getframe(0).f_code.co_name)
    read_list.extend(write_list)
    #print read_list, write_list    
    names = sys._getframe(1).f_code.co_names
    code = sys._getframe(1).f_code.co_code
    #print dis.disassemble(sys._getframe(1).f_code)
    i = 0
    while i < len(code):
        #print ord(code[i])
        op = ord(code[i])        
        if op == 116:       # dis.opmap['LOAD_GLOBAL']
            oparg = ord(code[i+1]) + ord(code[i+2]) * 256
            if str(names[oparg]) not in read_list:
                raise NameError, "read from global name %s, detected"
% names[oparg]
        elif op == 97:      # dis.opmap['STORE_GLOBAL']
            oparg = ord(code[i+1]) + ord(code[i+2]) * 256
            if names[oparg] not in write_list:
                raise NameError, "write to global name %s, detected" %
names[oparg]
        if op >= 90:        # dis.HAVE_ARGUMENT
            i += 3          # Not sure if this is always the same?
        else:
            i += 1


if __name__ == '__main__':
    """
    Test useglobals() function. Change values to test
    for error catching.
    """
                
    def a():
        useglobals(rw_globals='x', r_globals='y,b')
        # This function can read or write 'x',
        # Can read 'y', and function 'b',
        # and can access all builtins.
        global x
        y = 5
        x += y
        x = b(x)
        return x

    def b(g):
        useglobals('','y,c','int')
        # This function can only read 'y' and
        # function 'c' in globals, and can
        # only access 'int' in builtins.
        g = g+y
        c(int(g))
        return g

    def c(w):
        useglobals(builtins=None)
        # This function has no builtins or globals.
        w = w**2
        return w

    y = 4
    x = 5
    z = 6
    print a(),x,y,z

#---end---




More information about the Python-list mailing list