import os, sys, re import wsgiref.handlers from google.appengine.ext.webapp import template from google.appengine.ext import webapp from google.appengine.api import urlfetch BASE_URL = "http://a2parking.appspot.com/" PARKING_API_URL = \ "http://www.a2dda.org/parking__transportation/available_parking_spots/" PARKING_LOCATIONS_RE = re.compile(">[\s\w\.:]+[\r\n\s]*[\s\w\.]+<", re.MULTILINE) def xml_response(handler, page, templatevalues=None): """ Renders an XML response using a provided template page and values """ path = os.path.join(os.path.dirname(__file__), page) handler.response.headers["Content-Type"] = "text/xml" handler.response.out.write(template.render(path, templatevalues)) def fetch_parking(): result = urlfetch.fetch(PARKING_API_URL) if result.status_code != 200: return None return result.content class ParkingSpotsPage(webapp.RequestHandler): """ Accepts input digits from the caller, fetches the parking info from an external site, and reads back the number of spots to the caller """ def get(self): self.post() def _error(self, msg, redirecturl=None): templatevalues = { 'msg': msg, 'redirecturl': redirecturl } xml_response(self, 'error.xml', templatevalues) def post(self): location = self.request.get('Digits') try: location = location.replace('#', '').replace('*', '')[:1] location = int(location) except: self._error("Invalid parking location.", BASE_URL) return parkingpage = fetch_parking() if not parkingpage: self._error("Error fetching parking page. Good Bye.") return locations = PARKING_LOCATIONS_RE.findall(parkingpage) if not locations: self._error("Error parsing parking spots.", BASE_URL) return if location >= len(locations): self._error("Invalid parking location.", BASE_URL) return try: name = locations[location][1:].split(':')[0] spots = locations[location].\ split("")[1][1:].split('<')[0].strip('.') spots = int(spots) except: self._error("Error parsing parking spots.", BASE_URL) return templatevalues = { 'name': name, 'spots': spots, } xml_response(self, 'spots.xml', templatevalues) class ParkingLocationPage(webapp.RequestHandler): """ Initial user greeting. Fetches the parking locations and asks the user to select a location. Setup to work with less than 10 locations. """ def get(self): self.post() def post(self): parkingpage = fetch_parking() if not parkingpage: self._error("Error fetching parking page. Good Bye.") return l = PARKING_LOCATIONS_RE.findall(parkingpage) if not l: self._error("Error parsing parking locations.", BASE_URL) return locations = '' for i, p in enumerate(l): locations += 'Press %d for ' % i locations += p[1:].split(':')[0] + '\n' templatevalues = { 'locations': locations, 'postprefix': BASE_URL, } xml_response(self, 'locations.xml', templatevalues) def main(): application = webapp.WSGIApplication([ \ ('/', ParkingLocationPage), ('/spots', ParkingSpotsPage)], debug=True) wsgiref.handlers.CGIHandler().run(application) if __name__ == "__main__": main()