diff options
author | 2020-12-13 23:26:07 -0500 | |
---|---|---|
committer | 2020-12-13 23:26:07 -0500 | |
commit | 13ffd1229b50b9ffac22bec404184601c74ddc7c (patch) | |
tree | 613f009014f660d2786dd786eedd64496403a801 /pydis_site | |
parent | Add tests for infraction deletion method (diff) | |
parent | Merge pull request #437 from python-discord/bugfix/lemon/snekbox-not-showing-... (diff) |
Merge branch 'master' into ks123/infractions/delete-method
Diffstat (limited to 'pydis_site')
-rw-r--r-- | pydis_site/apps/home/tests/test_repodata_helpers.py | 8 | ||||
-rw-r--r-- | pydis_site/apps/home/views/home.py | 149 | ||||
-rw-r--r-- | pydis_site/settings.py | 4 | ||||
-rw-r--r-- | pydis_site/templates/home/index.html | 98 |
4 files changed, 130 insertions, 129 deletions
diff --git a/pydis_site/apps/home/tests/test_repodata_helpers.py b/pydis_site/apps/home/tests/test_repodata_helpers.py index 77b1a68d..34bbdcde 100644 --- a/pydis_site/apps/home/tests/test_repodata_helpers.py +++ b/pydis_site/apps/home/tests/test_repodata_helpers.py @@ -123,10 +123,4 @@ class TestRepositoryMetadataHelpers(TestCase): mock_get.return_value.json.return_value = ['garbage'] metadata = self.home_view._get_repo_data() - self.assertEquals(len(metadata), len(self.home_view.repos)) - for item in metadata: - with self.subTest(item=item): - self.assertEqual(item.description, "Not available.") - self.assertEqual(item.forks, 999) - self.assertEqual(item.stargazers, 999) - self.assertEqual(item.language, "Python") + self.assertEquals(len(metadata), 0) diff --git a/pydis_site/apps/home/views/home.py b/pydis_site/apps/home/views/home.py index c1c2055c..0e5d4edf 100644 --- a/pydis_site/apps/home/views/home.py +++ b/pydis_site/apps/home/views/home.py @@ -1,4 +1,4 @@ -import datetime +import logging from typing import Dict, List import requests @@ -10,11 +10,13 @@ from django.views import View from pydis_site.apps.home.models import RepositoryMetadata +log = logging.getLogger(__name__) + class HomeView(View): """The main landing page for the website.""" - github_api = "https://api.github.com/users/python-discord/repos" + github_api = "https://api.github.com/users/python-discord/repos?per_page=100" repository_cache_ttl = 3600 # Which of our GitHub repos should be displayed on the front page, and in which order? @@ -28,76 +30,88 @@ class HomeView(View): ] def _get_api_data(self) -> Dict[str, Dict[str, str]]: - """Call the GitHub API and get information about our repos.""" - repo_dict: Dict[str, dict] = {repo_name: {} for repo_name in self.repos} + """ + Call the GitHub API and get information about our repos. + + If we're unable to get that info for any reason, return an empty dict. + """ + repo_dict = {} # Fetch the data from the GitHub API api_data: List[dict] = requests.get(self.github_api).json() # Process the API data into our dict for repo in api_data: - full_name = repo["full_name"] - - if full_name in self.repos: - repo_dict[full_name] = { - "full_name": repo["full_name"], - "description": repo["description"], - "language": repo["language"], - "forks_count": repo["forks_count"], - "stargazers_count": repo["stargazers_count"], - } + try: + full_name = repo["full_name"] + + if full_name in self.repos: + repo_dict[full_name] = { + "full_name": repo["full_name"], + "description": repo["description"], + "language": repo["language"], + "forks_count": repo["forks_count"], + "stargazers_count": repo["stargazers_count"], + } + # Something is not right about the API data we got back from GitHub. + except (TypeError, ConnectionError, KeyError) as e: + log.error( + "Unable to parse the GitHub repository metadata from response!", + extra={ + 'api_data': api_data, + 'error': e + } + ) + continue return repo_dict def _get_repo_data(self) -> List[RepositoryMetadata]: """Build a list of RepositoryMetadata objects that we can use to populate the front page.""" - # Try to get site data from the cache - try: - repo_data = RepositoryMetadata.objects.get(repo_name="python-discord/site") + database_repositories = [] - # If the data is stale, we should refresh it. - if (timezone.now() - repo_data.last_updated).seconds > self.repository_cache_ttl: + # First, let's see if we have any metadata cached. + cached_data = RepositoryMetadata.objects.all() - # Try to get new data from the API. If it fails, return the cached data. - try: - api_repositories = self._get_api_data() - except (TypeError, ConnectionError): - return RepositoryMetadata.objects.all() - database_repositories = [] - - # Update or create all RepoData objects in self.repos - for repo_name, api_data in api_repositories.items(): - try: - repo_data = RepositoryMetadata.objects.get(repo_name=repo_name) - repo_data.description = api_data["description"] - repo_data.language = api_data["language"] - repo_data.forks = api_data["forks_count"] - repo_data.stargazers = api_data["stargazers_count"] - except RepositoryMetadata.DoesNotExist: - repo_data = RepositoryMetadata( - repo_name=api_data["full_name"], - description=api_data["description"], - forks=api_data["forks_count"], - stargazers=api_data["stargazers_count"], - language=api_data["language"], - ) - repo_data.save() - database_repositories.append(repo_data) - return database_repositories - - # Otherwise, if the data is fresher than 2 minutes old, we should just return it. - else: - return RepositoryMetadata.objects.all() + # If we don't, we have to create some! + if not cached_data: - # If this is raised, the database has no repodata at all, we will create them all. - except RepositoryMetadata.DoesNotExist: - database_repositories = [] - try: - # Get new data from API - api_repositories = self._get_api_data() + # Try to get new data from the API. If it fails, we'll return an empty list. + # In this case, we simply don't display our projects on the site. + api_repositories = self._get_api_data() + + # Create all the repodata records in the database. + for api_data in api_repositories.values(): + repo_data = RepositoryMetadata( + repo_name=api_data["full_name"], + description=api_data["description"], + forks=api_data["forks_count"], + stargazers=api_data["stargazers_count"], + language=api_data["language"], + ) - # Create all the repodata records in the database. - for api_data in api_repositories.values(): + repo_data.save() + database_repositories.append(repo_data) + + return database_repositories + + # If the data is stale, we should refresh it. + if (timezone.now() - cached_data[0].last_updated).seconds > self.repository_cache_ttl: + # Try to get new data from the API. If it fails, return the cached data. + api_repositories = self._get_api_data() + + if not api_repositories: + return RepositoryMetadata.objects.all() + + # Update or create all RepoData objects in self.repos + for repo_name, api_data in api_repositories.items(): + try: + repo_data = RepositoryMetadata.objects.get(repo_name=repo_name) + repo_data.description = api_data["description"] + repo_data.language = api_data["language"] + repo_data.forks = api_data["forks_count"] + repo_data.stargazers = api_data["stargazers_count"] + except RepositoryMetadata.DoesNotExist: repo_data = RepositoryMetadata( repo_name=api_data["full_name"], description=api_data["description"], @@ -105,23 +119,14 @@ class HomeView(View): stargazers=api_data["stargazers_count"], language=api_data["language"], ) - repo_data.save() - database_repositories.append(repo_data) - except TypeError: - for repo_name in self.repos: - repo_data = RepositoryMetadata( - last_updated=timezone.now() - datetime.timedelta(minutes=50), - repo_name=repo_name, - description="Not available.", - forks=999, - stargazers=999, - language="Python", - ) - repo_data.save() - database_repositories.append(repo_data) - + repo_data.save() + database_repositories.append(repo_data) return database_repositories + # Otherwise, if the data is fresher than 2 minutes old, we should just return it. + else: + return RepositoryMetadata.objects.all() + def get(self, request: WSGIRequest) -> HttpResponse: """Collect repo data and render the homepage view.""" repo_data = self._get_repo_data() diff --git a/pydis_site/settings.py b/pydis_site/settings.py index 204ce58f..449a343f 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -28,11 +28,11 @@ if typing.TYPE_CHECKING: env = environ.Env( DEBUG=(bool, False), - SITE_SENTRY_DSN=(str, "") + SITE_DSN=(str, "") ) sentry_sdk.init( - dsn=env('SITE_SENTRY_DSN'), + dsn=env('SITE_DSN'), integrations=[DjangoIntegration()], send_default_pii=True, release=f"pydis-site@{GIT_SHA}" diff --git a/pydis_site/templates/home/index.html b/pydis_site/templates/home/index.html index 72a5f67c..a98613a3 100644 --- a/pydis_site/templates/home/index.html +++ b/pydis_site/templates/home/index.html @@ -130,57 +130,59 @@ </section> <!-- Projects --> - <section id="projects" class="section"> - <div class="container"> - <h1 class="is-size-1">Projects</h1> - - <div class="columns is-multiline is-tablet"> - - {# Generate project data from HomeView.repos #} - {% for repo in repo_data %} - <div class="column is-one-third-desktop is-half-tablet"> - - <a href="https://github.com/{{ repo.repo_name }}"> - <article class="card"> - - <header class="card-header"> - <span class="card-header-icon"> - <span class="icon"><i class="fab fa-github"></i></span> - </span> - <div class="card-header-title"> - {{ repo.repo_name|cut:"python-discord/" }} - </div> - </header> - - <p class="card-content"> - {{ repo.description }} - </p> - - <footer class="card-footer"> - <div class="card-footer-item"> - <i class="repo-language-dot {{ repo.language | lower }}"></i> - {{ repo.language }} - </div> - <div class="card-footer-item"> - <i class="fas fa-star"></i> - {{ repo.stargazers }} - </div> - <div class="card-footer-item"> - <i class="fas fa-code-branch"></i> - {{ repo.forks }} - </div> - </footer> - - </article> - </a> + {% if repo_data %} + <section id="projects" class="section"> + <div class="container"> + <h1 class="is-size-1">Projects</h1> + + <div class="columns is-multiline is-tablet"> + + {# Generate project data from HomeView.repos #} + {% for repo in repo_data %} + <div class="column is-one-third-desktop is-half-tablet"> + + <a href="https://github.com/{{ repo.repo_name }}"> + <article class="card"> + + <header class="card-header"> + <span class="card-header-icon"> + <span class="icon"><i class="fab fa-github"></i></span> + </span> + <div class="card-header-title"> + {{ repo.repo_name|cut:"python-discord/" }} + </div> + </header> + + <p class="card-content"> + {{ repo.description }} + </p> + + <footer class="card-footer"> + <div class="card-footer-item"> + <i class="repo-language-dot {{ repo.language | lower }}"></i> + {{ repo.language }} + </div> + <div class="card-footer-item"> + <i class="fas fa-star"></i> + {{ repo.stargazers }} + </div> + <div class="card-footer-item"> + <i class="fas fa-code-branch"></i> + {{ repo.forks }} + </div> + </footer> + + </article> + </a> - </div> - {% endfor %} + </div> + {% endfor %} - </div> + </div> - </div> - </section> + </div> + </section> + {% endif %} <!-- Sponsors --> <section id="sponsors" class="hero is-light"> |