Send loop result within email body - python

I'm trying to present "print" result (example 1) in content of email (example 2).
Data I use:
{
"#odata.context": "XXX",
"value": [
{
"Customer_Name": "ABC inc",
"Customer_No": "002",
"Date_of_Export": "2020-01-10T05:36:55.3Z",
"Error_Message": "error message 1.",
"Type_of_Export": "E-Mail"
},
{
"Customer_Name": "CBA inc",
"Customer_No": "001",
"Date_of_Export": "2020-01-10T05:39:13.137Z",
"Error_Message": "Error message 2",
"Type_of_Export": "E-Mail"
}
]}
EXAMPLE 1 (PRINT):
When I use below code I get desired result printed:
r = requests.get("http://www.example.com/test.json")
r_dict = json.loads(r.text)
if len(r_dict["value"])==0:
print("No errors")
else:
print("List of errors:\n")
for item in r_dict["value"]:
print('"Customer":', '(' + item['Customer_No'] + ')' + item['Customer_Name'] + ', "Typ":', item['Type_of_Export'] + ', "Error": ', item['Error_Message'])
I get:
List of errors:
"Customer": (002)ABC inc, "Typ": E-Mail, "Error": error message 1.
"Customer": (001)CBA inc, "Typ": E-Mail, "Error": Error message 2
EXAMPLE 2 (MAIL):
But i can't get that right to send same result within email body, because only last line is enclosed
List of errors:
"Customer": (001)CBA inc, "Typ": E-Mail, "Error": Error message 2
Code I use:
import json
import requests
import smtplib
from requests_ntlm import HttpNtlmAuth
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
html_top = """<html><body>"""
html_end = """</body></html> """
r = requests.get("http://www.example.com/test.json")
r_dict = json.loads(r.text)
if len(r_dict["value"])==0:
print("No errors")
else:
html_body_top = "<p>List of errors:<br></p>"
for item in r_dict["value"]:
html_body = '"Customer":' + '(' + item['Customer_No'] + ')' + item['Customer_Name'] + ', "Typ":' + item['Type_of_Export'] + ', "Error": ' + item['Error_Message']
mail_html = MIMEText(html_top + html_body_top + html_body + html_end, "html")
message.attach(mail_html)
with smtplib.SMTP("000.000.000.000", xx) as server:
server.sendmail(sender_email, receiver_email, message.as_string())
I would like to send email containing all 2 lines, just like in example 1.

Your problem is that each time this loop iterate you are overwriting the previous value of html_body
for item in r_dict["value"]:
html_body = '"Customer":' + '(' + item['Customer_No'] + ')' + item['Customer_Name'] + ', "Typ":' + item['Type_of_Export'] + ', "Error": ' + item['Error_Message']
A quick solution is to change to using the += operator and add a new line character on the end.
html_body = ''
for item in r_dict["value"]:
html_body += '"Customer":' + '(' + item['Customer_No'] + ')' + item['Customer_Name'] + ', "Typ":' + item['Type_of_Export'] + ', "Error": ' + item['Error_Message'] + '\n'

Before your for loop, declare the html_body and add the values on it with +=:
html_body = ""
for item in r_dict["value"]:
html_body += '"Customer":' + '(' + item['Customer_No'] + ')' + item['Customer_Name'] + ', "Typ":' + item['Type_of_Export'] + ', "Error": ' + item['Error_Message'] + '\n'
I added the \n at the end to "print" a breakline.

Related

Python script fails to call Jira REST API

i have a python script which makes a call to Jira API for creating a Jira issue.
The API Call istself works fine, if i test it with Postman i am able to create tickets however the same URL does not work using Python.I do not not understand why i am not able to create a secure connection to jira
Executed [createIssue] action via OEC[integrationId: f457bfd9-5fe0-4fc5-89a9-ee007e85cf1b integrationType: Jira] with errors. Reason: Err: exit status 1, Stderr: Traceback (most recent call last): File
"/home/opsgenie/oec_test/scripts/actionExecutor.py", line 279, in <module> main() File "/home/opsgenie/oec_test/scripts/actionExecutor.py", line 233, in main timeout=timeout) File
"/usr/lib/python2.7/dist-packages/requests/api.py", line 112, in post return request('post', url, data=data, json=json, **kwargs) File "/usr/lib/python2.7/dist-packages/requests/api.py", line 58, in request return session.request(method=method, url=url, **kwargs) File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 520, in
request resp = self.send(prep, **send_kwargs) File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 630, in send r = adapter.send(request, **kwargs) File
"/usr/lib/python2.7/dist-packages/requests/adapters.py", line 508, in send raise
ConnectionError(e, request=request) requests.exceptions.ConnectionError: HTTPSConnectionPool(host='jiratest.gk.gk-software.com', port=443): Max retries exceeded with url: /rest/api/2/issue
(Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7ffa264aa1d0>: Failed to establish a new connection: [Errno -2] Name or service not known',))
The complete code looks like this:
import argparse
import json
import logging
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import re
import requests
from requests.auth import HTTPBasicAuth
parser = argparse.ArgumentParser()
parser.add_argument('-payload', '--queuePayload', help='Payload from queue', required=True)
parser.add_argument('-apiKey', '--apiKey', help='The apiKey of the integration', required=True)
parser.add_argument('-opsgenieUrl', '--opsgenieUrl', help='The url', required=True)
parser.add_argument('-logLevel', '--logLevel', help='Level of log', required=True)
parser.add_argument('-username', '--username', help='Username', required=False)
parser.add_argument('-password', '--password', help='Password', required=False)
parser.add_argument('-url', '--url', help='URL', required=False)
parser.add_argument('-projectKey', '--projectKey', help='Project Key', required=False)
parser.add_argument('-issueTypeName', '--issueTypeName', help='Issue Type', required=False)
args = vars(parser.parse_args())
logging.basicConfig(stream=sys.stdout, level=args['logLevel'])
def parse_field(key, mandatory):
variable = queue_message.get(key)
if not variable:
variable = args.get(key)
if mandatory and not variable:
logging.error(LOG_PREFIX + " Skipping action, Mandatory conf item '" + key +
"' is missing. Check your configuration file.")
raise ValueError(LOG_PREFIX + " Skipping action, Mandatory conf item '" + key +
"' is missing. Check your configuration file.")
return variable
def parse_timeout():
parsed_timeout = args.get('http.timeout')
if not parsed_timeout:
return 30000
return int(parsed_timeout)
def get_alert_details(alertId):
alert_api_url = args['opsgenieUrl'] + "/v2/alerts/" + alertId
headers = {
"Content-Type": "application/json",
"Accept-Language": "application/json",
"Authorization": "GenieKey " + args['apiKey']
}
req = requests.get(alert_api_url, headers=headers)
alert = req.json()
return alert["data"]
def get_transition_id(request_headers, jira_url, transition_name, token):
transition_id = str()
response = requests.get(jira_url, None, headers=request_headers, auth=token, timeout=timeout)
try:
body = response.json()
if body and response.status_code < 299:
transition_list = body["transitions"]
for transition in transition_list:
to = transition['to']
if transition_name == to['name']:
transition_id = transition['id']
logging.info(LOG_PREFIX + " Successfully executed at Jira")
logging.debug(LOG_PREFIX + " Jira response: " + str(response.status_code) + " " + str(response.content))
else:
logging.error(
LOG_PREFIX + " Could not execute at Jira; response: " + str(response.content) + " status code: " + str(
response.status_code))
if not transition_id:
logging.debug(LOG_PREFIX + " Transition id is empty")
return transition_id
except ValueError:
logging.error("The response body is not a valid json object!")
def get_comp():
jira_comp = re.search(r"topic:\s\'(.*)[']", str(queue_message.get("description")))
if jira_comp:
jira_comp = jira_comp.group(1)
return (jira_comp)
else:
jira_comp = "Dummy"
return (jira_comp)
def get_prio():
severity = re.search(r"severity:\s\'(.*)[']",queue_message.get("description"))
if severity:
jira_prio = severity.group(1)
if jira_prio == "critical":
jira_prio = "Very High"
return (jira_prio)
if jira_prio == "Very High":
jira_prio = "High"
return (jira_prio)
else:
severity = "High"
return (severity)
def get_context():
context = re.search(r"context:\s\'(.*)[']", str(queue_message.get("description")))
if context:
context = context.group(1)
return (context)
else:
context = ""
return (context)
def main():
global LOG_PREFIX
global queue_message
global timeout
global to_customfield_20500; to_customfield_20500=[]
global project_to_customfield_20500
global cluster_to_customfield_20500
queue_message_string = args['queuePayload']
queue_message_string = queue_message_string.strip()
queue_message = json.loads(queue_message_string)
alert_id = queue_message["alertId"]
mapped_action = queue_message["mappedActionV2"]["name"]
alert_details = get_alert_details(alert_id)
LOG_PREFIX = "[" + mapped_action + "]"
logging.info("Will execute " + mapped_action + " for alertId " + alert_id)
timeout = parse_timeout()
url = parse_field('url', True)
username = parse_field('username', True)
password = parse_field('password', True)
project_key = parse_field('projectKey', False)
issue_type_name = parse_field('issueTypeName', False)
issue_key = queue_message.get("key")
logging.debug("Url: " + str(url))
logging.debug("Username: " + str(username))
logging.debug("Project Key: " + str(project_key))
logging.debug("Issue Type: " + str(issue_type_name))
logging.debug("Issue Key: " + str(issue_key))
content_params = dict()
token = HTTPBasicAuth(username, password)
headers = {
"Content-Type": "application/json",
"Accept-Language": "application/json",
}
result_url = url + "/rest/api/2/issue"
if mapped_action == "addCommentToIssue":
content_params = {
"body": queue_message.get('body')
}
result_url += "/" + issue_key + "/comment"
elif mapped_action == "createIssue":
getcontext = get_context()
getcomp = get_comp()
priority = get_prio()
content_params = {
"fields": {
"project": {"key": project_key},
"issuetype": {"name": issue_type_name},
"summary": queue_message.get("summary"),
"description": queue_message.get("description"),
"customfield_20500": [{"value": "DE - Germany"}],
"customfield_13604": "tbd",
"components": [{"name": getcomp}],
"versions": [{"name": "tbd"}],
"customfield_15000": [getcontext],
"priority": {"name": priority},
"assignee": {"name": "#cloudoperations"}
}
}
elif mapped_action == "resolveIssue":
result_url += "/" + issue_key + "/transitions"
content_params = {
"transition": {
"id": get_transition_id(headers, result_url, "Resolved", token)
},
"fields": {
"resolution": {
"name": "Done"
}
}
}
elif mapped_action == "closeIssue":
result_url += "/" + issue_key + "/transitions"
content_params = {
"transition": {
"id": get_transition_id(headers, result_url, "Closed", token)
},
"fields": {
"resolution": {
"name": "Done"
}
}
}
elif mapped_action == "issueDone":
result_url += "/" + issue_key + "/transitions"
content_params = {
"transition": {
"id": get_transition_id(headers, result_url, "Done", token)
}
}
elif mapped_action == "inProgressIssue":
result_url += "/" + issue_key + "/transitions"
content_params = {
"transition": {
"id": get_transition_id(headers, result_url, "In Progress", token)
}
}
logging.debug(str(content_params))
response = requests.post(result_url, data=json.dumps(content_params), headers=headers, auth=token,
timeout=timeout)
if response.status_code < 299:
logging.info("Successfully executed at Jira")
if mapped_action == "createIssue":
try:
response_body = response.json()
if response_body:
issue_key_from_response = response_body['key']
if issue_key_from_response:
alert_api_url = args['opsgenieUrl'] + "/v2/alerts/" + alert_id + "/details"
content = {
"details":
{
"issueKey": issue_key_from_response
}
}
headers = {
"Content-Type": "application/json",
"Accept-Language": "application/json",
"Authorization": "GenieKey " + args['apiKey']
}
logging.debug(str(alert_api_url) + str(content) + str(headers))
alert_response = requests.post(alert_api_url,
data=json.dumps(content), headers=headers,
timeout=timeout)
if alert_response.status_code < 299:
logging.info(LOG_PREFIX + " Successfully sent to Opsgenie")
logging.debug(
LOG_PREFIX + " Jira response: " + str(alert_response.content) + " " + str(
alert_response.status_code))
else:
logging.warning(
LOG_PREFIX + " Could not execute at Opsgenie; response: " + str(
alert_response.content) + " status code: " + str(alert_response.status_code))
else:
logging.warning(
LOG_PREFIX + " Jira response is empty")
except ValueError:
logging.error(ValueError)
else:
logging.warning(
LOG_PREFIX + " Could not execute at Jira; response: " + str(response.content) + " status code: " + str(
response.status_code))
if __name__ == '__main__':
main()
I'm not sure either but I suggest using the Jira Python library, which in turn uses the requests library
i found out it was an connection issue as from the VM where py script is executed,the jira URL was not reachable

Getting 403 authorisation error when try to release Azure container lease

Code below fixed as per the helping comments. Now allows me to release the lease on a container, assuming you know the lease id.
I've been using Azure as an archive backup for a large number of files. I don't think it makes a huge amount of difference to day-to-day usage, but I accidentally hit the 'acquire lease' option on my container in the portal. The only two options in the portal are acquire and break, there isn't a 'release' option.
I'm trying to get back in to Python, and saw this as a possibility to practice by trying to interact with Azure APIs.
[This link][1] forms 95% of the code (retrieving the properties). I get a successful response when configured with my credentials (a 202).
I've then attempted to modify the code to release the lease:
import requests
import datetime
import hmac
import hashlib
import base64
storage_account_name = 'storageaccountname'
storage_account_key = 'storateaccountkey'
lease_id = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
container_name = 'containername'
api_version = '2019-07-07'
request_time = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
string_params = {
'verb': 'PUT',
'Content-Encoding': '',
'Content-Language': '',
'Content-Length': '',
'Content-MD5': '',
'Content-Type': '',
'Date': '',
'If-Modified-Since': '',
'If-Match': '',
'If-None-Match': '',
'If-Unmodified-Since': '',
'Range': '',
'CanonicalizedHeaders': 'x-ms-date:' + request_time + '\nx-ms-lease-action:release' + '\nx-ms-lease-id:' + lease_id + '\nx-ms-version:' + api_version + '\n',
'CanonicalizedResource': '/' + storage_account_name + '/' + container_name + '\ncomp:lease\nrestype:container'
}
string_to_sign = (string_params['verb'] + '\n'
+ string_params['Content-Encoding'] + '\n'
+ string_params['Content-Language'] + '\n'
+ string_params['Content-Length'] + '\n'
+ string_params['Content-MD5'] + '\n'
+ string_params['Content-Type'] + '\n'
+ string_params['Date'] + '\n'
+ string_params['If-Modified-Since'] + '\n'
+ string_params['If-Match'] + '\n'
+ string_params['If-None-Match'] + '\n'
+ string_params['If-Unmodified-Since'] + '\n'
+ string_params['Range'] + '\n'
+ string_params['CanonicalizedHeaders']
+ string_params['CanonicalizedResource'])
print (string_to_sign)
signed_string = base64.b64encode(hmac.HMAC(base64.b64decode(storage_account_key), string_to_sign.encode('utf-8'), hashlib.sha256).digest()).decode()
print (signed_string)
headers = {
'x-ms-date': request_time,
'x-ms-lease-action': 'release',
'x-ms-lease-id': lease_id,
'x-ms-version': api_version,
'Authorization': ('SharedKey ' + storage_account_name + ':' + signed_string)
}
url = ('https://' + storage_account_name + '.blob.core.windows.net/' + container_name + '?comp=lease&restype=container')
r = requests.put(url, headers = headers)
print (r)
print(r.content)
I got the lease ID by going in to the portal, breaking the lease and then acquiring a new one.
I get a 403 error, with the following information (obfuscated for obvious reasons):
<Response [403]>
b'\xef\xbb\xbf<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\nTime:2020-04-15T21:59:08.6983006Z</Message><AuthenticationErrorDetail>The MAC signature found in the HTTP request \'XXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXX=\' is not the same as any computed signature. Server used following string to sign: \'PUT\n\n\n53\n\n\n\n\n\n\n\n\nx-ms-date:Thu, 16 Apr 2020 21:46:56 GMT\nx-ms-lease-action:release\nx-ms-lease-id:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\nx-ms-version:2019-07-07\n/storageaccountname/containername\ncomp:lease\nrestype:container\'.</AuthenticationErrorDetail></Error>'
How can I release a lease? It must be something I'm doing in the headers, but I can't figure out where.
UPDATE (Based on latest code provided in replies). Get this error now:
Traceback (most recent call last):
File "Azure_release_lease_2.py", line 49, in <module>
signed_string = base64.b64encode(hmac.HMAC(base64.b64decode(storage_account_key), string_to_sign, hashlib.sha256).digest())
File "C:\Program Files (x86)\Python38-32\lib\hmac.py", line 88, in __init__
self.update(msg)
File "C:\Program Files (x86)\Python38-32\lib\hmac.py", line 96, in update
self.inner.update(msg)
TypeError: Unicode-objects must be encoded before hashing
There are a few issues with your code because of which you're getting this error.
First, you didn't include x-ms-lease-id and x-ms-lease-action in your CanonicalizedHeaders.
From the documentation link:
Retrieve all headers for the resource that begin with x-ms-, including
the x-ms-date header.
'CanonicalizedHeaders': 'x-ms-date:' + request_time + '\nx-ms-lease-action:acquire' + '\nnx-ms-lease-id:' + theleaseidfromazureportal + '\nx-ms-version:' + api_version + '\n',
Next, there's an issue with CanonicalizedResource. Currently it is missing container name and has incorrect values for comp and restype query parameters.
'CanonicalizedResource': '/' + storage_account_name + '/' + container_name + '/\ncomp:lease\nrestype:container'
Lastly your URL should be:
url = ('https://' + storage_account_name + '.blob.core.windows.net/' + container_name + '?comp=lease&restype=container')
Currently it is missing container name.
Please refer to lease container REST API documentation here: https://learn.microsoft.com/en-us/rest/api/storageservices/lease-container.
Furthermore, you don't really have to consumer REST API, there's a Python SDK for Azure Storage which is a wrapper over this REST API. You can find more information about the SDK here: https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/storage.
UPDATE
Found one issue in your updated code. In your string_to_sign, you're including Content-Type as application/xml however the same is not included in your request headers. This is causing your signatures to mismatch. Either add Content-Type request header in your headers definition or use an empty string in your string_to_sign. That should take care of the problem. Considering Release Lease request doesn't have a request body, I would recommend the latter.
UPDATE 2
There were a few other issues with your code. Please use the code below, it should work:
import requests
import datetime
import hmac
import hashlib
import base64
storage_account_name = 'storageaccountname'
storage_account_key = 'storateaccountkey'
lease_id = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
container_name = 'containername'
api_version = '2019-07-07'
request_time = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
string_params = {
'verb': 'PUT',
'Content-Encoding': '',
'Content-Language': '',
'Content-Length': '',
'Content-MD5': '',
'Content-Type': '',
'Date': '',
'If-Modified-Since': '',
'If-Match': '',
'If-None-Match': '',
'If-Unmodified-Since': '',
'Range': '',
'CanonicalizedHeaders': 'x-ms-date:' + request_time + '\nx-ms-lease-action:release' + '\nx-ms-lease-id:' + lease_id + '\nx-ms-version:' + api_version + '\n',
'CanonicalizedResource': '/' + storage_account_name + '/' + container_name + '\ncomp:lease\nrestype:container'
}
string_to_sign = (string_params['verb'] + '\n'
+ string_params['Content-Encoding'] + '\n'
+ string_params['Content-Language'] + '\n'
+ string_params['Content-Length'] + '\n'
+ string_params['Content-MD5'] + '\n'
+ string_params['Content-Type'] + '\n'
+ string_params['Date'] + '\n'
+ string_params['If-Modified-Since'] + '\n'
+ string_params['If-Match'] + '\n'
+ string_params['If-None-Match'] + '\n'
+ string_params['If-Unmodified-Since'] + '\n'
+ string_params['Range'] + '\n'
+ string_params['CanonicalizedHeaders']
+ string_params['CanonicalizedResource'])
print (string_to_sign)
signed_string = base64.b64encode(hmac.HMAC(base64.b64decode(storage_account_key), string_to_sign, hashlib.sha256).digest())
print (signed_string)
headers = {
'x-ms-date': request_time,
'x-ms-lease-action': 'release',
'x-ms-lease-id': lease_id,
'x-ms-version': api_version,
'Authorization': ('SharedKey ' + storage_account_name + ':' + signed_string)
}
url = ('https://' + storage_account_name + '.blob.core.windows.net/' + container_name + '?comp=lease&restype=container')
#r = requests.put(url, headers = headers, data=data)
r = requests.put(url, headers = headers)
print (r)
print(r.content)

How would you clean this dictionary in Python?

This is my first attempt building something non-web and involving logic coding.
Please take a look at this god-awful dictionary below:
Messy_Dict=
{
'name': "['\\r\\n NASDAQ: BKEP\\r\\n ']",
'underlying': "['1.12']",
'strike_prices_list': ["['2.50'", " '5.00'", " '7.50']"],
'call_bid': ["['\\r\\n0.05 '", " '\\r\\n0.00 '", " '\\r\\n0.00 ']"],
'put_ask': ["['\\r\\n2.10 '", " '\\r\\n4.50 '", " '\\r\\n7.00 ']"]
}
What I want to do is clean up the unnecessary sub-strings within each dictionary value to get something like this:
Clean_Dict=
{
'name': "BKEP",
'underlying': "1.12",
'strike_prices_list': ["2.50", "5.00", "7.50"],
'call_bid': ["0.05", "0.00", "0.00"],
'put_ask': ["2.10", "4.50", "7.00"]
}
I have managed to get from Messy_Dict to Clean_Dict but I used very barbaric means to do so. I will just say that it included a for loop and multiple strip(), replace('', '') methods. And it pains me to look at that block of code in my .py file.
So I guess, is there a more elegant method in performing the desired task of converting Messy_Dict to Clean_Dict? I feel as if I'm missing something here in my fundamentals.
Edit
def parse(self, response):
strike_prices_main = response.css('.highlight , .aright .strike-col').css('::text').extract()
if not strike_prices_main:
pass
else:
name = response.css('#instrumentticker::text').extract()
strike_prices_list = response.css('.aright .strike-col').css('::text').extract()
call_bid = response.css('.aright td:nth-child(5)').css('::text').extract()
put_ask = response.css('.aright td:nth-child(14)').css('::text').extract()
underlying = response.css('.pricewrap .bgLast').css('::text').extract()
file.write('%s|%s|%s|%s|%s\n'%(name,underlying,strike_prices_list,call_bid,put_ask))
Using spiders to crawl!
Maybe like this:
import re
Messy_Dict= \
{
'name': "['\\r\\n NASDAQ: BKEP\\r\\n ']",
'underlying': "['1.12']",
'strike_prices_list': ["['2.50'", " '5.00'", " '7.50']"],
'call_bid': ["['\\r\\n0.05 '", " '\\r\\n0.00 '", " '\\r\\n0.00 ']"],
'put_ask': ["['\\r\\n2.10 '", " '\\r\\n4.50 '", " '\\r\\n7.00 ']"]
}
regexstr = "\\\\(r|n)|\s|\[|\]|\'|NASDAQ:"
dict_clean = {}
for k, v in Messy_Dict.items():
if isinstance(v, list):
list_clean = []
for el in v:
el_clean = re.sub(regexstr, "", el)
list_clean.append(el_clean)
dict_clean[k] = list_clean
else:
dict_clean[k] = re.sub(regexstr, "", v)
dict_clean
You can use regular expressions.
Example:
import re
messy_dict = {
'name': "['\\r\\n NASDAQ: BKEP\\r\\n ']",
'underlying': "['1.12']",
'strike_prices_list': ["['2.50'", " '5.00'", " '7.50']"],
'call_bid': ["['\\r\\n0.05 '", " '\\r\\n0.00 '", " '\\r\\n0.00 ']"],
'put_ask': ["['\\r\\n2.10 '", " '\\r\\n4.50 '", " '\\r\\n7.00 ']"]
}
for key in messy_dict:
stripfunc = lambda x: re.sub('[^\d\.]', '', str(x))
if type(messy_dict[key]) is list:
messy_dict[key] = [stripfunc(x) for x in messy_dict[key]]
else:
messy_dict[key] = stripfunc(messy_dict[key])
print(messy_dict)
Explanation: [^ ] matches anything that is NOT in the set. \d is for numeric values and the backslash escapes the dot. Using str(val) to make strings out of the lists.
Output: {'name': '', 'underlying': '1.12', 'strike_prices_list': ['2.50', '5.00', '7.50'], 'call_bid': ['0.05', '0.00', '0.00'], 'put_ask': ['2.10', '4.50', '7.00']}
Edit: just noticed that you also want to keep the dot. Updated the code.

How do I URL encode this

Need this:
POST&https%3A%2F%2Fsecure.trademe.co.nz%2FOauth%2FRequestToken&oauth_callback%3Dhttp%253A%252F%252Fwww.website-tm-access.co.nz%252Ftrademe-callback%26oauth_consumer_key%3DC74CD73FDBE37D29BDD21BAB54BC70E422%26oauth_nonce%3D7O3kEe%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1285532322%26oauth_version%3D1.0%26scope%3DMyTradeMeRead%252CMyTradeMeWrite
Myattempt:
New_base_string ="POST&https%3A%2F%2Fsecure.trademe.co.nz%2FOauth%2FRequestToken&oauth_callback%3Dhttp%253A%252F%252Fwww.website-tm-access.co.nz%252Ftrademe-callback%26oauth_consumer_key%" + str(consumer_key) +"3DC74CD73FDBE37D29BDD21BAB54BC70E422%26oauth_nonce%3" + str(nonce) + "%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3" + str(time) + "%26oauth_version%3D1.0%26scope%3DMyTradeMeRead%252CMyTradeMeWrite"
I just tried to append it to the end, will this work or will i need to append to a list and then encode?
so like this:
headers = { my_variable + other_variable }
authorization = '5C82CC6BC7C6472154FBC9CAB24A29A2 ' + ', '.join([key + '="' + urllib.parse.quote_plus(str(value)) + '"' for key, value in headers.items()])
General
If you want to URL encode parameters to your POST request the best way is:
import urllib
f = { 'eventName' : 'myEvent',
'eventDescription' : 'cool event',
'url' : 'http://www.google.com'}
print 'POST&%s' % urllib.urlencode(f)
Output:
POST&eventName=myEvent&url=http%3A%2F%2Fwww.google.com&eventDescription=cool+event
with Dictionary its not ordered if you want to order it just use a list
import urllib
f = [ ('eventName', 'myEvent'),
('eventDescription', 'cool event'),
('url', 'http://www.google.com')]
print 'POST&%s' % urllib.urlencode(f)
Output
POST&eventName=myEvent&eventDescription=cool+event&url=http%3A%2F%2Fwww.google.com
How to get your need this string (Python 3.5)
While the general example is tested in python 2.7, I wrote your example with python 3.5 code.
import urllib.parse
method = "POST"
url = "https://secure.trademe.co.nz/Oauth/RequestToken"
params = [('oauth_callback', 'http://www.website-tm-access.co.nz/trademe-callback'),
('oauth_consumer_key', 'C74CD73FDBE37D29BDD21BAB54BC70E422'),
('oauth_nonce', '7O3kEe'),
('oauth_signature_method', 'HMAC-SHA1'),
('oauth_timestamp', 1285532322),
('oauth_version', 1.0),
('scope', "MyTradeMeRead,MyTradeMeWrite")]
print('POST&%(url)s&%(params)s' % { 'url' : urllib.parse.quote_plus(url), 'params' : urllib.parse.quote_plus(urllib.parse.urlencode(params)) })
Output
POST&https%3A%2F%2Fsecure.trademe.co.nz%2FOauth%2FRequestToken&oauth_callback%3Dhttp%253A%252F%252Fwww.website-tm-access.co.nz%252Ftrademe-callback%26oauth_consumer_key%3DC74CD73FDBE37D29BDD21BAB54BC70E422%26oauth_nonce%3D7O3kEe%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1285532322%26oauth_version%3D1.0%26scope%3DMyTradeMeRead%252CMyTradeMeWrite

URL request emulating curl --data-binary

I want to send a URL request equivalent to using to json objects in the post data, separated by newline.
This is for indexing two items in bulk for Elasticsearch.
This works fine:
curl -XPOST 'localhost:9200/myindex/mydoc?pretty=true' --data-binary #myfile.json
where myfile.json:
{"index": {"_parent": "btaCovzjQhqrP4s3iPjZKQ"}}
{"title": "hello"}
{"index": {"_parent": "btaCovzjQhqrP4s3iPjZKQ"}}
{"title": "world"}
When I try it using:
req = urllib2.Request(url,data=
json.dumps({"index": {"_parent": "btaCovzjQhqrP4s3iPjZKQ"}}) + "\n" +
json.dumps({"title":"hello"}) + "\n" +
json.dumps({"index": {"_parent": "btaCovzjQhqrP4s3iPjZKQ"}}) + "\n" +
json.dumps({"title":"world"})
I get:
HTTP Error 500: Internal Server Error
The "HTTP Error 500" may be from forgetting to include an index name or index type.
Also: for bulk inserts, elasticsearch requires a trailing "\n" character after the last record, or it won't insert that record.
Try:
import urllib2
import json
url = 'http://localhost:9200/myindex/mydoc/_bulk?pretty=true'
data = json.dumps({"index": {"_parent": "btaCovzjQhqrP4s3iPjZKQ"}}) + "\n" + json.dumps({"title":"hello"}) + "\n" + json.dumps({"index": {"_parent": "btaCovzjQhqrP4s3iPjZKQ"}}) + "\n" + json.dumps({"title":"world"})
req = urllib2.Request(url,data=data+"\n")
f = urllib2.urlopen(req)
print f.read()
Or, with some refactoring:
import urllib2
import json
url = 'http://localhost:9200/myindex/mydoc/_bulk?pretty=true'
data = [
{"index": {"_parent": "btaCovzjQhqrP4s3iPjZKQ"}},
{"title":"hello"},
{"index": {"_parent": "btaCovzjQhqrP4s3iPjZKQ"}},
{"title":"world"}
]
encoded_data = "\n".join(map(json.dumps,data)) + "\n"
req = urllib2.Request(url,data=encoded_data)
f = urllib2.urlopen(req)
print f.read()
The usecase for me is actually a bulk_index request for ElasticSearch.
This is made a lot easier with rawes:
import rawes
es = rawes.Elastic('localhost:9200')
with open('myfile.json') as f:
lines = f.readlines()
es.post('someindex/sometype/_bulk', data=lines)

Categories

Resources