Browse Source

#707: fix relative imports

Rafał Pitoń 8 years ago
parent
commit
311a5fda69
269 changed files with 557 additions and 505 deletions
  1. 52 0
      fixrelativeimports.py
  2. 1 1
      misago/acl/tests/test_acl_algebra.py
  3. 1 1
      misago/acl/tests/test_api.py
  4. 1 1
      misago/acl/tests/test_providers.py
  5. 2 2
      misago/acl/tests/test_roleadmin_views.py
  6. 2 2
      misago/acl/tests/test_testutils.py
  7. 1 1
      misago/admin/tests/test_admin_hierarchy.py
  8. 2 2
      misago/admin/tests/test_admin_views.py
  9. 2 2
      misago/admin/views/__init__.py
  10. 1 1
      misago/admin/views/auth.py
  11. 1 1
      misago/admin/views/errorpages.py
  12. 1 1
      misago/admin/views/generic/base.py
  13. 1 1
      misago/categories/management/commands/prunecategories.py
  14. 1 1
      misago/categories/management/commands/synchronizecategories.py
  15. 1 1
      misago/categories/tests/test_categories_admin_views.py
  16. 1 1
      misago/categories/tests/test_permissions_admin_views.py
  17. 2 2
      misago/categories/tests/test_prunecategories.py
  18. 2 2
      misago/categories/tests/test_synchronizecategories.py
  19. 2 2
      misago/categories/tests/test_utils.py
  20. 2 2
      misago/categories/tests/test_views.py
  21. 1 1
      misago/categories/urls/__init__.py
  22. 1 1
      misago/categories/urls/api.py
  23. 2 2
      misago/categories/views/categorieslist.py
  24. 2 2
      misago/categories/views/permsadmin.py
  25. 1 1
      misago/conf/tests/test_admin_views.py
  26. 2 2
      misago/conf/tests/test_context_processors.py
  27. 2 2
      misago/conf/tests/test_hydrators.py
  28. 2 2
      misago/conf/tests/test_migrationutils.py
  29. 1 1
      misago/conf/tests/test_models.py
  30. 4 4
      misago/conf/tests/test_settings.py
  31. 2 2
      misago/core/middleware/exceptionhandler.py
  32. 1 1
      misago/core/middleware/threadstore.py
  33. 1 1
      misago/core/templatetags/misago_json.py
  34. 1 1
      misago/core/testproject/urls.py
  35. 5 5
      misago/core/testproject/views.py
  36. 1 1
      misago/core/tests/test_apipatch.py
  37. 4 4
      misago/core/tests/test_cachebuster.py
  38. 1 1
      misago/core/tests/test_checks.py
  39. 1 1
      misago/core/tests/test_context_processors.py
  40. 1 1
      misago/core/tests/test_deprecations.py
  41. 2 2
      misago/core/tests/test_errorpages.py
  42. 1 1
      misago/core/tests/test_exceptionhandler_middleware.py
  43. 2 2
      misago/core/tests/test_exceptionhandlers.py
  44. 1 1
      misago/core/tests/test_frontendcontext_middleware.py
  45. 2 2
      misago/core/tests/test_migrationutils.py
  46. 1 1
      misago/core/tests/test_misagodbrelations.py
  47. 1 1
      misago/core/tests/test_momentjs.py
  48. 1 1
      misago/core/tests/test_page.py
  49. 1 1
      misago/core/tests/test_setup.py
  50. 1 1
      misago/core/tests/test_shortcuts.py
  51. 1 1
      misago/core/tests/test_testmailsetup.py
  52. 2 2
      misago/core/tests/test_threadstore.py
  53. 1 1
      misago/core/tests/test_utils.py
  54. 1 1
      misago/core/tests/test_validators.py
  55. 1 1
      misago/datamover/management/base.py
  56. 2 2
      misago/datamover/management/commands/buildmovesindex.py
  57. 2 2
      misago/datamover/management/commands/movecategories.py
  58. 2 2
      misago/datamover/management/commands/movesettings.py
  59. 2 2
      misago/datamover/management/commands/movethreads.py
  60. 2 2
      misago/datamover/management/commands/moveusers.py
  61. 1 1
      misago/datamover/management/commands/runmigration.py
  62. 1 1
      misago/datamover/markup/attachments.py
  63. 1 1
      misago/faker/management/commands/createfakethreads.py
  64. 1 1
      misago/faker/tests/test_englishcorpus.py
  65. 1 1
      misago/markup/tests/test_checksums.py
  66. 1 1
      misago/markup/tests/test_finalise.py
  67. 1 1
      misago/markup/tests/test_mentions.py
  68. 1 1
      misago/markup/tests/test_parser.py
  69. 1 1
      misago/readtracker/tests/test_dates.py
  70. 1 1
      misago/readtracker/tests/test_readtracker.py
  71. 1 1
      misago/search/tests/test_api.py
  72. 2 2
      misago/search/tests/test_searchproviders.py
  73. 1 1
      misago/search/urls/__init__.py
  74. 1 1
      misago/search/urls/api.py
  75. 2 2
      misago/threads/api/attachments.py
  76. 2 2
      misago/threads/api/pollvotecreateendpoint.py
  77. 2 2
      misago/threads/api/postendpoints/edits.py
  78. 1 1
      misago/threads/api/postendpoints/likes.py
  79. 2 2
      misago/threads/api/postendpoints/merge.py
  80. 2 2
      misago/threads/api/postendpoints/move.py
  81. 1 1
      misago/threads/api/postendpoints/patch_event.py
  82. 3 3
      misago/threads/api/postendpoints/patch_post.py
  83. 5 5
      misago/threads/api/postendpoints/split.py
  84. 1 1
      misago/threads/api/postingendpoint/attachments.py
  85. 2 2
      misago/threads/api/postingendpoint/category.py
  86. 1 1
      misago/threads/api/postingendpoint/close.py
  87. 1 1
      misago/threads/api/postingendpoint/emailnotification.py
  88. 1 1
      misago/threads/api/postingendpoint/hide.py
  89. 2 2
      misago/threads/api/postingendpoint/participants.py
  90. 2 2
      misago/threads/api/postingendpoint/reply.py
  91. 1 1
      misago/threads/api/postingendpoint/subscribe.py
  92. 1 1
      misago/threads/api/postingendpoint/syncprivatethreads.py
  93. 2 2
      misago/threads/api/threadendpoints/editor.py
  94. 2 2
      misago/threads/api/threadendpoints/list.py
  95. 7 7
      misago/threads/api/threadendpoints/merge.py
  96. 7 7
      misago/threads/api/threadendpoints/patch.py
  97. 1 1
      misago/threads/api/threadendpoints/pollmergehandler.py
  98. 1 1
      misago/threads/api/threadendpoints/read.py
  99. 4 4
      misago/threads/api/threadpoll.py
  100. 5 5
      misago/threads/api/threadposts.py
  101. 4 4
      misago/threads/api/threads.py
  102. 1 1
      misago/threads/management/commands/clearattachments.py
  103. 1 1
      misago/threads/management/commands/rebuildpostssearch.py
  104. 1 1
      misago/threads/management/commands/synchronizethreads.py
  105. 5 5
      misago/threads/models/post.py
  106. 3 3
      misago/threads/models/thread.py
  107. 1 1
      misago/threads/moderation/threads.py
  108. 1 1
      misago/threads/permissions/attachments.py
  109. 1 1
      misago/threads/permissions/polls.py
  110. 1 1
      misago/threads/permissions/privatethreads.py
  111. 1 1
      misago/threads/permissions/threads.py
  112. 1 1
      misago/threads/serializers/attachment.py
  113. 3 3
      misago/threads/serializers/moderation.py
  114. 1 1
      misago/threads/serializers/poll.py
  115. 1 1
      misago/threads/serializers/post.py
  116. 1 1
      misago/threads/serializers/postedit.py
  117. 1 1
      misago/threads/serializers/postlike.py
  118. 1 1
      misago/threads/serializers/thread.py
  119. 1 1
      misago/threads/serializers/threadparticipant.py
  120. 2 2
      misago/threads/tests/test_attachmentadmin_views.py
  121. 1 1
      misago/threads/tests/test_attachments_api.py
  122. 4 4
      misago/threads/tests/test_attachments_middleware.py
  123. 1 1
      misago/threads/tests/test_attachmenttypeadmin_views.py
  124. 2 2
      misago/threads/tests/test_attachmentview.py
  125. 3 3
      misago/threads/tests/test_clearattachments.py
  126. 1 1
      misago/threads/tests/test_emailnotification_middleware.py
  127. 3 3
      misago/threads/tests/test_events.py
  128. 1 1
      misago/threads/tests/test_floodprotection.py
  129. 2 2
      misago/threads/tests/test_floodprotection_middleware.py
  130. 1 1
      misago/threads/tests/test_gotoviews.py
  131. 1 1
      misago/threads/tests/test_paginator.py
  132. 2 2
      misago/threads/tests/test_participants.py
  133. 1 1
      misago/threads/tests/test_post_mentions.py
  134. 2 2
      misago/threads/tests/test_post_model.py
  135. 2 2
      misago/threads/tests/test_posts_moderation.py
  136. 2 2
      misago/threads/tests/test_privatethread_patch_api.py
  137. 2 2
      misago/threads/tests/test_privatethread_reply_api.py
  138. 1 1
      misago/threads/tests/test_privatethread_start_api.py
  139. 2 2
      misago/threads/tests/test_privatethread_view.py
  140. 2 2
      misago/threads/tests/test_privatethreads_api.py
  141. 2 2
      misago/threads/tests/test_privatethreads_lists.py
  142. 1 1
      misago/threads/tests/test_search.py
  143. 1 1
      misago/threads/tests/test_subscription_middleware.py
  144. 2 2
      misago/threads/tests/test_subscriptions.py
  145. 2 2
      misago/threads/tests/test_sync_unread_private_threads.py
  146. 2 2
      misago/threads/tests/test_synchronizethreads.py
  147. 2 2
      misago/threads/tests/test_thread_editreply_api.py
  148. 2 2
      misago/threads/tests/test_thread_merge_api.py
  149. 1 1
      misago/threads/tests/test_thread_model.py
  150. 1 1
      misago/threads/tests/test_thread_poll_api.py
  151. 2 2
      misago/threads/tests/test_thread_pollcreate_api.py
  152. 1 1
      misago/threads/tests/test_thread_polldelete_api.py
  153. 1 1
      misago/threads/tests/test_thread_polledit_api.py
  154. 1 1
      misago/threads/tests/test_thread_pollvotes_api.py
  155. 2 2
      misago/threads/tests/test_thread_postdelete_api.py
  156. 2 2
      misago/threads/tests/test_thread_postedits_api.py
  157. 2 2
      misago/threads/tests/test_thread_postlikes_api.py
  158. 3 3
      misago/threads/tests/test_thread_postmerge_api.py
  159. 3 3
      misago/threads/tests/test_thread_postmove_api.py
  160. 2 2
      misago/threads/tests/test_thread_postpatch_api.py
  161. 2 2
      misago/threads/tests/test_thread_postread_api.py
  162. 3 3
      misago/threads/tests/test_thread_postsplit_api.py
  163. 2 2
      misago/threads/tests/test_thread_reply_api.py
  164. 2 2
      misago/threads/tests/test_thread_start_api.py
  165. 1 1
      misago/threads/tests/test_threadparticipant_model.py
  166. 3 3
      misago/threads/tests/test_threads_api.py
  167. 3 3
      misago/threads/tests/test_threads_editor_api.py
  168. 4 4
      misago/threads/tests/test_threads_merge_api.py
  169. 2 2
      misago/threads/tests/test_threads_moderation.py
  170. 1 1
      misago/threads/tests/test_threadslists.py
  171. 5 5
      misago/threads/tests/test_threadview.py
  172. 1 1
      misago/threads/tests/test_treesmap.py
  173. 2 2
      misago/threads/tests/test_utils.py
  174. 1 1
      misago/threads/tests/test_validators.py
  175. 4 4
      misago/threads/urls/__init__.py
  176. 4 4
      misago/threads/urls/api.py
  177. 1 1
      misago/threads/viewmodels/category.py
  178. 1 1
      misago/threads/viewmodels/post.py
  179. 4 4
      misago/threads/viewmodels/posts.py
  180. 7 7
      misago/threads/viewmodels/thread.py
  181. 6 6
      misago/threads/viewmodels/threads.py
  182. 2 2
      misago/threads/views/admin/attachments.py
  183. 2 2
      misago/threads/views/admin/attachmenttypes.py
  184. 1 1
      misago/threads/views/attachment.py
  185. 2 2
      misago/threads/views/goto.py
  186. 1 1
      misago/threads/views/list.py
  187. 1 1
      misago/threads/views/thread.py
  188. 4 4
      misago/users/api/auth.py
  189. 2 2
      misago/users/api/ranks.py
  190. 2 2
      misago/users/api/rest_permissions.py
  191. 3 3
      misago/users/api/userendpoints/avatar.py
  192. 2 2
      misago/users/api/userendpoints/changeemail.py
  193. 2 2
      misago/users/api/userendpoints/changepassword.py
  194. 4 4
      misago/users/api/userendpoints/create.py
  195. 4 4
      misago/users/api/userendpoints/list.py
  196. 2 2
      misago/users/api/userendpoints/signature.py
  197. 2 2
      misago/users/api/userendpoints/username.py
  198. 2 2
      misago/users/api/usernamechanges.py
  199. 8 8
      misago/users/api/users.py
  200. 3 3
      misago/users/avatars/gallery.py
  201. 1 1
      misago/users/avatars/store.py
  202. 2 2
      misago/users/forms/admin.py
  203. 1 1
      misago/users/forms/auth.py
  204. 1 1
      misago/users/forms/moderation.py
  205. 1 1
      misago/users/forms/options.py
  206. 1 1
      misago/users/forms/register.py
  207. 1 1
      misago/users/forms/rename.py
  208. 1 1
      misago/users/management/commands/buildactivepostersranking.py
  209. 1 1
      misago/users/management/commands/createsuperuser.py
  210. 1 1
      misago/users/management/commands/invalidatebans.py
  211. 2 2
      misago/users/management/commands/loadavatargallery.py
  212. 1 1
      misago/users/management/commands/populateonlinetracker.py
  213. 1 1
      misago/users/models/avatar.py
  214. 1 1
      misago/users/models/avatargallery.py
  215. 2 2
      misago/users/models/ban.py
  216. 6 6
      misago/users/models/user.py
  217. 1 1
      misago/users/online/tracker.py
  218. 2 2
      misago/users/online/utils.py
  219. 1 1
      misago/users/permissions/moderation.py
  220. 1 1
      misago/users/serializers/ban.py
  221. 1 1
      misago/users/serializers/rank.py
  222. 1 1
      misago/users/serializers/usernamechange.py
  223. 2 2
      misago/users/tests/test_activation_views.py
  224. 2 2
      misago/users/tests/test_activepostersranking.py
  225. 2 2
      misago/users/tests/test_auth_api.py
  226. 1 1
      misago/users/tests/test_auth_backend.py
  227. 2 2
      misago/users/tests/test_avatars.py
  228. 1 1
      misago/users/tests/test_ban_model.py
  229. 1 1
      misago/users/tests/test_banadmin_views.py
  230. 2 2
      misago/users/tests/test_bans.py
  231. 1 1
      misago/users/tests/test_credentialchange.py
  232. 2 2
      misago/users/tests/test_decorators.py
  233. 3 3
      misago/users/tests/test_forgottenpassword_views.py
  234. 3 3
      misago/users/tests/test_invalidatebans.py
  235. 3 3
      misago/users/tests/test_lists_views.py
  236. 2 2
      misago/users/tests/test_loadavatargallery.py
  237. 1 1
      misago/users/tests/test_namechanges.py
  238. 1 1
      misago/users/tests/test_options_views.py
  239. 2 2
      misago/users/tests/test_populateonlinetracker.py
  240. 2 2
      misago/users/tests/test_profile_views.py
  241. 1 1
      misago/users/tests/test_rankadmin_views.py
  242. 1 1
      misago/users/tests/test_realip_middleware.py
  243. 2 2
      misago/users/tests/test_rest_permissions.py
  244. 1 1
      misago/users/tests/test_signatures.py
  245. 1 1
      misago/users/tests/test_testutils.py
  246. 1 1
      misago/users/tests/test_tokens.py
  247. 3 3
      misago/users/tests/test_user_avatar_api.py
  248. 1 1
      misago/users/tests/test_user_changeemail_api.py
  249. 1 1
      misago/users/tests/test_user_changepassword_api.py
  250. 2 2
      misago/users/tests/test_user_create_api.py
  251. 2 2
      misago/users/tests/test_user_middleware.py
  252. 1 1
      misago/users/tests/test_user_model.py
  253. 1 1
      misago/users/tests/test_user_signature_api.py
  254. 1 1
      misago/users/tests/test_user_username_api.py
  255. 1 1
      misago/users/tests/test_useradmin_views.py
  256. 1 1
      misago/users/tests/test_usernamechanges_api.py
  257. 3 3
      misago/users/tests/test_users_api.py
  258. 1 1
      misago/users/tests/test_utils.py
  259. 2 2
      misago/users/tests/test_validators.py
  260. 1 1
      misago/users/urls/__init__.py
  261. 4 4
      misago/users/urls/api.py
  262. 3 3
      misago/users/views/activation.py
  263. 2 2
      misago/users/views/admin/bans.py
  264. 2 2
      misago/users/views/admin/ranks.py
  265. 4 4
      misago/users/views/admin/users.py
  266. 3 3
      misago/users/views/forgottenpassword.py
  267. 5 5
      misago/users/views/lists.py
  268. 3 3
      misago/users/views/options.py
  269. 8 8
      misago/users/views/profile.py

+ 52 - 0
fixrelativeimports.py

@@ -0,0 +1,52 @@
+import os
+import re
+
+
+RELATIVE_IMPORT = re.compile(r'(from|import) \.\.+([a-z]+)?')
+
+
+def walk_directory(root, dirs, files):
+    for file_path in files:
+        if 'project_template' not in root and file_path.lower().endswith('.py'):
+            clean_file(os.path.join(root, file_path))
+
+
+def clean_file(file_path):
+    py_source = file(file_path).read()
+    if 'from ..' in py_source or 'import ..' in py_source:
+        print '====' * 8
+        print file_path
+        print '====' * 8
+
+        package = file_path.rstrip('.py').split('/')
+
+        def replace_import(matchobj):
+            prefix, suffix = matchobj.group(0).split()
+            return '{} {}'.format(prefix, clean_import(package, suffix))
+
+        py_source = RELATIVE_IMPORT.sub(replace_import, py_source)
+
+        #print py_source
+        with open(file_path, 'w') as package:
+            print file_path
+            package.write(py_source)
+
+
+def clean_import(package, match):
+    path = match[1:]
+
+    import_path = package[:]
+    while match and match[0] == '.':
+        import_path = import_path[:-1]
+        match = match[1:]
+
+    if match:
+        import_path.append(match)
+
+    return '.'.join(import_path)
+
+if __name__ == '__main__':
+    for args in os.walk('misago'):
+        walk_directory(*args)
+
+    print "\nDone! Don't forget to run isort to fix imports ordering!"

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from .. import algebra
+from misago.acl import algebra
 
 
 
 
 class ComparisionsTests(TestCase):
 class ComparisionsTests(TestCase):

+ 1 - 1
misago/acl/tests/test_api.py

@@ -3,7 +3,7 @@ from django.test import TestCase
 
 
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
 
 
-from ..api import get_user_acl
+from misago.acl.api import get_user_acl
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -6,7 +6,7 @@ from django.utils import six
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..providers import PermissionProviders
+from misago.acl.providers import PermissionProviders
 
 
 
 
 class TestType(object):
 class TestType(object):

+ 2 - 2
misago/acl/tests/test_roleadmin_views.py

@@ -2,8 +2,8 @@ from django.urls import reverse
 
 
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
 
 
-from ..models import Role
-from ..testutils import fake_post_data
+from misago.acl.models import Role
+from misago.acl.testutils import fake_post_data
 
 
 
 
 def fake_data(data_dict):
 def fake_data(data_dict):

+ 2 - 2
misago/acl/tests/test_testutils.py

@@ -1,7 +1,7 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..models import Role
-from ..testutils import fake_post_data
+from misago.acl.models import Role
+from misago.acl.testutils import fake_post_data
 
 
 
 
 class FakeTestDataTests(TestCase):
 class FakeTestDataTests(TestCase):

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..hierarchy import Node
+from misago.admin.hierarchy import Node
 
 
 
 
 class NodeTests(TestCase):
 class NodeTests(TestCase):

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

@@ -5,8 +5,8 @@ from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.test import TestCase
 from django.urls import reverse
 from django.urls import reverse
 
 
-from ..testutils import AdminTestCase
-from ..views import get_protected_namespace
+from misago.admin.testutils import AdminTestCase
+from misago.admin.views import get_protected_namespace
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/admin/views/__init__.py

@@ -3,8 +3,8 @@ from django.shortcuts import render as dj_render
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from .. import site
-from ..auth import is_admin_session, update_admin_session
+from misago.admin import site
+from misago.admin.auth import is_admin_session, update_admin_session
 from .auth import login
 from .auth import login
 
 
 
 

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

@@ -7,7 +7,7 @@ from django.views.decorators.debug import sensitive_post_parameters
 
 
 from misago.users.forms.auth import AdminAuthenticationForm
 from misago.users.forms.auth import AdminAuthenticationForm
 
 
-from .. import auth
+from misago.admin import auth
 
 
 
 
 @sensitive_post_parameters()
 @sensitive_post_parameters()

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

@@ -1,7 +1,7 @@
 from django.shortcuts import redirect
 from django.shortcuts import redirect
 
 
 from . import get_protected_namespace, protected_admin_view, render
 from . import get_protected_namespace, protected_admin_view, render
-from ..auth import is_admin_session, update_admin_session
+from misago.admin.auth import is_admin_session, update_admin_session
 
 
 
 
 # Magic error page used by admin
 # Magic error page used by admin

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

@@ -1,6 +1,6 @@
 from django.views.generic import View
 from django.views.generic import View
 
 
-from .. import render
+from misago.admin.views import render
 
 
 
 
 class AdminView(View):
 class AdminView(View):

+ 1 - 1
misago/categories/management/commands/prunecategories.py

@@ -3,7 +3,7 @@ from datetime import timedelta
 from django.core.management.base import BaseCommand
 from django.core.management.base import BaseCommand
 from django.utils import timezone
 from django.utils import timezone
 
 
-from ...models import Category
+from misago.categories.models import Category
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 1 - 1
misago/categories/management/commands/synchronizecategories.py

@@ -2,7 +2,7 @@ from django.core.management.base import BaseCommand
 
 
 from misago.core.management.progressbar import show_progress
 from misago.core.management.progressbar import show_progress
 
 
-from ...models import Category
+from misago.categories.models import Category
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 1 - 1
misago/categories/tests/test_categories_admin_views.py

@@ -4,7 +4,7 @@ from misago.admin.testutils import AdminTestCase
 from misago.threads import testutils
 from misago.threads import testutils
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 
 
-from ..models import Category
+from misago.categories.models import Category
 
 
 
 
 class CategoryAdminTestCate(AdminTestCase):
 class CategoryAdminTestCate(AdminTestCase):

+ 1 - 1
misago/categories/tests/test_permissions_admin_views.py

@@ -4,7 +4,7 @@ from misago.acl.models import Role
 from misago.acl.testutils import fake_post_data
 from misago.acl.testutils import fake_post_data
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
 
 
-from ..models import Category, CategoryRole
+from misago.categories.models import Category, CategoryRole
 
 
 
 
 def fake_data(data_dict):
 def fake_data(data_dict):

+ 2 - 2
misago/categories/tests/test_prunecategories.py

@@ -8,8 +8,8 @@ from django.utils.six.moves import range
 
 
 from misago.threads import testutils
 from misago.threads import testutils
 
 
-from ..management.commands import prunecategories
-from ..models import Category
+from misago.categories.management.commands import prunecategories
+from misago.categories.models import Category
 
 
 
 
 class PruneCategoriesTests(TestCase):
 class PruneCategoriesTests(TestCase):

+ 2 - 2
misago/categories/tests/test_synchronizecategories.py

@@ -5,8 +5,8 @@ from django.utils.six.moves import range
 
 
 from misago.threads import testutils
 from misago.threads import testutils
 
 
-from ..management.commands import synchronizecategories
-from ..models import Category
+from misago.categories.management.commands import synchronizecategories
+from misago.categories.models import Category
 
 
 
 
 class SynchronizeCategoriesTests(TestCase):
 class SynchronizeCategoriesTests(TestCase):

+ 2 - 2
misago/categories/tests/test_utils.py

@@ -2,8 +2,8 @@ from misago.acl.testutils import override_acl
 from misago.core import threadstore
 from misago.core import threadstore
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from ..models import Category
-from ..utils import get_categories_tree, get_category_path
+from misago.categories.models import Category
+from misago.categories.utils import get_categories_tree, get_category_path
 
 
 
 
 class CategoriesUtilsTests(AuthenticatedUserTestCase):
 class CategoriesUtilsTests(AuthenticatedUserTestCase):

+ 2 - 2
misago/categories/tests/test_views.py

@@ -3,8 +3,8 @@ from django.urls import reverse
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from ..models import Category
-from ..utils import get_categories_tree
+from misago.categories.models import Category
+from misago.categories.utils import get_categories_tree
 
 
 
 
 class CategoryViewsTests(AuthenticatedUserTestCase):
 class CategoryViewsTests(AuthenticatedUserTestCase):

+ 1 - 1
misago/categories/urls/__init__.py

@@ -3,7 +3,7 @@ from django.conf.urls import url
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.views import home_redirect
 from misago.core.views import home_redirect
 
 
-from ..views.categorieslist import categories
+from misago.categories.views.categorieslist import categories
 
 
 
 
 if settings.MISAGO_THREADS_ON_INDEX:
 if settings.MISAGO_THREADS_ON_INDEX:

+ 1 - 1
misago/categories/urls/api.py

@@ -1,6 +1,6 @@
 from misago.core.apirouter import MisagoApiRouter
 from misago.core.apirouter import MisagoApiRouter
 
 
-from ..api import CategoryViewSet
+from misago.categories.api import CategoryViewSet
 
 
 
 
 router = MisagoApiRouter()
 router = MisagoApiRouter()

+ 2 - 2
misago/categories/views/categorieslist.py

@@ -1,8 +1,8 @@
 from django.shortcuts import render
 from django.shortcuts import render
 from django.urls import reverse
 from django.urls import reverse
 
 
-from ..serializers import CategorySerializer
-from ..utils import get_categories_tree
+from misago.categories.serializers import CategorySerializer
+from misago.categories.utils import get_categories_tree
 
 
 
 
 def categories(request):
 def categories(request):

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

@@ -8,8 +8,8 @@ from misago.acl.models import Role
 from misago.acl.views import RoleAdmin, RolesList
 from misago.acl.views import RoleAdmin, RolesList
 from misago.admin.views import generic
 from misago.admin.views import generic
 
 
-from ..forms import CategoryRoleForm, CategoryRolesACLFormFactory, RoleCategoryACLFormFactory
-from ..models import Category, CategoryRole, RoleCategoryACL
+from misago.categories.forms import CategoryRoleForm, CategoryRolesACLFormFactory, RoleCategoryACLFormFactory
+from misago.categories.models import Category, CategoryRole, RoleCategoryACL
 from .categoriesadmin import CategoriesList, CategoryAdmin
 from .categoriesadmin import CategoriesList, CategoryAdmin
 
 
 
 

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

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
 
 
-from ..models import SettingsGroup
+from misago.conf.models import SettingsGroup
 
 
 
 
 class AdminSettingsViewsTests(AdminTestCase):
 class AdminSettingsViewsTests(AdminTestCase):

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

@@ -2,8 +2,8 @@ from django.test import TestCase
 
 
 from misago.core import threadstore
 from misago.core import threadstore
 
 
-from ..context_processors import settings
-from ..dbsettings import db_settings
+from misago.conf.context_processors import settings
+from misago.conf.dbsettings import db_settings
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

+ 2 - 2
misago/conf/tests/test_hydrators.py

@@ -1,7 +1,7 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..hydrators import dehydrate_value, hydrate_value
-from ..models import Setting
+from misago.conf.hydrators import dehydrate_value, hydrate_value
+from misago.conf.models import Setting
 
 
 
 
 class HydratorsTests(TestCase):
 class HydratorsTests(TestCase):

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

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

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..models import Setting
+from misago.conf.models import Setting
 
 
 
 
 class SettingModelTests(TestCase):
 class SettingModelTests(TestCase):

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

@@ -5,10 +5,10 @@ from django.test import TestCase, override_settings
 from misago.core import threadstore
 from misago.core import threadstore
 from misago.core.cache import cache
 from misago.core.cache import cache
 
 
-from .. import defaults
-from ..dbsettings import db_settings
-from ..gateway import settings as gateway
-from ..migrationutils import migrate_settings_group
+from misago.conf import defaults
+from misago.conf.dbsettings import db_settings
+from misago.conf.gateway import settings as gateway
+from misago.conf.migrationutils import migrate_settings_group
 
 
 
 
 class DBSettingsTests(TestCase):
 class DBSettingsTests(TestCase):

+ 2 - 2
misago/core/middleware/exceptionhandler.py

@@ -1,7 +1,7 @@
 from django.utils.deprecation import MiddlewareMixin
 from django.utils.deprecation import MiddlewareMixin
 
 
-from .. import exceptionhandler
-from ..utils import is_request_to_misago
+from misago.core import exceptionhandler
+from misago.core.utils import is_request_to_misago
 
 
 
 
 class ExceptionHandlerMiddleware(MiddlewareMixin):
 class ExceptionHandlerMiddleware(MiddlewareMixin):

+ 1 - 1
misago/core/middleware/threadstore.py

@@ -1,6 +1,6 @@
 from django.utils.deprecation import MiddlewareMixin
 from django.utils.deprecation import MiddlewareMixin
 
 
-from .. import threadstore
+from misago.core import threadstore
 
 
 
 
 class ThreadStoreMiddleware(MiddlewareMixin):
 class ThreadStoreMiddleware(MiddlewareMixin):

+ 1 - 1
misago/core/templatetags/misago_json.py

@@ -3,7 +3,7 @@ import json
 from django import template
 from django import template
 from django.utils.safestring import mark_safe
 from django.utils.safestring import mark_safe
 
 
-from ..utils import encode_json_html
+from misago.core.utils import encode_json_html
 
 
 register = template.Library()
 register = template.Library()
 
 

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

@@ -4,7 +4,7 @@ from django.contrib import admin
 
 
 from misago.users.forms.auth import AdminAuthenticationForm
 from misago.users.forms.auth import AdminAuthenticationForm
 
 
-from ..views import javascript_catalog
+from misago.core.views import javascript_catalog
 from . import views
 from . import views
 
 
 
 

+ 5 - 5
misago/core/testproject/views.py

@@ -6,11 +6,11 @@ from rest_framework.decorators import api_view
 
 
 from misago.users.models import Ban
 from misago.users.models import Ban
 
 
-from .. import errorpages, mail
-from ..decorators import require_POST
-from ..exceptions import Banned
-from ..shortcuts import paginate, paginated_response, validate_slug
-from ..views import home_redirect
+from misago.core import errorpages, mail
+from misago.core.decorators import require_POST
+from misago.core.exceptions import Banned
+from misago.core.shortcuts import paginate, paginated_response, validate_slug
+from misago.core.views import home_redirect
 from .models import Model
 from .models import Model
 from .serializers import MockSerializer
 from .serializers import MockSerializer
 
 

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

@@ -2,7 +2,7 @@ from django.core.exceptions import PermissionDenied
 from django.http import Http404
 from django.http import Http404
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..apipatch import ApiPatch, InvalidAction
+from misago.core.apipatch import ApiPatch, InvalidAction
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

+ 4 - 4
misago/core/tests/test_cachebuster.py

@@ -1,7 +1,7 @@
-from .. import cachebuster, threadstore
-from ..cache import cache
-from ..models import CacheVersion
-from ..testutils import MisagoTestCase
+from misago.core import cachebuster, threadstore
+from misago.core.cache import cache
+from misago.core.models import CacheVersion
+from misago.core.testutils import MisagoTestCase
 
 
 
 
 class CacheBusterTests(MisagoTestCase):
 class CacheBusterTests(MisagoTestCase):

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

@@ -2,7 +2,7 @@ import warnings
 
 
 from django.test import TestCase
 from django.test import TestCase
 
 
-from .. import SUPPORTED_ENGINES, check_db_engine
+from misago.core import SUPPORTED_ENGINES, check_db_engine
 
 
 
 
 INVALID_ENGINES = (
 INVALID_ENGINES = (

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

@@ -1,7 +1,7 @@
 from django.test import TestCase
 from django.test import TestCase
 from django.utils import translation
 from django.utils import translation
 
 
-from .. import context_processors
+from misago.core import context_processors
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

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

@@ -3,7 +3,7 @@ import warnings
 from django.test import TestCase, override_settings
 from django.test import TestCase, override_settings
 from django.utils import six
 from django.utils import six
 
 
-from ..deprecations import RemovedInMisagoWarning, warn
+from misago.core.deprecations import RemovedInMisagoWarning, warn
 
 
 
 
 class DeprecationsTests(TestCase):
 class DeprecationsTests(TestCase):

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

@@ -4,8 +4,8 @@ from django.urls import reverse
 
 
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
 
 
-from ..testproject.views import mock_custom_403_error_page, mock_custom_404_error_page
-from ..utils import encode_json_html
+from misago.core.testproject.views import mock_custom_403_error_page, mock_custom_404_error_page
+from misago.core.utils import encode_json_html
 
 
 
 
 class CSRFErrorViewTests(TestCase):
 class CSRFErrorViewTests(TestCase):

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

@@ -5,7 +5,7 @@ from django.urls import reverse
 
 
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
 
 
-from ..middleware.exceptionhandler import ExceptionHandlerMiddleware
+from misago.core.middleware.exceptionhandler import ExceptionHandlerMiddleware
 
 
 
 
 class ExceptionHandlerMiddlewareTests(TestCase):
 class ExceptionHandlerMiddlewareTests(TestCase):

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

@@ -5,8 +5,8 @@ from django.test import TestCase
 
 
 from misago.users.models import Ban
 from misago.users.models import Ban
 
 
-from .. import exceptionhandler
-from ..exceptions import Banned
+from misago.core import exceptionhandler
+from misago.core.exceptions import Banned
 
 
 
 
 INVALID_EXCEPTIONS = (
 INVALID_EXCEPTIONS = (

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..middleware.frontendcontext import FrontendContextMiddleware
+from misago.core.middleware.frontendcontext import FrontendContextMiddleware
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

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

@@ -1,8 +1,8 @@
 from django.apps import apps
 from django.apps import apps
 from django.test import TestCase
 from django.test import TestCase
 
 
-from .. import migrationutils
-from ..models import CacheVersion
+from misago.core import migrationutils
+from misago.core.models import CacheVersion
 
 
 
 
 class CacheBusterUtilsTests(TestCase):
 class CacheBusterUtilsTests(TestCase):

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

@@ -2,7 +2,7 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.test import TestCase
 from django.utils.six import StringIO
 from django.utils.six import StringIO
 
 
-from ..management.commands import misagodbrelations
+from misago.core.management.commands import misagodbrelations
 
 
 
 
 class MisagoDBRelationsTests(TestCase):
 class MisagoDBRelationsTests(TestCase):

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

@@ -1,7 +1,7 @@
 from django.conf import settings
 from django.conf import settings
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..momentjs import get_locale_url, clean_language_name
+from misago.core.momentjs import get_locale_url, clean_language_name
 
 
 
 
 class MomentJSTests(TestCase):
 class MomentJSTests(TestCase):

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..page import Page
+from misago.core.page import Page
 
 
 
 
 class SiteTests(TestCase):
 class SiteTests(TestCase):

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

@@ -3,7 +3,7 @@ import os
 from django.test import TestCase
 from django.test import TestCase
 from django.utils.encoding import smart_str
 from django.utils.encoding import smart_str
 
 
-from .. import setup
+from misago.core import setup
 
 
 
 
 class MockParser(object):
 class MockParser(object):

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

@@ -2,7 +2,7 @@ from django.http import Http404
 from django.test import TestCase, override_settings
 from django.test import TestCase, override_settings
 from django.urls import reverse
 from django.urls import reverse
 
 
-from ..shortcuts import get_int_or_404
+from misago.core.shortcuts import get_int_or_404
 
 
 
 
 @override_settings(ROOT_URLCONF='misago.core.testproject.urls')
 @override_settings(ROOT_URLCONF='misago.core.testproject.urls')

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

@@ -3,7 +3,7 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.test import TestCase
 from django.utils.six import StringIO
 from django.utils.six import StringIO
 
 
-from ..management.commands import testemailsetup
+from misago.core.management.commands import testemailsetup
 
 
 
 
 class TestEmailSetupTests(TestCase):
 class TestEmailSetupTests(TestCase):

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

@@ -2,8 +2,8 @@ from django.test import TestCase
 from django.test.client import RequestFactory
 from django.test.client import RequestFactory
 from django.urls import reverse
 from django.urls import reverse
 
 
-from .. import threadstore
-from ..middleware.threadstore import ThreadStoreMiddleware
+from misago.core import threadstore
+from misago.core.middleware.threadstore import ThreadStoreMiddleware
 
 
 
 
 class ThreadStoreTests(TestCase):
 class ThreadStoreTests(TestCase):

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

@@ -5,7 +5,7 @@ from django.test.client import RequestFactory
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import six, timezone
 from django.utils import six, timezone
 
 
-from ..utils import (
+from misago.core.utils import (
     clean_return_path,
     clean_return_path,
     format_plaintext_for_html,
     format_plaintext_for_html,
     is_referer_local,
     is_referer_local,

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

@@ -1,7 +1,7 @@
 from django.core.exceptions import ValidationError
 from django.core.exceptions import ValidationError
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..validators import validate_sluggable
+from misago.core.validators import validate_sluggable
 
 
 
 
 class ValidateSluggableTests(TestCase):
 class ValidateSluggableTests(TestCase):

+ 1 - 1
misago/datamover/management/base.py

@@ -3,7 +3,7 @@ import time
 from django.conf import settings
 from django.conf import settings
 from django.core.management import base
 from django.core.management import base
 
 
-from .. import OLD_FORUM
+from misago.datamover import OLD_FORUM
 
 
 
 
 CommandError = base.CommandError
 CommandError = base.CommandError

+ 2 - 2
misago/datamover/management/commands/buildmovesindex.py

@@ -1,7 +1,7 @@
 from misago.core.pgutils import batch_update
 from misago.core.pgutils import batch_update
 
 
-from ...models import MovedId, OldIdRedirect
-from ..base import BaseCommand
+from misago.datamover.models import MovedId, OldIdRedirect
+from misago.datamover.management.base import BaseCommand
 
 
 
 
 MAPPINGS = {
 MAPPINGS = {

+ 2 - 2
misago/datamover/management/commands/movecategories.py

@@ -1,5 +1,5 @@
-from ... import categories
-from ..base import BaseCommand
+from misago.datamover import categories
+from misago.datamover.management.base import BaseCommand
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 2 - 2
misago/datamover/management/commands/movesettings.py

@@ -1,5 +1,5 @@
-from ...settings import move_settings
-from ..base import BaseCommand
+from misago.datamover.settings import move_settings
+from misago.datamover.management.base import BaseCommand
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 2 - 2
misago/datamover/management/commands/movethreads.py

@@ -1,5 +1,5 @@
-from ... import attachments, markup, polls, threads
-from ..base import BaseCommand
+from misago.datamover import attachments, markup, polls, threads
+from misago.datamover.management.base import BaseCommand
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 2 - 2
misago/datamover/management/commands/moveusers.py

@@ -1,5 +1,5 @@
-from ... import avatars, bans, users
-from ..base import BaseCommand
+from misago.datamover import avatars, bans, users
+from misago.datamover.management.base import BaseCommand
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 1 - 1
misago/datamover/management/commands/runmigration.py

@@ -1,6 +1,6 @@
 from django.core.management import call_command
 from django.core.management import call_command
 
 
-from ..base import BaseCommand
+from misago.datamover.management.base import BaseCommand
 
 
 
 
 MOVE_COMMANDS = (
 MOVE_COMMANDS = (

+ 1 - 1
misago/datamover/markup/attachments.py

@@ -4,7 +4,7 @@ import re
 
 
 from misago.threads.models import Attachment
 from misago.threads.models import Attachment
 
 
-from .. import fetch_assoc, movedids
+from misago.datamover import fetch_assoc, movedids
 
 
 
 
 ATTACHMENT_RE = re.compile(r'/attachment/(?P<hash>[a-z0-9]+)/')
 ATTACHMENT_RE = re.compile(r'/attachment/(?P<hash>[a-z0-9]+)/')

+ 1 - 1
misago/faker/management/commands/createfakethreads.py

@@ -16,7 +16,7 @@ from misago.core.management.progressbar import show_progress
 from misago.threads.checksums import update_post_checksum
 from misago.threads.checksums import update_post_checksum
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
 
 
-from ...englishcorpus import EnglishCorpus
+from misago.faker.englishcorpus import EnglishCorpus
 
 
 
 
 PLACEKITTEN_URL = 'https://placekitten.com/g/%s/%s'
 PLACEKITTEN_URL = 'https://placekitten.com/g/%s/%s'

+ 1 - 1
misago/faker/tests/test_englishcorpus.py

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..englishcorpus import EnglishCorpus
+from misago.faker.englishcorpus import EnglishCorpus
 
 
 
 
 class EnglishCorpusTests(TestCase):
 class EnglishCorpusTests(TestCase):

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from .. import checksums
+from misago.markup import checksums
 
 
 
 
 class ChecksumsTests(TestCase):
 class ChecksumsTests(TestCase):

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

@@ -3,7 +3,7 @@ from __future__ import unicode_literals
 
 
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..finalise import finalise_markup
+from misago.markup.finalise import finalise_markup
 
 
 
 
 class QuoteTests(TestCase):
 class QuoteTests(TestCase):

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

@@ -1,6 +1,6 @@
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from ..mentions import add_mentions
+from misago.markup.mentions import add_mentions
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

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

@@ -4,7 +4,7 @@ from __future__ import unicode_literals
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..parser import parse
+from misago.markup.parser import parse
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -3,7 +3,7 @@ from datetime import timedelta
 from django.test import TestCase
 from django.test import TestCase
 from django.utils import timezone
 from django.utils import timezone
 
 
-from ..dates import is_date_tracked
+from misago.readtracker.dates import is_date_tracked
 
 
 
 
 class MockUser(object):
 class MockUser(object):

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

@@ -9,7 +9,7 @@ from misago.categories.models import Category
 from misago.threads import testutils
 from misago.threads import testutils
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
 
 
-from .. import categoriestracker, threadstracker
+from misago.readtracker import categoriestracker, threadstracker
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 1 - 1
misago/search/tests/test_api.py

@@ -4,7 +4,7 @@ from django.utils import six
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from ..searchproviders import searchproviders
+from misago.search.searchproviders import searchproviders
 
 
 
 
 class SearchApiTests(AuthenticatedUserTestCase):
 class SearchApiTests(AuthenticatedUserTestCase):

+ 2 - 2
misago/search/tests/test_searchproviders.py

@@ -3,8 +3,8 @@ from django.test import TestCase
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..searchprovider import SearchProvider
-from ..searchproviders import SearchProviders
+from misago.search.searchprovider import SearchProvider
+from misago.search.searchproviders import SearchProviders
 
 
 
 
 class MockProvider(SearchProvider):
 class MockProvider(SearchProvider):

+ 1 - 1
misago/search/urls/__init__.py

@@ -1,6 +1,6 @@
 from django.conf.urls import url
 from django.conf.urls import url
 
 
-from ..views import landing, search
+from misago.search.views import landing, search
 
 
 
 
 urlpatterns = [
 urlpatterns = [

+ 1 - 1
misago/search/urls/api.py

@@ -1,6 +1,6 @@
 from django.conf.urls import url
 from django.conf.urls import url
 
 
-from .. import api
+from misago.search import api
 
 
 
 
 urlpatterns = [
 urlpatterns = [

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

@@ -7,8 +7,8 @@ from rest_framework.response import Response
 
 
 from misago.acl import add_acl
 from misago.acl import add_acl
 
 
-from ..models import Attachment, AttachmentType
-from ..serializers import AttachmentSerializer
+from misago.threads.models import Attachment, AttachmentType
+from misago.threads.serializers import AttachmentSerializer
 
 
 
 
 IMAGE_EXTENSIONS = ('jpg', 'jpeg', 'png', 'gif')
 IMAGE_EXTENSIONS = ('jpg', 'jpeg', 'png', 'gif')

+ 2 - 2
misago/threads/api/pollvotecreateendpoint.py

@@ -9,8 +9,8 @@ from rest_framework.response import Response
 
 
 from misago.acl import add_acl
 from misago.acl import add_acl
 
 
-from ..permissions.polls import allow_vote_poll
-from ..serializers import PollSerializer
+from misago.threads.permissions.polls import allow_vote_poll
+from misago.threads.serializers import PollSerializer
 
 
 
 
 def poll_vote_create(request, thread, poll):
 def poll_vote_create(request, thread, poll):

+ 2 - 2
misago/threads/api/postendpoints/edits.py

@@ -11,8 +11,8 @@ from misago.core.shortcuts import get_int_or_404, get_object_or_404
 from misago.markup import common_flavour
 from misago.markup import common_flavour
 from misago.users.online.utils import make_users_status_aware
 from misago.users.online.utils import make_users_status_aware
 
 
-from ...checksums import update_post_checksum
-from ...serializers import PostEditSerializer, PostSerializer
+from misago.threads.checksums import update_post_checksum
+from misago.threads.serializers import PostEditSerializer, PostSerializer
 
 
 
 
 def get_edit_endpoint(request, post):
 def get_edit_endpoint(request, post):

+ 1 - 1
misago/threads/api/postendpoints/likes.py

@@ -1,6 +1,6 @@
 from rest_framework.response import Response
 from rest_framework.response import Response
 
 
-from ...serializers import PostLikeSerializer
+from misago.threads.serializers import PostLikeSerializer
 
 
 
 
 def likes_list_endpoint(request, post):
 def likes_list_endpoint(request, post):

+ 2 - 2
misago/threads/api/postendpoints/merge.py

@@ -7,8 +7,8 @@ from rest_framework.response import Response
 from misago.acl import add_acl
 from misago.acl import add_acl
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ...permissions.threads import exclude_invisible_posts
-from ...serializers import PostSerializer
+from misago.threads.permissions.threads import exclude_invisible_posts
+from misago.threads.serializers import PostSerializer
 
 
 
 
 MERGE_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL
 MERGE_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL

+ 2 - 2
misago/threads/api/postendpoints/move.py

@@ -7,8 +7,8 @@ from rest_framework.response import Response
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ...permissions.threads import allow_move_post, exclude_invisible_posts
-from ...utils import get_thread_id_from_url
+from misago.threads.permissions.threads import allow_move_post, exclude_invisible_posts
+from misago.threads.utils import get_thread_id_from_url
 
 
 
 
 MOVE_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL
 MOVE_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL

+ 1 - 1
misago/threads/api/postendpoints/patch_event.py

@@ -4,7 +4,7 @@ from django.utils.translation import gettext as _
 from misago.acl import add_acl
 from misago.acl import add_acl
 from misago.core.apipatch import ApiPatch
 from misago.core.apipatch import ApiPatch
 
 
-from ...moderation import posts as moderation
+from misago.threads.moderation import posts as moderation
 
 
 
 
 event_patch_dispatcher = ApiPatch()
 event_patch_dispatcher = ApiPatch()

+ 3 - 3
misago/threads/api/postendpoints/patch_post.py

@@ -4,9 +4,9 @@ from django.utils.translation import gettext as _
 from misago.acl import add_acl
 from misago.acl import add_acl
 from misago.core.apipatch import ApiPatch
 from misago.core.apipatch import ApiPatch
 
 
-from ...models import PostLike
-from ...moderation import posts as moderation
-from ...permissions.threads import (
+from misago.threads.models import PostLike
+from misago.threads.moderation import posts as moderation
+from misago.threads.permissions.threads import (
     allow_approve_post, allow_hide_post, allow_protect_post, allow_unhide_post)
     allow_approve_post, allow_hide_post, allow_protect_post, allow_unhide_post)
 
 
 
 

+ 5 - 5
misago/threads/api/postendpoints/split.py

@@ -7,11 +7,11 @@ from rest_framework.response import Response
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ...events import record_event
-from ...models import Thread
-from ...moderation import threads as moderation
-from ...permissions.threads import exclude_invisible_posts
-from ...serializers import NewThreadSerializer
+from misago.threads.events import record_event
+from misago.threads.models import Thread
+from misago.threads.moderation import threads as moderation
+from misago.threads.permissions.threads import exclude_invisible_posts
+from misago.threads.serializers import NewThreadSerializer
 
 
 
 
 SPLIT_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL
 SPLIT_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL

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

@@ -7,7 +7,7 @@ from misago.acl import add_acl
 from misago.conf import settings
 from misago.conf import settings
 
 
 from . import PostingEndpoint, PostingInterrupt, PostingMiddleware
 from . import PostingEndpoint, PostingInterrupt, PostingMiddleware
-from ...serializers import AttachmentSerializer
+from misago.threads.serializers import AttachmentSerializer
 
 
 
 
 class AttachmentsMiddleware(PostingMiddleware):
 class AttachmentsMiddleware(PostingMiddleware):

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

@@ -10,8 +10,8 @@ from misago.categories.models import Category
 from misago.categories.permissions import can_browse_category, can_see_category
 from misago.categories.permissions import can_browse_category, can_see_category
 
 
 from . import PostingEndpoint, PostingMiddleware
 from . import PostingEndpoint, PostingMiddleware
-from ...permissions.threads import allow_start_thread
-from ...threadtypes import trees_map
+from misago.threads.permissions.threads import allow_start_thread
+from misago.threads.threadtypes import trees_map
 
 
 
 
 class CategoryMiddleware(PostingMiddleware):
 class CategoryMiddleware(PostingMiddleware):

+ 1 - 1
misago/threads/api/postingendpoint/close.py

@@ -1,5 +1,5 @@
 from . import PostingEndpoint, PostingMiddleware
 from . import PostingEndpoint, PostingMiddleware
-from ... import moderation
+from misago.threads import moderation
 
 
 
 
 class CloseMiddleware(PostingMiddleware):
 class CloseMiddleware(PostingMiddleware):

+ 1 - 1
misago/threads/api/postingendpoint/emailnotification.py

@@ -3,7 +3,7 @@ from django.utils.translation import ugettext as _
 from misago.core.mail import build_mail, send_messages
 from misago.core.mail import build_mail, send_messages
 
 
 from . import PostingEndpoint, PostingMiddleware
 from . import PostingEndpoint, PostingMiddleware
-from ...permissions.threads import can_see_post, can_see_thread
+from misago.threads.permissions.threads import can_see_post, can_see_thread
 
 
 
 
 class EmailNotificationMiddleware(PostingMiddleware):
 class EmailNotificationMiddleware(PostingMiddleware):

+ 1 - 1
misago/threads/api/postingendpoint/hide.py

@@ -1,5 +1,5 @@
 from . import PostingEndpoint, PostingMiddleware
 from . import PostingEndpoint, PostingMiddleware
-from ... import moderation
+from misago.threads import moderation
 
 
 
 
 class HideMiddleware(PostingMiddleware):
 class HideMiddleware(PostingMiddleware):

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

@@ -9,8 +9,8 @@ from rest_framework import serializers
 from misago.categories import PRIVATE_THREADS_ROOT_NAME
 from misago.categories import PRIVATE_THREADS_ROOT_NAME
 
 
 from . import PostingEndpoint, PostingMiddleware
 from . import PostingEndpoint, PostingMiddleware
-from ...participants import add_participants, set_owner
-from ...permissions import allow_message_user
+from misago.threads.participants import add_participants, set_owner
+from misago.threads.permissions import allow_message_user
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -7,8 +7,8 @@ from misago.conf import settings
 from misago.markup import common_flavour
 from misago.markup import common_flavour
 
 
 from . import PostingEndpoint, PostingMiddleware
 from . import PostingEndpoint, PostingMiddleware
-from ...checksums import update_post_checksum
-from ...validators import validate_post, validate_title
+from misago.threads.checksums import update_post_checksum
+from misago.threads.validators import validate_post, validate_title
 
 
 
 
 class ReplyMiddleware(PostingMiddleware):
 class ReplyMiddleware(PostingMiddleware):

+ 1 - 1
misago/threads/api/postingendpoint/subscribe.py

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 
 
 from . import PostingEndpoint, PostingMiddleware
 from . import PostingEndpoint, PostingMiddleware
-from ...models import Subscription
+from misago.threads.models import Subscription
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 1 - 1
misago/threads/api/postingendpoint/syncprivatethreads.py

@@ -1,6 +1,6 @@
 from misago.categories import PRIVATE_THREADS_ROOT_NAME
 from misago.categories import PRIVATE_THREADS_ROOT_NAME
 
 
-from ...participants import set_users_unread_private_threads_sync
+from misago.threads.participants import set_users_unread_private_threads_sync
 from . import PostingEndpoint, PostingMiddleware
 from . import PostingEndpoint, PostingMiddleware
 
 
 
 

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

@@ -7,8 +7,8 @@ from misago.acl import add_acl
 from misago.categories import THREADS_ROOT_NAME
 from misago.categories import THREADS_ROOT_NAME
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from ...permissions.threads import can_start_thread
-from ...threadtypes import trees_map
+from misago.threads.permissions.threads import can_start_thread
+from misago.threads.threadtypes import trees_map
 
 
 
 
 def thread_start_editor(request):
 def thread_start_editor(request):

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

@@ -2,8 +2,8 @@ from rest_framework.response import Response
 
 
 from misago.core.shortcuts import get_int_or_404
 from misago.core.shortcuts import get_int_or_404
 
 
-from ...viewmodels.category import PrivateThreadsCategory, ThreadsCategory, ThreadsRootCategory
-from ...viewmodels.threads import ForumThreads, PrivateThreads
+from misago.threads.viewmodels.category import PrivateThreadsCategory, ThreadsCategory, ThreadsRootCategory
+from misago.threads.viewmodels.threads import ForumThreads, PrivateThreads
 
 
 
 
 class ThreadsList(object):
 class ThreadsList(object):

+ 7 - 7
misago/threads/api/threadendpoints/merge.py

@@ -9,13 +9,13 @@ from misago.acl import add_acl
 from misago.categories import THREADS_ROOT_NAME
 from misago.categories import THREADS_ROOT_NAME
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from ...events import record_event
-from ...models import Thread
-from ...moderation import threads as moderation
-from ...permissions import can_reply_thread, can_see_thread
-from ...serializers import NewThreadSerializer, ThreadsListSerializer
-from ...threadtypes import trees_map
-from ...utils import add_categories_to_items, get_thread_id_from_url
+from misago.threads.events import record_event
+from misago.threads.models import Thread
+from misago.threads.moderation import threads as moderation
+from misago.threads.permissions import can_reply_thread, can_see_thread
+from misago.threads.serializers import NewThreadSerializer, ThreadsListSerializer
+from misago.threads.threadtypes import trees_map
+from misago.threads.utils import add_categories_to_items, get_thread_id_from_url
 from .pollmergehandler import PollMergeHandler
 from .pollmergehandler import PollMergeHandler
 
 
 
 

+ 7 - 7
misago/threads/api/threadendpoints/patch.py

@@ -10,17 +10,17 @@ from misago.categories.serializers import CategorySerializer
 from misago.core.apipatch import ApiPatch
 from misago.core.apipatch import ApiPatch
 from misago.core.shortcuts import get_int_or_404, get_object_or_404
 from misago.core.shortcuts import get_int_or_404, get_object_or_404
 
 
-from ...models import ThreadParticipant
-from ...moderation import threads as moderation
-from ...participants import (
+from misago.threads.models import ThreadParticipant
+from misago.threads.moderation import threads as moderation
+from misago.threads.participants import (
     add_participant, change_owner, make_participants_aware, remove_participant)
     add_participant, change_owner, make_participants_aware, remove_participant)
-from ...permissions import (
+from misago.threads.permissions import (
     allow_add_participants, allow_add_participant,
     allow_add_participants, allow_add_participant,
     allow_change_owner, allow_edit_thread,
     allow_change_owner, allow_edit_thread,
     allow_remove_participant, allow_start_thread)
     allow_remove_participant, allow_start_thread)
-from ...serializers import ThreadParticipantSerializer
-from ...utils import add_categories_to_items
-from ...validators import validate_title
+from misago.threads.serializers import ThreadParticipantSerializer
+from misago.threads.utils import add_categories_to_items
+from misago.threads.validators import validate_title
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -1,6 +1,6 @@
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext as _
 
 
-from ...models import Poll
+from misago.threads.models import Poll
 
 
 
 
 class PollMergeHandler(object):
 class PollMergeHandler(object):

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

@@ -4,7 +4,7 @@ from misago.categories.permissions import allow_browse_category, allow_see_categ
 from misago.core.shortcuts import get_int_or_404, get_object_or_404
 from misago.core.shortcuts import get_int_or_404, get_object_or_404
 from misago.readtracker.categoriestracker import read_category
 from misago.readtracker.categoriestracker import read_category
 
 
-from ...threadtypes import trees_map
+from misago.threads.threadtypes import trees_map
 
 
 
 
 def read_threads(user, pk):
 def read_threads(user, pk):

+ 4 - 4
misago/threads/api/threadpoll.py

@@ -10,17 +10,17 @@ from rest_framework.response import Response
 from misago.acl import add_acl
 from misago.acl import add_acl
 from misago.core.shortcuts import get_int_or_404
 from misago.core.shortcuts import get_int_or_404
 
 
-from ..models import Poll
-from ..permissions.polls import (
+from misago.threads.models import Poll
+from misago.threads.permissions.polls import (
     allow_delete_poll,
     allow_delete_poll,
     allow_edit_poll,
     allow_edit_poll,
     allow_see_poll_votes,
     allow_see_poll_votes,
     allow_start_poll,
     allow_start_poll,
     can_start_poll
     can_start_poll
 )
 )
-from ..serializers import (
+from misago.threads.serializers import (
     EditPollSerializer, NewPollSerializer, PollSerializer, PollVoteSerializer)
     EditPollSerializer, NewPollSerializer, PollSerializer, PollVoteSerializer)
-from ..viewmodels import ForumThread
+from misago.threads.viewmodels import ForumThread
 from .pollvotecreateendpoint import poll_vote_create
 from .pollvotecreateendpoint import poll_vote_create
 
 
 
 

+ 5 - 5
misago/threads/api/threadposts.py

@@ -10,11 +10,11 @@ from misago.acl import add_acl
 from misago.core.shortcuts import get_int_or_404
 from misago.core.shortcuts import get_int_or_404
 from misago.users.online.utils import make_users_status_aware
 from misago.users.online.utils import make_users_status_aware
 
 
-from ..models import Post
-from ..moderation import posts as moderation
-from ..permissions.threads import allow_delete_event, allow_delete_post, allow_edit_post, allow_reply_thread
-from ..serializers import AttachmentSerializer, PostSerializer
-from ..viewmodels import ForumThread, PrivateThread, ThreadPost, ThreadPosts
+from misago.threads.models import Post
+from misago.threads.moderation import posts as moderation
+from misago.threads.permissions.threads import allow_delete_event, allow_delete_post, allow_edit_post, allow_reply_thread
+from misago.threads.serializers import AttachmentSerializer, PostSerializer
+from misago.threads.viewmodels import ForumThread, PrivateThread, ThreadPost, ThreadPosts
 from .postendpoints.edits import get_edit_endpoint, revert_post_endpoint
 from .postendpoints.edits import get_edit_endpoint, revert_post_endpoint
 from .postendpoints.likes import likes_list_endpoint
 from .postendpoints.likes import likes_list_endpoint
 from .postendpoints.merge import posts_merge_endpoint
 from .postendpoints.merge import posts_merge_endpoint

+ 4 - 4
misago/threads/api/threads.py

@@ -9,10 +9,10 @@ from rest_framework.response import Response
 from misago.categories import PRIVATE_THREADS_ROOT_NAME, THREADS_ROOT_NAME
 from misago.categories import PRIVATE_THREADS_ROOT_NAME, THREADS_ROOT_NAME
 from misago.core.shortcuts import get_int_or_404
 from misago.core.shortcuts import get_int_or_404
 
 
-from ..models import Post, Thread
-from ..moderation import threads as moderation
-from ..permissions import allow_use_private_threads
-from ..viewmodels import ForumThread, PrivateThread
+from misago.threads.models import Post, Thread
+from misago.threads.moderation import threads as moderation
+from misago.threads.permissions import allow_use_private_threads
+from misago.threads.viewmodels import ForumThread, PrivateThread
 from .postingendpoint import PostingEndpoint
 from .postingendpoint import PostingEndpoint
 from .threadendpoints.editor import thread_start_editor
 from .threadendpoints.editor import thread_start_editor
 from .threadendpoints.list import private_threads_list_endpoint, threads_list_endpoint
 from .threadendpoints.list import private_threads_list_endpoint, threads_list_endpoint

+ 1 - 1
misago/threads/management/commands/clearattachments.py

@@ -8,7 +8,7 @@ from misago.conf import settings
 from misago.core.management.progressbar import show_progress
 from misago.core.management.progressbar import show_progress
 from misago.core.pgutils import batch_update
 from misago.core.pgutils import batch_update
 
 
-from ...models import Attachment
+from misago.threads.models import Attachment
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 1 - 1
misago/threads/management/commands/rebuildpostssearch.py

@@ -5,7 +5,7 @@ from django.core.management.base import BaseCommand
 from misago.core.management.progressbar import show_progress
 from misago.core.management.progressbar import show_progress
 from misago.core.pgutils import batch_update
 from misago.core.pgutils import batch_update
 
 
-from ...models import Post
+from misago.threads.models import Post
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 1 - 1
misago/threads/management/commands/synchronizethreads.py

@@ -5,7 +5,7 @@ from django.core.management.base import BaseCommand
 from misago.core.management.progressbar import show_progress
 from misago.core.management.progressbar import show_progress
 from misago.core.pgutils import batch_update
 from misago.core.pgutils import batch_update
 
 
-from ...models import Thread
+from misago.threads.models import Thread
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 5 - 5
misago/threads/models/post.py

@@ -14,8 +14,8 @@ from misago.conf import settings
 from misago.core.utils import parse_iso8601_string
 from misago.core.utils import parse_iso8601_string
 from misago.markup import finalise_markup
 from misago.markup import finalise_markup
 
 
-from .. import threadtypes
-from ..checksums import is_post_valid, update_post_checksum
+from misago.threads import threadtypes
+from misago.threads.checksums import is_post_valid, update_post_checksum
 
 
 
 
 @python_2_unicode_compatible
 @python_2_unicode_compatible
@@ -95,7 +95,7 @@ class Post(models.Model):
         return '%s...' % self.original[10:].strip()
         return '%s...' % self.original[10:].strip()
 
 
     def delete(self, *args, **kwargs):
     def delete(self, *args, **kwargs):
-        from ..signals import delete_post
+        from misago.threads.signals import delete_post
         delete_post.send(sender=self)
         delete_post.send(sender=self)
 
 
         super(Post, self).delete(*args, **kwargs)
         super(Post, self).delete(*args, **kwargs)
@@ -114,11 +114,11 @@ class Post(models.Model):
         other_post.parsed = six.text_type('\n').join((other_post.parsed, self.parsed))
         other_post.parsed = six.text_type('\n').join((other_post.parsed, self.parsed))
         update_post_checksum(other_post)
         update_post_checksum(other_post)
 
 
-        from ..signals import merge_post
+        from misago.threads.signals import merge_post
         merge_post.send(sender=self, other_post=other_post)
         merge_post.send(sender=self, other_post=other_post)
 
 
     def move(self, new_thread):
     def move(self, new_thread):
-        from ..signals import move_post
+        from misago.threads.signals import move_post
 
 
         self.category = new_thread.category
         self.category = new_thread.category
         self.thread = new_thread
         self.thread = new_thread

+ 3 - 3
misago/threads/models/thread.py

@@ -95,7 +95,7 @@ class Thread(models.Model):
         return Thread.objects.select_for_update().get(id=self.id)
         return Thread.objects.select_for_update().get(id=self.id)
 
 
     def delete(self, *args, **kwargs):
     def delete(self, *args, **kwargs):
-        from ..signals import delete_thread
+        from misago.threads.signals import delete_thread
         delete_thread.send(sender=self)
         delete_thread.send(sender=self)
 
 
         super(Thread, self).delete(*args, **kwargs)
         super(Thread, self).delete(*args, **kwargs)
@@ -104,11 +104,11 @@ class Thread(models.Model):
         if self.pk == other_thread.pk:
         if self.pk == other_thread.pk:
             raise ValueError("thread can't be merged with itself")
             raise ValueError("thread can't be merged with itself")
 
 
-        from ..signals import merge_thread
+        from misago.threads.signals import merge_thread
         merge_thread.send(sender=self, other_thread=other_thread)
         merge_thread.send(sender=self, other_thread=other_thread)
 
 
     def move(self, new_category):
     def move(self, new_category):
-        from ..signals import move_thread
+        from misago.threads.signals import move_thread
 
 
         self.category = new_category
         self.category = new_category
         move_thread.send(sender=self)
         move_thread.send(sender=self)

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

@@ -2,7 +2,7 @@ from django.db.transaction import atomic
 from django.utils import timezone
 from django.utils import timezone
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 
 
-from ..events import record_event
+from misago.threads.events import record_event
 
 
 
 
 @atomic
 @atomic

+ 1 - 1
misago/threads/permissions/attachments.py

@@ -5,7 +5,7 @@ from misago.acl import algebra
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.core.forms import YesNoSwitch
 from misago.core.forms import YesNoSwitch
 
 
-from ..models import Attachment
+from misago.threads.models import Attachment
 
 
 
 
 """
 """

+ 1 - 1
misago/threads/permissions/polls.py

@@ -9,7 +9,7 @@ from misago.acl.decorators import return_boolean
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.core.forms import YesNoSwitch
 from misago.core.forms import YesNoSwitch
 
 
-from ..models import Poll, Thread
+from misago.threads.models import Poll, Thread
 
 
 
 
 """
 """

+ 1 - 1
misago/threads/permissions/privatethreads.py

@@ -12,7 +12,7 @@ from misago.categories import PRIVATE_THREADS_ROOT_NAME
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.core.forms import YesNoSwitch
 from misago.core.forms import YesNoSwitch
 
 
-from ..models import Thread
+from misago.threads.models import Thread
 
 
 
 
 """
 """

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

@@ -13,7 +13,7 @@ from misago.categories.models import Category, CategoryRole, RoleCategoryACL
 from misago.categories.permissions import get_categories_roles
 from misago.categories.permissions import get_categories_roles
 from misago.core.forms import YesNoSwitch
 from misago.core.forms import YesNoSwitch
 
 
-from ..models import Post, Thread
+from misago.threads.models import Post, Thread
 
 
 
 
 """
 """

+ 1 - 1
misago/threads/serializers/attachment.py

@@ -4,7 +4,7 @@ from rest_framework import serializers
 
 
 from misago.core.utils import format_plaintext_for_html
 from misago.core.utils import format_plaintext_for_html
 
 
-from ..models import Attachment
+from misago.threads.models import Attachment
 
 
 
 
 __all__ = ['AttachmentSerializer']
 __all__ = ['AttachmentSerializer']

+ 3 - 3
misago/threads/serializers/moderation.py

@@ -5,9 +5,9 @@ from rest_framework import serializers
 
 
 from misago.acl import add_acl
 from misago.acl import add_acl
 
 
-from ..models import Thread
-from ..permissions import can_start_thread
-from ..validators import validate_category, validate_title
+from misago.threads.models import Thread
+from misago.threads.permissions import can_start_thread
+from misago.threads.validators import validate_category, validate_title
 
 
 
 
 __all__ = [
 __all__ = [

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

@@ -5,7 +5,7 @@ from django.utils.translation import ungettext
 
 
 from rest_framework import serializers
 from rest_framework import serializers
 
 
-from ..models import Poll
+from misago.threads.models import Poll
 
 
 
 
 MAX_POLL_OPTIONS = 16
 MAX_POLL_OPTIONS = 16

+ 1 - 1
misago/threads/serializers/post.py

@@ -6,7 +6,7 @@ from misago.categories.models import Category
 from misago.categories.serializers import BasicCategorySerializer
 from misago.categories.serializers import BasicCategorySerializer
 from misago.users.serializers import BasicUserSerializer, UserSerializer
 from misago.users.serializers import BasicUserSerializer, UserSerializer
 
 
-from ..models import Post
+from misago.threads.models import Post
 
 
 
 
 __all__ = [
 __all__ = [

+ 1 - 1
misago/threads/serializers/postedit.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from rest_framework import serializers
 from rest_framework import serializers
 
 
-from ..models import PostEdit
+from misago.threads.models import PostEdit
 
 
 
 
 __all__ = [
 __all__ = [

+ 1 - 1
misago/threads/serializers/postlike.py

@@ -2,7 +2,7 @@ from django.urls import reverse
 
 
 from rest_framework import serializers
 from rest_framework import serializers
 
 
-from ..models import PostLike
+from misago.threads.models import PostLike
 
 
 
 
 __all__ = [
 __all__ = [

+ 1 - 1
misago/threads/serializers/thread.py

@@ -4,7 +4,7 @@ from rest_framework import serializers
 
 
 from misago.categories.serializers import BasicCategorySerializer
 from misago.categories.serializers import BasicCategorySerializer
 
 
-from ..models import Thread
+from misago.threads.models import Thread
 from .poll import PollSerializer
 from .poll import PollSerializer
 from .threadparticipant import ThreadParticipantSerializer
 from .threadparticipant import ThreadParticipantSerializer
 
 

+ 1 - 1
misago/threads/serializers/threadparticipant.py

@@ -1,6 +1,6 @@
 from rest_framework import serializers
 from rest_framework import serializers
 
 
-from ..models import ThreadParticipant
+from misago.threads.models import ThreadParticipant
 
 
 
 
 __all__ = ['ThreadParticipantSerializer']
 __all__ = ['ThreadParticipantSerializer']

+ 2 - 2
misago/threads/tests/test_attachmentadmin_views.py

@@ -3,8 +3,8 @@ from django.urls import reverse
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from .. import testutils
-from ..models import Attachment, AttachmentType
+from misago.threads import testutils
+from misago.threads.models import Attachment, AttachmentType
 
 
 
 
 class AttachmentAdminViewsTests(AdminTestCase):
 class AttachmentAdminViewsTests(AdminTestCase):

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

@@ -12,7 +12,7 @@ from misago.acl.testutils import override_acl
 from misago.conf import settings
 from misago.conf import settings
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from ..models import Attachment, AttachmentType
+from misago.threads.models import Attachment, AttachmentType
 
 
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')

+ 4 - 4
misago/threads/tests/test_attachments_middleware.py

@@ -5,10 +5,10 @@ from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..api.postingendpoint import PostingEndpoint
-from ..api.postingendpoint.attachments import AttachmentsMiddleware, validate_attachments_count
-from ..models import Attachment, AttachmentType
+from misago.threads import testutils
+from misago.threads.api.postingendpoint import PostingEndpoint
+from misago.threads.api.postingendpoint.attachments import AttachmentsMiddleware, validate_attachments_count
+from misago.threads.models import Attachment, AttachmentType
 
 
 
 
 class RequestMock(object):
 class RequestMock(object):

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

@@ -3,7 +3,7 @@ from django.urls import reverse
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
 
 
-from ..models import AttachmentType
+from misago.threads.models import AttachmentType
 
 
 
 
 class AttachmentTypeAdminViewsTests(AdminTestCase):
 class AttachmentTypeAdminViewsTests(AdminTestCase):

+ 2 - 2
misago/threads/tests/test_attachmentview.py

@@ -8,8 +8,8 @@ from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..models import Attachment, AttachmentType
+from misago.threads import testutils
+from misago.threads.models import Attachment, AttachmentType
 
 
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')

+ 3 - 3
misago/threads/tests/test_clearattachments.py

@@ -8,9 +8,9 @@ from django.utils.six import StringIO
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 
 
-from .. import testutils
-from ..management.commands import clearattachments
-from ..models import Attachment, AttachmentType
+from misago.threads import testutils
+from misago.threads.management.commands import clearattachments
+from misago.threads.models import Attachment, AttachmentType
 
 
 
 
 class ClearAttachmentsTests(TestCase):
 class ClearAttachmentsTests(TestCase):

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

@@ -14,7 +14,7 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
+from misago.threads import testutils
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 3 - 3
misago/threads/tests/test_events.py

@@ -8,9 +8,9 @@ from django.utils import timezone
 from misago.acl import add_acl
 from misago.acl import add_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from ..events import record_event
-from ..models import Post, Thread
-from ..testutils import reply_thread
+from misago.threads.events import record_event
+from misago.threads.models import Post, Thread
+from misago.threads.testutils import reply_thread
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -7,7 +7,7 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
+from misago.threads import testutils
 
 
 
 
 class PostMentionsTests(AuthenticatedUserTestCase):
 class PostMentionsTests(AuthenticatedUserTestCase):

+ 2 - 2
misago/threads/tests/test_floodprotection_middleware.py

@@ -5,8 +5,8 @@ from django.utils import timezone
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from ..api.postingendpoint import PostingInterrupt
-from ..api.postingendpoint.floodprotection import MIN_POSTING_PAUSE, FloodProtectionMiddleware
+from misago.threads.api.postingendpoint import PostingInterrupt
+from misago.threads.api.postingendpoint.floodprotection import MIN_POSTING_PAUSE, FloodProtectionMiddleware
 
 
 
 
 class FloodProtectionMiddlewareTests(AuthenticatedUserTestCase):
 class FloodProtectionMiddlewareTests(AuthenticatedUserTestCase):

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

@@ -6,7 +6,7 @@ from misago.conf import settings
 from misago.readtracker.threadstracker import make_thread_read_aware, read_thread
 from misago.readtracker.threadstracker import make_thread_read_aware, read_thread
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
+from misago.threads import testutils
 
 
 
 
 GOTO_URL = '%s#post-%s'
 GOTO_URL = '%s#post-%s'

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..paginator import PostsPaginator
+from misago.threads.paginator import PostsPaginator
 
 
 
 
 class PostsPaginatorTests(TestCase):
 class PostsPaginatorTests(TestCase):

+ 2 - 2
misago/threads/tests/test_participants.py

@@ -4,8 +4,8 @@ from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from ..models import Post, Thread, ThreadParticipant
-from ..participants import (
+from misago.threads.models import Post, Thread, ThreadParticipant
+from misago.threads.participants import (
     has_participants,
     has_participants,
     make_participants_aware,
     make_participants_aware,
     set_owner,
     set_owner,

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

@@ -10,7 +10,7 @@ from misago.categories.models import Category
 from misago.markup.mentions import MENTIONS_LIMIT
 from misago.markup.mentions import MENTIONS_LIMIT
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
+from misago.threads import testutils
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/threads/tests/test_post_model.py

@@ -6,8 +6,8 @@ from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from ..checksums import update_post_checksum
-from ..models import Post, Thread
+from misago.threads.checksums import update_post_checksum
+from misago.threads.models import Post, Thread
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/threads/tests/test_posts_moderation.py

@@ -1,8 +1,8 @@
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import moderation, testutils
-from ..models import Post, Thread
+from misago.threads import moderation, testutils
+from misago.threads.models import Post, Thread
 
 
 
 
 class PostsModerationTests(AuthenticatedUserTestCase):
 class PostsModerationTests(AuthenticatedUserTestCase):

+ 2 - 2
misago/threads/tests/test_privatethread_patch_api.py

@@ -5,8 +5,8 @@ from django.core import mail
 
 
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 
 
-from .. import testutils
-from ..models import Thread, ThreadParticipant
+from misago.threads import testutils
+from misago.threads.models import Thread, ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
 
 
 
 

+ 2 - 2
misago/threads/tests/test_privatethread_reply_api.py

@@ -2,8 +2,8 @@ from django.contrib.auth import get_user_model
 
 
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 
 
-from .. import testutils
-from ..models import ThreadParticipant
+from misago.threads import testutils
+from misago.threads.models import ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
 
 
 
 

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

@@ -12,7 +12,7 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from ..models import Thread, ThreadParticipant
+from misago.threads.models import Thread, ThreadParticipant
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/threads/tests/test_privatethread_view.py

@@ -1,7 +1,7 @@
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 
 
-from .. import testutils
-from ..models import ThreadParticipant
+from misago.threads import testutils
+from misago.threads.models import ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
 
 
 
 

+ 2 - 2
misago/threads/tests/test_privatethreads_api.py

@@ -2,8 +2,8 @@ from django.urls import reverse
 
 
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 
 
-from .. import testutils
-from ..models import Thread, ThreadParticipant
+from misago.threads import testutils
+from misago.threads.models import Thread, ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
 
 
 
 

+ 2 - 2
misago/threads/tests/test_privatethreads_lists.py

@@ -2,8 +2,8 @@ from django.urls import reverse
 
 
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 
 
-from .. import testutils
-from ..models import ThreadParticipant
+from misago.threads import testutils
+from misago.threads.models import ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
 
 
 
 

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

@@ -3,7 +3,7 @@ from django.urls import reverse
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
+from misago.threads import testutils
 
 
 
 
 class SearchApiTests(AuthenticatedUserTestCase):
 class SearchApiTests(AuthenticatedUserTestCase):

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

@@ -8,7 +8,7 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
+from misago.threads import testutils
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/threads/tests/test_subscriptions.py

@@ -8,8 +8,8 @@ from django.utils.six.moves import range
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
 
 
-from .. import testutils
-from ..subscriptions import make_subscription_aware
+from misago.threads import testutils
+from misago.threads.subscriptions import make_subscription_aware
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/threads/tests/test_sync_unread_private_threads.py

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 
 
-from .. import testutils
-from ..models import ThreadParticipant
+from misago.threads import testutils
+from misago.threads.models import ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 from .test_privatethreads import PrivateThreadsTestCase
 
 
 
 

+ 2 - 2
misago/threads/tests/test_synchronizethreads.py

@@ -5,8 +5,8 @@ from django.utils.six.moves import range
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from .. import testutils
-from ..management.commands import synchronizethreads
+from misago.threads import testutils
+from misago.threads.management.commands import synchronizethreads
 
 
 
 
 class SynchronizeThreadsTests(TestCase):
 class SynchronizeThreadsTests(TestCase):

+ 2 - 2
misago/threads/tests/test_thread_editreply_api.py

@@ -11,8 +11,8 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..models import Thread
+from misago.threads import testutils
+from misago.threads.models import Thread
 
 
 
 
 class EditReplyTests(AuthenticatedUserTestCase):
 class EditReplyTests(AuthenticatedUserTestCase):

+ 2 - 2
misago/threads/tests/test_thread_merge_api.py

@@ -6,8 +6,8 @@ from django.utils.encoding import smart_str
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from .. import testutils
-from ..models import Poll, PollVote, Thread
+from misago.threads import testutils
+from misago.threads.models import Poll, PollVote, Thread
 from .test_threads_api import ThreadsApiTestCase
 from .test_threads_api import ThreadsApiTestCase
 
 
 
 

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

@@ -6,7 +6,7 @@ from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from ..models import Poll, Post, Thread, ThreadParticipant
+from misago.threads.models import Poll, Post, Thread, ThreadParticipant
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -6,7 +6,7 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
+from misago.threads import testutils
 
 
 
 
 class ThreadPollApiTestCase(AuthenticatedUserTestCase):
 class ThreadPollApiTestCase(AuthenticatedUserTestCase):

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

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from ..models import Poll, Thread
-from ..serializers.poll import MAX_POLL_OPTIONS
+from misago.threads.models import Poll, Thread
+from misago.threads.serializers.poll import MAX_POLL_OPTIONS
 from .test_thread_poll_api import ThreadPollApiTestCase
 from .test_thread_poll_api import ThreadPollApiTestCase
 
 
 
 

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

@@ -3,7 +3,7 @@ from datetime import timedelta
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
-from ..models import Poll, PollVote, Thread
+from misago.threads.models import Poll, PollVote, Thread
 from .test_thread_poll_api import ThreadPollApiTestCase
 from .test_thread_poll_api import ThreadPollApiTestCase
 
 
 
 

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

@@ -3,7 +3,7 @@ from datetime import timedelta
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
-from ..serializers.poll import MAX_POLL_OPTIONS
+from misago.threads.serializers.poll import MAX_POLL_OPTIONS
 from .test_thread_poll_api import ThreadPollApiTestCase
 from .test_thread_poll_api import ThreadPollApiTestCase
 
 
 
 

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

@@ -4,7 +4,7 @@ from django.contrib.auth import get_user_model
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
-from ..models import Poll
+from misago.threads.models import Poll
 from .test_thread_poll_api import ThreadPollApiTestCase
 from .test_thread_poll_api import ThreadPollApiTestCase
 
 
 
 

+ 2 - 2
misago/threads/tests/test_thread_postdelete_api.py

@@ -3,8 +3,8 @@ from datetime import timedelta
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
-from .. import testutils
-from ..models import Post, Thread
+from misago.threads import testutils
+from misago.threads.models import Post, Thread
 from .test_threads_api import ThreadsApiTestCase
 from .test_threads_api import ThreadsApiTestCase
 
 
 
 

+ 2 - 2
misago/threads/tests/test_thread_postedits_api.py

@@ -9,8 +9,8 @@ from django.urls import reverse
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from .. import testutils
-from ..models import Post
+from misago.threads import testutils
+from misago.threads.models import Post
 from .test_threads_api import ThreadsApiTestCase
 from .test_threads_api import ThreadsApiTestCase
 
 
 
 

+ 2 - 2
misago/threads/tests/test_thread_postlikes_api.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from .. import testutils
-from ..serializers import PostLikeSerializer
+from misago.threads import testutils
+from misago.threads.serializers import PostLikeSerializer
 from .test_threads_api import ThreadsApiTestCase
 from .test_threads_api import ThreadsApiTestCase
 
 
 
 

+ 3 - 3
misago/threads/tests/test_thread_postmerge_api.py

@@ -13,9 +13,9 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..api.postendpoints.merge import MERGE_LIMIT
-from ..models import Post, Thread
+from misago.threads import testutils
+from misago.threads.api.postendpoints.merge import MERGE_LIMIT
+from misago.threads.models import Post, Thread
 
 
 
 
 class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):
 class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):

+ 3 - 3
misago/threads/tests/test_thread_postmove_api.py

@@ -10,9 +10,9 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..api.postendpoints.move import MOVE_LIMIT
-from ..models import Thread
+from misago.threads import testutils
+from misago.threads.api.postendpoints.move import MOVE_LIMIT
+from misago.threads.models import Thread
 
 
 
 
 class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):
 class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):

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

@@ -11,8 +11,8 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..models import Post, Thread
+from misago.threads import testutils
+from misago.threads.models import Post, Thread
 
 
 
 
 class ThreadPostPatchApiTestCase(AuthenticatedUserTestCase):
 class ThreadPostPatchApiTestCase(AuthenticatedUserTestCase):

+ 2 - 2
misago/threads/tests/test_thread_postread_api.py

@@ -1,8 +1,8 @@
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
 
 
-from .. import testutils
-from ..models import Post, Thread
+from misago.threads import testutils
+from misago.threads.models import Post, Thread
 from .test_threads_api import ThreadsApiTestCase
 from .test_threads_api import ThreadsApiTestCase
 
 
 
 

+ 3 - 3
misago/threads/tests/test_thread_postsplit_api.py

@@ -11,9 +11,9 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..api.postendpoints.split import SPLIT_LIMIT
-from ..models import Thread
+from misago.threads import testutils
+from misago.threads.api.postendpoints.split import SPLIT_LIMIT
+from misago.threads.models import Thread
 
 
 
 
 class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):
 class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):

+ 2 - 2
misago/threads/tests/test_thread_reply_api.py

@@ -10,8 +10,8 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..models import Thread
+from misago.threads import testutils
+from misago.threads.models import Thread
 
 
 
 
 class ReplyThreadTests(AuthenticatedUserTestCase):
 class ReplyThreadTests(AuthenticatedUserTestCase):

+ 2 - 2
misago/threads/tests/test_thread_start_api.py

@@ -8,8 +8,8 @@ from misago.categories import THREADS_ROOT_NAME
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from ..models import Thread
-from ..threadtypes import trees_map
+from misago.threads.models import Thread
+from misago.threads.threadtypes import trees_map
 
 
 
 
 class StartThreadTests(AuthenticatedUserTestCase):
 class StartThreadTests(AuthenticatedUserTestCase):

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

@@ -4,7 +4,7 @@ from django.utils import timezone
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from ..models import Post, Thread, ThreadParticipant
+from misago.threads.models import Post, Thread, ThreadParticipant
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 3 - 3
misago/threads/tests/test_threads_api.py

@@ -5,9 +5,9 @@ from misago.categories import THREADS_ROOT_NAME
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..models import Thread
-from ..threadtypes import trees_map
+from misago.threads import testutils
+from misago.threads.models import Thread
+from misago.threads.threadtypes import trees_map
 
 
 
 
 class ThreadsApiTestCase(AuthenticatedUserTestCase):
 class ThreadsApiTestCase(AuthenticatedUserTestCase):

+ 3 - 3
misago/threads/tests/test_threads_editor_api.py

@@ -9,9 +9,9 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..models import Attachment
-from ..serializers import AttachmentSerializer
+from misago.threads import testutils
+from misago.threads.models import Attachment
+from misago.threads.serializers import AttachmentSerializer
 
 
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')

+ 4 - 4
misago/threads/tests/test_threads_merge_api.py

@@ -7,10 +7,10 @@ from misago.acl import add_acl
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from .. import testutils
-from ..api.threadendpoints.merge import MERGE_LIMIT
-from ..models import Poll, PollVote, Post, Thread
-from ..serializers import ThreadsListSerializer
+from misago.threads import testutils
+from misago.threads.api.threadendpoints.merge import MERGE_LIMIT
+from misago.threads.models import Poll, PollVote, Post, Thread
+from misago.threads.serializers import ThreadsListSerializer
 from .test_threads_api import ThreadsApiTestCase
 from .test_threads_api import ThreadsApiTestCase
 
 
 
 

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

@@ -1,8 +1,8 @@
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import moderation, testutils
-from ..models import Post, Thread
+from misago.threads import moderation, testutils
+from misago.threads.models import Post, Thread
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

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

@@ -15,7 +15,7 @@ from misago.readtracker import categoriestracker, threadstracker
 from misago.users.models import AnonymousUser
 from misago.users.models import AnonymousUser
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
+from misago.threads import testutils
 
 
 
 
 LISTS_URLS = (
 LISTS_URLS = (

+ 5 - 5
misago/threads/tests/test_threadview.py

@@ -3,11 +3,11 @@ from misago.categories.models import Category
 from misago.conf import settings
 from misago.conf import settings
 from misago.users.testutils import AuthenticatedUserTestCase
 from misago.users.testutils import AuthenticatedUserTestCase
 
 
-from .. import testutils
-from ..events import record_event
-from ..models import Post, Thread
-from ..moderation import threads as threads_moderation
-from ..moderation.posts import hide_post
+from misago.threads import testutils
+from misago.threads.events import record_event
+from misago.threads.models import Post, Thread
+from misago.threads.moderation import threads as threads_moderation
+from misago.threads.moderation.posts import hide_post
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

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

@@ -3,7 +3,7 @@ from django.utils import six
 
 
 from misago.categories.models import Category
 from misago.categories.models import Category
 
 
-from ..threadtypes.treesmap import TreesMap
+from misago.threads.threadtypes.treesmap import TreesMap
 
 
 
 
 THREAD_TYPE = 'misago.threads.threadtypes.thread.Thread'
 THREAD_TYPE = 'misago.threads.threadtypes.thread.Thread'

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

@@ -1,8 +1,8 @@
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.core.testutils import MisagoTestCase
 from misago.core.testutils import MisagoTestCase
 
 
-from .. import testutils
-from ..utils import add_categories_to_items, get_thread_id_from_url
+from misago.threads import testutils
+from misago.threads.utils import add_categories_to_items, get_thread_id_from_url
 
 
 
 
 class AddCategoriesToItemsTests(MisagoTestCase):
 class AddCategoriesToItemsTests(MisagoTestCase):

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

@@ -3,7 +3,7 @@ from django.test import TestCase
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..validators import validate_post, validate_title
+from misago.threads.validators import validate_post, validate_title
 
 
 
 
 class ValidatePostTests(TestCase):
 class ValidatePostTests(TestCase):

+ 4 - 4
misago/threads/urls/__init__.py

@@ -2,12 +2,12 @@ from django.conf.urls import url
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..views.attachment import attachment_server
-from ..views.goto import (
+from misago.threads.views.attachment import attachment_server
+from misago.threads.views.goto import (
     ThreadGotoPostView, ThreadGotoLastView, ThreadGotoNewView, ThreadGotoUnapprovedView,
     ThreadGotoPostView, ThreadGotoLastView, ThreadGotoNewView, ThreadGotoUnapprovedView,
     PrivateThreadGotoPostView, PrivateThreadGotoLastView, PrivateThreadGotoNewView)
     PrivateThreadGotoPostView, PrivateThreadGotoLastView, PrivateThreadGotoNewView)
-from ..views.list import ForumThreads, CategoryThreads, PrivateThreads
-from ..views.thread import Thread, PrivateThread
+from misago.threads.views.list import ForumThreads, CategoryThreads, PrivateThreads
+from misago.threads.views.thread import Thread, PrivateThread
 
 
 
 
 LISTS_TYPES = (
 LISTS_TYPES = (

+ 4 - 4
misago/threads/urls/api.py

@@ -1,9 +1,9 @@
 from misago.core.apirouter import MisagoApiRouter
 from misago.core.apirouter import MisagoApiRouter
 
 
-from ..api.attachments import AttachmentViewSet
-from ..api.threadpoll import ThreadPollViewSet
-from ..api.threadposts import PrivateThreadPostsViewSet, ThreadPostsViewSet
-from ..api.threads import PrivateThreadViewSet, ThreadViewSet
+from misago.threads.api.attachments import AttachmentViewSet
+from misago.threads.api.threadpoll import ThreadPollViewSet
+from misago.threads.api.threadposts import PrivateThreadPostsViewSet, ThreadPostsViewSet
+from misago.threads.api.threads import PrivateThreadViewSet, ThreadViewSet
 
 
 
 
 router = MisagoApiRouter()
 router = MisagoApiRouter()

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

@@ -7,7 +7,7 @@ from misago.categories.serializers import BasicCategorySerializer
 from misago.core.shortcuts import validate_slug
 from misago.core.shortcuts import validate_slug
 from misago.core.viewmodel import ViewModel as BaseViewModel
 from misago.core.viewmodel import ViewModel as BaseViewModel
 
 
-from ..permissions import allow_use_private_threads
+from misago.threads.permissions import allow_use_private_threads
 
 
 
 
 __all__ = ['ThreadsRootCategory', 'ThreadsCategory', 'PrivateThreadsCategory']
 __all__ = ['ThreadsRootCategory', 'ThreadsCategory', 'PrivateThreadsCategory']

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

@@ -3,7 +3,7 @@ from django.shortcuts import get_object_or_404
 from misago.acl import add_acl
 from misago.acl import add_acl
 from misago.core.viewmodel import ViewModel as BaseViewModel
 from misago.core.viewmodel import ViewModel as BaseViewModel
 
 
-from ..permissions.threads import exclude_invisible_posts
+from misago.threads.permissions.threads import exclude_invisible_posts
 
 
 
 
 __all__ = ['ThreadPost']
 __all__ = ['ThreadPost']

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

@@ -4,10 +4,10 @@ from misago.core.shortcuts import paginate, pagination_dict
 from misago.readtracker.threadstracker import make_posts_read_aware
 from misago.readtracker.threadstracker import make_posts_read_aware
 from misago.users.online.utils import make_users_status_aware
 from misago.users.online.utils import make_users_status_aware
 
 
-from ..paginator import PostsPaginator
-from ..permissions.threads import exclude_invisible_posts
-from ..serializers import PostSerializer
-from ..utils import add_likes_to_posts
+from misago.threads.paginator import PostsPaginator
+from misago.threads.permissions.threads import exclude_invisible_posts
+from misago.threads.serializers import PostSerializer
+from misago.threads.utils import add_likes_to_posts
 
 
 
 
 __all__ = ['ThreadPosts']
 __all__ = ['ThreadPosts']

+ 7 - 7
misago/threads/viewmodels/thread.py

@@ -8,13 +8,13 @@ from misago.core.shortcuts import validate_slug
 from misago.core.viewmodel import ViewModel as BaseViewModel
 from misago.core.viewmodel import ViewModel as BaseViewModel
 from misago.readtracker.threadstracker import make_read_aware
 from misago.readtracker.threadstracker import make_read_aware
 
 
-from ..models import Poll, Thread
-from ..participants import make_participants_aware
-from ..permissions.privatethreads import allow_use_private_threads, allow_see_private_thread
-from ..permissions.threads import allow_see_thread
-from ..serializers import PrivateThreadSerializer, ThreadSerializer
-from ..subscriptions import make_subscription_aware
-from ..threadtypes import trees_map
+from misago.threads.models import Poll, Thread
+from misago.threads.participants import make_participants_aware
+from misago.threads.permissions.privatethreads import allow_use_private_threads, allow_see_private_thread
+from misago.threads.permissions.threads import allow_see_thread
+from misago.threads.serializers import PrivateThreadSerializer, ThreadSerializer
+from misago.threads.subscriptions import make_subscription_aware
+from misago.threads.threadtypes import trees_map
 
 
 
 
 __all__ = ['ForumThread', 'PrivateThread']
 __all__ = ['ForumThread', 'PrivateThread']

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

@@ -12,12 +12,12 @@ from misago.conf import settings
 from misago.core.shortcuts import paginate, pagination_dict
 from misago.core.shortcuts import paginate, pagination_dict
 from misago.readtracker import threadstracker
 from misago.readtracker import threadstracker
 
 
-from ..models import Thread
-from ..participants import make_participants_aware
-from ..permissions import exclude_invisible_threads
-from ..serializers import ThreadsListSerializer
-from ..subscriptions import make_subscription_aware
-from ..utils import add_categories_to_items
+from misago.threads.models import Thread
+from misago.threads.participants import make_participants_aware
+from misago.threads.permissions import exclude_invisible_threads
+from misago.threads.serializers import ThreadsListSerializer
+from misago.threads.subscriptions import make_subscription_aware
+from misago.threads.utils import add_categories_to_items
 
 
 
 
 __all__ = ['ForumThreads', 'PrivateThreads', 'filter_read_threads_queryset']
 __all__ = ['ForumThreads', 'PrivateThreads', 'filter_read_threads_queryset']

+ 2 - 2
misago/threads/views/admin/attachments.py

@@ -7,8 +7,8 @@ from django.utils.translation import ugettext_lazy as _
 
 
 from misago.admin.views import generic
 from misago.admin.views import generic
 
 
-from ...forms import SearchAttachmentsForm
-from ...models import Attachment, Post
+from misago.threads.forms import SearchAttachmentsForm
+from misago.threads.models import Attachment, Post
 
 
 
 
 class AttachmentAdmin(generic.AdminBaseMixin):
 class AttachmentAdmin(generic.AdminBaseMixin):

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

@@ -6,8 +6,8 @@ from django.utils.translation import ugettext_lazy as _
 
 
 from misago.admin.views import generic
 from misago.admin.views import generic
 
 
-from ...forms import AttachmentTypeForm
-from ...models import AttachmentType
+from misago.threads.forms import AttachmentTypeForm
+from misago.threads.models import AttachmentType
 
 
 
 
 class AttachmentTypeAdmin(generic.AdminBaseMixin):
 class AttachmentTypeAdmin(generic.AdminBaseMixin):

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

@@ -9,7 +9,7 @@ from django.shortcuts import get_object_or_404, redirect
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..models import Attachment, AttachmentType
+from misago.threads.models import Attachment, AttachmentType
 
 
 
 
 ATTACHMENT_404_URL = ''.join((settings.STATIC_URL, settings.MISAGO_404_IMAGE))
 ATTACHMENT_404_URL = ''.join((settings.STATIC_URL, settings.MISAGO_404_IMAGE))

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

@@ -7,8 +7,8 @@ from django.views.generic import View
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..permissions.threads import exclude_invisible_posts
-from ..viewmodels import ForumThread, PrivateThread
+from misago.threads.permissions.threads import exclude_invisible_posts
+from misago.threads.viewmodels import ForumThread, PrivateThread
 
 
 
 
 class GotoView(View):
 class GotoView(View):

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

@@ -6,7 +6,7 @@ from django.views.generic import View
 
 
 from misago.core.shortcuts import get_int_or_404
 from misago.core.shortcuts import get_int_or_404
 
 
-from ..viewmodels import ForumThreads, PrivateThreads, PrivateThreadsCategory, ThreadsCategory, ThreadsRootCategory
+from misago.threads.viewmodels import ForumThreads, PrivateThreads, PrivateThreadsCategory, ThreadsCategory, ThreadsRootCategory
 
 
 
 
 class ListBase(View):
 class ListBase(View):

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

@@ -2,7 +2,7 @@ from django.shortcuts import render
 from django.urls import reverse
 from django.urls import reverse
 from django.views.generic import View
 from django.views.generic import View
 
 
-from ..viewmodels import ForumThread, PrivateThread, ThreadPosts
+from misago.threads.viewmodels import ForumThread, PrivateThread, ThreadPosts
 
 
 
 
 class ThreadBase(View):
 class ThreadBase(View):

+ 4 - 4
misago/users/api/auth.py

@@ -11,10 +11,10 @@ from rest_framework.response import Response
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.mail import mail_user
 from misago.core.mail import mail_user
 
 
-from ..bans import get_user_ban
-from ..forms.auth import AuthenticationForm, ResendActivationForm, ResetPasswordForm
-from ..serializers import AnonymousUserSerializer, AuthenticatedUserSerializer
-from ..tokens import is_password_change_token_valid, make_activation_token, make_password_change_token
+from misago.users.bans import get_user_ban
+from misago.users.forms.auth import AuthenticationForm, ResendActivationForm, ResetPasswordForm
+from misago.users.serializers import AnonymousUserSerializer, AuthenticatedUserSerializer
+from misago.users.tokens import is_password_change_token_valid, make_activation_token, make_password_change_token
 from .rest_permissions import UnbannedAnonOnly, UnbannedOnly
 from .rest_permissions import UnbannedAnonOnly, UnbannedOnly
 
 
 
 

+ 2 - 2
misago/users/api/ranks.py

@@ -1,7 +1,7 @@
 from rest_framework import mixins, viewsets
 from rest_framework import mixins, viewsets
 
 
-from ..models import Rank
-from ..serializers import RankSerializer
+from misago.users.models import Rank
+from misago.users.serializers import RankSerializer
 
 
 
 
 class RanksViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
 class RanksViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):

+ 2 - 2
misago/users/api/rest_permissions.py

@@ -5,8 +5,8 @@ from rest_framework.permissions import BasePermission
 
 
 from misago.core.exceptions import Banned
 from misago.core.exceptions import Banned
 
 
-from ..bans import get_request_ip_ban
-from ..models import Ban
+from misago.users.bans import get_request_ip_ban
+from misago.users.models import Ban
 
 
 
 
 __all__ = [
 __all__ = [

+ 3 - 3
misago/users/api/userendpoints/avatar.py

@@ -9,9 +9,9 @@ from rest_framework.response import Response
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.utils import format_plaintext_for_html
 from misago.core.utils import format_plaintext_for_html
 
 
-from ... import avatars
-from ...forms.moderation import ModerateAvatarForm
-from ...models import AvatarGallery
+from misago.users import avatars
+from misago.users.forms.moderation import ModerateAvatarForm
+from misago.users.models import AvatarGallery
 
 
 
 
 def avatar_endpoint(request, pk=None):
 def avatar_endpoint(request, pk=None):

+ 2 - 2
misago/users/api/userendpoints/changeemail.py

@@ -6,8 +6,8 @@ from rest_framework.response import Response
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.mail import mail_user
 from misago.core.mail import mail_user
 
 
-from ...credentialchange import store_new_credential
-from ...forms.options import ChangeEmailForm
+from misago.users.credentialchange import store_new_credential
+from misago.users.forms.options import ChangeEmailForm
 
 
 
 
 def change_email_endpoint(request, pk=None):
 def change_email_endpoint(request, pk=None):

+ 2 - 2
misago/users/api/userendpoints/changepassword.py

@@ -6,8 +6,8 @@ from rest_framework.response import Response
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.mail import mail_user
 from misago.core.mail import mail_user
 
 
-from ...credentialchange import store_new_credential
-from ...forms.options import ChangePasswordForm
+from misago.users.credentialchange import store_new_credential
+from misago.users.forms.options import ChangePasswordForm
 
 
 
 
 def change_password_endpoint(request, pk=None):
 def change_password_endpoint(request, pk=None):

+ 4 - 4
misago/users/api/userendpoints/create.py

@@ -9,10 +9,10 @@ from rest_framework.response import Response
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.mail import mail_user
 from misago.core.mail import mail_user
 
 
-from ... import captcha
-from ...forms.register import RegisterForm
-from ...serializers import AuthenticatedUserSerializer
-from ...tokens import make_activation_token
+from misago.users import captcha
+from misago.users.forms.register import RegisterForm
+from misago.users.serializers import AuthenticatedUserSerializer
+from misago.users.tokens import make_activation_token
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 4 - 4
misago/users/api/userendpoints/list.py

@@ -12,10 +12,10 @@ from misago.core.cache import cache
 from misago.core.shortcuts import (
 from misago.core.shortcuts import (
     get_int_or_404, get_object_or_404, paginate, paginated_response)
     get_int_or_404, get_object_or_404, paginate, paginated_response)
 
 
-from ...activepostersranking import get_active_posters_ranking
-from ...models import Rank
-from ...online.utils import make_users_status_aware
-from ...serializers import ScoredUserSerializer, UserSerializer
+from misago.users.activepostersranking import get_active_posters_ranking
+from misago.users.models import Rank
+from misago.users.online.utils import make_users_status_aware
+from misago.users.serializers import ScoredUserSerializer, UserSerializer
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/users/api/userendpoints/signature.py

@@ -7,8 +7,8 @@ from rest_framework.response import Response
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.utils import format_plaintext_for_html
 from misago.core.utils import format_plaintext_for_html
 
 
-from ...forms.options import EditSignatureForm
-from ...signatures import is_user_signature_valid, set_user_signature
+from misago.users.forms.options import EditSignatureForm
+from misago.users.signatures import is_user_signature_valid, set_user_signature
 
 
 
 
 def signature_endpoint(request):
 def signature_endpoint(request):

+ 2 - 2
misago/users/api/userendpoints/username.py

@@ -6,8 +6,8 @@ from rest_framework.response import Response
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ...forms.rename import ChangeUsernameForm
-from ...namechanges import UsernameChanges
+from misago.users.forms.rename import ChangeUsernameForm
+from misago.users.namechanges import UsernameChanges
 
 
 
 
 def username_endpoint(request):
 def username_endpoint(request):

+ 2 - 2
misago/users/api/usernamechanges.py

@@ -9,8 +9,8 @@ from rest_framework.response import Response
 from misago.core.shortcuts import (
 from misago.core.shortcuts import (
     get_int_or_404, get_object_or_404, paginate, pagination_dict)
     get_int_or_404, get_object_or_404, paginate, pagination_dict)
 
 
-from ..models import UsernameChange
-from ..serializers.usernamechange import UsernameChangeSerializer
+from misago.users.models import UsernameChange
+from misago.users.serializers.usernamechange import UsernameChangeSerializer
 from .rest_permissions import BasePermission
 from .rest_permissions import BasePermission
 
 
 
 

+ 8 - 8
misago/users/api/users.py

@@ -19,14 +19,14 @@ from misago.core.shortcuts import get_int_or_404, get_object_or_404
 from misago.threads.moderation.posts import hide_post
 from misago.threads.moderation.posts import hide_post
 from misago.threads.moderation.threads import hide_thread
 from misago.threads.moderation.threads import hide_thread
 
 
-from ..bans import get_user_ban
-from ..forms.options import ForumOptionsForm
-from ..online.utils import get_user_status
-from ..permissions.delete import allow_delete_user
-from ..permissions.moderation import allow_moderate_avatar, allow_rename_user
-from ..permissions.profiles import allow_browse_users_list, allow_follow_user, allow_see_ban_details
-from ..serializers import BanDetailsSerializer, UserProfileSerializer, UserSerializer
-from ..viewmodels import UserPosts, UserThreads
+from misago.users.bans import get_user_ban
+from misago.users.forms.options import ForumOptionsForm
+from misago.users.online.utils import get_user_status
+from misago.users.permissions.delete import allow_delete_user
+from misago.users.permissions.moderation import allow_moderate_avatar, allow_rename_user
+from misago.users.permissions.profiles import allow_browse_users_list, allow_follow_user, allow_see_ban_details
+from misago.users.serializers import BanDetailsSerializer, UserProfileSerializer, UserSerializer
+from misago.users.viewmodels import UserPosts, UserThreads
 from .rest_permissions import BasePermission, UnbannedAnonOnly
 from .rest_permissions import BasePermission, UnbannedAnonOnly
 from .userendpoints.avatar import avatar_endpoint, moderate_avatar_endpoint
 from .userendpoints.avatar import avatar_endpoint, moderate_avatar_endpoint
 from .userendpoints.changeemail import change_email_endpoint
 from .userendpoints.changeemail import change_email_endpoint

+ 3 - 3
misago/users/avatars/gallery.py

@@ -20,7 +20,7 @@ def get_available_galleries(include_default=False):
     Only jpgs, gifs and pngs are supported avatar images.
     Only jpgs, gifs and pngs are supported avatar images.
     Galleries are
     Galleries are
     """
     """
-    from ..models import AvatarGallery
+    from misago.users.models import AvatarGallery
 
 
     galleries = []
     galleries = []
     galleries_dicts = {}
     galleries_dicts = {}
@@ -43,12 +43,12 @@ def get_available_galleries(include_default=False):
 
 
 
 
 def galleries_exist():
 def galleries_exist():
-    from ..models import AvatarGallery
+    from misago.users.models import AvatarGallery
     return AvatarGallery.objects.exists()
     return AvatarGallery.objects.exists()
 
 
 
 
 def load_avatar_galleries():
 def load_avatar_galleries():
-    from ..models import AvatarGallery
+    from misago.users.models import AvatarGallery
 
 
     galleries = []
     galleries = []
     for directory in Path(settings.MISAGO_AVATAR_GALLERY).dirs():
     for directory in Path(settings.MISAGO_AVATAR_GALLERY).dirs():

+ 1 - 1
misago/users/avatars/store.py

@@ -29,7 +29,7 @@ def delete_avatar(user):
 
 
 
 
 def store_avatar(user, image):
 def store_avatar(user, image):
-    from ..models import Avatar
+    from misago.users.models import Avatar
     image = normalize_image(image)
     image = normalize_image(image)
 
 
     avatars = []
     avatars = []

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

@@ -10,8 +10,8 @@ from misago.core import threadstore
 from misago.core.forms import IsoDateTimeField, YesNoSwitch
 from misago.core.forms import IsoDateTimeField, YesNoSwitch
 from misago.core.validators import validate_sluggable
 from misago.core.validators import validate_sluggable
 
 
-from ..models import Ban, Rank
-from ..validators import validate_email, validate_username
+from misago.users.models import Ban, Rank
+from misago.users.validators import validate_email, validate_username
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -5,7 +5,7 @@ from django.core.exceptions import ValidationError
 from django.core.validators import validate_email
 from django.core.validators import validate_email
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
-from ..bans import get_user_ban
+from misago.users.bans import get_user_ban
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -9,7 +9,7 @@ from django.utils.translation import ungettext
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.forms import YesNoSwitch
 from misago.core.forms import YesNoSwitch
 
 
-from ..bans import ban_user
+from misago.users.bans import ban_user
 
 
 
 
 class ModerateAvatarForm(forms.ModelForm):
 class ModerateAvatarForm(forms.ModelForm):

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

@@ -7,7 +7,7 @@ from django.utils.translation import ungettext
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.forms import YesNoSwitch
 from misago.core.forms import YesNoSwitch
 
 
-from ..validators import validate_email
+from misago.users.validators import validate_email
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -2,7 +2,7 @@ from django import forms
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.contrib.auth.password_validation import validate_password
 from django.contrib.auth.password_validation import validate_password
 
 
-from .. import validators
+from misago.users import validators
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -1,7 +1,7 @@
 from django import forms
 from django import forms
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
-from ..validators import validate_username
+from misago.users.validators import validate_username
 
 
 
 
 class ChangeUsernameForm(forms.Form):
 class ChangeUsernameForm(forms.Form):

+ 1 - 1
misago/users/management/commands/buildactivepostersranking.py

@@ -2,7 +2,7 @@ from django.core.management.base import BaseCommand
 
 
 from misago.core.management.progressbar import show_progress
 from misago.core.management.progressbar import show_progress
 
 
-from ...activepostersranking import build_active_posters_ranking
+from misago.users.activepostersranking import build_active_posters_ranking
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 1 - 1
misago/users/management/commands/createsuperuser.py

@@ -13,7 +13,7 @@ from django.db import DEFAULT_DB_ALIAS, IntegrityError
 from django.utils.encoding import force_str
 from django.utils.encoding import force_str
 from django.utils.six.moves import input
 from django.utils.six.moves import input
 
 
-from ...validators import validate_email, validate_username
+from misago.users.validators import validate_email, validate_username
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 1 - 1
misago/users/management/commands/invalidatebans.py

@@ -3,7 +3,7 @@ from django.utils import timezone
 
 
 from misago.core import cachebuster
 from misago.core import cachebuster
 
 
-from ...models import Ban, BanCache
+from misago.users.models import Ban, BanCache
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 2 - 2
misago/users/management/commands/loadavatargallery.py

@@ -2,8 +2,8 @@ from django.core.management.base import BaseCommand
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ...avatars.gallery import load_avatar_galleries
-from ...models import AvatarGallery
+from misago.users.avatars.gallery import load_avatar_galleries
+from misago.users.models import AvatarGallery
 
 
 
 
 class Command(BaseCommand):
 class Command(BaseCommand):

+ 1 - 1
misago/users/management/commands/populateonlinetracker.py

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 from django.core.management.base import BaseCommand
 
 
-from ...models import Online
+from misago.users.models import Online
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 1 - 1
misago/users/models/avatar.py

@@ -1,7 +1,7 @@
 from django.conf import settings
 from django.conf import settings
 from django.db import models
 from django.db import models
 
 
-from ..avatars import store
+from misago.users.avatars import store
 
 
 
 
 class Avatar(models.Model):
 class Avatar(models.Model):

+ 1 - 1
misago/users/models/avatargallery.py

@@ -1,6 +1,6 @@
 from django.db import models
 from django.db import models
 
 
-from ..avatars import store
+from misago.users.avatars import store
 
 
 
 
 class AvatarGallery(models.Model):
 class AvatarGallery(models.Model):

+ 2 - 2
misago/users/models/ban.py

@@ -83,7 +83,7 @@ class Ban(models.Model):
         return super(Ban, self).save(*args, **kwargs)
         return super(Ban, self).save(*args, **kwargs)
 
 
     def get_serialized_message(self):
     def get_serialized_message(self):
-        from ..serializers import BanMessageSerializer
+        from misago.users.serializers import BanMessageSerializer
         return BanMessageSerializer(self).data
         return BanMessageSerializer(self).data
 
 
     @property
     @property
@@ -127,7 +127,7 @@ class BanCache(models.Model):
             pass # first come is first serve with ban cache
             pass # first come is first serve with ban cache
 
 
     def get_serialized_message(self):
     def get_serialized_message(self):
-        from ..serializers import BanMessageSerializer
+        from misago.users.serializers import BanMessageSerializer
         temp_ban = Ban(
         temp_ban = Ban(
             id=1,
             id=1,
             check_type=Ban.USERNAME,
             check_type=Ban.USERNAME,

+ 6 - 6
misago/users/models/user.py

@@ -17,9 +17,9 @@ from misago.acl.models import Role
 from misago.conf import settings
 from misago.conf import settings
 from misago.core.utils import slugify
 from misago.core.utils import slugify
 
 
-from .. import avatars
-from ..signatures import is_user_signature_valid, make_signature_checksum
-from ..utils import hash_email
+from misago.users import avatars
+from misago.users.signatures import is_user_signature_valid, make_signature_checksum
+from misago.users.utils import hash_email
 from .rank import Rank
 from .rank import Rank
 
 
 
 
@@ -34,7 +34,7 @@ __all__ = [
 class UserManager(BaseUserManager):
 class UserManager(BaseUserManager):
     @transaction.atomic
     @transaction.atomic
     def create_user(self, username, email, password=None, set_default_avatar=False, **extra_fields):
     def create_user(self, username, email, password=None, set_default_avatar=False, **extra_fields):
-        from ..validators import validate_email, validate_username
+        from misago.users.validators import validate_email, validate_username
 
 
         email = self.normalize_email(email)
         email = self.normalize_email(email)
         username = self.model.normalize_username(username)
         username = self.model.normalize_username(username)
@@ -289,7 +289,7 @@ class User(AbstractBaseUser, PermissionsMixin):
         return super(User, self).delete(*args, **kwargs)
         return super(User, self).delete(*args, **kwargs)
 
 
     def delete_content(self):
     def delete_content(self):
-        from ..signals import delete_user_content
+        from misago.users.signals import delete_user_content
         delete_user_content.send(sender=self)
         delete_user_content.send(sender=self)
 
 
     @property
     @property
@@ -369,7 +369,7 @@ class User(AbstractBaseUser, PermissionsMixin):
                 self.record_name_change(
                 self.record_name_change(
                     changed_by, new_username, old_username)
                     changed_by, new_username, old_username)
 
 
-                from ..signals import username_changed
+                from misago.users.signals import username_changed
                 username_changed.send(sender=self)
                 username_changed.send(sender=self)
 
 
     def record_name_change(self, changed_by, new_username, old_username):
     def record_name_change(self, changed_by, new_username, old_username):

+ 1 - 1
misago/users/online/tracker.py

@@ -1,6 +1,6 @@
 from django.utils import timezone
 from django.utils import timezone
 
 
-from ..models import Online
+from misago.users.models import Online
 
 
 
 
 def mute_tracker(request):
 def mute_tracker(request):

+ 2 - 2
misago/users/online/utils.py

@@ -2,8 +2,8 @@ from datetime import timedelta
 
 
 from django.utils import timezone
 from django.utils import timezone
 
 
-from ..bans import get_user_ban
-from ..models import BanCache, Online
+from misago.users.bans import get_user_ban
+from misago.users.models import BanCache, Online
 
 
 
 
 ACTIVITY_CUTOFF = timedelta(minutes=2)
 ACTIVITY_CUTOFF = timedelta(minutes=2)

+ 1 - 1
misago/users/permissions/moderation.py

@@ -12,7 +12,7 @@ from misago.acl.decorators import return_boolean
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.core.forms import YesNoSwitch
 from misago.core.forms import YesNoSwitch
 
 
-from ..bans import get_user_ban
+from misago.users.bans import get_user_ban
 
 
 
 
 """
 """

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

@@ -4,7 +4,7 @@ from rest_framework import serializers
 
 
 from misago.core.utils import format_plaintext_for_html
 from misago.core.utils import format_plaintext_for_html
 
 
-from ..models import Ban
+from misago.users.models import Ban
 
 
 
 
 __all__ = [
 __all__ = [

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

@@ -2,7 +2,7 @@ from rest_framework import serializers
 
 
 from misago.core.utils import format_plaintext_for_html
 from misago.core.utils import format_plaintext_for_html
 
 
-from ..models import Rank
+from misago.users.models import Rank
 
 
 
 
 __all__ = ['RankSerializer']
 __all__ = ['RankSerializer']

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

@@ -1,6 +1,6 @@
 from rest_framework import serializers
 from rest_framework import serializers
 
 
-from ..models import UsernameChange
+from misago.users.models import UsernameChange
 from .user import BasicUserSerializer
 from .user import BasicUserSerializer
 
 
 
 

+ 2 - 2
misago/users/tests/test_activation_views.py

@@ -4,8 +4,8 @@ from django.urls import reverse
 
 
 from misago.core.utils import encode_json_html
 from misago.core.utils import encode_json_html
 
 
-from ..models import Ban
-from ..tokens import make_activation_token
+from misago.users.models import Ban
+from misago.users.tokens import make_activation_token
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/users/tests/test_activepostersranking.py

@@ -5,8 +5,8 @@ from misago.core import threadstore
 from misago.core.cache import cache
 from misago.core.cache import cache
 from misago.threads.testutils import post_thread
 from misago.threads.testutils import post_thread
 
 
-from ..activepostersranking import build_active_posters_ranking, get_active_posters_ranking
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.activepostersranking import build_active_posters_ranking, get_active_posters_ranking
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/users/tests/test_auth_api.py

@@ -2,8 +2,8 @@ from django.contrib.auth import get_user_model
 from django.core import mail
 from django.core import mail
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..models import Ban
-from ..tokens import make_password_change_token
+from misago.users.models import Ban
+from misago.users.tokens import make_password_change_token
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..authbackends import MisagoBackend
+from misago.users.authbackends import MisagoBackend
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -8,9 +8,9 @@ from django.utils.crypto import get_random_string
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..avatars import (
+from misago.users.avatars import (
     set_default_avatar, dynamic, gallery, gravatar, store, uploaded)
     set_default_avatar, dynamic, gallery, gravatar, store, uploaded)
-from ..models import Avatar, AvatarGallery
+from misago.users.models import Avatar, AvatarGallery
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -1,7 +1,7 @@
 #-*- coding: utf-8 -*-
 #-*- coding: utf-8 -*-
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..models import Ban
+from misago.users.models import Ban
 
 
 
 
 class BansManagerTests(TestCase):
 class BansManagerTests(TestCase):

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

@@ -5,7 +5,7 @@ from django.utils.six.moves import range
 
 
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
 
 
-from ..models import Ban
+from misago.users.models import Ban
 
 
 
 
 class BanAdminViewsTests(AdminTestCase):
 class BanAdminViewsTests(AdminTestCase):

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

@@ -4,10 +4,10 @@ from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.test import TestCase
 from django.utils import timezone
 from django.utils import timezone
 
 
-from ..bans import (
+from misago.users.bans import (
     ban_ip, ban_user, get_email_ban, get_ip_ban,
     ban_ip, ban_user, get_email_ban, get_ip_ban,
     get_request_ip_ban, get_user_ban, get_username_ban)
     get_request_ip_ban, get_user_ban, get_username_ban)
-from ..models import Ban
+from misago.users.models import Ban
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.test import TestCase
 
 
-from .. import credentialchange
+from misago.users import credentialchange
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/users/tests/test_decorators.py

@@ -2,8 +2,8 @@ from django.urls import reverse
 
 
 from misago.core.utils import encode_json_html
 from misago.core.utils import encode_json_html
 
 
-from ..models import Ban
-from ..testutils import UserTestCase
+from misago.users.models import Ban
+from misago.users.testutils import UserTestCase
 
 
 
 
 class DenyAuthenticatedTests(UserTestCase):
 class DenyAuthenticatedTests(UserTestCase):

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

@@ -3,9 +3,9 @@ from django.urls import reverse
 
 
 from misago.core.utils import encode_json_html
 from misago.core.utils import encode_json_html
 
 
-from ..models import Ban
-from ..testutils import UserTestCase
-from ..tokens import make_password_change_token
+from misago.users.models import Ban
+from misago.users.testutils import UserTestCase
+from misago.users.tokens import make_password_change_token
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -7,9 +7,9 @@ from django.utils import timezone
 from django.utils.six import StringIO
 from django.utils.six import StringIO
 from django.utils.six.moves import range
 from django.utils.six.moves import range
 
 
-from .. import bans
-from ..management.commands import invalidatebans
-from ..models import Ban, BanCache
+from misago.users import bans
+from misago.users.management.commands import invalidatebans
+from misago.users.models import Ban, BanCache
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -6,9 +6,9 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.threads.testutils import post_thread
 from misago.threads.testutils import post_thread
 
 
-from ..activepostersranking import build_active_posters_ranking
-from ..models import Rank
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.activepostersranking import build_active_posters_ranking
+from misago.users.models import Rank
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/users/tests/test_loadavatargallery.py

@@ -2,8 +2,8 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.test import TestCase
 from django.utils.six import StringIO
 from django.utils.six import StringIO
 
 
-from ..management.commands import loadavatargallery
-from ..models import AvatarGallery
+from misago.users.management.commands import loadavatargallery
+from misago.users.models import AvatarGallery
 
 
 
 
 class LoadAvatarGalleryTests(TestCase):
 class LoadAvatarGalleryTests(TestCase):

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

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..namechanges import UsernameChanges
+from misago.users.namechanges import UsernameChanges
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -1,7 +1,7 @@
 from django.core import mail
 from django.core import mail
 from django.urls import reverse
 from django.urls import reverse
 
 
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 class OptionsViewsTests(AuthenticatedUserTestCase):
 class OptionsViewsTests(AuthenticatedUserTestCase):

+ 2 - 2
misago/users/tests/test_populateonlinetracker.py

@@ -3,8 +3,8 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.test import TestCase
 from django.utils.six import StringIO
 from django.utils.six import StringIO
 
 
-from ..management.commands import populateonlinetracker
-from ..models import Online
+from misago.users.management.commands import populateonlinetracker
+from misago.users.models import Online
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -6,8 +6,8 @@ from misago.acl.testutils import override_acl
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.threads import testutils
 from misago.threads import testutils
 
 
-from ..models import Ban
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.models import Ban
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -3,7 +3,7 @@ from django.urls import reverse
 from misago.acl.models import Role
 from misago.acl.models import Role
 from misago.admin.testutils import AdminTestCase
 from misago.admin.testutils import AdminTestCase
 
 
-from ..models import Rank
+from misago.users.models import Rank
 
 
 
 
 class RankAdminViewsTests(AdminTestCase):
 class RankAdminViewsTests(AdminTestCase):

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..middleware import RealIPMiddleware
+from misago.users.middleware import RealIPMiddleware
 
 
 
 
 class MockRequest(object):
 class MockRequest(object):

+ 2 - 2
misago/users/tests/test_rest_permissions.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from ..models import Ban
-from ..testutils import UserTestCase
+from misago.users.models import Ban
+from misago.users.testutils import UserTestCase
 
 
 
 
 class UnbannedOnlyTests(UserTestCase):
 class UnbannedOnlyTests(UserTestCase):

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

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.test import TestCase
 
 
-from .. import signatures
+from misago.users import signatures
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -3,7 +3,7 @@ import json
 from django.urls import reverse
 from django.urls import reverse
 from django.utils.encoding import smart_str
 from django.utils.encoding import smart_str
 
 
-from ..testutils import AuthenticatedUserTestCase, SuperUserTestCase, UserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase, SuperUserTestCase, UserTestCase
 
 
 
 
 class UserTestCaseTests(UserTestCase):
 class UserTestCaseTests(UserTestCase):

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

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.test import TestCase
 
 
-from .. import tokens
+from misago.users import tokens
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -10,9 +10,9 @@ from django.utils.encoding import smart_str
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..avatars import gallery, store
-from ..models import AvatarGallery
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.avatars import gallery, store
+from misago.users.models import AvatarGallery
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testfiles')

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

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core import mail
 from django.core import mail
 
 
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core import mail
 from django.core import mail
 
 
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 class UserChangePasswordTests(AuthenticatedUserTestCase):
 class UserChangePasswordTests(AuthenticatedUserTestCase):

+ 2 - 2
misago/users/tests/test_user_create_api.py

@@ -4,8 +4,8 @@ from django.urls import reverse
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..models import Online
-from ..testutils import UserTestCase
+from misago.users.models import Online
+from misago.users.testutils import UserTestCase
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/users/tests/test_user_middleware.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 from django.urls import reverse
 
 
-from ..bans import ban_ip, ban_user
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.bans import ban_ip, ban_user
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 class UserMiddlewareTest(AuthenticatedUserTestCase):
 class UserMiddlewareTest(AuthenticatedUserTestCase):

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

@@ -1,7 +1,7 @@
 from django.core.exceptions import ValidationError
 from django.core.exceptions import ValidationError
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..models import User
+from misago.users.models import User
 
 
 
 
 class UserManagerTests(TestCase):
 class UserManagerTests(TestCase):

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

@@ -6,7 +6,7 @@ from django.utils.encoding import smart_str
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 class UserSignatureTests(AuthenticatedUserTestCase):
 class UserSignatureTests(AuthenticatedUserTestCase):

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

@@ -7,7 +7,7 @@ from django.utils.six.moves import range
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -12,7 +12,7 @@ from misago.admin.testutils import AdminTestCase
 from misago.categories.models import Category
 from misago.categories.models import Category
 from misago.threads.testutils import post_thread, reply_thread
 from misago.threads.testutils import post_thread, reply_thread
 
 
-from ..models import Ban, Rank
+from misago.users.models import Ban, Rank
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -2,7 +2,7 @@ from django.contrib.auth import get_user_model
 
 
 from misago.acl.testutils import override_acl
 from misago.acl.testutils import override_acl
 
 
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 class UsernameChangesApiTests(AuthenticatedUserTestCase):
 class UsernameChangesApiTests(AuthenticatedUserTestCase):

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

@@ -13,9 +13,9 @@ from misago.core.cache import cache
 from misago.threads.models import Post, Thread
 from misago.threads.models import Post, Thread
 from misago.threads.testutils import post_thread
 from misago.threads.testutils import post_thread
 
 
-from ..activepostersranking import build_active_posters_ranking
-from ..models import Ban, Rank
-from ..testutils import AuthenticatedUserTestCase
+from misago.users.activepostersranking import build_active_posters_ranking
+from misago.users.models import Ban, Rank
+from misago.users.testutils import AuthenticatedUserTestCase
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 from django.test import TestCase
 
 
-from ..utils import hash_email
+from misago.users.utils import hash_email
 
 
 
 
 class UserModelTests(TestCase):
 class UserModelTests(TestCase):

+ 2 - 2
misago/users/tests/test_validators.py

@@ -5,8 +5,8 @@ from django.test import TestCase
 
 
 from misago.conf import settings
 from misago.conf import settings
 
 
-from ..models import Ban
-from ..validators import (
+from misago.users.models import Ban
+from misago.users.validators import (
     validate_email,
     validate_email,
     validate_email_available,
     validate_email_available,
     validate_email_banned,
     validate_email_banned,

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

@@ -2,7 +2,7 @@ from django.conf.urls import include, url
 
 
 from misago.core.views import home_redirect
 from misago.core.views import home_redirect
 
 
-from ..views import activation, auth, avatarserver, forgottenpassword, lists, options, profile
+from misago.users.views import activation, auth, avatarserver, forgottenpassword, lists, options, profile
 
 
 
 
 urlpatterns = [
 urlpatterns = [

+ 4 - 4
misago/users/urls/api.py

@@ -2,10 +2,10 @@ from django.conf.urls import url
 
 
 from misago.core.apirouter import MisagoApiRouter
 from misago.core.apirouter import MisagoApiRouter
 
 
-from ..api import auth, captcha
-from ..api.ranks import RanksViewSet
-from ..api.usernamechanges import UsernameChangesViewSet
-from ..api.users import UserViewSet
+from misago.users.api import auth, captcha
+from misago.users.api.ranks import RanksViewSet
+from misago.users.api.usernamechanges import UsernameChangesViewSet
+from misago.users.api.users import UserViewSet
 
 
 
 
 urlpatterns = [
 urlpatterns = [

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

@@ -7,9 +7,9 @@ from misago.conf import settings
 from misago.core.exceptions import Banned
 from misago.core.exceptions import Banned
 from misago.core.mail import mail_user
 from misago.core.mail import mail_user
 
 
-from ..bans import get_user_ban
-from ..decorators import deny_authenticated, deny_banned_ips
-from ..tokens import is_activation_token_valid
+from misago.users.bans import get_user_ban
+from misago.users.decorators import deny_authenticated, deny_banned_ips
+from misago.users.tokens import is_activation_token_valid
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

+ 2 - 2
misago/users/views/admin/bans.py

@@ -3,8 +3,8 @@ from django.utils.translation import ugettext_lazy as _
 
 
 from misago.admin.views import generic
 from misago.admin.views import generic
 
 
-from ...forms.admin import BanForm, SearchBansForm
-from ...models import Ban
+from misago.users.forms.admin import BanForm, SearchBansForm
+from misago.users.models import Ban
 
 
 
 
 class BanAdmin(generic.AdminBaseMixin):
 class BanAdmin(generic.AdminBaseMixin):

+ 2 - 2
misago/users/views/admin/ranks.py

@@ -5,8 +5,8 @@ from django.utils.translation import ugettext_lazy as _
 
 
 from misago.admin.views import generic
 from misago.admin.views import generic
 
 
-from ...forms.admin import RankForm
-from ...models import Rank
+from misago.users.forms.admin import RankForm
+from misago.users.models import Rank
 
 
 
 
 class RankAdmin(generic.AdminBaseMixin):
 class RankAdmin(generic.AdminBaseMixin):

+ 4 - 4
misago/users/views/admin/users.py

@@ -13,12 +13,12 @@ from misago.core.mail import mail_users
 from misago.core.pgutils import batch_update
 from misago.core.pgutils import batch_update
 from misago.threads.models import Thread
 from misago.threads.models import Thread
 
 
-from ...avatars.dynamic import set_avatar as set_dynamic_avatar
-from ...forms.admin import (
+from misago.users.avatars.dynamic import set_avatar as set_dynamic_avatar
+from misago.users.forms.admin import (
     BanUsersForm, NewUserForm, SearchUsersForm,
     BanUsersForm, NewUserForm, SearchUsersForm,
     EditUserForm, EditUserFormFactory)
     EditUserForm, EditUserFormFactory)
-from ...models import Ban, User
-from ...signatures import set_user_signature
+from misago.users.models import Ban, User
+from misago.users.signatures import set_user_signature
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()

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

@@ -5,9 +5,9 @@ from django.utils.translation import ugettext as _
 
 
 from misago.core.exceptions import Banned
 from misago.core.exceptions import Banned
 
 
-from ..bans import get_user_ban
-from ..decorators import deny_banned_ips
-from ..tokens import is_password_change_token_valid
+from misago.users.bans import get_user_ban
+from misago.users.decorators import deny_banned_ips
+from misago.users.tokens import is_password_change_token_valid
 
 
 
 
 def reset_view(f):
 def reset_view(f):

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

@@ -9,11 +9,11 @@ from misago.conf import settings
 from misago.core.shortcuts import get_object_or_404, paginate, pagination_dict
 from misago.core.shortcuts import get_object_or_404, paginate, pagination_dict
 from misago.core.utils import format_plaintext_for_html
 from misago.core.utils import format_plaintext_for_html
 
 
-from ..activepostersranking import get_active_posters_ranking
-from ..models import Rank
-from ..pages import users_list
-from ..permissions.profiles import allow_browse_users_list
-from ..serializers import ScoredUserSerializer, UserSerializer
+from misago.users.activepostersranking import get_active_posters_ranking
+from misago.users.models import Rank
+from misago.users.pages import users_list
+from misago.users.permissions.profiles import allow_browse_users_list
+from misago.users.serializers import ScoredUserSerializer, UserSerializer
 
 
 
 
 def render(request, template, context):
 def render(request, template, context):

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

@@ -5,9 +5,9 @@ from django.urls import reverse
 from django.utils import six
 from django.utils import six
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 
 
-from ..credentialchange import read_new_credential
-from ..decorators import deny_guests
-from ..pages import usercp
+from misago.users.credentialchange import read_new_credential
+from misago.users.decorators import deny_guests
+from misago.users.pages import usercp
 
 
 
 
 @deny_guests
 @deny_guests

+ 8 - 8
misago/users/views/profile.py

@@ -16,14 +16,14 @@ from misago.core.shortcuts import get_object_or_404, paginate, pagination_dict,
 from misago.core.utils import clean_return_path
 from misago.core.utils import clean_return_path
 from misago.threads.permissions import allow_message_user
 from misago.threads.permissions import allow_message_user
 
 
-from ..bans import get_user_ban
-from ..decorators import deny_guests
-from ..online.utils import get_user_status
-from ..pages import user_profile
-from ..permissions.profiles import allow_block_user, allow_follow_user
-from ..serializers import BanDetailsSerializer, UserProfileSerializer, UserSerializer
-from ..serializers.usernamechange import UsernameChangeSerializer
-from ..viewmodels import UserPosts, UserThreads
+from misago.users.bans import get_user_ban
+from misago.users.decorators import deny_guests
+from misago.users.online.utils import get_user_status
+from misago.users.pages import user_profile
+from misago.users.permissions.profiles import allow_block_user, allow_follow_user
+from misago.users.serializers import BanDetailsSerializer, UserProfileSerializer, UserSerializer
+from misago.users.serializers.usernamechange import UsernameChangeSerializer
+from misago.users.viewmodels import UserPosts, UserThreads
 
 
 
 
 UserModel = get_user_model()
 UserModel = get_user_model()