Automatically set results name in pyparsing? - python

Is there any way to get pyparsing to automatically set the resultsName of a grammar element to whatever it's named in my source code? That is, I would write code like
my_number = Word(nums)
and it would automatically execute
my_number.setResultsName('my_number')

You should be able to simply do:
my_number = Word(nums)('my_number')
using the shortcut for .setResultsName. Python, in general, makes it hard to get at the name of the variable in question.
As an alternative, if you had a list of them as a dictionary you could do something like:
for key,val in grammar_dict.items():
grammar_dict[key] = val.setResultsName(key)

Using the inspect module you can do what you want. Define a function srn:
import inspect
def srn(expr):
"""Sets the results name to the variable *name* of `expr`"""
cf = inspect.currentframe()
of = inspect.getouterframes(cf)[1]
fs = inspect.getframeinfo(of[0]).code_context[0].strip()
# name of FIRST parameter
try:
args = fs[fs.find('(') + 1:-1].split(',')
n = args[0]
if n.find('=') != -1:
name = n.split('=')[1].strip()
else:
name = n
expr.resultsName = name
except IndexError:
pass
return expr
Then after my_number = Word(nums) call:
srn(my_number)
and my_number contains "my_number" as resultsName.
Disclaimer 1: This approach works well, but is quite hacky and dives deep into the Python internals, so do it at your own risk.
Disclaimer 2: The idea for this is not mine - I got it somewhere from StackOverflow but I don't now exactly where...

Related

Add a variable to the method call path in Python

Can you please tell me how to add a variable to the method call path?
Example, i have:
my_template = templates.rows.VARS_system.safe_substitute(**service.to_dict())
I want to substitute the value of the variable instead of the word VARS:
my_template = templates.rows.PROD_system.safe_substitute(**service.to_dict())
....
my_template = templates.rows.STAGE_system.safe_substitute(**service.to_dict())
You could use getattr while looping through a list of names.
It will depend on the type of templates.rows, but from the little amount of code given, this might work.
(Untested!)
sections = ['PROD', 'STAGE']
for section in sections:
name = section + '_system'
attr = getattr(templates.rows, name)
my_template = attr.safe_substitute(**service.to_dict())
# Do stuff with my_template

Finding pattern in binary file?

I have this two functions:
def make_regex_from_hex_sign(hex_sign):
regex_hex_sign = re.compile(hex_sign.decode('hex'))
return regex_hex_sign
def find_regex_pattern_and_return_its_offset(regex_pattern, bytes_array):
if found_regex_pattern in regex_pattern.finditer(bytes_array):
return found_regex_pattern.start()
else:
return 0
and i'm using them like this:
pattern = make_regex_from_hex_sign("634351535F")
file = open('somefile.bin', 'rb')
allbytes = file.read()
offset = find_regex_pattern_and_return_its_offset(pattern, allbytes)
Python throws: NameError: global name 'found_regex_pattern' is not defined
If i replace if with for in if found_regex_pattern in regex_pattern.finditer(bytes_array) it works, but then i need to break at the end to stop it from searching past first found pattern iteration. Is there more elegant way to solve this without using for and break?
You did not define found_regex_pattern.
When you do the change from if to for it works because its a valid syntax and that means that found_regex_pattern acts as an entry of the regex_pattern.finditer(bytes_array) iterable.

Python - How to obtain a dictionary(or even a list) of variables in a specific scope; more specific than locals/globals()

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.
how it works
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.
the code
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
usage
from ra import returnAssignments
#returnAssignments
def foo():
this = 'something'
that = 37
the_other = object()
print(foo())
output
rat#pandion:~/tmp$ python test.py
{'this': 'something', 'that': 37, 'the_other': <object object at 0x10205b130>}
I wonder if such a crude solution as I provide here might be useful to you. Note that I haven't tested it on all cases, so it might be a bit rough. Also, it returns everything as a string, a behavior which you might want to further change.
Define the function:
def get_local_vars_from_function(f):
import inspect
s = inspect.getsourcelines(f)[0]
d = {}
for l in s:
if '=' in l:
var, val = l.split('=')
var = var.strip()
val = val.strip()
d[var] = val
return d
Then to use it:
In[91]: get_local_vars_from_function(user_var_list)
Out[91]: {'font1': "'green'", 'font2': "'pink'"}

Declare global variables and access locally

I have two assignments/variables in my code:
OUTPUT1="/Users/check/1.html"
OUTPUT2="/Users/check/2.html"
When I use one of the above, for instance, I write c = open(OUTPUT1).
However, I think the correct approach for this would be to have something like a generic:
OUTPUT="/Users/check/$var.html" and then while using, I should first assign:
$var = 1.html
then open(OUTPUT)
This way I open 1.html.
How do you do this in Python?
Use string interpolation like so:
var = "1.html"
path = "/Users/check/{}".format(var)
open(path)
You may also want to use a more common pattern:
import os
var = "1.html"
path = os.path.join("/Users/check/", var)
open(path)
If you wanted to put it in a function:
def getPath(var):
return "/Users/check/" + str(var) + ".html"
print(getPath(1))
print(getPath(2))
Perhaps you would consider using a tuple:
OUTPUT_PATHS = (
'/Users/check/1.html',
'/Users/check/2.html',
'/tmp/3.html'
)
Then you can simply index them, starting with 0:
outnum = random(0, 3)
c = open(outnum)

How to create an array in Python by using as name the elements of another array

I am trying to do the following in python: I have a list which contains some string values. The list looks like this:
parameters = ['RH', 'WindSp_Avg', 'WindDir']
What I want to do - and I really hope the question is not ridiculous - is to create three lists which each of them have the name of the "parameters" list.
For example:
RH = []
WindSp_Avg = []
WindDir = []
I am new in python and although I had searched a bit online I couldn't find some elegant way to do something like this.
I am trying something like this:
for i in parameters:
parameters[0] = []
But it doesn't seem to work. Any suggestions?
Thanks
Dimitris
What you are trying to do is very unsafe and is against all good practices. Is there a problem in simply creating a dictionary?
myVars = {}
for param in parameters:
myVars[param] = []
WARNING The following code is for educational purposes! DO NOT USE IT IN REAL CODE!
You can do a hard hack to add dynamically a variable to the local variables inside a function. Normally locals() represent all local variables. However simply adding to that dictionary won't solve the problem. There is a hack to force Python to reevaluate locals by using exec, for example:
def test():
for param im parameters:
locals()[param] = []
exec ""
print WindSp_Avg
and result:
>>> test()
[]
parameters = ['RH', 'WindSp_Avg', 'WindDir']
for i in parameters:
vars()[i] = [];
print locals()
To create a variable you can do so:
parameters = ['RH', 'WindSp_Avg', 'WindDir']
for i in parameters:
exec("%s = []" % i);
print vars()
you could something like this:
code = "{0} = []"
for i in parameters:
codeobj = compile(code.format(i), "/dev/null", "single")
eval(codeobj)
but i think tha's very unsafe. Because it could be something in parameters and that will be excuted by the eval. So please only use this if it's only really necessary and security is less important.

Categories

Resources