Python values not getting added to Tuple - python

Hello I have a situation where I am trying to make a filter in my code customizable so there is minimum duplication of code below is the code that I want to update
for ent in NACLS:
response = ec2.describe_network_acls(Filters=[{'Name': 'network-acl-id', 'Values': [naclID]},
{'Name': 'entry.rule-number', 'Values': [str(ent[0])]},
{'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]},
{'Name': 'entry.port-range.from', 'Values': [str(ent[2])]},
{'Name': 'entry.port-range.to', 'Values': [str(ent[2])]},
{'Name': 'entry.rule-action', 'Values': ["deny"]},
])
I want the filter to customizable for example
for ent in NACLS:
if add = True:
response = ec2.describe_network_acls(Filters=[{'Name': 'network-acl-id', 'Values': [naclID]},
{'Name': 'entry.rule-number', 'Values': [str(ent[0])]},
])
else:
response = ec2.describe_network_acls(Filters=[{'Name': 'network-acl-id', 'Values': [naclID]},
{'Name': 'entry.rule-number', 'Values': [str(ent[0])]},
{'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]},
{'Name': 'entry.port-range.from', 'Values': [str(ent[2])]},
{'Name': 'entry.port-range.to', 'Values': [str(ent[2])]},
{'Name': 'entry.rule-action', 'Values': ["deny"]},
])
This is what I was wanting to do but doesn't work please let me know if there is a better way to achieve this
for ent in NACLS:
filters = {'Name': 'network-acl-id', 'Values': [naclID]}, {'Name': 'entry.rule-number', 'Values': [str(ent[0])]}
filters = filters + tuple({'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]}) //we can add more but this was just to test
print(str(filters)[1:-1])
The output for this is -
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540']}, {'Name': 'entry.rule-number', 'Values': ['80']}, 'Name', 'Values'
When I try to add the value in tuple it shows as blank can someone please guide me on what I am doing wrong here?

I suspect that by adding tuples, you meant to add the dictionary to the tuple of filters, which is not what you are doing in your current script. I suggest that you replace
filters = filters + tuple({'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]})
with
filters = filters + ({'Name': 'entry.protocol', 'Values': [ProtoDict[ent[1]]]},)

Related

Python dictionary not getting updated

Hello I have below code where I am trying to add elements to a dict
for ent in NACLS:
set_filter = {'Name': 'network-acl-id', 'Values': [naclID]}
print(set_filter)
set_filter.update({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter)
The output for the above code is
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}
{'Name': 'entry.rule-number', 'Values': ['50']}
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}
{'Name': 'entry.rule-number', 'Values': ['60']}
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}
{'Name': 'entry.rule-number', 'Values': ['70']}
Whereas I was wanting it to update the existing dictionary but somehow it's getting overwritten. Expected output
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}, {'Name': 'entry.rule-number', 'Values': ['50']}
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}, {'Name': 'entry.rule-number', 'Values': ['60']}
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}, {'Name': 'entry.rule-number', 'Values': ['70']}
can someone please guide me on how I can achieve this?
The update method adds {key:value} pairs to a dictionary unless the key already exists, in which case it just updates the value to the new value.
From the look of your expected output it seems you want a list of dictionaries all with the same keys but different values.
try this:
set_filter = []
for ent in NACLS:
set_filter.append({'Name': 'network-acl-id', 'Values': [naclID]})
set_filter.append({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter)
I didn't understand what is the problem here. Do you want to print these dicts like you expected ?
You can write :
for ent in NACLS:
set_filter = {'Name': 'network-acl-id', 'Values': [naclID]}
print(set_filter,end=",")
set_filter.update({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter,end="\n")
The expected output example isn't a valid dictionary:
{'Name': 'network-acl-id', 'Values': ['acl-08128a2540eb']}, {'Name': 'entry.rule-number', 'Values': ['50']}
Reformatted:
{
'Name': 'network-acl-id',
'Values': [ 'acl-08128a2540eb' ]
},
{
'Name': 'entry.rule-number',
'Values': [ '50' ]
}
To create a list of dictionaries:
for ent in NACLS:
set_filter = [{'Name': 'network-acl-id', 'Values': [naclID]}]
# ^ note square brackets ^
print(set_filter)
set_filter.append({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter)
Or to put them all into a list:
set_filter = []
for ent in NACLS:
set_filter.append({'Name': 'network-acl-id', 'Values': [naclID]})
print(set_filter)
set_filter.append({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
print(set_filter)
I don't understand much about your purpose of the list of dictionary, the suggested code
set_filters = []
for ent in NACLS:
set_filters.append({'Name': 'network-acl-id', 'Values': [naclID]})
set_filters.append({'Name': 'entry.rule-number', 'Values': [str(ent[0])]})
is close to your idea. However, the two dictionaries you tried to gather in the list can be combined into just one:
set_filters = []
for ent in NACLS:
set_filters.append(
{
'network-acl-id': [naclID],
'entry.rule-number': [str(ent[0])]
}
)
From here, you can make it shorter as
set_filters = [
{ 'network-acl-id': [naclID], 'entry.rule-number': [str(ent[0])] } for ent in NACLS
]

Convert nested dictionary within JSON from a string

I have JSON data that I loaded that appears to have a bit of a messy data structure where nested dictionaries are wrapped in single quotes and recognized as a string, rather than a single dictionary which I can loop through. What is the best way to drop the single quotes from the key-value property ('value').
Provided below is an example of the structure:
for val in json_data:
print(val)
{'id': 'status6',
'title': 'Estimation',
'text': '> 2 days',
'type': 'color',
'value': '{"index":14,"post_id":null,"changed_at":"2020-06-12T09:04:58.659Z"}',
'name': 'Internal: online course'},
{'id': 'date',
'title': 'Deadline',
'text': '2020-06-26',
'type': 'date',
'value': '{"date":"2020-06-26","changed_at":"2020-06-12T11:33:37.195Z"}',
'name': 'Internal: online course'},
{'id': 'tags',
'title': 'Tags',
'text': 'Internal',
'type': 'tag',
'value': '{"tag_ids":[3223513]}',
'name': 'Internal: online course'},
If I add a nested look targeting ['value'], it loops by character and not key-value pair in the dictionary.
Using json.loads to convert string to dict
import json
json_data = [{'id': 'status6',
'title': 'Estimation',
'text': '> 2 days',
'type': 'color',
'value': '{"index":14,"post_id":null,"changed_at":"2020-06-12T09:04:58.659Z"}',
'name': 'Internal: online course'},
{'id': 'date',
'title': 'Deadline',
'text': '2020-06-26',
'type': 'date',
'value': '{"date":"2020-06-26","changed_at":"2020-06-12T11:33:37.195Z"}',
'name': 'Internal: online course'},
{'id': 'tags',
'title': 'Tags',
'text': 'Internal',
'type': 'tag',
'value': '{"tag_ids":[3223513]}',
'name': 'Internal: online course'}]
# the result is a Python dictionary:
for val in json_data:
print(json.loads(val['value']))
this should be work!!

python - dictionary - update text values of keys - setting an priority (max principle)

I have the following strings as values for a dictionary key:
["low", "middle", "high", "very high"]
These are the options for the dicionary item key 'priority', a sample dict element is:
{'name': 'service', 'priority': value}
My task is to collect a list of dictionaries with the keys, all differ in the key value 'priority'.
my_list = [{'name': 'service', 'priority': 'low'}, {'name': 'service', 'priority': 'high'}]
In the end a final dictionary item should exist, that has the highest priority value. It should work like the maximum principle. In this case {'name': 'service', 'priority': 'high'} would be the result.
The problem is that the value is a string, not an integer.
Thanks for all ideas to get it work.
Here is the approach with itertools module usage:
# Step 0: prepare data
score = ["low", "middle", "high", "very high"]
my_list = [{'name': 'service', 'priority': 'low', 'label1':'text'}, {'name': 'service', 'priority': 'middle', 'label2':'text'}, {'name': 'service_b', 'priority': 'middle'}, {'name': 'service_b', 'priority': 'very high'}]
my_list # to just show source data in list
Out[1]:
[{'name': 'service', 'priority': 'low', 'label1': 'text'},
{'name': 'service', 'priority': 'middle', 'label2': 'text'},
{'name': 'service_b', 'priority': 'middle'},
{'name': 'service_b', 'priority': 'very high'}]
# Step 0.5: convert bytes-string (if it is) to string
# my_list = [{k:(lambda x: (x.decode() if type(x) == bytes else x))(v) for k,v in i.items()} for i in my_list ]
# Step 1: reorganize "score"-list on most useful way - to dict
score_dic = {i[0]:i[1] for i in list(zip(score, range(len(score))))}
score_dic
Out[2]:
{'low': 0, 'middle': 1, 'high': 2, 'very high': 3}
# Step 2: get result
import itertools
[max(list(g), key = lambda b: score_dic[b['priority']]) for k,g in itertools.groupby(my_list, lambda x:x['name'])]
Out[3]:
[{'name': 'service', 'priority': 'middle', 'label2': 'text'},
{'name': 'service_b', 'priority': 'very high'}]
Is this what you want?
priorities = ["low", "middle", "high", "very high"]
items = [{'name': 'service', 'priority': 'high'}, {'name': 'service2', 'priority': 'high'}, {'name': 'service', 'priority': 'very high'}, {'name': 'service2', 'priority': 'very high'}]
max_priority = max(items, key=lambda item: priorities.index(item['priority']))['priority']
max_items = [item for item in items if item['priority'] == max_priority]
print(max_items)
Output:
[{'name': 'service', 'priority': 'very high'}, {'name': 'service2', 'priority': 'very high'}]

Python get only values in each dictionary

I intend to get the values for each dictionary in array list and put the values in new dictionary.
There are two key,two values in each dictionary.
This is my array_list.
[{'Name': 'email',
'Value': 'mail#outlook.com'},
{'Name': 'name',
'Value': 'tester'},
{'Name': 'address',
'Value': 'abc'}]
My expected outcome (to get the both values in each dictionary):
{'email': 'mail#outlook.com',
'name': 'tester',
'address': 'abc'}
My current code:
outcome = {}
x = ""
for i in range(len(array_list)):
for key,value in array_list[i].items():
if key == 'Value':
x = value
elif key == 'Name':
outcome[value] = x
I still not able to get the expected outcome. Any helps?
l = [{'Name': 'email',
'Value': 'mail#outlook.com'},
{'Name': 'name',
'Value': 'tester'},
{'Name': 'address',
'Value': 'abc'}]
{k['Name'] : k['Value'] for k in l}
the result is
{'address': 'abc', 'email': 'mail#outlook.com', 'name': 'tester'}
You are almost correct. Just have some problems in if else.
After writing a code you should try to simulate your code by yourself. Please look carefully in you inner for loop. For each iteration either Name or Value will be set as if and elif is mutually exclusive. But the requirement is to create key-value in each iteration.
outcome = {}
array_list = [{'Name': 'email',
'Value': 'mail#outlook.com'},
{'Name': 'name',
'Value': 'tester'},
{'Name': 'address',
'Value': 'abc'}]
for i in range(len(array_list)):
keys = array_list[i].keys()
if 'Name' in keys and 'Value' in keys:
outcome[array_list[i]['Name']] = array_list[i]['Value']
It is almost same as your code but my thinking is different.

pystache: render context inside lambda

This is very similar to https://github.com/defunkt/pystache/issues/157, however in the mentioned post didn't really answer...
My target: print the following lines:
Al,John,Jack
Tim,Tom,Todd
without a final comma.
I tried this way:
ctx = {
'gangs': [
{'gangsters': [ {'name': 'Al' }, {'name': 'John'}, {'name': 'Jack'}]},
{'gangsters': [ {'name': 'Tim'}, {'name': 'Tom'} , {'name': 'Todd'}]},
]
}
class Lambdas(object):
def __init__(self, renderer):
self.renderer = renderer
def rstrip(self):
"Remove last character"
print self.renderer.context
return lambda s: self.renderer.render(s, self.renderer.context)[:-1]
renderer = pystache.Renderer(missing_tags='strict')
print renderer.render("""
{{#gangs}}
{{#rstrip}}{{#gangsters}}{{name}},{{/gangsters}}{{/rstrip}}
{{/gangs}}
""", ctx, Lambdas(renderer))
The output:
ContextStack({'gangs': [{'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]}, {'gangsters': [{'name': 'Tim'}, {'name': 'Tom'}, {'name': 'Todd'}]}]}, <__main__.Lambdas object at 0x15cadb10>, {'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]})
ContextStack({'gangs': [{'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]}, {'gangsters': [{'name': 'Tim'}, {'name': 'Tom'}, {'name': 'Todd'}]}]}, <__main__.Lambdas object at 0x15cadb10>, {'gangsters': [{'name': 'Al'}, {'name': 'John'}, {'name': 'Jack'}]})
Al,John,Jack
Al,John,Jack
The culprit is the invocation to render() inside rstrip. Notice how, during the second call, the 3d element of the ContextStack is exactly identical to the previous call.
Is this a bug, or am I missing something?!?
Answered upstream: https://github.com/defunkt/pystache/issues/158
def rstrip(self):
"Remove last character"
return lambda s: copy.deepcopy(self.renderer).render(s, self.renderer.context)[:-1]

Categories

Resources