I am trying to get the output in below nested dictionary format for the given input - python-3.x

I am trying to get the output in the form of nested dictionary. I am practicing this for python automation for Network simulator. I tried but not able to achieve. Kindly someone help me on this.
Interface IP-Address OK? Method Status Protocol
Vlan1 unassigned YES NVRAM up up
Vlan30 30.1.1.2 YES NVRAM up up
Vlan306 192.168.25.3 YES NVRAM up down
GigabitEthernet0/0 11.19.17.19 YES NVRAM up up
Te1/0/3 unassigned YES unset up up
Te1/0/21 unassigned YES unset up up
Te1/0/35 unassigned YES unset up up
output should be in below format.
{'interface': {
'vlan1': {
'name': 'vlan1',
'ip': 'unassigned',
'ok_status': 'YES',
'method': 'NVRAM',
'status': 'up',
'protocol': 'up',
},
'vlan30': {
'name': 'vlan30',
'ip': '30.1.1.2',
'ok_status': 'YES',
'method': 'NVRAM',
'status': 'up',
'protocol': 'up',
}
}
}

If you place your input data in a text file (example D:/test.txt), following code will format it according to your specification:
comma_sep = ""
with open("D:/test.txt") as f:
for line in f:
parts = [part for part in line.split(' ') if part != '']
comma_sep += ','.join(parts)
lines = [item for item in comma_sep.split('\n')]
output_dict = {"interface": {}}
for index, line in enumerate(lines):
if index == 0:
continue
# Compose each interface
interface = {}
for item_index, item in enumerate(line.split(',')):
if item_index == 0:
item = item.lower()
interface = {item: {}}
interface[item].update({'name': item})
main_key = item
elif item_index == 1:
interface[main_key].update({'ip': item})
elif item_index == 2:
interface[main_key].update({'ok_status': item})
elif item_index == 3:
interface[main_key].update({'method': item})
elif item_index == 4:
interface[main_key].update({'status': item})
elif item_index == 5:
interface[main_key].update({'protocol': item})
output_dict["interface"].update(interface)
print(output_dict)

Related

Unique nested dictionary from the 'for' loop Python3

I've got the host which executes commands via 'subprocess' and gets output list of several parameters. The problem is that output can not be correctly modified to be translated to the dictionary, whether it's yaml or json. After list is received Regexp takes part to match valuable information and to perform grouping. I am interested in getting a unique dictionary, where crossing keys are put into nested dictionary.
Here is the code and the example of output list:
from re import compile,match
# Output can differ from request to request, the "keys" from the #
# list_of_values can dublicate or appear more than two times. The values #
# mapped to the keys can differ too. #
list_of_values = [
"paramId: '11'", "valueId*: '11'",
"elementId: '010_541'", 'mappingType: Both',
"startRng: ''", "finishRng: ''",
'DbType: sql', "activeSt: 'false'",
'profile: TestPr1', "specificHost: ''",
'hostGroup: tstGroup10', 'balance: all',
"paramId: '194'", "valueId*: '194'",
"elementId: '010_541'", 'mappingType: Both',
"startRng: '1020304050'", "finishRng: '1020304050'",
'DbType: sql', "activeSt: 'true'",
'profile: TestPr1', "specificHost: ''",
'hostGroup: tstGroup10', 'balance: all']
re_compile_valueId = compile(
"valueId\*:\s.(?P<valueId>\d{1,5})"
"|elementId:\s.(?P<elementId>\d{3}_\d{2,3})"
"|startRng:\s.(?P<startRng>\d{1,10})"
"|finishRng:\s.(?P<finishRng>\d{1,10})"
"|DbType:\s(?P<DbType>nosql|sql)"
"|activeSt:\s.(?P<activeSt>true|false)"
"|profile:\s(?P<profile>[A-z0-9]+)"
"|hostGroup:\s(?P<hostGroup>[A-z0-9]+)"
"|balance:\s(?P<balance>none|all|priority group)"
)
iterator_loop = 0
uniq_dict = dict()
next_dict = dict()
for element in list_of_values:
match_result = match(re_compile_valueId,element)
if match_result:
temp_dict = match_result.groupdict()
for key, value in temp_dict.items():
if value:
if key == 'valueId':
uniq_dict['valueId'+str(iterator_loop)] = ''
iterator_loop +=1
next_dict.update({key: value})
else:
next_dict.update({key: value})
uniq_dict['valueId'+str(iterator_loop-1)] = next_dict
print(uniq_dict)
This code right here responses with:
{
'valueId0':
{
'valueId': '194',
'elementId': '010_541',
'DbType': 'sql',
'activeSt': 'true',
'profile': 'TestPr1',
'hostGroup': 'tstGroup10',
'balance': 'all',
'startRng': '1020304050',
'finishRng': '1020304050'
},
'valueId1':
{
'valueId': '194',
'elementId': '010_541',
'DbType': 'sql',
'activeSt': 'true',
'profile': 'TestPr1',
'hostGroup': 'tstGroup10',
'balance': 'all',
'startRng': '1020304050',
'finishRng': '1020304050'
}
}
And I was waiting for something like:
{
'valueId0':
{
'valueId': '11',
'elementId': '010_541',
'DbType': 'sql',
'activeSt': 'false',
'profile': 'TestPr1',
'hostGroup': 'tstGroup10',
'balance': 'all',
'startRng': '',
'finishRng': ''
},
'valueId1':
{
'valueId': '194',
'elementId': '010_541',
'DbType': 'sql',
'activeSt': 'true',
'profile': 'TestPr1',
'hostGroup': 'tstGroup10',
'balance': 'all',
'startRng': '1020304050',
'finishRng': '1020304050'
}
}
I've also got another code below, which runs and puts values as expected. But the structure breaks the idea of having this all looped around, because each dictionary result key has its own order number mapped. The example below. The list_of_values and re_compile_valueId can be used from previous example.
for element in list_of_values:
match_result = match(re_compile_valueId,element)
if match_result:
temp_dict = match_result.groupdict()
for key, value in temp_dict.items():
if value:
if key == 'balance':
key = key+str(iterator_loop)
uniq_dict.update({key: value})
iterator_loop +=1
else:
key = key+str(iterator_loop)
uniq_dict.update({key: value})
print(uniq_dict)
The output will look like:
{
'valueId1': '11', 'elementId1': '010_541',
'DbType1': 'sql', 'activeSt1': 'false',
'profile1': 'TestPr1', 'hostGroup1': 'tstGroup10',
'balance1': 'all', 'valueId2': '194',
'elementId2': '010_541', 'startRng2': '1020304050',
'finishRng2': '1020304050', 'DbType2': 'sql',
'activeSt2': 'true', 'profile2': 'TestPr1',
'hostGroup2': 'tstGroup10', 'balance2': 'all'
}
Would appreciate any help! Thanks!
It appeared that some documentation reading needs to be performed :D
The copy() of the next_dict under else statement needs to be applied. Thanks to thread:
Why does updating one dictionary object affect other?
Many thanks to answer's author #thefourtheye (https://stackoverflow.com/users/1903116/thefourtheye)
The final code:
for element in list_of_values:
match_result = match(re_compile_valueId,element)
if match_result:
temp_dict = match_result.groupdict()
for key, value in temp_dict.items():
if value:
if key == 'valueId':
uniq_dict['valueId'+str(iterator_loop)] = ''
iterator_loop +=1
next_dict.update({key: value})
else:
next_dict.update({key: value})
uniq_dict['valueId'+str(iterator_loop-1)] = next_dict.copy()
Thanks for the involvement to everyone.

How to fetch the action value from AWS policy document and store it as list?

I need to fetch "Action" values from the AWS policy document.
In some policies, the action values are having a list of values(like Policy 1) and in some policies, the action is having a single value which is a string (like Policy 2).
What I need is:
I want to get the action value from the policy and store it as a list.
(Here, Policy 1 is giving expected output but policy 2 is failing.)
Policy 1:
document_values:
[{'Version': '2012-10-17', 'Statement': [{'Sid': 'VisualEditor0', 'Effect': 'Allow', 'Action': ['iam:CreateInstanceProfile', 'iam:DeleteInstanceProfile', 'iam:GetRole', 'iam:GetInstanceProfile', 'iam:GetPolicy', 'iam:ListGroupPolicies', 'iam:GetAccessKeyLastUsed'],'Resource': ['arn:aws:iam::*:policy/*','arn:aws:iam::*:instance-profile/*']}, {'Sid': 'VisualEditor1', 'Effect': 'Allow', 'Action': ['iam:ListPolicies', 'iam:ListRoles', 'iam:ListGroups'],'Resource': '*'}]}]
Output - Policy 1:
['iam:CreateInstanceProfile', 'iam:DeleteInstanceProfile', 'iam:GetRole', 'iam:GetInstanceProfile', 'iam:GetPolicy', 'iam:ListGroupPolicies', 'iam:GetAccessKeyLastUsed','iam:ListPolicies', 'iam:ListRoles', 'iam:ListGroups']
Policy 2:
document_values:
[{'Version': '2012-10-17', 'Statement': [{'Sid': 'VisualEditor0', 'Effect': 'Allow', 'Action': 'sts:AssumeRole', 'Resource':'*"}]}]
Output-Policy2:
['s', 't', 's', ':', 'A', 's', 's', 'u', 'm', 'e', 'R', 'o', 'l', 'e']
Expected output from policy2:
['sts:AsseumeRole']
Python-Code:
I'm executing the same code for both the policies.
inline_services = [j for i in [i['Action'] for i in document_values[0]['Statement']] for j in i]
print(inline_services)
How to fetch the action value from the policy document irrespective of string or list..?
Instead of writing long list comprehension, you could just create simple function:
p1 = [{'Version': '2012-10-17', 'Statement': [{'Sid': 'VisualEditor0', 'Effect': 'Allow', 'Action': ['iam:CreateInstanceProfile', 'iam:DeleteInstanceProfile', 'iam:GetRole', 'iam:GetInstanceProfile', 'iam:GetPolicy', 'iam:ListGroupPolicies', 'iam:GetAccessKeyLastUsed'],'Resource': ['arn:aws:iam::*:policy/*','arn:aws:iam::*:instance-profile/*']}, {'Sid': 'VisualEditor1', 'Effect': 'Allow', 'Action': ['iam:ListPolicies', 'iam:ListRoles', 'iam:ListGroups'],'Resource': '*'}]}]
p2 = [{'Version': '2012-10-17', 'Statement': [{'Sid': 'VisualEditor0', 'Effect': 'Allow', 'Action': 'sts:AssumeRole', 'Resource':'*'}]}]
def get_actions(policy_doc):
actions_list = []
for i in policy_doc[0]['Statement']:
actions_list += i['Action'] if isinstance(i['Action'], list) else [i['Action']]
return actions_list
print(get_actions(p1))
print(get_actions(p2))
Output:
['iam:CreateInstanceProfile', 'iam:DeleteInstanceProfile', 'iam:GetRole', 'iam:GetInstanceProfile', 'iam:GetPolicy', 'iam:ListGroupPolicies', 'iam:GetAccessKeyLastUsed', 'iam:ListPolicies', 'iam:ListRoles', 'iam:ListGroups']
['sts:AssumeRole']

Flask TypeError: argument of type 'NoneType' is not iterable

I am not sure why I am getting this TypeError:
File "C:/Users/PycharmProjects/REST/app.py", line 30, in
valid_book_object
if ("isbn" in book and "name" in book and "price" in book):
TypeError: argument of type 'NoneType' is not iterable
127.0.0.1 - - [12/Nov/2018 14:22:29] "POST /books HTTP/1.1" 500 -
Code:
from flask import Flask, jsonify, request
from test import *
app=Flask(__name__)
books=[
{'name': 'M',
'price': 6.75,
'isbn':123
},
{'name': 'G',
'price': 7.75,
'isbn':456
},
]
#GET /store
#app.route('/books') #first endpoint
def get_books():
return jsonify({'books': books})
# POST /books
#{'name': 'F',
#'price': 7.00,
#'isbn': 789
#},
def valid_book_object(book):
if ("isbn" in book and "name" in book and "price" in book):
return True
print("true")
else:
return False
print("false")
#app.route('/books', methods=['POST'])
def add_book():
#return jsonify(request.get_json())
request_data=request.get_json()
if(valid_book_object(request_data)):
books.insert(0, request_data)
return "True"
else:
return "False"
#GET /books/456
#app.route('/books/<int:isbn>') #second endpoint
def get_book_by_isbn(isbn):
return_value={}
for book in books:
if book["isbn"]==isbn:
return_value={
'name': book["name"],
'price':book["price"]
}
return jsonify(return_value)
app.run(port=5000)
You are not sending JSON data to /books route using POST method.
I tried your solution with postman and it worked. Also, if you want to use some route for GET and POST, don't split them. Use methods=['GET', 'POST']. Here is your code reformatted with PEP 8 standard:
from flask import Flask, jsonify, request
app = Flask(__name__)
books = [
{'name': 'M',
'price': 6.75,
'isbn': 123
},
{'name': 'G',
'price': 7.75,
'isbn': 456
}
]
# POST /books
# {
# "name": "F",
# "price": 7.00,
# "isbn": 789
# }
def valid_book_object(book):
if "isbn" in book and "name" in book and "price" in book:
return True
else:
return False
#app.route('/books', methods=['GET', 'POST'])
def add_book():
# If request is GET, just return JSON data of books.
if request.method == 'GET':
return jsonify({'books': books})
else:
# This is part if it is POST request
request_data = request.get_json()
if valid_book_object(request_data):
books.insert(0, request_data)
return "True"
else:
return "False"
# GET /books/456
#app.route('/books/<int:isbn>') # second endpoint
def get_book_by_isbn(isbn):
return_value = {}
for book in books:
if book["isbn"] == isbn:
return_value = {
'name': book["name"],
'price': book["price"]
}
return jsonify(return_value)
return 'No book with {} isbn value'.format(isbn)
if __name__ == '__main__':
app.run(port=5000)
And here is the output from postman (you can see True at the bottom, that is what you return if POST was successful):
If you use postman, be sure to select application/json content-type.
If you are using JQuery ajax method, please read this answer. But anyway, here is using JQuery (tested):
data = JSON.stringify({
name: "F",
price: 7.00,
isbn: 789
});
$.ajax({
url: '/books',
type: "POST",
data: data,
contentType: "application/json",
dataType: "json",
success: function(){
console.log('Post executed successfully');
}
})

how to make parse of list(string) not list(char) in parse argument of list?

I use flask_restful in flask
My code like:
from flask_restful import Resource, reqparse
apilink_parser = reqparse.RequestParser()
apilink_parser.add_argument('provider_id', type=int,required=True)
apilink_parser.add_argument('name', type=str, required=True)
apilink_parser.add_argument('func_id', type=int)
apilink_parser.add_argument('method', type=str)
apilink_parser.add_argument('url', type=str)
apilink_parser.add_argument('parameter',type=list)
apilink_parser.add_argument("expectreturn", type=list)
#marshal_with(apilink_fields)
def post(self):
args = apilink_parser.parse_args()
print(args)
# user owns the task
task = APILink.create(**args)
return task, 201
My json post data like:
{
"name":"riskiqwhois",
"provider_id":1,
"func_id":1,
"url":"myurl",
"parameter":["query"], //******//
"expectreturn":[],
"method":"post"
}
but when I print the arrgs the result is:
{
'provider_id': 1,
'name': 'riskiqwhois',
'func_id': 1,
'method': 'post',
'url': 'myurl',
'parameter': ['q', 'u', 'e', 'r', 'y'], //******//
'expectreturn': None
}
I want
You can see I want parameter is list of string which is only one element named "query", but the real parameter tranlate into the database is ['q', 'u', 'e', 'r', 'y'], How to make the parameter is list of string not list of char? how to make sure the data is list(string)?
Well, you forgot to set action="append" and you should change from type=list to type=str.
If not, you will still be getting a result like [['q', 'u', 'e', 'r', 'y']].
...
apilink_parser.add_argument('parameter',type=str, action='append')
apilink_parser.add_argument("expectreturn", type=str, action='append')
You can solve this problem by adding action="append" to your request parser
like below
apilink_parser.add_argument('parameter',type=str,action="append")
apilink_parser.add_argument("expectreturn", type=list,action="append")
this will return you below output
{
'provider_id': 1,
'name': 'riskiqwhois',
'func_id': 1,
'method': 'post',
'url': 'myurl',
'parameter': ['query'],
'expectreturn': None
}

Getting tags from python 3 dictionary object. AWS Boto3 Python 3

I have a dictionary object that is being returned to me from AWS. I need to pull the tag "based_on_ami" out of this dictionary. I have tried converting to a list, but I am new to programming and have not been able to figure out how to access Tags since they are a few levels down in the dictionary.
What is the best way for me to pull that tag out of the dictionary and put it into a variable i can use?
{
'Images':[
{
'Architecture':'x86_64',
'CreationDate':'2017-11-27T14:41:30.000Z',
'ImageId':'ami-8e73e0f4',
'ImageLocation':'23452345234545/java8server_ubuntu16-2b71edd1-f95e-4ee5-8fd6-d8a46975fdb5',
'ImageType':'machine',
'Public':False,
'OwnerId':'23452345234545',
'State':'available',
'BlockDeviceMappings':[
{
'DeviceName':'/dev/sda1',
'Ebs':{
'Encrypted':False,
'DeleteOnTermination':True,
'SnapshotId':'snap-0c10e8f5ced5b5240',
'VolumeSize':8,
'VolumeType':'gp2'
}
},
{
'DeviceName':'/dev/sdb',
'VirtualName':'ephemeral0'
},
{
'DeviceName':'/dev/sdc',
'VirtualName':'ephemeral1'
}
],
'EnaSupport':True,
'Hypervisor':'xen',
'Name':'java8server_ubuntu16-2b71edd1-f95e-4ee5-8fd6-d8a46975fdb5',
'RootDeviceName':'/dev/sda1',
'RootDeviceType':'ebs',
'SriovNetSupport':'simple',
'Tags':[
{
'Key':'service',
'Value':'baseami'
},
{
'Key':'cloudservice',
'Value':'ami'
},
{
'Key':'Name',
'Value':'java8server_ubuntu16-2b71edd1-f95e-4ee5-8fd6-d8a46975fdb5'
},
{
'Key':'os',
'Value':'ubuntu 16.04 lts'
},
{
'Key':'based_on_ami',
'Value':'ami-aa2ea8d0'
}
],
'VirtualizationType':'hvm'
}
],
'ResponseMetadata':{
'RequestId':'2c376c75-c31f-4aba-a058-173f3b125a00',
'HTTPStatusCode':200,
'HTTPHeaders':{
'content-type':'text/xml;charset=UTF-8',
'transfer-encoding':'chunked',
'vary':'Accept-Encoding',
'date':'Fri, 01 Dec 2017 18:17:53 GMT',
'server':'AmazonEC2'
},
'RetryAttempts':0
}
}
The best way to approach this type of problem is to find the value you're looking for, and then work outwards until you find a solution. You need to look at what is at each of those levels.
So, what are you looking for? You're looking for the Value for based_on_ami's Key. So your final step is going to be:
if obj['Key'] == 'based_on_ami':
# do something with obj['Value'].
But how do you get there? Well, the object is inside of a list, so you'll need to iterate the list:
for tag in <some list>:
if tag['Key'] == 'based_on_ami':
# do something with tag['Value'].
What is that list? It's the list of tags:
for tag in image['Tags']:
if tag['Key'] == 'based_on_ami':
# do something with tag['Value'].
And where are those tags? In an image object that you find in a list:
for image in image_list:
for tag in image['Tags']:
if tag['Key'] == 'based_on_ami':
# do something with tag['Value'].
The image list is the value found at the Images key in your initial dict.
image_list = my_data['Images']
for image in image_list:
for tag in image['Tags']:
if tag['Key'] == 'based_on_ami':
# do something with tag['Value'].
And now you're collecting all of those values, so you'll need a list and you'll need to append to it:
result = []
image_list = my_data['Images']
for image in image_list:
for tag in image['Tags']:
if tag['Key'] == 'based_on_ami':
result.append(tag['Value'])
So, I took your example above, and added another based_on_ami node with the value quack:
{'ResponseMetadata': {'RequestId': '2c376c75-c31f-4aba-a058-173f3b125a00', 'RetryAttempts': 0, 'HTTPHeaders': {'vary': 'Accept-Encoding', 'transfer-encoding': 'chunked', 'server': 'AmazonEC2', 'content-type': 'text/xml;charset=UTF-8', 'date': 'Fri, 01 Dec 2017 18:17:53 GMT'}, 'HTTPStatusCode': 200}, 'Images': [{'Public': False, 'CreationDate': '2017-11-27T14:41:30.000Z', 'BlockDeviceMappings': [{'Ebs': {'SnapshotId': 'snap-0c10e8f5ced5b5240', 'VolumeSize': 8, 'Encrypted': False, 'VolumeType': 'gp2', 'DeleteOnTermination': True}, 'DeviceName': '/dev/sda1'}, {'VirtualName': 'ephemeral0', 'DeviceName': '/dev/sdb'}, {'VirtualName': 'ephemeral1', 'DeviceName': '/dev/sdc'}], 'OwnerId': '23452345234545', 'ImageLocation': '23452345234545/java8server_ubuntu16-2b71edd1-f95e-4ee5-8fd6-d8a46975fdb5', 'RootDeviceName': '/dev/sda1', 'ImageType': 'machine', 'Hypervisor': 'xen', 'RootDeviceType': 'ebs', 'State': 'available', 'Architecture': 'x86_64', 'Name': 'java8server_ubuntu16-2b71edd1-f95e-4ee5-8fd6-d8a46975fdb5', 'Tags': [{'Value': 'baseami', 'Key': 'service'}, {'Value': 'ami', 'Key': 'cloudservice'}, {'Value': 'java8server_ubuntu16-2b71edd1-f95e-4ee5-8fd6-d8a46975fdb5', 'Key': 'Name'}, {'Value': 'ubuntu 16.04 lts', 'Key': 'os'}, {'Value': 'ami-aa2ea8d0', 'Key': 'based_on_ami'}], 'EnaSupport': True, 'SriovNetSupport': 'simple', 'ImageId': 'ami-8e73e0f4'}, {'Public': False, 'CreationDate': '2017-11-27T14:41:30.000Z', 'BlockDeviceMappings': [{'Ebs': {'SnapshotId': 'snap-0c10e8f5ced5b5240', 'VolumeSize': 8, 'Encrypted': False, 'VolumeType': 'gp2', 'DeleteOnTermination': True}, 'DeviceName': '/dev/sda1'}, {'VirtualName': 'ephemeral0', 'DeviceName': '/dev/sdb'}, {'VirtualName': 'ephemeral1', 'DeviceName': '/dev/sdc'}], 'VirtualizationType': 'hvm', 'OwnerId': '23452345234545', 'ImageLocation': '23452345234545/java8server_ubuntu16-2b71edd1-f95e-4ee5-8fd6-d8a46975fdb5', 'RootDeviceName': '/dev/sda1', 'ImageType': 'machine', 'Hypervisor': 'xen', 'RootDeviceType': 'ebs', 'State': 'available', 'Architecture': 'x86_64', 'Name': 'java8server_ubuntu16-2b71edd1-f95e-4ee5-8fd6-d8a46975fdb5', 'Tags': [{'Value': 'baseami', 'Key': 'service'}, {'Value': 'ami', 'Key': 'cloudservice'}, {'Value': 'java8server_ubuntu16-2b71edd1-f95e-4ee5-8fd6-d8a46975fdb5', 'Key': 'Name'}, {'Value': 'ubuntu 16.04 lts', 'Key': 'os'}, {'Value': 'quack', 'Key': 'based_on_ami'}], 'EnaSupport': True, 'SriovNetSupport': 'simple', 'ImageId': 'ami-8e73e0f4'}]}
My result:
['ami-aa2ea8d0', 'quack']
info = {...}
tags = []
for image in info['Images']:
for tag in image['Tags']:
if tag['Key'] == 'based_on_ami':
tags.append(tag['Value'])
print(tags)

Resources