From 2404bc62530c9c2715fb3b9d33a60f27b5a790ae Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:15:21 +1000 Subject: Reformat a long string in Setuptools metadata. --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 26efe9e8..538c1a0b 100755 --- a/setup.py +++ b/setup.py @@ -17,7 +17,9 @@ setup( 'Environment :: Console :: Curses', 'Framework :: Twisted', 'Intended Audience :: End Users/Desktop', - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', + ( + 'License :: OSI Approved' + ':: GNU General Public License v3 or later (GPLv3+)'), 'Operating System :: POSIX', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', -- cgit v1.2.3 From 6f36401bcaecc6583514e5530138a54f46f036c6 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:16:27 +1000 Subject: Extract a level of nested conditionals for tag command. --- alot/db/manager.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/alot/db/manager.py b/alot/db/manager.py index cbde9c88..057c72d0 100644 --- a/alot/db/manager.py +++ b/alot/db/manager.py @@ -160,15 +160,14 @@ class DBManager(object): for msg in query.search_messages(): msg.freeze() if cmd == 'tag': - for tag in tags: - msg.add_tag(tag, sync_maildir_flags=sync) + strategy = msg.add_tag if cmd == 'set': msg.remove_all_tags() - for tag in tags: - msg.add_tag(tag, sync_maildir_flags=sync) + strategy = msg.add_tag elif cmd == 'untag': - for tag in tags: - msg.remove_tag(tag, sync_maildir_flags=sync) + strategy = msg.remove_tag + for tag in tags: + strategy(tag, sync_maildir_flags=sync) msg.thaw() logging.debug('ended atomic') -- cgit v1.2.3 From ec78184ffaa9c5aee56f98680810efcda082e263 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:20:35 +1000 Subject: Correct over-long comment lines in documentation code. --- docs/source/api/conf.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/source/api/conf.py b/docs/source/api/conf.py index 54b31e07..c1673859 100644 --- a/docs/source/api/conf.py +++ b/docs/source/api/conf.py @@ -3,7 +3,8 @@ # alot documentation build configuration file, created by # sphinx-quickstart on Tue Aug 9 15:00:51 2011. # -# This file is execfile()d with the current directory set to its containing dir. +# This file is execfile()d with the current directory set to its +# containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. @@ -55,8 +56,9 @@ from alot import __version__,__author__ # If your documentation needs a minimal Sphinx version, state it here. #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. +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx'] # Add any paths that contain templates here, relative to this directory. @@ -98,7 +100,8 @@ release = __version__ # 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. +# The reST default role (used for this markup: `text`) to use for all +# documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. @@ -208,7 +211,8 @@ htmlhelp_basename = 'alotdoc' #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). +# (source start file, target name, title, author, documentclass +# [howto/manual]). latex_documents = [ ('index', 'alot.tex', u'alot Documentation', u'Patrick Totzke', 'manual'), -- cgit v1.2.3 From 2b766949a7f2dd6025c9af3290d01f531130ed2d Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:21:02 +1000 Subject: Reformat a long statement in documentation code. --- docs/source/generate_commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/generate_commands.py b/docs/source/generate_commands.py index 4ead8c11..5eda4978 100755 --- a/docs/source/generate_commands.py +++ b/docs/source/generate_commands.py @@ -65,8 +65,8 @@ def rstify_parser(parser): for index, a in enumerate(parser._positionals._group_actions): out += " %s: %s" % (index, a.help) if a.choices: - out += ". valid choices are: %s." % ','.join(['\`%s\`' % s for s - in a.choices]) + out += ". valid choices are: %s." % ','.join( + ['\`%s\`' % s for s in a.choices]) if a.default: out += ". defaults to: '%s'." % a.default out += '\n' -- cgit v1.2.3 From d01d2e51da45dd87f0abf98b8a856f3b3de69153 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:22:09 +1000 Subject: Extract some context managers for patch objects. This allows writing less-nested statements. --- tests/commands/envelope_test.py | 12 ++++--- tests/commands/global_test.py | 77 +++++++++++++++++++++++++---------------- 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/tests/commands/envelope_test.py b/tests/commands/envelope_test.py index ee1c0acc..30e21c03 100644 --- a/tests/commands/envelope_test.py +++ b/tests/commands/envelope_test.py @@ -230,8 +230,10 @@ class TestSignCommand(unittest.TestCase): """ env, ui = self._make_ui_mock() - with mock.patch('alot.commands.envelope.settings.get_account_by_address', - mock.Mock(return_value=mock.Mock(gpg_key=None))): + func_patcher = mock.patch( + 'alot.commands.envelope.settings.get_account_by_address', + mock.Mock(return_value=mock.Mock(gpg_key=None))) + with func_patcher: cmd = envelope.SignCommand(action='sign', keyid=None) cmd.apply(ui) @@ -245,8 +247,10 @@ class TestSignCommand(unittest.TestCase): """ env, ui = self._make_ui_mock() - with mock.patch('alot.commands.envelope.settings.get_account_by_address', - mock.Mock(return_value=mock.Mock(gpg_key='sentinel'))): + func_patcher = mock.patch( + 'alot.commands.envelope.settings.get_account_by_address', + mock.Mock(return_value=mock.Mock(gpg_key='sentinel'))) + with func_patcher: cmd = envelope.SignCommand(action='sign', keyid=None) cmd.apply(ui) diff --git a/tests/commands/global_test.py b/tests/commands/global_test.py index e3d91f8a..102d75c2 100644 --- a/tests/commands/global_test.py +++ b/tests/commands/global_test.py @@ -17,6 +17,8 @@ """Tests for global commands.""" from __future__ import absolute_import + +import contextlib import os import tempfile @@ -63,16 +65,21 @@ class TestComposeCommand(unittest.TestCase): # This whole mess is required becasue ComposeCommand.apply is waaaaay # too complicated, it needs to be split into more manageable segments. - with mock.patch('alot.commands.globals.settings.get_account_by_address', - mock.Mock(return_value=account)): - with mock.patch('alot.commands.globals.settings.get_accounts', - mock.Mock(return_value=[account])): - with mock.patch('alot.commands.globals.settings.get_addressbooks', - mock.Mock(side_effect=Stop)): - try: - yield cmd.apply(mock.Mock()) - except Stop: - pass + func_patcher_get_account_by_address = mock.patch( + 'alot.commands.globals.settings.get_account_by_address', + mock.Mock(return_value=account)) + func_patcher_get_accounts = mock.patch( + 'alot.commands.globals.settings.get_accounts', + mock.Mock(return_value=[account])) + func_patcher_get_addressbooks = mock.patch( + 'alot.commands.globals.settings.get_addressbooks', + mock.Mock(side_effect=Stop)) + with contextlib.ExitStack() as stack: + stack.enter_context(func_patcher_get_account_by_address) + stack.enter_context(func_patcher_get_accounts) + stack.enter_context(func_patcher_get_addressbooks) + with self.assertRaises(Stop): + yield cmd.apply(mock.Mock()) self.assertTrue(envelope.sign) self.assertIs(envelope.sign_key, mock.sentinel.gpg_key) @@ -85,16 +92,21 @@ class TestComposeCommand(unittest.TestCase): # This whole mess is required becasue ComposeCommand.apply is waaaaay # too complicated, it needs to be split into more manageable segments. - with mock.patch('alot.commands.globals.settings.get_account_by_address', - mock.Mock(return_value=account)): - with mock.patch('alot.commands.globals.settings.get_accounts', - mock.Mock(return_value=[account])): - with mock.patch('alot.commands.globals.settings.get_addressbooks', - mock.Mock(side_effect=Stop)): - try: - yield cmd.apply(mock.Mock()) - except Stop: - pass + func_patcher_get_account_by_address = mock.patch( + 'alot.commands.globals.settings.get_account_by_address', + mock.Mock(return_value=account)) + func_patcher_get_accounts = mock.patch( + 'alot.commands.globals.settings.get_accounts', + mock.Mock(return_value=[account])) + func_patcher_get_addressbooks = mock.patch( + 'alot.commands.globals.settings.get_addressbooks', + mock.Mock(side_effect=Stop)) + with contextlib.ExitStack() as stack: + stack.enter_context(func_patcher_get_account_by_address) + stack.enter_context(func_patcher_get_accounts) + stack.enter_context(func_patcher_get_addressbooks) + with self.assertRaises(Stop): + yield cmd.apply(mock.Mock()) self.assertFalse(envelope.sign) self.assertIs(envelope.sign_key, None) @@ -107,16 +119,21 @@ class TestComposeCommand(unittest.TestCase): # This whole mess is required becasue ComposeCommand.apply is waaaaay # too complicated, it needs to be split into more manageable segments. - with mock.patch('alot.commands.globals.settings.get_account_by_address', - mock.Mock(return_value=account)): - with mock.patch('alot.commands.globals.settings.get_accounts', - mock.Mock(return_value=[account])): - with mock.patch('alot.commands.globals.settings.get_addressbooks', - mock.Mock(side_effect=Stop)): - try: - yield cmd.apply(mock.Mock()) - except Stop: - pass + func_patcher_get_account_by_address = mock.patch( + 'alot.commands.globals.settings.get_account_by_address', + mock.Mock(return_value=account)) + func_patcher_get_accounts = mock.patch( + 'alot.commands.globals.settings.get_accounts', + mock.Mock(return_value=[account])) + func_patcher_get_addressbooks = mock.patch( + 'alot.commands.globals.settings.get_addressbooks', + mock.Mock(side_effect=Stop)) + with contextlib.ExitStack() as stack: + stack.enter_context(func_patcher_get_account_by_address) + stack.enter_context(func_patcher_get_accounts) + stack.enter_context(func_patcher_get_addressbooks) + with self.assertRaises(Stop): + yield cmd.apply(mock.Mock()) self.assertFalse(envelope.sign) self.assertIs(envelope.sign_key, None) -- cgit v1.2.3 From c7770fc391100be63e2101305473796569b6a3ec Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:24:50 +1000 Subject: Rename some test functions to have shorter names. --- tests/commands/thread_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/commands/thread_test.py b/tests/commands/thread_test.py index 6897a953..81328410 100644 --- a/tests/commands/thread_test.py +++ b/tests/commands/thread_test.py @@ -163,7 +163,7 @@ class TestDetermineSender(unittest.TestCase): expected = (u'to@example.com', account2) self._test(accounts=[account1, account2, account3], expected=expected) - def test_force_realname_includes_real_name_in_returned_address_if_defined(self): + def test_force_realname_has_real_name_in_returned_address_if_defined(self): account1 = _AccountTestClass(address=u'foo@example.com') account2 = _AccountTestClass(address=u'to@example.com', realname='Bar') account3 = _AccountTestClass(address=u'baz@example.com') @@ -179,7 +179,7 @@ class TestDetermineSender(unittest.TestCase): self._test(accounts=[account1, account2, account3], expected=expected, force_realname=True) - def test_with_force_address_main_address_is_used_regardless_of_matching_address(self): + def test_with_force_address_main_address_is_always_used(self): # In python 3.4 this and the next test could be written as subtests. account1 = _AccountTestClass(address=u'foo@example.com') account2 = _AccountTestClass(address=u'bar@example.com', -- cgit v1.2.3 From 0abc64f78e3c5f9ad3faf9a3b6339ccd6b15de71 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:25:46 +1000 Subject: Re-format an over-long comment. --- extra/colour_picker.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extra/colour_picker.py b/extra/colour_picker.py index 8c28a2ee..2174d997 100755 --- a/extra/colour_picker.py +++ b/extra/colour_picker.py @@ -1,8 +1,9 @@ #!/usr/bin/python # # COLOUR PICKER. -# This is a lightly modified version of urwids palette_test.py example script as -# found at https://raw.github.com/wardi/urwid/master/examples/palette_test.py +# This is a lightly modified version of urwids palette_test.py example +# script as found at +# https://raw.github.com/wardi/urwid/master/examples/palette_test.py # # This version simply omits resetting the screens default colour palette, # and therefore displays the colour attributes as alot would render them in -- cgit v1.2.3 From 2441a4d7b3576eb3a1c519713974418638ab82ba Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:28:43 +1000 Subject: Refactor some long statements to allow shorter lines. --- tests/db/utils_test.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/db/utils_test.py b/tests/db/utils_test.py index b1187fe3..9013f5ce 100644 --- a/tests/db/utils_test.py +++ b/tests/db/utils_test.py @@ -263,7 +263,9 @@ class TestDecodeHeader(unittest.TestCase): """ string = unicode_string.encode(encoding) b64 = base64.encodebytes(string).strip() - return (b'=?' + encoding.encode('utf-8') + b'?B?' + b64 + b'?=').decode('ascii') + result_bytes = b'=?' + encoding.encode('utf-8') + b'?B?' + b64 + b'?=' + result = result_bytes.decode('ascii') + return result def _test(self, teststring, expected): @@ -317,7 +319,11 @@ class TestDecodeHeader(unittest.TestCase): ' again: ' + self._quote(part, 'utf-8') + \ ' latin1: ' + self._base64(part, 'iso-8859-1') + \ ' and ' + self._quote(part, 'iso-8859-1') - expected = u'utf-8: ÄÖÜäöü again: ÄÖÜäöü latin1: ÄÖÜäöü and ÄÖÜäöü' + expected = u' '.join([ + u'utf-8: ÄÖÜäöü', + u'again: ÄÖÜäöü', + u'latin1: ÄÖÜäöü and ÄÖÜäöü', + ]) self._test(text, expected) def test_tabs_are_expanded_to_align_with_eigth_spaces(self): -- cgit v1.2.3 From 950839f390dbdcd285ceae86b7ddeb4ce62a50d4 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:29:34 +1000 Subject: Raise an exception with a meaningful message. The `assert` statement is not always executed (it can be optimised away) so is not a suitable run-time check. Also, an exception allows for a better error message. --- alot/helper.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/alot/helper.py b/alot/helper.py index 4d8d782e..e621f751 100644 --- a/alot/helper.py +++ b/alot/helper.py @@ -640,7 +640,9 @@ def email_as_bytes(mail): # If we get here and the assert triggers it means that different # parts of the email are encoded differently. I don't think we're # likely to see that, but it's possible - assert {'utf-8', 'ascii', 'us-ascii'}.issuperset(charsets), charsets + if not {'utf-8', 'ascii', 'us-ascii'}.issuperset(charsets): + raise RuntimeError( + "different encodings detected: {}".format(charsets)) charset = 'utf-8' # It's a strict super-set else: charset = 'utf-8' -- cgit v1.2.3 From 018279b18e7c95b40d94a09fc68fa3b3aa1fc6b0 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:30:28 +1000 Subject: Wrap long statements on open-bracket syntax. --- alot/account.py | 8 +++++--- alot/commands/globals.py | 21 ++++++++++++--------- alot/commands/thread.py | 13 ++++++++++--- alot/crypto.py | 5 +++-- alot/db/envelope.py | 14 ++++++++------ alot/db/utils.py | 3 ++- alot/ui.py | 11 ++++++----- tests/commands/global_test.py | 20 +++++++++++++------- tests/commands/utils_tests.py | 6 ++++-- tests/completion_test.py | 6 ++++-- tests/crypto_test.py | 24 ++++++++++++++++-------- tests/db/utils_test.py | 24 ++++++++++++++++-------- 12 files changed, 99 insertions(+), 56 deletions(-) diff --git a/alot/account.py b/alot/account.py index 461d2bbf..fe304ac6 100644 --- a/alot/account.py +++ b/alot/account.py @@ -213,9 +213,11 @@ class Account(object): replied_tags = replied_tags or [] passed_tags = passed_tags or [] - self.address = Address.from_string(address, case_sensitive=case_sensitive_username) - self.aliases = [Address.from_string(a, case_sensitive=case_sensitive_username) - for a in (aliases or [])] + self.address = Address.from_string( + address, case_sensitive=case_sensitive_username) + self.aliases = [ + Address.from_string(a, case_sensitive=case_sensitive_username) + for a in (aliases or [])] self.alias_regexp = alias_regexp self.realname = realname self.encrypt_to_self = encrypt_to_self diff --git a/alot/commands/globals.py b/alot/commands/globals.py index d335e8cf..4e272b8e 100644 --- a/alot/commands/globals.py +++ b/alot/commands/globals.py @@ -271,9 +271,10 @@ class ExternalCommand(Command): def thread_code(*_): try: - proc = subprocess.Popen(self.cmdlist, shell=self.shell, - stdin=subprocess.PIPE if stdin else None, - stderr=subprocess.PIPE) + proc = subprocess.Popen( + self.cmdlist, shell=self.shell, + stdin=subprocess.PIPE if stdin else None, + stderr=subprocess.PIPE) except OSError as e: return str(e) @@ -623,8 +624,8 @@ class HelpCommand(Command): globalmaps, modemaps = settings.get_keybindings(ui.mode) # build table - maxkeylength = len(max(list(modemaps.keys()) + list(globalmaps.keys()), - key=len)) + maxkeylength = len( + max(list(modemaps.keys()) + list(globalmaps.keys()), key=len)) keycolumnwidth = maxkeylength + 2 linewidgets = [] @@ -689,10 +690,12 @@ class HelpCommand(Command): class ComposeCommand(Command): """compose a new email""" - def __init__(self, envelope=None, headers=None, template=None, sender=u'', - tags=None, subject=u'', to=None, cc=None, bcc=None, attach=None, - omit_signature=False, spawn=None, rest=None, encrypt=False, - **kwargs): + def __init__( + self, + envelope=None, headers=None, template=None, sender=u'', + tags=None, subject=u'', to=None, cc=None, bcc=None, attach=None, + omit_signature=False, spawn=None, rest=None, encrypt=False, + **kwargs): """ :param envelope: use existing envelope :type envelope: :class:`~alot.db.envelope.Envelope` diff --git a/alot/commands/thread.py b/alot/commands/thread.py index a6380ac9..6a631e62 100644 --- a/alot/commands/thread.py +++ b/alot/commands/thread.py @@ -72,13 +72,16 @@ def determine_sender(mail, action='reply'): # pick the most important account that has an address in candidates # and use that accounts realname and the address found here for account in my_accounts: - acc_addresses = [re.escape(str(a)) for a in account.get_addresses()] + acc_addresses = [ + re.escape(str(a)) for a in account.get_addresses()] if account.alias_regexp is not None: acc_addresses.append(account.alias_regexp) for alias in acc_addresses: regex = re.compile( u'^' + str(alias) + u'$', - flags=re.IGNORECASE if not account.address.case_sensitive else 0) + flags=( + re.IGNORECASE if not account.address.case_sensitive + else 0)) for seen_name, seen_address in candidate_addresses: if regex.match(seen_address): logging.debug("match!: '%s' '%s'", seen_address, alias) @@ -241,7 +244,11 @@ class ReplyCommand(Command): # Reply-To is standart reply target RFC 2822:, RFC 1036: 2.2.1 # X-BeenThere is needed by sourceforge ML also winehq # X-Mailing-List is also standart and is used by git-send-mail - to = mail['Reply-To'] or mail['X-BeenThere'] or mail['X-Mailing-List'] + to = ( + mail['Reply-To'] + or mail['X-BeenThere'] + or mail['X-Mailing-List'] + ) # Some mail server (gmail) will not resend you own mail, so you # have to deal with the one in sent if to is None: diff --git a/alot/crypto.py b/alot/crypto.py index 247dbd19..e7e0bd36 100644 --- a/alot/crypto.py +++ b/alot/crypto.py @@ -112,8 +112,9 @@ def get_key(keyid, validate=False, encrypt=False, sign=False, else: raise e # pragma: nocover if signed_only and not check_uid_validity(key, keyid): - raise GPGProblem('Cannot find a trusworthy key for "{}".'.format(keyid), - code=GPGCode.NOT_FOUND) + raise GPGProblem( + 'Cannot find a trusworthy key for "{}".'.format(keyid), + code=GPGCode.NOT_FOUND) return key diff --git a/alot/db/envelope.py b/alot/db/envelope.py index b742ba81..89a99ffa 100644 --- a/alot/db/envelope.py +++ b/alot/db/envelope.py @@ -223,9 +223,10 @@ class Envelope(object): # wrap signature in MIMEcontainter stype = 'pgp-signature; name="signature.asc"' - signature_mime = MIMEApplication(_data=signature_str.decode('ascii'), - _subtype=stype, - _encoder=encode_7or8bit) + signature_mime = MIMEApplication( + _data=signature_str.decode('ascii'), + _subtype=stype, + _encoder=encode_7or8bit) signature_mime['Content-Description'] = 'signature' signature_mime.set_charset('us-ascii') @@ -255,9 +256,10 @@ class Envelope(object): _encoder=encode_7or8bit) encryption_mime.set_charset('us-ascii') - encrypted_mime = MIMEApplication(_data=encrypted_str.decode('ascii'), - _subtype='octet-stream', - _encoder=encode_7or8bit) + encrypted_mime = MIMEApplication( + _data=encrypted_str.decode('ascii'), + _subtype='octet-stream', + _encoder=encode_7or8bit) encrypted_mime.set_charset('us-ascii') outer_msg.attach(encryption_mime) outer_msg.attach(encrypted_mime) diff --git a/alot/db/utils.py b/alot/db/utils.py index ba32b832..3ed88c74 100644 --- a/alot/db/utils.py +++ b/alot/db/utils.py @@ -364,7 +364,8 @@ def extract_body(mail, types=None, field_key='copiousoutput'): elif cte == 'base64': raw_payload = base64.b64decode(payload) else: - raise Exception('Unknown Content-Transfer-Encoding {}'.format(cte)) + raise Exception( + 'Unknown Content-Transfer-Encoding {}'.format(cte)) # message.get_payload(decode=True) also handles a number of unicode # encodindigs. maybe those are useful? payload = raw_payload.decode(enc) diff --git a/alot/ui.py b/alot/ui.py index deec3ab1..b3430e07 100644 --- a/alot/ui.py +++ b/alot/ui.py @@ -103,11 +103,12 @@ class UI(object): self._recipients_hist_file, size=size) # set up main loop - self.mainloop = urwid.MainLoop(self.root_widget, - handle_mouse=settings.get('handle_mouse'), - event_loop=urwid.TwistedEventLoop(), - unhandled_input=self._unhandled_input, - input_filter=self._input_filter) + self.mainloop = urwid.MainLoop( + self.root_widget, + handle_mouse=settings.get('handle_mouse'), + event_loop=urwid.TwistedEventLoop(), + unhandled_input=self._unhandled_input, + input_filter=self._input_filter) # Create a defered that calls the loop_hook loop_hook = settings.get_hook('loop_hook') diff --git a/tests/commands/global_test.py b/tests/commands/global_test.py index 102d75c2..59943e5e 100644 --- a/tests/commands/global_test.py +++ b/tests/commands/global_test.py @@ -50,7 +50,8 @@ class TestComposeCommand(unittest.TestCase): return envelope @staticmethod - def _make_account_mock(sign_by_default=True, gpg_key=mock.sentinel.gpg_key): + def _make_account_mock( + sign_by_default=True, gpg_key=mock.sentinel.gpg_key): account = mock.Mock() account.sign_by_default = sign_by_default account.gpg_key = gpg_key @@ -153,8 +154,9 @@ class TestComposeCommand(unittest.TestCase): cmd = g_commands.ComposeCommand(template=f.name) # Crutch to exit the giant `apply` method early. - with mock.patch('alot.commands.globals.settings.get_account_by_address', - mock.Mock(side_effect=Stop)): + with mock.patch( + 'alot.commands.globals.settings.get_account_by_address', + mock.Mock(side_effect=Stop)): try: yield cmd.apply(mock.Mock()) except Stop: @@ -189,7 +191,8 @@ class TestExternalCommand(unittest.TestCase): def test_no_spawn_stdin_attached(self): ui = utilities.make_ui() - cmd = g_commands.ExternalCommand(u"test -t 0", stdin=u'0', refocus=False) + cmd = g_commands.ExternalCommand( + u"test -t 0", stdin=u'0', refocus=False) cmd.apply(ui) ui.notify.assert_called_once_with('', priority='error') @@ -199,7 +202,8 @@ class TestExternalCommand(unittest.TestCase): cmd.apply(ui) ui.notify.assert_called_once_with('', priority='error') - @mock.patch('alot.commands.globals.settings.get', mock.Mock(return_value='')) + @mock.patch( + 'alot.commands.globals.settings.get', mock.Mock(return_value='')) @mock.patch.dict(os.environ, {'DISPLAY': ':0'}) def test_spawn_no_stdin_success(self): ui = utilities.make_ui() @@ -207,7 +211,8 @@ class TestExternalCommand(unittest.TestCase): cmd.apply(ui) ui.notify.assert_not_called() - @mock.patch('alot.commands.globals.settings.get', mock.Mock(return_value='')) + @mock.patch( + 'alot.commands.globals.settings.get', mock.Mock(return_value='')) @mock.patch.dict(os.environ, {'DISPLAY': ':0'}) def test_spawn_stdin_success(self): ui = utilities.make_ui() @@ -217,7 +222,8 @@ class TestExternalCommand(unittest.TestCase): cmd.apply(ui) ui.notify.assert_not_called() - @mock.patch('alot.commands.globals.settings.get', mock.Mock(return_value='')) + @mock.patch( + 'alot.commands.globals.settings.get', mock.Mock(return_value='')) @mock.patch.dict(os.environ, {'DISPLAY': ':0'}) def test_spawn_failure(self): ui = utilities.make_ui() diff --git a/tests/commands/utils_tests.py b/tests/commands/utils_tests.py index 487d0d3b..c17473dc 100644 --- a/tests/commands/utils_tests.py +++ b/tests/commands/utils_tests.py @@ -57,7 +57,8 @@ def setUpModule(): with gpg.core.Context(armor=True) as ctx: # Add the public and private keys. They have no password - search_dir = os.path.join(os.path.dirname(__file__), '../static/gpg-keys') + search_dir = os.path.join( + os.path.dirname(__file__), '../static/gpg-keys') for each in os.listdir(search_dir): if os.path.splitext(each)[1] == '.gpg': with open(os.path.join(search_dir, each)) as f: @@ -106,7 +107,8 @@ class TestGetKeys(unittest.TestCase): @inlineCallbacks def test_get_keys_ambiguous(self): """Test gettings keys when when the key is ambiguous.""" - key = crypto.get_key(FPR, validate=True, encrypt=True, signed_only=False) + key = crypto.get_key( + FPR, validate=True, encrypt=True, signed_only=False) ui = utilities.make_ui() # Creat a ui.choice object that can satisfy twisted, but can also be diff --git a/tests/completion_test.py b/tests/completion_test.py index 5b335779..15a80a89 100644 --- a/tests/completion_test.py +++ b/tests/completion_test.py @@ -57,7 +57,8 @@ class AbooksCompleterTest(unittest.TestCase): self.assertTupleEqual(actual[0], expected[0]) def test_empty_real_name_returns_plain_email_address(self): - actual = self.__class__.example_abook_completer.complete("real-name", 9) + actual = self.__class__.example_abook_completer.complete( + "real-name", 9) expected = [("no-real-name@example.com", 24)] self._assert_only_one_list_entry(actual, expected) @@ -79,7 +80,8 @@ class AbooksCompleterTest(unittest.TestCase): def test_real_name_double_quotes(self): actual = self.__class__.example_abook_completer.complete("dquote", 6) expected = [("", 0)] - expected = [(r""""double \"quote\" person" """, 46)] + expected = [ + (r""""double \"quote\" person" """, 46)] self._assert_only_one_list_entry(actual, expected) def test_real_name_with_quotes_and_comma(self): diff --git a/tests/crypto_test.py b/tests/crypto_test.py index 25cce8ba..c3db1055 100644 --- a/tests/crypto_test.py +++ b/tests/crypto_test.py @@ -59,7 +59,8 @@ def tearDownModule(): lookfor = 'gpg-agent --homedir {}'.format(os.environ['GNUPGHOME']) out = subprocess.check_output( - ['ps', 'xo', 'pid,cmd'], stderr=DEVNULL).decode(urwid.util.detected_encoding) + ['ps', 'xo', 'pid,cmd'], + stderr=DEVNULL).decode(urwid.util.detected_encoding) for each in out.strip().split('\n'): pid, cmd = each.strip().split(' ', 1) if cmd.startswith(lookfor): @@ -113,7 +114,8 @@ class TestDetachedSignatureFor(unittest.TestCase): def test_valid_signature_generated(self): to_sign = b"this is some text.\nit is more than nothing.\n" with gpg.core.Context() as ctx: - _, detached = crypto.detached_signature_for(to_sign, [ctx.get_key(FPR)]) + _, detached = crypto.detached_signature_for( + to_sign, [ctx.get_key(FPR)]) with tempfile.NamedTemporaryFile(delete=False) as f: f.write(detached) @@ -135,7 +137,8 @@ class TestVerifyDetached(unittest.TestCase): def test_verify_signature_good(self): to_sign = b"this is some text.\nIt's something\n." with gpg.core.Context() as ctx: - _, detached = crypto.detached_signature_for(to_sign, [ctx.get_key(FPR)]) + _, detached = crypto.detached_signature_for( + to_sign, [ctx.get_key(FPR)]) try: crypto.verify_detached(to_sign, detached) @@ -146,7 +149,8 @@ class TestVerifyDetached(unittest.TestCase): to_sign = b"this is some text.\nIt's something\n." similar = b"this is some text.\r\n.It's something\r\n." with gpg.core.Context() as ctx: - _, detached = crypto.detached_signature_for(to_sign, [ctx.get_key(FPR)]) + _, detached = crypto.detached_signature_for( + to_sign, [ctx.get_key(FPR)]) with self.assertRaises(GPGProblem): crypto.verify_detached(similar, detached) @@ -180,7 +184,8 @@ class TestValidateKey(unittest.TestCase): def test_encrypt(self): with self.assertRaises(GPGProblem) as caught: - crypto.validate_key(utilities.make_key(can_encrypt=False), encrypt=True) + crypto.validate_key( + utilities.make_key(can_encrypt=False), encrypt=True) self.assertEqual(caught.exception.code, GPGCode.KEY_CANNOT_ENCRYPT) @@ -286,7 +291,8 @@ class TestGetKey(unittest.TestCase): # once. with gpg.core.Context() as ctx: expected = ctx.get_key(FPR).uids[0].uid - actual = crypto.get_key(FPR, validate=True, encrypt=True, sign=True).uids[0].uid + actual = crypto.get_key( + FPR, validate=True, encrypt=True, sign=True).uids[0].uid self.assertEqual(expected, actual) def test_missing_key(self): @@ -306,7 +312,8 @@ class TestGetKey(unittest.TestCase): except GPGProblem as e: raise AssertionError(e) - @mock.patch('alot.crypto.check_uid_validity', mock.Mock(return_value=False)) + @mock.patch( + 'alot.crypto.check_uid_validity', mock.Mock(return_value=False)) def test_signed_only_false(self): with self.assertRaises(GPGProblem) as e: crypto.get_key(FPR, signed_only=True) @@ -370,7 +377,8 @@ class TestEncrypt(unittest.TestCase): enc_file = f.name self.addCleanup(os.unlink, enc_file) - dec = subprocess.check_output(['gpg', '--decrypt', enc_file], stderr=DEVNULL) + dec = subprocess.check_output( + ['gpg', '--decrypt', enc_file], stderr=DEVNULL) self.assertEqual(to_encrypt, dec) diff --git a/tests/db/utils_test.py b/tests/db/utils_test.py index 9013f5ce..25c3641d 100644 --- a/tests/db/utils_test.py +++ b/tests/db/utils_test.py @@ -385,7 +385,8 @@ class TestAddSignatureHeaders(unittest.TestCase): self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'True'), mail.headers) self.assertIn( - (utils.X_SIGNATURE_MESSAGE_HEADER, u'Untrusted: mocked'), mail.headers) + (utils.X_SIGNATURE_MESSAGE_HEADER, u'Untrusted: mocked'), + mail.headers) def test_unicode_as_bytes(self): mail = self.FakeMail() @@ -395,7 +396,8 @@ class TestAddSignatureHeaders(unittest.TestCase): self.assertIn((utils.X_SIGNATURE_VALID_HEADER, u'True'), mail.headers) self.assertIn( - (utils.X_SIGNATURE_MESSAGE_HEADER, u'Valid: Andreá'), mail.headers) + (utils.X_SIGNATURE_MESSAGE_HEADER, u'Valid: Andreá'), + mail.headers) def test_error_message_unicode(self): mail = self.check(mock.Mock(), mock.Mock(), u'error message') @@ -433,7 +435,8 @@ class TestMessageFromFile(TestCaseClassCleanup): with open(os.path.join(search_dir, each)) as f: ctx.op_import(f) - cls.keys = [ctx.get_key("DD19862809A7573A74058FF255937AFBB156245D")] + cls.keys = [ + ctx.get_key("DD19862809A7573A74058FF255937AFBB156245D")] def test_erase_alot_header_signature_valid(self): """Alot uses special headers for passing certain kinds of information, @@ -490,7 +493,8 @@ class TestMessageFromFile(TestCaseClassCleanup): m = self._make_signed() m = utils.message_from_file(io.StringIO(m.as_string())) # Don't test for valid/invalid since that might change - self.assertIn('ambig ', m[utils.X_SIGNATURE_MESSAGE_HEADER]) + self.assertIn( + 'ambig ', m[utils.X_SIGNATURE_MESSAGE_HEADER]) def test_signed_wrong_mimetype_second_payload(self): m = self._make_signed() @@ -601,7 +605,8 @@ class TestMessageFromFile(TestCaseClassCleanup): m = self._make_encrypted(True) m = utils.message_from_file(io.StringIO(m.as_string())) self.assertIn(utils.X_SIGNATURE_MESSAGE_HEADER, m) - self.assertIn('ambig ', m[utils.X_SIGNATURE_MESSAGE_HEADER]) + self.assertIn( + 'ambig ', m[utils.X_SIGNATURE_MESSAGE_HEADER]) # TODO: tests for the RFC 2440 style combined signed/encrypted blob @@ -728,7 +733,8 @@ class TestExtractBody(unittest.TestCase): @mock.patch('alot.db.utils.settings.mailcap_find_match', mock.Mock(return_value=(None, {'view': 'cat'}))) def test_prefer_html(self): - expected = 'This is an html email' + expected = ( + 'This is an html email') mail = self._make_mixed_plain_html() actual = utils.extract_body(mail) @@ -755,7 +761,8 @@ class TestExtractBody(unittest.TestCase): 'This is an html email', 'html')) actual = utils.extract_body(mail) - expected = 'This is an html email' + expected = ( + 'This is an html email') self.assertEqual(actual, expected) @@ -768,7 +775,8 @@ class TestExtractBody(unittest.TestCase): 'This is an html email', 'html')) actual = utils.extract_body(mail) - expected = 'This is an html email' + expected = ( + 'This is an html email') self.assertEqual(actual, expected) -- cgit v1.2.3 From 1708fd59ed2a44bd543d510a4895aa95e30c9af3 Mon Sep 17 00:00:00 2001 From: Ben Finney Date: Mon, 23 Apr 2018 16:37:22 +1000 Subject: Extract a level of nested control flow. --- alot/commands/thread.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/alot/commands/thread.py b/alot/commands/thread.py index 6a631e62..5d8a7939 100644 --- a/alot/commands/thread.py +++ b/alot/commands/thread.py @@ -83,22 +83,23 @@ def determine_sender(mail, action='reply'): re.IGNORECASE if not account.address.case_sensitive else 0)) for seen_name, seen_address in candidate_addresses: - if regex.match(seen_address): - logging.debug("match!: '%s' '%s'", seen_address, alias) - if settings.get(action + '_force_realname'): - realname = account.realname - else: - realname = seen_name - if settings.get(action + '_force_address'): - address = account.address - else: - address = seen_address - - logging.debug('using realname: "%s"', realname) - logging.debug('using address: %s', address) - - from_value = formataddr((realname, str(address))) - return from_value, account + if not regex.match(seen_address): + continue + logging.debug("match!: '%s' '%s'", seen_address, alias) + if settings.get(action + '_force_realname'): + realname = account.realname + else: + realname = seen_name + if settings.get(action + '_force_address'): + address = account.address + else: + address = seen_address + + logging.debug('using realname: "%s"', realname) + logging.debug('using address: %s', address) + + from_value = formataddr((realname, str(address))) + return from_value, account # revert to default account if nothing found account = my_accounts[0] -- cgit v1.2.3