#!/usr/bin/env python # # Copyright 2010 ESHA Research, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app from google.appengine.ext import db from google.appengine.api import urlfetch from django.utils import simplejson as json from operator import itemgetter import time API = "http://api.esha.com" PUBLIC_KEY = "2s35wsxke74rcut8jqapbkyf" def write(str, self): self.response.out.write(str+"\n") def toUrl(path, key): delim = "?" if path.find("?") < 0 else "&" return API + path + delim + "apikey=" + key def getJSON(path, key, cache): url = toUrl(path, key) latest = Cache.gql("WHERE url = :1", url).get(); if cache and latest: return json.loads(latest.json) result = urlfetch.fetch(url) if result.status_code == 200: # rudimentary rate-limit support time.sleep(0.5) if cache: latest = Cache() latest.url = url latest.json = result.content latest.put() return json.loads(result.content) def findIdForDescription(list, desc): for item in list: if item['description'] == desc: return item['id'] class Simple(webapp.RequestHandler): def get(self): self.response.headers['Content-Type'] = 'text/plain' key = self.request.get('apikey', default_value=PUBLIC_KEY) cache = not self.request.get('nocache') if not cache: write('Clearing cache...', self) q = self.request.get('query', default_value="pizza") write("Searching for '"+q+"'...", self) results = getJSON('/foods?query='+q, key, cache) write("Matches found: "+str(results['total']), self) if results['total'] == 0: return None write("Loading supported food units to identify id for 'Gram'...", self); units = getJSON('/food-units', key, cache) gramId = findIdForDescription(units, "Gram"); write("Gram unit id: "+str(gramId), self); write("Selecting results that support 'Gram' as a unit...", self); selectedFoods = []; for result in results['items']: for unit in result['units']: if gramId == unit: selectedFoods.append(result) break if len(selectedFoods) == 10: write("Stopped selection after 10 results (to keep this short).", self) break write("Loading supported nutrients to identify id for 'Calories'...", self) nutrients = getJSON('/nutrients', key, cache) caloriesId = findIdForDescription(nutrients, "Calories") write("Calories nutrient id: "+str(caloriesId), self); for food in selectedFoods: write("Analyzing 100 grams of '"+food['description']+"'...", self) analysis = getJSON("/analysis?n="+str(caloriesId)+ "&f0="+food['id']+ "&q0=100"+ "&u0="+str(gramId), key, cache) #There will be only one nutrient result in the analysis (for Calories) food['calories'] = analysis['results'][0]['value'] write("All "+str(len(selectedFoods))+" analyses have been returned. Sorting results by calories...", self) foods = sorted(selectedFoods, key=itemgetter('calories')) for food in foods: write("There are "+str(round(food['calories'],1))+" calories in 100g of '"+food['description']+"'", self) write("\nFor source code go to: "+self.request.url+"src", self) class Source(webapp.RequestHandler): def get(self): self.response.headers['Content-Type'] = 'text/plain' file = open('simple.py', "r") write(file.read(), self) class Reset(webapp.RequestHandler): def get(self): self.response.headers['Content-Type'] = 'text/plain' for cache in Cache.all(): cache.delete() write('Reset full cache.', self) class Cache(db.Model): url = db.StringProperty() json = db.TextProperty() def main(): application = webapp.WSGIApplication([('/', Simple), ('/src', Source), ('/reset', Reset)], debug=True) run_wsgi_app(application) if __name__ == '__main__': main()