.json",
+ views.badge,
+ {"format": "json", "tag": "*"},
+ name="hc-badge-json-all",
+ ),
+ path("api/v1/status/", views.status),
]
diff --git a/hc/api/views.py b/hc/api/views.py
index 5f094483..38a5a2e6 100644
--- a/hc/api/views.py
+++ b/hc/api/views.py
@@ -4,8 +4,12 @@ import uuid
from django.conf import settings
from django.core.exceptions import SuspiciousOperation
from django.db import connection
-from django.http import (HttpResponse, HttpResponseForbidden,
- HttpResponseNotFound, JsonResponse)
+from django.http import (
+ HttpResponse,
+ HttpResponseForbidden,
+ HttpResponseNotFound,
+ JsonResponse,
+)
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.views.decorators.cache import never_cache
@@ -228,12 +232,9 @@ def badge(request, badge_key, signature, tag, format="svg"):
status = "late"
if format == "json":
- return JsonResponse({
- "status": status,
- "total": total,
- "grace": grace,
- "down": down
- })
+ return JsonResponse(
+ {"status": status, "total": total, "grace": grace, "down": down}
+ )
svg = get_badge_svg(label, status)
return HttpResponse(svg, content_type="image/svg+xml")
diff --git a/hc/front/forms.py b/hc/front/forms.py
index cad5c03a..a43f0856 100644
--- a/hc/front/forms.py
+++ b/hc/front/forms.py
@@ -6,8 +6,11 @@ from urllib.parse import quote, urlencode
from django import forms
from django.conf import settings
from django.core.validators import RegexValidator
-from hc.front.validators import (CronExpressionValidator, TimezoneValidator,
- WebhookValidator)
+from hc.front.validators import (
+ CronExpressionValidator,
+ TimezoneValidator,
+ WebhookValidator,
+)
import requests
@@ -43,8 +46,7 @@ class TimeoutForm(forms.Form):
class CronForm(forms.Form):
- schedule = forms.CharField(max_length=100,
- validators=[CronExpressionValidator()])
+ schedule = forms.CharField(max_length=100, validators=[CronExpressionValidator()])
tz = forms.CharField(max_length=36, validators=[TimezoneValidator()])
grace = forms.IntegerField(min_value=1, max_value=43200)
@@ -66,17 +68,19 @@ class AddUrlForm(forms.Form):
value = forms.URLField(max_length=1000, validators=[WebhookValidator()])
-_valid_header_name = re.compile(r'\A[^:\s][^:\r\n]*\Z').match
+_valid_header_name = re.compile(r"\A[^:\s][^:\r\n]*\Z").match
class AddWebhookForm(forms.Form):
error_css_class = "has-error"
- url_down = forms.URLField(max_length=1000, required=False,
- validators=[WebhookValidator()])
+ url_down = forms.URLField(
+ max_length=1000, required=False, validators=[WebhookValidator()]
+ )
- url_up = forms.URLField(max_length=1000, required=False,
- validators=[WebhookValidator()])
+ url_up = forms.URLField(
+ max_length=1000, required=False, validators=[WebhookValidator()]
+ )
post_data = forms.CharField(max_length=1000, required=False)
@@ -109,8 +113,9 @@ class AddWebhookForm(forms.Form):
return json.dumps(val, sort_keys=True)
-phone_validator = RegexValidator(regex='^\+\d{5,15}$',
- message="Invalid phone number format.")
+phone_validator = RegexValidator(
+ regex="^\+\d{5,15}$", message="Invalid phone number format."
+)
class AddSmsForm(forms.Form):
@@ -136,8 +141,7 @@ class AddMatrixForm(forms.Form):
url += urlencode({"access_token": settings.MATRIX_ACCESS_TOKEN})
doc = requests.post(url, {}).json()
if "error" in doc:
- raise forms.ValidationError(
- "Response from Matrix: %s" % doc["error"])
+ raise forms.ValidationError("Response from Matrix: %s" % doc["error"])
self.cleaned_data["room_id"] = doc["room_id"]
diff --git a/hc/front/management/commands/pygmentize.py b/hc/front/management/commands/pygmentize.py
index 350c62f3..59a4e717 100644
--- a/hc/front/management/commands/pygmentize.py
+++ b/hc/front/management/commands/pygmentize.py
@@ -4,6 +4,7 @@ from django.core.management.base import BaseCommand
def _process(name, lexer):
from pygments import highlight
from pygments.formatters import HtmlFormatter
+
source = open("templates/front/snippets/%s.txt" % name).read()
processed = highlight(source, lexer, HtmlFormatter())
processed = processed.replace("PING_URL", "{{ ping_url }}")
@@ -14,7 +15,7 @@ def _process(name, lexer):
class Command(BaseCommand):
- help = 'Compiles snippets with Pygments'
+ help = "Compiles snippets with Pygments"
def handle(self, *args, **options):
diff --git a/hc/front/schemas.py b/hc/front/schemas.py
index 7bbd976b..3ecc9e53 100644
--- a/hc/front/schemas.py
+++ b/hc/front/schemas.py
@@ -10,14 +10,14 @@ telegram_callback = {
"id": {"type": "number"},
"type": {"enum": ["group", "private", "supergroup"]},
"title": {"type": "string"},
- "username": {"type": "string"}
+ "username": {"type": "string"},
},
- "required": ["id", "type"]
+ "required": ["id", "type"],
},
- "text": {"type": "string"}
+ "text": {"type": "string"},
},
- "required": ["chat", "text"]
+ "required": ["chat", "text"],
}
},
- "required": ["message"]
+ "required": ["message"],
}
diff --git a/hc/front/templatetags/hc_extras.py b/hc/front/templatetags/hc_extras.py
index 78a1010c..2d20ae34 100644
--- a/hc/front/templatetags/hc_extras.py
+++ b/hc/front/templatetags/hc_extras.py
@@ -38,22 +38,24 @@ def site_root():
@register.simple_tag
def debug_warning():
if settings.DEBUG:
- return mark_safe("""
+ return mark_safe(
+ """
Running in debug mode, do not use in production.
- """)
+ """
+ )
return ""
def naturalize_int_match(match):
- return '%08d' % (int(match.group(0)),)
+ return "%08d" % (int(match.group(0)),)
def natural_name_key(check):
s = check.name.lower().strip()
- return re.sub(r'\d+', naturalize_int_match, s)
+ return re.sub(r"\d+", naturalize_int_match, s)
def last_ping_key(check):
diff --git a/hc/front/tests/test_add_discord.py b/hc/front/tests/test_add_discord.py
index 5d05de20..214d0336 100644
--- a/hc/front/tests/test_add_discord.py
+++ b/hc/front/tests/test_add_discord.py
@@ -33,10 +33,7 @@ class AddDiscordTestCase(BaseTestCase):
oauth_response = {
"access_token": "test-token",
- "webhook": {
- "url": "foo",
- "id": "bar"
- }
+ "webhook": {"url": "foo", "id": "bar"},
}
mock_post.return_value.text = json.dumps(oauth_response)
diff --git a/hc/front/tests/test_add_pushover.py b/hc/front/tests/test_add_pushover.py
index 1206ed40..fe55ff49 100644
--- a/hc/front/tests/test_add_pushover.py
+++ b/hc/front/tests/test_add_pushover.py
@@ -3,7 +3,9 @@ from hc.api.models import Channel
from hc.test import BaseTestCase
-@override_settings(PUSHOVER_API_TOKEN="token", PUSHOVER_SUBSCRIPTION_URL="http://example.org")
+@override_settings(
+ PUSHOVER_API_TOKEN="token", PUSHOVER_SUBSCRIPTION_URL="http://example.org"
+)
class AddPushoverTestCase(BaseTestCase):
@override_settings(PUSHOVER_API_TOKEN=None)
def test_it_requires_api_token(self):
diff --git a/hc/front/tests/test_add_slack_btn.py b/hc/front/tests/test_add_slack_btn.py
index d78e95bd..8b724cdf 100644
--- a/hc/front/tests/test_add_slack_btn.py
+++ b/hc/front/tests/test_add_slack_btn.py
@@ -7,12 +7,10 @@ from mock import patch
class AddSlackBtnTestCase(BaseTestCase):
-
@override_settings(SLACK_CLIENT_ID="foo")
def test_it_prepares_login_link(self):
r = self.client.get("/integrations/add_slack/")
- self.assertContains(r, "Before adding Slack integration",
- status_code=200)
+ self.assertContains(r, "Before adding Slack integration", status_code=200)
self.assertContains(r, "?next=/integrations/add_slack/")
@@ -34,10 +32,7 @@ class AddSlackBtnTestCase(BaseTestCase):
oauth_response = {
"ok": True,
"team_name": "foo",
- "incoming_webhook": {
- "url": "http://example.org",
- "channel": "bar"
- }
+ "incoming_webhook": {"url": "http://example.org", "channel": "bar"},
}
mock_post.return_value.text = json.dumps(oauth_response)
@@ -76,10 +71,7 @@ class AddSlackBtnTestCase(BaseTestCase):
session["slack"] = "foo"
session.save()
- oauth_response = {
- "ok": False,
- "error": "something went wrong"
- }
+ oauth_response = {"ok": False, "error": "something went wrong"}
mock_post.return_value.text = json.dumps(oauth_response)
mock_post.return_value.json.return_value = oauth_response
diff --git a/hc/front/tests/test_add_telegram.py b/hc/front/tests/test_add_telegram.py
index f4a7a43d..5b106c94 100644
--- a/hc/front/tests/test_add_telegram.py
+++ b/hc/front/tests/test_add_telegram.py
@@ -37,16 +37,13 @@ class AddTelegramTestCase(BaseTestCase):
def test_it_sends_invite(self, mock_get):
data = {
"message": {
- "chat": {
- "id": 123,
- "title": "My Group",
- "type": "group"
- },
- "text": "/start"
+ "chat": {"id": 123, "title": "My Group", "type": "group"},
+ "text": "/start",
}
}
- r = self.client.post("/integrations/telegram/bot/", data,
- content_type="application/json")
+ r = self.client.post(
+ "/integrations/telegram/bot/", data, content_type="application/json"
+ )
self.assertEqual(r.status_code, 200)
self.assertTrue(mock_get.called)
@@ -56,21 +53,17 @@ class AddTelegramTestCase(BaseTestCase):
samples = ["", "{}"]
# text is missing
- samples.append({
- "message": {"chat": {"id": 123, "type": "group"}}
- })
+ samples.append({"message": {"chat": {"id": 123, "type": "group"}}})
# bad chat type
- samples.append({
- "message": {
- "chat": {"id": 123, "type": "invalid"},
- "text": "/start"
- }
- })
+ samples.append(
+ {"message": {"chat": {"id": 123, "type": "invalid"}, "text": "/start"}}
+ )
for sample in samples:
- r = self.client.post("/integrations/telegram/bot/", sample,
- content_type="application/json")
+ r = self.client.post(
+ "/integrations/telegram/bot/", sample, content_type="application/json"
+ )
if sample == "":
# Bad JSON payload
@@ -78,4 +71,3 @@ class AddTelegramTestCase(BaseTestCase):
else:
# JSON decodes but message structure not recognized
self.assertEqual(r.status_code, 200)
-
diff --git a/hc/front/tests/test_add_trello.py b/hc/front/tests/test_add_trello.py
index 8c9647bd..55a9406e 100644
--- a/hc/front/tests/test_add_trello.py
+++ b/hc/front/tests/test_add_trello.py
@@ -16,12 +16,16 @@ class AddPagerTreeTestCase(BaseTestCase):
@override_settings(TRELLO_APP_KEY="foo")
def test_it_works(self):
- form = {"settings": json.dumps({
- "token": "fake-token",
- "board_name": "My Board",
- "list_name": "My List",
- "list_id": "fake-list-id"
- })}
+ form = {
+ "settings": json.dumps(
+ {
+ "token": "fake-token",
+ "board_name": "My Board",
+ "list_name": "My List",
+ "list_id": "fake-list-id",
+ }
+ )
+ }
self.client.login(username="alice@example.org", password="password")
r = self.client.post(self.url, form)
diff --git a/hc/front/tests/test_add_webhook.py b/hc/front/tests/test_add_webhook.py
index 1ddbda50..cbe26d15 100644
--- a/hc/front/tests/test_add_webhook.py
+++ b/hc/front/tests/test_add_webhook.py
@@ -18,7 +18,10 @@ class AddWebhookTestCase(BaseTestCase):
self.assertRedirects(r, "/integrations/")
c = Channel.objects.get()
- self.assertEqual(c.value, '{"headers": {}, "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}')
+ self.assertEqual(
+ c.value,
+ '{"headers": {}, "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}',
+ )
self.assertEqual(c.project, self.project)
def test_it_adds_webhook_using_team_access(self):
@@ -31,7 +34,10 @@ class AddWebhookTestCase(BaseTestCase):
c = Channel.objects.get()
self.assertEqual(c.project, self.project)
- self.assertEqual(c.value, '{"headers": {}, "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}')
+ self.assertEqual(
+ c.value,
+ '{"headers": {}, "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}',
+ )
def test_it_rejects_bad_urls(self):
urls = [
@@ -41,7 +47,7 @@ class AddWebhookTestCase(BaseTestCase):
"ftp://example.org",
# no loopback
"http://localhost:1234/endpoint",
- "http://127.0.0.1/endpoint"
+ "http://127.0.0.1/endpoint",
]
self.client.login(username="alice@example.org", password="password")
@@ -60,7 +66,10 @@ class AddWebhookTestCase(BaseTestCase):
self.client.post(self.url, form)
c = Channel.objects.get()
- self.assertEqual(c.value, '{"headers": {}, "post_data": "", "url_down": "", "url_up": "http://foo.com"}')
+ self.assertEqual(
+ c.value,
+ '{"headers": {}, "post_data": "", "url_down": "", "url_up": "http://foo.com"}',
+ )
def test_it_adds_post_data(self):
form = {"url_down": "http://foo.com", "post_data": "hello"}
@@ -70,13 +79,16 @@ class AddWebhookTestCase(BaseTestCase):
self.assertRedirects(r, "/integrations/")
c = Channel.objects.get()
- self.assertEqual(c.value, '{"headers": {}, "post_data": "hello", "url_down": "http://foo.com", "url_up": ""}')
+ self.assertEqual(
+ c.value,
+ '{"headers": {}, "post_data": "hello", "url_down": "http://foo.com", "url_up": ""}',
+ )
def test_it_adds_headers(self):
form = {
"url_down": "http://foo.com",
"header_key[]": ["test", "test2"],
- "header_value[]": ["123", "abc"]
+ "header_value[]": ["123", "abc"],
}
self.client.login(username="alice@example.org", password="password")
@@ -91,7 +103,7 @@ class AddWebhookTestCase(BaseTestCase):
form = {
"url_down": "http://example.org",
"header_key[]": ["ill:egal"],
- "header_value[]": ["123"]
+ "header_value[]": ["123"],
}
r = self.client.post(self.url, form)
diff --git a/hc/front/tests/test_badges.py b/hc/front/tests/test_badges.py
index 705193e3..c79ed9c8 100644
--- a/hc/front/tests/test_badges.py
+++ b/hc/front/tests/test_badges.py
@@ -3,7 +3,6 @@ from hc.api.models import Check
class BadgesTestCase(BaseTestCase):
-
def setUp(self):
super(BadgesTestCase, self).setUp()
diff --git a/hc/front/tests/test_basics.py b/hc/front/tests/test_basics.py
index 95098968..fd3cbbaf 100644
--- a/hc/front/tests/test_basics.py
+++ b/hc/front/tests/test_basics.py
@@ -3,7 +3,6 @@ from django.test.utils import override_settings
class BasicsTestCase(TestCase):
-
def test_it_shows_welcome(self):
r = self.client.get("/")
self.assertContains(r, "Get Notified", status_code=200)
diff --git a/hc/front/tests/test_channel_checks.py b/hc/front/tests/test_channel_checks.py
index df04918d..84698ede 100644
--- a/hc/front/tests/test_channel_checks.py
+++ b/hc/front/tests/test_channel_checks.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class ChannelChecksTestCase(BaseTestCase):
-
def setUp(self):
super(ChannelChecksTestCase, self).setUp()
self.channel = Channel(project=self.project, kind="email")
diff --git a/hc/front/tests/test_channels.py b/hc/front/tests/test_channels.py
index 36c33c7d..e6e95991 100644
--- a/hc/front/tests/test_channels.py
+++ b/hc/front/tests/test_channels.py
@@ -5,17 +5,15 @@ from hc.test import BaseTestCase
class ChannelsTestCase(BaseTestCase):
-
def test_it_formats_complex_slack_value(self):
ch = Channel(kind="slack", project=self.project)
- ch.value = json.dumps({
- "ok": True,
- "team_name": "foo-team",
- "incoming_webhook": {
- "url": "http://example.org",
- "channel": "#bar"
+ ch.value = json.dumps(
+ {
+ "ok": True,
+ "team_name": "foo-team",
+ "incoming_webhook": {"url": "http://example.org", "channel": "#bar"},
}
- })
+ )
ch.save()
self.client.login(username="alice@example.org", password="password")
@@ -76,11 +74,9 @@ class ChannelsTestCase(BaseTestCase):
def test_it_shows_down_only_note_for_email(self):
channel = Channel(project=self.project, kind="email")
- channel.value = json.dumps({
- "value": "alice@example.org",
- "up": False,
- "down": True
- })
+ channel.value = json.dumps(
+ {"value": "alice@example.org", "up": False, "down": True}
+ )
channel.save()
self.client.login(username="alice@example.org", password="password")
@@ -90,11 +86,9 @@ class ChannelsTestCase(BaseTestCase):
def test_it_shows_up_only_note_for_email(self):
channel = Channel(project=self.project, kind="email")
- channel.value = json.dumps({
- "value": "alice@example.org",
- "up": True,
- "down": False
- })
+ channel.value = json.dumps(
+ {"value": "alice@example.org", "up": True, "down": False}
+ )
channel.save()
self.client.login(username="alice@example.org", password="password")
diff --git a/hc/front/tests/test_cron_preview.py b/hc/front/tests/test_cron_preview.py
index 8fced14c..0b226cdb 100644
--- a/hc/front/tests/test_cron_preview.py
+++ b/hc/front/tests/test_cron_preview.py
@@ -6,21 +6,13 @@ import pytz
class CronPreviewTestCase(BaseTestCase):
-
def test_it_works(self):
- payload = {
- "schedule": "* * * * *",
- "tz": "UTC"
- }
+ payload = {"schedule": "* * * * *", "tz": "UTC"}
r = self.client.post("/checks/cron_preview/", payload)
self.assertContains(r, "cron-preview-title", status_code=200)
def test_it_rejects_invalid_cron_expression(self):
- samples = ["",
- "*",
- "100 100 100 100 100",
- "* * * * * *",
- "1,2 3,* * * *"]
+ samples = ["", "*", "100 100 100 100 100", "* * * * * *", "1,2 3,* * * *"]
for schedule in samples:
payload = {"schedule": schedule, "tz": "UTC"}
@@ -52,9 +44,6 @@ class CronPreviewTestCase(BaseTestCase):
# This schedule will hit the ambiguous date. Cron preview must
# be able to handle this:
- payload = {
- "schedule": "0 3 * * *",
- "tz": "Europe/Riga"
- }
+ payload = {"schedule": "0 3 * * *", "tz": "Europe/Riga"}
r = self.client.post("/checks/cron_preview/", payload)
self.assertNotContains(r, "Invalid cron expression", status_code=200)
diff --git a/hc/front/tests/test_details.py b/hc/front/tests/test_details.py
index 63542809..8690df89 100644
--- a/hc/front/tests/test_details.py
+++ b/hc/front/tests/test_details.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class DetailsTestCase(BaseTestCase):
-
def setUp(self):
super(DetailsTestCase, self).setUp()
self.check = Check.objects.create(project=self.project)
diff --git a/hc/front/tests/test_hc_extras.py b/hc/front/tests/test_hc_extras.py
index 5e46105f..5142b8f9 100644
--- a/hc/front/tests/test_hc_extras.py
+++ b/hc/front/tests/test_hc_extras.py
@@ -4,7 +4,6 @@ from hc.front.templatetags.hc_extras import hc_duration
class HcExtrasTestCase(TestCase):
-
def test_hc_duration_works(self):
samples = [
(60, "1 minute"),
@@ -15,7 +14,7 @@ class HcExtrasTestCase(TestCase):
(604800, "1 week"),
(2419200, "4 weeks"),
(2592000, "30 days"),
- (3801600, "44 days")
+ (3801600, "44 days"),
]
for seconds, expected_result in samples:
diff --git a/hc/front/tests/test_log.py b/hc/front/tests/test_log.py
index 7e9735eb..93717390 100644
--- a/hc/front/tests/test_log.py
+++ b/hc/front/tests/test_log.py
@@ -5,7 +5,6 @@ from hc.test import BaseTestCase
class LogTestCase(BaseTestCase):
-
def setUp(self):
super(LogTestCase, self).setUp()
self.check = Check.objects.create(project=self.project)
@@ -55,19 +54,14 @@ class LogTestCase(BaseTestCase):
def test_it_shows_email_notification(self):
ch = Channel(kind="email", project=self.project)
- ch.value = json.dumps({
- "value": "alice@example.org",
- "up": True,
- "down": True
- })
+ ch.value = json.dumps({"value": "alice@example.org", "up": True, "down": True})
ch.save()
Notification(owner=self.check, channel=ch, check_status="down").save()
self.client.login(username="alice@example.org", password="password")
r = self.client.get(self.url)
- self.assertContains(r, "Sent email alert to alice@example.org",
- status_code=200)
+ self.assertContains(r, "Sent email alert to alice@example.org", status_code=200)
def test_it_shows_pushover_notification(self):
ch = Channel.objects.create(kind="po", project=self.project)
diff --git a/hc/front/tests/test_my_checks.py b/hc/front/tests/test_my_checks.py
index 1c5707ce..1d896ab8 100644
--- a/hc/front/tests/test_my_checks.py
+++ b/hc/front/tests/test_my_checks.py
@@ -5,7 +5,6 @@ from django.utils import timezone
class MyChecksTestCase(BaseTestCase):
-
def setUp(self):
super(MyChecksTestCase, self).setUp()
self.check = Check(project=self.project, name="Alice Was Here")
diff --git a/hc/front/tests/test_pause.py b/hc/front/tests/test_pause.py
index 5d0fed24..35176ae1 100644
--- a/hc/front/tests/test_pause.py
+++ b/hc/front/tests/test_pause.py
@@ -6,7 +6,6 @@ from hc.test import BaseTestCase
class PauseTestCase(BaseTestCase):
-
def setUp(self):
super(PauseTestCase, self).setUp()
self.check = Check.objects.create(project=self.project, status="up")
diff --git a/hc/front/tests/test_ping_details.py b/hc/front/tests/test_ping_details.py
index 8fcf19f6..77f5d965 100644
--- a/hc/front/tests/test_ping_details.py
+++ b/hc/front/tests/test_ping_details.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class LastPingTestCase(BaseTestCase):
-
def test_it_works(self):
check = Check.objects.create(project=self.project)
Ping.objects.create(owner=check, body="this is body")
diff --git a/hc/front/tests/test_remove_channel.py b/hc/front/tests/test_remove_channel.py
index a98ebc0a..50ca2063 100644
--- a/hc/front/tests/test_remove_channel.py
+++ b/hc/front/tests/test_remove_channel.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class RemoveChannelTestCase(BaseTestCase):
-
def setUp(self):
super(RemoveChannelTestCase, self).setUp()
self.channel = Channel(project=self.project, kind="email")
diff --git a/hc/front/tests/test_remove_check.py b/hc/front/tests/test_remove_check.py
index 67a65f98..c1cd48a2 100644
--- a/hc/front/tests/test_remove_check.py
+++ b/hc/front/tests/test_remove_check.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class RemoveCheckTestCase(BaseTestCase):
-
def setUp(self):
super(RemoveCheckTestCase, self).setUp()
self.check = Check.objects.create(project=self.project)
diff --git a/hc/front/tests/test_send_test_notification.py b/hc/front/tests/test_send_test_notification.py
index 04caa4d5..6ddec998 100644
--- a/hc/front/tests/test_send_test_notification.py
+++ b/hc/front/tests/test_send_test_notification.py
@@ -4,7 +4,6 @@ from hc.test import BaseTestCase
class SendTestNotificationTestCase(BaseTestCase):
-
def setUp(self):
super(SendTestNotificationTestCase, self).setUp()
self.channel = Channel(kind="email", project=self.project)
diff --git a/hc/front/tests/test_status.py b/hc/front/tests/test_status.py
index 1c9a5ead..17ddc3f5 100644
--- a/hc/front/tests/test_status.py
+++ b/hc/front/tests/test_status.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class MyChecksTestCase(BaseTestCase):
-
def setUp(self):
super(MyChecksTestCase, self).setUp()
self.check = Check(project=self.project, name="Alice Was Here")
diff --git a/hc/front/tests/test_status_single.py b/hc/front/tests/test_status_single.py
index b9c4c611..0889e361 100644
--- a/hc/front/tests/test_status_single.py
+++ b/hc/front/tests/test_status_single.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class StatusSingleTestCase(BaseTestCase):
-
def setUp(self):
super(StatusSingleTestCase, self).setUp()
self.check = Check(project=self.project, name="Alice Was Here")
diff --git a/hc/front/tests/test_switch_channel.py b/hc/front/tests/test_switch_channel.py
index d5abd8dd..0b74688d 100644
--- a/hc/front/tests/test_switch_channel.py
+++ b/hc/front/tests/test_switch_channel.py
@@ -4,7 +4,6 @@ from hc.test import BaseTestCase
class SwitchChannelTestCase(BaseTestCase):
-
def setUp(self):
super(SwitchChannelTestCase, self).setUp()
self.check = Check.objects.create(project=self.project)
@@ -13,7 +12,10 @@ class SwitchChannelTestCase(BaseTestCase):
self.channel.value = "alice@example.org"
self.channel.save()
- self.url = "/checks/%s/channels/%s/enabled" % (self.check.code, self.channel.code)
+ self.url = "/checks/%s/channels/%s/enabled" % (
+ self.check.code,
+ self.channel.code,
+ )
def test_it_enables(self):
self.client.login(username="alice@example.org", password="password")
diff --git a/hc/front/tests/test_transfer.py b/hc/front/tests/test_transfer.py
index f8f18e3a..952cce54 100644
--- a/hc/front/tests/test_transfer.py
+++ b/hc/front/tests/test_transfer.py
@@ -42,11 +42,9 @@ class TrabsferTestCase(BaseTestCase):
self.assertEqual(r.status_code, 400)
def test_it_reassigns_channels(self):
- alices_mail = Channel.objects.create(kind="email",
- project=self.project)
+ alices_mail = Channel.objects.create(kind="email", project=self.project)
- bobs_mail = Channel.objects.create(kind="email",
- project=self.bobs_project)
+ bobs_mail = Channel.objects.create(kind="email", project=self.bobs_project)
self.check.channel_set.add(bobs_mail)
diff --git a/hc/front/tests/test_unsubscribe_email.py b/hc/front/tests/test_unsubscribe_email.py
index a18acfea..034985cd 100644
--- a/hc/front/tests/test_unsubscribe_email.py
+++ b/hc/front/tests/test_unsubscribe_email.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class UnsubscribeEmailTestCase(BaseTestCase):
-
def setUp(self):
super(UnsubscribeEmailTestCase, self).setUp()
self.channel = Channel(project=self.project, kind="email")
@@ -24,8 +23,7 @@ class UnsubscribeEmailTestCase(BaseTestCase):
url = "/integrations/%s/unsub/faketoken/" % self.channel.code
r = self.client.get(url)
- self.assertContains(r, "link you just used is incorrect",
- status_code=200)
+ self.assertContains(r, "link you just used is incorrect", status_code=200)
def test_it_checks_channel_kind(self):
self.channel.kind = "webhook"
diff --git a/hc/front/tests/test_update_channel.py b/hc/front/tests/test_update_channel.py
index 8d857869..5cc20798 100644
--- a/hc/front/tests/test_update_channel.py
+++ b/hc/front/tests/test_update_channel.py
@@ -4,7 +4,6 @@ from hc.test import BaseTestCase
class UpdateChannelTestCase(BaseTestCase):
-
def setUp(self):
super(UpdateChannelTestCase, self).setUp()
self.check = Check.objects.create(project=self.project)
@@ -14,10 +13,7 @@ class UpdateChannelTestCase(BaseTestCase):
self.channel.save()
def test_it_works(self):
- payload = {
- "channel": self.channel.code,
- "check-%s" % self.check.code: True
- }
+ payload = {"channel": self.channel.code, "check-%s" % self.check.code: True}
self.client.login(username="alice@example.org", password="password")
r = self.client.post("/integrations/", data=payload)
@@ -29,10 +25,7 @@ class UpdateChannelTestCase(BaseTestCase):
assert checks[0].code == self.check.code
def test_team_access_works(self):
- payload = {
- "channel": self.channel.code,
- "check-%s" % self.check.code: True
- }
+ payload = {"channel": self.channel.code, "check-%s" % self.check.code: True}
# Logging in as bob, not alice. Bob has team access so this
# should work.
@@ -55,10 +48,7 @@ class UpdateChannelTestCase(BaseTestCase):
charlies_channel.email = "charlie@example.org"
charlies_channel.save()
- payload = {
- "channel": charlies_channel.code,
- "check-%s" % self.check.code: True
- }
+ payload = {"channel": charlies_channel.code, "check-%s" % self.check.code: True}
self.client.login(username="charlie@example.org", password="password")
r = self.client.post("/integrations/", data=payload)
@@ -77,7 +67,7 @@ class UpdateChannelTestCase(BaseTestCase):
# check- key has a correct UUID but there's no check object for it
payload = {
"channel": self.channel.code,
- "check-6837d6ec-fc08-4da5-a67f-08a9ed1ccf62": True
+ "check-6837d6ec-fc08-4da5-a67f-08a9ed1ccf62": True,
}
self.client.login(username="alice@example.org", password="password")
diff --git a/hc/front/tests/test_update_channel_name.py b/hc/front/tests/test_update_channel_name.py
index 8d27bc64..7d7bc2f3 100644
--- a/hc/front/tests/test_update_channel_name.py
+++ b/hc/front/tests/test_update_channel_name.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class UpdateChannelNameTestCase(BaseTestCase):
-
def setUp(self):
super(UpdateChannelNameTestCase, self).setUp()
self.channel = Channel(kind="email", project=self.project)
diff --git a/hc/front/tests/test_update_name.py b/hc/front/tests/test_update_name.py
index ee8f086a..55bb2d4e 100644
--- a/hc/front/tests/test_update_name.py
+++ b/hc/front/tests/test_update_name.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class UpdateNameTestCase(BaseTestCase):
-
def setUp(self):
super(UpdateNameTestCase, self).setUp()
self.check = Check.objects.create(project=self.project)
diff --git a/hc/front/tests/test_update_timeout.py b/hc/front/tests/test_update_timeout.py
index 861b0394..0b82909a 100644
--- a/hc/front/tests/test_update_timeout.py
+++ b/hc/front/tests/test_update_timeout.py
@@ -6,7 +6,6 @@ from hc.test import BaseTestCase
class UpdateTimeoutTestCase(BaseTestCase):
-
def setUp(self):
super(UpdateTimeoutTestCase, self).setUp()
self.check = Check(project=self.project, status="up")
@@ -47,12 +46,7 @@ class UpdateTimeoutTestCase(BaseTestCase):
self.assertEqual(self.check.status, "down")
def test_it_saves_cron_expression(self):
- payload = {
- "kind": "cron",
- "schedule": "5 * * * *",
- "tz": "UTC",
- "grace": 60
- }
+ payload = {"kind": "cron", "schedule": "5 * * * *", "tz": "UTC", "grace": 60}
self.client.login(username="alice@example.org", password="password")
r = self.client.post(self.url, data=payload)
@@ -67,12 +61,7 @@ class UpdateTimeoutTestCase(BaseTestCase):
samples = ["* invalid *", "1,2 3,* * * *"]
for sample in samples:
- payload = {
- "kind": "cron",
- "schedule": sample,
- "tz": "UTC",
- "grace": 60
- }
+ payload = {"kind": "cron", "schedule": sample, "tz": "UTC", "grace": 60}
r = self.client.post(self.url, data=payload)
self.assertEqual(r.status_code, 400)
@@ -86,7 +75,7 @@ class UpdateTimeoutTestCase(BaseTestCase):
"kind": "cron",
"schedule": "* * * * * *", # six fields instead of five
"tz": "UTC",
- "grace": 60
+ "grace": 60,
}
self.client.login(username="alice@example.org", password="password")
@@ -102,7 +91,7 @@ class UpdateTimeoutTestCase(BaseTestCase):
"kind": "cron",
"schedule": "* * * * *",
"tz": "not-a-tz",
- "grace": 60
+ "grace": 60,
}
self.client.login(username="alice@example.org", password="password")
@@ -115,11 +104,7 @@ class UpdateTimeoutTestCase(BaseTestCase):
def test_it_rejects_missing_schedule(self):
# tz field is omitted so this should fail:
- payload = {
- "kind": "cron",
- "grace": 60,
- "tz": "UTC"
- }
+ payload = {"kind": "cron", "grace": 60, "tz": "UTC"}
self.client.login(username="alice@example.org", password="password")
r = self.client.post(self.url, data=payload)
@@ -127,11 +112,7 @@ class UpdateTimeoutTestCase(BaseTestCase):
def test_it_rejects_missing_tz(self):
# tz field is omitted so this should fail:
- payload = {
- "kind": "cron",
- "schedule": "* * * * *",
- "grace": 60
- }
+ payload = {"kind": "cron", "schedule": "* * * * *", "grace": 60}
self.client.login(username="alice@example.org", password="password")
r = self.client.post(self.url, data=payload)
diff --git a/hc/front/tests/test_verify_email.py b/hc/front/tests/test_verify_email.py
index e53008a5..b2fc4731 100644
--- a/hc/front/tests/test_verify_email.py
+++ b/hc/front/tests/test_verify_email.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class VerifyEmailTestCase(BaseTestCase):
-
def setUp(self):
super(VerifyEmailTestCase, self).setUp()
self.channel = Channel(project=self.project, kind="email")
diff --git a/hc/front/urls.py b/hc/front/urls.py
index 71f1db9b..4bb6b004 100644
--- a/hc/front/urls.py
+++ b/hc/front/urls.py
@@ -3,63 +3,70 @@ from django.urls import include, path
from hc.front import views
check_urls = [
- path('name/', views.update_name, name="hc-update-name"),
- path('details/', views.details, name="hc-details"),
- path('email_settings/', views.email_settings, name="hc-email-settings"),
- path('timeout/', views.update_timeout, name="hc-update-timeout"),
- path('pause/', views.pause, name="hc-pause"),
- path('remove/', views.remove_check, name="hc-remove-check"),
- path('log/', views.log, name="hc-log"),
- path('status/', views.status_single),
- path('last_ping/', views.ping_details, name="hc-last-ping"),
- path('transfer/', views.transfer, name="hc-transfer"),
- path('channels//enabled', views.switch_channel, name="hc-switch-channel"),
- path('pings//', views.ping_details, name="hc-ping-details"),
+ path("name/", views.update_name, name="hc-update-name"),
+ path("details/", views.details, name="hc-details"),
+ path("email_settings/", views.email_settings, name="hc-email-settings"),
+ path("timeout/", views.update_timeout, name="hc-update-timeout"),
+ path("pause/", views.pause, name="hc-pause"),
+ path("remove/", views.remove_check, name="hc-remove-check"),
+ path("log/", views.log, name="hc-log"),
+ path("status/", views.status_single),
+ path("last_ping/", views.ping_details, name="hc-last-ping"),
+ path("transfer/", views.transfer, name="hc-transfer"),
+ path(
+ "channels//enabled",
+ views.switch_channel,
+ name="hc-switch-channel",
+ ),
+ path("pings//", views.ping_details, name="hc-ping-details"),
]
channel_urls = [
- path('', views.channels, name="hc-channels"),
- path('add_email/', views.add_email, name="hc-add-email"),
- path('add_webhook/', views.add_webhook, name="hc-add-webhook"),
- path('add_pd/', views.add_pd, name="hc-add-pd"),
- path('add_pd//', views.add_pd, name="hc-add-pd-state"),
- path('add_pagertree/', views.add_pagertree, name="hc-add-pagertree"),
- path('add_pagerteam/', views.add_pagerteam, name="hc-add-pagerteam"),
- path('add_slack/', views.add_slack, name="hc-add-slack"),
- path('add_slack_btn/', views.add_slack_btn, name="hc-add-slack-btn"),
- path('add_pushbullet/', views.add_pushbullet, name="hc-add-pushbullet"),
- path('add_discord/', views.add_discord, name="hc-add-discord"),
- path('add_pushover/', views.add_pushover, name="hc-add-pushover"),
- path('add_opsgenie/', views.add_opsgenie, name="hc-add-opsgenie"),
- path('add_victorops/', views.add_victorops, name="hc-add-victorops"),
- path('telegram/bot/', views.telegram_bot, name="hc-telegram-webhook"),
- path('add_telegram/', views.add_telegram, name="hc-add-telegram"),
- path('add_sms/', views.add_sms, name="hc-add-sms"),
- path('add_trello/', views.add_trello, name="hc-add-trello"),
- path('add_trello/settings/', views.trello_settings, name="hc-trello-settings"),
- path('add_matrix/', views.add_matrix, name="hc-add-matrix"),
- path('/checks/', views.channel_checks, name="hc-channel-checks"),
- path('/name/', views.update_channel_name, name="hc-channel-name"),
- path('/test/', views.send_test_notification, name="hc-channel-test"),
- path('/remove/', views.remove_channel, name="hc-remove-channel"),
- path('/verify//', views.verify_email,
- name="hc-verify-email"),
- path('/unsub//', views.unsubscribe_email,
- name="hc-unsubscribe-alerts"),
+ path("", views.channels, name="hc-channels"),
+ path("add_email/", views.add_email, name="hc-add-email"),
+ path("add_webhook/", views.add_webhook, name="hc-add-webhook"),
+ path("add_pd/", views.add_pd, name="hc-add-pd"),
+ path("add_pd//", views.add_pd, name="hc-add-pd-state"),
+ path("add_pagertree/", views.add_pagertree, name="hc-add-pagertree"),
+ path("add_pagerteam/", views.add_pagerteam, name="hc-add-pagerteam"),
+ path("add_slack/", views.add_slack, name="hc-add-slack"),
+ path("add_slack_btn/", views.add_slack_btn, name="hc-add-slack-btn"),
+ path("add_pushbullet/", views.add_pushbullet, name="hc-add-pushbullet"),
+ path("add_discord/", views.add_discord, name="hc-add-discord"),
+ path("add_pushover/", views.add_pushover, name="hc-add-pushover"),
+ path("add_opsgenie/", views.add_opsgenie, name="hc-add-opsgenie"),
+ path("add_victorops/", views.add_victorops, name="hc-add-victorops"),
+ path("telegram/bot/", views.telegram_bot, name="hc-telegram-webhook"),
+ path("add_telegram/", views.add_telegram, name="hc-add-telegram"),
+ path("add_sms/", views.add_sms, name="hc-add-sms"),
+ path("add_trello/", views.add_trello, name="hc-add-trello"),
+ path("add_trello/settings/", views.trello_settings, name="hc-trello-settings"),
+ path("add_matrix/", views.add_matrix, name="hc-add-matrix"),
+ path("/checks/", views.channel_checks, name="hc-channel-checks"),
+ path("/name/", views.update_channel_name, name="hc-channel-name"),
+ path("/test/", views.send_test_notification, name="hc-channel-test"),
+ path("/remove/", views.remove_channel, name="hc-remove-channel"),
+ path(
+ "/verify//", views.verify_email, name="hc-verify-email"
+ ),
+ path(
+ "/unsub//",
+ views.unsubscribe_email,
+ name="hc-unsubscribe-alerts",
+ ),
]
urlpatterns = [
- path('', views.index, name="hc-index"),
- path('projects//checks/', views.my_checks, name="hc-checks"),
- path('projects//badges/', views.badges, name="hc-badges"),
- path('projects//checks/add/', views.add_check, name="hc-add-check"),
- path('checks/cron_preview/', views.cron_preview),
- path('projects//checks/status/', views.status, name="hc-status"),
- path('checks//', include(check_urls)),
- path('integrations/', include(channel_urls)),
-
- path('docs/', views.docs, name="hc-docs"),
- path('docs/api/', views.docs_api, name="hc-docs-api"),
- path('docs/cron/', views.docs_cron, name="hc-docs-cron"),
- path('docs/resources/', views.docs_resources, name="hc-docs-resources"),
+ path("", views.index, name="hc-index"),
+ path("projects//checks/", views.my_checks, name="hc-checks"),
+ path("projects//badges/", views.badges, name="hc-badges"),
+ path("projects//checks/add/", views.add_check, name="hc-add-check"),
+ path("checks/cron_preview/", views.cron_preview),
+ path("projects//checks/status/", views.status, name="hc-status"),
+ path("checks//", include(check_urls)),
+ path("integrations/", include(channel_urls)),
+ path("docs/", views.docs, name="hc-docs"),
+ path("docs/api/", views.docs_api, name="hc-docs-api"),
+ path("docs/cron/", views.docs_cron, name="hc-docs-cron"),
+ path("docs/resources/", views.docs_resources, name="hc-docs-resources"),
]
diff --git a/hc/front/views.py b/hc/front/views.py
index ca896917..6a5bce7e 100644
--- a/hc/front/views.py
+++ b/hc/front/views.py
@@ -1,6 +1,5 @@
from datetime import datetime, timedelta as td
import json
-import re
from urllib.parse import urlencode
from croniter import croniter
@@ -9,8 +8,13 @@ from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core import signing
from django.db.models import Count
-from django.http import (Http404, HttpResponse, HttpResponseBadRequest,
- HttpResponseForbidden, JsonResponse)
+from django.http import (
+ Http404,
+ HttpResponse,
+ HttpResponseBadRequest,
+ HttpResponseForbidden,
+ JsonResponse,
+)
from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import get_template, render_to_string
from django.urls import reverse
@@ -19,16 +23,30 @@ from django.utils.crypto import get_random_string
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from hc.accounts.models import Project
-from hc.api.models import (DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check,
- Ping, Notification)
+from hc.api.models import (
+ DEFAULT_GRACE,
+ DEFAULT_TIMEOUT,
+ Channel,
+ Check,
+ Ping,
+ Notification,
+)
from hc.api.transports import Telegram
-from hc.front.forms import (AddWebhookForm, NameTagsForm,
- TimeoutForm, AddUrlForm, AddEmailForm,
- AddOpsGenieForm, CronForm, AddSmsForm,
- ChannelNameForm, EmailSettingsForm, AddMatrixForm)
+from hc.front.forms import (
+ AddWebhookForm,
+ NameTagsForm,
+ TimeoutForm,
+ AddUrlForm,
+ AddEmailForm,
+ AddOpsGenieForm,
+ CronForm,
+ AddSmsForm,
+ ChannelNameForm,
+ EmailSettingsForm,
+ AddMatrixForm,
+)
from hc.front.schemas import telegram_callback
-from hc.front.templatetags.hc_extras import (num_down_title, down_title,
- sortchecks)
+from hc.front.templatetags.hc_extras import num_down_title, down_title, sortchecks
from hc.lib import jsonschema
from hc.lib.badges import get_badge_url
import pytz
@@ -150,7 +168,7 @@ def my_checks(request, code):
"selected_tags": selected_tags,
"show_search": True,
"search": search,
- "hidden_checks": hidden_checks
+ "hidden_checks": hidden_checks,
}
return render(request, "front/my_checks.html", ctx)
@@ -165,18 +183,18 @@ def status(request, code):
details = []
for check in checks:
ctx = {"check": check}
- details.append({
- "code": str(check.code),
- "status": check.get_status(),
- "last_ping": LAST_PING_TMPL.render(ctx)
- })
+ details.append(
+ {
+ "code": str(check.code),
+ "status": check.get_status(),
+ "last_ping": LAST_PING_TMPL.render(ctx),
+ }
+ )
tags_statuses, num_down = _tags_statuses(checks)
- return JsonResponse({
- "details": details,
- "tags": tags_statuses,
- "title": num_down_title(num_down)
- })
+ return JsonResponse(
+ {"details": details, "tags": tags_statuses, "title": num_down_title(num_down)}
+ )
@login_required
@@ -200,10 +218,7 @@ def index(request):
if request.user.is_authenticated:
projects = list(request.profile.projects())
- ctx = {
- "page": "projects",
- "projects": projects
- }
+ ctx = {"page": "projects", "projects": projects}
return render(request, "front/projects.html", ctx)
check = Check()
@@ -220,7 +235,7 @@ def index(request):
"enable_pd": settings.PD_VENDOR_KEY is not None,
"enable_trello": settings.TRELLO_APP_KEY is not None,
"enable_matrix": settings.MATRIX_ACCESS_TOKEN is not None,
- "registration_open": settings.REGISTRATION_OPEN
+ "registration_open": settings.REGISTRATION_OPEN,
}
return render(request, "front/welcome.html", ctx)
@@ -233,7 +248,7 @@ def docs(request):
"ping_endpoint": settings.PING_ENDPOINT,
"ping_email": "your-uuid-here@%s" % settings.PING_EMAIL_DOMAIN,
"ping_email_domain": settings.PING_EMAIL_DOMAIN,
- "ping_url": settings.PING_ENDPOINT + "your-uuid-here"
+ "ping_url": settings.PING_ENDPOINT + "your-uuid-here",
}
return render(request, "front/docs.html", ctx)
@@ -246,7 +261,7 @@ def docs_api(request):
"SITE_ROOT": settings.SITE_ROOT,
"PING_ENDPOINT": settings.PING_ENDPOINT,
"default_timeout": int(DEFAULT_TIMEOUT.total_seconds()),
- "default_grace": int(DEFAULT_GRACE.total_seconds())
+ "default_grace": int(DEFAULT_GRACE.total_seconds()),
}
return render(request, "front/docs_api.html", ctx)
@@ -371,10 +386,7 @@ def ping_details(request, code, n=None):
ping = q.latest("created")
- ctx = {
- "check": check,
- "ping": ping
- }
+ ctx = {"check": check, "ping": ping}
return render(request, "front/ping_details.html", ctx)
@@ -424,9 +436,9 @@ def _get_events(check, limit):
alerts = []
if len(pings):
cutoff = pings[-1].created
- alerts = Notification.objects \
- .select_related("channel") \
- .filter(owner=check, check_status="down", created__gt=cutoff)
+ alerts = Notification.objects.select_related("channel").filter(
+ owner=check, check_status="down", created__gt=cutoff
+ )
events = pings + list(alerts)
events.sort(key=lambda el: el.created, reverse=True)
@@ -443,7 +455,7 @@ def log(request, code):
"check": check,
"events": _get_events(check, limit),
"limit": limit,
- "show_limit_notice": check.n_pings > limit and settings.USE_PAYMENTS
+ "show_limit_notice": check.n_pings > limit and settings.USE_PAYMENTS,
}
return render(request, "front/log.html", ctx)
@@ -461,7 +473,7 @@ def details(request, code):
"project": check.project,
"check": check,
"channels": channels,
- "timezones": pytz.all_timezones
+ "timezones": pytz.all_timezones,
}
return render(request, "front/details.html", ctx)
@@ -506,7 +518,7 @@ def status_single(request, code):
"status": status,
"status_text": STATUS_TEXT_TMPL.render({"check": check}),
"title": down_title(check),
- "updated": updated
+ "updated": updated,
}
if updated != request.GET.get("u"):
@@ -528,17 +540,19 @@ def badges(request, code):
urls = []
for tag in sorted_tags:
- urls.append({
- "tag": tag,
- "svg": get_badge_url(project.badge_key, tag),
- "json": get_badge_url(project.badge_key, tag, format="json"),
- })
+ urls.append(
+ {
+ "tag": tag,
+ "svg": get_badge_url(project.badge_key, tag),
+ "json": get_badge_url(project.badge_key, tag, format="json"),
+ }
+ )
ctx = {
"have_tags": len(urls) > 1,
"page": "badges",
"project": project,
- "badges": urls
+ "badges": urls,
}
return render(request, "front/badges.html", ctx)
@@ -587,7 +601,7 @@ def channels(request):
"enable_pd": settings.PD_VENDOR_KEY is not None,
"enable_trello": settings.TRELLO_APP_KEY is not None,
"enable_matrix": settings.MATRIX_ACCESS_TOKEN is not None,
- "use_payments": settings.USE_PAYMENTS
+ "use_payments": settings.USE_PAYMENTS,
}
return render(request, "front/channels.html", ctx)
@@ -599,14 +613,10 @@ def channel_checks(request, code):
if channel.project_id != request.project.id:
return HttpResponseForbidden()
- assigned = set(channel.checks.values_list('code', flat=True).distinct())
+ assigned = set(channel.checks.values_list("code", flat=True).distinct())
checks = Check.objects.filter(project=request.project).order_by("created")
- ctx = {
- "checks": checks,
- "assigned": assigned,
- "channel": channel
- }
+ ctx = {"checks": checks, "assigned": assigned, "channel": channel}
return render(request, "front/channel_checks.html", ctx)
@@ -696,11 +706,13 @@ def add_email(request):
form = AddEmailForm(request.POST)
if form.is_valid():
channel = Channel(project=request.project, kind="email")
- channel.value = json.dumps({
- "value": form.cleaned_data["value"],
- "up": form.cleaned_data["up"],
- "down": form.cleaned_data["down"]
- })
+ channel.value = json.dumps(
+ {
+ "value": form.cleaned_data["value"],
+ "up": form.cleaned_data["up"],
+ "down": form.cleaned_data["down"],
+ }
+ )
channel.save()
channel.assign_all_checks()
@@ -726,7 +738,7 @@ def add_email(request):
"page": "channels",
"project": request.project,
"use_verification": settings.EMAIL_USE_VERIFICATION,
- "form": form
+ "form": form,
}
return render(request, "integrations/add_email.html", ctx)
@@ -749,7 +761,7 @@ def add_webhook(request):
"page": "channels",
"project": request.project,
"form": form,
- "now": timezone.now().replace(microsecond=0).isoformat()
+ "now": timezone.now().replace(microsecond=0).isoformat(),
}
return render(request, "integrations/add_webhook.html", ctx)
@@ -790,10 +802,12 @@ def add_pd(request, state=None):
channel = Channel(kind="pd", project=request.project)
channel.user = request.project.owner
- channel.value = json.dumps({
- "service_key": request.GET.get("service_key"),
- "account": request.GET.get("account")
- })
+ channel.value = json.dumps(
+ {
+ "service_key": request.GET.get("service_key"),
+ "account": request.GET.get("account"),
+ }
+ )
channel.save()
channel.assign_all_checks()
messages.success(request, "The PagerDuty integration has been added!")
@@ -801,16 +815,11 @@ def add_pd(request, state=None):
state = _prepare_state(request, "pd")
callback = settings.SITE_ROOT + reverse("hc-add-pd-state", args=[state])
- connect_url = "https://connect.pagerduty.com/connect?" + urlencode({
- "vendor": settings.PD_VENDOR_KEY,
- "callback": callback
- })
+ connect_url = "https://connect.pagerduty.com/connect?" + urlencode(
+ {"vendor": settings.PD_VENDOR_KEY, "callback": callback}
+ )
- ctx = {
- "page": "channels",
- "project": request.project,
- "connect_url": connect_url
- }
+ ctx = {"page": "channels", "project": request.project, "connect_url": connect_url}
return render(request, "integrations/add_pd.html", ctx)
@@ -828,11 +837,7 @@ def add_pagertree(request):
else:
form = AddUrlForm()
- ctx = {
- "page": "channels",
- "project": request.project,
- "form": form
- }
+ ctx = {"page": "channels", "project": request.project, "form": form}
return render(request, "integrations/add_pagertree.html", ctx)
@@ -850,11 +855,7 @@ def add_pagerteam(request):
else:
form = AddUrlForm()
- ctx = {
- "page": "channels",
- "project": request.project,
- "form": form
- }
+ ctx = {"page": "channels", "project": request.project, "form": form}
return render(request, "integrations/add_pagerteam.html", ctx)
@@ -877,7 +878,7 @@ def add_slack(request):
ctx = {
"page": "channels",
"form": form,
- "slack_client_id": settings.SLACK_CLIENT_ID
+ "slack_client_id": settings.SLACK_CLIENT_ID,
}
if request.user.is_authenticated:
@@ -895,11 +896,14 @@ def add_slack_btn(request):
if code is None:
return HttpResponseBadRequest()
- result = requests.post("https://slack.com/api/oauth.access", {
- "client_id": settings.SLACK_CLIENT_ID,
- "client_secret": settings.SLACK_CLIENT_SECRET,
- "code": code
- })
+ result = requests.post(
+ "https://slack.com/api/oauth.access",
+ {
+ "client_id": settings.SLACK_CLIENT_ID,
+ "client_secret": settings.SLACK_CLIENT_SECRET,
+ "code": code,
+ },
+ )
doc = result.json()
if doc.get("ok"):
@@ -926,12 +930,15 @@ def add_pushbullet(request):
if code is None:
return HttpResponseBadRequest()
- result = requests.post("https://api.pushbullet.com/oauth2/token", {
- "client_id": settings.PUSHBULLET_CLIENT_ID,
- "client_secret": settings.PUSHBULLET_CLIENT_SECRET,
- "code": code,
- "grant_type": "authorization_code"
- })
+ result = requests.post(
+ "https://api.pushbullet.com/oauth2/token",
+ {
+ "client_id": settings.PUSHBULLET_CLIENT_ID,
+ "client_secret": settings.PUSHBULLET_CLIENT_SECRET,
+ "code": code,
+ "grant_type": "authorization_code",
+ },
+ )
doc = result.json()
if "access_token" in doc:
@@ -940,25 +947,26 @@ def add_pushbullet(request):
channel.value = doc["access_token"]
channel.save()
channel.assign_all_checks()
- messages.success(request,
- "The Pushbullet integration has been added!")
+ messages.success(request, "The Pushbullet integration has been added!")
else:
messages.warning(request, "Something went wrong")
return redirect("hc-channels")
redirect_uri = settings.SITE_ROOT + reverse("hc-add-pushbullet")
- authorize_url = "https://www.pushbullet.com/authorize?" + urlencode({
- "client_id": settings.PUSHBULLET_CLIENT_ID,
- "redirect_uri": redirect_uri,
- "response_type": "code",
- "state": _prepare_state(request, "pushbullet")
- })
+ authorize_url = "https://www.pushbullet.com/authorize?" + urlencode(
+ {
+ "client_id": settings.PUSHBULLET_CLIENT_ID,
+ "redirect_uri": redirect_uri,
+ "response_type": "code",
+ "state": _prepare_state(request, "pushbullet"),
+ }
+ )
ctx = {
"page": "channels",
"project": request.project,
- "authorize_url": authorize_url
+ "authorize_url": authorize_url,
}
return render(request, "integrations/add_pushbullet.html", ctx)
@@ -974,13 +982,16 @@ def add_discord(request):
if code is None:
return HttpResponseBadRequest()
- result = requests.post("https://discordapp.com/api/oauth2/token", {
- "client_id": settings.DISCORD_CLIENT_ID,
- "client_secret": settings.DISCORD_CLIENT_SECRET,
- "code": code,
- "grant_type": "authorization_code",
- "redirect_uri": redirect_uri
- })
+ result = requests.post(
+ "https://discordapp.com/api/oauth2/token",
+ {
+ "client_id": settings.DISCORD_CLIENT_ID,
+ "client_secret": settings.DISCORD_CLIENT_SECRET,
+ "code": code,
+ "grant_type": "authorization_code",
+ "redirect_uri": redirect_uri,
+ },
+ )
doc = result.json()
if "access_token" in doc:
@@ -989,32 +1000,32 @@ def add_discord(request):
channel.value = result.text
channel.save()
channel.assign_all_checks()
- messages.success(request,
- "The Discord integration has been added!")
+ messages.success(request, "The Discord integration has been added!")
else:
messages.warning(request, "Something went wrong")
return redirect("hc-channels")
- auth_url = "https://discordapp.com/api/oauth2/authorize?" + urlencode({
- "client_id": settings.DISCORD_CLIENT_ID,
- "scope": "webhook.incoming",
- "redirect_uri": redirect_uri,
- "response_type": "code",
- "state": _prepare_state(request, "discord")
- })
+ auth_url = "https://discordapp.com/api/oauth2/authorize?" + urlencode(
+ {
+ "client_id": settings.DISCORD_CLIENT_ID,
+ "scope": "webhook.incoming",
+ "redirect_uri": redirect_uri,
+ "response_type": "code",
+ "state": _prepare_state(request, "discord"),
+ }
+ )
- ctx = {
- "page": "channels",
- "project": request.project,
- "authorize_url": auth_url
- }
+ ctx = {"page": "channels", "project": request.project, "authorize_url": auth_url}
return render(request, "integrations/add_discord.html", ctx)
def add_pushover(request):
- if settings.PUSHOVER_API_TOKEN is None or settings.PUSHOVER_SUBSCRIPTION_URL is None:
+ if (
+ settings.PUSHOVER_API_TOKEN is None
+ or settings.PUSHOVER_SUBSCRIPTION_URL is None
+ ):
raise Http404("pushover integration is not available")
if not request.user.is_authenticated:
@@ -1026,15 +1037,23 @@ def add_pushover(request):
state = _prepare_state(request, "pushover")
failure_url = settings.SITE_ROOT + reverse("hc-channels")
- success_url = settings.SITE_ROOT + reverse("hc-add-pushover") + "?" + urlencode({
- "state": state,
- "prio": request.POST.get("po_priority", "0"),
- "prio_up": request.POST.get("po_priority_up", "0")
- })
- subscription_url = settings.PUSHOVER_SUBSCRIPTION_URL + "?" + urlencode({
- "success": success_url,
- "failure": failure_url,
- })
+ success_url = (
+ settings.SITE_ROOT
+ + reverse("hc-add-pushover")
+ + "?"
+ + urlencode(
+ {
+ "state": state,
+ "prio": request.POST.get("po_priority", "0"),
+ "prio_up": request.POST.get("po_priority_up", "0"),
+ }
+ )
+ )
+ subscription_url = (
+ settings.PUSHOVER_SUBSCRIPTION_URL
+ + "?"
+ + urlencode({"success": success_url, "failure": failure_url})
+ )
return redirect(subscription_url)
@@ -1091,11 +1110,7 @@ def add_opsgenie(request):
else:
form = AddUrlForm()
- ctx = {
- "page": "channels",
- "project": request.project,
- "form": form
- }
+ ctx = {"page": "channels", "project": request.project, "form": form}
return render(request, "integrations/add_opsgenie.html", ctx)
@@ -1113,11 +1128,7 @@ def add_victorops(request):
else:
form = AddUrlForm()
- ctx = {
- "page": "channels",
- "project": request.project,
- "form": form
- }
+ ctx = {"page": "channels", "project": request.project, "form": form}
return render(request, "integrations/add_victorops.html", ctx)
@@ -1140,9 +1151,10 @@ def telegram_bot(request):
chat = doc["message"]["chat"]
name = max(chat.get("title", ""), chat.get("username", ""))
- invite = render_to_string("integrations/telegram_invite.html", {
- "qs": signing.dumps((chat["id"], chat["type"], name))
- })
+ invite = render_to_string(
+ "integrations/telegram_invite.html",
+ {"qs": signing.dumps((chat["id"], chat["type"], name))},
+ )
Telegram.send(chat["id"], invite)
return HttpResponse()
@@ -1157,11 +1169,9 @@ def add_telegram(request):
if request.method == "POST":
channel = Channel(project=request.project, kind="telegram")
- channel.value = json.dumps({
- "id": chat_id,
- "type": chat_type,
- "name": chat_name
- })
+ channel.value = json.dumps(
+ {"id": chat_id, "type": chat_type, "name": chat_name}
+ )
channel.save()
channel.assign_all_checks()
@@ -1174,7 +1184,7 @@ def add_telegram(request):
"chat_id": chat_id,
"chat_type": chat_type,
"chat_name": chat_name,
- "bot_name": settings.TELEGRAM_BOT_NAME
+ "bot_name": settings.TELEGRAM_BOT_NAME,
}
return render(request, "integrations/add_telegram.html", ctx)
@@ -1190,9 +1200,7 @@ def add_sms(request):
if form.is_valid():
channel = Channel(project=request.project, kind="sms")
channel.name = form.cleaned_data["label"]
- channel.value = json.dumps({
- "value": form.cleaned_data["value"]
- })
+ channel.value = json.dumps({"value": form.cleaned_data["value"]})
channel.save()
channel.assign_all_checks()
@@ -1204,7 +1212,7 @@ def add_sms(request):
"page": "channels",
"project": request.project,
"form": form,
- "profile": request.project.owner_profile
+ "profile": request.project.owner_profile,
}
return render(request, "integrations/add_sms.html", ctx)
@@ -1222,19 +1230,21 @@ def add_trello(request):
channel.assign_all_checks()
return redirect("hc-channels")
- authorize_url = "https://trello.com/1/authorize?" + urlencode({
- "expiration": "never",
- "name": settings.SITE_NAME,
- "scope": "read,write",
- "response_type": "token",
- "key": settings.TRELLO_APP_KEY,
- "return_url": settings.SITE_ROOT + reverse("hc-add-trello")
- })
+ authorize_url = "https://trello.com/1/authorize?" + urlencode(
+ {
+ "expiration": "never",
+ "name": settings.SITE_NAME,
+ "scope": "read,write",
+ "response_type": "token",
+ "key": settings.TRELLO_APP_KEY,
+ "return_url": settings.SITE_ROOT + reverse("hc-add-trello"),
+ }
+ )
ctx = {
"page": "channels",
"project": request.project,
- "authorize_url": authorize_url
+ "authorize_url": authorize_url,
}
return render(request, "integrations/add_trello.html", ctx)
@@ -1268,7 +1278,7 @@ def add_matrix(request):
"page": "channels",
"project": request.project,
"form": form,
- "matrix_user_id": settings.MATRIX_USER_ID
+ "matrix_user_id": settings.MATRIX_USER_ID,
}
return render(request, "integrations/add_matrix.html", ctx)
@@ -1278,17 +1288,16 @@ def add_matrix(request):
def trello_settings(request):
token = request.POST.get("token")
- url = "https://api.trello.com/1/members/me/boards?" + urlencode({
- "key": settings.TRELLO_APP_KEY,
- "token": token,
- "fields": "id,name",
- "lists": "open",
- "list_fields": "id,name"
- })
+ url = "https://api.trello.com/1/members/me/boards?" + urlencode(
+ {
+ "key": settings.TRELLO_APP_KEY,
+ "token": token,
+ "fields": "id,name",
+ "lists": "open",
+ "list_fields": "id,name",
+ }
+ )
r = requests.get(url)
- ctx = {
- "token": token,
- "data": r.json()
- }
+ ctx = {"token": token, "data": r.json()}
return render(request, "integrations/trello_settings.html", ctx)
diff --git a/hc/lib/badges.py b/hc/lib/badges.py
index 9fc06f4b..8847e882 100644
--- a/hc/lib/badges.py
+++ b/hc/lib/badges.py
@@ -3,21 +3,75 @@ from django.core.signing import base64_hmac
from django.template.loader import render_to_string
from django.urls import reverse
-WIDTHS = {"a": 7, "b": 7, "c": 6, "d": 7, "e": 6, "f": 4, "g": 7, "h": 7,
- "i": 3, "j": 3, "k": 7, "l": 3, "m": 10, "n": 7, "o": 7, "p": 7,
- "q": 7, "r": 4, "s": 6, "t": 5, "u": 7, "v": 7, "w": 9, "x": 6,
- "y": 7, "z": 7, "0": 7, "1": 6, "2": 7, "3": 7, "4": 7, "5": 7,
- "6": 7, "7": 7, "8": 7, "9": 7, "A": 8, "B": 7, "C": 8, "D": 8,
- "E": 7, "F": 6, "G": 9, "H": 8, "I": 3, "J": 4, "K": 7, "L": 6,
- "M": 10, "N": 8, "O": 9, "P": 6, "Q": 9, "R": 7, "S": 7, "T": 7,
- "U": 8, "V": 8, "W": 11, "X": 7, "Y": 7, "Z": 7, "-": 4, "_": 6}
-
-COLORS = {
- "up": "#4c1",
- "late": "#fe7d37",
- "down": "#e05d44"
+WIDTHS = {
+ "a": 7,
+ "b": 7,
+ "c": 6,
+ "d": 7,
+ "e": 6,
+ "f": 4,
+ "g": 7,
+ "h": 7,
+ "i": 3,
+ "j": 3,
+ "k": 7,
+ "l": 3,
+ "m": 10,
+ "n": 7,
+ "o": 7,
+ "p": 7,
+ "q": 7,
+ "r": 4,
+ "s": 6,
+ "t": 5,
+ "u": 7,
+ "v": 7,
+ "w": 9,
+ "x": 6,
+ "y": 7,
+ "z": 7,
+ "0": 7,
+ "1": 6,
+ "2": 7,
+ "3": 7,
+ "4": 7,
+ "5": 7,
+ "6": 7,
+ "7": 7,
+ "8": 7,
+ "9": 7,
+ "A": 8,
+ "B": 7,
+ "C": 8,
+ "D": 8,
+ "E": 7,
+ "F": 6,
+ "G": 9,
+ "H": 8,
+ "I": 3,
+ "J": 4,
+ "K": 7,
+ "L": 6,
+ "M": 10,
+ "N": 8,
+ "O": 9,
+ "P": 6,
+ "Q": 9,
+ "R": 7,
+ "S": 7,
+ "T": 7,
+ "U": 8,
+ "V": 8,
+ "W": 11,
+ "X": 7,
+ "Y": 7,
+ "Z": 7,
+ "-": 4,
+ "_": 6,
}
+COLORS = {"up": "#4c1", "late": "#fe7d37", "down": "#e05d44"}
+
def get_width(s):
total = 0
@@ -37,7 +91,7 @@ def get_badge_svg(tag, status):
"status_center_x": w1 + w2 / 2,
"tag": tag,
"status": status,
- "color": COLORS[status]
+ "color": COLORS[status],
}
return render_to_string("badge.svg", ctx)
diff --git a/hc/lib/emails.py b/hc/lib/emails.py
index 63d5f6e1..68bd34ae 100644
--- a/hc/lib/emails.py
+++ b/hc/lib/emails.py
@@ -15,8 +15,9 @@ class EmailThread(Thread):
self.headers = headers
def run(self):
- msg = EmailMultiAlternatives(self.subject, self.text, to=(self.to, ),
- headers=self.headers)
+ msg = EmailMultiAlternatives(
+ self.subject, self.text, to=(self.to,), headers=self.headers
+ )
msg.attach_alternative(self.html, "text/html")
msg.send()
@@ -25,9 +26,9 @@ class EmailThread(Thread):
def send(name, to, ctx, headers={}):
ctx["SITE_ROOT"] = settings.SITE_ROOT
- subject = render('emails/%s-subject.html' % name, ctx).strip()
- text = render('emails/%s-body-text.html' % name, ctx)
- html = render('emails/%s-body-html.html' % name, ctx)
+ subject = render("emails/%s-subject.html" % name, ctx).strip()
+ text = render("emails/%s-body-text.html" % name, ctx)
+ html = render("emails/%s-body-html.html" % name, ctx)
t = EmailThread(subject, text, html, to, headers)
if hasattr(settings, "BLOCKING_EMAILS"):
@@ -62,11 +63,11 @@ def report(to, ctx, headers={}):
def invoice(to, ctx, filename, pdf_data):
ctx["SITE_ROOT"] = settings.SITE_ROOT
- subject = render('emails/invoice-subject.html', ctx).strip()
- text = render('emails/invoice-body-text.html', ctx)
- html = render('emails/invoice-body-html.html', ctx)
+ subject = render("emails/invoice-subject.html", ctx).strip()
+ text = render("emails/invoice-body-text.html", ctx)
+ html = render("emails/invoice-body-html.html", ctx)
- msg = EmailMultiAlternatives(subject, text, to=(to, ))
+ msg = EmailMultiAlternatives(subject, text, to=(to,))
msg.attach_alternative(html, "text/html")
msg.attach(filename, pdf_data, "application/pdf")
msg.send()
diff --git a/hc/lib/jsonschema.py b/hc/lib/jsonschema.py
index 53e33371..d7341c9c 100644
--- a/hc/lib/jsonschema.py
+++ b/hc/lib/jsonschema.py
@@ -24,8 +24,7 @@ def validate(obj, schema, obj_name="value"):
try:
croniter(obj)
except:
- raise ValidationError(
- "%s is not a valid cron expression" % obj_name)
+ raise ValidationError("%s is not a valid cron expression" % obj_name)
if schema.get("format") == "timezone" and obj not in all_timezones:
raise ValidationError("%s is not a valid timezone" % obj_name)
diff --git a/hc/lib/tests/test_badges.py b/hc/lib/tests/test_badges.py
index d5390e1e..f46fb87a 100644
--- a/hc/lib/tests/test_badges.py
+++ b/hc/lib/tests/test_badges.py
@@ -4,7 +4,6 @@ from hc.lib.badges import get_width, get_badge_svg
class BadgesTestCase(TestCase):
-
def test_get_width_works(self):
self.assertEqual(get_width("mm"), 20)
# Default width for unknown characters is 7
diff --git a/hc/lib/tests/test_date.py b/hc/lib/tests/test_date.py
index 26dbe9dd..99be8e44 100644
--- a/hc/lib/tests/test_date.py
+++ b/hc/lib/tests/test_date.py
@@ -5,7 +5,6 @@ from hc.lib.date import format_hms
class DateFormattingTestCase(TestCase):
-
def test_mins_secs_work(self):
s = format_hms(td(seconds=0))
self.assertEqual(s, "0 sec")
diff --git a/hc/lib/tests/test_jsonschema.py b/hc/lib/tests/test_jsonschema.py
index 88a08990..b83b95b6 100644
--- a/hc/lib/tests/test_jsonschema.py
+++ b/hc/lib/tests/test_jsonschema.py
@@ -4,7 +4,6 @@ from hc.lib.jsonschema import ValidationError, validate
class JsonSchemaTestCase(TestCase):
-
def test_it_validates_strings(self):
validate("foo", {"type": "string"})
@@ -36,12 +35,10 @@ class JsonSchemaTestCase(TestCase):
validate(5, {"type": "number", "maximum": 0})
def test_it_validates_objects(self):
- validate({"foo": "bar"}, {
- "type": "object",
- "properties": {
- "foo": {"type": "string"}
- }
- })
+ validate(
+ {"foo": "bar"},
+ {"type": "object", "properties": {"foo": {"type": "string"}}},
+ )
def test_it_checks_dict_type(self):
with self.assertRaises(ValidationError):
@@ -49,39 +46,25 @@ class JsonSchemaTestCase(TestCase):
def test_it_validates_objects_properties(self):
with self.assertRaises(ValidationError):
- validate({"foo": "bar"}, {
- "type": "object",
- "properties": {
- "foo": {"type": "number"}
- }
- })
+ validate(
+ {"foo": "bar"},
+ {"type": "object", "properties": {"foo": {"type": "number"}}},
+ )
def test_it_handles_required_properties(self):
with self.assertRaises(ValidationError):
- validate({"foo": "bar"}, {
- "type": "object",
- "required": ["baz"]
- })
+ validate({"foo": "bar"}, {"type": "object", "required": ["baz"]})
def test_it_validates_arrays(self):
- validate(["foo", "bar"], {
- "type": "array",
- "items": {"type": "string"}
- })
+ validate(["foo", "bar"], {"type": "array", "items": {"type": "string"}})
def test_it_validates_array_type(self):
with self.assertRaises(ValidationError):
- validate("not-an-array", {
- "type": "array",
- "items": {"type": "string"}
- })
+ validate("not-an-array", {"type": "array", "items": {"type": "string"}})
def test_it_validates_array_elements(self):
with self.assertRaises(ValidationError):
- validate(["foo", "bar"], {
- "type": "array",
- "items": {"type": "number"}
- })
+ validate(["foo", "bar"], {"type": "array", "items": {"type": "number"}})
def test_it_validates_enum(self):
validate("foo", {"enum": ["foo", "bar"]})
diff --git a/hc/payments/admin.py b/hc/payments/admin.py
index 6f724988..54e9a3a2 100644
--- a/hc/payments/admin.py
+++ b/hc/payments/admin.py
@@ -8,16 +8,28 @@ from hc.payments.models import Subscription
@admin.register(Subscription)
class SubsAdmin(admin.ModelAdmin):
- readonly_fields = ("email", )
- search_fields = ("customer_id", "payment_method_token", "subscription_id",
- "user__email")
- list_display = ("id", "email", "customer_id", "address_id",
- "payment_method_token", "subscription_id", "plan_id",
- "plan_name", "profile")
-
- list_filter = ("plan_id", )
- raw_id_fields = ("user", )
- actions = ("cancel", )
+ readonly_fields = ("email",)
+ search_fields = (
+ "customer_id",
+ "payment_method_token",
+ "subscription_id",
+ "user__email",
+ )
+ list_display = (
+ "id",
+ "email",
+ "customer_id",
+ "address_id",
+ "payment_method_token",
+ "subscription_id",
+ "plan_id",
+ "plan_name",
+ "profile",
+ )
+
+ list_filter = ("plan_id",)
+ raw_id_fields = ("user",)
+ actions = ("cancel",)
def email(self, obj):
return obj.user.email if obj.user else None
@@ -25,8 +37,7 @@ class SubsAdmin(admin.ModelAdmin):
@mark_safe
def profile(self, obj):
if obj.user.profile:
- url = reverse("admin:accounts_profile_change",
- args=[obj.user.profile.id])
+ url = reverse("admin:accounts_profile_change", args=[obj.user.profile.id])
return "View Profile" % url
return ""
diff --git a/hc/payments/context_processors.py b/hc/payments/context_processors.py
index 27da5020..a25e7039 100644
--- a/hc/payments/context_processors.py
+++ b/hc/payments/context_processors.py
@@ -2,4 +2,4 @@ from django.conf import settings
def payments(request):
- return {'show_pricing': settings.USE_PAYMENTS}
+ return {"show_pricing": settings.USE_PAYMENTS}
diff --git a/hc/payments/invoices.py b/hc/payments/invoices.py
index 5391cf8a..7edc8bdc 100644
--- a/hc/payments/invoices.py
+++ b/hc/payments/invoices.py
@@ -4,6 +4,7 @@ try:
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch
from reportlab.pdfgen.canvas import Canvas
+
W, H = A4
except ImportError:
# Don't crash if reportlab is not installed.
@@ -70,8 +71,7 @@ class PdfInvoice(Canvas):
self.linefeed()
self.hr()
- self.row(["Description", "Start", "End", tx.currency_iso_code],
- bold=True)
+ self.row(["Description", "Start", "End", tx.currency_iso_code], bold=True)
self.hr()
start = f(tx.subscription_details.billing_period_start_date)
end = f(tx.subscription_details.billing_period_end_date)
diff --git a/hc/payments/migrations/0001_initial.py b/hc/payments/migrations/0001_initial.py
index 48b241a7..54f225ee 100644
--- a/hc/payments/migrations/0001_initial.py
+++ b/hc/payments/migrations/0001_initial.py
@@ -7,19 +7,33 @@ from django.conf import settings
class Migration(migrations.Migration):
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
+ dependencies = [migrations.swappable_dependency(settings.AUTH_USER_MODEL)]
operations = [
migrations.CreateModel(
- name='Subscription',
+ name="Subscription",
fields=[
- ('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
- ('customer_id', models.CharField(blank=True, max_length=36)),
- ('payment_method_token', models.CharField(blank=True, max_length=35)),
- ('subscription_id', models.CharField(blank=True, max_length=10)),
- ('user', models.OneToOneField(blank=True, null=True, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
+ (
+ "id",
+ models.AutoField(
+ serialize=False,
+ primary_key=True,
+ auto_created=True,
+ verbose_name="ID",
+ ),
+ ),
+ ("customer_id", models.CharField(blank=True, max_length=36)),
+ ("payment_method_token", models.CharField(blank=True, max_length=35)),
+ ("subscription_id", models.CharField(blank=True, max_length=10)),
+ (
+ "user",
+ models.OneToOneField(
+ blank=True,
+ null=True,
+ to=settings.AUTH_USER_MODEL,
+ on_delete=models.CASCADE,
+ ),
+ ),
],
- ),
+ )
]
diff --git a/hc/payments/migrations/0002_subscription_plan_id.py b/hc/payments/migrations/0002_subscription_plan_id.py
index 03281f34..8fdac187 100644
--- a/hc/payments/migrations/0002_subscription_plan_id.py
+++ b/hc/payments/migrations/0002_subscription_plan_id.py
@@ -6,14 +6,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ('payments', '0001_initial'),
- ]
+ dependencies = [("payments", "0001_initial")]
operations = [
migrations.AddField(
- model_name='subscription',
- name='plan_id',
+ model_name="subscription",
+ name="plan_id",
field=models.CharField(blank=True, max_length=10),
- ),
+ )
]
diff --git a/hc/payments/migrations/0003_subscription_address_id.py b/hc/payments/migrations/0003_subscription_address_id.py
index 1df31f9d..4c3c1b5d 100644
--- a/hc/payments/migrations/0003_subscription_address_id.py
+++ b/hc/payments/migrations/0003_subscription_address_id.py
@@ -7,14 +7,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ('payments', '0002_subscription_plan_id'),
- ]
+ dependencies = [("payments", "0002_subscription_plan_id")]
operations = [
migrations.AddField(
- model_name='subscription',
- name='address_id',
+ model_name="subscription",
+ name="address_id",
field=models.CharField(blank=True, max_length=2),
- ),
+ )
]
diff --git a/hc/payments/migrations/0004_subscription_send_invoices.py b/hc/payments/migrations/0004_subscription_send_invoices.py
index 568a7894..48ba3d53 100644
--- a/hc/payments/migrations/0004_subscription_send_invoices.py
+++ b/hc/payments/migrations/0004_subscription_send_invoices.py
@@ -7,14 +7,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ('payments', '0003_subscription_address_id'),
- ]
+ dependencies = [("payments", "0003_subscription_address_id")]
operations = [
migrations.AddField(
- model_name='subscription',
- name='send_invoices',
+ model_name="subscription",
+ name="send_invoices",
field=models.BooleanField(default=True),
- ),
+ )
]
diff --git a/hc/payments/migrations/0005_subscription_plan_name.py b/hc/payments/migrations/0005_subscription_plan_name.py
index a2f8a339..18fb38da 100644
--- a/hc/payments/migrations/0005_subscription_plan_name.py
+++ b/hc/payments/migrations/0005_subscription_plan_name.py
@@ -7,14 +7,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ('payments', '0004_subscription_send_invoices'),
- ]
+ dependencies = [("payments", "0004_subscription_send_invoices")]
operations = [
migrations.AddField(
- model_name='subscription',
- name='plan_name',
+ model_name="subscription",
+ name="plan_name",
field=models.CharField(blank=True, max_length=50),
- ),
+ )
]
diff --git a/hc/payments/migrations/0006_subscription_invoice_email.py b/hc/payments/migrations/0006_subscription_invoice_email.py
index 81c2f2e0..d26d413f 100644
--- a/hc/payments/migrations/0006_subscription_invoice_email.py
+++ b/hc/payments/migrations/0006_subscription_invoice_email.py
@@ -7,14 +7,12 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ('payments', '0005_subscription_plan_name'),
- ]
+ dependencies = [("payments", "0005_subscription_plan_name")]
operations = [
migrations.AddField(
- model_name='subscription',
- name='invoice_email',
+ model_name="subscription",
+ name="invoice_email",
field=models.EmailField(blank=True, max_length=254),
- ),
+ )
]
diff --git a/hc/payments/models.py b/hc/payments/models.py
index e7f068ce..5903791c 100644
--- a/hc/payments/models.py
+++ b/hc/payments/models.py
@@ -11,13 +11,18 @@ else:
braintree = None
-ADDRESS_KEYS = ("company", "street_address",
- "extended_address", "locality", "region", "postal_code",
- "country_code_alpha2")
+ADDRESS_KEYS = (
+ "company",
+ "street_address",
+ "extended_address",
+ "locality",
+ "region",
+ "postal_code",
+ "country_code_alpha2",
+)
class SubscriptionManager(models.Manager):
-
def for_user(self, user):
sub, created = Subscription.objects.get_or_create(user_id=user.id)
return sub
@@ -74,16 +79,12 @@ class Subscription(models.Model):
return self._sub
def get_client_token(self):
- return braintree.ClientToken.generate({
- "customer_id": self.customer_id
- })
+ return braintree.ClientToken.generate({"customer_id": self.customer_id})
def update_payment_method(self, nonce):
# Create customer record if it does not exist:
if not self.customer_id:
- result = braintree.Customer.create({
- "email": self.user.email
- })
+ result = braintree.Customer.create({"email": self.user.email})
if not result.is_success:
return result
@@ -91,11 +92,13 @@ class Subscription(models.Model):
self.save()
# Create payment method
- result = braintree.PaymentMethod.create({
- "customer_id": self.customer_id,
- "payment_method_nonce": nonce,
- "options": {"make_default": True}
- })
+ result = braintree.PaymentMethod.create(
+ {
+ "customer_id": self.customer_id,
+ "payment_method_nonce": nonce,
+ "options": {"make_default": True},
+ }
+ )
if not result.is_success:
return result
@@ -105,9 +108,10 @@ class Subscription(models.Model):
# Update an existing subscription to use this payment method
if self.subscription_id:
- result = braintree.Subscription.update(self.subscription_id, {
- "payment_method_token": self.payment_method_token
- })
+ result = braintree.Subscription.update(
+ self.subscription_id,
+ {"payment_method_token": self.payment_method_token},
+ )
if not result.is_success:
return result
@@ -115,9 +119,7 @@ class Subscription(models.Model):
def update_address(self, post_data):
# Create customer record if it does not exist:
if not self.customer_id:
- result = braintree.Customer.create({
- "email": self.user.email
- })
+ result = braintree.Customer.create({"email": self.user.email})
if not result.is_success:
return result
@@ -126,9 +128,9 @@ class Subscription(models.Model):
payload = {key: str(post_data.get(key)) for key in ADDRESS_KEYS}
if self.address_id:
- result = braintree.Address.update(self.customer_id,
- self.address_id,
- payload)
+ result = braintree.Address.update(
+ self.customer_id, self.address_id, payload
+ )
else:
payload["customer_id"] = self.customer_id
result = braintree.Address.create(payload)
@@ -140,10 +142,9 @@ class Subscription(models.Model):
return result
def setup(self, plan_id):
- result = braintree.Subscription.create({
- "payment_method_token": self.payment_method_token,
- "plan_id": plan_id
- })
+ result = braintree.Subscription.create(
+ {"payment_method_token": self.payment_method_token, "plan_id": plan_id}
+ )
if result.is_success:
self.subscription_id = result.subscription.id
@@ -186,8 +187,9 @@ class Subscription(models.Model):
def address(self):
if not hasattr(self, "_address"):
try:
- self._address = braintree.Address.find(self.customer_id,
- self.address_id)
+ self._address = braintree.Address.find(
+ self.customer_id, self.address_id
+ )
except braintree.exceptions.NotFoundError:
self._address = None
@@ -206,6 +208,10 @@ class Subscription(models.Model):
if not self.customer_id:
self._tx = []
else:
- self._tx = list(braintree.Transaction.search(braintree.TransactionSearch.customer_id == self.customer_id))
+ self._tx = list(
+ braintree.Transaction.search(
+ braintree.TransactionSearch.customer_id == self.customer_id
+ )
+ )
return self._tx
diff --git a/hc/payments/tests/test_address.py b/hc/payments/tests/test_address.py
index 2901860c..3333de6d 100644
--- a/hc/payments/tests/test_address.py
+++ b/hc/payments/tests/test_address.py
@@ -5,7 +5,6 @@ from hc.test import BaseTestCase
class AddressTestCase(BaseTestCase):
-
@patch("hc.payments.models.braintree")
def test_it_retrieves_address(self, mock):
mock.Address.find.return_value = {"company": "FooCo"}
diff --git a/hc/payments/tests/test_billing.py b/hc/payments/tests/test_billing.py
index d62addbb..ce0c56dd 100644
--- a/hc/payments/tests/test_billing.py
+++ b/hc/payments/tests/test_billing.py
@@ -3,7 +3,6 @@ from hc.test import BaseTestCase
class BillingCase(BaseTestCase):
-
def test_it_disables_invoice_emailing(self):
self.client.login(username="alice@example.org", password="password")
diff --git a/hc/payments/tests/test_billing_history.py b/hc/payments/tests/test_billing_history.py
index e6c7a1ec..8ca67150 100644
--- a/hc/payments/tests/test_billing_history.py
+++ b/hc/payments/tests/test_billing_history.py
@@ -5,7 +5,6 @@ from hc.test import BaseTestCase
class BillingHistoryTestCase(BaseTestCase):
-
def setUp(self):
super(BillingHistoryTestCase, self).setUp()
self.sub = Subscription(user=self.alice)
diff --git a/hc/payments/tests/test_charge_webhook.py b/hc/payments/tests/test_charge_webhook.py
index 99213881..7ca3faa3 100644
--- a/hc/payments/tests/test_charge_webhook.py
+++ b/hc/payments/tests/test_charge_webhook.py
@@ -13,7 +13,6 @@ except ImportError:
class ChargeWebhookTestCase(BaseTestCase):
-
def setUp(self):
super(ChargeWebhookTestCase, self).setUp()
self.sub = Subscription(user=self.alice)
diff --git a/hc/payments/tests/test_get_client_token.py b/hc/payments/tests/test_get_client_token.py
index 3bd11d03..eb83a3c7 100644
--- a/hc/payments/tests/test_get_client_token.py
+++ b/hc/payments/tests/test_get_client_token.py
@@ -5,7 +5,6 @@ from hc.test import BaseTestCase
class GetClientTokenTestCase(BaseTestCase):
-
@patch("hc.payments.models.braintree")
def test_it_works(self, mock_braintree):
mock_braintree.ClientToken.generate.return_value = "test-token"
diff --git a/hc/payments/tests/test_payment_method.py b/hc/payments/tests/test_payment_method.py
index 8720746a..1a2b7ec6 100644
--- a/hc/payments/tests/test_payment_method.py
+++ b/hc/payments/tests/test_payment_method.py
@@ -5,7 +5,6 @@ from hc.test import BaseTestCase
class UpdatePaymentMethodTestCase(BaseTestCase):
-
def _setup_mock(self, mock):
""" Set up Braintree calls that the controller will use. """
diff --git a/hc/payments/tests/test_pdf_invoice.py b/hc/payments/tests/test_pdf_invoice.py
index 0c7d8cc3..64010f0f 100644
--- a/hc/payments/tests/test_pdf_invoice.py
+++ b/hc/payments/tests/test_pdf_invoice.py
@@ -12,7 +12,6 @@ except ImportError:
class PdfInvoiceTestCase(BaseTestCase):
-
def setUp(self):
super(PdfInvoiceTestCase, self).setUp()
self.sub = Subscription(user=self.alice)
diff --git a/hc/payments/tests/test_pricing.py b/hc/payments/tests/test_pricing.py
index d1cd9cc6..f5becf87 100644
--- a/hc/payments/tests/test_pricing.py
+++ b/hc/payments/tests/test_pricing.py
@@ -5,7 +5,6 @@ from hc.test import BaseTestCase
class PricingTestCase(BaseTestCase):
-
def test_anonymous(self):
r = self.client.get("/pricing/")
self.assertContains(r, "Unlimited Team Members", status_code=200)
diff --git a/hc/payments/tests/test_set_plan.py b/hc/payments/tests/test_set_plan.py
index c9529ede..50709478 100644
--- a/hc/payments/tests/test_set_plan.py
+++ b/hc/payments/tests/test_set_plan.py
@@ -5,7 +5,6 @@ from hc.test import BaseTestCase
class SetPlanTestCase(BaseTestCase):
-
def _setup_mock(self, mock):
""" Set up Braintree calls that the controller will use. """
diff --git a/hc/payments/urls.py b/hc/payments/urls.py
index a6031796..e0fabb41 100644
--- a/hc/payments/urls.py
+++ b/hc/payments/urls.py
@@ -3,37 +3,25 @@ from django.urls import path
from . import views
urlpatterns = [
- path('pricing/',
- views.pricing,
- name="hc-pricing"),
-
- path('accounts/profile/billing/',
- views.billing,
- name="hc-billing"),
-
- path('accounts/profile/billing/history/',
- views.billing_history,
- name="hc-billing-history"),
-
- path('accounts/profile/billing/address/',
- views.address,
- name="hc-billing-address"),
-
- path('accounts/profile/billing/payment_method/',
- views.payment_method,
- name="hc-payment-method"),
-
- path('invoice/pdf//',
- views.pdf_invoice,
- name="hc-invoice-pdf"),
-
- path('pricing/set_plan/',
- views.set_plan,
- name="hc-set-plan"),
-
- path('pricing/get_client_token/',
- views.get_client_token,
- name="hc-get-client-token"),
-
- path('pricing/charge/', views.charge_webhook),
+ path("pricing/", views.pricing, name="hc-pricing"),
+ path("accounts/profile/billing/", views.billing, name="hc-billing"),
+ path(
+ "accounts/profile/billing/history/",
+ views.billing_history,
+ name="hc-billing-history",
+ ),
+ path("accounts/profile/billing/address/", views.address, name="hc-billing-address"),
+ path(
+ "accounts/profile/billing/payment_method/",
+ views.payment_method,
+ name="hc-payment-method",
+ ),
+ path(
+ "invoice/pdf//", views.pdf_invoice, name="hc-invoice-pdf"
+ ),
+ path("pricing/set_plan/", views.set_plan, name="hc-set-plan"),
+ path(
+ "pricing/get_client_token/", views.get_client_token, name="hc-get-client-token"
+ ),
+ path("pricing/charge/", views.charge_webhook),
]
diff --git a/hc/payments/views.py b/hc/payments/views.py
index b77e5027..98466bf6 100644
--- a/hc/payments/views.py
+++ b/hc/payments/views.py
@@ -2,8 +2,12 @@ from io import BytesIO
from django.contrib import messages
from django.contrib.auth.decorators import login_required
-from django.http import (HttpResponseBadRequest, HttpResponseForbidden,
- JsonResponse, HttpResponse)
+from django.http import (
+ HttpResponseBadRequest,
+ HttpResponseForbidden,
+ JsonResponse,
+ HttpResponse,
+)
from django.shortcuts import get_object_or_404, redirect, render
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
@@ -57,7 +61,7 @@ def billing(request):
"send_invoices_status": send_invoices_status,
"set_plan_status": "default",
"address_status": "default",
- "payment_method_status": "default"
+ "payment_method_status": "default",
}
if "set_plan_status" in request.session:
@@ -67,8 +71,7 @@ def billing(request):
ctx["address_status"] = request.session.pop("address_status")
if "payment_method_status" in request.session:
- ctx["payment_method_status"] = \
- request.session.pop("payment_method_status")
+ ctx["payment_method_status"] = request.session.pop("payment_method_status")
return render(request, "accounts/billing.html", ctx)
@@ -164,10 +167,7 @@ def payment_method(request):
request.session["payment_method_status"] = "success"
return redirect("hc-billing")
- ctx = {
- "sub": sub,
- "pm": sub.payment_method
- }
+ ctx = {"sub": sub, "pm": sub.payment_method}
return render(request, "payments/payment_method.html", ctx)
@@ -195,9 +195,9 @@ def pdf_invoice(request, transaction_id):
if sub.user != request.user and not request.user.is_superuser:
return HttpResponseForbidden()
- response = HttpResponse(content_type='application/pdf')
+ response = HttpResponse(content_type="application/pdf")
filename = "MS-HC-%s.pdf" % tx.id.upper()
- response['Content-Disposition'] = 'attachment; filename="%s"' % filename
+ response["Content-Disposition"] = 'attachment; filename="%s"' % filename
PdfInvoice(response).render(tx, sub.flattened_address())
return response
diff --git a/hc/settings.py b/hc/settings.py
index 9cd77c64..53f0e813 100644
--- a/hc/settings.py
+++ b/hc/settings.py
@@ -36,66 +36,65 @@ USE_PAYMENTS = envbool("USE_PAYMENTS", "False")
REGISTRATION_OPEN = envbool("REGISTRATION_OPEN", "True")
INSTALLED_APPS = (
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.humanize',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'compressor',
-
- 'hc.accounts',
- 'hc.api',
- 'hc.front',
- 'hc.payments'
+ "django.contrib.admin",
+ "django.contrib.auth",
+ "django.contrib.contenttypes",
+ "django.contrib.humanize",
+ "django.contrib.sessions",
+ "django.contrib.messages",
+ "django.contrib.staticfiles",
+ "compressor",
+ "hc.accounts",
+ "hc.api",
+ "hc.front",
+ "hc.payments",
)
MIDDLEWARE = (
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
- 'hc.accounts.middleware.TeamAccessMiddleware',
+ "django.middleware.security.SecurityMiddleware",
+ "django.contrib.sessions.middleware.SessionMiddleware",
+ "django.middleware.common.CommonMiddleware",
+ "django.middleware.csrf.CsrfViewMiddleware",
+ "django.contrib.auth.middleware.AuthenticationMiddleware",
+ "django.contrib.messages.middleware.MessageMiddleware",
+ "django.middleware.clickjacking.XFrameOptionsMiddleware",
+ "hc.accounts.middleware.TeamAccessMiddleware",
)
AUTHENTICATION_BACKENDS = (
- 'hc.accounts.backends.EmailBackend',
- 'hc.accounts.backends.ProfileBackend'
+ "hc.accounts.backends.EmailBackend",
+ "hc.accounts.backends.ProfileBackend",
)
-ROOT_URLCONF = 'hc.urls'
+ROOT_URLCONF = "hc.urls"
TEMPLATES = [
{
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR, 'templates')],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- 'hc.payments.context_processors.payments'
- ],
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
+ "DIRS": [os.path.join(BASE_DIR, "templates")],
+ "APP_DIRS": True,
+ "OPTIONS": {
+ "context_processors": [
+ "django.template.context_processors.debug",
+ "django.template.context_processors.request",
+ "django.contrib.auth.context_processors.auth",
+ "django.contrib.messages.context_processors.messages",
+ "hc.payments.context_processors.payments",
+ ]
},
- },
+ }
]
-WSGI_APPLICATION = 'hc.wsgi.application'
-TEST_RUNNER = 'hc.api.tests.CustomRunner'
+WSGI_APPLICATION = "hc.wsgi.application"
+TEST_RUNNER = "hc.api.tests.CustomRunner"
# Default database engine is SQLite. So one can just check out code,
# install requirements.txt and do manage.py runserver and it works
DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': os.getenv("DB_NAME", BASE_DIR + "/hc.sqlite"),
+ "default": {
+ "ENGINE": "django.db.backends.sqlite3",
+ "NAME": os.getenv("DB_NAME", BASE_DIR + "/hc.sqlite"),
}
}
@@ -103,36 +102,38 @@ DATABASES = {
# variable 'DB'. Travis CI does this.
if os.getenv("DB") == "postgres":
DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.postgresql',
- 'HOST': os.getenv("DB_HOST", ""),
- 'PORT': os.getenv("DB_PORT", ""),
- 'NAME': os.getenv("DB_NAME", "hc"),
- 'USER': os.getenv("DB_USER", "postgres"),
- 'PASSWORD': os.getenv("DB_PASSWORD", ""),
- 'CONN_MAX_AGE': envint("DB_CONN_MAX_AGE", "0"),
- 'TEST': {'CHARSET': 'UTF8'},
- 'OPTIONS': {
+ "default": {
+ "ENGINE": "django.db.backends.postgresql",
+ "HOST": os.getenv("DB_HOST", ""),
+ "PORT": os.getenv("DB_PORT", ""),
+ "NAME": os.getenv("DB_NAME", "hc"),
+ "USER": os.getenv("DB_USER", "postgres"),
+ "PASSWORD": os.getenv("DB_PASSWORD", ""),
+ "CONN_MAX_AGE": envint("DB_CONN_MAX_AGE", "0"),
+ "TEST": {"CHARSET": "UTF8"},
+ "OPTIONS": {
"sslmode": os.getenv("DB_SSLMODE", "prefer"),
- "target_session_attrs": os.getenv("DB_TARGET_SESSION_ATTRS", "read-write")
- }
+ "target_session_attrs": os.getenv(
+ "DB_TARGET_SESSION_ATTRS", "read-write"
+ ),
+ },
}
}
if os.getenv("DB") == "mysql":
DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'HOST': os.getenv("DB_HOST", ""),
- 'PORT': os.getenv("DB_PORT", ""),
- 'NAME': os.getenv("DB_NAME", "hc"),
- 'USER': os.getenv("DB_USER", "root"),
- 'PASSWORD': os.getenv("DB_PASSWORD", ""),
- 'TEST': {'CHARSET': 'UTF8'}
+ "default": {
+ "ENGINE": "django.db.backends.mysql",
+ "HOST": os.getenv("DB_HOST", ""),
+ "PORT": os.getenv("DB_PORT", ""),
+ "NAME": os.getenv("DB_NAME", "hc"),
+ "USER": os.getenv("DB_USER", "root"),
+ "PASSWORD": os.getenv("DB_PASSWORD", ""),
+ "TEST": {"CHARSET": "UTF8"},
}
}
-TIME_ZONE = 'UTC'
+TIME_ZONE = "UTC"
USE_I18N = True
@@ -145,13 +146,13 @@ SITE_NAME = os.getenv("SITE_NAME", "Mychecks")
MASTER_BADGE_LABEL = os.getenv("MASTER_BADGE_LABEL", SITE_NAME)
PING_ENDPOINT = os.getenv("PING_ENDPOINT", SITE_ROOT + "/ping/")
PING_EMAIL_DOMAIN = os.getenv("PING_EMAIL_DOMAIN", "localhost")
-STATIC_URL = '/static/'
+STATIC_URL = "/static/"
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
-STATIC_ROOT = os.path.join(BASE_DIR, 'static-collected')
+STATIC_ROOT = os.path.join(BASE_DIR, "static-collected")
STATICFILES_FINDERS = (
- 'django.contrib.staticfiles.finders.FileSystemFinder',
- 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
- 'compressor.finders.CompressorFinder',
+ "django.contrib.staticfiles.finders.FileSystemFinder",
+ "django.contrib.staticfiles.finders.AppDirectoriesFinder",
+ "compressor.finders.CompressorFinder",
)
COMPRESS_OFFLINE = True
COMPRESS_CSS_HASHING_METHOD = "content"
diff --git a/hc/test.py b/hc/test.py
index 84579d12..cc28a82a 100644
--- a/hc/test.py
+++ b/hc/test.py
@@ -5,7 +5,6 @@ from hc.accounts.models import Member, Profile, Project
class BaseTestCase(TestCase):
-
def setUp(self):
super(BaseTestCase, self).setUp()
diff --git a/hc/urls.py b/hc/urls.py
index a9bce525..761250f7 100644
--- a/hc/urls.py
+++ b/hc/urls.py
@@ -4,13 +4,21 @@ from django.urls import include, path
from hc.accounts import views as accounts_views
urlpatterns = [
- path('admin/login/', accounts_views.login),
- path('admin/', admin.site.urls),
- path('accounts/', include('hc.accounts.urls')),
- path('projects/add/', accounts_views.add_project, name="hc-add-project"),
- path('projects//settings/', accounts_views.project, name="hc-project-settings"),
- path('projects//remove/', accounts_views.remove_project, name="hc-remove-project"),
- path('', include('hc.api.urls')),
- path('', include('hc.front.urls')),
- path('', include('hc.payments.urls'))
+ path("admin/login/", accounts_views.login),
+ path("admin/", admin.site.urls),
+ path("accounts/", include("hc.accounts.urls")),
+ path("projects/add/", accounts_views.add_project, name="hc-add-project"),
+ path(
+ "projects//settings/",
+ accounts_views.project,
+ name="hc-project-settings",
+ ),
+ path(
+ "projects//remove/",
+ accounts_views.remove_project,
+ name="hc-remove-project",
+ ),
+ path("", include("hc.api.urls")),
+ path("", include("hc.front.urls")),
+ path("", include("hc.payments.urls")),
]