From fe9b228aaa92a97a8f5638bc422fb19127bd01da Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 13 Jan 2015 20:19:08 +0100 Subject: [PATCH 01/24] PEP8 fixes and module renames. --- modoboa/core/app_settings.py | 2 +- modoboa/core/models.py | 2 +- modoboa/extensions/admin/app_settings.py | 2 +- modoboa/extensions/admin/forms/account.py | 2 +- modoboa/extensions/admin/forms/alias.py | 2 +- modoboa/extensions/admin/forms/domain.py | 2 +- modoboa/extensions/amavis/app_settings.py | 2 +- modoboa/extensions/amavis/forms.py | 2 +- modoboa/extensions/limits/app_settings.py | 2 +- .../postfix_autoreply/app_settings.py | 2 +- .../postfix_autoreply/general_callbacks.py | 2 +- .../postfix_relay_domains/app_settings.py | 2 +- .../extensions/postfix_relay_domains/forms.py | 2 +- modoboa/extensions/radicale/app_settings.py | 2 +- modoboa/extensions/radicale/forms.py | 2 +- .../extensions/sievefilters/app_settings.py | 2 +- modoboa/extensions/stats/app_settings.py | 2 +- modoboa/extensions/webmail/app_settings.py | 2 +- modoboa/lib/authbackends.py | 5 ++ modoboa/lib/events.py | 5 +- modoboa/lib/{formutils.py => form_utils.py} | 54 +++++++++++-------- modoboa/lib/{ldaputils.py => ldap_utils.py} | 0 modoboa/lib/parameters.py | 10 ++-- modoboa/lib/templatetags/form_tags.py | 2 +- 24 files changed, 65 insertions(+), 47 deletions(-) rename modoboa/lib/{formutils.py => form_utils.py} (94%) rename modoboa/lib/{ldaputils.py => ldap_utils.py} (100%) diff --git a/modoboa/core/app_settings.py b/modoboa/core/app_settings.py index f05e4028c..706639340 100644 --- a/modoboa/core/app_settings.py +++ b/modoboa/core/app_settings.py @@ -2,7 +2,7 @@ from django import forms from django.conf import settings from django.utils.translation import ugettext as _, ugettext_lazy -from modoboa.lib.formutils import YesNoField, SeparatorField, InlineRadioSelect +from modoboa.lib.form_utils import YesNoField, SeparatorField, InlineRadioSelect from modoboa.lib.cryptutils import random_key from modoboa.lib import parameters diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 57faece90..29f3be872 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -24,7 +24,7 @@ from modoboa.core.extensions import exts_pool from modoboa.core.password_hashers import get_password_hasher try: - from modoboa.lib.ldaputils import LDAPAuthBackend + from modoboa.lib.ldap_utils import LDAPAuthBackend ldap_available = True except ImportError: ldap_available = False diff --git a/modoboa/extensions/admin/app_settings.py b/modoboa/extensions/admin/app_settings.py index 3f27d114f..8638bce9e 100644 --- a/modoboa/extensions/admin/app_settings.py +++ b/modoboa/extensions/admin/app_settings.py @@ -1,7 +1,7 @@ from django import forms from django.conf import settings from django.utils.translation import ugettext_lazy -from modoboa.lib.formutils import YesNoField, SeparatorField +from modoboa.lib.form_utils import YesNoField, SeparatorField from modoboa.lib.sysutils import exec_cmd from modoboa.lib import parameters import os diff --git a/modoboa/extensions/admin/forms/account.py b/modoboa/extensions/admin/forms/account.py index 24aca55ca..5ddc27359 100644 --- a/modoboa/extensions/admin/forms/account.py +++ b/modoboa/extensions/admin/forms/account.py @@ -6,7 +6,7 @@ from modoboa.lib import events, parameters from modoboa.lib.exceptions import PermDeniedException, Conflict, NotFound from modoboa.lib.permissions import get_account_roles from modoboa.lib.emailutils import split_mailbox -from modoboa.lib.formutils import ( +from modoboa.lib.form_utils import ( DomainNameField, DynamicForm, TabForms, WizardForm ) from modoboa.lib.webutils import render_to_json_response diff --git a/modoboa/extensions/admin/forms/alias.py b/modoboa/extensions/admin/forms/alias.py index 9de56daed..5ba3471fd 100644 --- a/modoboa/extensions/admin/forms/alias.py +++ b/modoboa/extensions/admin/forms/alias.py @@ -3,7 +3,7 @@ from django.utils.translation import ugettext as _, ugettext_lazy from django.http import QueryDict from modoboa.lib.exceptions import BadRequest, NotFound, Conflict from modoboa.lib.emailutils import split_mailbox -from modoboa.lib.formutils import ( +from modoboa.lib.form_utils import ( DynamicForm ) from modoboa.extensions.admin.models import ( diff --git a/modoboa/extensions/admin/forms/domain.py b/modoboa/extensions/admin/forms/domain.py index e9efb0c78..b8a9879fd 100644 --- a/modoboa/extensions/admin/forms/domain.py +++ b/modoboa/extensions/admin/forms/domain.py @@ -5,7 +5,7 @@ from django.core.urlresolvers import reverse from modoboa.lib import events, parameters from modoboa.lib.exceptions import ModoboaException, Conflict -from modoboa.lib.formutils import ( +from modoboa.lib.form_utils import ( DomainNameField, YesNoField, WizardForm, DynamicForm, TabForms ) from modoboa.lib.webutils import render_to_json_response diff --git a/modoboa/extensions/amavis/app_settings.py b/modoboa/extensions/amavis/app_settings.py index 2fa1957cf..572d31d99 100644 --- a/modoboa/extensions/amavis/app_settings.py +++ b/modoboa/extensions/amavis/app_settings.py @@ -3,7 +3,7 @@ from django import forms from django.utils.translation import ugettext_lazy as _ -from modoboa.lib.formutils import SeparatorField, YesNoField, InlineRadioSelect +from modoboa.lib.form_utils import SeparatorField, YesNoField, InlineRadioSelect from modoboa.lib.parameters import AdminParametersForm, UserParametersForm diff --git a/modoboa/extensions/amavis/forms.py b/modoboa/extensions/amavis/forms.py index 72be441e9..cdf4489df 100644 --- a/modoboa/extensions/amavis/forms.py +++ b/modoboa/extensions/amavis/forms.py @@ -7,7 +7,7 @@ from django import forms from django.utils.translation import ugettext as _ from modoboa.lib import parameters -from modoboa.lib.formutils import InlineRadioSelect +from modoboa.lib.form_utils import InlineRadioSelect from .models import Policy, Users diff --git a/modoboa/extensions/limits/app_settings.py b/modoboa/extensions/limits/app_settings.py index 8b149a75f..6f423507f 100644 --- a/modoboa/extensions/limits/app_settings.py +++ b/modoboa/extensions/limits/app_settings.py @@ -1,7 +1,7 @@ from django import forms from django.utils.translation import ugettext_lazy as _ from modoboa.lib.parameters import AdminParametersForm -from modoboa.lib.formutils import SeparatorField +from modoboa.lib.form_utils import SeparatorField class ParametersForm(AdminParametersForm): diff --git a/modoboa/extensions/postfix_autoreply/app_settings.py b/modoboa/extensions/postfix_autoreply/app_settings.py index b5d74d99c..c19933cee 100644 --- a/modoboa/extensions/postfix_autoreply/app_settings.py +++ b/modoboa/extensions/postfix_autoreply/app_settings.py @@ -2,7 +2,7 @@ from django.utils.translation import ugettext_lazy from django import forms from modoboa.lib.parameters import AdminParametersForm -from modoboa.lib.formutils import SeparatorField +from modoboa.lib.form_utils import SeparatorField class ParametersForm(AdminParametersForm): diff --git a/modoboa/extensions/postfix_autoreply/general_callbacks.py b/modoboa/extensions/postfix_autoreply/general_callbacks.py index eb1417088..3b1555c70 100644 --- a/modoboa/extensions/postfix_autoreply/general_callbacks.py +++ b/modoboa/extensions/postfix_autoreply/general_callbacks.py @@ -103,7 +103,7 @@ def extra_mailform_fields(form_name, mailbox=None): :param str form_name: form name (must be 'mailform') :param Mailbox mailbox: mailbox """ - from modoboa.lib.formutils import YesNoField + from modoboa.lib.form_utils import YesNoField if form_name != "mailform": return [] diff --git a/modoboa/extensions/postfix_relay_domains/app_settings.py b/modoboa/extensions/postfix_relay_domains/app_settings.py index 107a16979..80cfc6a4d 100644 --- a/modoboa/extensions/postfix_relay_domains/app_settings.py +++ b/modoboa/extensions/postfix_relay_domains/app_settings.py @@ -6,7 +6,7 @@ from django import forms from django.utils.translation import ugettext_lazy from modoboa.lib import parameters -from modoboa.lib.formutils import SeparatorField +from modoboa.lib.form_utils import SeparatorField class AdminParametersForm(parameters.AdminParametersForm): diff --git a/modoboa/extensions/postfix_relay_domains/forms.py b/modoboa/extensions/postfix_relay_domains/forms.py index 001992539..a93683fb1 100644 --- a/modoboa/extensions/postfix_relay_domains/forms.py +++ b/modoboa/extensions/postfix_relay_domains/forms.py @@ -6,7 +6,7 @@ from django.http import QueryDict from django.utils.translation import ugettext as _, ugettext_lazy from django.core.urlresolvers import reverse from modoboa.lib import events -from modoboa.lib.formutils import DynamicForm, DomainNameField, TabForms +from modoboa.lib.form_utils import DynamicForm, DomainNameField, TabForms from modoboa.lib.webutils import render_to_json_response from modoboa.extensions.admin.models import Domain, DomainAlias from .models import RelayDomain, RelayDomainAlias diff --git a/modoboa/extensions/radicale/app_settings.py b/modoboa/extensions/radicale/app_settings.py index 2e7991f2a..80a6f10f8 100644 --- a/modoboa/extensions/radicale/app_settings.py +++ b/modoboa/extensions/radicale/app_settings.py @@ -1,7 +1,7 @@ from django.utils.translation import ugettext_lazy from django import forms from modoboa.lib.parameters import AdminParametersForm -from modoboa.lib.formutils import SeparatorField, YesNoField +from modoboa.lib.form_utils import SeparatorField, YesNoField class ParametersForm(AdminParametersForm): diff --git a/modoboa/extensions/radicale/forms.py b/modoboa/extensions/radicale/forms.py index 4e84979a1..11a9b1e87 100644 --- a/modoboa/extensions/radicale/forms.py +++ b/modoboa/extensions/radicale/forms.py @@ -5,7 +5,7 @@ from django import forms from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _, ugettext_lazy from modoboa.lib.webutils import render_to_json_response -from modoboa.lib.formutils import WizardForm, TabForms, DynamicForm +from modoboa.lib.form_utils import WizardForm, TabForms, DynamicForm from modoboa.extensions.admin.models import Domain, Mailbox from modoboa.extensions.radicale.models import UserCalendar, SharedCalendar diff --git a/modoboa/extensions/sievefilters/app_settings.py b/modoboa/extensions/sievefilters/app_settings.py index 0d6547559..c3d1cbb4d 100644 --- a/modoboa/extensions/sievefilters/app_settings.py +++ b/modoboa/extensions/sievefilters/app_settings.py @@ -3,7 +3,7 @@ from django.utils.translation import ugettext_lazy as _ from django import forms from sievelib.managesieve import SUPPORTED_AUTH_MECHS from modoboa.lib.parameters import AdminParametersForm, UserParametersForm -from modoboa.lib.formutils import SeparatorField, YesNoField, InlineRadioSelect +from modoboa.lib.form_utils import SeparatorField, YesNoField, InlineRadioSelect def supported_auth_mechs(): diff --git a/modoboa/extensions/stats/app_settings.py b/modoboa/extensions/stats/app_settings.py index 84afb8f3b..9c48d156e 100644 --- a/modoboa/extensions/stats/app_settings.py +++ b/modoboa/extensions/stats/app_settings.py @@ -2,7 +2,7 @@ from django.utils.translation import ugettext_lazy from django import forms from modoboa.lib.parameters import AdminParametersForm -from modoboa.lib.formutils import SeparatorField +from modoboa.lib.form_utils import SeparatorField class ParametersForm(AdminParametersForm): diff --git a/modoboa/extensions/webmail/app_settings.py b/modoboa/extensions/webmail/app_settings.py index eca4f4570..1fee71d06 100644 --- a/modoboa/extensions/webmail/app_settings.py +++ b/modoboa/extensions/webmail/app_settings.py @@ -2,7 +2,7 @@ from django import forms from django.utils.translation import ugettext_lazy as _ from modoboa.lib.parameters import AdminParametersForm, UserParametersForm -from modoboa.lib.formutils import SeparatorField, YesNoField, InlineRadioSelect +from modoboa.lib.form_utils import SeparatorField, YesNoField, InlineRadioSelect class ParametersForm(AdminParametersForm): diff --git a/modoboa/lib/authbackends.py b/modoboa/lib/authbackends.py index c08555a4e..565c8a03e 100644 --- a/modoboa/lib/authbackends.py +++ b/modoboa/lib/authbackends.py @@ -1,4 +1,7 @@ +"""Custom authentication backends.""" + from django.contrib.auth.backends import ModelBackend + from modoboa.core.models import User from modoboa.lib import parameters from modoboa.lib.emailutils import split_mailbox @@ -6,6 +9,8 @@ from modoboa.lib.emailutils import split_mailbox class SimpleBackend(ModelBackend): + """Simple authentication backend.""" + def authenticate(self, username=None, password=None): try: user = User.objects.get(username=username) diff --git a/modoboa/lib/events.py b/modoboa/lib/events.py index cd574b412..13c447af3 100644 --- a/modoboa/lib/events.py +++ b/modoboa/lib/events.py @@ -8,12 +8,15 @@ This module provides a simple way of managing events between Modoboa core application and additional components. """ -from functools import wraps import inspect import re +from functools import wraps + from django.conf import settings + from modoboa.lib.sysutils import guess_extension_name + events = [] callbacks = {} diff --git a/modoboa/lib/formutils.py b/modoboa/lib/form_utils.py similarity index 94% rename from modoboa/lib/formutils.py rename to modoboa/lib/form_utils.py index 9c75761b2..1af386b50 100644 --- a/modoboa/lib/formutils.py +++ b/modoboa/lib/form_utils.py @@ -1,24 +1,28 @@ # coding: utf-8 -import re -import abc -from django.shortcuts import render -from django.utils.translation import ugettext as _, ugettext_lazy -from django.forms import ChoiceField -from django.forms.widgets import RadioSelect, RadioInput -from django.forms.fields import CharField, Field +"""Form management utilities.""" + +import abc +import re + from django.core.exceptions import ValidationError +from django.forms import ChoiceField +from django.forms.fields import CharField, Field +from django.forms.widgets import RadioSelect, RadioInput +from django.shortcuts import render from django.utils.encoding import force_unicode -from django.utils.safestring import mark_safe from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _, ugettext_lazy from modoboa.lib.exceptions import BadRequest from modoboa.lib.webutils import render_to_json_response class WizardStep(object): - """A wizard step. - """ + + """A wizard step.""" + def __init__(self, cls, title, formtpl=None, new_args=None): """Constructor. @@ -65,8 +69,9 @@ class WizardStep(object): class WizardForm(object): - """Custom wizard. - """ + + """Custom wizard.""" + __metaclass__ = abc.ABCMeta template_name = "common/wizard_forms.html" @@ -159,12 +164,15 @@ class WizardForm(object): class DynamicForm(object): - """A form which accepts dynamic fields. + + """ + A form which accepts dynamic fields. We consider a field to be dynamic when it can appear multiple times within the same request. """ + def _create_field(self, typ, name, value=None, pos=None): """Create a new form field. """ @@ -222,8 +230,9 @@ class TabForms(object): args.append(request.POST) if instances is not None: self.instances = instances - if hasattr(self, "check_%s" % fd["id"]): - if not getattr(self, "check_%s" % fd["id"])(instances[fd["id"]]): + mname = "check_%s" % fd["id"] + if hasattr(self, mname): + if not getattr(self, mname)(instances[fd["id"]]): to_remove += [fd] continue kwargs["instance"] = instances[fd["id"]] @@ -231,7 +240,7 @@ class TabForms(object): fd["instance"] = classes[fd["id"]](*args, **kwargs) else: fd["instance"] = fd["cls"](*args, **kwargs) - self.forms = [form for form in self.forms if not form in to_remove] + self.forms = [form for form in self.forms if form not in to_remove] if self.forms: self.active_id = self.forms[0]["id"] @@ -263,10 +272,9 @@ class TabForms(object): to_remove = [] for f in self.forms: if mandatory_only and \ - (not 'mandatory' in f or not f["mandatory"]): + ('mandatory' not in f or not f["mandatory"]): continue - elif optional_only and \ - ('mandatory' in f and f["mandatory"]): + elif optional_only and ('mandatory' in f and f["mandatory"]): continue if not self._before_is_valid(f): to_remove.append(f) @@ -274,7 +282,7 @@ class TabForms(object): if not f["instance"].is_valid(): self.active_id = f["id"] return False - self.forms = [f for f in self.forms if not f in to_remove] + self.forms = [f for f in self.forms if f not in to_remove] return True @abc.abstractmethod @@ -334,11 +342,11 @@ class TabForms(object): def is_valid_host(host): - """IDN compatible domain validator - """ + """IDN compatible domain validator.""" host = host.encode('idna').lower() if not hasattr(is_valid_host, '_re'): - is_valid_host._re = re.compile(r'^([0-9a-z][-\w]*[0-9a-z]\.)+[a-z0-9\-]{2,15}$') + is_valid_host._re = re.compile( + r'^([0-9a-z][-\w]*[0-9a-z]\.)+[a-z0-9\-]{2,15}$') return bool(is_valid_host._re.match(host)) diff --git a/modoboa/lib/ldaputils.py b/modoboa/lib/ldap_utils.py similarity index 100% rename from modoboa/lib/ldaputils.py rename to modoboa/lib/ldap_utils.py diff --git a/modoboa/lib/parameters.py b/modoboa/lib/parameters.py index b682501bf..5ad4862c5 100644 --- a/modoboa/lib/parameters.py +++ b/modoboa/lib/parameters.py @@ -9,9 +9,11 @@ will be available and modifiable directly from the web interface. Only super users will be able to access this part of the web interface. """ from django import forms + from modoboa.lib import events -from modoboa.lib.sysutils import guess_extension_name from modoboa.lib.exceptions import ModoboaException +from modoboa.lib.sysutils import guess_extension_name + _params = {'A': {}, 'U': {}} @@ -92,7 +94,7 @@ class AdminParametersForm(GenericParametersForm): def save(self): from .models import Parameter - from modoboa.lib.formutils import SeparatorField + from modoboa.lib.form_utils import SeparatorField for name, value in self.cleaned_data.items(): if type(self.fields[name]) is SeparatorField: @@ -138,7 +140,7 @@ class UserParametersForm(GenericParametersForm): def save(self): from .models import UserParameter - from modoboa.lib.formutils import SeparatorField + from modoboa.lib.form_utils import SeparatorField for name, value in self.cleaned_data.items(): if type(self.fields[name]) is SeparatorField: @@ -162,7 +164,7 @@ def register(formclass, label): :param formclass: a form class :param string label: the label to display in parameters or settings pages """ - from modoboa.lib.formutils import SeparatorField + from modoboa.lib.form_utils import SeparatorField if issubclass(formclass, AdminParametersForm): level = 'A' diff --git a/modoboa/lib/templatetags/form_tags.py b/modoboa/lib/templatetags/form_tags.py index e29091907..cd8bf8a87 100644 --- a/modoboa/lib/templatetags/form_tags.py +++ b/modoboa/lib/templatetags/form_tags.py @@ -6,7 +6,7 @@ from django import forms from django import template from django.template.loader import render_to_string -from modoboa.lib.formutils import SeparatorField +from modoboa.lib.form_utils import SeparatorField register = template.Library() From 2e448a668206d0815b67235cd48ce3e890d9dec1 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 13 Jan 2015 21:27:31 +0100 Subject: [PATCH 02/24] PEP8 fixes and module renames. --- modoboa/core/views/admin.py | 2 +- modoboa/core/views/auth.py | 2 +- modoboa/core/views/user.py | 2 +- modoboa/demo/__init__.py | 2 +- modoboa/demo/views.py | 4 +-- modoboa/extensions/admin/__init__.py | 2 +- modoboa/extensions/admin/forms/account.py | 6 ++-- modoboa/extensions/admin/forms/alias.py | 2 +- modoboa/extensions/admin/forms/domain.py | 2 +- modoboa/extensions/admin/forms/forward.py | 2 +- modoboa/extensions/admin/lib.py | 2 +- modoboa/extensions/admin/models/alias.py | 2 +- .../admin/templatetags/admin_tags.py | 2 +- modoboa/extensions/admin/views/alias.py | 2 +- modoboa/extensions/admin/views/domain.py | 2 +- modoboa/extensions/admin/views/identity.py | 2 +- modoboa/extensions/admin/views/user.py | 2 +- modoboa/extensions/amavis/lib.py | 4 +-- .../amavis/management/commands/amnotify.py | 2 +- modoboa/extensions/amavis/sql_email.py | 2 +- modoboa/extensions/amavis/views.py | 2 +- .../management/commands/autoreply.py | 2 +- modoboa/extensions/postfix_autoreply/views.py | 2 +- .../extensions/postfix_relay_domains/forms.py | 2 +- .../extensions/postfix_relay_domains/views.py | 2 +- modoboa/extensions/radicale/forms.py | 4 +-- .../radicale/templatetags/radicale_tags.py | 2 +- modoboa/extensions/radicale/views.py | 2 +- .../templatetags/sfilters_tags.py | 2 +- modoboa/extensions/sievefilters/views.py | 2 +- modoboa/extensions/stats/views.py | 2 +- modoboa/extensions/webmail/forms.py | 2 +- modoboa/extensions/webmail/lib/attachments.py | 2 +- modoboa/extensions/webmail/lib/imapemail.py | 2 +- modoboa/extensions/webmail/lib/imapheader.py | 2 +- modoboa/extensions/webmail/lib/imaputils.py | 2 +- modoboa/extensions/webmail/lib/sendmail.py | 4 +-- modoboa/extensions/webmail/lib/utils.py | 2 +- modoboa/extensions/webmail/views.py | 2 +- modoboa/lib/authbackends.py | 2 +- modoboa/lib/connections.py | 7 +++-- modoboa/lib/{emailutils.py => email_utils.py} | 30 ++++++++++++------- modoboa/lib/form_utils.py | 2 +- modoboa/lib/middleware.py | 22 +++++++++----- modoboa/lib/{webutils.py => web_utils.py} | 24 ++++++++------- .../commands/migrate_from_postfixadmin.py | 2 +- 46 files changed, 100 insertions(+), 79 deletions(-) rename modoboa/lib/{emailutils.py => email_utils.py} (95%) rename modoboa/lib/{webutils.py => web_utils.py} (97%) diff --git a/modoboa/core/views/admin.py b/modoboa/core/views/admin.py index c45ea3042..a81af1880 100644 --- a/modoboa/core/views/admin.py +++ b/modoboa/core/views/admin.py @@ -15,7 +15,7 @@ from modoboa.core.models import Extension, Log from modoboa.core.utils import new_version_available from modoboa.lib import events, parameters from modoboa.lib.listing import get_sort_order, get_listing_page -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( _render_to_string, render_to_json_response ) diff --git a/modoboa/core/views/auth.py b/modoboa/core/views/auth.py index d49e77211..d46ef3ea2 100644 --- a/modoboa/core/views/auth.py +++ b/modoboa/core/views/auth.py @@ -6,7 +6,7 @@ from django.http import HttpResponse, HttpResponseRedirect from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ from modoboa.lib import events, parameters -from modoboa.lib.webutils import _render_to_string +from modoboa.lib.web_utils import _render_to_string from modoboa.core.forms import LoginForm diff --git a/modoboa/core/views/user.py b/modoboa/core/views/user.py index d3cb2e8ac..3cc2ec53d 100644 --- a/modoboa/core/views/user.py +++ b/modoboa/core/views/user.py @@ -2,7 +2,7 @@ from django.shortcuts import render from django.utils.translation import ugettext as _ from django.contrib.auth.decorators import login_required from modoboa.lib import events, parameters -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( _render_to_string, render_to_json_response ) from modoboa.lib.cryptutils import encrypt diff --git a/modoboa/demo/__init__.py b/modoboa/demo/__init__.py index a9fca9b36..ce86f9830 100755 --- a/modoboa/demo/__init__.py +++ b/modoboa/demo/__init__.py @@ -3,7 +3,7 @@ from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from django.template.loader import render_to_string from modoboa.lib import events -from modoboa.lib.webutils import static_url +from modoboa.lib.web_utils import static_url @events.observe("UserMenuDisplay") diff --git a/modoboa/demo/views.py b/modoboa/demo/views.py index 90c5e5dc1..57f266d85 100755 --- a/modoboa/demo/views.py +++ b/modoboa/demo/views.py @@ -3,8 +3,8 @@ import os from django.conf import settings from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ -from modoboa.lib.webutils import render_to_json_response -from modoboa.lib.emailutils import sendmail_simple, sendmail_fromfile +from modoboa.lib.web_utils import render_to_json_response +from modoboa.lib.email_utils import sendmail_simple, sendmail_fromfile from modoboa.extensions.admin.lib import needs_mailbox diff --git a/modoboa/extensions/admin/__init__.py b/modoboa/extensions/admin/__init__.py index 22979bb6f..75dbd30fc 100644 --- a/modoboa/extensions/admin/__init__.py +++ b/modoboa/extensions/admin/__init__.py @@ -4,7 +4,7 @@ from django.core.urlresolvers import reverse from modoboa.core.extensions import ModoExtension, exts_pool from modoboa.lib import parameters, events from modoboa.lib.exceptions import PermDeniedException, BadRequest, Conflict -from modoboa.lib.emailutils import split_mailbox +from modoboa.lib.email_utils import split_mailbox from modoboa.extensions.admin.models import ( Domain, DomainAlias, Mailbox, Alias ) diff --git a/modoboa/extensions/admin/forms/account.py b/modoboa/extensions/admin/forms/account.py index 5ddc27359..568c0ed25 100644 --- a/modoboa/extensions/admin/forms/account.py +++ b/modoboa/extensions/admin/forms/account.py @@ -5,11 +5,11 @@ from django.core.urlresolvers import reverse from modoboa.lib import events, parameters from modoboa.lib.exceptions import PermDeniedException, Conflict, NotFound from modoboa.lib.permissions import get_account_roles -from modoboa.lib.emailutils import split_mailbox +from modoboa.lib.email_utils import split_mailbox from modoboa.lib.form_utils import ( DomainNameField, DynamicForm, TabForms, WizardForm ) -from modoboa.lib.webutils import render_to_json_response +from modoboa.lib.web_utils import render_to_json_response from modoboa.core.models import User from modoboa.extensions.admin.models import ( Domain, Mailbox, Alias @@ -454,7 +454,7 @@ class AccountWizard(WizardForm): }) def done(self): - from modoboa.lib.webutils import render_to_json_response + from modoboa.lib.web_utils import render_to_json_response account = self.first_step.form.save() account.post_create(self.request.user) diff --git a/modoboa/extensions/admin/forms/alias.py b/modoboa/extensions/admin/forms/alias.py index 5ba3471fd..d66e2820e 100644 --- a/modoboa/extensions/admin/forms/alias.py +++ b/modoboa/extensions/admin/forms/alias.py @@ -2,7 +2,7 @@ from django import forms from django.utils.translation import ugettext as _, ugettext_lazy from django.http import QueryDict from modoboa.lib.exceptions import BadRequest, NotFound, Conflict -from modoboa.lib.emailutils import split_mailbox +from modoboa.lib.email_utils import split_mailbox from modoboa.lib.form_utils import ( DynamicForm ) diff --git a/modoboa/extensions/admin/forms/domain.py b/modoboa/extensions/admin/forms/domain.py index b8a9879fd..6ec676bbf 100644 --- a/modoboa/extensions/admin/forms/domain.py +++ b/modoboa/extensions/admin/forms/domain.py @@ -8,7 +8,7 @@ from modoboa.lib.exceptions import ModoboaException, Conflict from modoboa.lib.form_utils import ( DomainNameField, YesNoField, WizardForm, DynamicForm, TabForms ) -from modoboa.lib.webutils import render_to_json_response +from modoboa.lib.web_utils import render_to_json_response from modoboa.core.models import User from modoboa.extensions.admin.lib import check_if_domain_exists from modoboa.extensions.admin.models import ( diff --git a/modoboa/extensions/admin/forms/forward.py b/modoboa/extensions/admin/forms/forward.py index 63de1ee5c..f39a5ce5e 100644 --- a/modoboa/extensions/admin/forms/forward.py +++ b/modoboa/extensions/admin/forms/forward.py @@ -1,7 +1,7 @@ from django import forms from django.utils.translation import ugettext as _, ugettext_lazy from modoboa.lib.exceptions import BadRequest, PermDeniedException -from modoboa.lib.emailutils import split_mailbox +from modoboa.lib.email_utils import split_mailbox from modoboa.extensions.admin.models import ( Domain ) diff --git a/modoboa/extensions/admin/lib.py b/modoboa/extensions/admin/lib.py index 5b68e1273..decb4a804 100644 --- a/modoboa/extensions/admin/lib.py +++ b/modoboa/extensions/admin/lib.py @@ -7,7 +7,7 @@ from django.utils.translation import ugettext as _ from modoboa.core.models import User from modoboa.lib import events from modoboa.lib.exceptions import PermDeniedException -from modoboa.lib.emailutils import split_mailbox +from modoboa.lib.email_utils import split_mailbox from modoboa.extensions.admin.models import ( Domain, Alias ) diff --git a/modoboa/extensions/admin/models/alias.py b/modoboa/extensions/admin/models/alias.py index 4ced8b994..7a1687e44 100644 --- a/modoboa/extensions/admin/models/alias.py +++ b/modoboa/extensions/admin/models/alias.py @@ -1,7 +1,7 @@ import reversion from django.db import models from django.utils.translation import ugettext as _, ugettext_lazy -from modoboa.lib.emailutils import split_mailbox +from modoboa.lib.email_utils import split_mailbox from modoboa.lib.exceptions import ( PermDeniedException, BadRequest, Conflict ) diff --git a/modoboa/extensions/admin/templatetags/admin_tags.py b/modoboa/extensions/admin/templatetags/admin_tags.py index abc4d2451..24290feef 100644 --- a/modoboa/extensions/admin/templatetags/admin_tags.py +++ b/modoboa/extensions/admin/templatetags/admin_tags.py @@ -9,7 +9,7 @@ from django.utils.translation import ugettext as _, ugettext_lazy from modoboa.lib import events from modoboa.lib.templatetags.lib_tags import render_link -from modoboa.lib.webutils import render_actions +from modoboa.lib.web_utils import render_actions register = template.Library() diff --git a/modoboa/extensions/admin/views/alias.py b/modoboa/extensions/admin/views/alias.py index 4d73a4372..0104b667a 100644 --- a/modoboa/extensions/admin/views/alias.py +++ b/modoboa/extensions/admin/views/alias.py @@ -7,7 +7,7 @@ from django.contrib.auth.decorators import ( login_required, permission_required ) from modoboa.lib import events -from modoboa.lib.webutils import render_to_json_response +from modoboa.lib.web_utils import render_to_json_response from modoboa.lib.exceptions import PermDeniedException, Conflict from modoboa.extensions.admin.forms import AliasForm from modoboa.extensions.admin.models import Alias diff --git a/modoboa/extensions/admin/views/domain.py b/modoboa/extensions/admin/views/domain.py index 3cabdf935..35ef6a68d 100644 --- a/modoboa/extensions/admin/views/domain.py +++ b/modoboa/extensions/admin/views/domain.py @@ -15,7 +15,7 @@ import reversion from modoboa.core.models import User from modoboa.lib import parameters, events -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( _render_to_string, render_to_json_response ) from modoboa.lib.exceptions import ( diff --git a/modoboa/extensions/admin/views/identity.py b/modoboa/extensions/admin/views/identity.py index 0c0a29b20..539c14313 100644 --- a/modoboa/extensions/admin/views/identity.py +++ b/modoboa/extensions/admin/views/identity.py @@ -14,7 +14,7 @@ from modoboa.lib import parameters, events from modoboa.lib.exceptions import ( PermDeniedException, BadRequest ) -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( _render_to_string, render_to_json_response ) from modoboa.core.models import User diff --git a/modoboa/extensions/admin/views/user.py b/modoboa/extensions/admin/views/user.py index 15e0a9b6c..55166166c 100644 --- a/modoboa/extensions/admin/views/user.py +++ b/modoboa/extensions/admin/views/user.py @@ -1,7 +1,7 @@ import reversion from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( render_to_json_response, _render_to_string ) from modoboa.extensions.admin.lib import needs_mailbox diff --git a/modoboa/extensions/amavis/lib.py b/modoboa/extensions/amavis/lib.py index 646ca46c8..543913b8d 100644 --- a/modoboa/extensions/amavis/lib.py +++ b/modoboa/extensions/amavis/lib.py @@ -11,10 +11,10 @@ from django.core.urlresolvers import reverse from modoboa.extensions.admin.models import Mailbox, Alias from modoboa.lib import parameters -from modoboa.lib.emailutils import split_mailbox +from modoboa.lib.email_utils import split_mailbox from modoboa.lib.exceptions import InternalError from modoboa.lib.sysutils import exec_cmd -from modoboa.lib.webutils import NavigationParameters +from modoboa.lib.web_utils import NavigationParameters from .models import Users, Policy diff --git a/modoboa/extensions/amavis/management/commands/amnotify.py b/modoboa/extensions/amavis/management/commands/amnotify.py index a0ff57f57..82c5f62f0 100644 --- a/modoboa/extensions/amavis/management/commands/amnotify.py +++ b/modoboa/extensions/amavis/management/commands/amnotify.py @@ -10,7 +10,7 @@ from django.utils.translation import ugettext as _ from modoboa.core.management.commands import CloseConnectionMixin from modoboa.core.models import User from modoboa.lib import parameters -from modoboa.lib.emailutils import sendmail_simple +from modoboa.lib.email_utils import sendmail_simple from modoboa.extensions.admin.models import Domain from modoboa.extensions.amavis import Amavis diff --git a/modoboa/extensions/amavis/sql_email.py b/modoboa/extensions/amavis/sql_email.py index 2722f09a8..59a462932 100644 --- a/modoboa/extensions/amavis/sql_email.py +++ b/modoboa/extensions/amavis/sql_email.py @@ -5,7 +5,7 @@ An email representation based on a database record. from django.template.loader import render_to_string -from modoboa.lib.emailutils import Email +from modoboa.lib.email_utils import Email from .sql_connector import get_connector diff --git a/modoboa/extensions/amavis/views.py b/modoboa/extensions/amavis/views.py index 7a69b6528..9e9aa6af2 100644 --- a/modoboa/extensions/amavis/views.py +++ b/modoboa/extensions/amavis/views.py @@ -16,7 +16,7 @@ from django.contrib.auth.decorators import login_required from modoboa.lib import parameters from modoboa.lib.exceptions import BadRequest from modoboa.lib.paginator import Paginator -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( getctx, render_to_json_response, _render_to_string ) from modoboa.extensions.admin.models import Mailbox, Domain diff --git a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py index 00e9c20c4..cde210c63 100644 --- a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py +++ b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py @@ -8,7 +8,7 @@ from django.utils import timezone from modoboa.core.management.commands import CloseConnectionMixin from modoboa.lib import parameters -from modoboa.lib.emailutils import split_mailbox, sendmail_simple +from modoboa.lib.email_utils import split_mailbox, sendmail_simple from modoboa.extensions.admin.models import Mailbox from modoboa.extensions.postfix_autoreply import PostfixAutoreply from modoboa.extensions.postfix_autoreply.models import ARmessage, ARhistoric diff --git a/modoboa/extensions/postfix_autoreply/views.py b/modoboa/extensions/postfix_autoreply/views.py index 0351a8c18..cbf7befe0 100644 --- a/modoboa/extensions/postfix_autoreply/views.py +++ b/modoboa/extensions/postfix_autoreply/views.py @@ -2,7 +2,7 @@ from datetime import date from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( render_to_json_response, _render_to_string ) from modoboa.extensions.admin.lib import needs_mailbox diff --git a/modoboa/extensions/postfix_relay_domains/forms.py b/modoboa/extensions/postfix_relay_domains/forms.py index a93683fb1..9d31e2ba0 100644 --- a/modoboa/extensions/postfix_relay_domains/forms.py +++ b/modoboa/extensions/postfix_relay_domains/forms.py @@ -7,7 +7,7 @@ from django.utils.translation import ugettext as _, ugettext_lazy from django.core.urlresolvers import reverse from modoboa.lib import events from modoboa.lib.form_utils import DynamicForm, DomainNameField, TabForms -from modoboa.lib.webutils import render_to_json_response +from modoboa.lib.web_utils import render_to_json_response from modoboa.extensions.admin.models import Domain, DomainAlias from .models import RelayDomain, RelayDomainAlias diff --git a/modoboa/extensions/postfix_relay_domains/views.py b/modoboa/extensions/postfix_relay_domains/views.py index 987efa4da..e95ec849b 100644 --- a/modoboa/extensions/postfix_relay_domains/views.py +++ b/modoboa/extensions/postfix_relay_domains/views.py @@ -9,7 +9,7 @@ from django.contrib.auth.decorators import ( ) from modoboa.lib import events from modoboa.lib.exceptions import PermDeniedException -from modoboa.lib.webutils import render_to_json_response +from modoboa.lib.web_utils import render_to_json_response from .models import RelayDomain, Service from .forms import RelayDomainForm, RelayDomainFormGeneral diff --git a/modoboa/extensions/radicale/forms.py b/modoboa/extensions/radicale/forms.py index 11a9b1e87..857cfbc2c 100644 --- a/modoboa/extensions/radicale/forms.py +++ b/modoboa/extensions/radicale/forms.py @@ -4,7 +4,7 @@ Radicale extension forms. from django import forms from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _, ugettext_lazy -from modoboa.lib.webutils import render_to_json_response +from modoboa.lib.web_utils import render_to_json_response from modoboa.lib.form_utils import WizardForm, TabForms, DynamicForm from modoboa.extensions.admin.models import Domain, Mailbox from modoboa.extensions.radicale.models import UserCalendar, SharedCalendar @@ -109,7 +109,7 @@ class RightsForm(forms.Form, DynamicForm): def save(self): """Custom save method.""" import re - from modoboa.lib.emailutils import split_mailbox + from modoboa.lib.email_utils import split_mailbox from modoboa.lib.exceptions import BadRequest from modoboa.extensions.admin.models import Mailbox from .models import AccessRule diff --git a/modoboa/extensions/radicale/templatetags/radicale_tags.py b/modoboa/extensions/radicale/templatetags/radicale_tags.py index e655be253..ab28d44fd 100644 --- a/modoboa/extensions/radicale/templatetags/radicale_tags.py +++ b/modoboa/extensions/radicale/templatetags/radicale_tags.py @@ -5,7 +5,7 @@ from django import template from django.template.loader import render_to_string from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ -from modoboa.lib.webutils import render_actions +from modoboa.lib.web_utils import render_actions from modoboa.lib.templatetags.lib_tags import render_link diff --git a/modoboa/extensions/radicale/views.py b/modoboa/extensions/radicale/views.py index 281e7a719..619c41dde 100644 --- a/modoboa/extensions/radicale/views.py +++ b/modoboa/extensions/radicale/views.py @@ -11,7 +11,7 @@ from django.contrib.auth.decorators import ( from django.utils.translation import ugettext as _ from modoboa.lib.listing import get_sort_order, get_listing_page -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( _render_to_string, render_to_json_response ) from modoboa.lib.exceptions import NotFound, PermDeniedException diff --git a/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py b/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py index 0f977fee7..c1336a923 100644 --- a/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py +++ b/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py @@ -3,7 +3,7 @@ from django.core.urlresolvers import reverse from django.template.loader import render_to_string from django.utils.translation import ugettext as _ -from modoboa.lib.webutils import render_actions +from modoboa.lib.web_utils import render_actions from modoboa.lib.templatetags.form_tags import configure_field_classes register = template.Library() diff --git a/modoboa/extensions/sievefilters/views.py b/modoboa/extensions/sievefilters/views.py index ae5783db8..2aef75859 100644 --- a/modoboa/extensions/sievefilters/views.py +++ b/modoboa/extensions/sievefilters/views.py @@ -9,7 +9,7 @@ from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse from modoboa.lib import parameters -from modoboa.lib.webutils import _render_error, \ +from modoboa.lib.web_utils import _render_error, \ ajax_response, render_to_json_response from modoboa.lib.connections import ConnectionError from modoboa.lib.exceptions import BadRequest diff --git a/modoboa/extensions/stats/views.py b/modoboa/extensions/stats/views.py index 2e2b3b83c..49e1570d9 100644 --- a/modoboa/extensions/stats/views.py +++ b/modoboa/extensions/stats/views.py @@ -10,7 +10,7 @@ from django.contrib.auth.decorators import ( from modoboa.core.extensions import exts_pool from modoboa.lib import events from modoboa.lib.exceptions import BadRequest, PermDeniedException, NotFound -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( render_to_json_response ) from modoboa.extensions.admin.models import ( diff --git a/modoboa/extensions/webmail/forms.py b/modoboa/extensions/webmail/forms.py index fa14d5216..9b5165590 100644 --- a/modoboa/extensions/webmail/forms.py +++ b/modoboa/extensions/webmail/forms.py @@ -9,7 +9,7 @@ from django.conf import settings from django.utils.translation import ugettext_lazy as _ from modoboa.lib import parameters -from modoboa.lib.emailutils import set_email_headers +from modoboa.lib.email_utils import set_email_headers from .lib import ( ImapEmail, create_mail_attachment ) diff --git a/modoboa/extensions/webmail/lib/attachments.py b/modoboa/extensions/webmail/lib/attachments.py index 11ab08f93..b99a0408a 100644 --- a/modoboa/extensions/webmail/lib/attachments.py +++ b/modoboa/extensions/webmail/lib/attachments.py @@ -4,7 +4,7 @@ from django.conf import settings from django.core.files.uploadhandler import FileUploadHandler, SkipFile from modoboa.lib import parameters from modoboa.lib.exceptions import InternalError -from modoboa.lib.webutils import size2integer +from modoboa.lib.web_utils import size2integer def set_compose_session(request): diff --git a/modoboa/extensions/webmail/lib/imapemail.py b/modoboa/extensions/webmail/lib/imapemail.py index dcdb34b9e..6496e5a44 100644 --- a/modoboa/extensions/webmail/lib/imapemail.py +++ b/modoboa/extensions/webmail/lib/imapemail.py @@ -12,7 +12,7 @@ from django.conf import settings from django.utils.translation import ugettext as _ from modoboa.lib import parameters, u2u_decode -from modoboa.lib.emailutils import Email, EmailAddress +from modoboa.lib.email_utils import Email, EmailAddress from .imaputils import ( get_imapconnector, BodyStructure ) diff --git a/modoboa/extensions/webmail/lib/imapheader.py b/modoboa/extensions/webmail/lib/imapheader.py index 1e1f4dac9..dd2dbbb1a 100644 --- a/modoboa/extensions/webmail/lib/imapheader.py +++ b/modoboa/extensions/webmail/lib/imapheader.py @@ -2,7 +2,7 @@ Set of functions used to parse and transform email headers. """ import chardet -from modoboa.lib.emailutils import EmailAddress +from modoboa.lib.email_utils import EmailAddress __all__ = [ 'parse_from', 'parse_to', 'parse_message_id', 'parse_date', diff --git a/modoboa/extensions/webmail/lib/imaputils.py b/modoboa/extensions/webmail/lib/imaputils.py index 8305f9fef..796f80161 100644 --- a/modoboa/extensions/webmail/lib/imaputils.py +++ b/modoboa/extensions/webmail/lib/imaputils.py @@ -13,7 +13,7 @@ from django.utils.translation import ugettext as _ from modoboa.lib import parameters, imap_utf7 from modoboa.lib.exceptions import InternalError from modoboa.lib.connections import ConnectionsManager -from modoboa.lib.webutils import static_url +from modoboa.lib.web_utils import static_url from ..exceptions import ImapError, WebmailInternalError from .fetch_parser import parse_fetch_response diff --git a/modoboa/extensions/webmail/lib/sendmail.py b/modoboa/extensions/webmail/lib/sendmail.py index ba654cc02..14b4eaa19 100644 --- a/modoboa/extensions/webmail/lib/sendmail.py +++ b/modoboa/extensions/webmail/lib/sendmail.py @@ -1,7 +1,7 @@ import smtplib from modoboa.lib import parameters -from modoboa.lib.emailutils import prepare_addresses -from modoboa.lib.webutils import _render_to_string +from modoboa.lib.email_utils import prepare_addresses +from modoboa.lib.web_utils import _render_to_string from modoboa.lib.cryptutils import get_password from modoboa.extensions.webmail.exceptions import WebmailInternalError from . import get_imapconnector, clean_attachments diff --git a/modoboa/extensions/webmail/lib/utils.py b/modoboa/extensions/webmail/lib/utils.py index d48dd20ab..8c341c2d5 100644 --- a/modoboa/extensions/webmail/lib/utils.py +++ b/modoboa/extensions/webmail/lib/utils.py @@ -1,7 +1,7 @@ """ Misc. utilities. """ -from modoboa.lib.webutils import NavigationParameters +from modoboa.lib.web_utils import NavigationParameters def decode_payload(encoding, payload): diff --git a/modoboa/extensions/webmail/views.py b/modoboa/extensions/webmail/views.py index a307192c9..89b8b78f7 100644 --- a/modoboa/extensions/webmail/views.py +++ b/modoboa/extensions/webmail/views.py @@ -20,7 +20,7 @@ from django.views.decorators.gzip import gzip_page from modoboa.lib import parameters from modoboa.lib.exceptions import ModoboaException, BadRequest from modoboa.lib.paginator import Paginator -from modoboa.lib.webutils import ( +from modoboa.lib.web_utils import ( _render_to_string, ajax_response, render_to_json_response ) from modoboa.extensions.admin.lib import needs_mailbox diff --git a/modoboa/lib/authbackends.py b/modoboa/lib/authbackends.py index 565c8a03e..92509fd28 100644 --- a/modoboa/lib/authbackends.py +++ b/modoboa/lib/authbackends.py @@ -4,7 +4,7 @@ from django.contrib.auth.backends import ModelBackend from modoboa.core.models import User from modoboa.lib import parameters -from modoboa.lib.emailutils import split_mailbox +from modoboa.lib.email_utils import split_mailbox class SimpleBackend(ModelBackend): diff --git a/modoboa/lib/connections.py b/modoboa/lib/connections.py index adbe58b94..3cb4f175a 100644 --- a/modoboa/lib/connections.py +++ b/modoboa/lib/connections.py @@ -2,10 +2,13 @@ from modoboa.lib.cryptutils import decrypt class ConnectionsManager(type): - """Singleton pattern implementation + + """ + Singleton pattern implementation. This class is specialized in connection management. """ + def __init__(cls, name, bases, ctx): super(ConnectionsManager, cls).__init__(name, bases, ctx) cls.instances = {} @@ -16,7 +19,7 @@ class ConnectionsManager(type): key = kwargs["user"] else: return None - if not key in cls.instances: + if key not in cls.instances: cls.instances[key] = None if "password" in kwargs: kwargs["password"] = decrypt(kwargs["password"]) diff --git a/modoboa/lib/emailutils.py b/modoboa/lib/email_utils.py similarity index 95% rename from modoboa/lib/emailutils.py rename to modoboa/lib/email_utils.py index 425c898d8..1ed4b6377 100644 --- a/modoboa/lib/emailutils.py +++ b/modoboa/lib/email_utils.py @@ -1,16 +1,20 @@ # coding: utf-8 -import time + import re import smtplib +import time from email.header import Header, decode_header from email.mime.text import MIMEText from email.utils import make_msgid, formatdate, parseaddr -from django.template.loader import render_to_string + from django.conf import settings +from django.template.loader import render_to_string + from modoboa.lib import u2u_decode class EmailAddress(object): + def __init__(self, address): self.fulladdress = u2u_decode.u2u_decode(address).strip("\r\t\n") (self.name, self.address) = parseaddr(self.fulladdress) @@ -22,6 +26,7 @@ class EmailAddress(object): class Email(object): + def __init__(self, mailid, mformat="plain", dformat="plain", links=0): self.attached_map = {} self.contents = {"html": "", "plain": ""} @@ -42,11 +47,12 @@ class Email(object): @property def body(self): - """Return email's body. - """ + """Return email's body.""" if self._body is None: - self._body = getattr(self, "viewmail_%s" % self.mformat) \ + self._body = ( + getattr(self, "viewmail_%s" % self.mformat) (self.contents[self.mformat], links=self.links) + ) return self._body def get_header(self, msg, hdrname): @@ -231,19 +237,22 @@ def split_mailbox(mailbox): return (address, domain) -def decode(s, encodings=('utf8', 'latin1', 'windows-1252', 'ascii'), charset=None): +def decode(string, encodings=None, charset=None): + """Try to decode the given string.""" + if encodings is None: + encodings = ('utf8', 'latin1', 'windows-1252', 'ascii') if charset is not None: try: - return s.decode(charset, 'ignore') + return string.decode(charset, 'ignore') except LookupError: pass for encoding in encodings: try: - return s.decode(encoding) + return string.decode(encoding) except UnicodeDecodeError: pass - return s.decode('ascii', 'ignore') + return string.decode('ascii', 'ignore') def prepare_addresses(addresses, usage="header"): @@ -306,7 +315,8 @@ def __sendmail(sender, rcpt, msgstring, server='localhost', port=25): return True, None -def sendmail_simple(sender, rcpt, subject="Sample message", content="", **kwargs): +def sendmail_simple( + sender, rcpt, subject="Sample message", content="", **kwargs): """Simple way to send a text message Send a text/plain message with basic headers (msg-id, date). diff --git a/modoboa/lib/form_utils.py b/modoboa/lib/form_utils.py index 1af386b50..ef90c7ff4 100644 --- a/modoboa/lib/form_utils.py +++ b/modoboa/lib/form_utils.py @@ -16,7 +16,7 @@ from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _, ugettext_lazy from modoboa.lib.exceptions import BadRequest -from modoboa.lib.webutils import render_to_json_response +from modoboa.lib.web_utils import render_to_json_response class WizardStep(object): diff --git a/modoboa/lib/middleware.py b/modoboa/lib/middleware.py index d32e3037a..31b7df90a 100644 --- a/modoboa/lib/middleware.py +++ b/modoboa/lib/middleware.py @@ -1,21 +1,24 @@ # coding: utf-8 -""" -Custom middlewares. -""" + +"""Custom middlewares.""" + import re + from django.http import Http404, HttpResponseRedirect -from modoboa.core.models import Extension + from modoboa.core.extensions import exts_pool -from modoboa.lib.webutils import ( - _render_error, ajax_response, render_to_json_response -) +from modoboa.core.models import Extension from modoboa.lib.exceptions import ModoboaException from modoboa.lib.signals import request_accessor +from modoboa.lib.web_utils import ( + _render_error, ajax_response, render_to_json_response +) class ExtControlMiddleware(object): + def process_view(self, request, view, args, kwargs): - m = re.match("modoboa\.extensions\.(\w+)", view.__module__) + m = re.match(r"modoboa\.extensions\.(\w+)", view.__module__) if m is None: return None try: @@ -31,6 +34,7 @@ class ExtControlMiddleware(object): class AjaxLoginRedirect(object): + def process_response(self, request, response): if request.is_ajax(): if type(response) == HttpResponseRedirect: @@ -39,6 +43,7 @@ class AjaxLoginRedirect(object): class CommonExceptionCatcher(object): + def process_exception(self, request, exception): if not isinstance(exception, ModoboaException): return None @@ -57,6 +62,7 @@ class CommonExceptionCatcher(object): class RequestCatcherMiddleware(object): + """ Simple middleware to store the current request. """ diff --git a/modoboa/lib/webutils.py b/modoboa/lib/web_utils.py similarity index 97% rename from modoboa/lib/webutils.py rename to modoboa/lib/web_utils.py index 9d2b37c8a..947c32503 100644 --- a/modoboa/lib/webutils.py +++ b/modoboa/lib/web_utils.py @@ -3,16 +3,18 @@ """ This module contains extra functions/shortcuts used to render HTML. """ -import sys -import re + import json -from django.core.urlresolvers import reverse -from django.http import HttpResponse, HttpResponseRedirect -from django.contrib.auth.decorators import login_required -from django.shortcuts import render -from django.template.loader import render_to_string +import re +import sys + from django import template from django.conf import settings +from django.contrib.auth.decorators import login_required +from django.core.urlresolvers import reverse +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import render +from django.template.loader import render_to_string def _render_to_string(request, tpl, user_context): @@ -52,7 +54,7 @@ def getctx(status, level=1, callback=None, **kwargs): def ajax_response(request, status="ok", respmsg=None, - url=None, ajaxnav=False, norefresh=False, + url=None, ajaxnav=False, norefresh=False, template=None, **kwargs): """Ajax response shortcut @@ -74,7 +76,7 @@ def ajax_response(request, status="ok", respmsg=None, ctx[k] = v if template is not None: content = _render_to_string(request, template, ctx) - elif kwargs.has_key("content"): + elif "content" in kwargs: content = kwargs["content"] else: content = "" @@ -198,7 +200,7 @@ class NavigationParameters(object): def store(self): """Store navigation parameters into session. """ - if not self.sessionkey in self.request.session: + if self.sessionkey not in self.request.session: self.request.session[self.sessionkey] = {} self._store_page() navparams = self.request.session[self.sessionkey] @@ -222,7 +224,7 @@ class NavigationParameters(object): :param defaultvalue: default value if none is found :return: parameter's value """ - if not self.sessionkey in self.request.session: + if self.sessionkey not in self.request.session: return default_value return self.request.session[self.sessionkey].get(param, default_value) diff --git a/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py b/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py index 7b40d5461..4f22bf79b 100644 --- a/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py +++ b/modoboa/tools/pfxadmin_migrate/management/commands/migrate_from_postfixadmin.py @@ -41,7 +41,7 @@ from django.db import transaction import modoboa.core.models as core_models import modoboa.extensions.admin.models as admin_models -from modoboa.lib.emailutils import split_mailbox +from modoboa.lib.email_utils import split_mailbox from modoboa.extensions.admin import grant_access_to_all_objects from modoboa.tools.pfxadmin_migrate import models as pf_models From 40ee102610e22f5e7edd6401e4300ac6f969d2ad Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 13 Jan 2015 21:32:01 +0100 Subject: [PATCH 03/24] PEP8 fixes --- modoboa/lib/events.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/modoboa/lib/events.py b/modoboa/lib/events.py index 13c447af3..19bbe0b20 100644 --- a/modoboa/lib/events.py +++ b/modoboa/lib/events.py @@ -27,7 +27,7 @@ def declare(nevents): :param list nevents: a list of event names """ for evt in nevents: - if not evt in events: + if evt not in events: events.append(evt) @@ -42,10 +42,10 @@ def register(event, callback): # if not event in events: # print "Event %s not registered" % event # return 0 - if not event in callbacks.keys(): + if event not in callbacks.keys(): callbacks[event] = {} fullname = "%s.%s" % (callback.__module__, callback.__name__) - if not fullname in callbacks[event]: + if fullname not in callbacks[event]: callbacks[event][fullname] = callback return 1 @@ -96,7 +96,7 @@ class observe(object): else: if not ext.enabled: return None - elif not modname in settings.MODOBOA_APPS: + elif modname not in settings.MODOBOA_APPS: return [] return f(*args, **kwargs) for evt in self.evtnames: @@ -110,9 +110,9 @@ def unregister(event, callback): :param event: the targeted event :param callback: the callback to remove """ - if not event in events: + if event not in events: return False - if not event in callbacks: + if event not in callbacks: return False fullname = "%s.%s" % (callback.__module__, callback.__name__) try: @@ -142,7 +142,7 @@ def raiseEvent(event, *args, **kwargs): :param event: the event to raise """ - if not event in events or not event in callbacks: + if event not in events or event not in callbacks: return 0 for callback in callbacks[event].values(): callback(*args, **kwargs) @@ -158,7 +158,7 @@ def raiseQueryEvent(event, *args, **kwargs): :param event: the event to raise """ result = [] - if not event in events or not event in callbacks: + if event not in events or event not in callbacks: return result for callback in callbacks[event].values(): tmp = callback(*args, **kwargs) @@ -180,7 +180,7 @@ def raiseDictEvent(event, *args): :return: a dictionnary """ result = {} - if not event in events or not event in callbacks: + if event not in events or event not in callbacks: return result for callback in callbacks[event].values(): tmp = callback(*args) From 2d0b401c00c64feeaf833961fe29cfb7981ecf2b Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 13 Jan 2015 21:40:11 +0100 Subject: [PATCH 04/24] PEP8 fixes --- modoboa/lib/parameters.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/modoboa/lib/parameters.py b/modoboa/lib/parameters.py index 5ad4862c5..e430f02de 100644 --- a/modoboa/lib/parameters.py +++ b/modoboa/lib/parameters.py @@ -1,4 +1,5 @@ # coding: utf-8 + """ This interface provides a simple way to declare and store parameters in Modoboa's database. @@ -8,6 +9,7 @@ will be available and modifiable directly from the web interface. Only super users will be able to access this part of the web interface. """ + from django import forms from modoboa.lib import events @@ -85,10 +87,13 @@ class GenericParametersForm(forms.Form): class AdminParametersForm(GenericParametersForm): + def _load_initial_values(self): from .models import Parameter - names = ["%s.%s" % (self.app, name.upper()) for name in self.fields.keys()] + names = [ + "%s.%s" % (self.app, name.upper()) for name in self.fields.keys() + ] for p in Parameter.objects.filter(name__in=names): self.fields[p.shortname].initial = self._decode_value(p.value) @@ -121,6 +126,7 @@ class AdminParametersForm(GenericParametersForm): class UserParametersForm(GenericParametersForm): + def __init__(self, *args, **kwargs): self.user = kwargs.pop("user") if "user" in kwargs else None super(UserParametersForm, self).__init__(*args, **kwargs) @@ -130,7 +136,9 @@ class UserParametersForm(GenericParametersForm): return from .models import UserParameter - names = ["%s.%s" % (self.app, name.upper()) for name in self.fields.keys()] + names = [ + "%s.%s" % (self.app, name.upper()) for name in self.fields.keys() + ] for p in UserParameter.objects.filter(user=self.user, name__in=names): self.fields[p.shortname].initial = self._decode_value(p.value) @@ -198,9 +206,12 @@ def unregister(app=None): def __is_defined(app, level, name): - if not level in ['A', 'U'] \ - or not app in _params[level] \ - or not name in _params[level][app]["defaults"]: + not_defined = ( + level not in ['A', 'U'] + or app not in _params[level] + or name not in _params[level][app]["defaults"] + ) + if not_defined: raise NotDefined(app, name) From 7c010261483338414596fa14964c9744f19f9eb8 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 13 Jan 2015 21:46:21 +0100 Subject: [PATCH 05/24] PEP8 fixes --- modoboa/lib/imap_utf7.py | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/modoboa/lib/imap_utf7.py b/modoboa/lib/imap_utf7.py index bceddc5ee..2da57f0e9 100644 --- a/modoboa/lib/imap_utf7.py +++ b/modoboa/lib/imap_utf7.py @@ -1,8 +1,8 @@ # -*- coding: iso-8859-1 -*- """ -Imap folder names are encoded using a special version of utf-7 as defined in RFC -2060 section 5.1.3. +Imap folder names are encoded using a special version of utf-7 as +defined in RFC 2060 section 5.1.3. 5.1.3. Mailbox International Naming Convention @@ -56,15 +56,18 @@ import codecs # encoding + def modified_base64(s): s = s.encode('utf-16be') return binascii.b2a_base64(s).rstrip('\n=').replace('/', ',') + def doB64(_in, r): if _in: r.append('&%s-' % modified_base64(''.join(_in))) del _in[:] + def encoder(s): r = [] _in = [] @@ -127,12 +130,13 @@ def imap4_utf_7(name): codecs.register(imap4_utf_7) -## testing methods +# testing methods def imapUTF7Encode(ust): "Returns imap utf-7 encoded version of string" return ust.encode('imap4-utf-7') + def imapUTF7EncodeSequence(seq): "Returns imap utf-7 encoded version of strings in sequence" return [imapUTF7Encode(itm) for itm in seq] @@ -142,6 +146,7 @@ def imapUTF7Decode(st): "Returns utf7 encoded version of imap utf-7 string" return st.decode('imap4-utf-7') + def imapUTF7DecodeSequence(seq): "Returns utf7 encoded version of imap utf-7 strings in sequence" return [imapUTF7Decode(itm) for itm in seq] @@ -159,14 +164,14 @@ def utf7SequenceToUTF8(seq): __all__ = ['imapUTF7Encode', 'imapUTF7Decode', ] -if __name__=='__main__': +if __name__ == '__main__': + + # print u'bøx'.encode('imap4-utf-7') + # print 'expected b&APg-x' + + # print u'båx'.encode('imap4-utf-7') + # print 'expected b&AOU-x' -## print u'bøx'.encode('imap4-utf-7') -## print 'expected b&APg-x' -## -## print u'båx'.encode('imap4-utf-7') -## print 'expected b&AOU-x' -## print '#######' print 'bøx' e = imapUTF7Encode(u'bøx') @@ -191,12 +196,12 @@ if __name__=='__main__': print e print imapUTF7Decode(e).encode('latin-1') -## e = imapUTF7Decode('b&AOU-x') -## print e.encode('latin-1') -## -## e = imapUTF7Decode('b&APg-x') -## print e.encode('latin-1') -## + # e = imapUTF7Decode('b&AOU-x') + # print e.encode('latin-1') + + # e = imapUTF7Decode('b&APg-x') + # print e.encode('latin-1') + print '#######' print '~/Følder/mailbåx & stuff + more' n = u'~/Følder/mailbåx & stuff + more' @@ -207,4 +212,3 @@ if __name__=='__main__': print '#######' print '~peter/mail/&ZeVnLIqe-/&U,BTFw-' print imapUTF7Decode('~peter/mail/&ZeVnLIqe-/&U,BTFw-').encode('utf-8') - From 883fda0a18f9255c2d334b8e1715bcb1e55ae03d Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 13 Jan 2015 21:50:51 +0100 Subject: [PATCH 06/24] PEP8 fixes --- modoboa/lib/dbutils.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modoboa/lib/dbutils.py b/modoboa/lib/dbutils.py index 1bcd03fcb..242a24163 100644 --- a/modoboa/lib/dbutils.py +++ b/modoboa/lib/dbutils.py @@ -1,7 +1,9 @@ # coding: utf-8 -from django.db import connection + from django.conf import settings +from django.db import connection from django.utils.translation import ugettext as _ + from modoboa.lib.exceptions import InternalError @@ -33,7 +35,8 @@ def db_type(cname="default"): :return: a string or None """ if not cname in settings.DATABASES: - raise InternalError(_("Connection to database %s not configured" % cname)) + raise InternalError( + _("Connection to database %s not configured" % cname)) for t in ['postgres', 'mysql', 'sqlite']: if settings.DATABASES[cname]['ENGINE'].find(t) != -1: return t From bc9bb3c06837b13b1352ddf8f7207ee502472d65 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 13 Jan 2015 21:53:21 +0100 Subject: [PATCH 07/24] Few fixes --- modoboa/urls.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modoboa/urls.py b/modoboa/urls.py index 11c2bd5e9..2a4e3eef5 100644 --- a/modoboa/urls.py +++ b/modoboa/urls.py @@ -1,14 +1,16 @@ -from django.conf.urls import patterns, include, url from django.conf import settings +from django.conf.urls import patterns, include, url + +from modoboa.core import load_core_settings from modoboa.core.extensions import exts_pool from modoboa.lib import parameters, events -from modoboa.core import load_core_settings + load_core_settings() urlpatterns = patterns( '', - url(r'^$', 'modoboa.lib.webutils.topredirection', name="topredirection"), + url(r'^$', 'modoboa.lib.web_utils.topredirection', name="topredirection"), (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', {'packages': ('modoboa', ), }), ('', include('modoboa.core.urls', namespace="core")), From 25a9b09bfe84f77f37df3c26e7fec95474e166dd Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 13 Jan 2015 21:54:13 +0100 Subject: [PATCH 08/24] Module renamed --- modoboa/core/app_settings.py | 2 +- modoboa/extensions/admin/migrations/0015_move_passwords.py | 2 +- modoboa/extensions/admin/views/identity.py | 2 +- modoboa/extensions/amavis/sql_connector.py | 2 +- .../migrations/0002_auto__add_armessage__add_arhistoric.py | 2 +- modoboa/lib/{dbutils.py => db_utils.py} | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename modoboa/lib/{dbutils.py => db_utils.py} (100%) diff --git a/modoboa/core/app_settings.py b/modoboa/core/app_settings.py index 706639340..d4c04f7e0 100644 --- a/modoboa/core/app_settings.py +++ b/modoboa/core/app_settings.py @@ -18,7 +18,7 @@ def enabled_applications(): """ from modoboa.core.models import Extension from modoboa.core.extensions import exts_pool - from modoboa.lib.dbutils import db_table_exists + from modoboa.lib.db_utils import db_table_exists result = [("user", "user")] if db_table_exists("core_extension"): diff --git a/modoboa/extensions/admin/migrations/0015_move_passwords.py b/modoboa/extensions/admin/migrations/0015_move_passwords.py index ebf626a2e..8b32209ed 100644 --- a/modoboa/extensions/admin/migrations/0015_move_passwords.py +++ b/modoboa/extensions/admin/migrations/0015_move_passwords.py @@ -4,7 +4,7 @@ from south.db import db from south.v2 import DataMigration from django.db import models from modoboa.lib.models import Parameter -from modoboa.lib.dbutils import db_table_exists +from modoboa.lib.db_utils import db_table_exists class Migration(DataMigration): diff --git a/modoboa/extensions/admin/views/identity.py b/modoboa/extensions/admin/views/identity.py index 539c14313..bc41b2e55 100644 --- a/modoboa/extensions/admin/views/identity.py +++ b/modoboa/extensions/admin/views/identity.py @@ -67,7 +67,7 @@ def _identities(request): @login_required @permission_required("admin.add_mailbox") def list_quotas(request): - from modoboa.lib.dbutils import db_type + from modoboa.lib.db_utils import db_type sort_order, sort_dir = get_sort_order(request.GET, "address") mboxes = Mailbox.objects.get_for_admin( diff --git a/modoboa/extensions/amavis/sql_connector.py b/modoboa/extensions/amavis/sql_connector.py index 46f0075ae..050928788 100644 --- a/modoboa/extensions/amavis/sql_connector.py +++ b/modoboa/extensions/amavis/sql_connector.py @@ -6,7 +6,7 @@ import datetime from django.db.models import Q from modoboa.extensions.admin.models import Domain -from modoboa.lib.dbutils import db_type +from modoboa.lib.db_utils import db_type from .models import Quarantine, Msgrcpt, Maddr diff --git a/modoboa/extensions/postfix_autoreply/migrations/0002_auto__add_armessage__add_arhistoric.py b/modoboa/extensions/postfix_autoreply/migrations/0002_auto__add_armessage__add_arhistoric.py index 0f816e834..408cb8087 100644 --- a/modoboa/extensions/postfix_autoreply/migrations/0002_auto__add_armessage__add_arhistoric.py +++ b/modoboa/extensions/postfix_autoreply/migrations/0002_auto__add_armessage__add_arhistoric.py @@ -3,7 +3,7 @@ import datetime from south.db import db from south.v2 import SchemaMigration from django.db import models -from modoboa.lib.dbutils import db_table_exists +from modoboa.lib.db_utils import db_table_exists class Migration(SchemaMigration): diff --git a/modoboa/lib/dbutils.py b/modoboa/lib/db_utils.py similarity index 100% rename from modoboa/lib/dbutils.py rename to modoboa/lib/db_utils.py From 3914a49df63f4899b2e11925b44a665c958507f9 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Tue, 13 Jan 2015 22:02:25 +0100 Subject: [PATCH 09/24] PEP8 fixes --- modoboa/lib/db_utils.py | 2 +- modoboa/lib/ldap_utils.py | 7 ++++++- modoboa/lib/listing.py | 3 ++- modoboa/lib/permissions.py | 3 ++- modoboa/lib/signals.py | 9 ++++----- modoboa/lib/templatetags/form_tags.py | 2 +- modoboa/lib/tests.py | 7 ++++--- 7 files changed, 20 insertions(+), 13 deletions(-) diff --git a/modoboa/lib/db_utils.py b/modoboa/lib/db_utils.py index 242a24163..156fc5077 100644 --- a/modoboa/lib/db_utils.py +++ b/modoboa/lib/db_utils.py @@ -34,7 +34,7 @@ def db_type(cname="default"): :param str cname: connection name :return: a string or None """ - if not cname in settings.DATABASES: + if cname not in settings.DATABASES: raise InternalError( _("Connection to database %s not configured" % cname)) for t in ['postgres', 'mysql', 'sqlite']: diff --git a/modoboa/lib/ldap_utils.py b/modoboa/lib/ldap_utils.py index b83e0971c..3ba247dac 100644 --- a/modoboa/lib/ldap_utils.py +++ b/modoboa/lib/ldap_utils.py @@ -34,14 +34,17 @@ Extracted from `this blog """ import ldap + from django.conf import settings from django.utils.translation import ugettext as _ + from modoboa.core.password_hashers import get_password_hasher from modoboa.lib import parameters from modoboa.lib.exceptions import InternalError class LDAPAuthBackend(object): + def __init__(self): self.server_uri = self._setting( "AUTH_LDAP_SERVER_URI", "ldap://localhost" @@ -102,7 +105,9 @@ class LDAPAuthBackend(object): try: self.connect_to_server(user, password) if self.ldap_ad: - newpassword = ('"%s"' % newpassword).encode('utf-16').lstrip('\377\376') + newpassword = ( + ('"%s"' % newpassword).encode('utf-16').lstrip('\377\376') + ) ldif = [(ldap.MOD_REPLACE, self.pwd_attr, self._crypt_password(newpassword))] diff --git a/modoboa/lib/listing.py b/modoboa/lib/listing.py index 858b85b31..3ae82d832 100644 --- a/modoboa/lib/listing.py +++ b/modoboa/lib/listing.py @@ -1,4 +1,5 @@ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger + from modoboa.lib import parameters @@ -16,7 +17,7 @@ def get_sort_order(qdict, default, allowed_values=None): sort_order = sort_order[1:] else: sort_dir = "" - if allowed_values is not None and not sort_order in allowed_values: + if allowed_values is not None and sort_order not in allowed_values: return (default, "") return (sort_order, sort_dir) diff --git a/modoboa/lib/permissions.py b/modoboa/lib/permissions.py index a4b3487d3..b1a136b99 100644 --- a/modoboa/lib/permissions.py +++ b/modoboa/lib/permissions.py @@ -81,7 +81,8 @@ def grant_access_to_objects(user, objects, ct): """ for obj in objects: try: - ObjectAccess.objects.create(user=user, content_type=ct, object_id=obj.id) + ObjectAccess.objects.create( + user=user, content_type=ct, object_id=obj.id) except IntegrityError: pass diff --git a/modoboa/lib/signals.py b/modoboa/lib/signals.py index fbd5baad8..551898a40 100644 --- a/modoboa/lib/signals.py +++ b/modoboa/lib/signals.py @@ -1,11 +1,10 @@ -""" -Custom signals. -""" +"""Custom signals.""" + from django.dispatch import Signal request_accessor = Signal() + def get_request(): - """Get the current request from anywhere. - """ + """Get the current request from anywhere.""" return request_accessor.send(None)[0][1] diff --git a/modoboa/lib/templatetags/form_tags.py b/modoboa/lib/templatetags/form_tags.py index cd8bf8a87..4a2ae2034 100644 --- a/modoboa/lib/templatetags/form_tags.py +++ b/modoboa/lib/templatetags/form_tags.py @@ -63,7 +63,7 @@ def render_fields_group(form, pattern): haserror = len(first.errors) != 0 while True: fname = "%s_%d" % (pattern, cpt) - if not fname in form.fields: + if fname not in form.fields: break bfield = forms.forms.BoundField(form, form.fields[fname], fname) if len(bfield.errors): diff --git a/modoboa/lib/tests.py b/modoboa/lib/tests.py index cdf66b3db..5eee3edbd 100644 --- a/modoboa/lib/tests.py +++ b/modoboa/lib/tests.py @@ -11,13 +11,14 @@ class ModoTestCase(TestCase): def setUp(self, username="admin", password="password"): self.clt = Client() - self.assertEqual(self.clt.login(username=username, password=password), True) + self.assertEqual( + self.clt.login(username=username, password=password), True) def ajax_request(self, method, url, params=None, status=200): if params is None: params = {} - response = getattr(self.clt, method) \ - (url, params, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + response = getattr(self.clt, method)( + url, params, HTTP_X_REQUESTED_WITH='XMLHttpRequest') self.assertEqual(response.status_code, status) return json.loads(response.content) From 39781e1600495a8972b567872f4611a0b6027428 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 14 Jan 2015 13:43:35 +0100 Subject: [PATCH 10/24] PEP8 fixes --- modoboa/core/app_settings.py | 20 ++++-- modoboa/core/commands/__init__.py | 7 +- modoboa/core/commands/help.py | 5 +- modoboa/core/extensions.py | 8 ++- modoboa/core/forms.py | 22 ++++-- .../commands/clean_unknown_extensions.py | 2 +- .../management/commands/manage_extensions.py | 2 +- modoboa/core/models.py | 68 ++++++++++++------- modoboa/core/templatetags/core_tags.py | 12 ++-- modoboa/core/tests.py | 3 +- modoboa/core/views/admin.py | 13 ++-- modoboa/core/views/auth.py | 11 +-- modoboa/core/views/user.py | 12 ++-- setup.cfg | 3 + 14 files changed, 122 insertions(+), 66 deletions(-) create mode 100644 setup.cfg diff --git a/modoboa/core/app_settings.py b/modoboa/core/app_settings.py index d4c04f7e0..63c009777 100644 --- a/modoboa/core/app_settings.py +++ b/modoboa/core/app_settings.py @@ -2,9 +2,10 @@ from django import forms from django.conf import settings from django.utils.translation import ugettext as _, ugettext_lazy -from modoboa.lib.form_utils import YesNoField, SeparatorField, InlineRadioSelect -from modoboa.lib.cryptutils import random_key + from modoboa.lib import parameters +from modoboa.lib.cryptutils import random_key +from modoboa.lib.form_utils import YesNoField, SeparatorField, InlineRadioSelect def enabled_applications(): @@ -304,8 +305,9 @@ class GeneralParametersForm(parameters.AdminParametersForm): required_fields = ["ldap_user_dn_template"] for f in required_fields: - if not f in cleaned_data or cleaned_data[f] == u'': - self._errors[f] = self.error_class([_("This field is required")]) + if f not in cleaned_data or cleaned_data[f] == u'': + self._errors[f] = self.error_class( + [_("This field is required")]) return cleaned_data @@ -341,14 +343,20 @@ class GeneralParametersForm(parameters.AdminParametersForm): )) if values["ldap_auth_method"] == "searchbind": setattr(settings, "AUTH_LDAP_BIND_DN", values["ldap_bind_dn"]) - setattr(settings, "AUTH_LDAP_BIND_PASSWORD", values["ldap_bind_password"]) + setattr( + settings, "AUTH_LDAP_BIND_PASSWORD", + values["ldap_bind_password"] + ) search = LDAPSearch( values["ldap_search_base"], ldap.SCOPE_SUBTREE, values["ldap_search_filter"] ) setattr(settings, "AUTH_LDAP_USER_SEARCH", search) else: - setattr(settings, "AUTH_LDAP_USER_DN_TEMPLATE", values["ldap_user_dn_template"]) + setattr( + settings, "AUTH_LDAP_USER_DN_TEMPLATE", + values["ldap_user_dn_template"] + ) if values["ldap_is_active_directory"] == "yes": if not hasattr(settings, "AUTH_LDAP_GLOBAL_OPTIONS"): setattr(settings, "AUTH_LDAP_GLOBAL_OPTIONS", { diff --git a/modoboa/core/commands/__init__.py b/modoboa/core/commands/__init__.py index 9b2b1c9f2..e95f987b2 100644 --- a/modoboa/core/commands/__init__.py +++ b/modoboa/core/commands/__init__.py @@ -1,7 +1,9 @@ # coding: utf-8 + +import argparse import os import sys -import argparse + from django.conf import settings from django.template import Context, Template @@ -71,6 +73,7 @@ def scan_for_commands(dirname=""): def handle_command_line(): + """Parse the command line.""" commands = scan_for_commands() parser = argparse.ArgumentParser( description="A set of utilities to ease the installation of Modoboa.", @@ -83,7 +86,7 @@ def handle_command_line(): help='A valid command name') (args, remaining) = parser.parse_known_args() - if not args.command in commands: + if args.command not in commands: print >> sys.stderr, "Unknown command '%s'" % args.command sys.exit(1) diff --git a/modoboa/core/commands/help.py b/modoboa/core/commands/help.py index dfe46307c..ab6960d00 100644 --- a/modoboa/core/commands/help.py +++ b/modoboa/core/commands/help.py @@ -1,9 +1,12 @@ # coding: utf-8 + import sys + from . import Command class HelpCommand(Command): + help = "Display the help message associated to a specific command" def __init__(self, *args, **kwargs): @@ -12,7 +15,7 @@ class HelpCommand(Command): help='A command name') def handle(self, parsed_args): - if not parsed_args.name in self._commands: + if parsed_args.name not in self._commands: print >>sys.stderr, "Unknown command: %s" % parsed_args.name sys.exit(1) cmd = self._commands[parsed_args.name](self._commands) diff --git a/modoboa/core/extensions.py b/modoboa/core/extensions.py index 03997c150..99a89f7a3 100644 --- a/modoboa/core/extensions.py +++ b/modoboa/core/extensions.py @@ -1,3 +1,5 @@ +"""Extension management.""" + from django.conf import settings from django.conf.urls import include @@ -44,9 +46,9 @@ class ExtensionsPool(object): self.extensions[ext.name] = dict(cls=ext, show=show) def get_extension(self, name): - if not name in self.extensions: + if name not in self.extensions: return None - if not "instance" in self.extensions[name]: + if "instance" not in self.extensions[name]: self.extensions[name]["instance"] = self.extensions[name]["cls"]() return self.extensions[name]["instance"] @@ -54,7 +56,7 @@ class ExtensionsPool(object): """Check if an extension is enabled or not.""" from modoboa.core.models import Extension - if not name in self.extensions: + if name not in self.extensions: return False try: state = Extension.objects.get(name=name).enabled diff --git a/modoboa/core/forms.py b/modoboa/core/forms.py index 12c361797..a72f13d44 100644 --- a/modoboa/core/forms.py +++ b/modoboa/core/forms.py @@ -1,6 +1,10 @@ # coding: utf-8 + +"""Core forms.""" + from django import forms from django.utils.translation import ugettext as _, ugettext_lazy + from modoboa.core.models import User from modoboa.lib import parameters @@ -38,9 +42,9 @@ class ProfileForm(forms.ModelForm): model = User fields = ("first_name", "last_name") widgets = { - 'first_name': forms.TextInput(attrs={'class': 'form-control'}), - 'last_name': forms.TextInput(attrs={'class': 'form-control'}) - } + 'first_name': forms.TextInput(attrs={'class': 'form-control'}), + 'last_name': forms.TextInput(attrs={'class': 'form-control'}) + } def __init__(self, update_password, *args, **kwargs): super(ProfileForm, self).__init__(*args, **kwargs) @@ -61,15 +65,19 @@ class ProfileForm(forms.ModelForm): return self.cleaned_data["oldpassword"] def clean_confirmation(self): - if self.cleaned_data["newpassword"] != self.cleaned_data["confirmation"]: + newpassword = self.cleaned_data["newpassword"] + confirmation = self.cleaned_data["confirmation"] + if newpassword != confirmation: raise forms.ValidationError(_("Passwords mismatch")) return self.cleaned_data["confirmation"] def save(self, commit=True): user = super(ProfileForm, self).save(commit=False) if commit: - if self.cleaned_data.has_key("confirmation") and \ - self.cleaned_data["confirmation"] != "": - user.set_password(self.cleaned_data["confirmation"], self.cleaned_data["oldpassword"]) + if self.cleaned_data.get("confirmation", "") != "": + user.set_password( + self.cleaned_data["confirmation"], + self.cleaned_data["oldpassword"] + ) user.save() return user diff --git a/modoboa/core/management/commands/clean_unknown_extensions.py b/modoboa/core/management/commands/clean_unknown_extensions.py index f22c13852..d0a297fea 100644 --- a/modoboa/core/management/commands/clean_unknown_extensions.py +++ b/modoboa/core/management/commands/clean_unknown_extensions.py @@ -21,6 +21,6 @@ class Command(BaseCommand): """Entry point.""" for extension in Extension.objects.all(): fullname = "modoboa.extensions.{0}".format(extension.name) - if not fullname in settings.MODOBOA_APPS: + if fullname not in settings.MODOBOA_APPS: extension.delete() connection.close() diff --git a/modoboa/core/management/commands/manage_extensions.py b/modoboa/core/management/commands/manage_extensions.py index 24133a1e0..af90b1302 100644 --- a/modoboa/core/management/commands/manage_extensions.py +++ b/modoboa/core/management/commands/manage_extensions.py @@ -53,6 +53,6 @@ class Command(BaseCommand, CloseConnectionMixin): for extname in args: fullname = "modoboa.extensions.{0}".format(extname) - if not fullname in settings.MODOBOA_APPS: + if fullname not in settings.MODOBOA_APPS: continue self._change_extension_state(extname, options) diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 29f3be872..93f32451f 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -1,27 +1,33 @@ -import sys +"""Core models.""" + +import logging import os import re -import logging -import reversion -from django.db import models -from django.db.models.signals import post_delete +import sys + from django.conf import settings -from django.dispatch import receiver -from django.utils import timezone -from django.utils.translation import ugettext as _, ugettext_lazy -from django.contrib.contenttypes.models import ContentType -from django.contrib.contenttypes import generic +from django.contrib.auth.hashers import make_password, is_password_usable from django.contrib.auth.models import ( UserManager, Group, PermissionsMixin ) -from django.contrib.auth.hashers import make_password, is_password_usable +from django.contrib.contenttypes import generic +from django.contrib.contenttypes.models import ContentType +from django.db import models +from django.db.models.signals import post_delete +from django.dispatch import receiver +from django.utils import timezone +from django.utils.translation import ugettext as _, ugettext_lazy + +import reversion + +from modoboa.core.extensions import exts_pool +from modoboa.core.password_hashers import get_password_hasher from modoboa.lib import events, parameters from modoboa.lib.exceptions import ( PermDeniedException, InternalError, BadRequest, Conflict ) from modoboa.lib.sysutils import exec_cmd -from modoboa.core.extensions import exts_pool -from modoboa.core.password_hashers import get_password_hasher + try: from modoboa.lib.ldap_utils import LDAPAuthBackend @@ -242,7 +248,8 @@ class User(PermissionsMixin): """ ct = ContentType.objects.get_for_model(obj) try: - ooentry = self.objectaccess_set.get(content_type=ct, object_id=obj.id) + ooentry = self.objectaccess_set.get( + content_type=ct, object_id=obj.id) except ObjectAccess.DoesNotExist: return False return ooentry.is_owner @@ -263,7 +270,8 @@ class User(PermissionsMixin): ct = ContentType.objects.get_for_model(obj) try: - ooentry = self.objectaccess_set.get(content_type=ct, object_id=obj.id) + ooentry = self.objectaccess_set.get( + content_type=ct, object_id=obj.id) except ObjectAccess.DoesNotExist: pass else: @@ -333,7 +341,8 @@ class User(PermissionsMixin): if len(row) < 7: raise BadRequest(_("Invalid line")) role = row[6].strip() - if not user.is_superuser and not role in ["SimpleUsers", "DomainAdmins"]: + allowed_roles = ["SimpleUsers", "DomainAdmins"] + if not user.is_superuser and role not in allowed_roles: raise PermDeniedException( _("You can't import an account with a role greater than yours") ) @@ -345,13 +354,15 @@ class User(PermissionsMixin): else: raise Conflict if role == "SimpleUsers": - if (len(row) < 8 or not row[7].strip()): + 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 '%s' must have a valid email address" + % 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 '%s'" + % self.username) ) if crypt_password: @@ -374,9 +385,16 @@ class User(PermissionsMixin): :param csvwriter: csv object """ - row = ["account", self.username.encode("utf-8"), self.password.encode("utf-8"), - self.first_name.encode("utf-8"), self.last_name.encode("utf-8"), - self.is_active, self.group, self.email.encode("utf-8")] + row = [ + "account", + self.username.encode("utf-8"), + self.password.encode("utf-8"), + self.first_name.encode("utf-8"), + self.last_name.encode("utf-8"), + self.is_active, + self.group, + self.email.encode("utf-8") + ] row += events.raiseQueryEvent("AccountExported", self) csvwriter.writerow(row) @@ -414,7 +432,9 @@ class ObjectAccess(models.Model): unique_together = (("user", "content_type", "object_id"),) def __unicode__(self): - return "%s => %s (%s)" % (self.user, self.content_object, self.content_type) + return "%s => %s (%s)" % ( + self.user, self.content_object, self.content_type + ) class Extension(models.Model): @@ -501,7 +521,7 @@ def post_revision_commit(sender, **kwargs): """ from modoboa.lib.signals import get_request - current_user = get_request().user.username + current_user = get_request().user.username logger = logging.getLogger("modoboa.admin") for version in kwargs["versions"]: if version.object is None: diff --git a/modoboa/core/templatetags/core_tags.py b/modoboa/core/templatetags/core_tags.py index 9cbed9c08..9c9830c33 100644 --- a/modoboa/core/templatetags/core_tags.py +++ b/modoboa/core/templatetags/core_tags.py @@ -1,10 +1,14 @@ +"""Custom tags for Core application.""" + import re + from django import template +from django.contrib.sessions.models import Session +from django.core.urlresolvers import reverse from django.template.loader import render_to_string from django.utils import timezone from django.utils.translation import ugettext as _ -from django.core.urlresolvers import reverse -from django.contrib.sessions.models import Session + from modoboa.lib import events @@ -125,7 +129,7 @@ def colorize_level(level): "WARNING": "text-warning", "CRITICAL": "text-danger" } - if not level in classes: + if level not in classes: return level return "

%s

" % (classes[level], level) @@ -140,7 +144,7 @@ def tohtml(message): def visirule(field): if not hasattr(field, 'form') or \ not hasattr(field.form, "visirules") or \ - not field.html_name in field.form.visirules: + field.html_name not in field.form.visirules: return "" rule = field.form.visirules[field.html_name] return " data-visibility-field='%s' data-visibility-value='%s' " \ diff --git a/modoboa/core/tests.py b/modoboa/core/tests.py index 56ed41f2e..8c3608dae 100644 --- a/modoboa/core/tests.py +++ b/modoboa/core/tests.py @@ -74,7 +74,8 @@ class ModoboaAdminCommandTestCase(TestCase): categories = ["std", "autoreply", "relaydomains"] dburl = "{0}://user:password@localhost/testdb".format(engine) code, output = exec_cmd( - "modoboa-admin.py postfix_maps --categories {0} --dburl {1} {2}".format( + "modoboa-admin.py postfix_maps --categories {0}" + " --dburl {1} {2}".format( " ".join(categories), dburl, self.workdir ) ) diff --git a/modoboa/core/views/admin.py b/modoboa/core/views/admin.py index a81af1880..b4b36e056 100644 --- a/modoboa/core/views/admin.py +++ b/modoboa/core/views/admin.py @@ -1,15 +1,12 @@ """ Views available to super administrators only. """ - -from django.shortcuts import render -from django.template.loader import render_to_string -from django.utils.translation import ugettext as _ - from django.contrib.auth.decorators import ( login_required, user_passes_test ) - +from django.shortcuts import render +from django.template.loader import render_to_string +from django.utils.translation import ugettext as _ from modoboa.core.models import Extension, Log from modoboa.core.utils import new_version_available @@ -88,12 +85,12 @@ def saveextensions(request): if k.startswith("select_"): parts = k.split("_", 1) dbext = Extension.objects.get(name=parts[1]) - if not dbext in actived_exts: + if dbext not in actived_exts: dbext.on() else: found += [dbext] for ext in actived_exts: - if not ext in found: + if ext not in found: ext.off() return render_to_json_response(_("Modifications applied.")) diff --git a/modoboa/core/views/auth.py b/modoboa/core/views/auth.py index d46ef3ea2..44325a366 100644 --- a/modoboa/core/views/auth.py +++ b/modoboa/core/views/auth.py @@ -1,16 +1,19 @@ # coding: utf-8 import logging -from django.views.decorators.cache import never_cache + from django.contrib.auth import authenticate, login, logout -from django.http import HttpResponse, HttpResponseRedirect from django.core.urlresolvers import reverse +from django.http import HttpResponse, HttpResponseRedirect from django.utils.translation import ugettext as _ +from django.views.decorators.cache import never_cache + +from modoboa.core.forms import LoginForm from modoboa.lib import events, parameters from modoboa.lib.web_utils import _render_to_string -from modoboa.core.forms import LoginForm def dologin(request): + """Try to authenticate.""" error = None if request.method == "POST": form = LoginForm(request.POST) @@ -43,7 +46,7 @@ def dologin(request): error = _( "Your username and password didn't match. Please try again.") logger.warning( - "Failed connection attempt from '%(addr)s' as user '%(user)s'" \ + "Failed connection attempt from '%(addr)s' as user '%(user)s'" % {"addr": request.META["REMOTE_ADDR"], "user": form.cleaned_data["username"]} ) diff --git a/modoboa/core/views/user.py b/modoboa/core/views/user.py index 3cc2ec53d..7c444bbd6 100644 --- a/modoboa/core/views/user.py +++ b/modoboa/core/views/user.py @@ -1,12 +1,15 @@ +"""Simple user views.""" + +from django.contrib.auth.decorators import login_required from django.shortcuts import render from django.utils.translation import ugettext as _ -from django.contrib.auth.decorators import login_required + +from modoboa.core.forms import ProfileForm from modoboa.lib import events, parameters +from modoboa.lib.cryptutils import encrypt from modoboa.lib.web_utils import ( _render_to_string, render_to_json_response ) -from modoboa.lib.cryptutils import encrypt -from modoboa.core.forms import ProfileForm @login_required @@ -31,7 +34,8 @@ def profile(request, tplname='core/user_profile.html'): if form.is_valid(): form.save() if update_password and form.cleaned_data["confirmation"] != "": - request.session["password"] = encrypt(form.cleaned_data["confirmation"]) + request.session["password"] = encrypt( + form.cleaned_data["confirmation"]) return render_to_json_response(_("Profile updated")) return render_to_json_response({'form_errors': form.errors}, status=400) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 000000000..a7854adaf --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[pep8] +max-line-length = 80 +exclude = migrations From 2684f9eae9f14e743b688dae07f2f0c842c05ae0 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 14 Jan 2015 14:05:53 +0100 Subject: [PATCH 11/24] PEP8 fixes --- modoboa/extensions/admin/__init__.py | 33 +++++---- modoboa/extensions/admin/forms/account.py | 68 +++++++++++-------- modoboa/extensions/admin/forms/alias.py | 18 +++-- modoboa/extensions/admin/forms/domain.py | 22 +++--- modoboa/extensions/admin/forms/forward.py | 13 ++-- modoboa/extensions/admin/forms/import_.py | 13 +++- modoboa/extensions/admin/models/alias.py | 20 +++--- modoboa/extensions/admin/models/domain.py | 17 +++-- .../extensions/admin/models/domain_alias.py | 8 ++- modoboa/extensions/admin/models/mailbox.py | 33 +++++---- 10 files changed, 154 insertions(+), 91 deletions(-) diff --git a/modoboa/extensions/admin/__init__.py b/modoboa/extensions/admin/__init__.py index 75dbd30fc..1c23ae3d7 100644 --- a/modoboa/extensions/admin/__init__.py +++ b/modoboa/extensions/admin/__init__.py @@ -1,13 +1,15 @@ # coding: utf-8 -from django.utils.translation import ugettext as _, ugettext_lazy from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _, ugettext_lazy + from modoboa.core.extensions import ModoExtension, exts_pool -from modoboa.lib import parameters, events -from modoboa.lib.exceptions import PermDeniedException, BadRequest, Conflict -from modoboa.lib.email_utils import split_mailbox from modoboa.extensions.admin.models import ( Domain, DomainAlias, Mailbox, Alias ) +from modoboa.lib import parameters, events +from modoboa.lib.email_utils import split_mailbox +from modoboa.lib.exceptions import PermDeniedException, BadRequest, Conflict + admin_events = [ "DomainCreated", @@ -54,7 +56,8 @@ class AdminConsole(ModoExtension): def load(self): from modoboa.extensions.admin.app_settings import AdminParametersForm - parameters.register(AdminParametersForm, ugettext_lazy("Administration")) + parameters.register( + AdminParametersForm, ugettext_lazy("Administration")) events.declare(admin_events) def destroy(self): @@ -80,15 +83,15 @@ def admin_menu(target, user): entries = [] if user.has_perm("admin.view_domains"): entries += [ - {"name" : "domains", - "url" : reverse("admin:domain_list"), - "label" : _("Domains")} + {"name": "domains", + "url": reverse("admin:domain_list"), + "label": _("Domains")} ] if user.has_perm("core.add_user") or user.has_perm("admin.add_alias"): entries += [ - {"name" : "identities", - "url" : reverse("admin:identity_list"), - "label" : _("Identities")}, + {"name": "identities", + "url": reverse("admin:identity_list"), + "label": _("Identities")}, ] return entries @@ -166,7 +169,8 @@ def import_account_mailbox(user, account, row): domain = Domain.objects.get(name=domname) except Domain.DoesNotExist: raise BadRequest( - _("Account import failed (%s): domain does not exist" % account.username) + _("Account import failed (%s): domain does not exist" + % account.username) ) if not user.can_access(domain): raise PermDeniedException @@ -175,7 +179,7 @@ def import_account_mailbox(user, account, row): except Mailbox.DoesNotExist: pass else: - raise Conflict(_("Mailbox %s already exists" % account.email)) + raise Conflict(_("Mailbox %s already exists" % account.email)) if len(row) == 1: quota = None else: @@ -183,7 +187,8 @@ def import_account_mailbox(user, account, row): quota = int(row[1].strip()) except ValueError: raise BadRequest( - _("Account import failed (%s): wrong quota value" % account.username) + _("Account import failed (%s): wrong quota value" + % account.username) ) use_domain_quota = True if not quota else False mb = Mailbox(address=mailbox, domain=domain, diff --git a/modoboa/extensions/admin/forms/account.py b/modoboa/extensions/admin/forms/account.py index 568c0ed25..a010ec0dc 100644 --- a/modoboa/extensions/admin/forms/account.py +++ b/modoboa/extensions/admin/forms/account.py @@ -1,19 +1,22 @@ +"""Forms related to accounts management.""" + from django import forms -from django.utils.translation import ugettext as _, ugettext_lazy -from django.http import QueryDict from django.core.urlresolvers import reverse -from modoboa.lib import events, parameters -from modoboa.lib.exceptions import PermDeniedException, Conflict, NotFound -from modoboa.lib.permissions import get_account_roles -from modoboa.lib.email_utils import split_mailbox -from modoboa.lib.form_utils import ( - DomainNameField, DynamicForm, TabForms, WizardForm -) -from modoboa.lib.web_utils import render_to_json_response +from django.http import QueryDict +from django.utils.translation import ugettext as _, ugettext_lazy + from modoboa.core.models import User from modoboa.extensions.admin.models import ( Domain, Mailbox, Alias ) +from modoboa.lib import events, parameters +from modoboa.lib.email_utils import split_mailbox +from modoboa.lib.exceptions import PermDeniedException, Conflict, NotFound +from modoboa.lib.form_utils import ( + DomainNameField, DynamicForm, TabForms, WizardForm +) +from modoboa.lib.permissions import get_account_roles +from modoboa.lib.web_utils import render_to_json_response class AccountFormGeneral(forms.ModelForm): @@ -77,7 +80,8 @@ class AccountFormGeneral(forms.ModelForm): del self.fields["is_active"] self.fields["role"].initial = account.group if not account.is_local \ - and parameters.get_admin("LDAP_AUTH_METHOD", app="core") == "directbind": + and parameters.get_admin( + "LDAP_AUTH_METHOD", app="core") == "directbind": del self.fields["password1"] del self.fields["password2"] @@ -90,7 +94,7 @@ class AccountFormGeneral(forms.ModelForm): """ if not self.instance.mailbox_set.count(): return False - return self.instance.mailbox_set.all()[0].domain.enabled == False + return not self.instance.mailbox_set.all()[0].domain.enabled def clean_role(self): if self.user.group == "DomainAdmins": @@ -101,7 +105,7 @@ class AccountFormGeneral(forms.ModelForm): def clean_username(self): from django.core.validators import validate_email - if not "role" in self.cleaned_data: + if "role" not in self.cleaned_data: return self.cleaned_data["username"] if self.cleaned_data["role"] != "SimpleUsers": return self.cleaned_data["username"] @@ -113,7 +117,8 @@ class AccountFormGeneral(forms.ModelForm): password1 = self.cleaned_data.get("password1", "") password2 = self.cleaned_data["password2"] if password1 != password2: - raise forms.ValidationError(_("The two password fields didn't match.")) + raise forms.ValidationError( + _("The two password fields didn't match.")) return password2 def save(self, commit=True): @@ -165,7 +170,8 @@ class AccountFormMail(forms.Form, DynamicForm): "quota": 3 } self.extra_fields = [] - for fname, field in events.raiseQueryEvent('ExtraFormFields', 'mailform', self.mb): + result = events.raiseQueryEvent('ExtraFormFields', 'mailform', self.mb) + for fname, field in result: self.fields[fname] = field self.extra_fields.append(fname) if self.mb is not None: @@ -227,7 +233,7 @@ class AccountFormMail(forms.Form, DynamicForm): events.raiseEvent("CanCreate", user, "mailboxes") self.mb = Mailbox(address=locpart, domain=domain, user=account, use_domain_quota=self.cleaned_data["quota_act"]) - self.mb.set_quota(self.cleaned_data["quota"], + self.mb.set_quota(self.cleaned_data["quota"], user.has_perm("admin.add_domain")) self.mb.save(creator=user) @@ -235,7 +241,8 @@ class AccountFormMail(forms.Form, DynamicForm): newaddress = None if self.cleaned_data["email"] != self.mb.full_address: newaddress = self.cleaned_data["email"] - elif account.group == "SimpleUsers" and account.username != self.mb.full_address: + elif (account.group == "SimpleUsers" and + account.username != self.mb.full_address): newaddress = account.username if newaddress is not None: self.mb.old_full_address = self.mb.full_address @@ -267,7 +274,7 @@ class AccountFormMail(forms.Form, DynamicForm): aliases.append(value) for alias in self.mb.alias_set.all(): - if not alias.full_address in aliases: + if alias.full_address not in aliases: if len(alias.get_recipients()) >= 2: continue alias.delete() @@ -331,9 +338,9 @@ class AccountPermissionsForm(forms.Form, DynamicForm): if not hasattr(self, "account") or self.account is None: return - for pos, domain in enumerate(Domain.objects.get_for_admin(self.account)): + for pos, dom in enumerate(Domain.objects.get_for_admin(self.account)): name = "domains_%d" % (pos + 1) - self._create_field(DomainNameField, name, domain.name) + self._create_field(DomainNameField, name, dom.name) if len(args) and isinstance(args[0], QueryDict): self._load_from_qdict(args[0], "domains", DomainNameField) @@ -346,20 +353,20 @@ class AccountPermissionsForm(forms.Form, DynamicForm): continue if value in ["", None]: continue - if not value in current_domains: + if value not in current_domains: domain = Domain.objects.get(name=value) domain.add_admin(self.account) for domain in Domain.objects.get_for_admin(self.account): - if not len(filter(lambda name: self.cleaned_data[name] == domain.name, - self.cleaned_data.keys())): + if not filter(lambda name: self.cleaned_data[name] == domain.name, + self.cleaned_data.keys()): domain.remove_admin(self.account) class AccountForm(TabForms): - """Account edition form. - """ + """Account edition form.""" + def __init__(self, request, *args, **kwargs): self.user = request.user self.forms = [ @@ -369,8 +376,11 @@ class AccountForm(TabForms): new_args=[self.user], mandatory=True), dict(id="mail", title=_("Mail"), formtpl="admin/mailform.html", cls=AccountFormMail), - dict(id="perms", title=_("Permissions"), formtpl="admin/permsform.html", - cls=AccountPermissionsForm) + dict( + id="perms", title=_("Permissions"), + formtpl="admin/permsform.html", + cls=AccountPermissionsForm + ) ] cbargs = [self.user] if "instances" in kwargs: @@ -402,7 +412,9 @@ class AccountForm(TabForms): return False return True - if False in events.raiseQueryEvent("CheckExtraAccountForm", self.account, form): + extra_forms = events.raiseQueryEvent( + "CheckExtraAccountForm", self.account, form) + if False in extra_forms: return False return True diff --git a/modoboa/extensions/admin/forms/alias.py b/modoboa/extensions/admin/forms/alias.py index d66e2820e..d54dad929 100644 --- a/modoboa/extensions/admin/forms/alias.py +++ b/modoboa/extensions/admin/forms/alias.py @@ -1,14 +1,17 @@ +"""Forms related to aliases management.""" + from django import forms -from django.utils.translation import ugettext as _, ugettext_lazy from django.http import QueryDict -from modoboa.lib.exceptions import BadRequest, NotFound, Conflict -from modoboa.lib.email_utils import split_mailbox -from modoboa.lib.form_utils import ( - DynamicForm -) +from django.utils.translation import ugettext as _, ugettext_lazy + from modoboa.extensions.admin.models import ( Domain, Mailbox, Alias ) +from modoboa.lib.email_utils import split_mailbox +from modoboa.lib.exceptions import BadRequest, NotFound, Conflict +from modoboa.lib.form_utils import ( + DynamicForm +) class AliasForm(forms.ModelForm, DynamicForm): @@ -109,7 +112,8 @@ class AliasForm(forms.ModelForm, DynamicForm): rcpt = None if rcpt is None: try: - rcpt = Mailbox.objects.get(domain=domain, address=local_part) + rcpt = Mailbox.objects.get( + domain=domain, address=local_part) except Mailbox.DoesNotExist: raise NotFound( _("Local recipient %s not found" % v) diff --git a/modoboa/extensions/admin/forms/domain.py b/modoboa/extensions/admin/forms/domain.py index 6ec676bbf..667ad6ef0 100644 --- a/modoboa/extensions/admin/forms/domain.py +++ b/modoboa/extensions/admin/forms/domain.py @@ -1,19 +1,21 @@ +"""Forms related to domains management.""" + from django import forms +from django.core.urlresolvers import reverse from django.http import QueryDict from django.utils.translation import ugettext as _, ugettext_lazy -from django.core.urlresolvers import reverse +from modoboa.core.models import User +from modoboa.extensions.admin.lib import check_if_domain_exists +from modoboa.extensions.admin.models import ( + Domain, DomainAlias, Mailbox, Alias, Quota +) from modoboa.lib import events, parameters from modoboa.lib.exceptions import ModoboaException, Conflict from modoboa.lib.form_utils import ( DomainNameField, YesNoField, WizardForm, DynamicForm, TabForms ) from modoboa.lib.web_utils import render_to_json_response -from modoboa.core.models import User -from modoboa.extensions.admin.lib import check_if_domain_exists -from modoboa.extensions.admin.models import ( - Domain, DomainAlias, Mailbox, Alias, Quota -) class DomainFormGeneral(forms.ModelForm, DynamicForm): @@ -153,12 +155,13 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm): continue aliases.append(v) for dalias in d.domainalias_set.all(): - if not dalias.name in aliases: + if dalias.name not in aliases: dalias.delete() else: aliases.remove(dalias.name) if aliases: - events.raiseEvent("CanCreate", user, "domain_aliases", len(aliases)) + events.raiseEvent( + "CanCreate", user, "domain_aliases", len(aliases)) for alias in aliases: try: d.domainalias_set.get(name=alias) @@ -207,7 +210,8 @@ class DomainFormOptions(forms.Form): def __init__(self, user, *args, **kwargs): super(DomainFormOptions, self).__init__(*args, **kwargs) - if False in events.raiseQueryEvent('UserCanSetRole', user, 'DomainAdmins'): + result = events.raiseQueryEvent('UserCanSetRole', user, 'DomainAdmins') + if False in result: self.fields = {} return if args: diff --git a/modoboa/extensions/admin/forms/forward.py b/modoboa/extensions/admin/forms/forward.py index f39a5ce5e..c4d1e4a7b 100644 --- a/modoboa/extensions/admin/forms/forward.py +++ b/modoboa/extensions/admin/forms/forward.py @@ -1,10 +1,13 @@ +"""Forms related to forwards management.""" + from django import forms from django.utils.translation import ugettext as _, ugettext_lazy -from modoboa.lib.exceptions import BadRequest, PermDeniedException -from modoboa.lib.email_utils import split_mailbox + from modoboa.extensions.admin.models import ( Domain ) +from modoboa.lib.email_utils import split_mailbox +from modoboa.lib.exceptions import BadRequest, PermDeniedException class ForwardForm(forms.Form): @@ -12,12 +15,14 @@ class ForwardForm(forms.Form): label=ugettext_lazy("Recipient(s)"), widget=forms.Textarea(attrs={"class": "form-control"}), required=False, - help_text=ugettext_lazy("Indicate one or more recipients separated by a ','") + help_text=ugettext_lazy( + "Indicate one or more recipients separated by a ','") ) keepcopies = forms.BooleanField( label=ugettext_lazy("Keep local copies"), required=False, - help_text=ugettext_lazy("Forward messages and store copies into your local mailbox") + help_text=ugettext_lazy( + "Forward messages and store copies into your local mailbox") ) def parse_dest(self): diff --git a/modoboa/extensions/admin/forms/import_.py b/modoboa/extensions/admin/forms/import_.py index f63017037..0091e4ba8 100644 --- a/modoboa/extensions/admin/forms/import_.py +++ b/modoboa/extensions/admin/forms/import_.py @@ -1,8 +1,13 @@ +"""Forms related to import operations.""" + from django import forms from django.utils.translation import ugettext_lazy class ImportDataForm(forms.Form): + + """Base form to import objects.""" + sourcefile = forms.FileField(label=ugettext_lazy("Select a file")) sepchar = forms.CharField( label=ugettext_lazy("Separator"), @@ -26,7 +31,13 @@ class ImportDataForm(forms.Form): class ImportIdentitiesForm(ImportDataForm): + + """A form to import identities.""" + crypt_password = forms.BooleanField( label=ugettext_lazy("Crypt passwords"), required=False, - help_text=ugettext_lazy("Check this option if passwords contained in your file are not crypted") + help_text=ugettext_lazy( + "Check this option if passwords contained in your file " + "are not crypted" + ) ) diff --git a/modoboa/extensions/admin/models/alias.py b/modoboa/extensions/admin/models/alias.py index 7a1687e44..a44ea9bf9 100644 --- a/modoboa/extensions/admin/models/alias.py +++ b/modoboa/extensions/admin/models/alias.py @@ -1,13 +1,17 @@ -import reversion +"""Models related to aliases management.""" + from django.db import models from django.utils.translation import ugettext as _, ugettext_lazy + +import reversion + +from .base import AdminObject +from .domain import Domain +from .mailbox import Mailbox from modoboa.lib.email_utils import split_mailbox from modoboa.lib.exceptions import ( PermDeniedException, BadRequest, Conflict ) -from .base import AdminObject -from .domain import Domain -from .mailbox import Mailbox class Alias(AdminObject): @@ -108,16 +112,16 @@ class Alias(AdminObject): curmboxes = self.mboxes.all() for rcpt in int_rcpts: if isinstance(rcpt, Alias): - if not rcpt in curaliases: + if rcpt not in curaliases: self.aliases.add(rcpt) continue - if not rcpt in curmboxes: + if rcpt not in curmboxes: self.mboxes.add(rcpt) for rcpt in curaliases: - if not rcpt in int_rcpts: + if rcpt not in int_rcpts: self.aliases.remove(rcpt) for rcpt in curmboxes: - if not rcpt in int_rcpts: + if rcpt not in int_rcpts: self.mboxes.remove(rcpt) def get_recipients(self, with_external=True): diff --git a/modoboa/extensions/admin/models/domain.py b/modoboa/extensions/admin/models/domain.py index 5d8566d62..e03a36d02 100644 --- a/modoboa/extensions/admin/models/domain.py +++ b/modoboa/extensions/admin/models/domain.py @@ -1,12 +1,16 @@ -import reversion +"""Models related to domains management.""" + +from django.contrib.contenttypes import generic from django.db import models from django.db.models.manager import Manager from django.utils.translation import ugettext as _, ugettext_lazy -from django.contrib.contenttypes import generic + +import reversion + +from .base import AdminObject +from modoboa.core.models import User, ObjectAccess from modoboa.lib import events, parameters from modoboa.lib.exceptions import BadRequest, Conflict -from modoboa.core.models import User, ObjectAccess -from .base import AdminObject class DomainManager(Manager): @@ -109,7 +113,7 @@ class Domain(AdminObject): ungrant_access_to_object(mb, account) ungrant_access_to_object(mb.user, account) for al in self.alias_set.all(): - ungrant_access_to_object(al, account) + ungrant_access_to_object(al, account) def delete(self, fromuser, keepdir=False): """Custom delete method. @@ -157,7 +161,8 @@ class Domain(AdminObject): try: self.quota = int(row[2].strip()) except ValueError: - raise BadRequest(_("Invalid quota value for domain '%s'" % self.name)) + raise BadRequest( + _("Invalid quota value for domain '%s'" % self.name)) self.enabled = (row[3].strip() in ["True", "1", "yes", "y"]) self.save(creator=user) diff --git a/modoboa/extensions/admin/models/domain_alias.py b/modoboa/extensions/admin/models/domain_alias.py index 51b542dd0..a0ab23bfc 100644 --- a/modoboa/extensions/admin/models/domain_alias.py +++ b/modoboa/extensions/admin/models/domain_alias.py @@ -1,9 +1,13 @@ -import reversion +"""Models related to domain aliases management.""" + from django.db import models from django.utils.translation import ugettext as _, ugettext_lazy -from modoboa.lib.exceptions import BadRequest, Conflict + +import reversion + from .base import AdminObject from .domain import Domain +from modoboa.lib.exceptions import BadRequest, Conflict class DomainAlias(AdminObject): diff --git a/modoboa/extensions/admin/models/mailbox.py b/modoboa/extensions/admin/models/mailbox.py index 631dbb2ff..fcc46e52c 100644 --- a/modoboa/extensions/admin/models/mailbox.py +++ b/modoboa/extensions/admin/models/mailbox.py @@ -1,19 +1,24 @@ +"""Models related to mailboxes management.""" + import os import pwd -import reversion + +from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models import Q from django.db.models.manager import Manager -from django.contrib.contenttypes.models import ContentType -from django.utils.translation import ugettext as _, ugettext_lazy from django.db.models.signals import pre_delete from django.dispatch import receiver +from django.utils.translation import ugettext as _, ugettext_lazy + +import reversion + +from .base import AdminObject +from .domain import Domain +from modoboa.core.models import User from modoboa.lib import parameters, events from modoboa.lib.exceptions import BadRequest, InternalError from modoboa.lib.sysutils import exec_cmd -from modoboa.core.models import User -from .base import AdminObject -from .domain import Domain class Quota(models.Model): @@ -72,7 +77,8 @@ class Mailbox(AdminObject): address = models.CharField( ugettext_lazy('address'), max_length=252, - help_text=ugettext_lazy("Mailbox address (without the @domain.tld part)") + help_text=ugettext_lazy( + "Mailbox address (without the @domain.tld part)") ) quota = models.PositiveIntegerField() use_domain_quota = models.BooleanField(default=False) @@ -112,7 +118,7 @@ class Mailbox(AdminObject): @property def mail_home(self): """Retrieve the home directory of this mailbox. - + The home directory refers to the place on the file system where the mailbox data is stored. @@ -131,9 +137,10 @@ class Mailbox(AdminObject): options['sudo_user'] = mbowner code, output = exec_cmd( "doveadm user %s -f home" % self.full_address, **options - ) + ) if code: - raise InternalError(_("Failed to retrieve mailbox location (%s)" % output)) + raise InternalError( + _("Failed to retrieve mailbox location (%s)" % output)) self.__mail_home = output.strip() return self.__mail_home @@ -273,7 +280,9 @@ class Mailbox(AdminObject): We try to delete the associated quota in the same time (it may has already been removed if we're deleting a domain). - :param bool keepdir: delete the mailbox home dir on the filesystem or not + :param bool keepdir: delete the mailbox home dir on the + filesystem or not + """ try: q = Quota.objects.get(username=self.full_address) @@ -322,4 +331,4 @@ 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 'Delete %s' % self.argument From 38434191567b4ca687462bdcfa917a1d5152bb58 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 14 Jan 2015 15:25:58 +0100 Subject: [PATCH 12/24] PEP8 fixes --- .../admin/templatetags/admin_tags.py | 5 +-- modoboa/extensions/admin/tests/account.py | 20 ++++++---- modoboa/extensions/admin/tests/alias.py | 9 +++-- modoboa/extensions/admin/tests/export.py | 9 +++-- modoboa/extensions/admin/tests/import_.py | 15 +++++--- modoboa/extensions/admin/views/export.py | 21 ++++++---- modoboa/extensions/admin/views/identity.py | 38 +++++++++++-------- modoboa/extensions/admin/views/import.py | 22 +++++++---- .../amavis/templatetags/amavis_tags.py | 15 +++++--- 9 files changed, 94 insertions(+), 60 deletions(-) diff --git a/modoboa/extensions/admin/templatetags/admin_tags.py b/modoboa/extensions/admin/templatetags/admin_tags.py index 24290feef..d05b8ad9c 100644 --- a/modoboa/extensions/admin/templatetags/admin_tags.py +++ b/modoboa/extensions/admin/templatetags/admin_tags.py @@ -147,7 +147,8 @@ def domain_actions(user, domain): if domain.__class__.__name__ == 'Domain': actions = [ {"name": "listidentities", - "url": reverse("admin:identity_list") + "#list/?searchquery=@%s" % domain.name, + "url": "{0}#list/?searchquery=@{1}".format( + reverse("admin:identity_list"), domain.name), "title": _("View the domain's identities"), "img": "fa fa-user"} ] @@ -277,5 +278,3 @@ def get_extra_admin_content(user, target, currentpage): "ExtraAdminContent", user, target, currentpage ) return "".join(res) - - diff --git a/modoboa/extensions/admin/tests/account.py b/modoboa/extensions/admin/tests/account.py index 12b16fee8..6881056a4 100644 --- a/modoboa/extensions/admin/tests/account.py +++ b/modoboa/extensions/admin/tests/account.py @@ -1,10 +1,11 @@ from django.core.urlresolvers import reverse + from modoboa.core.models import User -from modoboa.lib.tests import ModoTestCase +from modoboa.extensions.admin import factories from modoboa.extensions.admin.models import ( Domain, Mailbox ) -from modoboa.extensions.admin import factories +from modoboa.lib.tests import ModoTestCase class AccountTestCase(ModoTestCase): @@ -62,10 +63,14 @@ class AccountTestCase(ModoTestCase): def test_set_nul_quota_as_domainadmin(self): self.clt.logout() - self.assertTrue(self.clt.login(username="admin@test.com", password="toto")) + self.assertTrue( + self.clt.login(username="admin@test.com", password="toto") + ) self._set_quota("user@test.com", 0, 400) self.clt.logout() - self.assertTrue(self.clt.login(username="admin@test2.com", password="toto")) + self.assertTrue( + self.clt.login(username="admin@test2.com", password="toto") + ) self._set_quota("user@test2.com", 0) @@ -119,8 +124,9 @@ class PermissionsTestCase(ModoTestCase): def test_self_modif(self): self.clt.logout() - self.assertEqual(self.clt.login(username="admin@test.com", password="toto"), - True) + self.assertTrue( + self.clt.login(username="admin@test.com", password="toto") + ) admin = User.objects.get(username="admin@test.com") values = dict( username="admin@test.com", first_name="Admin", @@ -132,7 +138,7 @@ class PermissionsTestCase(ModoTestCase): values ) self.assertEqual(admin.group, "DomainAdmins") - self.assertEqual(admin.can_access(Domain.objects.get(name="test.com")), True) + self.assertTrue(admin.can_access(Domain.objects.get(name="test.com"))) values["role"] = "SuperAdmins" self.ajax_post( diff --git a/modoboa/extensions/admin/tests/alias.py b/modoboa/extensions/admin/tests/alias.py index 5dbac1a8d..e470b8d49 100644 --- a/modoboa/extensions/admin/tests/alias.py +++ b/modoboa/extensions/admin/tests/alias.py @@ -1,10 +1,11 @@ from django.core.urlresolvers import reverse + from modoboa.core.models import User -from modoboa.lib.tests import ModoTestCase +from modoboa.extensions.admin import factories from modoboa.extensions.admin.models import ( Alias ) -from modoboa.extensions.admin import factories +from modoboa.lib.tests import ModoTestCase class AliasTestCase(ModoTestCase): @@ -80,8 +81,8 @@ class AliasTestCase(ModoTestCase): self.assertEqual(fwd.get_recipients_count(), 1) self.ajax_post( - reverse("admin:alias_delete") + "?selection=%d" \ - % fwd.id, {} + reverse("admin:alias_delete") + "?selection=%d" + % fwd.id, {} ) self.assertRaises(Alias.DoesNotExist, Alias.objects.get, address="forward2", domain__name="test.com") diff --git a/modoboa/extensions/admin/tests/export.py b/modoboa/extensions/admin/tests/export.py index 19df335a1..ca95c4b7d 100644 --- a/modoboa/extensions/admin/tests/export.py +++ b/modoboa/extensions/admin/tests/export.py @@ -1,6 +1,7 @@ from django.core.urlresolvers import reverse -from modoboa.lib.tests import ModoTestCase + from modoboa.extensions.admin import factories +from modoboa.lib.tests import ModoTestCase class ExportTestCase(ModoTestCase): @@ -12,8 +13,8 @@ class ExportTestCase(ModoTestCase): def __export_identities(self, idtfilter="", grpfilter=""): self.clt.get( - reverse("admin:_identity_list") \ - + "?grpfilter=%s&idtfilter=%s" % (grpfilter, idtfilter) + reverse("admin:_identity_list") + + "?grpfilter=%s&idtfilter=%s" % (grpfilter, idtfilter) ) return self.clt.post( reverse("admin:identity_export"), @@ -39,7 +40,7 @@ class ExportTestCase(ModoTestCase): idtfilter="account", grpfilter="SimpleUsers" ) self.assertListEqual( - "account;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10", + "account;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10", response.content.strip() ) diff --git a/modoboa/extensions/admin/tests/import_.py b/modoboa/extensions/admin/tests/import_.py index 5195ad0e0..dee11d995 100644 --- a/modoboa/extensions/admin/tests/import_.py +++ b/modoboa/extensions/admin/tests/import_.py @@ -1,12 +1,13 @@ # coding: utf-8 -from django.core.urlresolvers import reverse from django.core.files.base import ContentFile +from django.core.urlresolvers import reverse + from modoboa.core.models import User -from modoboa.lib.tests import ModoTestCase +from modoboa.extensions.admin import factories from modoboa.extensions.admin.models import ( Domain, Alias, DomainAlias ) -from modoboa.extensions.admin import factories +from modoboa.lib.tests import ModoTestCase class ImportTestCase(ModoTestCase): @@ -76,7 +77,9 @@ dlist; dlist@test.com; True; user1@test.com; user@extdomain.com self.assertEqual(mb1.quota, 0) self.assertTrue(admin.is_owner(mb1)) self.assertEqual(mb1.full_address, "user1@test.com") - self.assertTrue(self.clt.login(username="user1@test.com", password="toto")) + self.assertTrue( + self.clt.login(username="user1@test.com", password="toto") + ) da = User.objects.get(username="truc@test.com") damb = da.mailbox_set.all()[0] @@ -159,7 +162,9 @@ account; truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 0; Expected result: no """ self.clt.logout() - self.assertTrue(self.clt.login(username="admin@test.com", password="toto")) + self.assertTrue( + self.clt.login(username="admin@test.com", password="toto") + ) f = ContentFile(b""" account; sa@test.com; toto; Super; Admin; True; SuperAdmins; superadmin@test.com; 50 """, name="identities.csv") diff --git a/modoboa/extensions/admin/views/export.py b/modoboa/extensions/admin/views/export.py index 865371746..38fe6494f 100644 --- a/modoboa/extensions/admin/views/export.py +++ b/modoboa/extensions/admin/views/export.py @@ -1,17 +1,22 @@ -import csv +"""Export related views.""" + import cStringIO +import csv + from rfc6266 import build_header -from django.http import HttpResponse -from django.shortcuts import render -from django.core.urlresolvers import reverse -from django.utils.translation import ugettext as _ + from django.contrib.auth.decorators import ( login_required, permission_required, user_passes_test ) -from modoboa.extensions.admin.lib import get_domains, get_identities +from django.core.urlresolvers import reverse +from django.http import HttpResponse +from django.shortcuts import render +from django.utils.translation import ugettext as _ + from modoboa.extensions.admin.forms import ( ExportIdentitiesForm, ExportDomainsForm ) +from modoboa.extensions.admin.lib import get_domains, get_identities def _export(content, filename): @@ -46,7 +51,9 @@ def export_identities(request): form.is_valid() fp = cStringIO.StringIO() csvwriter = csv.writer(fp, delimiter=form.cleaned_data["sepchar"]) - for ident in get_identities(request.user, **request.session['identities_filters']): + identities = get_identities( + request.user, **request.session['identities_filters']) + for ident in identities: ident.to_csv(csvwriter) content = fp.getvalue() fp.close() diff --git a/modoboa/extensions/admin/views/identity.py b/modoboa/extensions/admin/views/identity.py index bc41b2e55..58b93cebb 100644 --- a/modoboa/extensions/admin/views/identity.py +++ b/modoboa/extensions/admin/views/identity.py @@ -1,30 +1,29 @@ -""" -Identity related views. -""" -from django.shortcuts import render -from django.utils.translation import ugettext as _, ungettext +"""Identity related views.""" + from django.contrib.auth.decorators import ( login_required, permission_required, user_passes_test ) +from django.shortcuts import render +from django.utils.translation import ugettext as _, ungettext from django.views.decorators.csrf import ensure_csrf_cookie import reversion +from modoboa.core.models import User +from modoboa.extensions.admin.forms import ( + AccountForm +) +from modoboa.extensions.admin.lib import get_identities +from modoboa.extensions.admin.models import Mailbox, Domain from modoboa.lib import parameters, events from modoboa.lib.exceptions import ( PermDeniedException, BadRequest ) -from modoboa.lib.web_utils import ( - _render_to_string, render_to_json_response -) -from modoboa.core.models import User -from modoboa.extensions.admin.models import Mailbox, Domain from modoboa.lib.listing import ( get_sort_order, get_listing_page ) -from modoboa.extensions.admin.lib import get_identities -from modoboa.extensions.admin.forms import ( - AccountForm +from modoboa.lib.web_utils import ( + _render_to_string, render_to_json_response ) @@ -80,9 +79,15 @@ def list_quotas(request): where = "admin_mailbox.address||'@'||admin_domain.name" db_type = db_type() if db_type == "postgres": - select = '(admin_quota.bytes::float / (CAST(admin_mailbox.quota AS BIGINT) * 1048576)) * 100' + select = ( + "(admin_quota.bytes::float / (CAST(admin_mailbox.quota " + "AS BIGINT) * 1048576)) * 100" + ) else: - select = 'admin_quota.bytes / (admin_mailbox.quota * 1048576) * 100' + select = ( + "admin_quota.bytes / (admin_mailbox.quota " + "* 1048576) * 100" + ) if db_type == "mysql": where = "CONCAT(admin_mailbox.address,'@',admin_domain.name)" mboxes = mboxes.extra( @@ -191,7 +196,8 @@ def remove_permission(request): domain = Domain.objects.get(pk=domid) except (User.DoesNotExist, Domain.DoesNotExist): raise BadRequest(_("Invalid request")) - if not request.user.can_access(account) or not request.user.can_access(domain): + if not request.user.can_access(account) or \ + not request.user.can_access(domain): raise PermDeniedException domain.remove_admin(account) return render_to_json_response({}) diff --git a/modoboa/extensions/admin/views/import.py b/modoboa/extensions/admin/views/import.py index fb1e6918f..a06a3a8cf 100644 --- a/modoboa/extensions/admin/views/import.py +++ b/modoboa/extensions/admin/views/import.py @@ -1,18 +1,23 @@ +"""Import related views.""" + import csv -import reversion -from django.utils.translation import ugettext as _ -from django.shortcuts import render -from django.core.urlresolvers import reverse + from django.contrib.auth.decorators import ( login_required, permission_required, user_passes_test ) -from modoboa.lib import events -from modoboa.lib.exceptions import ModoboaException, Conflict +from django.core.urlresolvers import reverse +from django.shortcuts import render +from django.utils.translation import ugettext as _ + +import reversion + from modoboa.core.models import User +from modoboa.extensions.admin.forms import ImportIdentitiesForm, ImportDataForm from modoboa.extensions.admin.models import ( Domain, DomainAlias, Alias ) -from modoboa.extensions.admin.forms import ImportIdentitiesForm, ImportDataForm +from modoboa.lib import events +from modoboa.lib.exceptions import ModoboaException, Conflict def import_domain(user, row, formopts): @@ -41,7 +46,8 @@ def import_domains(request):

The first element of each line is mandatory and must be equal to one of the previous values.

You can use a different character as separator.

-""" % ''.join([unicode(hlp) for hlp in events.raiseQueryEvent('ExtraDomainImportHelp')])) +""" % ''.join([unicode(hlp) for hlp in + events.raiseQueryEvent('ExtraDomainImportHelp')])) ctx = dict( title=_("Import domains"), diff --git a/modoboa/extensions/amavis/templatetags/amavis_tags.py b/modoboa/extensions/amavis/templatetags/amavis_tags.py index 79b8ac9b3..f5d1a2c9a 100644 --- a/modoboa/extensions/amavis/templatetags/amavis_tags.py +++ b/modoboa/extensions/amavis/templatetags/amavis_tags.py @@ -80,20 +80,23 @@ def viewm_menu(user, mail_id, rcpt): @register.simple_tag def viewm_menu_simple(user, mail_id, rcpt, secret_id=""): + release_url = "{0}?rcpt={1}".format( + reverse("amavis:mail_release", args=[mail_id]), rcpt) + delete_url = "{0}?rcpt={1}".format( + reverse("amavis:mail_delete", args=[mail_id]), rcpt) + if secret_id: + release_url += "&secret_id={0}".format(secret_id) + delete_url += "&secret_id={0}".format(secret_id) entries = [ {"name": "release", "img": "fa fa-check", "class": "btn-success", - "url": reverse('amavis:mail_release', args=[mail_id]) \ - + ("?rcpt=%s" % rcpt \ - + (("&secret_id=%s" % secret_id) if secret_id != "" else "")), + "url": release_url, "label": _("Release")}, {"name": "delete", "img": "fa fa-trash", "class": "btn-danger", - "url": reverse('amavis:mail_delete', args=[mail_id]) \ - + "?rcpt=%s" % rcpt \ - + ("&secret_id=%s" % secret_id if secret_id != "" else ""), + "url": delete_url, "label": _("Delete")}, ] From 7bca3a9ecb8ea3c086f3a8cc0e0636222eb2e92a Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Wed, 14 Jan 2015 15:27:35 +0100 Subject: [PATCH 13/24] PEP8 fixes --- modoboa/extensions/amavis/sql_connector.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modoboa/extensions/amavis/sql_connector.py b/modoboa/extensions/amavis/sql_connector.py index 050928788..daa6ed411 100644 --- a/modoboa/extensions/amavis/sql_connector.py +++ b/modoboa/extensions/amavis/sql_connector.py @@ -65,7 +65,7 @@ class SQLconnector(object): rcpts = [self.user.email] if self.user.mailbox_set.count(): rcpts += self.user.mailbox_set.all()[0].alias_addresses - return flt & Q(rid__email__in=rcpts) + return flt & Q(rid__email__in=rcpts) elif not self.user.is_superuser: doms = Domain.objects.get_for_admin(self.user) regexp = "(%s)" % '|'.join([dom.name for dom in doms]) @@ -238,7 +238,7 @@ class PgSQLconnector(SQLconnector): if self.user.mailbox_set.count(): rcpts += self.user.mailbox_set.all()[0].alias_addresses self._where.append( - "convert_from(maddr.email, 'UTF8') IN (%s)" \ + "convert_from(maddr.email, 'UTF8') IN (%s)" % (','.join(["'%s'" % rcpt for rcpt in rcpts]))) elif not self.user.is_superuser: doms = Domain.objects.get_for_admin(self.user) From 6b4edcc7c3f533718b9a4fda50ea0d957a9393be Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 15 Jan 2015 10:47:40 +0100 Subject: [PATCH 14/24] PEP8 fixes --- modoboa/extensions/amavis/forms.py | 2 +- modoboa/extensions/amavis/models.py | 77 ++++++++++++++++++++++------- modoboa/extensions/amavis/views.py | 2 +- 3 files changed, 62 insertions(+), 19 deletions(-) diff --git a/modoboa/extensions/amavis/forms.py b/modoboa/extensions/amavis/forms.py index cdf4489df..7af8c2b52 100644 --- a/modoboa/extensions/amavis/forms.py +++ b/modoboa/extensions/amavis/forms.py @@ -48,7 +48,7 @@ class DomainPolicyForm(forms.ModelForm): def save(self, user, commit=True): policy = super(DomainPolicyForm, self).save(commit=False) for field in ['bypass_spam_checks', 'bypass_virus_checks', - 'bypass_banned_checks']: + 'bypass_banned_checks']: if getattr(policy, field) == '': setattr(policy, field, None) diff --git a/modoboa/extensions/amavis/models.py b/modoboa/extensions/amavis/models.py index 7a711fdd8..b2df0cbb1 100644 --- a/modoboa/extensions/amavis/models.py +++ b/modoboa/extensions/amavis/models.py @@ -2,10 +2,11 @@ # You'll have to do the following manually to clean this up: # * Rearrange models' order # * Make sure each model has one field with primary_key=True -# Feel free to rename the models, but don't rename db_table values or field names. +# Feel free to rename the models, but don't rename db_table values +# or field names. # -# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]' -# into your database. +# Also note: You'll have to insert the output of +# 'django-admin.py sqlcustom [appname]'into your database. # # Original Amavis version : 2.6.2 @@ -95,42 +96,81 @@ class Policy(models.Model): ('Y', ugettext_lazy('no')), ('', ugettext_lazy('default'))), max_length=3, - help_text=ugettext_lazy("Bypass virus checks or not. Choose 'default' to use global settings.") + help_text=ugettext_lazy( + "Bypass virus checks or not. Choose 'default' to use global " + "settings." ) + ) bypass_spam_checks = models.CharField( ugettext_lazy("Spam filter"), default='', null=True, choices=(('N', ugettext_lazy('yes')), ('Y', ugettext_lazy('no')), ('', ugettext_lazy('default'))), max_length=3, - help_text=ugettext_lazy("Bypass spam checks or not. Choose 'default' to use global settings.") + help_text=ugettext_lazy( + "Bypass spam checks or not. Choose 'default' to use global " + "settings." ) + ) bypass_banned_checks = models.CharField( ugettext_lazy("Banned filter"), default='', null=True, choices=(('N', ugettext_lazy('yes')), ('Y', ugettext_lazy('no')), ('', ugettext_lazy('default'))), max_length=3, - help_text=ugettext_lazy("Bypass banned checks or not. Choose 'default' to use global settings.") + help_text=ugettext_lazy( + "Bypass banned checks or not. Choose 'default' to use global " + "settings." ) + ) bypass_header_checks = models.CharField(max_length=3, blank=True, null=True) - virus_quarantine_to = models.CharField(max_length=192, blank=True, null=True) + virus_quarantine_to = models.CharField( + max_length=192, + blank=True, + null=True) spam_quarantine_to = models.CharField(max_length=192, blank=True, null=True) - banned_quarantine_to = models.CharField(max_length=192, blank=True, null=True) - unchecked_quarantine_to = models.CharField(max_length=192, blank=True, null=True) - bad_header_quarantine_to = models.CharField(max_length=192, blank=True, null=True) - clean_quarantine_to = models.CharField(max_length=192, blank=True, null=True) - archive_quarantine_to = models.CharField(max_length=192, blank=True, null=True) + banned_quarantine_to = models.CharField( + max_length=192, + blank=True, + null=True) + unchecked_quarantine_to = models.CharField( + max_length=192, + blank=True, + null=True) + bad_header_quarantine_to = models.CharField( + max_length=192, + blank=True, + null=True) + clean_quarantine_to = models.CharField( + max_length=192, + blank=True, + null=True) + archive_quarantine_to = models.CharField( + max_length=192, + blank=True, + null=True) spam_tag_level = models.FloatField(null=True, blank=True) spam_tag2_level = models.FloatField(null=True, blank=True) spam_tag3_level = models.FloatField(null=True, blank=True) spam_kill_level = models.FloatField(null=True, blank=True) spam_dsn_cutoff_level = models.FloatField(null=True, blank=True) spam_quarantine_cutoff_level = models.FloatField(null=True, blank=True) - addr_extension_virus = models.CharField(max_length=192, blank=True, null=True) - addr_extension_spam = models.CharField(max_length=192, blank=True, null=True) - addr_extension_banned = models.CharField(max_length=192, blank=True, null=True) - addr_extension_bad_header = models.CharField(max_length=192, blank=True, null=True) + addr_extension_virus = models.CharField( + max_length=192, + blank=True, + null=True) + addr_extension_spam = models.CharField( + max_length=192, + blank=True, + null=True) + addr_extension_banned = models.CharField( + max_length=192, + blank=True, + null=True) + addr_extension_bad_header = models.CharField( + max_length=192, + blank=True, + null=True) warnvirusrecip = models.CharField(max_length=3, blank=True, null=True) warnbannedrecip = models.CharField(max_length=3, blank=True, null=True) warnbadhrecip = models.CharField(max_length=3, blank=True, null=True) @@ -143,8 +183,11 @@ class Policy(models.Model): spam_subject_tag2 = models.CharField( ugettext_lazy("Spam marker"), default=None, max_length=192, blank=True, null=True, - help_text=ugettext_lazy("Modify spam subject using the specified text. Choose 'default' to use global settings.") + help_text=ugettext_lazy( + "Modify spam subject using the specified text. Choose 'default' to " + "use global settings." ) + ) spam_subject_tag3 = models.CharField(max_length=192, blank=True, null=True) message_size_limit = models.IntegerField(null=True, blank=True) banned_rulenames = models.CharField(max_length=192, blank=True, null=True) diff --git a/modoboa/extensions/amavis/views.py b/modoboa/extensions/amavis/views.py index 9e9aa6af2..4b75d11cd 100644 --- a/modoboa/extensions/amavis/views.py +++ b/modoboa/extensions/amavis/views.py @@ -179,7 +179,7 @@ def viewheaders(request, mail_id): content = "" for qm in get_connector().get_mail_content(mail_id): content += qm.mail_text - if type(content) is unicode: + if isinstance(content, unicode): content = content.encode("utf-8") msg = email.message_from_string(content) headers = [] From 934525f895bab9cf6f004bedbc7dac4200b43325 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 15 Jan 2015 10:52:05 +0100 Subject: [PATCH 15/24] PEP8 fixes --- modoboa/extensions/radicale/__init__.py | 10 +++++++--- modoboa/extensions/radicale/forms.py | 8 +++++--- .../extensions/radicale/templatetags/radicale_tags.py | 8 +++++--- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/modoboa/extensions/radicale/__init__.py b/modoboa/extensions/radicale/__init__.py index 5e28f04a5..d7d884cf3 100644 --- a/modoboa/extensions/radicale/__init__.py +++ b/modoboa/extensions/radicale/__init__.py @@ -3,9 +3,11 @@ Radicale management frontend. """ import sys + from django.contrib.auth.models import Permission, Group from django.contrib.contenttypes.models import ContentType from django.utils.translation import ugettext_lazy + from modoboa.lib import events, parameters from modoboa.lib.permissions import add_permissions_to_group from modoboa.core.extensions import ModoExtension, exts_pool @@ -28,14 +30,16 @@ def init_limits_dependant_features(): class Radicale(ModoExtension): - """ - """ + + """Radicale extension declaration.""" + name = "radicale" label = ugettext_lazy("Radicale management") version = "1.0" url = "calendars" description = ugettext_lazy( - "Management frontend for Radicale, a simple calendar and contact server." + "Management frontend for Radicale, a simple calendar and contact " + "server." ) def init(self): diff --git a/modoboa/extensions/radicale/forms.py b/modoboa/extensions/radicale/forms.py index 857cfbc2c..14472ded1 100644 --- a/modoboa/extensions/radicale/forms.py +++ b/modoboa/extensions/radicale/forms.py @@ -1,13 +1,15 @@ """ Radicale extension forms. """ + from django import forms from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _, ugettext_lazy -from modoboa.lib.web_utils import render_to_json_response -from modoboa.lib.form_utils import WizardForm, TabForms, DynamicForm + from modoboa.extensions.admin.models import Domain, Mailbox from modoboa.extensions.radicale.models import UserCalendar, SharedCalendar +from modoboa.lib.form_utils import WizardForm, TabForms, DynamicForm +from modoboa.lib.web_utils import render_to_json_response class UserCalendarForm(forms.ModelForm): @@ -122,7 +124,7 @@ class RightsForm(forms.Form, DynamicForm): pos = int(res.group(1)) if res else None usernames[value] = pos for rule in self.calendar.rules.select_related().all(): - if not rule.mailbox.full_address in usernames: + if rule.mailbox.full_address not in usernames: rule.delete() for username, pos in usernames.iteritems(): local_part, domname = split_mailbox(username) diff --git a/modoboa/extensions/radicale/templatetags/radicale_tags.py b/modoboa/extensions/radicale/templatetags/radicale_tags.py index ab28d44fd..83bc07994 100644 --- a/modoboa/extensions/radicale/templatetags/radicale_tags.py +++ b/modoboa/extensions/radicale/templatetags/radicale_tags.py @@ -2,15 +2,17 @@ Custom template tags. """ from django import template -from django.template.loader import render_to_string from django.core.urlresolvers import reverse +from django.template.loader import render_to_string from django.utils.translation import ugettext as _ -from modoboa.lib.web_utils import render_actions + from modoboa.lib.templatetags.lib_tags import render_link +from modoboa.lib.web_utils import render_actions register = template.Library() + @register.simple_tag def radicale_left_menu(user): """Menu located inside the left column. @@ -96,7 +98,7 @@ def render_rule_fields(form): result = "" while True: fname = "username_%d" % cpt - if not fname in form.fields: + if fname not in form.fields: break rfieldname = "read_access_%d" % cpt wfieldname = "write_access_%d" % cpt From 5e71ed1917b1b1ffe58f1a00c0d022bed02a703c Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 15 Jan 2015 11:07:56 +0100 Subject: [PATCH 16/24] PEP8 fixes --- .../extensions/postfix_autoreply/__init__.py | 20 +- .../postfix_autoreply/app_settings.py | 15 +- modoboa/extensions/postfix_autoreply/forms.py | 30 +- .../postfix_autoreply/general_callbacks.py | 14 +- .../management/commands/autoreply.py | 5 +- modoboa/extensions/postfix_autoreply/tests.py | 1 - pylintrc | 329 ++++++++++++++++++ 7 files changed, 385 insertions(+), 29 deletions(-) create mode 100644 pylintrc diff --git a/modoboa/extensions/postfix_autoreply/__init__.py b/modoboa/extensions/postfix_autoreply/__init__.py index 2dee81f87..10578ca40 100644 --- a/modoboa/extensions/postfix_autoreply/__init__.py +++ b/modoboa/extensions/postfix_autoreply/__init__.py @@ -7,23 +7,27 @@ functionality into Postfix. """ import sys + from django.utils.translation import ugettext_lazy -from modoboa.lib import events, parameters + from modoboa.core.extensions import ModoExtension, exts_pool from modoboa.extensions.postfix_autoreply.models import ( Transport, Alias ) +from modoboa.lib import events, parameters class PostfixAutoreply(ModoExtension): + """ Auto-reply (vacation) functionality using Postfix. - + """ name = "postfix_autoreply" label = "Postfix autoreply" version = "1.0" - description = ugettext_lazy("Auto-reply (vacation) functionality using Postfix") + description = ugettext_lazy( + "Auto-reply (vacation) functionality using Postfix") def init(self): from modoboa.extensions.admin.models import Domain @@ -45,10 +49,14 @@ class PostfixAutoreply(ModoExtension): onMailboxCreated(None, mb) def load(self): - from modoboa.extensions.postfix_autoreply.app_settings import ParametersForm - parameters.register(ParametersForm, ugettext_lazy("Automatic replies")) + from modoboa.extensions.postfix_autoreply.app_settings import ( + ParametersForm + ) + parameters.register( + ParametersForm, ugettext_lazy("Automatic replies")) from modoboa.extensions.postfix_autoreply import general_callbacks - if 'modoboa.extensions.postfix_autoreply.general_callbacks' in sys.modules: + modname = "modoboa.extensions.postfix_autoreply.general_callbacks" + if modname in sys.modules: reload(general_callbacks) def destroy(self): diff --git a/modoboa/extensions/postfix_autoreply/app_settings.py b/modoboa/extensions/postfix_autoreply/app_settings.py index c19933cee..005f29029 100644 --- a/modoboa/extensions/postfix_autoreply/app_settings.py +++ b/modoboa/extensions/postfix_autoreply/app_settings.py @@ -1,8 +1,12 @@ # coding: utf-8 -from django.utils.translation import ugettext_lazy + +"""Custom settings.""" + from django import forms -from modoboa.lib.parameters import AdminParametersForm +from django.utils.translation import ugettext_lazy + from modoboa.lib.form_utils import SeparatorField +from modoboa.lib.parameters import AdminParametersForm class ParametersForm(AdminParametersForm): @@ -13,7 +17,9 @@ class ParametersForm(AdminParametersForm): autoreplies_timeout = forms.IntegerField( label=ugettext_lazy("Automatic reply timeout"), initial=86400, - help_text=ugettext_lazy("Timeout in seconds between two auto-replies to the same recipient"), + help_text=ugettext_lazy( + "Timeout in seconds between two auto-replies to the same recipient" + ), widget=forms.TextInput(attrs={"class": "form-control"}) ) @@ -21,7 +27,8 @@ class ParametersForm(AdminParametersForm): label=ugettext_lazy("Default subject"), initial=ugettext_lazy("I'm off"), help_text=ugettext_lazy( - "Default subject used when an auto-reply message is created automatically" + "Default subject used when an auto-reply message is created " + "automatically" ), widget=forms.TextInput(attrs={"class": "form-control"}) ) diff --git a/modoboa/extensions/postfix_autoreply/forms.py b/modoboa/extensions/postfix_autoreply/forms.py index 0344a8069..9e159343e 100644 --- a/modoboa/extensions/postfix_autoreply/forms.py +++ b/modoboa/extensions/postfix_autoreply/forms.py @@ -1,11 +1,16 @@ # coding: utf-8 + +"""Custom forms.""" + from django import forms -from django.utils.translation import ugettext as _, ugettext_lazy from django.utils import timezone +from django.utils.translation import ugettext as _, ugettext_lazy + from .models import ARmessage class ARmessageForm(forms.ModelForm): + fromdate = forms.DateTimeField( label=ugettext_lazy('From'), required=False, @@ -23,15 +28,15 @@ class ARmessageForm(forms.ModelForm): ) ) subject = forms.CharField( - widget=forms.TextInput( - attrs={'class': 'form-control'} - ) + widget=forms.TextInput( + attrs={'class': 'form-control'} + ) ) content = forms.CharField( - widget=forms.Textarea( - attrs={'class': 'form-control'} - ) + widget=forms.Textarea( + attrs={'class': 'form-control'} ) + ) class Meta: model = ARmessage @@ -67,13 +72,14 @@ class ARmessageForm(forms.ModelForm): else: self.cleaned_data['fromdate'] = timezone.now() if self.cleaned_data["untildate"] is not None: - if self.cleaned_data["untildate"] < timezone.now(): + untildate = self.cleaned_data["untildate"] + if untildate < timezone.now(): self._errors["untildate"] = self.error_class( [_("This date is over")]) - del self.cleaned_data['untildate'] - elif 'fromdate' in self.cleaned_data and \ - self.cleaned_data['untildate'] < self.cleaned_data['fromdate']: + del self.cleaned_data["untildate"] + elif "fromdate" in self.cleaned_data and \ + untildate < self.cleaned_data["fromdate"]: self._errors["untildate"] = \ self.error_class([_("Must be greater than start date")]) - del self.cleaned_data['untildate'] + del self.cleaned_data["untildate"] return self.cleaned_data diff --git a/modoboa/extensions/postfix_autoreply/general_callbacks.py b/modoboa/extensions/postfix_autoreply/general_callbacks.py index 3b1555c70..caff6b845 100644 --- a/modoboa/extensions/postfix_autoreply/general_callbacks.py +++ b/modoboa/extensions/postfix_autoreply/general_callbacks.py @@ -1,8 +1,11 @@ +"""Event callbacks.""" + from django.utils import timezone from django.utils.translation import ugettext_lazy -from modoboa.lib import events, parameters -from modoboa.extensions.postfix_autoreply.models import Transport, Alias + from .models import ARmessage +from modoboa.extensions.postfix_autoreply.models import Transport, Alias +from modoboa.lib import events, parameters @events.observe("ExtraUprefsJS") @@ -45,8 +48,11 @@ def onDomainModified(domain): return Transport.objects.filter(domain="autoreply.%s" % domain.oldname) \ .update(domain="autoreply.%s" % domain.name) - for al in Alias.objects.filter(full_address__contains="@%s" % domain.oldname): - new_address = al.full_address.replace("@%s" % domain.oldname, "@%s" % domain.name) + for al in Alias.objects.filter( + full_address__contains="@%s" % domain.oldname): + new_address = al.full_address.replace( + "@%s" % domain.oldname, + "@%s" % domain.name) al.full_address = new_address al.autoreply_address = "%s@autoreply.%s" % (new_address, domain.name) al.save() diff --git a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py index cde210c63..82f0c3064 100644 --- a/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py +++ b/modoboa/extensions/postfix_autoreply/management/commands/autoreply.py @@ -18,7 +18,7 @@ def send_autoreply(sender, mailbox, armessage): if armessage.fromdate > timezone.now(): return if armessage.untildate is not None \ - and armessage.untildate < timezone.now(): + and armessage.untildate < timezone.now(): armessage.enabled = False armessage.save() return @@ -51,7 +51,8 @@ class Command(BaseCommand, CloseConnectionMixin): def handle(self, *args, **options): if len(args) < 2: - raise CommandError("usage: ./manage.py autoreply ") + raise CommandError( + "usage: ./manage.py autoreply ") sender = args[0] for fulladdress in args[1:]: diff --git a/modoboa/extensions/postfix_autoreply/tests.py b/modoboa/extensions/postfix_autoreply/tests.py index 4c65b4032..e021e2929 100644 --- a/modoboa/extensions/postfix_autoreply/tests.py +++ b/modoboa/extensions/postfix_autoreply/tests.py @@ -82,7 +82,6 @@ class EventsTestCase(ExtTestCase): ARmessage.objects.get( mbox__address='user', mbox__domain__name='test.com') - def test_modify_mailbox_event(self): values = { 'username': "leon@test.com", diff --git a/pylintrc b/pylintrc new file mode 100644 index 000000000..7191ca562 --- /dev/null +++ b/pylintrc @@ -0,0 +1,329 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Profiled execution. +profile=no + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS,migrations + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +[MESSAGES CONTROL] + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=no-init,no-member,locally-disabled,too-few-public-methods,too-many-public-methods,too-many-ancestors + + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=yes + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Add a comment according to your evaluation note. This is used by the global +# evaluation report (RP0004). +comment=no + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[BASIC] + +# Required attributes for module, separated by a comma +required-attributes= + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,apply,input,file + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_,tz,logger,pk,qs + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=__.*__ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis +ignored-modules= + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject + +# When zope mode is activated, add a predefined set of Zope acquired attributes +# to generated-members. +zope=no + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST,acl_users,aq_parent + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + +[CLASSES] + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception From d47749400bf26e845a9ac58289e142c5d3f34f3f Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 15 Jan 2015 11:12:12 +0100 Subject: [PATCH 17/24] PEP8 fixes --- modoboa/extensions/stats/graphics.py | 8 +++++- modoboa/extensions/stats/lib.py | 2 +- .../stats/management/commands/logparser.py | 25 +++++++++++-------- modoboa/extensions/stats/views.py | 7 ++++-- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/modoboa/extensions/stats/graphics.py b/modoboa/extensions/stats/graphics.py index d7f657ba9..80ca0af88 100644 --- a/modoboa/extensions/stats/graphics.py +++ b/modoboa/extensions/stats/graphics.py @@ -7,10 +7,12 @@ from modoboa.lib.sysutils import exec_cmd class Curve(object): + """Graphic curve. Simple way to represent a graphic curve. """ + def __init__(self, dsname, color, legend, cfunc="AVERAGE"): """Constructor. """ @@ -37,9 +39,11 @@ class Curve(object): class Graphic(object): + """Graphic. """ + def __init__(self): """Constructor. """ @@ -76,7 +80,7 @@ class Graphic(object): cmdargs += curve.to_rrd_command_args(rrdfile) cmd = "rrdtool xport --start %s --end %s " % (str(start), str(end)) cmd += " ".join(cmdargs) - if type(cmd) is unicode: + if isinstance(cmd, unicode): cmd = cmd.encode("utf-8") code, output = exec_cmd(cmd) if code: @@ -95,6 +99,7 @@ class Graphic(object): class AverageTraffic(Graphic): + """Average traffic. """ title = ugettext_lazy('Average traffic (msgs/min)') @@ -109,6 +114,7 @@ class AverageTraffic(Graphic): class AverageTrafficSize(Graphic): + """Average traffic size. """ title = ugettext_lazy('Average normal traffic size (bytes/min)') diff --git a/modoboa/extensions/stats/lib.py b/modoboa/extensions/stats/lib.py index c71e5b59d..9d78c039f 100644 --- a/modoboa/extensions/stats/lib.py +++ b/modoboa/extensions/stats/lib.py @@ -12,7 +12,7 @@ def date_to_timestamp(timetuple): :return: an integer """ date = " ".join( - [("%d" % elem) if type(elem) is int else elem for elem in timetuple] + [("%d" % 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" diff --git a/modoboa/extensions/stats/management/commands/logparser.py b/modoboa/extensions/stats/management/commands/logparser.py index c622c5e05..3613f056b 100644 --- a/modoboa/extensions/stats/management/commands/logparser.py +++ b/modoboa/extensions/stats/management/commands/logparser.py @@ -21,10 +21,11 @@ import time import sys import os import re -import rrdtool import string from optparse import make_option +import rrdtool + from django.core.management.base import BaseCommand from modoboa.core.extensions import exts_pool @@ -71,9 +72,11 @@ class LogParser(object): self.workdict = {} self.lupdates = {} self._s_date_expr = \ - re.compile(r"(?P\w+)\s+(?P\d+)\s+(?P\d+):(?P\d+):(?P\d+)(?P.*)") + re.compile( + r"(?P\w+)\s+(?P\d+)\s+(?P\d+):(?P\d+):(?P\d+)(?P.*)") self._hp_date_expr = \ - re.compile(r"(?P\d+)-(?P\d+)-(?P\d+)T(?P\d+):(?P\d+):(?P\d+)\.\d+\+\d+:\d+(?P.*)") + re.compile( + r"(?P\d+)-(?P\d+)-(?P\d+)T(?P\d+):(?P\d+):(?P\d+)\.\d+\+\d+:\d+(?P.*)") self.date_expr = None self.line_expr = \ re.compile(r"\s+([-\w]+)\s+(\w+)/?\w*[[](\d+)[]]:\s+(.*)") @@ -200,7 +203,7 @@ class LogParser(object): self.lupdates[fname] = self.init_rrd(fname, m) self._dprint("[rrd] create new RRD file %s" % fname) else: - if not fname in self.lupdates: + if fname not in self.lupdates: self.lupdates[fname] = rrdtool.last(str(fname)) if m <= self.lupdates[fname]: @@ -250,11 +253,11 @@ class LogParser(object): def inc_counter(self, dom, counter, val=1): if dom is not None and dom in self.domains: - if not self.cur_t in self.data[dom]: + if self.cur_t not in self.data[dom]: self.initcounters(dom) self.data[dom][self.cur_t][counter] += val - if not self.cur_t in self.data["global"]: + if self.cur_t not in self.data["global"]: self.initcounters("global") self.data["global"][self.cur_t][counter] += val @@ -299,7 +302,9 @@ class LogParser(object): return (line_id, line_log) = m.groups() if line_id == "NOQUEUE": - addrto = re.match("reject: .*from=<.*> to=<[^@]+@([^>]+)>", line_log) + addrto = re.match( + "reject: .*from=<.*> to=<[^@]+@([^>]+)>", + line_log) if addrto and addrto.group(1) in self.domains: self.inc_counter(addrto.group(1), 'reject') return @@ -316,9 +321,9 @@ class LogParser(object): m = re.search("to=<([^>]*)>.*status=(\S+)", line_log) if m is not None: - if not line_id in self.workdict: - self._dprint("Inconsistent mail (%s: %s), skipping" \ - % (line_id, m.group(1))) + if line_id not in self.workdict: + self._dprint("Inconsistent mail (%s: %s), skipping" + % (line_id, m.group(1))) return if not m.group(2) in variables: self._dprint("Unsupported status %s, skipping" % m.group(2)) diff --git a/modoboa/extensions/stats/views.py b/modoboa/extensions/stats/views.py index 49e1570d9..b16756408 100644 --- a/modoboa/extensions/stats/views.py +++ b/modoboa/extensions/stats/views.py @@ -1,4 +1,7 @@ # coding: utf-8 + +"""Custom views.""" + import re import time from django.shortcuts import render @@ -83,7 +86,7 @@ def check_domain_access(user, pattern): def graphs(request): gset = request.GET.get("gset", None) gsets = events.raiseDictEvent("GetGraphSets") - if not gset in gsets: + if gset not in gsets: raise NotFound(_("Unknown graphic set")) searchq = request.GET.get("searchquery", None) period = request.GET.get("period", "day") @@ -94,7 +97,7 @@ def graphs(request): tplvars["domain"] = domain if period == "custom": - if not "start" in request.GET or not "end" in request.GET: + if "start" not in request.GET or "end" not in request.GET: raise BadRequest(_("Bad custom period")) start = request.GET["start"] end = request.GET["end"] From 5f3979acff4577ea6c25bb31e71786bd43e2185a Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 15 Jan 2015 11:23:22 +0100 Subject: [PATCH 18/24] PEP8 fixes --- modoboa/extensions/sievefilters/forms.py | 62 ++++++++++++++----- modoboa/extensions/sievefilters/lib.py | 26 +++++--- .../templatetags/sfilters_tags.py | 6 +- modoboa/extensions/sievefilters/test.py | 3 +- modoboa/extensions/sievefilters/views.py | 59 ++++++++++-------- 5 files changed, 101 insertions(+), 55 deletions(-) diff --git a/modoboa/extensions/sievefilters/forms.py b/modoboa/extensions/sievefilters/forms.py index 3db5cf368..01e91e98c 100644 --- a/modoboa/extensions/sievefilters/forms.py +++ b/modoboa/extensions/sievefilters/forms.py @@ -1,10 +1,13 @@ +"""Custom forms.""" + from django import forms -from django.http import QueryDict -from django.utils.translation import ugettext as _, ugettext_lazy from django.forms.widgets import RadioFieldRenderer, RadioSelect, RadioInput -from django.utils.safestring import mark_safe -from django.utils.html import conditional_escape +from django.http import QueryDict from django.utils.encoding import force_unicode +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext as _, ugettext_lazy + from modoboa.extensions.admin.templatetags.admin_tags import gender @@ -20,6 +23,7 @@ class FiltersSetForm(forms.Form): class CustomRadioInput(RadioInput): + def __unicode__(self): return self.render() @@ -39,13 +43,16 @@ class CustomRadioInput(RadioInput): class CustomRadioFieldRenderer(RadioFieldRenderer): + def __iter__(self): for i, choice in enumerate(self.choices): - yield CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, i) + yield CustomRadioInput( + self.name, self.value, self.attrs.copy(), choice, i) def __getitem__(self, idx): choice = self.choices[idx] - return CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, idx) + return CustomRadioInput( + self.name, self.value, self.attrs.copy(), choice, idx) def render(self): return mark_safe(u'\n'.join([force_unicode(w) for w in self])) @@ -56,6 +63,7 @@ class CustomRadioSelect(RadioSelect): class FilterForm(forms.Form): + def __init__(self, conditions, actions, request, *args, **kwargs): super(FilterForm, self).__init__(*args, **kwargs) @@ -80,10 +88,18 @@ class FilterForm(forms.Form): ] self.cond_templates = [ - {"name": "Subject", "label": _("Subject"), "operators": self.header_operators}, - {"name": "From", "label": _("Sender"), "operators": self.header_operators}, - {"name": "To", "label": _("Recipient"), "operators": self.header_operators}, - {"name": "Cc", "label": _("Cc"), "operators": self.header_operators}, + {"name": "Subject", + "label": _("Subject"), + "operators": self.header_operators}, + {"name": "From", + "label": _("Sender"), + "operators": self.header_operators}, + {"name": "To", + "label": _("Recipient"), + "operators": self.header_operators}, + {"name": "Cc", + "label": _("Cc"), + "operators": self.header_operators}, {"name": "size", "label": _("Size"), "operators": [("over", _("is greater than"), "number"), ("under", _("is less than"), "number")]}, @@ -160,10 +176,14 @@ class FilterForm(forms.Form): arg = args[cnt] aname = "action_arg_%d_%d" % (self.actions_cnt, cnt) if arg["type"] == "string": - self.fields[aname] = forms.CharField(max_length=255, initial=value) + self.fields[aname] = forms.CharField( + max_length=255, + initial=value) elif arg["type"] == "list": choices = getattr(self, arg["vloader"])(request) - self.fields[aname] = forms.ChoiceField(initial=value, choices=choices) + self.fields[aname] = forms.ChoiceField( + initial=value, + choices=choices) self.actions_cnt += 1 def _build_redirect_field(self, request, value): @@ -177,7 +197,10 @@ class FilterForm(forms.Form): for fd in folders: value = fd["path"] if "path" in fd else fd["name"] if parentmb: - ret += [(value, fd["name"].replace("%s%s" % (parentmb, imapc.hdelimiter), ""))] + ret += [ + (value, fd["name"].replace( + "%s%s" % (parentmb, imapc.hdelimiter), "")) + ] else: ret += [(value, fd["name"])] if "sub" in fd: @@ -206,7 +229,10 @@ class FilterForm(forms.Form): argcpt = 0 while True: try: - naction += (self.cleaned_data["action_arg_%d_%d" % (cpt, argcpt)],) + naction += ( + self.cleaned_data[ + "action_arg_%d_%d" % + (cpt, argcpt)],) except KeyError: break argcpt += 1 @@ -228,8 +254,12 @@ def build_filter_form_from_qdict(request): if cpt == int(request.POST["conds"]): break if "cond_target_%d" % i in request.POST: - qdict["cond_target_%d" % cpt] = request.POST["cond_target_%d" % i] - qdict["cond_operator_%d" % cpt] = request.POST["cond_operator_%d" % i] + qdict["cond_target_%d" % cpt] = ( + request.POST["cond_target_%d" % i] + ) + qdict["cond_operator_%d" % cpt] = ( + request.POST["cond_operator_%d" % i] + ) qdict["cond_value_%d" % cpt] = request.POST["cond_value_%d" % i] condtarget = request.POST["cond_target_%d" % i] condop = request.POST["cond_operator_%d" % i] diff --git a/modoboa/extensions/sievefilters/lib.py b/modoboa/extensions/sievefilters/lib.py index b980bc1d4..26cf8a2d1 100644 --- a/modoboa/extensions/sievefilters/lib.py +++ b/modoboa/extensions/sievefilters/lib.py @@ -1,12 +1,16 @@ # coding: utf-8 -from django.utils.translation import ugettext as _ +"""Internal tools.""" + +from sievelib.factory import FiltersSet from sievelib.managesieve import Client, Error from sievelib.parser import Parser -from sievelib.factory import FiltersSet + +from django.utils.translation import ugettext as _ + from modoboa.lib import parameters -from modoboa.lib.exceptions import ModoboaException from modoboa.lib.connections import ConnectionsManager, ConnectionError +from modoboa.lib.exceptions import ModoboaException class SieveClientError(ModoboaException): @@ -19,7 +23,7 @@ class SieveClient(object): def __init__(self, user=None, password=None): try: ret, msg = self.login(user, password) - except Error, e: + except Error as e: raise ConnectionError(str(e)) if not ret: raise ConnectionError(msg) @@ -38,7 +42,10 @@ class SieveClient(object): except Error: ret = False if not ret: - return False, _("Connection to MANAGESIEVE server failed, check your configuration") + return False, _( + "Connection to MANAGESIEVE server failed, check your " + "configuration" + ) return True, None def logout(self): @@ -51,13 +58,13 @@ class SieveClient(object): if self.msc is not None: try: self.msc.capability() - except Error, e: + except Error as e: pass else: return try: ret, msg = self.login(user, password) - except (Error, ssl.SSLError), e: + except (Error, ssl.SSLError) as e: raise ConnectionError(e) if not ret: raise ConnectionError(msg) @@ -80,10 +87,11 @@ class SieveClient(object): return fs def pushscript(self, name, content, active=False): - if type(content) is unicode: + if isinstance(content, unicode): content = content.encode("utf-8") if not self.msc.havespace(name, len(content)): - error = "%s (%s)" % (_("Not enough space on server"), self.msc.errmsg) + error = "%s (%s)" % ( + _("Not enough space on server"), self.msc.errmsg) raise SieveClientError(error) if not self.msc.putscript(name, content): raise SieveClientError(self.msc.errmsg) diff --git a/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py b/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py index c1336a923..3bc0f937f 100644 --- a/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py +++ b/modoboa/extensions/sievefilters/templatetags/sfilters_tags.py @@ -34,7 +34,7 @@ def fset_menu(mode, setname): "img": "fa fa-plus", "label": _("New filter"), "url": reverse("sievefilters:filter_add", - args=[setname]), + args=[setname]), "modal": True, "autowidth": True, "modalcb": "filterform_cb"} @@ -45,7 +45,7 @@ def fset_menu(mode, setname): "img": "fa fa-download-alt", "label": _("Save filters set"), "url": reverse("sievefilters:fs_save", - args=[setname])}, + args=[setname])}, ] entries += [ @@ -53,7 +53,7 @@ def fset_menu(mode, setname): "img": "fa fa-check", "label": _("Activate filters set"), "url": reverse("sievefilters:fs_activate", - args=[setname])}, + args=[setname])}, {"name": "removefs", "img": "fa fa-trash", "label": _("Remove filters set"), diff --git a/modoboa/extensions/sievefilters/test.py b/modoboa/extensions/sievefilters/test.py index 2555f22bc..9d35832dc 100644 --- a/modoboa/extensions/sievefilters/test.py +++ b/modoboa/extensions/sievefilters/test.py @@ -2,7 +2,7 @@ if __name__ == "__main__": clt = ManageSieveClient("mail.koalabs.org", 2000) if clt.connect("tonio@ngyn.org", "aka/12;c", starttls=True): print clt.get_sasl_mechanisms() - print clt.get_sieve_capabilities() + print clt.get_sieve_capabilities() print clt.havespace("test", 45) if not clt.putscript("myscript", """require ["fileinto", "envelope"]; @@ -40,4 +40,3 @@ InvalidSieveCommand else: print clt.errmsg clt.logout() - diff --git a/modoboa/extensions/sievefilters/views.py b/modoboa/extensions/sievefilters/views.py index 2aef75859..2a97b479b 100644 --- a/modoboa/extensions/sievefilters/views.py +++ b/modoboa/extensions/sievefilters/views.py @@ -1,25 +1,31 @@ # coding: utf-8 -from sievelib.managesieve import Error -from sievelib.commands import BadArgument, BadValue + +"""Custom views.""" + from rfc6266 import build_header -from django.shortcuts import render -from django.http import HttpResponse -from django.template.loader import render_to_string +from sievelib.commands import BadArgument, BadValue +from sievelib.managesieve import Error + from django.contrib.auth.decorators import login_required -from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse -from modoboa.lib import parameters -from modoboa.lib.web_utils import _render_error, \ - ajax_response, render_to_json_response -from modoboa.lib.connections import ConnectionError -from modoboa.lib.exceptions import BadRequest -from modoboa.extensions.admin.lib import needs_mailbox -from .lib import SieveClient, SieveClientError +from django.http import HttpResponse +from django.shortcuts import render +from django.template.loader import render_to_string +from django.utils.translation import ugettext as _ + from .forms import ( FilterForm, build_filter_form_from_qdict, build_filter_form_from_filter, FiltersSetForm ) +from .lib import SieveClient, SieveClientError from .templatetags.sfilters_tags import fset_menu +from modoboa.extensions.admin.lib import needs_mailbox +from modoboa.lib import parameters +from modoboa.lib.connections import ConnectionError +from modoboa.lib.exceptions import BadRequest +from modoboa.lib.web_utils import ( + _render_error, ajax_response, render_to_json_response +) @login_required @@ -30,12 +36,12 @@ def index(request, tplname="sievefilters/index.html"): try: sc = SieveClient(user=request.user.username, password=request.session["password"]) - except ConnectionError, e: + except ConnectionError as e: return _render_error(request, user_context={"error": e}) try: active_script, scripts = sc.listscripts() - except Error, e: + except Error as e: return _render_error(request, user_context={"error": e}) if active_script is None: @@ -73,7 +79,7 @@ def getfs(request, name): error = None try: content = sc.getscript(name, format=editormode) - except SieveClientError, e: + except SieveClientError as e: error = str(e) else: if content is None: @@ -104,7 +110,8 @@ def build_filter_ctx(ctx, form): return ctx -def submitfilter(request, setname, okmsg, tplname, tplctx, update=False, sc=None): +def submitfilter( + request, setname, okmsg, tplname, tplctx, update=False, sc=None): form = build_filter_form_from_qdict(request) if form.is_valid(): if sc is None: @@ -169,11 +176,13 @@ def editfilter(request, setname, fname, tplname="sievefilters/filter.html"): sc = SieveClient(user=request.user.username, password=request.session["password"]) if request.method == "POST": - return submitfilter(request, setname, _("Filter modified"), tplname, ctx, - update=True, sc=sc) + return submitfilter( + request, setname, _("Filter modified"), tplname, ctx, + update=True, sc=sc + ) fset = sc.getscript(setname, format="fset") - if type(fname) is unicode: + if isinstance(fname, unicode): fname = fname.encode("utf-8") f = fset.getfilter(fname) form = build_filter_form_from_filter(request, fname, f) @@ -199,13 +208,13 @@ def removefilter(request, setname, fname): @login_required @needs_mailbox() def savefs(request, name): - if not "scriptcontent" in request.POST: + if "scriptcontent" not in request.POST: return sc = SieveClient(user=request.user.username, password=request.session["password"]) try: sc.pushscript(name, request.POST["scriptcontent"]) - except SieveClientError, e: + except SieveClientError as e: error = str(e) return ajax_response(request, "ko", respmsg=error) return ajax_response(request, respmsg=_("Filters set saved")) @@ -258,7 +267,7 @@ def activate_filters_set(request, name): password=request.session["password"]) try: sc.activatescript(name) - except SieveClientError, e: + except SieveClientError as e: return ajax_response(request, "ko", respmsg=str(e)) return ajax_response(request, respmsg=_("Filters set activated")) @@ -270,7 +279,7 @@ def download_filters_set(request, name): password=request.session["password"]) try: script = sc.getscript(name) - except SieveClientError, e: + except SieveClientError as e: return ajax_response(request, "ko", respmsg=str(e)) resp = HttpResponse(script) @@ -285,7 +294,7 @@ def download_filters_set(request, name): def toggle_filter_state(request, setname, fname): sc = SieveClient(user=request.user.username, password=request.session["password"]) - if type(fname) is unicode: + if isinstance(fname, unicode): fname = fname.encode("utf-8") fset = sc.getscript(setname, format="fset") if fset.is_filter_disabled(fname): From 6b57c0ad0246c8a19caac71b9a664d1786bdc419 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 15 Jan 2015 11:31:29 +0100 Subject: [PATCH 19/24] PEP8 fixes --- .../postfix_relay_domains/__init__.py | 23 ++++++++++++------- .../extensions/postfix_relay_domains/forms.py | 11 +++++---- .../general_callbacks.py | 14 +++++++---- .../postfix_relay_domains/limits_callbacks.py | 21 ++++++++++++----- .../postfix_relay_domains/models.py | 22 ++++++++++++------ 5 files changed, 61 insertions(+), 30 deletions(-) diff --git a/modoboa/extensions/postfix_relay_domains/__init__.py b/modoboa/extensions/postfix_relay_domains/__init__.py index d3451781e..4c4ceac6b 100644 --- a/modoboa/extensions/postfix_relay_domains/__init__.py +++ b/modoboa/extensions/postfix_relay_domains/__init__.py @@ -1,13 +1,16 @@ # coding: utf-8 import sys + from django.contrib.auth.models import Group, Permission from django.contrib.contenttypes.models import ContentType from django.utils.translation import ugettext_lazy -from modoboa.lib import events, parameters -from modoboa.core.extensions import ModoExtension, exts_pool -from .models import RelayDomain, RelayDomainAlias, Service -extension_events = [ +from .models import RelayDomain, RelayDomainAlias, Service +from modoboa.core.extensions import ModoExtension, exts_pool +from modoboa.lib import events, parameters + + +EXTENSION_EVENTS = [ "RelayDomainCreated", "RelayDomainDeleted", "RelayDomainModified", @@ -66,6 +69,9 @@ def init_amavis_dependant_features(): class PostfixRelayDomains(ModoExtension): + + """Extension declaration.""" + name = "postfix_relay_domains" label = "Postfix relay domains" version = "1.0" @@ -88,17 +94,18 @@ class PostfixRelayDomains(ModoExtension): parameters.register( AdminParametersForm, ugettext_lazy("Relay domains") ) - events.declare(extension_events) + events.declare(EXTENSION_EVENTS) from modoboa.extensions.postfix_relay_domains import general_callbacks - if 'modoboa.extensions.postfix_relay_domains.general_callbacks' in sys.modules: + prefix = "modoboa.extensions.postfix_relay_domains." + if prefix + "general_callbacks" in sys.modules: reload(general_callbacks) if exts_pool.is_extension_enabled('limits'): import limits_callbacks - if 'modoboa.extensions.postfix_relay_domains.limits_callbacks' in sys.modules: + if prefix + "limits_callbacks" in sys.modules: reload(limits_callbacks) if exts_pool.is_extension_enabled('amavis'): import amavis_callbacks - if 'modoboa.extensions.postfix_relay_domains.amavis_callbacks' in sys.modules: + if prefix + "amavis_callbacks" in sys.modules: reload(amavis_callbacks) def destroy(self): diff --git a/modoboa/extensions/postfix_relay_domains/forms.py b/modoboa/extensions/postfix_relay_domains/forms.py index 9d31e2ba0..0fcd2535f 100644 --- a/modoboa/extensions/postfix_relay_domains/forms.py +++ b/modoboa/extensions/postfix_relay_domains/forms.py @@ -2,14 +2,15 @@ Postfix relay domains extension forms. """ from django import forms +from django.core.urlresolvers import reverse from django.http import QueryDict from django.utils.translation import ugettext as _, ugettext_lazy -from django.core.urlresolvers import reverse + +from .models import RelayDomain, RelayDomainAlias +from modoboa.extensions.admin.models import Domain, DomainAlias from modoboa.lib import events from modoboa.lib.form_utils import DynamicForm, DomainNameField, TabForms from modoboa.lib.web_utils import render_to_json_response -from modoboa.extensions.admin.models import Domain, DomainAlias -from .models import RelayDomain, RelayDomainAlias class RelayDomainFormGeneral(forms.ModelForm, DynamicForm): @@ -113,7 +114,7 @@ class RelayDomainFormGeneral(forms.ModelForm, DynamicForm): continue aliases.append(v) for rdalias in rd.relaydomainalias_set.all(): - if not rdalias.name in aliases: + if rdalias.name not in aliases: rdalias.delete() else: aliases.remove(rdalias.name) @@ -137,11 +138,13 @@ class RelayDomainFormGeneral(forms.ModelForm, DynamicForm): class RelayDomainForm(TabForms): + """Specific edition form for relay domains. We use a *tabs* compatible form because extensions can add their own tab. (ex: amavis) """ + def __init__(self, request, *args, **kwargs): self.user = request.user self.forms = [] diff --git a/modoboa/extensions/postfix_relay_domains/general_callbacks.py b/modoboa/extensions/postfix_relay_domains/general_callbacks.py index 43b25312d..765b32fcf 100644 --- a/modoboa/extensions/postfix_relay_domains/general_callbacks.py +++ b/modoboa/extensions/postfix_relay_domains/general_callbacks.py @@ -1,10 +1,13 @@ -from django.core.urlresolvers import reverse -from django.template import Template, Context +"""General event callbacks.""" + from django.conf import settings -from django.utils.translation import ugettext_lazy +from django.core.urlresolvers import reverse from django.db.models import Q -from modoboa.lib import events +from django.template import Template, Context +from django.utils.translation import ugettext_lazy + from .models import RelayDomain, RelayDomainAlias +from modoboa.lib import events @events.observe('GetStaticContent') @@ -101,7 +104,8 @@ def extra_limit_templates(): ugettext_lazy('Maximum number of relay domains this user can create'), 'Resellers'), ("relay_domain_aliases_limit", ugettext_lazy("Relay domain aliases"), - ugettext_lazy('Maximum number of relay domain aliases this user can create'), + ugettext_lazy( + 'Maximum number of relay domain aliases this user can create'), 'Resellers'), ] diff --git a/modoboa/extensions/postfix_relay_domains/limits_callbacks.py b/modoboa/extensions/postfix_relay_domains/limits_callbacks.py index 18911e159..8b1ce5d81 100644 --- a/modoboa/extensions/postfix_relay_domains/limits_callbacks.py +++ b/modoboa/extensions/postfix_relay_domains/limits_callbacks.py @@ -1,8 +1,11 @@ +"""Callbacks related to limits extension.""" + from django.utils.translation import ugettext_lazy + +from .models import RelayDomainAlias +from modoboa.extensions.limits.lib import inc_limit_usage, dec_limit_usage from modoboa.lib import events from modoboa.lib.permissions import get_object_owner -from modoboa.extensions.limits.lib import inc_limit_usage, dec_limit_usage -from .models import RelayDomainAlias @events.observe('GetExtraParameters') @@ -16,17 +19,23 @@ def extra_parameters(app, level): label=ugettext_lazy("Relay domains"), initial=0, help_text=ugettext_lazy( - "Maximum number of allowed relay domains for a new administrator" + "Maximum number of allowed relay domains for a new " + "administrator" ), - widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"}) + widget=forms.widgets.TextInput( + attrs={ + "class": "col-md-1 form-control"}) ), 'deflt_relay_domain_aliases_limit': forms.IntegerField( label=ugettext_lazy("Relay domain aliases"), initial=0, help_text=ugettext_lazy( - "Maximum number of allowed relay domain aliases for a new administrator" + "Maximum number of allowed relay domain aliases for a new " + "administrator" ), - widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"}) + widget=forms.widgets.TextInput( + attrs={ + "class": "col-md-1 form-control"}) ) } diff --git a/modoboa/extensions/postfix_relay_domains/models.py b/modoboa/extensions/postfix_relay_domains/models.py index 088874c2e..5e96959ac 100644 --- a/modoboa/extensions/postfix_relay_domains/models.py +++ b/modoboa/extensions/postfix_relay_domains/models.py @@ -1,12 +1,16 @@ -import reversion +"""Relay domain related models.""" + +from django.contrib.contenttypes import generic from django.db import models from django.db.models.manager import Manager -from django.contrib.contenttypes import generic from django.utils.translation import ugettext as _, ugettext_lazy + +import reversion + from modoboa.core.models import ObjectAccess +from modoboa.extensions.admin.models import AdminObject from modoboa.lib import parameters from modoboa.lib.exceptions import BadRequest, NotFound -from modoboa.extensions.admin.models import AdminObject class RelayDomainManager(Manager): @@ -46,12 +50,13 @@ class ServiceManager(Manager): services.append(parts[0]) to_delete = [] for service in self.all(): - if not service.name in services: + if service.name not in services: to_delete.append(service.name) Service.objects.filter(name__in=to_delete).delete() class Service(models.Model): + """Postfix service. """ name = models.CharField( @@ -66,6 +71,7 @@ class Service(models.Model): class RelayDomain(AdminObject): + """Relay domain. A relay domain differs from a usual domaine because its final @@ -101,7 +107,7 @@ class RelayDomain(AdminObject): def tags(self): return [ {"name": "relaydomain", "label": _("Relay Domain"), "type": "dom"}, - {"name": self.service.name, "label": "%s:" % self.service.name, + {"name": self.service.name, "label": "%s:" % self.service.name, "type": "srv", "color": "info"} ] @@ -118,7 +124,7 @@ class RelayDomain(AdminObject): :param csvwriter: """ csvwriter.writerow( - ["relaydomain", self.name, self.target_host, + ["relaydomain", self.name, self.target_host, self.service.name, self.enabled, self.verify_recipients] ) for rdalias in self.relaydomainalias_set.all(): @@ -134,7 +140,8 @@ class RelayDomain(AdminObject): raise BadRequest(_("Invalid line")) self.name = row[1].strip() self.target_host = row[2].strip() - self.service, created = Service.objects.get_or_create(name=row[3].strip()) + self.service, created = Service.objects.get_or_create( + name=row[3].strip()) self.enabled = (row[4].strip() == 'True') self.verify_recipients = (row[5].strip() == 'True') self.save(creator=user) @@ -152,6 +159,7 @@ reversion.register(RelayDomain) class RelayDomainAlias(AdminObject): + """Relay domain alias. """ From d4317b270e662562d999d57e6910c1b836dae91c Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 15 Jan 2015 11:43:17 +0100 Subject: [PATCH 20/24] PEP8 fixes --- modoboa/extensions/limits/app_settings.py | 24 ++++++++++++----- modoboa/extensions/limits/controls.py | 10 +++---- modoboa/extensions/limits/forms.py | 22 ++++++++++----- .../extensions/limits/general_callbacks.py | 11 +++++--- modoboa/extensions/limits/models.py | 27 ++++++++++++------- modoboa/extensions/limits/tests.py | 24 +++++++++++------ modoboa/extensions/limits/urls.py | 2 +- 7 files changed, 79 insertions(+), 41 deletions(-) diff --git a/modoboa/extensions/limits/app_settings.py b/modoboa/extensions/limits/app_settings.py index 6f423507f..2d759a3cd 100644 --- a/modoboa/extensions/limits/app_settings.py +++ b/modoboa/extensions/limits/app_settings.py @@ -1,42 +1,52 @@ +"""Custom settings.""" + from django import forms from django.utils.translation import ugettext_lazy as _ -from modoboa.lib.parameters import AdminParametersForm + from modoboa.lib.form_utils import SeparatorField +from modoboa.lib.parameters import AdminParametersForm class ParametersForm(AdminParametersForm): app = "limits" defv_sep = SeparatorField(label=_("Default limits")) - + deflt_domain_admins_limit = forms.IntegerField( label=_("Domain admins"), initial=0, - help_text=_("Maximum number of allowed domain administrators for a new administrator"), + help_text=_( + "Maximum number of allowed domain administrators for a new " + "administrator" + ), widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"}) ) deflt_domains_limit = forms.IntegerField( label=_("Domains"), initial=0, - help_text=_("Maximum number of allowed domains for a new administrator"), + help_text=_( + "Maximum number of allowed domains for a new administrator"), widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"}) ) deflt_domain_aliases_limit = forms.IntegerField( label=_("Domain aliases"), initial=0, - help_text=_("Maximum number of allowed domain aliases for a new administrator"), + help_text=_( + "Maximum number of allowed domain aliases for a new administrator"), widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"}) ) deflt_mailboxes_limit = forms.IntegerField( label=_("Mailboxes"), initial=0, - help_text=_("Maximum number of allowed mailboxes for a new administrator"), + help_text=_( + "Maximum number of allowed mailboxes for a new administrator"), widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"}) ) deflt_mailbox_aliases_limit = forms.IntegerField( label=_("Mailbox aliases"), initial=0, - help_text=_("Maximum number of allowed aliases for a new administrator"), + help_text=_( + "Maximum number of allowed aliases for a new administrator"), widget=forms.widgets.TextInput(attrs={"class": "col-md-1 form-control"}) ) diff --git a/modoboa/extensions/limits/controls.py b/modoboa/extensions/limits/controls.py index 34ff09159..f5d00b4ac 100644 --- a/modoboa/extensions/limits/controls.py +++ b/modoboa/extensions/limits/controls.py @@ -4,10 +4,10 @@ ---------------------------------------------------------------------------- """ -from modoboa.lib import events -from modoboa.lib.permissions import get_object_owner from .lib import LimitReached, inc_limit_usage, dec_limit_usage from .models import LimitTemplates, LimitsPool +from modoboa.lib import events +from modoboa.lib.permissions import get_object_owner def check_limit(user, lname, count=1): @@ -124,7 +124,7 @@ def can_create_new_object(user, objtype, count=1): @events.observe("AccountCreated") def create_pool(user): owner = get_object_owner(user) - if not owner.group in ['SuperAdmins', 'Resellers']: + if owner.group not in ['SuperAdmins', 'Resellers']: return if user.group == 'DomainAdmins': @@ -177,7 +177,7 @@ def on_account_modified(old, new): p.save() p.create_limits(owner) - if not new.group in ["DomainAdmins", "Resellers"]: + if new.group not in ["DomainAdmins", "Resellers"]: move_pool_resource(owner, new) if old.oldgroup == "DomainAdmins": @@ -193,7 +193,7 @@ def on_account_modified(old, new): @events.observe("AccountDeleted") def on_account_deleted(account, byuser, **kwargs): owner = get_object_owner(account) - if not owner.group in ["SuperAdmins", "Resellers"]: + if owner.group not in ["SuperAdmins", "Resellers"]: return move_pool_resource(owner, account) diff --git a/modoboa/extensions/limits/forms.py b/modoboa/extensions/limits/forms.py index a763284e2..61f977dba 100644 --- a/modoboa/extensions/limits/forms.py +++ b/modoboa/extensions/limits/forms.py @@ -1,9 +1,13 @@ # coding: utf-8 + +"""Custom forms.""" + from django import forms -from django.utils.translation import ugettext as _, ugettext_lazy -from modoboa.lib import parameters -from .models import LimitTemplates +from django.utils.translation import ugettext as _ + from .lib import BadLimitValue, UnsufficientResource +from .models import LimitTemplates +from modoboa.lib import parameters class ResourcePoolForm(forms.Form): @@ -15,7 +19,9 @@ class ResourcePoolForm(forms.Form): del kwargs["instance"] super(ResourcePoolForm, self).__init__(*args, **kwargs) for tpl in LimitTemplates().templates: - if len(tpl) > 3 and self.account is not None and self.account.group != tpl[3]: + if len(tpl) <= 3: + continue + if self.account is not None and self.account.group != tpl[3]: continue self.fields[tpl[0]] = forms.IntegerField( label=tpl[1], help_text=tpl[2] @@ -31,7 +37,7 @@ class ResourcePoolForm(forms.Form): def clean(self): cleaned_data = super(ResourcePoolForm, self).clean() for lname in self.fields.keys(): - if not lname in self._errors and cleaned_data[lname] < -1: + if lname not in self._errors and cleaned_data[lname] < -1: self._errors[lname] = self.error_class([_('Invalid limit')]) del cleaned_data[lname] return cleaned_data @@ -42,7 +48,9 @@ class ResourcePoolForm(forms.Form): # The following lines will become useless in a near # future. if self.fields[lname].initial == -2: - self.fields[lname].initial = parameters.get_admin("DEFLT_%s" % lname.upper()) + self.fields[lname].initial = parameters.get_admin( + "DEFLT_%s" % + lname.upper()) def allocate_from_pool(self, limit, pool): """Allocate resource using an existing pool. @@ -76,7 +84,7 @@ class ResourcePoolForm(forms.Form): owner = get_object_owner(self.account) for ltpl in LimitTemplates().templates: - if not ltpl[0] in self.cleaned_data: + if ltpl[0] not in self.cleaned_data: continue l = self.account.limitspool.limit_set.get(name=ltpl[0]) if not owner.is_superuser: diff --git a/modoboa/extensions/limits/general_callbacks.py b/modoboa/extensions/limits/general_callbacks.py index d06fea86b..66561368d 100644 --- a/modoboa/extensions/limits/general_callbacks.py +++ b/modoboa/extensions/limits/general_callbacks.py @@ -1,7 +1,10 @@ +"""General event callbacks.""" + from django.utils.translation import ugettext as _ -from modoboa.lib import events -from modoboa.extensions.limits.models import LimitTemplates + from modoboa.extensions.limits.forms import ResourcePoolForm +from modoboa.extensions.limits.models import LimitTemplates +from modoboa.lib import events @events.observe("GetExtraRoles") @@ -37,10 +40,10 @@ def display_pool_usage(user, target, currentpage): @events.observe("ExtraAccountForm") def extra_account_form(user, account=None): - if not user.group in ["SuperAdmins", "Resellers"]: + if user.group not in ["SuperAdmins", "Resellers"]: return [] if account is not None and \ - not account.group in ["Resellers", "DomainAdmins"]: + account.group not in ["Resellers", "DomainAdmins"]: return [] return [ diff --git a/modoboa/extensions/limits/models.py b/modoboa/extensions/limits/models.py index 21f4e7b32..60ced9325 100644 --- a/modoboa/extensions/limits/models.py +++ b/modoboa/extensions/limits/models.py @@ -1,10 +1,13 @@ # coding: utf-8 + +"""Models for the limits extensions.""" + +from django.conf import settings from django.db import models from django.utils.translation import ugettext as _, ugettext_lazy -from modoboa.lib import parameters + +from modoboa.lib import parameters, events from modoboa.lib.singleton import Singleton -from django.conf import settings -from modoboa.lib import events class LimitTemplates(Singleton): @@ -12,23 +15,27 @@ class LimitTemplates(Singleton): def __init__(self): self.__templates = [ ("domain_admins_limit", ugettext_lazy("Domain admins"), - ugettext_lazy("Maximum number of domain administrators this user can create"), + ugettext_lazy("Maximum number of domain administrators this user " + "can create"), 'Resellers'), ("domains_limit", ugettext_lazy("Domains"), ugettext_lazy("Maximum number of domains this user can create"), 'Resellers'), ("domain_aliases_limit", ugettext_lazy("Domain aliases"), - ugettext_lazy("Maximum number of domain aliases this user can create"), + ugettext_lazy( + "Maximum number of domain aliases this user can create"), 'Resellers'), ("mailboxes_limit", ugettext_lazy("Mailboxes"), ugettext_lazy("Maximum number of mailboxes this user can create")), ("mailbox_aliases_limit", ugettext_lazy("Mailbox aliases"), - ugettext_lazy("Maximum number of mailbox aliases this user can create")) + ugettext_lazy("Maximum number of mailbox aliases this user " + "can create")) ] - + @property def templates(self): - return self.__templates + events.raiseQueryEvent('GetExtraLimitTemplates') + return self.__templates + \ + events.raiseQueryEvent('GetExtraLimitTemplates') class LimitsPool(models.Model): @@ -47,8 +54,10 @@ class LimitsPool(models.Model): try: Limit.objects.get(name=ltpl[0], pool=self) except Limit.DoesNotExist: - maxvalue = int(parameters.get_admin("DEFLT_%s" % ltpl[0].upper())) \ + maxvalue = ( + int(parameters.get_admin("DEFLT_%s" % ltpl[0].upper())) if creator.is_superuser else 0 + ) Limit.objects.create( name=ltpl[0], pool=self, maxvalue=maxvalue ) diff --git a/modoboa/extensions/limits/tests.py b/modoboa/extensions/limits/tests.py index 4db5078df..893417ea0 100644 --- a/modoboa/extensions/limits/tests.py +++ b/modoboa/extensions/limits/tests.py @@ -1,13 +1,16 @@ +"""Test cases for the limits extension.""" + from django.core.urlresolvers import reverse -from modoboa.lib.tests import ExtTestCase -from modoboa.lib import parameters -from modoboa.core.models import User + from modoboa.core.factories import UserFactory +from modoboa.core.models import User from modoboa.extensions.admin.factories import ( populate_database ) from modoboa.extensions.admin.models import Alias, Domain from modoboa.extensions.limits.models import LimitTemplates +from modoboa.lib import parameters +from modoboa.lib.tests import ExtTestCase class PermissionsTestCase(ExtTestCase): @@ -142,8 +145,8 @@ class DomainAdminTestCase(ResourceTestCase): resp = self._create_alias('alias3@test.com', status=403) self._check_limit('mailbox_aliases', 2, 2) self.ajax_post( - reverse('admin:alias_delete') + '?selection=%d' \ - % Alias.objects.get(address='alias2', domain__name='test.com').id, + reverse('admin:alias_delete') + '?selection=%d' + % Alias.objects.get(address='alias2', domain__name='test.com').id, {} ) self._check_limit('mailbox_aliases', 1, 2) @@ -206,10 +209,14 @@ class ResellerTestCase(ResourceTestCase): self._check_limit('domain_admins', 1, 2) self._create_account('admin2@domain.tld', role='DomainAdmins') self._check_limit('domain_admins', 2, 2) - resp = self._create_account('admin3@domain.tld', role='DomainAdmins', status=400) + resp = self._create_account( + 'admin3@domain.tld', + role='DomainAdmins', + status=400) self.assertEqual( resp['form_errors']['role'][0], - 'Select a valid choice. DomainAdmins is not one of the available choices.' + 'Select a valid choice. DomainAdmins is not one of the available ' + 'choices.' ) self._check_limit('domain_admins', 2, 2) @@ -227,7 +234,8 @@ class ResellerTestCase(ResourceTestCase): ) self.assertEqual( resp['form_errors']['role'][0], - 'Select a valid choice. DomainAdmins is not one of the available choices.' + 'Select a valid choice. DomainAdmins is not one of the available ' + 'choices.' ) self._check_limit('domain_admins', 2, 2) diff --git a/modoboa/extensions/limits/urls.py b/modoboa/extensions/limits/urls.py index fa7b22416..9adc5e04a 100644 --- a/modoboa/extensions/limits/urls.py +++ b/modoboa/extensions/limits/urls.py @@ -3,4 +3,4 @@ from django.conf.urls import patterns urlpatterns = patterns( 'modoboa.extensions.limits.views', - ) +) From ff090820b1ea059171e4d9e6f1a2afce0c16ffd0 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 15 Jan 2015 14:44:19 +0100 Subject: [PATCH 21/24] Unit tests fixed. --- modoboa/extensions/limits/forms.py | 7 +++---- modoboa/extensions/limits/lib.py | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modoboa/extensions/limits/forms.py b/modoboa/extensions/limits/forms.py index 61f977dba..0f0b27f9a 100644 --- a/modoboa/extensions/limits/forms.py +++ b/modoboa/extensions/limits/forms.py @@ -19,10 +19,9 @@ class ResourcePoolForm(forms.Form): del kwargs["instance"] super(ResourcePoolForm, self).__init__(*args, **kwargs) for tpl in LimitTemplates().templates: - if len(tpl) <= 3: - continue - if self.account is not None and self.account.group != tpl[3]: - continue + if len(tpl) > 3: + if self.account is not None and self.account.group != tpl[3]: + continue self.fields[tpl[0]] = forms.IntegerField( label=tpl[1], help_text=tpl[2] ) diff --git a/modoboa/extensions/limits/lib.py b/modoboa/extensions/limits/lib.py index c190b26d7..c0135a234 100644 --- a/modoboa/extensions/limits/lib.py +++ b/modoboa/extensions/limits/lib.py @@ -5,8 +5,9 @@ """ from django.utils.translation import ugettext as _ -from modoboa.lib.exceptions import ModoboaException + from modoboa.extensions.limits.models import LimitsPool +from modoboa.lib.exceptions import ModoboaException class LimitReached(ModoboaException): From 46128fa61fc78f5011161cc5bff20cc8b0388fcc Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 15 Jan 2015 17:23:51 +0100 Subject: [PATCH 22/24] PEP8 fixes --- modoboa/extensions/admin/factories.py | 6 ++++-- modoboa/extensions/admin/forms/account.py | 2 ++ modoboa/extensions/admin/forms/domain.py | 2 ++ modoboa/extensions/admin/forms/export.py | 2 ++ modoboa/extensions/admin/models/alias.py | 1 + modoboa/extensions/admin/models/base.py | 2 ++ modoboa/extensions/admin/models/domain.py | 1 + modoboa/extensions/admin/views/import.py | 2 +- 8 files changed, 15 insertions(+), 3 deletions(-) diff --git a/modoboa/extensions/admin/factories.py b/modoboa/extensions/admin/factories.py index 9097f1b2c..b4399e0cd 100644 --- a/modoboa/extensions/admin/factories.py +++ b/modoboa/extensions/admin/factories.py @@ -37,7 +37,8 @@ def populate_database(): """ dom = DomainFactory.create(name="test.com") admin = UserFactory( - username="admin@test.com", groups=('DomainAdmins', ), password='{PLAIN}toto' + username="admin@test.com", groups=('DomainAdmins', ), + password='{PLAIN}toto' ) MailboxFactory(address='admin', domain=dom, user=admin) account = UserFactory.create( @@ -59,7 +60,8 @@ def populate_database(): dom2 = DomainFactory.create(name='test2.com', quota=0) admin = UserFactory.create( - username='admin@test2.com', groups=('DomainAdmins',), password='{PLAIN}toto' + username='admin@test2.com', groups=('DomainAdmins',), + password='{PLAIN}toto' ) MailboxFactory.create(address='admin', domain=dom2, user=admin) u = UserFactory.create( diff --git a/modoboa/extensions/admin/forms/account.py b/modoboa/extensions/admin/forms/account.py index a010ec0dc..dcda56951 100644 --- a/modoboa/extensions/admin/forms/account.py +++ b/modoboa/extensions/admin/forms/account.py @@ -447,8 +447,10 @@ class AccountForm(TabForms): class AccountWizard(WizardForm): + """Account creation wizard. """ + def __init__(self, request): super(AccountWizard, self).__init__(request) self.add_step( diff --git a/modoboa/extensions/admin/forms/domain.py b/modoboa/extensions/admin/forms/domain.py index 667ad6ef0..45bf1149e 100644 --- a/modoboa/extensions/admin/forms/domain.py +++ b/modoboa/extensions/admin/forms/domain.py @@ -328,8 +328,10 @@ class DomainForm(TabForms): class DomainWizard(WizardForm): + """Domain creation wizard. """ + def __init__(self, request): super(DomainWizard, self).__init__(request) self.add_step( diff --git a/modoboa/extensions/admin/forms/export.py b/modoboa/extensions/admin/forms/export.py index bee201157..f1f8a868b 100644 --- a/modoboa/extensions/admin/forms/export.py +++ b/modoboa/extensions/admin/forms/export.py @@ -32,12 +32,14 @@ class ExportDataForm(forms.Form): class ExportDomainsForm(ExportDataForm): + def __init__(self, *args, **kwargs): super(ExportDomainsForm, self).__init__(*args, **kwargs) self.fields["filename"].initial = "modoboa-domains.csv" class ExportIdentitiesForm(ExportDataForm): + def __init__(self, *args, **kwargs): super(ExportIdentitiesForm, self).__init__(*args, **kwargs) self.fields["filename"].initial = "modoboa-identities.csv" diff --git a/modoboa/extensions/admin/models/alias.py b/modoboa/extensions/admin/models/alias.py index a44ea9bf9..04c154603 100644 --- a/modoboa/extensions/admin/models/alias.py +++ b/modoboa/extensions/admin/models/alias.py @@ -15,6 +15,7 @@ from modoboa.lib.exceptions import ( class Alias(AdminObject): + """ Mailbox alias. """ diff --git a/modoboa/extensions/admin/models/base.py b/modoboa/extensions/admin/models/base.py index 5f3fd61a3..c576bdcad 100644 --- a/modoboa/extensions/admin/models/base.py +++ b/modoboa/extensions/admin/models/base.py @@ -6,6 +6,7 @@ from modoboa.lib.permissions import ( class ObjectDates(models.Model): + """Dates recording for admin objects This table keeps creation and last modification dates for Domains, @@ -32,6 +33,7 @@ class ObjectDates(models.Model): class AdminObject(models.Model): + """Abstract model to support dates Inherit from this model to automatically add the "dates" feature diff --git a/modoboa/extensions/admin/models/domain.py b/modoboa/extensions/admin/models/domain.py index e03a36d02..20b5d0c1e 100644 --- a/modoboa/extensions/admin/models/domain.py +++ b/modoboa/extensions/admin/models/domain.py @@ -27,6 +27,7 @@ class DomainManager(Manager): class Domain(AdminObject): + """Mail domain. """ name = models.CharField(ugettext_lazy('name'), max_length=100, unique=True, diff --git a/modoboa/extensions/admin/views/import.py b/modoboa/extensions/admin/views/import.py index a06a3a8cf..015db07d2 100644 --- a/modoboa/extensions/admin/views/import.py +++ b/modoboa/extensions/admin/views/import.py @@ -136,7 +136,7 @@ def importdata(request, formclass=ImportDataForm): return render(request, "admin/import_done.html", { "status": "ok", "msg": msg }) - except (ModoboaException), e: + except (ModoboaException) as e: error = str(e) return render(request, "admin/import_done.html", { From 38649a614f68a732b20925e8761ccf06a52af692 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 16 Jan 2015 10:24:15 +0100 Subject: [PATCH 23/24] PEP8 fixes --- modoboa/extensions/webmail/app_settings.py | 3 +- modoboa/extensions/webmail/exceptions.py | 2 + modoboa/extensions/webmail/forms.py | 7 +- modoboa/extensions/webmail/lib/attachments.py | 5 +- .../extensions/webmail/lib/fetch_parser.py | 24 +++-- modoboa/extensions/webmail/lib/imapemail.py | 4 +- modoboa/extensions/webmail/lib/imapheader.py | 3 +- modoboa/extensions/webmail/lib/imaputils.py | 94 ++++++++++++------- modoboa/extensions/webmail/lib/signature.py | 2 + modoboa/extensions/webmail/lib/utils.py | 2 + .../webmail/templatetags/webmail_tags.py | 9 +- modoboa/extensions/webmail/views.py | 14 +-- 12 files changed, 104 insertions(+), 65 deletions(-) diff --git a/modoboa/extensions/webmail/app_settings.py b/modoboa/extensions/webmail/app_settings.py index 1fee71d06..70e371332 100644 --- a/modoboa/extensions/webmail/app_settings.py +++ b/modoboa/extensions/webmail/app_settings.py @@ -13,7 +13,8 @@ class ParametersForm(AdminParametersForm): max_attachment_size = forms.CharField( label=_("Maximum attachment size"), initial="2048", - help_text=_("Maximum attachment size in bytes (or KB, MB, GB if specified)") + help_text=_( + "Maximum attachment size in bytes (or KB, MB, GB if specified)") ) sep1 = SeparatorField(label=_("IMAP settings")) diff --git a/modoboa/extensions/webmail/exceptions.py b/modoboa/extensions/webmail/exceptions.py index 51a42634a..e5012ab8a 100644 --- a/modoboa/extensions/webmail/exceptions.py +++ b/modoboa/extensions/webmail/exceptions.py @@ -25,6 +25,7 @@ class WebmailInternalError(InternalError): class UnknownAction(ModoboaException): + """ Use this exception when the webmail encounter an unknown action. """ @@ -35,6 +36,7 @@ class UnknownAction(ModoboaException): class ImapError(ModoboaException): + def __init__(self, reason): self.reason = reason diff --git a/modoboa/extensions/webmail/forms.py b/modoboa/extensions/webmail/forms.py index 9b5165590..c377fc91b 100644 --- a/modoboa/extensions/webmail/forms.py +++ b/modoboa/extensions/webmail/forms.py @@ -169,8 +169,8 @@ class ComposeMailForm(forms.Form): class ForwardMailForm(ComposeMailForm): - """Forward mail form. - """ + + """Forward mail form.""" def _build_msg(self, request): """Convert form's content to a MIME message. @@ -203,7 +203,8 @@ class FolderForm(forms.Form): widget=forms.HiddenInput(attrs={"class": "form-control"}), required=False ) - name = forms.CharField(widget=forms.TextInput(attrs={"class": "form-control"})) + name = forms.CharField( + widget=forms.TextInput(attrs={"class": "form-control"})) class AttachmentForm(forms.Form): diff --git a/modoboa/extensions/webmail/lib/attachments.py b/modoboa/extensions/webmail/lib/attachments.py index b99a0408a..7da2ed898 100644 --- a/modoboa/extensions/webmail/lib/attachments.py +++ b/modoboa/extensions/webmail/lib/attachments.py @@ -80,18 +80,19 @@ def create_mail_attachment(attdef, payload=None): res = MIMEBase(maintype, subtype) if payload is None: with open(os.path.join( - settings.MEDIA_ROOT, "webmail", attdef["tmpname"]), "rb") as fp: + settings.MEDIA_ROOT, "webmail", attdef["tmpname"]), "rb") as fp: res.set_payload(fp.read()) else: res.set_payload(payload) Encoders.encode_base64(res) - if type(attdef['fname']) is str: + if isinstance(attdef['fname'], str): attdef['fname'] = attdef['fname'].decode('utf-8') res['Content-Disposition'] = build_header(attdef['fname']) return res class AttachmentUploadHandler(FileUploadHandler): + """ Simple upload handler to limit the size of the attachments users can upload. diff --git a/modoboa/extensions/webmail/lib/fetch_parser.py b/modoboa/extensions/webmail/lib/fetch_parser.py index 97110d753..12bfadfc8 100644 --- a/modoboa/extensions/webmail/lib/fetch_parser.py +++ b/modoboa/extensions/webmail/lib/fetch_parser.py @@ -10,16 +10,19 @@ retrieve multiple attributes of a message. This simple module tries to fix that *problem*. """ + class ParseError(Exception): pass class Token(object): + def __init__(self, value): self.value = value class Literal(Token): + def __init__(self, value): super(Literal, self).__init__(value) self.next_token_len = int(self.value[1:-1]) @@ -50,7 +53,8 @@ def parse_next_token(buf): end = pos - 1 break if end == -1: - raise ParseError("End of buffer reached while looking for a token end") + raise ParseError( + "End of buffer reached while looking for a token end") end += 1 token = klass(buf[:end]) return token, end @@ -94,7 +98,7 @@ def parse_bodystructure(buf, depth=0, prefix=""): # make a difference between a content-disposition with # multiple args beeing parsed and a mime part! (see # the last example at the end of the file) - if type(ret[0]) == list or len(ret) >= 7: + if isinstance(ret[0], list) or len(ret) >= 7: partnum = prefix if partnum is not None: return [{"partnum": partnum, "struct": ret}], pos @@ -111,7 +115,8 @@ def parse_bodystructure(buf, depth=0, prefix=""): else: ret.append(token.value.strip('"')) - raise ParseError("End of buffer reached while looking for a BODY/BODYSTRUCTURE end") + raise ParseError( + "End of buffer reached while looking for a BODY/BODYSTRUCTURE end") def parse_fetch_response(data): @@ -128,7 +133,7 @@ def parse_fetch_response(data): while cpt < len(data): content = () while cpt < len(data) and data[cpt] != ')': - if type(data[cpt]) == str: + if isinstance(data[cpt], str): # FIXME : probably an unsolicited response cpt += 1 continue @@ -192,13 +197,13 @@ def parse_fetch_response(data): def dump_bodystructure(bs, depth=0): if depth: print " " * (depth * 4), - if type(bs[0]) == dict: + if isinstance(bs[0], dict): print "%s :" % bs[0]["partnum"], struct = bs[0]["struct"] else: struct = bs - if type(struct[0]) == list: + if isinstance(struct[0], list): print "multipart/%s" % struct[1] for part in struct[0]: dump_bodystructure(part, depth + 1) @@ -207,11 +212,14 @@ def dump_bodystructure(bs, depth=0): if __name__ == "__main__": -# resp = [('855 (UID 46931 BODYSTRUCTURE ((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 886 32 NIL NIL NIL NIL)("text" "html" ("charset" "us-ascii") NIL NIL "quoted-printable" 1208 16 NIL NIL NIL NIL) "alternative" ("boundary" "----=_NextPart_001_0003_01CCC564.B2F64FF0") NIL NIL NIL)("application" "octet-stream" ("name" "Carte Verte_2.pdf") NIL NIL "base64" 285610 NIL ("attachment" ("filename" "Carte Verte_2.pdf")) NIL NIL) "mixed" ("boundary" "----=_NextPart_000_0002_01CCC564.B2F64FF0") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {153}', 'From: \r\nTo: \r\nCc: \r\nSubject: Notre contact du 28/12/2011 - 192175092\r\nDate: Wed, 28 Dec 2011 13:29:17 +0100\r\n\r\n'), ')'] + # resp = [('855 (UID 46931 BODYSTRUCTURE ((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 886 32 NIL NIL NIL NIL)("text" "html" ("charset" "us-ascii") NIL NIL "quoted-printable" 1208 16 NIL NIL NIL NIL) "alternative" ("boundary" "----=_NextPart_001_0003_01CCC564.B2F64FF0") NIL NIL NIL)("application" "octet-stream" ("name" "Carte Verte_2.pdf") NIL NIL "base64" 285610 NIL ("attachment" ("filename" "Carte Verte_2.pdf")) NIL NIL) "mixed" ("boundary" "----=_NextPart_000_0002_01CCC564.B2F64FF0") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {153}', 'From: \r\nTo: \r\nCc: \r\nSubject: Notre contact du 28/12/2011 - 192175092\r\nDate: Wed, 28 Dec 2011 13:29:17 +0100\r\n\r\n'), ')'] # #resp = [('856 (UID 46936 BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 724 22 NIL NIL NIL NIL)("text" "html" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 2662 48 NIL NIL NIL NIL) "alternative" ("boundary" "----=_Part_1326887_254624357.1325083973970") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {258}', 'Date: Wed, 28 Dec 2011 15:52:53 +0100 (CET)\r\nFrom: =?ISO-8859-1?Q?Malakoff_M=E9d=E9ric?= \r\nTo: Antoine Nguyen \r\nSubject: =?ISO-8859-1?Q?Votre_inscription_au_grand_Jeu_Malakoff_M=E9d=E9ric?=\r\n\r\n'), ')'] - resp = [('856 (UID 11111 BODYSTRUCTURE ((("text" "plain" ("charset" "UTF-8") NIL NIL "7bit" 0 0 NIL NIL NIL NIL) "mixed" ("boundary" "----=_Part_407172_3159001.1321948277321") NIL NIL NIL)("application" "octet-stream" ("name" "26274308.pdf") NIL NIL "base64" 14906 NIL ("attachment" ("filename" "26274308.pdf")) NIL NIL) "mixed" ("boundary" "----=_Part_407171_9686991.1321948277321") NIL NIL NIL)',), ')'] + resp = [ + ('856 (UID 11111 BODYSTRUCTURE ((("text" "plain" ("charset" "UTF-8") NIL NIL "7bit" 0 0 NIL NIL NIL NIL) "mixed" ("boundary" "----=_Part_407172_3159001.1321948277321") NIL NIL NIL)("application" "octet-stream" ("name" "26274308.pdf") NIL NIL "base64" 14906 NIL ("attachment" ("filename" "26274308.pdf")) NIL NIL) "mixed" ("boundary" "----=_Part_407171_9686991.1321948277321") NIL NIL NIL)', + ), + ')'] # resp = [('19 (UID 19 FLAGS (\\Seen) BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1" "format" "flowed") NIL NIL "7bit" 2 1 NIL NIL NIL NIL)("message" "rfc822" ("name*" "ISO-8859-1\'\'%5B%49%4E%53%43%52%49%50%54%49%4F%4E%5D%20%52%E9%63%E9%70%74%69%6F%6E%20%64%65%20%76%6F%74%72%65%20%64%6F%73%73%69%65%72%20%64%27%69%6E%73%63%72%69%70%74%69%6F%6E%20%46%72%65%65%20%48%61%75%74%20%44%E9%62%69%74") NIL NIL "8bit" 3632 ("Wed, 13 Dec 2006 20:30:02 +0100" {70}', # "[INSCRIPTION] R\xe9c\xe9ption de votre dossier d'inscription Free Haut D\xe9bit"), diff --git a/modoboa/extensions/webmail/lib/imapemail.py b/modoboa/extensions/webmail/lib/imapemail.py index 6496e5a44..0b68b31e2 100644 --- a/modoboa/extensions/webmail/lib/imapemail.py +++ b/modoboa/extensions/webmail/lib/imapemail.py @@ -82,7 +82,7 @@ class ImapEmail(Email): ) self.bs = BodyStructure(self._msg['BODYSTRUCTURE']) self._find_attachments() - if not self.dformat in ["plain", "html"]: + if self.dformat not in ["plain", "html"]: self.dformat = parameters.get_user( self.request.user, self.dformat ) @@ -312,7 +312,7 @@ class ForwardModifier(Modifier): return "----- %s -----" % _("Original message") def _header_begin_html(self): - return "----- %s -----" % _("Original message") + return "----- %s -----" % _("Original message") def _header_line_plain(self, key, value): return "%s: %s\n" % (key, value) diff --git a/modoboa/extensions/webmail/lib/imapheader.py b/modoboa/extensions/webmail/lib/imapheader.py index dd2dbbb1a..4d6d9628d 100644 --- a/modoboa/extensions/webmail/lib/imapheader.py +++ b/modoboa/extensions/webmail/lib/imapheader.py @@ -13,7 +13,7 @@ __all__ = [ def to_unicode(value): """Try to convert a string to unicode. """ - if value is None or type(value) is unicode: + if value is None or isinstance(value, unicode): return value try: value = value.decode('utf-8') @@ -111,4 +111,3 @@ def parse_subject(value, **kwargs): except UnicodeDecodeError: subject = value return to_unicode(subject) - diff --git a/modoboa/extensions/webmail/lib/imaputils.py b/modoboa/extensions/webmail/lib/imaputils.py index 796f80161..7d34a75c8 100644 --- a/modoboa/extensions/webmail/lib/imaputils.py +++ b/modoboa/extensions/webmail/lib/imaputils.py @@ -3,24 +3,27 @@ :mod:`imaputils` --- Extra IMAPv4 utilities ------------------------------------------- """ -import imaplib -import ssl import email +import imaplib import re +import ssl import time from functools import wraps + from django.utils.translation import ugettext as _ -from modoboa.lib import parameters, imap_utf7 -from modoboa.lib.exceptions import InternalError -from modoboa.lib.connections import ConnectionsManager -from modoboa.lib.web_utils import static_url + from ..exceptions import ImapError, WebmailInternalError from .fetch_parser import parse_fetch_response +from modoboa.lib import parameters +from modoboa.lib.connections import ConnectionsManager +from modoboa.lib.exceptions import InternalError -#imaplib.Debug = 4 + +# imaplib.Debug = 4 class capability(object): + """ Simple decorator to check if the server presents the required capability. If not, a fallback method is called instead. @@ -28,6 +31,7 @@ class capability(object): :param name: the capability name (upper case) :param fallback_method: a method's name """ + def __init__(self, name, fallback_method): self.name = name self.fallback_method = fallback_method @@ -43,12 +47,14 @@ class capability(object): class BodyStructure(object): + """ BODYSTRUCTURE response parser. Just a simple class that tries to distinguish content parts from attachments. """ + def __init__(self, definition=None): self.is_multipart = False self.contents = {} @@ -71,7 +77,8 @@ class BodyStructure(object): * If the MIME type is text/plain or text/html: - * If no previous part of this type has already been seen, it's a content + * If no previous part of this type has already been seen, + it's a content * Otherwise it's an attachment * Else, if the multipart subtype is related, we consider this @@ -82,6 +89,7 @@ class BodyStructure(object): :param definition: a part definition (list) :param pnum: the part's number :param multisubtype: the multipart subtype + """ pnum = "1" if pnum is None else pnum params = dict(pnum=pnum, params=definition[2], cid=definition[3], @@ -91,7 +99,7 @@ class BodyStructure(object): subtype = definition[1].lower() ftype = "%s/%s" % (definition[0].lower(), subtype) if ftype in ("text/plain", "text/html"): - if not subtype in self.contents: + if subtype not in self.contents: self.contents[subtype] = [params] else: self.contents[subtype].append(params) @@ -106,24 +114,27 @@ class BodyStructure(object): if mtype == "text": extensions = ["textlines"] + extensions elif ftype == "message/rfc822": - extensions = ["envelopestruct", "bodystruct", "textlines"] + extensions + extensions = [ + "envelopestruct", + "bodystruct", + "textlines"] + extensions for idx, value in enumerate(definition[7:]): params[extensions[idx]] = value self.attachments += [params] def load_from_definition(self, definition, multisubtype=None): - if type(definition) == dict: + if isinstance(definition, dict): struct = definition["struct"] pnum = definition["partnum"] - elif type(definition[0]) == dict: + elif isinstance(definition[0], dict): struct = definition[0]["struct"] pnum = definition[0]["partnum"] else: struct = definition pnum = None - if type(struct[0]) == list: + if isinstance(struct[0], list): for part in struct[0]: self.load_from_definition(part, struct[1]) return @@ -146,8 +157,11 @@ class IMAPconnector(object): __metaclass__ = ConnectionsManager - list_base_pattern = r'\((?P.*?)\) "(?P.*)" "?(?P[^"]*)"?' - list_response_pattern_literal = re.compile(r'\((?P.*?)\) "(?P.*)" \{(?P\d+)\}') + list_base_pattern = ( + r'\((?P.*?)\) "(?P.*)" "?(?P[^"]*)"?' + ) + list_response_pattern_literal = re.compile( + r'\((?P.*?)\) "(?P.*)" \{(?P\d+)\}') list_response_pattern = re.compile(list_base_pattern) listextended_response_pattern = \ re.compile(list_base_pattern + r'\s*(?P.*)') @@ -178,7 +192,7 @@ class IMAPconnector(object): if name in ['FETCH', 'SORT', 'STORE', 'COPY', 'SEARCH']: try: typ, data = self.m.uid(name, *args) - except imaplib.IMAP4.error, e: + except imaplib.IMAP4.error as e: raise ImapError(e) if typ == "NO": raise ImapError(data) @@ -188,17 +202,17 @@ class IMAPconnector(object): try: typ, data = self.m._simple_command(name, *args) - except imaplib.IMAP4.error, e: + except imaplib.IMAP4.error as e: raise ImapError(e) if typ == "NO": raise ImapError(data) - if not 'responses' in kwargs: - if not name in self.m.untagged_responses: + if 'responses' not in kwargs: + if name not in self.m.untagged_responses: return None return self.m.untagged_responses.pop(name) res = [] for r in kwargs['responses']: - if not r in self.m.untagged_responses: + if r not in self.m.untagged_responses: return None res.append(self.m.untagged_responses.pop(r)) return res @@ -218,14 +232,20 @@ class IMAPconnector(object): if type(bodystruct[0]) in [list, tuple]: cpt = 1 for part in bodystruct[0]: - nprefix = "%s" % cpt if prefix == "" else "%s.%d" % (prefix, cpt) + nprefix = "%s" % cpt if prefix == "" else "%s.%d" % ( + prefix, cpt) index, encoding, size = \ - self.__find_content_in_bodystruct(part, mtype, stype, nprefix) + self.__find_content_in_bodystruct( + part, + mtype, + stype, + nprefix) if index is not None: return (index, encoding, size) cpt += 1 else: - if bodystruct[0].lower() == mtype and bodystruct[1].lower() == stype: + if bodystruct[0].lower() == mtype and \ + bodystruct[1].lower() == stype: return ("1" if not len(prefix) else prefix, bodystruct[5], int(bodystruct[6])) return (None, None, 0) @@ -275,9 +295,9 @@ class IMAPconnector(object): """ import socket - if type(user) is unicode: + if isinstance(user, unicode): user = user.encode("utf-8") - if type(passwd) is unicode: + if isinstance(passwd, unicode): passwd = passwd.encode("utf-8") try: secured = parameters.get_admin("IMAP_SECURED") @@ -285,7 +305,7 @@ class IMAPconnector(object): self.m = imaplib.IMAP4_SSL(self.address, self.port) else: self.m = imaplib.IMAP4(self.address, self.port) - except (socket.error, imaplib.IMAP4.error, ssl.SSLError), error: + except (socket.error, imaplib.IMAP4.error, ssl.SSLError) as error: raise ImapError(_("Connection to IMAP server failed: %s" % error)) data = self._cmd("LOGIN", user, passwd) @@ -320,9 +340,9 @@ class IMAPconnector(object): if criterion == u"both": criterion = u"from_addr, subject" criterions = "" - if type(pattern) is unicode: + if isinstance(pattern, unicode): pattern = pattern.encode("utf-8") - if type(criterion) is unicode: + if isinstance(criterion, unicode): criterion = criterion.encode("utf-8") for c in criterion.split(','): if c == "from_addr": @@ -418,12 +438,14 @@ class IMAPconnector(object): return True def _listmboxes_simple(self, topmailbox='INBOX', mailboxes=None, **kwargs): - #data = self._cmd("LIST", "", "*") - if not mailboxes: mailboxes = [] + # data = self._cmd("LIST", "", "*") + if not mailboxes: + mailboxes = [] (status, data) = self.m.list() newmboxes = [] for mb in data: - flags, delimiter, name = self.list_response_pattern.match(mb).groups() + flags, delimiter, name = self.list_response_pattern.match( + mb).groups() name = name.strip('"').decode("imap4-utf-7") mdm_found = False for idx, mdm in enumerate(mailboxes): @@ -437,7 +459,7 @@ class IMAPconnector(object): if re.search("\%s" % delimiter, name): parts = name.split(delimiter) - if not "path" in descr: + if "path" not in descr: descr["path"] = parts[0] descr["sub"] = [] if self._parse_mailbox_name(descr["sub"], parts[0], delimiter, @@ -480,7 +502,7 @@ class IMAPconnector(object): descr = dict(name=name) newmboxes += [descr] - if r'\Marked' in flags or not r'\UnMarked' in flags: + if r'\Marked' in flags or r'\UnMarked' not in flags: descr["send_status"] = True if r'\HasChildren' in flags: if r'\NonExistent' in flags: @@ -529,7 +551,7 @@ class IMAPconnector(object): if unseen_messages: for mb in md_mailboxes: - if not "send_status" in mb: + if "send_status" not in mb: continue del mb["send_status"] key = "path" if "path" in mb else "name" @@ -631,7 +653,7 @@ class IMAPconnector(object): We also compute the current usage. """ - if not "QUOTA" in self.capabilities: + if "QUOTA" not in self.capabilities: self.quota_limit = self.quota_current = None return @@ -700,7 +722,7 @@ class IMAPconnector(object): data[int(uid)]['BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)]'] ) msg['imapid'] = uid - if not r'\Seen' in data[int(uid)]['FLAGS']: + if r'\Seen' not in data[int(uid)]['FLAGS']: msg['style'] = 'unseen' if r'\Answered' in data[int(uid)]['FLAGS']: msg['answered'] = True diff --git a/modoboa/extensions/webmail/lib/signature.py b/modoboa/extensions/webmail/lib/signature.py index c90a00fa5..2b24507fa 100644 --- a/modoboa/extensions/webmail/lib/signature.py +++ b/modoboa/extensions/webmail/lib/signature.py @@ -3,10 +3,12 @@ from modoboa.lib import parameters class EmailSignature(object): + """User signature :param user: User object """ + def __init__(self, user): self._sig = u"" dformat = parameters.get_user(user, "EDITOR") diff --git a/modoboa/extensions/webmail/lib/utils.py b/modoboa/extensions/webmail/lib/utils.py index 8c341c2d5..366384de0 100644 --- a/modoboa/extensions/webmail/lib/utils.py +++ b/modoboa/extensions/webmail/lib/utils.py @@ -24,9 +24,11 @@ def decode_payload(encoding, payload): class WebmailNavigationParameters(NavigationParameters): + """ Specific NavigationParameters subclass for the webmail. """ + def __init__(self, request, defmailbox=None): super(WebmailNavigationParameters, self).__init__( request, 'webmail_navparams' diff --git a/modoboa/extensions/webmail/templatetags/webmail_tags.py b/modoboa/extensions/webmail/templatetags/webmail_tags.py index 2bf34d190..83b2f3d95 100644 --- a/modoboa/extensions/webmail/templatetags/webmail_tags.py +++ b/modoboa/extensions/webmail/templatetags/webmail_tags.py @@ -36,14 +36,14 @@ def viewmail_menu(selection, folder, user, mail_id=None): "url": "action=forward&mbox=%s&mailid=%s" % (folder, mail_id), "img": "fa fa-mail-forward", "label": _("Forward")}, - ]}, + ]}, {"name": "delete", "img": "fa fa-trash", "class": "btn-danger", "url": "{0}?mbox={1}&selection[]={2}".format( reverse("webmail:mail_delete"), folder, mail_id), "title": _("Delete") - }, + }, {"name": "display_options", "title": _("Display options"), "img": "fa fa-cog", @@ -150,7 +150,8 @@ def print_mailboxes( extra_attrs = ' data-toggle="%d"' % mbox["unseen"] if "sub" in mbox: - if selected is not None and selected != name and selected.count(name): + if selected is not None and selected != name and selected.count( + name): ul_state = "visible" div_state = "expanded" else: @@ -171,7 +172,7 @@ def print_mailboxes( result += "\n" + ) + "\n" result += "\n" return result diff --git a/modoboa/extensions/webmail/views.py b/modoboa/extensions/webmail/views.py index 89b8b78f7..230ddc230 100644 --- a/modoboa/extensions/webmail/views.py +++ b/modoboa/extensions/webmail/views.py @@ -71,7 +71,7 @@ def getattachment(request): @needs_mailbox() def move(request): for arg in ["msgset", "to"]: - if not arg in request.GET: + if arg not in request.GET: raise BadRequest(_("Invalid request")) mbc = get_imapconnector(request) navparams = WebmailNavigationParameters(request) @@ -291,8 +291,8 @@ def attachments(request, tplname="webmail/attachments.html"): @login_required @needs_mailbox() def delattachment(request): - if not "compose_mail" in request.session \ - or not "name" in request.GET \ + if "compose_mail" not in request.session \ + or "name" not in request.GET \ or not request.GET["name"]: return ajax_response(request, "ko", respmsg=_("Bad query")) @@ -305,7 +305,7 @@ def delattachment(request): ) try: os.remove(fullpath) - except OSError, e: + except OSError as e: error = _("Failed to remove attachment: ") + str(e) break request.session.modified = True @@ -390,11 +390,11 @@ def render_compose(request, form, posturl, email=None, insert_signature=False): signature = EmailSignature(request.user) body += unicode(signature) randid = None - if not "id" in request.GET: + if "id" not in request.GET: if "compose_mail" in request.session: clean_attachments(request.session["compose_mail"]["attachments"]) randid = set_compose_session(request) - elif not "compose_mail" in request.session \ + elif "compose_mail" not in request.session \ or request.session["compose_mail"]["id"] != request.GET["id"]: randid = set_compose_session(request) @@ -567,7 +567,7 @@ def index(request): """ action = request.GET.get("action", None) if action is not None: - if not action in globals(): + if action not in globals(): raise UnknownAction response = globals()[action](request) else: From 0a49b0a52b20b1ad9a073ffa421bb45c8600ddef Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 16 Jan 2015 10:31:35 +0100 Subject: [PATCH 24/24] PEP8 fixes --- modoboa/core/commands/__init__.py | 1 + modoboa/core/commands/postfix_maps.py | 12 ++++++++---- modoboa/core/extensions.py | 2 ++ modoboa/core/models.py | 5 +++-- modoboa/core/password_hashers/advanced.py | 3 +++ modoboa/core/password_hashers/base.py | 6 ++++++ modoboa/core/templatetags/core_tags.py | 1 + modoboa/extensions/webmail/lib/fetch_parser.py | 4 ++-- modoboa/tools/pfxadmin_migrate/models.py | 11 ++++++++--- 9 files changed, 34 insertions(+), 11 deletions(-) diff --git a/modoboa/core/commands/__init__.py b/modoboa/core/commands/__init__.py index e95f987b2..b1b2cf62e 100644 --- a/modoboa/core/commands/__init__.py +++ b/modoboa/core/commands/__init__.py @@ -9,6 +9,7 @@ from django.template import Context, Template class Command(object): + """Base command class A valid administrative command must inherit from this class. diff --git a/modoboa/core/commands/postfix_maps.py b/modoboa/core/commands/postfix_maps.py index 0cf9e9fb2..c663841fe 100644 --- a/modoboa/core/commands/postfix_maps.py +++ b/modoboa/core/commands/postfix_maps.py @@ -1,18 +1,22 @@ # coding: utf-8 + +"""postfix_maps command.""" + +import datetime import getpass import inspect import os import sys -import datetime + from django.template import Context, Template + from . import Command class MapFilesGenerator(object): def __init__(self, dbinfo=None): - """Constructor. - """ + """Constructor.""" self.template = Template("""user = {{ dbuser }} password = {{ dbpass }} dbname = {{ dbname }} @@ -69,7 +73,7 @@ query = {{ query|safe }} continue if v is MapFile: continue - if not v.category in args.categories: + if v.category not in args.categories: continue self.__render_map(args, v) diff --git a/modoboa/core/extensions.py b/modoboa/core/extensions.py index 99a89f7a3..96d3096cf 100644 --- a/modoboa/core/extensions.py +++ b/modoboa/core/extensions.py @@ -5,6 +5,7 @@ from django.conf.urls import include class ModoExtension(object): + """Base extension class. Each Modoboa extension must inherit from this class to be @@ -37,6 +38,7 @@ class ModoExtension(object): class ExtensionsPool(object): + """The extensions manager""" def __init__(self): diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 93f32451f..8d4aed543 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -37,6 +37,7 @@ except ImportError: class User(PermissionsMixin): + """Custom User model. It overloads the way passwords are stored into the database. The @@ -114,7 +115,7 @@ class User(PermissionsMixin): load_core_settings() scheme = parameters.get_admin("PASSWORD_SCHEME") - if type(raw_value) is unicode: + if isinstance(raw_value, unicode): raw_value = raw_value.encode("utf-8") return get_password_hasher(scheme.upper())().encrypt(raw_value) @@ -146,7 +147,7 @@ class User(PermissionsMixin): match = self.password_expr.match(self.password) if match is None: return False - if type(raw_value) is unicode: + if isinstance(raw_value, unicode): raw_value = raw_value.encode("utf-8") scheme = match.group(1) val2 = match.group(2) diff --git a/modoboa/core/password_hashers/advanced.py b/modoboa/core/password_hashers/advanced.py index 3bb632ad2..73b5ef493 100644 --- a/modoboa/core/password_hashers/advanced.py +++ b/modoboa/core/password_hashers/advanced.py @@ -9,6 +9,7 @@ from modoboa.lib import parameters class MD5CRYPTHasher(PasswordHasher): + """ MD5-CRYPT password hasher. @@ -29,6 +30,7 @@ class MD5CRYPTHasher(PasswordHasher): class SHA256CRYPTHasher(PasswordHasher): + """ SHA256-CRYPT password hasher. @@ -51,6 +53,7 @@ class SHA256CRYPTHasher(PasswordHasher): class SHA512CRYPTHasher(PasswordHasher): + """ SHA512-CRYPT password hasher. diff --git a/modoboa/core/password_hashers/base.py b/modoboa/core/password_hashers/base.py index 156a35616..b0902c926 100644 --- a/modoboa/core/password_hashers/base.py +++ b/modoboa/core/password_hashers/base.py @@ -12,9 +12,11 @@ from django.utils.crypto import constant_time_compare class PasswordHasher(object): + """ Base class of all hashers. """ + def __init__(self, target='local'): self._target = target @@ -61,6 +63,7 @@ class PasswordHasher(object): class PLAINHasher(PasswordHasher): + """ Plain (ie. clear) password hasher. """ @@ -73,6 +76,7 @@ class PLAINHasher(PasswordHasher): class CRYPTHasher(PasswordHasher): + """ crypt password hasher. @@ -89,6 +93,7 @@ class CRYPTHasher(PasswordHasher): class MD5Hasher(PasswordHasher): + """ MD5 password hasher. @@ -104,6 +109,7 @@ class MD5Hasher(PasswordHasher): class SHA256Hasher(PasswordHasher): + """ SHA256 password hasher. diff --git a/modoboa/core/templatetags/core_tags.py b/modoboa/core/templatetags/core_tags.py index 9c9830c33..bd50c7eb7 100644 --- a/modoboa/core/templatetags/core_tags.py +++ b/modoboa/core/templatetags/core_tags.py @@ -158,6 +158,7 @@ def get_version(): class ConnectedUsers(template.Node): + def __init__(self, varname): self.varname = varname diff --git a/modoboa/extensions/webmail/lib/fetch_parser.py b/modoboa/extensions/webmail/lib/fetch_parser.py index 12bfadfc8..8d83cdf2d 100644 --- a/modoboa/extensions/webmail/lib/fetch_parser.py +++ b/modoboa/extensions/webmail/lib/fetch_parser.py @@ -212,9 +212,9 @@ def dump_bodystructure(bs, depth=0): if __name__ == "__main__": - # resp = [('855 (UID 46931 BODYSTRUCTURE ((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 886 32 NIL NIL NIL NIL)("text" "html" ("charset" "us-ascii") NIL NIL "quoted-printable" 1208 16 NIL NIL NIL NIL) "alternative" ("boundary" "----=_NextPart_001_0003_01CCC564.B2F64FF0") NIL NIL NIL)("application" "octet-stream" ("name" "Carte Verte_2.pdf") NIL NIL "base64" 285610 NIL ("attachment" ("filename" "Carte Verte_2.pdf")) NIL NIL) "mixed" ("boundary" "----=_NextPart_000_0002_01CCC564.B2F64FF0") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {153}', 'From: \r\nTo: \r\nCc: \r\nSubject: Notre contact du 28/12/2011 - 192175092\r\nDate: Wed, 28 Dec 2011 13:29:17 +0100\r\n\r\n'), ')'] +# resp = [('855 (UID 46931 BODYSTRUCTURE ((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 886 32 NIL NIL NIL NIL)("text" "html" ("charset" "us-ascii") NIL NIL "quoted-printable" 1208 16 NIL NIL NIL NIL) "alternative" ("boundary" "----=_NextPart_001_0003_01CCC564.B2F64FF0") NIL NIL NIL)("application" "octet-stream" ("name" "Carte Verte_2.pdf") NIL NIL "base64" 285610 NIL ("attachment" ("filename" "Carte Verte_2.pdf")) NIL NIL) "mixed" ("boundary" "----=_NextPart_000_0002_01CCC564.B2F64FF0") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {153}', 'From: \r\nTo: \r\nCc: \r\nSubject: Notre contact du 28/12/2011 - 192175092\r\nDate: Wed, 28 Dec 2011 13:29:17 +0100\r\n\r\n'), ')'] - # #resp = [('856 (UID 46936 BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 724 22 NIL NIL NIL NIL)("text" "html" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 2662 48 NIL NIL NIL NIL) "alternative" ("boundary" "----=_Part_1326887_254624357.1325083973970") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {258}', 'Date: Wed, 28 Dec 2011 15:52:53 +0100 (CET)\r\nFrom: =?ISO-8859-1?Q?Malakoff_M=E9d=E9ric?= \r\nTo: Antoine Nguyen \r\nSubject: =?ISO-8859-1?Q?Votre_inscription_au_grand_Jeu_Malakoff_M=E9d=E9ric?=\r\n\r\n'), ')'] +# resp = [('856 (UID 46936 BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 724 22 NIL NIL NIL NIL)("text" "html" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 2662 48 NIL NIL NIL NIL) "alternative" ("boundary" "----=_Part_1326887_254624357.1325083973970") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {258}', 'Date: Wed, 28 Dec 2011 15:52:53 +0100 (CET)\r\nFrom: =?ISO-8859-1?Q?Malakoff_M=E9d=E9ric?= \r\nTo: Antoine Nguyen \r\nSubject: =?ISO-8859-1?Q?Votre_inscription_au_grand_Jeu_Malakoff_M=E9d=E9ric?=\r\n\r\n'), ')'] resp = [ ('856 (UID 11111 BODYSTRUCTURE ((("text" "plain" ("charset" "UTF-8") NIL NIL "7bit" 0 0 NIL NIL NIL NIL) "mixed" ("boundary" "----=_Part_407172_3159001.1321948277321") NIL NIL NIL)("application" "octet-stream" ("name" "26274308.pdf") NIL NIL "base64" 14906 NIL ("attachment" ("filename" "26274308.pdf")) NIL NIL) "mixed" ("boundary" "----=_Part_407171_9686991.1321948277321") NIL NIL NIL)', diff --git a/modoboa/tools/pfxadmin_migrate/models.py b/modoboa/tools/pfxadmin_migrate/models.py index c95f46216..f94e2f775 100755 --- a/modoboa/tools/pfxadmin_migrate/models.py +++ b/modoboa/tools/pfxadmin_migrate/models.py @@ -1,15 +1,20 @@ # coding: utf-8 + +"""postfixadmin models.""" + # This is an auto-generated Django model module. # You'll have to do the following manually to clean this up: # * Rearrange models' order # * Make sure each model has one field with primary_key=True -# Feel free to rename the models, but don't rename db_table values or field names. +# Feel free to rename the models, but don't rename db_table values or +# field names. # -# Also note: You'll have to insert the output of 'django-admin.py sqlcustom [appname]' -# into your database. +# Also note: You'll have to insert the output of 'django-admin.py +# sqlcustom [appname]' into your database. from django.db import models + class Admin(models.Model): username = models.CharField(max_length=255, primary_key=True) password = models.CharField(max_length=255)