def test_humanize_join(self): seq = ['1', '2', '3', '4'] separator = '[_]' spacing = '>' output = utils.humanize_join(seq, separator=separator, conjunction='and', oxford_comma=False) self.assertEqual('1[_] 2[_] 3 and 4', output) output = utils.humanize_join(seq, separator=separator, conjunction='and', oxford_comma=True) self.assertEqual('1[_] 2[_] 3[_] and 4', output) output = utils.humanize_join(seq, separator=separator, conjunction='or', oxford_comma=True) self.assertEqual('1[_] 2[_] 3[_] or 4', output) separator = '-' output = utils.humanize_join(seq, separator=separator, spacing=spacing, conjunction='or', oxford_comma=True) self.assertEqual('1->2->3->or>4', output)
def execute(self, **kwargs): """Retrieve the latest weather for the provided location for the given time. Keyword arguments: last -- if True, return the last retrieved weather data where -- the location to get weather data for (defaults to current location) Can be an alias (defined in the configuration file) when -- one of 'today' or 'tomorrow' (default 'today') """ if kwargs.get("last", None): if self.last: if time.time() < self.last[1].ttl: yield "Data for {0}: {1}".format(self.last[0], self.last[1].val) return else: self.last = None raise plugin.UnsuccessfulExecution("No recent data stored.") if "where" not in kwargs: try: # Try to call on latitude plugin to get the current location kwargs["where"] = re.sub( "[() ]", "", self.registrar.request_service('location', noreverse=True)) except: #raise plugin.UnsuccessfulExecution("No current location is available.") kwargs["where"] = (yield "I could not find your current location, " "where do you want weather for?")["_raw"] forecastday = 0 if "when" in kwargs: if kwargs["when"].upper() == "TODAY": forecastday = 0 if kwargs["when"].upper() == "TOMORROW": forecastday = 1 location = kwargs["where"] # Sub any aliases if location in self.locations: location = self.locations[location] # Look in the cache, pick item with minimum distance from location, then # check to see if it's within the tolerance if len(self.cache) > 0: cache_hit_distances = ((item, self.distance(location, item)) for item in self.cache) closest_hit = min(cache_hit_distances, key=lambda x: x[1])[0] if closest_hit < self.max_cache_distance: if time.time() < self.cache[location].expires: yield self.cache[location].val return else: self.cache.pop(location, None) url = "http://api.wunderground.com/api/{0}/forecast".format( self.api_key) query = "/q/{0}.json".format(re.sub('\s+', '_', location)) resp = json.load(urllib2.urlopen(urllib2.Request(url + query))) if not resp: raise plugin.UnsuccessfulExecution("Parsing failed for location " + location) ret = None if 'results' in resp['response']: results = resp['response']['results'] while len(results) > 1: ret = "Did you mean " states = set() countries = set() for result in results: if result['state'] != '': states.add(result['state'].lower()) elif result['country'] != '': countries.add(result['country'].lower()) if len(states) > 0: ret += "the state" if len(states) > 1: ret += "s" ret += ' ' + utils.humanize_join( abbrev.states.try_long(x).capitalize() for x in states) if len(countries) > 0: if len(states) > 0: ret += " or " ret += "the country" if len(countries) > 1: ret += "s" ret += ' ' + utils.humanize_join( abbrev.countries.try_long(x).capitalize() for x in countries) ret += "?" # TODO better parsing of conversation arguments cont = (yield ret)['_raw'].split() old_results = results results = [] for word in cont: # Try to convert long name to abbrev state = abbrev.states.try_short(word) country = abbrev.countries.try_short(word) for result in old_results: if result['state'].lower() == state.lower(): results.append(result) elif result['country'].lower() == country.lower(): results.append(result) if len(results) == 0: # Invalid input was given, back up results = old_results query = results[0]['l'] + '.json' resp = json.load(urllib2.urlopen(urllib2.Request(url + query))) if not resp: raise plugin.UnsuccessfulExecution( "Parsing failed for location " + location) try: forecast = resp['forecast']['txt_forecast']['forecastday'] ret = forecast[forecastday]['fcttext'] except KeyError as err: logger.log("Error parsing forecast:", err) if not ret: raise plugin.UnsuccessfulExecution( "There is no weather data for this location") self.last = (location, self.CacheItem(time.time() + self.ttl, ret)) self.cache[location] = self.last[1] yield ret
def execute(self, **kwargs): """Retrieve the latest weather for the provided location for the given time. Keyword arguments: last -- if True, return the last retrieved weather data where -- the location to get weather data for (defaults to current location) Can be an alias (defined in the configuration file) when -- one of 'today' or 'tomorrow' (default 'today') """ if kwargs.get("last", None): if self.last: if time.time() < self.last[1].ttl: yield "Data for {0}: {1}".format(self.last[0], self.last[1].val) return else: self.last = None raise plugin.UnsuccessfulExecution("No recent data stored.") if "where" not in kwargs: try: # Try to call on latitude plugin to get the current location kwargs["where"] = re.sub("[() ]", "", self.registrar.request_service('location', noreverse=True)) except: #raise plugin.UnsuccessfulExecution("No current location is available.") kwargs["where"] = (yield "I could not find your current location, " "where do you want weather for?")["_raw"] forecastday = 0 if "when" in kwargs: if kwargs["when"].upper() == "TODAY": forecastday = 0 if kwargs["when"].upper() == "TOMORROW": forecastday = 1 location = kwargs["where"] # Sub any aliases if location in self.locations: location = self.locations[location] # Look in the cache, pick item with minimum distance from location, then # check to see if it's within the tolerance if len(self.cache) > 0: cache_hit_distances = ((item, self.distance(location, item)) for item in self.cache) closest_hit = min(cache_hit_distances, key=lambda x: x[1])[0] if closest_hit < self.max_cache_distance: if time.time() < self.cache[location].expires: yield self.cache[location].val return else: self.cache.pop(location, None) url = "http://api.wunderground.com/api/{0}/forecast".format(self.api_key) query = "/q/{0}.json".format(re.sub('\s+', '_', location)) resp = json.load(urllib2.urlopen(urllib2.Request(url + query))) if not resp: raise plugin.UnsuccessfulExecution( "Parsing failed for location " + location) ret = None if 'results' in resp['response']: results = resp['response']['results'] while len(results) > 1: ret = "Did you mean " states = set() countries = set() for result in results: if result['state'] != '': states.add(result['state'].lower()) elif result['country'] != '': countries.add(result['country'].lower()) if len(states) > 0: ret += "the state" if len(states) > 1: ret += "s" ret += ' ' + utils.humanize_join( abbrev.states.try_long(x).capitalize() for x in states) if len(countries) > 0: if len(states) > 0: ret += " or " ret += "the country" if len(countries) > 1: ret += "s" ret += ' ' + utils.humanize_join( abbrev.countries.try_long(x).capitalize() for x in countries) ret += "?" # TODO better parsing of conversation arguments cont = (yield ret)['_raw'].split() old_results = results results = [] for word in cont: # Try to convert long name to abbrev state = abbrev.states.try_short(word) country = abbrev.countries.try_short(word) for result in old_results: if result['state'].lower() == state.lower(): results.append(result) elif result['country'].lower() == country.lower(): results.append(result) if len(results) == 0: # Invalid input was given, back up results = old_results query = results[0]['l'] + '.json' resp = json.load(urllib2.urlopen(urllib2.Request(url + query))) if not resp: raise plugin.UnsuccessfulExecution( "Parsing failed for location " + location) try: forecast = resp['forecast']['txt_forecast']['forecastday'] ret = forecast[forecastday]['fcttext'] except KeyError as err: logger.log("Error parsing forecast:", err) if not ret: raise plugin.UnsuccessfulExecution( "There is no weather data for this location") self.last = (location, self.CacheItem(time.time() + self.ttl, ret)) self.cache[location] = self.last[1] yield ret