-
Notifications
You must be signed in to change notification settings - Fork 3
Create growingrecs.py #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#!/usr/lib/python2.7 | ||
|
||
# MIT License. | ||
# Copyright 2014 Frances Hocutt | ||
|
||
# growingrecs.py is a command-line tool to help you plan your garden. | ||
# Given a crop, it uses the Growstuff API to finds the most common conditions | ||
# that Growstuff users have used for that crop: how much sun, and whether they | ||
# planted from seeds, seedlings, rootstock, etc.). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to have instructions for running this from the command line, eg. what args does it take, etc. |
||
|
||
import requests | ||
import string | ||
|
||
def getcropinfo(crop): | ||
"""Given a crop, gets the data available in Growstuff. | ||
|
||
crop - a string with the crop to get data on. Whitespace and capitalization | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe mention that it needs to match the display name of a crop in Growstuff's database |
||
are ok. | ||
""" | ||
cropslug = slugify(crop) | ||
cropinfo = apirequest(cropslug) | ||
return cropinfo | ||
|
||
def slugify(crop): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It might be good to explain what a slug is. |
||
"""Creates a slug. Lowercases, trims whitespace, replaces " " with "-".""" | ||
crop = string.lower(crop) | ||
crop = string.strip(crop) | ||
crop = crop.replace(" ", "-") | ||
return crop | ||
|
||
def apirequest(cropslug): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the interests of specificity I would suggest calling this something like fetch_crop_data |
||
"""Given a slug, retrieves data from the Growstuff API. Returns a dict. | ||
|
||
If the API returns an error, the user is prompted to try again. | ||
""" | ||
URI = "http://growstuff.org/crops/%s.json" % cropslug | ||
r = requests.get(URI) | ||
if r.status_code == 200: | ||
cropinfo = r.json() | ||
return cropinfo | ||
elif r.status_code == 404: | ||
#this gives NoneType not subscriptable errors, #FIXME | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a non-Python person, I don't understand this FIXME comment. Could you help me understand? |
||
print ("We couldn't find that crop. " | ||
"Please enter a crop that is in the Growstuff database.\n") | ||
run() | ||
else: | ||
print "API error, please try again.\n" | ||
run() | ||
|
||
def parseplantings(cropinfo): | ||
"""Counts how many plantings have the same (planted_from, sunniness) combo. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we necessarily need to combine these. We can just roughly replicate what's in the sidebar of the crop page, eg: Plant from: seed (18), seedling (4) You could express this as a percentage if you liked. But I'm thinking that the combined version is a) quite a lot of complicated code, and b) not actually as useful as it might seem -- as a gardener, I don't actually need that combined information. If we want this to be the simplest possible API example, we don't need to do all that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incidentally, Growstuff's own code for how we generate that is in app/models/crop.rb in the methods crop.sunniness and crop.planted_from, which each return a hash. The actual display of this data is in app/views/crops/_planting_advice.html.haml |
||
|
||
Returns a dict with frequency of conditions and an int with the total | ||
number of plantings. | ||
|
||
cropinfo - a dict from the API's json output | ||
""" | ||
planting_info = {} | ||
plantings_count = cropinfo["plantings_count"] | ||
for item in cropinfo["plantings"]: | ||
conditions = (item["planted_from"], item["sunniness"]) | ||
if conditions in planting_info: | ||
planting_info[conditions] += 1 | ||
else: | ||
planting_info[conditions] = 1 | ||
return (planting_info, plantings_count) | ||
|
||
def mostplantings(planting_info): | ||
"""Returns a tuple with the most frequent conditions: | ||
(planted_from, sunniness).""" | ||
v = list(planting_info.values()) | ||
k = list(planting_info.keys()) | ||
return k[v.index(max(v))] | ||
|
||
def run(): | ||
crop = raw_input("What would you like to plant?\n") | ||
cropinfo = getcropinfo(crop) | ||
planting_info, plantings_count = parseplantings(cropinfo) | ||
if plantings_count > 0: | ||
planted_from, sunniness = mostplantings(planting_info) | ||
print "%s was planted %s times." % (crop, plantings_count) | ||
print "It was most often planted from %s in %s." % (planted_from, | ||
sunniness) | ||
else: | ||
print "%s has not been planted yet." % crop | ||
|
||
if __name__ == "__main__": | ||
run() | ||
|
||
def test(crop, cropinfo): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be left in the code? |
||
"""Same as run() but without the API call.""" | ||
planting_info, plantings_count = parseplantings(cropinfo) | ||
if plantings_count > 0: | ||
planted_from, sunniness = mostplantings(planting_info) | ||
print "%s was planted %d times." % (crop, plantings_count) | ||
print "It was most often planted from %s in %s." % (planted_from, | ||
sunniness) | ||
else: | ||
print "%s has not been planted yet." % crop | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BSD license was what I chose for the github repo. It might be good for us to develop some suitable boilerplate to go at the top of each script, with links to the github, license, and other info. Not urgent, just a thought.