Просмотр исходного кода

Merge pull request #1160 from rafalp/setup-pylint

Add basic pylit-config
Rafał Pitoń 6 лет назад
Родитель
Сommit
a42508efb8
88 измененных файлов с 207 добавлено и 200 удалено
  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
 ignore=migrations
+max-line-length=88
 
 
 [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]

+ 4 - 2
.travis.yml

@@ -20,6 +20,8 @@ jobs:
       python: 3.6
       install:
         - pip install -U pip setuptools
-        - pip install black
+        - python setup.py install
+        - pip install black pylint pylint-django
       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
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
         # Permissions section
         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 not key:
             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)
 
@@ -46,10 +47,9 @@ def greater(a, b):
 def greater_or_zero(a, b):
     if a == 0:
         return a
-    elif b == 0:
+    if b == 0:
         return b
-    else:
-        return greater(a, b)
+    return greater(a, b)
 
 
 def lower(a, b):
@@ -59,7 +59,6 @@ def lower(a, b):
 def lower_non_zero(a, b):
     if a == 0:
         return b
-    elif b == 0:
+    if b == 0:
         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
 
 

+ 1 - 2
misago/acl/panels.py

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

+ 1 - 1
misago/acl/providers.py

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

+ 0 - 1
misago/acl/test.py

@@ -1,5 +1,4 @@
 from contextlib import ContextDecorator, ExitStack, contextmanager
-from functools import wraps
 from unittest.mock import patch
 
 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(4, 2) == 4
     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():
     assert algebra.greater_or_zero(1, 3) == 3
     assert algebra.greater_or_zero(4, 2) == 4
     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(0, 0) == 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(4, 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():

+ 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):
     @patch_user_acl({"is_patched": True})
-    def test_function(patch_user_acl):
+    def test_function():
         user_acl = useracl.get_user_acl(user, cache_versions)
         assert user_acl["is_patched"]
 
+    test_function()
     user_acl = useracl.get_user_acl(user, cache_versions)
     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
 
 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():
-    class TestType(object):
+    class TestType:
         pass
 
     def test_annotator():

+ 3 - 4
misago/acl/views.py

@@ -19,7 +19,7 @@ class RolesList(RoleAdmin, generic.ListView):
     ordering = (("name", None),)
 
 
-class RoleFormMixin(object):
+class RoleFormMixin:
     def real_dispatch(self, request, target):
         form = RoleForm(instance=target)
 
@@ -46,9 +46,8 @@ class RoleFormMixin(object):
 
                 if "stay" in request.POST:
                     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."))
 
         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"""
         if value in (True, "True", "true", 1, "1"):
             return 1
-        else:
-            return 0
+        return 0
 
     def clean(self, value):
         return self.prepare_value(value)

+ 17 - 14
misago/admin/hierarchy.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 
 
-class Node(object):
+class Node:
     def __init__(self, name=None, icon=None, link=None):
         self.parent = None
         self.name = name
@@ -9,15 +9,15 @@ class Node(object):
         self.link = link
         self._children = []
         self._children_dict = {}
+        self._resolved_namespace = None
 
     @property
     def namespace(self):
-        try:
+        if 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
 
     def children(self):
@@ -39,13 +39,12 @@ class Node(object):
     def add_node(self, node, after=None, before=None):
         if after:
             return self.add_node_after(node, after)
-        elif before:
+        if 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):
         success = False
@@ -91,7 +90,7 @@ class Node(object):
         return False
 
 
-class AdminHierarchyBuilder(object):
+class AdminHierarchyBuilder:
     def __init__(self):
         self.nodes_record = []
         self.nodes_dict = {}
@@ -103,7 +102,10 @@ class AdminHierarchyBuilder(object):
         while self.nodes_record:
             iterations += 1
             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)
 
             for index, node in enumerate(self.nodes_record):
@@ -143,7 +145,8 @@ class AdminHierarchyBuilder(object):
     ):
         if self.nodes_dict:
             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:

+ 4 - 5
misago/admin/middleware.py

@@ -9,13 +9,12 @@ from .views.auth import login
 class AdminAuthMiddleware(MiddlewareMixin):
     def process_view(self, request, view_func, view_args, view_kwargs):
         request.admin_namespace = get_protected_namespace(request)
-
         if request.admin_namespace:
             if not auth.is_admin_session(request):
                 auth.close_admin_session(request)
                 if request.resolver_match.url_name == "index":
                     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"
 
 
-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"})
     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})
     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})
     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})
     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})
     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})
     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})
     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")
 
 
-class RequestMock(object):
+class RequestMock:
     absolute_uri = "https://misago-project.org/somewhere/"
 
     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
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, path):
         self.path = path
 

+ 9 - 7
misago/admin/urlpatterns.py

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

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

@@ -15,8 +15,7 @@ def get_protected_namespace(request):
                 return namespace
         except NoReverseMatch:
             pass
-    else:
-        return None
+    return None
 
 
 def render(request, template, context=None, error_page=False):
@@ -61,10 +60,8 @@ def protected_admin_view(f):
             if is_admin_session(request):
                 update_admin_session(request)
                 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

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

@@ -38,5 +38,4 @@ def logout(request):
         auth.close_admin_session(request)
         messages.info(request, _("Your admin session has been closed."))
         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
 @protected_admin_view
 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")
 
+    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 decorator(request, *args, **kwargs):
         if get_protected_namespace(request):
             update_admin_session(request)
             return _error_page(request, *args, **kwargs)
-        else:
-            return f(request, *args, **kwargs)
+        return f(request, *args, **kwargs)
 
     return decorator
 
@@ -53,7 +52,6 @@ def admin_csrf_failure(f):
     def decorator(request, *args, **kwargs):
         if get_protected_namespace(request):
             return _csrf_failure(request, *args, **kwargs)
-        else:
-            return f(request, *args, **kwargs)
+        return f(request, *args, **kwargs)
 
     return decorator

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

@@ -12,17 +12,17 @@ class TargetedView(AdminView):
         pass
 
     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()()
 
+        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):
         try:
             return self.get_target(kwargs)
@@ -33,8 +33,7 @@ class TargetedView(AdminView):
         if self.is_atomic:
             with transaction.atomic():
                 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):
         target = self.get_target_or_none(request, kwargs)
@@ -42,7 +41,9 @@ class TargetedView(AdminView):
             messages.error(request, self.message_404)
             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:
             messages.error(request, error)
             return redirect(self.root_link)
@@ -63,8 +64,7 @@ class FormView(TargetedView):
     def initialize_form(self, form, request):
         if request.method == "POST":
             return form(request.POST, request.FILES)
-        else:
-            return form()
+        return form()
 
     def handle_form(self, form, request):
         raise NotImplementedError(
@@ -80,10 +80,9 @@ class FormView(TargetedView):
 
             if response:
                 return response
-            elif "stay" in request.POST:
+            if "stay" in request.POST:
                 return redirect(request.path)
-            else:
-                return redirect(self.root_link)
+            return redirect(self.root_link)
 
         return self.render(request, {"form": form})
 
@@ -97,8 +96,7 @@ class ModelFormView(FormView):
     def initialize_form(self, form, request, target):
         if request.method == "POST":
             return form(request.POST, request.FILES, instance=target)
-        else:
-            return form(instance=target)
+        return form(instance=target)
 
     def handle_form(self, form, request, target):
         form.instance.save()
@@ -110,14 +108,14 @@ class ModelFormView(FormView):
         form = self.initialize_form(FormType, request, target)
 
         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:
                 return response
-            elif "stay" in request.POST:
+            if "stay" in request.POST:
                 return redirect(request.path)
-            else:
-                return redirect(self.root_link)
+            return redirect(self.root_link)
 
         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):
         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 []
         extra_actions_list = self.extra_actions or []
 
@@ -90,8 +92,7 @@ class ListView(AdminView):
                 response = self.handle_mass_action(request, context)
                 if response:
                     return response
-                else:
-                    return redirect(request.path)
+                return redirect(request.path)
             except MassActionError as e:
                 messages.error(request, e.args[0])
 
@@ -214,8 +215,6 @@ class ListView(AdminView):
         for method in ("GET", "session"):
             if methods.get(method):
                 return methods.get(method)
-        else:
-            return {}
 
     def apply_filtering_on_context(self, context, active_filters, search_form):
         context["active_filters"] = active_filters
@@ -248,11 +247,10 @@ class ListView(AdminView):
         return self.clean_ordering(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:
                 return order_by
-        else:
-            return None
+        return None
 
     def get_ordering_methods(self, request):
         return {
@@ -267,7 +265,7 @@ class ListView(AdminView):
                 return methods.get(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 = {
                 "type": "desc" if order_by[0] == "-" else "asc",
                 "order_by": order_by,
@@ -306,11 +304,10 @@ class ListView(AdminView):
             return action_callable(request, action_queryset)
 
     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:
                 return definition
-        else:
-            raise MassActionError(_("Action is not allowed."))
+        raise MassActionError(_("Action is not allowed."))
 
     # Querystring builder
     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.
 

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

@@ -77,7 +77,7 @@ def check_version(request):
                 }
 
             cache.set(VERSION_CHECK_CACHE_KEY, version, 180)
-        except (RequestException, IndexError, KeyError, ValueError) as e:
+        except (RequestException, IndexError, KeyError, ValueError):
             version = {
                 "is_error": True,
                 "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):
         # Categories section
         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
 
 
-class AdminCategoryFieldMixin(object):
+class AdminCategoryFieldMixin:
     def __init__(self, *args, **kwargs):
         self.base_level = kwargs.pop("base_level", 1)
         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
 
 
-class CategoryFormMixin(object):
+class CategoryFormMixin:
     def create_form_type(self, request, target):
         return CategoryFormFactory(target)
 

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

@@ -27,7 +27,7 @@ class CategoryRolesList(CategoryRoleAdmin, generic.ListView):
     ordering = (("name", None),)
 
 
-class RoleFormMixin(object):
+class RoleFormMixin:
     def real_dispatch(self, request, 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
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
         urlpatterns.namespace(r"^settings/", "settings", "system")
 

+ 1 - 1
misago/conf/forms.py

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

+ 1 - 1
misago/conf/staticsettings.py

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

+ 1 - 1
misago/core/admin.py

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

+ 1 - 1
misago/core/apipatch.py

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

+ 1 - 1
misago/core/page.py

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

+ 1 - 1
misago/core/serializers.py

@@ -1,4 +1,4 @@
-class MutableFields(object):
+class MutableFields:
     @classmethod
     def subset_fields(cls, *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):
         self.id, self.pk = pk, pk
         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
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, data=None):
         self.data = data
 
 
-class MockObject(object):
+class MockObject:
     def __init__(self, pk):
         self.id = 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
 
 
-class MockRequest(object):
+class MockRequest:
     path = "/"
 
     def __init__(self, secure, host):
@@ -18,7 +18,7 @@ class MockRequest(object):
         return self.host
 
 
-class MetaMockRequest(object):
+class MetaMockRequest:
     def __init__(self, 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
 
 
-class MockRequest(object):
+class MockRequest:
     pass
 
 

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

@@ -6,7 +6,7 @@ from django.utils.encoding import smart_str
 from .. import setup
 
 
-class MockParser(object):
+class MockParser:
     def error(self, 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])
 
 
-class MockUser(object):
+class MockUser:
     id = 12
     pk = 12
     username = "User"

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

@@ -118,7 +118,7 @@ return:     %s
             self.assertEqual(output, html, assertion_message)
 
 
-class MockRequest(object):
+class MockRequest:
     scheme = "http"
 
     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
 
 
-class validate_sluggable(object):
+class validate_sluggable:
     def __init__(self, error_short=None, error_long=None):
         self.error_short = error_short or _(
             "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):
         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")
 
 
-class EnglishCorpus(object):
+class EnglishCorpus:
     def __init__(self, phrases_file=PHRASES_FILE, min_length=None, max_length=None):
         self._countdown = 0
         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):
         # Legal Agreements
         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
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, user):
         self.user = user
         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):
         self.user = user
         self.frontend_context = {}

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

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

+ 1 - 1
misago/markup/pipeline.py

@@ -5,7 +5,7 @@ from bs4 import BeautifulSoup
 from ..conf import settings
 
 
-class MarkupPipeline(object):
+class MarkupPipeline:
     """small framework for extending parser"""
 
     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
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, 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
 
 
-class MockRequest(object):
+class MockRequest:
     scheme = "http"
 
     def __init__(self, user=None):
@@ -14,7 +14,7 @@ class MockRequest(object):
         return "test.com"
 
 
-class MockPoster(object):
+class MockPoster:
     username = "LoremIpsum"
     slug = "loremipsum"
 

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

@@ -15,7 +15,7 @@ from ..models import PostRead
 cache_versions = get_cache_versions()
 
 
-class AnonymousUser(object):
+class AnonymousUser:
     is_authenticated = False
     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
 
 
-class MockUser(object):
+class MockUser:
     is_authenticated = True
 
     def __init__(self):
         self.joined_on = timezone.now()
 
 
-class MockAnonymousUser(object):
+class MockAnonymousUser:
     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
 
 
-class AnonymousUser(object):
+class AnonymousUser:
     is_authenticated = False
     is_anonymous = True
 

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

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

+ 1 - 1
misago/search/searchprovider.py

@@ -1,4 +1,4 @@
-class SearchProvider(object):
+class SearchProvider:
     def __init__(self, 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
 
 
-class SearchProviders(object):
+class SearchProviders:
     def __init__(self, search_providers):
         self._initialized = False
         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):
         # Attachment
         urlpatterns.namespace(r"^attachments/", "attachments", "system")

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

@@ -15,7 +15,7 @@ class PostingInterrupt(Exception):
         self.message = message
 
 
-class PostingEndpoint(object):
+class PostingEndpoint:
     START = 0
     REPLY = 1
     EDIT = 2
@@ -138,7 +138,7 @@ class PostingEndpoint(object):
             )
 
 
-class PostingMiddleware(object):
+class PostingMiddleware:
     """abstract middleware class"""
 
     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
 
     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
 
 
-class MergeConflictHandler(object):
+class MergeConflictHandler:
     def __init__(self, threads):
         self.items = []
         self.choices = {0: None}
@@ -80,7 +80,7 @@ class PollMergeHandler(MergeConflictHandler):
         return resolutions
 
 
-class MergeConflict(object):
+class MergeConflict:
     """
     Utility class single point of entry for detecting merge conflicts on different properties
     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
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, user):
         self.user = user
         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)
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, scheme, host, wsgialias=""):
         self.scheme = scheme
         self.host = host

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

@@ -1,7 +1,7 @@
 from .treesmap import trees_map
 
 
-class ThreadType(object):
+class ThreadType:
     """Abstract class for thread type strategy"""
 
     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
 
 
-class TreesMap(object):
+class TreesMap:
     """Object that maps trees to strategies"""
 
     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"]
 
 
-class ViewModel(object):
+class ViewModel:
     def __init__(self, request, thread, page):
         try:
             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):
         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()
 
 
-class GetFirstUnreadPostMixin(object):
+class GetFirstUnreadPostMixin:
     def get_first_unread_post(self, user, posts_queryset):
         if user.is_authenticated:
             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)
 
 
-class MisagoAdminExtension(object):
+class MisagoAdminExtension:
     def register_urlpatterns(self, urlpatterns):
         # Users section
         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
 
 
-class DataArchive(object):
+class DataArchive:
     def __init__(self, user, working_dir_path):
         self.user = user
         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()
 
 
-class MisagoAuthMixin(object):
+class MisagoAuthMixin:
     error_messages = {
         "empty_data": _("Fill out both fields."),
         "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")
 
 
-class ProfileFields(object):
+class ProfileFields:
     def __init__(self, fields_groups):
         self.is_loaded = False
 

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

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

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

@@ -10,7 +10,7 @@ User = get_user_model()
 __all__ = ["AuthenticatedUserSerializer", "AnonymousUserSerializer"]
 
 
-class AuthFlags(object):
+class AuthFlags:
     def get_is_authenticated(self, obj):
         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"
 
 
-class MockRequest(object):
+class MockRequest:
     user_ip = USER_IP
 
     def __init__(self, user):

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

@@ -181,7 +181,7 @@ class AvatarSetterTests(TestCase):
         self.assertAvatarWasSet()
 
 
-class MockAvatarFile(object):
+class MockAvatarFile:
     def __init__(self, size=None, name=None, mime=None):
         self.size = size
         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)
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self):
         self.user_ip = "127.0.0.1"
         self.session = {}

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

@@ -4,7 +4,7 @@ from ...users import credentialchange
 from ..test import create_test_user
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, user):
         self.session = {}
         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
 
 
-class MockRequest(object):
+class MockRequest:
     def __init__(self, addr, forwarded_for=None):
         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)
 
 
-class MockStrategy(object):
+class MockStrategy:
     def __init__(self, user_ip="0.0.0.0"):
         self.cleaned_partial_token = None
         self.request = create_request(user_ip)

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

@@ -1,8 +1,8 @@
-class NofieldnameField(object):
+class NofieldnameField:
     pass
 
 
-class FieldnameField(object):
+class FieldnameField:
     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
 
 
-class ActivePosters(object):
+class ActivePosters:
     def __init__(self, request):
         ranking = get_active_posters_ranking()
         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
 
 
-class Followers(object):
+class Followers:
     def __init__(self, request, profile, page=0, search=None):
         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
 
 
-class RankUsers(object):
+class RankUsers:
     def __init__(self, request, rank, page=0):
         queryset = rank.user_set.select_related(
             "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
 
 
-class UserThreads(object):
+class UserThreads:
     def __init__(self, request, profile, page=0):
         root_category = ThreadsRootCategory(request)
         threads_categories = [root_category.unwrap()] + root_category.subcategories