So, the title pretty much says it all.
for instance let's look at the below example code:
## How can I obtain a dict/list (like locals()) of all the variables in second and/or third layer scopes via a command
# coming from the first layer?
## Or another example would be how could I obtain the variables "locals() style" from the thirdlayer via a
# command from the second layer?
# essentially can a parent function/class access a list/dict of a child function
# or class??
def firstLayer():
a = 4.7
q = locals()
print(q)
# local vars of 1st layer
def secondlayer():
b = 7
r = locals()
print(r)
# local vars of 2nd layer
def thirdlayer():
c = False
s = locals()
i = globals()
print('c:\n', c, "\nglobals from 3rd layer:\n\t", i)
# local vars of 3rd layer
thirdlayer()
secondlayer()
firstLayer()
sample_var = globals()
print(sample_var)
# returns the list of global variables
to reiterate what I said in the comments in the code, essentially is their any way I can get a list of all the variables local to a 'child' scope? I know functions are shut off, but if their is no way to do this is their any more complicated code that could achieve this and I could integrate it into a function or class if necessary.
EDIT: To elaborate further; here's the situation i'm in.
def varsfunc():
font1 = "Harlow Solid"
grey = '#454545'
font2 = 'Mistral'
font3 = 'Italic 35px Times New Roman'
pnk = 'pink'
grn = 'green'
return locals()
Essentially, I am creating a module and the user must create some type of function that they list all of they variables they would like to declare to be used to modify a css file. Essentially, I would like to allow the user to not have to type "return locals()". I want to achieve it by having the end-users wrap the above example function in a decorator that will do the equivalent of returning locals() of the exact scope I want. The decorator does not work for me because it is in an outer scope.
TO BE EVEN MORE CLEAR: I need a decorator/function that wraps another function(i.e. a decorator), that can access and create a list of a child element.
def module_decorator_func_thing():
r = command_that_acts_like_locals()_but_for_child_scopes
def user_var_list():
font1 = 'green'
font2 = 'pink'
# back in "module_decorator_func_thing"'s scope
print(r) # this variable should contain only a dict/list containing the
# the following:
# r = {'font1': 'green', 'font2': 'pink')
currently users need to do this:
def vars_func_container():
font1 = 'green'
font2 = 'pink'
return locals() # <---- I want the user to not have to type this and for
# a function decorator to take care of it instead possibly.
Info for @aguy and others wishing for more info. The dictionary/list that I am obtaining via your guys' tips will be sent to this function to do the real job of the program. (If I were to start using lists, i'd need to convert to a dictionary but that's no problem for me to solve.) The dict of variables is used with this function to "compile/compyle"(Pun on the word 'Python' + 'compile) and is insert in the "variables" parameter. e.g. you execute the function like this.
compyle("My sample title", return_stylesheet_from_func(*insert .css filename),
return_variables_from_function(*insert function containing variables*), "**True/False to turn on compilation**",
"**True/False to turn on annotations/suggestions**")
def compyle(title, style_sheet, variables, boolean=False, boolean2=True):
"""
:param title: The name you wish your .css file to be named.
:param style_sheet: The name of the multi-line string that will compose your .css file
:param variables: The name of the dictionary containing your .pcss variables
:param boolean: A.K.A the "Compiler Parameter" - Turns the compiler on or off
:param boolean2: A.K.A the "Annotation Parameter" - Turns annotations on or off
:return: returns compiled .pcss text as normal .css style text to be utilized with .html
"""
# -----------------------------------
file_name = title + ".css"
replace_num = len(variables.keys())
counter = replace_num
content = style_sheet
# -----------------------------------
# add theme support with namedtuple's formatted to mimic structs in C/C++
# this will be a major feature update as well as a nice way to allow the future prospect of integrating C/C++ into
# the compiler. Info: https://stackoverflow.com/questions/35988/c-like-structures-in-python
for k, v in variables.items():
counter -= 1
content = content.replace(k, v, replace_num)
if counter == 0:
break
else:
pass
looped_content = str(content)
id_content = looped_content.replace("hash_", "#")
output = id_content.replace("dot_", ".")
if boolean is True:
if boolean2 is True:
output = " /* --- Pyle Sheet --- */\n" + output
with open(file_name, 'w') as writ:
writ.write(output)
writ.close()
print('compiled successfully; The file was saved as ' + "\"" + file_name + "\".")
elif boolean2 is False:
pass
else:
logging.warning("An Error Occurred - see module, documentation, or online Q&A for assistance.")
elif boolean is False:
if boolean2 is True:
print('compiled successfully; The file ' + "\"" + file_name + "\"" + "was not saved/created.")
elif boolean2 is False:
pass
else:
logging.warning("An Error Occurred - see module, documentation, or online Q&A for assistance.")
else:
logging.warning('An Error Occurred with the Compile Parameter (See: boolean in pyle_sheets source file) - \ '
'see module, documentation, or online Q&A for assistance.')
I can't see any way to do this without getting pretty deep; what follows is the simplest solution I've come up with.
Using the ast module, we go through the code of the given function and find all the assignments. These are evaluated in a given namespace and this namespace is returned.
import ast
import functools
import inspect
def returnAssignments(f):
@functools.wraps(f)
def returner():
assignments = dict()
for node in ast.walk(ast.parse(inspect.getsource(f))):
if isinstance(node, ast.Assign):
exec(compile(ast.Module([node]), '<ast>', 'exec'),
globals(),
assignments)
return assignments
return returner
from ra import returnAssignments
@returnAssignments
def foo():
this = 'something'
that = 37
the_other = object()
print(foo())
rat@pandion:~/tmp$ python test.py
{'this': 'something', 'that': 37, 'the_other': <object object at 0x10205b130>}