diff --git a/doc/conf.py b/doc/conf.py index 1cf6ecc96..1c1daa194 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -17,12 +17,12 @@ import os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. @@ -37,14 +37,14 @@ templates_path = [".templates"] source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. master_doc = "index" # General information about the project. -project = u'Modoboa' -copyright = u'2018, Antoine Nguyen' # NOQA:A001 +project = "Modoboa" +copyright = "2018, Antoine Nguyen" # NOQA:A001 # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -57,37 +57,37 @@ release = "1.10.0" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [".build"] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- @@ -104,26 +104,26 @@ else: # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -132,44 +132,44 @@ html_static_path = ["_static"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = "Modoboadoc" @@ -178,40 +178,40 @@ htmlhelp_basename = "Modoboadoc" # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' +# latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' +# latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ("index", "Modoboa.tex", u'Modoboa Documentation', - u'Antoine Nguyen', "manual"), + ("index", "Modoboa.tex", "Modoboa Documentation", + "Antoine Nguyen", "manual"), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Additional stuff for the LaTeX preamble. -#latex_preamble = '' +# latex_preamble = '' # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output -------------------------------------------- @@ -219,8 +219,8 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ("index", "modoboa", u'Modoboa Documentation', - [u'Antoine Nguyen'], 1) + ("index", "modoboa", "Modoboa Documentation", + ["Antoine Nguyen"], 1) ] intersphinx_mapping = { diff --git a/modoboa/admin/lib.py b/modoboa/admin/lib.py index 3b0dc8585..2b1819bed 100644 --- a/modoboa/admin/lib.py +++ b/modoboa/admin/lib.py @@ -185,8 +185,8 @@ def get_domain_mx_list(domain): logger.error(_("No working name servers found"), exc_info=e) except dns.resolver.Timeout as e: logger.warning( - _("DNS resolution timeout, unable to query %s at the moment") % domain, - exc_info=e) + _("DNS resolution timeout, unable to query %s at the moment") % + domain, exc_info=e) else: for dns_answer in dns_answers: try: diff --git a/modoboa/admin/management/commands/subcommands/_repair.py b/modoboa/admin/management/commands/subcommands/_repair.py index 04b0e7984..58fdc3aef 100644 --- a/modoboa/admin/management/commands/subcommands/_repair.py +++ b/modoboa/admin/management/commands/subcommands/_repair.py @@ -111,7 +111,10 @@ class Repair(BaseCommand): # Load known problems from extensions. for ext in settings.MODOBOA_APPS: try: - __import__(ext, locals(), globals(), [smart_str("known_problems")]) + __import__( + ext, locals(), globals(), + [smart_str("known_problems")] + ) except ImportError: pass for func in known_problems: diff --git a/modoboa/admin/models/domain_alias.py b/modoboa/admin/models/domain_alias.py index 590241563..b231b586e 100644 --- a/modoboa/admin/models/domain_alias.py +++ b/modoboa/admin/models/domain_alias.py @@ -62,7 +62,8 @@ class DomainAlias(AdminObject): def from_csv(self, user, row): """Create a domain alias from a CSV row - Expected format: ["domainalias", domain alias name, targeted domain, enabled] + Expected format: ["domainalias", domain alias name, targeted domain, + enabled] :param user: a ``User`` object :param row: a list containing the alias definition @@ -91,4 +92,5 @@ class DomainAlias(AdminObject): csvwriter.writerow(["domainalias", self.name, self.target.name, self.enabled]) + reversion.register(DomainAlias) diff --git a/modoboa/admin/serializers.py b/modoboa/admin/serializers.py index 68558007b..5620bc63d 100644 --- a/modoboa/admin/serializers.py +++ b/modoboa/admin/serializers.py @@ -61,8 +61,8 @@ class DomainSerializer(serializers.ModelSerializer): domain = models.Domain(**validated_data) creator = self.context["request"].user core_signals.can_create_object.send( - sender=self.__class__, context=creator, - klass=models.Domain, instance=domain) + sender=self.__class__, context=creator, + klass=models.Domain, instance=domain) domain.save(creator=creator) return domain diff --git a/modoboa/admin/tests/test_alias.py b/modoboa/admin/tests/test_alias.py index 506de3da7..6372c490f 100644 --- a/modoboa/admin/tests/test_alias.py +++ b/modoboa/admin/tests/test_alias.py @@ -12,9 +12,6 @@ from ..models import Alias, AliasRecipient, Domain """Admin test cases.""" - - - class AliasTestCase(ModoTestCase): @classmethod diff --git a/modoboa/admin/tests/test_export.py b/modoboa/admin/tests/test_export.py index fa0912086..c4fdf2db0 100644 --- a/modoboa/admin/tests/test_export.py +++ b/modoboa/admin/tests/test_export.py @@ -65,7 +65,7 @@ class ExportTestCase(ModoTestCase): def test_export_identities(self): response = self.__export_identities() self.assertListEqual( - "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com\r\naccount;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\nalias;alias@test.com;True;user@test.com\r\nalias;forward@test.com;True;user@external.com\r\nalias;postmaster@test.com;True;test@truc.fr;toto@titi.com\r\n", + "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com\r\naccount;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\nalias;alias@test.com;True;user@test.com\r\nalias;forward@test.com;True;user@external.com\r\nalias;postmaster@test.com;True;test@truc.fr;toto@titi.com\r\n", # NOQA:E501 response.content.strip() ) @@ -79,7 +79,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\r\naccount;toto@test.com;{PLAIN}toto;Léon;;True;SimpleUsers;toto@test.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\r\naccount;toto@test.com;{PLAIN}toto;Léon;;True;SimpleUsers;toto@test.com;10", # NOQA:E501 response.content.strip() ) @@ -103,7 +103,7 @@ class ExportTestCase(ModoTestCase): idtfilter="account", grpfilter="DomainAdmins" ) self.assertListEqual( - "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com", + "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com", # NOQA:E501 response.content.strip() ) @@ -111,5 +111,5 @@ class ExportTestCase(ModoTestCase): response = self.__export_identities(idtfilter="alias") self.assertEqual( response.content.decode().strip(), - "alias;alias@test.com;True;user@test.com\r\nalias;forward@test.com;True;user@external.com\r\nalias;postmaster@test.com;True;test@truc.fr;toto@titi.com" + "alias;alias@test.com;True;user@test.com\r\nalias;forward@test.com;True;user@external.com\r\nalias;postmaster@test.com;True;test@truc.fr;toto@titi.com" # NOQA:E501 ) diff --git a/modoboa/admin/tests/test_import_.py b/modoboa/admin/tests/test_import_.py index 49aeb8fbf..540fede38 100644 --- a/modoboa/admin/tests/test_import_.py +++ b/modoboa/admin/tests/test_import_.py @@ -134,7 +134,7 @@ alias; alias1@test.com; True; user1@test.com forward; alias2@test.com; True; user1+ext@test.com forward; fwd1@test.com; True; user@extdomain.com dlist; dlist@test.com; True; user1@test.com; user@extdomain.com -""", name="identities.csv") +""", name="identities.csv") # NOQA:E501 self.client.post( reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True} @@ -200,7 +200,7 @@ dlist; dlist@test.com; True; user1@test.com; user@extdomain.com """Try to import an account for nonlocal domain.""" f = ContentFile(b""" account; user1@nonlocal.com; toto; User; One; True; SimpleUsers; user1@nonlocal.com; 0 -""", name="identities.csv") +""", name="identities.csv") # NOQA:E501 self.client.post( reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True} @@ -211,7 +211,7 @@ account; user1@nonlocal.com; toto; User; One; True; SimpleUsers; user1@nonlocal. def test_import_invalid_quota(self): f = ContentFile(b""" account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; ; test.com -""", name="identities.csv") +""", name="identities.csv") # NOQA:E501 resp = self.client.post( reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True} @@ -229,7 +229,9 @@ domain; domain2.com; 1000; 200; False reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True} ) - self.assertIn("You are not allowed to import domains", resp.content.decode()) + self.assertIn( + "You are not allowed to import domains", + resp.content.decode()) f = ContentFile(b""" domainalias; domalias1.com; test.com; True """, name="identities.csv") @@ -238,7 +240,8 @@ domainalias; domalias1.com; test.com; True {"sourcefile": f, "crypt_password": True} ) self.assertIn( - "You are not allowed to import domain aliases", resp.content.decode()) + "You are not allowed to import domain aliases", + resp.content.decode()) def test_import_quota_too_big(self): self.client.logout() @@ -270,7 +273,7 @@ account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com f = ContentFile(""" account; admin@test.com; toto; Admin; ; True; DomainAdmins; admin@test.com; 0; test.com account; truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 0; test.com -""", name="identities.csv") +""", name="identities.csv") # NOQA:E501 self.client.post( reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True, @@ -291,7 +294,7 @@ account; truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 0; ) f = ContentFile(b""" account; sa@test.com; toto; Super; Admin; True; SuperAdmins; superadmin@test.com; 50 -""", name="identities.csv") +""", name="identities.csv") # NOQA:E501 self.client.post( reverse("admin:identity_import"), {"sourcefile": f, "crypt_password": True, diff --git a/modoboa/admin/tests/test_mx.py b/modoboa/admin/tests/test_mx.py index d75c149be..276afd990 100644 --- a/modoboa/admin/tests/test_mx.py +++ b/modoboa/admin/tests/test_mx.py @@ -53,7 +53,7 @@ class MXTestCase(ModoTestCase): @patch("socket.getaddrinfo") @patch.object(dns.resolver.Resolver, "query") def test_management_command( - self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): + self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): """Check that command works fine.""" mock_query.side_effect = utils.mock_dns_query_result mock_getaddrinfo.side_effect = utils.mock_ip_query_result @@ -81,7 +81,7 @@ class MXTestCase(ModoTestCase): @patch("socket.getaddrinfo") @patch.object(dns.resolver.Resolver, "query") def test_single_domain_update( - self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): + self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): """Update only one domain.""" mock_query.side_effect = utils.mock_dns_query_result mock_getaddrinfo.side_effect = utils.mock_ip_query_result @@ -130,7 +130,7 @@ class MXTestCase(ModoTestCase): ("modoboa.admin", "WARNING", _("Invalid IP address format for %(domain)s; %(addr)s") % {"domain": "bad-response.example.com", "addr": "BAD"}), - ) + ) @override_settings(DNSBL_PROVIDERS=["zen.spamhaus.org"]) @@ -153,7 +153,7 @@ class DNSBLTestCase(ModoTestCase): @patch("socket.getaddrinfo") @patch.object(dns.resolver.Resolver, "query") def test_management_command( - self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): + self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): """Check that command works fine.""" mock_query.side_effect = utils.mock_dns_query_result mock_getaddrinfo.side_effect = utils.mock_ip_query_result @@ -174,7 +174,7 @@ class DNSBLTestCase(ModoTestCase): @patch("socket.getaddrinfo") @patch.object(dns.resolver.Resolver, "query") def test_notifications( - self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): + self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): """Check notifications.""" mock_query.side_effect = utils.mock_dns_query_result mock_getaddrinfo.side_effect = utils.mock_ip_query_result @@ -190,7 +190,7 @@ class DNSBLTestCase(ModoTestCase): @patch("socket.getaddrinfo") @patch.object(dns.resolver.Resolver, "query") def test_management_command_no_dnsbl( - self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): + self, mock_query, mock_getaddrinfo, mock_g_gethostbyname): """Check that command works fine without dnsbl.""" mock_query.side_effect = utils.mock_dns_query_result mock_getaddrinfo.side_effect = utils.mock_ip_query_result diff --git a/modoboa/admin/tests/utils.py b/modoboa/admin/tests/utils.py index bf1887465..797fc6dcb 100644 --- a/modoboa/admin/tests/utils.py +++ b/modoboa/admin/tests/utils.py @@ -13,7 +13,8 @@ from dns.resolver import NXDOMAIN, NoAnswer, NoNameservers, Timeout _MX_RECORD_1 = MX("IN", "MX", 10, Name("mx.example.com".split("."))) _MX_RECORD_2 = MX("IN", "MX", 10, Name("mx2.example.com".split("."))) _BAD_MX_RECORD = MX("IN", "MX", 10, Name("bad-response.example.com".split("."))) -_DNE_MX_RECORD = MX("IN", "MX", 10, Name("does-not-exist.example.com".split("."))) +_DNE_MX_RECORD = MX("IN", "MX", 10, Name( + "does-not-exist.example.com".split("."))) _MX_RECORDS = [_MX_RECORD_1] _IPV4_RECORD_1 = (socket.AF_INET, socket.SOCK_STREAM, 6, "", ("192.0.2.1", 25)) diff --git a/modoboa/core/mocks.py b/modoboa/core/mocks.py index 8b97f6b2f..fc474b357 100644 --- a/modoboa/core/mocks.py +++ b/modoboa/core/mocks.py @@ -6,6 +6,7 @@ import httmock # Modoboa API mocks + @httmock.urlmatch( netloc=r"api\.modoboa\.org$", path=r"^/1/instances/search/", method="post") def modo_api_instance_search(url, request): diff --git a/modoboa/core/password_hashers/base.py b/modoboa/core/password_hashers/base.py index f065bc67a..eb926adea 100644 --- a/modoboa/core/password_hashers/base.py +++ b/modoboa/core/password_hashers/base.py @@ -93,7 +93,13 @@ class CRYPTHasher(PasswordHasher): def _encrypt(self, clearvalue, salt=None): if salt is None: - salt = "".join(Random().sample(string.ascii_letters + string.digits, 2)) + salt = "".join( + Random().sample( + string.ascii_letters + + string.digits, + 2 + ) + ) return crypt.crypt(clearvalue, salt) diff --git a/modoboa/core/tests/stupid_extension_1/modo_extension.py b/modoboa/core/tests/stupid_extension_1/modo_extension.py index 4115447d0..171646e73 100644 --- a/modoboa/core/tests/stupid_extension_1/modo_extension.py +++ b/modoboa/core/tests/stupid_extension_1/modo_extension.py @@ -19,4 +19,5 @@ class StupidExtension1(extensions.ModoExtension): def load_initial_data(self): raise RuntimeError + extensions.exts_pool.register_extension(StupidExtension1) diff --git a/modoboa/core/utils.py b/modoboa/core/utils.py index 1ac62a320..280bcb366 100644 --- a/modoboa/core/utils.py +++ b/modoboa/core/utils.py @@ -42,9 +42,9 @@ def check_for_updates(request): continue extension["last_version"] = api_extension["version"] if ( - parse_version(api_extension["version"]) - > parse_version(extension["version"]) - ): + parse_version(api_extension["version"]) > + parse_version(extension["version"]) + ): extension["update"] = True extension["changelog_url"] = api_extension["url"] update_avail = True diff --git a/modoboa/lib/email_utils.py b/modoboa/lib/email_utils.py index f1be3a8e6..72d11c42e 100644 --- a/modoboa/lib/email_utils.py +++ b/modoboa/lib/email_utils.py @@ -179,7 +179,8 @@ class Email(object): if content_type == "text": self._parse_text(part, level=level) else: - # I'm a dumb mail parser and treat all non-text parts as attachments + # I'm a dumb mail parser and treat all non-text parts as + # attachments self._parse_inline_image(part, level=level) def _parse_inline_image(self, msg, level=0): @@ -225,13 +226,13 @@ class Email(object): html.rewrite_links(lambda x: None) cleaner = Cleaner( - scripts=True, - javascript=True, - links=True, - page_structure=True, - embedded=True, - frames=True, - add_nofollow=True) + scripts=True, + javascript=True, + links=True, + page_structure=True, + embedded=True, + frames=True, + add_nofollow=True) mail_text = lxml.html.tostring(cleaner.clean_html(html)) self.contents["html"] = smart_text(mail_text) @@ -289,18 +290,18 @@ def split_local_part(local_part, delimiter=None): # never split these special addresses pass elif ( - delimiter == "-" - and (local_part.startswith("owner-") - or local_part.endswith("-request")) + delimiter == "-" and + (local_part.startswith("owner-") or + local_part.endswith("-request")) ): # don't split owner-* or *-request if - is the delimiter, they are # special addresses used by mail lists. pass elif ( - delimiter - and delimiter in local_part - and local_part[0] != delimiter - and local_part[-1] != delimiter + delimiter and + delimiter in local_part and + local_part[0] != delimiter and + local_part[-1] != delimiter ): local_part, extension = local_part.split(delimiter, 1) @@ -341,8 +342,8 @@ def decode(value_bytes, encoding, append_to_error=""): except (TypeError, UnicodeDecodeError) as exc: six.raise_from( InternalError( - _("unable to determine encoding of string") - + append_to_error + _("unable to determine encoding of string") + + append_to_error ), exc ) diff --git a/modoboa/lib/templatetags/lib_tags.py b/modoboa/lib/templatetags/lib_tags.py index ebd09c163..c48ef2a3c 100644 --- a/modoboa/lib/templatetags/lib_tags.py +++ b/modoboa/lib/templatetags/lib_tags.py @@ -35,7 +35,7 @@ def alert(msg, typ): t = Template("""""") +""") # NOQA:E501 return t.render(Context({"type": typ, "msg": msg})) @@ -50,7 +50,7 @@ class="{{ mdclass }}{% if link.class %} {{ link.class }}{% endif %}" {% for attr, value in link.extra_attributes.items %} {{ attr }}="{{ value }}"{% endfor %} > {% if link.img %}{% endif %} -{{ link.label }}""") +{{ link.label }}""") # NOQA:E501 return t.render(Context({"link": linkdef, "mdclass": mdclass})) @@ -76,7 +76,7 @@ def render_tags(tags): {{ tag.label }} {% endfor %} -""") +""") # NOQA:E501 return t.render(Context({"tags": tags})) diff --git a/modoboa/lib/tests/test_email_utils.py b/modoboa/lib/tests/test_email_utils.py index 943036366..6b2c8bbc4 100644 --- a/modoboa/lib/tests/test_email_utils.py +++ b/modoboa/lib/tests/test_email_utils.py @@ -65,9 +65,10 @@ class EmailTests(SimpleTestCase): EmailTestImplementation("text_plain", links="0") ex_message = cm.exception.messages - self.assertEqual(ex_message, - "links == \"0\" is not valid, did you mean True or " - "False?") + self.assertEqual( + ex_message, + "links == \"0\" is not valid, did you mean True or False?" + ) def test_links_value_for_webmail(self): """modoboa-webmail sets links = 0 or 1 @@ -106,7 +107,7 @@ class EmailTests(SimpleTestCase): self._test_email("multipart", dformat="html", links=True) def test_email_multipart_without_links(self): - """display the text/html part of a multipart message with links removed""" + """display the text/html part of a multipart message without links""" self._test_email("multipart", dformat="html", links=False) diff --git a/modoboa/lib/validators.py b/modoboa/lib/validators.py index bd5e29918..69e64b914 100644 --- a/modoboa/lib/validators.py +++ b/modoboa/lib/validators.py @@ -49,7 +49,8 @@ class UTF8EmailValidator(EmailValidator): # dot-atom r"^[" + ascii_set + ul + r"]+(\.[" + ascii_set + ul + r"]+)*\Z" # quoted-string - r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"\Z)' + r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|' + r'\\[\001-\011\013\014\016-\177])*"\Z)' ) user_regex = re.compile(r"(" + user_regex_raw, re.IGNORECASE) diff --git a/modoboa/limits/tests/test_import.py b/modoboa/limits/tests/test_import.py index f70516675..184a1c878 100644 --- a/modoboa/limits/tests/test_import.py +++ b/modoboa/limits/tests/test_import.py @@ -68,7 +68,7 @@ domainalias; domalias2.com; {domain}; True self.assertTrue(limit.is_exceeded()) f = ContentFile("""account; admin3@{domain}; toto; User; One; True; DomainAdmins; admin3@{domain}; 5; {domain} -""".format(domain=self.domain), name="domain_admins.csv") +""".format(domain=self.domain), name="domain_admins.csv") # NOQA:E501 response = self.client.post( reverse("admin:identity_import"), { "sourcefile": f diff --git a/modoboa/parameters/tools.py b/modoboa/parameters/tools.py index a8271fa13..59b898b60 100644 --- a/modoboa/parameters/tools.py +++ b/modoboa/parameters/tools.py @@ -96,6 +96,7 @@ class Registry(object): raise NotDefined(app) return self._registry[level][app]["defaults"] + registry = Registry() diff --git a/modoboa/test_settings.py b/modoboa/test_settings.py index 781bc5705..3e61f31c2 100644 --- a/modoboa/test_settings.py +++ b/modoboa/test_settings.py @@ -23,7 +23,8 @@ if DB == "MYSQL": # such as data truncation upon insertion, by escalating warnings # into errors. It is strongly recommended you activate it. # MySQL >= 5.7 set STRICT_TRANS_TABLES by default - # See: https://docs.djangoproject.com/en/1.11/ref/databases/#mysql-sql-mode + # See: + # https://docs.djangoproject.com/en/1.11/ref/databases/#mysql-sql-mode "OPTIONS": { "init_command": 'SET sql_mode=\'STRICT_TRANS_TABLES\'', }, diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py index 85c35a3c2..9b5f0e166 100644 --- a/test_project/test_project/settings.py +++ b/test_project/test_project/settings.py @@ -178,16 +178,16 @@ MODOBOA_API_URL = "https://api.modoboa.org/1/" AUTH_PASSWORD_VALIDATORS = [ { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", # NOQA:E501 }, { - "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", # NOQA:E501 }, { - "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", # NOQA:E501 }, { - "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", # NOQA:E501 }, { "NAME": "modoboa.core.password_validation.ComplexityValidator",