Browse Source

Merge pull request #1160 from rafalp/setup-pylint

Add basic pylit-config
Rafał Pitoń 6 years ago
parent
commit
a42508efb8
88 changed files with 207 additions and 200 deletions
  1. 23 1
      .pylintrc
  2. 4 2
      .travis.yml
  3. 1 1
      misago/acl/admin.py
  4. 6 7
      misago/acl/algebra.py
  5. 0 2
      misago/acl/middleware.py
  6. 1 2
      misago/acl/panels.py
  7. 1 1
      misago/acl/providers.py
  8. 0 1
      misago/acl/test.py
  9. 3 3
      misago/acl/tests/test_acl_algebra.py
  10. 2 1
      misago/acl/tests/test_patching_user_acl.py
  11. 2 1
      misago/acl/tests/test_providers.py
  12. 3 4
      misago/acl/views.py
  13. 1 2
      misago/admin/forms.py
  14. 17 14
      misago/admin/hierarchy.py
  15. 4 5
      misago/admin/middleware.py
  16. 7 12
      misago/admin/tests/test_admin_form_templatetags.py
  17. 1 1
      misago/admin/tests/test_admin_index.py
  18. 1 1
      misago/admin/tests/test_admin_views.py
  19. 9 7
      misago/admin/urlpatterns.py
  20. 4 7
      misago/admin/views/__init__.py
  21. 1 2
      misago/admin/views/auth.py
  22. 14 16
      misago/admin/views/errorpages.py
  23. 22 24
      misago/admin/views/generic/formsbuttons.py
  24. 9 12
      misago/admin/views/generic/list.py
  25. 1 1
      misago/admin/views/generic/mixin.py
  26. 1 1
      misago/admin/views/index.py
  27. 1 1
      misago/categories/admin.py
  28. 1 1
      misago/categories/forms.py
  29. 1 1
      misago/categories/views/categoriesadmin.py
  30. 1 1
      misago/categories/views/permsadmin.py
  31. 1 1
      misago/conf/admin.py
  32. 1 1
      misago/conf/forms.py
  33. 1 1
      misago/conf/staticsettings.py
  34. 1 1
      misago/core/admin.py
  35. 1 1
      misago/core/apipatch.py
  36. 1 1
      misago/core/page.py
  37. 1 1
      misago/core/serializers.py
  38. 1 1
      misago/core/testproject/models.py
  39. 2 2
      misago/core/tests/test_apipatch.py
  40. 2 2
      misago/core/tests/test_context_processors.py
  41. 1 1
      misago/core/tests/test_frontendcontext_middleware.py
  42. 1 1
      misago/core/tests/test_setup.py
  43. 1 1
      misago/core/tests/test_templatetags.py
  44. 1 1
      misago/core/tests/test_utils.py
  45. 1 1
      misago/core/validators.py
  46. 1 1
      misago/core/viewmodel.py
  47. 1 1
      misago/faker/englishcorpus.py
  48. 1 1
      misago/legal/admin.py
  49. 1 1
      misago/legal/tests/test_context_processors.py
  50. 1 1
      misago/legal/tests/test_utils.py
  51. 1 1
      misago/markup/bbcode/inline.py
  52. 1 1
      misago/markup/pipeline.py
  53. 1 1
      misago/markup/tests/test_mentions.py
  54. 2 2
      misago/markup/tests/test_parser.py
  55. 1 1
      misago/readtracker/tests/test_categoriestracker.py
  56. 2 2
      misago/readtracker/tests/test_dates.py
  57. 1 1
      misago/readtracker/tests/test_poststracker.py
  58. 1 1
      misago/readtracker/tests/test_threadstracker.py
  59. 1 1
      misago/search/searchprovider.py
  60. 1 1
      misago/search/searchproviders.py
  61. 1 1
      misago/threads/admin.py
  62. 2 2
      misago/threads/api/postingendpoint/__init__.py
  63. 1 1
      misago/threads/api/threadendpoints/list.py
  64. 2 2
      misago/threads/mergeconflict.py
  65. 1 1
      misago/threads/tests/test_threads_moderation.py
  66. 1 1
      misago/threads/tests/test_utils.py
  67. 1 1
      misago/threads/threadtypes/__init__.py
  68. 1 1
      misago/threads/threadtypes/treesmap.py
  69. 1 1
      misago/threads/viewmodels/posts.py
  70. 1 1
      misago/threads/viewmodels/threads.py
  71. 1 1
      misago/threads/views/goto.py
  72. 1 1
      misago/users/admin.py
  73. 1 1
      misago/users/datadownloads/dataarchive.py
  74. 1 1
      misago/users/forms/auth.py
  75. 1 1
      misago/users/profilefields/__init__.py
  76. 1 1
      misago/users/profilefields/basefields.py
  77. 1 1
      misago/users/serializers/auth.py
  78. 1 1
      misago/users/tests/test_audittrail.py
  79. 1 1
      misago/users/tests/test_avatars.py
  80. 1 1
      misago/users/tests/test_bans.py
  81. 1 1
      misago/users/tests/test_credentialchange.py
  82. 1 1
      misago/users/tests/test_realip_middleware.py
  83. 1 1
      misago/users/tests/test_social_pipeline.py
  84. 2 2
      misago/users/tests/testfiles/profilefields.py
  85. 1 1
      misago/users/viewmodels/activeposters.py
  86. 1 1
      misago/users/viewmodels/followers.py
  87. 1 1
      misago/users/viewmodels/rankusers.py
  88. 1 1
      misago/users/viewmodels/threads.py

+ 23 - 1
.pylintrc

@@ -2,11 +2,33 @@
 
 
 load-plugins=pylint_django
 load-plugins=pylint_django
 ignore=migrations
 ignore=migrations
+max-line-length=88
 
 
 
 
 [MESSAGES CONTROL]
 [MESSAGES CONTROL]
 
 
-disable=abstract-method,duplicate-code,invalid-name,missing-docstring,no-else-return,no-self-use,redefined-builtin,super-init-not-called,too-few-public-methods,too-many-ancestors,too-many-lines,too-many-public-methods,too-many-statement,unused-argument
+disable=
+    abstract-method,
+    arguments-differ,
+    bad-continuation,
+    expression-not-assigned,
+    fixme,
+    inconsistent-return-statements,
+    invalid-name,
+    missing-docstring,
+    no-member,
+    no-self-use,
+    redefined-outer-name,
+    too-few-public-methods,
+    too-many-ancestors,
+    too-many-arguments,
+    too-many-instance-attributes,
+    too-many-lines,  # FIXME
+    too-many-public-methods,
+    too-many-statements,  # FIXME
+    ungrouped-imports,
+    unsubscriptable-object,
+    unused-argument
 
 
 
 
 [REPORTS]
 [REPORTS]

+ 4 - 2
.travis.yml

@@ -20,6 +20,8 @@ jobs:
       python: 3.6
       python: 3.6
       install:
       install:
         - pip install -U pip setuptools
         - pip install -U pip setuptools
-        - pip install black
+        - python setup.py install
+        - pip install black pylint pylint-django
       script:
       script:
-        - black --check devproject misago
+        - black --check devproject misago
+        - pylint misago/acl misago/admin

+ 1 - 1
misago/acl/admin.py

@@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _
 from .views import DeleteRole, EditRole, NewRole, RolesList, RoleUsers
 from .views import DeleteRole, EditRole, NewRole, RolesList, RoleUsers
 
 
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
     def register_urlpatterns(self, urlpatterns):
         # Permissions section
         # Permissions section
         urlpatterns.namespace(r"^permissions/", "permissions")
         urlpatterns.namespace(r"^permissions/", "permissions")

+ 6 - 7
misago/acl/algebra.py

@@ -17,7 +17,8 @@ def sum_acls(result_acl, acls=None, roles=None, key=None, **permissions):
     if roles is not None:
     if roles is not None:
         if not key:
         if not key:
             raise ValueError(
             raise ValueError(
-                'You have to provide "key" argument if you are passing roles instead of acls'
+                'You have to provide "key" argument if you '
+                "are passing roles instead of acls"
             )
             )
         acls = _roles_acls(key, roles)
         acls = _roles_acls(key, roles)
 
 
@@ -46,10 +47,9 @@ def greater(a, b):
 def greater_or_zero(a, b):
 def greater_or_zero(a, b):
     if a == 0:
     if a == 0:
         return a
         return a
-    elif b == 0:
+    if b == 0:
         return b
         return b
-    else:
-        return greater(a, b)
+    return greater(a, b)
 
 
 
 
 def lower(a, b):
 def lower(a, b):
@@ -59,7 +59,6 @@ def lower(a, b):
 def lower_non_zero(a, b):
 def lower_non_zero(a, b):
     if a == 0:
     if a == 0:
         return b
         return b
-    elif b == 0:
+    if b == 0:
         return a
         return a
-    else:
-        return lower(a, b)
+    return lower(a, b)

+ 0 - 2
misago/acl/middleware.py

@@ -1,5 +1,3 @@
-from django.utils.functional import SimpleLazyObject
-
 from . import useracl
 from . import useracl
 
 
 
 

+ 1 - 2
misago/acl/panels.py

@@ -14,8 +14,7 @@ class MisagoACLPanel(Panel):
 
 
         if misago_user and misago_user.is_authenticated:
         if misago_user and misago_user.is_authenticated:
             return misago_user.username
             return misago_user.username
-        else:
-            return _("Anonymous user")
+        return _("Anonymous user")
 
 
     def process_response(self, request, response):
     def process_response(self, request, response):
         try:
         try:

+ 1 - 1
misago/acl/providers.py

@@ -14,7 +14,7 @@ _ALREADY_INITIALIZED_ERROR = (
 )
 )
 
 
 
 
-class PermissionProviders(object):
+class PermissionProviders:
     """manager for permission providers"""
     """manager for permission providers"""
 
 
     def __init__(self):
     def __init__(self):

+ 0 - 1
misago/acl/test.py

@@ -1,5 +1,4 @@
 from contextlib import ContextDecorator, ExitStack, contextmanager
 from contextlib import ContextDecorator, ExitStack, contextmanager
-from functools import wraps
 from unittest.mock import patch
 from unittest.mock import patch
 
 
 from .forms import get_permissions_forms
 from .forms import get_permissions_forms

+ 3 - 3
misago/acl/tests/test_acl_algebra.py

@@ -5,14 +5,14 @@ def test_greatest_value_is_returned():
     assert algebra.greater(1, 3) == 3
     assert algebra.greater(1, 3) == 3
     assert algebra.greater(4, 2) == 4
     assert algebra.greater(4, 2) == 4
     assert algebra.greater(2, 2) == 2
     assert algebra.greater(2, 2) == 2
-    assert algebra.greater(True, False) == True
+    assert algebra.greater(True, False) is True
 
 
 
 
 def test_greatest_or_zero_value_is_returned():
 def test_greatest_or_zero_value_is_returned():
     assert algebra.greater_or_zero(1, 3) == 3
     assert algebra.greater_or_zero(1, 3) == 3
     assert algebra.greater_or_zero(4, 2) == 4
     assert algebra.greater_or_zero(4, 2) == 4
     assert algebra.greater_or_zero(2, 2) == 2
     assert algebra.greater_or_zero(2, 2) == 2
-    assert algebra.greater_or_zero(True, False) == False
+    assert algebra.greater_or_zero(True, False) is False
     assert algebra.greater_or_zero(2, 0) == 0
     assert algebra.greater_or_zero(2, 0) == 0
     assert algebra.greater_or_zero(0, 0) == 0
     assert algebra.greater_or_zero(0, 0) == 0
     assert algebra.greater_or_zero(0, 120) == 0
     assert algebra.greater_or_zero(0, 120) == 0
@@ -22,7 +22,7 @@ def test_lower_value_is_returned():
     assert algebra.lower(1, 3) == 1
     assert algebra.lower(1, 3) == 1
     assert algebra.lower(4, 2) == 2
     assert algebra.lower(4, 2) == 2
     assert algebra.lower(2, 2) == 2
     assert algebra.lower(2, 2) == 2
-    assert algebra.lower(True, False) == False
+    assert algebra.lower(True, False) is False
 
 
 
 
 def test_lowest_non_zero_value_is_returned():
 def test_lowest_non_zero_value_is_returned():

+ 2 - 1
misago/acl/tests/test_patching_user_acl.py

@@ -14,10 +14,11 @@ def test_decorator_patches_all_users_acls_in_test(cache_versions, user):
 
 
 def test_decorator_removes_patches_after_test(cache_versions, user):
 def test_decorator_removes_patches_after_test(cache_versions, user):
     @patch_user_acl({"is_patched": True})
     @patch_user_acl({"is_patched": True})
-    def test_function(patch_user_acl):
+    def test_function():
         user_acl = useracl.get_user_acl(user, cache_versions)
         user_acl = useracl.get_user_acl(user, cache_versions)
         assert user_acl["is_patched"]
         assert user_acl["is_patched"]
 
 
+    test_function()
     user_acl = useracl.get_user_acl(user, cache_versions)
     user_acl = useracl.get_user_acl(user, cache_versions)
     assert "is_patched" not in user_acl
     assert "is_patched" not in user_acl
 
 

+ 2 - 1
misago/acl/tests/test_providers.py

@@ -1,3 +1,4 @@
+# pylint: disable=protected-access
 import pytest
 import pytest
 
 
 from ...conf import settings
 from ...conf import settings
@@ -59,7 +60,7 @@ def test_accessing_providers_dict_before_load_raises_assertion_error():
 
 
 
 
 def test_getter_returns_registered_type_annotator():
 def test_getter_returns_registered_type_annotator():
-    class TestType(object):
+    class TestType:
         pass
         pass
 
 
     def test_annotator():
     def test_annotator():

+ 3 - 4
misago/acl/views.py

@@ -19,7 +19,7 @@ class RolesList(RoleAdmin, generic.ListView):
     ordering = (("name", None),)
     ordering = (("name", None),)
 
 
 
 
-class RoleFormMixin(object):
+class RoleFormMixin:
     def real_dispatch(self, request, target):
     def real_dispatch(self, request, target):
         form = RoleForm(instance=target)
         form = RoleForm(instance=target)
 
 
@@ -46,9 +46,8 @@ class RoleFormMixin(object):
 
 
                 if "stay" in request.POST:
                 if "stay" in request.POST:
                     return redirect(request.path)
                     return redirect(request.path)
-                else:
-                    return redirect(self.root_link)
-            elif form.is_valid() and len(perms_forms) != valid_forms:
+                return redirect(self.root_link)
+            if form.is_valid() and len(perms_forms) != valid_forms:
                 form.add_error(None, _("Form contains errors."))
                 form.add_error(None, _("Form contains errors."))
 
 
         return self.render(
         return self.render(

+ 1 - 2
misago/admin/forms.py

@@ -32,8 +32,7 @@ class YesNoSwitchBase(TypedChoiceField):
         """normalize bools to binary 1/0 so field works on them too"""
         """normalize bools to binary 1/0 so field works on them too"""
         if value in (True, "True", "true", 1, "1"):
         if value in (True, "True", "true", 1, "1"):
             return 1
             return 1
-        else:
-            return 0
+        return 0
 
 
     def clean(self, value):
     def clean(self, value):
         return self.prepare_value(value)
         return self.prepare_value(value)

+ 17 - 14
misago/admin/hierarchy.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
 
 
-class Node(object):
+class Node:
     def __init__(self, name=None, icon=None, link=None):
     def __init__(self, name=None, icon=None, link=None):
         self.parent = None
         self.parent = None
         self.name = name
         self.name = name
@@ -9,15 +9,15 @@ class Node(object):
         self.link = link
         self.link = link
         self._children = []
         self._children = []
         self._children_dict = {}
         self._children_dict = {}
+        self._resolved_namespace = None
 
 
     @property
     @property
     def namespace(self):
     def namespace(self):
-        try:
+        if self._resolved_namespace:
             return self._resolved_namespace
             return self._resolved_namespace
-        except AttributeError:
-            bits = self.link.split(":")
-            self._resolved_namespace = ":".join(bits[:-1])
 
 
+        bits = self.link.split(":")
+        self._resolved_namespace = ":".join(bits[:-1])
         return self._resolved_namespace
         return self._resolved_namespace
 
 
     def children(self):
     def children(self):
@@ -39,13 +39,12 @@ class Node(object):
     def add_node(self, node, after=None, before=None):
     def add_node(self, node, after=None, before=None):
         if after:
         if after:
             return self.add_node_after(node, after)
             return self.add_node_after(node, after)
-        elif before:
+        if before:
             return self.add_node_before(node, before)
             return self.add_node_before(node, before)
-        else:
-            node.parent = self
-            self._children.append(node)
-            self._children_dict[node.link] = node
-            return True
+        node.parent = self
+        self._children.append(node)
+        self._children_dict[node.link] = node
+        return True
 
 
     def add_node_after(self, node, after):
     def add_node_after(self, node, after):
         success = False
         success = False
@@ -91,7 +90,7 @@ class Node(object):
         return False
         return False
 
 
 
 
-class AdminHierarchyBuilder(object):
+class AdminHierarchyBuilder:
     def __init__(self):
     def __init__(self):
         self.nodes_record = []
         self.nodes_record = []
         self.nodes_dict = {}
         self.nodes_dict = {}
@@ -103,7 +102,10 @@ class AdminHierarchyBuilder(object):
         while self.nodes_record:
         while self.nodes_record:
             iterations += 1
             iterations += 1
             if iterations > 512:
             if iterations > 512:
-                message = "Misago Admin hierarchy is invalid or too complex to resolve. Nodes left: %s"
+                message = (
+                    "Misago Admin hierarchy is invalid or too complex to resolve. "
+                    "Nodes left: %s"
+                )
                 raise ValueError(message % self.nodes_record)
                 raise ValueError(message % self.nodes_record)
 
 
             for index, node in enumerate(self.nodes_record):
             for index, node in enumerate(self.nodes_record):
@@ -143,7 +145,8 @@ class AdminHierarchyBuilder(object):
     ):
     ):
         if self.nodes_dict:
         if self.nodes_dict:
             raise RuntimeError(
             raise RuntimeError(
-                "Misago admin site has already been initialized. You can't add new nodes to it."
+                "Misago admin site has already been initialized. "
+                "You can't add new nodes to it."
             )
             )
 
 
         if after and before:
         if after and before:

+ 4 - 5
misago/admin/middleware.py

@@ -9,13 +9,12 @@ from .views.auth import login
 class AdminAuthMiddleware(MiddlewareMixin):
 class AdminAuthMiddleware(MiddlewareMixin):
     def process_view(self, request, view_func, view_args, view_kwargs):
     def process_view(self, request, view_func, view_args, view_kwargs):
         request.admin_namespace = get_protected_namespace(request)
         request.admin_namespace = get_protected_namespace(request)
-
         if request.admin_namespace:
         if request.admin_namespace:
             if not auth.is_admin_session(request):
             if not auth.is_admin_session(request):
                 auth.close_admin_session(request)
                 auth.close_admin_session(request)
                 if request.resolver_match.url_name == "index":
                 if request.resolver_match.url_name == "index":
                     return login(request)
                     return login(request)
-                else:
-                    return redirect("%s:index" % request.admin_namespace)
-            else:
-                auth.update_admin_session(request)
+                return redirect("%s:index" % request.admin_namespace)
+            auth.update_admin_session(request)
+
+        return None

+ 7 - 12
misago/admin/tests/test_admin_form_templatetags.py

@@ -185,41 +185,36 @@ def test_attr_with_boolean_true_value_is_rendered():
     assert result == "bool"
     assert result == "bool"
 
 
 
 
-def test_attr_with_string_value_is_not_rendered():
+def test_bool_attr_with_string_value_is_not_rendered():
     result = render_bool_attrs({"name": "hello"})
     result = render_bool_attrs({"name": "hello"})
     assert result == ""
     assert result == ""
 
 
 
 
-def test_attr_with_int_value_is_not_rendered():
+def test_bool_attr_with_int_value_is_not_rendered():
     result = render_bool_attrs({"col": 13})
     result = render_bool_attrs({"col": 13})
     assert result == ""
     assert result == ""
 
 
 
 
-def test_attr_with_boolean_false_value_is_not_rendered():
+def test_bool_attr_with_boolean_false_value_is_not_rendered():
     result = render_bool_attrs({"selected": False})
     result = render_bool_attrs({"selected": False})
     assert result == ""
     assert result == ""
 
 
 
 
-def test_attr_with_none_value_is_not_rendered():
+def test_bool_attr_with_none_value_is_not_rendered():
     result = render_bool_attrs({"selected": None})
     result = render_bool_attrs({"selected": None})
     assert result == ""
     assert result == ""
 
 
 
 
-def test_attr_with_false_int_value_is_not_rendered():
+def test_bool_attr_with_false_int_value_is_not_rendered():
     result = render_bool_attrs({"selected": 0})
     result = render_bool_attrs({"selected": 0})
     assert result == ""
     assert result == ""
 
 
 
 
-def test_multiple_attrs_with_boolean_true_value_are_rendered():
+def test_multiple_bool_attrs_with_boolean_true_value_are_rendered():
     result = render_bool_attrs({"selected": True, "required": True})
     result = render_bool_attrs({"selected": True, "required": True})
     assert result == "selected required"
     assert result == "selected required"
 
 
 
 
-def test_only_attrs_with_boolean_true_value_are_rendered():
+def test_only_bool_attrs_with_boolean_true_value_are_rendered():
     result = render_bool_attrs({"bool": True, "string": "hello", "int": 123})
     result = render_bool_attrs({"bool": True, "string": "hello", "int": 123})
     assert result == "bool"
     assert result == "bool"
-
-
-def test_empty_attr_dict_is_not_rendered():
-    result = render_bool_attrs({})
-    assert result == ""

+ 1 - 1
misago/admin/tests/test_admin_index.py

@@ -19,7 +19,7 @@ class AdminIndexViewTests(AdminTestCase):
         self.assertContains(response, "MISAGO_ADDRESS")
         self.assertContains(response, "MISAGO_ADDRESS")
 
 
 
 
-class RequestMock(object):
+class RequestMock:
     absolute_uri = "https://misago-project.org/somewhere/"
     absolute_uri = "https://misago-project.org/somewhere/"
 
 
     def build_absolute_uri(self, location):
     def build_absolute_uri(self, location):

+ 1 - 1
misago/admin/tests/test_admin_views.py

@@ -6,7 +6,7 @@ from ..test import AdminTestCase
 from ..views import get_protected_namespace
 from ..views import get_protected_namespace
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, path):
     def __init__(self, path):
         self.path = path
         self.path = path
 
 

+ 9 - 7
misago/admin/urlpatterns.py

@@ -1,10 +1,12 @@
 from django.conf.urls import include, url
 from django.conf.urls import include, url
 
 
 
 
-class URLPatterns(object):
+class URLPatterns:
     def __init__(self):
     def __init__(self):
+        self.namespace_patterns = None
         self._namespaces = []
         self._namespaces = []
         self._patterns = []
         self._patterns = []
+        self._urlpatterns = None
 
 
     def namespace(self, path, namespace, parent=None):
     def namespace(self, path, namespace, parent=None):
         self._namespaces.append(
         self._namespaces.append(
@@ -57,13 +59,13 @@ class URLPatterns(object):
         return self.build_root_urlpatterns()
         return self.build_root_urlpatterns()
 
 
     def __call__(self):
     def __call__(self):
-        try:
-            return self._urlpatterns
-        except AttributeError:
-            self._urlpatterns = self.build_urlpatterns()
-            self._namespaces = []
-            self._patterns = []
+        if self._urlpatterns:
             return self._urlpatterns
             return self._urlpatterns
 
 
+        self._urlpatterns = self.build_urlpatterns()
+        self._namespaces = []
+        self._patterns = []
+        return self._urlpatterns
+
 
 
 urlpatterns = URLPatterns()
 urlpatterns = URLPatterns()

+ 4 - 7
misago/admin/views/__init__.py

@@ -15,8 +15,7 @@ def get_protected_namespace(request):
                 return namespace
                 return namespace
         except NoReverseMatch:
         except NoReverseMatch:
             pass
             pass
-    else:
-        return None
+    return None
 
 
 
 
 def render(request, template, context=None, error_page=False):
 def render(request, template, context=None, error_page=False):
@@ -61,10 +60,8 @@ def protected_admin_view(f):
             if is_admin_session(request):
             if is_admin_session(request):
                 update_admin_session(request)
                 update_admin_session(request)
                 return f(request, *args, **kwargs)
                 return f(request, *args, **kwargs)
-            else:
-                request.admin_namespace = protected_view
-                return login(request)
-        else:
-            return f(request, *args, **kwargs)
+            request.admin_namespace = protected_view
+            return login(request)
+        return f(request, *args, **kwargs)
 
 
     return decorator
     return decorator

+ 1 - 2
misago/admin/views/auth.py

@@ -38,5 +38,4 @@ def logout(request):
         auth.close_admin_session(request)
         auth.close_admin_session(request)
         messages.info(request, _("Your admin session has been closed."))
         messages.info(request, _("Your admin session has been closed."))
         return redirect("misago:index")
         return redirect("misago:index")
-    else:
-        return redirect("misago:admin:index")
+    return redirect("misago:admin:index")

+ 14 - 16
misago/admin/views/errorpages.py

@@ -7,28 +7,27 @@ from ..auth import is_admin_session, update_admin_session
 # Magic error page used by admin
 # Magic error page used by admin
 @protected_admin_view
 @protected_admin_view
 def _error_page(request, code, exception=None, default_message=None):
 def _error_page(request, code, exception=None, default_message=None):
-    if is_admin_session(request):
-        template_pattern = "misago/admin/errorpages/%s.html" % code
-
-        response = render(
-            request,
-            template_pattern,
-            {"message": get_exception_message(exception, default_message)},
-            error_page=True,
-        )
-        response.status_code = code
-        return response
-    else:
+    if not is_admin_session(request):
         return redirect("misago:admin:index")
         return redirect("misago:admin:index")
 
 
+    template_pattern = "misago/admin/errorpages/%s.html" % code
+
+    response = render(
+        request,
+        template_pattern,
+        {"message": get_exception_message(exception, default_message)},
+        error_page=True,
+    )
+    response.status_code = code
+    return response
+
 
 
 def admin_error_page(f):
 def admin_error_page(f):
     def decorator(request, *args, **kwargs):
     def decorator(request, *args, **kwargs):
         if get_protected_namespace(request):
         if get_protected_namespace(request):
             update_admin_session(request)
             update_admin_session(request)
             return _error_page(request, *args, **kwargs)
             return _error_page(request, *args, **kwargs)
-        else:
-            return f(request, *args, **kwargs)
+        return f(request, *args, **kwargs)
 
 
     return decorator
     return decorator
 
 
@@ -53,7 +52,6 @@ def admin_csrf_failure(f):
     def decorator(request, *args, **kwargs):
     def decorator(request, *args, **kwargs):
         if get_protected_namespace(request):
         if get_protected_namespace(request):
             return _csrf_failure(request, *args, **kwargs)
             return _csrf_failure(request, *args, **kwargs)
-        else:
-            return f(request, *args, **kwargs)
+        return f(request, *args, **kwargs)
 
 
     return decorator
     return decorator

+ 22 - 24
misago/admin/views/generic/formsbuttons.py

@@ -12,17 +12,17 @@ class TargetedView(AdminView):
         pass
         pass
 
 
     def get_target(self, kwargs):
     def get_target(self, kwargs):
-        if len(kwargs) == 1:
-            select_for_update = self.get_model().objects
-            if self.is_atomic:
-                select_for_update = select_for_update.select_for_update()
-            # Does not work on Python 3:
-            # return select_for_update.get(pk=kwargs[kwargs.keys()[0]])
-            (pk,) = kwargs.values()
-            return select_for_update.get(pk=pk)
-        else:
+        if len(kwargs) != 1:
             return self.get_model()()
             return self.get_model()()
 
 
+        select_for_update = self.get_model().objects
+        if self.is_atomic:
+            select_for_update = select_for_update.select_for_update()
+        # Does not work on Python 3:
+        # return select_for_update.get(pk=kwargs[kwargs.keys()[0]])
+        (pk,) = kwargs.values()
+        return select_for_update.get(pk=pk)
+
     def get_target_or_none(self, request, kwargs):
     def get_target_or_none(self, request, kwargs):
         try:
         try:
             return self.get_target(kwargs)
             return self.get_target(kwargs)
@@ -33,8 +33,7 @@ class TargetedView(AdminView):
         if self.is_atomic:
         if self.is_atomic:
             with transaction.atomic():
             with transaction.atomic():
                 return self.wrapped_dispatch(request, *args, **kwargs)
                 return self.wrapped_dispatch(request, *args, **kwargs)
-        else:
-            return self.wrapped_dispatch(request, *args, **kwargs)
+        return self.wrapped_dispatch(request, *args, **kwargs)
 
 
     def wrapped_dispatch(self, request, *args, **kwargs):
     def wrapped_dispatch(self, request, *args, **kwargs):
         target = self.get_target_or_none(request, kwargs)
         target = self.get_target_or_none(request, kwargs)
@@ -42,7 +41,9 @@ class TargetedView(AdminView):
             messages.error(request, self.message_404)
             messages.error(request, self.message_404)
             return redirect(self.root_link)
             return redirect(self.root_link)
 
 
-        error = self.check_permissions(request, target)
+        error = self.check_permissions(  # pylint: disable=assignment-from-no-return
+            request, target
+        )
         if error:
         if error:
             messages.error(request, error)
             messages.error(request, error)
             return redirect(self.root_link)
             return redirect(self.root_link)
@@ -63,8 +64,7 @@ class FormView(TargetedView):
     def initialize_form(self, form, request):
     def initialize_form(self, form, request):
         if request.method == "POST":
         if request.method == "POST":
             return form(request.POST, request.FILES)
             return form(request.POST, request.FILES)
-        else:
-            return form()
+        return form()
 
 
     def handle_form(self, form, request):
     def handle_form(self, form, request):
         raise NotImplementedError(
         raise NotImplementedError(
@@ -80,10 +80,9 @@ class FormView(TargetedView):
 
 
             if response:
             if response:
                 return response
                 return response
-            elif "stay" in request.POST:
+            if "stay" in request.POST:
                 return redirect(request.path)
                 return redirect(request.path)
-            else:
-                return redirect(self.root_link)
+            return redirect(self.root_link)
 
 
         return self.render(request, {"form": form})
         return self.render(request, {"form": form})
 
 
@@ -97,8 +96,7 @@ class ModelFormView(FormView):
     def initialize_form(self, form, request, target):
     def initialize_form(self, form, request, target):
         if request.method == "POST":
         if request.method == "POST":
             return form(request.POST, request.FILES, instance=target)
             return form(request.POST, request.FILES, instance=target)
-        else:
-            return form(instance=target)
+        return form(instance=target)
 
 
     def handle_form(self, form, request, target):
     def handle_form(self, form, request, target):
         form.instance.save()
         form.instance.save()
@@ -110,14 +108,14 @@ class ModelFormView(FormView):
         form = self.initialize_form(FormType, request, target)
         form = self.initialize_form(FormType, request, target)
 
 
         if request.method == "POST" and form.is_valid():
         if request.method == "POST" and form.is_valid():
-            response = self.handle_form(form, request, target)
-
+            response = self.handle_form(  # pylint: disable=assignment-from-no-return
+                form, request, target
+            )
             if response:
             if response:
                 return response
                 return response
-            elif "stay" in request.POST:
+            if "stay" in request.POST:
                 return redirect(request.path)
                 return redirect(request.path)
-            else:
-                return redirect(self.root_link)
+            return redirect(self.root_link)
 
 
         return self.render(request, {"form": form, "target": target})
         return self.render(request, {"form": form, "target": target})
 
 

+ 9 - 12
misago/admin/views/generic/list.py

@@ -60,7 +60,9 @@ class ListView(AdminView):
     def get_queryset(self):
     def get_queryset(self):
         return self.get_model().objects.all()
         return self.get_model().objects.all()
 
 
-    def dispatch(self, request, *args, **kwargs):
+    def dispatch(
+        self, request, *args, **kwargs
+    ):  # pylint: disable=too-many-branches, too-many-locals
         mass_actions_list = self.mass_actions or []
         mass_actions_list = self.mass_actions or []
         extra_actions_list = self.extra_actions or []
         extra_actions_list = self.extra_actions or []
 
 
@@ -90,8 +92,7 @@ class ListView(AdminView):
                 response = self.handle_mass_action(request, context)
                 response = self.handle_mass_action(request, context)
                 if response:
                 if response:
                     return response
                     return response
-                else:
-                    return redirect(request.path)
+                return redirect(request.path)
             except MassActionError as e:
             except MassActionError as e:
                 messages.error(request, e.args[0])
                 messages.error(request, e.args[0])
 
 
@@ -214,8 +215,6 @@ class ListView(AdminView):
         for method in ("GET", "session"):
         for method in ("GET", "session"):
             if methods.get(method):
             if methods.get(method):
                 return methods.get(method)
                 return methods.get(method)
-        else:
-            return {}
 
 
     def apply_filtering_on_context(self, context, active_filters, search_form):
     def apply_filtering_on_context(self, context, active_filters, search_form):
         context["active_filters"] = active_filters
         context["active_filters"] = active_filters
@@ -248,11 +247,10 @@ class ListView(AdminView):
         return self.clean_ordering(new_ordering)
         return self.clean_ordering(new_ordering)
 
 
     def clean_ordering(self, new_ordering):
     def clean_ordering(self, new_ordering):
-        for order_by, _ in self.ordering:
+        for order_by, _ in self.ordering:  # pylint: disable=not-an-iterable
             if order_by == new_ordering:
             if order_by == new_ordering:
                 return order_by
                 return order_by
-        else:
-            return None
+        return None
 
 
     def get_ordering_methods(self, request):
     def get_ordering_methods(self, request):
         return {
         return {
@@ -267,7 +265,7 @@ class ListView(AdminView):
                 return methods.get(method)
                 return methods.get(method)
 
 
     def set_ordering_in_context(self, context, method):
     def set_ordering_in_context(self, context, method):
-        for order_by, name in self.ordering:
+        for order_by, name in self.ordering:  # pylint: disable=not-an-iterable
             order_as_dict = {
             order_as_dict = {
                 "type": "desc" if order_by[0] == "-" else "asc",
                 "type": "desc" if order_by[0] == "-" else "asc",
                 "order_by": order_by,
                 "order_by": order_by,
@@ -306,11 +304,10 @@ class ListView(AdminView):
             return action_callable(request, action_queryset)
             return action_callable(request, action_queryset)
 
 
     def select_mass_action(self, action):
     def select_mass_action(self, action):
-        for definition in self.mass_actions:
+        for definition in self.mass_actions:  # pylint: disable=not-an-iterable
             if definition["action"] == action:
             if definition["action"] == action:
                 return definition
                 return definition
-        else:
-            raise MassActionError(_("Action is not allowed."))
+        raise MassActionError(_("Action is not allowed."))
 
 
     # Querystring builder
     # Querystring builder
     def make_querystring(self, context):
     def make_querystring(self, context):

+ 1 - 1
misago/admin/views/generic/mixin.py

@@ -1,4 +1,4 @@
-class AdminBaseMixin(object):
+class AdminBaseMixin:
     """
     """
     Admin mixin abstraciton used for configuring admin CRUD views.
     Admin mixin abstraciton used for configuring admin CRUD views.
 
 

+ 1 - 1
misago/admin/views/index.py

@@ -77,7 +77,7 @@ def check_version(request):
                 }
                 }
 
 
             cache.set(VERSION_CHECK_CACHE_KEY, version, 180)
             cache.set(VERSION_CHECK_CACHE_KEY, version, 180)
-        except (RequestException, IndexError, KeyError, ValueError) as e:
+        except (RequestException, IndexError, KeyError, ValueError):
             version = {
             version = {
                 "is_error": True,
                 "is_error": True,
                 "message": _("Failed to connect to pypi.org API. Try again later."),
                 "message": _("Failed to connect to pypi.org API. Try again later."),

+ 1 - 1
misago/categories/admin.py

@@ -19,7 +19,7 @@ from .views.permsadmin import (
 )
 )
 
 
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
     def register_urlpatterns(self, urlpatterns):
         # Categories section
         # Categories section
         urlpatterns.namespace(r"^categories/", "categories")
         urlpatterns.namespace(r"^categories/", "categories")

+ 1 - 1
misago/categories/forms.py

@@ -11,7 +11,7 @@ from ..threads.threadtypes import trees_map
 from .models import Category, CategoryRole
 from .models import Category, CategoryRole
 
 
 
 
-class AdminCategoryFieldMixin(object):
+class AdminCategoryFieldMixin:
     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", "- - ")

+ 1 - 1
misago/categories/views/categoriesadmin.py

@@ -52,7 +52,7 @@ class CategoriesList(CategoryAdmin, generic.ListView):
         return context
         return context
 
 
 
 
-class CategoryFormMixin(object):
+class CategoryFormMixin:
     def create_form_type(self, request, target):
     def create_form_type(self, request, target):
         return CategoryFormFactory(target)
         return CategoryFormFactory(target)
 
 

+ 1 - 1
misago/categories/views/permsadmin.py

@@ -27,7 +27,7 @@ class CategoryRolesList(CategoryRoleAdmin, generic.ListView):
     ordering = (("name", None),)
     ordering = (("name", None),)
 
 
 
 
-class RoleFormMixin(object):
+class RoleFormMixin:
     def real_dispatch(self, request, target):
     def real_dispatch(self, request, target):
         form = CategoryRoleForm(instance=target)
         form = CategoryRoleForm(instance=target)
 
 

+ 1 - 1
misago/conf/admin.py

@@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _
 from . import views
 from . import views
 
 
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
     def register_urlpatterns(self, urlpatterns):
         urlpatterns.namespace(r"^settings/", "settings", "system")
         urlpatterns.namespace(r"^settings/", "settings", "system")
 
 

+ 1 - 1
misago/conf/forms.py

@@ -7,7 +7,7 @@ from ..admin.forms import YesNoSwitch
 __all__ = ["ChangeSettingsForm"]
 __all__ = ["ChangeSettingsForm"]
 
 
 
 
-class ValidateChoicesNum(object):
+class ValidateChoicesNum:
     def __init__(self, min_choices=0, max_choices=0):
     def __init__(self, min_choices=0, max_choices=0):
         self.min_choices = min_choices
         self.min_choices = min_choices
         self.max_choices = max_choices
         self.max_choices = max_choices

+ 1 - 1
misago/conf/staticsettings.py

@@ -3,7 +3,7 @@ from django.conf import settings
 from . import defaults
 from . import defaults
 
 
 
 
-class StaticSettings(object):
+class StaticSettings:
     def __getattr__(self, name):
     def __getattr__(self, name):
         try:
         try:
             return getattr(settings, name)
             return getattr(settings, name)

+ 1 - 1
misago/core/admin.py

@@ -1,7 +1,7 @@
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import gettext_lazy as _
 
 
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
     def register_urlpatterns(self, urlpatterns):
         urlpatterns.namespace(r"^system/", "system")
         urlpatterns.namespace(r"^system/", "system")
 
 

+ 1 - 1
misago/core/apipatch.py

@@ -10,7 +10,7 @@ class InvalidAction(Exception):
     pass
     pass
 
 
 
 
-class ApiPatch(object):
+class ApiPatch:
     def __init__(self):
     def __init__(self):
         self._actions = []
         self._actions = []
 
 

+ 1 - 1
misago/core/page.py

@@ -1,4 +1,4 @@
-class Page(object):
+class Page:
     """
     """
     Misago page utility
     Misago page utility
 
 

+ 1 - 1
misago/core/serializers.py

@@ -1,4 +1,4 @@
-class MutableFields(object):
+class MutableFields:
     @classmethod
     @classmethod
     def subset_fields(cls, *fields):
     def subset_fields(cls, *fields):
         fields_in_name = [f.title().replace("_", "") for f in fields]
         fields_in_name = [f.title().replace("_", "") for f in fields]

+ 1 - 1
misago/core/testproject/models.py

@@ -1,4 +1,4 @@
-class Model(object):
+class Model:
     def __init__(self, pk, slug):
     def __init__(self, pk, slug):
         self.id, self.pk = pk, pk
         self.id, self.pk = pk, pk
         self.slug = slug
         self.slug = slug

+ 2 - 2
misago/core/tests/test_apipatch.py

@@ -5,12 +5,12 @@ from django.test import TestCase
 from ..apipatch import ApiPatch, InvalidAction
 from ..apipatch import ApiPatch, InvalidAction
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, data=None):
     def __init__(self, data=None):
         self.data = data
         self.data = data
 
 
 
 
-class MockObject(object):
+class MockObject:
     def __init__(self, pk):
     def __init__(self, pk):
         self.id = pk
         self.id = pk
         self.pk = pk
         self.pk = pk

+ 2 - 2
misago/core/tests/test_context_processors.py

@@ -4,7 +4,7 @@ from django.utils import translation
 from .. import context_processors
 from .. import context_processors
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     path = "/"
     path = "/"
 
 
     def __init__(self, secure, host):
     def __init__(self, secure, host):
@@ -18,7 +18,7 @@ class MockRequest(object):
         return self.host
         return self.host
 
 
 
 
-class MetaMockRequest(object):
+class MetaMockRequest:
     def __init__(self, meta):
     def __init__(self, meta):
         self.META = meta
         self.META = meta
 
 

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

@@ -3,7 +3,7 @@ from django.test import TestCase
 from ..middleware import FrontendContextMiddleware
 from ..middleware import FrontendContextMiddleware
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     pass
     pass
 
 
 
 

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

@@ -6,7 +6,7 @@ from django.utils.encoding import smart_str
 from .. import setup
 from .. import setup
 
 
 
 
-class MockParser(object):
+class MockParser:
     def error(self, message):
     def error(self, message):
         raise ValueError(message)
         raise ValueError(message)
 
 

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

@@ -88,7 +88,7 @@ class BatchTests(TestCase):
             self.assertEqual(test_result, result[i])
             self.assertEqual(test_result, result[i])
 
 
 
 
-class MockUser(object):
+class MockUser:
     id = 12
     id = 12
     pk = 12
     pk = 12
     username = "User"
     username = "User"

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

@@ -118,7 +118,7 @@ return:     %s
             self.assertEqual(output, html, assertion_message)
             self.assertEqual(output, html, assertion_message)
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     scheme = "http"
     scheme = "http"
 
 
     def __init__(self, method, meta=None, post=None):
     def __init__(self, method, meta=None, post=None):

+ 1 - 1
misago/core/validators.py

@@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _
 from .utils import slugify
 from .utils import slugify
 
 
 
 
-class validate_sluggable(object):
+class validate_sluggable:
     def __init__(self, error_short=None, error_long=None):
     def __init__(self, error_short=None, error_long=None):
         self.error_short = error_short or _(
         self.error_short = error_short or _(
             "Value has to contain alpha-numerical characters."
             "Value has to contain alpha-numerical characters."

+ 1 - 1
misago/core/viewmodel.py

@@ -1,4 +1,4 @@
-class ViewModel(object):
+class ViewModel:
     def __getattr__(self, name):
     def __getattr__(self, name):
         return getattr(self._model, name)
         return getattr(self._model, name)
 
 

+ 1 - 1
misago/faker/englishcorpus.py

@@ -4,7 +4,7 @@ import random
 PHRASES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "phrases.txt")
 PHRASES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "phrases.txt")
 
 
 
 
-class EnglishCorpus(object):
+class EnglishCorpus:
     def __init__(self, phrases_file=PHRASES_FILE, min_length=None, max_length=None):
     def __init__(self, phrases_file=PHRASES_FILE, min_length=None, max_length=None):
         self._countdown = 0
         self._countdown = 0
         self._previous = None
         self._previous = None

+ 1 - 1
misago/legal/admin.py

@@ -10,7 +10,7 @@ from .views.admin import (
 )
 )
 
 
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
     def register_urlpatterns(self, urlpatterns):
         # Legal Agreements
         # Legal Agreements
         urlpatterns.namespace(r"^agreements/", "agreements", "users")
         urlpatterns.namespace(r"^agreements/", "agreements", "users")

+ 1 - 1
misago/legal/tests/test_context_processors.py

@@ -5,7 +5,7 @@ from ..context_processors import legal_links
 from ..models import Agreement
 from ..models import Agreement
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, user):
     def __init__(self, user):
         self.user = user
         self.user = user
         self.frontend_context = {}
         self.frontend_context = {}

+ 1 - 1
misago/legal/tests/test_utils.py

@@ -10,7 +10,7 @@ from ..utils import (
 )
 )
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, user=None):
     def __init__(self, user=None):
         self.user = user
         self.user = user
         self.frontend_context = {}
         self.frontend_context = {}

+ 1 - 1
misago/markup/bbcode/inline.py

@@ -36,7 +36,7 @@ italics = SimpleBBCodePattern("i")
 underline = SimpleBBCodePattern("u")
 underline = SimpleBBCodePattern("u")
 
 
 
 
-class BBcodePattern(object):
+class BBcodePattern:
     def __init__(self, pattern, markdown_instance=None):
     def __init__(self, pattern, markdown_instance=None):
         self.pattern = pattern
         self.pattern = pattern
         self.compiled_re = re.compile(
         self.compiled_re = re.compile(

+ 1 - 1
misago/markup/pipeline.py

@@ -5,7 +5,7 @@ from bs4 import BeautifulSoup
 from ..conf import settings
 from ..conf import settings
 
 
 
 
-class MarkupPipeline(object):
+class MarkupPipeline:
     """small framework for extending parser"""
     """small framework for extending parser"""
 
 
     def extend_markdown(self, md):
     def extend_markdown(self, md):

+ 1 - 1
misago/markup/tests/test_mentions.py

@@ -2,7 +2,7 @@ from ...users.test import AuthenticatedUserTestCase
 from ..mentions import add_mentions
 from ..mentions import add_mentions
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, user):
     def __init__(self, user):
         self.user = user
         self.user = user
 
 

+ 2 - 2
misago/markup/tests/test_parser.py

@@ -4,7 +4,7 @@ from ...users.test import create_test_user
 from ..parser import parse
 from ..parser import parse
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     scheme = "http"
     scheme = "http"
 
 
     def __init__(self, user=None):
     def __init__(self, user=None):
@@ -14,7 +14,7 @@ class MockRequest(object):
         return "test.com"
         return "test.com"
 
 
 
 
-class MockPoster(object):
+class MockPoster:
     username = "LoremIpsum"
     username = "LoremIpsum"
     slug = "loremipsum"
     slug = "loremipsum"
 
 

+ 1 - 1
misago/readtracker/tests/test_categoriestracker.py

@@ -15,7 +15,7 @@ from ..models import PostRead
 cache_versions = get_cache_versions()
 cache_versions = get_cache_versions()
 
 
 
 
-class AnonymousUser(object):
+class AnonymousUser:
     is_authenticated = False
     is_authenticated = False
     is_anonymous = True
     is_anonymous = True
 
 

+ 2 - 2
misago/readtracker/tests/test_dates.py

@@ -7,14 +7,14 @@ from ...conf import settings
 from ..dates import get_cutoff_date, is_date_tracked
 from ..dates import get_cutoff_date, is_date_tracked
 
 
 
 
-class MockUser(object):
+class MockUser:
     is_authenticated = True
     is_authenticated = True
 
 
     def __init__(self):
     def __init__(self):
         self.joined_on = timezone.now()
         self.joined_on = timezone.now()
 
 
 
 
-class MockAnonymousUser(object):
+class MockAnonymousUser:
     is_authenticated = False
     is_authenticated = False
 
 
 
 

+ 1 - 1
misago/readtracker/tests/test_poststracker.py

@@ -11,7 +11,7 @@ from ..models import PostRead
 from ..poststracker import make_read_aware, save_read
 from ..poststracker import make_read_aware, save_read
 
 
 
 
-class AnonymousUser(object):
+class AnonymousUser:
     is_authenticated = False
     is_authenticated = False
     is_anonymous = True
     is_anonymous = True
 
 

+ 1 - 1
misago/readtracker/tests/test_threadstracker.py

@@ -16,7 +16,7 @@ from ..models import PostRead
 cache_versions = get_cache_versions()
 cache_versions = get_cache_versions()
 
 
 
 
-class AnonymousUser(object):
+class AnonymousUser:
     is_authenticated = False
     is_authenticated = False
     is_anonymous = True
     is_anonymous = True
 
 

+ 1 - 1
misago/search/searchprovider.py

@@ -1,4 +1,4 @@
-class SearchProvider(object):
+class SearchProvider:
     def __init__(self, request):
     def __init__(self, request):
         self.request = request
         self.request = request
 
 

+ 1 - 1
misago/search/searchproviders.py

@@ -4,7 +4,7 @@ from django.utils.module_loading import import_string
 from ..conf import settings
 from ..conf import settings
 
 
 
 
-class SearchProviders(object):
+class SearchProviders:
     def __init__(self, search_providers):
     def __init__(self, search_providers):
         self._initialized = False
         self._initialized = False
         self._providers = []
         self._providers = []

+ 1 - 1
misago/threads/admin.py

@@ -10,7 +10,7 @@ from .views.admin.attachmenttypes import (
 )
 )
 
 
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
     def register_urlpatterns(self, urlpatterns):
         # Attachment
         # Attachment
         urlpatterns.namespace(r"^attachments/", "attachments", "system")
         urlpatterns.namespace(r"^attachments/", "attachments", "system")

+ 2 - 2
misago/threads/api/postingendpoint/__init__.py

@@ -15,7 +15,7 @@ class PostingInterrupt(Exception):
         self.message = message
         self.message = message
 
 
 
 
-class PostingEndpoint(object):
+class PostingEndpoint:
     START = 0
     START = 0
     REPLY = 1
     REPLY = 1
     EDIT = 2
     EDIT = 2
@@ -138,7 +138,7 @@ class PostingEndpoint(object):
             )
             )
 
 
 
 
-class PostingMiddleware(object):
+class PostingMiddleware:
     """abstract middleware class"""
     """abstract middleware class"""
 
 
     def __init__(self, **kwargs):
     def __init__(self, **kwargs):

+ 1 - 1
misago/threads/api/threadendpoints/list.py

@@ -10,7 +10,7 @@ from ...viewmodels import (
 )
 )
 
 
 
 
-class ThreadsList(object):
+class ThreadsList:
     threads = None
     threads = None
 
 
     def __call__(self, request, **kwargs):
     def __call__(self, request, **kwargs):

+ 2 - 2
misago/threads/mergeconflict.py

@@ -4,7 +4,7 @@ from rest_framework.exceptions import ValidationError
 from .models import Poll
 from .models import Poll
 
 
 
 
-class MergeConflictHandler(object):
+class MergeConflictHandler:
     def __init__(self, threads):
     def __init__(self, threads):
         self.items = []
         self.items = []
         self.choices = {0: None}
         self.choices = {0: None}
@@ -80,7 +80,7 @@ class PollMergeHandler(MergeConflictHandler):
         return resolutions
         return resolutions
 
 
 
 
-class MergeConflict(object):
+class MergeConflict:
     """
     """
     Utility class single point of entry for detecting merge conflicts on different properties
     Utility class single point of entry for detecting merge conflicts on different properties
     and validating user resolutions.
     and validating user resolutions.

+ 1 - 1
misago/threads/tests/test_threads_moderation.py

@@ -4,7 +4,7 @@ from ...users.test import AuthenticatedUserTestCase
 from ..models import Thread
 from ..models import Thread
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, user):
     def __init__(self, user):
         self.user = user
         self.user = user
         self.user_ip = "123.14.15.222"
         self.user_ip = "123.14.15.222"

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

@@ -123,7 +123,7 @@ class AddCategoriesToItemsTests(TestCase):
         self.assertEqual(thread.category, self.category_d)
         self.assertEqual(thread.category, self.category_d)
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, scheme, host, wsgialias=""):
     def __init__(self, scheme, host, wsgialias=""):
         self.scheme = scheme
         self.scheme = scheme
         self.host = host
         self.host = host

+ 1 - 1
misago/threads/threadtypes/__init__.py

@@ -1,7 +1,7 @@
 from .treesmap import trees_map
 from .treesmap import trees_map
 
 
 
 
-class ThreadType(object):
+class ThreadType:
     """Abstract class for thread type strategy"""
     """Abstract class for thread type strategy"""
 
 
     root_name = "undefined"
     root_name = "undefined"

+ 1 - 1
misago/threads/threadtypes/treesmap.py

@@ -3,7 +3,7 @@ from django.utils.module_loading import import_string
 from ...conf import settings
 from ...conf import settings
 
 
 
 
-class TreesMap(object):
+class TreesMap:
     """Object that maps trees to strategies"""
     """Object that maps trees to strategies"""
 
 
     def __init__(self, types_modules):
     def __init__(self, types_modules):

+ 1 - 1
misago/threads/viewmodels/posts.py

@@ -11,7 +11,7 @@ from ..utils import add_likes_to_posts
 __all__ = ["ThreadPosts"]
 __all__ = ["ThreadPosts"]
 
 
 
 
-class ViewModel(object):
+class ViewModel:
     def __init__(self, request, thread, page):
     def __init__(self, request, thread, page):
         try:
         try:
             thread_model = thread.unwrap()
             thread_model = thread.unwrap()

+ 1 - 1
misago/threads/viewmodels/threads.py

@@ -47,7 +47,7 @@ LIST_DENIED_MESSAGES = {
 }
 }
 
 
 
 
-class ViewModel(object):
+class ViewModel:
     def __init__(self, request, category, list_type, page):
     def __init__(self, request, category, list_type, page):
         self.allow_see_list(request, category, list_type)
         self.allow_see_list(request, category, list_type)
 
 

+ 1 - 1
misago/threads/views/goto.py

@@ -87,7 +87,7 @@ class ThreadGotoLastView(GotoView):
         return posts_queryset.order_by("id").last()
         return posts_queryset.order_by("id").last()
 
 
 
 
-class GetFirstUnreadPostMixin(object):
+class GetFirstUnreadPostMixin:
     def get_first_unread_post(self, user, posts_queryset):
     def get_first_unread_post(self, user, posts_queryset):
         if user.is_authenticated:
         if user.is_authenticated:
             expired_posts = Q(posted_on__lt=get_cutoff_date(user))
             expired_posts = Q(posted_on__lt=get_cutoff_date(user))

+ 1 - 1
misago/users/admin.py

@@ -28,7 +28,7 @@ from .views.admin.users import (
 djadmin.site.register(model_or_iterable=get_user_model(), admin_class=UserAdminModel)
 djadmin.site.register(model_or_iterable=get_user_model(), admin_class=UserAdminModel)
 
 
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
     def register_urlpatterns(self, urlpatterns):
         # Users section
         # Users section
         urlpatterns.namespace(r"^users/", "users")
         urlpatterns.namespace(r"^users/", "users")

+ 1 - 1
misago/users/datadownloads/dataarchive.py

@@ -10,7 +10,7 @@ from ...core.utils import slugify
 FILENAME_MAX_LEN = 50
 FILENAME_MAX_LEN = 50
 
 
 
 
-class DataArchive(object):
+class DataArchive:
     def __init__(self, user, working_dir_path):
     def __init__(self, user, working_dir_path):
         self.user = user
         self.user = user
         self.working_dir_path = working_dir_path
         self.working_dir_path = working_dir_path

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

@@ -10,7 +10,7 @@ from ..bans import get_user_ban
 User = get_user_model()
 User = get_user_model()
 
 
 
 
-class MisagoAuthMixin(object):
+class MisagoAuthMixin:
     error_messages = {
     error_messages = {
         "empty_data": _("Fill out both fields."),
         "empty_data": _("Fill out both fields."),
         "invalid_login": _("Login or password is incorrect."),
         "invalid_login": _("Login or password is incorrect."),

+ 1 - 1
misago/users/profilefields/__init__.py

@@ -15,7 +15,7 @@ from .serializers import serialize_profilefields_data
 logger = logging.getLogger("misago.users.ProfileFields")
 logger = logging.getLogger("misago.users.ProfileFields")
 
 
 
 
-class ProfileFields(object):
+class ProfileFields:
     def __init__(self, fields_groups):
     def __init__(self, fields_groups):
         self.is_loaded = False
         self.is_loaded = False
 
 

+ 1 - 1
misago/users/profilefields/basefields.py

@@ -13,7 +13,7 @@ __all__ = [
 ]
 ]
 
 
 
 
-class ProfileField(object):
+class ProfileField:
     """
     """
     Basic profile field
     Basic profile field
     """
     """

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

@@ -10,7 +10,7 @@ User = get_user_model()
 __all__ = ["AuthenticatedUserSerializer", "AnonymousUserSerializer"]
 __all__ = ["AuthenticatedUserSerializer", "AnonymousUserSerializer"]
 
 
 
 
-class AuthFlags(object):
+class AuthFlags:
     def get_is_authenticated(self, obj):
     def get_is_authenticated(self, obj):
         return bool(obj.is_authenticated)
         return bool(obj.is_authenticated)
 
 

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

@@ -13,7 +13,7 @@ User = get_user_model()
 USER_IP = "13.41.51.41"
 USER_IP = "13.41.51.41"
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     user_ip = USER_IP
     user_ip = USER_IP
 
 
     def __init__(self, user):
     def __init__(self, user):

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

@@ -181,7 +181,7 @@ class AvatarSetterTests(TestCase):
         self.assertAvatarWasSet()
         self.assertAvatarWasSet()
 
 
 
 
-class MockAvatarFile(object):
+class MockAvatarFile:
     def __init__(self, size=None, name=None, mime=None):
     def __init__(self, size=None, name=None, mime=None):
         self.size = size
         self.size = size
         self.name = name
         self.name = name

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

@@ -180,7 +180,7 @@ class UserBansTests(TestCase):
         self.assertFalse(self.user.ban_cache.is_banned)
         self.assertFalse(self.user.ban_cache.is_banned)
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self):
     def __init__(self):
         self.user_ip = "127.0.0.1"
         self.user_ip = "127.0.0.1"
         self.session = {}
         self.session = {}

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

@@ -4,7 +4,7 @@ from ...users import credentialchange
 from ..test import create_test_user
 from ..test import create_test_user
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, user):
     def __init__(self, user):
         self.session = {}
         self.session = {}
         self.user = user
         self.user = user

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

@@ -3,7 +3,7 @@ from django.test import TestCase
 from ..middleware import RealIPMiddleware
 from ..middleware import RealIPMiddleware
 
 
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, addr, forwarded_for=None):
     def __init__(self, addr, forwarded_for=None):
         self.META = {"REMOTE_ADDR": addr}
         self.META = {"REMOTE_ADDR": addr}
 
 

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

@@ -52,7 +52,7 @@ def create_strategy():
     return load_strategy(request=request)
     return load_strategy(request=request)
 
 
 
 
-class MockStrategy(object):
+class MockStrategy:
     def __init__(self, user_ip="0.0.0.0"):
     def __init__(self, user_ip="0.0.0.0"):
         self.cleaned_partial_token = None
         self.cleaned_partial_token = None
         self.request = create_request(user_ip)
         self.request = create_request(user_ip)

+ 2 - 2
misago/users/tests/testfiles/profilefields.py

@@ -1,8 +1,8 @@
-class NofieldnameField(object):
+class NofieldnameField:
     pass
     pass
 
 
 
 
-class FieldnameField(object):
+class FieldnameField:
     fieldname = "hello"
     fieldname = "hello"
 
 
 
 

+ 1 - 1
misago/users/viewmodels/activeposters.py

@@ -4,7 +4,7 @@ from ..online.utils import make_users_status_aware
 from ..serializers import UserCardSerializer
 from ..serializers import UserCardSerializer
 
 
 
 
-class ActivePosters(object):
+class ActivePosters:
     def __init__(self, request):
     def __init__(self, request):
         ranking = get_active_posters_ranking()
         ranking = get_active_posters_ranking()
         make_users_status_aware(request, ranking["users"], fetch_state=True)
         make_users_status_aware(request, ranking["users"], fetch_state=True)

+ 1 - 1
misago/users/viewmodels/followers.py

@@ -6,7 +6,7 @@ from ..online.utils import make_users_status_aware
 from ..serializers import UserCardSerializer
 from ..serializers import UserCardSerializer
 
 
 
 
-class Followers(object):
+class Followers:
     def __init__(self, request, profile, page=0, search=None):
     def __init__(self, request, profile, page=0, search=None):
         queryset = self.get_queryset(profile).select_related("rank").order_by("slug")
         queryset = self.get_queryset(profile).select_related("rank").order_by("slug")
 
 

+ 1 - 1
misago/users/viewmodels/rankusers.py

@@ -4,7 +4,7 @@ from ..online.utils import make_users_status_aware
 from ..serializers import UserCardSerializer
 from ..serializers import UserCardSerializer
 
 
 
 
-class RankUsers(object):
+class RankUsers:
     def __init__(self, request, rank, page=0):
     def __init__(self, request, rank, page=0):
         queryset = rank.user_set.select_related(
         queryset = rank.user_set.select_related(
             "rank", "ban_cache", "online_tracker"
             "rank", "ban_cache", "online_tracker"

+ 1 - 1
misago/users/viewmodels/threads.py

@@ -7,7 +7,7 @@ from ...threads.utils import add_categories_to_items
 from ...threads.viewmodels import ThreadsRootCategory
 from ...threads.viewmodels import ThreadsRootCategory
 
 
 
 
-class UserThreads(object):
+class UserThreads:
     def __init__(self, request, profile, page=0):
     def __init__(self, request, profile, page=0):
         root_category = ThreadsRootCategory(request)
         root_category = ThreadsRootCategory(request)
         threads_categories = [root_category.unwrap()] + root_category.subcategories
         threads_categories = [root_category.unwrap()] + root_category.subcategories