Re: Multi-line string extension ( upglobals, uplocals )

Steven D. Majewski (sdm7g@elvis.med.virginia.edu)
Tue, 19 Apr 1994 13:30:49 -0400

On Apr 19, 4:27, Tim Peters wrote:
>
> I hate to mention this, but I have sometimes wished for functions along
> the lines of
>
> uplocals(i)
> upglobals(i)
>
> that return dicts holding the current bindings of the local & global
> namespaces "i" levels up the call stack (and where i==0 means the current
> function). The i==1 case in particular would be handy for writing a
> pleasant-to-use "substitute" function. BTW, in all the uses I've ever
> imagined for this, I never wanted to _change_ an up-level binding via
> fiddling the returned dict; just wanted to get a current _snapshot_ of
> the up-level name->value maps, for inspection only. Insisting on
> returning the _actual_ namespaces would probably be an implementation
> nightmare (for locals, since they're not ordinarily maintained in genuine
> dicts anymore, & that's a feature).
>

You wish is my command, Tim!

You may remember, I *DID* want to change (or add) an uplevel binding
in my newmod module. ImportModule is supposed to have a side effect
in it's callers namespace, the same as an import statement:

def caller():
import sys
try:
1 + '' # make an error happen
except: # and return the caller's caller's frame
return sys.exc_traceback.tb_frame.f_back.f_back

def ImportModule( filename, modname ):
newmodule = importmodule( filename, modname )
frame = caller() # get the caller's frame
frame.f_globals[modname] = newmodule # and enter name in dict

Adapting a more generalized piece of code done when we were on the
subject of tracebacks ( from which I also clipped the above from
newmod.py ), here is your upglobals/uplocals.

( Note: when you uplocals(n) all the way up to the main interactive
level, you get a recursive (non printable) object. )

-- Steve Majewski (804-982-0831) <sdm7g@Virginia.EDU> --
-- UVA Department of Molecular Physiology and Biological Physics --
-- Box 449 Health Science Center Charlottesville,VA 22908 --
[ "Cognitive Science is where Philosophy goes when it dies ...
if it hasn't been good!" - Jerry Fodor ]

--------------------------------

def linearize( head, link_attr ):
list = []
obj = head
while obj:
list.append( obj )
obj = getattr( obj, link_attr )
return list

def callers():
import sys
try:
1 + ''
except:
traces = linearize( sys.exc_traceback.tb_frame, 'f_back' )
list = []
for frame in traces :
list.append( frame )
return list[2:] # return my callers callers

def upglobals( n ):
return callers()[n].f_globals

def uplocals( n ):
return callers()[n].f_locals

def upfname( n ):
return callers()[n].f_code.co_name