diff --git a/config.py b/config.py index ca0b3cd..353a70d 100644 --- a/config.py +++ b/config.py @@ -6,7 +6,7 @@ Configuration overrides for settings.py import os import sys from django.urls import reverse_lazy -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.contrib.messages import constants as message_constants from ivatar.settings import BASE_DIR diff --git a/ivatar/ivataraccount/forms.py b/ivatar/ivataraccount/forms.py index 2f98dfe..36b302e 100644 --- a/ivatar/ivataraccount/forms.py +++ b/ivatar/ivataraccount/forms.py @@ -1,112 +1,117 @@ -''' +# -*- coding: utf-8 -*- +""" Classes for our ivatar.ivataraccount.forms -''' +""" from urllib.parse import urlsplit, urlunsplit from django import forms -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from ipware import get_client_ip from ivatar import settings from ivatar.settings import MIN_LENGTH_EMAIL, MAX_LENGTH_EMAIL from ivatar.settings import MIN_LENGTH_URL, MAX_LENGTH_URL -from . models import UnconfirmedEmail, ConfirmedEmail, Photo -from . models import UnconfirmedOpenId, ConfirmedOpenId -from . models import UserPreference +from .models import UnconfirmedEmail, ConfirmedEmail, Photo +from .models import UnconfirmedOpenId, ConfirmedOpenId +from .models import UserPreference MAX_NUM_UNCONFIRMED_EMAILS_DEFAULT = 5 class AddEmailForm(forms.Form): - ''' + """ Form to handle adding email addresses - ''' + """ + email = forms.EmailField( - label=_('Email'), + label=_("Email"), min_length=MIN_LENGTH_EMAIL, max_length=MAX_LENGTH_EMAIL, ) def clean_email(self): - ''' + """ Enforce lowercase email - ''' + """ # TODO: Domain restriction as in libravatar? - return self.cleaned_data['email'].lower() + return self.cleaned_data["email"].lower() def save(self, request): - ''' + """ Save the model, ensuring some safety - ''' + """ user = request.user # Enforce the maximum number of unconfirmed emails a user can have num_unconfirmed = user.unconfirmedemail_set.count() max_num_unconfirmed_emails = getattr( - settings, - 'MAX_NUM_UNCONFIRMED_EMAILS', - MAX_NUM_UNCONFIRMED_EMAILS_DEFAULT) + settings, "MAX_NUM_UNCONFIRMED_EMAILS", MAX_NUM_UNCONFIRMED_EMAILS_DEFAULT + ) if num_unconfirmed >= max_num_unconfirmed_emails: - self.add_error(None, _('Too many unconfirmed mail addresses!')) + self.add_error(None, _("Too many unconfirmed mail addresses!")) return False # Check whether or not a confirmation email has been # sent by this user already if UnconfirmedEmail.objects.filter( # pylint: disable=no-member - user=user, email=self.cleaned_data['email']).exists(): - self.add_error( - 'email', - _('Address already added, currently unconfirmed')) + user=user, email=self.cleaned_data["email"] + ).exists(): + self.add_error("email", _("Address already added, currently unconfirmed")) return False # Check whether or not the email is already confirmed (by someone) - check_mail = ConfirmedEmail.objects.filter( - email=self.cleaned_data['email']) + check_mail = ConfirmedEmail.objects.filter(email=self.cleaned_data["email"]) if check_mail.exists(): - msg = _('Address already confirmed (by someone else)') + msg = _("Address already confirmed (by someone else)") if check_mail.first().user == request.user: - msg = _('Address already confirmed (by you)') - self.add_error('email', msg) + msg = _("Address already confirmed (by you)") + self.add_error("email", msg) return False unconfirmed = UnconfirmedEmail() - unconfirmed.email = self.cleaned_data['email'] + unconfirmed.email = self.cleaned_data["email"] unconfirmed.user = user unconfirmed.save() - unconfirmed.send_confirmation_mail(url=request.build_absolute_uri('/')[:-1]) + unconfirmed.send_confirmation_mail(url=request.build_absolute_uri("/")[:-1]) return True class UploadPhotoForm(forms.Form): - ''' + """ Form handling photo upload - ''' + """ + photo = forms.FileField( - label=_('Photo'), - error_messages={'required': _('You must choose an image to upload.')}) + label=_("Photo"), + error_messages={"required": _("You must choose an image to upload.")}, + ) not_porn = forms.BooleanField( - label=_('suitable for all ages (i.e. no offensive content)'), + label=_("suitable for all ages (i.e. no offensive content)"), required=True, error_messages={ - 'required': - _('We only host "G-rated" images and so this field must be checked.') - }) + "required": _( + 'We only host "G-rated" images and so this field must be checked.' + ) + }, + ) can_distribute = forms.BooleanField( - label=_('can be freely copied'), + label=_("can be freely copied"), required=True, error_messages={ - 'required': - _('This field must be checked since we need to be able to distribute photos to third parties.') - }) + "required": _( + "This field must be checked since we need to be able to distribute photos to third parties." + ) + }, + ) @staticmethod def save(request, data): - ''' + """ Save the model and assign it to the current user - ''' + """ # Link this file to the user's profile photo = Photo() photo.user = request.user @@ -119,47 +124,48 @@ class UploadPhotoForm(forms.Form): class AddOpenIDForm(forms.Form): - ''' + """ Form to handle adding OpenID - ''' + """ + openid = forms.URLField( - label=_('OpenID'), + label=_("OpenID"), min_length=MIN_LENGTH_URL, max_length=MAX_LENGTH_URL, - initial='http://' + initial="http://", ) def clean_openid(self): - ''' + """ Enforce restrictions - ''' + """ # Lowercase hostname port of the URL - url = urlsplit(self.cleaned_data['openid']) + url = urlsplit(self.cleaned_data["openid"]) data = urlunsplit( - (url.scheme.lower(), url.netloc.lower(), url.path, - url.query, url.fragment)) + (url.scheme.lower(), url.netloc.lower(), url.path, url.query, url.fragment) + ) # TODO: Domain restriction as in libravatar? return data def save(self, user): - ''' + """ Save the model, ensuring some safety - ''' + """ if ConfirmedOpenId.objects.filter( # pylint: disable=no-member - openid=self.cleaned_data['openid']).exists(): - self.add_error('openid', _('OpenID already added and confirmed!')) + openid=self.cleaned_data["openid"] + ).exists(): + self.add_error("openid", _("OpenID already added and confirmed!")) return False if UnconfirmedOpenId.objects.filter( # pylint: disable=no-member - openid=self.cleaned_data['openid']).exists(): - self.add_error( - 'openid', - _('OpenID already added, but not confirmed yet!')) + openid=self.cleaned_data["openid"] + ).exists(): + self.add_error("openid", _("OpenID already added, but not confirmed yet!")) return False unconfirmed = UnconfirmedOpenId() - unconfirmed.openid = self.cleaned_data['openid'] + unconfirmed.openid = self.cleaned_data["openid"] unconfirmed.user = user unconfirmed.save() @@ -167,40 +173,50 @@ class AddOpenIDForm(forms.Form): class UpdatePreferenceForm(forms.ModelForm): - ''' + """ Form for updating user preferences - ''' + """ class Meta: # pylint: disable=too-few-public-methods - ''' + """ Meta class for UpdatePreferenceForm - ''' + """ + model = UserPreference - fields = ['theme'] + fields = ["theme"] class UploadLibravatarExportForm(forms.Form): - ''' + """ Form handling libravatar user export upload - ''' + """ + export_file = forms.FileField( - label=_('Export file'), - error_messages={'required': _('You must choose an export file to upload.')}) + label=_("Export file"), + error_messages={"required": _("You must choose an export file to upload.")}, + ) not_porn = forms.BooleanField( - label=_('suitable for all ages (i.e. no offensive content)'), + label=_("suitable for all ages (i.e. no offensive content)"), required=True, error_messages={ - 'required': - _('We only host "G-rated" images and so this field must be checked.') - }) + "required": _( + 'We only host "G-rated" images and so this field must be checked.' + ) + }, + ) can_distribute = forms.BooleanField( - label=_('can be freely copied'), + label=_("can be freely copied"), required=True, error_messages={ - 'required': - _('This field must be checked since we need to be able to\ - distribute photos to third parties.') - }) + "required": _( + "This field must be checked since we need to be able to\ + distribute photos to third parties." + ) + }, + ) + class DeleteAccountForm(forms.Form): - password = forms.CharField(label=_('Password'), required=False, widget=forms.PasswordInput()) + password = forms.CharField( + label=_("Password"), required=False, widget=forms.PasswordInput() + ) diff --git a/ivatar/ivataraccount/models.py b/ivatar/ivataraccount/models.py index 478619f..689fd8a 100644 --- a/ivatar/ivataraccount/models.py +++ b/ivatar/ivataraccount/models.py @@ -19,7 +19,7 @@ from django.db import models from django.utils import timezone from django.http import HttpResponseRedirect from django.urls import reverse_lazy, reverse -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ObjectDoesNotExist from django.core.mail import send_mail from django.template.loader import render_to_string diff --git a/ivatar/ivataraccount/views.py b/ivatar/ivataraccount/views.py index 1758730..2bb7711 100644 --- a/ivatar/ivataraccount/views.py +++ b/ivatar/ivataraccount/views.py @@ -27,7 +27,7 @@ from django.contrib.auth.views import LoginView from django.contrib.auth.views import ( PasswordResetView as PasswordResetViewOriginal, ) -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.http import HttpResponseRedirect, HttpResponse from django.urls import reverse_lazy, reverse from django.shortcuts import render diff --git a/ivatar/tools/forms.py b/ivatar/tools/forms.py index 3e895a5..fbe1a2c 100644 --- a/ivatar/tools/forms.py +++ b/ivatar/tools/forms.py @@ -1,8 +1,9 @@ -''' +# -*- coding: utf-8 -*- +""" Classes for our ivatar.tools.forms -''' +""" from django import forms -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError from django.forms.utils import ErrorList @@ -12,45 +13,40 @@ from ivatar.settings import MIN_LENGTH_EMAIL, MAX_LENGTH_EMAIL class CheckDomainForm(forms.Form): - ''' + """ Form handling domain check - ''' + """ + domain = forms.CharField( - label=_('Domain'), + label=_("Domain"), required=True, - error_messages={ - 'required': - _('Cannot check without a domain name.') - } + error_messages={"required": _("Cannot check without a domain name.")}, ) class CheckForm(forms.Form): - ''' + """ Form handling check - ''' + """ + mail = forms.EmailField( - label=_('E-Mail'), + label=_("E-Mail"), required=False, min_length=MIN_LENGTH_EMAIL, max_length=MAX_LENGTH_EMAIL, - error_messages={ - 'required': - _('Cannot check without a domain name.') - }) + error_messages={"required": _("Cannot check without a domain name.")}, + ) openid = forms.CharField( - label=_('OpenID'), + label=_("OpenID"), required=False, min_length=MIN_LENGTH_URL, max_length=MAX_LENGTH_URL, - error_messages={ - 'required': - _('Cannot check without an openid name.') - }) + error_messages={"required": _("Cannot check without an openid name.")}, + ) size = forms.IntegerField( - label=_('Size'), + label=_("Size"), initial=80, min_value=5, max_value=AVATAR_MAX_SIZE, @@ -58,24 +54,24 @@ class CheckForm(forms.Form): ) default_opt = forms.ChoiceField( - label=_('Default'), + label=_("Default"), required=False, widget=forms.RadioSelect, - choices = [ - ('retro', _('Retro style (similar to GitHub)')), - ('robohash', _('Roboter style')), - ('pagan', _('Retro adventure character')), - ('wavatar', _('Wavatar style')), - ('monsterid', _('Monster style')), - ('identicon', _('Identicon style')), - ('mm', _('Mystery man')), - ('mmng', _('Mystery man NextGen')), - ('none', _('None')), + choices=[ + ("retro", _("Retro style (similar to GitHub)")), + ("robohash", _("Roboter style")), + ("pagan", _("Retro adventure character")), + ("wavatar", _("Wavatar style")), + ("monsterid", _("Monster style")), + ("identicon", _("Identicon style")), + ("mm", _("Mystery man")), + ("mmng", _("Mystery man NextGen")), + ("none", _("None")), ], ) default_url = forms.URLField( - label=_('Default URL'), + label=_("Default URL"), min_length=1, max_length=MAX_LENGTH_URL, required=False, @@ -83,28 +79,28 @@ class CheckForm(forms.Form): def clean(self): self.cleaned_data = super().clean() - mail = self.cleaned_data.get('mail') - openid = self.cleaned_data.get('openid') - default_url = self.cleaned_data.get('default_url') - default_opt = self.cleaned_data.get('default_opt') - if default_url and default_opt and default_opt != 'none': - if not 'default_url' in self._errors: - self._errors['default_url'] = ErrorList() - if not 'default_opt' in self._errors: - self._errors['default_opt'] = ErrorList() + mail = self.cleaned_data.get("mail") + openid = self.cleaned_data.get("openid") + default_url = self.cleaned_data.get("default_url") + default_opt = self.cleaned_data.get("default_opt") + if default_url and default_opt and default_opt != "none": + if "default_url" not in self._errors: + self._errors["default_url"] = ErrorList() + if "default_opt" not in self._errors: + self._errors["default_opt"] = ErrorList() - errstring = _('Only default URL OR default keyword may be specified') - self._errors['default_url'].append(errstring) - self._errors['default_opt'].append(errstring) + errstring = _("Only default URL OR default keyword may be specified") + self._errors["default_url"].append(errstring) + self._errors["default_opt"].append(errstring) if not mail and not openid: - raise ValidationError(_('Either OpenID or mail must be specified')) + raise ValidationError(_("Either OpenID or mail must be specified")) return self.cleaned_data def clean_openid(self): - data = self.cleaned_data['openid'] + data = self.cleaned_data["openid"] return data.lower() def clean_mail(self): - data = self.cleaned_data['mail'] + data = self.cleaned_data["mail"] print(data) return data.lower() diff --git a/ivatar/views.py b/ivatar/views.py index d1dcb4d..2ec933c 100644 --- a/ivatar/views.py +++ b/ivatar/views.py @@ -13,7 +13,7 @@ from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponseNotFound, JsonResponse from django.core.exceptions import ObjectDoesNotExist from django.core.cache import cache, caches -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.urls import reverse_lazy from django.db.models import Q from django.contrib.auth.models import User diff --git a/requirements.txt b/requirements.txt index e674bb1..f385a08 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ autopep8 bcrypt defusedxml -Django +Django < 4.0 django-anymail[mailgun] django-auth-ldap django-bootstrap4