aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.flake82
-rw-r--r--.github/workflows/deploy.yaml2
-rw-r--r--Dockerfile14
-rw-r--r--README.md2
-rw-r--r--gunicorn.conf.py10
-rwxr-xr-xmanage.py15
-rw-r--r--poetry.lock30
-rw-r--r--pydis_site/apps/api/admin.py4
-rw-r--r--pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py19
-rw-r--r--pydis_site/apps/api/models/bot/documentation_link.py1
-rw-r--r--pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md2
-rw-r--r--pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md2
-rw-r--r--pydis_site/apps/home/urls.py1
-rw-r--r--pydis_site/apps/home/views/home.py80
-rw-r--r--pydis_site/constants.py2
-rw-r--r--pydis_site/settings.py15
-rw-r--r--pydis_site/templates/events/index.html2
-rw-r--r--pydis_site/templates/events/pages/code-jams/8/_index.html21
-rw-r--r--pydis_site/templates/events/pages/code-jams/8/frameworks.html5
-rw-r--r--pydis_site/templates/events/pages/code-jams/8/submissions.html484
-rw-r--r--pydis_site/templates/events/pages/code-jams/_index.html2
-rw-r--r--pydis_site/templates/events/pages/code-jams/code-style-guide.html268
-rw-r--r--pydis_site/templates/events/sidebar/code-jams/8.html2
-rw-r--r--pydis_site/templates/events/sidebar/code-jams/ongoing-code-jam.html (renamed from pydis_site/templates/events/sidebar/code-jams/upcoming-code-jam.html)2
-rw-r--r--pydis_site/templates/events/sidebar/code-jams/useful-information.html1
-rw-r--r--pydis_site/templates/events/sidebar/ongoing-event.html (renamed from pydis_site/templates/events/sidebar/upcoming-event.html)2
-rw-r--r--pydis_site/templates/home/index.html4
-rw-r--r--pydis_site/templates/home/timeline.html2
-rw-r--r--pyproject.toml1
29 files changed, 929 insertions, 68 deletions
diff --git a/.flake8 b/.flake8
index 6690af3e..e665771f 100644
--- a/.flake8
+++ b/.flake8
@@ -3,7 +3,7 @@ max-line-length=100
docstring-convention=all
import-order-style=pycharm
application_import_names=pydis_site
-exclude=__pycache__, venv, .venv, **/migrations/**, .cache/
+exclude=__pycache__, venv, .venv, **/migrations/**, .cache/, gunicorn.conf.py
ignore=
B311,W503,E226,S311,T000
# Missing Docstrings
diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml
index 4208f727..0e315327 100644
--- a/.github/workflows/deploy.yaml
+++ b/.github/workflows/deploy.yaml
@@ -41,7 +41,7 @@ jobs:
uses: Azure/k8s-deploy@v1
with:
manifests: |
- site/deployment.yaml
+ namespaces/default/site/deployment.yaml
images: 'ghcr.io/python-discord/site:${{ steps.sha_tag.outputs.tag }}'
kubectl-version: 'latest'
diff --git a/Dockerfile b/Dockerfile
index 5594b458..046e7f80 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.9.5-slim-buster
+FROM --platform=linux/amd64 python:3.9-slim-buster
# Allow service to handle stops gracefully
STOPSIGNAL SIGQUIT
@@ -24,6 +24,18 @@ ENV GIT_SHA=$git_sha
# Copy the source code in last to optimize rebuilding the image
COPY . .
+# Set dummy variables so collectstatic can load settings.py
+RUN \
+ # Set BUILDING_DOCKER to anything but undefined so settings.py
+ # does not insert django_prometheus into the list of installed apps.
+ # This prevents django_prometheus from attempting to connect to the database
+ # when the collectstatic task is ran.
+ BUILDING_DOCKER=yes \
+ SECRET_KEY=dummy_value \
+ DATABASE_URL=postgres://localhost \
+ METRICITY_DB_URL=postgres://localhost \
+ python manage.py collectstatic --noinput --clear
+
# Run web server through custom manager
ENTRYPOINT ["python", "manage.py"]
CMD ["run"]
diff --git a/README.md b/README.md
index 9867bfc8..6e725fa3 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ This is all of the code that is responsible for maintaining [our website][9] and
The website is built on Django and should be simple to set up and get started with.
If you happen to run into issues with setup, please don't hesitate to open an issue!
-If you're looking to contribute or play around with the code, take a look at [the wiki][10] or the [`docs` directory](docs). If you're looking for things to do, check out [our issues][11].
+If you're looking to contribute or play around with the code, take a look at [the wiki][10]. If you're looking for things to do, check out [our issues][11].
[1]: https://github.com/python-discord/site/workflows/Lint%20&%20Test/badge.svg?branch=main
[2]: https://github.com/python-discord/site/actions?query=workflow%3A%22Lint+%26+Test%22+branch%3Amain
diff --git a/gunicorn.conf.py b/gunicorn.conf.py
new file mode 100644
index 00000000..4930ae5b
--- /dev/null
+++ b/gunicorn.conf.py
@@ -0,0 +1,10 @@
+"""
+Configuration file for gunicorn.
+
+Code taken from https://github.com/prometheus/client_python#multiprocess-mode-eg-gunicorn
+"""
+from prometheus_client import multiprocess
+
+
+def child_exit(server, worker) -> None:
+ multiprocess.mark_process_dead(worker.pid)
diff --git a/manage.py b/manage.py
index d21546e1..66ad26f4 100755
--- a/manage.py
+++ b/manage.py
@@ -138,10 +138,17 @@ class SiteManager:
print("Applying migrations.")
call_command("migrate", verbosity=self.verbosity)
- print("Collecting static files.")
- call_command("collectstatic", interactive=False, clear=True, verbosity=self.verbosity)
if self.debug:
+ # In Production, collectstatic is ran in the Docker image
+ print("Collecting static files.")
+ call_command(
+ "collectstatic",
+ interactive=False,
+ clear=True,
+ verbosity=self.verbosity - 1
+ )
+
self.set_dev_site_name()
self.create_superuser()
@@ -169,12 +176,10 @@ class SiteManager:
"--preload",
"-b", "0.0.0.0:8000",
"pydis_site.wsgi:application",
- "--threads", "8",
"-w", "2",
- "--max-requests", "1000",
- "--max-requests-jitter", "50",
"--statsd-host", "graphite.default.svc.cluster.local:8125",
"--statsd-prefix", "site",
+ "--config", "file:gunicorn.conf.py"
]
# Run gunicorn for the production server.
diff --git a/poetry.lock b/poetry.lock
index c2a03f30..62b89e54 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -165,6 +165,17 @@ optional = false
python-versions = ">=3.5"
[[package]]
+name = "django-prometheus"
+version = "2.1.0"
+description = "Django middlewares to monitor your application with Prometheus.io."
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+prometheus-client = ">=0.7"
+
+[[package]]
name = "django-simple-bulma"
version = "2.4.0"
description = "Django application to add the Bulma CSS framework and its extensions"
@@ -477,6 +488,17 @@ toml = "*"
virtualenv = ">=20.0.8"
[[package]]
+name = "prometheus-client"
+version = "0.11.0"
+description = "Python client for the Prometheus monitoring system."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[package.extras]
+twisted = ["twisted"]
+
+[[package]]
name = "psutil"
version = "5.8.0"
description = "Cross-platform lib for process and system monitoring in Python."
@@ -852,6 +874,10 @@ django-hosts = [
{file = "django-hosts-4.0.tar.gz", hash = "sha256:59a870d453f113c889a7888bae5408888870350e83e362740f382dad569c2281"},
{file = "django_hosts-4.0-py2.py3-none-any.whl", hash = "sha256:136ac225f34e7f2c007294441a38663ec2bba9637d870ad001def81bca87e390"},
]
+django-prometheus = [
+ {file = "django-prometheus-2.1.0.tar.gz", hash = "sha256:dd3f8da1399140fbef5c00d1526a23d1ade286b144281c325f8e409a781643f2"},
+ {file = "django_prometheus-2.1.0-py2.py3-none-any.whl", hash = "sha256:c338d6efde1ca336e90c540b5e87afe9287d7bcc82d651a778f302b0be17a933"},
+]
django-simple-bulma = [
{file = "django-simple-bulma-2.4.0.tar.gz", hash = "sha256:99a15261b0c61062a128af3c6a45da9c066d6a4a548c9063464e0fb7a5438aa1"},
{file = "django_simple_bulma-2.4.0-py3-none-any.whl", hash = "sha256:95d5e26bebbf6a0184e33df844a0ff534bdfd91431e413d1a844d47a75c55fff"},
@@ -968,6 +994,10 @@ pre-commit = [
{file = "pre_commit-2.14.0-py2.py3-none-any.whl", hash = "sha256:ec3045ae62e1aa2eecfb8e86fa3025c2e3698f77394ef8d2011ce0aedd85b2d4"},
{file = "pre_commit-2.14.0.tar.gz", hash = "sha256:2386eeb4cf6633712c7cc9ede83684d53c8cafca6b59f79c738098b51c6d206c"},
]
+prometheus-client = [
+ {file = "prometheus_client-0.11.0-py2.py3-none-any.whl", hash = "sha256:b014bc76815eb1399da8ce5fc84b7717a3e63652b0c0f8804092c9363acab1b2"},
+ {file = "prometheus_client-0.11.0.tar.gz", hash = "sha256:3a8baade6cb80bcfe43297e33e7623f3118d660d41387593758e2fb1ea173a86"},
+]
psutil = [
{file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"},
{file = "psutil-5.8.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c"},
diff --git a/pydis_site/apps/api/admin.py b/pydis_site/apps/api/admin.py
index 449e660e..2aca38a1 100644
--- a/pydis_site/apps/api/admin.py
+++ b/pydis_site/apps/api/admin.py
@@ -48,8 +48,8 @@ class BotSettingAdmin(admin.ModelAdmin):
class DocumentationLinkAdmin(admin.ModelAdmin):
"""Admin formatting for the DocumentationLink model."""
- fields = ("package", "base_url", "inventory_url")
- list_display = ("package", "base_url", "inventory_url")
+ fields = ("package", "inventory_url", "base_url")
+ list_display = ("package", "inventory_url", "base_url")
list_editable = ("base_url", "inventory_url")
search_fields = ("package",)
diff --git a/pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py b/pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py
new file mode 100644
index 00000000..d4899354
--- /dev/null
+++ b/pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.14 on 2021-08-30 21:09
+
+from django.db import migrations, models
+import pydis_site.apps.api.models.bot.documentation_link
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0071_increase_message_content_4000'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='documentationlink',
+ name='base_url',
+ field=models.URLField(blank=True, help_text='The base URL from which documentation will be available for this project. Used to generate links to various symbols within this package.', validators=[pydis_site.apps.api.models.bot.documentation_link.ends_with_slash_validator]),
+ ),
+ ]
diff --git a/pydis_site/apps/api/models/bot/documentation_link.py b/pydis_site/apps/api/models/bot/documentation_link.py
index 3dcc71fc..9941907c 100644
--- a/pydis_site/apps/api/models/bot/documentation_link.py
+++ b/pydis_site/apps/api/models/bot/documentation_link.py
@@ -30,6 +30,7 @@ class DocumentationLink(ModelReprMixin, models.Model):
"The base URL from which documentation will be available for this project. "
"Used to generate links to various symbols within this package."
),
+ blank=True,
validators=(ends_with_slash_validator,)
)
inventory_url = models.URLField(
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
index 601cfa4a..068b08ae 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
@@ -97,7 +97,7 @@ The first time you run this command, it may take a few minutes while Docker down
$ docker-compose up
```
-If you get any Docker related errors, reference the [Possible Issues](./docker/possible-issues) section of the Docker page.
+If you get any Docker related errors, reference the [Possible Issues](../docker#possible-issues) section of the Docker page.
{: .notification .is-warning }
## Run on the host
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md
index 5c472eb2..2a7ef0d6 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md
@@ -32,7 +32,7 @@ Additionally, you may find the following environment variables useful during dev
| `REDIS_PASSWORD` | |
| `USE_FAKEREDIS` | If the FakeRedis module should be used. Set this to true if you don't have a Redis database setup. |
| `BOT_SENTRY_DSN` | The DSN of the sentry monitor. |
-| `TRASHCAN_EMOJI` | The emoji to use for the trashcan during paginated embeds |
+| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of `\:emoji:`. |
---
diff --git a/pydis_site/apps/home/urls.py b/pydis_site/apps/home/urls.py
index 1e2af8f3..bb77220b 100644
--- a/pydis_site/apps/home/urls.py
+++ b/pydis_site/apps/home/urls.py
@@ -7,6 +7,7 @@ app_name = 'home'
urlpatterns = [
path('', HomeView.as_view(), name='home'),
path('', include('pydis_site.apps.redirect.urls')),
+ path('', include('django_prometheus.urls')),
path('admin/', admin.site.urls),
path('resources/', include('pydis_site.apps.resources.urls')),
path('pages/', include('pydis_site.apps.content.urls')),
diff --git a/pydis_site/apps/home/views/home.py b/pydis_site/apps/home/views/home.py
index b3767d37..bbb4b815 100644
--- a/pydis_site/apps/home/views/home.py
+++ b/pydis_site/apps/home/views/home.py
@@ -9,7 +9,7 @@ from django.utils import timezone
from django.views import View
from pydis_site.apps.home.models import RepositoryMetadata
-from pydis_site.constants import GITHUB_TOKEN
+from pydis_site.constants import GITHUB_TOKEN, TIMEOUT_PERIOD
log = logging.getLogger(__name__)
@@ -19,7 +19,6 @@ class HomeView(View):
github_api = "https://api.github.com/users/python-discord/repos?per_page=100"
repository_cache_ttl = 3600
- headers = {"Authorization": f"token {GITHUB_TOKEN}"}
# Which of our GitHub repos should be displayed on the front page, and in which order?
repos = [
@@ -35,6 +34,16 @@ class HomeView(View):
"""Clean up stale RepositoryMetadata."""
RepositoryMetadata.objects.exclude(repo_name__in=self.repos).delete()
+ # If no token is defined (for example in local development), then
+ # it does not make sense to pass the Authorization header. More
+ # specifically, GitHub will reject any requests from us due to the
+ # invalid header. We can make a limited number of anonymous requests
+ # though, which is useful for testing.
+ if GITHUB_TOKEN:
+ self.headers = {"Authorization": f"token {GITHUB_TOKEN}"}
+ else:
+ self.headers = {}
+
def _get_api_data(self) -> Dict[str, Dict[str, str]]:
"""
Call the GitHub API and get information about our repos.
@@ -42,9 +51,16 @@ class HomeView(View):
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, headers=self.headers).json()
+ try:
+ # Fetch the data from the GitHub API
+ api_data: List[dict] = requests.get(
+ self.github_api,
+ headers=self.headers,
+ timeout=TIMEOUT_PERIOD
+ ).json()
+ except requests.exceptions.Timeout:
+ log.error("Request to fetch GitHub repository metadata for timed out!")
+ return repo_dict
# Process the API data into our dict
for repo in api_data:
@@ -74,35 +90,33 @@ class HomeView(View):
def _get_repo_data(self) -> List[RepositoryMetadata]:
"""Build a list of RepositoryMetadata objects that we can use to populate the front page."""
- database_repositories = []
-
- # First, let's see if we have any metadata cached.
- cached_data = RepositoryMetadata.objects.all()
+ # First off, load the timestamp of the least recently updated entry.
+ last_update = (
+ RepositoryMetadata.objects.values_list("last_updated", flat=True)
+ .order_by("last_updated").first()
+ )
- # If we don't, we have to create some!
- if not cached_data:
+ # If we did not retrieve any results here, we should import them!
+ if last_update is None:
# 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(
+ return RepositoryMetadata.objects.bulk_create(
+ 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
+ for api_data in api_repositories.values()
+ )
# If the data is stale, we should refresh it.
- if (timezone.now() - cached_data[0].last_updated).seconds > self.repository_cache_ttl:
+ if (timezone.now() - last_update).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()
@@ -110,22 +124,18 @@ class HomeView(View):
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"],
- forks=api_data["forks_count"],
- stargazers=api_data["stargazers_count"],
- language=api_data["language"],
- )
- repo_data.save()
+ database_repositories = []
+ for api_data in api_repositories.values():
+ repo_data, _created = RepositoryMetadata.objects.update_or_create(
+ repo_name=api_data["full_name"],
+ defaults={
+ 'repo_name': api_data["full_name"],
+ 'description': api_data["description"],
+ 'forks': api_data["forks_count"],
+ 'stargazers': api_data["stargazers_count"],
+ 'language': api_data["language"],
+ }
+ )
database_repositories.append(repo_data)
return database_repositories
diff --git a/pydis_site/constants.py b/pydis_site/constants.py
index e6a63d12..e913f40f 100644
--- a/pydis_site/constants.py
+++ b/pydis_site/constants.py
@@ -2,3 +2,5 @@ import os
GIT_SHA = os.environ.get("GIT_SHA", "development")
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN")
+# How long to wait for synchronous requests before timing out
+TIMEOUT_PERIOD = int(os.environ.get("TIMEOUT_PERIOD", 5))
diff --git a/pydis_site/settings.py b/pydis_site/settings.py
index 710c56cc..da582517 100644
--- a/pydis_site/settings.py
+++ b/pydis_site/settings.py
@@ -14,6 +14,7 @@ import os
import secrets
import sys
from pathlib import Path
+from socket import gethostbyname, gethostname
import environ
import sentry_sdk
@@ -23,7 +24,8 @@ from pydis_site.constants import GIT_SHA
env = environ.Env(
DEBUG=(bool, False),
- SITE_DSN=(str, "")
+ SITE_DSN=(str, ""),
+ BUILDING_DOCKER=(bool, False)
)
sentry_sdk.init(
@@ -58,6 +60,8 @@ else:
'api.pythondiscord.com',
'staff.pythondiscord.com',
'pydis-api.default.svc.cluster.local',
+ gethostname(),
+ gethostbyname(gethostname())
]
)
SECRET_KEY = env('SECRET_KEY')
@@ -84,10 +88,15 @@ INSTALLED_APPS = [
'django_filters',
'django_simple_bulma',
'rest_framework',
- 'rest_framework.authtoken'
+ 'rest_framework.authtoken',
]
+if not env("BUILDING_DOCKER"):
+ INSTALLED_APPS.append("django_prometheus")
+
+# Ensure that Prometheus middlewares are first and last here.
MIDDLEWARE = [
+ 'django_prometheus.middleware.PrometheusBeforeMiddleware',
'django_hosts.middleware.HostsRequestMiddleware',
'django.middleware.security.SecurityMiddleware',
@@ -100,7 +109,9 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django_hosts.middleware.HostsResponseMiddleware',
+ 'django_prometheus.middleware.PrometheusAfterMiddleware'
]
+
ROOT_URLCONF = 'pydis_site.urls'
TEMPLATES = [
diff --git a/pydis_site/templates/events/index.html b/pydis_site/templates/events/index.html
index 64bf2c25..daad1c9c 100644
--- a/pydis_site/templates/events/index.html
+++ b/pydis_site/templates/events/index.html
@@ -121,6 +121,6 @@
{% endblock %}
{% block sidebar %}
- {% include "events/sidebar/upcoming-event.html" %}
+ {% include "events/sidebar/ongoing-event.html" %}
{% include "events/sidebar/events-list.html" %}
{% endblock %}
diff --git a/pydis_site/templates/events/pages/code-jams/8/_index.html b/pydis_site/templates/events/pages/code-jams/8/_index.html
index c510c250..55bdc95b 100644
--- a/pydis_site/templates/events/pages/code-jams/8/_index.html
+++ b/pydis_site/templates/events/pages/code-jams/8/_index.html
@@ -12,12 +12,12 @@
{% block event_content %}
<p>Twice a year we host a code jam for members of our server to participate in. The code jam is an event where we place you
- in a team with 5 other random server members. You then have 7 days to code some sort of application or program in Python.
+ in a team with 5 other random server members. You then have 8 days to code some sort of application or program in Python.
Your program must use the specified technology/framework and incorporate the theme chosen by the server.
</p>
<p>
- After the 7 days is complete, your team has 2 days to finish documentation and create a video presentation showcasing
- and walking through the program that your team has created. More details and specifics of this will be released within the next 2 weeks.
+ After the 8 days is complete, your team has 3 days to finish documentation and create a video presentation showcasing
+ and walking through the program that your team has created.
</p>
<h3 id="important-dates"><a href="#important-dates">Important Dates</a></h3>
@@ -26,10 +26,10 @@
<li>Monday, June 21 - <a href="https://github.com/python-discord/cj8-qualifier">The Qualifier</a> is released</li>
<li>Friday, June 25 - Voting for the theme opens</li>
<li>Saturday, June 26 @ 4PM UTC- <a class="has-text-link" href="{% url "events:page" path="code-jams/8/github-bootcamp" %}">GitHub Bootcamp</a></li>
- <li>Wednesday, June 30 - The Qualifier closes</li>
- <li>Friday, July 9 - Code Jam begins</li>
- <li>Friday, July 16 - Coding portion of the jam ends</li>
- <li>Sunday, July 18 - Code Jam submissions are closed</li>
+ <li>Wednesday, July 1 - The Qualifier closes</li>
+ <li>Friday, July 9 @ 5PM UTC - Code Jam begins and the theme is announced</li>
+ <li>Saturday, July 17 @ 5PM UTC - Coding portion of the jam ends</li>
+ <li>Tuesday, July 20 - Code Jam submissions are closed and video presentation must be submitted</li>
</ul>
<h3 id="technology"><a href="#technology">Technology</a></h3>
@@ -52,11 +52,10 @@
<li>The Qualifier must be submitted through the Code Jam sign-up form.</li>
</ul>
</p>
- <h3 id="how-to-join"><a href="#how-to-join">How to Join</a></h3>
+ <h3 id="submissions"><a href="#submissions">Submissions</a></h3>
<p>
- To enter into the code jam you must complete <a href="#qualifier">The Qualifier</a> and submit the sign-up form.
- Don't forget to join us on Discord at <a href="https://discord.gg/python">discord.gg/python</a>!
- <div class="has-text-centered"><a class="button is-link" href="https://form.jotform.com/211714357615050" target="_blank">Sign up for the Code Jam</a></div>
+ 63 teams started out on July 9th 2021. By the end of the jam, 51 teams made project submissions. Check them all out here:
+ <div class="has-text-centered"><a class="button is-link" href="submissions">View Submissions</a></div>
</p>
<h3 id="prizes"><a href="#prizes">Prizes</a></h3>
<p>
diff --git a/pydis_site/templates/events/pages/code-jams/8/frameworks.html b/pydis_site/templates/events/pages/code-jams/8/frameworks.html
index 532fb71f..34ac4f0a 100644
--- a/pydis_site/templates/events/pages/code-jams/8/frameworks.html
+++ b/pydis_site/templates/events/pages/code-jams/8/frameworks.html
@@ -73,6 +73,11 @@
<li><strong>Supports:</strong> Linux, Mac, and Windows</li>
<li>Documentation is good and overall is very OOP focused</li>
<li>Robust with many features and example snippets</li>
+ <li>To supplement Rich the following library is approved, although no guarantees are made for stability.</li>
+ <ul>
+ <li><a href="https://github.com/willmcgugan/textual" target="_blank">Textual</a> - a TUI framework using Rich as the render.
+ <br>It is still under active development, is only available on Mac/Linux, and is not stable yet.</li>
+ </ul>
</ul>
</div>
<div class="column">
diff --git a/pydis_site/templates/events/pages/code-jams/8/submissions.html b/pydis_site/templates/events/pages/code-jams/8/submissions.html
new file mode 100644
index 00000000..16309bd3
--- /dev/null
+++ b/pydis_site/templates/events/pages/code-jams/8/submissions.html
@@ -0,0 +1,484 @@
+{% extends "events/base_sidebar.html" %}
+
+{% load static %}
+
+{% block title %}Summer Code Jam 2021{% endblock %}
+
+{% block breadcrumb %}
+ <li><a href="{% url "events:index" %}">Events</a></li>
+ <li><a href="{% url "events:page" path="code-jams" %}">Code Jams</a></li>
+ <li><a href="{% url "events:page" path="code-jams/8" %}">Summer Code Jam 2021</a></li>
+ <li class="is-active"><a href="#">Submissions</a></li>
+{% endblock %}
+
+{% block event_content %}
+ <p>
+ Below is a list of all projects submitted by the end of Summer Code Jam 2021
+ </p>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Acute Alligators</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/n0remac/Acute-Alligators-2021-Summer-Code-Jam" title="Acute Alligators' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Adaptable Antelopes</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/BoraxTheClean/adaptable-antelopes" title="Adaptable Antelopes' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Astounding Arapaimas</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/p0lygun/astounding-arapaimas" title="Astounding Arapaimas' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Beatific Bulldogs</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/beatific-bulldogs/code-jam" title="Beatific Bulldogs' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Benevolent Bonobos</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Anand1310/summer-code-jam-2021" title="Benevolent Bonobos' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Blessed Badgers</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/StephD/CJ8-blessed-badgers" title="Blessed Badgers' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Bright Bluefins</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/DavinderJolly/bright-bluefins/" title="Bright Bluefins' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Businesslike Buffalo</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Sahaj001/Businesslike_Buffalo" title="Businesslike Buffalo's Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Canny Capybaras</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/aiyayayaya/canny-capybaras-collab-code-contest" title="Canny Capybaras' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Cheerful Cheetahs</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/cj8-cheerful-cheetahs/project" title="Cheerful Cheetahs' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Classic Clownfish</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Istalantar/SCJ-2021-classic-clownfish" title="Classic Clownfish's Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Considerate Coatis</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/yashkir/considerate-coatis" title="Considerate Coatis' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Dedicated Dugongs</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Areking-RS/Code-jam-2021" title="Dedicated Dugongs' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Discrete Dingos</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/somthecoder/CodeJam-Discrete-Dingos" title="Discrete Dingos' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Enlightened Elks</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/GriceTurrble/enlightened-elks-codejam/" title="Enlightened Elks' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Esteemed Emus</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Vthechamp22/esteemed-emus" title="Esteemed Emus' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Favorable Fishers</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/UntriexTv/favorable-fishers" title="Favorable Fishers' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Feisty Ferrets</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/ToxicKidz/summer-code-jam-8" title="Feisty Ferrets' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Gallant Grasshoppers</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/StackedQueries/gallant-grasshoppers" title="Gallant Grasshoppers' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Grand Geckos</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/imsofi/codejam-grand-geckos/" title="Grand Geckos' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Hospitable Hares</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/samarthkulshrestha/hospitable-hares_code-jam-8" title="Hospitable Hares' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Humorous Honeybees</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/mirandazellnik/code-jam-2021" title="Humorous Honeybees' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Jaunty Jackals</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Jaunty-Jackals/jaunty-jackals" title="Jaunty Jackals' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Jazzed Jerboas</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/tomheaton/pcj8-jazzed-jerboas" title="Jazzed Jerboas' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Jubilant Jellyfish</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Cheepsss/Jubilant-Jellyfish" title="Jubilant Jellyfish's Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Lovable Lobsters</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/A5rocks/code-jam-8" title="Lovable Lobsters' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Magical Muskrats</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/harjyotbagga/escape-room" title="Magical Muskrats' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Mature Magpies</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Mature-Magpies/think-inside-the-box" title="Mature Magpies' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Merciful Millipedes</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Reuben27/Merciful-Millipedes" title="Merciful Millipedes' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Meteoric Minks</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/meteoric-minks/code-jam" title="Meteoric Minks' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Modern Meerkats</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Ahmed-Khaled-dev/modern-meerkats" title="Modern Meerkats' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Notable Newts</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/meysam81/notable-newts" title="Notable Newts' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Notorious Narwhals</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/smileyface12349/notorious-narwhals" title="Notorious Narwhals' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Patient Panthers</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Willd14469/cj8-patient-panthers" title="Patient Panthers' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Perceptive Porcupines</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/what-the-python/wtpython" title="Perceptive Porcupines' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Poetic Pumas</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/roogla/poetic_pumas" title="Poetic Pumas' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Purposeful Pangolins</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/doodletaco/dataset-viewer" title="Purposeful Pangolins' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Quirky Quokkas</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/joshuacc1/Music-Player-CLI-Anywhere" title="Quirky Quokkas' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Respectful Racoons</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/manjunaath5583/respectful_racoons" title="Respectful Racoons' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Rhapsodic Rabbits</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/yummyyummybaguette/rhapsodic-rabbits" title="Rhapsodic Rabbits' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Robust Reindeer</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/bjoseru/pdcj8-robust-reindeer" title="Robust Reindeer's Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Scholarly Skunks</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Davidy22/scholarlySkunkJam/" title="Scholarly Skunks' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Secretive Squirrels</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/dain-xyz/python-jam-2021-2" title="Secretive Squirrels' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Sleek Snails</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Sleek-Snails/Snail-Snacks" title="Sleek Snails' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Spellbinding Squids</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/SystematicError/code-jam" title="Spellbinding Squids' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Stylish Salamanders</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Darklight-user/code-jam-stylish-salamanders" title="Stylish Salamanders' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Tactful Tunas</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Yagueteiro/code-jam-2021/" title="Tactful Tunas' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Transcendent Tarsiers</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/kronifer/cj8-repo" title="Transcendent Tarsiers' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Tubular Terriers</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/Tubular-Terriers/code-jam" title="Tubular Terriers' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Virtuous Vultures</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/iceCream-Taco/cj8-virtuous-vultures" title="Virtuous Vultures' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+ <div class="columns is-mobile is-centered">
+ <div class="column is-half">
+ <p class="has-text-centered">Whimsical Woolly Mammoths</p>
+ </div>
+ <div class="column is-half">
+ <p class="has-text-centered"><a href="https://github.com/SilverSlashDiscord/whimsical-woolly-mammoths" title="Whimsical Woolly Mammoths' Repository">GitHub</a></p>
+ </div>
+ </div>
+
+{% endblock %}
+
+{% block sidebar %}
+
+ {% include "events/sidebar/code-jams/8.html" %}
+
+{% endblock %}
diff --git a/pydis_site/templates/events/pages/code-jams/_index.html b/pydis_site/templates/events/pages/code-jams/_index.html
index fcbfa4d9..22a86db3 100644
--- a/pydis_site/templates/events/pages/code-jams/_index.html
+++ b/pydis_site/templates/events/pages/code-jams/_index.html
@@ -66,7 +66,7 @@
{% endblock %}
{% block sidebar %}
- {% include "events/sidebar/code-jams/upcoming-code-jam.html" %}
+ {% include "events/sidebar/code-jams/ongoing-code-jam.html" %}
{% include "events/sidebar/code-jams/previous-code-jams.html" %}
{% include "events/sidebar/code-jams/useful-information.html" %}
{% endblock %}
diff --git a/pydis_site/templates/events/pages/code-jams/code-style-guide.html b/pydis_site/templates/events/pages/code-jams/code-style-guide.html
new file mode 100644
index 00000000..4ff5baaf
--- /dev/null
+++ b/pydis_site/templates/events/pages/code-jams/code-style-guide.html
@@ -0,0 +1,268 @@
+{% extends "events/base_sidebar.html" %}
+
+{% block breadcrumb %}
+ <li><a href="{% url "events:index" %}">Events</a></li>
+ <li><a href="{% url "events:page" path="code-jams" %}">Code Jams</a></li>
+ <li class="is-active"><a href="#">The Code Style Guide</a></li>
+{% endblock %}
+
+{% block title %}The Code Style Guide{% endblock %}
+
+{% block event_content %}
+ <p>
+ For end-users, the most important parts of the software are functionality and UI/UX.
+ But for developers, there is one more important aspect - code style.
+ While ugly code can do everything that it has to do, developing it further may be a difficult task,
+ especially if the developer didn't write the original code.
+ Which one of the following do you prefer to read and work with?
+ </p>
+ <pre><code class="language-python">MyPath = '/file.txt'
+from pathlib import *
+import os.path,sys
+def check(p):
+ """Uses os.path.exist """
+ return os.path.exists(p)
+
+def getF(
+ p):
+ """Not sure what this do, this just worked.
+ """
+ return Path(p
+ )
+result=[check(MyPath),getF(MyPath)]</code></pre>
+ <p>or</p>
+ <pre><code class="language-python">import os.path
+from pathlib import Path
+
+FILE_PATH = '/file.txt'
+
+
+def check_file_exists(path: str) -> bool:
+ """Checks does file exists in path. Uses os.path.exists."""
+ return os.path.exists(path)
+
+
+def get_path_object(path: str) -> Path:
+ """
+ Returns Path object of the path provided in arguments.
+
+ This is here for backward compatibility, will be removed in the future.
+ """
+ return Path(path)
+
+result = [
+ check_file_exists(FILE_PATH),
+ get_path_object(FILE_PATH),
+]</code></pre>
+
+ <p>
+ The second is definitely easier to read and understand.
+ These scripts are small and even with the first code snippet you can understand what the code does pretty quickly,
+ but what if the project has thousands and thousands of files in a really complex folder structure?
+ Do you want to work with code that looks like the first example?
+ You can save hours sometimes if you write beautiful code that follows the style guidelines.
+ </p>
+ <p>
+ The most important code style document for Python is <b><a href="https://www.python.org/dev/peps/pep-0008/">PEP 8</a></b>.
+ This Python Enhancement Proposal lays out the majority of all Python code style guidelines.
+ This article will cover the most important aspects of PEP 8.
+ </p>
+
+ <h2>Linters</h2>
+ <p>
+ But everyone makes mistakes and there are so many style rules that can be really difficult to remember and always follow.
+ Luckily, we have amazing tools that help us - linters. While there are many linters,
+ we'd like code jam participants to use <b><a href="https://flake8.pycqa.org/en/latest/">flake8</a></b>.
+ Flake8 points out to you rules what you did break in your code so you can fix them.
+ </p>
+
+ <h2>Guidelines</h2>
+ <h3>Basics</h3>
+ <p>For indentation, you should use 4 spaces. Using tabs is not suggested, but if you do, you can't mix spaces and tabs.</p>
+ <p>
+ PEP 8 defines a maximum line length of 79 characters, however,
+ we are not so strict - teams are welcome to choose a maximum line length between 79 and 119 characters.
+ </p>
+ <p>2 blank lines should be left before functions and classes. Single blank lines are used to split sections and make logical breaks.</p>
+
+ <h3>Naming</h3>
+ <p>Module, file, function, and variable names (except type variables) should be lowercase and use underscores.</p>
+ <pre><code class="language-python"># File: my_module.py/mymodule.py
+
+def my_function():
+ my_variable = "value"</code></pre>
+ <p>Class and type variable names should use the PascalCase style.</p>
+ <pre><code class="language-python">from typing import List
+
+
+class MyClass:
+ pass
+
+ListOfMyClass = List[MyClass]</code></pre>
+ <p>Constant names should use the SCREAMING_SNAKE_CASE style.</p>
+ <pre><code class="language-python">MY_CONSTANT = 1</code></pre>
+ <p>
+ You should avoid single-character names, as these might be confusing.
+ But if you still do, you should avoid characters that may look like zero or one in some fonts:
+ "O" (uppercase o), "l" (lowercase L), and "I" (uppercase i).
+ </p>
+
+ <h3>Operators</h3>
+ <p>
+ If you have a chain of mathematic operations that you split into multiple lines,
+ you should put the operator at the beginning of the line and not the end of the line.
+ </p>
+ <pre><code class="language-python"># No
+result = (
+ 1 +
+ 2 *
+ 3
+)
+
+# Yes
+result = (
+ 1
+ + 2
+ * 3
+)</code></pre>
+ <p>If you ever check if something is equivalent to <code>None</code>, you should use <code>is</code> and <code>is not</code> instead of the <code>==</code> operator.</p>
+ <pre><code class="language-python"># No
+if variable == None:
+ print("Variable is None")
+
+# Yes
+if variable is None:
+ print("Variable is None")</code></pre>
+ <p>
+ You should prefer using <code>&lt;item one&gt; is not &lt;item two&gt;</code> over <code>not &lt;item one&gt; is &lt;item two&gt;</code>.
+ Using the latter makes it harder to understand what the expression is trying to do.
+ </p>
+ <pre><code class="language-python"># No
+if not variable is None:
+ print("Variable is not None")
+
+# Yes - it is much easier to read and understand this than previous
+if variable is not None:
+ print("Variable is not None")</code></pre>
+
+ <h3>Imports</h3>
+ <p>Imports should be at top of the file, the only things that should be before them are module comments and docstrings.</p>
+ <p>You shouldn't import multiple modules in one line, but give each module import its own line instead.</p>
+ <pre><code class="language-python"># No
+import pathlib, os
+
+# Yes
+import os
+import pathlib</code></pre>
+ <p>Wildcard imports should be avoided in most cases. It clutters the namespace and makes it less clear where functions or classes are coming from.</p>
+ <pre><code class="language-python"># No
+from pathlib import *
+
+# Yes
+from pathlib import Path</code></pre>
+ <p>You should use <b><a href="https://pycqa.github.io/isort/">isort</a></b> imports order specification, which means:</p>
+ <ul>
+ <li>
+ <b>Group by type:</b> order of import types should be: <code>__future__</code> imports, standard library imports,
+ third-party library imports, and finally project imports.
+ </li>
+ <li>
+ <b>Group by import method:</b> inside each group, first should come imports in format <code>import &lt;package&gt;</code>
+ and after them <code>from &lt;package&gt; import &lt;items&gt;</code>.
+ </li>
+ <li>
+ <b>Order imports alphabetically:</b> inside each import method group, imports should be ordered by package names.
+ </li>
+ <li>
+ <b>Order individual import items by type and alphabetically:</b> in <code>from &lt;package&gt; import &lt;items&gt;</code> format,
+ <code>&lt;items&gt;</code> should be ordered alphabetically, starting with bare module imports.
+ </li>
+ </ul>
+
+ <h3>Comments</h3>
+ <p>
+ Comments are really important because they help everyone understand what code does.
+ In general, comments should explain <i>why</i> you are doing something if it's not obvious.
+ You should aim to write code that makes it obvious what it is doing and you can use the comments to explain why and provide some context.
+ </p>
+ <p>
+ Keep in mind that just as important as having comments, is making sure they stay up to date.
+ Out-of-date and incorrect comments confuse readers of your code (including future you).
+ </p>
+ <p>Comments content should start with a capital letter and be a full sentence(s).</p>
+ <p>There are three types of comments: block comments, inline comments, and docstrings.</p>
+ <ul>
+ <li>
+ <h4>Block comments</h4>
+ <p>
+ Probably most common comment type. Should be indented to the same level as the code they describe.
+ Each line in the block comment has to start with <code>#</code> and should be followed by a single space.
+ To separate paragraphs, use one line containing only <code>#</code>.
+ </p>
+ <pre><code class="language-python">if variable is None or variable == 1:
+ # If variable is None, something went wrong previously.
+ #
+ # Here starts a new important paragraph.</code></pre>
+ </li>
+ <li>
+ <h4>Inline comments</h4>
+ <p>
+ You should prefer block comments over inline comments and use inline comments only where it is really necessary.
+ Never use inline comments to explain obvious things like what a line does.
+ </p>
+ <p>If you want to use an inline comment on a variable, think first, maybe you can use a better variable name instead.</p>
+ <p>
+ After code and before the start of inline comments should be at least two spaces.
+ Just like block comments, inline comments also have to start with <code>#</code> followed by a single space.
+ </p>
+ <pre><code class="language-python"># Do not use inline comments to explain things
+# that the reader can understand even without the inline comment.
+my_variable = "Value!" # Assign value to my_variable
+
+# Here better variable name can be used like shown in the second line.
+x = "Walmart" # Shop name
+shop_name = "Walmart"
+
+# Sometimes, if something is not obvious, then inline comments are useful.
+# Example is from PEP 8.
+x = x + 1 # Compensate for border</code></pre>
+ </li>
+ <li>
+ <h4>Docstrings</h4>
+ <p>
+ Last, but not least important comment type is docstring, which is a short version of documentation string.
+ Docstring rules haven't been defined by PEP 8, but by <a href="https://www.python.org/dev/peps/pep-0257">PEP 257</a> instead.
+ </p>
+ <p>Docstrings should start and end with three quotes (""").</p>
+ <p>There are two types of docstrings: one-line docstrings and multiline docstrings.</p>
+ <p>
+ One-line docstrings have to start and end in the same line, while multiline docstrings start and end in different lines.
+ Multiline docstring has two parts: summary line and a longer description, which are separated by one empty line.
+ The multiline docstring start and end quotes should be on different lines than the content.
+ </p>
+ <pre><code class="language-python"># This is a one-line docstring.
+"""This is one line module docstring."""
+
+
+# This is a multiline docstring.
+def my_function():
+ """
+ This is the summary line.
+
+ This is the description.
+ """</code></pre>
+ </li>
+ </ul>
+
+ <h2>Too much for you?</h2>
+ <p>
+ Do all these style rules make your head explode? We have something for you! We have a song!
+ We have <a href="https://www.youtube.com/watch?v=hgI0p1zf31k">The PEP 8 Song (featuring lemonsaurus)</a>!
+ Great way to get started with writing beautiful code.
+ </p>
+ <iframe width="500" height="315" src="https://www.youtube.com/embed/hgI0p1zf31k"></iframe>
+{% endblock %}
+
+{% block sidebar %}
+ {% include "events/sidebar/code-jams/useful-information.html" %}
+{% endblock %}
diff --git a/pydis_site/templates/events/sidebar/code-jams/8.html b/pydis_site/templates/events/sidebar/code-jams/8.html
index ff5131c2..36fad680 100644
--- a/pydis_site/templates/events/sidebar/code-jams/8.html
+++ b/pydis_site/templates/events/sidebar/code-jams/8.html
@@ -4,6 +4,8 @@
<a class="panel-block has-text-link" href="{% url "events:page" path="code-jams/8/rules" %}">Rules</a>
<a class="panel-block has-text-link" href="{% url "events:page" path="code-jams/8/frameworks" %}">Approved Frameworks</a>
<a class="panel-block has-text-link" href="{% url "events:page" path="code-jams/8/github-bootcamp" %}">GitHub Bootcamp</a>
+ <a class="panel-block has-text-link" href="{% url "events:page" path="code-jams/8/submissions" %}">Submissions</a>
+ <a class="panel-block has-text-link" href="{% url "events:page" path="code-jams/code-style-guide" %}">The Code Style Guide</a>
</ul>
</div>
<div class="box">
diff --git a/pydis_site/templates/events/sidebar/code-jams/upcoming-code-jam.html b/pydis_site/templates/events/sidebar/code-jams/ongoing-code-jam.html
index 19806b4e..f4fa3a37 100644
--- a/pydis_site/templates/events/sidebar/code-jams/upcoming-code-jam.html
+++ b/pydis_site/templates/events/sidebar/code-jams/ongoing-code-jam.html
@@ -1,7 +1,7 @@
{% load static %}
<div class="box">
- <h4 class="menu-label">Upcoming Code Jam</h4>
+ <h4 class="menu-label">Ongoing Code Jam</h4>
<a href="{% url "events:page" path="code-jams/8" %}">
<img src="{% static "images/events/summer_code_jam_2021/banner.png" %}" alt="Summer Code Jam 2021">
</a>
diff --git a/pydis_site/templates/events/sidebar/code-jams/useful-information.html b/pydis_site/templates/events/sidebar/code-jams/useful-information.html
index c4e665e6..87a92ade 100644
--- a/pydis_site/templates/events/sidebar/code-jams/useful-information.html
+++ b/pydis_site/templates/events/sidebar/code-jams/useful-information.html
@@ -4,5 +4,6 @@
<li><a class="has-text-link" href="{% url "events:page" path="code-jams/using-git" %}">How to use git</a></li>
<li><a class="has-text-link" href="{% url "events:page" path="code-jams/judging" %}">How does judging work?</a></li>
<li><a class="has-text-link" href="{% url "events:page" path="code-jams/pull-request" %}">Opening a Pull Request</a></li>
+ <li><a class="has-text-link" href="{% url "events:page" path="code-jams/code-style-guide" %}">The Code Style Guide</a></li>
</ul>
</div>
diff --git a/pydis_site/templates/events/sidebar/upcoming-event.html b/pydis_site/templates/events/sidebar/ongoing-event.html
index cfa4cf88..37dfdf77 100644
--- a/pydis_site/templates/events/sidebar/upcoming-event.html
+++ b/pydis_site/templates/events/sidebar/ongoing-event.html
@@ -1,7 +1,7 @@
{% load static %}
<div class="box">
- <p class="menu-label">Upcoming Event</p>
+ <p class="menu-label">Ongoing Event</p>
<a href="{% url "events:page" path="code-jams/8" %}">
<img src="{% static "images/events/summer_code_jam_2021/banner.png" %}" alt="Summer Code Jam 2021">
</a>
diff --git a/pydis_site/templates/home/index.html b/pydis_site/templates/home/index.html
index 2efa5b49..072e3817 100644
--- a/pydis_site/templates/home/index.html
+++ b/pydis_site/templates/home/index.html
@@ -12,7 +12,7 @@
<!-- Mobile-only Notice -->
<section id="mobile-notice" class="message is-primary is-hidden-tablet">
<a href="/events/code-jams/8/">
- <img src="{% static "images/events/summer_code_jam_2021/front_page_banners/sign_up_now.png" %}" alt="Summer Code Jam 2021">
+ <img src="{% static "images/events/summer_code_jam_2021/front_page_banners/currently_live.png" %}" alt="Summer Code Jam 2021">
</a>
</section>
@@ -48,7 +48,7 @@
{# Code Jam banner #}
<div id="wave-hero-right" class="column is-half">
<a href="/events/code-jams/8/">
- <img src="{% static "images/events/summer_code_jam_2021/front_page_banners/sign_up_now.png" %}" alt="Summer Code Jam 2021">
+ <img src="{% static "images/events/summer_code_jam_2021/front_page_banners/currently_live.png" %}" alt="Summer Code Jam 2021">
</a>
</div>
</div>
diff --git a/pydis_site/templates/home/timeline.html b/pydis_site/templates/home/timeline.html
index d9069aca..b404d6c0 100644
--- a/pydis_site/templates/home/timeline.html
+++ b/pydis_site/templates/home/timeline.html
@@ -111,7 +111,7 @@
pretty much as soon as our new bot and site starts collecting some data. To this day, we keep <a
href="https://pythondiscord.com/pages/privacy/">our privacy policy</a> up to date with all
changes, and since April 2020 we've started doing <a
- href="https://pythondiscord.com/pages/data-reviews/">monthly data reviews</a>.</p>
+ href="https://pythondiscord.notion.site/6784e3a9752444e89d19e65fd4510d8d">monthly data reviews</a>.</p>
<div class="flex justify-between items-center">
<span class="cd-timeline__date">May 21st, 2018</span>
diff --git a/pyproject.toml b/pyproject.toml
index f0800db8..8c0dc937 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -21,6 +21,7 @@ gunicorn = "~=20.0.4"
sentry-sdk = "~=0.19"
markdown = "~=3.3.4"
python-frontmatter = "~=1.0"
+django-prometheus = "~=2.1"
[tool.poetry.dev-dependencies]
coverage = "~=5.0"