Example #1
0
    def test_cache_clear(self):
        """ Test cache clearing by downloading a page (and thus 
        creating the cached version), then asking for it to be cleared,
        and checking if the file still exists """

        # download a test page first - make sure it is cached
        climate.get_climate_data("Melbourne")

        # clear, and see if it reports successful
        paths = cache.clear("Melbourne")
        self.assertEqual(cache.exists("Melbourne"), False)

        # check if file physically exists
        for path in paths:
            self.assertFalse(os.path.exists(path))
Example #2
0
    def test_cache_clear_all(self):
        """ Test cache clearing by downloading a page (and thus 
        creating the cached version), then asking for everything 
        to be cleared, and checking if files reported exist """
        # download a test page first - make sure it is cached
        climate.get_climate_data("Melbourne")

        paths = cache.clear_all()

        # see if it self-reports successful for the test page
        self.assertEquals(cache.exists("Melbourne"), False)

        # check if files physically exists
        for path in paths:
            self.assertFalse(os.path.exists(path))
Example #3
0
    def test_any_unicode(self):
        """arbitrary unicode should work in query"""

        pagenames = ["Reykjavík", "Gdańsk", "香港", "ᐃᓄᒃᑕᐅᑦ"]

        for pagename in pagenames:
            data = climate.get_climate_data(pagename)
Example #4
0
    def test_nonexistent_page(self):
        """nonexisting page should give corresponding error message"""

        data = climate.get_climate_data("Fakey Place, gdsngkjdsnk")

        self.assertEqual(data["page_error"], True)
        self.assertEqual(data["title"].endswith("location not found"), True)
Example #5
0
    def test_weatherbox_cached_template(self):
        """ Test a New York City-specific weatherbox use that invokes
        a pre-rendered {{New York City weatherbox/cached}} template.
        More information in a comment in 
        climate.get_climate_data.find_separate_weatherbox_template """

        data = climate.get_climate_data("New York City")

        self.assertEqual(data["record high C"][2], 30.0)  # March
        self.assertEqual(data["low C"][10], 5.3)  # November
Example #6
0
    def test_unicode_page_name(self):
        """Page that is accessible on Wikipedia via a Unicode name 
        should return correct climate info.
        Test with Jan high and Dec record low for Hong Kong (香港)"""

        data = climate.get_climate_data("香港")

        self.assertEqual(data["title"], "Hong Kong")
        self.assertEqual(data["high C"][0], 18.6)
        self.assertEqual(data["record low C"][11], 4.3)
Example #7
0
    def test_cache_timing(self):
        """ Bit of a wonky test: test actual caching by comparing time
        to load a page uncached and time to load it cached. The latter
        should be shorter.
        Might fail with a false negative if filesystem is being slow 
        at the moment, but in general it should work pretty well. """

        page = "Melbourne"
        cache.clear(page)

        time1 = time.time()
        climate.get_climate_data(page)
        time_with_no_cache = time.time() - time1

        time2 = time.time()
        climate.get_climate_data(page)
        time_with_cache = time.time() - time2

        self.assertTrue(time_with_cache < time_with_no_cache)
Example #8
0
    def test_no_climate_data(self):
        """page with no climate data should return a default
        initialized-but-empty result set"""

        pagename = "Elmira, Ontario"
        data = climate.get_climate_data(pagename)

        self.assertEqual(data["page_error"], False)
        self.assertEqual(data["title"], pagename)

        for row_name in climate.ROWS:
            self.assertEqual(len(data[row_name]), 0)
Example #9
0
    def test_cache_timeout(self):
        """ Make sure files older than 7 days are treated as not valid
        for cache purposes. Fake this with changing a file's 
        modified time with os.utime() """

        page = "Melbourne"

        climate.get_climate_data(page)
        self.assertEqual(cache.exists(page), True)

        # cache.get_file_name should really be treated as private
        # most of the time, but for the purposes of the test
        # it's OK to use it I guess
        file_name = cache.get_file_name(page)

        # set new filetime to (max cache age + 1 day) ago
        new_file_datetime = datetime.now() - timedelta(cache.CACHE_PERIOD_DAYS + 1, 0)
        new_file_timestamp = time.mktime(new_file_datetime.timetuple())

        # use the new timestamp as both access time and modify time
        os.utime(file_name, (new_file_timestamp, new_file_timestamp))

        # assert it's now reported as not cacheable
        self.assertEqual(cache.exists(page), False)
Example #10
0
    def test_unit_conversion(self):
        """ Test for correct conversion of units. Includes F->C and 
        inches to mm and cm. Based on data for Seattle and NYC. """

        known_data = {
            "New York City": {
                "precipitation mm": {5: 112, 10: 102.1},  # jun, nov
                "snow cm": {0: 17.8, 5: 0, 11: 12.2},  # jan, jun, dec
            },
            "Seattle": {
                "high C": {3: 14.7},  # april
                "record low C": {1: -17.2, 7: 6.7},  # feb, aug
                "precipitation mm": {0: 141.5, 6: 17.8},  # jan, jul
                "snow cm": {1: 4.3, 11: 4.3, 5: 0},  # feb, dec, jun
            },
        }

        for city, data in known_data.items():
            actual_data = climate.get_climate_data(city)

            for key, key_data in data.items():
                for month, expected_value in key_data.items():
                    self.assertEqual(actual_data[key][month], expected_value)
Example #11
0
    def test_cache_create(self):
        """ Really basic test: get a page, then check if it is 
        reported as having cache available. """

        climate.get_climate_data("Melbourne")
        self.assertEqual(cache.exists("Melbourne"), True)
Example #12
0
    def test_redirect(self):
        """wikipedia redirects should be followed"""

        data = climate.get_climate_data("nyc")

        self.assertEqual(data["title"], "New York City")
Example #13
0
    def test_known_data(self):
        """Test for correct retrieval of some data for some cities.
        Test against known-correct values retrieved via browser at time
        of test authoring.
        Basically make sure future changes don't mess up known-working
        queries."""

        known_data = {
            "Vancouver": {
                "record high C": {6: 34.4},  # july
                "mean C": {9: 10.3},  # october
                "precipitation mm": {7: 36.7},  # august
            },
            "Mount Fuji": {
                # tests cleaning of "&minus;10.9"-like values
                "high C": {2: -10.9},  # march
                "record low C": {0: -37.3},  # january
            },
            "Seattle": {
                # temperatures here also test conversion into C
                "high C": {3: 14.7},  # april
                "record low C": {1: -17.2, 7: 6.7},  # feb, aug
                "precipitation days": {10: 18.4},  # november
                "sun": {7: 281.4},  # august
            },
            "Calgary": {
                "snow cm": {2: 17.1},  # march
                "mean C": {4: 9.8},  # may
                "low C": {10: -7.5},  # november
                "record low C": {1: -38},  # february
            },
            "Melbourne": {
                "record high C": {1: 46.4},  # february
                "record low C": {6: -2.8},  # july
                "sun": {5: 108},  # june
            },
            "Toronto": {
                "mean C": {6: 22.3},  # july
                "snow days": {0: 12.0, 4: 0},  # january, may
                "record low C": {11: -30},  # december
                "rain mm": {7: 81.1},  # august
                "sun": {4: 227.7},  # may
            },
            # for Sydney, test conversion from daily sun hours, as
            # specified on wiki page, into monthly hours, as used
            # elsewhere in the script
            "Sydney": {
                "sun": {11: 235.6, 5: 165},  # december, june
                "record high C": {0: 45.8},  # january
                "record low C": {3: 7},  # april
                "rain days": {5: 12.5},
                "rain mm": {8: 68.3},
            },
        }

        for city, data in known_data.items():
            actual_data = climate.get_climate_data(city)

            for key, key_data in data.items():
                for month, expected_value in key_data.items():
                    self.assertEqual(actual_data[key][month], expected_value)
Example #14
0
    def get(self, irc, msg, args, strings):
        """ <text> (including <places>, <months>, <categories>)
        Gets climate data for <places> during <months> for <categories>.
        Normally at least one each of place and month are required,
        except script will pick most contrasting month if two cities are given.
        Category will default to average high temperature if not specified.
        Get the list of recognized <categories> with `@climate categories`.
        Places, months, and categories can be mixed within <text> in any order.
        Unrecognized words will be silently ignored (this means you can write
        e.g. "Toronto and Sydney high for December"). """

        import climate

        query = climate.parse_text_query(strings)

        cities = query['cities']
        months = query['months']
        categories = query['categories']

        has_category = False
        has_month = False

        for month in months:
            has_month = has_month or month

        for category in categories:
            has_category = has_category or categories[category]

        if has_category is False:
            # default to showing high temperature if no category is specified
            categories['high C'] = True
            has_category = True

        if has_month is True:
            data = climate.get_comparison_data(cities, months, categories)
        elif len(cities) == 2:
            # get data for all, and pick most interesting one automagically
            # criterion is biggest difference between the numerical values
            # among chosen categories for the chosen cities

            # for now only two cities are supported
            # TODO: expand to arbitrary amount - will need to round-robin
            # the calculations or something

            for i in range(len(months)):
                months[i] = True

            data = climate.get_comparison_data(cities, months, categories)

            # get cities' names directly from data - they are likely 
            # different than in request (capitalization, redirects, etc)
            data_cities = data[data.keys()[0]].keys()

            comparisons = {}
            sums = {}
            for i in range(len(data_cities)):
                city = data_cities[i]
                for category,category_include in categories.items():
                    if not category_include:
                        continue

                    if category == 'location':
                        # only non-numerical 'category' so far. cannot 
                        # be compared. detect this case more robustly if we
                        # get more non-numerical categories
                        continue

                    if category not in comparisons:
                        comparisons[category] = {}
                        sums[category] = []

                    for month,month_include in enumerate(months):
                        if not month_include:
                            continue

                        if not month in comparisons[category]:
                            comparisons[category][month] = {}

                        comparisons[category][month][city] = \
                            data[month][city][category]

                    if i > 0:
                        for m,dummy_var in enumerate(months):
                            # calculate difference between the two cities for
                            # each month

                            # order within sums[category] list will be created
                            # automagically
                            sums[category].append(abs( \
                                comparisons[category][m][data_cities[i-1]] - \
                                comparisons[category][m][data_cities[i]]))

            max_month = -1
            max_value = float('-inf')
            for category in categories:
                if category in sums:
                    category_max = max(sums[category])
                    category_index = sums[category].index(category_max)
                    if category_max > max_value:
                        max_value = category_max
                        max_month = category_index

            filtered_data = {}
            if max_month > -1:
                filtered_data[max_month] = data[max_month]
            data = filtered_data
        else:
            # not supported, return empty
            data = {}

        # output format is roughly:
        """October: Toronto high 10, Melbourne high 20; April: Toronto high 10, Melbourne high 15

October: Toronto high 10, low 5, Melbourne high 20, low 12; April: Toronto high 10, low 3, Melbourne high 15, low 8"""
        # so each month first, then each city with its categories grouped

        output = []
        for month,month_data in data.items():
            month_line = calendar.month_name[month+1] + ': '

            city_lines = []
            for city,city_data in month_data.items():
                city_line = city + ' '

                category_lines = []
                for category,category_data in city_data.items():
                    if category in climate.PRINTED_ROW_TITLES:
                        category_lines.append(
                            climate.PRINTED_ROW_TITLES[category]
                            + ' ' + str(int(round(category_data, 0))))

                city_line += ', '.join(category_lines)
                city_lines.append(city_line)

            month_line += ', '.join(city_lines)
            output.append(month_line)

        output = '; '.join(output)

        response = ''
        if len(output) > 0:
            response = output
        elif len(cities) == 1 and 'location' in categories \
            and categories['location'] == True:
            data = climate.get_climate_data(cities[0])
            if 'location' in data and len(data['location']) > 0:
                response = data['title'] + ': ' + data['location']
        
        if len(response) == 0:
            response = 'No data found or invalid query. Try @help climate get.'

        irc.reply(response.encode('utf-8'), prefixNick = False)