Modifying a python dictionary from user inputted dot notation - python

I'm trying to provide an API like interface in my Django python application that allows someone to input an id and then also include key/values with the request as form data.
For example the following field name and values for ticket 111:
ticket.subject = Hello World
ticket.group_id = 12345678
ticket.collaborators = [123, 4567, 890]
ticket.custom_fields: [{id: 32656147,value: "something"}]
On the backend, I have a corresponding Dict that should match this structure (and i'd do validation). Something like this:
ticket: {
subject: "some subject I want to change",
group_id: 99999,
collaborator_ids: [ ],
custom_fields: [
{
id: 32656147,
value: null
}
]
}
1) I'm not sure exactly the best way to parse the dot notation there, and
2) Assuming I am able to parse it, how would I be able to change the values of the Dict to match what was passed in. I'd imagine maybe something like a class with these inputs?
class SetDictValueFromUserInput(userDotNotation, userNewValue, originalDict)
...
SetDictValueFromUserInput("ticket.subject", "hello world", myDict)

Fastest way is probably splitting the string and indexing based on seperation. For example:
obj = "ticket.subject".split(".")
actual_obj = eval(obj[0]) # this is risky, they is a way around this if you just use if statements and predifined variables.
actual_obj[obj[1]] = value
To have further indexing where an object like ticket.subject.name might work try using a for loop as so.
for key in obj[1:-2]: # basically for all the values in between the object name and the defining key
actual_obj = actual_obj[key] # make the new object based on the value in-between.
actual_obj[obj[-1]] = value

Related

How to add a value to a dictionary that has a duplicate key

I have this problem where I would like to add a value to a dictionary but the key is duplicate.
I would like the key to to hold a list with multiple values
this is what I have tried
def storingPassword():
username=("bob")#key,
password=("PASSWROD1")#value
allpasswords={
"jeff":"jeff 123 ",
"bob" : "bob 123"
}
if username not in allpasswords:
allpasswords[username]=password
else:
allpasswords[username].append(password)
return allpasswords
but i keep getting this error
"AttributeError: 'str' object has no attribute 'append'"
I expect a output something like this;
"jeff":"jeff 123 ",
"bob" : ["bob 123","PASSWORD1"]
That's because the value in your allpasswords dict is a string and you are trying to treat it like a list. Why are you trying to make your data structure complex with few values as list and few as string? I recommend to convert everything to list for a simpler logic.
Hence your code should be like this:
allpasswords={
"jeff": ["jeff 123 "],
"bob" : ["bob 123"]
}
allpasswords[username].append(password)
Instead of using dict object, you can use collections.defaultdict. It will let you define a dict with default value as list. So you don't need to even explicitly initialise value of new key as list. For example:
from collections import defaultdict
my_dict = defaultdict(list)
my_dict['new_key'].append('new_value')
# dictionary will hold the value:
# {'new_key': ['new_value']})
Initiate your dictionary entry with a list instead of just a string.
allpasswords[username] = [password] # List containing a single password
You will then be able to append to it.
(Having some entries contain a string while others contain a list of strings is best avoided - when it is time to look them up or print them, you would have to check each time whether it is a list or string.)

Using a dict to call functions from a string

I would like the first two words of a user input string to be read as function arguments for where to save the string. I've settled on using a dict instead of many if statements, but I'm not sure how to structure the dict.
I believe this is a correct start:
input: "question physics What happens to atoms when they are hit by photons?"
result: program saves the input in location questions\physics
raw_entry = input("Enter text in the following format: type subtype text")
instructions = raw_entry.split()[:2]
The two words (each being a "get_id" in the example) will designate where to save the text. This example seems to be what I'm looking for, but I'm not sure how to change it for my case.
function_dict = {'get_id':
(
# function
requests.get,
# tuple of arguments
(url + "/users/" + user,),
# dict of keyword args
{'headers': self.headers}
)
}
Let me know if I'm going about this logically or if it doesn't make sense. Thanks!
You will need to define the functions separately from the dictionary
For example:
def get_id():
... the function's code ...
function_dict = { "get_id":get_id, ... }
you can then call the function with its keyword:
function_dict["get_id"]()
but you can also do this without a dictionary if the keyword is the same as the function name:
globals()["get_id"]()

am new to python, please share logic for below concept

Eg:
ECE_student_list = [['section-1', [["sai",'science'], ["rama",'maths']]],
['section-2', [["seetha",'science'], ["ravana",'maths']]]]
I have to print student name and subject by passing key as section name.
for Eg : if the key is 'section-1' first student then it should print "sai",'science'
second student ,then it should print "rama",'maths'
please share the logic in python.
Won't share the code directly. That you have to learn and experiment on your own. Although I can tell you what you can expect as your output.
You can create a dictionary in python and add section-1, section-2 as the keys and the list of students as value for each key.
Your dictionary structure will be something like this:
{
'section-1' : [
{'sai':'science'},
{'rama':'math'}
],
'section-2':[
{'sai':'science'},
{'rama':'math'}
]
}

How to create URL Parameters from a list

I have a form with multiple select field. It is working through GET method.
An example of request parameters generated by the form:
action=not-strummed&action=not-rewarded&keywords=test&page=2
Note that there is two "action" parameters. This is happening because of the multiple select.
What I want to do is:
Make a dict from parameters
Remove "page" key from the dict
Transform-back the dict into the parameter string
The urllib.urlencode() isn't smart enough to generate url parameters from the list.
For example:
{
"action": [u"not-strummed", u"not-rewarded"]
}
urllib.urlencode() transforms this dict as:
action=%5Bu%27not-strummed%27%2C+u%27not-rewarded%27%5D
This is completely wrong and useless.
That's why i wrote this iteration code to re-generate url parameters.
parameters_dict = dict(self.request.GET.iterlists())
parameters_dict.pop("page", None)
pagination_parameters = ""
for key, value_list in parameters_dict.iteritems():
for value in value_list:
pagination_item = "&%(key)s=%(value)s" % ({
"key": key,
"value": value,
})
pagination_parameters += pagination_item
It is working well. But it doesn't cover all possibilities and it is definitely not very pythonic.
Do you have a better (more pythonic) idea for creating url parameters from a list?
Thank you
You should be able to use the second doseq parameter urlencode offers:
http://docs.python.org/2/library/urllib.html
So basically, you can pass a dictionary of lists to urlencode like so:
urllib.urlencode(params, True)
And it will do the right thing.

How to create a dictionary based on variable value in Python

I am trying to create a dictionary where the name comes from a variable.
Here is the situation since maybe there is a better way:
Im using an API to get attributes of "objects". (Name, Description, X, Y, Z) etc. I want to store this information in a way that keeps the data by "object".
In order to get this info, the API iterates through all the "objects".
So what my proposal was that if the object name is one of the ones i want to "capture", I want to create a dictionary with that name like so:
ObjectName = {'Description': VarDescrption, 'X': VarX.. etc}
(Where I say "Varetc..." that would be the value of that attribute passed by the API.
Now since I know the list of names ahead of time, I CAN use a really long If tree but am looking for something easier to code to accomplish this. (and extensible without adding too much code)
Here is code I have:
def py_cell_object():
#object counter - unrelated to question
addtototal()
#is this an object I want?
if aw.aw_string (239)[:5] == "TDT3_":
#If yes, make a dictionary with the object description as the name of the dictionary.
vars()[aw.aw_string (239)]={'X': aw.aw_int (232), 'Y': aw.aw_int (233), 'Z': aw.aw_int (234), 'No': aw.aw_int (231)}
#print back result to test
for key in aw.aw_string (239):
print 'key=%s, value=%s' % (key, aw.aw_string (239)[key])
here are the first two lines of code to show what "aw" is
from ctypes import *
aw = CDLL("aw")
to explain what the numbers in the API calls are:
231 AW_OBJECT_NUMBER,
232 AW_OBJECT_X,
233 AW_OBJECT_Y,
234 AW_OBJECT_Z,
239 AW_OBJECT_DESCRIPTION,
231-234 are integers and 239 is a string
I deduce that you are using the Active Worlds SDK. It would save time to mention that in the first place in future questions.
I guess your goal is to create a top-level dictionary, where each key is the object description. Each value is another dictionary, storing many of the attributes of that object.
I took a quick look at the AW SDK documentation on the wiki and I don't see a way to ask the SDK for a list of attribute names, IDs, and types. So you will have to hard-code that information in your program somehow. Unless you need it elsewhere, it's simplest to just hard-code it where you create the dictionary, which is what you are already doing. To print it back out, just print the attribute dictionary's repr. I would probably format your method more like this:
def py_cell_object():
#object counter - unrelated to question
addtototal()
description = aw.aw_string(239)
if description.startswith("TDT3_"):
vars()[description] = {
'DESCRIPTION': description,
'X': aw.aw_int(232),
'Y': aw.aw_int(233),
'Z': aw.aw_int(234),
'NUMBER': aw.aw_int (231),
... etc for remaining attributes
}
print repr(vars()[description])
Some would argue that you should make named constants for the numbers 232, 233, 234, etc., but I see little reason to do that unless you need them in multiple places, or unless it's easy to generate them automatically from the SDK (for example, by parsing a .h file).
If the variables are defined in the local scope, it's as simple as:
obj_names = {}
while True:
varname = read_name()
if not varname: break
obj_names[varname] = locals()[varname]
This is actual code I am using in my production environment
hope it helps.
cveDict = {}
# StrVul is a python list holding list of vulnerabilities belonging to a report
report = Report.objects.get(pk=report_id)
vul = Vulnerability.objects.filter(report_id=report_id)
strVul = map(str, vul)
# fill up the python dict, += 1 if cvetype already exists
for cve in strVul:
i = Cve.objects.get(id=cve)
if i.vul_cvetype in cveDict.keys():
cveDict[i.vul_cvetype] += 1
else:
cveDict[i.vul_cvetype] = 1

Categories