appending text using loop - python

I need a help so basically I am making a function where we give URL as input with parameter and then it will modify the value of parameters and then print the modified URL.
def findingParams(url):
#url = url+'?name=aman&test=aman'
base_url = url.split('?')[0]
parameters = url.split('?')[1]
myparms = {}
myparms1 = []
payload = "modified_value"
if '&' in parameters:
#['name=123', 'test=321']
parameters = parameters.split('&')
for params in parameters:
myparms1.append(params.split('=')[0])
myparms[(params.split('=')[0])] = payload
#['name', '123']
#['test', '321']
print(f'url = {url}\nparams = {myparms}')
#here I want the ouput as modified parameter
else:
#print(params.split('='))
print(base_url)
print(parameters)
myparms1.append(parameters.split('=')[0])
myparms[(parameters.split('=')[0])] = payload
print(f'url = {url}\nparams = {myparms}')
#['name', '123']
#myparms = {'name':'123', 'test':'321'}
for i in myparms1:
print(f'{base_url}?{i}={myparms[i]}')
#base_url+?[params]=[payload]
I wrote this function and this function works fine with URL that have single parameter eg: testme.com/test.php?name=123 and I also have to make it work with multiple parameters but the problem is that I don't know How can I use for loop to append value in URL for example: If I'm using for loop then output is like this
testme.com/test.php?name=modified_Value
testme.com/test.php?test=modified_Value
but I want URL like this
testme.com/test.php?name=modified_value&test=modified_value.

Try using a temp variable to build the url in your loop, then printing at the end, like this:
result = f'{base_url}?'
for i in myparms1:
result = result + f'{i}=myparms1[i]&'
# remove extra & at end after last parameter
result = result[:-1]
print(result)

#!/usr/bin/env python3
def findingParams(url):
if "?" not in url:
print(url)
else:
base_url, parameters = url.split("?")
payload = "modified_value"
if "&" in parameters:
modif = ""
for params in parameters.split("&"):
name, value = params.split("=")
modif += name + "=" + payload + "&"
print(base_url + "?" + modif.strip("&"))
else:
print(url.split("=")[0] + "=" + payload)
findingParams("testme.com/test.php")
# testme.com/test.php
findingParams("testme.com/test.php?name=123")
# testme.com/test.php?name=modified_value
findingParams("testme.com/test.php?name=12345&test=12345")
# testme.com/test.php?name=modified_value&test=modified_value
findingParams("testme.com/test.php?name=12345&test=12345&foo=12345")
# testme.com/test.php?name=modified_value&test=modified_value&foo=modified_value
Like this ?

Related

How to iterate over three lists in Python?

I have 3 the same lists how to dig in to id in one of the list?I tryed
create_card_on_the_board[0]['content']['id'] but i got Object is not subscriptable error
def create_card_on_the_board_call(self, id_list, card_count, card_name):
global create_card
responses = []
for i in range(card_count):
create_card = self.rest_api_helper.post_call(
self.base_url + '/cards?' + 'key=' + test_config[
'key'] + '&' + 'token=' + test_config[
'token'] + '&' + f'idList={id_list}' + '&' + f'name={card_name}', headers=None)
responses.append(create_card)
return responses
what you have is a list of 3 HTTP responses.
create_card_on_the_board = [resp1,resp2,resp3]
for resp in create_card_on_the_board:
data = resp.json()
# now you have a python dict named 'data' - assuming all responses have the same content you can do:
print(f'id: {data["id"]}')
create_card_on_the_board[0]['content'] is bytes data. You’ll need to convert it into a dict first. E.g.,
myList = dict(create_card_on_the_board[0]['content'])

HP ALM results attachment and status update using python

Challenge : Attach screenshots to Tests in TestLab , update status as PASS/FAIL steps wise (currently updating pass status is enough)
I am expected to write a script in python , to attach test results to the testcases present in test lab, then for each test step Expected result to be set as "As Expected" and pass the TC step by step.
Ie while performing manually, we select the case , click run and then enter "As expected" in expected output area and pass that step, and perfrom this for all teststeps on the test case. This need to be automated. I hav a folder which has Screenshots(similar to TC name), so script shoudl upload the screenshots and update the status.
What I have tried so far :
I was able to connect to alm , with partial testcase name, I was able to pull full testcase name from testplan, but unfortunately i am still struggling to achieve the final goal.
My code so far :
import win32com
from win32com.client import Dispatch
import codecs
import re
import json
# Login Credentials
qcServer = "https://almurl.saas.microfocus.com/qcbin/"
qcUser = "my_username"
qcPassword = "pwd"
qcDomain = "domain"
testList = []
testdict = {}
project = "Crew_Management"
# Do the actual login
td = win32com.client.Dispatch("TDApiOle80.TDConnection.1")
td.InitConnectionEx(qcServer)
td.Login(qcUser,qcPassword)
td.Connect(qcDomain,project)
if td.Connected == True:
print ("System: Logged in to " +project)
else:
print ("Connect failed to " +project)
mg = td.TreeManager # Tree manager
name = ['TC001','TC002','TC003','TC003','TC004','TC005','TC006','TC007','TC008','TC009','TC010','TC011','TC012','TC013','TC014']
folder = mg.NodeByPath('Subject\\Test Factory\\MPG\\MPG Regression Test_Yearly Request\\GUI')
for x in name:
testList = folder.FindTests(x)
#print(type(testList))
print(testList[0].Name)
print(testList[0].DesStepsNum)
td.Disconnect()
td.Logout()
Any help or guidance is much appreciated !
Assuming that you have working experience in Python. Here I am writing all the different functions needed to complete your task.
Reference: https://admhelp.microfocus.com/alm/api_refs/REST_TECH_PREVIEW/ALM_REST_API_TP.html
Global Variable
import re
import json
import datetime
import time
import sys
import os, fnmatch
from os import listdir
from os.path import isfile, join
from xml.etree.ElementTree import Element, SubElement, tostring, parse
import glob
from requests.auth import HTTPBasicAuth
import requests
ALM_USER_NAME = ""
ALM_PASSWORD = ""
ALM_DOMAIN = ""
ALM_URL = ""
AUTH_END_POINT = ALM_URL + "authentication-point/authenticate"
QC_SESSION_END_POINT = ALM_URL + "rest/site-session"
QC_LOGOUT_END_POINT = ALM_URL + "authentication-point/logout"
ALM_MIDPOINT = "rest/domains/" + ALM_DOMAIN + "/projects/"
PATH_SEP = os.path.sep
Login Function
def alm_login(self):
"""
Function : alm_login
Description : Authenticate user
Parameters : global parameter
alm_username - ALM User
alm_password - ALM Password
"""
response = self.alm_session.post(AUTH_END_POINT,
auth=HTTPBasicAuth(ALM_USER_NAME, ALM_PASSWORD))
if response.status_code == 200:
response = self.alm_session.post(QC_SESSION_END_POINT)
if response.status_code == 200 | response.status_code == 201:
print "ALM Authentication successful"
else:
print "Error: ", response.staus_code
else:
print "Error: ", response.staus_code
self.alm_session.headers.update({'Accept':'application/json',
'Content-Type': 'application/xml'})
return
Logout Function
After the logout method is successful the cookie should expire
def alm_logout(self):
'''
Function : alm_logout
Description : terminate user session
Parameters : No Parameters
'''
response = self.alm_session.post(QC_LOGOUT_END_POINT)
print "Logout successful", response.headers.get('Expires'), response.status_code
return
Get Test Set Folder
If the test cases span across multiple test suites then it is better to get the test set folder first and find the necessary test suite.
def find_test_set_folder(self):
'''
Function : find_test_set_folder
Description : This sends a couple of http request and authenticate the user
Parameters : 1 Parameter
test_set_path - ALM test set path
'''
json_str = json.loads(self.find_folder_id(self.test_set_path.split("\\"), "test-set-folders"
, 0, "id"))
if 'entities' in json_str:
return create_key_value(json_str['entities'][0]['Fields'])['id']
else:
return create_key_value(json_str['Fields'])['id']
Get Folder Id
This method will help you find the Test Suite Folder ID or Test Plan Folder Id.
def find_folder_id(self, arrfolder, str_api, parent_id, fields):
'''
Function : find_folder_id
Description : This sends a couple of http request and authenticate the user
Parameters : 1 Parameter
test_set_path - ALM test set path
'''
for foldername in arrfolder:
payload = {"query": "{name['" + foldername + "'];parent-id[" + str(parent_id) + "]}",
"fields": fields}
response = self.alm_session.get(ALM_URL + ALM_MIDPOINT + "/" + str_api, params=payload)
obj = json.loads(response.text)
if obj["TotalResults"] >= 1:
parent_id = get_field_value(obj['entities'][0]['Fields'], "id")
# print("folder id of " + foldername + " is " + str(parent_id))
else:
# print("Folder " + foldername + " does not exists")
inputdata = dict()
inputdata['Type'] = str_api[0:len(str_api) - 1]
inputdata['name'] = foldername
inputdata['parent-id'] = str(parent_id)
data = generate_xml_data(inputdata)
response = self.alm_session.post(ALM_URL + ALM_MIDPOINT + "/" + str_api, data=data)
obj = json.loads(response.text)
if response.status_code == 200 | response.status_code == 201:
parent_id = get_field_value(obj['Fields'], "id")
# print("folder id of " + foldername + " is " + str(parent_id))
return response.text
Create Run Instance
Before updating the testing status, we must create a run instance for the test.
def create_run_instance(self, test_set_id, test_map):
'''
Function : create_run_instance
Description : Create new run instances
Parameters : Test Set Id
'''
str_api = "test-instances"
fields = "id,test-id,test-config-id,cycle-id"
payload = {"query": "{cycle-id['" + test_set_id + "']}", "fields": fields,
"page-size": 5000}
response = self.alm_session.get(ALM_URL + ALM_MIDPOINT + "/" + str_api, params=payload)
obj = json.loads(response.text)
run_instance_post = "<Entities>"
for entity in obj["entities"]:
run_name = re.sub('[-:]', '_',
'automation_' + datetime.datetime.fromtimestamp(time.time()).strftime(
'%Y-%m-%d %H:%M:%S'))
temp_map = create_key_value(entity["Fields"])
_test_id = int(temp_map['test-id'])
self.parser_temp_dic[_test_id]['testcycl-id'] = temp_map['id']
self.parser_temp_dic[_test_id]['test-config-id'] = temp_map['test-config-id']
self.parser_temp_dic[_test_id]['test-id'] = temp_map['test-id']
self.parser_temp_dic[_test_id]['cycle-id'] = temp_map['cycle-id']
# parser_temp_dic[int(temp_map['test-id'])]['status'].sort()
status = "Passed"
if 'Failed' in self.parser_temp_dic[int(temp_map['test-id'])]['status']:
status = 'Failed'
self.parser_temp_dic[int(temp_map['test-id'])]['final-status'] = status
inputdata = dict()
inputdata['Type'] = 'run'
inputdata['name'] = run_name
inputdata['owner'] = ALM_USER_NAME
inputdata['test-instance'] = str(1)
inputdata['testcycl-id'] = str(temp_map['id'])
inputdata['cycle-id'] = str(temp_map['cycle-id'])
inputdata['status'] = 'Not Completed'
inputdata['test-id'] = temp_map['test-id']
inputdata['subtype-id'] = 'hp.qc.run.MANUAL'
data = generate_xml_data(inputdata)
run_instance_post = run_instance_post + data
self.bulk_operation("runs", run_instance_post + "</Entities>", True, "POST")
return
Update Run Instance
def update_run_instance(self, test_set_id):
'''
Function : update_run_instance
Description : Update the test status in run instances
Parameters : No input parameter
'''
fields = "id,test-id"
payload = {"query": "{cycle-id['" + test_set_id + "']}", "fields": fields,
"page-size": 5000}
response = self.alm_session.get(ALM_URL + ALM_MIDPOINT + "/runs", params=payload)
obj = json.loads(response.text)
run_instance_put = "<Entities>"
for entity in obj["entities"]:
if len(entity["Fields"]) != 1:
temp_map = create_key_value(entity["Fields"])
self.parser_temp_dic[int(temp_map['test-id'])]['run-id'] = temp_map['id']
inputdata = dict()
inputdata['Type'] = 'run'
inputdata['id'] = str(temp_map['id'])
intermediate_ = self.parser_temp_dic[int(temp_map['test-id'])]['testcycl-id']
inputdata['testcycl-id'] = str(intermediate_)
inputdata['status'] = self.parser_temp_dic[int(temp_map['test-id'])]['final-status']
data = generate_xml_data(inputdata)
run_instance_put = run_instance_put + data
self.bulk_operation("runs", run_instance_put + "</Entities>", True, "PUT")
return
Upload Result File
Uploading file to any object in ALM
def upload_result_file(self, test_set_id, report_file):
'''
Function : upload_result_file
Description : Upload test result to ALM
'''
payload = open(report_file, 'rb')
headers = {}
headers['Content-Type'] = "application/octet-stream"
headers['slug'] = "test-results" + report_file[report_file.rfind(".")+1: ]
response = self.alm_session.post(ALM_URL + ALM_MIDPOINT + "/test-sets/" +
str(test_set_id) + "/attachments/",
headers=headers, data=payload)
if not (response.status_code == 200 or response.status_code == 201):
print "Attachment step failed!", response.text, response.url, response.status_code
return
Bulk Operation
This is a helper that allows us to POST an array of data.
def bulk_operation(self, str_api, data, isbulk, request_type):
'''
Function : Post Test Case / Test Instance
Description : Generic function to post multiple entities.
Parameters : 3 parameters
str_api - End point name
data - Actual data to post
isbulk - True or False
'''
response = None
headers = {}
try:
if isbulk:
headers['Content-Type'] = "application/xml;type = collection"
if request_type == 'POST':
response = self.alm_session.post(ALM_URL + ALM_MIDPOINT + "/" + str_api, data=data,
headers=headers)
elif request_type == 'PUT':
response = self.alm_session.put(ALM_URL + ALM_MIDPOINT + "/" + str_api, data=data,
headers=headers)
except Exception as err:
print err
if response.status_code == 200 | response.status_code == 201:
return response.text
return response
You can refer this code
https://github.com/arunprabusamy/Python-Libraries/blob/main/alm_RestAPI/almLib.py
You need to send only three values - Test Set ID (Cycle ID), ALM Test ID & Execution Status. The library automatically builds the json payload and creates a test run and update result.

Python when using "def" API - return nothing (or error)

I do not know how exactly to ask this question, as I can't share API access. If someone could help with the correct way of asking, will appreciate it.
I have a code which works perfectly fine and executes what I need, BUT when I use this API request code inside the DEF function, it returns with nothing or error...
The error is simple that I cannot get the output, or return with 0 values
This is the code:
def sm_main_data():
#DATA PROCESSING - Impression|Engagements|VideoViews
urlMain = "https://api.simplymeasured.com/v1/analytics/" + key.accountId + "/posts/metrics?\
filter=analytics.timeseries_key.gte(" + config.start + ").lte(" + config.end + ")&\
filter=channel.eq(" + config.which_social_media + ")&\
metrics=analytics.engagement_total,analytics.video.views_count,analytics.impressions&\
dimensions=data_source_id,channel,analytics.timeseries_key.by(" + config.per_what + ")"
headers = {'content-type': 'application/json',
'Authorization': 'Bearer ' + key.token}
#Receive data from SM (main data) / modified it and save as JSON file
responseMain = requests.get(urlMain, headers=headers).json()
pprint.pprint(responseMain)
pass
sm_main_data()
I have tried to print variables inside def:
print(key.accountId)
print(config.start)
print(config.end)
print(config.which_social_media)
print(config.per_what)
Which all printed correctly.
Currently I'm lost... and cannot get an even theoretical idea about what could go wrong. Why this code does not work inside def function???
Edit 1.0
Error
{u'errors': [{u'detail': u'` filter` parameter is not supported.,` metrics` parameter is not supported.,` dimensions` parameter is not supported.',
u'status': u'422',
u'title': u'Unprocessable Entity'}]}
Edit 1.1
Code without def
#DATA PROCESSING - Impression|Engagements|VideoViews
urlMain = "https://api.simplymeasured.com/v1/analytics/" + key.accountId + "/posts/metrics?\
filter=analytics.timeseries_key.gte(" + config.start + ").lte(" + config.end + ")&\
filter=channel.eq(" + config.which_social_media + ")&\
metrics=analytics.engagement_total,analytics.video.views_count,analytics.impressions&\
dimensions=data_source_id,channel,analytics.timeseries_key.by(" + config.per_what + ")"
headers = {'content-type': 'application/json',
'Authorization': 'Bearer ' + key.token}
#Receive data from SM (main data) / modified it and save as JSON file
responseMain = requests.get(urlMain, headers=headers).json()
pprint.pprint(responseMain)
The error shows you are trying to send parameters with extra spaces before them to the server:
` filter` parameter is not supported.
` metrics` parameter is not supported.
Those extra spaces before the names are part of the parameter name, because you included those in your string:
def sm_main_data():
# ...
urlMain = "https://api.simplymeasured.com/v1/analytics/" + key.accountId + "/posts/metrics?\
filter=analytics.timeseries_key.gte(" + config.start + ").lte(" + config.end + ")&\
filter=channel.eq(" + config.which_social_media + ")&\
metrics=analytics.engagement_total,analytics.video.views_count,analytics.impressions&\
dimensions=data_source_id,channel,analytics.timeseries_key.by(" + config.per_what + ")"
# ^^^ those lines are indented but the whitespace is part of the string
You would get the same problem if you had indented the urlMain string definition for any other reason, like for a if statement or a try...except statement, not just a function. You'd have to not indent those parts that are inside a string literal.
Rather than use \ continuations in the string, you could use separate string literals to create one long string, or end the string literal with a closing " followed by a + and a " opening quote on the next line:
urlMain = (
"https://api.simplymeasured.com/v1/analytics/" +
key.accountId + "/posts/metrics?" +
"filter=analytics.timeseries_key.gte(" + config.start + ").lte(" + config.end + ")&" +
"filter=channel.eq(" + config.which_social_media + ")&" +
"metrics=analytics.engagement_total,analytics.video.views_count,analytics.impressions&" +
"dimensions=data_source_id,channel,analytics.timeseries_key.by(" + config.per_what + ")"
)
All those + concatenations are not very readable, you should really use string formatting to insert values into a string.
However, you do not need to build a string like that anyway, as requests can do this for you when you give it a dictionary as the params argument. Use lists to pass in multiple values for a given parameter name:
url = "https://api.simplymeasured.com/v1/analytics/{k.accountId}/posts/metrics".format(
k=key)
params = {
'filter': [ # a list for multiple entries: filter=...&filter=...
'analytics.timeseries_key.gte({c.start}).lte({c.end})'.format(c=config),
'channel.eq({c.which_social_media})'.format(c=config),
],
'metrics': (
'analytics.engagement_total,analytics.video.views_count,'
'analytics.impressions'),
'dimensions':
'data_source_id,channel,'
'analytics.timeseries_key.by({c.per_what})'.format(c=config),
}
headers = {'Authorization': 'Bearer {k.token}'.format(k=key)}
responseMain = requests.get(urlMain, params=params, headers=headers).json()
Here I used str.format() to insert values from the config and key objects; note that the placeholders pull out the attributes
Note: I removed the Content-Type header, as that header doesn't apply to a GET request (which doesn't have content, the request body is always empty).

return and print in python

how can I return the output of the function print () in python? I have the following function
def read_image(raw_image_path):
raw_image_path = get_one_track()
with open (raw_image_path) as raw_image_file:
content = raw_image_file.readlines()
for content in itertools.islice(content,1,len(content)):
image_id = content.split()[0]
driver_id = content.split()[2]
camera_spec = content.split()[1] + content.split()[2]
image_spec = [image_id,driver_id,camera_spec]
image_folder_file = read_img_folders_file()[0]
cam_spec=read_img_folders_file()[1]
nb = read_img_folders_file()[2]
image_path=''
for i in range(nb-1):
if cam_spec[i]== image_spec[2]:
image_path=image_folder_file[i]+'/'
raw_image= image_path+str(image_id).zfill(10)+'.png'
#print (raw_image)
return (raw image)
The problem is that when I use print (raw_image) I become all the images I need like
/home/stereo_front_left/0000001756.png
/home/stereo_front_left/0000001757.png
/home/stereo_front_left/0000001758.png
but when I try the get them outside the function I become just the first one. What can I do?
If you want to have all the raw_image outside the loop, you would need to store them in a list or somewhere and then write "return all_raw_images".
all_raw_images = []
for content in itertools.islice(content,1,len(content)):
image_id = content.split()[0]
driver_id = content.split()[2]
camera_spec = content.split()[1] + content.split()[2]
image_spec = [image_id,driver_id,camera_spec]
image_folder_file = read_img_folders_file()[0]
cam_spec=read_img_folders_file()[1]
nb = read_img_folders_file()[2]
image_path=''
for i in range(nb-1):
if cam_spec[i]== image_spec[2]:
image_path=image_folder_file[i]+'/'
raw_image= image_path+str(image_id).zfill(10)+'.png'
all_raw_images.append(raw_image)
return (all_raw_images)
You don't need to make print() return.
It is a function, not a method, so it automatically returns.
Sorry if I misunderstood your question. :)

Trying to Optimize Python API read script

So I am creating a script to communicate to our API server for asset management and retrieve some information. I've found that the longest total time portion of the script is:
{method 'read' of '_ssl._SSLSocket' objects}
Currently we're pulling information about 25 assets or so and that specific portion is taking 18.89 seconds.
Is there any way to optimize this so it doesn't take 45 minutes to do all 2,700 computers we have?
I can provide a copy of the actual code if that would be helpful.
import urllib2
import base64
import json
import csv
# Count Number so that process only runs for 25 assets at a time will be
# replaced with a variable that is determined by the number of computers added
# to the list
Count_Stop = 25
final_output_list = []
def get_creds():
# Credentials Function that retrieves username:pw from .file
with open('.cred') as cred_file:
cred_string = cred_file.read().rstrip()
return cred_string
print(cred_string)
def get_all_assets():
# Function to retrieve computer ID + computer names and store the ID in a
# new list called computers_parsed
request = urllib2.Request('jss'
'JSSResource/computers')
creds = get_creds()
request.add_header('Authorization', 'Basic ' + base64.b64encode(creds))
response = urllib2.urlopen(request).read()
# At this point the request for ID + name has been retrieved and now to be
# formatted in json
parsed_ids_json = json.loads(response)
# Then assign the parsed list (which has nested lists) at key 'computers'
# to a new list variable called computer_set
computer_set = parsed_ids_json['computers']
# New list to store just the computer ID's obtained in Loop below
computer_ids = []
# Count variable, when equal to max # of computers in Count_stop it stops.
count = 0
# This for loop iterates over ID + name in computer_set and returns the ID
# to the list computer_ids
for computers in computer_set:
count += 1
computer_ids.append(computers['id'])
# This IF condition allows for the script to be tested at 25 assets
# instead of all 2,000+ (comment out other announce_all_assets call)
if count == Count_Stop:
announce_all_assets(computer_ids, count)
# announce_all_assets(computer_ids, count)
def announce_all_assets(computer_ids, count):
print('Final list of ID\'s for review: ' + str(computer_ids))
print('Total number of computers to check against JSS: ' +
str(count))
extension_attribute_request(computer_ids, count)
def extension_attribute_request(computer_ids, count):
# Creating new variable, first half of new URL used in loop to get
# extension attributes using the computer ID's in computers_ids
base_url = 'jss'
what_we_want = '/subset/extensionattributes'
creds = get_creds()
print('Extension attribute function starts now:')
for ids in computer_ids:
request_url = base_url + str(ids) + what_we_want
request = urllib2.Request(request_url)
request.add_header('Authorization', 'Basic ' + base64.b64encode(creds))
response = urllib2.urlopen(request).read()
parsed_ext_json = json.loads(response)
ext_att_json = parsed_ext_json['computer']['extension_attributes']
retrieve_all_ext(ext_att_json)
def retrieve_all_ext(ext_att_json):
new_computer = {}
# new_computer['original_id'] = ids['id']
# new_computer['original_name'] = ids['name']
for computer in ext_att_json:
new_computer[str(computer['name'])] = computer['value']
add_to_master_list(new_computer)
def add_to_master_list(new_computer):
final_output_list.append(new_computer)
print(final_output_list)
def main():
# Function to run the get all assets function
get_all_assets()
if __name__ == '__main__':
# Function to run the functions in order: main > get all assets >
main()
I'd _highly recommend using the 'requests' module over 'urllib2'. It handles a lot of stuff for you and will save you many a headache.
I believe it will also give you better performance, but I'd love to hear your feedback.
Here's your code using requests. (I've added newlines to highlight my changes. Note the built-in .json() decoder.):
# Requires requests module be installed.:
# `pip install requests` or `pip3 install requests`
# https://pypi.python.org/pypi/requests/
import requests
import base64
import json
import csv
# Count Number so that process only runs for 25 assets at a time will be
# replaced with a variable that is determined by the number of computers added
# to the list
Count_Stop = 25
final_output_list = []
def get_creds():
# Credentials Function that retrieves username:pw from .file
with open('.cred') as cred_file:
cred_string = cred_file.read().rstrip()
return cred_string
print(cred_string)
def get_all_assets():
# Function to retrieve computer ID + computer names and store the ID in a
# new list called computers_parsed
base_url = 'jss'
what_we_want = 'JSSResource/computers'
request_url = base_url + what_we_want
# NOTE the request_url is constructed based on your request assignment just below.
# As such, it is malformed as a URL, and I assume anonymized for your posting on SO.
# request = urllib2.Request('jss'
# 'JSSResource/computers')
#
creds = get_creds()
headers={
'Authorization': 'Basic ' + base64.b64encode(creds),
}
response = requests.get( request_url, headers )
parsed_ids_json = response.json()
#[NO NEED FOR THE FOLLOWING. 'requests' HANDLES DECODES JSON. SEE ABOVE ASSIGNMENT.]
# At this point the request for ID + name has been retrieved and now to be
# formatted in json
# parsed_ids_json = json.loads(response)
# Then assign the parsed list (which has nested lists) at key 'computers'
# to a new list variable called computer_set
computer_set = parsed_ids_json['computers']
# New list to store just the computer ID's obtained in Loop below
computer_ids = []
# Count variable, when equal to max # of computers in Count_stop it stops.
count = 0
# This for loop iterates over ID + name in computer_set and returns the ID
# to the list computer_ids
for computers in computer_set:
count += 1
computer_ids.append(computers['id'])
# This IF condition allows for the script to be tested at 25 assets
# instead of all 2,000+ (comment out other announce_all_assets call)
if count == Count_Stop:
announce_all_assets(computer_ids, count)
# announce_all_assets(computer_ids, count)
def announce_all_assets(computer_ids, count):
print('Final list of ID\'s for review: ' + str(computer_ids))
print('Total number of computers to check against JSS: ' +
str(count))
extension_attribute_request(computer_ids, count)
def extension_attribute_request(computer_ids, count):
# Creating new variable, first half of new URL used in loop to get
# extension attributes using the computer ID's in computers_ids
base_url = 'jss'
what_we_want = '/subset/extensionattributes'
creds = get_creds()
print('Extension attribute function starts now:')
for ids in computer_ids:
request_url = base_url + str(ids) + what_we_want
headers={
'Authorization': 'Basic ' + base64.b64encode(creds),
}
response = requests.get( request_url, headers )
parsed_ext_json = response.json()
ext_att_json = parsed_ext_json['computer']['extension_attributes']
retrieve_all_ext(ext_att_json)
def retrieve_all_ext(ext_att_json):
new_computer = {}
# new_computer['original_id'] = ids['id']
# new_computer['original_name'] = ids['name']
for computer in ext_att_json:
new_computer[str(computer['name'])] = computer['value']
add_to_master_list(new_computer)
def add_to_master_list(new_computer):
final_output_list.append(new_computer)
print(final_output_list)
def main():
# Function to run the get all assets function
get_all_assets()
if __name__ == '__main__':
# Function to run the functions in order: main > get all assets >
main()
Please do let me know the relative performance time with your 25 assets in 18.89 seconds! I'm very curious.
I'd still recommend my other answer below(?) regarding the use of the requests module from a pure cleanliness perspective (requests is very clean to work with), but I recognize it may or may not address your original question.
If you want to try PyCurl, which likely will impact your original question, here's the same code implemented with that approach:
# Requires pycurl module be installed.:
# `pip install pycurl` or `pip3 install pycurl`
# https://pypi.python.org/pypi/pycurl/7.43.0
# NOTE: The syntax used herein for pycurl is python 3 compliant.
# Not python 2 compliant.
import pycurl
import base64
import json
import csv
def pycurl_data( url, headers ):
buffer = BytesIO()
connection = pycurl.Curl()
connection.setopt( connection.URL, url )
connection.setopt(pycurl.HTTPHEADER, headers )
connection.setopt( connection.WRITEDATA, buffer )
connection.perform()
connection.close()
body = buffer.getvalue()
# NOTE: The following assumes a byte string and a utf8 format. Change as desired.
return json.loads( body.decode('utf8') )
# Count Number so that process only runs for 25 assets at a time will be
# replaced with a variable that is determined by the number of computers added
# to the list
Count_Stop = 25
final_output_list = []
def get_creds():
# Credentials Function that retrieves username:pw from .file
with open('.cred') as cred_file:
cred_string = cred_file.read().rstrip()
return cred_string
print(cred_string)
def get_all_assets():
# Function to retrieve computer ID + computer names and store the ID in a
# new list called computers_parsed
base_url = 'jss'
what_we_want = 'JSSResource/computers'
request_url = base_url + what_we_want
# NOTE the request_url is constructed based on your request assignment just below.
# As such, it is malformed as a URL, and I assume anonymized for your posting on SO.
# request = urllib2.Request('jss'
# 'JSSResource/computers')
#
creds = get_creds()
headers= [ 'Authorization: Basic ' + base64.b64encode(creds) ]
response = pycurl_data( url, headers )
# At this point the request for ID + name has been retrieved and now to be
# formatted in json
parsed_ids_json = json.dumps( response )
# Then assign the parsed list (which has nested lists) at key 'computers'
# to a new list variable called computer_set
computer_set = parsed_ids_json['computers']
# New list to store just the computer ID's obtained in Loop below
computer_ids = []
# Count variable, when equal to max # of computers in Count_stop it stops.
count = 0
# This for loop iterates over ID + name in computer_set and returns the ID
# to the list computer_ids
for computers in computer_set:
count += 1
computer_ids.append(computers['id'])
# This IF condition allows for the script to be tested at 25 assets
# instead of all 2,000+ (comment out other announce_all_assets call)
if count == Count_Stop:
announce_all_assets(computer_ids, count)
# announce_all_assets(computer_ids, count)
def announce_all_assets(computer_ids, count):
print('Final list of ID\'s for review: ' + str(computer_ids))
print('Total number of computers to check against JSS: ' +
str(count))
extension_attribute_request(computer_ids, count)
def extension_attribute_request(computer_ids, count):
# Creating new variable, first half of new URL used in loop to get
# extension attributes using the computer ID's in computers_ids
base_url = 'jss'
what_we_want = '/subset/extensionattributes'
creds = get_creds()
print('Extension attribute function starts now:')
for ids in computer_ids:
request_url = base_url + str(ids) + what_we_want
headers= [ 'Authorization: Basic ' + base64.b64encode(creds) ]
response = pycurl_data( url, headers )
parsed_ext_json = json.dumps( response )
ext_att_json = parsed_ext_json['computer']['extension_attributes']
retrieve_all_ext(ext_att_json)
def retrieve_all_ext(ext_att_json):
new_computer = {}
# new_computer['original_id'] = ids['id']
# new_computer['original_name'] = ids['name']
for computer in ext_att_json:
new_computer[str(computer['name'])] = computer['value']
add_to_master_list(new_computer)
def add_to_master_list(new_computer):
final_output_list.append(new_computer)
print(final_output_list)
def main():
# Function to run the get all assets function
get_all_assets()
if __name__ == '__main__':
# Function to run the functions in order: main > get all assets >
main()

Categories

Resources