From 7fd9b50a7f43821c6931e4f19efc37c138d77837 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 26 Jan 2017 15:23:00 -0800 Subject: tests/widgets/globals: Add test for sorting of TagWidgets --- tests/widgets/__init__.py | 0 tests/widgets/globals_test.py | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/widgets/__init__.py create mode 100644 tests/widgets/globals_test.py (limited to 'tests') diff --git a/tests/widgets/__init__.py b/tests/widgets/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/widgets/globals_test.py b/tests/widgets/globals_test.py new file mode 100644 index 00000000..4974062e --- /dev/null +++ b/tests/widgets/globals_test.py @@ -0,0 +1,40 @@ +# encoding=utf-8 +# Copyright © 2017 Dylan Baker + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Tests for the alot.widgets.globals module.""" + +from __future__ import absolute_import + +import unittest + +import mock + +from alot.widgets import globals as globals_ + + +class TestTagWidget(unittest.TestCase): + + def test_sort(self): + """Test sorting.""" + from alot.helper import tag_cmp + with mock.patch( + 'alot.widgets.globals.settings.get_tagstring_representation', + lambda t, _, __: {'translated': t, 'normal': None, + 'focussed': None}): + expected = ['a', 'z', 'aa', 'bar', 'foo'] + base = [globals_.TagWidget(x) for x in expected] + actual = list(sorted(base, cmp=tag_cmp, key=lambda x: x.translated)) + self.assertListEqual([g.translated for g in actual], expected) -- cgit v1.2.3 From bef724a5d142a1ca06476d56015a6c6bcdf89f1b Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 20 Jan 2017 16:01:25 -0800 Subject: Replace cmp with rich comparisons This is both a performance issue (since cmp is slower than rich comparisons), and a python3 issue since cmp (and __cmp__) are gone in python 3. --- alot/helper.py | 11 ----------- alot/widgets/globals.py | 28 ++++++++++++++++++++++++++++ alot/widgets/search.py | 7 ++----- alot/widgets/thread.py | 10 ++++------ tests/widgets/globals_test.py | 7 +++---- 5 files changed, 37 insertions(+), 26 deletions(-) (limited to 'tests') diff --git a/alot/helper.py b/alot/helper.py index a60c9ea7..0195a065 100644 --- a/alot/helper.py +++ b/alot/helper.py @@ -498,17 +498,6 @@ def shell_quote(text): return "'%s'" % text.replace("'", """'"'"'""") -def tag_cmp(a, b): - r''' - Sorting tags using this function puts all tags of length 1 at the - beginning. This groups all tags mapped to unicode characters. - ''' - if min(len(a), len(b)) == 1 and max(len(a), len(b)) > 1: - return cmp(len(a), len(b)) - else: - return cmp(a.lower(), b.lower()) - - def humanize_size(size): """Create a nice human readable representation of the given number (understood as bytes) using the "K" and "M" suffixes to indicate kilo- and diff --git a/alot/widgets/globals.py b/alot/widgets/globals.py index 822d0ae9..c4f7379c 100644 --- a/alot/widgets/globals.py +++ b/alot/widgets/globals.py @@ -7,6 +7,7 @@ This contains alot-specific :class:`urwid.Widget` used in more than one mode. """ from __future__ import absolute_import +import functools import re import operator import urwid @@ -271,6 +272,7 @@ class HeadersList(urwid.WidgetWrap): return headerlines +@functools.total_ordering class TagWidget(urwid.AttrMap): """ text widget that renders a tagstring. @@ -313,3 +315,29 @@ class TagWidget(urwid.AttrMap): def set_unfocussed(self): self.set_attr_map(self.attmaps['normal']) + + def __lt__(self, other): + """Groups tags of 1 character first, then alphabetically. + + This groups tags unicode characters at the begnining. + """ + if not isinstance(other, TagWidget): + return NotImplemented + + self_len = len(self.translated) + oth_len = len(other.translated) + if min(self_len, oth_len) == 1 and max(self_len, oth_len) > 1: + return self_len < oth_len + return self.translated.lower() < other.translated.lower() + + def __eq__(self, other): + if not isinstance(other, TagWidget): + return NotImplemented + if len(self.translated) != len(other.translated): + return False + return self.translated.lower() == other.translated.lower() + + def __ne__(self, other): + if not isinstance(other, TagWidget): + return NotImplemented + return self.translated.lower() != other.translated.lower() diff --git a/alot/widgets/search.py b/alot/widgets/search.py index a0f23b5e..32a078c7 100644 --- a/alot/widgets/search.py +++ b/alot/widgets/search.py @@ -10,7 +10,6 @@ import urwid from ..settings import settings from ..helper import shorten_author_string -from ..helper import tag_cmp from .utils import AttrFlipWidget from .globals import TagWidget @@ -116,10 +115,8 @@ class ThreadlineWidget(urwid.AttrMap): if self.thread: fallback_normal = struct[name]['normal'] fallback_focus = struct[name]['focus'] - tag_widgets = [TagWidget(t, fallback_normal, fallback_focus) - for t in self.thread.get_tags()] - tag_widgets.sort(tag_cmp, - lambda tag_widget: tag_widget.translated) + tag_widgets = sorted(TagWidget(t, fallback_normal, fallback_focus) + for t in self.thread.get_tags()) else: tag_widgets = [] cols = [] diff --git a/alot/widgets/thread.py b/alot/widgets/thread.py index 0568cb94..9b5f8095 100644 --- a/alot/widgets/thread.py +++ b/alot/widgets/thread.py @@ -15,7 +15,6 @@ from .globals import AttachmentWidget from ..settings import settings from ..db.utils import decode_header, X_SIGNATURE_MESSAGE_HEADER from ..db.utils import extract_body -from ..helper import tag_cmp class MessageSummaryWidget(urwid.WidgetWrap): @@ -47,12 +46,11 @@ class MessageSummaryWidget(urwid.WidgetWrap): if settings.get('msg_summary_hides_threadwide_tags'): thread_tags = message.get_thread().get_tags(intersection=True) outstanding_tags = set(message.get_tags()).difference(thread_tags) - tag_widgets = [TagWidget(t, attr, focus_att) - for t in outstanding_tags] + tag_widgets = sorted(TagWidget(t, attr, focus_att) + for t in outstanding_tags) else: - tag_widgets = [TagWidget(t, attr, focus_att) - for t in message.get_tags()] - tag_widgets.sort(tag_cmp, lambda tag_widget: tag_widget.translated) + tag_widgets = sorted(TagWidget(t, attr, focus_att) + for t in message.get_tags()) for tag_widget in tag_widgets: if not tag_widget.hidden: cols.append(('fixed', tag_widget.width(), tag_widget)) diff --git a/tests/widgets/globals_test.py b/tests/widgets/globals_test.py index 4974062e..7d7d6547 100644 --- a/tests/widgets/globals_test.py +++ b/tests/widgets/globals_test.py @@ -29,12 +29,11 @@ class TestTagWidget(unittest.TestCase): def test_sort(self): """Test sorting.""" - from alot.helper import tag_cmp with mock.patch( 'alot.widgets.globals.settings.get_tagstring_representation', lambda t, _, __: {'translated': t, 'normal': None, 'focussed': None}): expected = ['a', 'z', 'aa', 'bar', 'foo'] - base = [globals_.TagWidget(x) for x in expected] - actual = list(sorted(base, cmp=tag_cmp, key=lambda x: x.translated)) - self.assertListEqual([g.translated for g in actual], expected) + actual = [g.translated for g in + sorted(globals_.TagWidget(x) for x in expected)] + self.assertListEqual(actual, expected) -- cgit v1.2.3