mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
New fixes
This commit is contained in:
@@ -178,7 +178,7 @@ class DomainAliasSerializer(serializers.ModelSerializer):
|
||||
object_type="domain_aliases",
|
||||
)
|
||||
except lib_exceptions.ModoboaException as inst:
|
||||
raise serializers.ValidationError({"domain": force_str(inst)})
|
||||
raise serializers.ValidationError({"domain": force_str(inst)}) from None
|
||||
domain_alias.save(creator=creator)
|
||||
return domain_alias
|
||||
|
||||
@@ -311,7 +311,7 @@ class AccountPasswordSerializer(serializers.ModelSerializer):
|
||||
try:
|
||||
password_validation.validate_password(value, self.instance)
|
||||
except ValidationError as exc:
|
||||
raise serializers.ValidationError(exc.messages[0])
|
||||
raise serializers.ValidationError(exc.messages[0]) from None
|
||||
return value
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
@@ -363,7 +363,7 @@ class WritableAccountSerializer(AccountSerializer):
|
||||
try:
|
||||
validators.UTF8EmailValidator()(username)
|
||||
except ValidationError as err:
|
||||
raise ValidationError({"username": err.message})
|
||||
raise ValidationError({"username": err.message}) from None
|
||||
mailbox = data.get("mailbox")
|
||||
if mailbox is None:
|
||||
if not self.instance:
|
||||
@@ -396,7 +396,9 @@ class WritableAccountSerializer(AccountSerializer):
|
||||
object_type="mailboxes",
|
||||
)
|
||||
except lib_exceptions.ModoboaException as inst:
|
||||
raise serializers.ValidationError({"mailbox": force_str(inst)})
|
||||
raise serializers.ValidationError(
|
||||
{"mailbox": force_str(inst)}
|
||||
) from None
|
||||
condition = not data.get("random_password") and (
|
||||
data.get("password") or not self.partial
|
||||
)
|
||||
@@ -408,7 +410,9 @@ class WritableAccountSerializer(AccountSerializer):
|
||||
data["password"], self.instance
|
||||
)
|
||||
except ValidationError as exc:
|
||||
raise serializers.ValidationError({"password": exc.messages[0]})
|
||||
raise serializers.ValidationError(
|
||||
{"password": exc.messages[0]}
|
||||
) from None
|
||||
elif not self.instance:
|
||||
raise serializers.ValidationError(
|
||||
{"password": _("This field is required.")}
|
||||
@@ -523,9 +527,9 @@ class AliasSerializer(serializers.ModelSerializer):
|
||||
value, self.context["request"].user, instance=self.instance
|
||||
)
|
||||
except ValidationError as err:
|
||||
raise serializers.ValidationError(err)
|
||||
raise serializers.ValidationError(err) from None
|
||||
except AliasExists:
|
||||
raise serializers.ValidationError(_("This alias already exists"))
|
||||
raise serializers.ValidationError(_("This alias already exists")) from None
|
||||
return value.lower()
|
||||
|
||||
def create(self, validated_data):
|
||||
|
||||
@@ -135,7 +135,7 @@ class AccountViewSet(
|
||||
try:
|
||||
user = core_models.User.objects.get(pk=pk)
|
||||
except core_models.User.DoesNotExist:
|
||||
raise http.Http404
|
||||
raise http.Http404 from None
|
||||
serializer = self.get_serializer(user, data=request.data)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
|
||||
@@ -94,7 +94,7 @@ class DomainSerializer(v1_serializers.DomainSerializer):
|
||||
return domain
|
||||
|
||||
# 1. Create a domain administrator
|
||||
username = "%s@%s" % (domain_admin["username"], domain.name)
|
||||
username = "{}@{}".format(domain_admin["username"], domain.name)
|
||||
try:
|
||||
da = core_models.User.objects.get(username=username)
|
||||
except core_models.User.DoesNotExist:
|
||||
@@ -244,7 +244,7 @@ class AdminGlobalParametersSerializer(serializers.Serializer):
|
||||
except ValueError:
|
||||
raise serializers.ValidationError(
|
||||
_("This field only allows valid IP addresses (or networks)")
|
||||
)
|
||||
) from None
|
||||
return value
|
||||
|
||||
def validate_auto_create_domain_and_mailbox(self, value):
|
||||
@@ -479,7 +479,7 @@ class WritableAccountSerializer(v1_serializers.WritableAccountSerializer):
|
||||
try:
|
||||
validators.UTF8EmailValidator()(username)
|
||||
except ValidationError as err:
|
||||
raise ValidationError({"username": err.message})
|
||||
raise ValidationError({"username": err.message}) from None
|
||||
mailbox = data.get("mailbox")
|
||||
if mailbox is None:
|
||||
if not self.instance:
|
||||
@@ -501,7 +501,7 @@ class WritableAccountSerializer(v1_serializers.WritableAccountSerializer):
|
||||
object_type="mailboxes",
|
||||
)
|
||||
except lib_exceptions.ModoboaException as inst:
|
||||
raise serializers.ValidationError({"mailbox": str(inst)})
|
||||
raise serializers.ValidationError({"mailbox": str(inst)}) from None
|
||||
if len(self.address) > 64:
|
||||
raise serializers.ValidationError(
|
||||
{
|
||||
@@ -518,7 +518,9 @@ class WritableAccountSerializer(v1_serializers.WritableAccountSerializer):
|
||||
data["password"], self.instance
|
||||
)
|
||||
except ValidationError as exc:
|
||||
raise serializers.ValidationError({"password": exc.messages[0]})
|
||||
raise serializers.ValidationError(
|
||||
{"password": exc.messages[0]}
|
||||
) from None
|
||||
elif not self.instance:
|
||||
raise serializers.ValidationError(
|
||||
{"password": _("This field is required.")}
|
||||
|
||||
@@ -212,7 +212,7 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
dpath = fpath
|
||||
if dpath:
|
||||
try:
|
||||
code, version = exec_cmd("%s --version" % dpath)
|
||||
code, version = exec_cmd(f"{dpath} --version")
|
||||
except OSError:
|
||||
hide_fields = True
|
||||
else:
|
||||
@@ -259,12 +259,12 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
except ValueError:
|
||||
raise forms.ValidationError(
|
||||
gettext_lazy("This field only allows valid IP addresses (or networks)")
|
||||
)
|
||||
) from None
|
||||
return value
|
||||
|
||||
def clean(self):
|
||||
"""Check MX options."""
|
||||
cleaned_data = super(AdminParametersForm, self).clean()
|
||||
cleaned_data = super().clean()
|
||||
condition = (
|
||||
cleaned_data.get("enable_mx_checks")
|
||||
and cleaned_data.get("domains_must_have_authorized_mx")
|
||||
|
||||
@@ -71,7 +71,7 @@ class AccountFormGeneral(forms.ModelForm):
|
||||
labels = {"is_active": gettext_lazy("Enabled")}
|
||||
|
||||
def __init__(self, user, *args, **kwargs):
|
||||
super(AccountFormGeneral, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields = OrderedDict(
|
||||
(key, self.fields[key])
|
||||
for key in [
|
||||
@@ -163,7 +163,7 @@ class AccountFormGeneral(forms.ModelForm):
|
||||
|
||||
def clean(self):
|
||||
"""Check master user mode."""
|
||||
super(AccountFormGeneral, self).clean()
|
||||
super().clean()
|
||||
if self.errors:
|
||||
return self.cleaned_data
|
||||
condition = (
|
||||
@@ -200,7 +200,7 @@ class AccountFormGeneral(forms.ModelForm):
|
||||
return self.cleaned_data
|
||||
|
||||
def save(self, commit=True):
|
||||
account = super(AccountFormGeneral, self).save(commit=False)
|
||||
account = super().save(commit=False)
|
||||
if self.user == account and not self.cleaned_data["is_active"]:
|
||||
raise lib_exceptions.PermDeniedException(
|
||||
_("You can't disable your own account")
|
||||
@@ -355,7 +355,7 @@ class AccountFormMail(forms.Form, DynamicForm):
|
||||
|
||||
Check if quota is >= 0 only when the domain value is not used.
|
||||
"""
|
||||
cleaned_data = super(AccountFormMail, self).clean()
|
||||
cleaned_data = super().clean()
|
||||
use_default_domain_quota = cleaned_data["quota_act"]
|
||||
condition = (
|
||||
not use_default_domain_quota
|
||||
@@ -510,13 +510,13 @@ class AccountPermissionsForm(forms.Form, DynamicForm):
|
||||
self.account = kwargs["instance"]
|
||||
del kwargs["instance"]
|
||||
|
||||
super(AccountPermissionsForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if not hasattr(self, "account") or self.account is None:
|
||||
return
|
||||
qset = models.Domain.objects.get_for_admin(self.account)
|
||||
for pos, dom in enumerate(qset):
|
||||
name = "domains_%d" % (pos + 1)
|
||||
name = f"domains_{pos + 1}"
|
||||
self._create_field(lib_fields.DomainNameField, name, dom.name)
|
||||
if len(args) and isinstance(args[0], QueryDict):
|
||||
self._load_from_qdict(args[0], "domains", lib_fields.DomainNameField)
|
||||
@@ -580,7 +580,7 @@ class AccountForm(TabForms):
|
||||
cbargs["account"] = kwargs["instances"]["general"]
|
||||
results = signals.extra_account_forms.send(sender=self.__class__, **cbargs)
|
||||
self.forms += reduce(lambda a, b: a + b, [result[1] for result in results])
|
||||
super(AccountForm, self).__init__(request, *args, **kwargs)
|
||||
super().__init__(request, *args, **kwargs)
|
||||
|
||||
def extra_context(self, context):
|
||||
account = self.instances["general"]
|
||||
@@ -604,8 +604,8 @@ class AccountForm(TabForms):
|
||||
if form["id"] == "general":
|
||||
return True
|
||||
|
||||
if hasattr(self, "check_%s" % form["id"]):
|
||||
if not getattr(self, "check_%s" % form["id"])(self.account):
|
||||
if hasattr(self, "check_{}".format(form["id"])):
|
||||
if not getattr(self, "check_{}".format(form["id"]))(self.account):
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -620,9 +620,9 @@ class AccountForm(TabForms):
|
||||
def is_valid(self):
|
||||
"""Two steps validation."""
|
||||
self.instances["general"].oldgroup = self.instances["general"].role
|
||||
if super(AccountForm, self).is_valid(mandatory_only=True):
|
||||
if super().is_valid(mandatory_only=True):
|
||||
self.account = self.forms[0]["instance"].save()
|
||||
return super(AccountForm, self).is_valid(optional_only=True)
|
||||
return super().is_valid(optional_only=True)
|
||||
return False
|
||||
|
||||
def save(self):
|
||||
@@ -646,7 +646,7 @@ class AccountWizard(WizardForm):
|
||||
"""Account creation wizard."""
|
||||
|
||||
def __init__(self, request):
|
||||
super(AccountWizard, self).__init__(request)
|
||||
super().__init__(request)
|
||||
self.add_step(
|
||||
WizardStep(
|
||||
"general", AccountFormGeneral, _("General"), new_args=[request.user]
|
||||
|
||||
@@ -49,7 +49,7 @@ class AliasForm(forms.ModelForm, DynamicForm):
|
||||
|
||||
def __init__(self, user, *args, **kwargs):
|
||||
self.user = user
|
||||
super(AliasForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields = OrderedDict(
|
||||
(key, self.fields[key])
|
||||
for key in [
|
||||
@@ -80,7 +80,7 @@ class AliasForm(forms.ModelForm, DynamicForm):
|
||||
self.fields["enabled"].widget.attrs["disabled"] = "disabled"
|
||||
cpt = 1
|
||||
for rcpt in alias.aliasrecipient_set.filter(alias__internal=False):
|
||||
name = "recipients_%d" % cpt
|
||||
name = f"recipients_{cpt}"
|
||||
self._create_field(forms.EmailField, name, rcpt.address, 2)
|
||||
cpt += 1
|
||||
|
||||
@@ -92,7 +92,7 @@ class AliasForm(forms.ModelForm, DynamicForm):
|
||||
try:
|
||||
domain = Domain.objects.get(name=domname)
|
||||
except Domain.DoesNotExist:
|
||||
raise forms.ValidationError(_("Domain does not exist"))
|
||||
raise forms.ValidationError(_("Domain does not exist")) from None
|
||||
if not self.user.can_access(domain):
|
||||
raise forms.ValidationError(_("You don't have access to this domain"))
|
||||
if not self.instance.pk:
|
||||
@@ -101,12 +101,12 @@ class AliasForm(forms.ModelForm, DynamicForm):
|
||||
sender=self.__class__, context=domain, object_type="mailbox_aliases"
|
||||
)
|
||||
except lib_exceptions.ModoboaException as inst:
|
||||
raise forms.ValidationError(inst)
|
||||
raise forms.ValidationError(inst) from None
|
||||
return self.cleaned_data["address"].lower()
|
||||
|
||||
def clean(self):
|
||||
"""Check it there is at least one recipient."""
|
||||
super(AliasForm, self).clean()
|
||||
super().clean()
|
||||
random_address = self.cleaned_data.get("random_address")
|
||||
if not random_address:
|
||||
if not self.cleaned_data.get("address"):
|
||||
@@ -121,7 +121,7 @@ class AliasForm(forms.ModelForm, DynamicForm):
|
||||
|
||||
def save(self, commit=True):
|
||||
"""Custom save method."""
|
||||
alias = super(AliasForm, self).save(commit=False)
|
||||
alias = super().save(commit=False)
|
||||
if self.cleaned_data.get("random_address"):
|
||||
alias.address = f"{Alias.generate_random_address()}@{alias.domain}"
|
||||
else:
|
||||
|
||||
@@ -13,7 +13,7 @@ class ExportDataForm(forms.Form):
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ExportDataForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["sepchar"].widget.attrs = {"class": "col-md-1 form-control"}
|
||||
|
||||
def clean_sepchar(self):
|
||||
|
||||
@@ -21,7 +21,7 @@ class ImportDataForm(forms.Form):
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ImportDataForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["sepchar"].widget.attrs = {"class": "col-md-1 form-control"}
|
||||
|
||||
def clean_sepchar(self):
|
||||
|
||||
@@ -253,7 +253,7 @@ def get_dns_records(name, typ, resolver=None):
|
||||
exc_info=e,
|
||||
)
|
||||
except dns.name.NameTooLong as e:
|
||||
logger.error(_("DNS name is too long: %s" % name), exc_info=e)
|
||||
logger.error(_("DNS name is too long: {}".format(name)), exc_info=e)
|
||||
else:
|
||||
return dns_answers
|
||||
return None
|
||||
@@ -359,7 +359,7 @@ def import_data(user, file_object, options: dict):
|
||||
raise Conflict(
|
||||
_("Object already exists: %s")
|
||||
% options["sepchar"].join(row[:2])
|
||||
)
|
||||
) from None
|
||||
cpt += 1
|
||||
msg = _("%d objects imported successfully") % cpt
|
||||
return True, msg
|
||||
|
||||
@@ -54,7 +54,7 @@ def validate_alias_address(
|
||||
object_type="mailbox_aliases",
|
||||
)
|
||||
except ModoboaException as inst:
|
||||
raise ValidationError(str(inst))
|
||||
raise ValidationError(str(inst)) from None
|
||||
return local_part, domain
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ class Alias(AdminObject):
|
||||
return "---"
|
||||
rcpts = self.recipients
|
||||
if rcpts_count > 1:
|
||||
return "%s, ..." % rcpts[0]
|
||||
return f"{rcpts[0]}, ..."
|
||||
return rcpts[0]
|
||||
|
||||
@property
|
||||
@@ -150,7 +150,7 @@ class Alias(AdminObject):
|
||||
def post_create(self, creator):
|
||||
from modoboa.lib.permissions import grant_access_to_object
|
||||
|
||||
super(Alias, self).post_create(creator)
|
||||
super().post_create(creator)
|
||||
if creator.is_superuser:
|
||||
for admin in self.domain.admins:
|
||||
grant_access_to_object(admin, self)
|
||||
@@ -174,7 +174,7 @@ class Alias(AdminObject):
|
||||
address, return_extension=True
|
||||
)
|
||||
if domname is None:
|
||||
raise BadRequest("%s %s" % (_("Invalid address"), address))
|
||||
raise BadRequest("{} {}".format(_("Invalid address"), address))
|
||||
domain = Domain.objects.filter(name=domname).first()
|
||||
kwargs = {"address": address, "alias": self}
|
||||
if (domain is not None) and (
|
||||
@@ -189,7 +189,7 @@ class Alias(AdminObject):
|
||||
rcpt = Mailbox.objects.filter(domain=domain, address=local_part).first()
|
||||
if rcpt is None:
|
||||
rcpt = Alias.objects.filter(
|
||||
address="%s@%s" % (local_part, domname)
|
||||
address=f"{local_part}@{domname}"
|
||||
).first()
|
||||
if rcpt is None:
|
||||
raise NotFound(
|
||||
|
||||
@@ -62,10 +62,10 @@ class AdminObject(models.Model):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
creator = kwargs.pop("creator", None)
|
||||
super(AdminObject, self).save(*args, **kwargs)
|
||||
super().save(*args, **kwargs)
|
||||
if creator is not None:
|
||||
self.post_create(creator)
|
||||
|
||||
def delete(self):
|
||||
ungrant_access_to_object(self)
|
||||
super(AdminObject, self).delete()
|
||||
super().delete()
|
||||
|
||||
@@ -271,17 +271,17 @@ class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
@property
|
||||
def bind_format_dkim_public_key(self):
|
||||
"""Return DKIM public key using Bind format."""
|
||||
record = "v=DKIM1;k=rsa;p=%s" % self.dkim_public_key
|
||||
record = f"v=DKIM1;k=rsa;p={self.dkim_public_key}"
|
||||
# TXT records longer than 255 characters need split into chunks
|
||||
# split record into 74 character chunks (+2 for indent, +2 for quotes(")
|
||||
# == 78 characters) to make more readable in text editors.
|
||||
split_record = []
|
||||
while record:
|
||||
if len(record) > 74:
|
||||
split_record.append(' "%s"' % record[:74])
|
||||
split_record.append(f' "{record[:74]}"')
|
||||
record = record[74:]
|
||||
else:
|
||||
split_record.append(' "%s"' % record)
|
||||
split_record.append(f' "{record}"')
|
||||
break
|
||||
record = "\n".join(split_record)
|
||||
return f"{self.dkim_key_selector}._domainkey.{self.name}. IN TXT (\n{record})"
|
||||
@@ -343,7 +343,7 @@ class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
if param_tools.get_global_parameter("auto_account_removal"):
|
||||
User.objects.filter(mailbox__domain=self).delete()
|
||||
elif self.mailbox_set.count():
|
||||
Quota.objects.filter(username__contains="@%s" % self.name).delete()
|
||||
Quota.objects.filter(username__contains=f"@{self.name}").delete()
|
||||
ungrant_access_to_objects(self.mailbox_set.all())
|
||||
super().delete()
|
||||
|
||||
@@ -378,7 +378,9 @@ class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
try:
|
||||
self.quota = int(row[2].strip())
|
||||
except ValueError:
|
||||
raise BadRequest(_("{}: invalid quota value for domain").format(self.name))
|
||||
raise BadRequest(
|
||||
_("{}: invalid quota value for domain").format(self.name)
|
||||
) from None
|
||||
try:
|
||||
self.default_mailbox_quota = int(row[3].strip())
|
||||
except ValueError:
|
||||
@@ -386,7 +388,7 @@ class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
_("{}: invalid default mailbox quota value for domain").format(
|
||||
self.name
|
||||
)
|
||||
)
|
||||
) from None
|
||||
if self.quota != 0 and self.default_mailbox_quota > self.quota:
|
||||
raise BadRequest(
|
||||
_(
|
||||
|
||||
@@ -76,7 +76,7 @@ class DomainAlias(AdminObject):
|
||||
try:
|
||||
self.target = Domain.objects.get(name=domname)
|
||||
except Domain.DoesNotExist:
|
||||
raise BadRequest(_("Unknown domain %s") % domname)
|
||||
raise BadRequest(_("Unknown domain %s") % domname) from None
|
||||
core_signals.can_create_object.send(
|
||||
sender="import", context=self.target, object_type="domain_aliases"
|
||||
)
|
||||
|
||||
@@ -114,7 +114,7 @@ class Mailbox(mixins.MessageLimitMixin, AdminObject):
|
||||
return smart_str(self.full_address)
|
||||
|
||||
def __full_address(self, localpart):
|
||||
return "%s@%s" % (localpart, self.domain.name)
|
||||
return f"{localpart}@{self.domain.name}"
|
||||
|
||||
@property
|
||||
def full_address(self):
|
||||
@@ -147,7 +147,7 @@ class Mailbox(mixins.MessageLimitMixin, AdminObject):
|
||||
if not admin_params.get("handle_mailboxes"):
|
||||
return None
|
||||
if self.__mail_home is None:
|
||||
code, output = doveadm_cmd("user -f home %s" % self.full_address)
|
||||
code, output = doveadm_cmd(f"user -f home {self.full_address}")
|
||||
if code:
|
||||
raise lib_exceptions.InternalError(
|
||||
_("Failed to retrieve mailbox location (%s)") % output
|
||||
@@ -384,5 +384,5 @@ class MailboxOperation(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
if self.type == "rename":
|
||||
return "Rename %s -> %s" % (self.argument, self.mailbox.mail_home)
|
||||
return "Delete %s" % self.argument
|
||||
return f"Rename {self.argument} -> {self.mailbox.mail_home}"
|
||||
return f"Delete {self.argument}"
|
||||
|
||||
@@ -151,7 +151,7 @@ def domain_actions(user, domain):
|
||||
actions = [
|
||||
{
|
||||
"name": "listidentities",
|
||||
"url": "{0}#list/?searchquery=@{1}".format(
|
||||
"url": "{}#list/?searchquery=@{}".format(
|
||||
reverse("admin:identity_list"), domain.name
|
||||
),
|
||||
"title": _("View the domain's identities"),
|
||||
@@ -268,7 +268,7 @@ def domain_aliases(domain):
|
||||
return "---"
|
||||
res = ""
|
||||
for alias in domain.aliases.all():
|
||||
res += "%s<br/>" % alias.name
|
||||
res += f"{alias.name}<br/>"
|
||||
return mark_safe(res)
|
||||
|
||||
|
||||
@@ -286,7 +286,7 @@ def identity_modify_link(identity, active_tab="default"):
|
||||
linkdef = {"label": identity.identity, "modal": True}
|
||||
if identity.__class__.__name__ == "User":
|
||||
linkdef["url"] = reverse("admin:account_change", args=[identity.id])
|
||||
linkdef["url"] += "?active_tab=%s" % active_tab
|
||||
linkdef["url"] += f"?active_tab={active_tab}"
|
||||
linkdef["modalcb"] = "admin.editaccount_cb"
|
||||
else:
|
||||
linkdef["url"] = reverse("admin:alias_change", args=[identity.id])
|
||||
@@ -299,7 +299,7 @@ def domadmin_actions(daid, domid):
|
||||
actions = [
|
||||
{
|
||||
"name": "removeperm",
|
||||
"url": "{0}?domid={1}&daid={2}".format(
|
||||
"url": "{}?domid={}&daid={}".format(
|
||||
reverse("admin:permission_remove"), domid, daid
|
||||
),
|
||||
"img": "fa fa-trash",
|
||||
|
||||
@@ -17,7 +17,7 @@ class AuthenticationTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(AuthenticationTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.mb = factories.MailboxFactory(
|
||||
domain__name="test.com",
|
||||
address="user",
|
||||
@@ -42,7 +42,7 @@ class AccountTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(AccountTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def test_crud(self):
|
||||
@@ -612,7 +612,7 @@ class PermissionsTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(PermissionsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
parameters = {}
|
||||
for name, _definition in limits_utils.get_user_limit_templates():
|
||||
parameters[f"deflt_user_{name}_limit"] = 2
|
||||
@@ -625,7 +625,7 @@ class PermissionsTestCase(ModoTestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Initiate test context."""
|
||||
super(PermissionsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.values = {
|
||||
"username": self.user.username,
|
||||
"role": "DomainAdmins",
|
||||
|
||||
@@ -13,7 +13,7 @@ class AliasTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(AliasTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def test_alias(self):
|
||||
@@ -173,7 +173,7 @@ class AliasTestCase(ModoTestCase):
|
||||
self.ajax_post(reverse("admin:alias_change", args=[fwd.id]), values)
|
||||
self.assertEqual(fwd.recipients_count, 1)
|
||||
|
||||
self.ajax_delete(reverse("admin:alias_delete") + "?selection=%d" % fwd.id, {})
|
||||
self.ajax_delete(reverse("admin:alias_delete") + f"?selection={fwd.id}", {})
|
||||
self.assertRaises(
|
||||
Alias.DoesNotExist, Alias.objects.get, address="forward2@test.com"
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ class DomainTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(DomainTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def test_create(self):
|
||||
@@ -431,7 +431,7 @@ class DKIMTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(DKIMTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def setUp(self):
|
||||
|
||||
@@ -10,7 +10,7 @@ class DomainAliasTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(DomainAliasTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
cls.dom = Domain.objects.get(name="test.com")
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class ExportTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(ExportTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def __export_domains(self, domfilter=""):
|
||||
@@ -31,7 +31,7 @@ class ExportTestCase(ModoTestCase):
|
||||
def __export_identities(self, idtfilter="", grpfilter=""):
|
||||
self.client.get(
|
||||
reverse("admin:_identity_list")
|
||||
+ "?grpfilter=%s&idtfilter=%s" % (grpfilter, idtfilter)
|
||||
+ f"?grpfilter={grpfilter}&idtfilter={idtfilter}"
|
||||
)
|
||||
return self.client.post(
|
||||
reverse("admin:identity_export"), {"filename": "test.csv"}
|
||||
|
||||
@@ -20,12 +20,12 @@ class MailboxOperationTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(MailboxOperationTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def setUp(self):
|
||||
"""Initiate test env."""
|
||||
super(MailboxOperationTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.workdir = tempfile.mkdtemp()
|
||||
path = f"{self.workdir}/test.com/admin"
|
||||
os.makedirs(path)
|
||||
|
||||
@@ -23,7 +23,7 @@ class MXTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create some data."""
|
||||
super(MXTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.domain = factories.DomainFactory(name="modoboa.org")
|
||||
# should not exist
|
||||
cls.bad_domain = factories.DomainFactory(name="does-not-exist.example.com")
|
||||
@@ -297,7 +297,7 @@ class DNSChecksTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create some data."""
|
||||
super(DNSChecksTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.domain = factories.DomainFactory(name="dns-checks.com")
|
||||
|
||||
@mock.patch("gevent.socket.gethostbyname")
|
||||
|
||||
@@ -10,7 +10,7 @@ class PasswordSchemesTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(PasswordSchemesTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def _create_account(self):
|
||||
|
||||
@@ -13,7 +13,7 @@ class RepairTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create some data."""
|
||||
super(RepairTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def test_management_command(self):
|
||||
|
||||
@@ -12,7 +12,7 @@ class ForwardTestCase(ModoTestCase):
|
||||
"""User forward test cases."""
|
||||
|
||||
def setUp(self):
|
||||
super(ForwardTestCase, self).setUp()
|
||||
super().setUp()
|
||||
populate_database()
|
||||
|
||||
def test_set_forward(self):
|
||||
|
||||
@@ -27,7 +27,7 @@ def _validate_alias(request, form, successmsg, callback=None):
|
||||
try:
|
||||
alias = form.save()
|
||||
except IntegrityError:
|
||||
raise Conflict(_("Alias with this name already exists"))
|
||||
raise Conflict(_("Alias with this name already exists")) from None
|
||||
if callback:
|
||||
callback(request.user, alias)
|
||||
return render_to_json_response(successmsg)
|
||||
@@ -110,13 +110,13 @@ class AliasDetailView(auth_mixins.PermissionRequiredMixin, generic.DetailView):
|
||||
|
||||
def has_permission(self):
|
||||
"""Check object-level access."""
|
||||
result = super(AliasDetailView, self).has_permission()
|
||||
result = super().has_permission()
|
||||
if not result:
|
||||
return result
|
||||
return self.request.user.can_access(self.get_object())
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add information to context."""
|
||||
context = super(AliasDetailView, self).get_context_data(**kwargs)
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["selection"] = "identities"
|
||||
return context
|
||||
|
||||
@@ -16,15 +16,11 @@ class MXDomainDetailView(auth_mixins.PermissionRequiredMixin, generic.DetailView
|
||||
|
||||
def get_queryset(self):
|
||||
"""Add some prefetching."""
|
||||
return (
|
||||
super(MXDomainDetailView, self)
|
||||
.get_queryset()
|
||||
.prefetch_related("mxrecord_set")
|
||||
)
|
||||
return super().get_queryset().prefetch_related("mxrecord_set")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add extra variables."""
|
||||
context = super(MXDomainDetailView, self).get_context_data(**kwargs)
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({"title": _("MX records of {}").format(self.object.name)})
|
||||
return context
|
||||
|
||||
@@ -38,14 +34,10 @@ class DNSBLDomainDetailView(auth_mixins.PermissionRequiredMixin, generic.DetailV
|
||||
|
||||
def get_queryset(self):
|
||||
"""Add some prefetching."""
|
||||
return (
|
||||
super(DNSBLDomainDetailView, self)
|
||||
.get_queryset()
|
||||
.prefetch_related("dnsblresult_set")
|
||||
)
|
||||
return super().get_queryset().prefetch_related("dnsblresult_set")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add extra variables."""
|
||||
context = super(DNSBLDomainDetailView, self).get_context_data(**kwargs)
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({"title": _("DNSBL summary for {}").format(self.object.name)})
|
||||
return context
|
||||
|
||||
@@ -75,7 +75,7 @@ def list_quotas(request):
|
||||
)
|
||||
mboxes = mboxes.exclude(quota=0)
|
||||
if sort_order in ["address", "quota"]:
|
||||
mboxes = mboxes.order_by("%s%s" % (sort_dir, sort_order))
|
||||
mboxes = mboxes.order_by(f"{sort_dir}{sort_order}")
|
||||
elif sort_order in ("quota_value__bytes", "quota_usage"):
|
||||
db_type = db_type()
|
||||
if db_type == "mysql":
|
||||
@@ -85,9 +85,9 @@ def list_quotas(request):
|
||||
if sort_order == "quota_value__bytes":
|
||||
mboxes = mboxes.extra(
|
||||
select={"quota_value__bytes": "admin_quota.bytes"},
|
||||
where=["admin_quota.username=%s" % where],
|
||||
where=[f"admin_quota.username={where}"],
|
||||
tables=["admin_quota", "admin_domain"],
|
||||
order_by=["%s%s" % (sort_dir, sort_order)],
|
||||
order_by=[f"{sort_dir}{sort_order}"],
|
||||
)
|
||||
else:
|
||||
if db_type == "postgres":
|
||||
@@ -102,9 +102,9 @@ def list_quotas(request):
|
||||
)
|
||||
mboxes = mboxes.extra(
|
||||
select={"quota_usage": select},
|
||||
where=["admin_quota.username=%s" % where],
|
||||
where=[f"admin_quota.username={where}"],
|
||||
tables=["admin_quota", "admin_domain"],
|
||||
order_by=["%s%s" % (sort_dir, sort_order)],
|
||||
order_by=[f"{sort_dir}{sort_order}"],
|
||||
)
|
||||
else:
|
||||
raise BadRequest(_("Invalid request"))
|
||||
@@ -199,7 +199,7 @@ def remove_permission(request):
|
||||
account = User.objects.get(pk=daid)
|
||||
domain = Domain.objects.get(pk=domid)
|
||||
except (User.DoesNotExist, Domain.DoesNotExist):
|
||||
raise BadRequest(_("Invalid request"))
|
||||
raise BadRequest(_("Invalid request")) from None
|
||||
if not request.user.can_access(account) or not request.user.can_access(domain):
|
||||
raise PermDeniedException
|
||||
domain.remove_admin(account)
|
||||
@@ -215,14 +215,14 @@ class AccountDetailView(auth_mixins.PermissionRequiredMixin, generic.DetailView)
|
||||
|
||||
def has_permission(self):
|
||||
"""Check object-level access."""
|
||||
result = super(AccountDetailView, self).has_permission()
|
||||
result = super().has_permission()
|
||||
if not result:
|
||||
return result
|
||||
return self.request.user.can_access(self.get_object())
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add information to context."""
|
||||
context = super(AccountDetailView, self).get_context_data(**kwargs)
|
||||
context = super().get_context_data(**kwargs)
|
||||
del context["user"]
|
||||
result = signals.extra_account_dashboard_widgets.send(
|
||||
self.__class__, user=self.request.user, account=self.object
|
||||
|
||||
@@ -12,7 +12,7 @@ class UserCalendarFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = models.UserCalendar
|
||||
|
||||
name = factory.Sequence(lambda n: "User calendar %s" % n)
|
||||
name = factory.Sequence(lambda n: f"User calendar {n}")
|
||||
mailbox = factory.SubFactory(admin_factories.MailboxFactory)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class SharedCalendarFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = models.SharedCalendar
|
||||
|
||||
name = factory.Sequence(lambda n: "Shared calendar %s" % n)
|
||||
name = factory.Sequence(lambda n: f"Shared calendar {n}")
|
||||
domain = factory.SubFactory(admin_factories.DomainFactory)
|
||||
|
||||
|
||||
|
||||
@@ -162,6 +162,7 @@ class AccessRule(models.Model):
|
||||
access = "r" if self.read else ""
|
||||
access += "w" if self.write else ""
|
||||
return smart_str(
|
||||
"%s access rule to %s -> %s"
|
||||
% (self.mailbox, self.calendar, access if access else "no access")
|
||||
"{} access rule to {} -> {}".format(
|
||||
self.mailbox, self.calendar, access if access else "no access"
|
||||
)
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ class Command(BaseCommand):
|
||||
).first()
|
||||
if not addressbook:
|
||||
raise CommandError(
|
||||
"Address Book for email '%s' not found" % options["email"]
|
||||
"Address Book for email '{}' not found".format(options["email"])
|
||||
)
|
||||
try:
|
||||
import_csv_file(
|
||||
@@ -55,5 +55,5 @@ class Command(BaseCommand):
|
||||
options.get("carddav_password"),
|
||||
)
|
||||
except RuntimeError as err:
|
||||
raise CommandError(err)
|
||||
raise CommandError(err) from None
|
||||
self.stdout.write(self.style.SUCCESS("File was imported successfuly"))
|
||||
|
||||
@@ -24,7 +24,7 @@ class TestDataMixin:
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create test data."""
|
||||
super(TestDataMixin, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
cls.user = core_models.User.objects.get(username="user@test.com")
|
||||
cls.addressbook = cls.user.addressbook_set.first()
|
||||
|
||||
@@ -45,7 +45,7 @@ class AccountViewSet(GetThrottleViewsetMixin, viewsets.ViewSet):
|
||||
device = StaticDevice.objects.create(
|
||||
user=request.user, name=f"{request.user} static device"
|
||||
)
|
||||
for cpt in range(10):
|
||||
for _cpt in range(10):
|
||||
token = StaticToken.random_token()
|
||||
device.token_set.create(token=token)
|
||||
django_otp.login(self.request, request.user.totpdevice_set.first())
|
||||
@@ -82,7 +82,7 @@ class AccountViewSet(GetThrottleViewsetMixin, viewsets.ViewSet):
|
||||
if device is None:
|
||||
return response.Response({"error": _("2FA is not enabled")}, status=403)
|
||||
device.token_set.all().delete()
|
||||
for cpt in range(10):
|
||||
for _cpt in range(10):
|
||||
token = StaticToken.random_token()
|
||||
device.token_set.create(token=token)
|
||||
return response.Response(
|
||||
|
||||
@@ -180,21 +180,21 @@ class CoreGlobalParametersSerializer(serializers.Serializer):
|
||||
try:
|
||||
value % {"user": "toto"}
|
||||
except (KeyError, ValueError):
|
||||
raise serializers.ValidationError(_("Invalid syntax"))
|
||||
raise serializers.ValidationError(_("Invalid syntax")) from None
|
||||
return value
|
||||
|
||||
def validate_ldap_sync_account_dn_template(self, value):
|
||||
try:
|
||||
value % {"user": "toto"}
|
||||
except (KeyError, ValueError):
|
||||
raise serializers.ValidationError(_("Invalid syntax"))
|
||||
raise serializers.ValidationError(_("Invalid syntax")) from None
|
||||
return value
|
||||
|
||||
def validate_ldap_search_filter(self, value):
|
||||
try:
|
||||
value % {"user": "toto"}
|
||||
except (KeyError, ValueError, TypeError):
|
||||
raise serializers.ValidationError(_("Invalid syntax"))
|
||||
raise serializers.ValidationError(_("Invalid syntax")) from None
|
||||
return value
|
||||
|
||||
def validate_rounds_number(self, value):
|
||||
@@ -416,7 +416,7 @@ class PasswordRecoverySmsConfirmSerializer(serializers.Serializer):
|
||||
except KeyError:
|
||||
raise CustomValidationError(
|
||||
{"reason": "totp secret not set in session"}, 403
|
||||
)
|
||||
) from None
|
||||
if not oath.accept_totp(self.context["totp_secret"], data["sms_totp"])[0]:
|
||||
raise CustomValidationError({"reason": "Wrong totp"}, 400)
|
||||
|
||||
@@ -445,7 +445,7 @@ class PasswordRecoverySmsResendSerializer(serializers.Serializer):
|
||||
except KeyError:
|
||||
raise CustomValidationError(
|
||||
{"reason": "totp secret not set in session"}, status.HTTP_403_FORBIDDEN
|
||||
)
|
||||
) from None
|
||||
|
||||
# Attempt to get user, will raise an error if pk is not valid
|
||||
self.context["user"] = User.objects.filter(
|
||||
@@ -501,7 +501,7 @@ class PasswordRecoveryConfirmSerializer(serializers.Serializer):
|
||||
try:
|
||||
password_validation.validate_password(data["new_password1"], user)
|
||||
except djangoValidationError as e:
|
||||
raise PasswordRequirementsFailure(e.messages)
|
||||
raise PasswordRequirementsFailure(e.messages) from None
|
||||
self.context["user"] = user
|
||||
return super().validate(data)
|
||||
|
||||
|
||||
@@ -512,7 +512,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GeneralParametersForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["default_top_redirection"].choices = enabled_applications()
|
||||
self._add_visibilty_rules(sms_backends.get_all_backend_visibility_rules())
|
||||
self.fields["password_scheme"].choices = get_password_scheme()
|
||||
@@ -532,7 +532,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
|
||||
try:
|
||||
tpl % {"user": "toto"}
|
||||
except (KeyError, ValueError):
|
||||
raise forms.ValidationError(_("Invalid syntax"))
|
||||
raise forms.ValidationError(_("Invalid syntax")) from None
|
||||
return tpl
|
||||
|
||||
def clean_ldap_sync_account_dn_template(self):
|
||||
@@ -540,7 +540,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
|
||||
try:
|
||||
tpl % {"user": "toto"}
|
||||
except (KeyError, ValueError):
|
||||
raise forms.ValidationError(_("Invalid syntax"))
|
||||
raise forms.ValidationError(_("Invalid syntax")) from None
|
||||
return tpl
|
||||
|
||||
def clean_ldap_search_filter(self):
|
||||
@@ -548,7 +548,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
|
||||
try:
|
||||
ldap_filter % {"user": "toto"}
|
||||
except (KeyError, ValueError, TypeError):
|
||||
raise forms.ValidationError(_("Invalid syntax"))
|
||||
raise forms.ValidationError(_("Invalid syntax")) from None
|
||||
return ldap_filter
|
||||
|
||||
def clean_rounds_number(self):
|
||||
@@ -613,10 +613,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
|
||||
{"first_name": "givenName", "email": "mail", "last_name": "sn"},
|
||||
)
|
||||
ldap_uri = "ldaps://" if values["ldap_secured"] == "ssl" else "ldap://"
|
||||
ldap_uri += "%s:%s" % (
|
||||
values[backend.srv_address_setting_name],
|
||||
values[backend.srv_port_setting_name],
|
||||
)
|
||||
ldap_uri += f"{values[backend.srv_address_setting_name]}:{values[backend.srv_port_setting_name]}"
|
||||
setattr(settings, backend.setting_fullname("SERVER_URI"), ldap_uri)
|
||||
if values["ldap_secured"] == "starttls":
|
||||
setattr(settings, backend.setting_fullname("START_TLS"), True)
|
||||
|
||||
@@ -25,7 +25,7 @@ class Command:
|
||||
{"BACKEND": ("django.template.backends.django.DjangoTemplates")}
|
||||
]
|
||||
)
|
||||
self._templates_dir = "%s/templates" % os.path.dirname(__file__)
|
||||
self._templates_dir = f"{os.path.dirname(__file__)}/templates"
|
||||
|
||||
def _render_template(self, tplfile, env):
|
||||
"""Render an HTML template."""
|
||||
@@ -70,7 +70,7 @@ def scan_for_commands(dirname=""):
|
||||
else:
|
||||
cmdclassname = cmdname.capitalize()
|
||||
try:
|
||||
cmdclass = getattr(cmdmod, "%sCommand" % cmdclassname)
|
||||
cmdclass = getattr(cmdmod, f"{cmdclassname}Command")
|
||||
except AttributeError:
|
||||
continue
|
||||
result[cmdname] = cmdclass
|
||||
@@ -83,9 +83,10 @@ def handle_command_line():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="A set of utilities to ease the installation of Modoboa.",
|
||||
epilog="""Available commands:
|
||||
%s
|
||||
"""
|
||||
% "\n".join(["\t%s" % c for c in sorted(commands)]),
|
||||
{}
|
||||
""".format(
|
||||
"\n".join([f"\t{c}" for c in sorted(commands)])
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--verbose", action="store_true", help="Activate verbose output"
|
||||
@@ -94,7 +95,7 @@ def handle_command_line():
|
||||
(args, remaining) = parser.parse_known_args()
|
||||
|
||||
if args.command not in commands:
|
||||
print("Unknown command '%s'" % args.command, file=sys.stderr)
|
||||
print(f"Unknown command '{args.command}'", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
commands[args.command](commands, verbose=args.verbose).run(remaining)
|
||||
|
||||
@@ -8,14 +8,14 @@ class HelpCommand(Command):
|
||||
help = "Display the help message associated to a specific command" # NOQA:A003
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HelpCommand, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self._parser.add_argument("name", type=str, help="A command name")
|
||||
|
||||
def handle(self, parsed_args):
|
||||
if parsed_args.name not in self._commands:
|
||||
print("Unknown command: %s" % parsed_args.name, file=sys.stderr)
|
||||
print(f"Unknown command: {parsed_args.name}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
cmd = self._commands[parsed_args.name](self._commands)
|
||||
cmd._parser.prog = "modoboa-admin.py %s" % parsed_args.name
|
||||
cmd._parser.prog = f"modoboa-admin.py {parsed_args.name}"
|
||||
cmd._parser.description = cmd.help
|
||||
cmd._parser.print_help()
|
||||
|
||||
@@ -133,7 +133,7 @@ class APIAccessForm(forms.Form):
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize form."""
|
||||
user = kwargs.pop("user")
|
||||
super(APIAccessForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["enable_api_access"].initial = hasattr(user, "auth_token")
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class Command(BaseCommand):
|
||||
self.verbose = options["verbose"]
|
||||
|
||||
log_maximum_age = param_tools.get_global_parameter("log_maximum_age")
|
||||
self.__vprint("Deleting logs older than %d days..." % log_maximum_age)
|
||||
self.__vprint(f"Deleting logs older than {log_maximum_age} days...")
|
||||
limit = timezone.now() - datetime.timedelta(log_maximum_age)
|
||||
Log.objects.filter(date_created__lt=limit).delete()
|
||||
self.__vprint("Done.")
|
||||
|
||||
@@ -373,15 +373,17 @@ class User(AbstractUser):
|
||||
if len(row) < 8 or not row[7].strip():
|
||||
raise BadRequest(
|
||||
_(
|
||||
"The simple user '%s' must have a valid email address"
|
||||
% self.username
|
||||
"The simple user '{}' must have a valid email address".format(
|
||||
self.username
|
||||
)
|
||||
)
|
||||
)
|
||||
if self.username != row[7].strip():
|
||||
raise BadRequest(
|
||||
_(
|
||||
"username and email fields must not differ for '%s'"
|
||||
% self.username
|
||||
"username and email fields must not differ for '{}'".format(
|
||||
self.username
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ def get_password_hasher(scheme: str) -> type[PasswordHasher]:
|
||||
"""
|
||||
try:
|
||||
scheme = scheme.replace("-", "")
|
||||
hasher = globals()["%sHasher" % scheme.upper()]
|
||||
hasher = globals()[f"{scheme.upper()}Hasher"]
|
||||
except KeyError:
|
||||
hasher = PLAINHasher
|
||||
return hasher
|
||||
|
||||
@@ -148,7 +148,7 @@ if argon2_hasher is not None:
|
||||
def __init__(
|
||||
self,
|
||||
):
|
||||
super(ARGON2IDHasher, self).__init__()
|
||||
super().__init__()
|
||||
|
||||
parameters = dict()
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ class PasswordHasher(metaclass=MetaHasher):
|
||||
:return: encrypted password
|
||||
"""
|
||||
pwhash = self._b64encode(self._encrypt(force_str(clearvalue)))
|
||||
return "%s%s" % (self.scheme, force_str(pwhash))
|
||||
return f"{self.scheme}{force_str(pwhash)}"
|
||||
|
||||
def verify(self, clearvalue, hashed_value):
|
||||
"""Verify a password against a hashed value.
|
||||
|
||||
@@ -181,7 +181,7 @@ def colorize_level(level):
|
||||
}
|
||||
if level not in classes:
|
||||
return level
|
||||
return "<p class='%s'>%s</p>" % (classes[level], level)
|
||||
return f"<p class='{classes[level]}'>{level}</p>"
|
||||
|
||||
|
||||
@register.filter
|
||||
@@ -238,7 +238,7 @@ def connected_users(parser, token):
|
||||
except ValueError:
|
||||
raise template.TemplateSyntaxError(
|
||||
"connected_users usage: {% connected_users as users %}"
|
||||
)
|
||||
) from None
|
||||
return ConnectedUsers(varname)
|
||||
|
||||
|
||||
@@ -279,14 +279,13 @@ def display_messages(msgs):
|
||||
timeout = "undefined"
|
||||
|
||||
return mark_safe(
|
||||
"""
|
||||
f"""
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('body').notify('%s', '%s', %s);
|
||||
});
|
||||
$(document).ready(function() {{
|
||||
$('body').notify('{level}', '{text}', {timeout});
|
||||
}});
|
||||
</script>
|
||||
"""
|
||||
% (level, text, timeout)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class AuthenticationTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(AuthenticationTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.account = factories.UserFactory(
|
||||
username="user@test.com", groups=("SimpleUsers",)
|
||||
)
|
||||
@@ -115,7 +115,7 @@ class ProfileTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(ProfileTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.account = factories.UserFactory(
|
||||
username="user@test.com", groups=("SimpleUsers",)
|
||||
)
|
||||
@@ -231,7 +231,7 @@ class APIAccessFormTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(APIAccessFormTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.account = factories.UserFactory(
|
||||
username="user@test.com", groups=("SimpleUsers",)
|
||||
)
|
||||
|
||||
@@ -84,7 +84,7 @@ class LDAPAuthenticationTestCase(LDAPTestCaseMixin, ModoTestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Create test data."""
|
||||
super(LDAPAuthenticationTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.activate_ldap_authentication()
|
||||
|
||||
def check_created_user(self, username, group="SimpleUsers", with_mb=True):
|
||||
@@ -142,7 +142,7 @@ class ProfileTestCase(LDAPTestCaseMixin, ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(ProfileTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.account = factories.UserFactory(
|
||||
username="user@test.com", groups=("SimpleUsers",)
|
||||
)
|
||||
|
||||
@@ -148,7 +148,7 @@ class DashboardTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create some data."""
|
||||
super(DashboardTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.dadmin = factories.UserFactory(
|
||||
username="admin@test.com", groups=("DomainAdmins",)
|
||||
)
|
||||
@@ -317,13 +317,13 @@ class PreferencesTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Register user form."""
|
||||
super(PreferencesTestCase, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
param_tools.registry.add("user", UserSettings, "Test")
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
"""Remove user class."""
|
||||
super(PreferencesTestCase, cls).tearDownClass()
|
||||
super().tearDownClass()
|
||||
del param_tools.registry._registry["user"]["core"]
|
||||
|
||||
def test_get_user_index(self):
|
||||
|
||||
@@ -88,7 +88,7 @@ def get_logs_page(request, page_id=None):
|
||||
if page_id is None:
|
||||
return None
|
||||
return get_listing_page(
|
||||
Log.objects.all().order_by("%s%s" % (sort_dir, sort_order)), page_id
|
||||
Log.objects.all().order_by(f"{sort_dir}{sort_order}"), page_id
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -141,11 +141,10 @@ class LoginView(LoginViewMixin, auth_views.LoginView):
|
||||
def form_invalid(self, form):
|
||||
# FIXME: should we return a 401 as before ?
|
||||
self.logger.warning(
|
||||
"Failed connection attempt from '%(addr)s' as user '%(user)s'"
|
||||
% {
|
||||
"addr": self.request.META["REMOTE_ADDR"],
|
||||
"user": escape(form.cleaned_data["username"]),
|
||||
}
|
||||
"Failed connection attempt from '{addr}' as user '{user}'".format(
|
||||
addr=self.request.META["REMOTE_ADDR"],
|
||||
user=escape(form.cleaned_data["username"]),
|
||||
)
|
||||
)
|
||||
return self.render_to_response(self.get_context_data(form=form), status=401)
|
||||
|
||||
@@ -220,7 +219,7 @@ class VerifySMSCodeView(generic.FormView):
|
||||
try:
|
||||
kwargs.update({"totp_secret": self.request.session["totp_secret"]})
|
||||
except KeyError:
|
||||
raise Http404
|
||||
raise Http404 from None
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
@@ -241,11 +240,11 @@ class ResendSMSCodeView(generic.View):
|
||||
"sms_password_recovery"
|
||||
)
|
||||
if not sms_password_recovery:
|
||||
raise Http404
|
||||
raise Http404 from None
|
||||
try:
|
||||
user = models.User._default_manager.get(pk=self.request.session["user_pk"])
|
||||
except KeyError:
|
||||
raise Http404
|
||||
raise Http404 from None
|
||||
backend = sms_backends.get_active_backend(self.request.localconfig.parameters)
|
||||
secret = cryptutils.random_hex_key(20)
|
||||
code = oath.totp(secret)
|
||||
@@ -255,7 +254,7 @@ class ResendSMSCodeView(generic.View):
|
||||
)
|
||||
)
|
||||
if not backend.send(text, [user.phone_number]):
|
||||
raise Http404
|
||||
raise Http404 from None
|
||||
self.request.session["totp_secret"] = secret
|
||||
return JsonResponse({"status": "ok"})
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class ManagementCommandTestCase(mixins.CallCommandMixin, ModoTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(ManagementCommandTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.domain = admin_factories.DomainFactory(name="ngyn.org")
|
||||
|
||||
def test_import_from_archive(self):
|
||||
|
||||
@@ -78,7 +78,7 @@ class DomainReportView(auth_mixins.PermissionRequiredMixin, generic.TemplateView
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
"""Extra context data."""
|
||||
context = super(DomainReportView, self).get_context_data(*args, **kwargs)
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
qset = self.get_queryset()
|
||||
stats = {"total": 0, "aligned": 0, "trusted": 0, "forwarded": 0, "failed": 0}
|
||||
aligned = {}
|
||||
|
||||
@@ -83,7 +83,7 @@ def check_spf_ip4(value):
|
||||
try:
|
||||
ipaddress.ip_network(parts[1], False)
|
||||
except ValueError:
|
||||
raise DNSSyntaxError(_("Wrong IPv4 address format"))
|
||||
raise DNSSyntaxError(_("Wrong IPv4 address format")) from None
|
||||
|
||||
|
||||
def check_spf_ip6(value):
|
||||
@@ -94,7 +94,7 @@ def check_spf_ip6(value):
|
||||
try:
|
||||
ipaddress.ip_network(value, False)
|
||||
except ValueError:
|
||||
raise DNSSyntaxError(_("Wrong IPv6 address format"))
|
||||
raise DNSSyntaxError(_("Wrong IPv6 address format")) from None
|
||||
|
||||
|
||||
def _check_domain_and_mask(value, mechanism):
|
||||
@@ -229,7 +229,7 @@ def check_dmarc_tag(tag, value):
|
||||
try:
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
raise DNSSyntaxError(error + _(" not an integer"))
|
||||
raise DNSSyntaxError(error + _(" not an integer")) from None
|
||||
if "min_value" in tdef and value < tdef["min_value"]:
|
||||
raise DNSSyntaxError(error + _(" less than {}").format(tdef["min_value"]))
|
||||
if "max_value" in tdef and value > tdef["max_value"]:
|
||||
|
||||
@@ -133,7 +133,7 @@ class ViewsTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create some records."""
|
||||
super(ViewsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.spf_rec = factories.DNSRecordFactory(
|
||||
type="spf", value="v=SPF1 mx -all", is_valid=True, domain__name="test.com"
|
||||
)
|
||||
|
||||
@@ -16,7 +16,7 @@ class DomainAccessRequiredMixin(auth_mixins.AccessMixin):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.can_access(self.get_object()):
|
||||
return self.handle_no_permission()
|
||||
return super(DomainAccessRequiredMixin, self).dispatch(request, *args, **kwargs)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class DNSRecordDetailView(
|
||||
@@ -29,7 +29,7 @@ class DNSRecordDetailView(
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add extra variables."""
|
||||
context = super(DNSRecordDetailView, self).get_context_data(**kwargs)
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update(
|
||||
{
|
||||
"title": _("{} record of {}").format(
|
||||
@@ -59,7 +59,7 @@ class AutoConfigRecordsStatusView(
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add extra data to context."""
|
||||
context = super(AutoConfigRecordsStatusView, self).get_context_data(**kwargs)
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update(
|
||||
{"title": _("Auto configuration records for {}").format(self.object.name)}
|
||||
)
|
||||
@@ -76,6 +76,6 @@ class DomainDNSConfigurationView(
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add extra variables."""
|
||||
context = super(DomainDNSConfigurationView, self).get_context_data(**kwargs)
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({"title": _("DNS configuration for {}").format(self.object)})
|
||||
return context
|
||||
|
||||
@@ -26,7 +26,7 @@ class DataMixin:
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(DataMixin, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
cls.mb = admin_models.Mailbox.objects.get(user__username="user@test.com")
|
||||
cls.migration = factories.MigrationFactory(
|
||||
@@ -110,7 +110,7 @@ class ManagementCommandTestCase(DataMixin, ModoTestCase):
|
||||
"""Management command test cases."""
|
||||
|
||||
def setUp(self):
|
||||
super(ManagementCommandTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.workdir = tempfile.mkdtemp()
|
||||
|
||||
def tearDown(self):
|
||||
|
||||
@@ -18,4 +18,4 @@ class IndexView(
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Set menu selection."""
|
||||
kwargs.update({"selection": "imap_migrations"})
|
||||
return super(IndexView, self).get_context_data(**kwargs)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
@@ -9,7 +9,7 @@ class ConnectionsManager(type):
|
||||
"""
|
||||
|
||||
def __init__(self, name, bases, ctx):
|
||||
super(ConnectionsManager, self).__init__(name, bases, ctx)
|
||||
super().__init__(name, bases, ctx)
|
||||
self.instances = {}
|
||||
|
||||
def __call__(self, **kwargs):
|
||||
@@ -24,7 +24,7 @@ class ConnectionsManager(type):
|
||||
kwargs["password"] = decrypt(kwargs["password"])
|
||||
|
||||
if self.instances[key] is None:
|
||||
self.instances[key] = super(ConnectionsManager, self).__call__(**kwargs)
|
||||
self.instances[key] = super().__call__(**kwargs)
|
||||
else:
|
||||
self.instances[key].refresh(key, kwargs["password"])
|
||||
return self.instances[key]
|
||||
|
||||
@@ -19,7 +19,7 @@ def db_type(cname="default"):
|
||||
:return: a string or None
|
||||
"""
|
||||
if cname not in settings.DATABASES:
|
||||
raise InternalError(_("Connection to database %s not configured" % cname))
|
||||
raise InternalError(_("Connection to database {} not configured".format(cname)))
|
||||
for t in ["postgres", "mysql", "sqlite"]:
|
||||
if settings.DATABASES[cname]["ENGINE"].find(t) != -1:
|
||||
return t
|
||||
|
||||
@@ -113,7 +113,7 @@ class Email:
|
||||
def body(self):
|
||||
if self._body is None:
|
||||
self._parse(self.msg)
|
||||
self._body = getattr(self, "viewmail_%s" % self.dformat)()
|
||||
self._body = getattr(self, f"viewmail_{self.dformat}")()
|
||||
|
||||
return self._body
|
||||
|
||||
@@ -215,7 +215,7 @@ class Email:
|
||||
# Duplicate Content-ID
|
||||
return
|
||||
|
||||
self._images[cid] = "data:%s;base64,%s" % (
|
||||
self._images[cid] = "data:{};base64,{}".format(
|
||||
content_type,
|
||||
"".join(msg.get_payload().splitlines(False)),
|
||||
)
|
||||
@@ -263,7 +263,7 @@ class Email:
|
||||
contents = self.contents["plain"]
|
||||
else:
|
||||
contents = conditional_escape(contents)
|
||||
return "<pre>%s</pre>" % contents
|
||||
return f"<pre>{contents}</pre>"
|
||||
|
||||
def viewmail_html(self, contents=None, **kwargs):
|
||||
# contents and **kwargs parameters to maintain compatibility with
|
||||
@@ -385,7 +385,7 @@ def set_email_headers(msg, subject, sender, rcpt):
|
||||
msg["From"] = sender
|
||||
msg["To"] = prepare_addresses(rcpt)
|
||||
msg["Message-ID"] = make_msgid()
|
||||
msg["User-Agent"] = "Modoboa %s" % (
|
||||
msg["User-Agent"] = "Modoboa {}".format(
|
||||
pkg_resources.get_distribution("modoboa").version
|
||||
)
|
||||
msg["Date"] = formatdate(time.time(), True)
|
||||
@@ -409,7 +409,7 @@ def _sendmail(sender, rcpt, msgstring, server="localhost", port=25):
|
||||
s.sendmail(sender, [rcpt], msgstring)
|
||||
s.quit()
|
||||
except smtplib.SMTPException as e:
|
||||
return False, "SMTP error: %s" % str(e)
|
||||
return False, f"SMTP error: {str(e)}"
|
||||
return True, None
|
||||
|
||||
|
||||
@@ -449,12 +449,9 @@ def sendmail_fromfile(sender, rcpt, fname):
|
||||
except OSError as e:
|
||||
return False, str(e)
|
||||
|
||||
content = """From: %s
|
||||
To: %s
|
||||
""" % (
|
||||
sender,
|
||||
rcpt,
|
||||
)
|
||||
content = f"""From: {sender}
|
||||
To: {rcpt}
|
||||
"""
|
||||
content += fp.read()
|
||||
fp.close()
|
||||
|
||||
|
||||
@@ -82,5 +82,5 @@ class PermDeniedException(ModoboaException):
|
||||
|
||||
def __str__(self):
|
||||
if self.msg:
|
||||
return _("Permission denied: %s" % self.msg)
|
||||
return _("Permission denied: {}".format(self.msg))
|
||||
return _("Permission denied")
|
||||
|
||||
@@ -17,7 +17,7 @@ class DomainNameField(forms.fields.CharField):
|
||||
|
||||
def clean(self, value):
|
||||
value = self.to_python(value).strip()
|
||||
return super(DomainNameField, self).clean(value)
|
||||
return super().clean(value)
|
||||
|
||||
|
||||
class UTF8EmailField(forms.fields.EmailField):
|
||||
@@ -41,7 +41,7 @@ class DRFEmailFieldUTF8(serializers.CharField):
|
||||
default_error_messages = {"invalid": gettext_lazy("Enter a valid email address.")}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(DRFEmailFieldUTF8, self).__init__(**kwargs)
|
||||
super().__init__(**kwargs)
|
||||
validator = validators.UTF8EmailValidator(
|
||||
message=self.error_messages["invalid"]
|
||||
)
|
||||
@@ -54,7 +54,7 @@ class DRFEmailFieldUTF8AndEmptyUser(serializers.CharField):
|
||||
default_error_messages = {"invalid": gettext_lazy("Enter a valid email address.")}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(DRFEmailFieldUTF8AndEmptyUser, self).__init__(**kwargs)
|
||||
super().__init__(**kwargs)
|
||||
validator = validators.UTF8AndEmptyUserEmailValidator(
|
||||
message=self.error_messages["invalid"]
|
||||
)
|
||||
|
||||
@@ -218,7 +218,7 @@ class DynamicForm:
|
||||
:param string pattern: pattern used to find field instances
|
||||
:param typ: a form field class
|
||||
"""
|
||||
expr = re.compile(r"%s_\d+" % pattern)
|
||||
expr = re.compile(rf"{pattern}_\d+")
|
||||
values = []
|
||||
for k, v in list(qdict.items()):
|
||||
if k == pattern or expr.match(k):
|
||||
@@ -258,7 +258,7 @@ class TabForms:
|
||||
args.append(request.POST)
|
||||
if instances is not None:
|
||||
self.instances = instances
|
||||
mname = "check_%s" % fd["id"]
|
||||
mname = "check_{}".format(fd["id"])
|
||||
if hasattr(self, mname):
|
||||
if not getattr(self, mname)(instances[fd["id"]]):
|
||||
to_remove += [fd]
|
||||
@@ -326,8 +326,7 @@ class TabForms:
|
||||
return self.forward()
|
||||
|
||||
def forward(self):
|
||||
for form in self.forms:
|
||||
yield form
|
||||
yield from self.forms
|
||||
|
||||
def extra_context(self, context):
|
||||
""" "Provide additional information to template's context."""
|
||||
@@ -387,7 +386,7 @@ class SeparatorField(Field):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["required"] = False
|
||||
super(SeparatorField, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class YesNoField(TypedChoiceField):
|
||||
@@ -402,4 +401,4 @@ class YesNoField(TypedChoiceField):
|
||||
"coerce": lambda x: x == "True",
|
||||
}
|
||||
)
|
||||
super(YesNoField, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@@ -112,7 +112,7 @@ class LDAPAuthBackend:
|
||||
self.connect_to_server(user, password)
|
||||
user_dn = self._find_user_dn(user)
|
||||
if self.ldap_ad:
|
||||
newpassword = ('"%s"' % newpassword).encode("utf-16").lstrip("\377\376")
|
||||
newpassword = (f'"{newpassword}"').encode("utf-16").lstrip("\377\376")
|
||||
ldif = [
|
||||
(
|
||||
ldap.MOD_REPLACE,
|
||||
|
||||
@@ -4,7 +4,7 @@ class _Singleton(type):
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
if self not in self._instances:
|
||||
self._instances[self] = super(_Singleton, self).__call__(*args, **kwargs)
|
||||
self._instances[self] = super().__call__(*args, **kwargs)
|
||||
return self._instances[self]
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ def exec_cmd(cmd, sudo_user=None, pinput=None, capture_output=True, **kwargs):
|
||||
:return: return code, command output
|
||||
"""
|
||||
if sudo_user is not None:
|
||||
cmd = "sudo -u %s %s" % (sudo_user, cmd)
|
||||
cmd = f"sudo -u {sudo_user} {cmd}"
|
||||
kwargs["shell"] = True
|
||||
if pinput is not None:
|
||||
kwargs["stdin"] = subprocess.PIPE
|
||||
|
||||
@@ -20,7 +20,7 @@ def render_form(form, tpl=None):
|
||||
|
||||
ret = ""
|
||||
for field in form:
|
||||
ret += "%s\n" % render_field(field)
|
||||
ret += f"{render_field(field)}\n"
|
||||
return mark_safe(ret)
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ def render_field(field, help_display_mode="tooltip", label_width="col-sm-4", **o
|
||||
from modoboa.core.templatetags.core_tags import visirule
|
||||
|
||||
if isinstance(field.field, SeparatorField):
|
||||
return "<h5%s>%s</h5>" % (visirule(field), smart_str(field.label))
|
||||
return f"<h5{visirule(field)}>{smart_str(field.label)}</h5>"
|
||||
configure_field_classes(field)
|
||||
context = {
|
||||
"field": field,
|
||||
@@ -64,7 +64,7 @@ def render_fields_group(form, pattern):
|
||||
cpt = 1
|
||||
haserror = len(first.errors) != 0
|
||||
while True:
|
||||
fname = "%s_%d" % (pattern, cpt)
|
||||
fname = f"{pattern}_{cpt}"
|
||||
if fname not in form.fields:
|
||||
break
|
||||
bfield = forms.BoundField(form, form.fields[fname], fname)
|
||||
|
||||
@@ -18,13 +18,13 @@ def join(items, sep=","):
|
||||
for k, v in list(items.items()):
|
||||
if res != "":
|
||||
res += sep
|
||||
res += "%s : '%s'" % (k, v)
|
||||
res += f"{k} : '{v}'"
|
||||
return res
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def tolist(values):
|
||||
return mark_safe("[%s]" % ",".join(['"%s"' % v for v in values]))
|
||||
return mark_safe("[{}]".format(",".join([f'"{v}"' for v in values])))
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
|
||||
@@ -15,8 +15,8 @@ SAMPLES_DIR = os.path.realpath(
|
||||
class EmailTestImplementation(Email):
|
||||
|
||||
def _fetch_message(self):
|
||||
message_path = os.path.join(SAMPLES_DIR, "%s-input.txt" % self.mailid)
|
||||
assert os.path.isfile(message_path), "%s does not exist." % message_path
|
||||
message_path = os.path.join(SAMPLES_DIR, f"{self.mailid}-input.txt")
|
||||
assert os.path.isfile(message_path), f"{message_path} does not exist."
|
||||
|
||||
with open(message_path, "rb") as fp:
|
||||
mail_text = smart_bytes(fp.read())
|
||||
@@ -38,7 +38,7 @@ class EmailTests(SimpleTestCase):
|
||||
ext = kwargs["dformat"] if "dformat" in kwargs else "plain"
|
||||
ext += "_links" if "links" in kwargs and kwargs["links"] else "_nolinks"
|
||||
message_path = os.path.join(SAMPLES_DIR, f"{message_id}-output-{ext}.txt")
|
||||
assert os.path.isfile(message_path), "%s does not exist." % message_path
|
||||
assert os.path.isfile(message_path), f"{message_path} does not exist."
|
||||
|
||||
with open(message_path, "rb") as fp:
|
||||
# output should always be unicode (py2) or str (py3)
|
||||
|
||||
@@ -16,7 +16,7 @@ from django.template.loader import render_to_string
|
||||
def _render_error(request, errortpl="error", user_context=None):
|
||||
if user_context is None:
|
||||
user_context = {}
|
||||
return render(request, "common/%s.html" % errortpl, user_context)
|
||||
return render(request, f"common/{errortpl}.html", user_context)
|
||||
|
||||
|
||||
def render_actions(actions):
|
||||
@@ -102,7 +102,7 @@ def static_url(path):
|
||||
"""
|
||||
if path.startswith("/"):
|
||||
path = path[1:]
|
||||
return "%s%s" % (settings.STATIC_URL, path)
|
||||
return f"{settings.STATIC_URL}{path}"
|
||||
|
||||
|
||||
def size2integer(value, output_unit="B"):
|
||||
|
||||
@@ -20,7 +20,7 @@ class APIAdminLimitsTestCase(lib_tests.ModoAPITestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(APIAdminLimitsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
for name, _definition in utils.get_user_limit_templates():
|
||||
cls.localconfig.parameters.set_value(f"deflt_user_{name}_limit", 2)
|
||||
cls.localconfig.save()
|
||||
@@ -189,7 +189,7 @@ class APIDomainLimitsTestCase(lib_tests.ModoAPITestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(APIDomainLimitsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.localconfig.parameters.set_value("enable_domain_limits", True)
|
||||
for name, _definition in utils.get_domain_limit_templates():
|
||||
cls.localconfig.parameters.set_value(f"deflt_domain_{name}_limit", 2)
|
||||
@@ -251,7 +251,7 @@ class ResourcesAPITestCase(lib_tests.ModoAPITestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(ResourcesAPITestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
for name, _definition in utils.get_user_limit_templates():
|
||||
cls.localconfig.parameters.set_value(f"deflt_user_{name}_limit", 2)
|
||||
cls.localconfig.save()
|
||||
|
||||
@@ -13,7 +13,7 @@ class ResourcePoolForm(forms.Form):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.account = kwargs.pop("instance", None)
|
||||
super(ResourcePoolForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
for name, tpl in utils.get_user_limit_templates():
|
||||
if "required_role" in tpl:
|
||||
condition = (
|
||||
@@ -30,7 +30,7 @@ class ResourcePoolForm(forms.Form):
|
||||
|
||||
def clean(self):
|
||||
"""Ensure limit values are correct."""
|
||||
cleaned_data = super(ResourcePoolForm, self).clean()
|
||||
cleaned_data = super().clean()
|
||||
if self.errors:
|
||||
return cleaned_data
|
||||
for lname in list(self.fields.keys()):
|
||||
@@ -65,7 +65,7 @@ class DomainLimitsForm(forms.Form):
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Define limits as fields."""
|
||||
self.domain = kwargs.pop("instance", None)
|
||||
super(DomainLimitsForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
for name, tpl in utils.get_domain_limit_templates():
|
||||
self.fields[f"{name}_limit"] = forms.IntegerField(
|
||||
label=tpl["label"], help_text=tpl["help"]
|
||||
@@ -80,7 +80,7 @@ class DomainLimitsForm(forms.Form):
|
||||
|
||||
def clean(self):
|
||||
"""Ensure limit values are correct."""
|
||||
cleaned_data = super(DomainLimitsForm, self).clean()
|
||||
cleaned_data = super().clean()
|
||||
if self.errors:
|
||||
return cleaned_data
|
||||
for lname in list(self.fields.keys()):
|
||||
|
||||
@@ -14,7 +14,7 @@ class LimitImportTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(LimitImportTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
cls.reseller = core_factories.UserFactory(
|
||||
username="reseller", groups=("Resellers",)
|
||||
@@ -119,7 +119,7 @@ class UserLimitImportTestCase(LimitImportTestCase):
|
||||
for name, _definition in utils.get_user_limit_templates():
|
||||
localconfig.parameters.set_value(f"deflt_user_{name}_limit", 2)
|
||||
localconfig.save()
|
||||
super(UserLimitImportTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
|
||||
def test_domains_import(self):
|
||||
"""Check domains limit."""
|
||||
@@ -181,7 +181,7 @@ class DomainLimitImportTestCase(LimitImportTestCase):
|
||||
for name, _definition in utils.get_domain_limit_templates():
|
||||
localconfig.parameters.set_value(f"deflt_domain_{name}_limit", 2)
|
||||
localconfig.save()
|
||||
super(DomainLimitImportTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
mb = admin_factories.MailboxFactory(
|
||||
user__username="user@test4.com", domain__name="test4.com", address="user"
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ class PermissionsTestCase(lib_tests.ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(PermissionsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
populate_database()
|
||||
|
||||
def test_domainadmin_deletes_reseller(self):
|
||||
@@ -49,7 +49,7 @@ class ResourceTestCase(lib_tests.ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Custom setUpTestData method."""
|
||||
super(ResourceTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.localconfig.parameters.set_values(
|
||||
{"enable_admin_limits": True, "enable_domain_limits": False}
|
||||
)
|
||||
@@ -116,7 +116,7 @@ class ResourceTestCase(lib_tests.ModoTestCase):
|
||||
else:
|
||||
aliases.remove(name)
|
||||
for cpt, alias in enumerate(aliases):
|
||||
fname = "aliases" if not cpt else "aliases_%d" % cpt
|
||||
fname = "aliases" if not cpt else f"aliases_{cpt}"
|
||||
values[fname] = alias
|
||||
self.ajax_post(reverse("admin:domain_change", args=[dom.id]), values, status)
|
||||
|
||||
@@ -131,7 +131,7 @@ class DomainAdminTestCase(ResourceTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(DomainAdminTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.user = User.objects.get(username="admin@test.com")
|
||||
cls.user.userobjectlimit_set.filter(
|
||||
name__in=["mailboxes", "mailbox_aliases"]
|
||||
@@ -139,7 +139,7 @@ class DomainAdminTestCase(ResourceTestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Test initialization."""
|
||||
super(DomainAdminTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.client.force_login(self.user)
|
||||
|
||||
def test_mailboxes_limit(self):
|
||||
@@ -173,7 +173,7 @@ class DomainAdminTestCase(ResourceTestCase):
|
||||
self._check_limit("mailbox_aliases", 3, -1)
|
||||
self.ajax_delete(
|
||||
reverse("admin:alias_delete")
|
||||
+ "?selection=%d" % Alias.objects.get(address="alias2@test.com").id
|
||||
+ f"?selection={Alias.objects.get(address='alias2@test.com').id}"
|
||||
)
|
||||
self._check_limit("mailbox_aliases", 2, -1)
|
||||
|
||||
@@ -201,14 +201,14 @@ class ResellerTestCase(ResourceTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(ResellerTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
cls.localconfig.parameters.set_value("deflt_user_quota_limit", 1000)
|
||||
cls.localconfig.save()
|
||||
cls.user = UserFactory(username="reseller", groups=("Resellers",))
|
||||
|
||||
def setUp(self):
|
||||
"""Test initialization."""
|
||||
super(ResellerTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.client.force_login(self.user)
|
||||
|
||||
def test_domains_limit(self):
|
||||
@@ -380,7 +380,7 @@ class ResellerTestCase(ResourceTestCase):
|
||||
self.client.logout()
|
||||
self.client.login(username="admin", password="password")
|
||||
self.ajax_delete(
|
||||
"{0}?domid={1}&daid={2}".format(
|
||||
"{}?domid={}&daid={}".format(
|
||||
reverse("admin:permission_remove"), dom.id, self.user.id
|
||||
),
|
||||
{},
|
||||
|
||||
@@ -36,12 +36,12 @@ class Curve:
|
||||
:return: a list
|
||||
"""
|
||||
rrdfile = os.path.join(
|
||||
param_tools.get_global_parameter("rrd_rootdir"), "%s.rrd" % rrdfile
|
||||
param_tools.get_global_parameter("rrd_rootdir"), f"{rrdfile}.rrd"
|
||||
)
|
||||
return [
|
||||
"DEF:%s=%s:%s:%s" % (self.dsname, rrdfile, self.dsname, self.cfunc),
|
||||
"CDEF:%(ds)spm=%(ds)s,UN,0,%(ds)s,IF,60,*" % {"ds": self.dsname},
|
||||
'XPORT:%spm:"%s"' % (self.dsname, self.legend),
|
||||
f"DEF:{self.dsname}={rrdfile}:{self.dsname}:{self.cfunc}",
|
||||
f"CDEF:{self.dsname}pm={self.dsname},UN,0,{self.dsname},IF,60,*",
|
||||
f'XPORT:{self.dsname}pm:"{self.legend}"',
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ def date_to_timestamp(timetuple):
|
||||
:return: an integer
|
||||
"""
|
||||
date = " ".join(
|
||||
[("%d" % elem) if isinstance(elem, int) else elem for elem in timetuple]
|
||||
[str(elem) if isinstance(elem, int) else elem for elem in timetuple]
|
||||
)
|
||||
fmt = "%Y %m %d %H %M %S" if timetuple[1].isdigit() else "%Y %b %d %H %M %S"
|
||||
try:
|
||||
|
||||
@@ -204,12 +204,12 @@ class LogParser:
|
||||
# Set up data sources for our RRD
|
||||
params = []
|
||||
for v in variables:
|
||||
params += ["DS:%s:%s:%s:0:U" % (v, ds_type, rrdstep * 2)]
|
||||
params += [f"DS:{v}:{ds_type}:{rrdstep * 2}:0:U"]
|
||||
|
||||
# Set up RRD to archive data
|
||||
for cf in ["AVERAGE", "MAX"]:
|
||||
for step in [day_steps, week_steps, month_steps, year_steps]:
|
||||
params += ["RRA:%s:0.5:%s:%s" % (cf, step, realrows)]
|
||||
params += [f"RRA:{cf}:0.5:{step}:{realrows}"]
|
||||
|
||||
# With those setup, we can now created the RRD
|
||||
rrdtool.create(str(fname), "--start", str(m), "--step", str(rrdstep), *params)
|
||||
@@ -221,16 +221,16 @@ class LogParser:
|
||||
Add missing Data Sources (DS) to existing Round Robin Archive (RRA):
|
||||
See init_rrd for details.
|
||||
"""
|
||||
ds_def = "DS:%s:ABSOLUTE:%s:0:U" % (dsname, rrdstep * 2)
|
||||
ds_def = f"DS:{dsname}:ABSOLUTE:{rrdstep * 2}:0:U"
|
||||
rrdtool.tune(fname, ds_def)
|
||||
self._dprint("[rrd] added DS %s to %s" % (dsname, fname))
|
||||
self._dprint(f"[rrd] added DS {dsname} to {fname}")
|
||||
|
||||
def add_point_to_rrd(self, fname, tpl, values, ts=None):
|
||||
"""Try to add a new point to RRD file."""
|
||||
if ts:
|
||||
values = f"{ts}:{values}"
|
||||
if self.verbose:
|
||||
print("[rrd] VERBOSE update -t %s %s" % (tpl, values))
|
||||
print(f"[rrd] VERBOSE update -t {tpl} {values}")
|
||||
try:
|
||||
rrdtool.update(str(fname), "-t", tpl, values)
|
||||
except rrdtool.OperationalError as e:
|
||||
@@ -249,20 +249,20 @@ class LogParser:
|
||||
False : syslog may have probably been already recorded
|
||||
or something wrong
|
||||
"""
|
||||
fname = "%s/%s.rrd" % (self.workdir, dom)
|
||||
fname = f"{self.workdir}/{dom}.rrd"
|
||||
m = t - (t % rrdstep)
|
||||
|
||||
self._dprint("[rrd] updating %s" % fname)
|
||||
self._dprint(f"[rrd] updating {fname}")
|
||||
if not os.path.exists(fname):
|
||||
self.lupdates[fname] = self.init_rrd(fname, m)
|
||||
self._dprint("[rrd] create new RRD file %s" % fname)
|
||||
self._dprint(f"[rrd] create new RRD file {fname}")
|
||||
else:
|
||||
if fname not in self.lupdates:
|
||||
self.lupdates[fname] = rrdtool.last(str(fname))
|
||||
|
||||
if m <= self.lupdates[fname]:
|
||||
if self.verbose:
|
||||
print("[rrd] VERBOSE events at %s already recorded in RRD" % m)
|
||||
print(f"[rrd] VERBOSE events at {m} already recorded in RRD")
|
||||
return False
|
||||
|
||||
tpl = ""
|
||||
@@ -281,7 +281,7 @@ class LogParser:
|
||||
for p in range(self.lupdates[fname] + rrdstep, m, rrdstep):
|
||||
self.add_point_to_rrd(fname, tpl, values, ts=p)
|
||||
|
||||
values = "%s" % m
|
||||
values = f"{m}"
|
||||
tpl = ""
|
||||
for v in variables:
|
||||
values += ":"
|
||||
@@ -356,7 +356,7 @@ class LogParser:
|
||||
m = self._srs_regex["reverse_srs1"].match(mail_address) if m is None else m
|
||||
|
||||
if m is not None:
|
||||
return "%s@%s" % m.group(2, 1)
|
||||
return "{}@{}".format(*m.group(2, 1))
|
||||
else:
|
||||
return mail_address
|
||||
|
||||
@@ -474,12 +474,10 @@ class LogParser:
|
||||
return False
|
||||
(msg_to, msg_status) = m.groups()
|
||||
if queue_id not in self.workdict:
|
||||
self._dprint(
|
||||
"[parser] inconsistent mail (%s: %s), skipping" % (queue_id, msg_to)
|
||||
)
|
||||
self._dprint(f"[parser] inconsistent mail ({queue_id}: {msg_to}), skipping")
|
||||
return True
|
||||
if msg_status not in variables:
|
||||
self._dprint("[parser] unsupported status %s, skipping" % msg_status)
|
||||
self._dprint(f"[parser] unsupported status {msg_status}, skipping")
|
||||
return True
|
||||
|
||||
# orig_to is optional.
|
||||
@@ -564,7 +562,7 @@ class LogParser:
|
||||
try:
|
||||
parser = getattr(self, f"_parse_{prog}")
|
||||
if not parser(log, host, pid, subprog):
|
||||
self._dprint("[parser] ignoring %r log: %r" % (prog, log))
|
||||
self._dprint(f"[parser] ignoring {prog!r} log: {log!r}")
|
||||
except AttributeError:
|
||||
self._dprint(f'[parser] no log handler for "{prog}": {log}')
|
||||
|
||||
@@ -579,11 +577,11 @@ class LogParser:
|
||||
for line in fp:
|
||||
self._parse_line(line)
|
||||
except OSError as errno:
|
||||
self._dprint("%s" % errno)
|
||||
self._dprint(f"{errno}")
|
||||
sys.exit(1)
|
||||
|
||||
for dom, data in self.data.items():
|
||||
self._dprint("[rrd] dealing with domain %s" % dom)
|
||||
self._dprint(f"[rrd] dealing with domain {dom}")
|
||||
for t in sorted(data.keys()):
|
||||
self.update_rrd(dom, t)
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ class MaillogParser:
|
||||
m = self._srs_regex["reverse_srs1"].match(mail_address) if m is None else m
|
||||
|
||||
if m is not None:
|
||||
return "%s@%s" % m.group(2, 1)
|
||||
return "{}@{}".format(*m.group(2, 1))
|
||||
return mail_address
|
||||
|
||||
def new_domain_event(self, domain, name, size=None):
|
||||
@@ -221,9 +221,7 @@ class MaillogParser:
|
||||
return False
|
||||
(msg_to, msg_status) = m.groups()
|
||||
if queue_id not in self.workdict:
|
||||
self._dprint(
|
||||
"[parser] inconsistent mail (%s: %s), skipping" % (queue_id, msg_to)
|
||||
)
|
||||
self._dprint(f"[parser] inconsistent mail ({queue_id}: {msg_to}), skipping")
|
||||
return True
|
||||
|
||||
# orig_to is optional.
|
||||
@@ -270,16 +268,16 @@ class MaillogParser:
|
||||
try:
|
||||
parser = getattr(self, f"_parse_{prog}")
|
||||
if not parser(log, host, pid, subprog):
|
||||
self._dprint("[parser] ignoring %r log: %r" % (prog, log))
|
||||
self._dprint(f"[parser] ignoring {prog!r} log: {log!r}")
|
||||
except AttributeError:
|
||||
self._dprint('[parser] no log handler for "%r": %r' % (prog, log))
|
||||
self._dprint(f'[parser] no log handler for "{prog!r}": {log!r}')
|
||||
|
||||
def parse(self, logfile):
|
||||
"""Process the log file."""
|
||||
try:
|
||||
fp = open(logfile, encoding="utf-8")
|
||||
except OSError as errno:
|
||||
self._dprint("%s" % errno)
|
||||
self._dprint(f"{errno}")
|
||||
return
|
||||
|
||||
for line in fp.readlines():
|
||||
|
||||
@@ -19,7 +19,7 @@ class RunCommandsMixin:
|
||||
"""Mixin to run management commands."""
|
||||
|
||||
def setUp(self):
|
||||
super(RunCommandsMixin, self).setUp()
|
||||
super().setUp()
|
||||
self.workdir = tempfile.mkdtemp()
|
||||
self.set_global_parameter("rrd_rootdir", self.workdir)
|
||||
|
||||
@@ -54,12 +54,12 @@ class ViewsTestCase(RunCommandsMixin, ModoTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls): # noqa
|
||||
super(ViewsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
cls.da = core_models.User.objects.get(username="admin@test.com")
|
||||
|
||||
def tearDown(self):
|
||||
super(ViewsTestCase, self).tearDown()
|
||||
super().tearDown()
|
||||
self.set_global_parameter("greylist", False)
|
||||
|
||||
def test_index(self):
|
||||
@@ -139,7 +139,7 @@ class ManagementCommandsTestCase(RunCommandsMixin, ModoTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls): # noqa
|
||||
super(ManagementCommandsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
|
||||
def test_logparser(self):
|
||||
|
||||
@@ -75,12 +75,12 @@ def graphs(request):
|
||||
start = request.GET["start"]
|
||||
end = request.GET["end"]
|
||||
expr = re.compile(r"[:\- ]")
|
||||
period_name = "%s_%s" % (expr.sub("", start), expr.sub("", end))
|
||||
period_name = "{}_{}".format(expr.sub("", start), expr.sub("", end))
|
||||
start = date_to_timestamp(expr.split(start))
|
||||
end = date_to_timestamp(expr.split(end))
|
||||
else:
|
||||
end = int(time.mktime(time.localtime()))
|
||||
start = "-1%s" % period
|
||||
start = f"-1{period}"
|
||||
period_name = period
|
||||
|
||||
tplvars["domain_selector"] = graph_sets[gset].domain_selector
|
||||
|
||||
@@ -21,7 +21,7 @@ class GenericParametersForm(forms.Form):
|
||||
|
||||
kwargs["prefix"] = self.app
|
||||
load_values_from_db = kwargs.pop("load_values_from_db", True)
|
||||
super(GenericParametersForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self._add_dynamic_fields()
|
||||
|
||||
@@ -36,8 +36,8 @@ class GenericParametersForm(forms.Form):
|
||||
"""Add visibility rules to this form."""
|
||||
for key, rule in list(rules.items()):
|
||||
field, value = rule.split("=")
|
||||
visibility = {"field": "id_%s-%s" % (self.app, field), "value": value}
|
||||
self.visirules["%s-%s" % (self.app, key)] = visibility
|
||||
visibility = {"field": f"id_{self.app}-{field}", "value": value}
|
||||
self.visirules[f"{self.app}-{key}"] = visibility
|
||||
|
||||
def _add_dynamic_fields(self):
|
||||
"""Add dynamic fields to this form."""
|
||||
@@ -60,7 +60,7 @@ class AdminParametersForm(GenericParametersForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Store LocalConfig instance."""
|
||||
self.localconfig = kwargs.pop("localconfig", None)
|
||||
super(AdminParametersForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _load_initial_values(self):
|
||||
"""Load form initial values from database."""
|
||||
@@ -92,7 +92,7 @@ class UserParametersForm(GenericParametersForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.user = kwargs.pop("user", None)
|
||||
super(UserParametersForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _load_initial_values(self):
|
||||
"""Load initial values from User instance."""
|
||||
|
||||
@@ -308,7 +308,7 @@ class ParametersForm(param_forms.AdminParametersForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Set initial values."""
|
||||
super(ParametersForm, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
if not self.fields["webpanel_url"].initial:
|
||||
url = f"https://{self.hostname}{settings.LOGIN_URL}"
|
||||
self.fields["webpanel_url"].initial = url
|
||||
|
||||
@@ -19,12 +19,12 @@ class EventsTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create some data."""
|
||||
super(EventsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.DomainFactory(name="test.com")
|
||||
|
||||
def setUp(self):
|
||||
"""Create temp. directory to store files."""
|
||||
super(EventsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.workdir = tempfile.mkdtemp()
|
||||
self.set_global_parameter("storage_dir", self.workdir)
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class ARMessageViewSetTestCase(ModoAPITestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
super(ARMessageViewSetTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
cls.account = User.objects.get(username="user@test.com")
|
||||
cls.account2 = User.objects.get(username="user@test2.com")
|
||||
|
||||
@@ -150,7 +150,7 @@ Best regards,
|
||||
try:
|
||||
tpl % {"name": "Antoine Nguyen"}
|
||||
except (KeyError, ValueError):
|
||||
raise forms.ValidationError(gettext_lazy("Invalid syntax"))
|
||||
raise forms.ValidationError(gettext_lazy("Invalid syntax")) from None
|
||||
return tpl
|
||||
|
||||
|
||||
|
||||
@@ -92,15 +92,13 @@ def extra_js(sender, caller, st_type, user, **kwargs):
|
||||
"""Add static content."""
|
||||
if caller != "user_index" or st_type != "js":
|
||||
return ""
|
||||
return """function autoreply_cb() {
|
||||
$('.datefield').datetimepicker({
|
||||
return f"""function autoreply_cb() {{
|
||||
$('.datefield').datetimepicker({{
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
locale: '%(lang)s'
|
||||
});
|
||||
}
|
||||
""" % {
|
||||
"lang": user.language
|
||||
}
|
||||
locale: '{user.language}'
|
||||
}});
|
||||
}}
|
||||
"""
|
||||
|
||||
|
||||
@receiver(core_signals.extra_user_menu_entries)
|
||||
|
||||
@@ -111,7 +111,7 @@ class EventsTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(EventsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
|
||||
def test_domain_created_event(self):
|
||||
@@ -241,12 +241,12 @@ class FormTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(FormTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
|
||||
def setUp(self):
|
||||
"""Initialize tests."""
|
||||
super(FormTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.client.logout()
|
||||
self.client.login(username="user@test.com", password="toto")
|
||||
|
||||
@@ -314,7 +314,7 @@ class RepairTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create some data."""
|
||||
super(RepairTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
|
||||
def test_management_command(self):
|
||||
@@ -342,13 +342,13 @@ class ManagementCommandTestCase(ModoTestCase):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create some data."""
|
||||
super(ManagementCommandTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
cls.account = User.objects.get(username="user@test.com")
|
||||
|
||||
def setUp(self):
|
||||
"""Replace stdin."""
|
||||
super(ManagementCommandTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.stdin = sys.stdin
|
||||
sys.stdin = StringIO(SIMPLE_EMAIL_CONTENT.strip())
|
||||
self.arm = factories.ARmessageFactory(mbox=self.account.mailbox)
|
||||
|
||||
@@ -14,7 +14,7 @@ class DataMixin:
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
super(DataMixin, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
transport = tr_factories.TransportFactory(
|
||||
pattern="test.com",
|
||||
_settings={
|
||||
|
||||
@@ -52,7 +52,7 @@ class RelayDomainFormGeneral(tr_forms.TransportForm):
|
||||
# We don't want to recreate the transport we just deleted it
|
||||
# (post_save signal).
|
||||
return None
|
||||
instance = super(RelayDomainFormGeneral, self).save()
|
||||
instance = super().save()
|
||||
instance.pattern = domain.name
|
||||
instance.save()
|
||||
if not domain.transport:
|
||||
|
||||
@@ -48,7 +48,7 @@ class Operations:
|
||||
else:
|
||||
aliases.remove(name)
|
||||
for cpt, alias in enumerate(aliases):
|
||||
fname = "aliases" if not cpt else "aliases_%d" % cpt
|
||||
fname = "aliases" if not cpt else f"aliases_{cpt}"
|
||||
values[fname] = alias
|
||||
return self.ajax_post(
|
||||
reverse("admin:domain_change", args=[domain.id]), values, status
|
||||
@@ -65,7 +65,7 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(RelayDomainsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
cls.transport = tr_factories.TransportFactory(
|
||||
pattern="relaydomain.tld",
|
||||
@@ -277,7 +277,7 @@ class LimitsTestCase(ModoTestCase, Operations):
|
||||
@classmethod
|
||||
def setUpTestData(cls): # NOQA:N802
|
||||
"""Create test data."""
|
||||
super(LimitsTestCase, cls).setUpTestData()
|
||||
super().setUpTestData()
|
||||
for name, _definition in limits_utils.get_user_limit_templates():
|
||||
cls.localconfig.parameters.set_value(
|
||||
f"deflt_user_{name}_limit", 2, app="limits"
|
||||
@@ -287,7 +287,7 @@ class LimitsTestCase(ModoTestCase, Operations):
|
||||
|
||||
def setUp(self):
|
||||
"""Initialize test."""
|
||||
super(LimitsTestCase, self).setUp()
|
||||
super().setUp()
|
||||
self.client.force_login(self.user)
|
||||
|
||||
def test_relay_domains_limit(self):
|
||||
|
||||
@@ -76,7 +76,7 @@ class SieveClient:
|
||||
|
||||
def pushscript(self, name: str, content: str, active: bool = False) -> None:
|
||||
if not self.msc.havespace(name, len(content)):
|
||||
error = "%s (%s)" % (_("Not enough space on server"), self.msc.errmsg)
|
||||
error = "{} ({})".format(_("Not enough space on server"), self.msc.errmsg)
|
||||
raise SieveClientError(error)
|
||||
if not self.msc.putscript(name, content):
|
||||
raise SieveClientError(self.msc.errmsg.decode())
|
||||
|
||||
@@ -82,25 +82,25 @@ def build_header(filename, disposition="attachment", filename_compat=None):
|
||||
rv = disposition
|
||||
|
||||
if is_token(filename):
|
||||
rv += "; filename=%s" % (filename,)
|
||||
rv += f"; filename={filename}"
|
||||
return rv
|
||||
elif is_ascii(filename) and is_lws_safe(filename):
|
||||
qd_filename = qd_quote(filename)
|
||||
rv += '; filename="%s"' % (qd_filename,)
|
||||
rv += f'; filename="{qd_filename}"'
|
||||
if qd_filename == filename:
|
||||
# RFC 6266 claims some implementations are iffy on qdtext's
|
||||
# backslash-escaping, we'll include filename* in that case.
|
||||
return rv
|
||||
elif filename_compat:
|
||||
if is_token(filename_compat):
|
||||
rv += "; filename=%s" % (filename_compat,)
|
||||
rv += f"; filename={filename_compat}"
|
||||
else:
|
||||
assert is_lws_safe(filename_compat)
|
||||
rv += '; filename="%s"' % (qd_quote(filename_compat),)
|
||||
rv += f'; filename="{qd_quote(filename_compat)}"'
|
||||
|
||||
# alnum are already considered always-safe, but the rest isn't.
|
||||
# Python encodes ~ when it shouldn't, for example.
|
||||
rv += "; filename*=utf-8''%s" % (
|
||||
rv += "; filename*=utf-8''{}".format(
|
||||
percent_encode(filename, safe=attr_chars_nonalnum, encoding="utf-8"),
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -120,4 +120,4 @@ version = {attr = "modoboa.version.get_version"}
|
||||
exclude = ["migrations"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E4", "E7", "E9", "F", "Q"]
|
||||
select = ["E4", "E7", "E9", "F", "B", "Q", "UP"]
|
||||
|
||||
Reference in New Issue
Block a user