Rafał Pitoń 10 лет назад
Родитель
Сommit
b1b33dd1f7
93 измененных файлов с 188 добавлено и 235 удалено
  1. 0 1
      misago/acl/algebra.py
  2. 1 1
      misago/acl/models.py
  3. 0 1
      misago/acl/panels.py
  4. 2 4
      misago/acl/testutils.py
  5. 0 1
      misago/acl/views.py
  6. 0 1
      misago/admin/admin.py
  7. 0 2
      misago/admin/hierarchy.py
  8. 0 1
      misago/admin/urlpatterns.py
  9. 0 4
      misago/admin/urls.py
  10. 6 6
      misago/admin/views/generic/__init__.py
  11. 5 3
      misago/admin/views/generic/list.py
  12. 0 1
      misago/conf/tests/test_admin_views.py
  13. 1 1
      misago/conf/tests/test_migrationutils.py
  14. 4 5
      misago/conf/tests/test_settings.py
  15. 1 1
      misago/conf/views.py
  16. 0 3
      misago/core/forms.py
  17. 0 2
      misago/core/management/commands/testemailsetup.py
  18. 0 5
      misago/core/migrationutils.py
  19. 9 4
      misago/core/pgutils.py
  20. 0 1
      misago/core/templatetags/misago_batch.py
  21. 0 1
      misago/core/templatetags/misago_capture.py
  22. 0 2
      misago/core/tests/test_fileserver.py
  23. 1 1
      misago/core/tests/test_mailer.py
  24. 2 3
      misago/core/tests/test_templatetags.py
  25. 0 1
      misago/core/tests/test_uiviews.py
  26. 0 1
      misago/core/tests/test_utils.py
  27. 3 1
      misago/core/timezones.py
  28. 2 4
      misago/faker/management/commands/createfakebans.py
  29. 1 4
      misago/faker/management/commands/createfakefollowers.py
  30. 2 1
      misago/faker/management/commands/createfakeusers.py
  31. 21 21
      misago/forums/forms.py
  32. 1 2
      misago/forums/lists.py
  33. 2 2
      misago/forums/migrations/0001_initial.py
  34. 4 4
      misago/forums/tests/test_forums_admin_views.py
  35. 12 2
      misago/forums/tests/test_lists.py
  36. 0 2
      misago/forums/views/permsadmin.py
  37. 1 0
      misago/legal/__init__.py
  38. 7 3
      misago/markup/__init__.py
  39. 1 1
      misago/markup/templatetags/misago_editor.py
  40. 0 3
      misago/markup/tests.py
  41. 3 0
      misago/notifications/__init__.py
  42. 2 1
      misago/notifications/api.py
  43. 5 4
      misago/notifications/migrations/0001_initial.py
  44. 3 5
      misago/notifications/models.py
  45. 0 3
      misago/notifications/views.py
  46. 1 0
      misago/threads/__init__.py
  47. 0 1
      misago/threads/forms/admin.py
  48. 1 1
      misago/threads/migrations/0001_initial.py
  49. 1 0
      misago/threads/models/__init__.py
  50. 0 1
      misago/threads/models/prefix.py
  51. 0 1
      misago/threads/tests/test_prefix_model.py
  52. 2 1
      misago/threads/tests/test_prefixesadmin_views.py
  53. 0 1
      misago/users/admin.py
  54. 7 0
      misago/users/apps.py
  55. 0 1
      misago/users/avatars/dynamic.py
  56. 0 2
      misago/users/avatars/paths.py
  57. 0 1
      misago/users/decorators.py
  58. 2 2
      misago/users/forms/admin.py
  59. 1 1
      misago/users/forms/auth.py
  60. 1 2
      misago/users/forms/modusers.py
  61. 2 4
      misago/users/management/commands/bansmaintenance.py
  62. 0 2
      misago/users/middleware.py
  63. 1 0
      misago/users/models/__init__.py
  64. 2 3
      misago/users/models/bans.py
  65. 0 1
      misago/users/models/rank.py
  66. 3 4
      misago/users/models/user.py
  67. 6 7
      misago/users/models/warnings.py
  68. 1 1
      misago/users/namechanges.py
  69. 1 5
      misago/users/online/ranks.py
  70. 12 12
      misago/users/permissions/profiles.py
  71. 7 11
      misago/users/permissions/warnings.py
  72. 0 2
      misago/users/templatetags/misago_avatars.py
  73. 0 3
      misago/users/tests/test_avatars.py
  74. 0 1
      misago/users/tests/test_avatarserver_views.py
  75. 4 4
      misago/users/tests/test_ban_model.py
  76. 2 3
      misago/users/tests/test_lists_views.py
  77. 3 3
      misago/users/tests/test_profile_views.py
  78. 6 6
      misago/users/tests/test_registration_views.py
  79. 1 1
      misago/users/tests/test_usercp_views.py
  80. 1 0
      misago/users/tests/test_validators.py
  81. 2 1
      misago/users/tests/test_warningadmin_views.py
  82. 6 5
      misago/users/tests/test_warnings_views.py
  83. 0 1
      misago/users/urls.py
  84. 1 3
      misago/users/views/admin/users.py
  85. 0 1
      misago/users/views/admin/warnings.py
  86. 0 1
      misago/users/views/auth.py
  87. 0 3
      misago/users/views/forgottenpassword.py
  88. 3 3
      misago/users/views/lists.py
  89. 3 1
      misago/users/views/profile.py
  90. 1 2
      misago/users/views/register.py
  91. 2 2
      misago/users/views/usercp.py
  92. 0 1
      misago/users/warnings.py
  93. 0 3
      runtests.py

+ 0 - 1
misago/acl/algebra.py

@@ -55,4 +55,3 @@ def greater_or_zero(a, b):
 
 def lower(a, b):
     return a if a < b else b
-

+ 1 - 1
misago/acl/models.py

@@ -36,7 +36,7 @@ class BaseRole(models.Model):
                 self.permissions_cache = serializer.loads(
                     self.pickled_permissions)
             else:
-               self.permissions_cache = {}
+                self.permissions_cache = {}
         return self.permissions_cache
 
     @permissions.setter

+ 0 - 1
misago/acl/panels.py

@@ -1,5 +1,4 @@
 from debug_toolbar.panels import Panel
-from django.template.loader import render_to_string
 from django.utils.translation import ugettext_lazy as _
 
 

+ 2 - 4
misago/acl/testutils.py

@@ -1,10 +1,8 @@
 from hashlib import md5
-from time import time
 
 from misago.core import threadstore
 
 from misago.acl.forms import get_permissions_forms
-from misago.acl.models import Role
 
 
 def fake_post_data(target, data_dict):
@@ -15,9 +13,9 @@ def fake_post_data(target, data_dict):
     """
     for form in get_permissions_forms(target):
         for field in form:
-            if field.value() == True:
+            if field.value() is True:
                 data_dict[field.html_name] = 1
-            elif field.value() == False:
+            elif field.value() is False:
                 data_dict[field.html_name] = 0
             else:
                 data_dict[field.html_name] = field.value()

+ 0 - 1
misago/acl/views.py

@@ -22,7 +22,6 @@ class RolesList(RoleAdmin, generic.ListView):
 
 class RoleFormMixin(object):
     def real_dispatch(self, request, target):
-        role_permissions = target.permissions
         form = RoleForm(instance=target)
 
         perms_forms = get_permissions_forms(target)

+ 0 - 1
misago/admin/admin.py

@@ -1,6 +1,5 @@
 from django.conf.urls import url
 from django.utils.translation import ugettext_lazy as _
-from misago.acl.views import RolesList, NewRole, EditRole, DeleteRole
 
 
 class MisagoAdminExtension(object):

+ 0 - 2
misago/admin/hierarchy.py

@@ -166,7 +166,6 @@ class AdminHierarchyBuilder(object):
                     branches.append(children)
                 node = node.parent
 
-
         namespace = request.resolver_match.namespaces
 
         branches.reverse()
@@ -176,7 +175,6 @@ class AdminHierarchyBuilder(object):
                 node_namespace = node['namespace'].split(':')[2:3 + depth]
                 node['is_active'] = depth_namespace == node_namespace
 
-
         return branches
 
 

+ 0 - 1
misago/admin/urlpatterns.py

@@ -1,5 +1,4 @@
 from django.conf.urls import patterns, url, include
-from django.core.urlresolvers import reverse
 
 
 class URLPatterns(object):

+ 0 - 4
misago/admin/urls.py

@@ -1,8 +1,4 @@
-import importlib
-
-from django.conf import settings
 from django.conf.urls import patterns, include, url
-
 from misago import admin
 
 

+ 6 - 6
misago/admin/views/generic/__init__.py

@@ -1,6 +1,6 @@
-from misago.admin.views.generic.mixin import AdminBaseMixin  # noqa
-from misago.admin.views.generic.base import AdminView  # noqa
-from misago.admin.views.generic.list import ListView, MassActionError  # noqa
-from misago.admin.views.generic.formsbuttons import (TargetedView, FormView,
-                                                     ModelFormView,
-                                                     ButtonView)  # noqa
+# flake8: noqa
+from misago.admin.views.generic.mixin import AdminBaseMixin
+from misago.admin.views.generic.base import AdminView
+from misago.admin.views.generic.list import ListView, MassActionError
+from misago.admin.views.generic.formsbuttons import (
+    TargetedView, FormView, ModelFormView, ButtonView)

+ 5 - 3
misago/admin/views/generic/list.py

@@ -73,7 +73,7 @@ class ListView(AdminView):
             elif page == 0:
                 page = 1
         except ValueError:
-            page_no = 1
+            page = 1
 
         context['paginator'] = Paginator(context['items'],
                                          self.items_per_page,
@@ -317,12 +317,14 @@ class ListView(AdminView):
         SearchForm = self.get_search_form(request)
         if SearchForm:
             filtering_methods = self.get_filtering_methods(request)
-            active_filters = self.get_filtering_method_to_use(filtering_methods)
+            active_filters = self.get_filtering_method_to_use(
+                filtering_methods)
             if request.GET.get('clear_filters'):
                 # Clear filters from querystring
                 request.session.pop(self.filters_session_key, None)
                 active_filters = {}
-            self.apply_filtering_on_context(context, active_filters, SearchForm)
+            self.apply_filtering_on_context(
+                context, active_filters, SearchForm)
 
             if (filtering_methods['GET'] and
                     filtering_methods['GET'] != filtering_methods['session']):

+ 0 - 1
misago/conf/tests/test_admin_views.py

@@ -1,4 +1,3 @@
-from django.contrib.auth import get_user_model
 from django.core.urlresolvers import reverse
 
 from misago.admin.testutils import AdminTestCase

+ 1 - 1
misago/conf/tests/test_migrationutils.py

@@ -4,7 +4,7 @@ from django.test import TestCase
 from misago.core import threadstore
 
 from misago.conf import migrationutils
-from misago.conf.models import SettingsGroup, Setting
+from misago.conf.models import SettingsGroup
 
 
 class DBConfMigrationUtilsTests(TestCase):

+ 4 - 5
misago/conf/tests/test_settings.py

@@ -8,7 +8,6 @@ from misago.core.cache import cache
 from misago.conf.gateway import settings as gateway
 from misago.conf.dbsettings import db_settings
 from misago.conf.migrationutils import migrate_settings_group
-from misago.conf.models import SettingsGroup, Setting
 
 
 class DBSettingsTests(TestCase):
@@ -78,11 +77,11 @@ class GatewaySettingsTests(TestCase):
         self.assertTrue(db_settings.lazy_fish_name)
 
         self.assertTrue(gateway.lazy_fish_name)
-        self.assertEqual(gateway.get_lazy_setting('lazy_fish_name'),
-                        'Lazy Eric')
+        self.assertEqual(
+            gateway.get_lazy_setting('lazy_fish_name'), 'Lazy Eric')
         self.assertTrue(db_settings.lazy_fish_name)
-        self.assertEqual(db_settings.get_lazy_setting('lazy_fish_name'),
-                        'Lazy Eric')
+        self.assertEqual(
+            db_settings.get_lazy_setting('lazy_fish_name'), 'Lazy Eric')
 
         self.assertTrue(gateway.lazy_empty_setting is None)
         self.assertTrue(db_settings.lazy_empty_setting is None)

+ 1 - 1
misago/conf/views.py

@@ -6,7 +6,7 @@ from misago.admin.views import render as mi_render
 
 from misago.conf import db_settings
 from misago.conf.forms import ChangeSettingsForm
-from misago.conf.models import SettingsGroup, Setting
+from misago.conf.models import SettingsGroup
 
 
 def render(request, template, context=None):

+ 0 - 3
misago/core/forms.py

@@ -1,10 +1,7 @@
-from crispy_forms.helper import FormHelper
-
 from mptt.forms import *  # noqa
 
 from django.forms import *  # noqa
 from django.forms import Form as BaseForm, ModelForm as BaseModelForm
-from django.utils.html import conditional_escape, mark_safe
 from django.utils.translation import ugettext_lazy as _
 
 

+ 0 - 2
misago/core/management/commands/testemailsetup.py

@@ -1,5 +1,3 @@
-import os
-
 from django.conf import settings
 from django.core import mail
 from django.core.exceptions import ValidationError

+ 0 - 5
misago/core/migrationutils.py

@@ -1,12 +1,7 @@
-from importlib import import_module
-
 from misago.core.cache import cache as default_cache
 from misago.core.cachebuster import CACHE_KEY
 
 
-"""
-cache versioning utils
-"""
 def _CacheVersion(apps):
     return apps.get_model('misago_core', 'CacheVersion')
 

+ 9 - 4
misago/core/pgutils.py

@@ -23,7 +23,8 @@ DROP INDEX %(index_name)s
     def state_forwards(self, app_label, state):
         pass
 
-    def database_forwards(self, app_label, schema_editor, from_state, to_state):
+    def database_forwards(self, app_label, schema_editor,
+                          from_state, to_state):
         apps = from_state.render()
         model = apps.get_model(app_label, self.model)
 
@@ -36,8 +37,12 @@ DROP INDEX %(index_name)s
 
         schema_editor.execute(statement)
 
-    def database_backwards(self, app_label, schema_editor, from_state, to_state):
-        schema_editor.execute(self.REMOVE_SQL % {'index_name': self.index_name})
+    def database_backwards(self, app_label, schema_editor,
+                           from_state, to_state):
+        schema_editor.execute(
+            self.REMOVE_SQL % {'index_name': self.index_name})
 
     def describe(self):
-        return "Create PostgreSQL partial index on field %s in %s for %s" % (self.field, self.model_name, self.values)
+        message = "Create PostgreSQL partial index on field %s in %s for %s"
+        formats = (self.field, self.model_name, self.values)
+        return message % formats

+ 0 - 1
misago/core/templatetags/misago_batch.py

@@ -1,5 +1,4 @@
 from django import template
-from django.template import Context
 
 
 register = template.Library()

+ 0 - 1
misago/core/templatetags/misago_capture.py

@@ -8,7 +8,6 @@ Syntax:
 """
 
 from django import template
-from django.template import Context
 
 
 register = template.Library()

+ 0 - 2
misago/core/tests/test_fileserver.py

@@ -1,5 +1,3 @@
-import os
-
 from django.conf import settings
 from django.http import HttpResponse, StreamingHttpResponse
 from django.test import TestCase

+ 1 - 1
misago/core/tests/test_mailer.py

@@ -10,7 +10,7 @@ class MisagoFormsTests(TestCase):
     def test_mail_user(self):
         """mail_user sets message in backend"""
         User = get_user_model()
-        test_user = User.objects.create_user('Bob', 'bob@bob.com', 'pass123')
+        User.objects.create_user('Bob', 'bob@bob.com', 'pass123')
 
         response = self.client.get(reverse('test_mail_user'))
         self.assertEqual(response.status_code, 200)

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

@@ -50,7 +50,7 @@ class BatchTests(TestCase):
             ['l', 'o', 'r'],
             ['e', 'm', 'i'],
             ['p', 's', 'u'],
-            ['m',],
+            ['m'],
         )
 
         for i, test_yield in enumerate(misago_batch.batch(batch, 3)):
@@ -70,7 +70,6 @@ class BatchTests(TestCase):
             self.assertEqual(test_yield, yields[i])
 
 
-
 class TestForm(forms.Form):
     somefield = forms.CharField(label="Hello!", max_length=255)
 
@@ -180,4 +179,4 @@ class PaginationTests(TestCase):
 """
 
         tpl = Template(tpl_content)
-        render = tpl.render(self.context).strip()
+        tpl.render(self.context).strip()

+ 0 - 1
misago/core/tests/test_uiviews.py

@@ -5,7 +5,6 @@ from django.http import JsonResponse
 from django.test import TestCase
 
 from misago.admin.testutils import AdminTestCase
-from misago.users.models import AnonymousUser
 
 from misago.core import uiviews
 

+ 0 - 1
misago/core/tests/test_utils.py

@@ -99,7 +99,6 @@ class CleanReturnPathTests(TestCase):
         })
         self.assertEqual(clean_return_path(ok_request), '/register/')
 
-
     def test_post_request(self):
         """clean_return_path works for POST requests"""
         bad_request = MockRequest('POST', {

+ 3 - 1
misago/core/timezones.py

@@ -1,8 +1,10 @@
+# flake8: noqa
 import datetime
 
-from django.utils.translation import ugettext_lazy as _
 import pytz
 
+from django.utils.translation import ugettext_lazy as _
+
 
 TIMEZONES = (
     ('Pacific/Apia', _('(UTC-13:00) Samoa'), _('(UTC-14:00) Samoa')),

+ 2 - 4
misago/faker/management/commands/createfakebans.py

@@ -1,10 +1,8 @@
-import random
 from datetime import timedelta
+import random
+import sys
 
-from django.contrib.auth import get_user_model
-from django.core.exceptions import ValidationError
 from django.core.management.base import BaseCommand
-from django.db import IntegrityError
 from django.utils import timezone
 
 from faker import Factory

+ 1 - 4
misago/faker/management/commands/createfakefollowers.py

@@ -1,12 +1,9 @@
 import random
 
 from django.contrib.auth import get_user_model
-from django.core.exceptions import ValidationError
 from django.core.management.base import BaseCommand
-from django.db import IntegrityError
 
 from misago.core.management.progressbar import show_progress
-from misago.users.models import Rank
 
 
 class Command(BaseCommand):
@@ -29,7 +26,7 @@ class Command(BaseCommand):
             user.followed_by.clear()
 
             users_to_add = random.randint(1, total_users - 1)
-            random_queryset =  User.objects.exclude(id=user.id).order_by('?')
+            random_queryset = User.objects.exclude(id=user.id).order_by('?')
             while users_to_add > 0:
                 new_follower = random_queryset[:1][0]
                 if not new_follower.is_following(user):

+ 2 - 1
misago/faker/management/commands/createfakeusers.py

@@ -1,4 +1,5 @@
-import random, sys
+import random
+import sys
 
 from django.contrib.auth import get_user_model
 from django.core.exceptions import ValidationError

+ 21 - 21
misago/forums/forms.py

@@ -67,24 +67,33 @@ class MisagoForumMixin(object):
 
 class ForumChoiceField(MisagoForumMixin, TreeNodeChoiceField):
     def __init__(self, parent=None, acl=None, *args, **kwargs):
-        kwargs['queryset'] = ForumListLazyQueryset(parent, acl)
+        if not 'queryset' in kwargs:
+            kwargs['queryset'] = ForumListLazyQueryset(parent, acl)
         super(ForumChoiceField, self).__init__(*args, **kwargs)
 
 
 class ForumsMultipleChoiceField(MisagoForumMixin, TreeNodeMultipleChoiceField):
     def __init__(self, parent=None, acl=None, *args, **kwargs):
-        kwargs['queryset'] = ForumListLazyQueryset(parent, acl)
+        if not 'queryset' in kwargs:
+            kwargs['queryset'] = ForumListLazyQueryset(parent, acl)
         super(ForumsMultipleChoiceField, self).__init__(*args, **kwargs)
 
 
 """
 Forms
 """
-class ForumChoiceField(TreeNodeChoiceField):
+FORUM_ROLES = (
+    ('category', _('Category')),
+    ('forum', _('Forum')),
+    ('redirect', _('Redirect')),
+)
+
+
+class AdminForumChoiceField(TreeNodeChoiceField):
     def __init__(self, *args, **kwargs):
         self.base_level = kwargs.pop('base_level', 1)
         kwargs['level_indicator'] = kwargs.get('level_indicator', '- - ')
-        super(ForumChoiceField, self).__init__(*args, **kwargs)
+        super(AdminForumChoiceField, self).__init__(*args, **kwargs)
 
     def _get_level_indicator(self, obj):
         level = getattr(obj, obj._mptt_meta.level_attr) - self.base_level
@@ -94,13 +103,6 @@ class ForumChoiceField(TreeNodeChoiceField):
             return ''
 
 
-FORUM_ROLES = (
-    ('category', _('Category')),
-    ('forum', _('Forum')),
-    ('redirect', _('Redirect')),
-)
-
-
 class ForumFormBase(forms.ModelForm):
     role = forms.ChoiceField(label=_("Type"), choices=FORUM_ROLES)
     name = forms.CharField(
@@ -195,26 +197,24 @@ def ForumFormFactory(instance):
         parent_queryset = parent_queryset.filter(not_siblings)
 
     return type('ForumFormFinal', (ForumFormBase,), {
-        'new_parent': ForumChoiceField(
+        'new_parent': AdminForumChoiceField(
             label=_("Parent forum"),
             queryset=parent_queryset,
             initial=instance.parent,
             empty_label=None),
-        'copy_permissions': ForumChoiceField(
+        'copy_permissions': AdminForumChoiceField(
             label=_("Copy permissions"),
             help_text=_("You can replace this forum permissions with "
                         "permissions copied from forum selected here."),
             queryset=Forum.objects.all_forums(),
             empty_label=_("Don't copy permissions"),
-            base_level=1,
             required=False),
-        'archive_pruned_in': ForumChoiceField(
+        'archive_pruned_in': AdminForumChoiceField(
             label=_("Archive"),
             help_text=_("Instead of being deleted, pruned threads can be "
                         "moved to designated forum."),
             queryset=Forum.objects.all_forums(),
             empty_label=_("Don't archive pruned threads"),
-            base_level=1,
             required=False),
         })
 
@@ -252,9 +252,9 @@ class DeleteForumFormBase(forms.ModelForm):
             if data['move_children_to'].special_role == 'root_category':
                 for child in self.instance.get_children().iterator():
                     if child.role != 'category':
-                        message = _("One or more child forums in forum are not "
-                                    "categories and thus cannot be made root "
-                                    "categories.")
+                        message = _("One or more child forums in forum are "
+                                    "not categories and thus cannot be made "
+                                    "root categories.")
                         raise forms.ValidationError(message)
 
         return data
@@ -263,7 +263,7 @@ class DeleteForumFormBase(forms.ModelForm):
 def DeleteFormFactory(instance):
     content_queryset = Forum.objects.all_forums().order_by('lft')
     fields = {
-        'move_threads_to': ForumChoiceField(
+        'move_threads_to': AdminForumChoiceField(
             label=_("Move forum threads to"),
             queryset=content_queryset,
             initial=instance.parent,
@@ -277,7 +277,7 @@ def DeleteFormFactory(instance):
     children_queryset = children_queryset.filter(not_siblings).order_by('lft')
 
     if children_queryset.exists():
-        fields['move_children_to'] = ForumChoiceField(
+        fields['move_children_to'] = AdminForumChoiceField(
             label=_("Move child forums to"),
             queryset=children_queryset,
             empty_label=_('Delete with forum'),

+ 1 - 2
misago/forums/lists.py

@@ -32,8 +32,7 @@ def get_forums_list(user, parent=None):
 
     flat_list = []
     for forum in forums_list:
-        has_content = (forum.role != "category" or forum.subforums)
-        if forum.level == parent_level and has_content:
+        if forum.role != "category" or forum.subforums:
             flat_list.append(forum)
 
     add_acl(user, flat_list)

+ 2 - 2
misago/forums/migrations/0001_initial.py

@@ -34,8 +34,8 @@ class Migration(migrations.Migration):
                 ('rght', models.PositiveIntegerField(editable=False, db_index=True)),
                 ('tree_id', models.PositiveIntegerField(editable=False, db_index=True)),
                 ('level', models.PositiveIntegerField(editable=False, db_index=True)),
-                ('archive_pruned_in', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, to_field='id', blank=True, to='misago_forums.Forum', null=True)),
-                ('parent', mptt.fields.TreeForeignKey(to_field='id', blank=True, to='misago_forums.Forum', null=True)),
+                ('archive_pruned_in', models.ForeignKey(related_name=b'pruned_archive', on_delete=django.db.models.deletion.SET_NULL, blank=True, to='misago_forums.Forum', null=True)),
+                ('parent', mptt.fields.TreeForeignKey(related_name=b'children', blank=True, to='misago_forums.Forum', null=True)),
             ],
             options={
                 'abstract': False,

+ 4 - 4
misago/forums/tests/test_forums_admin_views.py

@@ -146,7 +146,7 @@ class ForumAdminViewsTests(AdminTestCase):
                              'prune_replied_after': 0,
                          })
 
-        category_a = Forum.objects.get(slug='category-a')
+
         category_b = Forum.objects.get(slug='category-b')
 
         response = self.client.post(
@@ -280,7 +280,7 @@ class ForumAdminDeleteViewTests(AdminTestCase):
         response = self.client.post(
             reverse('misago:admin:forums:nodes:delete',
                     kwargs={'forum_id': self.subforum_d.pk}),
-            data={'move_children_to': '', 'move_threads_to': '',})
+            data={'move_children_to': '', 'move_threads_to': ''})
         self.assertEqual(response.status_code, 302)
         self.assertEqual(Forum.objects.all_forums().count(), 8)
 
@@ -311,14 +311,14 @@ class ForumAdminDeleteViewTests(AdminTestCase):
         response = self.client.post(
             reverse('misago:admin:forums:nodes:delete',
                     kwargs={'forum_id': self.forum_b.pk}),
-            data={'move_children_to': self.root.pk, 'move_threads_to': '',})
+            data={'move_children_to': self.root.pk, 'move_threads_to': ''})
         self.assertEqual(response.status_code, 200)
         self.assertEqual(Forum.objects.all_forums().count(), 9)
 
         response = self.client.post(
             reverse('misago:admin:forums:nodes:delete',
                     kwargs={'forum_id': self.forum_b.pk}),
-            data={'move_children_to': '', 'move_threads_to': '',})
+            data={'move_children_to': '', 'move_threads_to': ''})
         self.assertEqual(response.status_code, 302)
 
         self.assertEqual(Forum.objects.all_forums().count(), 6)

+ 12 - 2
misago/forums/tests/test_lists.py

@@ -1,5 +1,6 @@
 from django.test import TestCase
 
+from misago.acl.testutils import override_acl
 from misago.admin.testutils import AdminTestCase
 
 from misago.forums.lists import get_forums_list, get_forum_path
@@ -7,15 +8,24 @@ from misago.forums.models import Forum
 
 
 class GetForumListTests(AdminTestCase):
+    def setUp(self):
+        super(GetForumListTests, self).setUp()
+
+        forums_acl = {'forums': {}, 'visible_forums': []}
+        for forum in Forum.objects.all_forums():
+            forums_acl['visible_forums'].append(forum.pk)
+            forums_acl['forums'][forum.pk] = {'can_see': 1, 'can_browse': 1}
+        override_acl(self.test_admin, forums_acl)
+
     def test_root_forums_list_no_parent(self):
         """get_forums_list returns all children of root nodes"""
         self.assertEqual(len(get_forums_list(self.test_admin)), 3)
 
-    def test_root_forums_list_no_parent(self):
+    def test_root_forums_list_with_parents(self):
         """get_forums_list returns all children of given node"""
         for i, node in enumerate(get_forums_list(self.test_admin)):
             child_nodes = len(get_forums_list(self.test_admin, node))
-            self.assertEqual(child_nodes, 3 - 1)
+            self.assertEqual(child_nodes, len(node.get_descendants()))
 
 
 class GetForumPathTests(TestCase):

+ 0 - 2
misago/forums/views/permsadmin.py

@@ -27,7 +27,6 @@ class ForumRolesList(ForumRoleAdmin, generic.ListView):
 
 class RoleFormMixin(object):
     def real_dispatch(self, request, target):
-        role_permissions = target.permissions
         form = ForumRoleForm(instance=target)
 
         perms_forms = get_permissions_forms(target)
@@ -96,7 +95,6 @@ class ForumPermissions(ForumAdmin, generic.ModelFormView):
     def real_dispatch(self, request, target):
         forum_roles = ForumRole.objects.order_by('name')
 
-
         assigned_roles = {}
         for acl in target.forum_role_set.select_related('forum_role'):
             assigned_roles[acl.role_id] = acl.forum_role

+ 1 - 0
misago/legal/__init__.py

@@ -0,0 +1 @@
+default_app_config = 'misago.legal.apps.MisagoLegalConfig'

+ 7 - 3
misago/markup/__init__.py

@@ -1,5 +1,9 @@
+# flake8: noqa
 from misago.markup.flavours import (common as common_flavour,
                                     limited as limited_flavour,
-                                    signature as signature_flavour)  # noqa
-from misago.markup.parser import parse  # noqa
-from misago.markup.editor import Editor  # noqa
+                                    signature as signature_flavour)
+from misago.markup.parser import parse
+from misago.markup.editor import Editor
+
+
+default_app_config = 'misago.markup.apps.MisagoMarkupConfig'

+ 1 - 1
misago/markup/templatetags/misago_editor.py

@@ -8,7 +8,7 @@ register = template.Library()
 
 def _render_editor_template(context, editor, tpl):
     c = Context(context)
-    c['editor'] =  editor
+    c['editor'] = editor
 
     return get_template(tpl).render(c)
 

+ 0 - 3
misago/markup/tests.py

@@ -68,6 +68,3 @@ class ChecksupTests(TestCase):
             checksums.is_checksum_valid(fake_message, checksum, [post_pk]))
         self.assertFalse(
             checksums.is_checksum_valid(fake_message, checksum, [3]))
-
-
-

+ 3 - 0
misago/notifications/__init__.py

@@ -1 +1,4 @@
 from misago.notifications.api import *  # noqa
+
+
+default_app_config = 'misago.notifications.apps.MisagoNotificationsConfig'

+ 2 - 1
misago/notifications/api.py

@@ -2,7 +2,6 @@ from django.db.models import F
 from django.db import transaction
 from django.utils.html import escape
 
-from misago.notifications.models import Notification
 from misago.notifications.utils import hash_trigger
 
 
@@ -16,6 +15,8 @@ __all__ = [
 
 def notify_user(user, message, url, trigger, formats=None, sender=None,
                 update_user=True):
+    from misago.notifications.models import Notification
+
     message_escaped = escape(message)
     if formats:
         final_formats = {}

+ 5 - 4
misago/notifications/migrations/0001_initial.py

@@ -2,6 +2,7 @@
 from __future__ import unicode_literals
 
 from django.db import models, migrations
+import django.db.models.deletion
 import django.utils.timezone
 from django.conf import settings
 
@@ -22,10 +23,10 @@ class Migration(migrations.Migration):
                 ('trigger', models.CharField(max_length=8)),
                 ('message', models.TextField()),
                 ('url', models.TextField()),
-                ('sender_username', models.CharField(max_length=255, blank=True, null=True)),
-                ('sender_slug', models.CharField(max_length=255, blank=True, null=True)),
-                ('sender', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, to=settings.AUTH_USER_MODEL, null=True)),
-                ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
+                ('sender_username', models.CharField(max_length=255, null=True, blank=True)),
+                ('sender_slug', models.CharField(max_length=255, null=True, blank=True)),
+                ('sender', models.ForeignKey(related_name=b'notifications_by', on_delete=django.db.models.deletion.SET_NULL, blank=True, to=settings.AUTH_USER_MODEL, null=True)),
+                ('user', models.ForeignKey(related_name=b'notifications', to=settings.AUTH_USER_MODEL)),
             ],
             options={
             },

+ 3 - 5
misago/notifications/models.py

@@ -1,5 +1,3 @@
-import cgi
-
 from django.conf import settings
 from django.db import models
 from django.utils import timezone
@@ -14,8 +12,8 @@ class Notification(models.Model):
     message = models.TextField()
     url = models.TextField()
     sender = models.ForeignKey(settings.AUTH_USER_MODEL,
-                           on_delete=models.SET_NULL,
-                           related_name='notifications_by',
-                           blank=True, null=True)
+                               on_delete=models.SET_NULL,
+                               related_name='notifications_by',
+                               blank=True, null=True)
     sender_username = models.CharField(max_length=255, blank=True, null=True)
     sender_slug = models.CharField(max_length=255, blank=True, null=True)

+ 0 - 3
misago/notifications/views.py

@@ -1,10 +1,7 @@
-from datetime import timedelta
-
 from django.contrib import messages
 from django.db.transaction import atomic
 from django.http import JsonResponse
 from django.shortcuts import redirect, render
-from django.utils import timezone
 from django.utils.translation import ugettext as _, ungettext
 
 from misago.core.uiviews import uiview

+ 1 - 0
misago/threads/__init__.py

@@ -0,0 +1 @@
+default_app_config = 'misago.threads.apps.MisagoThreadsConfig'

+ 0 - 1
misago/threads/forms/admin.py

@@ -3,7 +3,6 @@ from django.utils.translation import ugettext_lazy as _
 from misago.core import forms
 from misago.core.validators import validate_sluggable
 from misago.forums.forms import ForumsMultipleChoiceField
-from misago.forums.models import Forum
 
 from misago.threads.models import Prefix
 

+ 1 - 1
misago/threads/migrations/0001_initial.py

@@ -18,7 +18,7 @@ class Migration(migrations.Migration):
                 ('name', models.CharField(max_length=255)),
                 ('slug', models.SlugField(max_length=255)),
                 ('css_class', models.CharField(max_length=255, null=True, blank=True)),
-                ('forums', models.ManyToManyField(to='misago_forums.Forum')),
+                ('forums', models.ManyToManyField(related_name=b'prefixes', to='misago_forums.Forum')),
             ],
             options={
             },

+ 1 - 0
misago/threads/models/__init__.py

@@ -1,3 +1,4 @@
+# flake8: noqa
 #from misago.threads.models.thread import Thread
 #from misago.threads.models.post import Post
 from misago.threads.models.prefix import Prefix

+ 0 - 1
misago/threads/models/prefix.py

@@ -45,7 +45,6 @@ class Prefix(models.Model):
 
     objects = PrefixManager()
 
-
     def delete(self, *args, **kwargs):
         Prefix.objects.clear_cache()
         return super(Prefix, self).delete(*args, **kwargs)

+ 0 - 1
misago/threads/tests/test_prefix_model.py

@@ -1,4 +1,3 @@
-from django.core.exceptions import ValidationError
 from django.test import TestCase
 
 from misago.forums.models import Forum

+ 2 - 1
misago/threads/tests/test_prefixesadmin_views.py

@@ -37,7 +37,8 @@ class PrefixAdminViewsTests(AdminTestCase):
             })
         self.assertEqual(response.status_code, 302)
 
-        response = self.client.get(reverse('misago:admin:forums:prefixes:index'))
+        response = self.client.get(
+            reverse('misago:admin:forums:prefixes:index'))
         self.assertEqual(response.status_code, 200)
         self.assertIn('Test Prefix', response.content)
         self.assertIn('test_prefix', response.content)

+ 0 - 1
misago/users/admin.py

@@ -1,5 +1,4 @@
 from django.conf.urls import url
-from django.conf.urls import url
 from django.contrib import admin as djadmin
 from django.contrib.auth import get_user_model
 from django.utils.translation import ugettext_lazy as _

+ 7 - 0
misago/users/apps.py

@@ -37,6 +37,7 @@ class MisagoUsersConfig(AppConfig):
     def register_default_users_list_pages(self):
         def can_see_online_list(request):
             return request.user.acl['can_see_users_online_list']
+
         users_list.add_page(link='misago:users_active_posters',
                             name=_('Active posters'))
         users_list.add_page(link='misago:users_online',
@@ -46,12 +47,16 @@ class MisagoUsersConfig(AppConfig):
     def register_default_user_profile_pages(self):
         def posts_badge(request, profile):
             return profile.posts
+
         def threads_badge(request, profile):
             return profile.threads
+
         def followers_badge(request, profile):
             return profile.followers
+
         def following_badge(request, profile):
             return profile.following
+
         def can_see_names_history(request, profile):
             if request.user.is_authenticated():
                 is_account_owner = profile.pk == request.user.pk
@@ -59,6 +64,7 @@ class MisagoUsersConfig(AppConfig):
                 return is_account_owner or has_permission
             else:
                 return False
+
         def can_see_warnings(request, profile):
             if request.user.is_authenticated():
                 is_account_owner = profile.pk == request.user.pk
@@ -67,6 +73,7 @@ class MisagoUsersConfig(AppConfig):
                 return is_account_owner or has_permission
             else:
                 return False
+
         def can_see_ban_details(request, profile):
             if request.user.is_authenticated():
                 if request.user.acl['can_see_ban_details']:

+ 0 - 1
misago/users/avatars/dynamic.py

@@ -1,4 +1,3 @@
-from hashlib import md5
 from importlib import import_module
 import math
 import os

+ 0 - 2
misago/users/avatars/paths.py

@@ -1,7 +1,5 @@
 import os
 
-from path import path
-
 from misago.conf import settings
 
 

+ 0 - 1
misago/users/decorators.py

@@ -40,4 +40,3 @@ def deny_banned_ips(f):
         else:
             return f(request, *args, **kwargs)
     return decorator
-

+ 2 - 2
misago/users/forms/admin.py

@@ -240,7 +240,6 @@ def SearchUsersForm(*args, **kwargs):
             roles_choices.append((role.pk, role.name))
         threadstore.set('misago_admin_roles_choices', roles_choices)
 
-
     extra_fields = {
         'rank': forms.TypedChoiceField(label=_("Has rank"),
                                        coerce=int,
@@ -362,7 +361,8 @@ class BanForm(forms.ModelForm):
                     'for rought matches. For example, making IP ban for value '
                     '"83.*" will ban all IP addresses beginning with "83.".'),
         error_messages={
-            'max_length': _("Banned value can't be longer than 250 characters.")
+            'max_length': _("Banned value can't be longer "
+                            "than 250 characters.")
         })
     user_message = forms.CharField(
         label=_("User message"), required=False, max_length=1000,

+ 1 - 1
misago/users/forms/auth.py

@@ -125,7 +125,7 @@ class GetUserForm(MisagoAuthMixin, forms.Form):
 
         try:
             User = get_user_model()
-            user =  User.objects.get_by_username_or_email(data['username'])
+            user = User.objects.get_by_username_or_email(data['username'])
             self.user_cache = user
         except User.DoesNotExist:
             raise forms.ValidationError(_("Invalid username or e-mail."))

+ 1 - 2
misago/users/forms/modusers.py

@@ -6,10 +6,9 @@ from django.utils import timezone
 
 from misago.conf import settings
 from misago.core import forms
-from misago.core.utils import clean_return_path
 
 from misago.users.forms.admin import BanUsersForm
-from misago.users.models import Ban, BAN_EMAIL, BAN_USERNAME
+from misago.users.models import Ban
 
 
 class WarnUserForm(forms.Form):

+ 2 - 4
misago/users/management/commands/bansmaintenance.py

@@ -1,8 +1,6 @@
 from django.core.management.base import BaseCommand
 from django.utils import timezone
 
-from misago.core import cachebuster
-
 from misago.users.models import BanCache
 
 
@@ -18,7 +16,7 @@ class Command(BaseCommand):
         queryset = queryset.filter(valid_until__lte=timezone.now().date())
 
         expired_count = queryset.update(is_valid=False)
-        self.stdout.write('Bans invalidated: %s' expired_count)
+        self.stdout.write('Bans invalidated: %s' % expired_count)
 
     def handle_bans_caches(self):
         queryset = BanCache.objects.filter(valid_until__isnull=False)
@@ -30,4 +28,4 @@ class Command(BaseCommand):
         queryset = BanCache.objects.filter(bans_version__lt=bans_version)
         expired_count += queryset.delete()
 
-        self.stdout.write('Ban caches emptied: %s' expired_count)
+        self.stdout.write('Ban caches emptied: %s' % expired_count)

+ 0 - 2
misago/users/middleware.py

@@ -2,12 +2,10 @@ from django.conf import settings
 from django.contrib.auth import logout
 from django.contrib.auth.models import AnonymousUser as DjAnonymousUser
 from django.core.urlresolvers import resolve
-from django.utils import timezone
 
 from misago.users.bans import get_request_ip_ban, get_user_ban
 from misago.users.models import AnonymousUser, Online
 from misago.users.online import tracker
-from misago.users.views import avatarserver
 
 
 class RealIPMiddleware(object):

+ 1 - 0
misago/users/models/__init__.py

@@ -1,3 +1,4 @@
+# flake8: noqa
 from misago.users.models.rank import *
 from misago.users.models.user import *
 from misago.users.models.bans import *

+ 2 - 3
misago/users/models/bans.py

@@ -1,4 +1,4 @@
-from datetime import date, timedelta
+from datetime import timedelta
 import re
 
 from django.conf import settings
@@ -7,7 +7,6 @@ from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 
 from misago.core import cachebuster
-from misago.core.utils import time_amount
 
 
 __all__ = [
@@ -107,7 +106,7 @@ class Ban(models.Model):
     def test_value(self, value):
         if '*' in self.banned_value:
             regex = re.escape(self.banned_value).replace('\*', '(.*?)')
-            return re.search('^%s$' % regex, value) != None
+            return re.search('^%s$' % regex, value) is not None
         else:
             return self.banned_value == value
 

+ 0 - 1
misago/users/models/rank.py

@@ -1,7 +1,6 @@
 from django.db import models, transaction
 
 from misago.acl import version as acl_version
-from misago.core.cache import cache
 from misago.core.utils import slugify
 
 

+ 3 - 4
misago/users/models/user.py

@@ -86,8 +86,8 @@ class UserManager(BaseUserManager):
                 extra_fields['subscribe_to_replied_threads'] = new_value
 
             now = timezone.now()
-            user = self.model(is_staff=False, is_superuser=False, last_login=now,
-                              joined_on=now, **extra_fields)
+            user = self.model(is_staff=False, is_superuser=False,
+                              last_login=now, joined_on=now, **extra_fields)
 
             user.set_username(username)
             user.set_email(email)
@@ -122,7 +122,6 @@ class UserManager(BaseUserManager):
             except Rank.DoesNotExist:
                 pass
 
-
             user.is_staff = True
             user.is_superuser = True
 
@@ -218,7 +217,7 @@ class User(AbstractBaseUser, PermissionsMixin):
     last_post = models.DateTimeField(null=True, blank=True)
     last_search = models.DateTimeField(null=True, blank=True)
 
-    is_active = True # Django's is_active means "is not deleted"
+    is_active = True  # Django's is_active means "is not deleted"
 
     USERNAME_FIELD = 'slug'
     REQUIRED_FIELDS = ['email']

+ 6 - 7
misago/users/models/warnings.py

@@ -2,7 +2,6 @@ from collections import OrderedDict
 from datetime import timedelta
 
 from django.conf import settings
-from django.contrib.auth import get_user_model
 from django.db import models
 from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
@@ -119,17 +118,17 @@ class UserWarning(models.Model):
     reason = models.TextField(null=True, blank=True)
     given_on = models.DateTimeField(default=timezone.now)
     giver = models.ForeignKey(settings.AUTH_USER_MODEL,
-                                 null=True, blank=True,
-                                 on_delete=models.SET_NULL,
-                                 related_name="warnings_given")
+                              null=True, blank=True,
+                              on_delete=models.SET_NULL,
+                              related_name="warnings_given")
     giver_username = models.CharField(max_length=255)
     giver_slug = models.CharField(max_length=255)
     is_canceled = models.BooleanField(default=False)
     canceled_on = models.DateTimeField(null=True, blank=True)
     canceler = models.ForeignKey(settings.AUTH_USER_MODEL,
-                                    null=True, blank=True,
-                                    on_delete=models.SET_NULL,
-                                    related_name="warnings_canceled")
+                                 null=True, blank=True,
+                                 on_delete=models.SET_NULL,
+                                 related_name="warnings_canceled")
     canceler_username = models.CharField(max_length=255)
     canceler_slug = models.CharField(max_length=255)
 

+ 1 - 1
misago/users/namechanges.py

@@ -22,7 +22,7 @@ class UsernameChanges(object):
         valid_changes_qs = user.namechanges.filter(changed_by=user)
         if name_changes_expire:
             cutoff = timezone.now() - timedelta(days=name_changes_expire)
-            valid_changes_qs = used_changes_qs.filter(changed_on__gte=cutoff)
+            valid_changes_qs = valid_changes_qs.filter(changed_on__gte=cutoff)
 
         used_changes = valid_changes_qs.count()
         if name_changes_allowed <= used_changes:

+ 1 - 5
misago/users/online/ranks.py

@@ -1,10 +1,6 @@
-from datetime import timedelta
-
-from django.utils import timezone
-
 from misago.core.cache import cache
 
-from misago.users.models import Online, Rank
+from misago.users.models import Rank
 from misago.users.online.utils import get_online_queryset
 
 

+ 12 - 12
misago/users/permissions/profiles.py

@@ -89,18 +89,18 @@ def build_acl(acl, roles, key_name):
     new_acl.update(acl)
 
     return algebra.sum_acls(
-            new_acl, roles=roles, key=key_name,
-            can_browse_users_list=algebra.greater,
-            can_see_users_online_list=algebra.greater,
-            can_search_users=algebra.greater,
-            can_follow_users=algebra.greater,
-            can_be_blocked=algebra.lower,
-            can_see_users_name_history=algebra.greater,
-            can_see_ban_details=algebra.greater,
-            can_see_users_emails=algebra.greater,
-            can_see_users_ips=algebra.greater,
-            can_see_hidden_users=algebra.greater
-            )
+        new_acl, roles=roles, key=key_name,
+        can_browse_users_list=algebra.greater,
+        can_see_users_online_list=algebra.greater,
+        can_search_users=algebra.greater,
+        can_follow_users=algebra.greater,
+        can_be_blocked=algebra.lower,
+        can_see_users_name_history=algebra.greater,
+        can_see_ban_details=algebra.greater,
+        can_see_users_emails=algebra.greater,
+        can_see_users_ips=algebra.greater,
+        can_see_hidden_users=algebra.greater
+        )
 
 
 """

+ 7 - 11
misago/users/permissions/warnings.py

@@ -63,13 +63,13 @@ def build_acl(acl, roles, key_name):
     new_acl.update(acl)
 
     return algebra.sum_acls(
-            new_acl, roles=roles, key=key_name,
-            can_see_other_users_warnings=algebra.greater,
-            can_warn_users=algebra.greater,
-            can_cancel_warnings=algebra.greater,
-            can_delete_warnings=algebra.greater,
-            can_be_warned=algebra.lower
-            )
+        new_acl, roles=roles, key=key_name,
+        can_see_other_users_warnings=algebra.greater,
+        can_warn_users=algebra.greater,
+        can_cancel_warnings=algebra.greater,
+        can_delete_warnings=algebra.greater,
+        can_be_warned=algebra.lower
+        )
 
 
 """
@@ -90,10 +90,6 @@ def add_acl_to_user(user, target):
     target_acl['can_cancel_warnings'] = False
     target_acl['can_delete_warnings'] = False
 
-    mod_permissions = (
-        'can_warn',
-    )
-
     if target_acl['can_warn']:
         target_acl['can_moderate'] = True
 

+ 0 - 2
misago/users/templatetags/misago_avatars.py

@@ -1,5 +1,3 @@
-import hashlib
-
 from django import template
 from django.core.urlresolvers import reverse
 

+ 0 - 3
misago/users/tests/test_avatars.py

@@ -8,7 +8,6 @@ from django.test import TestCase
 from misago.conf import settings
 
 from misago.users.avatars import store, dynamic, gallery, gravatar, uploaded
-from misago.users.avatars.paths import AVATARS_STORE
 
 
 class AvatarsStoreTests(TestCase):
@@ -142,5 +141,3 @@ class UploadedAvatarTests(TestCase):
         for valid_mime in uploaded.ALLOWED_MIME_TYPES:
             image = MockAvatarFile(mime=valid_mime)
             uploaded.validate_mime(image)
-
-

+ 0 - 1
misago/users/tests/test_avatarserver_views.py

@@ -1,6 +1,5 @@
 from django.contrib.auth import get_user_model
 from django.core.urlresolvers import reverse
-from django.template import Context, Template
 from django.test import TestCase
 
 

+ 4 - 4
misago/users/tests/test_ban_model.py

@@ -13,26 +13,26 @@ class BansManagerTests(TestCase):
 
     def test_find_ban_for_banned_name(self):
         """find_ban finds ban for given username"""
-        self.assertTrue(Ban.objects.find_ban(username='Bob') != None)
+        self.assertIsNotNone(Ban.objects.find_ban(username='Bob'))
         with self.assertRaises(Ban.DoesNotExist):
             Ban.objects.find_ban(username='Jeb')
 
     def test_find_ban_for_banned_email(self):
         """find_ban finds ban for given email"""
-        self.assertTrue(Ban.objects.find_ban(email='bob@test.com') != None)
+        self.assertIsNotNone(Ban.objects.find_ban(email='bob@test.com'))
         with self.assertRaises(Ban.DoesNotExist):
             Ban.objects.find_ban(email='jeb@test.com')
 
     def test_find_ban_for_banned_ip(self):
         """find_ban finds ban for given ip"""
-        self.assertTrue(Ban.objects.find_ban(ip='127.0.0.1') != None)
+        self.assertIsNotNone(Ban.objects.find_ban(ip='127.0.0.1'))
         with self.assertRaises(Ban.DoesNotExist):
             Ban.objects.find_ban(ip='42.0.0.1')
 
     def test_find_ban_for_all_bans(self):
         """find_ban finds ban for given values"""
         valid_kwargs = {'username': 'bob', 'ip': '42.51.52.51'}
-        self.assertTrue(Ban.objects.find_ban(**valid_kwargs) != None)
+        self.assertIsNotNone(Ban.objects.find_ban(**valid_kwargs))
 
         invalid_kwargs = {'username': 'bsob', 'ip': '42.51.52.51'}
         with self.assertRaises(Ban.DoesNotExist):

+ 2 - 3
misago/users/tests/test_lists_views.py

@@ -4,7 +4,7 @@ from django.core.urlresolvers import reverse
 from misago.acl.testutils import override_acl
 from misago.admin.testutils import AdminTestCase
 
-from misago.users.models import Ban, Rank
+from misago.users.models import Rank
 
 
 class UsersListTestCase(AdminTestCase):
@@ -30,7 +30,7 @@ class UsersListLanderTests(UsersListTestCase):
         response = self.client.get(reverse('misago:users'))
         self.assertEqual(response.status_code, 302)
         self.assertTrue(response['location'].endswith(
-                         reverse('misago:users_active_posters')))
+                        reverse('misago:users_active_posters')))
 
 
 class ActivePostersTests(UsersListTestCase):
@@ -90,4 +90,3 @@ class UsersRankTests(UsersListTestCase):
                 self.assertEqual(response.status_code, 200)
             else:
                 self.assertEqual(response.status_code, 404)
-

+ 3 - 3
misago/users/tests/test_profile_views.py

@@ -167,9 +167,9 @@ class UserProfileViewsTests(AdminTestCase):
             'can_see_ban_details': 1,
         })
 
-        test_ban = Ban.objects.create(banned_value=test_user.username,
-                                      user_message="User m3ss4ge.",
-                                      staff_message="Staff m3ss4ge.")
+        Ban.objects.create(banned_value=test_user.username,
+                           user_message="User m3ss4ge.",
+                           staff_message="Staff m3ss4ge.")
 
         response = self.client.get(reverse('misago:user_ban',
                                            kwargs=link_kwargs))

+ 6 - 6
misago/users/tests/test_registration_views.py

@@ -46,8 +46,8 @@ class RegisterViewTests(TestCase):
         self.assertIn('Bob', response.content)
 
         User = get_user_model()
-        user = User.objects.get_by_username('Bob')
-        user = User.objects.get_by_email('bob@bob.com')
+        User.objects.get_by_username('Bob')
+        User.objects.get_by_email('bob@bob.com')
 
         response = self.client.get(reverse('misago:index'))
         self.assertIn('Bob', response.content)
@@ -68,8 +68,8 @@ class RegisterViewTests(TestCase):
         self.assertIn('bob@bob.com', response.content)
 
         User = get_user_model()
-        user = User.objects.get_by_username('Bob')
-        user = User.objects.get_by_email('bob@bob.com')
+        User.objects.get_by_username('Bob')
+        User.objects.get_by_email('bob@bob.com')
 
         self.assertIn('Welcome', mail.outbox[0].subject)
 
@@ -87,7 +87,7 @@ class RegisterViewTests(TestCase):
         self.assertIn('administrator', response.content)
 
         User = get_user_model()
-        user = User.objects.get_by_username('Bob')
-        user = User.objects.get_by_email('bob@bob.com')
+        User.objects.get_by_username('Bob')
+        User.objects.get_by_email('bob@bob.com')
 
         self.assertIn('Welcome', mail.outbox[0].subject)

+ 1 - 1
misago/users/tests/test_usercp_views.py

@@ -288,7 +288,7 @@ class ChangeEmailPasswordTests(AdminTestCase):
         self.assertEqual(response.status_code, 302)
 
         User = get_user_model()
-        test_user = User.objects.get(email='newmail@test.com')
+        User.objects.get(email='newmail@test.com')
 
     def test_change_password(self):
         """POST to usercp change password view returns 302"""

+ 1 - 0
misago/users/tests/test_validators.py

@@ -48,6 +48,7 @@ class ValidateEmailBannedTests(TestCase):
         with self.assertRaises(ValidationError):
             validate_email_banned('ban@test.com')
 
+
 class ValidateEmailTests(TestCase):
     def test_validate_email(self):
         """validate_email has no crashes"""

+ 2 - 1
misago/users/tests/test_warningadmin_views.py

@@ -39,7 +39,8 @@ class WarningsAdminViewsTests(AdminTestCase):
             })
         self.assertEqual(response.status_code, 302)
 
-        response = self.client.get(reverse('misago:admin:users:warnings:index'))
+        response = self.client.get(
+            reverse('misago:admin:users:warnings:index'))
         self.assertEqual(response.status_code, 200)
         self.assertIn('Test Level', response.content)
 

+ 6 - 5
misago/users/tests/test_warnings_views.py

@@ -29,9 +29,8 @@ class WarningTestCase(AdminTestCase):
 
     def warn_user(self, reason):
         override_acl(self.test_admin, {'can_warn_users': 1})
-        response = self.client.post(
-            reverse('misago:warn_user', kwargs=self.link_kwargs),
-            data={'reason': reason})
+        self.client.post(reverse('misago:warn_user', kwargs=self.link_kwargs),
+                         data={'reason': reason})
 
 
 class WarnUserTests(WarningTestCase):
@@ -156,7 +155,8 @@ class CancelWarningTests(WarningTestCase):
                 'warning_id': warning.pk
             }))
         self.assertEqual(response.status_code, 403)
-        self.assertFalse(self.test_user.warnings.get(id=warning.pk).is_canceled)
+        self.assertFalse(
+            self.test_user.warnings.get(id=warning.pk).is_canceled)
 
     def test_no_permission_other(self):
         """can't cancel other mod warnings"""
@@ -170,7 +170,8 @@ class CancelWarningTests(WarningTestCase):
                 'warning_id': warning.pk
             }))
         self.assertEqual(response.status_code, 403)
-        self.assertFalse(self.test_user.warnings.get(id=warning.pk).is_canceled)
+        self.assertFalse(
+            self.test_user.warnings.get(id=warning.pk).is_canceled)
 
         warning = warn_user(self.test_admin, self.test_user)
         self.allow_cancel_owned_warning()

+ 0 - 1
misago/users/urls.py

@@ -1,4 +1,3 @@
-from django.conf import settings
 from django.conf.urls import include, patterns, url
 
 

+ 1 - 3
misago/users/views/admin/users.py

@@ -95,7 +95,7 @@ class UsersList(UserAdmin, generic.ListView):
             queryset.update(requires_activation=ACTIVATION_REQUIRED_NONE)
 
             mail_subject = _("Your account on %(forum_title)s "
-                                 "forums has been activated")
+                             "forums has been activated")
             subject_formats = {'forum_title': settings.forum_name}
             mail_subject = mail_subject % subject_formats
 
@@ -138,7 +138,6 @@ class UsersList(UserAdmin, generic.ListView):
             })
 
     def action_delete_accounts(self, request, users):
-        inactive_users = []
         for user in users:
             if user.is_staff or user.is_superuser:
                 message = _("%(user)s is admin and can't be deleted.")
@@ -152,7 +151,6 @@ class UsersList(UserAdmin, generic.ListView):
         messages.success(request, message)
 
     def action_delete_all(self, request, users):
-        inactive_users = []
         for user in users:
             if user.is_staff or user.is_superuser:
                 message = _("%(user)s is admin and can't be deleted.")

+ 0 - 1
misago/users/views/admin/warnings.py

@@ -2,7 +2,6 @@ from django.contrib import messages
 from django.utils.translation import ugettext_lazy as _
 
 from misago.admin.views import generic
-from misago.core import cachebuster
 
 from misago.users.models import WarningLevel
 from misago.users.forms.admin import WarningLevelForm

+ 0 - 1
misago/users/views/auth.py

@@ -1,6 +1,5 @@
 from django.conf import settings
 from django.contrib import auth, messages
-from django.http import Http404
 from django.shortcuts import render, redirect
 from django.utils.translation import ugettext as _
 from django.views.decorators.cache import never_cache

+ 0 - 3
misago/users/views/forgottenpassword.py

@@ -1,4 +1,3 @@
-from faker import Factory
 from django.contrib import messages
 from django.contrib.auth import get_user_model
 from django.http import Http404
@@ -12,7 +11,6 @@ from misago.core.mail import mail_user
 from misago.users.bans import get_user_ban
 from misago.users.decorators import deny_authenticated, deny_banned_ips
 from misago.users.forms.auth import ResetPasswordForm, SetNewPasswordForm
-from misago.users.models import ACTIVATION_REQUIRED_NONE
 from misago.users.tokens import (make_password_reset_token,
                                  is_password_reset_token_valid)
 
@@ -121,6 +119,5 @@ def reset_password_form(request, user_id, token):
             messages.success(request, message)
             return redirect(settings.LOGIN_URL)
 
-
     return render(request, 'misago/forgottenpassword/reset_password_form.html',
                   {'requesting_user': requesting_user, 'form': form})

+ 3 - 3
misago/users/views/lists.py

@@ -72,7 +72,7 @@ def active_posters(request, page=0):
     User = get_user_model()
     queryset = User.objects.all().select_related('user__rank')
 
-    template =  "misago/userslists/active_posters.html"
+    template = "misago/userslists/active_posters.html"
     return list_view(request, template, queryset, page, {
         'tracked_period': tracked_period
     })
@@ -83,7 +83,7 @@ def online(request, page=0):
     queryset = get_online_queryset(request.user).order_by('user__slug')
     queryset = queryset.select_related('user__rank')
 
-    template =  "misago/userslists/online.html"
+    template = "misago/userslists/online.html"
     return list_view(request, template, queryset, page, {
         'data_from': timezone.now()
     })
@@ -94,5 +94,5 @@ def rank(request, rank_slug, page=0):
     rank = get_object_or_404(Rank.objects.filter(is_tab=True), slug=rank_slug)
     queryset = rank.user_set.order_by('slug')
 
-    template =  "misago/userslists/rank.html"
+    template = "misago/userslists/rank.html"
     return list_view(request, template, queryset, page, {'rank': rank})

+ 3 - 1
misago/users/views/profile.py

@@ -249,6 +249,7 @@ def follow_user(request, profile):
         request.user.follows.remove(profile)
         followed = False
     else:
+        allow_follow_user(request.user, profile)
         followed = True
         request.user.follows.add(profile)
 
@@ -284,12 +285,13 @@ def follow_user(request, profile):
 
 @action_view
 def block_user(request, profile):
-    user_locked = request.user.lock()
+    request.user.lock()
 
     if request.user.is_blocking(profile):
         request.user.blocks.remove(profile)
         blocked = False
     else:
+        allow_block_user(request.user, profile)
         blocked = True
         request.user.blocks.add(profile)
 

+ 1 - 2
misago/users/views/register.py

@@ -90,7 +90,7 @@ def register(request):
                 request.session['registered_user'] = new_user.pk
                 return redirect('misago:register_completed')
 
-    return render(request, 'misago/register/form.html', {'form': form, 'testname': 'and<b>rzej'})
+    return render(request, 'misago/register/form.html', {'form': form})
 
 
 def register_disabled(request):
@@ -122,4 +122,3 @@ def register_completed(request):
             'activation_by_user': activation_by_user,
             'registered_user': registered_user,
         })
-

+ 2 - 2
misago/users/views/usercp.py

@@ -124,7 +124,7 @@ def upload_avatar_handler(request):
     if not settings.allow_custom_avatars:
         raise AjaxError(_("Avatar uploads are currently disabled."))
 
-    new_avatar = request.FILES.get('new-avatar');
+    new_avatar = request.FILES.get('new-avatar')
     if not new_avatar:
         raise AjaxError(_("No file was sent."))
 
@@ -145,7 +145,7 @@ def crop_avatar(request, use_tmp_avatar):
             return redirect('misago:usercp_change_avatar')
     else:
         if not avatars.uploaded.has_original_avatar(request.user):
-            messages.error(request, _("You don't have uploaded image to crop."))
+            messages.error(request, _("You haven't uploaded image to crop."))
             return redirect('misago:usercp_change_avatar')
 
     if use_tmp_avatar:

+ 0 - 1
misago/users/warnings.py

@@ -43,7 +43,6 @@ def fetch_user_valid_warnings(user):
     return active_warnings
 
 
-
 def update_user_warning_level(user):
     warnings = fetch_user_valid_warnings(user)
     user.warning_level = len(warnings)

+ 0 - 3
runtests.py

@@ -3,10 +3,7 @@ import pwd
 import shutil
 import sys
 
-from path import path
-
 from django import setup
-from django.core.management import call_command
 from django.test.utils import setup_test_environment