listproperty GAE to string method - python

So my problem below is that when it sends the json object lets say I have multiple items in the lists? well it sends that many objects except changing that field once in the dict that i created above. For some reason , even though I use the for loops above to create a string from the list it doesn't actually make it so and i get 15 objects instead of 1 object with maybe a field that has 15 things in it separated by commas.
my expected output should be
name,special1,special2,special3..etc, review1,review2
instead i get
name,special1,review1
name,special2,review1
name,special3,review1
etc..
name,special1,review2
name,special1,review3
My main question is how do I convert the list to an array or even just to a string(like a toString Method) so that my json dump doesn't spit out multiples?
class store(db.Model):
mykey = db.StringProperty(db.Key)
storeSpecial = db.ListProperty(item_type=str)
reviews = db.ListProperty(item_type=str)
storeName = db.StringProperty()
#later in the code
qy1 = GqlQuery("SELECT storeName,storeSpecial,reviews FROM store WHERE mykey =:1",dataInput)
records_to_send = []
for i in qy1:
rev =""
for k in i.review:
rev = rev + str(k) + ","
spec = ""
for k2 in i.storeSpecial:
spec = spec + str(k2) + ","
output = {"store name": i.storeName,"specials": spec,"reviews":rev}
records_to_send.append(output)
self.response.out.write(json.dumps(records_to_send))

I'm not really sure what you want, your example is confusing. If you use JSON, why not just keep it as list? Why do you change it to a string?
It seems you want something like this
for store in qy1:
records_to_send.append({'store name': store.storeName, 'specials': store.storeSpecial}, 'reviews': store.reviews})

Related

Dynamically generated Class instances

I want to store values that I plan to later use for sorting pdfs on my computer using PyPDF2.
I thought that if I created a class and stored identifying info for each type of file (such as a descriptor, a string that is unique to the file and can be found by PyPDF2 later such as an account number, and the path where the file should be moved to) that would work. Something like this:
class File_Sort(object):
def __init__(self, identifier, file_text, file_path):
self.identifier = identifier
self.file_text = file_text
self.file_path = file_path
so an example input from me would be:
filetype0001 = File_Sort("Phone Bill", "123456", "/Users/Me/PhoneBills/")
I would like to be able to have users generate new file types via a series of raw_input questions, but I can't figure how to generate the variable to create a new instance, so that I can get:
filetype000[automatically incrementing number] = File_Sort(UserResponse1, UserResponse3, UserResponse3).
Creating the "filetype000[automatically incrementing number]" text itself seems easy enough with:
file_number += 1
file_name = "filetype" + str(file_number).zfill(4)
but how do you turn the generated file_name string into a variable and populate it?
It sounds like you're wanting to dynamically create variables. That's almost always a foolish thing to do. Instead, you should be using a data structure like a list or dictionary, indexed by the parts of the variable name you wanted to generate dynamically.
So instead of creating a list named filetype000, start with a list named filetypes, and append an inner list, so you can do filetypes[0] to get at it. Or if string names make more sense for your specific application, let filetypes be a dictionary, and access the inner lists with something like filetypes['pdf'].
I'm being a little vague here because I don't really understand all of your pseudocode. It's not at all obvious what the purpose of the [automatically incrementing number] parts of your example are, so I'm more or less ignoring those bits. You probably just want to start with an empty list and append values to it, rather than somehow initializing it to a specific size and magically indexing it.
so fyi this is what I ended up using:
file_descriptor = []
file_string = []
file_location = []
filetype_new = len(file_descriptor)
input_descriptor = raw_input("What is the description of the new file type? ")
file_descriptor.append(input_descriptor)
input_filestring = raw_input("What is unique string to search for in this file type? ")
file_string.append(input_filestring)
input_filelocation = raw_input("where should we put this file type? ")
file_location.append(input_filelocation)
print("file%s: %s, \t%s, \t%s" % (str(filetype_new+1).zfill(4), file_descriptor[filetype_new], file_string[filetype_new], file_location[filetype_new]))
review = raw_input("\nWould you like to review the current files? y/n ").lower()
while review not in "yn":
review = raw_input("Sorry, I don't understand. Would you like to review your file types? y/n ").lower()
print("There are currently sort instructions for %s filetypes: " % (len(file_descriptor)))
file_increment = 0
while file_increment in range(0, len(file_descriptor)):
print("file%s: %s, \t%s, \t%s" % (
str(file_increment + 1).zfill(4), file_descriptor[file_increment], file_string[file_increment],
file_location[file_increment]))
file_increment += 1
thanks for your advice.

Iterating a conversion of a string to a float in a scripting file when parsing an old file

I am using a new script (a) to extract information from an old script (b) to create a new file (c). I am looking for an equal sign in the old script (b) and want to modify the modification script (a) to make it automated.
The string is
lev1tolev2 'from=e119-b3331l1 mappars="simp:180" targ=enceladus.bi.def.3 km=0.6 lat=(-71.5,90) lon=(220,360)'
It is written in python 3.
The current output is fixed at
cam2map from=e119-b3331l1 to=rsmap-x map=enc.Ink.map pixres=mpp defaultrange=MAP res=300 minlat=-71.5 maxlat=90 minlon=220 maxlon=360
Currently, I have the code able to export a string of 0.6 for all of the iterations of lev1tolev2, but each one of these is going to be different.
cam2map = Call("cam2map")
cam2map.kwargs["from"] = old_lev1tolev2.kwargs["from"]
cam2map.kwargs["to"] = "rsmap-x"
cam2map.kwargs["map"] = "enc.Ink.map"
cam2map.kwargs["pixres"] = "mpp"
cam2map.kwargs["defaultrange"] = "MAP"
**cam2map.kwargs["res"] = float((old_lev1tolev2.kwargs["km"]))**
cam2map.kwargs["minlat"] = lat[0]
cam2map.kwargs["maxlat"] = lat[1]
cam2map.kwargs["minlon"] = lon[0]
cam2map.kwargs["maxlon"] = lon[1]
I have two questions, why is this not converting the string to a float? And, why is this not iterating over all of the lev1tolev2 commands as everything else in the code does?
The full code is available here.
https://codeshare.io/G6drmk
The problem occurred at a different location in the code.
def escape_kw_value(value):
if not isinstance(value, str):
return value
elif (value.startswith(('"', "'")) and value.endswith(('"', "'"))):
return value
# TODO escape the quote with \" or \'
#if value.startswith(('"', "'")) or value.endswith(('"', "'")):
# return value
if " " in value:
value = '"{}"'.format(value)
return value
it doesn't seem to clear to me, but from you syntax here :
**cam2map.kwargs["res"] = float((old_lev1tolev2.kwargs["km"]))**
I'd bet that cam2map.kwargs["res"] is a dict, and you thought that it would convert every values in the dict, using the ** syntax. The float built-in should then be called in a loop over the elements of the dict, or possible a list-comprehension as here :
cam2map.kwargs["res"] = dict()
for key, value in old_lev1tolev2.kwars["res"].items():
cam2map.kwargs["res"][key] = float(value)
Edit :
Ok so, it seems you took the string 'from=e119-b3331l1 mappars="simp:180" targ=enceladus.bi.def.3 km=0.6 lat=(-71.5,90) lon=(220,360)'
And then thought that calling youstring.kwargs would give you a dict, but it won't, you can probably parse it to a dict first, using some lib, or, you use mystring.split('=') and then work your way to a dict first, like that:
output = dict()
for one_bit in lev_1_lev2.split(' '):
key, value = one_bit.split('=')
output[key] = value

String indices must be integers, new to python

I hope I won't get trashed for this question. This is my first day with Python and all I've done so far is copy pasting and deducing from other snippets of code. I have no experience with code. I'm trying my hardest however this one I can't get past for the past few hours.
I'm currently adjusting an Editorial (iOS app) workflow to fit my needs — namely: posting to my WordPress site, including the ability to choose from a list of all possible post formats (I have "standard" and "link" enabled).
Here is the faulty bit from the relevant Python script:
console.show_activity('Fetching formats...')
server = xmlrpclib.ServerProxy(wp_url)
format = server.wp.getPostFormats(wp_blogid, wp_username, wp_password, 'post_format')
i = 0
for x in format:
formats += '\n' + x['name'] + " " + str(i)
i = i+1
workflow.set_variable("formats", formats)
console.hide_activity()
I'm getting the error: "string indices must be integers, not str"
What is this supposed to do is later show me in a list my available formats. I've done this successfully with server.wp.getPostFormats(wp_blogid, wp_username, wp_password, 'post_tag') and server.wp.getTerms(wp_blogid, wp_username, wp_password, 'category')
I know my problem is where the line with the i starts, I just have no idea how to solve it. I'm assuming by reading other topics that I need to cast, but I'm not even sure what getPostFormats returns, or how to do that.
Thanks in advance!
Edit: I've now concluded that server.wp.getPostFormats returns a dictionary, but I have not a slightest idea on how to retrieve only one set of data (either the key or value) of this dictionary. Please help.
You're getting that error because "string indices must be integers, not str".
formats += '\n' + x['name'] + " " + str(i)
Here, you are accessing the 'name'th element of x, where 'name' is of course a string and x is a string too, since server.wp.getPostFormats obviously returns a list of strings.
So simply look at format and you should immediately see how to obtain the required data.
UPDATE:
OK, so you figured out that format is a dictionary (returned from server.wp.getPostFormats). In Python, if you iterate over a dictionary (your for-loop), you iterate through its keys. This is the standard behaviour.
Look at this example:
>>> foo = {'a': 1, 'c': 3, 'b': 2}
>>> for x in foo: print(x)
...
a
c
b
Of course you also need the values, not only the keys (you seem to look for an entry with the key name). One way is to iterate though the keys and items in one shot:
>>> for key, value in foo.iteritems():
... print(key + ":" + str(value))
...
a:1
c:3
b:2
So the .iteritems() method of a dictionary returns for every iteration a key/value-pair, which you can unpack within the for loops definition.
In your case, you can do the following:
for key, value in format.iteritems():
formats += 'key: ' + key + ', value: ' + value + '\n'
Given that you are new, I would also suggest using the enumerate method and refactoring your code:
for i, x in enumerate(format):
formats += '\n' + x[idx_for_name] + " " + str(i)
The idx_for_name would be the index for the name.
If you wanna go even further, you can use the join method too:
formats = '\n'.join(x[idx_for_name] + " " + str(i) \
for i, x in enumerate(format))
warning: This code is untested.
Read:
http://python-wordpress-xmlrpc.readthedocs.org/en/latest/ref/methods.html#wordpress_xmlrpc.methods.posts.GetPostFormats
GetPostFormats return a dictionary so x iterates among the keys which are strings.
Try:
x= format['all']:

Stuck on learnpython.org exercise using JSON

http://www.learnpython.org/Serialization_using_JSON_and_pickle
Here are the instructions:
The aim of this exercise is to print out the JSON string with key-value pair "Me" : 800 added to it.
And below is the starting code, which we should modify.
#Exercise fix this function, so it adds the given name and salary pair to the json it returns
def add_employee(jsonSalaries, name, salary):
# Add your code here
return jsonSalaries
#Test code - shouldn't need to be modified
originalJsonSalaries = '{"Alfred" : 300, "Jane" : 301 }'
newJsonSalaries = add_employee(originalJsonSalaries, "Me", 800)
print(newJsonSalaries)
I'm completely lost. The JSON lesson was brief, at best. The issue I seem to be running in to here is that orginalJsonSalaries is defined as a string (containing all sort of unnecessary symbols like brackets. In fact, I think if the single quotes surrounding its definition were removed, originalJsonSalaries would be a dictionary and this would be a lot easier. But as it stands, how can I append "Me" and 800 to the string and still maintain the dictionary-like formatting?
And yes, I'm very very new to coding. The only other language I know is tcl.
EDIT:
OK, thanks to the answers, I figured out I was being dense and I wrote this code:
import json
#Exercise fix this function, so it adds the given name and salary pair to the json it returns
def add_employee(jsonSalaries, name, salary):
# Add your code here
jsonSalaries = json.loads(jsonSalaries)
jsonSalaries["Me"] = 800
return jsonSalaries
#Test code - shouldn't need to be modified
originalJsonSalaries = '{"Alfred" : 300, "Jane" : 301 }'
newJsonSalaries = add_employee(originalJsonSalaries, "Me", 800)
print(newJsonSalaries)
This does not work. For whatever reason, the original dictionary keys are formatted as unicode (I don't know where that happened), so when I print out the dictionary, the "u" flag is shown:
{u'Jane': 301, 'Me': 800, u'Alfred': 300}
I have tried using dict.pop() to replace the key ( dict("Jane") = dict.pop(u"Jane") ) but that just brings up SyntaxError: can't assign to function call
Is my original solution incorrect, or is this some annoying formatting issue and how to resolve it?
The page you linked to says exactly how to do this:
In order to use the json module, it must first be imported:
import json
[...]
To load JSON back to a data structure, use the "loads" method. This method takes a string and turns it back into the json object datastructure:
print json.loads(json_string)
They gave you a string (jsonSalaries). Use json.loads to turn it into a dictionary.
Your last question is a new question, but... When you print a dictionary like that you are just using the fact that python is nice enough to show you the contents of its variables in a meaningful way. To print the dictionary in your own format, you would want to iterate through the keys and print the key and value:
for k in newJsonSalaries:
print("Employee {0} makes {1}".format(k, newJsonSalaries[k]))
There are other problems in your code....
It is weird to load the JSON inside the add employee function. That should be separate...
Also, in your add_employee() function you are hardwired always to add the same values of Me and 800 instead of using the name and salary variables that are passed in, so that line should be:
jsonSalaries[name] = salary
Use this:
import json
def add_employee(jsonSalaries, name, salary):
# Add your code here
jsonSalaries = json.loads(jsonSalaries)
jsonSalaries[name] = salary
jsonSalaries = json.dumps(jsonSalaries)
return jsonSalaries
#Test code - shouldn't need to be modified
originalJsonSalaries = '{"Alfred" : 300, "Jane" : 301 }'
newJsonSalaries = add_employee(originalJsonSalaries, "Me", 800)
print(newJsonSalaries)
Add this before return jsonSalaries:
jsonSalaries = json.dumps(jsonSalaries)

ListProperty with GoogleAppEngine

How do I assign a ListProperty with Google App Engine?
name = self.request.get("name")
description = self.request.get("description")
list = '''insert code here'''
I want list to work like a dictionary, is this possible with Google App Engine, if so, how:
[wordone : score; wordtwo : score; wordthree : score]
^I want the list property to store some data like this, how is this possible?
You actually won't be able to store a true dictionary as type in a ListProperty (it only supports datastore property types, of which dict is not one), so you won't be able to get the behavior you're looking for. Will all of the data be the same (i.e. each element represents a word score)? Assuming storing each word as its own property on the model doesn't make sense, one 'dirty' solution would be to make a ListProperty of type str, and then append the word and score as separate elements. Then, when you searched for a word in the list, you would return the value at the index position of the word + 1. That would looks something like:
class MyEntity(db.Model):
name = db.StringProperty()
description = db.TextProperty()
word_list = db.ListProperty()
You could then add words like:
new_entity = MyEntity()
new_entity.word_list = ['word1', 1, 'word2', 2, 'word3', 10]
You could then query for a particular entity and then examine its word_list property (a list), looking for your target word and returning the element one position after it.
More convoluted suggestion
However if that isn't an option, you could look into creating another model (let's say WordScore) that looked something like:
class WordScore(db.Model):
word = db.StringProperty()
score = db.IntegerProperty()
Then, whenever you needed to add a new score, you would create a WordScore instance, fill out the properties and then assign it to the proper entity. I haven't tested any of this, but the idea would be something like:
# Pull the 'other' entity (this would be your main class as defined above)
q = OtherEntity.all()
q.filter('name =', 'Someone')
my_entity = q.get()
# Create new score
ws = WordScore(parent=my_entity)
ws.word = 'dog'
ws.score = 2
ws.put()
You could then pull out the score for dog for 'Someone' by doing something like this (again, completely untested for now - be warned :) ):
# Get key of 'Someone'
q = OtherEntity.all()
q.filter('name =', 'Someone')
my_entity = q.get().key()
# Now get the score
ws = WordScore.all()
ws.filter('word = ', 'dog').ancestor(my_entity)
word_score = ws.get().score
Change to NDB and use the Pickle property:
Value is a Python object (such as a list or a dict or a string) that is serializable using Python's pickle protocol; the Datastore stores the pickle serialization as a blob. Unindexed by default.
NDB Properties
Then you can use it directly:
class table(ndb.Model):
data_dict = ndb.PickleProperty(default = {})
then
dd = table()
dd.data_dict['word_one'] = "Some_Score"

Categories

Resources