def get(self): lot_results = {'lots': []} city_lots = [] campus_lots = [] include_special_events = False # always include these headers self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Allow'] = 'GET' if self.request.get('expand') == 'specialevents': include_special_events = True logging.info(include_special_events) logging.info(city_lots) try: city_lots = CityParkingService().get_data(include_special_events) logging.debug('API: city_lots json response %s' % city_lots) except (ValueError, urlfetch.DownloadError, AttributeError) as e: logging.error('Failed to retrieve city data', str(e)) self.response.status = 500 self.response.out.write( json.dumps( api_utils.buildErrorResponse( '-1', 'There was a problem retrieving the city parking data') )) try: campus_lots = CampusParkingService().get_data( include_special_events) logging.debug('API: campus lots added, json response %s' % campus_lots) except (ValueError, urlfetch.DownloadError, AttributeError) as e: logging.error('Failed to retrieve campus data', str(e)) self.response.status = 500 self.response.out.write( json.dumps( api_utils.buildErrorResponse( '-1', 'There was a problem retrieving the campus parking data' ))) lot_results['lots'] = city_lots + campus_lots # encapsulate response in json or jsonp callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response_payload = callback + '(' + json.dumps(lot_results) + ');' else: self.response.headers['Content-Type'] = 'application/json' response_payload = json.dumps(lot_results) stathat.apiStatCount() self.response.out.write(response_payload)
def get(self): lot_results = {'lots': []} city_lots = [] campus_lots = [] include_special_events = False # always include these headers self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Allow'] = 'GET' if self.request.get('expand') == 'specialevents': include_special_events = True logging.info(include_special_events) logging.info(city_lots) try: city_lots = CityParkingService().get_data(include_special_events) logging.debug('API: city_lots json response %s' % city_lots) except (ValueError, urlfetch.DownloadError, AttributeError) as e: logging.error('Failed to retrieve city data', str(e)) self.response.status = 500 self.response.out.write( json.dumps( api_utils.buildErrorResponse('-1', 'There was a problem retrieving the city parking data') ) ) try: campus_lots = CampusParkingService().get_data(include_special_events) logging.debug('API: campus lots added, json response %s' % campus_lots) except (ValueError, urlfetch.DownloadError, AttributeError) as e: logging.error('Failed to retrieve campus data', str(e)) self.response.status = 500 self.response.out.write( json.dumps( api_utils.buildErrorResponse('-1', 'There was a problem retrieving the campus parking data') ) ) lot_results['lots'] = city_lots + campus_lots # encapsulate response in json or jsonp callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response_payload = callback + '(' + json.dumps(lot_results) + ');' else: self.response.headers['Content-Type'] = 'application/json' response_payload = json.dumps(lot_results) stathat.apiStatCount() self.response.out.write(response_payload)
def get(self): # validate the request parameters devStoreKey = validateRequest(self.request, api_utils.GETROUTES) if devStoreKey is None: logging.debug("unable to validate the request parameters") self.response.headers['Content-Type'] = 'application/javascript' self.response.out.write( json.dumps( api_utils.buildErrorResponse( '-1', 'Illegal request parameters'))) return logging.debug('getroutes request... ') if self.request.get('force') is not '': refresh = True else: refresh = False if api_utils.afterHours() is True: # don't run these jobs during "off" hours json_response = api_utils.buildErrorResponse( '-1', 'The Metro service is not currently running') else: if refresh is True: json_response = getRoutes(refresh) # drop it into the memcache again memcache.set(api_utils.GETROUTES, json_response) logging.debug('---> storing in memcache') else: logging.debug('---> memcache hit') json_response = memcache.get(api_utils.GETROUTES) if json_response is None: json_response = getRoutes(refresh) # drop it into the memcache again memcache.set(api_utils.GETROUTES, json_response) logging.debug('---> storing in memcache') # record the API call for this devkey api_utils.recordDeveloperRequest(devStoreKey, api_utils.GETROUTES, self.request.query_string, self.request.remote_addr) #logging.debug('API: json response %s' % json_response); callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json_response self.response.out.write(response) stathat.apiStatCount()
def get(self): # validate the request parameters devStoreKey = validateRequest(self.request, api_utils.GETSTOPLOCATION) if devStoreKey is None: logging.debug("unable to validate the request parameters") self.response.headers['Content-Type'] = 'application/javascript' self.response.out.write( json.dumps( api_utils.buildErrorResponse( '-1', 'Illegal request parameters'))) return # snare the inputs stopID = api_utils.conformStopID(self.request.get('stopID')) logging.debug('getstoplocation request parameters... stopID %s' % stopID) if api_utils.afterHours() is True: # don't run these jobs during "off" hours json_response = api_utils.buildErrorResponse( '-1', 'The Metro service is not currently running') elif stopID is not '': json_response = stopLocationRequest(stopID) api_utils.recordDeveloperRequest(devStoreKey, api_utils.GETSTOPS, self.request.query_string, self.request.remote_addr) else: logging.error("API: invalid request") json_response = api_utils.buildErrorResponse( '-1', 'Invalid Request parameters. Did you forget to include a stpID?' ) api_utils.recordDeveloperRequest( devStoreKey, api_utils.GETSTOPS, self.request.query_string, self.request.remote_addr, 'illegal query string combination') #logging.debug('API: json response %s' % json_response); # encapsulate response in json callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json.dumps(json_response) self.response.out.write(response) stathat.apiStatCount() # push event out to anyone watching the live board task = Task(url='/map/task', params={'stopID': stopID}) task.add('eventlogger')
def get(self): # validate the request parameters devStoreKey = validateRequest(self.request,api_utils.GETROUTES) if devStoreKey is None: logging.debug("unable to validate the request parameters") self.response.headers['Content-Type'] = 'application/javascript' self.response.out.write(json.dumps(api_utils.buildErrorResponse('-1','Illegal request parameters'))) return logging.debug('getroutes request... ') if self.request.get('force') is not '': refresh = True else: refresh = False if api_utils.afterHours() is True: # don't run these jobs during "off" hours json_response = api_utils.buildErrorResponse('-1','The Metro service is not currently running') else: if refresh is True: json_response = getRoutes(refresh) # drop it into the memcache again memcache.set(api_utils.GETROUTES, json_response) logging.debug('---> storing in memcache'); else: logging.debug('---> memcache hit'); json_response = memcache.get(api_utils.GETROUTES) if json_response is None: json_response = getRoutes(refresh) # drop it into the memcache again memcache.set(api_utils.GETROUTES, json_response) logging.debug('---> storing in memcache'); # record the API call for this devkey api_utils.recordDeveloperRequest(devStoreKey,api_utils.GETROUTES,self.request.query_string,self.request.remote_addr); #logging.debug('API: json response %s' % json_response); callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json_response self.response.out.write(response) stathat.apiStatCount()
def get(self): # validate the request parameters devStoreKey = validateRequest(self.request) if devStoreKey is None: logging.debug("unable to validate the request parameters") self.response.headers['Content-Type'] = 'application/javascript' self.response.out.write( json.dumps( api_utils.buildErrorResponse( '-1', 'Illegal request parameters'))) return # snare the inputs routeID = self.request.get('routeID') logging.debug('getvehicles request parameters... routeID %s' % routeID) if api_utils.afterHours() is True: # don't run these jobs during "off" hours json_response = api_utils.buildErrorResponse( '-1', 'The Metro service is not currently running') elif routeID is not '': json_response = routeRequest(routeID) api_utils.recordDeveloperRequest(devStoreKey, api_utils.GETVEHICLES, self.request.query_string, self.request.remote_addr) else: logging.error("API: invalid request") json_response = api_utils.buildErrorResponse( '-1', 'Invalid Request parameters. Did you forget to include a routeID?' ) api_utils.recordDeveloperRequest( devStoreKey, api_utils.GETVEHICLES, self.request.query_string, self.request.remote_addr, 'illegal query string combination') #logging.debug('API: json response %s' % json_response); # encapsulate response in json callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json.dumps(json_response) self.response.out.write(response) stathat.apiStatCount()
def get(self): # validate the request parameters devStoreKey = validateRequest(self.request,api_utils.GETSTOPS) if devStoreKey is None: if( not (self.request.get('key') == 'kiosk' and self.request.get('stopID') == '') ): logging.error("failed to validate the request parameters") self.response.headers['Content-Type'] = 'application/javascript' self.response.out.write(json.dumps(api_utils.buildErrorResponse('-1','Illegal request parameters'))) return # snare the inputs stopID = api_utils.conformStopID(self.request.get('stopID')) routeID = self.request.get('routeID') destination = self.request.get('destination') logging.debug('getstops request parameters... routeID %s destination %s' % (routeID,destination)) if api_utils.afterHours() is True: # don't run these jobs during "off" hours json_response = api_utils.buildErrorResponse('-1','The Metro service is not currently running') elif routeID is not '' and destination is '': json_response = routeRequest(routeID, None) api_utils.recordDeveloperRequest(devStoreKey,api_utils.GETSTOPS,self.request.query_string,self.request.remote_addr); elif routeID is not '' and destination is not '': json_response = routeRequest(routeID, destination) api_utils.recordDeveloperRequest(devStoreKey,api_utils.GETSTOPS,self.request.query_string,self.request.remote_addr); else: logging.error("API: invalid request") json_response = api_utils.buildErrorResponse('-1','Invalid Request parameters. Did you forget to include a routeID?') api_utils.recordDeveloperRequest(devStoreKey,api_utils.GETSTOPS,self.request.query_string,self.request.remote_addr,'illegal query string combination'); #logging.debug('API: json response %s' % json_response); # encapsulate response in json callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json.dumps(json_response) self.response.out.write(response) stathat.apiStatCount() # push event out to anyone watching the live board task = Task(url='/map/task', params={'stopID':stopID}) task.add('eventlogger')
def get(self): # validate the request parameters devStoreKey = validateRequest(self.request) if devStoreKey is None: logging.debug("unable to validate the request parameters") self.response.headers['Content-Type'] = 'application/javascript' self.response.out.write(json.dumps(api_utils.buildErrorResponse('-1','Illegal request parameters'))) return # snare the inputs routeID = self.request.get('routeID') if len(routeID) == 1: routeID = "0" + routeID logging.debug('getvehicles request parameters... routeID %s' % routeID) if api_utils.afterHours() is True: # don't run these jobs during "off" hours json_response = api_utils.buildErrorResponse('-1', 'The Metro service is not currently running') elif routeID is not '': json_response = routeRequest(routeID) api_utils.recordDeveloperRequest(devStoreKey, api_utils.GETVEHICLES, self.request.query_string, self.request.remote_addr); else: logging.error("API: invalid request") json_response = api_utils.buildErrorResponse('-1','Invalid Request parameters. Did you forget to include a routeID?') api_utils.recordDeveloperRequest(devStoreKey, api_utils.GETVEHICLES, self.request.query_string, self.request.remote_addr,'illegal query string combination'); #logging.debug('API: json response %s' % json_response); # encapsulate response in json callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json.dumps(json_response) self.response.out.write(response) stathat.apiStatCount()
def get(self): # validate the request parameters devStoreKey = validateRequest(self.request, api_utils.GETNEARBYSTOPS) if devStoreKey is None: logging.error("unable to validate the request parameters") self.response.headers['Content-Type'] = 'application/json' self.response.out.write( json.dumps( api_utils.buildErrorResponse( '-1', 'Illegal request parameters'))) return # snare the inputs lat = float(self.request.get('lat')) lon = float(self.request.get('lon')) radius = self.request.get('radius') if radius == '' or radius is None: radius = 100 else: radius = int(radius) routeID = self.request.get('routeID') destination = self.request.get('destination') # stop location requests... json_response = nearbyStops(lat, lon, radius, routeID, destination) # encapsulate response in json #logging.debug('API: json response %s' % response); callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json.dumps(json_response) self.response.out.write(response) stathat.apiStatCount()
def get(self): # validate the request parameters devStoreKey = validateRequest(self.request,api_utils.GETNEARBYSTOPS) if devStoreKey is None: logging.error("unable to validate the request parameters") self.response.headers['Content-Type'] = 'application/json' self.response.out.write(json.dumps(api_utils.buildErrorResponse('-1','Illegal request parameters'))) return # snare the inputs lat = float(self.request.get('lat')) lon = float(self.request.get('lon')) radius = self.request.get('radius') if radius == '' or radius is None: radius = 100 else: radius = int(radius) routeID = self.request.get('routeID') destination = self.request.get('destination') # stop location requests... json_response = nearbyStops(lat,lon,radius,routeID,destination) # encapsulate response in json #logging.debug('API: json response %s' % response); callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json.dumps(json_response) self.response.out.write(response) stathat.apiStatCount()
def get(self): start = time.time() # snare the inputs dev_key = self.request.get('key') stopID = api_utils.conformStopID(self.request.get('stopID')) routeID = self.request.get('routeID') vehicleID = self.request.get('vehicleID') #logging.debug('getarrivals request parameters... stopID %s routeID %s vehicleID %s' % (stopID,routeID,vehicleID)) self.request.registry['aggregated_results'] = [] try: if api_utils.afterHours() is False: # and dev_key != 'uwkiosk9': # validate the request parameters devStoreKey = validateRequest(self.request) if devStoreKey is None: # filter out the kiosk errors from the log if (not (dev_key == 'kiosk' and self.request.get('stopID') == '')): logging.error( "failed to validate the request parameters") self.response.headers[ 'Content-Type'] = 'application/javascript' self.response.out.write( json.dumps( api_utils.buildErrorResponse( '-1', 'Unable to validate the request. There may be an illegal developer key.' ))) return if stopID is not '' and routeID is '': json_response = stopRequest(stopID, dev_key) api_utils.recordDeveloperRequest(devStoreKey, api_utils.GETARRIVALS, self.request.query_string, self.request.remote_addr) elif stopID is not '' and routeID is not '': json_response = stopRouteRequest(stopID, routeID, devStoreKey) api_utils.recordDeveloperRequest(devStoreKey, api_utils.GETARRIVALS, self.request.query_string, self.request.remote_addr) elif routeID is not '' and vehicleID is not '': json_response = routeVehicleRequest( routeID, vehicleID, devStoreKey) api_utils.recordDeveloperRequest(devStoreKey, api_utils.GETVEHICLE, self.request.query_string, self.request.remote_addr) else: logging.debug("API: invalid request") api_utils.recordDeveloperRequest( devStoreKey, api_utils.GETARRIVALS, self.request.query_string, self.request.remote_addr, 'illegal query string combination') json_response = api_utils.buildErrorResponse( '-1', 'Invalid Request parameters') # push event out to anyone watching the live board channels = memcache.get('channels') if channels is not None: task = Task(url='/map/task', params={'stopID': stopID}) task.add('eventlogger') # stop statistics - DISABLED # if( "kiosk" not in dev_key ): # task = Task(url='/stats/stop', params={'apikey':dev_key,'stop':stopID}) # task.add('stats') else: # don't run these jobs during "off" hours #logging.debug('shunted... off hour request') #if dev_key.find('kiosk') >= 0: # json_response = api_utils.buildErrorResponse('-1','Kiosk requests no longer supported') #else: json_response = api_utils.buildErrorResponse( '-1', 'The Metro service is not currently running') # encapsulate response in json or jsonp callback = self.request.get('callback') if callback is not '': self.response.headers[ 'Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json.dumps(json_response) self.response.out.write(response) except DeadlineExceededError: self.response.clear() self.response.set_status(500) self.response.out.write( "This operation could not be completed in time...") # persist some statistics # stathat: if api_utils.afterHours() is False and dev_key != 'uwkiosk9': stathat.apiTimeStat(config.STATHAT_API_GETARRIVALS_TIME_KEY, ((time.time() - start) * 1000)) stathat.apiStatCount()
def get(self): start = time.time() # snare the inputs dev_key = self.request.get('key') stopID = api_utils.conformStopID(self.request.get('stopID')) routeID = self.request.get('routeID') vehicleID = self.request.get('vehicleID') #logging.debug('getarrivals request parameters... stopID %s routeID %s vehicleID %s' % (stopID,routeID,vehicleID)) self.request.registry['aggregated_results'] = [] try: if api_utils.afterHours() is False: # and dev_key != 'uwkiosk9': # validate the request parameters devStoreKey = validateRequest(self.request) if devStoreKey is None: # filter out the kiosk errors from the log if( not (dev_key == 'kiosk' and self.request.get('stopID') == '') ): logging.error("failed to validate the request parameters") self.response.headers['Content-Type'] = 'application/javascript' self.response.out.write(json.dumps(api_utils.buildErrorResponse('-1','Unable to validate the request. There may be an illegal developer key.'))) return if stopID is not '' and routeID is '': json_response = stopRequest(stopID, dev_key) api_utils.recordDeveloperRequest(devStoreKey,api_utils.GETARRIVALS,self.request.query_string,self.request.remote_addr); elif stopID is not '' and routeID is not '': json_response = stopRouteRequest(stopID, routeID, devStoreKey) api_utils.recordDeveloperRequest(devStoreKey,api_utils.GETARRIVALS,self.request.query_string,self.request.remote_addr); elif routeID is not '' and vehicleID is not '': json_response = routeVehicleRequest(routeID, vehicleID, devStoreKey) api_utils.recordDeveloperRequest(devStoreKey,api_utils.GETVEHICLE,self.request.query_string,self.request.remote_addr); else: logging.debug("API: invalid request") api_utils.recordDeveloperRequest(devStoreKey,api_utils.GETARRIVALS,self.request.query_string,self.request.remote_addr,'illegal query string combination'); json_response = api_utils.buildErrorResponse('-1','Invalid Request parameters') # push event out to anyone watching the live board channels = memcache.get('channels') if channels is not None: task = Task(url='/map/task', params={'stopID':stopID}) task.add('eventlogger') # stop statistics - DISABLED # if( "kiosk" not in dev_key ): # task = Task(url='/stats/stop', params={'apikey':dev_key,'stop':stopID}) # task.add('stats') else: # don't run these jobs during "off" hours #logging.debug('shunted... off hour request') #if dev_key.find('kiosk') >= 0: # json_response = api_utils.buildErrorResponse('-1','Kiosk requests no longer supported') #else: json_response = api_utils.buildErrorResponse('-1','The Metro service is not currently running') # encapsulate response in json or jsonp callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json.dumps(json_response) self.response.out.write(response) except DeadlineExceededError: self.response.clear() self.response.set_status(500) self.response.out.write("This operation could not be completed in time...") # persist some statistics # stathat: if api_utils.afterHours() is False and dev_key != 'uwkiosk9': stathat.apiTimeStat(config.STATHAT_API_GETARRIVALS_TIME_KEY,((time.time()-start)*1000)) stathat.apiStatCount()
def get(self): events = {} loop = 0 done = False result = None while not done and loop < 3: try: result = urlfetch.fetch("http://www.cityofmadison.com/parkingUtility/garagesLots/availability/") done = True except urlfetch.DownloadError: logging.error("Error loading page (%s)... sleeping" % loop) if result: logging.debug("Error status: %s" % result.status_code) logging.debug("Error header: %s" % result.headers) logging.debug("Error content: %s" % result.content) time.sleep(6) loop = loop + 1 if result is None or result.status_code != 200: logging.error("Exiting early: error fetching URL: " + result.status_code) return # # TODO - rework this section to load the realtime data using the # async calls in parallel with the scraped event data # Because we can cache it, don't worry about it for now, though # specialEvents = memcache.get("ParkingEvents") if specialEvents is None: eventsResult = None specialEventsWarning = memcache.get("ParkingEventsServiceStatus") if (specialEventsWarning < 3) or specialEventsWarning is None: eventsResult = getParkingSpecialEvents() if eventsResult is None or eventsResult.status_code != 200: logging.error("Error fetching special events URL: " + eventsResult.status_code) specialEvents = [] # Ignore race condition - we're not wiping out anything serious if we hit the race anyway # and the atomic incr API doesn't let you set cache expiration times memcache.set( "ParkingEventsServiceStatus", 0 if specialEventsWarning is None else specialEventsWarning + 1, 6 * 3600, ) else: specialEvents = json.loads(eventsResult.content) cacheexpiretime = datetime.datetime.strptime(specialEvents["CacheUntil"], "%Y-%m-%dT%H:%M:%S") diff = cacheexpiretime - datetime.datetime.now() seconds = (diff.days * 86400) + diff.seconds if seconds < 0: # if the data from scraper is stale we need to ignore it logging.debug("API parking: Special events feed is stale") memcache.set( "ParkingEventsServiceStatus", 0 if specialEventsWarning is None else specialEventsWarning + 1, 6 * 3600, ) specialEvents = {} else: logging.info("API: Caching Special Events Parking for %d more seconds" % seconds) memcache.set("ParkingEvents", specialEvents, seconds) searchwindow = self.request.get_range("searchwindow", default=3, min_value=0, max_value=24) testingtimeparam = self.request.get("testingts") if testingtimeparam is "": testingtime = None else: try: testingtime = datetime.datetime.fromtimestamp(float(testingtimeparam)) except ValueError: logging.debug("Invalid date passed for testing, ignoring: %s" % testingtimeparam) events = parseSpecialEvents(specialEvents, searchwindow, testingtime) soup = BeautifulSoup(result.content) json_response = [] getLots(soup, json_response, "dataRow rowShade") getLots(soup, json_response, "dataRow") for lot in json_response: if lot["name"] == "Brayton Lot": lot["address"] = "1 South Butler St." lot["total_spots"] = "243" if events["Brayton Lot"]: lot["SpecialEventNotice"] = events["Brayton Lot"] # lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/brayton.cfm' elif lot["name"] == "Capitol Square North Garage": lot["address"] = "218 East Mifflin St." lot["total_spots"] = "613" if events["Capitol Square North Garage"]: lot["SpecialEventNotice"] = events["Capitol Square North Garage"] # lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/capSquareNorth.cfm' elif lot["name"] == "Government East Garage": lot["address"] = "215 S. Pinckney St." lot["total_spots"] = "516" if events["Government East Garage"]: lot["SpecialEventNotice"] = events["Government East Garage"] # lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/govtEast.cfm' elif lot["name"] == "Overture Center Garage": lot["address"] = "318 W. Mifflin St." lot["total_spots"] = "620" if events["Overture Center Garage"]: lot["SpecialEventNotice"] = events["Overture Center Garage"] # lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/overture.cfm' elif lot["name"] == "State Street Campus Garage": lot["address"] = ["430 N. Frances St.", "415 N. Lake St."] lot["total_spots"] = "1066" if events["State Street Campus Garage"]: lot["SpecialEventNotice"] = events["State Street Campus Garage"] # lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/stateStCampus.cfm' elif lot["name"] == "State Street Capitol Garage": lot["address"] = "214 N. Carroll St." lot["total_spots"] = "855" if events["State Street Capitol Garage"]: lot["SpecialEventNotice"] = events["State Street Capitol Garage"] # lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/stateStCapitol.cfm' # encapsulate response in json or jsonp logging.debug("API: json response %s" % json_response) callback = self.request.get("callback") if callback is not "": self.response.headers["Content-Type"] = "application/javascript" self.response.headers["Access-Control-Allow-Origin"] = "*" self.response.headers["Access-Control-Allow-Methods"] = "GET" response = callback + "(" + json.dumps(json_response) + ");" else: self.response.headers["Content-Type"] = "application/json" response = json.dumps(json_response) stathat.apiStatCount() self.response.out.write(response)
def get(self): events = {} loop = 0 done = False result = None while not done and loop < 3: try: result = urlfetch.fetch( 'http://www.cityofmadison.com/parkingUtility/garagesLots/availability/' ) done = True except urlfetch.DownloadError: logging.error("Error loading page (%s)... sleeping" % loop) if result: logging.debug("Error status: %s" % result.status_code) logging.debug("Error header: %s" % result.headers) logging.debug("Error content: %s" % result.content) time.sleep(6) loop = loop + 1 if result is None or result.status_code != 200: logging.error("Exiting early: error fetching URL: " + result.status_code) return # # TODO - rework this section to load the realtime data using the # async calls in parallel with the scraped event data # Because we can cache it, don't worry about it for now, though # specialEvents = memcache.get('ParkingEvents') if specialEvents is None: eventsResult = None specialEventsWarning = memcache.get('ParkingEventsServiceStatus') if ((specialEventsWarning < 3) or specialEventsWarning is None): eventsResult = getParkingSpecialEvents() if eventsResult is None or eventsResult.status_code != 200: logging.error("Error fetching special events URL: " + eventsResult.status_code) specialEvents = [] # Ignore race condition - we're not wiping out anything serious if we hit the race anyway # and the atomic incr API doesn't let you set cache expiration times memcache.set( 'ParkingEventsServiceStatus', 0 if specialEventsWarning is None else specialEventsWarning + 1, 6 * 3600) else: specialEvents = json.loads(eventsResult.content) cacheexpiretime = datetime.datetime.strptime( specialEvents['CacheUntil'], "%Y-%m-%dT%H:%M:%S") diff = cacheexpiretime - datetime.datetime.now() seconds = (diff.days * 86400) + diff.seconds if seconds < 0: # if the data from scraper is stale we need to ignore it logging.debug( 'API parking: Special events feed is stale') memcache.set( 'ParkingEventsServiceStatus', 0 if specialEventsWarning is None else specialEventsWarning + 1, 6 * 3600) specialEvents = {} else: logging.info( "API: Caching Special Events Parking for %d more seconds" % seconds) memcache.set('ParkingEvents', specialEvents, seconds) searchwindow = self.request.get_range('searchwindow', default=3, min_value=0, max_value=24) testingtimeparam = self.request.get('testingts') if testingtimeparam is '': testingtime = None else: try: testingtime = datetime.datetime.fromtimestamp( float(testingtimeparam)) except ValueError: logging.debug("Invalid date passed for testing, ignoring: %s" % testingtimeparam) events = parseSpecialEvents(specialEvents, searchwindow, testingtime) soup = BeautifulSoup(result.content) json_response = [] getLots(soup, json_response, "dataRow rowShade") getLots(soup, json_response, "dataRow") for lot in json_response: if lot['name'] == 'Brayton Lot': lot['address'] = '1 South Butler St.' lot['total_spots'] = '243' if events['Brayton Lot']: lot['SpecialEventNotice'] = events['Brayton Lot'] #lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/brayton.cfm' elif lot['name'] == 'Capitol Square North Garage': lot['address'] = '218 East Mifflin St.' lot['total_spots'] = '613' if events['Capitol Square North Garage']: lot['SpecialEventNotice'] = events[ 'Capitol Square North Garage'] #lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/capSquareNorth.cfm' elif lot['name'] == 'Government East Garage': lot['address'] = '215 S. Pinckney St.' lot['total_spots'] = '516' if events['Government East Garage']: lot['SpecialEventNotice'] = events[ 'Government East Garage'] #lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/govtEast.cfm' elif lot['name'] == 'Overture Center Garage': lot['address'] = '318 W. Mifflin St.' lot['total_spots'] = '620' if events['Overture Center Garage']: lot['SpecialEventNotice'] = events[ 'Overture Center Garage'] #lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/overture.cfm' elif lot['name'] == 'State Street Campus Garage': lot['address'] = ['430 N. Frances St.', '415 N. Lake St.'] lot['total_spots'] = '1066' if events['State Street Campus Garage']: lot['SpecialEventNotice'] = events[ 'State Street Campus Garage'] #lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/stateStCampus.cfm' elif lot['name'] == 'State Street Capitol Garage': lot['address'] = '214 N. Carroll St.' lot['total_spots'] = '855' if events['State Street Capitol Garage']: lot['SpecialEventNotice'] = events[ 'State Street Capitol Garage'] #lot['url'] = 'http://www.cityofmadison.com/parkingUtility/garagesLots/facilities/stateStCapitol.cfm' # encapsulate response in json or jsonp logging.debug('API: json response %s' % json_response) callback = self.request.get('callback') if callback is not '': self.response.headers['Content-Type'] = 'application/javascript' self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Methods'] = 'GET' response = callback + '(' + json.dumps(json_response) + ');' else: self.response.headers['Content-Type'] = 'application/json' response = json.dumps(json_response) stathat.apiStatCount() self.response.out.write(response)