I'm trying to use selenium to locate a checkbox within an unordered list:
ul=browser.find_element_by_xpath('//[#id="TestTake"]/div[2]/div/div/ol/li[{}]/div[2]/ul'.format(num))
checkbox_id=ul.find_element_by_xpath("//[contains(text(),'{}')]".format(correct.replace("'","\'"))).get_attribute("for")
The problem with:
"//[contains(text(),'{}')]".format(correct.replace("'","\'"))).get_attribute("for"
occurs when correct is equal to L' or something that contains a quote.
How can I properly escape the single quote? I'm not sure if the correct will have a quote or not, so I need to be able to handle both cases, a double quote as well.
Also, this is the only approach because I only can get the id by the attribute for which I find by using its contents.
Turns out that string concatenation did the trick:
checkbox_id = ul.find_element_by_xpath("//*[contains(text(),\"" + correct + "\")]").get_attribute("for")
I have a long text file that I am trying to pull certain strings out of. The length of these strings are variable with the text file but are always located after certain identifiers. So for example say my text file looks like this:
junk text...
Name:
Age:
Robert
twenty
four.
junk text...
I always know that the "Robert" string is located at "Age:\n\n" but I am not sure how long it is only that it will end at a "\n\n" and the same principle with the "twenty four." string. I have tried using
namepos1 = string.find("Age:")
namepos2 = namepos1 + 6
this will give the starting location of the string I want but I do not know how to save it into a variable such that it always saves the whole string up to the two new line characters. If it was a set length and not variable I think I could use:
name = string[namepos2:length]
but any help would be greatly appreciated. I may have to go about doing it completely different, but this is the first way I have thought about it and tried to do it.
Thanks!
You could do this by finding age, then moving forward your cursor two lines if you would like to do that, if you want the entire section of text after the "junk", and you know how long that text is, this would also work:
lookup = 'age'
lines=[]
with open('C:/Users/Luke/Desktop/Summer 2016/Programs/untitled5.txt') as myFile:
for num, line in enumerate(myFile, 1):
if lookup in line:
lines.append(num+2)
ofile=open('C:/Users/Luke/Desktop/Summer 2016/Programs/untitled5.txt')
line=ofile.readlines()
interestinglines=''
for i in range(len(lines)):
interestinglines+=(line[lines[i]]+'\n')
you may need to tinker with it a bit, but I believe this should reproduce mostly what you're looking for. The '\n' is added onto the line[lines[i]] so that you may save it to a new file.
After you found the location in string, you can split the String by \n\n and get the first item.
s = file_str[namepos2 :]
name = s.split('\n\n')[0]
I want to know how to allow multiple inputs in Python.
Ex: If a message is "!comment postid customcomment"
I want to be able to take that post ID, put that somewhere, and then the customcomment, and put that somewhere else.
Here's my code:
import fb
token="access_token_here"
facebook=fb.graph.api(token)
#__________ Later on in the code: __________
elif msg.startswith('!comment '):
postid = msg.replace('!comment ','',1)
send('Commenting...')
facebook.publish(cat="comments", id=postid, message="customcomment")
send('Commented!')
I can't seem to figure it out.
Thank you in advanced.
I can't quite tell what you are asking but it seems that this will do what you want.
Assuming that
msg = "!comment postid customcomment"
you can use the built-in string method split to turn the string into a list of strings, using " " as a separator and a maximum number of splits of 2:
msg_list=msg.split(" ",2)
the zeroth index will contain "!comment" so you can ignore it
postid=msg_list[1] or postid=int(msg_list[1]) if you need a numerical input
message = msg_list[2]
If you don't limit split and just use the default behavior (ie msg_list=msg.split()), you would have to rejoin the rest of the strings separated by spaces. To do so you can use the built-in string method join which does just that:
message=" ".join(msg_list[2:])
and finally
facebook.publish(cat="comments", id=postid, message=message)
I've been searching on this but am coming up a little short on exactly how to do specifically what i am trying to do.. I want to concatentate a string (I guess it would be a string in this case as it has a variable and string) such as below, where I need to use a variable consisting of a string to call a listname that has an index (from another variable).. I simplified my code below to just show the relevant parts its part of a macro that is replacing values:
toreplacetype = 'type'
toreplace_indx = 5
replacement_string = 'list'+toreplacetype[toreplace_indx]
so... I am trying to make the string on the last line equal to the actual variable name:
replacement_string = listtype[5]
Any advice on how to do this is appreciated
EDIT:
To explain further, this is for a macro that is sort of a template system where I am indicating things in a python script that I want to replace with specific values so I am using regex to do this. So, when I match something, I want to be able to replace it from a specific value within a list, but, for example, in the template I have {{type}}, so I extract this, but then I need to manipulate it as above so that I can use the extracted value "type" to call a specific value from within a list (such as from a list called "listtype") (there is more than 1 list so I need to find the one called "listtype" so I just want to concatenate as above to get this, based on the value I extracted using regex
This is not recommended. Use a dict instead.
vars['list%s' % toreplacetype][5] = ...
Hrm...
globals()['list%s'% toreplacetype][toreplace_indx]
replacement_string = 'list'+toreplacetype+'['+str(toreplace_indx)+']'
will yield listtype[5] when you print it.
You need to basically break it into 5 parts: 1 string variable, 3 strings and an int casted to a string.
I think this is what you are asking?
I am expecting users to upload a CSV file of max size 1MB to a web form that should fit a given format similar to:
"<String>","<String>",<Int>,<Float>
That will be processed later. I would like to verify the file fits a specified format so that the program that shall later use the file doesnt receive unexpected input and that there are no security concerns (say some injection attack against the parsing script that does some calculations and db insert).
(1) What would be the best way to go about doing this that would be fast and thorough? From what I've researched I could go the path of regex or something more like this. I've looked at the python csv module but that doesnt appear to have any built in verification.
(2) Assuming I go for a regex, can anyone direct me to towards the best way to do this? Do I match for illegal characters and reject on that? (eg. no '/' '\' '<' '>' '{' '}' etc.) or match on all legal eg. [a-zA-Z0-9]{1,10} for the string component? I'm not too familiar with regular expressions so pointers or examples would be appreciated.
EDIT:
Strings should contain no commas or quotes it would just contain a name (ie. first name, last name). And yes I forgot to add they would be double quoted.
EDIT #2:
Thanks for all the answers. Cutplace is quite interesting but is a standalone. Decided to go with pyparsing in the end because it gives more flexibility should I add more formats.
Pyparsing will process this data, and will be tolerant of unexpected things like spaces before and after commas, commas within quotes, etc. (csv module is too, but regex solutions force you to add "\s*" bits all over the place).
from pyparsing import *
integer = Regex(r"-?\d+").setName("integer")
integer.setParseAction(lambda tokens: int(tokens[0]))
floatnum = Regex(r"-?\d+\.\d*").setName("float")
floatnum.setParseAction(lambda tokens: float(tokens[0]))
dblQuotedString.setParseAction(removeQuotes)
COMMA = Suppress(',')
validLine = dblQuotedString + COMMA + dblQuotedString + COMMA + \
integer + COMMA + floatnum + LineEnd()
tests = """\
"good data","good2",100,3.14
"good data" , "good2", 100, 3.14
bad, "good","good2",100,3.14
"bad","good2",100,3
"bad","good2",100.5,3
""".splitlines()
for t in tests:
print t
try:
print validLine.parseString(t).asList()
except ParseException, pe:
print pe.markInputline('?')
print pe.msg
print
Prints
"good data","good2",100,3.14
['good data', 'good2', 100, 3.1400000000000001]
"good data" , "good2", 100, 3.14
['good data', 'good2', 100, 3.1400000000000001]
bad, "good","good2",100,3.14
?bad, "good","good2",100,3.14
Expected string enclosed in double quotes
"bad","good2",100,3
"bad","good2",100,?3
Expected float
"bad","good2",100.5,3
"bad","good2",100?.5,3
Expected ","
You will probably be stripping those quotation marks off at some future time, pyparsing can do that at parse time by adding:
dblQuotedString.setParseAction(removeQuotes)
If you want to add comment support to your input file, say a '#' followed by the rest of the line, you can do this:
comment = '#' + restOfline
validLine.ignore(comment)
You can also add names to these fields, so that you can access them by name instead of index position (which I find gives more robust code in light of changes down the road):
validLine = dblQuotedString("key") + COMMA + dblQuotedString("title") + COMMA + \
integer("qty") + COMMA + floatnum("price") + LineEnd()
And your post-processing code can then do this:
data = validLine.parseString(t)
print "%(key)s: %(title)s, %(qty)d in stock at $%(price).2f" % data
print data.qty*data.price
I'd vote for parsing the file, checking you've got 4 components per record, that the first two components are strings, the third is an int (checking for NaN conditions), and the fourth is a float (also checking for NaN conditions).
Python would be an excellent tool for the job.
I'm not aware of any libraries in Python to deal with validation of CSV files against a spec, but it really shouldn't be too hard to write.
import csv
import math
dataChecker = csv.reader(open('data.csv'))
for row in dataChecker:
if len(row) != 4:
print 'Invalid row length.'
return
my_int = int(row[2])
my_float = float(row[3])
if math.isnan(my_int):
print 'Bad int found'
return
if math.isnan(my_float):
print 'Bad float found'
return
print 'All good!'
Here's a small snippet I made:
import csv
f = csv.reader(open("test.csv"))
for value in f:
value[0] = str(value[0])
value[1] = str(value[1])
value[2] = int(value[2])
value[3] = float(value[3])
If you run that with a file that doesn't have the format your specified, you'll get an exception:
$ python valid.py
Traceback (most recent call last):
File "valid.py", line 8, in <module>
i[2] = int(i[2])
ValueError: invalid literal for int() with base 10: 'a3'
You can then make a try-except ValueError to catch it and let the users know what they did wrong.
There can be a lot of corner-cases for parsing CSV, so you probably don't want to try doing it "by hand". At least start with a package/library built-in to the language that you're using, even if it doesn't do all the "verification" you can think of.
Once you get there, then examine the fields for your list of "illegal" chars, or examine the values in each field to determine they're valid (if you can do so). You also don't even need a regex for this task necessarily, but it may be more concise to do it that way.
You might also disallow embedded \r or \n, \0 or \t. Just loop through the fields and check them after you've loaded the data with your csv lib.
Try Cutplace. It verifies that tabluar data conforms to an interface control document.
Ideally, you want your filtering to be as restrictive as possible - the fewer things you allow, the fewer potential avenues of attack. For instance, a float or int field has a very small number of characters (and very few configurations of those characters) which should actually be allowed. String filtering should ideally be restricted to only what characters people would have a reason to input - without knowing the larger context it's hard to tell you exactly which you should allow, but at a bare minimum the string match regex should require quoting of strings and disallow anything that would terminate the string early.
Keep in mind, however, that some names may contain things like single quotes ("O'Neil", for instance) or dashes, so you couldn't necessarily rule those out.
Something like...
/"[a-zA-Z' -]+"/
...would probably be ideal for double-quoted strings which are supposed to contain names. You could replace the + with a {x,y} length min/max if you wanted to enforce certain lengths as well.