mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
whitespace fixes
This commit is contained in:
+44
-44
@@ -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
|
||||
# "<project> v<release> 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 <link> 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 = {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -12,9 +12,6 @@ from ..models import Alias, AliasRecipient, Domain
|
||||
"""Admin test cases."""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class AliasTestCase(ModoTestCase):
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -19,4 +19,5 @@ class StupidExtension1(extensions.ModoExtension):
|
||||
def load_initial_data(self):
|
||||
raise RuntimeError
|
||||
|
||||
|
||||
extensions.exts_pool.register_extension(StupidExtension1)
|
||||
|
||||
@@ -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
|
||||
|
||||
+18
-17
@@ -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
|
||||
)
|
||||
|
||||
@@ -35,7 +35,7 @@ def alert(msg, typ):
|
||||
t = Template("""<div class="alert alert-{{ type }}" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
{{ msg }}
|
||||
</div>""")
|
||||
</div>""") # 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 %}<i class="{{ link.img }}"></i>{% endif %}
|
||||
{{ link.label }}</a>""")
|
||||
{{ link.label }}</a>""") # NOQA:E501
|
||||
return t.render(Context({"link": linkdef, "mdclass": mdclass}))
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ def render_tags(tags):
|
||||
<a href="#" class="filter {{ tag.type }}" name="{{ tag.name }}">{{ tag.label }}</a>
|
||||
</span>
|
||||
{% endfor %}
|
||||
""")
|
||||
""") # NOQA:E501
|
||||
return t.render(Context({"tags": tags}))
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -96,6 +96,7 @@ class Registry(object):
|
||||
raise NotDefined(app)
|
||||
return self._registry[level][app]["defaults"]
|
||||
|
||||
|
||||
registry = Registry()
|
||||
|
||||
|
||||
|
||||
@@ -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\'',
|
||||
},
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user