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

Merge pull request #1159 from rafalp/update-isort

Update isort config
Rafał Pitoń 6 лет назад
Родитель
Сommit
9f303b1b51
523 измененных файлов с 1584 добавлено и 1974 удалено
  1. 4 11
      .isort.cfg
  2. 4 0
      dev
  3. 1 0
      misago/acl/apps.py
  4. 1 2
      misago/acl/cache.py
  5. 1 1
      misago/acl/migrations/0001_initial.py
  6. 0 1
      misago/acl/migrations/0003_default_roles.py
  7. 2 2
      misago/acl/migrations/0004_cache_version.py
  8. 0 1
      misago/acl/panels.py
  9. 1 2
      misago/acl/providers.py
  10. 1 1
      misago/acl/tests/test_acl_algebra.py
  11. 1 1
      misago/acl/tests/test_getting_user_acl.py
  12. 2 2
      misago/acl/tests/test_mock_role_admin_form_data.py
  13. 2 2
      misago/acl/tests/test_patching_user_acl.py
  14. 2 2
      misago/acl/tests/test_providers.py
  15. 5 5
      misago/acl/tests/test_roleadmin_views.py
  16. 1 1
      misago/acl/tests/test_serializing_user_acl.py
  17. 1 1
      misago/acl/tests/test_user_acl_context_processor.py
  18. 1 1
      misago/acl/tests/test_user_acl_middleware.py
  19. 1 2
      misago/acl/views.py
  20. 1 2
      misago/admin/auth.py
  21. 1 1
      misago/admin/forms.py
  22. 1 1
      misago/admin/test.py
  23. 3 3
      misago/admin/tests/test_admin_form_templatetags.py
  24. 1 1
      misago/admin/tests/test_admin_hierarchy.py
  25. 2 2
      misago/admin/tests/test_admin_index.py
  26. 3 3
      misago/admin/tests/test_admin_views.py
  27. 1 1
      misago/admin/tests/test_forms.py
  28. 1 3
      misago/admin/urls.py
  29. 3 4
      misago/admin/views/__init__.py
  30. 2 2
      misago/admin/views/auth.py
  31. 2 4
      misago/admin/views/errorpages.py
  32. 1 1
      misago/admin/views/generic/base.py
  33. 1 2
      misago/admin/views/generic/list.py
  34. 5 8
      misago/admin/views/index.py
  35. 1 1
      misago/cache/management/commands/invalidateversionedcaches.py
  36. 2 2
      misago/cache/migrations/0001_initial.py
  37. 1 1
      misago/cache/tests/conftest.py
  38. 3 3
      misago/cache/tests/test_assert_invalidates_cache.py
  39. 1 1
      misago/cache/tests/test_cache_versions_middleware.py
  40. 1 1
      misago/cache/tests/test_getting_cache_versions.py
  41. 2 2
      misago/cache/tests/test_invalidating_caches.py
  42. 4 6
      misago/categories/forms.py
  43. 2 2
      misago/categories/management/commands/fixcategoriestree.py
  44. 1 1
      misago/categories/management/commands/prunecategories.py
  45. 2 2
      misago/categories/management/commands/synchronizecategories.py
  46. 2 3
      misago/categories/migrations/0001_initial.py
  47. 1 2
      misago/categories/migrations/0002_default_categories.py
  48. 0 1
      misago/categories/migrations/0003_categories_roles.py
  49. 0 1
      misago/categories/migrations/0006_moderation_queue_roles.py
  50. 0 1
      misago/categories/migrations/0007_best_answers_roles.py
  51. 7 9
      misago/categories/models.py
  52. 4 5
      misago/categories/permissions.py
  53. 3 6
      misago/categories/serializers.py
  54. 1 3
      misago/categories/signals.py
  55. 6 6
      misago/categories/tests/test_categories_admin_views.py
  56. 4 4
      misago/categories/tests/test_category_model.py
  57. 4 4
      misago/categories/tests/test_fixcategoriestree.py
  58. 6 6
      misago/categories/tests/test_permissions_admin_views.py
  59. 3 3
      misago/categories/tests/test_prunecategories.py
  60. 3 3
      misago/categories/tests/test_synchronizecategories.py
  61. 5 5
      misago/categories/tests/test_utils.py
  62. 3 3
      misago/categories/tests/test_views.py
  63. 3 3
      misago/categories/urls/__init__.py
  64. 2 3
      misago/categories/urls/api.py
  65. 2 3
      misago/categories/utils.py
  66. 6 6
      misago/categories/views/categoriesadmin.py
  67. 2 4
      misago/categories/views/categorieslist.py
  68. 7 8
      misago/categories/views/permsadmin.py
  69. 1 2
      misago/conf/cache.py
  70. 1 2
      misago/conf/context_processors.py
  71. 1 1
      misago/conf/forms.py
  72. 2 3
      misago/conf/migrations/0002_cache_version.py
  73. 1 1
      misago/conf/test.py
  74. 1 1
      misago/conf/tests/conftest.py
  75. 2 2
      misago/conf/tests/test_admin_views.py
  76. 1 1
      misago/conf/tests/test_context_processors.py
  77. 1 2
      misago/conf/tests/test_dynamic_settings_middleware.py
  78. 2 2
      misago/conf/tests/test_getting_dynamic_settings_values.py
  79. 0 1
      misago/conf/tests/test_getting_static_settings_values.py
  80. 2 2
      misago/conf/tests/test_hydrators.py
  81. 2 2
      misago/conf/tests/test_migrationutils.py
  82. 1 1
      misago/conf/tests/test_models.py
  83. 2 2
      misago/conf/tests/test_overridding_dynamic_settings.py
  84. 1 2
      misago/conf/views.py
  85. 7 7
      misago/conftest.py
  86. 1 3
      misago/core/apipatch.py
  87. 2 2
      misago/core/cache.py
  88. 3 4
      misago/core/errorpages.py
  89. 1 3
      misago/core/exceptionhandler.py
  90. 1 2
      misago/core/mail.py
  91. 2 2
      misago/core/middleware.py
  92. 1 2
      misago/core/migrations/0002_basic_settings.py
  93. 1 2
      misago/core/momentjs.py
  94. 1 2
      misago/core/rest_permissions.py
  95. 1 2
      misago/core/shortcuts.py
  96. 1 2
      misago/core/slugify.py
  97. 1 1
      misago/core/templatetags/misago_absoluteurl.py
  98. 0 1
      misago/core/templatetags/misago_batch.py
  99. 0 1
      misago/core/templatetags/misago_capture.py
  100. 1 2
      misago/core/templatetags/misago_json.py
  101. 0 1
      misago/core/templatetags/misago_pagetitle.py
  102. 0 1
      misago/core/templatetags/misago_shorthands.py
  103. 0 1
      misago/core/templatetags/misago_stringutils.py
  104. 1 3
      misago/core/testproject/urls.py
  105. 0 1
      misago/core/testproject/urlswitherrorhandlers.py
  106. 8 10
      misago/core/testproject/views.py
  107. 1 1
      misago/core/tests/test_apipatch.py
  108. 1 2
      misago/core/tests/test_checks.py
  109. 2 2
      misago/core/tests/test_chunk_queryset.py
  110. 1 1
      misago/core/tests/test_common_middleware_redirect.py
  111. 1 1
      misago/core/tests/test_context_processors.py
  112. 1 1
      misago/core/tests/test_deprecations.py
  113. 6 9
      misago/core/tests/test_errorpages.py
  114. 5 7
      misago/core/tests/test_exceptionhandler_middleware.py
  115. 3 4
      misago/core/tests/test_exceptionhandlers.py
  116. 1 1
      misago/core/tests/test_frontendcontext_middleware.py
  117. 0 1
      misago/core/tests/test_jsi18n.py
  118. 4 4
      misago/core/tests/test_mail.py
  119. 1 1
      misago/core/tests/test_momentjs.py
  120. 1 1
      misago/core/tests/test_page.py
  121. 2 3
      misago/core/tests/test_pgpartialindex.py
  122. 5 6
      misago/core/tests/test_serializers.py
  123. 1 1
      misago/core/tests/test_setup.py
  124. 1 1
      misago/core/tests/test_shortcuts.py
  125. 10 11
      misago/core/tests/test_templatetags.py
  126. 4 4
      misago/core/tests/test_utils.py
  127. 1 1
      misago/core/tests/test_validators.py
  128. 0 1
      misago/core/utils.py
  129. 0 1
      misago/faker/englishcorpus.py
  130. 3 4
      misago/faker/management/commands/createfakebans.py
  131. 4 5
      misago/faker/management/commands/createfakecategories.py
  132. 1 2
      misago/faker/management/commands/createfakefollowers.py
  133. 6 8
      misago/faker/management/commands/createfakethreads.py
  134. 4 6
      misago/faker/management/commands/createfakeusers.py
  135. 1 1
      misago/faker/tests/test_englishcorpus.py
  136. 0 1
      misago/legal/api.py
  137. 0 1
      misago/legal/context_processors.py
  138. 1 2
      misago/legal/migrations/0001_initial.py
  139. 2 2
      misago/legal/migrations/0002_agreement_useragreement.py
  140. 2 3
      misago/legal/migrations/0003_create_agreements_from_settings.py
  141. 2 3
      misago/legal/models.py
  142. 1 2
      misago/legal/signals.py
  143. 2 2
      misago/legal/tests/test_admin_views.py
  144. 2 2
      misago/legal/tests/test_api.py
  145. 3 3
      misago/legal/tests/test_context_processors.py
  146. 2 2
      misago/legal/tests/test_required_agreement.py
  147. 3 3
      misago/legal/tests/test_utils.py
  148. 1 1
      misago/legal/tests/test_views.py
  149. 1 2
      misago/legal/urls/__init__.py
  150. 1 2
      misago/legal/urls/api.py
  151. 2 3
      misago/legal/utils.py
  152. 4 5
      misago/legal/views/admin.py
  153. 2 2
      misago/legal/views/legal.py
  154. 1 3
      misago/markup/bbcode/blocks.py
  155. 0 1
      misago/markup/finalise.py
  156. 0 1
      misago/markup/md/shortimgs.py
  157. 0 1
      misago/markup/md/striketrough.py
  158. 0 2
      misago/markup/mentions.py
  159. 3 6
      misago/markup/parser.py
  160. 1 1
      misago/markup/pipeline.py
  161. 1 1
      misago/markup/serializers.py
  162. 0 1
      misago/markup/templatetags/misago_editor.py
  163. 1 1
      misago/markup/tests/test_api.py
  164. 1 1
      misago/markup/tests/test_checksums.py
  165. 1 1
      misago/markup/tests/test_finalise.py
  166. 2 2
      misago/markup/tests/test_mentions.py
  167. 2 2
      misago/markup/tests/test_parser.py
  168. 0 1
      misago/markup/urls.py
  169. 2 6
      misago/readtracker/categoriestracker.py
  170. 1 1
      misago/readtracker/dates.py
  171. 2 2
      misago/readtracker/management/commands/clearreadtracker.py
  172. 2 2
      misago/readtracker/migrations/0002_postread.py
  173. 2 3
      misago/readtracker/migrations/0003_migrate_reads_to_posts.py
  174. 3 4
      misago/readtracker/signals.py
  175. 8 8
      misago/readtracker/tests/test_categoriestracker.py
  176. 6 6
      misago/readtracker/tests/test_clearreadtracker.py
  177. 2 2
      misago/readtracker/tests/test_dates.py
  178. 16 16
      misago/readtracker/tests/test_poststracker.py
  179. 9 9
      misago/readtracker/tests/test_threadstracker.py
  180. 2 3
      misago/readtracker/threadstracker.py
  181. 3 5
      misago/search/api.py
  182. 3 3
      misago/search/permissions.py
  183. 1 1
      misago/search/searchproviders.py
  184. 3 3
      misago/search/tests/test_api.py
  185. 3 3
      misago/search/tests/test_searchproviders.py
  186. 3 3
      misago/search/tests/test_views.py
  187. 1 1
      misago/search/urls/__init__.py
  188. 1 2
      misago/search/urls/api.py
  189. 0 1
      misago/threads/anonymize.py
  190. 6 8
      misago/threads/api/attachments.py
  191. 3 3
      misago/threads/api/pollvotecreateendpoint.py
  192. 7 9
      misago/threads/api/postendpoints/delete.py
  193. 7 8
      misago/threads/api/postendpoints/edits.py
  194. 1 1
      misago/threads/api/postendpoints/likes.py
  195. 3 4
      misago/threads/api/postendpoints/merge.py
  196. 2 3
      misago/threads/api/postendpoints/move.py
  197. 4 5
      misago/threads/api/postendpoints/patch_event.py
  198. 9 11
      misago/threads/api/postendpoints/patch_post.py
  199. 2 2
      misago/threads/api/postendpoints/read.py
  200. 4 5
      misago/threads/api/postendpoints/split.py
  201. 1 1
      misago/threads/api/postingendpoint/__init__.py
  202. 4 6
      misago/threads/api/postingendpoint/attachments.py
  203. 7 9
      misago/threads/api/postingendpoint/category.py
  204. 1 2
      misago/threads/api/postingendpoint/close.py
  205. 3 4
      misago/threads/api/postingendpoint/emailnotification.py
  206. 1 3
      misago/threads/api/postingendpoint/floodprotection.py
  207. 1 2
      misago/threads/api/postingendpoint/hide.py
  208. 1 2
      misago/threads/api/postingendpoint/moderationqueue.py
  209. 7 9
      misago/threads/api/postingendpoint/participants.py
  210. 2 3
      misago/threads/api/postingendpoint/pin.py
  211. 3 4
      misago/threads/api/postingendpoint/privatethread.py
  212. 5 11
      misago/threads/api/postingendpoint/reply.py
  213. 1 2
      misago/threads/api/postingendpoint/savechanges.py
  214. 1 3
      misago/threads/api/postingendpoint/subscribe.py
  215. 2 3
      misago/threads/api/postingendpoint/syncprivatethreads.py
  216. 1 2
      misago/threads/api/postingendpoint/updatestats.py
  217. 4 5
      misago/threads/api/threadendpoints/delete.py
  218. 6 7
      misago/threads/api/threadendpoints/editor.py
  219. 2 2
      misago/threads/api/threadendpoints/list.py
  220. 9 10
      misago/threads/api/threadendpoints/merge.py
  221. 16 17
      misago/threads/api/threadendpoints/patch.py
  222. 10 12
      misago/threads/api/threadpoll.py
  223. 11 18
      misago/threads/api/threadposts.py
  224. 10 12
      misago/threads/api/threads.py
  225. 1 1
      misago/threads/checksums.py
  226. 1 2
      misago/threads/events.py
  227. 1 2
      misago/threads/filtersearch.py
  228. 4 4
      misago/threads/management/commands/clearattachments.py
  229. 3 3
      misago/threads/management/commands/rebuildpostssearch.py
  230. 3 3
      misago/threads/management/commands/synchronizethreads.py
  231. 4 4
      misago/threads/management/commands/updatepostschecksums.py
  232. 2 3
      misago/threads/mergeconflict.py
  233. 1 2
      misago/threads/middleware.py
  234. 1 2
      misago/threads/migrations/0002_threads_settings.py
  235. 0 1
      misago/threads/migrations/0003_attachment_types.py
  236. 1 1
      misago/threads/migrations/0004_update_settings.py
  237. 1 1
      misago/threads/migrations/0008_auto_20180310_2234.py
  238. 3 4
      misago/threads/models/attachment.py
  239. 10 10
      misago/threads/models/post.py
  240. 1 1
      misago/threads/models/subscription.py
  241. 6 6
      misago/threads/models/thread.py
  242. 1 1
      misago/threads/models/threadparticipant.py
  243. 0 1
      misago/threads/moderation/posts.py
  244. 1 2
      misago/threads/moderation/threads.py
  245. 1 3
      misago/threads/participants.py
  246. 4 5
      misago/threads/permissions/attachments.py
  247. 9 9
      misago/threads/permissions/bestanswers.py
  248. 5 6
      misago/threads/permissions/polls.py
  249. 7 8
      misago/threads/permissions/privatethreads.py
  250. 11 11
      misago/threads/permissions/threads.py
  251. 3 5
      misago/threads/search.py
  252. 2 4
      misago/threads/serializers/attachment.py
  253. 4 6
      misago/threads/serializers/feed.py
  254. 13 14
      misago/threads/serializers/moderation.py
  255. 2 4
      misago/threads/serializers/poll.py
  256. 1 3
      misago/threads/serializers/pollvote.py
  257. 4 6
      misago/threads/serializers/post.py
  258. 2 4
      misago/threads/serializers/postedit.py
  259. 2 4
      misago/threads/serializers/postlike.py
  260. 4 7
      misago/threads/serializers/thread.py
  261. 1 2
      misago/threads/serializers/threadparticipant.py
  262. 4 6
      misago/threads/signals.py
  263. 0 1
      misago/threads/templatetags/misago_poststags.py
  264. 4 5
      misago/threads/test.py
  265. 8 10
      misago/threads/tests/test_anonymize_data.py
  266. 4 4
      misago/threads/tests/test_attachmentadmin_views.py
  267. 6 7
      misago/threads/tests/test_attachments_api.py
  268. 10 10
      misago/threads/tests/test_attachments_middleware.py
  269. 3 3
      misago/threads/tests/test_attachmenttypeadmin_views.py
  270. 7 7
      misago/threads/tests/test_attachmentview.py
  271. 5 5
      misago/threads/tests/test_clearattachments.py
  272. 5 6
      misago/threads/tests/test_delete_user_likes.py
  273. 4 4
      misago/threads/tests/test_emailnotification_middleware.py
  274. 7 7
      misago/threads/tests/test_events.py
  275. 4 4
      misago/threads/tests/test_floodprotection.py
  276. 3 3
      misago/threads/tests/test_floodprotection_middleware.py
  277. 6 7
      misago/threads/tests/test_gotoviews.py
  278. 5 7
      misago/threads/tests/test_mergeconflict.py
  279. 1 1
      misago/threads/tests/test_paginator.py
  280. 4 4
      misago/threads/tests/test_participants.py
  281. 4 4
      misago/threads/tests/test_post_mentions.py
  282. 4 4
      misago/threads/tests/test_post_model.py
  283. 4 4
      misago/threads/tests/test_posts_moderation.py
  284. 5 6
      misago/threads/tests/test_privatethread_patch_api.py
  285. 3 4
      misago/threads/tests/test_privatethread_reply_api.py
  286. 5 5
      misago/threads/tests/test_privatethread_start_api.py
  287. 3 4
      misago/threads/tests/test_privatethread_view.py
  288. 2 2
      misago/threads/tests/test_privatethreads.py
  289. 4 5
      misago/threads/tests/test_privatethreads_api.py
  290. 3 4
      misago/threads/tests/test_privatethreads_lists.py
  291. 3 3
      misago/threads/tests/test_search.py
  292. 5 6
      misago/threads/tests/test_subscription_middleware.py
  293. 5 5
      misago/threads/tests/test_subscriptions.py
  294. 3 4
      misago/threads/tests/test_sync_unread_private_threads.py
  295. 3 3
      misago/threads/tests/test_synchronizethreads.py
  296. 4 5
      misago/threads/tests/test_thread_bulkpatch_api.py
  297. 6 6
      misago/threads/tests/test_thread_editreply_api.py
  298. 5 6
      misago/threads/tests/test_thread_merge_api.py
  299. 4 4
      misago/threads/tests/test_thread_model.py
  300. 5 6
      misago/threads/tests/test_thread_patch_api.py
  301. 3 3
      misago/threads/tests/test_thread_poll_api.py
  302. 4 5
      misago/threads/tests/test_thread_pollcreate_api.py
  303. 3 4
      misago/threads/tests/test_thread_polldelete_api.py
  304. 3 4
      misago/threads/tests/test_thread_polledit_api.py
  305. 3 4
      misago/threads/tests/test_thread_pollvotes_api.py
  306. 3 4
      misago/threads/tests/test_thread_postbulkdelete_api.py
  307. 5 5
      misago/threads/tests/test_thread_postbulkpatch_api.py
  308. 3 4
      misago/threads/tests/test_thread_postdelete_api.py
  309. 2 3
      misago/threads/tests/test_thread_postedits_api.py
  310. 3 4
      misago/threads/tests/test_thread_postlikes_api.py
  311. 7 7
      misago/threads/tests/test_thread_postmerge_api.py
  312. 7 7
      misago/threads/tests/test_thread_postmove_api.py
  313. 5 5
      misago/threads/tests/test_thread_postpatch_api.py
  314. 1 2
      misago/threads/tests/test_thread_postread_api.py
  315. 7 7
      misago/threads/tests/test_thread_postsplit_api.py
  316. 6 6
      misago/threads/tests/test_thread_reply_api.py
  317. 4 4
      misago/threads/tests/test_thread_start_api.py
  318. 3 3
      misago/threads/tests/test_threadparticipant_model.py
  319. 8 8
      misago/threads/tests/test_threads_api.py
  320. 7 8
      misago/threads/tests/test_threads_bulkdelete_api.py
  321. 9 9
      misago/threads/tests/test_threads_editor_api.py
  322. 10 11
      misago/threads/tests/test_threads_merge_api.py
  323. 4 4
      misago/threads/tests/test_threads_moderation.py
  324. 7 7
      misago/threads/tests/test_threadslists.py
  325. 11 11
      misago/threads/tests/test_threadview.py
  326. 2 3
      misago/threads/tests/test_treesmap.py
  327. 4 4
      misago/threads/tests/test_updatepostschecksums.py
  328. 3 3
      misago/threads/tests/test_utils.py
  329. 2 2
      misago/threads/tests/test_validate_post.py
  330. 1 1
      misago/threads/tests/test_validators.py
  331. 1 2
      misago/threads/threadtypes/privatethread.py
  332. 1 2
      misago/threads/threadtypes/thread.py
  333. 2 2
      misago/threads/threadtypes/treesmap.py
  334. 5 9
      misago/threads/urls/__init__.py
  335. 5 6
      misago/threads/urls/api.py
  336. 5 6
      misago/threads/validators.py
  337. 7 8
      misago/threads/viewmodels/category.py
  338. 3 4
      misago/threads/viewmodels/post.py
  339. 9 10
      misago/threads/viewmodels/posts.py
  340. 12 13
      misago/threads/viewmodels/thread.py
  341. 11 14
      misago/threads/viewmodels/threads.py
  342. 3 3
      misago/threads/views/admin/attachments.py
  343. 3 3
      misago/threads/views/admin/attachmenttypes.py
  344. 2 3
      misago/threads/views/attachment.py
  345. 4 4
      misago/threads/views/goto.py
  346. 2 2
      misago/threads/views/list.py
  347. 1 1
      misago/threads/views/thread.py
  348. 2 3
      misago/urls.py
  349. 2 4
      misago/users/activepostersranking.py
  350. 0 1
      misago/users/admin.py
  351. 10 20
      misago/users/api/auth.py
  352. 1 2
      misago/users/api/captcha.py
  353. 3 5
      misago/users/api/mention.py
  354. 2 2
      misago/users/api/ranks.py
  355. 4 5
      misago/users/api/rest_permissions.py
  356. 8 9
      misago/users/api/userendpoints/avatar.py
  357. 5 6
      misago/users/api/userendpoints/changeemail.py
  358. 4 5
      misago/users/api/userendpoints/changepassword.py
  359. 8 9
      misago/users/api/userendpoints/create.py
  360. 2 4
      misago/users/api/userendpoints/editdetails.py
  361. 5 7
      misago/users/api/userendpoints/list.py
  362. 5 6
      misago/users/api/userendpoints/signature.py
  363. 4 5
      misago/users/api/userendpoints/username.py
  364. 5 8
      misago/users/api/usernamechanges.py
  365. 17 23
      misago/users/api/users.py
  366. 1 2
      misago/users/apps.py
  367. 0 1
      misago/users/authbackends.py
  368. 1 2
      misago/users/avatars/__init__.py
  369. 2 5
      misago/users/avatars/dynamic.py
  370. 5 8
      misago/users/avatars/gallery.py
  371. 1 3
      misago/users/avatars/gravatar.py
  372. 3 4
      misago/users/avatars/store.py
  373. 2 4
      misago/users/avatars/uploaded.py
  374. 0 1
      misago/users/captcha.py
  375. 3 3
      misago/users/datadownloads/__init__.py
  376. 1 2
      misago/users/datadownloads/dataarchive.py
  377. 1 2
      misago/users/decorators.py
  378. 8 9
      misago/users/forms/admin.py
  379. 1 2
      misago/users/forms/auth.py
  380. 2 7
      misago/users/forms/register.py
  381. 2 1
      misago/users/management/commands/buildactivepostersranking.py
  382. 4 5
      misago/users/management/commands/createsuperuser.py
  383. 2 3
      misago/users/management/commands/deleteinactiveusers.py
  384. 4 6
      misago/users/management/commands/deletemarkedusers.py
  385. 2 2
      misago/users/management/commands/deleteprofilefield.py
  386. 3 3
      misago/users/management/commands/expireuserdatadownloads.py
  387. 3 4
      misago/users/management/commands/invalidatebans.py
  388. 1 2
      misago/users/management/commands/listusedprofilefields.py
  389. 3 3
      misago/users/management/commands/loadavatargallery.py
  390. 2 3
      misago/users/management/commands/populateonlinetracker.py
  391. 7 8
      misago/users/management/commands/prepareuserdatadownloads.py
  392. 2 2
      misago/users/management/commands/removeoldips.py
  393. 3 4
      misago/users/management/commands/synchronizeusers.py
  394. 1 2
      misago/users/migrations/0002_users_settings.py
  395. 1 2
      misago/users/migrations/0004_default_ranks.py
  396. 1 1
      misago/users/migrations/0006_update_settings.py
  397. 1 0
      misago/users/migrations/0009_redo_partial_indexes.py
  398. 1 0
      misago/users/migrations/0011_auto_20180331_2208.py
  399. 2 2
      misago/users/migrations/0012_audittrail.py
  400. 3 2
      misago/users/migrations/0014_datadownload.py
  401. 1 1
      misago/users/migrations/0016_cache_version.py
  402. 1 1
      misago/users/migrations/0017_move_bans_to_cache_version.py
  403. 1 1
      misago/users/models/avatar.py
  404. 1 1
      misago/users/models/avatargallery.py
  405. 4 4
      misago/users/models/ban.py
  406. 2 2
      misago/users/models/rank.py
  407. 13 13
      misago/users/models/user.py
  408. 2 3
      misago/users/online/tracker.py
  409. 2 3
      misago/users/online/utils.py
  410. 1 2
      misago/users/pages.py
  411. 3 3
      misago/users/permissions/account.py
  412. 0 1
      misago/users/permissions/decorators.py
  413. 4 5
      misago/users/permissions/delete.py
  414. 5 6
      misago/users/permissions/moderation.py
  415. 4 6
      misago/users/permissions/profiles.py
  416. 1 1
      misago/users/profilefields/__init__.py
  417. 1 2
      misago/users/profilefields/basefields.py
  418. 2 1
      misago/users/profilefields/default.py
  419. 1 1
      misago/users/profilefields/serializers.py
  420. 4 4
      misago/users/registration.py
  421. 1 3
      misago/users/search.py
  422. 2 4
      misago/users/serializers/auth.py
  423. 3 5
      misago/users/serializers/ban.py
  424. 1 2
      misago/users/serializers/datadownload.py
  425. 2 4
      misago/users/serializers/moderation.py
  426. 4 6
      misago/users/serializers/options.py
  427. 2 3
      misago/users/serializers/rank.py
  428. 2 5
      misago/users/serializers/user.py
  429. 1 3
      misago/users/serializers/usernamechange.py
  430. 1 1
      misago/users/setupnewuser.py
  431. 2 4
      misago/users/signals.py
  432. 1 1
      misago/users/signatures.py
  433. 9 12
      misago/users/social/pipeline.py
  434. 1 2
      misago/users/social/utils.py
  435. 0 1
      misago/users/templatetags/misago_avatars.py
  436. 4 4
      misago/users/tests/test_activation_views.py
  437. 4 4
      misago/users/tests/test_activepostersranking.py
  438. 4 4
      misago/users/tests/test_audittrail.py
  439. 3 3
      misago/users/tests/test_auth_api.py
  440. 2 2
      misago/users/tests/test_auth_backend.py
  441. 1 1
      misago/users/tests/test_avatar_filter.py
  442. 5 13
      misago/users/tests/test_avatars.py
  443. 2 2
      misago/users/tests/test_avatarserver_views.py
  444. 1 1
      misago/users/tests/test_ban_model.py
  445. 2 2
      misago/users/tests/test_banadmin_views.py
  446. 5 5
      misago/users/tests/test_bans.py
  447. 1 2
      misago/users/tests/test_bio_profilefield.py
  448. 1 1
      misago/users/tests/test_captcha_api.py
  449. 2 2
      misago/users/tests/test_credentialchange.py
  450. 7 8
      misago/users/tests/test_datadownloads.py
  451. 3 4
      misago/users/tests/test_datadownloads_dataarchive.py
  452. 4 4
      misago/users/tests/test_datadownloadsadmin_views.py
  453. 3 3
      misago/users/tests/test_decorators.py
  454. 2 2
      misago/users/tests/test_deleteinactiveusers.py
  455. 2 2
      misago/users/tests/test_deletemarkedusers.py
  456. 2 2
      misago/users/tests/test_deleteprofilefield.py
  457. 1 1
      misago/users/tests/test_djangoadmin_auth.py
  458. 3 3
      misago/users/tests/test_djangoadmin_user.py
  459. 4 5
      misago/users/tests/test_expireuserdatadownloads.py
  460. 4 4
      misago/users/tests/test_forgottenpassword_views.py
  461. 1 2
      misago/users/tests/test_gender_profilefield.py
  462. 2 2
      misago/users/tests/test_getting_user_status.py
  463. 5 6
      misago/users/tests/test_invalidatebans.py
  464. 2 3
      misago/users/tests/test_joinip_profilefield.py
  465. 6 6
      misago/users/tests/test_lists_views.py
  466. 2 2
      misago/users/tests/test_listusedprofilefields.py
  467. 2 2
      misago/users/tests/test_loadavatargallery.py
  468. 2 2
      misago/users/tests/test_mention_api.py
  469. 2 2
      misago/users/tests/test_namechanges.py
  470. 2 2
      misago/users/tests/test_new_user_setup.py
  471. 1 1
      misago/users/tests/test_options_views.py
  472. 2 2
      misago/users/tests/test_populate_online_tracker_command.py
  473. 5 5
      misago/users/tests/test_prepareuserdatadownloads.py
  474. 5 5
      misago/users/tests/test_profile_views.py
  475. 1 2
      misago/users/tests/test_profilefields.py
  476. 5 5
      misago/users/tests/test_rankadmin_views.py
  477. 1 1
      misago/users/tests/test_realip_middleware.py
  478. 1 2
      misago/users/tests/test_remove_old_ips_command.py
  479. 2 2
      misago/users/tests/test_rest_permissions.py
  480. 2 2
      misago/users/tests/test_search.py
  481. 2 2
      misago/users/tests/test_signatures.py
  482. 10 12
      misago/users/tests/test_social_pipeline.py
  483. 1 1
      misago/users/tests/test_social_utils.py
  484. 1 1
      misago/users/tests/test_testutils.py
  485. 1 1
      misago/users/tests/test_token_creation_and_validation.py
  486. 1 2
      misago/users/tests/test_twitter_profilefield.py
  487. 6 6
      misago/users/tests/test_user_avatar_api.py
  488. 1 1
      misago/users/tests/test_user_changeemail_api.py
  489. 1 1
      misago/users/tests/test_user_changepassword_api.py
  490. 4 4
      misago/users/tests/test_user_create_api.py
  491. 2 2
      misago/users/tests/test_user_creation.py
  492. 2 2
      misago/users/tests/test_user_datadownloads_api.py
  493. 2 2
      misago/users/tests/test_user_details_api.py
  494. 2 2
      misago/users/tests/test_user_editdetails_api.py
  495. 2 2
      misago/users/tests/test_user_feeds_api.py
  496. 3 3
      misago/users/tests/test_user_middleware.py
  497. 4 5
      misago/users/tests/test_user_model.py
  498. 2 2
      misago/users/tests/test_user_requestdatadownload_api.py
  499. 2 2
      misago/users/tests/test_user_signature_api.py
  500. 3 3
      misago/users/tests/test_user_username_api.py
  501. 9 10
      misago/users/tests/test_useradmin_views.py
  502. 2 2
      misago/users/tests/test_usernamechanges_api.py
  503. 7 7
      misago/users/tests/test_users_api.py
  504. 1 1
      misago/users/tests/test_utils.py
  505. 3 3
      misago/users/tests/test_validators.py
  506. 2 2
      misago/users/urls/__init__.py
  507. 5 6
      misago/users/urls/api.py
  508. 1 4
      misago/users/validators.py
  509. 4 4
      misago/users/viewmodels/activeposters.py
  510. 4 4
      misago/users/viewmodels/followers.py
  511. 2 3
      misago/users/viewmodels/posts.py
  512. 4 4
      misago/users/viewmodels/rankusers.py
  513. 7 7
      misago/users/viewmodels/threads.py
  514. 4 5
      misago/users/views/activation.py
  515. 3 3
      misago/users/views/admin/bans.py
  516. 4 4
      misago/users/views/admin/datadownloads.py
  517. 3 3
      misago/users/views/admin/ranks.py
  518. 14 17
      misago/users/views/admin/users.py
  519. 1 2
      misago/users/views/avatarserver.py
  520. 4 4
      misago/users/views/forgottenpassword.py
  521. 5 5
      misago/users/views/lists.py
  522. 3 3
      misago/users/views/options.py
  523. 8 13
      misago/users/views/profile.py

+ 4 - 11
.isort.cfg

@@ -1,14 +1,7 @@
 [settings]
-line_length=100
-lines_after_imports=2
-known_crispyforms=crispy_forms
-known_django=django
-known_faker=faker
-kmown_mptt=mptt
-knowm_requests=requests
-known_restframework=rest_framework
-known_unidecode=unidecode
+include_trailing_comma=true
+line_length=88
+lines_after_imports=1
 known_first_party=misago
-sections=FUTURE,STDLIB,THIRDPARTY,FAKER,MPTT,REQUESTS,RESTFRAMEWORK,UNIDECODE,DJANGO,FIRSTPARTY,LOCALFOLDER
-multi_line_output=4
+multi_line_output=3
 verbose=true

+ 4 - 0
dev

@@ -89,6 +89,7 @@ intro() {
     echo "    ${BOLD}bash${NORMAL}              starts bash session inside running Misago container."
     echo "    ${BOLD}run${NORMAL}               runs \"docker-compose run --rm misago\"."
     echo "    ${BOLD}psql${NORMAL}              runs psql connected to development database."
+    echo "    ${BOLD}fmtpy${NORMAL}             runs isort + black on python code."
     echo
 }
 
@@ -310,6 +311,9 @@ if [[ $1 ]]; then
         run_psql
     elif [[ $1 = "psql_in_docker" ]]; then
         psql_in_docker
+    elif [[ $1 = "fmtpy" ]]; then
+        isort -rc misago
+        black devproject misago
     else
         invalid_argument $1
     fi

+ 1 - 0
misago/acl/apps.py

@@ -1,4 +1,5 @@
 from django.apps import AppConfig
+
 from .providers import providers
 
 

+ 1 - 2
misago/acl/cache.py

@@ -1,8 +1,7 @@
 from django.core.cache import cache
 
-from misago.cache.versions import invalidate_cache
-
 from . import ACL_CACHE
+from ..cache.versions import invalidate_cache
 
 
 def get_acl_cache(user, cache_versions):

+ 1 - 1
misago/acl/migrations/0001_initial.py

@@ -1,7 +1,7 @@
 from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
-from misago.acl.models import permissions_default
+from ..models import permissions_default
 
 
 class Migration(migrations.Migration):

+ 0 - 1
misago/acl/migrations/0003_default_roles.py

@@ -1,6 +1,5 @@
 from django.db import migrations
 
-
 _ = lambda s: s
 
 

+ 2 - 2
misago/acl/migrations/0004_cache_version.py

@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
 from django.db import migrations
 
-from misago.acl import ACL_CACHE
-from misago.cache.operations import StartCacheVersioning
+from .. import ACL_CACHE
+from ...cache.operations import StartCacheVersioning
 
 
 class Migration(migrations.Migration):

+ 0 - 1
misago/acl/panels.py

@@ -1,5 +1,4 @@
 from debug_toolbar.panels import Panel
-
 from django.utils.translation import gettext_lazy as _
 
 

+ 1 - 2
misago/acl/providers.py

@@ -1,7 +1,6 @@
 from importlib import import_module
 
-from misago.conf import settings
-
+from ..conf import settings
 
 _NOT_INITIALIZED_ERROR = (
     "PermissionProviders instance has to load providers with load() "

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

@@ -1,4 +1,4 @@
-from misago.acl import algebra
+from .. import algebra
 
 
 def test_greatest_value_is_returned():

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

@@ -1,4 +1,4 @@
-from misago.acl.useracl import get_user_acl
+from ..useracl import get_user_acl
 
 
 def test_getter_returns_authenticated_user_acl(cache_versions, user):

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

@@ -1,5 +1,5 @@
-from misago.acl.models import Role
-from misago.acl.test import mock_role_form_data
+from ..models import Role
+from ..test import mock_role_form_data
 
 
 def test_factory_for_change_role_permissions_form_data():

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

@@ -1,5 +1,5 @@
-from misago.acl import useracl
-from misago.acl.test import patch_user_acl
+from .. import useracl
+from ..test import patch_user_acl
 
 
 def callable_acl_patch(user, user_acl):

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

@@ -1,7 +1,7 @@
 import pytest
 
-from misago.acl.providers import PermissionProviders
-from misago.conf import settings
+from ...conf import settings
+from ..providers import PermissionProviders
 
 
 def test_providers_are_not_loaded_on_container_init():

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

@@ -1,10 +1,10 @@
 from django.urls import reverse
 
-from misago.acl import ACL_CACHE
-from misago.acl.models import Role
-from misago.acl.test import mock_role_form_data
-from misago.cache.test import assert_invalidates_cache
-from misago.admin.test import AdminTestCase
+from .. import ACL_CACHE
+from ...admin.test import AdminTestCase
+from ...cache.test import assert_invalidates_cache
+from ..models import Role
+from ..test import mock_role_form_data
 
 
 def create_data(data_dict):

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

@@ -1,6 +1,6 @@
 import json
 
-from misago.acl.useracl import get_user_acl, serialize_user_acl
+from ..useracl import get_user_acl, serialize_user_acl
 
 
 def test_user_acl_is_serializeable(cache_versions, user):

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

@@ -1,6 +1,6 @@
 from unittest.mock import Mock
 
-from misago.acl.context_processors import user_acl
+from ..context_processors import user_acl
 
 
 def test_context_processor_adds_request_user_acl_to_context():

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

@@ -1,6 +1,6 @@
 from unittest.mock import Mock
 
-from misago.acl.middleware import user_acl_middleware
+from ..middleware import user_acl_middleware
 
 
 def test_middleware_sets_attr_on_request(cache_versions, user):

+ 1 - 2
misago/acl/views.py

@@ -3,8 +3,7 @@ from django.shortcuts import redirect
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from misago.admin.views import generic
-
+from ..admin.views import generic
 from .forms import RoleForm, get_permissions_forms
 from .models import Role
 

+ 1 - 2
misago/admin/auth.py

@@ -5,8 +5,7 @@ from django.contrib import auth as dj_auth
 from django.contrib import messages
 from django.utils.translation import gettext as _
 
-from misago.conf import settings
-
+from ..conf import settings
 
 KEY_TOKEN = "misago_admin_session_token"
 KEY_UPDATED = "misago_admin_session_updated"

+ 1 - 1
misago/admin/forms.py

@@ -1,7 +1,7 @@
 from django.forms import DateTimeField, RadioSelect, TypedChoiceField, ValidationError
 from django.utils.translation import gettext_lazy as _
 
-from misago.core.utils import parse_iso8601_string
+from ..core.utils import parse_iso8601_string
 
 
 class IsoDateTimeField(DateTimeField):

+ 1 - 1
misago/admin/test.py

@@ -1,6 +1,6 @@
 from django.urls import reverse
 
-from misago.users.test import SuperUserTestCase
+from ..users.test import SuperUserTestCase
 
 
 class AdminTestCase(SuperUserTestCase):

+ 3 - 3
misago/admin/tests/test_admin_form_templatetags.py

@@ -2,15 +2,15 @@ import pytest
 from django import forms
 from django.template import Context, Template, TemplateSyntaxError
 
-from misago.admin.templatetags.misago_admin_form import (
+from ..forms import YesNoSwitch
+from ..templatetags.misago_admin_form import (
+    is_multiple_choice_field,
     is_radio_select_field,
     is_select_field,
-    is_multiple_choice_field,
     is_textarea_field,
     render_attrs,
     render_bool_attrs,
 )
-from misago.admin.forms import YesNoSwitch
 
 
 class Form(forms.Form):

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

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

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

@@ -1,8 +1,8 @@
 from django.test import TestCase, override_settings
 from django.urls import reverse
 
-from misago.admin.test import AdminTestCase
-from misago.admin.views.index import check_misago_address
+from ..test import AdminTestCase
+from ..views.index import check_misago_address
 
 
 class AdminIndexViewTests(AdminTestCase):

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

@@ -1,9 +1,9 @@
 from django.test import TestCase
 from django.urls import reverse
 
-from misago.admin.test import AdminTestCase
-from misago.admin.views import get_protected_namespace
-from misago.users.test import create_test_user
+from ...users.test import create_test_user
+from ..test import AdminTestCase
+from ..views import get_protected_namespace
 
 
 class MockRequest(object):

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

@@ -1,7 +1,7 @@
 from django import forms
 from django.test import TestCase
 
-from misago.admin.forms import YesNoSwitch
+from ..forms import YesNoSwitch
 
 
 class YesNoForm(forms.Form):

+ 1 - 3
misago/admin/urls.py

@@ -1,10 +1,8 @@
 from django.conf.urls import url
 
-from misago import admin
-
+from .. import admin
 from .views import auth, index
 
-
 urlpatterns = [
     # "misago:admin:index" link symbolises "root" of Misago admin links space
     # any request with path that falls below this one is assumed to be directed

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

@@ -1,10 +1,9 @@
 from django.urls import reverse, NoReverseMatch
 from django.shortcuts import render as dj_render
 
-from misago.conf import settings
-
-from misago.admin import site
-from misago.admin.auth import is_admin_session, update_admin_session
+from ...conf import settings
+from .. import site
+from ..auth import is_admin_session, update_admin_session
 from .auth import login
 
 

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

@@ -5,8 +5,8 @@ from django.views.decorators.cache import never_cache
 from django.views.decorators.csrf import csrf_protect
 from django.views.decorators.debug import sensitive_post_parameters
 
-from misago.admin import auth
-from misago.users.forms.auth import AdminAuthenticationForm
+from .. import auth
+from ...users.forms.auth import AdminAuthenticationForm
 
 
 @sensitive_post_parameters()

+ 2 - 4
misago/admin/views/errorpages.py

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

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

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

+ 1 - 2
misago/admin/views/generic/list.py

@@ -7,8 +7,7 @@ from django.shortcuts import redirect
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from misago.core.exceptions import ExplicitFirstPage
-
+from ....core.exceptions import ExplicitFirstPage
 from .base import AdminView
 
 

+ 5 - 8
misago/admin/views/index.py

@@ -1,17 +1,14 @@
 import requests
-from requests.exceptions import RequestException
-
 from django.contrib.auth import get_user_model
 from django.http import Http404, JsonResponse
 from django.utils.translation import gettext as _
-
-from misago import __version__
-from misago.conf import settings
-from misago.core.cache import cache
-from misago.threads.models import Post, Thread
+from requests.exceptions import RequestException
 
 from . import render
-
+from ... import __version__
+from ...conf import settings
+from ...core.cache import cache
+from ...threads.models import Post, Thread
 
 VERSION_CHECK_CACHE_KEY = "misago_version_check"
 

+ 1 - 1
misago/cache/management/commands/invalidateversionedcaches.py

@@ -1,6 +1,6 @@
 from django.core.management.base import BaseCommand
 
-from misago.cache.versions import invalidate_all_caches
+from ...versions import invalidate_all_caches
 
 
 class Command(BaseCommand):

+ 2 - 2
misago/cache/migrations/0001_initial.py

@@ -1,7 +1,7 @@
 # Generated by Django 1.11.16 on 2018-11-25 15:15
 from django.db import migrations, models
 
-import misago.cache.utils
+from .. import utils
 
 
 class Migration(migrations.Migration):
@@ -21,7 +21,7 @@ class Migration(migrations.Migration):
                 (
                     "version",
                     models.CharField(
-                        default=misago.cache.utils.generate_version_string, max_length=8
+                        default=utils.generate_version_string, max_length=8
                     ),
                 ),
             ],

+ 1 - 1
misago/cache/tests/conftest.py

@@ -1,6 +1,6 @@
 import pytest
 
-from misago.cache.models import CacheVersion
+from ..models import CacheVersion
 
 
 @pytest.fixture

+ 3 - 3
misago/cache/tests/test_assert_invalidates_cache.py

@@ -1,8 +1,8 @@
 import pytest
 
-from misago.cache.models import CacheVersion
-from misago.cache.test import assert_invalidates_cache
-from misago.cache.versions import invalidate_cache
+from ..models import CacheVersion
+from ..test import assert_invalidates_cache
+from ..versions import invalidate_cache
 
 
 def test_assertion_fails_if_specified_cache_is_not_invaldiated(cache_version):

+ 1 - 1
misago/cache/tests/test_cache_versions_middleware.py

@@ -2,7 +2,7 @@ from unittest.mock import Mock
 
 import pytest
 
-from misago.cache.middleware import cache_versions_middleware
+from ..middleware import cache_versions_middleware
 
 
 @pytest.fixture

+ 1 - 1
misago/cache/tests/test_getting_cache_versions.py

@@ -1,4 +1,4 @@
-from misago.cache.versions import (
+from ..versions import (
     CACHE_NAME,
     get_cache_versions,
     get_cache_versions_from_cache,

+ 2 - 2
misago/cache/tests/test_invalidating_caches.py

@@ -1,7 +1,7 @@
 import pytest
 
-from misago.cache.versions import CACHE_NAME, invalidate_cache, invalidate_all_caches
-from misago.cache.models import CacheVersion
+from ..models import CacheVersion
+from ..versions import CACHE_NAME, invalidate_all_caches, invalidate_cache
 
 
 @pytest.fixture

+ 4 - 6
misago/categories/forms.py

@@ -1,15 +1,13 @@
-from mptt.forms import TreeNodeChoiceField, TreeNodeMultipleChoiceField
-
 from django import forms
 from django.db import models
 from django.utils.html import conditional_escape, mark_safe
 from django.utils.translation import gettext_lazy as _
-
-from misago.admin.forms import YesNoSwitch
-from misago.core.validators import validate_sluggable
-from misago.threads.threadtypes import trees_map
+from mptt.forms import TreeNodeChoiceField, TreeNodeMultipleChoiceField
 
 from . import THREADS_ROOT_NAME
+from ..admin.forms import YesNoSwitch
+from ..core.validators import validate_sluggable
+from ..threads.threadtypes import trees_map
 from .models import Category, CategoryRole
 
 

+ 2 - 2
misago/categories/management/commands/fixcategoriestree.py

@@ -1,7 +1,7 @@
 from django.core.management.base import BaseCommand
 
-from misago.acl.cache import clear_acl_cache
-from misago.categories.models import Category
+from ....acl.cache import clear_acl_cache
+from ...models import Category
 
 
 class Command(BaseCommand):

+ 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.utils import timezone
 
-from misago.categories.models import Category
+from ...models import Category
 
 
 class Command(BaseCommand):

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

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

+ 2 - 3
misago/categories/migrations/0001_initial.py

@@ -1,11 +1,10 @@
-import mptt.fields
-
 import django.db.models.deletion
+import mptt.fields
 from django.conf import settings
 from django.contrib.postgres.fields import JSONField
 from django.db import migrations, models
 
-from misago.acl.models import permissions_default
+from ...acl.models import permissions_default
 
 
 class Migration(migrations.Migration):

+ 1 - 2
misago/categories/migrations/0002_default_categories.py

@@ -1,7 +1,6 @@
 from django.db import migrations
 
-from misago.core.utils import slugify
-
+from ...core.utils import slugify
 
 _ = lambda s: s
 

+ 0 - 1
misago/categories/migrations/0003_categories_roles.py

@@ -1,6 +1,5 @@
 from django.db import migrations
 
-
 _ = lambda s: s
 
 

+ 0 - 1
misago/categories/migrations/0006_moderation_queue_roles.py

@@ -1,6 +1,5 @@
 from django.db import migrations
 
-
 _ = lambda s: s
 
 

+ 0 - 1
misago/categories/migrations/0007_best_answers_roles.py

@@ -1,7 +1,6 @@
 # Generated by Django 1.11.9 on 2018-03-18 20:40
 from django.db import migrations
 
-
 _ = lambda s: s
 
 

+ 7 - 9
misago/categories/models.py

@@ -1,16 +1,14 @@
+from django.db import models
 from mptt.managers import TreeManager
 from mptt.models import MPTTModel, TreeForeignKey
 
-from django.db import models
-
-from misago.acl.cache import clear_acl_cache
-from misago.acl.models import BaseRole
-from misago.conf import settings
-from misago.core.cache import cache
-from misago.core.utils import slugify
-from misago.threads.threadtypes import trees_map
-
 from . import PRIVATE_THREADS_ROOT_NAME, THREADS_ROOT_NAME
+from ..acl.cache import clear_acl_cache
+from ..acl.models import BaseRole
+from ..conf import settings
+from ..core.cache import cache
+from ..core.utils import slugify
+from ..threads.threadtypes import trees_map
 
 CACHE_NAME = "misago_categories_tree"
 

+ 4 - 5
misago/categories/permissions.py

@@ -4,11 +4,10 @@ from django.core.exceptions import PermissionDenied
 from django.http import Http404
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl import algebra
-from misago.acl.decorators import return_boolean
-from misago.admin.forms import YesNoSwitch
-from misago.users.models import AnonymousUser
-
+from ..acl import algebra
+from ..acl.decorators import return_boolean
+from ..admin.forms import YesNoSwitch
+from ..users.models import AnonymousUser
 from .models import Category, CategoryRole, RoleCategoryACL
 
 

+ 3 - 6
misago/categories/serializers.py

@@ -1,13 +1,10 @@
-from rest_framework import serializers
-
 from django.urls import reverse
+from rest_framework import serializers
 
-from misago.core.serializers import MutableFields
-from misago.core.utils import format_plaintext_for_html
-
+from ..core.serializers import MutableFields
+from ..core.utils import format_plaintext_for_html
 from .models import Category
 
-
 __all__ = ["CategorySerializer"]
 
 

+ 1 - 3
misago/categories/signals.py

@@ -1,10 +1,8 @@
 from django.dispatch import Signal, receiver
 
-from misago.users.signals import anonymize_user_data, username_changed
-
+from ..users.signals import anonymize_user_data, username_changed
 from .models import Category
 
-
 delete_category_content = Signal()
 move_category_content = Signal(providing_args=["new_category"])
 

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

@@ -1,11 +1,11 @@
 from django.urls import reverse
 
-from misago.acl import ACL_CACHE
-from misago.admin.test import AdminTestCase
-from misago.cache.test import assert_invalidates_cache
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.models import Thread
+from ...acl import ACL_CACHE
+from ...admin.test import AdminTestCase
+from ...cache.test import assert_invalidates_cache
+from ...threads import test
+from ...threads.models import Thread
+from ..models import Category
 
 
 class CategoryAdminTestCase(AdminTestCase):

+ 4 - 4
misago/categories/tests/test_category_model.py

@@ -1,9 +1,9 @@
 from django.test import TestCase
 
-from misago.categories import THREADS_ROOT_NAME
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.threadtypes import trees_map
+from .. import THREADS_ROOT_NAME
+from ...threads import test
+from ...threads.threadtypes import trees_map
+from ..models import Category
 
 
 class CategoryManagerTests(TestCase):

+ 4 - 4
misago/categories/tests/test_fixcategoriestree.py

@@ -3,10 +3,10 @@ from io import StringIO
 from django.core.management import call_command
 from django.test import TestCase
 
-from misago.acl import ACL_CACHE
-from misago.cache.test import assert_invalidates_cache
-from misago.categories.management.commands import fixcategoriestree
-from misago.categories.models import Category
+from ...acl import ACL_CACHE
+from ...cache.test import assert_invalidates_cache
+from ..management.commands import fixcategoriestree
+from ..models import Category
 
 
 def run_command():

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

@@ -1,11 +1,11 @@
 from django.urls import reverse
 
-from misago.acl import ACL_CACHE
-from misago.acl.models import Role
-from misago.acl.test import mock_role_form_data
-from misago.admin.test import AdminTestCase
-from misago.cache.test import assert_invalidates_cache
-from misago.categories.models import Category, CategoryRole
+from ...acl import ACL_CACHE
+from ...acl.models import Role
+from ...acl.test import mock_role_form_data
+from ...admin.test import AdminTestCase
+from ...cache.test import assert_invalidates_cache
+from ..models import Category, CategoryRole
 
 
 def create_data(data_dict):

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

@@ -5,9 +5,9 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.categories.management.commands import prunecategories
-from misago.categories.models import Category
-from misago.threads import test
+from ...threads import test
+from ..management.commands import prunecategories
+from ..models import Category
 
 
 class PruneCategoriesTests(TestCase):

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

@@ -3,9 +3,9 @@ from io import StringIO
 from django.core.management import call_command
 from django.test import TestCase
 
-from misago.categories.management.commands import synchronizecategories
-from misago.categories.models import Category
-from misago.threads import test
+from ...threads import test
+from ..management.commands import synchronizecategories
+from ..models import Category
 
 
 class SynchronizeCategoriesTests(TestCase):

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

@@ -1,8 +1,8 @@
-from misago.acl.useracl import get_user_acl
-from misago.categories.models import Category
-from misago.categories.utils import get_categories_tree, get_category_path
-from misago.conftest import get_cache_versions
-from misago.users.test import AuthenticatedUserTestCase
+from ...acl.useracl import get_user_acl
+from ...conftest import get_cache_versions
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Category
+from ..utils import get_categories_tree, get_category_path
 
 cache_versions = get_cache_versions()
 

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

@@ -2,9 +2,9 @@ import json
 
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.users.test import AuthenticatedUserTestCase
+from ...acl.test import patch_user_acl
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Category
 
 
 class CategoryViewsTests(AuthenticatedUserTestCase):

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

@@ -1,9 +1,9 @@
 from django.conf.urls import url
 
-from misago.conf import settings
-from misago.core.views import home_redirect
+from ...conf import settings
+from ...core.views import home_redirect
 
-from misago.categories.views.categorieslist import categories
+from ..views.categorieslist import categories
 
 if settings.MISAGO_THREADS_ON_INDEX:
     URL_PATH = r"^categories/$"

+ 2 - 3
misago/categories/urls/api.py

@@ -1,6 +1,5 @@
-from misago.categories.api import CategoryViewSet
-from misago.core.apirouter import MisagoApiRouter
-
+from ...core.apirouter import MisagoApiRouter
+from ..api import CategoryViewSet
 
 router = MisagoApiRouter()
 router.register(r"categories", CategoryViewSet, base_name="category")

+ 2 - 3
misago/categories/utils.py

@@ -1,6 +1,5 @@
-from misago.acl.objectacl import add_acl_to_obj
-from misago.readtracker import categoriestracker
-
+from ..acl.objectacl import add_acl_to_obj
+from ..readtracker import categoriestracker
 from .models import Category
 
 

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

@@ -2,12 +2,12 @@ from django.contrib import messages
 from django.shortcuts import redirect
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl.cache import clear_acl_cache
-from misago.admin.views import generic
-from misago.categories import THREADS_ROOT_NAME
-from misago.categories.forms import CategoryFormFactory, DeleteFormFactory
-from misago.categories.models import Category, RoleCategoryACL
-from misago.threads.threadtypes import trees_map
+from .. import THREADS_ROOT_NAME
+from ...acl.cache import clear_acl_cache
+from ...admin.views import generic
+from ...threads.threadtypes import trees_map
+from ..forms import CategoryFormFactory, DeleteFormFactory
+from ..models import Category, RoleCategoryACL
 
 
 class CategoryAdmin(generic.AdminBaseMixin):

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

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

+ 7 - 8
misago/categories/views/permsadmin.py

@@ -2,18 +2,17 @@ from django.contrib import messages
 from django.shortcuts import redirect
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl.cache import clear_acl_cache
-from misago.acl.forms import get_permissions_forms
-from misago.acl.models import Role
-from misago.acl.views import RoleAdmin, RolesList
-from misago.admin.views import generic
-from misago.categories.forms import (
+from ...acl.cache import clear_acl_cache
+from ...acl.forms import get_permissions_forms
+from ...acl.models import Role
+from ...acl.views import RoleAdmin, RolesList
+from ...admin.views import generic
+from ..forms import (
     CategoryRoleForm,
     CategoryRolesACLFormFactory,
     RoleCategoryACLFormFactory,
 )
-from misago.categories.models import Category, CategoryRole, RoleCategoryACL
-
+from ..models import Category, CategoryRole, RoleCategoryACL
 from .categoriesadmin import CategoriesList, CategoryAdmin
 
 

+ 1 - 2
misago/conf/cache.py

@@ -1,8 +1,7 @@
 from django.core.cache import cache
 
-from misago.cache.versions import invalidate_cache
-
 from . import SETTINGS_CACHE
+from ..cache.versions import invalidate_cache
 
 
 def get_settings_cache(cache_versions):

+ 1 - 2
misago/conf/context_processors.py

@@ -2,9 +2,8 @@ from django.contrib.staticfiles.templatetags.staticfiles import static
 from django.urls import reverse
 from django.utils.translation import get_language
 
-from misago.users.social.utils import get_enabled_social_auth_sites_list
-
 from . import settings
+from ..users.social.utils import get_enabled_social_auth_sites_list
 
 BLANK_AVATAR_URL = static(settings.MISAGO_BLANK_AVATAR)
 

+ 1 - 1
misago/conf/forms.py

@@ -2,7 +2,7 @@ from django import forms
 from django.utils.translation import gettext as _
 from django.utils.translation import ngettext
 
-from misago.admin.forms import YesNoSwitch
+from ..admin.forms import YesNoSwitch
 
 __all__ = ["ChangeSettingsForm"]
 

+ 2 - 3
misago/conf/migrations/0002_cache_version.py

@@ -1,9 +1,8 @@
 # Generated by Django 1.11.16 on 2018-12-02 15:54
 from django.db import migrations
 
-from misago.cache.operations import StartCacheVersioning
-
-from misago.conf import SETTINGS_CACHE
+from .. import SETTINGS_CACHE
+from ...cache.operations import StartCacheVersioning
 
 
 class Migration(migrations.Migration):

+ 1 - 1
misago/conf/test.py

@@ -1,6 +1,6 @@
 from functools import wraps
 
-from misago.conf.dynamicsettings import DynamicSettings
+from .dynamicsettings import DynamicSettings
 
 
 class override_dynamic_settings:

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

@@ -1,6 +1,6 @@
 import pytest
 
-from misago.conf.models import Setting, SettingsGroup
+from ..models import Setting, SettingsGroup
 
 
 @pytest.fixture

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

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

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

@@ -2,7 +2,7 @@ from unittest.mock import Mock
 
 import pytest
 
-from misago.conf.context_processors import conf
+from ..context_processors import conf
 
 
 def test_request_settings_are_included_in_template_context(db, dynamic_settings):

+ 1 - 2
misago/conf/tests/test_dynamic_settings_middleware.py

@@ -1,10 +1,9 @@
 from unittest.mock import Mock, PropertyMock
 
 import pytest
-
 from django.utils.functional import SimpleLazyObject
 
-from misago.conf.middleware import dynamic_settings_middleware
+from ..middleware import dynamic_settings_middleware
 
 
 @pytest.fixture

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

@@ -1,7 +1,7 @@
 import pytest
 
-from misago.conf import SETTINGS_CACHE
-from misago.conf.dynamicsettings import DynamicSettings
+from .. import SETTINGS_CACHE
+from ..dynamicsettings import DynamicSettings
 
 
 def test_settings_are_loaded_from_database_if_cache_is_not_available(

+ 0 - 1
misago/conf/tests/test_getting_static_settings_values.py

@@ -1,5 +1,4 @@
 import pytest
-
 from django.test import override_settings
 
 

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

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

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

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

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

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

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

@@ -1,7 +1,7 @@
 import pytest
 
-from misago.conf.dynamicsettings import DynamicSettings
-from misago.conf.test import override_dynamic_settings
+from ..dynamicsettings import DynamicSettings
+from ..test import override_dynamic_settings
 
 
 def test_dynamic_setting_can_be_overridden_using_context_manager(dynamic_settings):

+ 1 - 2
misago/conf/views.py

@@ -2,8 +2,7 @@ from django.contrib import messages
 from django.shortcuts import redirect
 from django.utils.translation import gettext as _
 
-from misago.admin.views import render as mi_render
-
+from ..admin.views import render as mi_render
 from .cache import clear_settings_cache
 from .forms import ChangeSettingsForm
 from .models import SettingsGroup

+ 7 - 7
misago/conftest.py

@@ -1,12 +1,12 @@
 import pytest
 
-from misago.acl import ACL_CACHE, useracl
-from misago.conf import SETTINGS_CACHE
-from misago.conf.dynamicsettings import DynamicSettings
-from misago.conf.staticsettings import StaticSettings
-from misago.users import BANS_CACHE
-from misago.users.models import AnonymousUser
-from misago.users.test import create_test_superuser, create_test_user
+from .acl import ACL_CACHE, useracl
+from .conf import SETTINGS_CACHE
+from .conf.dynamicsettings import DynamicSettings
+from .conf.staticsettings import StaticSettings
+from .users import BANS_CACHE
+from .users.models import AnonymousUser
+from .users.test import create_test_superuser, create_test_user
 
 
 def get_cache_versions():

+ 1 - 3
misago/core/apipatch.py

@@ -1,9 +1,7 @@
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.db import transaction
 from django.http import Http404
-
+from rest_framework.response import Response
 
 ALLOWED_OPS = ("add", "remove", "replace")
 

+ 2 - 2
misago/core/cache.py

@@ -1,6 +1,6 @@
+from django.core.cache import InvalidCacheBackendError
 from django.core.cache import cache as default_cache
-from django.core.cache import InvalidCacheBackendError, caches
-
+from django.core.cache import caches
 
 try:
     cache = caches["misago"]

+ 3 - 4
misago/core/errorpages.py

@@ -3,10 +3,9 @@ from django.shortcuts import render
 from django.utils.translation import gettext as _
 from social_core import exceptions as social_exceptions
 
-from misago.admin.views.errorpages import admin_csrf_failure, admin_error_page
-from misago.core.exceptions import SocialAuthFailed, SocialAuthBanned
-from misago.users.social.utils import get_social_auth_backend_name
-
+from ..admin.views.errorpages import admin_csrf_failure, admin_error_page
+from ..users.social.utils import get_social_auth_backend_name
+from .exceptions import SocialAuthBanned, SocialAuthFailed
 from .utils import get_exception_message, is_request_to_misago
 
 

+ 1 - 3
misago/core/exceptionhandler.py

@@ -1,15 +1,13 @@
-from rest_framework.views import exception_handler as rest_exception_handler
-
 from django.core.exceptions import PermissionDenied
 from django.http import Http404, HttpResponsePermanentRedirect, JsonResponse
 from django.urls import reverse
+from rest_framework.views import exception_handler as rest_exception_handler
 from social_core.exceptions import SocialAuthBaseException
 from social_core.utils import social_logger
 
 from . import errorpages
 from .exceptions import AjaxError, Banned, ExplicitFirstPage, OutdatedSlug
 
-
 HANDLED_EXCEPTIONS = (
     AjaxError,
     Banned,

+ 1 - 2
misago/core/mail.py

@@ -2,8 +2,7 @@ from django.core import mail as djmail
 from django.template.loader import render_to_string
 from django.utils.translation import get_language
 
-from misago.conf import settings
-
+from ..conf import settings
 from .utils import get_host_from_address
 
 

+ 2 - 2
misago/core/middleware.py

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

+ 1 - 2
misago/core/migrations/0002_basic_settings.py

@@ -1,7 +1,6 @@
 from django.db import migrations
 
-from misago.conf.migrationutils import migrate_settings_group
-
+from ...conf.migrationutils import migrate_settings_group
 
 _ = lambda s: s
 

+ 1 - 2
misago/core/momentjs.py

@@ -1,5 +1,4 @@
-from misago.conf import settings
-
+from ..conf import settings
 
 MOMENT_STATIC_PATH = "misago/momentjs/%s.js"
 

+ 1 - 2
misago/core/rest_permissions.py

@@ -1,7 +1,6 @@
-from rest_framework.permissions import SAFE_METHODS, BasePermission
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
+from rest_framework.permissions import SAFE_METHODS, BasePermission
 
 
 class IsAuthenticatedOrReadOnly(BasePermission):

+ 1 - 2
misago/core/shortcuts.py

@@ -1,6 +1,5 @@
-from rest_framework.response import Response
-
 from django.http import Http404
+from rest_framework.response import Response
 
 
 def paginate(

+ 1 - 2
misago/core/slugify.py

@@ -1,6 +1,5 @@
-from unidecode import unidecode
-
 from django.template.defaultfilters import slugify as django_slugify
+from unidecode import unidecode
 
 
 def default(string):

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

@@ -1,7 +1,7 @@
 from django import template
 from django.urls import NoReverseMatch, reverse
 
-from misago.conf import settings
+from ...conf import settings
 
 register = template.Library()
 

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

@@ -1,6 +1,5 @@
 from django import template
 
-
 register = template.Library()
 
 

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

@@ -9,7 +9,6 @@ Syntax:
 
 from django import template
 
-
 register = template.Library()
 SYNTAX_ERROR = 'capture tag syntax is "capture [trimmed] as [value]"'
 

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

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

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

@@ -1,7 +1,6 @@
 from django import template
 from django.utils.translation import gettext as _
 
-
 register = template.Library()
 
 

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

@@ -1,6 +1,5 @@
 from django import template
 
-
 register = template.Library()
 
 

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

@@ -1,6 +1,5 @@
 from django import template
 
-
 register = template.Library()
 
 

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

@@ -7,10 +7,8 @@ from django.views.decorators.cache import cache_page
 from django.views.decorators.http import last_modified
 from django.views.i18n import JavaScriptCatalog
 
-from misago.users.forms.auth import AdminAuthenticationForm
-
 from . import views
-
+from ...users.forms.auth import AdminAuthenticationForm
 
 admin.autodiscover()
 admin.site.login_form = AdminAuthenticationForm

+ 0 - 1
misago/core/testproject/urlswitherrorhandlers.py

@@ -1,5 +1,4 @@
 from .urls import *
 
-
 handler403 = "misago.core.testproject.views.mock_custom_403_error_page"
 handler404 = "misago.core.testproject.views.mock_custom_404_error_page"

+ 8 - 10
misago/core/testproject/views.py

@@ -1,17 +1,15 @@
-from rest_framework.decorators import api_view
-
 from django.core.exceptions import PermissionDenied
 from django.http import Http404, HttpResponse
-from social_core.exceptions import AuthFailed, NotAllowedToDisconnect, WrongBackend
+from rest_framework.decorators import api_view
 from social_core.backends.github import GithubOAuth2
+from social_core.exceptions import AuthFailed, NotAllowedToDisconnect, WrongBackend
 
-from misago.core import errorpages
-from misago.core.decorators import require_POST
-from misago.core.exceptions import Banned, SocialAuthBanned, SocialAuthFailed
-from misago.core.shortcuts import paginate, paginated_response, validate_slug
-from misago.core.views import home_redirect
-from misago.users.models import Ban
-
+from .. import errorpages
+from ...users.models import Ban
+from ..decorators import require_POST
+from ..exceptions import Banned, SocialAuthBanned, SocialAuthFailed
+from ..shortcuts import paginate, paginated_response, validate_slug
+from ..views import home_redirect
 from .models import Model
 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.test import TestCase
 
-from misago.core.apipatch import ApiPatch, InvalidAction
+from ..apipatch import ApiPatch, InvalidAction
 
 
 class MockRequest(object):

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

@@ -2,8 +2,7 @@ import warnings
 
 from django.test import TestCase
 
-from misago.core import SUPPORTED_ENGINES, check_db_engine
-
+from .. import SUPPORTED_ENGINES, check_db_engine
 
 INVALID_ENGINES = [
     "django.db.backends.sqlite3",

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

@@ -1,7 +1,7 @@
 from django.test import TestCase
 
-from misago.core.models import CacheVersion
-from misago.core.pgutils import chunk_queryset
+from ..models import CacheVersion
+from ..pgutils import chunk_queryset
 
 
 class ChunkQuerysetTest(TestCase):

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

@@ -1,4 +1,4 @@
-from misago.users.test import AuthenticatedUserTestCase
+from ...users.test import AuthenticatedUserTestCase
 
 
 class CommonMiddlewareRedirectTests(AuthenticatedUserTestCase):

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

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

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

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

+ 6 - 9
misago/core/tests/test_errorpages.py

@@ -4,15 +4,12 @@ from django.test import Client, TestCase, override_settings
 from django.test.client import RequestFactory
 from django.urls import reverse
 
-from misago.acl.useracl import get_user_acl
-from misago.users.models import AnonymousUser
-from misago.conf.dynamicsettings import DynamicSettings
-from misago.conftest import get_cache_versions
-from misago.core.testproject.views import (
-    mock_custom_403_error_page,
-    mock_custom_404_error_page,
-)
-from misago.core.utils import encode_json_html
+from ...acl.useracl import get_user_acl
+from ...conf.dynamicsettings import DynamicSettings
+from ...conftest import get_cache_versions
+from ...users.models import AnonymousUser
+from ..testproject.views import mock_custom_403_error_page, mock_custom_404_error_page
+from ..utils import encode_json_html
 
 
 class CSRFErrorViewTests(TestCase):

+ 5 - 7
misago/core/tests/test_exceptionhandler_middleware.py

@@ -3,13 +3,11 @@ from django.test import TestCase
 from django.test.client import RequestFactory
 from django.urls import reverse
 
-from misago.acl.useracl import get_user_acl
-from misago.conf.dynamicsettings import DynamicSettings
-from misago.core.middleware import ExceptionHandlerMiddleware
-from misago.conftest import get_cache_versions
-from misago.users.models import AnonymousUser
-
-from misago.core.middleware import ExceptionHandlerMiddleware
+from ...acl.useracl import get_user_acl
+from ...conf.dynamicsettings import DynamicSettings
+from ...conftest import get_cache_versions
+from ...users.models import AnonymousUser
+from ..middleware import ExceptionHandlerMiddleware
 
 
 def create_request():

+ 3 - 4
misago/core/tests/test_exceptionhandlers.py

@@ -3,10 +3,9 @@ from django.core.exceptions import PermissionDenied
 from django.http import Http404
 from django.test import TestCase
 
-from misago.core import exceptionhandler
-from misago.core.exceptions import Banned
-from misago.users.models import Ban
-
+from .. import exceptionhandler
+from ...users.models import Ban
+from ..exceptions import Banned
 
 INVALID_EXCEPTIONS = [
     django_exceptions.ObjectDoesNotExist,

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

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

+ 0 - 1
misago/core/tests/test_jsi18n.py

@@ -5,7 +5,6 @@ from django.test import TestCase
 from django.urls import reverse
 from django.utils import translation
 
-
 MISAGO_DIR = os.path.dirname(
     os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 )

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

@@ -2,10 +2,10 @@ from django.core import mail
 from django.test import TestCase
 from django.urls import reverse
 
-from misago.cache.versions import get_cache_versions
-from misago.conf.dynamicsettings import DynamicSettings
-from misago.core.mail import build_mail, mail_user, mail_users
-from misago.users.test import create_test_user
+from ...cache.versions import get_cache_versions
+from ...conf.dynamicsettings import DynamicSettings
+from ...users.test import create_test_user
+from ..mail import build_mail, mail_user, mail_users
 
 
 class MailTests(TestCase):

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

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

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

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

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

@@ -1,9 +1,8 @@
 from django.db import connection
 from django.test import TestCase
 
-from misago.threads.models import Thread
-
-from misago.core.pgutils import PgPartialIndex
+from ...threads.models import Thread
+from ..pgutils import PgPartialIndex
 
 
 class PgPartialIndexTests(TestCase):

+ 5 - 6
misago/core/tests/test_serializers.py

@@ -1,11 +1,10 @@
-from rest_framework import serializers
-
 from django.test import TestCase
+from rest_framework import serializers
 
-from misago.categories.models import Category
-from misago.core.serializers import MutableFields
-from misago.threads import test
-from misago.threads.models import Thread
+from ...categories.models import Category
+from ...threads import test
+from ...threads.models import Thread
+from ..serializers import MutableFields
 
 
 class Serializer(serializers.ModelSerializer, MutableFields):

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

@@ -3,7 +3,7 @@ import os
 from django.test import TestCase
 from django.utils.encoding import smart_str
 
-from misago.core import setup
+from .. import setup
 
 
 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.urls import reverse
 
-from misago.core.shortcuts import get_int_or_404
+from ..shortcuts import get_int_or_404
 
 
 @override_settings(ROOT_URLCONF="misago.core.testproject.urls")

+ 10 - 11
misago/core/tests/test_templatetags.py

@@ -1,9 +1,8 @@
 from django.template import Context, Template
 from django.test import TestCase, override_settings
 
-from misago.core.templatetags import misago_batch
-from misago.core.templatetags.misago_absoluteurl import absoluteurl
-
+from ..templatetags.misago_absoluteurl import absoluteurl
+from ..templatetags.misago_batch import batch, batchnonefilled
 
 TEST_ADDRESS = "https://testsite.com/"
 
@@ -74,19 +73,19 @@ Hello, <b>{{ the_var|safe }}</b>
 class BatchTests(TestCase):
     def test_batch(self):
         """standard batch yields valid results"""
-        batch = "loremipsum"
-        yields = [["l", "o", "r"], ["e", "m", "i"], ["p", "s", "u"], ["m"]]
+        value = "loremipsum"
+        result = [["l", "o", "r"], ["e", "m", "i"], ["p", "s", "u"], ["m"]]
 
-        for i, test_yield in enumerate(misago_batch.batch(batch, 3)):
-            self.assertEqual(test_yield, yields[i])
+        for i, test_result in enumerate(batch(value, 3)):
+            self.assertEqual(test_result, result[i])
 
     def test_batchnonefilled(self):
         """none-filled batch yields valid results"""
-        batch = "loremipsum"
-        yields = [["l", "o", "r"], ["e", "m", "i"], ["p", "s", "u"], ["m", None, None]]
+        value = "loremipsum"
+        result = [["l", "o", "r"], ["e", "m", "i"], ["p", "s", "u"], ["m", None, None]]
 
-        for i, test_yield in enumerate(misago_batch.batchnonefilled(batch, 3)):
-            self.assertEqual(test_yield, yields[i])
+        for i, test_result in enumerate(batchnonefilled(value, 3)):
+            self.assertEqual(test_result, result[i])
 
 
 class MockUser(object):

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

@@ -3,16 +3,16 @@ from django.test import TestCase
 from django.test.client import RequestFactory
 from django.urls import reverse
 
-from misago.core.utils import (
+from ..utils import (
+    clean_ids_list,
     clean_return_path,
     format_plaintext_for_html,
+    get_exception_message,
+    get_host_from_address,
     is_referer_local,
     is_request_to_misago,
     parse_iso8601_string,
     slugify,
-    get_exception_message,
-    clean_ids_list,
-    get_host_from_address,
 )
 
 

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

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

+ 0 - 1
misago/core/utils.py

@@ -8,7 +8,6 @@ from django.utils import html, timezone
 from django.utils.encoding import force_text
 from django.utils.module_loading import import_string
 
-
 MISAGO_SLUGIFY = getattr(settings, "MISAGO_SLUGIFY", "misago.core.slugify.default")
 
 slugify = import_string(MISAGO_SLUGIFY)

+ 0 - 1
misago/faker/englishcorpus.py

@@ -1,7 +1,6 @@
 import os
 import random
 
-
 PHRASES_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "phrases.txt")
 
 

+ 3 - 4
misago/faker/management/commands/createfakebans.py

@@ -2,13 +2,12 @@ import random
 import sys
 from datetime import timedelta
 
-from faker import Factory
-
 from django.core.management.base import BaseCommand
 from django.utils import timezone
+from faker import Factory
 
-from misago.core.management.progressbar import show_progress
-from misago.users.models import Ban
+from ....core.management.progressbar import show_progress
+from ....users.models import Ban
 
 
 def fake_username_ban(fake):

+ 4 - 5
misago/faker/management/commands/createfakecategories.py

@@ -1,13 +1,12 @@
 import random
 import time
 
-from faker import Factory
-
 from django.core.management.base import BaseCommand
+from faker import Factory
 
-from misago.acl.cache import clear_acl_cache
-from misago.categories.models import Category, RoleCategoryACL
-from misago.core.management.progressbar import show_progress
+from ....acl.cache import clear_acl_cache
+from ....categories.models import Category, RoleCategoryACL
+from ....core.management.progressbar import show_progress
 
 
 class Command(BaseCommand):

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

@@ -4,8 +4,7 @@ import time
 from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 
-from misago.core.management.progressbar import show_progress
-
+from ....core.management.progressbar import show_progress
 
 User = get_user_model()
 

+ 6 - 8
misago/faker/management/commands/createfakethreads.py

@@ -1,19 +1,17 @@
 import random
 import time
 
-from faker import Factory
-
 from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 from django.db.transaction import atomic
 from django.utils import timezone
+from faker import Factory
 
-from misago.categories.models import Category
-from misago.core.management.progressbar import show_progress
-from misago.faker.englishcorpus import EnglishCorpus
-from misago.threads.checksums import update_post_checksum
-from misago.threads.models import Post, Thread
-
+from ....categories.models import Category
+from ....core.management.progressbar import show_progress
+from ....threads.checksums import update_post_checksum
+from ....threads.models import Post, Thread
+from ...englishcorpus import EnglishCorpus
 
 PLACEKITTEN_URL = "https://placekitten.com/g/%s/%s"
 

+ 4 - 6
misago/faker/management/commands/createfakeusers.py

@@ -1,17 +1,15 @@
 import random
 import time
 
-from faker import Factory
-
 from django.contrib.auth import get_user_model
 from django.core.exceptions import ValidationError
 from django.core.management.base import BaseCommand
 from django.db import IntegrityError
+from faker import Factory
 
-from misago.core.management.progressbar import show_progress
-from misago.users.avatars import dynamic, gallery
-from misago.users.models import Rank
-
+from ....core.management.progressbar import show_progress
+from ....users.avatars import dynamic, gallery
+from ....users.models import Rank
 
 User = get_user_model()
 

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

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

+ 0 - 1
misago/legal/api.py

@@ -2,7 +2,6 @@ from django.contrib.auth import logout
 from django.core.exceptions import PermissionDenied
 from django.shortcuts import get_object_or_404
 from django.utils.translation import gettext as _
-
 from rest_framework.decorators import api_view
 from rest_framework.response import Response
 

+ 0 - 1
misago/legal/context_processors.py

@@ -3,7 +3,6 @@ from django.urls import reverse
 from .models import Agreement
 from .utils import get_parsed_agreement_text, get_required_user_agreement
 
-
 # fixme: rename this context processor to more suitable name
 def legal_links(request):
     agreements = Agreement.objects.get_agreements()

+ 1 - 2
misago/legal/migrations/0001_initial.py

@@ -1,7 +1,6 @@
 from django.db import migrations
 
-from misago.conf.migrationutils import migrate_settings_group
-
+from ...conf.migrationutils import migrate_settings_group
 
 _ = lambda s: s
 

+ 2 - 2
misago/legal/migrations/0002_agreement_useragreement.py

@@ -1,8 +1,8 @@
 # Generated by Django 1.11.15 on 2018-08-15 20:58
-from django.conf import settings
-from django.db import migrations, models
 import django.db.models.deletion
 import django.utils.timezone
+from django.conf import settings
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):

+ 2 - 3
misago/legal/migrations/0003_create_agreements_from_settings.py

@@ -1,9 +1,8 @@
 # Generated by Django 1.11.15 on 2018-08-16 14:22
 from django.db import migrations
 
-from misago.conf.migrationutils import migrate_settings_group
-from misago.legal.models import Agreement as MisagoAgreement
-
+from ...conf.migrationutils import migrate_settings_group
+from ..models import Agreement as MisagoAgreement
 
 _ = lambda s: s
 

+ 2 - 3
misago/legal/models.py

@@ -2,9 +2,8 @@ from django.db import models
 from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
-from misago.conf import settings
-from misago.core.cache import cache
-
+from ..conf import settings
+from ..core.cache import cache
 
 CACHE_KEY = "misago_agreements"
 

+ 1 - 2
misago/legal/signals.py

@@ -1,7 +1,6 @@
 from django.dispatch import receiver
 
-from misago.users.signals import anonymize_user_data, username_changed
-
+from ..users.signals import anonymize_user_data, username_changed
 from .models import Agreement
 
 

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

@@ -1,7 +1,7 @@
 from django.urls import reverse
 
-from misago.admin.test import AdminTestCase
-from misago.legal.models import Agreement
+from ...admin.test import AdminTestCase
+from ..models import Agreement
 
 
 class AgreementAdminViewsTests(AdminTestCase):

+ 2 - 2
misago/legal/tests/test_api.py

@@ -2,8 +2,8 @@ import json
 
 from django.urls import reverse
 
-from misago.legal.models import Agreement
-from misago.users.test import AuthenticatedUserTestCase
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Agreement
 
 
 class SubmitAgreementTests(AuthenticatedUserTestCase):

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

@@ -1,8 +1,8 @@
 from django.urls import reverse
 
-from misago.legal.context_processors import legal_links
-from misago.legal.models import Agreement
-from misago.users.test import AuthenticatedUserTestCase
+from ...users.test import AuthenticatedUserTestCase
+from ..context_processors import legal_links
+from ..models import Agreement
 
 
 class MockRequest(object):

+ 2 - 2
misago/legal/tests/test_required_agreement.py

@@ -1,7 +1,7 @@
 from django.urls import reverse
 
-from misago.legal.models import Agreement
-from misago.users.test import AuthenticatedUserTestCase
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Agreement
 
 
 class RequiredAgreementTests(AuthenticatedUserTestCase):

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

@@ -1,13 +1,13 @@
 from django.test import TestCase
 
-from misago.legal.models import Agreement, UserAgreement
-from misago.legal.utils import (
+from ...users.test import UserTestCase
+from ..models import Agreement, UserAgreement
+from ..utils import (
     get_parsed_agreement_text,
     get_required_user_agreement,
     save_user_agreement_acceptance,
     set_agreement_as_active,
 )
-from misago.users.test import UserTestCase
 
 
 class MockRequest(object):

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

@@ -1,7 +1,7 @@
 from django.test import TestCase
 from django.urls import reverse
 
-from misago.legal.models import Agreement
+from ..models import Agreement
 
 
 class PrivacyPolicyTests(TestCase):

+ 1 - 2
misago/legal/urls/__init__.py

@@ -1,7 +1,6 @@
 from django.conf.urls import url
 
-from misago.legal.views import privacy_policy, terms_of_service
-
+from ..views import privacy_policy, terms_of_service
 
 urlpatterns = [
     url(r"^privacy-policy/$", privacy_policy, name="privacy-policy"),

+ 1 - 2
misago/legal/urls/api.py

@@ -1,7 +1,6 @@
 from django.conf.urls import url
 
-from misago.legal.api import submit_agreement
-
+from ..api import submit_agreement
 
 urlpatterns = [
     url(r"^submit-agreement/(?P<pk>\d+)/$", submit_agreement, name="submit-agreement")

+ 2 - 3
misago/legal/utils.py

@@ -3,9 +3,8 @@ from hashlib import md5
 from django.conf import settings
 from django.utils.encoding import force_bytes
 
-from misago.core.cache import cache
-from misago.markup import common_flavour
-
+from ..core.cache import cache
+from ..markup import common_flavour
 from .models import Agreement, UserAgreement
 
 

+ 4 - 5
misago/legal/views/admin.py

@@ -2,11 +2,10 @@ from django.contrib import messages
 from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
-from misago.admin.views import generic
-
-from misago.legal.forms import AgreementForm, SearchAgreementsForm
-from misago.legal.models import Agreement
-from misago.legal.utils import set_agreement_as_active
+from ...admin.views import generic
+from ..forms import AgreementForm, SearchAgreementsForm
+from ..models import Agreement
+from ..utils import set_agreement_as_active
 
 
 class AgreementAdmin(generic.AdminBaseMixin):

+ 2 - 2
misago/legal/views/legal.py

@@ -1,7 +1,7 @@
 from django.shortcuts import get_object_or_404, redirect, render
 
-from misago.legal.models import Agreement
-from misago.legal.utils import get_parsed_agreement_text
+from ..models import Agreement
+from ..utils import get_parsed_agreement_text
 
 
 def legal_view(request, agreement_type):

+ 1 - 3
misago/markup/bbcode/blocks.py

@@ -1,14 +1,12 @@
 import re
 
 import markdown
+from django.utils.crypto import get_random_string
 from markdown.blockprocessors import BlockProcessor, HRProcessor
 from markdown.extensions.fenced_code import FencedBlockPreprocessor
 from markdown.preprocessors import Preprocessor
 from markdown.util import etree
 
-from django.utils.crypto import get_random_string
-
-
 QUOTE_START = get_random_string(32)
 QUOTE_END = get_random_string(32)
 

+ 0 - 1
misago/markup/finalise.py

@@ -2,7 +2,6 @@ import re
 
 from django.utils.translation import gettext as _
 
-
 HEADER_RE = re.compile(
     r"""
 <div class="quote-heading">(?P<title>.*?)</div>

+ 0 - 1
misago/markup/md/shortimgs.py

@@ -2,7 +2,6 @@ import markdown
 from markdown.inlinepatterns import LinkPattern
 from markdown.util import etree
 
-
 IMAGES_RE = r"\!(\s?)\((<.*?>|([^\)]*))\)"
 
 

+ 0 - 1
misago/markup/md/striketrough.py

@@ -1,7 +1,6 @@
 import markdown
 from markdown.inlinepatterns import SimpleTagPattern
 
-
 STRIKETROUGH_RE = r"(~{2})(.+?)\2"
 
 

+ 0 - 2
misago/markup/mentions.py

@@ -1,10 +1,8 @@
 import re
 
 from bs4 import BeautifulSoup
-
 from django.contrib.auth import get_user_model
 
-
 SUPPORTED_TAGS = ("h1", "h2", "h3", "h4", "h5", "h6", "div", "p")
 USERNAME_RE = re.compile(r"@[0-9a-z]+", re.IGNORECASE)
 MENTIONS_LIMIT = 24

+ 3 - 6
misago/markup/parser.py

@@ -3,21 +3,18 @@ import warnings
 import bleach
 import markdown
 from bs4 import BeautifulSoup
-from htmlmin.minify import html_minify
-from markdown.extensions.fenced_code import FencedCodeExtension
-
 from django.http import Http404
 from django.urls import resolve
+from htmlmin.minify import html_minify
+from markdown.extensions.fenced_code import FencedCodeExtension
 
-from misago.conf import settings
-
+from ..conf import settings
 from .bbcode import blocks, inline
 from .md.shortimgs import ShortImagesExtension
 from .md.striketrough import StriketroughExtension
 from .mentions import add_mentions
 from .pipeline import pipeline
 
-
 MISAGO_ATTACHMENT_VIEWS = ("misago:attachment", "misago:attachment-thumbnail")
 
 

+ 1 - 1
misago/markup/pipeline.py

@@ -2,7 +2,7 @@ from importlib import import_module
 
 from bs4 import BeautifulSoup
 
-from misago.conf import settings
+from ..conf import settings
 
 
 class MarkupPipeline(object):

+ 1 - 1
misago/markup/serializers.py

@@ -1,6 +1,6 @@
 from rest_framework import serializers
 
-from misago.threads.validators import validate_post_length
+from ..threads.validators import validate_post_length
 
 
 class MarkupSerializer(serializers.Serializer):

+ 0 - 1
misago/markup/templatetags/misago_editor.py

@@ -2,7 +2,6 @@ from django import template
 from django.template import Context
 from django.template.loader import get_template
 
-
 register = template.Library()
 
 

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

@@ -1,6 +1,6 @@
 from django.urls import reverse
 
-from misago.users.test import AuthenticatedUserTestCase
+from ...users.test import AuthenticatedUserTestCase
 
 
 class ParseMarkupApiTests(AuthenticatedUserTestCase):

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

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

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 
-from misago.markup.finalise import finalise_markup
+from ..finalise import finalise_markup
 
 
 class QuoteTests(TestCase):

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

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

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

@@ -1,7 +1,7 @@
 from django.test import TestCase
 
-from misago.markup.parser import parse
-from misago.users.test import create_test_user
+from ...users.test import create_test_user
+from ..parser import parse
 
 
 class MockRequest(object):

+ 0 - 1
misago/markup/urls.py

@@ -2,5 +2,4 @@ from django.conf.urls import url
 
 from .api import parse_markup
 
-
 urlpatterns = [url(r"^parse-markup/$", parse_markup, name="parse-markup")]

+ 2 - 6
misago/readtracker/categoriestracker.py

@@ -1,9 +1,5 @@
-from misago.threads.models import Post, Thread
-from misago.threads.permissions import (
-    exclude_invisible_posts,
-    exclude_invisible_threads,
-)
-
+from ..threads.models import Post, Thread
+from ..threads.permissions import exclude_invisible_posts, exclude_invisible_threads
 from .dates import get_cutoff_date
 
 

+ 1 - 1
misago/readtracker/dates.py

@@ -2,7 +2,7 @@ from datetime import timedelta
 
 from django.utils import timezone
 
-from misago.conf import settings
+from ..conf import settings
 
 
 def get_cutoff_date(user=None):

+ 2 - 2
misago/readtracker/management/commands/clearreadtracker.py

@@ -1,7 +1,7 @@
 from django.core.management.base import BaseCommand
 
-from misago.readtracker.dates import get_cutoff_date
-from misago.readtracker.models import PostRead
+from ...dates import get_cutoff_date
+from ...models import PostRead
 
 
 class Command(BaseCommand):

+ 2 - 2
misago/readtracker/migrations/0002_postread.py

@@ -1,8 +1,8 @@
 # Generated by Django 1.11.5 on 2017-10-07 14:32
-from django.conf import settings
-from django.db import migrations, models
 import django.db.models.deletion
 import django.utils.timezone
+from django.conf import settings
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):

+ 2 - 3
misago/readtracker/migrations/0003_migrate_reads_to_posts.py

@@ -1,12 +1,11 @@
 # Generated by Django 1.11.5 on 2017-10-07 14:49
 from datetime import timedelta
 
-from django.db import migrations
 from django.conf import settings
+from django.db import migrations
 from django.utils import timezone
 
-from misago.conf import defaults
-
+from ...conf import defaults
 
 try:
     READS_CUTOFF = settings.MISAGO_READTRACKER_CUTOFF

+ 3 - 4
misago/readtracker/signals.py

@@ -1,9 +1,8 @@
 from django.dispatch import Signal, receiver
 
-from misago.categories import PRIVATE_THREADS_ROOT_NAME
-from misago.categories.signals import delete_category_content, move_category_content
-from misago.threads.signals import merge_thread, move_thread, merge_post, move_post
-
+from ..categories import PRIVATE_THREADS_ROOT_NAME
+from ..categories.signals import delete_category_content, move_category_content
+from ..threads.signals import merge_post, merge_thread, move_post, move_thread
 
 thread_read = Signal(providing_args=["thread"])
 

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

@@ -3,14 +3,14 @@ from datetime import timedelta
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.acl.useracl import get_user_acl
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.conftest import get_cache_versions
-from misago.readtracker import poststracker, categoriestracker
-from misago.readtracker.models import PostRead
-from misago.threads import test
-from misago.users.test import create_test_user
+from .. import categoriestracker, poststracker
+from ...acl.useracl import get_user_acl
+from ...categories.models import Category
+from ...conf import settings
+from ...conftest import get_cache_versions
+from ...threads import test
+from ...users.test import create_test_user
+from ..models import PostRead
 
 cache_versions = get_cache_versions()
 

+ 6 - 6
misago/readtracker/tests/test_clearreadtracker.py

@@ -5,12 +5,12 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.readtracker.management.commands import clearreadtracker
-from misago.readtracker.models import PostRead
-from misago.threads import test
-from misago.users.test import create_test_user
+from ...categories.models import Category
+from ...conf import settings
+from ...threads import test
+from ...users.test import create_test_user
+from ..management.commands import clearreadtracker
+from ..models import PostRead
 
 
 class ClearReadTrackerTests(TestCase):

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

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

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

@@ -3,12 +3,12 @@ from datetime import timedelta
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.readtracker import poststracker
-from misago.readtracker.models import PostRead
-from misago.threads import test
-from misago.users.test import create_test_user
+from ...categories.models import Category
+from ...conf import settings
+from ...threads import test
+from ...users.test import create_test_user
+from ..models import PostRead
+from ..poststracker import make_read_aware, save_read
 
 
 class AnonymousUser(object):
@@ -24,16 +24,16 @@ class PostsTrackerTests(TestCase):
 
     def test_falsy_value(self):
         """passing falsy value to readtracker causes no errors"""
-        poststracker.make_read_aware(self.user, None)
-        poststracker.make_read_aware(self.user, False)
-        poststracker.make_read_aware(self.user, [])
+        make_read_aware(self.user, None)
+        make_read_aware(self.user, False)
+        make_read_aware(self.user, [])
 
     def test_anon_post_before_cutoff(self):
         """non-tracked post is marked as read for anonymous users"""
         posted_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         post = test.reply_thread(self.thread, posted_on=posted_on)
 
-        poststracker.make_read_aware(AnonymousUser(), post)
+        make_read_aware(AnonymousUser(), post)
         self.assertTrue(post.is_read)
         self.assertFalse(post.is_new)
 
@@ -41,7 +41,7 @@ class PostsTrackerTests(TestCase):
         """tracked post is marked as read for anonymous users"""
         post = test.reply_thread(self.thread, posted_on=timezone.now())
 
-        poststracker.make_read_aware(AnonymousUser(), post)
+        make_read_aware(AnonymousUser(), post)
         self.assertTrue(post.is_read)
         self.assertFalse(post.is_new)
 
@@ -50,7 +50,7 @@ class PostsTrackerTests(TestCase):
         posted_on = timezone.now() - timedelta(days=settings.MISAGO_READTRACKER_CUTOFF)
         post = test.reply_thread(self.thread, posted_on=posted_on)
 
-        poststracker.make_read_aware(self.user, post)
+        make_read_aware(self.user, post)
         self.assertTrue(post.is_read)
         self.assertFalse(post.is_new)
 
@@ -58,7 +58,7 @@ class PostsTrackerTests(TestCase):
         """tracked post is marked as unread for authenticated users"""
         post = test.reply_thread(self.thread, posted_on=timezone.now())
 
-        poststracker.make_read_aware(self.user, post)
+        make_read_aware(self.user, post)
         self.assertFalse(post.is_read)
         self.assertTrue(post.is_new)
 
@@ -67,7 +67,7 @@ class PostsTrackerTests(TestCase):
         posted_on = timezone.now() - timedelta(days=1)
         post = test.reply_thread(self.thread, posted_on=posted_on)
 
-        poststracker.make_read_aware(self.user, post)
+        make_read_aware(self.user, post)
         self.assertTrue(post.is_read)
         self.assertFalse(post.is_new)
 
@@ -75,8 +75,8 @@ class PostsTrackerTests(TestCase):
         """tracked post is marked as read for authenticated users with read entry"""
         post = test.reply_thread(self.thread, posted_on=timezone.now())
 
-        poststracker.save_read(self.user, post)
-        poststracker.make_read_aware(self.user, post)
+        save_read(self.user, post)
+        make_read_aware(self.user, post)
 
         self.assertTrue(post.is_read)
         self.assertFalse(post.is_new)

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

@@ -3,15 +3,15 @@ from datetime import timedelta
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.acl.useracl import get_user_acl
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.conftest import get_cache_versions
-from misago.readtracker import poststracker, threadstracker
-from misago.readtracker.models import PostRead
-from misago.threads import test
-from misago.users.test import create_test_user
+from .. import poststracker, threadstracker
+from ...acl.objectacl import add_acl_to_obj
+from ...acl.useracl import get_user_acl
+from ...categories.models import Category
+from ...conf import settings
+from ...conftest import get_cache_versions
+from ...threads import test
+from ...users.test import create_test_user
+from ..models import PostRead
 
 cache_versions = get_cache_versions()
 

+ 2 - 3
misago/readtracker/threadstracker.py

@@ -1,6 +1,5 @@
-from misago.threads.models import Post
-from misago.threads.permissions import exclude_invisible_posts
-
+from ..threads.models import Post
+from ..threads.permissions import exclude_invisible_posts
 from .dates import get_cutoff_date
 
 

+ 3 - 5
misago/search/api.py

@@ -1,14 +1,12 @@
 from time import time
 
-from rest_framework.decorators import api_view
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.urls import reverse
 from django.utils.translation import gettext as _
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
 
-from misago.core.shortcuts import get_int_or_404
-
+from ..core.shortcuts import get_int_or_404
 from .searchproviders import searchproviders
 
 

+ 3 - 3
misago/search/permissions.py

@@ -1,9 +1,9 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl import algebra
-from misago.acl.models import Role
-from misago.admin.forms import YesNoSwitch
+from ..acl import algebra
+from ..acl.models import Role
+from ..admin.forms import YesNoSwitch
 
 
 class PermissionsForm(forms.Form):

+ 1 - 1
misago/search/searchproviders.py

@@ -1,7 +1,7 @@
 from django.core.exceptions import PermissionDenied
 from django.utils.module_loading import import_string
 
-from misago.conf import settings
+from ..conf import settings
 
 
 class SearchProviders(object):

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

@@ -1,8 +1,8 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.search.searchproviders import searchproviders
-from misago.users.test import AuthenticatedUserTestCase
+from ...acl.test import patch_user_acl
+from ...users.test import AuthenticatedUserTestCase
+from ..searchproviders import searchproviders
 
 
 class SearchApiTests(AuthenticatedUserTestCase):

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

@@ -1,9 +1,9 @@
 from django.core.exceptions import PermissionDenied
 from django.test import TestCase
 
-from misago.conf import settings
-from misago.search.searchprovider import SearchProvider
-from misago.search.searchproviders import SearchProviders
+from ...conf import settings
+from ..searchprovider import SearchProvider
+from ..searchproviders import SearchProviders
 
 
 class MockProvider(SearchProvider):

+ 3 - 3
misago/search/tests/test_views.py

@@ -1,8 +1,8 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.threads.search import SearchThreads
-from misago.users.test import AuthenticatedUserTestCase
+from ...acl.test import patch_user_acl
+from ...threads.search import SearchThreads
+from ...users.test import AuthenticatedUserTestCase
 
 
 class LandingTests(AuthenticatedUserTestCase):

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

@@ -1,6 +1,6 @@
 from django.conf.urls import url
 
-from misago.search.views import landing, search
+from ..views import landing, search
 
 urlpatterns = [
     url(r"^search/$", landing, name="search"),

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

@@ -1,7 +1,6 @@
 from django.conf.urls import url
 
-from misago.search import api
-
+from .. import api
 
 urlpatterns = [
     url(r"^search/$", api.search, name="search"),

+ 0 - 1
misago/threads/anonymize.py

@@ -1,6 +1,5 @@
 from django.urls import reverse
 
-
 ANONYMIZABLE_EVENTS = (
     "added_participant",
     "changed_owner",

+ 6 - 8
misago/threads/api/attachments.py

@@ -1,15 +1,13 @@
-from rest_framework import viewsets
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied, ValidationError
 from django.template.defaultfilters import filesizeformat
 from django.utils.translation import gettext as _
+from rest_framework import viewsets
+from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.threads.models import Attachment, AttachmentType
-from misago.threads.serializers import AttachmentSerializer
-from misago.users.audittrail import create_audit_trail
-
+from ...acl.objectacl import add_acl_to_obj
+from ...users.audittrail import create_audit_trail
+from ..models import Attachment, AttachmentType
+from ..serializers import AttachmentSerializer
 
 IMAGE_EXTENSIONS = ("jpg", "jpeg", "png", "gif")
 

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

@@ -2,9 +2,9 @@ from copy import deepcopy
 
 from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.threads.permissions import allow_vote_poll
-from misago.threads.serializers import PollSerializer, NewVoteSerializer
+from ...acl.objectacl import add_acl_to_obj
+from ..permissions import allow_vote_poll
+from ..serializers import NewVoteSerializer, PollSerializer
 
 
 def poll_vote_create(request, thread, poll):

+ 7 - 9
misago/threads/api/postendpoints/delete.py

@@ -1,20 +1,18 @@
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
 from django.utils.translation import ngettext
+from rest_framework.response import Response
 
-from misago.conf import settings
-from misago.core.utils import clean_ids_list
-from misago.threads.moderation import posts as moderation
-from misago.threads.permissions import (
+from ....conf import settings
+from ....core.utils import clean_ids_list
+from ...moderation import posts as moderation
+from ...permissions import (
     allow_delete_best_answer,
     allow_delete_event,
     allow_delete_post,
+    exclude_invisible_posts,
 )
-from misago.threads.permissions import exclude_invisible_posts
-from misago.threads.serializers import DeletePostsSerializer
-
+from ...serializers import DeletePostsSerializer
 
 DELETE_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL
 

+ 7 - 8
misago/threads/api/postendpoints/edits.py

@@ -1,17 +1,16 @@
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.db.models import F
 from django.shortcuts import get_object_or_404
 from django.utils import timezone
 from django.utils.translation import gettext as _
+from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.core.shortcuts import get_int_or_404
-from misago.markup import common_flavour
-from misago.threads.checksums import update_post_checksum
-from misago.threads.serializers import PostEditSerializer, PostSerializer
-from misago.users.online.utils import make_users_status_aware
+from ....acl.objectacl import add_acl_to_obj
+from ....core.shortcuts import get_int_or_404
+from ....markup import common_flavour
+from ....users.online.utils import make_users_status_aware
+from ...checksums import update_post_checksum
+from ...serializers import PostEditSerializer, PostSerializer
 
 
 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 misago.threads.serializers import PostLikeSerializer
+from ...serializers import PostLikeSerializer
 
 
 def likes_list_endpoint(request, post):

+ 3 - 4
misago/threads/api/postendpoints/merge.py

@@ -1,10 +1,9 @@
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
+from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.threads.serializers import MergePostsSerializer, PostSerializer
+from ....acl.objectacl import add_acl_to_obj
+from ...serializers import MergePostsSerializer, PostSerializer
 
 
 def posts_merge_endpoint(request, thread):

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

@@ -1,9 +1,8 @@
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
+from rest_framework.response import Response
 
-from misago.threads.serializers import MovePostsSerializer
+from ...serializers import MovePostsSerializer
 
 
 def posts_move_endpoint(request, thread, viewmodel):

+ 4 - 5
misago/threads/api/postendpoints/patch_event.py

@@ -1,11 +1,10 @@
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.core.apipatch import ApiPatch
-from misago.threads.moderation import posts as moderation
-from misago.threads.permissions import allow_hide_event, allow_unhide_event
-
+from ....acl.objectacl import add_acl_to_obj
+from ....core.apipatch import ApiPatch
+from ...moderation import posts as moderation
+from ...permissions import allow_hide_event, allow_unhide_event
 
 event_patch_dispatcher = ApiPatch()
 

+ 9 - 11
misago/threads/api/postendpoints/patch_post.py

@@ -1,23 +1,21 @@
-from rest_framework import serializers
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
+from rest_framework import serializers
+from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.conf import settings
-from misago.core.apipatch import ApiPatch
-from misago.threads.models import PostLike
-from misago.threads.moderation import posts as moderation
-from misago.threads.permissions import (
+from ....acl.objectacl import add_acl_to_obj
+from ....conf import settings
+from ....core.apipatch import ApiPatch
+from ...models import PostLike
+from ...moderation import posts as moderation
+from ...permissions import (
     allow_approve_post,
     allow_hide_best_answer,
     allow_hide_post,
     allow_protect_post,
     allow_unhide_post,
+    exclude_invisible_posts,
 )
-from misago.threads.permissions import exclude_invisible_posts
-
 
 PATCH_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL
 

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

@@ -1,7 +1,7 @@
 from rest_framework.response import Response
 
-from misago.readtracker import poststracker, threadstracker
-from misago.readtracker.signals import thread_read
+from ....readtracker import poststracker, threadstracker
+from ....readtracker.signals import thread_read
 
 
 def post_read_endpoint(request, thread, post):

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

@@ -1,11 +1,10 @@
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
+from rest_framework.response import Response
 
-from misago.threads.models import Thread
-from misago.threads.moderation import threads as moderation
-from misago.threads.serializers import SplitPostsSerializer
+from ...models import Thread
+from ...moderation import threads as moderation
+from ...serializers import SplitPostsSerializer
 
 
 def posts_split_endpoint(request, thread):

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

@@ -5,7 +5,7 @@ from django.http import QueryDict
 from django.utils import timezone
 from django.utils.module_loading import import_string
 
-from misago.conf import settings
+from ....conf import settings
 
 
 class PostingInterrupt(Exception):

+ 4 - 6
misago/threads/api/postingendpoint/attachments.py

@@ -1,13 +1,11 @@
-from rest_framework import serializers
-
 from django.utils.translation import gettext as _
 from django.utils.translation import ngettext
-
-from misago.acl.objectacl import add_acl_to_obj
-from misago.conf import settings
-from misago.threads.serializers import AttachmentSerializer
+from rest_framework import serializers
 
 from . import PostingEndpoint, PostingMiddleware
+from ....acl.objectacl import add_acl_to_obj
+from ....conf import settings
+from ...serializers import AttachmentSerializer
 
 
 class AttachmentsMiddleware(PostingMiddleware):

+ 7 - 9
misago/threads/api/postingendpoint/category.py

@@ -1,17 +1,15 @@
-from rest_framework import serializers
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext_lazy
-
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories import THREADS_ROOT_NAME
-from misago.categories.models import Category
-from misago.categories.permissions import can_browse_category, can_see_category
-from misago.threads.permissions import allow_start_thread
-from misago.threads.threadtypes import trees_map
+from rest_framework import serializers
 
 from . import PostingEndpoint, PostingMiddleware
+from ....acl.objectacl import add_acl_to_obj
+from ....categories import THREADS_ROOT_NAME
+from ....categories.models import Category
+from ....categories.permissions import can_browse_category, can_see_category
+from ...permissions import allow_start_thread
+from ...threadtypes import trees_map
 
 
 class CategoryMiddleware(PostingMiddleware):

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

@@ -1,8 +1,7 @@
 from rest_framework import serializers
 
-from misago.threads import moderation
-
 from . import PostingEndpoint, PostingMiddleware
+from ... import moderation
 
 
 class CloseMiddleware(PostingMiddleware):

+ 3 - 4
misago/threads/api/postingendpoint/emailnotification.py

@@ -1,10 +1,9 @@
 from django.utils.translation import gettext as _
 
-from misago.acl import useracl
-from misago.core.mail import build_mail, send_messages
-from misago.threads.permissions import can_see_post, can_see_thread
-
 from . import PostingEndpoint, PostingMiddleware
+from ....acl import useracl
+from ....core.mail import build_mail, send_messages
+from ...permissions import can_see_post, can_see_thread
 
 
 class EmailNotificationMiddleware(PostingMiddleware):

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

@@ -3,10 +3,8 @@ from datetime import timedelta
 from django.utils import timezone
 from django.utils.translation import gettext as _
 
-from misago.conf import settings
-
 from . import PostingEndpoint, PostingInterrupt, PostingMiddleware
-
+from ....conf import settings
 
 MIN_POSTING_PAUSE = 3
 

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

@@ -1,8 +1,7 @@
 from rest_framework import serializers
 
-from misago.threads import moderation
-
 from . import PostingEndpoint, PostingMiddleware
+from ... import moderation
 
 
 class HideMiddleware(PostingMiddleware):

+ 1 - 2
misago/threads/api/postingendpoint/moderationqueue.py

@@ -1,6 +1,5 @@
-from misago.categories import PRIVATE_THREADS_ROOT_NAME
-
 from . import PostingEndpoint, PostingMiddleware
+from ....categories import PRIVATE_THREADS_ROOT_NAME
 
 
 class ModerationQueueMiddleware(PostingMiddleware):

+ 7 - 9
misago/threads/api/postingendpoint/participants.py

@@ -1,16 +1,14 @@
-from rest_framework import serializers
-
 from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
-from django.utils.translation import gettext as _, ngettext
-
-from misago.acl import useracl
-from misago.categories import PRIVATE_THREADS_ROOT_NAME
-from misago.threads.participants import add_participants, set_owner
-from misago.threads.permissions import allow_message_user
+from django.utils.translation import gettext as _
+from django.utils.translation import ngettext
+from rest_framework import serializers
 
 from . import PostingEndpoint, PostingMiddleware
-
+from ....acl import useracl
+from ....categories import PRIVATE_THREADS_ROOT_NAME
+from ...participants import add_participants, set_owner
+from ...permissions import allow_message_user
 
 User = get_user_model()
 

+ 2 - 3
misago/threads/api/postingendpoint/pin.py

@@ -1,9 +1,8 @@
 from rest_framework import serializers
 
-from misago.threads import moderation
-from misago.threads.models import Thread
-
 from . import PostingEndpoint, PostingMiddleware
+from ... import moderation
+from ...models import Thread
 
 
 class PinMiddleware(PostingMiddleware):

+ 3 - 4
misago/threads/api/postingendpoint/privatethread.py

@@ -1,8 +1,7 @@
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories import PRIVATE_THREADS_ROOT_NAME
-from misago.categories.models import Category
-
 from . import PostingEndpoint, PostingMiddleware
+from ....acl.objectacl import add_acl_to_obj
+from ....categories import PRIVATE_THREADS_ROOT_NAME
+from ....categories.models import Category
 
 
 class PrivateThreadMiddleware(PostingMiddleware):

+ 5 - 11
misago/threads/api/postingendpoint/reply.py

@@ -1,17 +1,11 @@
-from rest_framework import serializers
-
 from django.utils.translation import gettext_lazy
-
-from misago.markup import common_flavour
-from misago.threads.checksums import update_post_checksum
-from misago.threads.validators import (
-    validate_post,
-    validate_post_length,
-    validate_thread_title,
-)
-from misago.users.audittrail import create_audit_trail
+from rest_framework import serializers
 
 from . import PostingEndpoint, PostingMiddleware
+from ....markup import common_flavour
+from ....users.audittrail import create_audit_trail
+from ...checksums import update_post_checksum
+from ...validators import validate_post, validate_post_length, validate_thread_title
 
 
 class ReplyMiddleware(PostingMiddleware):

+ 1 - 2
misago/threads/api/postingendpoint/savechanges.py

@@ -1,8 +1,7 @@
 from collections import OrderedDict
 
-from misago.categories.models import Category
-
 from . import PostingMiddleware
+from ....categories.models import Category
 
 
 class SaveChangesMiddleware(PostingMiddleware):

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

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

+ 2 - 3
misago/threads/api/postingendpoint/syncprivatethreads.py

@@ -1,7 +1,6 @@
-from misago.categories import PRIVATE_THREADS_ROOT_NAME
-from misago.threads.participants import set_users_unread_private_threads_sync
-
 from . import PostingEndpoint, PostingMiddleware
+from ....categories import PRIVATE_THREADS_ROOT_NAME
+from ...participants import set_users_unread_private_threads_sync
 
 
 class SyncPrivateThreadsMiddleware(PostingMiddleware):

+ 1 - 2
misago/threads/api/postingendpoint/updatestats.py

@@ -1,8 +1,7 @@
 from django.db.models import F
 
-from misago.categories import THREADS_ROOT_NAME
-
 from . import PostingEndpoint, PostingMiddleware
+from ....categories import THREADS_ROOT_NAME
 
 
 class UpdateStatsMiddleware(PostingMiddleware):

+ 4 - 5
misago/threads/api/threadendpoints/delete.py

@@ -1,10 +1,9 @@
-from rest_framework.response import Response
-
 from django.db import transaction
+from rest_framework.response import Response
 
-from misago.threads.moderation import threads as moderation
-from misago.threads.permissions import allow_delete_thread
-from misago.threads.serializers import DeleteThreadsSerializer
+from ...moderation import threads as moderation
+from ...permissions import allow_delete_thread
+from ...serializers import DeleteThreadsSerializer
 
 
 @transaction.atomic

+ 6 - 7
misago/threads/api/threadendpoints/editor.py

@@ -1,13 +1,12 @@
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
+from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories import THREADS_ROOT_NAME
-from misago.categories.models import Category
-from misago.threads.permissions import can_start_thread
-from misago.threads.threadtypes import trees_map
+from ....acl.objectacl import add_acl_to_obj
+from ....categories import THREADS_ROOT_NAME
+from ....categories.models import Category
+from ...permissions import can_start_thread
+from ...threadtypes import trees_map
 
 
 def thread_start_editor(request):

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

@@ -1,7 +1,7 @@
 from rest_framework.response import Response
 
-from misago.core.shortcuts import get_int_or_404
-from misago.threads.viewmodels import (
+from ....core.shortcuts import get_int_or_404
+from ...viewmodels import (
     ForumThreads,
     PrivateThreads,
     PrivateThreadsCategory,

+ 9 - 10
misago/threads/api/threadendpoints/merge.py

@@ -1,16 +1,15 @@
-from rest_framework.exceptions import ValidationError
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
+from rest_framework.exceptions import ValidationError
+from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.threads.events import record_event
-from misago.threads.mergeconflict import MergeConflict
-from misago.threads.models import Thread
-from misago.threads.moderation import threads as moderation
-from misago.threads.permissions import allow_merge_thread
-from misago.threads.serializers import (
+from ....acl.objectacl import add_acl_to_obj
+from ...events import record_event
+from ...mergeconflict import MergeConflict
+from ...models import Thread
+from ...moderation import threads as moderation
+from ...permissions import allow_merge_thread
+from ...serializers import (
     MergeThreadSerializer,
     MergeThreadsSerializer,
     ThreadsListSerializer,

+ 16 - 17
misago/threads/api/threadendpoints/patch.py

@@ -1,47 +1,46 @@
-from rest_framework import serializers
-from rest_framework.response import Response
-
 from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied, ValidationError
 from django.http import Http404
 from django.shortcuts import get_object_or_404
 from django.utils.translation import gettext as _
+from rest_framework import serializers
+from rest_framework.response import Response
 
-from misago.acl import useracl
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories.models import Category
-from misago.categories.permissions import allow_browse_category, allow_see_category
-from misago.categories.serializers import CategorySerializer
-from misago.conf import settings
-from misago.core.apipatch import ApiPatch
-from misago.core.shortcuts import get_int_or_404
-from misago.threads.moderation import threads as moderation
-from misago.threads.participants import (
+from ....acl import useracl
+from ....acl.objectacl import add_acl_to_obj
+from ....categories.models import Category
+from ....categories.permissions import allow_browse_category, allow_see_category
+from ....categories.serializers import CategorySerializer
+from ....conf import settings
+from ....core.apipatch import ApiPatch
+from ....core.shortcuts import get_int_or_404
+from ...moderation import threads as moderation
+from ...participants import (
     add_participant,
     change_owner,
     make_participants_aware,
     remove_participant,
 )
-from misago.threads.permissions import (
+from ...permissions import (
     allow_add_participant,
     allow_add_participants,
     allow_approve_thread,
     allow_change_best_answer,
     allow_change_owner,
     allow_edit_thread,
-    allow_pin_thread,
     allow_hide_thread,
     allow_mark_as_best_answer,
     allow_mark_best_answer,
     allow_move_thread,
+    allow_pin_thread,
     allow_remove_participant,
     allow_see_post,
     allow_start_thread,
     allow_unhide_thread,
     allow_unmark_best_answer,
 )
-from misago.threads.serializers import ThreadParticipantSerializer
-from misago.threads.validators import validate_thread_title
+from ...serializers import ThreadParticipantSerializer
+from ...validators import validate_thread_title
 
 PATCH_LIMIT = settings.MISAGO_THREADS_PER_PAGE + settings.MISAGO_THREADS_TAIL
 

+ 10 - 12
misago/threads/api/threadpoll.py

@@ -1,31 +1,29 @@
-from rest_framework import viewsets
-from rest_framework.decorators import detail_route
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.db import transaction
 from django.http import Http404
 from django.utils.translation import gettext as _
+from rest_framework import viewsets
+from rest_framework.decorators import detail_route
+from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.core.shortcuts import get_int_or_404
-from misago.threads.models import Poll
-from misago.threads.permissions import (
+from ...acl.objectacl import add_acl_to_obj
+from ...core.shortcuts import get_int_or_404
+from ...users.audittrail import create_audit_trail
+from ..models import Poll
+from ..permissions import (
     allow_delete_poll,
     allow_edit_poll,
     allow_see_poll_votes,
     allow_start_poll,
     can_start_poll,
 )
-from misago.threads.serializers import (
+from ..serializers import (
     EditPollSerializer,
     NewPollSerializer,
     PollSerializer,
     PollVoteSerializer,
 )
-from misago.threads.viewmodels import ForumThread
-from misago.users.audittrail import create_audit_trail
-
+from ..viewmodels import ForumThread
 from .pollvotecreateendpoint import poll_vote_create
 
 

+ 11 - 18
misago/threads/api/threadposts.py

@@ -1,31 +1,24 @@
-from rest_framework import viewsets
-from rest_framework.decorators import detail_route, list_route
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.db import transaction
 from django.utils.translation import gettext as _
+from rest_framework import viewsets
+from rest_framework.decorators import detail_route, list_route
+from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.core.shortcuts import get_int_or_404
-from misago.threads.models import Post
-from misago.threads.permissions import allow_edit_post, allow_reply_thread
-from misago.threads.serializers import AttachmentSerializer, PostSerializer
-from misago.threads.viewmodels import (
-    ForumThread,
-    PrivateThread,
-    ThreadPost,
-    ThreadPosts,
-)
-from misago.users.online.utils import make_users_status_aware
-
+from ...acl.objectacl import add_acl_to_obj
+from ...core.shortcuts import get_int_or_404
+from ...users.online.utils import make_users_status_aware
+from ..models import Post
+from ..permissions import allow_edit_post, allow_reply_thread
+from ..serializers import AttachmentSerializer, PostSerializer
+from ..viewmodels import ForumThread, PrivateThread, ThreadPost, ThreadPosts
 from .postendpoints.delete import delete_bulk, delete_post
 from .postendpoints.edits import get_edit_endpoint, revert_post_endpoint
 from .postendpoints.likes import likes_list_endpoint
 from .postendpoints.merge import posts_merge_endpoint
 from .postendpoints.move import posts_move_endpoint
 from .postendpoints.patch_event import event_patch_endpoint
-from .postendpoints.patch_post import post_patch_endpoint, bulk_patch_endpoint
+from .postendpoints.patch_post import bulk_patch_endpoint, post_patch_endpoint
 from .postendpoints.read import post_read_endpoint
 from .postendpoints.split import posts_split_endpoint
 from .postingendpoint import PostingEndpoint

+ 10 - 12
misago/threads/api/threads.py

@@ -1,23 +1,21 @@
-from rest_framework import viewsets
-from rest_framework.decorators import detail_route, list_route
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.db import transaction
 from django.utils.translation import gettext as _
+from rest_framework import viewsets
+from rest_framework.decorators import detail_route, list_route
+from rest_framework.response import Response
 
-from misago.categories import PRIVATE_THREADS_ROOT_NAME, THREADS_ROOT_NAME
-from misago.core.shortcuts import get_int_or_404
-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 (
+from ...categories import PRIVATE_THREADS_ROOT_NAME, THREADS_ROOT_NAME
+from ...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,
-    ThreadsRootCategory,
     PrivateThreadsCategory,
+    ThreadsRootCategory,
 )
-
 from .postingendpoint import PostingEndpoint
 from .threadendpoints.delete import delete_bulk, delete_thread
 from .threadendpoints.editor import thread_start_editor

+ 1 - 1
misago/threads/checksums.py

@@ -1,4 +1,4 @@
-from misago.markup import checksums
+from ..markup import checksums
 
 
 def is_post_valid(post):

+ 1 - 2
misago/threads/events.py

@@ -1,7 +1,6 @@
 from django.utils import timezone
 
-from misago.readtracker import poststracker
-
+from ..readtracker import poststracker
 from .models import Post
 
 

+ 1 - 2
misago/threads/filtersearch.py

@@ -1,7 +1,6 @@
 from django.utils.module_loading import import_string
 
-from misago.conf import settings
-
+from ..conf import settings
 
 filters_list = settings.MISAGO_POST_SEARCH_FILTERS
 SEARCH_FILTERS = list(map(import_string, filters_list))

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

@@ -4,10 +4,10 @@ from datetime import timedelta
 from django.core.management.base import BaseCommand
 from django.utils import timezone
 
-from misago.conf import settings
-from misago.core.management.progressbar import show_progress
-from misago.core.pgutils import chunk_queryset
-from misago.threads.models import Attachment
+from ....conf import settings
+from ....core.management.progressbar import show_progress
+from ....core.pgutils import chunk_queryset
+from ...models import Attachment
 
 
 class Command(BaseCommand):

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

@@ -2,9 +2,9 @@ import time
 
 from django.core.management.base import BaseCommand
 
-from misago.core.management.progressbar import show_progress
-from misago.core.pgutils import chunk_queryset
-from misago.threads.models import Post
+from ....core.management.progressbar import show_progress
+from ....core.pgutils import chunk_queryset
+from ...models import Post
 
 
 class Command(BaseCommand):

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

@@ -2,9 +2,9 @@ import time
 
 from django.core.management.base import BaseCommand
 
-from misago.core.management.progressbar import show_progress
-from misago.core.pgutils import chunk_queryset
-from misago.threads.models import Thread
+from ....core.management.progressbar import show_progress
+from ....core.pgutils import chunk_queryset
+from ...models import Thread
 
 
 class Command(BaseCommand):

+ 4 - 4
misago/threads/management/commands/updatepostschecksums.py

@@ -2,10 +2,10 @@ import time
 
 from django.core.management.base import BaseCommand
 
-from misago.core.management.progressbar import show_progress
-from misago.core.pgutils import chunk_queryset
-from misago.threads.checksums import update_post_checksum
-from misago.threads.models import Post
+from ....core.management.progressbar import show_progress
+from ....core.pgutils import chunk_queryset
+from ...checksums import update_post_checksum
+from ...models import Post
 
 
 class Command(BaseCommand):

+ 2 - 3
misago/threads/mergeconflict.py

@@ -1,8 +1,7 @@
-from rest_framework.exceptions import ValidationError
-
 from django.utils.translation import gettext as _
+from rest_framework.exceptions import ValidationError
 
-from misago.threads.models import Poll
+from .models import Poll
 
 
 class MergeConflictHandler(object):

+ 1 - 2
misago/threads/middleware.py

@@ -1,7 +1,6 @@
 from django.utils.deprecation import MiddlewareMixin
 
-from misago.categories.models import Category
-
+from ..categories.models import Category
 from .models import Thread
 from .viewmodels import filter_read_threads_queryset
 

+ 1 - 2
misago/threads/migrations/0002_threads_settings.py

@@ -1,7 +1,6 @@
 from django.db import migrations
 
-from misago.conf.migrationutils import migrate_settings_group
-
+from ...conf.migrationutils import migrate_settings_group
 
 _ = lambda s: s
 

+ 0 - 1
misago/threads/migrations/0003_attachment_types.py

@@ -1,7 +1,6 @@
 # Generated by Django 1.9.7 on 2016-10-04 21:41
 from django.db import migrations
 
-
 ATTACHMENTS = [
     {
         "name": "GIF",

+ 1 - 1
misago/threads/migrations/0004_update_settings.py

@@ -1,6 +1,6 @@
 from django.db import migrations
 
-from misago.conf.migrationutils import migrate_settings_group
+from ...conf.migrationutils import migrate_settings_group
 
 _ = lambda s: s
 

+ 1 - 1
misago/threads/migrations/0008_auto_20180310_2234.py

@@ -1,7 +1,7 @@
 # Generated by Django 1.11.9 on 2018-03-10 22:34
+import django.db.models.deletion
 from django.conf import settings
 from django.db import migrations, models
-import django.db.models.deletion
 
 
 class Migration(migrations.Migration):

+ 3 - 4
misago/threads/models/attachment.py

@@ -2,17 +2,16 @@ import os
 from hashlib import md5
 from io import BytesIO
 
-from PIL import Image
-
 from django.core.files import File
 from django.core.files.base import ContentFile
 from django.db import models
 from django.urls import reverse
 from django.utils import timezone
 from django.utils.crypto import get_random_string
+from PIL import Image
 
-from misago.conf import settings
-from misago.core.utils import slugify
+from ...conf import settings
+from ...core.utils import slugify
 
 
 def upload_to(instance, filename):

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

@@ -1,17 +1,17 @@
 import copy
 
-from django.contrib.postgres.indexes import GinIndex
 from django.contrib.postgres.fields import JSONField
+from django.contrib.postgres.indexes import GinIndex
 from django.contrib.postgres.search import SearchVector, SearchVectorField
 from django.db import models
 from django.utils import timezone
 
-from misago.conf import settings
-from misago.core.pgutils import PgPartialIndex
-from misago.core.utils import parse_iso8601_string
-from misago.markup import finalise_markup
-from misago.threads.checksums import is_post_valid, update_post_checksum
-from misago.threads.filtersearch import filter_search
+from ...conf import settings
+from ...core.pgutils import PgPartialIndex
+from ...core.utils import parse_iso8601_string
+from ...markup import finalise_markup
+from ..checksums import is_post_valid, update_post_checksum
+from ..filtersearch import filter_search
 
 
 class Post(models.Model):
@@ -97,7 +97,7 @@ class Post(models.Model):
         return "%s..." % self.original[10:].strip()
 
     def delete(self, *args, **kwargs):
-        from misago.threads.signals import delete_post
+        from ..signals import delete_post
 
         delete_post.send(sender=self)
 
@@ -133,12 +133,12 @@ class Post(models.Model):
         if other_post.is_best_answer:
             self.thread.best_answer_is_protected = other_post.is_protected
 
-        from misago.threads.signals import merge_post
+        from ..signals import merge_post
 
         merge_post.send(sender=self, other_post=other_post)
 
     def move(self, new_thread):
-        from misago.threads.signals import move_post
+        from ..signals import move_post
 
         if self.is_best_answer:
             self.thread.clear_best_answer()

+ 1 - 1
misago/threads/models/subscription.py

@@ -1,7 +1,7 @@
 from django.db import models
 from django.utils import timezone
 
-from misago.conf import settings
+from ...conf import settings
 
 
 class Subscription(models.Model):

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

@@ -3,9 +3,9 @@ from django.db import models
 from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
-from misago.conf import settings
-from misago.core.pgutils import PgPartialIndex
-from misago.core.utils import slugify
+from ...conf import settings
+from ...core.pgutils import PgPartialIndex
+from ...core.utils import slugify
 
 
 class Thread(models.Model):
@@ -122,7 +122,7 @@ class Thread(models.Model):
         return self.title
 
     def delete(self, *args, **kwargs):
-        from misago.threads.signals import delete_thread
+        from ..signals import delete_thread
 
         delete_thread.send(sender=self)
 
@@ -132,12 +132,12 @@ class Thread(models.Model):
         if self.pk == other_thread.pk:
             raise ValueError("thread can't be merged with itself")
 
-        from misago.threads.signals import merge_thread
+        from ..signals import merge_thread
 
         merge_thread.send(sender=self, other_thread=other_thread)
 
     def move(self, new_category):
-        from misago.threads.signals import move_thread
+        from ..signals import move_thread
 
         self.category = new_category
         move_thread.send(sender=self)

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

@@ -1,6 +1,6 @@
 from django.db import models
 
-from misago.conf import settings
+from ...conf import settings
 
 
 class ThreadParticipantManager(models.Manager):

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

@@ -4,7 +4,6 @@ from django.utils.translation import gettext as _
 
 from .exceptions import ModerationError
 
-
 __all__ = [
     "approve_post",
     "protect_post",

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

@@ -1,8 +1,7 @@
 from django.db import transaction
 from django.utils import timezone
 
-from misago.threads.events import record_event
-
+from ..events import record_event
 
 __all__ = [
     "change_thread_title",

+ 1 - 3
misago/threads/participants.py

@@ -1,12 +1,10 @@
 from django.contrib.auth import get_user_model
 from django.utils.translation import gettext as _
 
-from misago.core.mail import build_mail, send_messages
-
+from ..core.mail import build_mail, send_messages
 from .events import record_event
 from .models import ThreadParticipant
 
-
 User = get_user_model()
 
 

+ 4 - 5
misago/threads/permissions/attachments.py

@@ -1,11 +1,10 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl import algebra
-from misago.acl.models import Role
-from misago.admin.forms import YesNoSwitch
-from misago.threads.models import Attachment
-
+from ...acl import algebra
+from ...acl.models import Role
+from ...admin.forms import YesNoSwitch
+from ..models import Attachment
 
 # Admin Permissions Forms
 class PermissionsForm(forms.Form):

+ 9 - 9
misago/threads/permissions/bestanswers.py

@@ -1,15 +1,15 @@
 from django import forms
 from django.core.exceptions import PermissionDenied
 from django.utils import timezone
-from django.utils.translation import gettext_lazy as _, ngettext
-
-from misago.acl import algebra
-from misago.acl.decorators import return_boolean
-from misago.admin.forms import YesNoSwitch
-from misago.categories.models import Category, CategoryRole
-from misago.categories.permissions import get_categories_roles
-from misago.threads.models import Post, Thread
-
+from django.utils.translation import gettext_lazy as _
+from django.utils.translation import ngettext
+
+from ...acl import algebra
+from ...acl.decorators import return_boolean
+from ...admin.forms import YesNoSwitch
+from ...categories.models import Category, CategoryRole
+from ...categories.permissions import get_categories_roles
+from ..models import Post, Thread
 
 __all__nope = [
     "allow_mark_best_answer",

+ 5 - 6
misago/threads/permissions/polls.py

@@ -4,12 +4,11 @@ from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import ngettext
 
-from misago.acl import algebra
-from misago.acl.decorators import return_boolean
-from misago.acl.models import Role
-from misago.admin.forms import YesNoSwitch
-from misago.threads.models import Poll, Thread
-
+from ...acl import algebra
+from ...acl.decorators import return_boolean
+from ...acl.models import Role
+from ...admin.forms import YesNoSwitch
+from ..models import Poll, Thread
 
 __all__ = [
     "allow_start_poll",

+ 7 - 8
misago/threads/permissions/privatethreads.py

@@ -3,14 +3,13 @@ from django.core.exceptions import PermissionDenied
 from django.http import Http404
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl import algebra
-from misago.acl.decorators import return_boolean
-from misago.acl.models import Role
-from misago.admin.forms import YesNoSwitch
-from misago.categories import PRIVATE_THREADS_ROOT_NAME
-from misago.categories.models import Category
-from misago.threads.models import Thread
-
+from ...acl import algebra
+from ...acl.decorators import return_boolean
+from ...acl.models import Role
+from ...admin.forms import YesNoSwitch
+from ...categories import PRIVATE_THREADS_ROOT_NAME
+from ...categories.models import Category
+from ..models import Thread
 
 __all__ = [
     "allow_use_private_threads",

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

@@ -3,17 +3,17 @@ from django.core.exceptions import PermissionDenied
 from django.db.models import Q
 from django.http import Http404
 from django.utils import timezone
-from django.utils.translation import gettext_lazy as _, ngettext
-
-from misago.acl import algebra
-from misago.acl.decorators import return_boolean
-from misago.acl.models import Role
-from misago.acl.objectacl import add_acl_to_obj
-from misago.admin.forms import YesNoSwitch
-from misago.categories.models import Category, CategoryRole
-from misago.categories.permissions import get_categories_roles
-from misago.threads.models import Post, Thread
-
+from django.utils.translation import gettext_lazy as _
+from django.utils.translation import ngettext
+
+from ...acl import algebra
+from ...acl.decorators import return_boolean
+from ...acl.models import Role
+from ...acl.objectacl import add_acl_to_obj
+from ...admin.forms import YesNoSwitch
+from ...categories.models import Category, CategoryRole
+from ...categories.permissions import get_categories_roles
+from ..models import Post, Thread
 
 __all__ = [
     "allow_see_thread",

+ 3 - 5
misago/threads/search.py

@@ -1,10 +1,9 @@
 from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
 from django.utils.translation import gettext_lazy as _
 
-from misago.conf import settings
-from misago.core.shortcuts import paginate, pagination_dict
-from misago.search import SearchProvider
-
+from ..conf import settings
+from ..core.shortcuts import paginate, pagination_dict
+from ..search import SearchProvider
 from .filtersearch import filter_search
 from .models import Post, Thread
 from .permissions import exclude_invisible_threads
@@ -12,7 +11,6 @@ from .serializers import FeedSerializer
 from .utils import add_categories_to_items
 from .viewmodels import ThreadsRootCategory
 
-
 HITS_CEILING = settings.MISAGO_POSTS_PER_PAGE * 5
 
 

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

@@ -1,9 +1,7 @@
-from rest_framework import serializers
-
 from django.urls import reverse
+from rest_framework import serializers
 
-from misago.threads.models import Attachment
-
+from ..models import Attachment
 
 __all__ = ["AttachmentSerializer"]
 

+ 4 - 6
misago/threads/serializers/feed.py

@@ -1,13 +1,11 @@
 from rest_framework import serializers
 
-from misago.categories.serializers import CategorySerializer
-from misago.core.serializers import MutableFields
-from misago.threads.models import Post
-from misago.users.serializers import UserSerializer
-
+from ...categories.serializers import CategorySerializer
+from ...core.serializers import MutableFields
+from ...users.serializers import UserSerializer
+from ..models import Post
 from .post import PostSerializer
 
-
 __all__ = ["FeedSerializer"]
 
 FeedUserSerializer = UserSerializer.subset_fields(

+ 13 - 14
misago/threads/serializers/moderation.py

@@ -1,15 +1,15 @@
-from rest_framework import serializers
-
 from django.core.exceptions import PermissionDenied, ValidationError
 from django.http import Http404
-from django.utils.translation import gettext as _, gettext_lazy, ngettext
-
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories import THREADS_ROOT_NAME
-from misago.conf import settings
-from misago.threads.mergeconflict import MergeConflict
-from misago.threads.models import Thread
-from misago.threads.permissions import (
+from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy, ngettext
+from rest_framework import serializers
+
+from ...acl.objectacl import add_acl_to_obj
+from ...categories import THREADS_ROOT_NAME
+from ...conf import settings
+from ..mergeconflict import MergeConflict
+from ..models import Thread
+from ..permissions import (
     allow_delete_best_answer,
     allow_delete_event,
     allow_delete_post,
@@ -23,10 +23,9 @@ from misago.threads.permissions import (
     can_start_thread,
     exclude_invisible_posts,
 )
-from misago.threads.threadtypes import trees_map
-from misago.threads.utils import get_thread_id_from_url
-from misago.threads.validators import validate_category, validate_thread_title
-
+from ..threadtypes import trees_map
+from ..utils import get_thread_id_from_url
+from ..validators import validate_category, validate_thread_title
 
 POSTS_LIMIT = settings.MISAGO_POSTS_PER_PAGE + settings.MISAGO_POSTS_TAIL
 THREADS_LIMIT = settings.MISAGO_THREADS_PER_PAGE + settings.MISAGO_THREADS_TAIL

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

@@ -1,12 +1,10 @@
-from rest_framework import serializers
-
 from django.urls import reverse
 from django.utils.crypto import get_random_string
 from django.utils.translation import gettext as _
 from django.utils.translation import ngettext
+from rest_framework import serializers
 
-from misago.threads.models import Poll
-
+from ..models import Poll
 
 __all__ = [
     "PollSerializer",

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

@@ -1,9 +1,7 @@
-from rest_framework import serializers
-
 from django.urls import reverse
 from django.utils.translation import gettext as _
 from django.utils.translation import ngettext
-
+from rest_framework import serializers
 
 __all__ = ["NewVoteSerializer", "PollVoteSerializer"]
 

+ 4 - 6
misago/threads/serializers/post.py

@@ -1,11 +1,9 @@
-from rest_framework import serializers
-
 from django.urls import reverse
+from rest_framework import serializers
 
-from misago.core.serializers import MutableFields
-from misago.threads.models import Post
-from misago.users.serializers import UserSerializer as BaseUserSerializer
-
+from ...core.serializers import MutableFields
+from ...users.serializers import UserSerializer as BaseUserSerializer
+from ..models import Post
 
 __all__ = ["PostSerializer"]
 

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

@@ -1,9 +1,7 @@
-from rest_framework import serializers
-
 from django.urls import reverse
+from rest_framework import serializers
 
-from misago.threads.models import PostEdit
-
+from ..models import PostEdit
 
 __all__ = ["PostEditSerializer"]
 

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

@@ -1,9 +1,7 @@
-from rest_framework import serializers
-
 from django.urls import reverse
+from rest_framework import serializers
 
-from misago.threads.models import PostLike
-
+from ..models import PostLike
 
 __all__ = ["PostLikeSerializer"]
 

+ 4 - 7
misago/threads/serializers/thread.py

@@ -1,15 +1,12 @@
-from rest_framework import serializers
-
 from django.urls import reverse
+from rest_framework import serializers
 
-from misago.categories.serializers import CategorySerializer
-from misago.core.serializers import MutableFields
-from misago.threads.models import Thread
-
+from ...categories.serializers import CategorySerializer
+from ...core.serializers import MutableFields
+from ..models import Thread
 from .poll import PollSerializer
 from .threadparticipant import ThreadParticipantSerializer
 
-
 __all__ = ["ThreadSerializer", "PrivateThreadSerializer", "ThreadsListSerializer"]
 
 BasicCategorySerializer = CategorySerializer.subset_fields(

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

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

+ 4 - 6
misago/threads/signals.py

@@ -6,20 +6,18 @@ from django.db.models.signals import pre_delete
 from django.dispatch import Signal, receiver
 from django.utils.translation import gettext as _
 
-from misago.categories.models import Category
-from misago.categories.signals import delete_category_content, move_category_content
-from misago.core.pgutils import chunk_queryset
-from misago.users.signals import (
+from ..categories.models import Category
+from ..categories.signals import delete_category_content, move_category_content
+from ..core.pgutils import chunk_queryset
+from ..users.signals import (
     anonymize_user_data,
     archive_user_data,
     delete_user_content,
     username_changed,
 )
-
 from .anonymize import ANONYMIZABLE_EVENTS, anonymize_event, anonymize_post_last_likes
 from .models import Attachment, Poll, PollVote, Post, PostEdit, PostLike, Thread
 
-
 delete_post = Signal()
 delete_thread = Signal()
 merge_post = Signal(providing_args=["other_post"])

+ 0 - 1
misago/threads/templatetags/misago_poststags.py

@@ -2,7 +2,6 @@ from django import template
 from django.utils.translation import gettext as _
 from django.utils.translation import ngettext
 
-
 register = template.Library()
 
 

+ 4 - 5
misago/threads/test.py

@@ -3,11 +3,10 @@ from datetime import timedelta
 from django.contrib.auth import get_user_model
 from django.utils import timezone
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.core.utils import slugify
-from misago.users.test import create_test_user
-
+from ..acl.test import patch_user_acl
+from ..categories.models import Category
+from ..core.utils import slugify
+from ..users.test import create_test_user
 from .checksums import update_post_checksum
 from .models import Poll, Post, Thread
 

+ 8 - 10
misago/threads/tests/test_anonymize_data.py

@@ -1,22 +1,20 @@
 from django.test import RequestFactory
 from django.urls import reverse
 
-from misago.cache.versions import get_cache_versions
-from misago.categories.models import Category
-from misago.conf.dynamicsettings import DynamicSettings
-from misago.users.test import AuthenticatedUserTestCase
-
-from misago.threads import test
-from misago.threads.api.postendpoints.patch_post import patch_is_liked
-from misago.threads.models import Post
-from misago.threads.participants import (
+from .. import test
+from ...cache.versions import get_cache_versions
+from ...categories.models import Category
+from ...conf.dynamicsettings import DynamicSettings
+from ...users.test import AuthenticatedUserTestCase, create_test_user
+from ..api.postendpoints.patch_post import patch_is_liked
+from ..models import Post
+from ..participants import (
     add_participant,
     change_owner,
     make_participants_aware,
     remove_participant,
     set_owner,
 )
-from misago.users.test import create_test_user
 
 
 class AnonymizeEventsTests(AuthenticatedUserTestCase):

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

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

+ 6 - 7
misago/threads/tests/test_attachments_api.py

@@ -1,14 +1,13 @@
 import os
 
-from PIL import Image
-
 from django.urls import reverse
+from PIL import Image
 
-from misago.acl.models import Role
-from misago.acl.test import patch_user_acl
-from misago.conf import settings
-from misago.threads.models import Attachment, AttachmentType
-from misago.users.test import AuthenticatedUserTestCase
+from ...acl.models import Role
+from ...acl.test import patch_user_acl
+from ...conf import settings
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Attachment, AttachmentType
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_DOCUMENT_PATH = os.path.join(TESTFILES_DIR, "document.pdf")

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

@@ -2,19 +2,19 @@ from unittest.mock import Mock
 
 from rest_framework import serializers
 
-from misago.acl import useracl
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.conftest import get_cache_versions
-from misago.threads import test
-from misago.threads.api.postingendpoint import PostingEndpoint
-from misago.threads.api.postingendpoint.attachments import (
+from .. import test
+from ...acl import useracl
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...conf import settings
+from ...conftest import get_cache_versions
+from ...users.test import AuthenticatedUserTestCase
+from ..api.postingendpoint import PostingEndpoint
+from ..api.postingendpoint.attachments import (
     AttachmentsMiddleware,
     validate_attachments_count,
 )
-from misago.threads.models import Attachment, AttachmentType
-from misago.users.test import AuthenticatedUserTestCase
+from ..models import Attachment, AttachmentType
 
 cache_versions = get_cache_versions()
 

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

@@ -1,8 +1,8 @@
 from django.urls import reverse
 
-from misago.acl.models import Role
-from misago.admin.test import AdminTestCase
-from misago.threads.models import AttachmentType
+from ...acl.models import Role
+from ...admin.test import AdminTestCase
+from ..models import AttachmentType
 
 
 class AttachmentTypeAdminViewsTests(AdminTestCase):

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

@@ -2,13 +2,13 @@ import os
 
 from django.urls import reverse
 
-from misago.acl.models import Role
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.threads import test
-from misago.threads.models import Attachment, AttachmentType
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...acl.models import Role
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...conf import settings
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Attachment, AttachmentType
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_DOCUMENT_PATH = os.path.join(TESTFILES_DIR, "document.pdf")

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

@@ -5,11 +5,11 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.threads import test
-from misago.threads.management.commands import clearattachments
-from misago.threads.models import Attachment, AttachmentType
+from .. import test
+from ...categories.models import Category
+from ...conf import settings
+from ..management.commands import clearattachments
+from ..models import Attachment, AttachmentType
 
 
 class ClearAttachmentsTests(TestCase):

+ 5 - 6
misago/threads/tests/test_delete_user_likes.py

@@ -1,11 +1,10 @@
 from django.test import RequestFactory
 
-from misago.categories.models import Category
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
-
-from misago.threads import test
-from misago.threads.api.postendpoints.patch_post import patch_is_liked
-from misago.threads.models import Post
+from .. import test
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase, create_test_user
+from ..api.postendpoints.patch_post import patch_is_liked
+from ..models import Post
 
 
 class DeleteUserLikesTests(AuthenticatedUserTestCase):

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

@@ -6,10 +6,10 @@ from django.urls import reverse
 from django.utils import timezone
 from django.utils.encoding import smart_str
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.test import patch_category_acl, patch_other_user_category_acl
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from .. import test
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase, create_test_user
+from ..test import patch_category_acl, patch_other_user_category_acl
 
 
 class EmailNotificationTests(AuthenticatedUserTestCase):

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

@@ -3,13 +3,13 @@ from unittest.mock import Mock
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.acl import useracl
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories.models import Category
-from misago.conftest import get_cache_versions
-from misago.threads.events import record_event
-from misago.threads.models import Thread
-from misago.users.test import create_test_user
+from ...acl import useracl
+from ...acl.objectacl import add_acl_to_obj
+from ...categories.models import Category
+from ...conftest import get_cache_versions
+from ...users.test import create_test_user
+from ..events import record_event
+from ..models import Thread
 
 cache_versions = get_cache_versions()
 

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

@@ -1,9 +1,9 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.threads import test
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
 
 
 class FloodProtectionTests(AuthenticatedUserTestCase):

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

@@ -2,9 +2,9 @@ from datetime import timedelta
 
 from django.utils import timezone
 
-from misago.threads.api.postingendpoint import PostingInterrupt
-from misago.threads.api.postingendpoint.floodprotection import FloodProtectionMiddleware
-from misago.users.test import AuthenticatedUserTestCase
+from ...users.test import AuthenticatedUserTestCase
+from ..api.postingendpoint import PostingInterrupt
+from ..api.postingendpoint.floodprotection import FloodProtectionMiddleware
 
 user_acl = {"can_omit_flood_protection": False}
 

+ 6 - 7
misago/threads/tests/test_gotoviews.py

@@ -1,12 +1,11 @@
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.readtracker.poststracker import save_read
-from misago.threads import test
-from misago.threads.test import patch_category_acl
-from misago.users.test import AuthenticatedUserTestCase
-
+from .. import test
+from ...categories.models import Category
+from ...conf import settings
+from ...readtracker.poststracker import save_read
+from ...users.test import AuthenticatedUserTestCase
+from ..test import patch_category_acl
 
 GOTO_URL = "%s#post-%s"
 GOTO_PAGE_URL = "%s%s/#post-%s"

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

@@ -1,12 +1,10 @@
-from rest_framework.exceptions import ValidationError
-
 from django.test import TestCase
+from rest_framework.exceptions import ValidationError
 
-from misago.categories.models import Category
-
-from misago.threads import test
-from misago.threads.mergeconflict import MergeConflict
-from misago.users.test import create_test_user
+from .. import test
+from ...categories.models import Category
+from ...users.test import create_test_user
+from ..mergeconflict import MergeConflict
 
 
 class MergeConflictTests(TestCase):

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

@@ -2,7 +2,7 @@ from itertools import product
 
 from django.test import TestCase
 
-from misago.threads.paginator import PostsPaginator
+from ..paginator import PostsPaginator
 
 
 class PostsPaginatorTests(TestCase):

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

@@ -1,15 +1,15 @@
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.threads.models import Post, Thread, ThreadParticipant
-from misago.threads.participants import (
+from ...categories.models import Category
+from ...users.test import create_test_user
+from ..models import Post, Thread, ThreadParticipant
+from ..participants import (
     has_participants,
     make_participants_aware,
     set_owner,
     set_users_unread_private_threads_sync,
 )
-from misago.users.test import create_test_user
 
 
 class ParticipantsTests(TestCase):

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

@@ -1,10 +1,10 @@
 from django.test.client import BOUNDARY, MULTIPART_CONTENT, encode_multipart
 from django.urls import reverse
 
-from misago.categories.models import Category
-from misago.markup.mentions import MENTIONS_LIMIT
-from misago.threads import test
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from .. import test
+from ...categories.models import Category
+from ...markup.mentions import MENTIONS_LIMIT
+from ...users.test import AuthenticatedUserTestCase, create_test_user
 
 
 class PostMentionsTests(AuthenticatedUserTestCase):

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

@@ -3,10 +3,10 @@ from datetime import timedelta
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.threads.checksums import update_post_checksum
-from misago.threads.models import Post, Thread
-from misago.users.test import create_test_user
+from ...categories.models import Category
+from ...users.test import create_test_user
+from ..checksums import update_post_checksum
+from ..models import Post, Thread
 
 
 class PostModelTests(TestCase):

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

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

+ 5 - 6
misago/threads/tests/test_privatethread_patch_api.py

@@ -2,12 +2,11 @@ import json
 
 from django.core import mail
 
-from misago.acl.test import patch_user_acl
-from misago.threads import test
-from misago.threads.test import other_user_cant_use_private_threads
-from misago.threads.models import Thread, ThreadParticipant
-from misago.users.test import create_test_user
-
+from .. import test
+from ...acl.test import patch_user_acl
+from ...users.test import create_test_user
+from ..models import Thread, ThreadParticipant
+from ..test import other_user_cant_use_private_threads
 from .test_privatethreads import PrivateThreadsTestCase
 
 

+ 3 - 4
misago/threads/tests/test_privatethread_reply_api.py

@@ -1,7 +1,6 @@
-from misago.threads import test
-from misago.threads.models import ThreadParticipant
-from misago.users.test import create_test_user
-
+from .. import test
+from ...users.test import create_test_user
+from ..models import ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 
 

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

@@ -3,11 +3,11 @@ from django.core import mail
 from django.urls import reverse
 from django.utils.encoding import smart_str
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.threads.models import ThreadParticipant
-from misago.threads.test import other_user_cant_use_private_threads
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase, create_test_user
+from ..models import ThreadParticipant
+from ..test import other_user_cant_use_private_threads
 
 User = get_user_model()
 

+ 3 - 4
misago/threads/tests/test_privatethread_view.py

@@ -1,7 +1,6 @@
-from misago.acl.test import patch_user_acl
-from misago.threads import test
-from misago.threads.models import ThreadParticipant
-
+from .. import test
+from ...acl.test import patch_user_acl
+from ..models import ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 
 

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

@@ -1,5 +1,5 @@
-from misago.categories.models import Category
-from misago.users.test import AuthenticatedUserTestCase
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
 
 
 class PrivateThreadsTestCase(AuthenticatedUserTestCase):

+ 4 - 5
misago/threads/tests/test_privatethreads_api.py

@@ -1,10 +1,9 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.threads import test
-from misago.threads.models import Thread, ThreadParticipant
-from misago.threads.test import patch_private_threads_acl
-
+from .. import test
+from ...acl.test import patch_user_acl
+from ..models import Thread, ThreadParticipant
+from ..test import patch_private_threads_acl
 from .test_privatethreads import PrivateThreadsTestCase
 
 

+ 3 - 4
misago/threads/tests/test_privatethreads_lists.py

@@ -1,9 +1,8 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.threads import test
-from misago.threads.models import ThreadParticipant
-
+from .. import test
+from ...acl.test import patch_user_acl
+from ..models import ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 
 

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

@@ -1,8 +1,8 @@
 from django.urls import reverse
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
 
 
 class SearchApiTests(AuthenticatedUserTestCase):

+ 5 - 6
misago/threads/tests/test_subscription_middleware.py

@@ -1,12 +1,11 @@
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.test import patch_category_acl
-from misago.users.test import AuthenticatedUserTestCase
-
+from .. import test
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
+from ..test import patch_category_acl
 
 User = get_user_model()
 

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

@@ -3,11 +3,11 @@ from datetime import timedelta
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.subscriptions import make_subscription_aware
-from misago.users.models import AnonymousUser
-from misago.users.test import create_test_user
+from .. import test
+from ...categories.models import Category
+from ...users.models import AnonymousUser
+from ...users.test import create_test_user
+from ..subscriptions import make_subscription_aware
 
 
 class SubscriptionsTests(TestCase):

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

@@ -1,7 +1,6 @@
-from misago.threads import test
-from misago.threads.models import ThreadParticipant
-from misago.users.test import create_test_user
-
+from .. import test
+from ...users.test import create_test_user
+from ..models import ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 
 

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

@@ -3,9 +3,9 @@ from io import StringIO
 from django.core.management import call_command
 from django.test import TestCase
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.management.commands import synchronizethreads
+from .. import test
+from ...categories.models import Category
+from ..management.commands import synchronizethreads
 
 
 class SynchronizeThreadsTests(TestCase):

+ 4 - 5
misago/threads/tests/test_thread_bulkpatch_api.py

@@ -2,11 +2,10 @@ import json
 
 from django.urls import reverse
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.models import Thread
-from misago.threads.test import patch_category_acl, patch_other_category_acl
-
+from .. import test
+from ...categories.models import Category
+from ..models import Thread
+from ..test import patch_category_acl, patch_other_category_acl
 from .test_threads_api import ThreadsApiTestCase
 
 

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

@@ -4,12 +4,12 @@ from django.test.client import BOUNDARY, MULTIPART_CONTENT, encode_multipart
 from django.urls import reverse
 from django.utils import timezone
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.models import Post, Thread
-from misago.threads.test import patch_category_acl
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Post, Thread
+from ..test import patch_category_acl
 
 
 class EditReplyTests(AuthenticatedUserTestCase):

+ 5 - 6
misago/threads/tests/test_thread_merge_api.py

@@ -1,11 +1,10 @@
 from django.urls import reverse
 
-from misago.categories.models import Category
-from misago.readtracker import poststracker
-from misago.threads import test
-from misago.threads.models import Poll, PollVote, Thread
-from misago.threads.test import patch_category_acl, patch_other_category_acl
-
+from .. import test
+from ...categories.models import Category
+from ...readtracker import poststracker
+from ..models import Poll, PollVote, Thread
+from ..test import patch_category_acl, patch_other_category_acl
 from .test_threads_api import ThreadsApiTestCase
 
 

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

@@ -3,10 +3,10 @@ from datetime import timedelta
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.models import Poll, Post, Thread, ThreadParticipant
-from misago.users.test import create_test_user
+from .. import test
+from ...categories.models import Category
+from ...users.test import create_test_user
+from ..models import Poll, Post, Thread, ThreadParticipant
 
 
 class ThreadModelTests(TestCase):

+ 5 - 6
misago/threads/tests/test_thread_patch_api.py

@@ -3,12 +3,11 @@ from datetime import timedelta
 
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.readtracker import poststracker
-from misago.threads import test
-from misago.threads.test import patch_category_acl, patch_other_category_acl
-from misago.threads.models import Thread
-
+from .. import test
+from ...categories.models import Category
+from ...readtracker import poststracker
+from ..models import Thread
+from ..test import patch_category_acl, patch_other_category_acl
 from .test_threads_api import ThreadsApiTestCase
 
 

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

@@ -2,9 +2,9 @@ import json
 
 from django.urls import reverse
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
 
 
 class ThreadPollApiTestCase(AuthenticatedUserTestCase):

+ 4 - 5
misago/threads/tests/test_thread_pollcreate_api.py

@@ -1,10 +1,9 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.threads.models import Poll, Thread
-from misago.threads.serializers.poll import MAX_POLL_OPTIONS
-from misago.threads.test import patch_category_acl
-
+from ...acl.test import patch_user_acl
+from ..models import Poll, Thread
+from ..serializers.poll import MAX_POLL_OPTIONS
+from ..test import patch_category_acl
 from .test_thread_poll_api import ThreadPollApiTestCase
 
 

+ 3 - 4
misago/threads/tests/test_thread_polldelete_api.py

@@ -3,10 +3,9 @@ from datetime import timedelta
 from django.urls import reverse
 from django.utils import timezone
 
-from misago.acl.test import patch_user_acl
-from misago.threads.models import Poll, PollVote, Thread
-from misago.threads.test import patch_category_acl
-
+from ...acl.test import patch_user_acl
+from ..models import Poll, PollVote, Thread
+from ..test import patch_category_acl
 from .test_thread_poll_api import ThreadPollApiTestCase
 
 

+ 3 - 4
misago/threads/tests/test_thread_polledit_api.py

@@ -3,10 +3,9 @@ from datetime import timedelta
 from django.urls import reverse
 from django.utils import timezone
 
-from misago.acl.test import patch_user_acl
-from misago.threads.serializers.poll import MAX_POLL_OPTIONS
-from misago.threads.test import patch_category_acl
-
+from ...acl.test import patch_user_acl
+from ..serializers.poll import MAX_POLL_OPTIONS
+from ..test import patch_category_acl
 from .test_thread_poll_api import ThreadPollApiTestCase
 
 

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

@@ -4,10 +4,9 @@ from django.contrib.auth import get_user_model
 from django.urls import reverse
 from django.utils import timezone
 
-from misago.acl.test import patch_user_acl
-from misago.threads.models import Poll
-from misago.threads.test import patch_category_acl
-
+from ...acl.test import patch_user_acl
+from ..models import Poll
+from ..test import patch_category_acl
 from .test_thread_poll_api import ThreadPollApiTestCase
 
 User = get_user_model()

+ 3 - 4
misago/threads/tests/test_thread_postbulkdelete_api.py

@@ -4,10 +4,9 @@ from datetime import timedelta
 from django.urls import reverse
 from django.utils import timezone
 
-from misago.threads import test
-from misago.threads.models import Post, Thread
-from misago.threads.test import patch_category_acl
-
+from .. import test
+from ..models import Post, Thread
+from ..test import patch_category_acl
 from .test_threads_api import ThreadsApiTestCase
 
 

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

@@ -4,11 +4,11 @@ from datetime import timedelta
 from django.urls import reverse
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.models import Post, Thread
-from misago.threads.test import patch_category_acl
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Post, Thread
+from ..test import patch_category_acl
 
 
 class ThreadPostBulkPatchApiTestCase(AuthenticatedUserTestCase):

+ 3 - 4
misago/threads/tests/test_thread_postdelete_api.py

@@ -3,10 +3,9 @@ from datetime import timedelta
 from django.urls import reverse
 from django.utils import timezone
 
-from misago.threads import test
-from misago.threads.models import Post, Thread
-from misago.threads.test import patch_category_acl
-
+from .. import test
+from ..models import Post, Thread
+from ..test import patch_category_acl
 from .test_threads_api import ThreadsApiTestCase
 
 

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

@@ -1,8 +1,7 @@
 from django.urls import reverse
 
-from misago.threads import test
-from misago.threads.test import patch_category_acl
-
+from .. import test
+from ..test import patch_category_acl
 from .test_threads_api import ThreadsApiTestCase
 
 

+ 3 - 4
misago/threads/tests/test_thread_postlikes_api.py

@@ -1,9 +1,8 @@
 from django.urls import reverse
 
-from misago.threads import test
-from misago.threads.test import patch_category_acl
-from misago.threads.serializers import PostLikeSerializer
-
+from .. import test
+from ..serializers import PostLikeSerializer
+from ..test import patch_category_acl
 from .test_threads_api import ThreadsApiTestCase
 
 

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

@@ -2,13 +2,13 @@ import json
 
 from django.urls import reverse
 
-from misago.categories.models import Category
-from misago.readtracker import poststracker
-from misago.threads import test
-from misago.threads.models import Post, Thread
-from misago.threads.serializers.moderation import POSTS_LIMIT
-from misago.threads.test import patch_category_acl
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...categories.models import Category
+from ...readtracker import poststracker
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Post, Thread
+from ..serializers.moderation import POSTS_LIMIT
+from ..test import patch_category_acl
 
 
 class ThreadPostMergeApiTestCase(AuthenticatedUserTestCase):

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

@@ -2,13 +2,13 @@ import json
 
 from django.urls import reverse
 
-from misago.categories.models import Category
-from misago.readtracker import poststracker
-from misago.threads import test
-from misago.threads.models import Thread
-from misago.threads.serializers.moderation import POSTS_LIMIT
-from misago.threads.test import patch_category_acl, patch_other_category_acl
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...categories.models import Category
+from ...readtracker import poststracker
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Thread
+from ..serializers.moderation import POSTS_LIMIT
+from ..test import patch_category_acl, patch_other_category_acl
 
 
 class ThreadPostMoveApiTestCase(AuthenticatedUserTestCase):

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

@@ -4,11 +4,11 @@ from datetime import timedelta
 from django.urls import reverse
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.models import Thread, Post
-from misago.threads.test import patch_category_acl
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Post, Thread
+from ..test import patch_category_acl
 
 
 class ThreadPostPatchApiTestCase(AuthenticatedUserTestCase):

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

@@ -1,8 +1,7 @@
 from django.urls import reverse
 from django.utils import timezone
 
-from misago.threads import test
-
+from .. import test
 from .test_threads_api import ThreadsApiTestCase
 
 

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

@@ -2,13 +2,13 @@ import json
 
 from django.urls import reverse
 
-from misago.categories.models import Category
-from misago.readtracker import poststracker
-from misago.threads import test
-from misago.threads.models import Post, Thread
-from misago.threads.serializers.moderation import POSTS_LIMIT
-from misago.threads.test import patch_category_acl, patch_other_category_acl
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...categories.models import Category
+from ...readtracker import poststracker
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Post, Thread
+from ..serializers.moderation import POSTS_LIMIT
+from ..test import patch_category_acl, patch_other_category_acl
 
 
 class ThreadPostSplitApiTestCase(AuthenticatedUserTestCase):

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

@@ -1,11 +1,11 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.models import Thread
-from misago.threads.test import patch_category_acl
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Thread
+from ..test import patch_category_acl
 
 
 class ReplyThreadTests(AuthenticatedUserTestCase):

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

@@ -1,9 +1,9 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.threads.test import patch_category_acl
-from misago.users.test import AuthenticatedUserTestCase
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
+from ..test import patch_category_acl
 
 
 class StartThreadTests(AuthenticatedUserTestCase):

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

@@ -1,9 +1,9 @@
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.threads.models import Post, Thread, ThreadParticipant
-from misago.users.test import create_test_user
+from ...categories.models import Category
+from ...users.test import create_test_user
+from ..models import Post, Thread, ThreadParticipant
 
 
 class ThreadParticipantTests(TestCase):

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

@@ -1,15 +1,15 @@
 from datetime import timedelta
 
-from django.utils import timezone
 from django.urls import reverse
+from django.utils import timezone
 
-from misago.categories import THREADS_ROOT_NAME
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.models import Thread
-from misago.threads.test import patch_category_acl
-from misago.threads.threadtypes import trees_map
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...categories import THREADS_ROOT_NAME
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Thread
+from ..test import patch_category_acl
+from ..threadtypes import trees_map
 
 
 class ThreadsApiTestCase(AuthenticatedUserTestCase):

+ 7 - 8
misago/threads/tests/test_threads_bulkdelete_api.py

@@ -2,14 +2,13 @@ import json
 
 from django.urls import reverse
 
-from misago.categories import PRIVATE_THREADS_ROOT_NAME
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.models import Thread
-from misago.threads.serializers.moderation import THREADS_LIMIT
-from misago.threads.test import patch_category_acl
-from misago.threads.threadtypes import trees_map
-
+from .. import test
+from ...categories import PRIVATE_THREADS_ROOT_NAME
+from ...categories.models import Category
+from ..models import Thread
+from ..serializers.moderation import THREADS_LIMIT
+from ..test import patch_category_acl
+from ..threadtypes import trees_map
 from .test_threads_api import ThreadsApiTestCase
 
 

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

@@ -2,15 +2,15 @@ import os
 
 from django.urls import reverse
 
-from misago.acl import useracl
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories.models import Category
-from misago.conftest import get_cache_versions
-from misago.threads import test
-from misago.threads.models import Attachment
-from misago.threads.serializers import AttachmentSerializer
-from misago.threads.test import patch_category_acl
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...acl import useracl
+from ...acl.objectacl import add_acl_to_obj
+from ...categories.models import Category
+from ...conftest import get_cache_versions
+from ...users.test import AuthenticatedUserTestCase
+from ..models import Attachment
+from ..serializers import AttachmentSerializer
+from ..test import patch_category_acl
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_DOCUMENT_PATH = os.path.join(TESTFILES_DIR, "document.pdf")

+ 10 - 11
misago/threads/tests/test_threads_merge_api.py

@@ -2,17 +2,16 @@ import json
 
 from django.urls import reverse
 
-from misago.acl import useracl
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories.models import Category
-from misago.conftest import get_cache_versions
-from misago.readtracker import poststracker
-from misago.threads import test
-from misago.threads.models import Poll, PollVote, Post, Thread
-from misago.threads.serializers import ThreadsListSerializer
-from misago.threads.serializers.moderation import THREADS_LIMIT
-from misago.threads.test import patch_category_acl, patch_other_category_acl
-
+from .. import test
+from ...acl import useracl
+from ...acl.objectacl import add_acl_to_obj
+from ...categories.models import Category
+from ...conftest import get_cache_versions
+from ...readtracker import poststracker
+from ..models import Poll, PollVote, Post, Thread
+from ..serializers import ThreadsListSerializer
+from ..serializers.moderation import THREADS_LIMIT
+from ..test import patch_category_acl, patch_other_category_acl
 from .test_threads_api import ThreadsApiTestCase
 
 cache_versions = get_cache_versions()

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

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

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

@@ -4,13 +4,13 @@ from django.urls import reverse
 from django.utils import timezone
 from django.utils.encoding import smart_str
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.readtracker import poststracker
-from misago.threads import test
-from misago.users.models import AnonymousUser
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...conf import settings
+from ...readtracker import poststracker
+from ...users.models import AnonymousUser
+from ...users.test import AuthenticatedUserTestCase
 
 LISTS_URLS = ("", "my/", "new/", "unread/", "subscribed/")
 

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

@@ -1,16 +1,16 @@
 from unittest.mock import Mock
 
-from misago.acl import useracl
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.conftest import get_cache_versions
-from misago.threads import test
-from misago.threads.checksums import update_post_checksum
-from misago.threads.events import record_event
-from misago.threads.moderation import threads as threads_moderation
-from misago.threads.moderation import hide_post
-from misago.users.test import AuthenticatedUserTestCase
+from .. import test
+from ...acl import useracl
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...conf import settings
+from ...conftest import get_cache_versions
+from ...users.test import AuthenticatedUserTestCase
+from ..checksums import update_post_checksum
+from ..events import record_event
+from ..moderation import hide_post
+from ..moderation import threads as threads_moderation
 
 cache_versions = get_cache_versions()
 

+ 2 - 3
misago/threads/tests/test_treesmap.py

@@ -1,8 +1,7 @@
 from django.test import TestCase
 
-from misago.categories.models import Category
-from misago.threads.threadtypes.treesmap import TreesMap
-
+from ...categories.models import Category
+from ..threadtypes.treesmap import TreesMap
 
 THREAD_TYPE = "misago.threads.threadtypes.thread.Thread"
 

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

@@ -3,10 +3,10 @@ from io import StringIO
 from django.core.management import call_command
 from django.test import TestCase
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.management.commands import updatepostschecksums
-from misago.threads.models import Post
+from .. import test
+from ...categories.models import Category
+from ..management.commands import updatepostschecksums
+from ..models import Post
 
 
 class UpdatePostsChecksumsTests(TestCase):

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

@@ -1,8 +1,8 @@
 from django.test import TestCase
 
-from misago.categories.models import Category
-from misago.threads import test
-from misago.threads.utils import add_categories_to_items, get_thread_id_from_url
+from .. import test
+from ...categories.models import Category
+from ..utils import add_categories_to_items, get_thread_id_from_url
 
 
 class AddCategoriesToItemsTests(TestCase):

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

@@ -1,7 +1,7 @@
 from django.urls import reverse
 
-from misago.categories.models import Category
-from misago.users.test import AuthenticatedUserTestCase
+from ...categories.models import Category
+from ...users.test import AuthenticatedUserTestCase
 
 
 class ValidatePostTests(AuthenticatedUserTestCase):

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

@@ -3,7 +3,7 @@ from unittest.mock import Mock
 from django.core.exceptions import ValidationError
 from django.test import TestCase
 
-from misago.threads.validators import validate_post_length, validate_thread_title
+from ..validators import validate_post_length, validate_thread_title
 
 
 class ValidatePostLengthTests(TestCase):

+ 1 - 2
misago/threads/threadtypes/privatethread.py

@@ -1,9 +1,8 @@
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from misago.categories import PRIVATE_THREADS_ROOT_NAME
-
 from . import ThreadType
+from ...categories import PRIVATE_THREADS_ROOT_NAME
 
 
 class PrivateThread(ThreadType):

+ 1 - 2
misago/threads/threadtypes/thread.py

@@ -1,9 +1,8 @@
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from misago.categories import THREADS_ROOT_NAME
-
 from . import ThreadType
+from ...categories import THREADS_ROOT_NAME
 
 
 class Thread(ThreadType):

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

@@ -1,6 +1,6 @@
 from django.utils.module_loading import import_string
 
-from misago.conf import settings
+from ...conf import settings
 
 
 class TreesMap(object):
@@ -24,7 +24,7 @@ class TreesMap(object):
         return loaded_types
 
     def load_trees(self, types):
-        from misago.categories.models import Category
+        from ...categories.models import Category
 
         trees = {}
         for category in Category.objects.filter(level=0, special_role__in=types.keys()):

+ 5 - 9
misago/threads/urls/__init__.py

@@ -1,9 +1,9 @@
 from django.conf.urls import url
 
-from misago.conf import settings
+from ...conf import settings
 
-from misago.threads.views.attachment import attachment_server
-from misago.threads.views.goto import (
+from ..views.attachment import attachment_server
+from ..views.goto import (
     ThreadGotoPostView,
     ThreadGotoLastView,
     ThreadGotoNewView,
@@ -13,12 +13,8 @@ from misago.threads.views.goto import (
     PrivateThreadGotoLastView,
     PrivateThreadGotoNewView,
 )
-from misago.threads.views.list import (
-    ForumThreadsList,
-    CategoryThreadsList,
-    PrivateThreadsList,
-)
-from misago.threads.views.thread import ThreadView, PrivateThreadView
+from ..views.list import ForumThreadsList, CategoryThreadsList, PrivateThreadsList
+from ..views.thread import ThreadView, PrivateThreadView
 
 LISTS_TYPES = ("all", "my", "new", "unread", "subscribed", "unapproved")
 

+ 5 - 6
misago/threads/urls/api.py

@@ -1,9 +1,8 @@
-from misago.core.apirouter import MisagoApiRouter
-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
-
+from ...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
 
 router = MisagoApiRouter()
 

+ 5 - 6
misago/threads/validators.py

@@ -3,12 +3,11 @@ from django.utils.module_loading import import_string
 from django.utils.translation import gettext as _
 from django.utils.translation import ngettext
 
-from misago.categories import THREADS_ROOT_NAME
-from misago.categories.models import Category
-from misago.categories.permissions import can_browse_category, can_see_category
-from misago.conf import settings
-from misago.core.validators import validate_sluggable
-
+from ..categories import THREADS_ROOT_NAME
+from ..categories.models import Category
+from ..categories.permissions import can_browse_category, can_see_category
+from ..conf import settings
+from ..core.validators import validate_sluggable
 from .threadtypes import trees_map
 
 

+ 7 - 8
misago/threads/viewmodels/category.py

@@ -1,13 +1,12 @@
 from django.http import Http404
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories.models import Category
-from misago.categories.permissions import allow_browse_category, allow_see_category
-from misago.categories.serializers import CategorySerializer
-from misago.core.shortcuts import validate_slug
-from misago.core.viewmodel import ViewModel as BaseViewModel
-from misago.threads.permissions import allow_use_private_threads
-
+from ...acl.objectacl import add_acl_to_obj
+from ...categories.models import Category
+from ...categories.permissions import allow_browse_category, allow_see_category
+from ...categories.serializers import CategorySerializer
+from ...core.shortcuts import validate_slug
+from ...core.viewmodel import ViewModel as BaseViewModel
+from ..permissions import allow_use_private_threads
 
 __all__ = ["ThreadsRootCategory", "ThreadsCategory", "PrivateThreadsCategory"]
 

+ 3 - 4
misago/threads/viewmodels/post.py

@@ -1,9 +1,8 @@
 from django.shortcuts import get_object_or_404
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.core.viewmodel import ViewModel as BaseViewModel
-from misago.threads.permissions import exclude_invisible_posts
-
+from ...acl.objectacl import add_acl_to_obj
+from ...core.viewmodel import ViewModel as BaseViewModel
+from ..permissions import exclude_invisible_posts
 
 __all__ = ["ThreadPost"]
 

+ 9 - 10
misago/threads/viewmodels/posts.py

@@ -1,13 +1,12 @@
-from misago.acl.objectacl import add_acl_to_obj
-from misago.conf import settings
-from misago.core.shortcuts import paginate, pagination_dict
-from misago.readtracker.poststracker import make_read_aware
-from misago.threads.paginator import PostsPaginator
-from misago.threads.permissions import exclude_invisible_posts
-from misago.threads.serializers import PostSerializer
-from misago.threads.utils import add_likes_to_posts
-from misago.users.online.utils import make_users_status_aware
-
+from ...acl.objectacl import add_acl_to_obj
+from ...conf import settings
+from ...core.shortcuts import paginate, pagination_dict
+from ...readtracker.poststracker import make_read_aware
+from ...users.online.utils import make_users_status_aware
+from ..paginator import PostsPaginator
+from ..permissions import exclude_invisible_posts
+from ..serializers import PostSerializer
+from ..utils import add_likes_to_posts
 
 __all__ = ["ThreadPosts"]
 

+ 12 - 13
misago/threads/viewmodels/thread.py

@@ -1,23 +1,22 @@
 from django.shortcuts import get_object_or_404
 from django.utils.translation import gettext as _
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories import PRIVATE_THREADS_ROOT_NAME, THREADS_ROOT_NAME
-from misago.categories.models import Category
-from misago.core.shortcuts import validate_slug
-from misago.core.viewmodel import ViewModel as BaseViewModel
-from misago.readtracker.threadstracker import make_read_aware
-from misago.threads.models import Poll, Thread
-from misago.threads.participants import make_participants_aware
-from misago.threads.permissions import (
+from ...acl.objectacl import add_acl_to_obj
+from ...categories import PRIVATE_THREADS_ROOT_NAME, THREADS_ROOT_NAME
+from ...categories.models import Category
+from ...core.shortcuts import validate_slug
+from ...core.viewmodel import ViewModel as BaseViewModel
+from ...readtracker.threadstracker import make_read_aware
+from ..models import Poll, Thread
+from ..participants import make_participants_aware
+from ..permissions import (
     allow_see_private_thread,
     allow_see_thread,
     allow_use_private_threads,
 )
-from misago.threads.serializers import PrivateThreadSerializer, ThreadSerializer
-from misago.threads.subscriptions import make_subscription_aware
-from misago.threads.threadtypes import trees_map
-
+from ..serializers import PrivateThreadSerializer, ThreadSerializer
+from ..subscriptions import make_subscription_aware
+from ..threadtypes import trees_map
 
 __all__ = ["ForumThread", "PrivateThread"]
 

+ 11 - 14
misago/threads/viewmodels/threads.py

@@ -7,20 +7,17 @@ from django.utils import timezone
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext_lazy
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.conf import settings
-from misago.core.shortcuts import paginate, pagination_dict
-from misago.readtracker import threadstracker
-from misago.readtracker.dates import get_cutoff_date
-from misago.threads.models import Post, Thread
-from misago.threads.participants import make_participants_aware
-from misago.threads.permissions import (
-    exclude_invisible_posts,
-    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
+from ...acl.objectacl import add_acl_to_obj
+from ...conf import settings
+from ...core.shortcuts import paginate, pagination_dict
+from ...readtracker import threadstracker
+from ...readtracker.dates import get_cutoff_date
+from ..models import Post, Thread
+from ..participants import make_participants_aware
+from ..permissions import exclude_invisible_posts, exclude_invisible_threads
+from ..serializers import ThreadsListSerializer
+from ..subscriptions import make_subscription_aware
+from ..utils import add_categories_to_items
 
 __all__ = ["ForumThreads", "PrivateThreads", "filter_read_threads_queryset"]
 

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

@@ -2,9 +2,9 @@ from django.contrib import messages
 from django.db import transaction
 from django.utils.translation import gettext_lazy as _
 
-from misago.admin.views import generic
-from misago.threads.forms import SearchAttachmentsForm
-from misago.threads.models import Attachment, Post
+from ....admin.views import generic
+from ...forms import SearchAttachmentsForm
+from ...models import Attachment, Post
 
 
 class AttachmentAdmin(generic.AdminBaseMixin):

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

@@ -2,9 +2,9 @@ from django.contrib import messages
 from django.db.models import Count
 from django.utils.translation import gettext_lazy as _
 
-from misago.admin.views import generic
-from misago.threads.forms import AttachmentTypeForm
-from misago.threads.models import AttachmentType
+from ....admin.views import generic
+from ...forms import AttachmentTypeForm
+from ...models import AttachmentType
 
 
 class AttachmentTypeAdmin(generic.AdminBaseMixin):

+ 2 - 3
misago/threads/views/attachment.py

@@ -2,9 +2,8 @@ from django.core.exceptions import PermissionDenied
 from django.http import Http404
 from django.shortcuts import get_object_or_404, redirect
 
-from misago.conf import settings
-from misago.threads.models import Attachment, AttachmentType
-
+from ...conf import settings
+from ..models import Attachment, AttachmentType
 
 ATTACHMENT_404_URL = "".join((settings.STATIC_URL, settings.MISAGO_404_IMAGE))
 ATTACHMENT_403_URL = "".join((settings.STATIC_URL, settings.MISAGO_403_IMAGE))

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

@@ -6,10 +6,10 @@ from django.shortcuts import get_object_or_404, redirect
 from django.utils.translation import gettext as _
 from django.views import View
 
-from misago.conf import settings
-from misago.readtracker.dates import get_cutoff_date
-from misago.threads.permissions import exclude_invisible_posts
-from misago.threads.viewmodels import ForumThread, PrivateThread
+from ...conf import settings
+from ...readtracker.dates import get_cutoff_date
+from ..permissions import exclude_invisible_posts
+from ..viewmodels import ForumThread, PrivateThread
 
 
 class GotoView(View):

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

@@ -3,8 +3,8 @@ from django.shortcuts import render
 from django.urls import reverse
 from django.views import View
 
-from misago.core.shortcuts import get_int_or_404
-from misago.threads.viewmodels import (
+from ...core.shortcuts import get_int_or_404
+from ..viewmodels import (
     ForumThreads,
     PrivateThreads,
     PrivateThreadsCategory,

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

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

+ 2 - 3
misago/urls.py

@@ -1,9 +1,8 @@
 from django.conf.urls import include, url
 from django.views.generic import TemplateView
 
-from misago.conf import settings
-from misago.core.views import forum_index
-
+from .conf import settings
+from .core.views import forum_index
 
 app_name = "misago"
 

+ 2 - 4
misago/users/activepostersranking.py

@@ -4,12 +4,10 @@ from django.contrib.auth import get_user_model
 from django.db.models import Count
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.conf import settings
-
+from ..categories.models import Category
+from ..conf import settings
 from .models import ActivityRanking
 
-
 User = get_user_model()
 
 

+ 0 - 1
misago/users/admin.py

@@ -25,7 +25,6 @@ from .views.admin.users import (
     UsersList,
 )
 
-
 djadmin.site.register(model_or_iterable=get_user_model(), admin_class=UserAdminModel)
 
 

+ 10 - 20
misago/users/api/auth.py

@@ -1,35 +1,25 @@
-from rest_framework import status
-from rest_framework.decorators import api_view, permission_classes
-from rest_framework.response import Response
-
 from django.contrib import auth
 from django.contrib.auth.password_validation import validate_password
 from django.core.exceptions import ValidationError
 from django.utils.translation import gettext as _
 from django.views.decorators.csrf import csrf_protect
+from rest_framework import status
+from rest_framework.decorators import api_view, permission_classes
+from rest_framework.response import Response
 
-from misago.conf import settings
-from misago.core.decorators import require_dict_data
-from misago.core.mail import mail_user
-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 (
+from ...conf import settings
+from ...core.decorators import require_dict_data
+from ...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 .rest_permissions import UnbannedAnonOnly, UnbannedOnly
 
-
 User = auth.get_user_model()
 
 

+ 1 - 2
misago/users/api/captcha.py

@@ -1,8 +1,7 @@
+from django.http import Http404
 from rest_framework.decorators import api_view
 from rest_framework.response import Response
 
-from django.http import Http404
-
 
 @api_view()
 def question(request):

+ 3 - 5
misago/users/api/mention.py

@@ -1,11 +1,9 @@
-from rest_framework.decorators import api_view
-from rest_framework.response import Response
-
 from django.contrib.auth import get_user_model
 from django.contrib.staticfiles.templatetags.staticfiles import static
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
 
-from misago.conf import settings
-
+from ...conf import settings
 
 User = get_user_model()
 

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

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

+ 4 - 5
misago/users/api/rest_permissions.py

@@ -1,11 +1,10 @@
-from rest_framework.permissions import BasePermission
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
+from rest_framework.permissions import BasePermission
 
-from misago.core.exceptions import Banned
-from misago.users.bans import get_request_ip_ban
-from misago.users.models import Ban
+from ...core.exceptions import Banned
+from ..bans import get_request_ip_ban
+from ..models import Ban
 
 
 class UnbannedOnly(BasePermission):

+ 8 - 9
misago/users/api/userendpoints/avatar.py

@@ -1,17 +1,16 @@
 import json
 
-from rest_framework import status
-from rest_framework.response import Response
-
 from django.core.exceptions import ValidationError
 from django.utils.translation import gettext as _
+from rest_framework import status
+from rest_framework.response import Response
 
-from misago.conf import settings
-from misago.core.decorators import require_dict_data
-from misago.core.utils import format_plaintext_for_html
-from misago.users import avatars
-from misago.users.models import AvatarGallery
-from misago.users.serializers import ModerateAvatarSerializer
+from ... import avatars
+from ....conf import settings
+from ....core.decorators import require_dict_data
+from ....core.utils import format_plaintext_for_html
+from ...models import AvatarGallery
+from ...serializers import ModerateAvatarSerializer
 
 
 @require_dict_data

+ 5 - 6
misago/users/api/userendpoints/changeemail.py

@@ -1,12 +1,11 @@
+from django.utils.translation import gettext as _
 from rest_framework import status
 from rest_framework.response import Response
 
-from django.utils.translation import gettext as _
-
-from misago.conf import settings
-from misago.core.mail import mail_user
-from misago.users.credentialchange import store_new_credential
-from misago.users.serializers import ChangeEmailSerializer
+from ....conf import settings
+from ....core.mail import mail_user
+from ...credentialchange import store_new_credential
+from ...serializers import ChangeEmailSerializer
 
 
 def change_email_endpoint(request, pk=None):

+ 4 - 5
misago/users/api/userendpoints/changepassword.py

@@ -1,11 +1,10 @@
+from django.utils.translation import gettext as _
 from rest_framework import status
 from rest_framework.response import Response
 
-from django.utils.translation import gettext as _
-
-from misago.core.mail import mail_user
-from misago.users.credentialchange import store_new_credential
-from misago.users.serializers import ChangePasswordSerializer
+from ....core.mail import mail_user
+from ...credentialchange import store_new_credential
+from ...serializers import ChangePasswordSerializer
 
 
 def change_password_endpoint(request, pk=None):

+ 8 - 9
misago/users/api/userendpoints/create.py

@@ -1,22 +1,21 @@
-from rest_framework import status
-from rest_framework.response import Response
-
 from django.contrib.auth import authenticate, get_user_model, login
 from django.core.exceptions import PermissionDenied, ValidationError
 from django.db import IntegrityError
 from django.utils.translation import gettext as _
 from django.views.decorators.csrf import csrf_protect
+from rest_framework import status
+from rest_framework.response import Response
 
-from misago.conf import settings
-from misago.legal.models import Agreement
-from misago.users import captcha
-from misago.users.forms.register import RegisterForm
-from misago.users.registration import (
+from ... import captcha
+from ....conf import settings
+from ....legal.models import Agreement
+from ...forms.register import RegisterForm
+from ...registration import (
     get_registration_result_json,
     save_user_agreements,
     send_welcome_email,
 )
-from misago.users.setupnewuser import setup_new_user
+from ...setupnewuser import setup_new_user
 
 User = get_user_model()
 

+ 2 - 4
misago/users/api/userendpoints/editdetails.py

@@ -1,9 +1,7 @@
-from rest_framework.response import Response
-
 from django import forms
+from rest_framework.response import Response
 
-
-from misago.users.profilefields import profilefields, serialize_profilefields_data
+from ...profilefields import profilefields, serialize_profilefields_data
 
 
 def edit_details_endpoint(request, user):

+ 5 - 7
misago/users/api/userendpoints/list.py

@@ -1,13 +1,11 @@
-from rest_framework.response import Response
-
 from django.contrib.auth import get_user_model
 from django.shortcuts import get_object_or_404
+from rest_framework.response import Response
 
-from misago.core.shortcuts import get_int_or_404
-from misago.users.models import Rank
-from misago.users.serializers import UserCardSerializer
-from misago.users.viewmodels import ActivePosters, RankUsers
-
+from ....core.shortcuts import get_int_or_404
+from ...models import Rank
+from ...serializers import UserCardSerializer
+from ...viewmodels import ActivePosters, RankUsers
 
 User = get_user_model()
 

+ 5 - 6
misago/users/api/userendpoints/signature.py

@@ -1,12 +1,11 @@
-from rest_framework import status
-from rest_framework.response import Response
-
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
+from rest_framework import status
+from rest_framework.response import Response
 
-from misago.core.utils import format_plaintext_for_html
-from misago.users.serializers import EditSignatureSerializer
-from misago.users.signatures import is_user_signature_valid, set_user_signature
+from ....core.utils import format_plaintext_for_html
+from ...serializers import EditSignatureSerializer
+from ...signatures import is_user_signature_valid, set_user_signature
 
 
 def signature_endpoint(request):

+ 4 - 5
misago/users/api/userendpoints/username.py

@@ -1,11 +1,10 @@
-from rest_framework import status
-from rest_framework.response import Response
-
 from django.db import IntegrityError
 from django.utils.translation import gettext as _
+from rest_framework import status
+from rest_framework.response import Response
 
-from misago.users.namechanges import get_username_options
-from misago.users.serializers import ChangeUsernameSerializer
+from ...namechanges import get_username_options
+from ...serializers import ChangeUsernameSerializer
 
 
 def username_endpoint(request):

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

@@ -1,19 +1,16 @@
-from rest_framework import viewsets
-from rest_framework.response import Response
-
 from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.db.models import Q
 from django.shortcuts import get_object_or_404
 from django.utils.translation import gettext as _
+from rest_framework import viewsets
+from rest_framework.response import Response
 
-from misago.core.shortcuts import get_int_or_404, paginate, pagination_dict
-from misago.users.models import UsernameChange
-from misago.users.serializers import UsernameChangeSerializer
-
+from ...core.shortcuts import get_int_or_404, paginate, pagination_dict
+from ..models import UsernameChange
+from ..serializers import UsernameChangeSerializer
 from .rest_permissions import BasePermission
 
-
 User = get_user_model()
 
 

+ 17 - 23
misago/users/api/users.py

@@ -1,8 +1,3 @@
-from rest_framework import status, viewsets
-from rest_framework.decorators import detail_route
-from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
-from rest_framework.response import Response
-
 from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.db import transaction
@@ -10,20 +5,21 @@ from django.db.models import F
 from django.http import Http404
 from django.shortcuts import get_object_or_404
 from django.utils.translation import gettext as _
+from rest_framework import status, viewsets
+from rest_framework.decorators import detail_route
+from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
+from rest_framework.response import Response
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.categories.models import Category
-from misago.conf import settings
-from misago.core.rest_permissions import IsAuthenticatedOrReadOnly
-from misago.core.shortcuts import get_int_or_404
-from misago.threads.moderation import hide_post, hide_thread
-from misago.users.bans import get_user_ban
-from misago.users.datadownloads import (
-    request_user_data_download,
-    user_has_data_download_request,
-)
-from misago.users.online.utils import get_user_status
-from misago.users.permissions import (
+from ...acl.objectacl import add_acl_to_obj
+from ...categories.models import Category
+from ...conf import settings
+from ...core.rest_permissions import IsAuthenticatedOrReadOnly
+from ...core.shortcuts import get_int_or_404
+from ...threads.moderation import hide_post, hide_thread
+from ..bans import get_user_ban
+from ..datadownloads import request_user_data_download, user_has_data_download_request
+from ..online.utils import get_user_status
+from ..permissions import (
     allow_browse_users_list,
     allow_delete_user,
     allow_edit_profile_details,
@@ -32,16 +28,15 @@ from misago.users.permissions import (
     allow_rename_user,
     allow_see_ban_details,
 )
-from misago.users.profilefields import profilefields, serialize_profilefields_data
-from misago.users.serializers import (
+from ..profilefields import profilefields, serialize_profilefields_data
+from ..serializers import (
     BanDetailsSerializer,
     DataDownloadSerializer,
     DeleteOwnAccountSerializer,
     ForumOptionsSerializer,
     UserSerializer,
 )
-from misago.users.viewmodels import Followers, Follows, UserPosts, UserThreads
-
+from ..viewmodels import Followers, Follows, UserPosts, UserThreads
 from .rest_permissions import BasePermission, UnbannedAnonOnly
 from .userendpoints.avatar import avatar_endpoint, moderate_avatar_endpoint
 from .userendpoints.changeemail import change_email_endpoint
@@ -52,7 +47,6 @@ from .userendpoints.list import list_endpoint
 from .userendpoints.signature import signature_endpoint
 from .userendpoints.username import moderate_username_endpoint, username_endpoint
 
-
 User = get_user_model()
 
 

+ 1 - 2
misago/users/apps.py

@@ -1,8 +1,7 @@
 from django.apps import AppConfig
 from django.utils.translation import gettext_lazy as _
 
-from misago.conf import settings
-
+from ..conf import settings
 from .pages import user_profile, usercp, users_list
 
 

+ 0 - 1
misago/users/authbackends.py

@@ -1,7 +1,6 @@
 from django.contrib.auth import get_user_model
 from django.contrib.auth.backends import ModelBackend
 
-
 User = get_user_model()
 
 

+ 1 - 2
misago/users/avatars/__init__.py

@@ -1,5 +1,4 @@
-from misago.conf import settings
-
+from ...conf import settings
 from . import store, gravatar, dynamic, gallery, uploaded
 
 AVATAR_TYPES = ("gravatar", "dynamic", "gallery", "uploaded")

+ 2 - 5
misago/users/avatars/dynamic.py

@@ -1,13 +1,10 @@
 import os
 
-from PIL import Image, ImageColor, ImageDraw, ImageFont
-
 from django.utils.module_loading import import_string
-
-from misago.conf import settings
+from PIL import Image, ImageColor, ImageDraw, ImageFont
 
 from . import store
-
+from ...conf import settings
 
 COLOR_WHEEL = (
     "#d32f2f",

+ 5 - 8
misago/users/avatars/gallery.py

@@ -1,14 +1,11 @@
 import random
 from pathlib import Path
 
-from PIL import Image
-
 from django.core.files.base import ContentFile
-
-from misago.conf import settings
+from PIL import Image
 
 from . import store
-
+from ...conf import settings
 
 DEFAULT_GALLERY = "__default__"
 
@@ -20,7 +17,7 @@ def get_available_galleries(include_default=False):
     Only jpgs, gifs and pngs are supported avatar images.
     Galleries are
     """
-    from misago.users.models import AvatarGallery
+    from ..models import AvatarGallery
 
     galleries = []
     galleries_dicts = {}
@@ -40,13 +37,13 @@ def get_available_galleries(include_default=False):
 
 
 def galleries_exist():
-    from misago.users.models import AvatarGallery
+    from ..models import AvatarGallery
 
     return AvatarGallery.objects.exists()
 
 
 def load_avatar_galleries():
-    from misago.users.models import AvatarGallery
+    from ..models import AvatarGallery
 
     galleries = []
     for directory in Path(settings.MISAGO_AVATAR_GALLERY).iterdir():

+ 1 - 3
misago/users/avatars/gravatar.py

@@ -3,10 +3,8 @@ from io import BytesIO
 import requests
 from PIL import Image
 
-from misago.conf import settings
-
 from . import store
-
+from ...conf import settings
 
 GRAVATAR_URL = "http://www.gravatar.com/avatar/%s?s=%s&d=404"
 

+ 3 - 4
misago/users/avatars/store.py

@@ -2,12 +2,11 @@ import os
 from hashlib import md5
 from io import BytesIO
 
-from PIL import Image
-
 from django.core.files.base import ContentFile
 from django.utils.crypto import get_random_string
+from PIL import Image
 
-from misago.conf import settings
+from ...conf import settings
 
 
 def normalize_image(image):
@@ -29,7 +28,7 @@ def delete_avatar(user, delete_tmp=True, delete_src=True):
 
 
 def store_avatar(user, image):
-    from misago.users.models import Avatar
+    from ..models import Avatar
 
     image = normalize_image(image)
 

+ 2 - 4
misago/users/avatars/uploaded.py

@@ -1,13 +1,11 @@
 from pathlib import Path
 
-from PIL import Image
-
 from django.core.exceptions import ValidationError
 from django.utils.translation import gettext as _
-
-from misago.conf import settings
+from PIL import Image
 
 from . import store
+from ...conf import settings
 
 ALLOWED_EXTENSIONS = (".gif", ".png", ".jpg", ".jpeg")
 ALLOWED_MIME_TYPES = ("image/gif", "image/jpeg", "image/png", "image/mpo")

+ 0 - 1
misago/users/captcha.py

@@ -1,5 +1,4 @@
 import requests
-
 from django.core.exceptions import ValidationError
 from django.utils.translation import gettext as _
 

+ 3 - 3
misago/users/datadownloads/__init__.py

@@ -2,9 +2,9 @@ from datetime import timedelta
 
 from django.utils import timezone
 
-from misago.conf import settings
-from misago.users.models import DataDownload
-from misago.users.signals import archive_user_data
+from ...conf import settings
+from ..models import DataDownload
+from ..signals import archive_user_data
 
 from .dataarchive import DataArchive
 

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

@@ -5,8 +5,7 @@ from django.core.files import File
 from django.utils import timezone
 from django.utils.crypto import get_random_string
 
-from misago.core.utils import slugify
-
+from ...core.utils import slugify
 
 FILENAME_MAX_LEN = 50
 

+ 1 - 2
misago/users/decorators.py

@@ -3,8 +3,7 @@ from django.core.exceptions import PermissionDenied
 from django.shortcuts import redirect
 from django.utils.translation import gettext as _
 
-from misago.core.exceptions import Banned
-
+from ..core.exceptions import Banned
 from .bans import get_request_ip_ban
 from .models import Ban
 

+ 8 - 9
misago/users/forms/admin.py

@@ -1,18 +1,17 @@
 from django import forms
-from django.db.models import Q
 from django.contrib.auth import get_user_model
 from django.contrib.auth.password_validation import validate_password
+from django.db.models import Q
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import ngettext
 
-from misago.acl.models import Role
-from misago.admin.forms import IsoDateTimeField, YesNoSwitch
-from misago.core.validators import validate_sluggable
-
-from misago.users.models import Ban, DataDownload, Rank
-from misago.users.profilefields import profilefields
-from misago.users.utils import hash_email
-from misago.users.validators import validate_email, validate_username
+from ...acl.models import Role
+from ...admin.forms import IsoDateTimeField, YesNoSwitch
+from ...core.validators import validate_sluggable
+from ..models import Ban, DataDownload, Rank
+from ..profilefields import profilefields
+from ..utils import hash_email
+from ..validators import validate_email, validate_username
 
 User = get_user_model()
 

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

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

+ 2 - 7
misago/users/forms/register.py

@@ -4,13 +4,8 @@ from django.contrib.auth.password_validation import validate_password
 from django.core.exceptions import ValidationError
 from django.utils.translation import gettext as _
 
-from misago.users.bans import get_email_ban, get_ip_ban, get_username_ban
-from misago.users.validators import (
-    validate_email,
-    validate_new_registration,
-    validate_username,
-)
-
+from ..bans import get_email_ban, get_ip_ban, get_username_ban
+from ..validators import validate_email, validate_new_registration, validate_username
 
 User = get_user_model()
 

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

@@ -1,7 +1,8 @@
 from time import time
+
 from django.core.management.base import BaseCommand
 
-from misago.users.activepostersranking import build_active_posters_ranking
+from ...activepostersranking import build_active_posters_ranking
 
 
 class Command(BaseCommand):

+ 4 - 5
misago/users/management/commands/createsuperuser.py

@@ -12,11 +12,10 @@ from django.core.management.base import BaseCommand
 from django.db import DEFAULT_DB_ALIAS, IntegrityError
 from django.utils.encoding import force_str
 
-from misago.cache.versions import get_cache_versions
-from misago.conf.dynamicsettings import DynamicSettings
-
-from misago.users.setupnewuser import setup_new_user
-from misago.users.validators import validate_email, validate_username
+from ....cache.versions import get_cache_versions
+from ....conf.dynamicsettings import DynamicSettings
+from ...setupnewuser import setup_new_user
+from ...validators import validate_email, validate_username
 
 User = get_user_model()
 

+ 2 - 3
misago/users/management/commands/deleteinactiveusers.py

@@ -4,9 +4,8 @@ from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 from django.utils import timezone
 
-from misago.conf import settings
-from misago.core.pgutils import chunk_queryset
-
+from ....conf import settings
+from ....core.pgutils import chunk_queryset
 
 User = get_user_model()
 

+ 4 - 6
misago/users/management/commands/deletemarkedusers.py

@@ -1,11 +1,9 @@
 from django.contrib.auth import get_user_model
-from django.core.management.base import CommandError, BaseCommand
-
-from misago.conf import settings
-from misago.core.pgutils import chunk_queryset
-
-from misago.users.permissions import can_delete_own_account
+from django.core.management.base import BaseCommand, CommandError
 
+from ....conf import settings
+from ....core.pgutils import chunk_queryset
+from ...permissions import can_delete_own_account
 
 User = get_user_model()
 

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

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
-from django.core.management.base import CommandError, BaseCommand
+from django.core.management.base import BaseCommand, CommandError
 
-from misago.core.pgutils import chunk_queryset
+from ....core.pgutils import chunk_queryset
 
 User = get_user_model()
 

+ 3 - 3
misago/users/management/commands/expireuserdatadownloads.py

@@ -1,9 +1,9 @@
 from django.core.management.base import BaseCommand
 from django.utils import timezone
 
-from misago.core.pgutils import chunk_queryset
-from misago.users.datadownloads import expire_user_data_download
-from misago.users.models import DataDownload
+from ....core.pgutils import chunk_queryset
+from ...datadownloads import expire_user_data_download
+from ...models import DataDownload
 
 
 class Command(BaseCommand):

+ 3 - 4
misago/users/management/commands/invalidatebans.py

@@ -1,10 +1,9 @@
 from django.core.management.base import BaseCommand
 from django.utils import timezone
 
-from misago.cache.versions import get_cache_versions
-
-from misago.users import BANS_CACHE
-from misago.users.models import Ban, BanCache
+from ....cache.versions import get_cache_versions
+from ....users import BANS_CACHE
+from ...models import Ban, BanCache
 
 
 class Command(BaseCommand):

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

@@ -1,8 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 
-from misago.core.pgutils import chunk_queryset
-
+from ....core.pgutils import chunk_queryset
 
 User = get_user_model()
 

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

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

+ 2 - 3
misago/users/management/commands/populateonlinetracker.py

@@ -1,9 +1,8 @@
 from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 
-from misago.core.pgutils import chunk_queryset
-from misago.users.models import Online
-
+from ....core.pgutils import chunk_queryset
+from ...models import Online
 
 User = get_user_model()
 

+ 7 - 8
misago/users/management/commands/prepareuserdatadownloads.py

@@ -3,14 +3,13 @@ import logging
 from django.core.management.base import BaseCommand
 from django.utils.translation import gettext
 
-from misago.cache.versions import get_cache_versions
-from misago.conf import settings
-from misago.conf.dynamicsettings import DynamicSettings
-from misago.core.mail import mail_user
-from misago.core.pgutils import chunk_queryset
-from misago.users.datadownloads import prepare_user_data_download
-from misago.users.models import DataDownload
-
+from ....cache.versions import get_cache_versions
+from ....conf import settings
+from ....conf.dynamicsettings import DynamicSettings
+from ....core.mail import mail_user
+from ....core.pgutils import chunk_queryset
+from ...datadownloads import prepare_user_data_download
+from ...models import DataDownload
 
 logger = logging.getLogger("misago.users.datadownloads")
 

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

@@ -1,7 +1,7 @@
 from django.core.management import BaseCommand
 
-from misago.conf import settings
-from misago.users.signals import remove_old_ips
+from ....conf import settings
+from ...signals import remove_old_ips
 
 
 class Command(BaseCommand):

+ 3 - 4
misago/users/management/commands/synchronizeusers.py

@@ -3,10 +3,9 @@ import time
 from django.contrib.auth import get_user_model
 from django.core.management.base import BaseCommand
 
-from misago.categories.models import Category
-from misago.core.management.progressbar import show_progress
-from misago.core.pgutils import chunk_queryset
-
+from ....categories.models import Category
+from ....core.management.progressbar import show_progress
+from ....core.pgutils import chunk_queryset
 
 User = get_user_model()
 

+ 1 - 2
misago/users/migrations/0002_users_settings.py

@@ -1,7 +1,6 @@
 from django.db import migrations
 
-from misago.conf.migrationutils import migrate_settings_group
-
+from ...conf.migrationutils import migrate_settings_group
 
 _ = lambda s: s
 

+ 1 - 2
misago/users/migrations/0004_default_ranks.py

@@ -1,8 +1,7 @@
 from django.db import migrations
 from django.utils.translation import gettext
 
-from misago.core.utils import slugify
-
+from ...core.utils import slugify
 
 _ = lambda s: s
 

+ 1 - 1
misago/users/migrations/0006_update_settings.py

@@ -1,7 +1,7 @@
 # Generated by Django 1.10.5 on 2017-02-05 14:34
 from django.db import migrations
 
-from misago.conf.migrationutils import migrate_settings_group
+from ...conf.migrationutils import migrate_settings_group
 
 _ = lambda s: s
 

+ 1 - 0
misago/users/migrations/0009_redo_partial_indexes.py

@@ -1,5 +1,6 @@
 # Generated by Django 1.11.1 on 2017-05-26 21:56
 from django.db import migrations
+
 import misago.core.pgutils
 
 

+ 1 - 0
misago/users/migrations/0011_auto_20180331_2208.py

@@ -1,5 +1,6 @@
 # Generated by Django 1.11.11 on 2018-03-31 22:08
 from django.db import migrations, models
+
 import misago.core.pgutils
 
 

+ 2 - 2
misago/users/migrations/0012_audittrail.py

@@ -1,8 +1,8 @@
 # Generated by Django 1.11.13 on 2018-06-03 18:46
-from django.conf import settings
-from django.db import migrations, models
 import django.db.models.deletion
 import django.utils.timezone
+from django.conf import settings
+from django.db import migrations, models
 
 
 class Migration(migrations.Migration):

+ 3 - 2
misago/users/migrations/0014_datadownload.py

@@ -1,8 +1,9 @@
 # Generated by Django 1.11.13 on 2018-06-24 00:13
-from django.conf import settings
-from django.db import migrations, models
 import django.db.models.deletion
 import django.utils.timezone
+from django.conf import settings
+from django.db import migrations, models
+
 import misago.users.models.datadownload
 
 

+ 1 - 1
misago/users/migrations/0016_cache_version.py

@@ -1,7 +1,7 @@
 # Generated by Django 1.11.16 on 2018-11-25 15:31
 from django.db import migrations
 
-from misago.cache.operations import StartCacheVersioning
+from ...cache.operations import StartCacheVersioning
 
 
 class Migration(migrations.Migration):

+ 1 - 1
misago/users/migrations/0017_move_bans_to_cache_version.py

@@ -1,7 +1,7 @@
 # Generated by Django 1.11.16 on 2018-11-29 20:28
 from django.db import migrations, models
 
-from misago.users import BANS_CACHE
+from .. import BANS_CACHE
 
 
 def populate_cache_version(apps, _):

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

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

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

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

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

@@ -5,8 +5,8 @@ from django.db import IntegrityError, models
 from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
-from misago.cache.versions import invalidate_cache
-from misago.users import BANS_CACHE
+from .. import BANS_CACHE
+from ...cache.versions import invalidate_cache
 
 
 class BansManager(models.Manager):
@@ -92,7 +92,7 @@ class Ban(models.Model):
         return super().save(*args, **kwargs)
 
     def get_serialized_message(self):
-        from misago.users.serializers import BanMessageSerializer
+        from ..serializers import BanMessageSerializer
 
         return BanMessageSerializer(self).data
 
@@ -138,7 +138,7 @@ class BanCache(models.Model):
             pass  # first come is first serve with ban cache
 
     def get_serialized_message(self):
-        from misago.users.serializers import BanMessageSerializer
+        from ..serializers import BanMessageSerializer
 
         temp_ban = Ban(
             id=1,

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

@@ -1,8 +1,8 @@
 from django.db import models, transaction
 from django.urls import reverse
 
-from misago.acl.cache import clear_acl_cache
-from misago.core.utils import slugify
+from ...acl.cache import clear_acl_cache
+from ...core.utils import slugify
 
 
 class RankManager(models.Manager):

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

@@ -1,8 +1,9 @@
 from hashlib import md5
 
+from django.contrib.auth.models import AbstractBaseUser
 from django.contrib.auth.models import AnonymousUser as DjangoAnonymousUser
+from django.contrib.auth.models import PermissionsMixin
 from django.contrib.auth.models import UserManager as BaseUserManager
-from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
 from django.contrib.auth.password_validation import validate_password
 from django.contrib.postgres.fields import ArrayField, HStoreField, JSONField
 from django.core.mail import send_mail
@@ -11,15 +12,14 @@ from django.urls import reverse
 from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl.models import Role
-from misago.conf import settings
-from misago.core.pgutils import PgPartialIndex
-from misago.core.utils import slugify
-from misago.users import avatars
-from misago.users.audittrail import create_user_audit_trail
-from misago.users.signatures import is_user_signature_valid
-from misago.users.utils import hash_email
-
+from .. import avatars
+from ...acl.models import Role
+from ...conf import settings
+from ...core.pgutils import PgPartialIndex
+from ...core.utils import slugify
+from ..audittrail import create_user_audit_trail
+from ..signatures import is_user_signature_valid
+from ..utils import hash_email
 from .online import Online
 from .rank import Rank
 
@@ -251,7 +251,7 @@ class User(AbstractBaseUser, PermissionsMixin):
         return super().delete(*args, **kwargs)
 
     def delete_content(self):
-        from misago.users.signals import delete_user_content
+        from ..signals import delete_user_content
 
         delete_user_content.send(sender=self)
 
@@ -269,7 +269,7 @@ class User(AbstractBaseUser, PermissionsMixin):
         self.username = settings.MISAGO_ANONYMOUS_USERNAME
         self.slug = slugify(self.username)
 
-        from misago.users.signals import anonymize_user_data
+        from ..signals import anonymize_user_data
 
         anonymize_user_data.send(sender=self)
 
@@ -329,7 +329,7 @@ class User(AbstractBaseUser, PermissionsMixin):
                     changed_by, new_username, old_username
                 )
 
-                from misago.users.signals import username_changed
+                from ..signals import username_changed
 
                 username_changed.send(sender=self)
 

+ 2 - 3
misago/users/online/tracker.py

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

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

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

+ 1 - 2
misago/users/pages.py

@@ -1,5 +1,4 @@
-from misago.core.page import Page
-
+from ..core.page import Page
 
 usercp = Page("usercp")
 users_list = Page("users list")

+ 3 - 3
misago/users/permissions/account.py

@@ -1,9 +1,9 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl import algebra
-from misago.acl.models import Role
-from misago.admin.forms import YesNoSwitch
+from ...acl import algebra
+from ...acl.models import Role
+from ...admin.forms import YesNoSwitch
 
 
 class PermissionsForm(forms.Form):

+ 0 - 1
misago/users/permissions/decorators.py

@@ -1,7 +1,6 @@
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext_lazy as _
 
-
 __all__ = ["authenticated_only", "anonymous_only"]
 
 

+ 4 - 5
misago/users/permissions/delete.py

@@ -7,11 +7,10 @@ from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import ngettext
 
-from misago.acl import algebra
-from misago.acl.decorators import return_boolean
-from misago.acl.models import Role
-from misago.conf import settings
-
+from ...acl import algebra
+from ...acl.decorators import return_boolean
+from ...acl.models import Role
+from ...conf import settings
 
 __all__ = [
     "allow_delete_user",

+ 5 - 6
misago/users/permissions/moderation.py

@@ -7,12 +7,11 @@ from django.template.defaultfilters import date as format_date
 from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl import algebra
-from misago.acl.decorators import return_boolean
-from misago.acl.models import Role
-from misago.admin.forms import YesNoSwitch
-from misago.users.bans import get_user_ban
-
+from ...acl import algebra
+from ...acl.decorators import return_boolean
+from ...acl.models import Role
+from ...admin.forms import YesNoSwitch
+from ..bans import get_user_ban
 
 __all__ = [
     "allow_rename_user",

+ 4 - 6
misago/users/permissions/profiles.py

@@ -3,14 +3,12 @@ from django.contrib.auth import get_user_model
 from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl import algebra
-from misago.acl.decorators import return_boolean
-from misago.acl.models import Role
-from misago.admin.forms import YesNoSwitch
-
+from ...acl import algebra
+from ...acl.decorators import return_boolean
+from ...acl.models import Role
+from ...admin.forms import YesNoSwitch
 from .decorators import authenticated_only
 
-
 __all__ = [
     "allow_browse_users_list",
     "can_browse_users_list",

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

@@ -6,7 +6,7 @@ from django.urls import reverse
 from django.utils.module_loading import import_string
 from django.utils.translation import gettext as _
 
-from misago.conf import settings
+from ...conf import settings
 
 from .basefields import *
 from .serializers import serialize_profilefields_data

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

@@ -2,8 +2,7 @@ from django import forms
 from django.db.models import Q
 from django.utils import html
 
-from misago.core.utils import format_plaintext_for_html
-
+from ...core.utils import format_plaintext_for_html
 
 __all__ = [
     "ProfileField",

+ 2 - 1
misago/users/profilefields/default.py

@@ -1,7 +1,8 @@
 import re
 
 from django.forms import ValidationError
-from django.utils.translation import gettext, gettext_lazy as _
+from django.utils.translation import gettext
+from django.utils.translation import gettext_lazy as _
 
 from . import basefields
 

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

@@ -1,4 +1,4 @@
-from misago.users.permissions import can_edit_profile_details
+from ..permissions import can_edit_profile_details
 
 
 def serialize_profilefields_data(request, profilefields, user):

+ 4 - 4
misago/users/registration.py

@@ -1,9 +1,9 @@
 from django.utils.translation import gettext as _
 
-from misago.core.mail import mail_user
-from misago.legal.models import Agreement
-from misago.legal.utils import save_user_agreement_acceptance
-from misago.users.tokens import make_activation_token
+from ..core.mail import mail_user
+from ..legal.models import Agreement
+from ..legal.utils import save_user_agreement_acceptance
+from .tokens import make_activation_token
 
 
 def send_welcome_email(request, user):

+ 1 - 3
misago/users/search.py

@@ -3,11 +3,9 @@ from django.core.exceptions import PermissionDenied
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext_lazy
 
-from misago.search import SearchProvider
-
+from ..search import SearchProvider
 from .serializers import UserCardSerializer
 
-
 HEAD_RESULTS = 8
 TAIL_RESULTS = 8
 

+ 2 - 4
misago/users/serializers/auth.py

@@ -1,10 +1,8 @@
-from rest_framework import serializers
-
 from django.contrib.auth import get_user_model
 from django.urls import reverse
+from rest_framework import serializers
 
-from misago.acl.useracl import serialize_user_acl
-
+from ...acl.useracl import serialize_user_acl
 from .user import UserSerializer
 
 User = get_user_model()

+ 3 - 5
misago/users/serializers/ban.py

@@ -1,10 +1,8 @@
-from rest_framework import serializers
-
 from django.utils.translation import gettext as _
+from rest_framework import serializers
 
-from misago.core.utils import format_plaintext_for_html
-from misago.users.models import Ban
-
+from ...core.utils import format_plaintext_for_html
+from ..models import Ban
 
 __all__ = ["BanMessageSerializer", "BanDetailsSerializer"]
 

+ 1 - 2
misago/users/serializers/datadownload.py

@@ -1,7 +1,6 @@
 from rest_framework import serializers
 
-from misago.users.models import DataDownload
-
+from ..models import DataDownload
 
 __all__ = ["DataDownloadSerializer"]
 

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

@@ -1,10 +1,8 @@
-from rest_framework import serializers
-
 from django.contrib.auth import get_user_model
 from django.utils.translation import ngettext
+from rest_framework import serializers
 
-from misago.conf import settings
-
+from ...conf import settings
 
 User = get_user_model()
 

+ 4 - 6
misago/users/serializers/options.py

@@ -1,13 +1,11 @@
-from rest_framework import serializers
-
 from django.contrib.auth import get_user_model, logout
 from django.contrib.auth.password_validation import validate_password
 from django.utils.translation import gettext as _
+from rest_framework import serializers
 
-from misago.users.online.tracker import clear_tracking
-from misago.users.permissions import allow_delete_own_account
-from misago.users.validators import validate_email, validate_username
-
+from ..online.tracker import clear_tracking
+from ..permissions import allow_delete_own_account
+from ..validators import validate_email, validate_username
 
 User = get_user_model()
 

+ 2 - 3
misago/users/serializers/rank.py

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

+ 2 - 5
misago/users/serializers/user.py

@@ -1,12 +1,9 @@
-from rest_framework import serializers
-
 from django.contrib.auth import get_user_model
 from django.urls import reverse
-
-from misago.core.serializers import MutableFields
+from rest_framework import serializers
 
 from . import RankSerializer
-
+from ...core.serializers import MutableFields
 
 User = get_user_model()
 

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

@@ -1,10 +1,8 @@
 from rest_framework import serializers
 
-from misago.users.models import UsernameChange
-
+from ..models import UsernameChange
 from .user import UserSerializer as BaseUserSerializer
 
-
 __all__ = ["UsernameChangeSerializer"]
 
 UserSerializer = BaseUserSerializer.subset_fields("id", "username", "avatars", "url")

+ 1 - 1
misago/users/setupnewuser.py

@@ -1,5 +1,5 @@
-from .avatars import set_default_avatar
 from .audittrail import create_user_audit_trail
+from .avatars import set_default_avatar
 from .models import User
 
 

+ 2 - 4
misago/users/signals.py

@@ -7,13 +7,11 @@ from django.dispatch import Signal, receiver
 from django.utils import timezone
 from django.utils.translation import gettext as _
 
-from misago.conf import settings
-from misago.core.pgutils import chunk_queryset
-
+from ..conf import settings
+from ..core.pgutils import chunk_queryset
 from .models import AuditTrail
 from .profilefields import profilefields
 
-
 User = get_user_model()
 
 anonymize_user_data = Signal()

+ 1 - 1
misago/users/signatures.py

@@ -1,4 +1,4 @@
-from misago.markup import checksums, signature_flavour
+from ..markup import checksums, signature_flavour
 
 
 def set_user_signature(request, user, user_acl, signature):

+ 9 - 12
misago/users/social/pipeline.py

@@ -8,28 +8,25 @@ from django.urls import reverse
 from django.utils.translation import gettext as _
 from social_core.pipeline.partial import partial
 
-from misago.core.exceptions import SocialAuthFailed, SocialAuthBanned
-from misago.legal.models import Agreement
-
-from misago.users.bans import get_request_ip_ban, get_user_ban
-from misago.users.forms.register import SocialAuthRegisterForm
-from misago.users.models import Ban
-from misago.users.registration import (
+from ...core.exceptions import SocialAuthBanned, SocialAuthFailed
+from ...legal.models import Agreement
+from ..bans import get_request_ip_ban, get_user_ban
+from ..forms.register import SocialAuthRegisterForm
+from ..models import Ban
+from ..registration import (
     get_registration_result_json,
     save_user_agreements,
     send_welcome_email,
 )
-from misago.users.setupnewuser import setup_new_user
-from misago.users.validators import (
+from ..setupnewuser import setup_new_user
+from ..validators import (
     ValidationError,
-    validate_new_registration,
     validate_email,
+    validate_new_registration,
     validate_username,
 )
-
 from .utils import get_social_auth_backend_name, perpare_username
 
-
 User = get_user_model()
 
 

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

@@ -2,8 +2,7 @@ from django.urls import reverse
 from social_core.backends.utils import load_backends
 from unidecode import unidecode
 
-from misago.conf import settings
-
+from ...conf import settings
 from .backendsnames import BACKENDS_NAMES
 
 

+ 0 - 1
misago/users/templatetags/misago_avatars.py

@@ -1,6 +1,5 @@
 from django import template
 
-
 register = template.Library()
 
 

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

@@ -2,10 +2,10 @@ from django.contrib.auth import get_user_model
 from django.test import TestCase
 from django.urls import reverse
 
-from misago.core.utils import encode_json_html
-from misago.users.models import Ban
-from misago.users.test import create_test_user
-from misago.users.tokens import make_activation_token
+from ...core.utils import encode_json_html
+from ..models import Ban
+from ..test import create_test_user
+from ..tokens import make_activation_token
 
 User = get_user_model()
 

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

@@ -2,13 +2,13 @@ from datetime import timedelta
 
 from django.utils import timezone
 
-from misago.categories.models import Category
-from misago.threads.test import post_thread
-from misago.users.activepostersranking import (
+from ...categories.models import Category
+from ...threads.test import post_thread
+from ..activepostersranking import (
     build_active_posters_ranking,
     get_active_posters_ranking,
 )
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 
 class TestActivePostersRanking(AuthenticatedUserTestCase):

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

@@ -3,10 +3,10 @@ from datetime import timedelta
 from django.contrib.auth import get_user_model
 from django.utils import timezone
 
-from misago.users.audittrail import create_audit_trail, create_user_audit_trail
-from misago.users.models import AuditTrail
-from misago.users.signals import remove_old_ips
-from misago.users.test import UserTestCase, create_test_user
+from ..audittrail import create_audit_trail, create_user_audit_trail
+from ..models import AuditTrail
+from ..signals import remove_old_ips
+from ..test import UserTestCase, create_test_user
 
 User = get_user_model()
 

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

@@ -2,9 +2,9 @@ from django.contrib.auth import get_user_model
 from django.core import mail
 from django.test import TestCase
 
-from misago.users.models import Ban
-from misago.users.test import create_test_user
-from misago.users.tokens import make_password_change_token
+from ..models import Ban
+from ..test import create_test_user
+from ..tokens import make_password_change_token
 
 
 class GatewayTests(TestCase):

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

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

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

@@ -1,6 +1,6 @@
 import pytest
 
-from misago.users.templatetags.misago_avatars import avatar
+from ..templatetags.misago_avatars import avatar
 
 
 @pytest.fixture

+ 5 - 13
misago/users/tests/test_avatars.py

@@ -1,23 +1,15 @@
 from pathlib import Path
 from unittest.mock import Mock
 
-from PIL import Image
-
 from django.core.exceptions import ValidationError
 from django.test import TestCase
 from django.utils.crypto import get_random_string
+from PIL import Image
 
-from misago.conf import settings
-from misago.users.avatars import (
-    dynamic,
-    gallery,
-    gravatar,
-    set_default_avatar,
-    store,
-    uploaded,
-)
-from misago.users.models import Avatar, AvatarGallery
-from misago.users.test import create_test_user
+from ...conf import settings
+from ..avatars import dynamic, gallery, gravatar, set_default_avatar, store, uploaded
+from ..models import Avatar, AvatarGallery
+from ..test import create_test_user
 
 
 class AvatarsStoreTests(TestCase):

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

@@ -1,8 +1,8 @@
 from django.test import TestCase
 from django.urls import reverse
 
-from misago.conf import settings
-from misago.users.test import create_test_user
+from ...conf import settings
+from ..test import create_test_user
 
 
 class AvatarServerTests(TestCase):

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

@@ -1,6 +1,6 @@
 from django.test import TestCase
 
-from misago.users.models import Ban
+from ..models import Ban
 
 
 class BansManagerTests(TestCase):

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

@@ -2,8 +2,8 @@ from datetime import datetime, timedelta
 
 from django.urls import reverse
 
-from misago.admin.test import AdminTestCase
-from misago.users.models import Ban
+from ...admin.test import AdminTestCase
+from ..models import Ban
 
 
 class BanAdminViewsTests(AdminTestCase):

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

@@ -3,8 +3,9 @@ from datetime import timedelta
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.conftest import get_cache_versions
-from misago.users.bans import (
+from ...conftest import get_cache_versions
+from ...users import BANS_CACHE
+from ..bans import (
     ban_ip,
     ban_user,
     get_email_ban,
@@ -13,9 +14,8 @@ from misago.users.bans import (
     get_user_ban,
     get_username_ban,
 )
-from misago.users import BANS_CACHE
-from misago.users.models import Ban
-from misago.users.test import create_test_user
+from ..models import Ban
+from ..test import create_test_user
 
 cache_versions = get_cache_versions()
 

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

@@ -1,8 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 
-from misago.admin.test import AdminTestCase
-
+from ...admin.test import AdminTestCase
 
 User = get_user_model()
 

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

@@ -1,7 +1,7 @@
 from django.test import TestCase
 from django.urls import reverse
 
-from misago.conf.test import override_dynamic_settings
+from ...conf.test import override_dynamic_settings
 
 test_qa_question = "Do you like pies?"
 test_qa_help_text = 'Type in "yes".'

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

@@ -1,7 +1,7 @@
 from django.test import TestCase
 
-from misago.users import credentialchange
-from misago.users.test import create_test_user
+from ...users import credentialchange
+from ..test import create_test_user
 
 
 class MockRequest(object):

+ 7 - 8
misago/users/tests/test_datadownloads.py

@@ -2,19 +2,18 @@ import os
 
 from django.core.files import File
 
-from misago.categories.models import Category
-from misago.threads.models import Attachment, AttachmentType
-from misago.threads.test import post_thread, post_poll
-from misago.users.audittrail import create_user_audit_trail
-from misago.users.datadownloads import (
+from ...categories.models import Category
+from ...threads.models import Attachment, AttachmentType
+from ...threads.test import post_poll, post_thread
+from ..audittrail import create_user_audit_trail
+from ..datadownloads import (
     expire_user_data_download,
     prepare_user_data_download,
     request_user_data_download,
     user_has_data_download_request,
 )
-from misago.users.models import DataDownload
-from misago.users.test import AuthenticatedUserTestCase
-
+from ..models import DataDownload
+from ..test import AuthenticatedUserTestCase
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_FILE_PATH = os.path.join(TESTFILES_DIR, "avatar.png")

+ 3 - 4
misago/users/tests/test_datadownloads_dataarchive.py

@@ -5,14 +5,13 @@ from django.core.files import File
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.conf import settings
-from misago.users.datadownloads.dataarchive import (
+from ...conf import settings
+from ..datadownloads.dataarchive import (
     FILENAME_MAX_LEN,
     DataArchive,
     trim_long_filename,
 )
-from misago.users.test import AuthenticatedUserTestCase
-
+from ..test import AuthenticatedUserTestCase
 
 DATA_DOWNLOADS_WORKING_DIR = settings.MISAGO_USER_DATA_DOWNLOADS_WORKING_DIR
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")

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

@@ -3,10 +3,10 @@ import os
 from django.core.files import File
 from django.urls import reverse
 
-from misago.admin.test import AdminTestCase
-from misago.users.datadownloads import request_user_data_download
-from misago.users.models import DataDownload
-from misago.users.test import create_test_user
+from ...admin.test import AdminTestCase
+from ..datadownloads import request_user_data_download
+from ..models import DataDownload
+from ..test import create_test_user
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_FILE_PATH = os.path.join(TESTFILES_DIR, "avatar.png")

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

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

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

@@ -6,8 +6,8 @@ from django.core.management import call_command
 from django.test import TestCase, override_settings
 from django.utils import timezone
 
-from misago.users.management.commands import deleteinactiveusers
-from misago.users.test import create_test_user
+from ..management.commands import deleteinactiveusers
+from ..test import create_test_user
 
 User = get_user_model()
 

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

@@ -4,8 +4,8 @@ from django.contrib.auth import get_user_model
 from django.core.management import call_command
 from django.test import TestCase, override_settings
 
-from misago.users.management.commands import deletemarkedusers
-from misago.users.test import create_test_user
+from ..management.commands import deletemarkedusers
+from ..test import create_test_user
 
 User = get_user_model()
 

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

@@ -3,8 +3,8 @@ from io import StringIO
 from django.core.management import call_command
 from django.test import TestCase
 
-from misago.users.management.commands import deleteprofilefield
-from misago.users.test import create_test_user
+from ..management.commands import deleteprofilefield
+from ..test import create_test_user
 
 
 class DeleteProfileFieldTests(TestCase):

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

@@ -1,7 +1,7 @@
 from django.test import override_settings
 from django.urls import reverse
 
-from misago.admin.test import AdminTestCase
+from ...admin.test import AdminTestCase
 
 
 @override_settings(ROOT_URLCONF="misago.core.testproject.urls")

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

@@ -3,9 +3,9 @@ from django.test import override_settings
 from django.urls import reverse
 from django.utils import formats
 
-from misago.admin.test import AdminTestCase
-from misago.users.djangoadmin import UserAdminModel
-from misago.users.test import create_test_user
+from ...admin.test import AdminTestCase
+from ..djangoadmin import UserAdminModel
+from ..test import create_test_user
 
 
 @override_settings(ROOT_URLCONF="misago.core.testproject.urls")

+ 4 - 5
misago/users/tests/test_expireuserdatadownloads.py

@@ -5,11 +5,10 @@ from io import StringIO
 from django.core.files import File
 from django.core.management import call_command
 
-from misago.users.datadownloads import request_user_data_download
-from misago.users.management.commands import expireuserdatadownloads
-from misago.users.models import DataDownload
-from misago.users.test import AuthenticatedUserTestCase
-
+from ..datadownloads import request_user_data_download
+from ..management.commands import expireuserdatadownloads
+from ..models import DataDownload
+from ..test import AuthenticatedUserTestCase
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_FILE_PATH = os.path.join(TESTFILES_DIR, "avatar.png")

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

@@ -1,9 +1,9 @@
 from django.urls import reverse
 
-from misago.core.utils import encode_json_html
-from misago.users.models import Ban
-from misago.users.test import UserTestCase, create_test_user
-from misago.users.tokens import make_password_change_token
+from ...core.utils import encode_json_html
+from ..models import Ban
+from ..test import UserTestCase, create_test_user
+from ..tokens import make_password_change_token
 
 
 class ForgottenPasswordViewsTests(UserTestCase):

+ 1 - 2
misago/users/tests/test_gender_profilefield.py

@@ -1,8 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 
-from misago.admin.test import AdminTestCase
-
+from ...admin.test import AdminTestCase
 
 User = get_user_model()
 

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

@@ -1,7 +1,7 @@
 from unittest.mock import Mock
 
-from misago.users.online.utils import get_user_status
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ..online.utils import get_user_status
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 
 class GetUserStatusTests(AuthenticatedUserTestCase):

+ 5 - 6
misago/users/tests/test_invalidatebans.py

@@ -5,12 +5,11 @@ from django.core.management import call_command
 from django.test import TestCase
 from django.utils import timezone
 
-from misago.cache.versions import get_cache_versions
-
-from misago.users import bans
-from misago.users.management.commands import invalidatebans
-from misago.users.models import Ban, BanCache
-from misago.users.test import create_test_user
+from ...cache.versions import get_cache_versions
+from ...users import bans
+from ..management.commands import invalidatebans
+from ..models import Ban, BanCache
+from ..test import create_test_user
 
 
 class InvalidateBansTests(TestCase):

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

@@ -1,9 +1,8 @@
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.admin.test import AdminTestCase
-
+from ...acl.test import patch_user_acl
+from ...admin.test import AdminTestCase
 
 User = get_user_model()
 

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

@@ -1,11 +1,11 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.threads.test import post_thread
-from misago.users.activepostersranking import build_active_posters_ranking
-from misago.users.models import Rank
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...threads.test import post_thread
+from ..activepostersranking import build_active_posters_ranking
+from ..models import Rank
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 
 class UsersListTestCase(AuthenticatedUserTestCase):

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

@@ -3,8 +3,8 @@ from io import StringIO
 from django.core.management import call_command
 from django.test import TestCase
 
-from misago.users.management.commands import listusedprofilefields
-from misago.users.test import create_test_user
+from ..management.commands import listusedprofilefields
+from ..test import create_test_user
 
 
 class ListUsedProfileFieldsTests(TestCase):

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

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

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

@@ -1,8 +1,8 @@
 from django.test import TestCase
 from django.urls import reverse
 
-from misago.conf import settings
-from misago.users.test import create_test_user
+from ...conf import settings
+from ..test import create_test_user
 
 
 class AuthenticateApiTests(TestCase):

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

@@ -1,8 +1,8 @@
 from datetime import timedelta
 
-from misago.users.namechanges import (
-    get_next_available_namechange,
+from ..namechanges import (
     get_left_namechanges,
+    get_next_available_namechange,
     get_username_options,
 )
 

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

@@ -1,7 +1,7 @@
 from django.contrib.auth import get_user_model
 
-from misago.conf.test import override_dynamic_settings
-from misago.users.setupnewuser import set_default_subscription_options, setup_new_user
+from ...conf.test import override_dynamic_settings
+from ..setupnewuser import set_default_subscription_options, setup_new_user
 
 User = get_user_model()
 

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

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

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

@@ -2,8 +2,8 @@ from io import StringIO
 
 from django.core.management import call_command
 
-from misago.users.management.commands import populateonlinetracker
-from misago.users.models import Online
+from ..management.commands import populateonlinetracker
+from ..models import Online
 
 
 def test_management_command_creates_online_tracker_for_user_without_one(user):

+ 5 - 5
misago/users/tests/test_prepareuserdatadownloads.py

@@ -3,11 +3,11 @@ from io import StringIO
 from django.core import mail
 from django.core.management import call_command
 
-from misago.conf import settings
-from misago.users.datadownloads import request_user_data_download
-from misago.users.management.commands import prepareuserdatadownloads
-from misago.users.models import DataDownload
-from misago.users.test import AuthenticatedUserTestCase
+from ...conf import settings
+from ..datadownloads import request_user_data_download
+from ..management.commands import prepareuserdatadownloads
+from ..models import DataDownload
+from ..test import AuthenticatedUserTestCase
 
 
 class PrepareUserDataDownloadsTests(AuthenticatedUserTestCase):

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

@@ -1,10 +1,10 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.threads import test
-from misago.users.models import Ban
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...threads import test
+from ..models import Ban
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 
 class UserProfileViewsTests(AuthenticatedUserTestCase):

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

@@ -1,8 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.test import TestCase
 
-from misago.users.profilefields import ProfileFields
-
+from ..profilefields import ProfileFields
 
 User = get_user_model()
 

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

@@ -1,10 +1,10 @@
 from django.urls import reverse
 
-from misago.acl import ACL_CACHE
-from misago.acl.models import Role
-from misago.admin.test import AdminTestCase
-from misago.cache.test import assert_invalidates_cache
-from misago.users.models import Rank
+from ...acl import ACL_CACHE
+from ...acl.models import Role
+from ...admin.test import AdminTestCase
+from ...cache.test import assert_invalidates_cache
+from ..models import Rank
 
 
 class RankAdminViewsTests(AdminTestCase):

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

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

+ 1 - 2
misago/users/tests/test_remove_old_ips_command.py

@@ -6,8 +6,7 @@ from django.core.management import call_command
 from django.test import override_settings
 from django.utils import timezone
 
-from misago.users.management.commands import removeoldips
-
+from ..management.commands import removeoldips
 
 IP_STORE_TIME = 2
 

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

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

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

@@ -1,7 +1,7 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ...acl.test import patch_user_acl
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 
 class SearchApiTests(AuthenticatedUserTestCase):

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

@@ -2,8 +2,8 @@ from unittest.mock import Mock
 
 import pytest
 
-from misago.acl.useracl import get_user_acl
-from misago.users import signatures
+from ...acl.useracl import get_user_acl
+from ...users import signatures
 
 
 @pytest.fixture

+ 10 - 12
misago/users/tests/test_social_pipeline.py

@@ -6,16 +6,15 @@ from django.test import RequestFactory
 from social_core.backends.github import GithubOAuth2
 from social_django.utils import load_strategy
 
-from misago.acl import ACL_CACHE
-from misago.acl.useracl import get_user_acl
-from misago.conf.dynamicsettings import DynamicSettings
-from misago.core.exceptions import SocialAuthFailed, SocialAuthBanned
-from misago.conf.test import override_dynamic_settings
-from misago.conftest import get_cache_versions
-from misago.legal.models import Agreement
-
-from misago.users.models import AnonymousUser, Ban, BanCache
-from misago.users.social.pipeline import (
+from ...acl import ACL_CACHE
+from ...acl.useracl import get_user_acl
+from ...conf.dynamicsettings import DynamicSettings
+from ...conf.test import override_dynamic_settings
+from ...conftest import get_cache_versions
+from ...core.exceptions import SocialAuthBanned, SocialAuthFailed
+from ...legal.models import Agreement
+from ..models import AnonymousUser, Ban, BanCache
+from ..social.pipeline import (
     associate_by_email,
     create_user,
     create_user_with_form,
@@ -24,8 +23,7 @@ from misago.users.social.pipeline import (
     validate_ip_not_banned,
     validate_user_not_banned,
 )
-from misago.users.test import UserTestCase
-
+from ..test import UserTestCase
 
 User = get_user_model()
 

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

@@ -1,7 +1,7 @@
 from django.test import TestCase, override_settings
 from django.urls import reverse
 
-from misago.users.social.utils import get_enabled_social_auth_sites_list
+from ..social.utils import get_enabled_social_auth_sites_list
 
 
 class SocialUtilsTests(TestCase):

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

@@ -1,6 +1,6 @@
 from django.urls import reverse
 
-from misago.users.test import AuthenticatedUserTestCase, SuperUserTestCase, UserTestCase
+from ..test import AuthenticatedUserTestCase, SuperUserTestCase, UserTestCase
 
 
 class UserTestCaseTests(UserTestCase):

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

@@ -1,4 +1,4 @@
-from misago.users import tokens
+from ...users import tokens
 
 
 def test_token_can_be_created_for_user(user):

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

@@ -1,8 +1,7 @@
 from django.contrib.auth import get_user_model
 from django.urls import reverse
 
-from misago.admin.test import AdminTestCase
-
+from ...admin.test import AdminTestCase
 
 User = get_user_model()
 

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

@@ -4,12 +4,12 @@ from pathlib import Path
 
 from django.contrib.auth import get_user_model
 
-from misago.acl.test import patch_user_acl
-from misago.conf import settings
-from misago.conf.test import override_dynamic_settings
-from misago.users.avatars import gallery, store
-from misago.users.models import AvatarGallery
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ...acl.test import patch_user_acl
+from ...conf import settings
+from ...conf.test import override_dynamic_settings
+from ..avatars import gallery, store
+from ..models import AvatarGallery
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 TESTFILES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testfiles")
 TEST_AVATAR_PATH = os.path.join(TESTFILES_DIR, "avatar.png")

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

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

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

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

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

@@ -2,10 +2,10 @@ from django.contrib.auth import get_user_model
 from django.core import mail
 from django.urls import reverse
 
-from misago.conf.test import override_dynamic_settings
-from misago.legal.models import Agreement
-from misago.users.models import Ban, Online
-from misago.users.test import UserTestCase
+from ...conf.test import override_dynamic_settings
+from ...legal.models import Agreement
+from ..models import Ban, Online
+from ..test import UserTestCase
 
 User = get_user_model()
 

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

@@ -1,8 +1,8 @@
 import pytest
 from django.contrib.auth import get_user_model
 
-from misago.users.models import Rank
-from misago.users.utils import hash_email
+from ..models import Rank
+from ..utils import hash_email
 
 User = get_user_model()
 

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

@@ -1,5 +1,5 @@
-from misago.users.datadownloads import request_user_data_download
-from misago.users.test import AuthenticatedUserTestCase
+from ..datadownloads import request_user_data_download
+from ..test import AuthenticatedUserTestCase
 
 
 class UserDataDownloadsApiTests(AuthenticatedUserTestCase):

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

@@ -1,7 +1,7 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ...acl.test import patch_user_acl
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 
 class UserDetailsApiTests(AuthenticatedUserTestCase):

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

@@ -1,7 +1,7 @@
 from django.urls import reverse
 
-from misago.acl.test import patch_user_acl
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ...acl.test import patch_user_acl
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 
 class UserEditDetailsApiTests(AuthenticatedUserTestCase):

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

@@ -1,7 +1,7 @@
 from django.urls import reverse
 
-from misago.threads import test
-from misago.threads.tests.test_threads_api import ThreadsApiTestCase
+from ...threads import test
+from ...threads.tests.test_threads_api import ThreadsApiTestCase
 
 
 class UserThreadsApiTests(ThreadsApiTestCase):

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

@@ -1,8 +1,8 @@
 from django.urls import reverse
 
-from misago.users.bans import ban_ip, ban_user
-from misago.users.models import Ban
-from misago.users.test import AuthenticatedUserTestCase
+from ..bans import ban_ip, ban_user
+from ..models import Ban
+from ..test import AuthenticatedUserTestCase
 
 
 class UserMiddlewareTest(AuthenticatedUserTestCase):

+ 4 - 5
misago/users/tests/test_user_model.py

@@ -2,11 +2,10 @@ from pathlib import Path
 
 from django.test import TestCase
 
-from misago.conf import settings
-from misago.core.utils import slugify
-
-from misago.users.avatars import dynamic
-from misago.users.models import Avatar, User
+from ...conf import settings
+from ...core.utils import slugify
+from ..avatars import dynamic
+from ..models import Avatar, User
 
 
 class UserTests(TestCase):

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

@@ -1,7 +1,7 @@
 from django.test.utils import override_settings
 
-from misago.users.datadownloads import request_user_data_download
-from misago.users.test import AuthenticatedUserTestCase
+from ..datadownloads import request_user_data_download
+from ..test import AuthenticatedUserTestCase
 
 
 class UserRequestDataDownload(AuthenticatedUserTestCase):

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

@@ -1,5 +1,5 @@
-from misago.acl.test import patch_user_acl
-from misago.users.test import AuthenticatedUserTestCase
+from ...acl.test import patch_user_acl
+from ..test import AuthenticatedUserTestCase
 
 
 class UserSignatureTests(AuthenticatedUserTestCase):

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

@@ -1,8 +1,8 @@
 import json
 
-from misago.acl.test import patch_user_acl
-from misago.conf.test import override_dynamic_settings
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ...acl.test import patch_user_acl
+from ...conf.test import override_dynamic_settings
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 
 class UserUsernameTests(AuthenticatedUserTestCase):

+ 9 - 10
misago/users/tests/test_useradmin_views.py

@@ -2,16 +2,15 @@ from django.contrib.auth import get_user_model
 from django.core import mail
 from django.urls import reverse
 
-from misago.acl.models import Role
-from misago.admin.test import AdminTestCase
-from misago.categories.models import Category
-from misago.legal.models import Agreement
-from misago.legal.utils import save_user_agreement_acceptance
-from misago.threads.test import post_thread, reply_thread
-
-from misago.users.datadownloads import request_user_data_download
-from misago.users.models import Ban, DataDownload, Rank
-from misago.users.test import create_test_user
+from ...acl.models import Role
+from ...admin.test import AdminTestCase
+from ...categories.models import Category
+from ...legal.models import Agreement
+from ...legal.utils import save_user_agreement_acceptance
+from ...threads.test import post_thread, reply_thread
+from ..datadownloads import request_user_data_download
+from ..models import Ban, DataDownload, Rank
+from ..test import create_test_user
 
 User = get_user_model()
 

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

@@ -1,5 +1,5 @@
-from misago.acl.test import patch_user_acl
-from misago.users.test import AuthenticatedUserTestCase
+from ...acl.test import patch_user_acl
+from ..test import AuthenticatedUserTestCase
 
 
 class UsernameChangesApiTests(AuthenticatedUserTestCase):

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

@@ -6,13 +6,13 @@ from django.test import override_settings
 from django.urls import reverse
 from django.utils.encoding import smart_str
 
-from misago.acl.test import patch_user_acl
-from misago.categories.models import Category
-from misago.threads.models import Post, Thread
-from misago.threads.test import post_thread
-from misago.users.activepostersranking import build_active_posters_ranking
-from misago.users.models import Ban, Rank
-from misago.users.test import AuthenticatedUserTestCase, create_test_user
+from ...acl.test import patch_user_acl
+from ...categories.models import Category
+from ...threads.models import Post, Thread
+from ...threads.test import post_thread
+from ..activepostersranking import build_active_posters_ranking
+from ..models import Ban, Rank
+from ..test import AuthenticatedUserTestCase, create_test_user
 
 User = get_user_model()
 

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

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

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

@@ -3,9 +3,9 @@ from unittest.mock import Mock
 from django.core.exceptions import ValidationError
 from django.test import TestCase
 
-from misago.users.models import Ban
-from misago.users.test import create_test_user
-from misago.users.validators import (
+from ..models import Ban
+from ..test import create_test_user
+from ..validators import (
     validate_email,
     validate_email_available,
     validate_email_banned,

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

@@ -1,8 +1,8 @@
 from django.conf.urls import include, url
 
-from misago.core.views import home_redirect
+from ...core.views import home_redirect
 
-from misago.users.views import (
+from ..views import (
     activation,
     auth,
     avatarserver,

+ 5 - 6
misago/users/urls/api.py

@@ -1,11 +1,10 @@
 from django.conf.urls import url
 
-from misago.core.apirouter import MisagoApiRouter
-from misago.users.api import auth, captcha, mention
-from misago.users.api.ranks import RanksViewSet
-from misago.users.api.usernamechanges import UsernameChangesViewSet
-from misago.users.api.users import UserViewSet
-
+from ...core.apirouter import MisagoApiRouter
+from ..api import auth, captcha, mention
+from ..api.ranks import RanksViewSet
+from ..api.usernamechanges import UsernameChangesViewSet
+from ..api.users import UserViewSet
 
 urlpatterns = [
     url(r"^auth/$", auth.gateway, name="auth"),

+ 1 - 4
misago/users/validators.py

@@ -2,7 +2,6 @@ import json
 import re
 
 import requests
-
 from django.contrib.auth import get_user_model
 from django.core.exceptions import ValidationError
 from django.core.validators import validate_email as validate_email_content
@@ -11,11 +10,9 @@ from django.utils.module_loading import import_string
 from django.utils.translation import gettext_lazy as _
 from django.utils.translation import ngettext
 
-from misago.conf import settings
-
+from ..conf import settings
 from .bans import get_email_ban, get_username_ban
 
-
 USERNAME_RE = re.compile(r"^[0-9a-z]+$", re.IGNORECASE)
 
 User = get_user_model()

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

@@ -1,7 +1,7 @@
-from misago.conf import settings
-from misago.users.activepostersranking import get_active_posters_ranking
-from misago.users.online.utils import make_users_status_aware
-from misago.users.serializers import UserCardSerializer
+from ...conf import settings
+from ..activepostersranking import get_active_posters_ranking
+from ..online.utils import make_users_status_aware
+from ..serializers import UserCardSerializer
 
 
 class ActivePosters(object):

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

@@ -1,9 +1,9 @@
 from django.http import Http404
 
-from misago.conf import settings
-from misago.core.shortcuts import paginate, pagination_dict
-from misago.users.online.utils import make_users_status_aware
-from misago.users.serializers import UserCardSerializer
+from ...conf import settings
+from ...core.shortcuts import paginate, pagination_dict
+from ..online.utils import make_users_status_aware
+from ..serializers import UserCardSerializer
 
 
 class Followers(object):

+ 2 - 3
misago/users/viewmodels/posts.py

@@ -1,6 +1,5 @@
-from misago.threads.models import Thread
-from misago.threads.permissions import exclude_invisible_threads
-
+from ...threads.models import Thread
+from ...threads.permissions import exclude_invisible_threads
 from .threads import UserThreads
 
 

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

@@ -1,7 +1,7 @@
-from misago.conf import settings
-from misago.core.shortcuts import paginate, pagination_dict
-from misago.users.online.utils import make_users_status_aware
-from misago.users.serializers import UserCardSerializer
+from ...conf import settings
+from ...core.shortcuts import paginate, pagination_dict
+from ..online.utils import make_users_status_aware
+from ..serializers import UserCardSerializer
 
 
 class RankUsers(object):

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

@@ -1,10 +1,10 @@
-from misago.acl.objectacl import add_acl_to_obj
-from misago.conf import settings
-from misago.core.shortcuts import paginate, pagination_dict
-from misago.threads.permissions import exclude_invisible_threads
-from misago.threads.serializers import FeedSerializer
-from misago.threads.utils import add_categories_to_items
-from misago.threads.viewmodels import ThreadsRootCategory
+from ...acl.objectacl import add_acl_to_obj
+from ...conf import settings
+from ...core.shortcuts import paginate, pagination_dict
+from ...threads.permissions import exclude_invisible_threads
+from ...threads.serializers import FeedSerializer
+from ...threads.utils import add_categories_to_items
+from ...threads.viewmodels import ThreadsRootCategory
 
 
 class UserThreads(object):

+ 4 - 5
misago/users/views/activation.py

@@ -3,11 +3,10 @@ from django.shortcuts import get_object_or_404, render
 from django.urls import reverse
 from django.utils.translation import gettext as _
 
-from misago.core.exceptions import Banned
-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
-
+from ...core.exceptions import Banned
+from ..bans import get_user_ban
+from ..decorators import deny_authenticated, deny_banned_ips
+from ..tokens import is_activation_token_valid
 
 User = get_user_model()
 

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

@@ -1,9 +1,9 @@
 from django.contrib import messages
 from django.utils.translation import gettext_lazy as _
 
-from misago.admin.views import generic
-from misago.users.forms.admin import BanForm, SearchBansForm
-from misago.users.models import Ban
+from ....admin.views import generic
+from ...forms.admin import BanForm, SearchBansForm
+from ...models import Ban
 
 
 class BanAdmin(generic.AdminBaseMixin):

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

@@ -1,14 +1,14 @@
 from django.contrib import messages
 from django.utils.translation import gettext_lazy as _
 
-from misago.admin.views import generic
-from misago.users.datadownloads import (
+from ....admin.views import generic
+from ...datadownloads import (
     expire_user_data_download,
     request_user_data_download,
     user_has_data_download_request,
 )
-from misago.users.forms.admin import RequestDataDownloadsForm, SearchDataDownloadsForm
-from misago.users.models import DataDownload
+from ...forms.admin import RequestDataDownloadsForm, SearchDataDownloadsForm
+from ...models import DataDownload
 
 
 class DataDownloadAdmin(generic.AdminBaseMixin):

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

@@ -3,9 +3,9 @@ from django.shortcuts import redirect
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
 
-from misago.admin.views import generic
-from misago.users.forms.admin import RankForm
-from misago.users.models import Rank
+from ....admin.views import generic
+from ...forms.admin import RankForm
+from ...models import Rank
 
 
 class RankAdmin(generic.AdminBaseMixin):

+ 14 - 17
misago/users/views/admin/users.py

@@ -5,29 +5,26 @@ from django.http import JsonResponse
 from django.shortcuts import redirect
 from django.utils.translation import gettext_lazy as _
 
-from misago.acl.useracl import get_user_acl
-from misago.admin.auth import start_admin_session
-from misago.admin.views import generic
-from misago.categories.models import Category
-from misago.core.mail import mail_users
-from misago.core.pgutils import chunk_queryset
-from misago.threads.models import Thread
-from misago.users.avatars.dynamic import set_avatar as set_dynamic_avatar
-from misago.users.datadownloads import (
-    request_user_data_download,
-    user_has_data_download_request,
-)
-from misago.users.forms.admin import (
+from ....acl.useracl import get_user_acl
+from ....admin.auth import start_admin_session
+from ....admin.views import generic
+from ....categories.models import Category
+from ....core.mail import mail_users
+from ....core.pgutils import chunk_queryset
+from ....threads.models import Thread
+from ...avatars.dynamic import set_avatar as set_dynamic_avatar
+from ...datadownloads import request_user_data_download, user_has_data_download_request
+from ...forms.admin import (
     BanUsersForm,
     EditUserForm,
     EditUserFormFactory,
     NewUserForm,
     create_search_users_form,
 )
-from misago.users.models import Ban
-from misago.users.profilefields import profilefields
-from misago.users.setupnewuser import setup_new_user
-from misago.users.signatures import set_user_signature
+from ...models import Ban
+from ...profilefields import profilefields
+from ...setupnewuser import setup_new_user
+from ...signatures import set_user_signature
 
 User = get_user_model()
 

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

@@ -2,8 +2,7 @@ from django.contrib.auth import get_user_model
 from django.contrib.staticfiles.templatetags.staticfiles import static
 from django.shortcuts import redirect
 
-from misago.conf import settings
-
+from ...conf import settings
 
 User = get_user_model()
 

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

@@ -3,10 +3,10 @@ from django.shortcuts import get_object_or_404, render
 from django.urls import reverse
 from django.utils.translation import gettext as _
 
-from misago.core.exceptions import Banned
-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
+from ...core.exceptions import Banned
+from ..bans import get_user_ban
+from ..decorators import deny_banned_ips
+from ..tokens import is_password_change_token_valid
 
 
 def reset_view(f):

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

@@ -2,11 +2,11 @@ from django.shortcuts import get_object_or_404, redirect, render
 from django.urls import reverse
 from django.views import View
 
-from misago.core.utils import format_plaintext_for_html
-from misago.users.models import Rank
-from misago.users.pages import users_list
-from misago.users.permissions import allow_browse_users_list
-from misago.users.viewmodels import ActivePosters, RankUsers
+from ...core.utils import format_plaintext_for_html
+from ..models import Rank
+from ..pages import users_list
+from ..permissions import allow_browse_users_list
+from ..viewmodels import ActivePosters, RankUsers
 
 
 class ListView(View):

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

@@ -3,9 +3,9 @@ from django.db import IntegrityError
 from django.shortcuts import render
 from django.utils.translation import gettext as _
 
-from misago.users.credentialchange import read_new_credential
-from misago.users.decorators import deny_guests
-from misago.users.pages import usercp
+from ..credentialchange import read_new_credential
+from ..decorators import deny_guests
+from ..pages import usercp
 
 
 @deny_guests

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

@@ -3,19 +3,14 @@ from django.http import Http404
 from django.shortcuts import get_object_or_404, redirect, render
 from django.views import View
 
-from misago.acl.objectacl import add_acl_to_obj
-from misago.core.shortcuts import paginate, pagination_dict, validate_slug
-from misago.users.bans import get_user_ban
-from misago.users.online.utils import get_user_status
-from misago.users.pages import user_profile
-from misago.users.profilefields import profilefields, serialize_profilefields_data
-from misago.users.serializers import (
-    BanDetailsSerializer,
-    UsernameChangeSerializer,
-    UserSerializer,
-)
-from misago.users.viewmodels import Followers, Follows, UserPosts, UserThreads
-
+from ...acl.objectacl import add_acl_to_obj
+from ...core.shortcuts import paginate, pagination_dict, validate_slug
+from ..bans import get_user_ban
+from ..online.utils import get_user_status
+from ..pages import user_profile
+from ..profilefields import profilefields, serialize_profilefields_data
+from ..serializers import BanDetailsSerializer, UsernameChangeSerializer, UserSerializer
+from ..viewmodels import Followers, Follows, UserPosts, UserThreads
 
 User = get_user_model()