Browse Source

Resolve all line-too-long errors raised by pylint

rafalp 6 years ago
parent
commit
3cf45e5908
57 changed files with 362 additions and 238 deletions
  1. 8 13
      misago/categories/forms.py
  2. 0 4
      misago/categories/views/permsadmin.py
  3. 4 4
      misago/legal/forms.py
  4. 3 1
      misago/markup/tests/test_api.py
  5. 8 6
      misago/markup/tests/test_mentions.py
  6. 4 1
      misago/search/tests/test_searchproviders.py
  7. 2 1
      misago/threads/api/attachments.py
  8. 4 2
      misago/threads/api/postingendpoint/__init__.py
  9. 3 1
      misago/threads/api/postingendpoint/attachments.py
  10. 5 2
      misago/threads/api/postingendpoint/category.py
  11. 3 1
      misago/threads/api/postingendpoint/participants.py
  12. 4 2
      misago/threads/api/threadendpoints/editor.py
  13. 2 1
      misago/threads/api/threadendpoints/patch.py
  14. 12 10
      misago/threads/forms.py
  15. 2 2
      misago/threads/mergeconflict.py
  16. 1 1
      misago/threads/paginator.py
  17. 46 53
      misago/threads/permissions/bestanswers.py
  18. 4 2
      misago/threads/serializers/moderation.py
  19. 3 1
      misago/threads/serializers/poll.py
  20. 6 8
      misago/threads/templatetags/misago_poststags.py
  21. 2 1
      misago/threads/tests/test_attachments_api.py
  22. 9 3
      misago/threads/tests/test_attachments_middleware.py
  23. 7 2
      misago/threads/tests/test_mergeconflict.py
  24. 4 1
      misago/threads/tests/test_privatethread_patch_api.py
  25. 4 2
      misago/threads/tests/test_privatethread_start_api.py
  26. 3 1
      misago/threads/tests/test_sync_unread_private_threads.py
  27. 61 40
      misago/threads/tests/test_thread_patch_api.py
  28. 6 2
      misago/threads/tests/test_thread_pollcreate_api.py
  29. 3 1
      misago/threads/tests/test_thread_pollvotes_api.py
  30. 4 1
      misago/threads/tests/test_thread_postmerge_api.py
  31. 6 2
      misago/threads/tests/test_thread_postpatch_api.py
  32. 2 1
      misago/threads/tests/test_thread_postsplit_api.py
  33. 18 5
      misago/threads/tests/test_threads_editor_api.py
  34. 2 1
      misago/threads/tests/test_threads_merge_api.py
  35. 3 1
      misago/threads/tests/test_threadview.py
  36. 4 0
      misago/threads/validators.py
  37. 2 1
      misago/threads/views/admin/attachmenttypes.py
  38. 13 13
      misago/users/forms/admin.py
  39. 2 2
      misago/users/forms/auth.py
  40. 2 1
      misago/users/management/commands/prepareuserdatadownloads.py
  41. 5 5
      misago/users/profilefields/default.py
  42. 5 7
      misago/users/serializers/moderation.py
  43. 2 2
      misago/users/serializers/options.py
  44. 2 1
      misago/users/social/backendsnames.py
  45. 8 4
      misago/users/social/pipeline.py
  46. 3 1
      misago/users/tests/test_auth_api.py
  47. 4 1
      misago/users/tests/test_bio_profilefield.py
  48. 13 4
      misago/users/tests/test_datadownloads.py
  49. 3 1
      misago/users/tests/test_forgottenpassword_views.py
  50. 1 0
      misago/users/tests/test_profilefields.py
  51. 4 4
      misago/users/tests/test_social_pipeline.py
  52. 3 2
      misago/users/tests/test_twitter_profilefield.py
  53. 4 1
      misago/users/tests/test_user_create_api.py
  54. 3 1
      misago/users/tests/test_user_requestdatadownload_api.py
  55. 3 1
      misago/users/tests/test_useradmin_views.py
  56. 16 5
      misago/users/tests/test_users_api.py
  57. 2 1
      misago/users/views/forgottenpassword.py

+ 8 - 13
misago/categories/forms.py

@@ -55,7 +55,8 @@ class CategoryFormBase(forms.ModelForm):
         label=_("CSS class"),
         required=False,
         help_text=_(
-            "Optional CSS class used to customize this category appearance from templates."
+            "Optional CSS class used to customize this "
+            "category's appearance from templates."
         ),
     )
     is_closed = YesNoSwitch(
@@ -65,13 +66,6 @@ class CategoryFormBase(forms.ModelForm):
             "Only members with valid permissions can post in closed categories."
         ),
     )
-    css_class = forms.CharField(
-        label=_("CSS class"),
-        required=False,
-        help_text=_(
-            "Optional CSS class used to customize this category appearance from templates."
-        ),
-    )
     require_threads_approval = YesNoSwitch(
         label=_("Threads"),
         required=False,
@@ -90,23 +84,24 @@ class CategoryFormBase(forms.ModelForm):
         label=_("Edits"),
         required=False,
         help_text=_(
-            "Will make all edited replies return to unapproved state for moderator to review."
+            "Will make all edited replies return to unapproved state "
+            "for moderator to review."
         ),
     )
     prune_started_after = forms.IntegerField(
         label=_("Thread age"),
         min_value=0,
         help_text=_(
-            "Prune thread if number of days since its creation is greater than specified. "
-            "Enter 0 to disable this pruning criteria."
+            "Prune thread if number of days since its creation is greater than "
+            "specified. Enter 0 to disable this pruning criteria."
         ),
     )
     prune_replied_after = forms.IntegerField(
         label=_("Last reply"),
         min_value=0,
         help_text=_(
-            "Prune thread if number of days since last reply is greater than specified. "
-            "Enter 0 to disable this pruning criteria."
+            "Prune thread if number of days since last reply is greater than "
+            "specified. Enter 0 to disable this pruning criteria."
         ),
     )
 

+ 0 - 4
misago/categories/views/permsadmin.py

@@ -87,8 +87,6 @@ class DeleteCategoryRole(CategoryRoleAdmin, generic.ButtonView):
 
 
 class CategoryPermissions(CategoryAdmin, generic.ModelFormView):
-    """category roles view for assinging roles to category, add link to it in categories list"""
-
     templates_dir = "misago/admin/categoryroles"
     template = "categoryroles.html"
 
@@ -148,8 +146,6 @@ CategoriesList.add_item_action(
 
 
 class RoleCategoriesACL(RoleAdmin, generic.ModelFormView):
-    """role categories view for assinging categories to role, add link to it in user roles list"""
-
     templates_dir = "misago/admin/categoryroles"
     template = "rolecategories.html"
 

+ 4 - 4
misago/legal/forms.py

@@ -16,10 +16,10 @@ class AgreementForm(forms.ModelForm):
     is_active = forms.BooleanField(
         label=_("Set as active for its type"),
         help_text=_(
-            "If other agreement is already active for this type, it will be unset and replaced "
-            "with this one. "
-            "Misago will ask users who didn't accept this agreement to do so before allowing them "
-            "to continue using the site's features."
+            "If other agreement is already active for this type, it will be unset "
+            "and replaced with this one. "
+            "Misago will ask users who didn't accept this agreement to do so "
+            "before allowing them to continue using the site's features."
         ),
         required=False,
     )

+ 3 - 1
misago/markup/tests/test_api.py

@@ -81,7 +81,9 @@ class ParseMarkupApiTests(AuthenticatedUserTestCase):
         self.assertEqual(
             response.json(),
             {
-                "detail": "Posted message should be at least 5 characters long (it has 3)."
+                "detail": (
+                    "Posted message should be at least 5 characters long (it has 3)."
+                )
             },
         )
 

+ 8 - 6
misago/markup/tests/test_mentions.py

@@ -59,9 +59,10 @@ class MentionsTests(AuthenticatedUserTestCase):
             self.user.username
         )
 
-        after = '<p>Hello <a href="{0}">@{1}</a> and <a href="{0}">@{1}</a>, how is it going?</p>'.format(
-            self.user.get_absolute_url(), self.user.username
-        )
+        after = (
+            # pylint: disable=line-too-long
+            '<p>Hello <a href="{0}">@{1}</a> and <a href="{0}">@{1}</a>, how is it going?</p>'
+        ).format(self.user.get_absolute_url(), self.user.username)
 
         result = {"parsed_text": before, "mentions": []}
 
@@ -75,9 +76,10 @@ class MentionsTests(AuthenticatedUserTestCase):
             self.user.username
         )
 
-        after = '<p>Hello <a href="{0}">@{1}</a></p><p><a href="{0}">@{1}</a>, how is it going?</p>'.format(
-            self.user.get_absolute_url(), self.user.username
-        )
+        after = (
+            # pylint: disable=line-too-long
+            '<p>Hello <a href="{0}">@{1}</a></p><p><a href="{0}">@{1}</a>, how is it going?</p>'
+        ).format(self.user.get_absolute_url(), self.user.username)
 
         result = {"parsed_text": before, "mentions": []}
 

+ 4 - 1
misago/search/tests/test_searchproviders.py

@@ -53,7 +53,10 @@ class SearchProvidersTests(TestCase):
         self.assertEqual(searchproviders.get_providers("REQUEST")[0].request, "REQUEST")
 
     def test_get_allowed_providers(self):
-        """get_allowed_providers returns only providers that didn't raise in allow_search"""
+        """
+        allowed providers getter returns only providers that didn't raise an exception 
+        in allow_search
+        """
         searchproviders = SearchProviders([])
 
         searchproviders._initialized = True

+ 2 - 1
misago/threads/api/attachments.py

@@ -101,7 +101,8 @@ def validate_filesize(upload, filetype, hard_limit):
 
     if filetype.size_limit and upload.size > filetype.size_limit * 1024:
         message = _(
-            "You can't upload files of this type larger than %(limit)s (your file has %(upload)s)."
+            "You can't upload files of this type larger "
+            "than %(limit)s (your file has %(upload)s)."
         )
         raise ValidationError(
             message

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

@@ -118,7 +118,8 @@ class PostingEndpoint:
                 obj.pre_save(self._serializers.get(middleware))
         except PostingInterrupt as e:
             raise ValueError(
-                "Posting process can only be interrupted from within interrupt_posting method"
+                "Posting process can only be interrupted "
+                "from within interrupt_posting method"
             )
 
         try:
@@ -134,7 +135,8 @@ class PostingEndpoint:
                 obj.post_save(self._serializers.get(middleware))
         except PostingInterrupt as e:
             raise ValueError(
-                "Posting process can only be interrupted from within interrupt_posting method"
+                "Posting process can only be interrupted "
+                "from within interrupt_posting method"
             )
 
 

+ 3 - 1
misago/threads/api/postingendpoint/attachments.py

@@ -59,7 +59,8 @@ class AttachmentsSerializer(serializers.Serializer):
                     self.removed_attachments.append(attachment)
                 else:
                     message = _(
-                        'You don\'t have permission to remove "%(attachment)s" attachment.'
+                        "You don't have permission to remove "
+                        '"%(attachment)s" attachment.'
                     )
                     raise serializers.ValidationError(
                         message % {"attachment": attachment.filename}
@@ -123,6 +124,7 @@ class AttachmentsSerializer(serializers.Serializer):
 def validate_attachments_count(data):
     total_attachments = len(data)
     if total_attachments > settings.MISAGO_POST_ATTACHMENTS_LIMIT:
+        # pylint: disable=line-too-long
         message = ngettext(
             "You can't attach more than %(limit_value)s file to single post (added %(show_value)s).",
             "You can't attach more than %(limit_value)s flies to single post (added %(show_value)s).",

+ 5 - 2
misago/threads/api/postingendpoint/category.py

@@ -13,7 +13,9 @@ from ...threadtypes import trees_map
 
 
 class CategoryMiddleware(PostingMiddleware):
-    """middleware that validates category id and sets category on thread and post instances"""
+    """
+    middleware that validates category id and sets category on thread and post instances
+    """
 
     def use_this_middleware(self):
         if self.mode == PostingEndpoint.START:
@@ -66,7 +68,8 @@ class CategorySerializer(serializers.Serializer):
         except Category.DoesNotExist:
             raise serializers.ValidationError(
                 _(
-                    "Selected category doesn't exist or you don't have permission to browse it."
+                    "Selected category doesn't exist or "
+                    "you don't have permission to browse it."
                 )
             )
         except PermissionDenied as e:

+ 3 - 1
misago/threads/api/postingendpoint/participants.py

@@ -49,7 +49,8 @@ class ParticipantsSerializer(serializers.Serializer):
             if clean_name == self.context["user"].slug:
                 raise serializers.ValidationError(
                     _(
-                        "You can't include yourself on the list of users to invite to new thread."
+                        "You can't include yourself on the "
+                        "list of users to invite to new thread."
                     )
                 )
 
@@ -61,6 +62,7 @@ class ParticipantsSerializer(serializers.Serializer):
 
         max_participants = self.context["user_acl"]["max_private_thread_participants"]
         if max_participants and len(clean_usernames) > max_participants:
+            # pylint: disable=line-too-long
             message = ngettext(
                 "You can't add more than %(users)s user to private thread (you've added %(added)s).",
                 "You can't add more than %(users)s users to private thread (you've added %(added)s).",

+ 4 - 2
misago/threads/api/threadendpoints/editor.py

@@ -47,7 +47,8 @@ def thread_start_editor(request):
             }
         )
 
-    # list only categories that allow new threads, or contains subcategory that allows one
+    # list only categories that allow new threads,
+    # or contains subcategory that allows one
     cleaned_categories = []
     for category in reversed(categories):
         if category["id"] in available:
@@ -56,7 +57,8 @@ def thread_start_editor(request):
     if not cleaned_categories:
         raise PermissionDenied(
             _(
-                "No categories that allow new threads are available to you at the moment."
+                "No categories that allow new threads "
+                "are available to you at the moment."
             )
         )
 

+ 2 - 1
misago/threads/api/threadendpoints/patch.py

@@ -272,7 +272,8 @@ def patch_unmark_best_answer(request, thread, value):
     if not post.is_best_answer:
         raise PermissionDenied(
             _(
-                "This post can't be unmarked because it's not currently marked as best answer."
+                "This post can't be unmarked because "
+                "it's not currently marked as best answer."
             )
         )
 

+ 12 - 10
misago/threads/forms.py

@@ -61,10 +61,12 @@ class AttachmentTypeForm(forms.ModelForm):
         }
         help_texts = {
             "extensions": _(
-                "List of comma separated file extensions associated with this attachment type."
+                "List of comma separated file extensions associated with this "
+                "attachment type."
             ),
             "mimetypes": _(
-                "Optional list of comma separated mime types associated with this attachment type."
+                "Optional list of comma separated mime types associated with this "
+                "attachment type."
             ),
             "size_limit": _(
                 "Maximum allowed uploaded file size for this type, in kb. "
@@ -72,16 +74,16 @@ class AttachmentTypeForm(forms.ModelForm):
             ),
             "status": _("Controls this attachment type availability on your site."),
             "limit_uploads_to": _(
-                "If you wish to limit option to upload files of this type to users with specific "
-                "roles, select them on this list. Otherwhise don't select any roles to allow all "
-                "users with permission to upload attachments to be able to upload attachments of "
-                "this type."
+                "If you wish to limit option to upload files of this type to users "
+                "with specific roles, select them on this list. Otherwhise don't "
+                "select any roles to allow all users with permission to upload "
+                "attachments to be able to upload attachments of this type."
             ),
             "limit_downloads_to": _(
-                "If you wish to limit option to download files of this type to users with "
-                "specific roles, select them on this list. Otherwhise don't select any roles to "
-                "allow all users with permission to download attachments to be able to download "
-                "attachments of this type."
+                "If you wish to limit option to download files of this type to users "
+                "with specific roles, select them on this list. Otherwhise don't "
+                "select any roles to allow all users with permission to download "
+                "attachments to be able to download attachments of this type."
             ),
         }
         widgets = {

+ 2 - 2
misago/threads/mergeconflict.py

@@ -82,8 +82,8 @@ class PollMergeHandler(MergeConflictHandler):
 
 class MergeConflict:
     """
-    Utility class single point of entry for detecting merge conflicts on different properties
-    and validating user resolutions.
+    Utility class single point of entry for detecting merge conflicts on different
+    properties and validating user resolutions.
     """
 
     HANDLERS = (BestAnswerMergeHandler, PollMergeHandler)

+ 1 - 1
misago/threads/paginator.py

@@ -2,7 +2,7 @@ from django.core.paginator import Paginator
 
 
 class PostsPaginator(Paginator):
-    """paginator that returns that makes last item on page repeat as first item on next page."""
+    """paginator that makes last item on page repeat as first item on next page."""
 
     def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True):
         per_page = int(per_page) - 1

+ 46 - 53
misago/threads/permissions/bestanswers.py

@@ -44,7 +44,8 @@ class CategoryPermissionsForm(forms.Form):
             "Time limit for changing marked best answer in owned thread, in minutes"
         ),
         help_text=_(
-            "Enter 0 to don't limit time for changing marked best answer in owned thread."
+            "Enter 0 to don't limit time for changing marked best answer in "
+            "owned thread."
         ),
         initial=0,
         min_value=0,
@@ -137,7 +138,8 @@ def allow_mark_best_answer(user_acl, target):
     if not category_acl.get("can_mark_best_answers"):
         raise PermissionDenied(
             _(
-                'You don\'t have permission to mark best answers in the "%(category)s" category.'
+                "You don't have permission to mark best answers in the "
+                '"%(category)s" category.'
             )
             % {"category": target.category}
         )
@@ -148,8 +150,8 @@ def allow_mark_best_answer(user_acl, target):
     ):
         raise PermissionDenied(
             _(
-                "You don't have permission to mark best answer in this thread because you didn't "
-                "start it."
+                "You don't have permission to mark best answer in this thread "
+                "because you didn't start it."
             )
         )
 
@@ -157,16 +159,16 @@ def allow_mark_best_answer(user_acl, target):
         if target.category.is_closed:
             raise PermissionDenied(
                 _(
-                    "You don't have permission to mark best answer in this thread because its "
-                    'category "%(category)s" is closed.'
+                    "You don't have permission to mark best answer in this thread "
+                    'because its category "%(category)s" is closed.'
                 )
                 % {"category": target.category}
             )
         if target.is_closed:
             raise PermissionDenied(
                 _(
-                    "You can't mark best answer in this thread because it's closed and you don't "
-                    "have permission to open it."
+                    "You can't mark best answer in this thread because it's closed "
+                    "and you don't have permission to open it."
                 )
             )
 
@@ -183,8 +185,8 @@ def allow_change_best_answer(user_acl, target):
     if not category_acl.get("can_change_marked_answers"):
         raise PermissionDenied(
             _(
-                "You don't have permission to change this thread's marked answer because it's "
-                'in the "%(category)s" category.'
+                "You don't have permission to change this thread's marked answer "
+                'because it\'s in the "%(category)s" category.'
             )
             % {"category": target.category}
         )
@@ -193,31 +195,26 @@ def allow_change_best_answer(user_acl, target):
         if user_acl["user_id"] != target.starter_id:
             raise PermissionDenied(
                 _(
-                    "You don't have permission to change this thread's marked answer because you "
-                    "are not a thread starter."
+                    "You don't have permission to change this thread's marked answer "
+                    "because you are not a thread starter."
                 )
             )
         if not has_time_to_change_answer(user_acl, target):
+            # pylint: disable=line-too-long
+            message = ngettext(
+                "You don't have permission to change best answer that was marked for more than %(minutes)s minute.",
+                "You don't have permission to change best answer that was marked for more than %(minutes)s minutes.",
+                category_acl["best_answer_change_time"],
+            )
             raise PermissionDenied(
-                ngettext(
-                    (
-                        "You don't have permission to change best answer that was marked for more "
-                        "than %(minutes)s minute."
-                    ),
-                    (
-                        "You don't have permission to change best answer that was marked for more "
-                        "than %(minutes)s minutes."
-                    ),
-                    category_acl["best_answer_change_time"],
-                )
-                % {"minutes": category_acl["best_answer_change_time"]}
+                message % {"minutes": category_acl["best_answer_change_time"]}
             )
 
     if target.best_answer_is_protected and not category_acl["can_protect_posts"]:
         raise PermissionDenied(
             _(
-                "You don't have permission to change this thread's best answer because "
-                "a moderator has protected it."
+                "You don't have permission to change this thread's best answer "
+                "because a moderator has protected it."
             )
         )
 
@@ -237,8 +234,8 @@ def allow_unmark_best_answer(user_acl, target):
     if not category_acl.get("can_change_marked_answers"):
         raise PermissionDenied(
             _(
-                'You don\'t have permission to unmark threads answers in the "%(category)s" '
-                "category."
+                "You don't have permission to unmark threads answers in "
+                'the "%(category)s" category.'
             )
             % {"category": target.category}
         )
@@ -247,48 +244,43 @@ def allow_unmark_best_answer(user_acl, target):
         if user_acl["user_id"] != target.starter_id:
             raise PermissionDenied(
                 _(
-                    "You don't have permission to unmark this best answer because you are not a "
-                    "thread starter."
+                    "You don't have permission to unmark this best answer "
+                    "because you are not a thread starter."
                 )
             )
         if not has_time_to_change_answer(user_acl, target):
+            # pylint: disable=line-too-long
+            message = ngettext(
+                "You don't have permission to unmark best answer that was marked for more than %(minutes)s minute.",
+                "You don't have permission to unmark best answer that was marked for more than %(minutes)s minutes.",
+                category_acl["best_answer_change_time"],
+            )
             raise PermissionDenied(
-                ngettext(
-                    (
-                        "You don't have permission to unmark best answer that was marked for more "
-                        "than %(minutes)s minute."
-                    ),
-                    (
-                        "You don't have permission to unmark best answer that was marked for more "
-                        "than %(minutes)s minutes."
-                    ),
-                    category_acl["best_answer_change_time"],
-                )
-                % {"minutes": category_acl["best_answer_change_time"]}
+                message % {"minutes": category_acl["best_answer_change_time"]}
             )
 
     if not category_acl["can_close_threads"]:
         if target.category.is_closed:
             raise PermissionDenied(
                 _(
-                    "You don't have permission to unmark this best answer because its category "
-                    '"%(category)s" is closed.'
+                    "You don't have permission to unmark this best answer "
+                    'because its category "%(category)s" is closed.'
                 )
                 % {"category": target.category}
             )
         if target.is_closed:
             raise PermissionDenied(
                 _(
-                    "You can't unmark this thread's best answer because it's closed and you "
-                    "don't have permission to open it."
+                    "You can't unmark this thread's best answer "
+                    "because it's closed and you don't have permission to open it."
                 )
             )
 
     if target.best_answer_is_protected and not category_acl["can_protect_posts"]:
         raise PermissionDenied(
             _(
-                "You don't have permission to unmark this thread's best answer because a "
-                "moderator has protected it."
+                "You don't have permission to unmark this thread's best answer "
+                "because a moderator has protected it."
             )
         )
 
@@ -308,7 +300,8 @@ def allow_mark_as_best_answer(user_acl, target):
     if not category_acl.get("can_mark_best_answers"):
         raise PermissionDenied(
             _(
-                'You don\'t have permission to mark best answers in the "%(category)s" category.'
+                "You don't have permission to mark best answers "
+                'in the "%(category)s" category.'
             )
             % {"category": target.category}
         )
@@ -319,8 +312,8 @@ def allow_mark_as_best_answer(user_acl, target):
     ):
         raise PermissionDenied(
             _(
-                "You don't have permission to mark best answer in this thread because you "
-                "didn't start it."
+                "You don't have permission to mark best answer in this thread "
+                "because you didn't start it."
             )
         )
 
@@ -338,8 +331,8 @@ def allow_mark_as_best_answer(user_acl, target):
     if target.is_protected and not category_acl["can_protect_posts"]:
         raise PermissionDenied(
             _(
-                "You don't have permission to mark this post as best answer because a moderator "
-                "has protected it."
+                "You don't have permission to mark this post as best answer "
+                "because a moderator has protected it."
             )
         )
 

+ 4 - 2
misago/threads/serializers/moderation.py

@@ -163,7 +163,8 @@ class MergePostsSerializer(serializers.Serializer):
             if posts[0].is_first_post and post.is_best_answer:
                 raise serializers.ValidationError(
                     _(
-                        "Post marked as best answer can't be merged with thread's first post."
+                        "Post marked as best answer can't be merged with "
+                        "thread's first post."
                     )
                 )
 
@@ -311,7 +312,8 @@ class NewThreadSerializer(serializers.Serializer):
             if weight == 2:
                 raise ValidationError(
                     _(
-                        "You don't have permission to pin threads globally in this category."
+                        "You don't have permission to pin threads globally "
+                        "in this category."
                     )
                 )
             else:

+ 3 - 1
misago/threads/serializers/poll.py

@@ -117,6 +117,7 @@ class EditPollSerializer(serializers.ModelSerializer):
             )
 
         if total_choices > MAX_POLL_OPTIONS:
+            # pylint: disable=line-too-long
             message = ngettext(
                 "You can't add more than %(limit_value)s option to a single poll (added %(show_value)s).",
                 "You can't add more than %(limit_value)s options to a single poll (added %(show_value)s).",
@@ -130,7 +131,8 @@ class EditPollSerializer(serializers.ModelSerializer):
         if data["allowed_choices"] > len(data["choices"]):
             raise serializers.ValidationError(
                 _(
-                    "Number of allowed choices can't be greater than number of all choices."
+                    "Number of allowed choices can't be "
+                    "greater than number of all choices."
                 )
             )
         return data

+ 6 - 8
misago/threads/templatetags/misago_poststags.py

@@ -25,16 +25,14 @@ def likes_label(post):
     if not hidden_likes:
         return _("%(users)s like this.") % {"users": usernames_string}
 
+    label = ngettext(
+        "%(users)s and %(likes)s other user like this.",
+        "%(users)s and %(likes)s other users like this.",
+        hidden_likes,
+    )
     formats = {"users": usernames_string, "likes": hidden_likes}
 
-    return (
-        ngettext(
-            "%(users)s and %(likes)s other user like this.",
-            "%(users)s and %(likes)s other users like this.",
-            hidden_likes,
-        )
-        % formats
-    )
+    return label % formats
 
 
 def humanize_usernames_list(usernames):

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

@@ -158,7 +158,8 @@ class AttachmentsApiTestCase(AuthenticatedUserTestCase):
                 response.json(),
                 {
                     "detail": (
-                        "You can't upload files larger than 100.0\xa0KB (your file has 253.9\xa0KB)."
+                        "You can't upload files larger than 100.0\xa0KB "
+                        "(your file has 253.9\xa0KB)."
                     )
                 },
             )

+ 9 - 3
misago/threads/tests/test_attachments_middleware.py

@@ -107,7 +107,9 @@ class AttachmentsMiddlewareTests(AuthenticatedUserTestCase):
 
     @patch_attachments_acl()
     def test_get_initial_attachments(self):
-        """get_initial_attachments returns list of attachments already existing on post"""
+        """
+        get_initial_attachments returns list of attachments already existing on post
+        """
         user_acl = useracl.get_user_acl(self.user, cache_versions)
         middleware = AttachmentsMiddleware(
             request=Mock(data={}),
@@ -132,7 +134,9 @@ class AttachmentsMiddlewareTests(AuthenticatedUserTestCase):
 
     @patch_attachments_acl()
     def test_get_new_attachments(self):
-        """get_initial_attachments returns list of attachments already existing on post"""
+        """
+        get_initial_attachments returns list of attachments already existing on post
+        """
         user_acl = useracl.get_user_acl(self.user, cache_versions)
         middleware = AttachmentsMiddleware(
             request=Mock(data={}),
@@ -160,7 +164,9 @@ class AttachmentsMiddlewareTests(AuthenticatedUserTestCase):
 
     @patch_attachments_acl({"can_delete_other_users_attachments": False})
     def test_cant_delete_attachment(self):
-        """middleware validates if we have permission to delete other users attachments"""
+        """
+        middleware validates if we have permission to delete other users attachments
+        """
         attachment = self.mock_attachment(user=False, post=self.post)
         self.assertIsNone(attachment.uploader)
 

+ 7 - 2
misago/threads/tests/test_mergeconflict.py

@@ -75,7 +75,9 @@ class MergeConflictTests(TestCase):
         self.assertFalse(merge_conflict.is_merge_conflict())
 
     def test_three_best_answers_one_poll_two_plain_conflict(self):
-        """three threads with best answer, thread with poll and two plain threads conflict"""
+        """
+        three threads with best answer, thread with poll and two plain threads conflict
+        """
         best_answers = [self.create_best_answer_thread() for i in range(3)]
         polls = [self.create_poll_thread()]
         threads = (
@@ -133,7 +135,10 @@ class MergeConflictTests(TestCase):
         )
 
     def test_one_best_answer_three_polls_two_plain_conflict(self):
-        """one thread with best answer, three threads with poll and two plain threads conflict"""
+        """
+        one thread with best answer, three threads with poll
+        and two plain threads conflict
+        """
         best_answers = [self.create_best_answer_thread()]
         polls = [self.create_poll_thread() for i in range(3)]
         threads = (

+ 4 - 1
misago/threads/tests/test_privatethread_patch_api.py

@@ -168,7 +168,10 @@ class PrivateThreadAddParticipantApiTests(PrivateThreadPatchApiTestCase):
         )
 
     def test_add_user(self):
-        """adding user to thread add user to thread as participant, sets event and emails him"""
+        """
+        adding user to thread add user to thread as participant,
+        sets event and emails him
+        """
         ThreadParticipant.objects.set_owner(self.thread, self.user)
 
         self.patch(

+ 4 - 2
misago/threads/tests/test_privatethread_start_api.py

@@ -112,7 +112,8 @@ class StartPrivateThreadTests(AuthenticatedUserTestCase):
             response.json(),
             {
                 "to": [
-                    "You can't include yourself on the list of users to invite to new thread."
+                    "You can't include yourself on the list "
+                    "of users to invite to new thread."
                 ]
             },
         )
@@ -149,7 +150,8 @@ class StartPrivateThreadTests(AuthenticatedUserTestCase):
             response.json(),
             {
                 "to": [
-                    "You can't add more than 3 users to private thread (you've added 50)."
+                    "You can't add more than 3 users to private thread "
+                    "(you've added 50)."
                 ]
             },
         )

+ 3 - 1
misago/threads/tests/test_sync_unread_private_threads.py

@@ -29,7 +29,9 @@ class SyncUnreadPrivateThreadsTestCase(PrivateThreadsTestCase):
         self.assertEqual(self.user.unread_private_threads, 1)
 
     def test_middleware_counts_unread_thread(self):
-        """middleware counts thread with unread reply, post read flags user for recount"""
+        """
+        middleware counts thread with unread reply, post read flags user for recount
+        """
         self.user.sync_unread_private_threads = True
         self.user.save()
 

+ 61 - 40
misago/threads/tests/test_thread_patch_api.py

@@ -30,7 +30,9 @@ class ThreadAddAclApiTests(ThreadPatchApiTestCase):
         self.assertTrue(response_json["acl"])
 
     def test_add_acl_false(self):
-        """if value is false, api won't add acl to the response, but will set empty key"""
+        """
+        if value is false, api won't add acl to the response, but will set empty key
+        """
         response = self.patch(
             self.api_link, [{"op": "add", "path": "acl", "value": False}]
         )
@@ -1048,7 +1050,8 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    'You don\'t have permission to mark best answers in the "First category" category.'
+                    "You don't have permission to mark best answers "
+                    'in the "First category" category.'
                 ],
             },
         )
@@ -1071,8 +1074,8 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to mark best answer in this thread because you didn't "
-                    "start it."
+                    "You don't have permission to mark best answer in this thread "
+                    "because you didn't start it."
                 ],
             },
         )
@@ -1108,8 +1111,8 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to mark best answer in this thread because its "
-                    'category "First category" is closed.'
+                    "You don't have permission to mark best answer in this thread "
+                    'because its category "First category" is closed.'
                 ],
             },
         )
@@ -1149,8 +1152,8 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You can't mark best answer in this thread because it's closed and you don't have "
-                    "permission to open it."
+                    "You can't mark best answer in this thread because it's closed and "
+                    "you don't have permission to open it."
                 ],
             },
         )
@@ -1356,8 +1359,8 @@ class ThreadMarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to mark this post as best answer because a moderator "
-                    "has protected it."
+                    "You don't have permission to mark this post as best answer "
+                    "because a moderator has protected it."
                 ],
             },
         )
@@ -1441,7 +1444,9 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
 
     @patch_category_acl({"can_mark_best_answers": 0, "can_change_marked_answers": 2})
     def test_change_best_answer_no_permission_to_mark(self):
-        """api validates permission to mark best answers before allowing answer change"""
+        """
+        api validates permission to mark best answers before allowing answer change
+        """
         best_answer = test.reply_thread(self.thread)
 
         response = self.patch(
@@ -1454,7 +1459,8 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    'You don\'t have permission to mark best answers in the "First category" category.'
+                    "You don't have permission to mark best answers in the "
+                    '"First category" category.'
                 ],
             },
         )
@@ -1477,8 +1483,8 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to change this thread's marked answer because it's "
-                    'in the "First category" category.'
+                    "You don't have permission to change this thread's marked answer "
+                    'because it\'s in the "First category" category.'
                 ],
             },
         )
@@ -1501,8 +1507,8 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to change this thread's marked answer because you are "
-                    "not a thread starter."
+                    "You don't have permission to change this thread's marked answer "
+                    "because you are not a thread starter."
                 ],
             },
         )
@@ -1528,7 +1534,9 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
         }
     )
     def test_change_best_answer_timelimit_out_of_time(self):
-        """api validates permission for starter to change best answers within timelimit"""
+        """
+        api validates permission for starter to change best answers within timelimit
+        """
         best_answer = test.reply_thread(self.thread)
 
         self.thread.best_answer_marked_on = timezone.now() - timedelta(minutes=6)
@@ -1545,8 +1553,8 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to change best answer that was marked for more than "
-                    "5 minutes."
+                    "You don't have permission to change best answer that was marked "
+                    "for more than 5 minutes."
                 ],
             },
         )
@@ -1562,7 +1570,9 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
         }
     )
     def test_change_best_answer_timelimit(self):
-        """api validates permission for starter to change best answers within timelimit"""
+        """
+        api validates permission for starter to change best answers within timelimit
+        """
         best_answer = test.reply_thread(self.thread)
 
         self.thread.best_answer_marked_on = timezone.now() - timedelta(minutes=1)
@@ -1599,8 +1609,8 @@ class ThreadChangeBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to change this thread's best answer because a "
-                    "moderator has protected it."
+                    "You don't have permission to change this thread's best answer "
+                    "because a moderator has protected it."
                 ],
             },
         )
@@ -1727,7 +1737,8 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "This post can't be unmarked because it's not currently marked as best answer."
+                    "This post can't be unmarked because it's not currently marked "
+                    "as best answer."
                 ],
             },
         )
@@ -1748,8 +1759,8 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    'You don\'t have permission to unmark threads answers in the "First category" '
-                    "category."
+                    "You don't have permission to unmark threads answers in "
+                    'the "First category" category.'
                 ],
             },
         )
@@ -1770,8 +1781,8 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to unmark this best answer because you are not a "
-                    "thread starter."
+                    "You don't have permission to unmark this best answer because "
+                    "you are not a thread starter."
                 ],
             },
         )
@@ -1797,7 +1808,9 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
         }
     )
     def test_unmark_best_answer_timelimit(self):
-        """api validates if starter has permission to unmark best answer within time limit"""
+        """
+        api validates if starter has permission to unmark best answer within time limit
+        """
         self.thread.best_answer_marked_on = timezone.now() - timedelta(minutes=6)
         self.thread.starter = self.user
         self.thread.save()
@@ -1812,8 +1825,8 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to unmark best answer that was marked for more than "
-                    "5 minutes."
+                    "You don't have permission to unmark best answer that was marked "
+                    "for more than 5 minutes."
                 ],
             },
         )
@@ -1839,7 +1852,9 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
         }
     )
     def test_unmark_best_answer_closed_category_no_permission(self):
-        """api validates if user has permission to unmark best answer in closed category"""
+        """
+        api validates if user has permission to unmark best answer in closed category
+        """
         self.category.is_closed = True
         self.category.save()
 
@@ -1853,8 +1868,8 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to unmark this best answer because its category "
-                    '"First category" is closed.'
+                    "You don't have permission to unmark this best answer because "
+                    'its category "First category" is closed.'
                 ],
             },
         )
@@ -1870,7 +1885,9 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
         }
     )
     def test_unmark_best_answer_closed_category(self):
-        """api validates if user has permission to unmark best answer in closed category"""
+        """
+        api validates if user has permission to unmark best answer in closed category
+        """
         self.category.is_closed = True
         self.category.save()
 
@@ -1888,7 +1905,9 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
         }
     )
     def test_unmark_best_answer_closed_thread_no_permission(self):
-        """api validates if user has permission to unmark best answer in closed thread"""
+        """
+        api validates if user has permission to unmark best answer in closed thread
+        """
         self.thread.is_closed = True
         self.thread.save()
 
@@ -1902,8 +1921,8 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You can't unmark this thread's best answer because it's closed and you don't "
-                    "have permission to open it."
+                    "You can't unmark this thread's best answer because it's closed "
+                    "and you don't have permission to open it."
                 ],
             },
         )
@@ -1919,7 +1938,9 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
         }
     )
     def test_unmark_best_answer_closed_thread(self):
-        """api validates if user has permission to unmark best answer in closed thread"""
+        """
+        api validates if user has permission to unmark best answer in closed thread
+        """
         self.thread.is_closed = True
         self.thread.save()
 
@@ -1951,8 +1972,8 @@ class ThreadUnmarkBestAnswerApiTests(ThreadPatchApiTestCase):
             {
                 "id": self.thread.id,
                 "detail": [
-                    "You don't have permission to unmark this thread's best answer because a "
-                    "moderator has protected it."
+                    "You don't have permission to unmark this thread's best answer "
+                    "because a moderator has protected it."
                 ],
             },
         )

+ 6 - 2
misago/threads/tests/test_thread_pollcreate_api.py

@@ -90,7 +90,9 @@ class ThreadPollCreateTests(ThreadPollApiTestCase):
 
     @patch_user_acl({"can_start_polls": 1})
     def test_other_user_thread_no_permission(self):
-        """api validates that user has permission to start poll in other user's thread"""
+        """
+        api validates that user has permission to start poll in other user's thread
+        """
         self.thread.starter = None
         self.thread.save()
 
@@ -102,7 +104,9 @@ class ThreadPollCreateTests(ThreadPollApiTestCase):
 
     @patch_user_acl({"can_start_polls": 2})
     def test_other_user_thread(self):
-        """api validates that user has permission to start poll in other user's thread"""
+        """
+        api validates that user has permission to start poll in other user's thread
+        """
         self.thread.starter = None
         self.thread.save()
 

+ 3 - 1
misago/threads/tests/test_thread_pollvotes_api.py

@@ -243,7 +243,9 @@ class ThreadPostVotesTests(ThreadPollApiTestCase):
         )
 
     def test_revote(self):
-        """api validates if user is trying to change vote in poll that disallows revoting"""
+        """
+        api validates if user is trying to change vote in poll that disallows revoting
+        """
         response = self.post(self.api_link, data=["lorem", "ipsum"])
         self.assertEqual(response.status_code, 403)
         self.assertEqual(

+ 4 - 1
misago/threads/tests/test_thread_postmerge_api.py

@@ -414,7 +414,10 @@ class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
         self.assertEqual(
             response.json(),
             {
-                "detail": "Post marked as best answer can't be merged with thread's first post."
+                "detail": (
+                    "Post marked as best answer can't be "
+                    "merged with thread's first post."
+                )
             },
         )
 

+ 6 - 2
misago/threads/tests/test_thread_postpatch_api.py

@@ -42,7 +42,9 @@ class PostAddAclApiTests(ThreadPostPatchApiTestCase):
         self.assertTrue(response_json["acl"])
 
     def test_add_acl_false(self):
-        """if value is false, api won't add acl to the response, but will set empty key"""
+        """
+        if value is false, api won't add acl to the response, but will set empty key
+        """
         response = self.patch(
             self.api_link, [{"op": "add", "path": "acl", "value": False}]
         )
@@ -879,7 +881,9 @@ class EventAddAclApiTests(ThreadEventPatchApiTestCase):
         self.assertTrue(response_json["acl"])
 
     def test_add_acl_false(self):
-        """if value is false, api won't add acl to the response, but will set empty key"""
+        """
+        if value is false, api won't add acl to the response, but will set empty key
+        """
         response = self.patch(
             self.api_link, [{"op": "add", "path": "acl", "value": False}]
         )

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

@@ -407,7 +407,8 @@ class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
             response_json,
             {
                 "weight": [
-                    "You don't have permission to pin threads globally in this category."
+                    "You don't have permission to pin threads "
+                    "globally in this category."
                 ]
             },
         )

+ 18 - 5
misago/threads/tests/test_threads_editor_api.py

@@ -49,7 +49,10 @@ class ThreadPostEditorApiTests(EditorApiTestCase):
         self.assertEqual(
             response.json(),
             {
-                "detail": "No categories that allow new threads are available to you at the moment."
+                "detail": (
+                    "No categories that allow new threads are available "
+                    "to you at the moment."
+                )
             },
         )
 
@@ -61,7 +64,10 @@ class ThreadPostEditorApiTests(EditorApiTestCase):
         self.assertEqual(
             response.json(),
             {
-                "detail": "No categories that allow new threads are available to you at the moment."
+                "detail": (
+                    "No categories that allow new threads are available "
+                    "to you at the moment."
+                )
             },
         )
 
@@ -76,7 +82,10 @@ class ThreadPostEditorApiTests(EditorApiTestCase):
         self.assertEqual(
             response.json(),
             {
-                "detail": "No categories that allow new threads are available to you at the moment."
+                "detail": (
+                    "No categories that allow new threads are available "
+                    "to you at the moment."
+                )
             },
         )
 
@@ -258,7 +267,9 @@ class ThreadReplyEditorApiTests(EditorApiTestCase):
             self.assertEqual(
                 response.json(),
                 {
-                    "detail": "This category is closed. You can't reply to threads in it."
+                    "detail": (
+                        "This category is closed. You can't reply to threads in it."
+                    )
                 },
             )
 
@@ -511,7 +522,9 @@ class EditReplyEditorApiTests(EditorApiTestCase):
 
     @patch_category_acl({"can_hide_threads": 1, "can_edit_posts": 2})
     def test_edit_first_post_hidden(self):
-        """endpoint returns valid configuration for editor of hidden thread's first post"""
+        """
+        endpoint returns valid configuration for editor of hidden thread's first post
+        """
         self.thread.is_hidden = True
         self.thread.save()
         self.thread.first_post.is_hidden = True

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

@@ -371,7 +371,8 @@ class ThreadsMergeApiTests(ThreadsApiTestCase):
             response.json(),
             {
                 "weight": [
-                    "You don't have permission to pin threads globally in this category."
+                    "You don't have permission to pin threads globally "
+                    "in this category."
                 ]
             },
         )

+ 3 - 1
misago/threads/tests/test_threadview.py

@@ -191,7 +191,9 @@ class ThreadPostsVisibilityTests(ThreadViewTestCase):
             self.assertContains(response, post.parsed)
 
     def test_unapproved_post_visibility(self):
-        """unapproved post renders for its author and users with perm to approve content"""
+        """
+        unapproved post renders for its author and users with perm to approve content
+        """
         post = test.reply_thread(self.thread, is_unapproved=True)
 
         # post is hdden because we aren't its author nor user with permission to approve

+ 4 - 0
misago/threads/validators.py

@@ -45,6 +45,7 @@ def validate_thread_title_length(settings, value):
         raise ValidationError(_("You have to enter an thread title."))
 
     if value_len < settings.thread_title_length_min:
+        # pylint: disable=line-too-long
         message = ngettext(
             "Thread title should be at least %(limit_value)s character long (it has %(show_value)s).",
             "Thread title should be at least %(limit_value)s characters long (it has %(show_value)s).",
@@ -56,6 +57,7 @@ def validate_thread_title_length(settings, value):
         )
 
     if value_len > settings.thread_title_length_max:
+        # pylint: disable=line-too-long
         message = ngettext(
             "Thread title cannot be longer than %(limit_value)s character (it has %(show_value)s).",
             "Thread title cannot be longer than %(limit_value)s characters (it has %(show_value)s).",
@@ -74,6 +76,7 @@ def validate_post_length(settings, value):
         raise ValidationError(_("You have to enter a message."))
 
     if value_len < settings.post_length_min:
+        # pylint: disable=line-too-long
         message = ngettext(
             "Posted message should be at least %(limit_value)s character long (it has %(show_value)s).",
             "Posted message should be at least %(limit_value)s characters long (it has %(show_value)s).",
@@ -84,6 +87,7 @@ def validate_post_length(settings, value):
         )
 
     if settings.post_length_max and value_len > settings.post_length_max:
+        # pylint: disable=line-too-long
         message = ngettext(
             "Posted message cannot be longer than %(limit_value)s character (it has %(show_value)s).",
             "Posted message cannot be longer than %(limit_value)s characters (it has %(show_value)s).",

+ 2 - 1
misago/threads/views/admin/attachmenttypes.py

@@ -44,7 +44,8 @@ class DeleteAttachmentType(AttachmentTypeAdmin, generic.ButtonView):
     def check_permissions(self, request, target):
         if target.attachment_set.exists():
             message = _(
-                'Attachment type "%(name)s" has associated attachments and can\'t be deleted.'
+                'Attachment type "%(name)s" has '
+                "associated attachments and can't be deleted."
             )
             return message % {"name": target.name}
 

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

@@ -215,14 +215,12 @@ class EditUserForm(UserBaseForm):
 
         length_limit = self.settings.signature_length_max
         if len(data) > length_limit:
-            raise forms.ValidationError(
-                ngettext(
-                    "Signature can't be longer than %(limit)s character.",
-                    "Signature can't be longer than %(limit)s characters.",
-                    length_limit,
-                )
-                % {"limit": length_limit}
+            message = ngettext(
+                "Signature can't be longer than %(limit)s character.",
+                "Signature can't be longer than %(limit)s characters.",
+                length_limit,
             )
+            raise forms.ValidationError(message % {"limit": length_limit})
 
         return data
 
@@ -504,9 +502,10 @@ class BanForm(forms.ModelForm):
     registration_only = YesNoSwitch(
         label=_("Restrict this ban to registrations"),
         help_text=_(
-            "Changing this to yes will make this ban check be only performed on registration "
-            "step. This is good if you want to block certain registrations like ones from "
-            "recently comprimised e-mail providers, without harming existing users."
+            "Changing this to yes will make this ban check be only performed on "
+            "registration step. This is good if you want to block certain "
+            "registrations like ones from recently comprimised e-mail providers, "
+            "without harming existing users."
         ),
     )
     banned_value = forms.CharField(
@@ -628,9 +627,10 @@ class RequestDataDownloadsForm(forms.Form):
         label=_("Usernames or emails"),
         help_text=_(
             "Enter every item in new line. Duplicates will be ignored. "
-            "This field is case insensitive. Depending on site configuration and amount of data "
-            "to archive it may take up to few days for requests to complete. E-mail "
-            "will notification will be sent to every user once their download is ready."
+            "This field is case insensitive. Depending on site configuration and "
+            "amount of data to archive it may take up to few days for requests to "
+            "complete. E-mail will notification will be sent to every user once their "
+            "download is ready."
         ),
         widget=forms.Textarea,
     )

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

@@ -18,8 +18,8 @@ class MisagoAuthMixin:
             "You have to activate your account before you will be able to sign in."
         ),
         "inactive_admin": _(
-            "Your account has to be activated by site administrator before you will be able "
-            "to sign in."
+            "Your account has to be activated by site administrator "
+            "before you will be able to sign in."
         ),
     }
 

+ 2 - 1
misago/users/management/commands/prepareuserdatadownloads.py

@@ -29,6 +29,7 @@ class Command(BaseCommand):
 
         cache_versions = get_cache_versions()
         dynamic_settings = DynamicSettings(cache_versions)
+        expires_in = settings.MISAGO_USER_DATA_DOWNLOADS_EXPIRE_IN_HOURS
 
         downloads_prepared = 0
         queryset = DataDownload.objects.select_related("user")
@@ -45,7 +46,7 @@ class Command(BaseCommand):
                     "misago/emails/data_download",
                     context={
                         "data_download": data_download,
-                        "expires_in": settings.MISAGO_USER_DATA_DOWNLOADS_EXPIRE_IN_HOURS,
+                        "expires_in": expires_in,
                         "settings": dynamic_settings,
                     },
                 )

+ 5 - 5
misago/users/profilefields/default.py

@@ -48,8 +48,8 @@ class SkypeIdField(basefields.TextProfileField):
     fieldname = "skype"
     label = _("Skype ID")
     help_text = _(
-        "Entering your Skype ID in this field may invite other users to contact you over "
-        "the Skype instead of via private threads."
+        "Entering your Skype ID in this field may invite other users to "
+        "contact you over the Skype instead of via private threads."
     )
 
 
@@ -59,9 +59,9 @@ class TwitterHandleField(basefields.TextProfileField):
 
     def get_help_text(self, user):
         return _(
-            "If you own Twitter account, here you may enter your Twitter handle for other users "
-            'to find you. Starting your handle with "@" sign is optional. Either "@%(slug)s" or '
-            '"%(slug)s" are valid values.'
+            "If you own Twitter account, here you may enter your Twitter handle for "
+            'other users to find you. Starting your handle with "@" sign is optional. '
+            'Either "@%(slug)s" or "%(slug)s" are valid values.'
         ) % {"slug": user.slug}
 
     def get_value_display_data(self, request, user, value):

+ 5 - 7
misago/users/serializers/moderation.py

@@ -32,13 +32,11 @@ class ModerateSignatureSerializer(serializers.ModelSerializer):
     def validate_signature(self, value):
         length_limit = settings.signature_length_max
         if len(value) > length_limit:
-            raise serializers.ValidationError(
-                ngettext(
-                    "Signature can't be longer than %(limit)s character.",
-                    "Signature can't be longer than %(limit)s characters.",
-                    length_limit,
-                )
-                % {"limit": length_limit}
+            message = ngettext(
+                "Signature can't be longer than %(limit)s character.",
+                "Signature can't be longer than %(limit)s characters.",
+                length_limit,
             )
+            raise serializers.ValidationError(message % {"limit": length_limit})
 
         return value

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

@@ -118,8 +118,8 @@ class DeleteOwnAccountSerializer(serializers.Serializer):
 
     def mark_account_for_deletion(self, request):
         """
-        Deleting user account can be costful, so just mark account for deletion, deactivate it
-        and sign user out.
+        Deleting user account can be costful, so just mark account for deletion,
+        deactivate it and sign user out.
         """
         profile = self.context["user"]
         allow_delete_own_account(request.user, profile)

+ 2 - 1
misago/users/social/backendsnames.py

@@ -1,6 +1,7 @@
 """
 Python Social Auth doesn't provide information about proper names for OAuth sites,
-so we are using this file for overrides whenever name is different than `provider.name.title`
+so we are using this file to define those for displaying the UI.
+If provider is not defined here, it's name is created with `provider.name.title()`
 """
 
 BACKENDS_NAMES = {

+ 8 - 4
misago/users/social/pipeline.py

@@ -31,7 +31,9 @@ User = get_user_model()
 
 
 def validate_ip_not_banned(strategy, details, backend, user=None, *args, **kwargs):
-    """Pipeline step that interrupts pipeline if found user is non-staff and IP banned"""
+    """
+    Pipeline step that interrupts pipeline if found user is non-staff and IP banned
+    """
     if not user or user.is_staff:
         return None
 
@@ -85,8 +87,8 @@ def associate_by_email(strategy, details, backend, user=None, *args, **kwargs):
         raise SocialAuthFailed(
             backend,
             _(
-                "Your account has to be activated by site administrator before you will be able to "
-                "sign in with %(backend)s."
+                "Your account has to be activated by site administrator "
+                "before you will be able to sign in with %(backend)s."
             )
             % {"backend": backend_name},
         )
@@ -169,7 +171,9 @@ def create_user(strategy, details, backend, user=None, *args, **kwargs):
 
 @partial
 def create_user_with_form(strategy, details, backend, user=None, *args, **kwargs):
-    """Alternatively to create_user lets user confirm account creation before authenticating"""
+    """
+    create_user lets user confirm account creation by entering final username or email
+    """
     if user:
         return None
 

+ 3 - 1
misago/users/tests/test_auth_api.py

@@ -581,6 +581,8 @@ class ChangePasswordApiTests(TestCase):
         self.assertEqual(
             response.json(),
             {
-                "detail": "This password is too short. It must contain at least 7 characters."
+                "detail": (
+                    "This password is too short. It must contain at least 7 characters."
+                )
             },
         )

+ 4 - 1
misago/users/tests/test_bio_profilefield.py

@@ -140,7 +140,10 @@ class BioProfileFieldTests(AdminTestCase):
                         {
                             "fieldname": "bio",
                             "name": "Bio",
-                            "html": "<p>I am Bob!</p>\n\n<p>This is &lt;b&gt;my&lt;/b&gt; bio!</p>",
+                            "html": (
+                                "<p>I am Bob!</p>\n\n"
+                                "<p>This is &lt;b&gt;my&lt;/b&gt; bio!</p>"
+                            ),
                         }
                     ],
                 },

+ 13 - 4
misago/users/tests/test_datadownloads.py

@@ -176,7 +176,9 @@ class PrepareUserDataDownload(AuthenticatedUserTestCase):
         self.assert_download_is_valid()
 
     def test_prepare_download_with_username_changed_by_deleted_user(self):
-        """function creates data download for user with username changed by deleted user"""
+        """
+        function creates data download for user with username changed by deleted user
+        """
         self.user.record_name_change(self.user, "aerith", "alice")
         self.user.namechanges.update(changed_by=None)
 
@@ -271,7 +273,10 @@ class RequestUserDataDownloadTests(AuthenticatedUserTestCase):
         self.assertEqual(data_download.status, DataDownload.STATUS_PENDING)
 
     def test_util_creates_data_download_for_user_explicit_requester(self):
-        """request_user_data_download created valid data download for user with other requester"""
+        """
+        request_user_data_download created valid data download
+        for user with other requester
+        """
         requester = self.get_superuser()
         data_download = request_user_data_download(self.user, requester)
 
@@ -283,7 +288,9 @@ class RequestUserDataDownloadTests(AuthenticatedUserTestCase):
 
 class UserHasRequestedDataDownloadTests(AuthenticatedUserTestCase):
     def test_util_returns_false_for_no_download(self):
-        """user_has_data_download_request returns false if user has no requests in progress"""
+        """
+        user_has_data_download_request returns false if user has no requests in progress
+        """
         self.assertFalse(user_has_data_download_request(self.user))
 
     def test_util_returns_false_for_ready_download(self):
@@ -311,7 +318,9 @@ class UserHasRequestedDataDownloadTests(AuthenticatedUserTestCase):
         self.assertTrue(user_has_data_download_request(self.user))
 
     def test_util_returns_true_for_processing_download(self):
-        """user_has_data_download_request returns true if user has processing download"""
+        """
+        user_has_data_download_request returns true if user has processing download
+        """
         data_download = request_user_data_download(self.user)
         data_download.status = DataDownload.STATUS_PROCESSING
         data_download.save()

+ 3 - 1
misago/users/tests/test_forgottenpassword_views.py

@@ -20,7 +20,9 @@ class ForgottenPasswordViewsTests(UserTestCase):
         self.assertEqual(response.status_code, 200)
 
     def test_authenticated_request_unusable_password_view_returns_200(self):
-        """request new password view returns 200 for authenticated with unusable password"""
+        """
+        request new password view returns 200 for authenticated with unusable password
+        """
         user = self.get_authenticated_user()
         user.set_password(None)
         user.save()

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

@@ -89,6 +89,7 @@ class ProfileFieldsLoadTests(TestCase):
                 {
                     "name": "Other test",
                     "fields": [
+                        # pylint: disable=line-too-long
                         "misago.users.tests.testfiles.profilefields.RepeatedFieldnameField"
                     ],
                 },

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

@@ -122,8 +122,8 @@ class AssociateByEmailTests(PipelineTestCase):
             self.assertEqual(
                 e.message,
                 (
-                    "The e-mail address associated with your GitHub account is not available for "
-                    "use on this site."
+                    "The e-mail address associated with your GitHub account "
+                    "is not available for use on this site."
                 ),
             )
 
@@ -139,8 +139,8 @@ class AssociateByEmailTests(PipelineTestCase):
             self.assertEqual(
                 e.message,
                 (
-                    "Your account has to be activated by site administrator before you will be "
-                    "able to sign in with GitHub."
+                    "Your account has to be activated by site administrator "
+                    "before you will be able to sign in with GitHub."
                 ),
             )
 

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

@@ -196,8 +196,9 @@ class TwitterProfileFieldTests(AdminTestCase):
                 "fieldname": "twitter",
                 "label": "Twitter handle",
                 "help_text": (
-                    "If you own Twitter account, here you may enter your Twitter handle for other users to find you. "
-                    'Starting your handle with "@" sign is optional. Either "@testsuperuser" or "testsuperuser" are '
+                    "If you own Twitter account, here you may enter your Twitter "
+                    'handle for other users to find you. Starting your handle with "@" '
+                    'sign is optional. Either "@testsuperuser" or "testsuperuser" are '
                     "valid values."
                 ),
                 "input": {"type": "text"},

+ 4 - 1
misago/users/tests/test_user_create_api.py

@@ -261,7 +261,10 @@ class UserCreateTests(UserTestCase):
             {
                 "email": ["This email is not allowed."],
                 "password": [
-                    "This password is too short. It must contain at least 7 characters.",
+                    (
+                        "This password is too short. "
+                        "It must contain at least 7 characters."
+                    ),
                     "This password is entirely numeric.",
                 ],
             },

+ 3 - 1
misago/users/tests/test_user_requestdatadownload_api.py

@@ -47,7 +47,9 @@ class UserRequestDataDownload(AuthenticatedUserTestCase):
         self.assertEqual(
             response.json(),
             {
-                "detail": "You can't have more than one data download request at single time."
+                "detail": (
+                    "You can't have more than one data download request at single time."
+                )
             },
         )
 

+ 3 - 1
misago/users/tests/test_useradmin_views.py

@@ -898,7 +898,9 @@ class UserAdminViewsTests(AdminTestCase):
         self.assertTrue(updated_user.has_usable_password())
 
     def test_edit_keep_unusable_password(self):
-        """admin edit form handles unusable passwords and lets admin leave them unchanged"""
+        """
+        admin edit form handles unusable passwords and lets admin leave them unchanged
+        """
         test_user = create_test_user("User", "user@example.com")
         self.assertFalse(test_user.has_usable_password())
 

+ 16 - 5
misago/users/tests/test_users_api.py

@@ -454,7 +454,10 @@ class UserBanTests(AuthenticatedUserTestCase):
 
 
 class UserDeleteOwnAccountTests(AuthenticatedUserTestCase):
-    """tests for user request own account delete RPC (POST to /api/users/1/delete-own-account/)"""
+    """
+    tests for user request own account delete RPC
+    (POST to /api/users/1/delete-own-account/)
+    """
 
     def setUp(self):
         super().setUp()
@@ -462,7 +465,9 @@ class UserDeleteOwnAccountTests(AuthenticatedUserTestCase):
 
     @override_settings(MISAGO_ENABLE_DELETE_OWN_ACCOUNT=False)
     def test_delete_own_account_feature_disabled(self):
-        """raises 403 error when attempting to delete own account but feature is disabled"""
+        """
+        raises 403 error when attempting to delete own account but feature is disabled
+        """
         response = self.client.post(self.api_link, {"password": self.USER_PASSWORD})
 
         self.assertEqual(response.status_code, 403)
@@ -482,7 +487,9 @@ class UserDeleteOwnAccountTests(AuthenticatedUserTestCase):
         self.assertEqual(
             response.json(),
             {
-                "detail": "You can't delete your account because you are an administrator."
+                "detail": (
+                    "You can't delete your account because you are an administrator."
+                )
             },
         )
 
@@ -500,7 +507,9 @@ class UserDeleteOwnAccountTests(AuthenticatedUserTestCase):
         self.assertEqual(
             response.json(),
             {
-                "detail": "You can't delete your account because you are an administrator."
+                "detail": (
+                    "You can't delete your account because you are an administrator."
+                )
             },
         )
 
@@ -509,7 +518,9 @@ class UserDeleteOwnAccountTests(AuthenticatedUserTestCase):
         self.assertFalse(self.user.is_deleting_account)
 
     def test_delete_own_account_invalid_password(self):
-        """raises 400 error when attempting to delete own account with invalid password"""
+        """
+        raises 400 error when attempting to delete own account with invalid password
+        """
         response = self.client.post(self.api_link, {"password": "hello"})
         self.assertEqual(response.status_code, 400)
         self.assertEqual(

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

@@ -36,7 +36,8 @@ def reset_password_form(request, pk, token):
     try:
         if request.user.is_authenticated and request.user.id != requesting_user.id:
             message = _(
-                "%(user)s, your link has expired. Please request new link and try again."
+                "%(user)s, your link has expired. "
+                "Please request new link and try again."
             )
             raise ResetError(message % {"user": requesting_user.username})