Create strings with user defined variables from user input string - python

Is there a method to get a user input with a variable from the user input?
I don't even know how to describe it.
Consider this.
I want to have a user input a string and within that string have a variable.
user_defined_command_input = "config ap {ap_name} {old_ap_name}"
The idea is, instead of me generating a template for every possible command, they can generate the command template using string interpolation without having to know python. The idea is that they have a list of commands generated for hundreds of devices and they get to manage the template of the commands they need.
user_defined_command_input = "config ap {new_AP_name} {mac_address} {description}"
OR
user_defined_command_input = "config description {short_description}
Since they should be able to name their own variables, I can't hardcode them.
I understand that there are security risks with unsanitized code being injected. So I would love to learn about that too.

Use .format()
user_defined_command = "config ap {ap_name} {old_ap_name}"
user_defined_variables = {"ap_name": "freewifi", "old_ap_name": "wifi"}
command = user_defined_command.format(**user_defined_variables)
# command == "config ap freewifi wifi"
Do not ever trust user input though! Always sanitize their input and use a whitelist of allowed values/characters. Arbitrary command injections are a huge deal and can negate any other security you have in place.
Also, in my honest opinion it would be best to reconsider implementing this, as it is very hard to get right.

You can use the command .split("") for the most part and that solves a lot fo your problems.
Where command = input("What's your command").split() for the input "config ap newTestVar oldTestVar" would set the command variable to ["config", "ap", "newTestVar", "oldTestVar"]
if your user never inputs spaces to screw with your commands, you can see config and AP are always at 0 and 1 index and what your looking for is the 2nd and 3rd variable always.
Next you can use globals() and vars() which can get and create the values of variables to do
vars()[command[2]] = globals()[command[3]]
and you'll see that if you check the variable now named newTestVarit should be set to the value of oldTestVar

You can use eval() and do something like this:
formatter = lambda text: eval(f'f"""{text}"""')
ap_name = 'AP NAME' # Example data
old_ap_name = 'OLD AP NAME' # More example data
user_defined_command_input = 'config ap {ap_name}{old_ap_name}'
print(formatter(user_defined_command_input))
Output: config ap AP NAMEOLD AP NAME
But as you have mentioned, be careful with injection like this. It can be quite dangerous.

It's not clear to me what exactly you're asking, but here's a guess based on the accepted answer to How to postpone/defer the evaluation of f-strings?:
import inspect
class MagicFstring:
def __init__(self, payload):
self.payload = payload
def __str__(self):
vars = inspect.currentframe().f_back.f_globals.copy()
vars.update(inspect.currentframe().f_back.f_locals)
return self.payload.format(**vars)
user_defined_command_input = MagicFstring("config ap {ap_name} {old_ap_name}")
ap_name = 'someapp'
old_ap_name = 'oldapp'
print(user_defined_command_input) # -> config ap someapp oldapp

Related

How to use argparse to let user make changes to output of existing program?

I have a program that produces an array of data and prints it out very nicely. The challenge for which I seek a solution is as follows:
Muck up the data in the array before it gets printed, e.g., sticking in
non-UTF-8 characters, putting the fields in the wrong order,
changing the date format.
Let the user pick which "muck ups" occur.
Here is a stripped-down version of my existing program that works, whose output I wish to intercept and muck up:
ex_matrix = [[402, 'Mayonnaise', '0123', 2014-12-18, '(Burlington, -, -)', 1.0],
[413, 'Peanuts', '0177', 2014-11-10, '(Place, Florida, South Afrika)', 1.0],
[415, 'Seaweed', '0713', 2014-12-02, '(The Pub, -, Newfoundland)', 1.0]]
def print_forecasts(matrix, num_rows):
for r in xrange(num_rows):
print("{%s, [%s, %s, %s, %s], %s}" % (matrix[r][0], matrix[r][1],
matrix[r][2], matrix[r][3], matrix[r][4], matrix[r][5]))
print "# Generated using pickles_program.py \n"
def main():
print_forecasts(ex_matrix, 3)
main()
From what I've read of Python's argparse tutorial, the PEP re. argparse, and several StackOverflow answers, it seems argparse is the key to this problem. Here is what I've written, just trying to get a feel for how argparse works:
import argparse
num_rows = 3
parser = argparse.ArgumentParser(description="base rate model: error adder")
parser.add_argument("muck2", help="muck up the population field", nargs='?')
args = parser.parse_args()
for i in xrange(num_rows):
matrix[i][1] = "^&*#$)(*DJJJJ)"
print matrix
There will be >10 types of muck-up's for the user to choose from. What I think I would like would be for the user to be able to say to the command-line, "python pickles_program.py 1 3 8 11," or something like that, and have the muck-up's 1, 3, 8 and 11 happen, and for "python pickles_program.py --help" to display all the muck-up options.
I hope you'll forgive me if this is a dull-witted question. I'm a Python novice and still learning how to use the many resources there are for learning this great language, but I've searched SO and Python documentation high and low -- please believe me, if there is an answer to my problem out there, it's either not been explained well enough for people like me, or it's too darned hard to find, because I haven't found it yet.
Please advise, esp. on how I can pose my question better/more clearly!
It will be MUCH easier in my opinion to handle your "muck ups" as flags, instead of numbers. Then, you can use ArgParse to check if those flags are enabled. For example:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbose", help="increase output verbosity",
action="store_true")
args = parser.parse_args()
if args.verbose:
print "verbosity turned on"
This way, add all of your "muck ups" via parser.add_argument("argument", action="store_true") then do the logic for each "muck up" under a series of if statements.
For your learing purposes, it would be good to start without any extra modules. Just work from the sys.argv directly. For example
import sys
muck_ups = []
if sys.argv[1:]: # values beyond the program name
muck_ups = [int(i) for i in sys.argv[1:]]
# this will throw an error if one of the strings can't be converted to an int
# we can refine that later
if len(muck_ups)==0:
print('help...')
sys.exit(1)
# print help if they don't give you any numbers
for m in muck_ups:
if m in [1]:
pass # do one muckup
elif m in [2]:
<do another>
elif m in [3]:
<etc>
else:
print('muckup %s not found'%m)
muck_ups values don't have to be numbers. They could be strings, and you could have aliases, e.g.
elif m in [1,'1','one','first']:
....
Use logic like this if you want to perform the actions in the order indicated by the muck_ups values. You'd want to use a different logic if you want to do action1 if 1 in muck_ups, then action2 if 2 in muck_ups:, etc.
A simple argparse parser with:
parser.add_argument('muck_ups', type=int, nargs='*')
would gave the same list of integers in args.muck_ups. If you want to add more switches and options, argparse would useful, but for just one parameter like this, it doesn't make much difference.
argparse (and related modules) is primarily a way of parsing the input; of figuring out what the user wants to do. It isn't an execution mechanism. And don't get hungup over making it do something fancy.

python dragonfly to recognize similar words

I am doing a program with dragon fly using wsr,where it has to analyse a word,any voice matching that word should output 'yes it matches'
If i say 'czechoslovakia' then it must print true even for all the similar matches of this world ,like words for 'circle slovakia, cat on slavia,seko vakia...'
What specific methods,should i use for this?
My program
from dragonfly.all import *
import pythoncom
import time
# Voice command rule combining spoken form and recognition processing.
class ExampleRule(CompoundRule):
spec = "czechoslovakia|circle slovalia|sceko bakia|cat on ania" # Spoken form of command.
def _process_recognition(self, node, extras): # Callback when command is spoken.
print "Voice command spoken."
# Create a grammar which contains and loads the command rule.
grammar = Grammar("example grammar") # Create a grammar to contain the command rule.
grammar.add_rule(ExampleRule()) # Add the command rule to the grammar.
grammar.load() # Load the grammar.
while True:
pythoncom.PumpWaitingMessages()
time.sleep(.1)
There is nothing built into Dragonfly to allow you to do this, but you have some other options.
If you're looking to dynamically generate the spec, you might want
to look at Fuzzy. You could give it a word and use it to generate
other similar sounding words from that word. Then you could create
the spec from them.
Here is the WSR engine class in Dragonfly.
I don't know much about SAPI5, but you might be able to ask it for
alternatives. If you can, you might be able to extend the
Dragonfly GrammarWrapper to expose the alternatives, and then use a
catchall grammar to save all utterances and then filter out what you
want (possibly using Fuzzy).
If you were using Natlink, I would recommend
looking at the results object. As you can see here, the results
object has access to all of Dragon's different hypotheses for what
you said in a given utterance. Just as with my second suggestion,
you could catch everything and then filter what you wanted:
.
from natlinkutils import GrammarBase
class CatchAll(GrammarBase):
# this spec will catch everything
gramSpec = """
<start> exported = {emptyList};
"""
def initialize(self):
self.load(self.gramSpec, allResults=1)
self.activateAll()
def gotResultsObject(self, recogType, resObj):
for x in range(0, 100):
try:
possible_interpretation = resObj.getWords(x)
# do whatever sort of filtering you want here
except Exception:
break
c = CatchAll()
c.initialize()
def unload():
global c
if c:
c.unload()
c = None

How do I assign variables within WMI calls?

Using WMI within Python to request data from other servers. I know my credentials are correct, as I can hard-code them in the file and connect without issues. However, my string formatting for variables doesn't seem to be working.
I've tried both of these with no luck:
wmi_sql = wmi.WMI(SQLServer_raw, user="%s\\%s", password="%s") % (sql_domain, sql_user, sql_pass)
and
wmi_sql = wmi.WMI(SQLServer_raw, user="{0}\\{1}", password="{2}").format(sql_domain, sql_user, sql_pass)
Tried moving the format() call inside, but it didn't work either:
wmi_sql = wmi.WMI(SQLServer_raw, user="{0}\\{1}", password="{2}".format(sql_domain, sql_user, sql_pass))
You've got the string formatters in the wrong place. They need to be used for each string, not the result of the call. As written, python thinks you want to call wmi.WMI and then apply the formatting to whatever is returned.
Try:
wmi_sql = wmi.WMI(SQLServer_raw, user="%s\\%s" % (sql_domain, sql_user),
password=sql_pass)
In one and two you are executing wmi.WMI() and then doing the formatting on the return type. In the third example you are formatting the value of the password but providing three parameters to it hoping it would build user variable. If you really want to build user and password dynamically do this:
usr ="{0}\\{1}".format(sql_domain,ql_user)
wmi.WMI(SQLServer_raw, user=usr, password=sql_pass)

Change python command to subtract value instead of add in MYSQL

Just got one other question for my python plugin.
Here is the code:
def cmd_give(self, data, client=None, cmd=None):
"""
^3<player> <money> - Give someone however much money you want.
"""
input = self._adminPlugin.parseUserCmd(data)
if not data:
client.message('^7 correct syntax is !give <player> <money>')
return False
else:
if len([x for x in data if x.isspace()]) < 1:
client.message('^7 correct syntax is !give <player> <money>')
return False
else:
input_data = data.split(' ',1)
scname = input_data[0]
ammount = int(input_data[1])
sclient = self._adminPlugin.findClientPrompt(scname, client)
if not sclient: return False
self.earn_money(sclient, ammount)
return True
Now this obviously adds the value given in the command to the user inputting into mysql.
I'm also wanting a command to subtract any value given in the command as well.
So this command above is a give and I also want a take.
My problem is I don't know what the change is to minus the amount off the value input instead of adding.
Hope someone can help,
Thanks guys.
Without modifying the function that does the actual addition, the suggestion by Rob Watts in a comment will work:
ammount = -int(input_data[1])
You can either create a new function, cmd_take, and do that there, or have a more general function (cmd_transaction?) that takes an extra argument (eg give) and has the appropriate logic:
if not give:
ammount = -int(input_data[1])
In the first case, it would be good practice to extract most of the code to a helper function, to avoid repetition, but if you don't know python and this is just a one time thing, having a cmd_take function that is exactly like command_give, except for that one line, is the simplest solution.

Python: Networked IDLE/Redo IDLE front-end while using the same back-end?

Is there any existing web app that lets multiple users work with an interactive IDLE type session at once?
Something like:
IDLE 2.6.4
Morgan: >>> letters = list("abcdefg")
Morgan: >>> # now, how would you iterate over letters?
Jack: >>> for char in letters:
print "char %s" % char
char a
char b
char c
char d
char e
char f
char g
Morgan: >>> # nice nice
If not, I would like to create one. Is there some module I can use that simulates an interactive session? I'd want an interface like this:
def class InteractiveSession():
''' An interactive Python session '''
def putLine(line):
''' Evaluates line '''
pass
def outputLines():
''' A list of all lines that have been output by the session '''
pass
def currentVars():
''' A dictionary of currently defined variables and their values '''
pass
(Although that last function would be more of an extra feature.)
To formulate my problem another way: I'd like to create a new front end for IDLE. How can I do this?
UPDATE: Or maybe I can simulate IDLE through eval()?
UPDATE 2: What if I did something like this:
I already have a simple GAE Python chat app set up, that allows users to sign in, make chat rooms, and chat with each other.
Instead of just saving incoming messages to the datastore, I could do something like this:
def putLine(line, user, chat_room):
''' Evaluates line for the session used by chat_room '''
# get the interactive session for this chat room
curr_vars = InteractiveSession.objects.where("chatRoom = %s" % chat_room).get()
result = eval(prepared_line, curr_vars.state, {})
curr_vars.state = curr_globals
curr_vars.lines.append((user, line))
if result:
curr_vars.lines.append(('SELF', result.__str__()))
curr_vars.put()
The InteractiveSession model:
def class InteractiveSession(db.Model):
# a dictionary mapping variables to values
# it looks like GAE doesn't actually have a dictionary field, so what would be best to use here?
state = db.DictionaryProperty()
# a transcript of the session
#
# a list of tuples of the form (user, line_entered)
#
# looks something like:
#
# [('Morgan', '# hello'),
# ('Jack', 'x = []'),
# ('Morgan', 'x.append(1)'),
# ('Jack', 'x'),
# ('SELF', '[1]')]
lines = db.ListProperty()
Could this work, or am I way off/this approach is infeasible/I'm duplicating work when I should use something already built?
UPDATE 3: Also, assuming I get everything else working, I'd like syntax highlighting. Ideally, I'd have some API or service I could use that would parse the code and style it appropriately.
for c in "characters":
would become:
<span class="keyword">for</span> <span class="var">c</span> <span class="keyword">in</span> <span class="string>"characters"</span><span class="punctuation">:</span>
Is there a good existing Python tool to do this?
I could implement something like this pretty quickly in Nevow. Obviously, access would need to be pretty restricted since doing something like this involves allowing access to a Python console to someone via HTTP.
What I'd do is create an Athena widget for the console, that used an instance of a custom subclass of code.InteractiveInterpreter that is common to all users logged in.
UPDATE: Okay, so you have something chat-like in GAE. If you just submit lines to a code.InteractiveInterpreter subclass that looks like this, it should work for you. Note that the interface is pretty similar to the InteractiveSession class you describe:
class SharedConsole(code.InteractiveInterpreter):
def __init__(self):
self.users = []
def write(self, data):
# broadcast output to connected clients here
for user in self.users:
user.addOutput(data)
class ConnectedUser(object):
def __init__(self, sharedConsole):
self.sharedConsole = sharedConsole
sharedConsole.users.append(self) # reference look, should use weak refs
def addOutput(self, data):
pass # do GAE magic to send data to connected client
# this is a hook for submitted code lines; call it from GAE when a user submits code
def gotCommand(self, command):
needsMore = self.sharedConsole.runsource(command)
if needsMore:
pass # tell the client to change the command line to a textarea
# or otherwise add more lines of code to complete the statement
The closest Python interpreter I know of to what you are looking for, in terms of interface, is DreamPie. It has separate input and output areas, much like a chat interface. Also, DreamPie runs all of the code in a subprocess. DreamPie also does completion and syntax coloring, much like IDLE, which means it doesn't just pipe input and output to/from the subprocess -- it has implemented the abstractions which you are looking for.
If you wish to develop a desktop application (not a web-app), I recommend basing your work on DreamPie and just adding the multiple-frontend functionality.
Update: For syntax highlighting (including HTML) see the Pygments project. But that is a completely different question; please ask one question at a time here.
As a proof of concept, you may be able to put something together using sockets and a command-line session.
this is likely possible with the upcoming implimentation of IPython using a 0MQ backend.
I would use ipython and screen. With this method, you would have to create a shared login, but you could both connect to the shared screen session. One downside would be that you would both appear as the same user.

Categories

Resources