aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.flake82
-rw-r--r--.github/workflows/deploy.yaml2
-rw-r--r--Dockerfile7
-rw-r--r--docker-compose.yml8
-rw-r--r--gunicorn.conf.py10
-rwxr-xr-xmanage.py45
-rw-r--r--poetry.lock286
-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/migrations/0073_otn_allow_GT_and_LT.py19
-rw-r--r--pydis_site/apps/api/models/bot/documentation_link.py1
-rw-r--r--pydis_site/apps/api/models/bot/metricity.py10
-rw-r--r--pydis_site/apps/api/models/bot/off_topic_channel_name.py2
-rw-r--r--pydis_site/apps/api/models/utils.py2
-rw-r--r--pydis_site/apps/api/tests/test_users.py10
-rw-r--r--pydis_site/apps/api/tests/test_validators.py2
-rw-r--r--pydis_site/apps/api/urls.py2
-rw-r--r--pydis_site/apps/api/viewsets/bot/user.py6
-rw-r--r--pydis_site/apps/content/resources/frequently-asked-questions.md2
-rw-r--r--pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/supplemental-information.md2
-rw-r--r--pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md9
-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/tests/mock_github_api_response.json2
-rw-r--r--pydis_site/apps/home/views/home.py17
-rw-r--r--pydis_site/apps/resources/resources/communities/panda3d.yaml2
-rw-r--r--pydis_site/apps/resources/resources/reading/books/byte_of_python.yaml2
-rw-r--r--pydis_site/apps/resources/resources/reading/books/flask_web_development.yaml2
-rw-r--r--pydis_site/apps/resources/resources/reading/books/python_cookbook.yaml2
-rw-r--r--pydis_site/apps/resources/resources/reading/tutorials/simple_guide_to_git.yaml2
-rw-r--r--pydis_site/apps/resources/resources/videos/microsoft.yaml2
-rw-r--r--pydis_site/constants.py2
-rw-r--r--pydis_site/settings.py29
-rw-r--r--pydis_site/static/css/home/index.css12
-rw-r--r--pydis_site/static/images/sponsors/netlify.pngbin0 -> 177462 bytes
-rw-r--r--pydis_site/templates/base/navbar.html2
-rw-r--r--pydis_site/templates/events/index.html76
-rw-r--r--pydis_site/templates/events/pages/code-jams/8/_index.html68
-rw-r--r--pydis_site/templates/events/pages/code-jams/8/frameworks.html2
-rw-r--r--pydis_site/templates/events/pages/code-jams/_index.html1
-rw-r--r--pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html1
-rw-r--r--pydis_site/templates/events/sidebar/events-list.html10
-rw-r--r--pydis_site/templates/home/index.html22
-rw-r--r--pydis_site/urls.py1
-rw-r--r--pyproject.toml3
44 files changed, 430 insertions, 282 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 c07fc2e2..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
@@ -26,6 +26,11 @@ 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 \
diff --git a/docker-compose.yml b/docker-compose.yml
index 05867a46..eb987624 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -18,6 +18,11 @@ services:
POSTGRES_DB: pysite
POSTGRES_PASSWORD: pysite
POSTGRES_USER: pysite
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U pysite"]
+ interval: 2s
+ timeout: 1s
+ retries: 5
volumes:
- ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
@@ -35,7 +40,8 @@ services:
ports:
- "127.0.0.1:8000:8000"
depends_on:
- - postgres
+ postgres:
+ condition: service_healthy
tty: true
volumes:
- .:/app:ro
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 8bb5ae0d..578f4748 100755
--- a/manage.py
+++ b/manage.py
@@ -1,10 +1,6 @@
#!/usr/bin/env python
import os
-import re
-import socket
import sys
-import time
-from typing import List
import django
from django.contrib.auth import get_user_model
@@ -42,7 +38,7 @@ class SiteManager:
--verbose Sets verbose console output.
"""
- def __init__(self, args: List[str]):
+ def __init__(self, args: list[str]):
self.debug = "--debug" in args
self.silent = "--silent" in args
@@ -85,38 +81,6 @@ class SiteManager:
print(f"Existing bot token found: {token}")
@staticmethod
- def wait_for_postgres() -> None:
- """Wait for the PostgreSQL database specified in DATABASE_URL."""
- print("Waiting for PostgreSQL database.")
-
- # Get database URL based on environmental variable passed in compose
- database_url = os.environ["DATABASE_URL"]
- match = re.search(r"@([\w.]+):(\d+)/", database_url)
- if not match:
- raise OSError("Valid DATABASE_URL environmental variable not found.")
- domain = match.group(1)
- port = int(match.group(2))
-
- # Attempt to connect to the database socket
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
- attempts_left = 10
- while attempts_left:
- try:
- # Ignore 'incomplete startup packet'
- s.connect((domain, port))
- s.shutdown(socket.SHUT_RDWR)
- print("Database is ready.")
- break
- except socket.error:
- attempts_left -= 1
- print("Not ready yet, retrying.")
- time.sleep(0.5)
- else:
- print("Database could not be found, exiting.")
- sys.exit(1)
-
- @staticmethod
def set_dev_site_name() -> None:
"""Set the development site domain in admin from default example."""
# import Site model now after django setup
@@ -133,9 +97,6 @@ class SiteManager:
"""Perform preparation tasks before running the server."""
django.setup()
- if self.debug:
- self.wait_for_postgres()
-
print("Applying migrations.")
call_command("migrate", verbosity=self.verbosity)
@@ -176,12 +137,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 b43cd7ff..c6724cfc 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,14 +1,6 @@
[[package]]
-name = "appdirs"
-version = "1.4.4"
-description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-category = "dev"
-optional = false
-python-versions = "*"
-
-[[package]]
name = "asgiref"
-version = "3.3.4"
+version = "3.4.1"
description = "ASGI specs, helper code, and adapters"
category = "main"
optional = false
@@ -32,6 +24,18 @@ tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)"
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
[[package]]
+name = "backports.entry-points-selectable"
+version = "1.1.0"
+description = "Compatibility shim providing selectable entry points for older implementations"
+category = "dev"
+optional = false
+python-versions = ">=2.7"
+
+[package.extras]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3.7)", "pytest-mypy", "pytest-checkdocs (>=2.4)", "pytest-enabler (>=1.0.1)"]
+
+[[package]]
name = "bandit"
version = "1.7.0"
description = "Security oriented static analyser for python code."
@@ -48,7 +52,7 @@ stevedore = ">=1.20.0"
[[package]]
name = "certifi"
-version = "2020.12.5"
+version = "2021.5.30"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
@@ -56,19 +60,22 @@ python-versions = "*"
[[package]]
name = "cfgv"
-version = "3.2.0"
+version = "3.3.1"
description = "Validate configuration and produce human readable error messages."
category = "dev"
optional = false
python-versions = ">=3.6.1"
[[package]]
-name = "chardet"
-version = "4.0.0"
-description = "Universal encoding detector for Python 2 and 3"
+name = "charset-normalizer"
+version = "2.0.6"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=3.5.0"
+
+[package.extras]
+unicode_backport = ["unicodedata2"]
[[package]]
name = "colorama"
@@ -107,7 +114,7 @@ yaml = ["PyYAML (>=3.10)"]
[[package]]
name = "distlib"
-version = "0.3.1"
+version = "0.3.3"
description = "Distribution utilities"
category = "dev"
optional = false
@@ -150,8 +157,19 @@ python-versions = ">=3.4"
Django = ">=1.11"
[[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.2.0"
+version = "2.4.0"
description = "Django application to add the Bulma CSS framework and its extensions"
category = "main"
optional = false
@@ -185,11 +203,15 @@ python-versions = "*"
[[package]]
name = "filelock"
-version = "3.0.12"
+version = "3.3.0"
description = "A platform independent file lock."
category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.6"
+
+[package.extras]
+docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"]
+testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"]
[[package]]
name = "flake8"
@@ -291,14 +313,14 @@ flake8 = "*"
[[package]]
name = "flake8-tidy-imports"
-version = "4.3.0"
+version = "4.4.1"
description = "A flake8 plugin that helps you write tidier imports."
category = "dev"
optional = false
python-versions = ">=3.6"
[package.dependencies]
-flake8 = ">=3.0,<3.2.0 || >3.2.0,<4"
+flake8 = ">=3.8.0,<4"
[[package]]
name = "flake8-todo"
@@ -324,14 +346,15 @@ smmap = ">=3.0.1,<5"
[[package]]
name = "gitpython"
-version = "3.1.17"
-description = "Python Git Library"
+version = "3.1.24"
+description = "GitPython is a python library used to interact with Git repositories"
category = "dev"
optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.7"
[package.dependencies]
gitdb = ">=4.0.1,<5"
+typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.10\""}
[[package]]
name = "gunicorn"
@@ -349,7 +372,7 @@ tornado = ["tornado (>=0.2)"]
[[package]]
name = "identify"
-version = "2.2.4"
+version = "2.3.0"
description = "File identification library for Python"
category = "dev"
optional = false
@@ -360,15 +383,15 @@ license = ["editdistance-s"]
[[package]]
name = "idna"
-version = "2.10"
+version = "3.2"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.5"
[[package]]
name = "libsass"
-version = "0.20.1"
+version = "0.21.0"
description = "Sass for Python: A straightforward binding of libsass for Python."
category = "main"
optional = false
@@ -422,18 +445,31 @@ python-versions = ">=2.6"
[[package]]
name = "pep8-naming"
-version = "0.11.1"
+version = "0.12.1"
description = "Check PEP-8 naming conventions, plugin for flake8"
category = "dev"
optional = false
python-versions = "*"
[package.dependencies]
+flake8 = ">=3.9.1"
flake8-polyfill = ">=1.0.2,<2"
[[package]]
+name = "platformdirs"
+version = "2.4.0"
+description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
+test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
+
+[[package]]
name = "pre-commit"
-version = "2.12.1"
+version = "2.15.0"
description = "A framework for managing and maintaining multi-language pre-commit hooks."
category = "dev"
optional = false
@@ -448,6 +484,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."
@@ -476,7 +523,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pydocstyle"
-version = "6.0.0"
+version = "6.1.1"
description = "Python docstring style checker"
category = "dev"
optional = false
@@ -485,6 +532,9 @@ python-versions = ">=3.6"
[package.dependencies]
snowballstemmer = "*"
+[package.extras]
+toml = ["toml"]
+
[[package]]
name = "pyfakefs"
version = "4.4.0"
@@ -529,7 +579,7 @@ test = ["pytest", "toml", "pyaml"]
[[package]]
name = "pytz"
-version = "2021.1"
+version = "2021.3"
description = "World timezone definitions, modern and historical"
category = "main"
optional = false
@@ -545,21 +595,21 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
[[package]]
name = "requests"
-version = "2.25.1"
+version = "2.26.0"
description = "Python HTTP for Humans."
category = "main"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
[package.dependencies]
certifi = ">=2017.4.17"
-chardet = ">=3.0.2,<5"
-idna = ">=2.5,<3"
+charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""}
+idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""}
urllib3 = ">=1.21.1,<1.27"
[package.extras]
-security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
+use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
[[package]]
name = "sentry-sdk"
@@ -615,7 +665,7 @@ python-versions = "*"
[[package]]
name = "sqlparse"
-version = "0.4.1"
+version = "0.4.2"
description = "A non-validating SQL parser."
category = "main"
optional = false
@@ -623,7 +673,7 @@ python-versions = ">=3.5"
[[package]]
name = "stevedore"
-version = "3.3.0"
+version = "3.4.0"
description = "Manage dynamic plugins for Python applications"
category = "dev"
optional = false
@@ -654,39 +704,48 @@ optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
+name = "typing-extensions"
+version = "3.10.0.2"
+description = "Backported and Experimental Type Hints for Python 3.5+"
+category = "dev"
+optional = false
+python-versions = "*"
+
+[[package]]
name = "urllib3"
-version = "1.26.4"
+version = "1.26.7"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
[package.extras]
+brotli = ["brotlipy (>=0.6.0)"]
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
-brotli = ["brotlipy (>=0.6.0)"]
[[package]]
name = "virtualenv"
-version = "20.4.6"
+version = "20.8.1"
description = "Virtual Python Environment builder"
category = "dev"
optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
[package.dependencies]
-appdirs = ">=1.4.3,<2"
+"backports.entry-points-selectable" = ">=1.0.4"
distlib = ">=0.3.1,<1"
filelock = ">=3.0.0,<4"
+platformdirs = ">=2,<3"
six = ">=1.9.0,<2"
[package.extras]
docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"]
-testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)", "xonsh (>=0.9.16)"]
+testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"]
[[package]]
name = "whitenoise"
-version = "5.2.0"
+version = "5.3.0"
description = "Radically simplified static file serving for WSGI applications"
category = "main"
optional = false
@@ -698,36 +757,36 @@ brotli = ["brotli"]
[metadata]
lock-version = "1.1"
python-versions = "3.9.*"
-content-hash = "b5750a4a7ad3e6d1f51c3053164889e0e58b004bf7f92b908cd3d6316e7e9945"
+content-hash = "ed7da8dbc905d4f2c47e01301b49c4aed0083bee269da0ee5ebcc3abee4ab1a0"
[metadata.files]
-appdirs = [
- {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
- {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
-]
asgiref = [
- {file = "asgiref-3.3.4-py3-none-any.whl", hash = "sha256:92906c611ce6c967347bbfea733f13d6313901d54dcca88195eaeb52b2a8e8ee"},
- {file = "asgiref-3.3.4.tar.gz", hash = "sha256:d1216dfbdfb63826470995d31caed36225dcaf34f182e0fa257a4dd9e86f1b78"},
+ {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"},
+ {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
]
attrs = [
{file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
{file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
]
+"backports.entry-points-selectable" = [
+ {file = "backports.entry_points_selectable-1.1.0-py2.py3-none-any.whl", hash = "sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc"},
+ {file = "backports.entry_points_selectable-1.1.0.tar.gz", hash = "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a"},
+]
bandit = [
{file = "bandit-1.7.0-py3-none-any.whl", hash = "sha256:216be4d044209fa06cf2a3e51b319769a51be8318140659719aa7a115c35ed07"},
{file = "bandit-1.7.0.tar.gz", hash = "sha256:8a4c7415254d75df8ff3c3b15cfe9042ecee628a1e40b44c15a98890fbfc2608"},
]
certifi = [
- {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"},
- {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"},
+ {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
+ {file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"},
]
cfgv = [
- {file = "cfgv-3.2.0-py2.py3-none-any.whl", hash = "sha256:32e43d604bbe7896fe7c248a9c2276447dbef840feb28fe20494f62af110211d"},
- {file = "cfgv-3.2.0.tar.gz", hash = "sha256:cf22deb93d4bcf92f345a5c3cd39d3d41d6340adc60c78bbbd6588c384fda6a1"},
+ {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
+ {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
]
-chardet = [
- {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"},
- {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"},
+charset-normalizer = [
+ {file = "charset-normalizer-2.0.6.tar.gz", hash = "sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f"},
+ {file = "charset_normalizer-2.0.6-py3-none-any.whl", hash = "sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6"},
]
colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
@@ -792,8 +851,8 @@ coveralls = [
{file = "coveralls-2.2.0.tar.gz", hash = "sha256:b990ba1f7bc4288e63340be0433698c1efe8217f78c689d254c2540af3d38617"},
]
distlib = [
- {file = "distlib-0.3.1-py2.py3-none-any.whl", hash = "sha256:8c09de2c67b3e7deef7184574fc060ab8a793e7adbb183d942c389c8b13c52fb"},
- {file = "distlib-0.3.1.zip", hash = "sha256:edf6116872c863e1aa9d5bb7cb5e05a022c519a4594dc703843343a9ddd9bff1"},
+ {file = "distlib-0.3.3-py2.py3-none-any.whl", hash = "sha256:c8b54e8454e5bf6237cc84c20e8264c3e991e824ef27e8f1e81049867d861e31"},
+ {file = "distlib-0.3.3.zip", hash = "sha256:d982d0751ff6eaaab5e2ec8e691d949ee80eddf01a62eaa96ddb11531fe16b05"},
]
django = [
{file = "Django-3.0.14-py3-none-any.whl", hash = "sha256:9bc7aa619ed878fedba62ce139abe663a147dccfd20e907725ec11e02a1ca225"},
@@ -807,9 +866,13 @@ django-filter = [
{file = "django-filter-2.1.0.tar.gz", hash = "sha256:3dafb7d2810790498895c22a1f31b2375795910680ac9c1432821cbedb1e176d"},
{file = "django_filter-2.1.0-py3-none-any.whl", hash = "sha256:a3014de317bef0cd43075a0f08dfa1d319a7ccc5733c3901fb860da70b0dda68"},
]
+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.2.0.tar.gz", hash = "sha256:dfc34839e050d5e4749498806ed7ee8c77794021efa54ab224a2de925c644fea"},
- {file = "django_simple_bulma-2.2.0-py3-none-any.whl", hash = "sha256:38530d787b2b6a091b480f7cbb8841a3b3709733ebfa5e543ae339c3d8fece03"},
+ {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"},
]
djangorestframework = [
{file = "djangorestframework-3.11.2-py3-none-any.whl", hash = "sha256:5cc724dc4b076463497837269107e1995b1fbc917468d1b92d188fd1af9ea789"},
@@ -819,8 +882,8 @@ docopt = [
{file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"},
]
filelock = [
- {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"},
- {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"},
+ {file = "filelock-3.3.0-py3-none-any.whl", hash = "sha256:bbc6a0382fe8ec4744ecdf6683a2e07f65eb10ff1aff53fc02a202565446cde0"},
+ {file = "filelock-3.3.0.tar.gz", hash = "sha256:8c7eab13dc442dc249e95158bcc12dec724465919bdc9831fdbf0660f03d1785"},
]
flake8 = [
{file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
@@ -854,8 +917,8 @@ flake8-string-format = [
{file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"},
]
flake8-tidy-imports = [
- {file = "flake8-tidy-imports-4.3.0.tar.gz", hash = "sha256:e66d46f58ed108f36da920e7781a728dc2d8e4f9269e7e764274105700c0a90c"},
- {file = "flake8_tidy_imports-4.3.0-py3-none-any.whl", hash = "sha256:d6e64cb565ca9474d13d5cb3f838b8deafb5fed15906998d4a674daf55bd6d89"},
+ {file = "flake8-tidy-imports-4.4.1.tar.gz", hash = "sha256:c18b3351b998787db071e766e318da1f0bd9d5cecc69c4022a69e7aa2efb2c51"},
+ {file = "flake8_tidy_imports-4.4.1-py3-none-any.whl", hash = "sha256:631a1ba9daaedbe8bb53f6086c5a92b390e98371205259e0e311a378df8c3dc8"},
]
flake8-todo = [
{file = "flake8-todo-0.7.tar.gz", hash = "sha256:6e4c5491ff838c06fe5a771b0e95ee15fc005ca57196011011280fc834a85915"},
@@ -865,35 +928,31 @@ gitdb = [
{file = "gitdb-4.0.7.tar.gz", hash = "sha256:96bf5c08b157a666fec41129e6d327235284cca4c81e92109260f353ba138005"},
]
gitpython = [
- {file = "GitPython-3.1.17-py3-none-any.whl", hash = "sha256:29fe82050709760081f588dd50ce83504feddbebdc4da6956d02351552b1c135"},
- {file = "GitPython-3.1.17.tar.gz", hash = "sha256:ee24bdc93dce357630764db659edaf6b8d664d4ff5447ccfeedd2dc5c253f41e"},
+ {file = "GitPython-3.1.24-py3-none-any.whl", hash = "sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647"},
+ {file = "GitPython-3.1.24.tar.gz", hash = "sha256:df83fdf5e684fef7c6ee2c02fc68a5ceb7e7e759d08b694088d0cacb4eba59e5"},
]
gunicorn = [
{file = "gunicorn-20.0.4-py2.py3-none-any.whl", hash = "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c"},
{file = "gunicorn-20.0.4.tar.gz", hash = "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626"},
]
identify = [
- {file = "identify-2.2.4-py2.py3-none-any.whl", hash = "sha256:ad9f3fa0c2316618dc4d840f627d474ab6de106392a4f00221820200f490f5a8"},
- {file = "identify-2.2.4.tar.gz", hash = "sha256:9bcc312d4e2fa96c7abebcdfb1119563b511b5e3985ac52f60d9116277865b2e"},
+ {file = "identify-2.3.0-py2.py3-none-any.whl", hash = "sha256:d1e82c83d063571bb88087676f81261a4eae913c492dafde184067c584bc7c05"},
+ {file = "identify-2.3.0.tar.gz", hash = "sha256:fd08c97f23ceee72784081f1ce5125c8f53a02d3f2716dde79a6ab8f1039fea5"},
]
idna = [
- {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
- {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
+ {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"},
+ {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"},
]
libsass = [
- {file = "libsass-0.20.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:4a246e4b88fd279abef8b669206228c92534d96ddcd0770d7012088c408dff23"},
- {file = "libsass-0.20.1-cp27-cp27m-win32.whl", hash = "sha256:697f0f9fa8a1367ca9ec6869437cb235b1c537fc8519983d1d890178614a8903"},
- {file = "libsass-0.20.1-cp27-cp27m-win_amd64.whl", hash = "sha256:1b2d415bbf6fa7da33ef46e549db1418498267b459978eff8357e5e823962d35"},
- {file = "libsass-0.20.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1521d2a8d4b397c6ec90640a1f6b5529077035efc48ef1c2e53095544e713d1b"},
- {file = "libsass-0.20.1-cp36-abi3-macosx_10_14_x86_64.whl", hash = "sha256:2ae806427b28bc1bb7cb0258666d854fcf92ba52a04656b0b17ba5e190fb48a9"},
- {file = "libsass-0.20.1-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:25ebc2085f5eee574761ccc8d9cd29a9b436fc970546d5ef08c6fa41eb57dff1"},
- {file = "libsass-0.20.1-cp36-cp36m-win32.whl", hash = "sha256:553e5096414a8d4fb48d0a48f5a038d3411abe254d79deac5e008516c019e63a"},
- {file = "libsass-0.20.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e64ae2587f1a683e831409aad03ba547c245ef997e1329fffadf7a866d2510b8"},
- {file = "libsass-0.20.1-cp37-cp37m-win32.whl", hash = "sha256:c9411fec76f480ffbacc97d8188322e02a5abca6fc78e70b86a2a2b421eae8a2"},
- {file = "libsass-0.20.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a8fd4af9f853e8bf42b1425c5e48dd90b504fa2e70d7dac5ac80b8c0a5a5fe85"},
- {file = "libsass-0.20.1-cp38-cp38-win32.whl", hash = "sha256:f6852828e9e104d2ce0358b73c550d26dd86cc3a69439438c3b618811b9584f5"},
- {file = "libsass-0.20.1-cp38-cp38-win_amd64.whl", hash = "sha256:daa98a51086d92aa7e9c8871cf1a8258124b90e2abf4697852a3dca619838618"},
- {file = "libsass-0.20.1.tar.gz", hash = "sha256:e0e60836eccbf2d9e24ec978a805cd6642fa92515fbd95e3493fee276af76f8a"},
+ {file = "libsass-0.21.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:06c8776417fe930714bdc930a3d7e795ae3d72be6ac883ff72a1b8f7c49e5ffb"},
+ {file = "libsass-0.21.0-cp27-cp27m-win32.whl", hash = "sha256:a005f298f64624f313a3ac618ab03f844c71d84ae4f4a4aec4b68d2a4ffe75eb"},
+ {file = "libsass-0.21.0-cp27-cp27m-win_amd64.whl", hash = "sha256:6b984510ed94993708c0d697b4fef2d118929bbfffc3b90037be0f5ccadf55e7"},
+ {file = "libsass-0.21.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e25dd9047a9392d3c59a0b869e0404f2b325a03871ee45285ee33b3664f5613"},
+ {file = "libsass-0.21.0-cp36-abi3-macosx_10_14_x86_64.whl", hash = "sha256:12f39712de38689a8b785b7db41d3ba2ea1d46f9379d81ea4595802d91fa6529"},
+ {file = "libsass-0.21.0-cp36-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e2b1a7d093f2e76dc694c17c0c285e846d0b0deb0e8b21dc852ba1a3a4e2f1d6"},
+ {file = "libsass-0.21.0-cp36-abi3-win32.whl", hash = "sha256:abc29357ee540849faf1383e1746d40d69ed5cb6d4c346df276b258f5aa8977a"},
+ {file = "libsass-0.21.0-cp36-abi3-win_amd64.whl", hash = "sha256:659ae41af8708681fa3ec73f47b9735a6725e71c3b66ff570bfce78952f2314e"},
+ {file = "libsass-0.21.0.tar.gz", hash = "sha256:d5ba529d9ce668be9380563279f3ffe988f27bc5b299c5a28453df2e0b0fbaf2"},
]
markdown = [
{file = "Markdown-3.3.4-py3-none-any.whl", hash = "sha256:96c3ba1261de2f7547b46a00ea8463832c921d3f9d6aba3f255a6f71386db20c"},
@@ -916,12 +975,20 @@ pbr = [
{file = "pbr-5.6.0.tar.gz", hash = "sha256:42df03e7797b796625b1029c0400279c7c34fd7df24a7d7818a1abb5b38710dd"},
]
pep8-naming = [
- {file = "pep8-naming-0.11.1.tar.gz", hash = "sha256:a1dd47dd243adfe8a83616e27cf03164960b507530f155db94e10b36a6cd6724"},
- {file = "pep8_naming-0.11.1-py2.py3-none-any.whl", hash = "sha256:f43bfe3eea7e0d73e8b5d07d6407ab47f2476ccaeff6937c84275cd30b016738"},
+ {file = "pep8-naming-0.12.1.tar.gz", hash = "sha256:bb2455947757d162aa4cad55dba4ce029005cd1692f2899a21d51d8630ca7841"},
+ {file = "pep8_naming-0.12.1-py2.py3-none-any.whl", hash = "sha256:4a8daeaeb33cfcde779309fc0c9c0a68a3bbe2ad8a8308b763c5068f86eb9f37"},
+]
+platformdirs = [
+ {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"},
+ {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"},
]
pre-commit = [
- {file = "pre_commit-2.12.1-py2.py3-none-any.whl", hash = "sha256:70c5ec1f30406250b706eda35e868b87e3e4ba099af8787e3e8b4b01e84f4712"},
- {file = "pre_commit-2.12.1.tar.gz", hash = "sha256:900d3c7e1bf4cf0374bb2893c24c23304952181405b4d88c9c40b72bda1bb8a9"},
+ {file = "pre_commit-2.15.0-py2.py3-none-any.whl", hash = "sha256:a4ed01000afcb484d9eb8d504272e642c4c4099bbad3a6b27e519bd6a3e928a6"},
+ {file = "pre_commit-2.15.0.tar.gz", hash = "sha256:3c25add78dbdfb6a28a651780d5c311ac40dd17f160eb3954a0c59da40a505a7"},
+]
+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"},
@@ -995,8 +1062,8 @@ pycodestyle = [
{file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
]
pydocstyle = [
- {file = "pydocstyle-6.0.0-py3-none-any.whl", hash = "sha256:d4449cf16d7e6709f63192146706933c7a334af7c0f083904799ccb851c50f6d"},
- {file = "pydocstyle-6.0.0.tar.gz", hash = "sha256:164befb520d851dbcf0e029681b91f4f599c62c5cd8933fd54b1bfbd50e89e1f"},
+ {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"},
+ {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"},
]
pyfakefs = [
{file = "pyfakefs-4.4.0-py3-none-any.whl", hash = "sha256:1ac3b2845dabe69af56c20691b9347914581195ccdde352535fb7d4ff0055c19"},
@@ -1015,8 +1082,8 @@ python-frontmatter = [
{file = "python_frontmatter-1.0.0-py3-none-any.whl", hash = "sha256:766ae75f1b301ffc5fe3494339147e0fd80bc3deff3d7590a93991978b579b08"},
]
pytz = [
- {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
- {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
+ {file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"},
+ {file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"},
]
pyyaml = [
{file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"},
@@ -1050,8 +1117,8 @@ pyyaml = [
{file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
]
requests = [
- {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"},
- {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"},
+ {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
+ {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
]
sentry-sdk = [
{file = "sentry-sdk-0.20.3.tar.gz", hash = "sha256:4ae8d1ced6c67f1c8ea51d82a16721c166c489b76876c9f2c202b8a50334b237"},
@@ -1070,12 +1137,12 @@ snowballstemmer = [
{file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"},
]
sqlparse = [
- {file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"},
- {file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"},
+ {file = "sqlparse-0.4.2-py3-none-any.whl", hash = "sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"},
+ {file = "sqlparse-0.4.2.tar.gz", hash = "sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae"},
]
stevedore = [
- {file = "stevedore-3.3.0-py3-none-any.whl", hash = "sha256:50d7b78fbaf0d04cd62411188fa7eedcb03eb7f4c4b37005615ceebe582aa82a"},
- {file = "stevedore-3.3.0.tar.gz", hash = "sha256:3a5bbd0652bf552748871eaa73a4a8dc2899786bc497a2aa1fcb4dcdb0debeee"},
+ {file = "stevedore-3.4.0-py3-none-any.whl", hash = "sha256:920ce6259f0b2498aaa4545989536a27e4e4607b8318802d7ddc3a533d3d069e"},
+ {file = "stevedore-3.4.0.tar.gz", hash = "sha256:59b58edb7f57b11897f150475e7bc0c39c5381f0b8e3fa9f5c20ce6c89ec4aa1"},
]
taskipy = [
{file = "taskipy-1.7.0-py3-none-any.whl", hash = "sha256:9e284c10898e9dee01a3e72220b94b192b1daa0f560271503a6df1da53d03844"},
@@ -1085,15 +1152,20 @@ toml = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
+typing-extensions = [
+ {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"},
+ {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"},
+ {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"},
+]
urllib3 = [
- {file = "urllib3-1.26.4-py2.py3-none-any.whl", hash = "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df"},
- {file = "urllib3-1.26.4.tar.gz", hash = "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"},
+ {file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"},
+ {file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"},
]
virtualenv = [
- {file = "virtualenv-20.4.6-py2.py3-none-any.whl", hash = "sha256:307a555cf21e1550885c82120eccaf5acedf42978fd362d32ba8410f9593f543"},
- {file = "virtualenv-20.4.6.tar.gz", hash = "sha256:72cf267afc04bf9c86ec932329b7e94db6a0331ae9847576daaa7ca3c86b29a4"},
+ {file = "virtualenv-20.8.1-py2.py3-none-any.whl", hash = "sha256:10062e34c204b5e4ec5f62e6ef2473f8ba76513a9a617e873f1f8fb4a519d300"},
+ {file = "virtualenv-20.8.1.tar.gz", hash = "sha256:bcc17f0b3a29670dd777d6f0755a4c04f28815395bca279cdcb213b97199a6b8"},
]
whitenoise = [
- {file = "whitenoise-5.2.0-py2.py3-none-any.whl", hash = "sha256:05d00198c777028d72d8b0bbd234db605ef6d60e9410125124002518a48e515d"},
- {file = "whitenoise-5.2.0.tar.gz", hash = "sha256:05ce0be39ad85740a78750c86a93485c40f08ad8c62a6006de0233765996e5c7"},
+ {file = "whitenoise-5.3.0-py2.py3-none-any.whl", hash = "sha256:d963ef25639d1417e8a247be36e6aedd8c7c6f0a08adcb5a89146980a96b577c"},
+ {file = "whitenoise-5.3.0.tar.gz", hash = "sha256:d234b871b52271ae7ed6d9da47ffe857c76568f11dd30e28e18c5869dbd11e12"},
]
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/migrations/0073_otn_allow_GT_and_LT.py b/pydis_site/apps/api/migrations/0073_otn_allow_GT_and_LT.py
new file mode 100644
index 00000000..09ad13da
--- /dev/null
+++ b/pydis_site/apps/api/migrations/0073_otn_allow_GT_and_LT.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.0.14 on 2021-09-27 20:38
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0072_doc_allow_blank_base_url'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='offtopicchannelname',
+ name='name',
+ field=models.CharField(help_text='The actual channel name that will be used on our Discord server.', max_length=96, primary_key=True, serialize=False, validators=[django.core.validators.RegexValidator(regex="^[a-z0-9\\U0001d5a0-\\U0001d5b9-ǃ?’'<>]+$")]),
+ ),
+ ]
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/api/models/bot/metricity.py b/pydis_site/apps/api/models/bot/metricity.py
index 5daa5c66..33fb7ad7 100644
--- a/pydis_site/apps/api/models/bot/metricity.py
+++ b/pydis_site/apps/api/models/bot/metricity.py
@@ -10,7 +10,7 @@ EXCLUDE_CHANNELS = [
]
-class NotFound(Exception):
+class NotFoundError(Exception):
"""Raised when an entity cannot be found."""
pass
@@ -37,7 +37,7 @@ class Metricity:
values = self.cursor.fetchone()
if not values:
- raise NotFound()
+ raise NotFoundError()
return dict(zip(columns, values))
@@ -58,7 +58,7 @@ class Metricity:
values = self.cursor.fetchone()
if not values:
- raise NotFound()
+ raise NotFoundError()
return values[0]
@@ -88,7 +88,7 @@ class Metricity:
values = self.cursor.fetchone()
if not values:
- raise NotFound()
+ raise NotFoundError()
return values[0]
@@ -127,6 +127,6 @@ class Metricity:
values = self.cursor.fetchall()
if not values:
- raise NotFound()
+ raise NotFoundError()
return values
diff --git a/pydis_site/apps/api/models/bot/off_topic_channel_name.py b/pydis_site/apps/api/models/bot/off_topic_channel_name.py
index 403c7465..8999e560 100644
--- a/pydis_site/apps/api/models/bot/off_topic_channel_name.py
+++ b/pydis_site/apps/api/models/bot/off_topic_channel_name.py
@@ -11,7 +11,7 @@ class OffTopicChannelName(ModelReprMixin, models.Model):
primary_key=True,
max_length=96,
validators=(
- RegexValidator(regex=r"^[a-z0-9\U0001d5a0-\U0001d5b9-ǃ?’']+$"),
+ RegexValidator(regex=r"^[a-z0-9\U0001d5a0-\U0001d5b9-ǃ?’'<>]+$"),
),
help_text="The actual channel name that will be used on our Discord server."
)
diff --git a/pydis_site/apps/api/models/utils.py b/pydis_site/apps/api/models/utils.py
index 107231ba..0e220a1d 100644
--- a/pydis_site/apps/api/models/utils.py
+++ b/pydis_site/apps/api/models/utils.py
@@ -142,7 +142,7 @@ def validate_embed(embed: Any) -> None:
),
MaxLengthValidator(limit_value=256)
),
- 'description': (MaxLengthValidator(limit_value=2048),),
+ 'description': (MaxLengthValidator(limit_value=4096),),
'fields': (
MaxLengthValidator(limit_value=25),
validate_embed_fields
diff --git a/pydis_site/apps/api/tests/test_users.py b/pydis_site/apps/api/tests/test_users.py
index bed6342e..77876d6f 100644
--- a/pydis_site/apps/api/tests/test_users.py
+++ b/pydis_site/apps/api/tests/test_users.py
@@ -5,7 +5,7 @@ from django.urls import reverse
from .base import AuthenticatedAPITestCase
from ..models import Role, User
-from ..models.bot.metricity import NotFound
+from ..models.bot.metricity import NotFoundError
class UnauthedUserAPITests(AuthenticatedAPITestCase):
@@ -501,7 +501,7 @@ class UserMetricityTests(AuthenticatedAPITestCase):
self.metricity = patcher.start()
self.addCleanup(patcher.stop)
self.metricity = self.metricity.return_value.__enter__.return_value
- self.metricity.user.side_effect = NotFound()
- self.metricity.total_messages.side_effect = NotFound()
- self.metricity.total_message_blocks.side_effect = NotFound()
- self.metricity.top_channel_activity.side_effect = NotFound()
+ self.metricity.user.side_effect = NotFoundError()
+ self.metricity.total_messages.side_effect = NotFoundError()
+ self.metricity.total_message_blocks.side_effect = NotFoundError()
+ self.metricity.top_channel_activity.side_effect = NotFoundError()
diff --git a/pydis_site/apps/api/tests/test_validators.py b/pydis_site/apps/api/tests/test_validators.py
index 8bb7b917..551cc2aa 100644
--- a/pydis_site/apps/api/tests/test_validators.py
+++ b/pydis_site/apps/api/tests/test_validators.py
@@ -72,7 +72,7 @@ class TagEmbedValidatorTests(TestCase):
def test_rejects_too_long_description(self):
with self.assertRaises(ValidationError):
validate_embed({
- 'description': 'd' * 2049
+ 'description': 'd' * 4097
})
def test_allows_valid_embed(self):
diff --git a/pydis_site/apps/api/urls.py b/pydis_site/apps/api/urls.py
index 2e1ef0b4..b0ab545b 100644
--- a/pydis_site/apps/api/urls.py
+++ b/pydis_site/apps/api/urls.py
@@ -16,7 +16,7 @@ from .viewsets import (
UserViewSet
)
-# http://www.django-rest-framework.org/api-guide/routers/#defaultrouter
+# https://www.django-rest-framework.org/api-guide/routers/#defaultrouter
bot_router = DefaultRouter(trailing_slash=False)
bot_router.register(
'filter-lists',
diff --git a/pydis_site/apps/api/viewsets/bot/user.py b/pydis_site/apps/api/viewsets/bot/user.py
index 25722f5a..0356e193 100644
--- a/pydis_site/apps/api/viewsets/bot/user.py
+++ b/pydis_site/apps/api/viewsets/bot/user.py
@@ -11,7 +11,7 @@ from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from pydis_site.apps.api.models.bot.infraction import Infraction
-from pydis_site.apps.api.models.bot.metricity import Metricity, NotFound
+from pydis_site.apps.api.models.bot.metricity import Metricity, NotFoundError
from pydis_site.apps.api.models.bot.user import User
from pydis_site.apps.api.serializers import UserSerializer
@@ -275,7 +275,7 @@ class UserViewSet(ModelViewSet):
data["voice_banned"] = voice_banned
data["activity_blocks"] = metricity.total_message_blocks(user.id)
return Response(data, status=status.HTTP_200_OK)
- except NotFound:
+ except NotFoundError:
return Response(dict(detail="User not found in metricity"),
status=status.HTTP_404_NOT_FOUND)
@@ -290,6 +290,6 @@ class UserViewSet(ModelViewSet):
data["total_messages"] = metricity.total_messages(user.id)
data["top_channel_activity"] = metricity.top_channel_activity(user.id)
return Response(data, status=status.HTTP_200_OK)
- except NotFound:
+ except NotFoundError:
return Response(dict(detail="User not found in metricity"),
status=status.HTTP_404_NOT_FOUND)
diff --git a/pydis_site/apps/content/resources/frequently-asked-questions.md b/pydis_site/apps/content/resources/frequently-asked-questions.md
index 212ea5f8..a9a092fe 100644
--- a/pydis_site/apps/content/resources/frequently-asked-questions.md
+++ b/pydis_site/apps/content/resources/frequently-asked-questions.md
@@ -89,7 +89,7 @@ It's also to ease the burden on our moderators, otherwise they would have to dow
Even though Discord does support previewing of files like `.txt` and `.py`, that support is only available on Desktop, not mobile. Additionally, we prefer people to use hastebin as it encourages them to only copy over the relevant code snippets instead of their whole code; this makes helping much easier for all involved.
-If you want to share code please use our hosted hastebin, [paste.pythondiscord.com](http://paste.pythondiscord.com).
+If you want to share code please use our hosted hastebin, [paste.pythondiscord.com](https://paste.pythondiscord.com).
#### **Q: Why is this permission not allowed in that channel?**
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/supplemental-information.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/supplemental-information.md
index 70d47563..e64e4fc6 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/supplemental-information.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/supplemental-information.md
@@ -90,7 +90,7 @@ Our projects currently defines logging levels as follows, from lowest to highest
- **ERROR:** These events can cause a failure in a specific part of the application and require urgent attention.
- **CRITICAL:** These events can cause the whole application to fail and require immediate intervention.
-Any logging above the **INFO** level will trigger a [Sentry](http://sentry.io) issue and alert the Core Developer team.
+Any logging above the **INFO** level will trigger a [Sentry](https://sentry.io) issue and alert the Core Developer team.
## Draft Pull Requests
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 068b08ae..60169c01 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
@@ -16,6 +16,15 @@ toc: 1
- [MacOS Installer](https://git-scm.com/download/mac) or `brew install git`
- [Linux](https://git-scm.com/download/linux)
+## Using Gitpod
+Sir Lancebot can be edited and tested on Gitpod. Gitpod will automatically install the correct dependencies and Python version, so you can get straight to coding.
+To do this, you will need a Gitpod account, which you can get [here](https://www.gitpod.io/#get-started), and a fork of Sir Lancebot. This guide covers forking the repository [here](#fork-the-project). Afterwards, either click the button on Sir Lancebot's README or go to [https://gitpod.io/#/python-discord/sir-lancebot]() and run the following commands in the terminal:
+```sh
+git remote rename origin upstream
+git add remote origin https://github.com/{your_username}/sir-lancebot
+```
+Make sure you replace `{your_username}` with your Github username. These commands will set Python Discord as the parent repository, and your branch as the fork. This means you can easily grab new changes from the parent repository. Once you set your environment variables to test your code, you are ready to begin contributing to Sir Lancebot.
+
## Using Docker
Sir Lancebot can be started using Docker. Using Docker is generally recommended (but not strictly required) because it abstracts away some additional set up work.
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 2a7ef0d6..eba737ad 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
@@ -43,7 +43,7 @@ If you will be working with an external service, you might have to set one of th
| -------- | -------- |
| `GITHUB_TOKEN` | Personal access token for GitHub, raises rate limits from 60 to 5000 requests per hour. |
| `GIPHY_TOKEN` | Required for API access. [Docs](https://developers.giphy.com/docs/api) |
-| `OMDB_API_KEY` | Required for API access. [Docs](http://www.omdbapi.com/) |
+| `OMDB_API_KEY` | Required for API access. [Docs](https://www.omdbapi.com/) |
| `REDDIT_CLIENT_ID` | OAuth2 client ID for authenticating with the [reddit API](https://github.com/reddit-archive/reddit/wiki/OAuth2). |
| `REDDIT_SECRET` | OAuth2 secret for authenticating with the reddit API. *Leave empty if you're not using the reddit API.* |
| `REDDIT_WEBHOOK` | Webhook ID for Reddit channel |
diff --git a/pydis_site/apps/home/tests/mock_github_api_response.json b/pydis_site/apps/home/tests/mock_github_api_response.json
index ddbffed8..3b0a7078 100644
--- a/pydis_site/apps/home/tests/mock_github_api_response.json
+++ b/pydis_site/apps/home/tests/mock_github_api_response.json
@@ -21,7 +21,7 @@
"forks_count": 31
},
{
- "full_name": "python-discord/django-simple-bulma",
+ "full_name": "python-discord/king-arthur",
"description": "test",
"stargazers_count": 97,
"language": "Python",
diff --git a/pydis_site/apps/home/views/home.py b/pydis_site/apps/home/views/home.py
index 0f26cef3..401c768f 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__)
@@ -27,7 +27,7 @@ class HomeView(View):
"python-discord/snekbox",
"python-discord/sir-lancebot",
"python-discord/metricity",
- "python-discord/django-simple-bulma",
+ "python-discord/king-arthur",
]
def __init__(self):
@@ -51,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:
diff --git a/pydis_site/apps/resources/resources/communities/panda3d.yaml b/pydis_site/apps/resources/resources/communities/panda3d.yaml
index 4235793d..47797882 100644
--- a/pydis_site/apps/resources/resources/communities/panda3d.yaml
+++ b/pydis_site/apps/resources/resources/communities/panda3d.yaml
@@ -1,6 +1,6 @@
description: Panda3D is a Python-focused 3-D framework for rapid development of games,
visualizations, and simulations, written in C++ with an emphasis on performance and flexibility.
-title_image: http://www.panda3d.org/wp-content/uploads/2019/01/panda3d_logo.png
+title_image: https://www.panda3d.org/wp-content/uploads/2019/01/panda3d_logo.png
title_url: https://discord.gg/9XsucTT
position: 9
urls:
diff --git a/pydis_site/apps/resources/resources/reading/books/byte_of_python.yaml b/pydis_site/apps/resources/resources/reading/books/byte_of_python.yaml
index 1f9642ad..2530c1a4 100644
--- a/pydis_site/apps/resources/resources/reading/books/byte_of_python.yaml
+++ b/pydis_site/apps/resources/resources/reading/books/byte_of_python.yaml
@@ -8,7 +8,7 @@ urls:
url: https://python.swaroopch.com/
color: teal
- icon: regular/book
- url: http://www.lulu.com/shop/swaroop-c-h/a-byte-of-python/paperback/product-21142968.html
+ url: https://www.lulu.com/shop/swaroop-c-h/a-byte-of-python/paperback/product-21142968.html
color: black
- icon: branding/amazon
url: https://www.amazon.com/Byte-Python-Swaroop-C-H-ebook/dp/B00FJ7S2JU/
diff --git a/pydis_site/apps/resources/resources/reading/books/flask_web_development.yaml b/pydis_site/apps/resources/resources/reading/books/flask_web_development.yaml
index cc83a331..d191f02d 100644
--- a/pydis_site/apps/resources/resources/reading/books/flask_web_development.yaml
+++ b/pydis_site/apps/resources/resources/reading/books/flask_web_development.yaml
@@ -4,7 +4,7 @@ name: Flask Web Development
position: 6
urls:
- icon: regular/link
- url: http://shop.oreilly.com/product/0636920031116.do
+ url: https://shop.oreilly.com/product/0636920031116.do
color: teal
- icon: branding/amazon
url: https://www.amazon.com/Flask-Web-Development-Developing-Applications/dp/1449372627
diff --git a/pydis_site/apps/resources/resources/reading/books/python_cookbook.yaml b/pydis_site/apps/resources/resources/reading/books/python_cookbook.yaml
index 032f8c64..c939ab9e 100644
--- a/pydis_site/apps/resources/resources/reading/books/python_cookbook.yaml
+++ b/pydis_site/apps/resources/resources/reading/books/python_cookbook.yaml
@@ -4,7 +4,7 @@ name: Python Cookbook
position: 8
urls:
- icon: regular/link
- url: http://shop.oreilly.com/product/0636920027072.do
+ url: https://shop.oreilly.com/product/0636920027072.do
color: teal
- icon: branding/amazon
url: https://www.amazon.com/Python-Cookbook-Third-David-Beazley/dp/1449340377
diff --git a/pydis_site/apps/resources/resources/reading/tutorials/simple_guide_to_git.yaml b/pydis_site/apps/resources/resources/reading/tutorials/simple_guide_to_git.yaml
index a505715d..9d151bf9 100644
--- a/pydis_site/apps/resources/resources/reading/tutorials/simple_guide_to_git.yaml
+++ b/pydis_site/apps/resources/resources/reading/tutorials/simple_guide_to_git.yaml
@@ -1,6 +1,6 @@
description: A simple, no-nonsense guide to the basics of using Git.
name: A Simple Guide to Git
-title_url: http://rogerdudler.github.io/git-guide/
+title_url: https://rogerdudler.github.io/git-guide/
title_icon: branding/github
title_icon_color: black
position: 4
diff --git a/pydis_site/apps/resources/resources/videos/microsoft.yaml b/pydis_site/apps/resources/resources/videos/microsoft.yaml
index 720ee202..3ceaa1a2 100644
--- a/pydis_site/apps/resources/resources/videos/microsoft.yaml
+++ b/pydis_site/apps/resources/resources/videos/microsoft.yaml
@@ -7,7 +7,7 @@ description: A trove of tutorials & guides for developers from Microsoft's Devel
</ul>
Microsoft's Python Development Team also runs a Discord Server for discussions of Python in the Microsoft ecosystem,
including Visual Studio Code and Azure.
-title_image: http://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE2qVsJ?ver=3f74
+title_image: https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE2qVsJ?ver=3f74
position: 4
urls:
- icon: branding/youtube
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 f7c4401d..35afea22 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(
@@ -52,7 +54,17 @@ elif 'CI' in os.environ:
else:
ALLOWED_HOSTS = env.list(
'ALLOWED_HOSTS',
- default=['pythondiscord.com'],
+ default=[
+ 'www.pythondiscord.com',
+ 'pythondiscord.com',
+ gethostname(),
+ gethostbyname(gethostname()),
+ # "That needs to be there for now, until we move back to...
+ # no, don't put that there, actually, yeah, put that there,
+ # that's fine, yeah, no no no no no no, stop it, you're being
+ # a problem now, I'm phoning [DAD'S NAME]" - Joe
+ 'pydis-api.default.svc.cluster.local',
+ ],
)
SECRET_KEY = env('SECRET_KEY')
@@ -77,10 +89,16 @@ 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.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
@@ -89,7 +107,10 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
+
+ 'django_prometheus.middleware.PrometheusAfterMiddleware'
]
+
ROOT_URLCONF = 'pydis_site.urls'
TEMPLATES = [
@@ -170,7 +191,7 @@ else:
PARENT_HOST = env('PARENT_HOST', default='pythondiscord.com')
# Django REST framework
-# http://www.django-rest-framework.org
+# https://www.django-rest-framework.org
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
diff --git a/pydis_site/static/css/home/index.css b/pydis_site/static/css/home/index.css
index ee6f6e4c..7ec8af74 100644
--- a/pydis_site/static/css/home/index.css
+++ b/pydis_site/static/css/home/index.css
@@ -215,12 +215,20 @@ h1 {
}
#sponsors .columns {
+ display: block;
justify-content: center;
margin: auto;
max-width: 80%;
}
+#sponsors a {
+ margin: auto;
+ display: inline-block;
+}
+
#sponsors img {
- height: 5rem;
- margin: auto 1rem;
+ width: auto;
+ height: auto;
+
+ max-height: 5rem;
}
diff --git a/pydis_site/static/images/sponsors/netlify.png b/pydis_site/static/images/sponsors/netlify.png
new file mode 100644
index 00000000..0f14f385
--- /dev/null
+++ b/pydis_site/static/images/sponsors/netlify.png
Binary files differ
diff --git a/pydis_site/templates/base/navbar.html b/pydis_site/templates/base/navbar.html
index d0d708ed..4b68dd6c 100644
--- a/pydis_site/templates/base/navbar.html
+++ b/pydis_site/templates/base/navbar.html
@@ -44,7 +44,7 @@
</a>
{# Patreon #}
- <a class="navbar-item" href="http://patreon.com/python_discord">
+ <a class="navbar-item" href="https://patreon.com/python_discord">
<span class="icon is-size-4 is-medium"><i class="fab fa-patreon"></i></span>
<span>&nbsp;Patreon</span>
</a>
diff --git a/pydis_site/templates/events/index.html b/pydis_site/templates/events/index.html
index daad1c9c..158ec56b 100644
--- a/pydis_site/templates/events/index.html
+++ b/pydis_site/templates/events/index.html
@@ -9,58 +9,34 @@
{% block event_content %}
<div class="box">
<h2 class="title is-4">Code Jams</h2>
- <div class="notification is-success">
- The 2021 Summer Code Jam qualifier will open June 21st. Check out the details <a href="{% url "events:page" path="code-jams/8" %}">here</a>.
- </div>
- <p>Each year, we organize a Winter Code Jam and a Summer Code Jam. During these events, members of our community will work together in teams to create something amazing using a technology we picked for them. One such technology that was picked for the Winter Code Jam 2020 was Kivy, a cross-platform GUI framework.</p>
- <p>To help fuel the creative process, we provide a specific theme, like <strong>Ancient Technology</strong> or <strong>This App Hates You</strong>. At the end of the Code Jam, the projects are judged by Python Discord server staff members and guest judges from the larger Python community. The judges will consider creativity, code quality, teamwork, and adherence to the theme.</p>
+ <p>Each year, we organize at least one code jam, one during the summer and sometimes one during the winter. During these events, members of our community will work together in teams to create something amazing using a technology we picked for them. One such technology that was picked for the Summer 2021 Code Jam was text user interfaces (TUIS), where teams could pick from a pre-approved list of frameworks.</p>
+ <p>To help fuel the creative process, we provide a specific theme, like <strong>Think Inside the Box</strong> or <strong>Early Internet</strong>. At the end of the Code Jam, the projects are judged by Python Discord server staff members and guest judges from the larger Python community. The judges will consider creativity, code quality, teamwork, and adherence to the theme.</p>
<p>If you want to read more about Code Jams, visit our <a href="{% url "events:page" path="code-jams" %}">Code Jam info page</a> or watch this video showcasing the best projects created during the <strong>Winter Code Jam 2020: Ancient Technology</strong>:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/8fbZsGrqBzo" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<div class="box">
- <h2 class="title is-4">Game Jam</h2>
+ <h2 class="title is-4">PyWeek</h2>
<div class="columns is-3" style="--columnGap: 0.75rem;">
<div class="column">
<p>
- The Game Jam is similar to our Code Jams, but smaller in scope. Instead of having to complete a qualifier
- and being teamed up with random strangers, members of our community can just sign-up individually or pair up
- with whoever they like.
- </p>
- <p>
- The participants will have ten days to create a game using the technology we've selected, and drawing
- inspiration from a provided theme. After the event, a panel of judges will play all the games and select a
- winner. The top 5 will featured in a special video on our <a href="https://www.youtube.com/channel/UCQsrA4xo6jvdgsJZhKaBL6w">YouTube channel</a>.
- </p>
- <p>
- The <a class="has-text-link" href="{% url "events:page" path="game-jams/2020" %}">first edition of the Game Jam</a> ran from
- <strong>April 17, 2020 to April 26, 2020</strong>.
+ For the past 15 years, <a href="https://pyweek.org" target="_blank" rel="noopener">PyWeek</a> has been running a bi-annual game jam for the
+ Python language. As of 2020, we are excited to say we are officially partnered with PyWeek to co-run these
+ events.
</p>
- </div>
- <div class="column is-3">
- <img src="https://user-images.githubusercontent.com/33516116/77593036-5fb09780-6eeb-11ea-9feb-336b2e5e23de.png" style="border-radius: 10px;" alt="">
- </div>
- </div>
- </div>
-
- <div class="box">
- <h2 class="title is-4">Hacktoberfest</h2>
- <div class="columns is-3" style="--columnGap: 0.75rem;">
- <div class="column">
<p>
- This event revolves around the annual <a href="https://hacktoberfest.digitalocean.com/">Hacktoberfest
- event</a> organized by Digital Ocean. In addition to promoting Hacktoberfest in our community and supporting
- those who choose to take their first steps into the world of open source, we will also ease our members into
- contributing to open source by starting a low-entry, beginner-friendly open source project where we will
- guide our members through the open source process in a safe environment.
+ During each PyWeek event, we open a special discussion channel in which our members can discuss their
+ submissions, meet other participants, and talk to PyWeek staff. The PyWeek organizer,
+ Daniel Pope (<a href="https://twitter.com/lordmauve" target="_blank" rel="noopener">@lordmauve</a>) will be present during the entire event to answer
+ questions and post announcements and information in our community.
</p>
<p>
- The exact form this event will take has not been decided yet, but we'll make sure to keep you updated in
- our community announcements!
+ Unlike our other events, the <strong>community</strong> will select the winner from all the submissions
+ during PyWeek. We may release YouTube content showcasing the best submissions after the events are finished.
</p>
</div>
<div class="column is-3">
- <img src="https://raw.githubusercontent.com/python-discord/branding/master/seasonal/halloween/hacktoberfest/2020/animated_server_icon.gif" style="border-radius: 10px;" alt="">
+ <img src="https://pyweek.readthedocs.io/en/latest/_static/pyweek.svg" style="border-radius: 10px;" alt="">
</div>
</div>
</div>
@@ -71,7 +47,7 @@
<div class="column">
<p>
Each year, many of our members take part of an online coding competition called
- <a href="https://adventofcode.com/">Advent of Code</a> that takes place in December. Advent of Code is an
+ <a href="https://adventofcode.com/" target="_blank" rel="noopener">Advent of Code</a> that takes place in December. Advent of Code is an
Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved
in any programming language you like, including Python.
</p>
@@ -88,39 +64,37 @@
</p>
</div>
<div class="column is-3">
- <img src="https://raw.githubusercontent.com/python-discord/branding/master/seasonal/christmas/2019/festive_256.gif" style="border-radius: 10px;" alt="">
+ <img src="https://raw.githubusercontent.com/python-discord/branding/main/events/christmas/server_icons/festive_256.gif" style="border-radius: 10px;" alt="">
</div>
</div>
</div>
<div class="box">
- <h2 class="title is-4">PyWeek</h2>
+ <h2 class="title is-4">Game Jam</h2>
<div class="columns is-3" style="--columnGap: 0.75rem;">
<div class="column">
<p>
- For the past 15 years, <a href="https://pyweek.org">PyWeek</a> has been running a bi-annual game jam for the
- Python language. As of 2020, we are excited to say we are officially partnered with PyWeek to co-run these
- events.
+ The Game Jam is similar to our Code Jams, but smaller in scope. Instead of having to complete a qualifier
+ and being teamed up with random strangers, members of our community can just sign-up individually or pair up
+ with whoever they like.
</p>
<p>
- During each PyWeek event, we open a special discussion channel in which our members can discuss their
- submissions, meet other participants, and talk to PyWeek staff. The PyWeek organizer,
- Daniel Pope (<a href="https://twitter.com/lordmauve">@lordmauve</a>) will be present during the entire event to answer
- questions and post announcements and information in our community.
+ The participants will have ten days to create a game using the technology we've selected, and drawing
+ inspiration from a provided theme. After the event, a panel of judges will play all the games and select a
+ winner. The top 5 will featured in a special video on our <a href="https://www.youtube.com/channel/UCQsrA4xo6jvdgsJZhKaBL6w" target="_blank" rel="noopener">YouTube channel</a>.
</p>
<p>
- Unlike our other events, the <strong>community</strong> will select the winner from all the submissions
- during PyWeek. We may release YouTube content showcasing the best submissions after the events are finished.
+ The <a class="has-text-link" href="{% url "events:page" path="game-jams/2020" %}">first edition of the Game Jam</a> ran from
+ <strong>April 17, 2020 to April 26, 2020</strong>.
</p>
</div>
<div class="column is-3">
- <img src="https://pyweek.readthedocs.io/en/latest/_static/pyweek.svg" style="border-radius: 10px;" alt="">
+ <img src="https://user-images.githubusercontent.com/33516116/77593036-5fb09780-6eeb-11ea-9feb-336b2e5e23de.png" style="border-radius: 10px;" alt="">
</div>
</div>
</div>
{% endblock %}
{% block sidebar %}
- {% 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 55bdc95b..628a2c22 100644
--- a/pydis_site/templates/events/pages/code-jams/8/_index.html
+++ b/pydis_site/templates/events/pages/code-jams/8/_index.html
@@ -20,10 +20,58 @@
and walking through the program that your team has created.
</p>
+ <h3 id="winners"><a href="#winners">Code Jam Winners</a></h3>
+ <p>Congratulations to our winners and the two runner ups! Check out their projects below.</p>
+
+ <h4 class="mt-5 mb-2"><i class="fa fa-trophy"></i> Perceptive Porcupines: WTPython!?</h4>
+ <p class="my-1"><em>VV, Poppinawhile, ethansocal, Jeff Z, Cohan, ¯\_(ツ)_/¯</em></p>
+ <p class="my-1">
+ What the Python (wtpython) is a simple terminal user interface that allows you to explore relevant answers on Stackoverflow without leaving your terminal or IDE. When you get an error, all you have to do is swap python for wtpython. When your code hits an error, you'll see a textual interface for exploring relevant answers allowing you to stay focused and ship faster!
+ </p>
+ <p>
+ <a href="https://www.youtube.com/watch?v=DV3uMdsw9KE" title="Perceptive Porcupines Demo Video" target="_blank" rel="noopener"><i class="fa fa-video"> </i> Demo video</a>
+ <br/>
+ <a href="https://github.com/what-the-python/wtpython" title="Perceptive Porcupines GitHub Repository" target="_blank" rel="noopener"><i class="fa fa-github"></i> GitHub Repository</a>
+ <br/>
+
+ </p>
+
+ <h4 class="mt-5 mb-2"><i class="fa fa-medal"></i> Lovable Lobsters: Ultimate Tic Tac Toe</h4>
+ <p class="my-1"><em>A5Rocks, Bast, Dacheat, mega_hirtz, CopOnTheRun, richphi</em></p>
+ <p class="my-1">
+ Thinking inside a box, that is inside a box, that is inside yet another box.
+
+ The terminal program created by the Lovable Lobsters allows you to play Ultimate Tic Tac Toe right form your terminal. The really impressive part though? You can play with your friends and family over your network! Their program has a server-client set-up that lets you play with your friends and family from different computers.
+ </p>
+ <p>
+ <a href="https://www.youtube.com/watch?v=WI9tgQeAfXw" title="Lovable Lobsters Demo Video" target="_blank" rel="noopener"><i class="fa fa-video"> </i> Demo video</a>
+ <br/>
+ <a href="https://github.com/A5rocks/code-jam-8" title="Lovable Lobsters GitHub Repository" target="_blank" rel="noopener"><i class="fa fa-github"></i> GitHub Repository</a>
+ <br/>
+ </p>
+
+ <h4 class="mt-5 mb-2"><i class="fa fa-medal"></i> Robust Reindeer: Rubik's Cube</h4>
+ <p class="my-1"><em>Björn, aaronshenhao, mathsman, Dude Saber, 詭異, Keppo</em></p>
+ <p class="my-1">
+ This submission is a Rubik's cube, rendered in a text user interface (that was a constraint) using the asciimatics package, and addressing the theme "thinking inside the box".
+
+ Just like a real world Rubik's cube, you can move this cube around to look at it from all sides. And, of course, you can rotate the individual discs it is made up of to first scramble up the order and then to try and solve it into perfect ordering again.
+ </p>
+ <p>
+ <a href="https://github.com/bjoseru/pdcj8-robust-reindeer" title="Robust Reindeer GitHub Repository" target="_blank" rel="noopener"><i class="fa fa-github"></i> GitHub Repository</a>
+ <br/>
+ </p>
+
+ <h3 id="submissions"><a href="#submissions">Submissions</a></h3>
+ <p>
+ 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="important-dates"><a href="#important-dates">Important Dates</a></h3>
<ul>
<li>Tuesday, June 15 - Form to submit theme suggestions opens</li>
- <li>Monday, June 21 - <a href="https://github.com/python-discord/cj8-qualifier">The Qualifier</a> is released</li>
+ <li>Monday, June 21 - <a href="https://github.com/python-discord/cj8-qualifier" target="_blank" rel="noopener">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, July 1 - The Qualifier closes</li>
@@ -36,14 +84,14 @@
<p>
The chosen technology/tech stack for this year is <strong>Text User Interfaces</strong> (TUIs).
Each team must create a program with one of <a href="{% url "events:page" path="code-jams/8/frameworks" %}">the approved frameworks</a> that creates a user interface that is text based.
- For more information of TUIs and what's involved with such an interface, check out <a href="https://en.wikipedia.org/wiki/Text-based_user_interface">this wikipedia article</a>.
+ For more information of TUIs and what's involved with such an interface, check out <a href="https://en.wikipedia.org/wiki/Text-based_user_interface" target="_blank" rel="noopener">this wikipedia article</a>.
</p>
- <h3 if="qualifier"><a href="#qualifier">The Qualifier</a></h3>
+ <h3 id="qualifier"><a href="#qualifier">The Qualifier</a></h3>
<p>
The qualifier is a coding challenge that you are required to complete before registering for the code jam.
This is meant as a basic assessment of your skills to ensure you have enough python knowledge to effectively contribute in a team environment.
</p>
- <p class="has-text-centered"><a class="button is-link" href="https://github.com/python-discord/cj8-qualifier" target="_blank">View the Qualifier</a></p
+ <p class="has-text-centered"><a class="button is-link" href="https://github.com/python-discord/cj8-qualifier" target="_blank" rel="noopener">View the Qualifier</a></p>
<p>
Please note the requirements for the qualifier.
<ul>
@@ -52,11 +100,7 @@
<li>The Qualifier must be submitted through the Code Jam sign-up form.</li>
</ul>
</p>
- <h3 id="submissions"><a href="#submissions">Submissions</a></h3>
- <p>
- 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>
Our Code Jam Sponsors have provided prizes for the winners of the code jam.
@@ -71,7 +115,7 @@
<img src="{% static "images/events/DO_Logo_Vertical_Blue.png" %}" alt="Digital Ocean">
</div>
<div class="media-content">
- <p class="subtitle has-link"><a href="https://www.digitalocean.com/">DigitalOcean</a></p>
+ <p class="subtitle has-link"><a href="https://www.digitalocean.com/" target="_blank" rel="noopener">DigitalOcean</a></p>
<p class="is-italic">
Scalable compute platform with add-on storage, security, and monitoring capabilities.
We make it simple to launch in the cloud and scale up as you grow—whether you’re running one virtual machine or ten thousand.
@@ -90,7 +134,7 @@
<img src="{% static "images/sponsors/jetbrains.png" %}" alt="JetBrains">
</div>
<div class="media-content">
- <p class="subtitle has-link"><a href="https://www.jetbrains.com/">JetBrains</a></p>
+ <p class="subtitle has-link"><a href="https://www.jetbrains.com/" target="_blank" rel="noopener">JetBrains</a></p>
<p class="is-italic">
Whatever platform or language you work with, JetBrains has a development tool for you.
We help developers work faster by automating common, repetitive tasks to enable them to stay focused on code design and the big picture.
@@ -109,7 +153,7 @@
<img src="{% static "images/events/Tabnine.png" %}" alt="Tabnine">
</div>
<div class="media-content">
- <p class="subtitle has-link"><a href="https://www.tabnine.com/now?utm_source=discord&utm_medium=Ins&utm_campaign=PythonDis">Tabnine</a></p>
+ <p class="subtitle has-link"><a href="https://www.tabnine.com/now?utm_source=discord&utm_medium=Ins&utm_campaign=PythonDis" target="_blank" rel="noopener">Tabnine</a></p>
<p class="is-italic">Tabnine is an AI-powered code completion tool used by millions of devs around the world every day
- Tabnine supports dozens of programming languages, in all of your favorite IDEs, saving you tons of time - so that you can type less and code more.
Tabnine comes as a plugin and has a free-forever basic plan, so you can get started with it right away!
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 34ac4f0a..1c02e38a 100644
--- a/pydis_site/templates/events/pages/code-jams/8/frameworks.html
+++ b/pydis_site/templates/events/pages/code-jams/8/frameworks.html
@@ -19,7 +19,7 @@
<div class="columns">
<div class="column">
<ul>
- <li><a href="http://urwid.org/" target="_blank">Documentation Link</a></li>
+ <li><a href="https://urwid.org/" target="_blank">Documentation Link</a></li>
<li><strong>Supports:</strong> Linux, Mac, other unix-like OS</li>
<li>Somewhat in-depth tutorial</li>
<li>Uses widgets in a fairly straight forward design</li>
diff --git a/pydis_site/templates/events/pages/code-jams/_index.html b/pydis_site/templates/events/pages/code-jams/_index.html
index 22a86db3..207d4b9a 100644
--- a/pydis_site/templates/events/pages/code-jams/_index.html
+++ b/pydis_site/templates/events/pages/code-jams/_index.html
@@ -66,7 +66,6 @@
{% endblock %}
{% block sidebar %}
- {% 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/sidebar/code-jams/previous-code-jams.html b/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html
index 9f9ecd1a..21b2ccb4 100644
--- a/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html
+++ b/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html
@@ -1,6 +1,7 @@
<div class="box">
<p class="menu-label">Previous Code Jams</p>
<ul class="menu-list">
+ <li><a class="has-text-link" href="{% url "events:page" path="code-jams/8" %}">Code Jam 8: Think Inside the Box</a></li>
<li><a class="has-text-link" href="{% url "events:page" path="code-jams/7" %}">Code Jam 7: Early Internet</a></li>
<li><a class="has-text-link" href="{% url "events:page" path="code-jams/6" %}">Code Jam 6: Ancient Technology</a></li>
<li><a class="has-text-link" href="{% url "events:page" path="code-jams/5" %}">Code Jam 5: Climate Change</a></li>
diff --git a/pydis_site/templates/events/sidebar/events-list.html b/pydis_site/templates/events/sidebar/events-list.html
index 327b0e77..5dfe5dc2 100644
--- a/pydis_site/templates/events/sidebar/events-list.html
+++ b/pydis_site/templates/events/sidebar/events-list.html
@@ -1,10 +1,10 @@
<div class="box">
- <p class="menu-label">Event Calendar 2020</p>
+ <p class="menu-label">Event Calendar 2021</p>
<ul class="menu-list">
- <li><a class="has-text-link" href="{% url "events:page" path="code-jams/6" %}">January 17-January 26: Winter Code Jam</a></li>
- <li><a class="has-text-link" href="{% url "events:page" path="game-jams/2020" %}">April 17-April 26: Game Jam</a></li>
- <li><a class="has-text-link" href="{% url "events:page" path="code-jams/7" %}">July 31-August 9: Summer Code Jam</a></li>
- <li><a class="has-text-black" style="cursor: default;">October: Hacktoberfest</a></li>
+ <li><a class="has-text-link" href="https://pyweek.org/31/" target="_blank" rel="noopener">March: PyWeek 31</a></li>
+ <li><a class="has-text-black" style="cursor: default;">May: Pixels</a></li>
+ <li><a class="has-text-link" href="{% url "events:page" path="code-jams/8" %}">July: Summer Code Jam</a></li>
+ <li><a class="has-text-link" href="https://pyweek.org/32/" target="_blank" rel="noopener">September: PyWeek 32</a></li>
<li><a class="has-text-black" style="cursor: default;">December: Advent of Code</a></li>
</ul>
</div>
diff --git a/pydis_site/templates/home/index.html b/pydis_site/templates/home/index.html
index 129320b3..985ccae1 100644
--- a/pydis_site/templates/home/index.html
+++ b/pydis_site/templates/home/index.html
@@ -9,21 +9,14 @@
{% block content %}
{% include "base/navbar.html" %}
- <!-- 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/currently_live.png" %}" alt="Summer Code Jam 2021">
- </a>
- </section>
-
<!-- Wave Hero -->
<section id="wave-hero" class="section is-hidden-mobile">
<div class="container">
- <div class="columns is-variable is-8">
+ <div class="columns is-variable is-8 is-centered">
{# Embedded Welcome video #}
- <div id="wave-hero-left" class="column is-half">
+ <div id="wave-hero-left" class="column is-half ">
<div class="force-aspect-container">
<iframe
class="force-aspect-content"
@@ -44,13 +37,6 @@
></iframe>
</div>
</div>
-
- {# 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/currently_live.png" %}" alt="Summer Code Jam 2021">
- </a>
- </div>
</div>
</div>
@@ -201,6 +187,10 @@
</a>
<a href="https://streamyard.com" class="column is-narrow">
<img src="{% static "images/sponsors/streamyard.png" %}" alt="StreamYard"/>
+ </a>
+ <a href="https://www.netlify.com/" class="column is-narrow">
+ <img src="{% static "images/sponsors/netlify.png" %}" alt="Netlify"/>
+ </a>
<a href="https://www.cloudflare.com/" class="column is-narrow">
<img src="{% static "images/sponsors/cloudflare.png" %}" alt="Cloudflare"/>
</a>
diff --git a/pydis_site/urls.py b/pydis_site/urls.py
index 3c9fe347..891dbdcc 100644
--- a/pydis_site/urls.py
+++ b/pydis_site/urls.py
@@ -13,6 +13,7 @@ urlpatterns = (
# This must be mounted before the `content` app to prevent Django
# from wildcard matching all requests to `pages/...`.
path('', include('pydis_site.apps.redirect.urls')),
+ path('', include('django_prometheus.urls')),
path('pages/', include('pydis_site.apps.content.urls', namespace='content')),
path('resources/', include('pydis_site.apps.resources.urls')),
path('events/', include('pydis_site.apps.events.urls', namespace='events')),
diff --git a/pyproject.toml b/pyproject.toml
index 0b546781..d0beb632 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ django = "~=3.0.4"
django-environ = "~=0.4.5"
django-filter = "~=2.1.0"
djangorestframework = "~=3.11.0"
-psycopg2-binary = "~=2.8"
+psycopg2-binary = "~=2.8.0"
django-simple-bulma = "~=2.1"
whitenoise = "~=5.0"
requests = "~=2.21"
@@ -20,6 +20,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"