diff --git a/checks/__init__.py b/checks/__init__.py index 3d1d5a5..3065c04 100644 --- a/checks/__init__.py +++ b/checks/__init__.py @@ -21,6 +21,7 @@ from checks import load_in_browser from checks import page_content from checks import url_canonicalization from checks import url_reachability +from checks import green_power from checks.config import Config @@ -50,6 +51,7 @@ def perform_checks(input_url): ('load_favicons', load_favicons), ('load_feeds', load_feeds), ('load_in_browser', load_in_browser), + ('green_power', green_power), ] results = {} diff --git a/checks/green_power.py b/checks/green_power.py new file mode 100644 index 0000000..4f448ab --- /dev/null +++ b/checks/green_power.py @@ -0,0 +1,56 @@ +""" +This check looks up the domain of site against the Green Web Foundation API, +to confirm that sites in the green party, run on green power, rather +than fossil fuels. +""" + +import logging + +import requests +from urllib.parse import urlparse + +from checks.abstract_checker import AbstractChecker + +logger = logging.getLogger(__name__) + + +class Checker(AbstractChecker): + + API_ENDPOINT = "http://api.thegreenwebfoundation.org/greencheck/" + + def __init__(self, config, previous_results=None): + super().__init__(config, previous_results) + + def run(self): + """Executes the check routine, returns result dict""" + + results = {} + + urls = list(self.config.urls) + for url in urls: + hostname = urlparse(url).hostname + results[url] = self.check_for_green_power(hostname) + + return results + + def check_for_green_power(self, url): + """ + Checks the url passed in agains the Green web Foundation API + to see if the domain known to be running on green power. + """ + # use the "big tarp" to catch the error, but don't crash the program + # returning false because we didn't come back with any evidence that + # the site uses green power + # more on the big tarp: + # https://www.loggly.com/blog/exceptional-logging-of-exceptions-in-python/ + check_url = f"{self.API_ENDPOINT}{url}" + + try: + result = requests.get(check_url) + return result.json().get('green') + except Exception: + logger.exception("Requesting data from the API failed") + + return False + + diff --git a/checks/green_power_test.py b/checks/green_power_test.py new file mode 100644 index 0000000..dec9ec8 --- /dev/null +++ b/checks/green_power_test.py @@ -0,0 +1,22 @@ +import unittest + +from checks import green_power +from checks.config import Config + +class TestGreenPower(unittest.TestCase): + + def test_is_green(self): + """Check that we get a green result for green powered site""" + # google is green, Koch Industries. predictably is not + # TODO mock the result, so we don't need to hit a live API + config = Config(urls=['https://google.com/']) + checker = green_power.Checker(config=config) + result = checker.run() + self.assertEqual(result['https://google.com/'], True) + + def test_is_not_green(self): + """Check that we get a grey result for grey powered site""" + config = Config(urls=['http://www.kochind.com/']) + checker = green_power.Checker(config=config) + result = checker.run() + self.assertEqual(result['http://www.kochind.com/'], False) \ No newline at end of file diff --git a/rating/__init__.py b/rating/__init__.py index 4d247b5..9c09097 100644 --- a/rating/__init__.py +++ b/rating/__init__.py @@ -22,6 +22,7 @@ from rating import responsive_layout from rating import social_media_links from rating import use_specific_fonts from rating import www_optional +from rating import green_power def calculate_rating(results): @@ -51,6 +52,7 @@ def calculate_rating(results): 'SOCIAL_MEDIA_LINKS': social_media_links, 'USE_SPECIFIC_FONTS': use_specific_fonts, 'WWW_OPTIONAL': www_optional, + 'GREEN_POWER': green_power, } output = {} diff --git a/rating/green_power.py b/rating/green_power.py new file mode 100644 index 0000000..d6ee97d --- /dev/null +++ b/rating/green_power.py @@ -0,0 +1,31 @@ +""" +This checks the result for an url using green power, and returns +a boolean based on whether it's using green power or not +""" + +from rating.abstract_rater import AbstractRater + +class Rater(AbstractRater): + + rating_type = 'boolean' + default_value = False + depends_on_checks = ['green_power'] + max_score = 1 + + def __init__(self, check_results): + super().__init__(check_results) + + def rate(self): + value = self.default_value + score = 0 + + if check_results['green_power']: + value = True + score = self.max_score + + return { + 'type': self.rating_type, + 'value': value, + 'score': score, + 'max_score': self.max_score, + } \ No newline at end of file