Browse Source

Code maintenance

Rafał Pitoń 10 years ago
parent
commit
b1b33dd1f7
93 changed files with 188 additions and 235 deletions
  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):
 def lower(a, b):
     return a if a < b else 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.permissions_cache = serializer.loads(
                     self.pickled_permissions)
                     self.pickled_permissions)
             else:
             else:
-               self.permissions_cache = {}
+                self.permissions_cache = {}
         return self.permissions_cache
         return self.permissions_cache
 
 
     @permissions.setter
     @permissions.setter

+ 0 - 1
misago/acl/panels.py

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

+ 2 - 4
misago/acl/testutils.py

@@ -1,10 +1,8 @@
 from hashlib import md5
 from hashlib import md5
-from time import time
 
 
 from misago.core import threadstore
 from misago.core import threadstore
 
 
 from misago.acl.forms import get_permissions_forms
 from misago.acl.forms import get_permissions_forms
-from misago.acl.models import Role
 
 
 
 
 def fake_post_data(target, data_dict):
 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 form in get_permissions_forms(target):
         for field in form:
         for field in form:
-            if field.value() == True:
+            if field.value() is True:
                 data_dict[field.html_name] = 1
                 data_dict[field.html_name] = 1
-            elif field.value() == False:
+            elif field.value() is False:
                 data_dict[field.html_name] = 0
                 data_dict[field.html_name] = 0
             else:
             else:
                 data_dict[field.html_name] = field.value()
                 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):
 class RoleFormMixin(object):
     def real_dispatch(self, request, target):
     def real_dispatch(self, request, target):
-        role_permissions = target.permissions
         form = RoleForm(instance=target)
         form = RoleForm(instance=target)
 
 
         perms_forms = get_permissions_forms(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.conf.urls import url
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
-from misago.acl.views import RolesList, NewRole, EditRole, DeleteRole
 
 
 
 
 class MisagoAdminExtension(object):
 class MisagoAdminExtension(object):

+ 0 - 2
misago/admin/hierarchy.py

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

+ 0 - 1
misago/admin/urlpatterns.py

@@ -1,5 +1,4 @@
 from django.conf.urls import patterns, url, include
 from django.conf.urls import patterns, url, include
-from django.core.urlresolvers import reverse
 
 
 
 
 class URLPatterns(object):
 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 django.conf.urls import patterns, include, url
-
 from misago import admin
 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:
             elif page == 0:
                 page = 1
                 page = 1
         except ValueError:
         except ValueError:
-            page_no = 1
+            page = 1
 
 
         context['paginator'] = Paginator(context['items'],
         context['paginator'] = Paginator(context['items'],
                                          self.items_per_page,
                                          self.items_per_page,
@@ -317,12 +317,14 @@ class ListView(AdminView):
         SearchForm = self.get_search_form(request)
         SearchForm = self.get_search_form(request)
         if SearchForm:
         if SearchForm:
             filtering_methods = self.get_filtering_methods(request)
             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'):
             if request.GET.get('clear_filters'):
                 # Clear filters from querystring
                 # Clear filters from querystring
                 request.session.pop(self.filters_session_key, None)
                 request.session.pop(self.filters_session_key, None)
                 active_filters = {}
                 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
             if (filtering_methods['GET'] and
                     filtering_methods['GET'] != filtering_methods['session']):
                     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 django.core.urlresolvers import reverse
 
 
 from misago.admin.testutils import AdminTestCase
 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.core import threadstore
 
 
 from misago.conf import migrationutils
 from misago.conf import migrationutils
-from misago.conf.models import SettingsGroup, Setting
+from misago.conf.models import SettingsGroup
 
 
 
 
 class DBConfMigrationUtilsTests(TestCase):
 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.gateway import settings as gateway
 from misago.conf.dbsettings import db_settings
 from misago.conf.dbsettings import db_settings
 from misago.conf.migrationutils import migrate_settings_group
 from misago.conf.migrationutils import migrate_settings_group
-from misago.conf.models import SettingsGroup, Setting
 
 
 
 
 class DBSettingsTests(TestCase):
 class DBSettingsTests(TestCase):
@@ -78,11 +77,11 @@ class GatewaySettingsTests(TestCase):
         self.assertTrue(db_settings.lazy_fish_name)
         self.assertTrue(db_settings.lazy_fish_name)
 
 
         self.assertTrue(gateway.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.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(gateway.lazy_empty_setting is None)
         self.assertTrue(db_settings.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 import db_settings
 from misago.conf.forms import ChangeSettingsForm
 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):
 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 mptt.forms import *  # noqa
 
 
 from django.forms import *  # noqa
 from django.forms import *  # noqa
 from django.forms import Form as BaseForm, ModelForm as BaseModelForm
 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 _
 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.conf import settings
 from django.core import mail
 from django.core import mail
 from django.core.exceptions import ValidationError
 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.cache import cache as default_cache
 from misago.core.cachebuster import CACHE_KEY
 from misago.core.cachebuster import CACHE_KEY
 
 
 
 
-"""
-cache versioning utils
-"""
 def _CacheVersion(apps):
 def _CacheVersion(apps):
     return apps.get_model('misago_core', 'CacheVersion')
     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):
     def state_forwards(self, app_label, state):
         pass
         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()
         apps = from_state.render()
         model = apps.get_model(app_label, self.model)
         model = apps.get_model(app_label, self.model)
 
 
@@ -36,8 +37,12 @@ DROP INDEX %(index_name)s
 
 
         schema_editor.execute(statement)
         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):
     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 import template
-from django.template import Context
 
 
 
 
 register = template.Library()
 register = template.Library()

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

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

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

@@ -1,5 +1,3 @@
-import os
-
 from django.conf import settings
 from django.conf import settings
 from django.http import HttpResponse, StreamingHttpResponse
 from django.http import HttpResponse, StreamingHttpResponse
 from django.test import TestCase
 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):
     def test_mail_user(self):
         """mail_user sets message in backend"""
         """mail_user sets message in backend"""
         User = get_user_model()
         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'))
         response = self.client.get(reverse('test_mail_user'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)

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

@@ -50,7 +50,7 @@ class BatchTests(TestCase):
             ['l', 'o', 'r'],
             ['l', 'o', 'r'],
             ['e', 'm', 'i'],
             ['e', 'm', 'i'],
             ['p', 's', 'u'],
             ['p', 's', 'u'],
-            ['m',],
+            ['m'],
         )
         )
 
 
         for i, test_yield in enumerate(misago_batch.batch(batch, 3)):
         for i, test_yield in enumerate(misago_batch.batch(batch, 3)):
@@ -70,7 +70,6 @@ class BatchTests(TestCase):
             self.assertEqual(test_yield, yields[i])
             self.assertEqual(test_yield, yields[i])
 
 
 
 
-
 class TestForm(forms.Form):
 class TestForm(forms.Form):
     somefield = forms.CharField(label="Hello!", max_length=255)
     somefield = forms.CharField(label="Hello!", max_length=255)
 
 
@@ -180,4 +179,4 @@ class PaginationTests(TestCase):
 """
 """
 
 
         tpl = Template(tpl_content)
         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 django.test import TestCase
 
 
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
-from misago.users.models import AnonymousUser
 
 
 from misago.core import uiviews
 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/')
         self.assertEqual(clean_return_path(ok_request), '/register/')
 
 
-
     def test_post_request(self):
     def test_post_request(self):
         """clean_return_path works for POST requests"""
         """clean_return_path works for POST requests"""
         bad_request = MockRequest('POST', {
         bad_request = MockRequest('POST', {

+ 3 - 1
misago/core/timezones.py

@@ -1,8 +1,10 @@
+# flake8: noqa
 import datetime
 import datetime
 
 
-from django.utils.translation import ugettext_lazy as _
 import pytz
 import pytz
 
 
+from django.utils.translation import ugettext_lazy as _
+
 
 
 TIMEZONES = (
 TIMEZONES = (
     ('Pacific/Apia', _('(UTC-13:00) Samoa'), _('(UTC-14:00) Samoa')),
     ('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
 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.core.management.base import BaseCommand
-from django.db import IntegrityError
 from django.utils import timezone
 from django.utils import timezone
 
 
 from faker import Factory
 from faker import Factory

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

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

+ 21 - 21
misago/forums/forms.py

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

+ 1 - 2
misago/forums/lists.py

@@ -32,8 +32,7 @@ def get_forums_list(user, parent=None):
 
 
     flat_list = []
     flat_list = []
     for forum in forums_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)
             flat_list.append(forum)
 
 
     add_acl(user, flat_list)
     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)),
                 ('rght', models.PositiveIntegerField(editable=False, db_index=True)),
                 ('tree_id', models.PositiveIntegerField(editable=False, db_index=True)),
                 ('tree_id', models.PositiveIntegerField(editable=False, db_index=True)),
                 ('level', 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={
             options={
                 'abstract': False,
                 'abstract': False,

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

@@ -146,7 +146,7 @@ class ForumAdminViewsTests(AdminTestCase):
                              'prune_replied_after': 0,
                              'prune_replied_after': 0,
                          })
                          })
 
 
-        category_a = Forum.objects.get(slug='category-a')
+
         category_b = Forum.objects.get(slug='category-b')
         category_b = Forum.objects.get(slug='category-b')
 
 
         response = self.client.post(
         response = self.client.post(
@@ -280,7 +280,7 @@ class ForumAdminDeleteViewTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:forums:nodes:delete',
             reverse('misago:admin:forums:nodes:delete',
                     kwargs={'forum_id': self.subforum_d.pk}),
                     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(response.status_code, 302)
         self.assertEqual(Forum.objects.all_forums().count(), 8)
         self.assertEqual(Forum.objects.all_forums().count(), 8)
 
 
@@ -311,14 +311,14 @@ class ForumAdminDeleteViewTests(AdminTestCase):
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:forums:nodes:delete',
             reverse('misago:admin:forums:nodes:delete',
                     kwargs={'forum_id': self.forum_b.pk}),
                     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(response.status_code, 200)
         self.assertEqual(Forum.objects.all_forums().count(), 9)
         self.assertEqual(Forum.objects.all_forums().count(), 9)
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:forums:nodes:delete',
             reverse('misago:admin:forums:nodes:delete',
                     kwargs={'forum_id': self.forum_b.pk}),
                     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(response.status_code, 302)
 
 
         self.assertEqual(Forum.objects.all_forums().count(), 6)
         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 django.test import TestCase
 
 
+from misago.acl.testutils import override_acl
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
 
 
 from misago.forums.lists import get_forums_list, get_forum_path
 from misago.forums.lists import get_forums_list, get_forum_path
@@ -7,15 +8,24 @@ from misago.forums.models import Forum
 
 
 
 
 class GetForumListTests(AdminTestCase):
 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):
     def test_root_forums_list_no_parent(self):
         """get_forums_list returns all children of root nodes"""
         """get_forums_list returns all children of root nodes"""
         self.assertEqual(len(get_forums_list(self.test_admin)), 3)
         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"""
         """get_forums_list returns all children of given node"""
         for i, node in enumerate(get_forums_list(self.test_admin)):
         for i, node in enumerate(get_forums_list(self.test_admin)):
             child_nodes = len(get_forums_list(self.test_admin, node))
             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):
 class GetForumPathTests(TestCase):

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

@@ -27,7 +27,6 @@ class ForumRolesList(ForumRoleAdmin, generic.ListView):
 
 
 class RoleFormMixin(object):
 class RoleFormMixin(object):
     def real_dispatch(self, request, target):
     def real_dispatch(self, request, target):
-        role_permissions = target.permissions
         form = ForumRoleForm(instance=target)
         form = ForumRoleForm(instance=target)
 
 
         perms_forms = get_permissions_forms(target)
         perms_forms = get_permissions_forms(target)
@@ -96,7 +95,6 @@ class ForumPermissions(ForumAdmin, generic.ModelFormView):
     def real_dispatch(self, request, target):
     def real_dispatch(self, request, target):
         forum_roles = ForumRole.objects.order_by('name')
         forum_roles = ForumRole.objects.order_by('name')
 
 
-
         assigned_roles = {}
         assigned_roles = {}
         for acl in target.forum_role_set.select_related('forum_role'):
         for acl in target.forum_role_set.select_related('forum_role'):
             assigned_roles[acl.role_id] = acl.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,
 from misago.markup.flavours import (common as common_flavour,
                                     limited as limited_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):
 def _render_editor_template(context, editor, tpl):
     c = Context(context)
     c = Context(context)
-    c['editor'] =  editor
+    c['editor'] = editor
 
 
     return get_template(tpl).render(c)
     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]))
             checksums.is_checksum_valid(fake_message, checksum, [post_pk]))
         self.assertFalse(
         self.assertFalse(
             checksums.is_checksum_valid(fake_message, checksum, [3]))
             checksums.is_checksum_valid(fake_message, checksum, [3]))
-
-
-

+ 3 - 0
misago/notifications/__init__.py

@@ -1 +1,4 @@
 from misago.notifications.api import *  # noqa
 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.db import transaction
 from django.utils.html import escape
 from django.utils.html import escape
 
 
-from misago.notifications.models import Notification
 from misago.notifications.utils import hash_trigger
 from misago.notifications.utils import hash_trigger
 
 
 
 
@@ -16,6 +15,8 @@ __all__ = [
 
 
 def notify_user(user, message, url, trigger, formats=None, sender=None,
 def notify_user(user, message, url, trigger, formats=None, sender=None,
                 update_user=True):
                 update_user=True):
+    from misago.notifications.models import Notification
+
     message_escaped = escape(message)
     message_escaped = escape(message)
     if formats:
     if formats:
         final_formats = {}
         final_formats = {}

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

@@ -2,6 +2,7 @@
 from __future__ import unicode_literals
 from __future__ import unicode_literals
 
 
 from django.db import models, migrations
 from django.db import models, migrations
+import django.db.models.deletion
 import django.utils.timezone
 import django.utils.timezone
 from django.conf import settings
 from django.conf import settings
 
 
@@ -22,10 +23,10 @@ class Migration(migrations.Migration):
                 ('trigger', models.CharField(max_length=8)),
                 ('trigger', models.CharField(max_length=8)),
                 ('message', models.TextField()),
                 ('message', models.TextField()),
                 ('url', 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={
             options={
             },
             },

+ 3 - 5
misago/notifications/models.py

@@ -1,5 +1,3 @@
-import cgi
-
 from django.conf import settings
 from django.conf import settings
 from django.db import models
 from django.db import models
 from django.utils import timezone
 from django.utils import timezone
@@ -14,8 +12,8 @@ class Notification(models.Model):
     message = models.TextField()
     message = models.TextField()
     url = models.TextField()
     url = models.TextField()
     sender = models.ForeignKey(settings.AUTH_USER_MODEL,
     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_username = models.CharField(max_length=255, blank=True, null=True)
     sender_slug = 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.contrib import messages
 from django.db.transaction import atomic
 from django.db.transaction import atomic
 from django.http import JsonResponse
 from django.http import JsonResponse
 from django.shortcuts import redirect, render
 from django.shortcuts import redirect, render
-from django.utils import timezone
 from django.utils.translation import ugettext as _, ungettext
 from django.utils.translation import ugettext as _, ungettext
 
 
 from misago.core.uiviews import uiview
 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 import forms
 from misago.core.validators import validate_sluggable
 from misago.core.validators import validate_sluggable
 from misago.forums.forms import ForumsMultipleChoiceField
 from misago.forums.forms import ForumsMultipleChoiceField
-from misago.forums.models import Forum
 
 
 from misago.threads.models import Prefix
 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)),
                 ('name', models.CharField(max_length=255)),
                 ('slug', models.SlugField(max_length=255)),
                 ('slug', models.SlugField(max_length=255)),
                 ('css_class', models.CharField(max_length=255, null=True, blank=True)),
                 ('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={
             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.thread import Thread
 #from misago.threads.models.post import Post
 #from misago.threads.models.post import Post
 from misago.threads.models.prefix import Prefix
 from misago.threads.models.prefix import Prefix

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

@@ -45,7 +45,6 @@ class Prefix(models.Model):
 
 
     objects = PrefixManager()
     objects = PrefixManager()
 
 
-
     def delete(self, *args, **kwargs):
     def delete(self, *args, **kwargs):
         Prefix.objects.clear_cache()
         Prefix.objects.clear_cache()
         return super(Prefix, self).delete(*args, **kwargs)
         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 django.test import TestCase
 
 
 from misago.forums.models import Forum
 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)
         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.assertEqual(response.status_code, 200)
         self.assertIn('Test Prefix', response.content)
         self.assertIn('Test Prefix', response.content)
         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.conf.urls import url
 from django.contrib import admin as djadmin
 from django.contrib import admin as djadmin
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.utils.translation import ugettext_lazy as _
 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 register_default_users_list_pages(self):
         def can_see_online_list(request):
         def can_see_online_list(request):
             return request.user.acl['can_see_users_online_list']
             return request.user.acl['can_see_users_online_list']
+
         users_list.add_page(link='misago:users_active_posters',
         users_list.add_page(link='misago:users_active_posters',
                             name=_('Active posters'))
                             name=_('Active posters'))
         users_list.add_page(link='misago:users_online',
         users_list.add_page(link='misago:users_online',
@@ -46,12 +47,16 @@ class MisagoUsersConfig(AppConfig):
     def register_default_user_profile_pages(self):
     def register_default_user_profile_pages(self):
         def posts_badge(request, profile):
         def posts_badge(request, profile):
             return profile.posts
             return profile.posts
+
         def threads_badge(request, profile):
         def threads_badge(request, profile):
             return profile.threads
             return profile.threads
+
         def followers_badge(request, profile):
         def followers_badge(request, profile):
             return profile.followers
             return profile.followers
+
         def following_badge(request, profile):
         def following_badge(request, profile):
             return profile.following
             return profile.following
+
         def can_see_names_history(request, profile):
         def can_see_names_history(request, profile):
             if request.user.is_authenticated():
             if request.user.is_authenticated():
                 is_account_owner = profile.pk == request.user.pk
                 is_account_owner = profile.pk == request.user.pk
@@ -59,6 +64,7 @@ class MisagoUsersConfig(AppConfig):
                 return is_account_owner or has_permission
                 return is_account_owner or has_permission
             else:
             else:
                 return False
                 return False
+
         def can_see_warnings(request, profile):
         def can_see_warnings(request, profile):
             if request.user.is_authenticated():
             if request.user.is_authenticated():
                 is_account_owner = profile.pk == request.user.pk
                 is_account_owner = profile.pk == request.user.pk
@@ -67,6 +73,7 @@ class MisagoUsersConfig(AppConfig):
                 return is_account_owner or has_permission
                 return is_account_owner or has_permission
             else:
             else:
                 return False
                 return False
+
         def can_see_ban_details(request, profile):
         def can_see_ban_details(request, profile):
             if request.user.is_authenticated():
             if request.user.is_authenticated():
                 if request.user.acl['can_see_ban_details']:
                 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
 from importlib import import_module
 import math
 import math
 import os
 import os

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

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

+ 0 - 1
misago/users/decorators.py

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

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

@@ -240,7 +240,6 @@ def SearchUsersForm(*args, **kwargs):
             roles_choices.append((role.pk, role.name))
             roles_choices.append((role.pk, role.name))
         threadstore.set('misago_admin_roles_choices', roles_choices)
         threadstore.set('misago_admin_roles_choices', roles_choices)
 
 
-
     extra_fields = {
     extra_fields = {
         'rank': forms.TypedChoiceField(label=_("Has rank"),
         'rank': forms.TypedChoiceField(label=_("Has rank"),
                                        coerce=int,
                                        coerce=int,
@@ -362,7 +361,8 @@ class BanForm(forms.ModelForm):
                     'for rought matches. For example, making IP ban for value '
                     'for rought matches. For example, making IP ban for value '
                     '"83.*" will ban all IP addresses beginning with "83.".'),
                     '"83.*" will ban all IP addresses beginning with "83.".'),
         error_messages={
         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(
     user_message = forms.CharField(
         label=_("User message"), required=False, max_length=1000,
         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:
         try:
             User = get_user_model()
             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
             self.user_cache = user
         except User.DoesNotExist:
         except User.DoesNotExist:
             raise forms.ValidationError(_("Invalid username or e-mail."))
             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.conf import settings
 from misago.core import forms
 from misago.core import forms
-from misago.core.utils import clean_return_path
 
 
 from misago.users.forms.admin import BanUsersForm
 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):
 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.core.management.base import BaseCommand
 from django.utils import timezone
 from django.utils import timezone
 
 
-from misago.core import cachebuster
-
 from misago.users.models import BanCache
 from misago.users.models import BanCache
 
 
 
 
@@ -18,7 +16,7 @@ class Command(BaseCommand):
         queryset = queryset.filter(valid_until__lte=timezone.now().date())
         queryset = queryset.filter(valid_until__lte=timezone.now().date())
 
 
         expired_count = queryset.update(is_valid=False)
         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):
     def handle_bans_caches(self):
         queryset = BanCache.objects.filter(valid_until__isnull=False)
         queryset = BanCache.objects.filter(valid_until__isnull=False)
@@ -30,4 +28,4 @@ class Command(BaseCommand):
         queryset = BanCache.objects.filter(bans_version__lt=bans_version)
         queryset = BanCache.objects.filter(bans_version__lt=bans_version)
         expired_count += queryset.delete()
         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 import logout
 from django.contrib.auth.models import AnonymousUser as DjAnonymousUser
 from django.contrib.auth.models import AnonymousUser as DjAnonymousUser
 from django.core.urlresolvers import resolve
 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.bans import get_request_ip_ban, get_user_ban
 from misago.users.models import AnonymousUser, Online
 from misago.users.models import AnonymousUser, Online
 from misago.users.online import tracker
 from misago.users.online import tracker
-from misago.users.views import avatarserver
 
 
 
 
 class RealIPMiddleware(object):
 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.rank import *
 from misago.users.models.user import *
 from misago.users.models.user import *
 from misago.users.models.bans 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
 import re
 
 
 from django.conf import settings
 from django.conf import settings
@@ -7,7 +7,6 @@ from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
 from misago.core import cachebuster
 from misago.core import cachebuster
-from misago.core.utils import time_amount
 
 
 
 
 __all__ = [
 __all__ = [
@@ -107,7 +106,7 @@ class Ban(models.Model):
     def test_value(self, value):
     def test_value(self, value):
         if '*' in self.banned_value:
         if '*' in self.banned_value:
             regex = re.escape(self.banned_value).replace('\*', '(.*?)')
             regex = re.escape(self.banned_value).replace('\*', '(.*?)')
-            return re.search('^%s$' % regex, value) != None
+            return re.search('^%s$' % regex, value) is not None
         else:
         else:
             return self.banned_value == value
             return self.banned_value == value
 
 

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

@@ -1,7 +1,6 @@
 from django.db import models, transaction
 from django.db import models, transaction
 
 
 from misago.acl import version as acl_version
 from misago.acl import version as acl_version
-from misago.core.cache import cache
 from misago.core.utils import slugify
 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
                 extra_fields['subscribe_to_replied_threads'] = new_value
 
 
             now = timezone.now()
             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_username(username)
             user.set_email(email)
             user.set_email(email)
@@ -122,7 +122,6 @@ class UserManager(BaseUserManager):
             except Rank.DoesNotExist:
             except Rank.DoesNotExist:
                 pass
                 pass
 
 
-
             user.is_staff = True
             user.is_staff = True
             user.is_superuser = True
             user.is_superuser = True
 
 
@@ -218,7 +217,7 @@ class User(AbstractBaseUser, PermissionsMixin):
     last_post = models.DateTimeField(null=True, blank=True)
     last_post = models.DateTimeField(null=True, blank=True)
     last_search = 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'
     USERNAME_FIELD = 'slug'
     REQUIRED_FIELDS = ['email']
     REQUIRED_FIELDS = ['email']

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

@@ -2,7 +2,6 @@ from collections import OrderedDict
 from datetime import timedelta
 from datetime import timedelta
 
 
 from django.conf import settings
 from django.conf import settings
-from django.contrib.auth import get_user_model
 from django.db import models
 from django.db import models
 from django.utils import timezone
 from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
@@ -119,17 +118,17 @@ class UserWarning(models.Model):
     reason = models.TextField(null=True, blank=True)
     reason = models.TextField(null=True, blank=True)
     given_on = models.DateTimeField(default=timezone.now)
     given_on = models.DateTimeField(default=timezone.now)
     giver = models.ForeignKey(settings.AUTH_USER_MODEL,
     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_username = models.CharField(max_length=255)
     giver_slug = models.CharField(max_length=255)
     giver_slug = models.CharField(max_length=255)
     is_canceled = models.BooleanField(default=False)
     is_canceled = models.BooleanField(default=False)
     canceled_on = models.DateTimeField(null=True, blank=True)
     canceled_on = models.DateTimeField(null=True, blank=True)
     canceler = models.ForeignKey(settings.AUTH_USER_MODEL,
     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_username = models.CharField(max_length=255)
     canceler_slug = 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)
         valid_changes_qs = user.namechanges.filter(changed_by=user)
         if name_changes_expire:
         if name_changes_expire:
             cutoff = timezone.now() - timedelta(days=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()
         used_changes = valid_changes_qs.count()
         if name_changes_allowed <= used_changes:
         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.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
 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)
     new_acl.update(acl)
 
 
     return algebra.sum_acls(
     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)
     new_acl.update(acl)
 
 
     return algebra.sum_acls(
     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_cancel_warnings'] = False
     target_acl['can_delete_warnings'] = False
     target_acl['can_delete_warnings'] = False
 
 
-    mod_permissions = (
-        'can_warn',
-    )
-
     if target_acl['can_warn']:
     if target_acl['can_warn']:
         target_acl['can_moderate'] = True
         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 import template
 from django.core.urlresolvers import reverse
 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.conf import settings
 
 
 from misago.users.avatars import store, dynamic, gallery, gravatar, uploaded
 from misago.users.avatars import store, dynamic, gallery, gravatar, uploaded
-from misago.users.avatars.paths import AVATARS_STORE
 
 
 
 
 class AvatarsStoreTests(TestCase):
 class AvatarsStoreTests(TestCase):
@@ -142,5 +141,3 @@ class UploadedAvatarTests(TestCase):
         for valid_mime in uploaded.ALLOWED_MIME_TYPES:
         for valid_mime in uploaded.ALLOWED_MIME_TYPES:
             image = MockAvatarFile(mime=valid_mime)
             image = MockAvatarFile(mime=valid_mime)
             uploaded.validate_mime(image)
             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.contrib.auth import get_user_model
 from django.core.urlresolvers import reverse
 from django.core.urlresolvers import reverse
-from django.template import Context, Template
 from django.test import TestCase
 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):
     def test_find_ban_for_banned_name(self):
         """find_ban finds ban for given username"""
         """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):
         with self.assertRaises(Ban.DoesNotExist):
             Ban.objects.find_ban(username='Jeb')
             Ban.objects.find_ban(username='Jeb')
 
 
     def test_find_ban_for_banned_email(self):
     def test_find_ban_for_banned_email(self):
         """find_ban finds ban for given email"""
         """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):
         with self.assertRaises(Ban.DoesNotExist):
             Ban.objects.find_ban(email='jeb@test.com')
             Ban.objects.find_ban(email='jeb@test.com')
 
 
     def test_find_ban_for_banned_ip(self):
     def test_find_ban_for_banned_ip(self):
         """find_ban finds ban for given ip"""
         """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):
         with self.assertRaises(Ban.DoesNotExist):
             Ban.objects.find_ban(ip='42.0.0.1')
             Ban.objects.find_ban(ip='42.0.0.1')
 
 
     def test_find_ban_for_all_bans(self):
     def test_find_ban_for_all_bans(self):
         """find_ban finds ban for given values"""
         """find_ban finds ban for given values"""
         valid_kwargs = {'username': 'bob', 'ip': '42.51.52.51'}
         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'}
         invalid_kwargs = {'username': 'bsob', 'ip': '42.51.52.51'}
         with self.assertRaises(Ban.DoesNotExist):
         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.acl.testutils import override_acl
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
 
 
-from misago.users.models import Ban, Rank
+from misago.users.models import Rank
 
 
 
 
 class UsersListTestCase(AdminTestCase):
 class UsersListTestCase(AdminTestCase):
@@ -30,7 +30,7 @@ class UsersListLanderTests(UsersListTestCase):
         response = self.client.get(reverse('misago:users'))
         response = self.client.get(reverse('misago:users'))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
         self.assertTrue(response['location'].endswith(
         self.assertTrue(response['location'].endswith(
-                         reverse('misago:users_active_posters')))
+                        reverse('misago:users_active_posters')))
 
 
 
 
 class ActivePostersTests(UsersListTestCase):
 class ActivePostersTests(UsersListTestCase):
@@ -90,4 +90,3 @@ class UsersRankTests(UsersListTestCase):
                 self.assertEqual(response.status_code, 200)
                 self.assertEqual(response.status_code, 200)
             else:
             else:
                 self.assertEqual(response.status_code, 404)
                 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,
             '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',
         response = self.client.get(reverse('misago:user_ban',
                                            kwargs=link_kwargs))
                                            kwargs=link_kwargs))

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

@@ -46,8 +46,8 @@ class RegisterViewTests(TestCase):
         self.assertIn('Bob', response.content)
         self.assertIn('Bob', response.content)
 
 
         User = get_user_model()
         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'))
         response = self.client.get(reverse('misago:index'))
         self.assertIn('Bob', response.content)
         self.assertIn('Bob', response.content)
@@ -68,8 +68,8 @@ class RegisterViewTests(TestCase):
         self.assertIn('bob@bob.com', response.content)
         self.assertIn('bob@bob.com', response.content)
 
 
         User = get_user_model()
         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)
         self.assertIn('Welcome', mail.outbox[0].subject)
 
 
@@ -87,7 +87,7 @@ class RegisterViewTests(TestCase):
         self.assertIn('administrator', response.content)
         self.assertIn('administrator', response.content)
 
 
         User = get_user_model()
         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)
         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)
         self.assertEqual(response.status_code, 302)
 
 
         User = get_user_model()
         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):
     def test_change_password(self):
         """POST to usercp change password view returns 302"""
         """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):
         with self.assertRaises(ValidationError):
             validate_email_banned('ban@test.com')
             validate_email_banned('ban@test.com')
 
 
+
 class ValidateEmailTests(TestCase):
 class ValidateEmailTests(TestCase):
     def test_validate_email(self):
     def test_validate_email(self):
         """validate_email has no crashes"""
         """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)
         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.assertEqual(response.status_code, 200)
         self.assertIn('Test Level', response.content)
         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):
     def warn_user(self, reason):
         override_acl(self.test_admin, {'can_warn_users': 1})
         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):
 class WarnUserTests(WarningTestCase):
@@ -156,7 +155,8 @@ class CancelWarningTests(WarningTestCase):
                 'warning_id': warning.pk
                 'warning_id': warning.pk
             }))
             }))
         self.assertEqual(response.status_code, 403)
         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):
     def test_no_permission_other(self):
         """can't cancel other mod warnings"""
         """can't cancel other mod warnings"""
@@ -170,7 +170,8 @@ class CancelWarningTests(WarningTestCase):
                 'warning_id': warning.pk
                 'warning_id': warning.pk
             }))
             }))
         self.assertEqual(response.status_code, 403)
         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)
         warning = warn_user(self.test_admin, self.test_user)
         self.allow_cancel_owned_warning()
         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
 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)
             queryset.update(requires_activation=ACTIVATION_REQUIRED_NONE)
 
 
             mail_subject = _("Your account on %(forum_title)s "
             mail_subject = _("Your account on %(forum_title)s "
-                                 "forums has been activated")
+                             "forums has been activated")
             subject_formats = {'forum_title': settings.forum_name}
             subject_formats = {'forum_title': settings.forum_name}
             mail_subject = mail_subject % subject_formats
             mail_subject = mail_subject % subject_formats
 
 
@@ -138,7 +138,6 @@ class UsersList(UserAdmin, generic.ListView):
             })
             })
 
 
     def action_delete_accounts(self, request, users):
     def action_delete_accounts(self, request, users):
-        inactive_users = []
         for user in users:
         for user in users:
             if user.is_staff or user.is_superuser:
             if user.is_staff or user.is_superuser:
                 message = _("%(user)s is admin and can't be deleted.")
                 message = _("%(user)s is admin and can't be deleted.")
@@ -152,7 +151,6 @@ class UsersList(UserAdmin, generic.ListView):
         messages.success(request, message)
         messages.success(request, message)
 
 
     def action_delete_all(self, request, users):
     def action_delete_all(self, request, users):
-        inactive_users = []
         for user in users:
         for user in users:
             if user.is_staff or user.is_superuser:
             if user.is_staff or user.is_superuser:
                 message = _("%(user)s is admin and can't be deleted.")
                 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 django.utils.translation import ugettext_lazy as _
 
 
 from misago.admin.views import generic
 from misago.admin.views import generic
-from misago.core import cachebuster
 
 
 from misago.users.models import WarningLevel
 from misago.users.models import WarningLevel
 from misago.users.forms.admin import WarningLevelForm
 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.conf import settings
 from django.contrib import auth, messages
 from django.contrib import auth, messages
-from django.http import Http404
 from django.shortcuts import render, redirect
 from django.shortcuts import render, redirect
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 from django.views.decorators.cache import never_cache
 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 import messages
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.http import Http404
 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.bans import get_user_ban
 from misago.users.decorators import deny_authenticated, deny_banned_ips
 from misago.users.decorators import deny_authenticated, deny_banned_ips
 from misago.users.forms.auth import ResetPasswordForm, SetNewPasswordForm
 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,
 from misago.users.tokens import (make_password_reset_token,
                                  is_password_reset_token_valid)
                                  is_password_reset_token_valid)
 
 
@@ -121,6 +119,5 @@ def reset_password_form(request, user_id, token):
             messages.success(request, message)
             messages.success(request, message)
             return redirect(settings.LOGIN_URL)
             return redirect(settings.LOGIN_URL)
 
 
-
     return render(request, 'misago/forgottenpassword/reset_password_form.html',
     return render(request, 'misago/forgottenpassword/reset_password_form.html',
                   {'requesting_user': requesting_user, 'form': form})
                   {'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()
     User = get_user_model()
     queryset = User.objects.all().select_related('user__rank')
     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, {
     return list_view(request, template, queryset, page, {
         'tracked_period': tracked_period
         'tracked_period': tracked_period
     })
     })
@@ -83,7 +83,7 @@ def online(request, page=0):
     queryset = get_online_queryset(request.user).order_by('user__slug')
     queryset = get_online_queryset(request.user).order_by('user__slug')
     queryset = queryset.select_related('user__rank')
     queryset = queryset.select_related('user__rank')
 
 
-    template =  "misago/userslists/online.html"
+    template = "misago/userslists/online.html"
     return list_view(request, template, queryset, page, {
     return list_view(request, template, queryset, page, {
         'data_from': timezone.now()
         '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)
     rank = get_object_or_404(Rank.objects.filter(is_tab=True), slug=rank_slug)
     queryset = rank.user_set.order_by('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})
     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)
         request.user.follows.remove(profile)
         followed = False
         followed = False
     else:
     else:
+        allow_follow_user(request.user, profile)
         followed = True
         followed = True
         request.user.follows.add(profile)
         request.user.follows.add(profile)
 
 
@@ -284,12 +285,13 @@ def follow_user(request, profile):
 
 
 @action_view
 @action_view
 def block_user(request, profile):
 def block_user(request, profile):
-    user_locked = request.user.lock()
+    request.user.lock()
 
 
     if request.user.is_blocking(profile):
     if request.user.is_blocking(profile):
         request.user.blocks.remove(profile)
         request.user.blocks.remove(profile)
         blocked = False
         blocked = False
     else:
     else:
+        allow_block_user(request.user, profile)
         blocked = True
         blocked = True
         request.user.blocks.add(profile)
         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
                 request.session['registered_user'] = new_user.pk
                 return redirect('misago:register_completed')
                 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):
 def register_disabled(request):
@@ -122,4 +122,3 @@ def register_completed(request):
             'activation_by_user': activation_by_user,
             'activation_by_user': activation_by_user,
             'registered_user': registered_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:
     if not settings.allow_custom_avatars:
         raise AjaxError(_("Avatar uploads are currently disabled."))
         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:
     if not new_avatar:
         raise AjaxError(_("No file was sent."))
         raise AjaxError(_("No file was sent."))
 
 
@@ -145,7 +145,7 @@ def crop_avatar(request, use_tmp_avatar):
             return redirect('misago:usercp_change_avatar')
             return redirect('misago:usercp_change_avatar')
     else:
     else:
         if not avatars.uploaded.has_original_avatar(request.user):
         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')
             return redirect('misago:usercp_change_avatar')
 
 
     if use_tmp_avatar:
     if use_tmp_avatar:

+ 0 - 1
misago/users/warnings.py

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

+ 0 - 3
runtests.py

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