Browse Source

#702: build fixed again

Rafał Pitoń 8 years ago
parent
commit
f3c87d5be0

+ 2 - 3
misago/categories/serializers.py

@@ -104,11 +104,10 @@ class CategorySerializer(serializers.ModelSerializer, MutableFields):
     def get_last_poster_url(self, obj):
         if obj.last_poster_id:
             return reverse(
-                'misago:user',
-                kwargs={
+                'misago:user', kwargs={
                     'slug': obj.last_poster_slug,
                     'pk': obj.last_poster_id,
-                },
+                }
             )
         else:
             return None

+ 3 - 1
misago/categories/signals.py

@@ -7,9 +7,11 @@ from .models import Category
 
 delete_category_content = Signal()
 move_category_content = Signal(providing_args=["new_category"])
+"""
+Signal handlers
+"""
 
 
-# Signal handlers
 @receiver(username_changed)
 def update_usernames(sender, **kwargs):
     Category.objects.filter(last_poster=sender).update(

+ 8 - 3
misago/core/exceptionhandler.py

@@ -9,9 +9,14 @@ from . import errorpages
 from .exceptions import AjaxError, Banned, ExplicitFirstPage, OutdatedSlug
 
 
-HANDLED_EXCEPTIONS = (
-    AjaxError, Banned, ExplicitFirstPage, Http404, OutdatedSlug, PermissionDenied
-)
+HANDLED_EXCEPTIONS = [
+    AjaxError,
+    Banned,
+    ExplicitFirstPage,
+    Http404,
+    OutdatedSlug,
+    PermissionDenied,
+]
 
 
 def is_misago_exception(exception):

+ 5 - 3
misago/core/tests/test_checks.py

@@ -5,9 +5,11 @@ from django.test import TestCase
 from misago.core import SUPPORTED_ENGINES, check_db_engine
 
 
-INVALID_ENGINES = (
-    'django.db.backends.sqlite3', 'django.db.backends.mysql', 'django.db.backends.oracle',
-)
+INVALID_ENGINES = [
+    'django.db.backends.sqlite3',
+    'django.db.backends.mysql',
+    'django.db.backends.oracle',
+]
 
 
 class TestCheckDBEngine(TestCase):

+ 4 - 6
misago/core/tests/test_serializers.py

@@ -14,7 +14,7 @@ class MutableFieldsSerializerTests(TestCase):
         category = Category.objects.get(slug='first-category')
         thread = testutils.post_thread(category=category)
 
-        fields = ('id', 'title', 'replies', 'last_poster_name')
+        fields = ['id', 'title', 'replies', 'last_poster_name']
 
         serializer = TestSerializer.subset_fields(*fields)
         self.assertEqual(serializer.__name__, 'TestSerializerIdTitleRepliesLastPosterNameSubset')
@@ -37,8 +37,8 @@ class MutableFieldsSerializerTests(TestCase):
         category = Category.objects.get(slug='first-category')
         thread = testutils.post_thread(category=category)
 
-        kept_fields = ('id', 'title', 'weight')
-        removed_fields = tuple(set(TestSerializer.Meta.fields) - set(kept_fields))
+        kept_fields = ['id', 'title', 'weight']
+        removed_fields = list(set(TestSerializer.Meta.fields) - set(kept_fields))
 
         serializer = TestSerializer.exclude_fields(*removed_fields)
         self.assertEqual(serializer.__name__, 'TestSerializerIdTitleWeightSubset')
@@ -60,9 +60,7 @@ class MutableFieldsSerializerTests(TestCase):
         category = Category.objects.get(slug='first-category')
         thread = testutils.post_thread(category=category)
 
-        added_fields = ('category', )
-
-        serializer = TestSerializer.extend_fields(*added_fields)
+        serializer = TestSerializer.extend_fields('category')
 
         serialized_thread = serializer(thread).data
         self.assertEqual(serialized_thread['category'], category.pk)

+ 17 - 2
misago/core/tests/test_shortcuts.py

@@ -57,14 +57,29 @@ class ValidateSlugTests(TestCase):
 class GetIntOr404Tests(TestCase):
     def test_valid_inputs(self):
         """get_int_or_404 returns int for valid values"""
-        VALID_VALUES = (('0', 0), ('123', 123), ('000123', 123), ('1', 1), )
+        VALID_VALUES = [
+            ('0', 0),
+            ('123', 123),
+            ('000123', 123),
+            ('1', 1),
+        ]
 
         for value, result in VALID_VALUES:
             self.assertEqual(get_int_or_404(value), result)
 
     def test_invalid_inputs(self):
         """get_int_or_404 raises Http404 for invalid values"""
-        INVALID_VALUES = (None, '', 'bob', '1bob', 'b0b', 'bob123', '12.321', '.4', '5.', )
+        INVALID_VALUES = [
+            None,
+            '',
+            'bob',
+            '1bob',
+            'b0b',
+            'bob123',
+            '12.321',
+            '.4',
+            '5.',
+        ]
 
         for value in INVALID_VALUES:
             with self.assertRaises(Http404):

+ 12 - 2
misago/core/tests/test_templatetags.py

@@ -45,7 +45,12 @@ class BatchTests(TestCase):
     def test_batch(self):
         """standard batch yields valid results"""
         batch = 'loremipsum'
-        yields = (['l', 'o', 'r'], ['e', 'm', 'i'], ['p', 's', 'u'], ['m'], )
+        yields = [
+            ['l', 'o', 'r'],
+            ['e', 'm', 'i'],
+            ['p', 's', 'u'],
+            ['m'],
+        ]
 
         for i, test_yield in enumerate(misago_batch.batch(batch, 3)):
             self.assertEqual(test_yield, yields[i])
@@ -53,7 +58,12 @@ class BatchTests(TestCase):
     def test_batchnonefilled(self):
         """none-filled batch yields valid results"""
         batch = 'loremipsum'
-        yields = (['l', 'o', 'r'], ['e', 'm', 'i'], ['p', 's', 'u'], ['m', None, None], )
+        yields = [
+            ['l', 'o', 'r'],
+            ['e', 'm', 'i'],
+            ['p', 's', 'u'],
+            ['m', None, None],
+        ]
 
         for i, test_yield in enumerate(misago_batch.batchnonefilled(batch, 3)):
             self.assertEqual(test_yield, yields[i])

+ 13 - 5
misago/datamover/management/commands/runmigration.py

@@ -3,11 +3,19 @@ from django.core.management import call_command
 from misago.datamover.management.base import BaseCommand
 
 
-MOVE_COMMANDS = (
-    'movesettings', 'moveusers', 'movecategories', 'movethreads', 'buildmovesindex',
-    'synchronizethreads', 'synchronizecategories', 'rebuildpostssearch', 'invalidatebans',
-    'populateonlinetracker', 'synchronizeusers',
-)
+MOVE_COMMANDS = [
+    'movesettings',
+    'moveusers',
+    'movecategories',
+    'movethreads',
+    'buildmovesindex',
+    'synchronizethreads',
+    'synchronizecategories',
+    'rebuildpostssearch',
+    'invalidatebans',
+    'populateonlinetracker',
+    'synchronizeusers',
+]
 
 
 class Command(BaseCommand):

+ 4 - 3
misago/markup/tests/test_mentions.py

@@ -35,11 +35,12 @@ class MentionsTests(AuthenticatedUserTestCase):
 
     def test_invalid_mentions(self):
         """markup extension leaves invalid mentions alone"""
-        TEST_CASES = (
-            '<p>Hello, Bob!</p>', '<p>Hello, @Bob!</p>',
+        TEST_CASES = [
+            '<p>Hello, Bob!</p>',
+            '<p>Hello, @Bob!</p>',
             '<p>Hello, <a href="/">@{}</a>!</p>'.format(self.user.username),
             '<p>Hello, <a href="/"><b>@{}</b></a>!</p>'.format(self.user.username),
-        )
+        ]
 
         for markup in TEST_CASES:
             result = {'parsed_text': markup, 'mentions': []}

+ 77 - 64
misago/threads/migrations/0003_attachment_types.py

@@ -5,70 +5,83 @@ from __future__ import unicode_literals
 from django.db import migrations
 
 
-ATTACHMENTS = ({
-    'name': 'GIF',
-    'extensions': ('gif', ),
-    'mimetypes': ('image/gif', ),
-    'size_limit': 5 * 1024
-}, {
-    'name': 'JPG',
-    'extensions': ('jpg', 'jpeg', ),
-    'mimetypes': ('image/jpeg', ),
-    'size_limit': 3 * 1024
-}, {
-    'name': 'PNG',
-    'extensions': ('png', ),
-    'mimetypes': ('image/png', ),
-    'size_limit': 3 * 1024
-}, {
-    'name':
-        'PDF',
-    'extensions': ('pdf', ),
-    'mimetypes':
-        ('application/pdf', 'application/x-pdf', 'application/x-bzpdf', 'application/x-gzpdf'),
-    'size_limit':
-        4 * 1024
-}, {
-    'name': 'Text',
-    'extensions': ('txt', ),
-    'mimetypes': ('text/plain', ),
-    'size_limit': 4 * 1024
-}, {
-    'name': 'Markdown',
-    'extensions': ('md', ),
-    'mimetypes': ('text/markdown', ),
-    'size_limit': 4 * 1024
-}, {
-    'name': 'reStructuredText',
-    'extensions': ('rst', ),
-    'mimetypes': ('text/x-rst', ),
-    'size_limit': 4 * 1024
-}, {
-    'name': '7Z',
-    'extensions': ('7z', ),
-    'mimetypes': ('application/x-7z-compressed', ),
-    'size_limit': 4 * 1024
-}, {
-    'name': 'RAR',
-    'extensions': ('rar', ),
-    'mimetypes': ('application/vnd.rar', ),
-    'size_limit': 4 * 1024
-}, {
-    'name': 'TAR',
-    'extensions': ('tar', ),
-    'mimetypes': ('application/x-tar', ),
-    'size_limit': 4 * 1024
-}, {
-    'name': 'GZ',
-    'extensions': ('gz', ),
-    'mimetypes': ('application/gzip', ),
-    'size_limit': 4 * 1024
-}, {
-    'name': 'ZIP',
-    'extensions': ('zip', 'zipx', ),
-    'mimetypes': ('application/zip', ),
-    'size_limit': 4 * 1024
-}, )
+ATTACHMENTS = [
+    {
+        'name': 'GIF',
+        'extensions': ('gif', ),
+        'mimetypes': ('image/gif', ),
+        'size_limit': 5 * 1024
+    },
+    {
+        'name': 'JPG',
+        'extensions': ('jpg', 'jpeg', ),
+        'mimetypes': ('image/jpeg', ),
+        'size_limit': 3 * 1024
+    },
+    {
+        'name': 'PNG',
+        'extensions': ('png', ),
+        'mimetypes': ('image/png', ),
+        'size_limit': 3 * 1024
+    },
+    {
+        'name':
+            'PDF',
+        'extensions': ('pdf', ),
+        'mimetypes':
+            ('application/pdf', 'application/x-pdf', 'application/x-bzpdf', 'application/x-gzpdf'),
+        'size_limit':
+            4 * 1024
+    },
+    {
+        'name': 'Text',
+        'extensions': ('txt', ),
+        'mimetypes': ('text/plain', ),
+        'size_limit': 4 * 1024
+    },
+    {
+        'name': 'Markdown',
+        'extensions': ('md', ),
+        'mimetypes': ('text/markdown', ),
+        'size_limit': 4 * 1024
+    },
+    {
+        'name': 'reStructuredText',
+        'extensions': ('rst', ),
+        'mimetypes': ('text/x-rst', ),
+        'size_limit': 4 * 1024
+    },
+    {
+        'name': '7Z',
+        'extensions': ('7z', ),
+        'mimetypes': ('application/x-7z-compressed', ),
+        'size_limit': 4 * 1024
+    },
+    {
+        'name': 'RAR',
+        'extensions': ('rar', ),
+        'mimetypes': ('application/vnd.rar', ),
+        'size_limit': 4 * 1024
+    },
+    {
+        'name': 'TAR',
+        'extensions': ('tar', ),
+        'mimetypes': ('application/x-tar', ),
+        'size_limit': 4 * 1024
+    },
+    {
+        'name': 'GZ',
+        'extensions': ('gz', ),
+        'mimetypes': ('application/gzip', ),
+        'size_limit': 4 * 1024
+    },
+    {
+        'name': 'ZIP',
+        'extensions': ('zip', 'zipx', ),
+        'mimetypes': ('application/zip', ),
+        'size_limit': 4 * 1024
+    },
+]
 
 
 def create_attachment_types(apps, schema_editor):

+ 3 - 1
misago/threads/signals.py

@@ -17,9 +17,11 @@ merge_post = Signal(providing_args=["other_post"])
 merge_thread = Signal(providing_args=["other_thread"])
 move_post = Signal()
 move_thread = Signal()
+"""
+Signal handlers
+"""
 
 
-# Signal handlers
 @receiver(merge_thread)
 def merge_threads_posts(sender, **kwargs):
     other_thread = kwargs['other_thread']

+ 2 - 2
misago/threads/tests/test_attachments_middleware.py

@@ -59,7 +59,7 @@ class AttachmentsMiddlewareTests(AuthenticatedUserTestCase):
 
     def test_middleware_is_optional(self):
         """middleware is optional"""
-        INPUTS = ({}, {'attachments': []})
+        INPUTS = [{}, {'attachments': []}]
 
         for test_input in INPUTS:
             middleware = AttachmentsMiddleware(
@@ -74,7 +74,7 @@ class AttachmentsMiddlewareTests(AuthenticatedUserTestCase):
 
     def test_middleware_validates_ids(self):
         """middleware validates attachments ids"""
-        INPUTS = ('none', ['a', 'b', 123], range(settings.MISAGO_POST_ATTACHMENTS_LIMIT + 1))
+        INPUTS = ['none', ['a', 'b', 123], range(settings.MISAGO_POST_ATTACHMENTS_LIMIT + 1)]
 
         for test_input in INPUTS:
             middleware = AttachmentsMiddleware(

+ 10 - 4
misago/threads/tests/test_attachmenttypeadmin_views.py

@@ -132,10 +132,16 @@ class AttachmentTypeAdminViewsTests(AdminTestCase):
 
     def test_clean_params_view(self):
         """admin form nicely cleans lists of extensions/mimetypes"""
-        TEST_CASES = (('test', ['test']), ('.test', ['test']), ('.tar.gz', ['tar.gz']),
-                      ('. test', ['test']), ('test, test', ['test']), ('test, tEst', ['test']),
-                      ('test, other, tEst', ['test', 'other']),
-                      ('test, other, tEst,OTher', ['test', 'other']), )
+        TEST_CASES = [
+            ('test', ['test']),
+            ('.test', ['test']),
+            ('.tar.gz', ['tar.gz']),
+            ('. test', ['test']),
+            ('test, test', ['test']),
+            ('test, tEst', ['test']),
+            ('test, other, tEst', ['test', 'other']),
+            ('test, other, tEst,OTher', ['test', 'other']),
+        ]
 
         for raw, final in TEST_CASES:
             response = self.client.post(

+ 2 - 2
misago/threads/tests/test_threadview.py

@@ -220,7 +220,7 @@ class ThreadPostsVisibilityTests(ThreadViewTestCase):
 class ThreadEventVisibilityTests(ThreadViewTestCase):
     def test_thread_events_render(self):
         """different thread events render"""
-        TEST_ACTIONS = (
+        TEST_ACTIONS = [
             (threads_moderation.pin_thread_globally, "Thread has been pinned globally."),
             (threads_moderation.pin_thread_locally, "Thread has been pinned locally."),
             (threads_moderation.unpin_thread, "Thread has been unpinned."),
@@ -229,7 +229,7 @@ class ThreadEventVisibilityTests(ThreadViewTestCase):
             (threads_moderation.open_thread, "Thread has been opened."),
             (threads_moderation.hide_thread, "Thread has been made hidden."),
             (threads_moderation.unhide_thread, "Thread has been revealed."),
-        )
+        ]
 
         self.thread.is_unapproved = True
         self.thread.save()

+ 4 - 4
misago/threads/tests/test_utils.py

@@ -185,7 +185,7 @@ class MockRequest(object):
 class GetThreadIdFromUrlTests(MisagoTestCase):
     def test_get_thread_id_from_valid_urls(self):
         """get_thread_id_from_url extracts thread pk from valid urls"""
-        TEST_CASES = (
+        TEST_CASES = [
             {
                 # perfect match
                 'request': MockRequest('https', 'testforum.com', '/discuss/'),
@@ -247,7 +247,7 @@ class GetThreadIdFromUrlTests(MisagoTestCase):
                 'url': '   /t/test-thread/13/   ',
                 'pk': 13,
             }
-        )
+        ]
 
         for case in TEST_CASES:
             pk = get_thread_id_from_url(case['request'], case['url'])
@@ -257,7 +257,7 @@ class GetThreadIdFromUrlTests(MisagoTestCase):
             )
 
     def test_get_thread_id_from_invalid_urls(self):
-        TEST_CASES = (
+        TEST_CASES = [
             {
                 # invalid wsgi alias
                 'request': MockRequest('https', 'testforum.com'),
@@ -298,7 +298,7 @@ class GetThreadIdFromUrlTests(MisagoTestCase):
                 'request': MockRequest('http', 'testforum.com'),
                 'url': ''
             }
-        )
+        ]
 
         for case in TEST_CASES:
             pk = get_thread_id_from_url(case['request'], case['url'])

+ 5 - 1
misago/threads/tests/test_validators.py

@@ -31,7 +31,11 @@ class ValidatePostTests(TestCase):
 class ValidateTitleTests(TestCase):
     def test_valid_titles(self):
         """validate_title is ok with valid titles"""
-        VALID_TITLES = ('Lorem ipsum dolor met', '123 456 789 112' 'Ugabugagagagagaga', )
+        VALID_TITLES = [
+            'Lorem ipsum dolor met',
+            '123 456 789 112'
+            'Ugabugagagagagaga',
+        ]
 
         for title in VALID_TITLES:
             validate_title(title)

+ 8 - 3
misago/threads/viewmodels/thread.py

@@ -18,9 +18,14 @@ from misago.threads.threadtypes import trees_map
 
 __all__ = ['ForumThread', 'PrivateThread']
 
-BASE_RELATIONS = (
-    'category', 'poll', 'starter', 'starter__rank', 'starter__ban_cache', 'starter__online_tracker'
-)
+BASE_RELATIONS = [
+    'category',
+    'poll',
+    'starter',
+    'starter__rank',
+    'starter__ban_cache',
+    'starter__online_tracker',
+]
 
 
 class ViewModel(BaseViewModel):

+ 8 - 3
misago/threads/views/admin/attachments.py

@@ -20,9 +20,14 @@ class AttachmentAdmin(generic.AdminBaseMixin):
 
 class AttachmentsList(AttachmentAdmin, generic.ListView):
     items_per_page = 20
-    ordering = (('-id', _("From newest")), ('id', _("From oldest")), ('filename', _("A to z")),
-                ('-filename', _("Z to a")), ('size', _("Smallest files")),
-                ('-size', _("Largest files")), )
+    ordering = [
+        ('-id', _("From newest")),
+        ('id', _("From oldest")),
+        ('filename', _("A to z")),
+        ('-filename', _("Z to a")),
+        ('size', _("Smallest files")),
+        ('-size', _("Largest files")),
+    ]
     selection_label = _('With attachments: 0')
     empty_selection_label = _('Select attachments')
     mass_actions = [

+ 6 - 1
misago/users/permissions/moderation.py

@@ -104,7 +104,12 @@ def add_acl_to_user(user, target):
     target.acl['max_ban_length'] = user.acl_cache['max_ban_length']
     target.acl['can_lift_ban'] = can_lift_ban(user, target)
 
-    mod_permissions = ('can_rename', 'can_moderate_avatar', 'can_moderate_signature', 'can_ban', )
+    mod_permissions = [
+        'can_rename',
+        'can_moderate_avatar',
+        'can_moderate_signature',
+        'can_ban',
+    ]
 
     for permission in mod_permissions:
         if target.acl[permission]:

+ 2 - 2
misago/users/serializers/auth.py

@@ -31,11 +31,11 @@ class AuthenticatedUserSerializer(UserSerializer, AuthFlags):
 
     class Meta:
         model = UserModel
-        fields = UserSerializer.Meta.fields + (
+        fields = UserSerializer.Meta.fields + [
             'is_hiding_presence', 'limits_private_thread_invites_to',
             'subscribe_to_started_threads', 'subscribe_to_replied_threads', 'is_authenticated',
             'is_anonymous',
-        )
+        ]
 
     def get_acl(self, obj):
         return serialize_acl(obj)

+ 10 - 40
misago/users/serializers/user.py

@@ -107,46 +107,16 @@ class UserSerializer(serializers.ModelSerializer, MutableFields):
 
     def get_api_url(self, obj):
         return {
-            'root':
-                reverse('misago:api:user-detail', kwargs={
-                    'pk': obj.pk,
-                }),
-            'follow':
-                reverse('misago:api:user-follow', kwargs={
-                    'pk': obj.pk,
-                }),
-            'ban':
-                reverse('misago:api:user-ban', kwargs={
-                    'pk': obj.pk,
-                }),
-            'moderate_avatar':
-                reverse('misago:api:user-moderate-avatar', kwargs={
-                    'pk': obj.pk,
-                }),
-            'moderate_username':
-                reverse('misago:api:user-moderate-username', kwargs={
-                    'pk': obj.pk,
-                }),
-            'delete':
-                reverse('misago:api:user-delete', kwargs={
-                    'pk': obj.pk,
-                }),
-            'followers':
-                reverse('misago:api:user-followers', kwargs={
-                    'pk': obj.pk,
-                }),
-            'follows':
-                reverse('misago:api:user-follows', kwargs={
-                    'pk': obj.pk,
-                }),
-            'threads':
-                reverse('misago:api:user-threads', kwargs={
-                    'pk': obj.pk,
-                }),
-            'posts':
-                reverse('misago:api:user-posts', kwargs={
-                    'pk': obj.pk,
-                }),
+            'root': reverse('misago:api:user-detail', kwargs={'pk': obj.pk}),
+            'follow': reverse('misago:api:user-follow', kwargs={'pk': obj.pk}),
+            'ban': reverse('misago:api:user-ban', kwargs={'pk': obj.pk}),
+            'moderate_avatar': reverse('misago:api:user-moderate-avatar', kwargs={'pk': obj.pk}),
+            'moderate_username': reverse('misago:api:user-moderate-username', kwargs={'pk': obj.pk}),
+            'delete': reverse('misago:api:user-delete', kwargs={'pk': obj.pk}),
+            'followers': reverse('misago:api:user-followers', kwargs={'pk': obj.pk}),
+            'follows': reverse('misago:api:user-follows', kwargs={'pk': obj.pk}),
+            'threads': reverse('misago:api:user-threads', kwargs={'pk': obj.pk}),
+            'posts':  reverse('misago:api:user-posts', kwargs={'pk': obj.pk}),
         }
 
 

+ 3 - 1
misago/users/signals.py

@@ -3,9 +3,11 @@ from django.dispatch import Signal, receiver
 
 delete_user_content = Signal()
 username_changed = Signal()
+"""
+Signal handlers
+"""
 
 
-# Signal handlers
 @receiver(username_changed)
 def handle_name_change(sender, **kwargs):
     sender.user_renames.update(changed_by_username=sender.username)

+ 2 - 2
misago/users/tests/test_invalidatebans.py

@@ -20,7 +20,7 @@ class InvalidateBansTests(TestCase):
         # create 5 bans then update their valid date to past one
         for _ in range(5):
             Ban.objects.create(banned_value="abcd")
-        expired_date = (timezone.now() - timedelta(days=10))
+        expired_date = timezone.now() - timedelta(days=10)
         Ban.objects.all().update(expires_on=expired_date, is_checked=True)
 
         self.assertEqual(Ban.objects.filter(is_checked=True).count(), 5)
@@ -57,7 +57,7 @@ class InvalidateBansTests(TestCase):
         self.assertEqual(Ban.objects.filter(is_checked=True).count(), 1)
 
         # expire bans
-        expired_date = (timezone.now() - timedelta(days=10))
+        expired_date = timezone.now() - timedelta(days=10)
         Ban.objects.all().update(
             expires_on=expired_date,
             is_checked=True,

+ 14 - 6
misago/users/tokens.py

@@ -45,10 +45,14 @@ def is_valid(user, token_type, token):
 
 
 def _make_hash(user, token_type):
-    seeds = (
-        user.pk, user.email, user.password, user.last_login.replace(microsecond=0, tzinfo=None),
-        token_type, settings.SECRET_KEY,
-    )
+    seeds = [
+        user.pk,
+        user.email,
+        user.password,
+        user.last_login.replace(microsecond=0, tzinfo=None),
+        token_type,
+        settings.SECRET_KEY,
+    ]
 
     return sha256(force_bytes('+'.join([six.text_type(s) for s in seeds]))).hexdigest()[:8]
 
@@ -61,7 +65,9 @@ def _make_checksum(obfuscated):
     return sha256(force_bytes('%s:%s' % (settings.SECRET_KEY, obfuscated))).hexdigest()[:8]
 
 
-# Convenience functions for activation token
+"""
+Convenience functions for activation token
+"""
 ACTIVATION_TOKEN = 'activation'
 
 
@@ -73,7 +79,9 @@ def is_activation_token_valid(user, token):
     return is_valid(user, ACTIVATION_TOKEN, token)
 
 
-# Convenience functions for password change token
+"""
+Convenience functions for password change token
+"""
 PASSWORD_CHANGE_TOKEN = 'change_password'
 
 

+ 9 - 3
misago/users/validators.py

@@ -48,7 +48,9 @@ def validate_email(value, exclude=None):
     validate_email_banned(value)
 
 
-# Username validators
+"""
+Username validators
+"""
 def validate_username_available(value, exclude=None):
     try:
         user = UserModel.objects.get_by_username(value)
@@ -99,7 +101,9 @@ def validate_username(value, exclude=None):
     validate_username_banned(value)
 
 
-# New account validators
+"""
+New account validators
+"""
 SFS_API_URL = u'http://api.stopforumspam.org/api?email=%(email)s&ip=%(ip)s&f=json&confidence'  # noqa
 
 
@@ -136,7 +140,9 @@ def validate_gmail_email(request, form, cleaned_data):
         form.add_error('email', ValidationError(_("This email is not allowed.")))
 
 
-# Registration validation
+"""
+Registration validation
+"""
 def load_registration_validators(validators):
     loaded_validators = []
     for path in validators:

+ 6 - 2
misago/users/views/admin/bans.py

@@ -20,8 +20,12 @@ class BanAdmin(generic.AdminBaseMixin):
 
 class BansList(BanAdmin, generic.ListView):
     items_per_page = 30
-    ordering = (('-id', _("From newest")), ('id', _("From oldest")), ('banned_value', _("A to z")),
-                ('-banned_value', _("Z to a")), )
+    ordering = [
+        ('-id', _("From newest")),
+        ('id', _("From oldest")),
+        ('banned_value', _("A to z")),
+        ('-banned_value', _("Z to a")),
+    ]
     search_form = SearchBansForm
     selection_label = _('With bans: 0')
     empty_selection_label = _('Select bans')

+ 42 - 32
misago/users/views/admin/users.py

@@ -50,40 +50,50 @@ class UserAdmin(generic.AdminBaseMixin):
 
 class UsersList(UserAdmin, generic.ListView):
     items_per_page = 24
-    ordering = (('-id', _("From newest")), ('id', _("From oldest")), ('slug', _("A to z")),
-                ('-slug', _("Z to a")), ('posts', _("Biggest posters")),
-                ('-posts', _("Smallest posters")), )
+    ordering = [
+        ('-id', _("From newest")),
+        ('id', _("From oldest")),
+        ('slug', _("A to z")),
+        ('-slug', _("Z to a")),
+        ('posts', _("Biggest posters")),
+        ('-posts', _("Smallest posters")),
+    ]
     selection_label = _('With users: 0')
     empty_selection_label = _('Select users')
-    mass_actions = [{
-        'action': 'activate',
-        'name': _("Activate accounts"),
-        'icon': 'fa fa-check-square-o',
-    }, {
-        'action': 'ban',
-        'name': _("Ban users"),
-        'icon': 'fa fa-lock',
-    }, {
-        'action': 'delete_accounts',
-        'name': _("Delete accounts"),
-        'icon': 'fa fa-times-circle',
-        'confirmation': _("Are you sure you want to delete selected users?"),
-    }, {
-        'action':
-            'delete_all',
-        'name':
-            _("Delete all"),
-        'icon':
-            'fa fa-eraser',
-        'confirmation':
-            _(
-                "Are you sure you want to delete selected "
-                "users? This will also delete all content "
-                "associated with their accounts."
-            ),
-        'is_atomic':
-            False,
-    }]
+    mass_actions = [
+        {
+            'action': 'activate',
+            'name': _("Activate accounts"),
+            'icon': 'fa fa-check-square-o',
+        },
+        {
+            'action': 'ban',
+            'name': _("Ban users"),
+            'icon': 'fa fa-lock',
+        },
+        {
+            'action': 'delete_accounts',
+            'name': _("Delete accounts"),
+            'icon': 'fa fa-times-circle',
+            'confirmation': _("Are you sure you want to delete selected users?"),
+        },
+        {
+            'action':
+                'delete_all',
+            'name':
+                _("Delete all"),
+            'icon':
+                'fa fa-eraser',
+            'confirmation':
+                _(
+                    "Are you sure you want to delete selected "
+                    "users? This will also delete all content "
+                    "associated with their accounts."
+                ),
+            'is_atomic':
+                False,
+        },
+    ]
 
     def get_queryset(self):
         qs = super(UsersList, self).get_queryset()