Is there a way to insert a string in a string constant/variable that contains a string specifier?
Example:
temp_body = 'Hello %s, please visit %s to confirm your registration.'
body = temp_body % (name, url)
But this raises a TypeError.
Usually it is the way strings are generated e.g. msg template will be loaded from db or some file and things inserted in between, what is url and name in your case?
This works on my machine
>>> temp_body = 'Hello %s, please visit %s to confirm your registration.'
>>> temp_body%("anurag", "stackoverflow")
'Hello anurag, please visit stackoverflow to confirm your registration.'
Also try if str(name), str(url) works , ost probably it won't and try to fix that problem instead.
Works on my machine(TM).
Are you sure that name and url really are strings? What do you get when you do
>>> type(name), type(url)
Related
I've a string of dictionary as following:
CREDENTIALS = "{\"aaaUser\": {\"attributes\": {\"pwd\": \"cisco123\", \"name\": \"admin\"}}}"
Now I want to format this string to replace the pwd and name dynamically. What I've tried is:
CREDENTIALS = "{\"aaaUser\": {\"attributes\": {\"pwd\": \"{0}\", \"name\": \"{1}\"}}}".format('password', 'username')
But this gives following error:
traceback (most recent call last):
File ".\ll.py", line 4, in <module>
CREDENTIALS = "{\"aaaUser\": {\"attributes\": {\"pwd\": \"{0}\", \"name\": \"{1}\"}}}".format('password', 'username')
KeyError: '"aaaUser"
It is possible by just loading the string as dict using json.loads()and then setting the attributes as required, but this is not what I want. I want to format the string, so that I can use this string in other files/modules.
'
What I'm missing here? Any help would be appreciated.
Don't try to work with the JSON string directly; decode it, update the data structure, and re-encode it:
# Use single quotes instead of escaping all the double quotes
CREDENTIALS = '{"aaaUser": {"attributes": {"pwd": "cisco123", "name": "admin"}}}'
d = json.loads(CREDENTIALS)
attributes = d["aaaUser"]["attributes"]
attributes["name"] = username
attributes["pwd"] = password
CREDENTIALS = json.dumps(d)
With string formatting, you would need to change your string to look like
CREDENTIALS = '{{"aaaUser": {{"attributes": {{"pwd": "{0}", "name": "{1}"}}}}}}'
doubling all the literal braces so that the format method doesn't mistake them for placeholders.
However, formatting also means that the password needs to be pre-escaped if it contains anything that could be mistaken for JSON syntax, such as a double quote.
# This produces invalid JSON
NEW_CREDENTIALS = CREDENTIALS.format('new"password', 'bob')
# This produces valid JSON
NEW_CREDENTIALS = CREDENTIALS.format('new\\"password', 'bob')
It's far easier and safer to just decode and re-encode.
str.format deals with the text enclosed with braces {}. Here variable CREDENTIALS has the starting letter as braces { which follows the str.format rule to replace it's text and find the immediately closing braces since it don't find it and instead gets another opening braces '{' that's why it throws the error.
The string on which this method is called can contain literal text or replacement fields delimited by braces {}
Now to escape braces and replace only which indented can be done if enclosed twice like
'{{ Hey Escape }} {0}'.format(12) # O/P '{ Hey Escape } 12'
If you escape the parent and grandparent {} then it will work.
Example:
'{{Escape Me {n} }}'.format(n='Yes') # {Escape Me Yes}
So following the rule of the str.format, I'm escaping the parents text enclosed with braces by adding one extra brace to escape it.
"{{\"aaaUser\": {{\"attributes\": {{\"pwd\": \"{0}\", \"name\": \"{1}\"}}}}}}".format('password', 'username')
#O/P '{"aaaUser": {"attributes": {"pwd": "password", "name": "username"}}}'
Now Coming to the string formatting to make it work. There is other way of doing it. However this is not recommended in your case as you need to make sure the problem always has the format as you mentioned and never mess with other otherwise the result could change drastically.
So here the solution that I follow is using string replace to convert the format from {0} to %(0)s so that string formatting works without any issue and never cares about braces .
'Hello %(0)s' % {'0': 'World'} # Hello World
SO here I'm using re.sub to replace all occurrence
def myReplace(obj):
found = obj.group(0)
if found:
found = found.replace('{', '%(')
found = found.replace('}', ')s')
return found
CREDENTIALS = re.sub('\{\d{1}\}', myReplace, "{\"aaaUser\": {\"attributes\": {\"pwd\": \"{0}\", \"name\": \"{1}\"}}}"% {'0': 'password', '1': 'username'}
print CREDENTIALS # It should print desirable result
I want to list once my script in python search for specific strings , but I also want to add country code first two letters , but when I try then it says invalid KeyError: 'country_code', but the api says ocation.country_code how can I achieve that?
#!/usr/bin/python
import shodan
SHODAN_API_KEY="xxxxxxxxxxxxxxxxxxxx"
api = shodan.Shodan(SHODAN_API_KEY)
try:
# Search Shodan
results = api.search('ProFTPd-1.3.3c')
# Show the results
for result in results['matches']:
print '%s' % result['ip_str']
print '%s' % result['country_code']
except shodan.APIError, e:
print 'Error: %s' % e
I think this is the method You are using in Python
https://github.com/achillean/shodan-python/blob/master/shodan/client.py#L324
and it triggers:
return self._request('/shodan/host/search', args)
Shodan API documentation:
https://developer.shodan.io/api
check out /shodan/host/search API
I just saw that the answer is in Your question but You ate one letter from location (ocation).
Try this:
print '%s' % result['location']['country_code']
So field You are looking for is there but it is in another dictionary.
I would recommend to read API documentation well next time and as Nofal Daud said, Python error are self explanatory if You have KeyError on dict it means that field is not there. Next time listen to Python it will reveal the truth.
I am developing a new payment_acquirer module for Odoo, and since last week, I am always getting an error when I try to decrypt data that I received through the server.
When I copy the data in an another python file to test, it seems to be working perfectly with the same data, but when I do it in my controller, it returns an error.
This is the code inside my controller :
#http.route('/payment/ariarynet/result', type='http', auth="none", methods=['POST', 'GET'], csrf=False)
def ariarynet_result(self, **post):
""" Handle Ariary.net response and redirect to form_validate"""
_logger.info('Beginning Ariary.net form_feedback with post data %s', pprint.pformat(post)) # debug
key = bytes("477c3551da64136491eff1cb6ab27be35093b2512eb78f2c8d"[:24])
params = dict(post)
raw = b"%s"%post.get('idpanier')
decode = raw.encode('utf8')
idpanier = main.Utils().decrypt(key,decode) #it return an error
When executed, I have the following error:
raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.")
ValueError: Invalid data length, data must be a multiple of 8 bytes
I am using pyDes module to crypt and decrypt data.
This is the test that is working :
def test_bytes(self):
key = bytes("477c3551da64136491eff1cb6ab27be35093b2512eb78f2c8d"[:24])
expect = "12177"
raw = "%8E%16%B8n%A6%1F%2Fj" #this is the data that I copied from the url
text = urllib.unquote(raw)
byteArray = bytes(text)
print Utils().decrypt(key, text)
self.assertEqual(expect,Utils().decrypt(key, text), "%s est diférent de %s" % (expect, Utils().decrypt(key, text)) )
I really need your help to figure out what am I doing wrong.
Update:
I think that the probleme have to do with the character encoding, because when I am trying to compare the data I get with the excpected one, I don't get the same thing:
param = post.get('idpanier')
text = (param.encode('utf8'))
print "utf8 encode %s, hex encoded text %s" % (text, text.encode('hex'))
print "utf8 encode %s, hex encoded text %s" % ("b4227475d651420b".decode('hex'), "b4227475d651420b") #excpected behavior
Here is the output:
utf8 encode �"tu�QB
, hex encoded text efbfbd227475efbfbd51420b
utf8 encode �"tu�QB
, hex encoded text b4227475d651420b
The solution I found : instead of retriving parameters with post.get(), I have manage to get the real parameters data through the incoming url directly, where parameters encoding is not changed yet.
query = parse_qs("http://url?%s"%request.httprequest.query_string) #append the query string to a dummy url to get a well formed url
param = query.get('idpanier')
After that, everything worked fine.
name = form.getvalue('name')
age = form.getvalue('age') + 1
next_age1 = int(form["age"].value
print "Content-type: text/html"
print
print "<html><head>"
print "<p> Hello, %s</p>" % (name)
print "<p> Next year, you will be %s years old.</p>" % next_age1
Having trouble understanding why this doesn't work.
Can someone please help me?
Thank you!
You are missing a closing parenthesis:
next_age1 = int(form["age"].value
# ----^ -------^ nothing here
Rule of thumb: when you get a syntax error you cannot immediately spot on that line, look at the previous line to see if you balanced your parenthesis and braces properly.
I'm really starting to get the hang of IMAPClient. The code: 'BODY[HEADER.FIELDS (FROM)]' returns
From: First Last <first.last#domain.com>
I'd really just like it to return the email address like this:
first.last#lbox.com
Do I need to pass it to a variable first and trim it down or is there another fetch modifier I can use?
response = server.fetch(messages, ['FLAGS', 'RFC822.SIZE', 'BODY[HEADER.FIELDS (FROM)]'])
for msgid, data in response.iteritems():
print ' ID %d: %d bytes, From: %s flags=%s' % (msgid,
data['RFC822.SIZE'],
data['BODY[HEADER.FIELDS (FROM)]'],
data['FLAGS'])
No - you can't do that with an IMAP request, if you look at my other post you'll notice something using parseaddr, but here it is again with your example:
>>> from email.utils import parseaddr
>>> a = 'From: First Last <first.last#domain.com>'
>>> parseaddr(a)
('First Last', 'first.last#domain.com')
IMAPLIB doesn't parse much of the protocol for you. It's returning the line from the server as is.
You can and should use the parsers in the email library to help you out.