Python source :
#app.route('/pret/<int:idPret>', methods=['GET'])
def descrire_un_pret(idPret):
j = 0
for j in prets:
if prets[j]['id'] == idPret:
reponse = make_response(json.dumps(prets[j],200))
reponse.headers = {"Content-Type": "application/json"}
return reponse
I would like to retrieve a record in the prets list by the idPret parameter. Nevertheless I get an error:
TypeError: list indices must be integers, not dict
j is not a number. j is one element in the prets list. Python loops are foreach loops. if j['id'] == idPret: would work:
for j in prets:
if j['id'] == idPret:
reponse = make_response(json.dumps(j, 200))
reponse.headers = {"Content-Type": "application/json"}
return reponse
I'd use a different name here, and use the flask.json.jsonify() function to create the response:
from flask import jsonify
for pret in prets:
if pret['id'] == idPret:
return jsonify(pret)
jsonify() takes care of converting to JSON and creating the response object with the right headers for you.
You are mistaking Python's for behavior for Javascript's. When you do
for j in prets: in Python, the contents of j are already the elements in pretz, not an index number.
Related
I was wondering if i could get some input from some season python exports, i have a couple questions
I am extracting data from an api request and calculating the total vulnerabilities,
what is the best way i can return this data so that i can call it in another function
what is the way i can add up all the vulnerabilities (right now its just adding it per 500 at a time, id like to do the sum of every vulnerability
def _request():
third_party_patching_filer = {
"asset": "asset.agentKey IS NOT NULL",
"vulnerability" : "vulnerability.categories NOT IN ['microsoft patch']"}
headers = _headers()
print(headers)
url1 = f"https://us.api.insight.rapid7.com/vm/v4/integration/assets"
resp = requests.post(url=url1, headers=headers, json=third_party_patching_filer, verify=False).json()
jsonData = resp
#print(jsonData)
has_next_cursor = False
nextKey = ""
if "cursor" in jsonData["metadata"]:
has_next_cursor = True
nextKey = jsonData["metadata"]["cursor"]
while has_next_cursor:
url2 = f"https://us.api.insight.rapid7.com/vm/v4/integration/assets?&size=500&cursor={nextKey}"
resp2 = requests.post(url=url2, headers=headers, json=third_party_patching_filer, verify=False).json()
cursor = resp2["metadata"]
print(cursor)
if "cursor" in cursor:
nextKey = cursor["cursor"]
print(f"next key {nextKey}")
#print(desktop_support)
for data in resp2["data"]:
for tags in data['tags']:
total_critical_vul_osswin = []
total_severe_vul_osswin = []
total_modoer_vuln_osswin = []
if tags["name"] == 'OSSWIN':
print("OSSWIN")
critical_vuln_osswin = data['critical_vulnerabilities']
severe_vuln_osswin = data['severe_vulnerabilities']
modoer_vuln_osswin = data['moderate_vulnerabilities']
total_critical_vul_osswin.append(critical_vuln_osswin)
total_severe_vul_osswin.append(severe_vuln_osswin)
total_modoer_vuln_osswin.append(modoer_vuln_osswin)
print(sum(total_critical_vul_osswin))
print(sum(total_severe_vul_osswin))
print(sum(total_modoer_vuln_osswin))
if tags["name"] == 'DESKTOP_SUPPORT':
print("Desktop")
total_critical_vul_desktop = []
total_severe_vul_desktop = []
total_modorate_vuln_desktop = []
critical_vuln_desktop = data['critical_vulnerabilities']
severe_vuln_desktop = data['severe_vulnerabilities']
moderate_vuln_desktop = data['moderate_vulnerabilities']
total_critical_vul_desktop.append(critical_vuln_desktop)
total_severe_vul_desktop.append(severe_vuln_desktop)
total_modorate_vuln_desktop.append(moderate_vuln_desktop)
print(sum(total_critical_vul_desktop))
print(sum(total_severe_vul_desktop))
print(sum(total_modorate_vuln_desktop))
else:
pass
else:
has_next_cursor = False
If you have a lot of parameters to pass, consider using a dict to combine them. Then you can just return the dict and pass it along to the next function that needs that data. Another approach would be to create a class and either access the variables directly or have helper functions that do so. The latter is a cleaner solution vs a dict, since with a dict you have to quote every variable name, and with a class you can easily add additional functionally beyond just being a container for a bunch of instance variables.
If you want the total across all the data, you should put these initializations:
total_critical_vul_osswin = []
total_severe_vul_osswin = []
total_modoer_vuln_osswin = []
before the while has_next_cursor loop (and similarly for the desktop totals). The way your code is currently, they are initialized each cursor (ie, each 500 samples based on the URL).
I'm calling a LinkedIn API with the code below and it does what I want.
However when I use almost identical code inside a loop it returns a type error.
it returns a type error:
File "C:\Users\pchmurzynski\OneDrive - Centiq Ltd\Documents\Python\mergedreqs.py", line 54, in <module>
auth_headers = headers(access_token)
TypeError: 'dict' object is not callable
It has a problem with this line (which again, works fine outside of the loop):
headers = headers(access_token)
I tried changing it to
headers = headers.get(access_token)
or
headers = headers[access_token]
EDIT:
I have also tried this, with the same error:
auth_headers = headers(access_token)
But it didn't help. What am I doing wrong? Why does the dictionary work fine outside of the loop, but not inside of it and what should I do to make it work?
What I am hoping to achieve is to get a list, which I can save as json with share statistics called for each ID from the "shids" list. That can be done with individual requests - one link for one ID,
(f'https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn%3Ali%3Aorganization%3A77487&ugcPosts=List(urn%3Ali%3AugcPost%3A{shid})
or a a request with a list of ids.
(f'https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn%3Ali%3Aorganization%3A77487&ugcPosts=List(urn%3Ali%3AugcPost%3A{shid},urn%3Ali%3AugcPost%3A{shid2},...,urn%3Ali%3AugcPost%3A{shidx})
Updated Code thanks to your comments.
shlink = ("https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn%3Ali%3Aorganization%3A77487&shares=List(urn%3Ali%3Ashare%3A{})")
#loop through the list of share ids and make an api request for each of them
shares = []
token = auth(credentials) # Authenticate the API
headers = fheaders(token) # Make the headers to attach to the API call.
for shid in shids:
#create a request link for each sh id
r = (shlink.format(shid))
#call the api
res = requests.get(r, headers = auth_headers)
share_stats = res.json()
#append the shares list with the responce
shares.append(share_stats["elements"])
works fine outside the loop
Because in the loop, you re-define the variable. Added print statments to show it
from liapiauth import auth, headers # one type
for ...:
...
print(type(headers))
headers = headers(access_token) # now set to another type
print(type(headers))
Lesson learned - don't overrwrite your imports
Some refactors - your auth token isn't changing, so don't put it in the loop; You can use one method for all LinkedIn API queries
from liapiauth import auth, headers
import requests
API_PREFIX = 'https://api.linkedin.com/v2'
SHARES_ENDPOINT_FMT = '/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn%3Ali%3Aorganization%3A77487&shares=List(urn%3Ali%3Ashare%3A{}'
def get_linkedin_response(endpoint, headers):
return requests.get(API_PREFIX + endpoint, headers=headers)
def main(access_token=None):
if access_token is None:
raise ValueError('Access-Token not defined')
auth_headers = headers(access_token)
shares = []
for shid in shids:
endpoint = SHARES_ENDPOINT_FMT.format(shid)
resp = get_linkedin_response(endpoint, auth_headers)
if resp.status_code // 100 == 2:
share_stats = resp.json()
shares.append(share_stats[1])
# TODO: extract your data here
idlist = [el["id"] for el in shares_list["elements"]]
if __name__ == '__main__':
credentials = 'credentials.json'
main(auth(credentials))
I'm new to Python. Trying to automate some painful API calls using the Python requests module. Getting pretty close, but can't figure out how to pass lists of timestamps as request parameters
Example: Generate list of lastModified timestamps
import datetime
from datetime import datetime, timedelta
earliest_ts_str = '2020-10-01T15:00:00Z'
earliest_ts_obj = datetime.strptime(earliest_ts_str, timestamp_format)
#bottom_ts_obj = earliest_ts_obj.replace(second=0, microsecond=0, minute=0)
latest_ts_str = '2020-10-01T23:00:00Z'
latest_ts_obj = datetime.strptime(latest_ts_str, timestamp_format)
ts_raw = []
while earliest_ts_obj < latest_ts_obj:
ts_raw.append(earliest_ts_obj)
earliest_ts_obj += timedelta(hours=1)
ts_raw.append(latest_ts_obj)
ts_formatted = [d.strftime('%Y-%m-%dT%H:%M:%SZ') for d in ts_raw]
ts_formatted
Results:
['2020-10-01T15:00:00Z',
'2020-10-01T16:00:00Z',
'2020-10-01T17:00:00Z',
'2020-10-01T18:00:00Z',
'2020-10-01T19:00:00Z',
'2020-10-01T20:00:00Z',
'2020-10-01T21:00:00Z',
'2020-10-01T22:00:00Z',
'2020-10-01T23:00:00Z']
Example 2: Create the request call
Here is (obviously) where my problem is. I tried to flesh out a function to handle it, but its not even close!
How do I pass the first timestamp in the list as the lastModifiedStart parameter? AND
Pass the second timestamp in the list as the lastModifiedEnd parameter?
Then so on until all timestamps have been tried?
import requests
method = 'get'
base_url = 'https://sandbox-api.com/'
api_type = 'items'
api_version = '/v1/'
api_path = api_type + api_version
api_key = 'myKey'
full_url = base_url + api_path
def make_historic_calls(last_mod_start, last_mod_end):
last_mod_start = for ts in ts_formatted: ts
last_mod_end = for ts in ts_formatted: ts
parameters = {'api_key':api_key, 'lastModifiedStart': last_mod_start, 'lastModifiedEnd': last_mod_end}
auth_header = {'Authorization': 'Basic <base64EncodedStringHere>'}
resp_raw = requests.request(method, full_url, headers=auth_header, params=parameters)
resp_processed = json.loads(resp_raw.content)
resp_pretty = json.dumps(resp_processed, indent=2, sort_keys=True)
return print(pretty)
test = make_historic_calls(ts_formatted, ts_formatted)
I know this isn't an easy solve (its taken me days and days to get this far), but any guidance on how to tackle this would be appreciated.
Thank you
EDIT 1: This adjusted function works great!
def make_historic_calls(ts_formatted):
for last_mod_start, last_mod_end in zip(ts_formatted, ts_formatted[1:]):
parameters = {'api_key':api_key, 'lastModifiedStart': last_mod_start, 'lastModifiedEnd': last_mod_end}
auth_header = {'Authorization': 'Basic <base64EncodedString>'}
resp_raw = requests.request(method, full_url, headers=auth_header, params=parameters)
print(f'{resp_raw.url} Status Code: {str(resp_raw.status_code)}')
return print(resp_raw)
test = make_historic_calls(ts_formatted)
The standard trick for extracting pairs of consecutive items from a list is:
for this_one, next_one in zip(my_list, my_list[1:]):
...
So your code needs to be something like:
def make_historic_calls(ts_formatted):
for last_mod_start, last_mod_end in zip(ts_formatted, ts_formatted[1:]):
make the request using last_mod_start and last_mod_end
return some value combining all of the results from your requests
make_historic_calls(ts_formatted)
I hope I've understood correctly what it is you're trying to do.
So basically what you want to do is to chunk the list by 2 elements, and then unpack those 2 element lists and pass them to functions, consider something like the following generator:
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
And then you can use it like the following:
for first, second in chunks(iterable, 2):
make_historic_calls(first, second)
Hope this helps
Edit:
I'm not sure if you want to pass the variables by pairs that overlap or don't, if you want them to overlap like (0,1) (1,2) (2,3)... instead of (0,1) (2,3) (4,5)... then use the version of "chunks" below:
def chunks(l, n, repeat=True):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
additional = int(repeat)
yield l[i:i + n + additional]
I have the following error coming in my Python code:
if data['result'] == 0:
TypeError: list indices must be integers, not str
Following is the code :
data = urllib.urlencode(parameters)
req = urllib2.Request(url, data)
try:
response = urllib2.urlopen(req)
except urllib2.URLError, e:
self.redirect('/error')
json_post = response.read()
data = json.loads(json_post)
response_dict = simplejson.loads(json_post)
virustotal = VirusTotal()
if data['result'] == 0:
virustotal_result = True
elif data['result'] == -2:
self.response.out.write("API Request Rate Limit Exceeded<br/>")
elif data['result'] == -1:
self.response.out.write("API Key provided is wrong<br/>")
elif data['result'] == 1:
self.response.out.write("Time Stamp : %s<br/>"% data['report'][0])
I know that data is a list. So I changed it into integers as well but the code then showed the range error. Please Help??
When you say data = json.loads(json_post), it sounds like you got a list, not the dict you seem to be expecting.
If this isn't the problem, try updating with the full traceback and the value of json_post.
You are getting an array of objects back from response.read, which means you're getting a Python list. Try this:
data = json.loads(json_post)[0]
I got two functions that return a list of dictionary and i'm trying to get json to encode it, it works when i try doing it with my first function, but now i'm appending second function with a syntax error of ": expected". I will eventually be appending total of 7 functions that each output a list of dict. Is there a better way of accomplishing this?
import dmidecode
import simplejson as json
def get_bios_specs():
BIOSdict = {}
BIOSlist = []
for v in dmidecode.bios().values():
if type(v) == dict and v['dmi_type'] == 0:
BIOSdict["Name"] = str((v['data']['Vendor']))
BIOSdict["Description"] = str((v['data']['Vendor']))
BIOSdict["BuildNumber"] = str((v['data']['Version']))
BIOSdict["SoftwareElementID"] = str((v['data']['BIOS Revision']))
BIOSdict["primaryBIOS"] = "True"
BIOSlist.append(BIOSdict)
return BIOSlist
def get_board_specs():
MOBOdict = {}
MOBOlist = []
for v in dmidecode.baseboard().values():
if type(v) == dict and v['dmi_type'] == 2:
MOBOdict["Manufacturer"] = str(v['data']['Manufacturer'])
MOBOdict["Model"] = str(v['data']['Product Name'])
MOBOlist.append(MOBOdict)
return MOBOlist
def get_json_dumps():
jsonOBJ = json
#Syntax error is here, i can't use comma to continue adding more, nor + to append.
return jsonOBJ.dumps({'HardwareSpec':{'BIOS': get_bios_specs()},{'Motherboard': get_board_specs()}})
Use multiple items within your nested dictionary.
jsonOBJ.dumps({
'HardwareSpec': {
'BIOS': get_bios_specs(),
'Motherboard': get_board_specs()
}
})
And if you want multiple BIOS items or Motherboard items, just use a list.
...
'HardwareSpec': {
'BIOS': [
get_bios_specs(),
get_uefi_specs()
]
...
}
If you want a more convenient lookup of specs, you can just embed a dict:
jsonOBJ.dumps({'HardwareSpec':{'BIOS': get_bios_specs(),
'Motherboard': get_board_specs()
}
})