codex 1.6.0__py3-none-any.whl → 1.6.0a0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of codex might be problematic. Click here for more details.

Files changed (769) hide show
  1. codex/exceptions.py +18 -22
  2. codex/integrity.py +3 -66
  3. codex/librarian/covers/coverd.py +2 -2
  4. codex/librarian/covers/create.py +29 -50
  5. codex/librarian/covers/path.py +6 -8
  6. codex/librarian/covers/purge.py +18 -28
  7. codex/librarian/covers/tasks.py +2 -3
  8. codex/librarian/importer/{aggregate.py → aggregate_metadata.py} +88 -58
  9. codex/librarian/importer/{extract.py → clean_metadata.py} +4 -33
  10. codex/librarian/importer/const.py +13 -46
  11. codex/librarian/importer/create_comics.py +17 -101
  12. codex/librarian/importer/create_fks.py +134 -99
  13. codex/librarian/importer/deleted.py +28 -103
  14. codex/librarian/importer/failed_imports.py +64 -42
  15. codex/librarian/importer/importerd.py +290 -71
  16. codex/librarian/importer/link_comics.py +26 -26
  17. codex/librarian/importer/moved.py +81 -128
  18. codex/librarian/importer/query_fks.py +122 -142
  19. codex/librarian/importer/status.py +39 -8
  20. codex/librarian/importer/tasks.py +9 -26
  21. codex/librarian/importer/update_comics.py +89 -0
  22. codex/librarian/janitor/cleanup.py +2 -26
  23. codex/librarian/janitor/failed_imports.py +1 -1
  24. codex/librarian/janitor/janitor.py +1 -13
  25. codex/librarian/janitor/janitord.py +1 -1
  26. codex/librarian/janitor/status.py +0 -1
  27. codex/librarian/janitor/tasks.py +0 -5
  28. codex/librarian/librariand.py +5 -9
  29. codex/librarian/notifier/notifierd.py +1 -1
  30. codex/librarian/notifier/tasks.py +4 -4
  31. codex/librarian/search/update.py +1 -1
  32. codex/librarian/watchdog/db_snapshot.py +6 -9
  33. codex/librarian/watchdog/emitter.py +0 -3
  34. codex/librarian/watchdog/event_batcherd.py +3 -19
  35. codex/librarian/watchdog/events.py +36 -176
  36. codex/librarian/watchdog/observers.py +3 -13
  37. codex/middleware.py +2 -1
  38. codex/migrations/0027_sort_name.py +149 -0
  39. codex/models/admin.py +2 -0
  40. codex/models/base.py +0 -3
  41. codex/models/comic.py +9 -13
  42. codex/models/{util.py → const.py} +2 -15
  43. codex/models/groups.py +14 -28
  44. codex/models/library.py +3 -11
  45. codex/models/paths.py +14 -61
  46. codex/permissions.py +1 -1
  47. codex/search/backend_search.py +8 -5
  48. codex/search/query.py +2 -25
  49. codex/search/writing.py +1 -1
  50. codex/serializers/admin.py +44 -53
  51. codex/serializers/browser/choices.py +42 -37
  52. codex/serializers/browser/filters.py +131 -32
  53. codex/serializers/browser/metadata.py +1 -45
  54. codex/serializers/browser/mixins.py +4 -37
  55. codex/serializers/browser/page.py +6 -3
  56. codex/serializers/browser/settings.py +11 -42
  57. codex/serializers/choices.py +1 -14
  58. codex/serializers/models/pycountry.py +51 -11
  59. codex/serializers/opds/v2.py +16 -10
  60. codex/serializers/opds/v2_unused.py +3 -5
  61. codex/serializers/reader.py +7 -21
  62. codex/serializers/redirect.py +2 -3
  63. codex/serializers/route.py +7 -16
  64. codex/settings/settings.py +8 -23
  65. codex/startup.py +3 -77
  66. codex/static_root/assets/VCheckbox-Aq_ImMNC.da711f8b6a15.js +1 -0
  67. codex/static_root/assets/VCheckbox-Aq_ImMNC.da711f8b6a15.js.br +0 -0
  68. codex/static_root/assets/VCheckbox-Aq_ImMNC.da711f8b6a15.js.gz +0 -0
  69. codex/static_root/assets/VCheckbox-Aq_ImMNC.js +1 -0
  70. codex/static_root/assets/VCheckbox-Aq_ImMNC.js.br +0 -0
  71. codex/static_root/assets/VCheckbox-Aq_ImMNC.js.gz +0 -0
  72. codex/static_root/assets/{VCheckboxBtn-DxNOKONG.5ab34c4c47aa.js → VCheckboxBtn-D3izCBa7.54f4d7f48bbf.js} +1 -1
  73. codex/static_root/assets/VCheckboxBtn-D3izCBa7.54f4d7f48bbf.js.br +0 -0
  74. codex/static_root/assets/VCheckboxBtn-D3izCBa7.54f4d7f48bbf.js.gz +0 -0
  75. codex/static_root/assets/{VCheckboxBtn-DxNOKONG.js → VCheckboxBtn-D3izCBa7.js} +1 -1
  76. codex/static_root/assets/VCheckboxBtn-D3izCBa7.js.br +0 -0
  77. codex/static_root/assets/VCheckboxBtn-D3izCBa7.js.gz +0 -0
  78. codex/static_root/assets/VCombobox-DLL1EsSN.55622a0cd4ab.js +1 -0
  79. codex/static_root/assets/VCombobox-DLL1EsSN.55622a0cd4ab.js.br +0 -0
  80. codex/static_root/assets/VCombobox-DLL1EsSN.55622a0cd4ab.js.gz +0 -0
  81. codex/static_root/assets/VCombobox-DLL1EsSN.js +1 -0
  82. codex/static_root/assets/VCombobox-DLL1EsSN.js.br +0 -0
  83. codex/static_root/assets/VCombobox-DLL1EsSN.js.gz +0 -0
  84. codex/static_root/assets/{VDialog-lQ13FnRR.1c801ad756b2.css → VDialog-C5Nxd_zP.css} +1 -1
  85. codex/static_root/assets/VDialog-C5Nxd_zP.css.br +0 -0
  86. codex/static_root/assets/VDialog-C5Nxd_zP.css.gz +0 -0
  87. codex/static_root/assets/{VDialog-lQ13FnRR.css → VDialog-C5Nxd_zP.d327f505ef0e.css} +1 -1
  88. codex/static_root/assets/VDialog-C5Nxd_zP.d327f505ef0e.css.br +0 -0
  89. codex/static_root/assets/VDialog-C5Nxd_zP.d327f505ef0e.css.gz +0 -0
  90. codex/static_root/assets/VDialog-yDKzaGEj.e8dba78ac8db.js +1 -0
  91. codex/static_root/assets/VDialog-yDKzaGEj.e8dba78ac8db.js.br +0 -0
  92. codex/static_root/assets/VDialog-yDKzaGEj.e8dba78ac8db.js.gz +0 -0
  93. codex/static_root/assets/VDialog-yDKzaGEj.js +1 -0
  94. codex/static_root/assets/VDialog-yDKzaGEj.js.br +0 -0
  95. codex/static_root/assets/VDialog-yDKzaGEj.js.gz +0 -0
  96. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.d733b7906e00.js +1 -0
  97. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.d733b7906e00.js.br +0 -0
  98. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.d733b7906e00.js.gz +0 -0
  99. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.js +1 -0
  100. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.js.br +0 -0
  101. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.js.gz +0 -0
  102. codex/static_root/assets/VRadioGroup-DEezv8bL.4a609e74e507.js +1 -0
  103. codex/static_root/assets/VRadioGroup-DEezv8bL.4a609e74e507.js.br +0 -0
  104. codex/static_root/assets/VRadioGroup-DEezv8bL.4a609e74e507.js.gz +0 -0
  105. codex/static_root/assets/VRadioGroup-DEezv8bL.js +1 -0
  106. codex/static_root/assets/VRadioGroup-DEezv8bL.js.br +0 -0
  107. codex/static_root/assets/VRadioGroup-DEezv8bL.js.gz +0 -0
  108. codex/static_root/assets/VSelect-BKXcujPy.8871035f5634.js +1 -0
  109. codex/static_root/assets/VSelect-BKXcujPy.8871035f5634.js.br +0 -0
  110. codex/static_root/assets/VSelect-BKXcujPy.8871035f5634.js.gz +0 -0
  111. codex/static_root/assets/VSelect-BKXcujPy.js +1 -0
  112. codex/static_root/assets/VSelect-BKXcujPy.js.br +0 -0
  113. codex/static_root/assets/VSelect-BKXcujPy.js.gz +0 -0
  114. codex/static_root/assets/VSelectionControl-DJAPiluk.402a7ad84a8e.js +1 -0
  115. codex/static_root/assets/VSelectionControl-DJAPiluk.402a7ad84a8e.js.br +0 -0
  116. codex/static_root/assets/VSelectionControl-DJAPiluk.402a7ad84a8e.js.gz +0 -0
  117. codex/static_root/assets/VSelectionControl-DJAPiluk.js +1 -0
  118. codex/static_root/assets/VSelectionControl-DJAPiluk.js.br +0 -0
  119. codex/static_root/assets/VSelectionControl-DJAPiluk.js.gz +0 -0
  120. codex/static_root/assets/VSlideGroup-C-kO93Va.8c9e31362dc5.js +1 -0
  121. codex/static_root/assets/VSlideGroup-C-kO93Va.8c9e31362dc5.js.br +0 -0
  122. codex/static_root/assets/VSlideGroup-C-kO93Va.8c9e31362dc5.js.gz +0 -0
  123. codex/static_root/assets/VSlideGroup-C-kO93Va.js +1 -0
  124. codex/static_root/assets/VSlideGroup-C-kO93Va.js.br +0 -0
  125. codex/static_root/assets/VSlideGroup-C-kO93Va.js.gz +0 -0
  126. codex/static_root/assets/{VTable-2RHFqfg6.f0f2106b158b.js → VTable-9vsIQObs.0a135029e924.js} +1 -1
  127. codex/static_root/assets/VTable-9vsIQObs.0a135029e924.js.br +0 -0
  128. codex/static_root/assets/VTable-9vsIQObs.0a135029e924.js.gz +0 -0
  129. codex/static_root/assets/{VTable-2RHFqfg6.js → VTable-9vsIQObs.js} +1 -1
  130. codex/static_root/assets/VTable-9vsIQObs.js.br +0 -0
  131. codex/static_root/assets/VTable-9vsIQObs.js.gz +0 -0
  132. codex/static_root/assets/VTextField-DI9HAmWh.0de01739bbf9.js +1 -0
  133. codex/static_root/assets/VTextField-DI9HAmWh.0de01739bbf9.js.br +0 -0
  134. codex/static_root/assets/VTextField-DI9HAmWh.0de01739bbf9.js.gz +0 -0
  135. codex/static_root/assets/VTextField-DI9HAmWh.js +1 -0
  136. codex/static_root/assets/VTextField-DI9HAmWh.js.br +0 -0
  137. codex/static_root/assets/VTextField-DI9HAmWh.js.gz +0 -0
  138. codex/static_root/assets/VTextField-DuIIp-VY.580110ad24dc.css +1 -0
  139. codex/static_root/assets/VTextField-DuIIp-VY.580110ad24dc.css.br +0 -0
  140. codex/static_root/assets/VTextField-DuIIp-VY.580110ad24dc.css.gz +0 -0
  141. codex/static_root/assets/VTextField-DuIIp-VY.css +1 -0
  142. codex/static_root/assets/VTextField-DuIIp-VY.css.br +0 -0
  143. codex/static_root/assets/VTextField-DuIIp-VY.css.gz +0 -0
  144. codex/static_root/assets/VWindowItem-DpnYkF3y.017d99c27b7b.js +1 -0
  145. codex/static_root/assets/VWindowItem-DpnYkF3y.017d99c27b7b.js.br +0 -0
  146. codex/static_root/assets/VWindowItem-DpnYkF3y.017d99c27b7b.js.gz +0 -0
  147. codex/static_root/assets/VWindowItem-DpnYkF3y.js +1 -0
  148. codex/static_root/assets/VWindowItem-DpnYkF3y.js.br +0 -0
  149. codex/static_root/assets/VWindowItem-DpnYkF3y.js.gz +0 -0
  150. codex/static_root/assets/admin-2BTkfSQA.e7ef29cb106d.js +1 -0
  151. codex/static_root/assets/admin-2BTkfSQA.e7ef29cb106d.js.br +0 -0
  152. codex/static_root/assets/admin-2BTkfSQA.e7ef29cb106d.js.gz +0 -0
  153. codex/static_root/assets/admin-2BTkfSQA.js +1 -0
  154. codex/static_root/assets/admin-2BTkfSQA.js.br +0 -0
  155. codex/static_root/assets/admin-2BTkfSQA.js.gz +0 -0
  156. codex/static_root/assets/{admin-B8Bp2Uih.82c98714bcf1.css → admin-BbrOU9Y9.29936748af9e.css} +1 -1
  157. codex/static_root/assets/admin-BbrOU9Y9.29936748af9e.css.br +0 -0
  158. codex/static_root/assets/admin-BbrOU9Y9.29936748af9e.css.gz +0 -0
  159. codex/static_root/assets/{admin-B8Bp2Uih.css → admin-BbrOU9Y9.css} +1 -1
  160. codex/static_root/assets/admin-BbrOU9Y9.css.br +0 -0
  161. codex/static_root/assets/admin-BbrOU9Y9.css.gz +0 -0
  162. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.1514926c78e8.css +1 -0
  163. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.1514926c78e8.css.br +0 -0
  164. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.1514926c78e8.css.gz +0 -0
  165. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.css +1 -0
  166. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.css.br +0 -0
  167. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.css.gz +0 -0
  168. codex/static_root/assets/admin-drawer-panel-mtdde7vY.c172dbae9463.js +30 -0
  169. codex/static_root/assets/admin-drawer-panel-mtdde7vY.c172dbae9463.js.br +0 -0
  170. codex/static_root/assets/admin-drawer-panel-mtdde7vY.c172dbae9463.js.gz +0 -0
  171. codex/static_root/assets/admin-drawer-panel-mtdde7vY.js +30 -0
  172. codex/static_root/assets/admin-drawer-panel-mtdde7vY.js.br +0 -0
  173. codex/static_root/assets/admin-drawer-panel-mtdde7vY.js.gz +0 -0
  174. codex/static_root/assets/browser-BA-AwUn-.23bb4b2f6a29.js +1 -0
  175. codex/static_root/assets/browser-BA-AwUn-.23bb4b2f6a29.js.br +0 -0
  176. codex/static_root/assets/browser-BA-AwUn-.23bb4b2f6a29.js.gz +0 -0
  177. codex/static_root/assets/browser-BA-AwUn-.js +1 -0
  178. codex/static_root/assets/browser-BA-AwUn-.js.br +0 -0
  179. codex/static_root/assets/browser-BA-AwUn-.js.gz +0 -0
  180. codex/static_root/assets/browser-CZeVqRNy.ccfca9a05bfe.css +1 -0
  181. codex/static_root/assets/browser-CZeVqRNy.ccfca9a05bfe.css.br +0 -0
  182. codex/static_root/assets/browser-CZeVqRNy.ccfca9a05bfe.css.gz +0 -0
  183. codex/static_root/assets/browser-CZeVqRNy.css +1 -0
  184. codex/static_root/assets/browser-CZeVqRNy.css.br +0 -0
  185. codex/static_root/assets/browser-CZeVqRNy.css.gz +0 -0
  186. codex/static_root/assets/change-password-dialog-C8YONrId.49aa6df6a91d.js +1 -0
  187. codex/static_root/assets/change-password-dialog-C8YONrId.49aa6df6a91d.js.br +0 -0
  188. codex/static_root/assets/change-password-dialog-C8YONrId.49aa6df6a91d.js.gz +0 -0
  189. codex/static_root/assets/change-password-dialog-C8YONrId.js +1 -0
  190. codex/static_root/assets/change-password-dialog-C8YONrId.js.br +0 -0
  191. codex/static_root/assets/change-password-dialog-C8YONrId.js.gz +0 -0
  192. codex/static_root/assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css +1 -0
  193. codex/static_root/assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css.br +0 -0
  194. codex/static_root/assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css.gz +0 -0
  195. codex/static_root/assets/change-password-dialog-HvIvmmIE.css +1 -0
  196. codex/static_root/assets/change-password-dialog-HvIvmmIE.css.br +0 -0
  197. codex/static_root/assets/change-password-dialog-HvIvmmIE.css.gz +0 -0
  198. codex/static_root/assets/confirm-dialog-Clg-o2G-.e11d8efef3fb.js +1 -0
  199. codex/static_root/assets/confirm-dialog-Clg-o2G-.e11d8efef3fb.js.br +0 -0
  200. codex/static_root/assets/confirm-dialog-Clg-o2G-.e11d8efef3fb.js.gz +0 -0
  201. codex/static_root/assets/confirm-dialog-Clg-o2G-.js +1 -0
  202. codex/static_root/assets/confirm-dialog-Clg-o2G-.js.br +0 -0
  203. codex/static_root/assets/confirm-dialog-Clg-o2G-.js.gz +0 -0
  204. codex/static_root/assets/datetime-column-DejrPZxl.9fd36bef6fdd.js +1 -0
  205. codex/static_root/assets/datetime-column-DejrPZxl.9fd36bef6fdd.js.br +0 -0
  206. codex/static_root/assets/datetime-column-DejrPZxl.9fd36bef6fdd.js.gz +0 -0
  207. codex/static_root/assets/datetime-column-DejrPZxl.js +1 -0
  208. codex/static_root/assets/datetime-column-DejrPZxl.js.br +0 -0
  209. codex/static_root/assets/datetime-column-DejrPZxl.js.gz +0 -0
  210. codex/static_root/assets/datetime-column-Dg_RxTVM.1fa7c5cbead7.css +1 -0
  211. codex/static_root/assets/datetime-column-Dg_RxTVM.1fa7c5cbead7.css.br +0 -0
  212. codex/static_root/assets/datetime-column-Dg_RxTVM.css +1 -0
  213. codex/static_root/assets/datetime-column-Dg_RxTVM.css.br +0 -0
  214. codex/static_root/assets/filter-DHo57nTp.4d79a276d806.js +1 -0
  215. codex/static_root/assets/filter-DHo57nTp.4d79a276d806.js.br +0 -0
  216. codex/static_root/assets/filter-DHo57nTp.4d79a276d806.js.gz +0 -0
  217. codex/static_root/assets/filter-DHo57nTp.js +1 -0
  218. codex/static_root/assets/filter-DHo57nTp.js.br +0 -0
  219. codex/static_root/assets/filter-DHo57nTp.js.gz +0 -0
  220. codex/static_root/assets/flag-tab-BacZLlVi.8deba6a5370d.css +1 -0
  221. codex/static_root/assets/flag-tab-BacZLlVi.8deba6a5370d.css.br +0 -0
  222. codex/static_root/assets/flag-tab-BacZLlVi.8deba6a5370d.css.gz +0 -0
  223. codex/static_root/assets/flag-tab-BacZLlVi.css +1 -0
  224. codex/static_root/assets/flag-tab-BacZLlVi.css.br +0 -0
  225. codex/static_root/assets/flag-tab-BacZLlVi.css.gz +0 -0
  226. codex/static_root/assets/flag-tab-CagMLGSE.125739911c45.js +1 -0
  227. codex/static_root/assets/flag-tab-CagMLGSE.125739911c45.js.br +0 -0
  228. codex/static_root/assets/flag-tab-CagMLGSE.125739911c45.js.gz +0 -0
  229. codex/static_root/assets/flag-tab-CagMLGSE.js +1 -0
  230. codex/static_root/assets/flag-tab-CagMLGSE.js.br +0 -0
  231. codex/static_root/assets/flag-tab-CagMLGSE.js.gz +0 -0
  232. codex/static_root/assets/{group-tab-D5vWrihT.js → group-tab-BTAjhv32.ac196780d0a9.js} +1 -1
  233. codex/static_root/assets/group-tab-BTAjhv32.ac196780d0a9.js.br +0 -0
  234. codex/static_root/assets/group-tab-BTAjhv32.ac196780d0a9.js.gz +0 -0
  235. codex/static_root/assets/{group-tab-D5vWrihT.1afb2ce453ff.js → group-tab-BTAjhv32.js} +1 -1
  236. codex/static_root/assets/group-tab-BTAjhv32.js.br +0 -0
  237. codex/static_root/assets/group-tab-BTAjhv32.js.gz +0 -0
  238. codex/static_root/assets/http-error-DaHEsKbT.55d56ce2b9b4.js +1 -0
  239. codex/static_root/assets/http-error-DaHEsKbT.55d56ce2b9b4.js.br +0 -0
  240. codex/static_root/assets/http-error-DaHEsKbT.55d56ce2b9b4.js.gz +0 -0
  241. codex/static_root/assets/http-error-DaHEsKbT.js +1 -0
  242. codex/static_root/assets/http-error-DaHEsKbT.js.br +0 -0
  243. codex/static_root/assets/http-error-DaHEsKbT.js.gz +0 -0
  244. codex/static_root/assets/http-error-_wlDqEcp.5b78d3e332c9.css +1 -0
  245. codex/static_root/assets/{http-error-DKulXuTl.95e42988d5d5.css.br → http-error-_wlDqEcp.5b78d3e332c9.css.br} +0 -0
  246. codex/static_root/assets/http-error-_wlDqEcp.5b78d3e332c9.css.gz +0 -0
  247. codex/static_root/assets/http-error-_wlDqEcp.css +1 -0
  248. codex/static_root/assets/{http-error-DKulXuTl.css.br → http-error-_wlDqEcp.css.br} +0 -0
  249. codex/static_root/assets/http-error-_wlDqEcp.css.gz +0 -0
  250. codex/static_root/assets/index-DUjeNg4x.36d50c91b2c1.js +1 -0
  251. codex/static_root/assets/index-DUjeNg4x.36d50c91b2c1.js.br +0 -0
  252. codex/static_root/assets/index-DUjeNg4x.36d50c91b2c1.js.gz +0 -0
  253. codex/static_root/assets/index-DUjeNg4x.js +1 -0
  254. codex/static_root/assets/index-DUjeNg4x.js.br +0 -0
  255. codex/static_root/assets/index-DUjeNg4x.js.gz +0 -0
  256. codex/static_root/assets/library-tab-CXbkxNZt.954f2850a439.css +1 -0
  257. codex/static_root/assets/library-tab-CXbkxNZt.954f2850a439.css.br +2 -0
  258. codex/static_root/assets/library-tab-CXbkxNZt.954f2850a439.css.gz +0 -0
  259. codex/static_root/assets/library-tab-CXbkxNZt.css +1 -0
  260. codex/static_root/assets/library-tab-CXbkxNZt.css.br +2 -0
  261. codex/static_root/assets/library-tab-CXbkxNZt.css.gz +0 -0
  262. codex/static_root/assets/library-tab-Cud4639b.7f5a50aaabe8.js +1 -0
  263. codex/static_root/assets/library-tab-Cud4639b.7f5a50aaabe8.js.br +0 -0
  264. codex/static_root/assets/library-tab-Cud4639b.7f5a50aaabe8.js.gz +0 -0
  265. codex/static_root/assets/library-tab-Cud4639b.js +1 -0
  266. codex/static_root/assets/library-tab-Cud4639b.js.br +0 -0
  267. codex/static_root/assets/library-tab-Cud4639b.js.gz +0 -0
  268. codex/static_root/assets/main-BnzL_Byv.22f98ee91990.js +32 -0
  269. codex/static_root/assets/main-BnzL_Byv.22f98ee91990.js.br +0 -0
  270. codex/static_root/assets/main-BnzL_Byv.22f98ee91990.js.gz +0 -0
  271. codex/static_root/assets/main-BnzL_Byv.js +32 -0
  272. codex/static_root/assets/main-BnzL_Byv.js.br +0 -0
  273. codex/static_root/assets/main-BnzL_Byv.js.gz +0 -0
  274. codex/static_root/assets/{main-Ztp855PW.d46d718fac45.css → main-sK7HC5h4.6f04ddfc5f1a.css} +1 -1
  275. codex/static_root/assets/main-sK7HC5h4.6f04ddfc5f1a.css.br +0 -0
  276. codex/static_root/assets/{main-Ztp855PW.d46d718fac45.css.gz → main-sK7HC5h4.6f04ddfc5f1a.css.gz} +0 -0
  277. codex/static_root/assets/{main-Ztp855PW.css → main-sK7HC5h4.css} +1 -1
  278. codex/static_root/assets/main-sK7HC5h4.css.br +0 -0
  279. codex/static_root/assets/{main-Ztp855PW.css.gz → main-sK7HC5h4.css.gz} +0 -0
  280. codex/static_root/assets/pagination-toolbar-B3wS4_7p.7695fafdefce.css +1 -0
  281. codex/static_root/assets/pagination-toolbar-B3wS4_7p.7695fafdefce.css.br +0 -0
  282. codex/static_root/assets/pagination-toolbar-B3wS4_7p.7695fafdefce.css.gz +0 -0
  283. codex/static_root/assets/pagination-toolbar-B3wS4_7p.css +1 -0
  284. codex/static_root/assets/pagination-toolbar-B3wS4_7p.css.br +0 -0
  285. codex/static_root/assets/pagination-toolbar-B3wS4_7p.css.gz +0 -0
  286. codex/static_root/assets/pagination-toolbar-Covpd-k8.b71277bd7a2d.js +1 -0
  287. codex/static_root/assets/pagination-toolbar-Covpd-k8.b71277bd7a2d.js.br +0 -0
  288. codex/static_root/assets/pagination-toolbar-Covpd-k8.b71277bd7a2d.js.gz +0 -0
  289. codex/static_root/assets/pagination-toolbar-Covpd-k8.js +1 -0
  290. codex/static_root/assets/pagination-toolbar-Covpd-k8.js.br +0 -0
  291. codex/static_root/assets/pagination-toolbar-Covpd-k8.js.gz +0 -0
  292. codex/static_root/assets/pdf-doc-CD2lnB32.1cef3bf498be.js +35 -0
  293. codex/static_root/assets/pdf-doc-CD2lnB32.1cef3bf498be.js.br +0 -0
  294. codex/static_root/assets/pdf-doc-CD2lnB32.1cef3bf498be.js.gz +0 -0
  295. codex/static_root/assets/pdf-doc-CD2lnB32.js +35 -0
  296. codex/static_root/assets/pdf-doc-CD2lnB32.js.br +0 -0
  297. codex/static_root/assets/pdf-doc-CD2lnB32.js.gz +0 -0
  298. codex/static_root/assets/reader-Dspy46e8.925a6b05bfcf.css +1 -0
  299. codex/static_root/assets/reader-Dspy46e8.925a6b05bfcf.css.br +0 -0
  300. codex/static_root/assets/reader-Dspy46e8.925a6b05bfcf.css.gz +0 -0
  301. codex/static_root/assets/reader-Dspy46e8.css +1 -0
  302. codex/static_root/assets/reader-Dspy46e8.css.br +0 -0
  303. codex/static_root/assets/reader-Dspy46e8.css.gz +0 -0
  304. codex/static_root/assets/reader-L85y7IXD.6de58f450421.js +2 -0
  305. codex/static_root/assets/reader-L85y7IXD.6de58f450421.js.br +0 -0
  306. codex/static_root/assets/reader-L85y7IXD.6de58f450421.js.gz +0 -0
  307. codex/static_root/assets/reader-L85y7IXD.js +2 -0
  308. codex/static_root/assets/reader-L85y7IXD.js.br +0 -0
  309. codex/static_root/assets/reader-L85y7IXD.js.gz +0 -0
  310. codex/static_root/assets/relation-chips-BpuqEeqM.1372d8a3e6cf.js +1 -0
  311. codex/static_root/assets/relation-chips-BpuqEeqM.1372d8a3e6cf.js.br +0 -0
  312. codex/static_root/assets/relation-chips-BpuqEeqM.1372d8a3e6cf.js.gz +0 -0
  313. codex/static_root/assets/relation-chips-BpuqEeqM.js +1 -0
  314. codex/static_root/assets/relation-chips-BpuqEeqM.js.br +0 -0
  315. codex/static_root/assets/relation-chips-BpuqEeqM.js.gz +0 -0
  316. codex/static_root/assets/{relation-chips-Bsc-gUxE.98e65384c3c9.css → relation-chips-D6T6FX7G.css} +1 -1
  317. codex/static_root/assets/relation-chips-D6T6FX7G.css.br +0 -0
  318. codex/static_root/assets/relation-chips-D6T6FX7G.css.gz +0 -0
  319. codex/static_root/assets/{relation-chips-Bsc-gUxE.css → relation-chips-D6T6FX7G.db095b2497e4.css} +1 -1
  320. codex/static_root/assets/relation-chips-D6T6FX7G.db095b2497e4.css.br +0 -0
  321. codex/static_root/assets/relation-chips-D6T6FX7G.db095b2497e4.css.gz +0 -0
  322. codex/static_root/assets/settings-drawer-BgUazs7O.7bbeb1fd98f1.css +1 -0
  323. codex/static_root/assets/settings-drawer-BgUazs7O.7bbeb1fd98f1.css.br +0 -0
  324. codex/static_root/assets/settings-drawer-BgUazs7O.7bbeb1fd98f1.css.gz +0 -0
  325. codex/static_root/assets/settings-drawer-BgUazs7O.css +1 -0
  326. codex/static_root/assets/settings-drawer-BgUazs7O.css.br +0 -0
  327. codex/static_root/assets/settings-drawer-BgUazs7O.css.gz +0 -0
  328. codex/static_root/assets/settings-drawer-CLMcxfVd.b9619341ad48.js +2 -0
  329. codex/static_root/assets/settings-drawer-CLMcxfVd.b9619341ad48.js.br +0 -0
  330. codex/static_root/assets/settings-drawer-CLMcxfVd.b9619341ad48.js.gz +0 -0
  331. codex/static_root/assets/settings-drawer-CLMcxfVd.js +2 -0
  332. codex/static_root/assets/settings-drawer-CLMcxfVd.js.br +0 -0
  333. codex/static_root/assets/settings-drawer-CLMcxfVd.js.gz +0 -0
  334. codex/static_root/assets/stats-tab-CQa3-W05.3d7c61418528.js +1 -0
  335. codex/static_root/assets/stats-tab-CQa3-W05.3d7c61418528.js.br +0 -0
  336. codex/static_root/assets/stats-tab-CQa3-W05.3d7c61418528.js.gz +0 -0
  337. codex/static_root/assets/stats-tab-CQa3-W05.js +1 -0
  338. codex/static_root/assets/stats-tab-CQa3-W05.js.br +0 -0
  339. codex/static_root/assets/stats-tab-CQa3-W05.js.gz +0 -0
  340. codex/static_root/assets/stats-tab-TsyG3wH_.b93c080356fc.css +1 -0
  341. codex/static_root/assets/stats-tab-TsyG3wH_.b93c080356fc.css.br +2 -0
  342. codex/static_root/assets/stats-tab-TsyG3wH_.b93c080356fc.css.gz +0 -0
  343. codex/static_root/assets/stats-tab-TsyG3wH_.css +1 -0
  344. codex/static_root/assets/stats-tab-TsyG3wH_.css.br +2 -0
  345. codex/static_root/assets/stats-tab-TsyG3wH_.css.gz +0 -0
  346. codex/static_root/assets/task-tab-OPhBm-O2.8f31f4215114.js +1 -0
  347. codex/static_root/assets/task-tab-OPhBm-O2.8f31f4215114.js.br +0 -0
  348. codex/static_root/assets/task-tab-OPhBm-O2.8f31f4215114.js.gz +0 -0
  349. codex/static_root/assets/task-tab-OPhBm-O2.js +1 -0
  350. codex/static_root/assets/task-tab-OPhBm-O2.js.br +0 -0
  351. codex/static_root/assets/task-tab-OPhBm-O2.js.gz +0 -0
  352. codex/static_root/assets/to-case-kUm8NPpW.5b3369f511b8.js +1 -0
  353. codex/static_root/assets/to-case-kUm8NPpW.js +1 -0
  354. codex/static_root/assets/unauthorized-ClQNhRb5.32a8a84d1781.js +1 -0
  355. codex/static_root/assets/unauthorized-ClQNhRb5.32a8a84d1781.js.br +0 -0
  356. codex/static_root/assets/unauthorized-ClQNhRb5.32a8a84d1781.js.gz +0 -0
  357. codex/static_root/assets/unauthorized-ClQNhRb5.js +1 -0
  358. codex/static_root/assets/unauthorized-ClQNhRb5.js.br +0 -0
  359. codex/static_root/assets/unauthorized-ClQNhRb5.js.gz +0 -0
  360. codex/static_root/assets/{unauthorized-CibJYD8o.4c2de98c2b53.css → unauthorized-DWgytUow.ca2f13dbdbf5.css} +1 -1
  361. codex/static_root/assets/unauthorized-DWgytUow.ca2f13dbdbf5.css.br +0 -0
  362. codex/static_root/assets/unauthorized-DWgytUow.ca2f13dbdbf5.css.gz +0 -0
  363. codex/static_root/assets/{unauthorized-CibJYD8o.css → unauthorized-DWgytUow.css} +1 -1
  364. codex/static_root/assets/unauthorized-DWgytUow.css.br +0 -0
  365. codex/static_root/assets/unauthorized-DWgytUow.css.gz +0 -0
  366. codex/static_root/assets/user-tab-BKkxa2WL.50d83951c09f.js +1 -0
  367. codex/static_root/assets/user-tab-BKkxa2WL.50d83951c09f.js.br +0 -0
  368. codex/static_root/assets/user-tab-BKkxa2WL.50d83951c09f.js.gz +0 -0
  369. codex/static_root/assets/user-tab-BKkxa2WL.js +1 -0
  370. codex/static_root/assets/user-tab-BKkxa2WL.js.br +0 -0
  371. codex/static_root/assets/user-tab-BKkxa2WL.js.gz +0 -0
  372. codex/static_root/js/choices-admin.248384ece3f6.json +1 -0
  373. codex/static_root/js/choices-admin.248384ece3f6.json.br +0 -0
  374. codex/static_root/js/choices-admin.248384ece3f6.json.gz +0 -0
  375. codex/static_root/js/choices-admin.json +1 -1
  376. codex/static_root/js/choices-admin.json.br +0 -0
  377. codex/static_root/js/choices-admin.json.gz +0 -0
  378. codex/static_root/js/choices.b60817ba0a93.json +1 -0
  379. codex/static_root/js/choices.b60817ba0a93.json.br +0 -0
  380. codex/static_root/js/choices.b60817ba0a93.json.gz +0 -0
  381. codex/static_root/js/choices.json +1 -1
  382. codex/static_root/js/choices.json.br +0 -0
  383. codex/static_root/js/choices.json.gz +0 -0
  384. codex/static_root/manifest.c5fa10a7dfdc.json +641 -0
  385. codex/static_root/manifest.c5fa10a7dfdc.json.br +0 -0
  386. codex/static_root/manifest.c5fa10a7dfdc.json.gz +0 -0
  387. codex/static_root/manifest.json +298 -279
  388. codex/static_root/manifest.json.br +0 -0
  389. codex/static_root/manifest.json.gz +0 -0
  390. codex/static_root/staticfiles.json +1 -1
  391. codex/status_controller.py +2 -11
  392. codex/urls/api/auth.py +1 -2
  393. codex/urls/api/browser.py +4 -13
  394. codex/urls/api/reader.py +9 -3
  395. codex/urls/api/v3.py +0 -2
  396. codex/urls/opds/binary.py +1 -1
  397. codex/views/admin/api_key.py +8 -7
  398. codex/views/admin/flag.py +7 -2
  399. codex/views/admin/group.py +6 -2
  400. codex/views/admin/library.py +37 -44
  401. codex/views/admin/stats.py +83 -20
  402. codex/views/admin/tasks.py +12 -26
  403. codex/views/admin/user.py +9 -3
  404. codex/views/auth.py +54 -31
  405. codex/views/bookmark.py +72 -92
  406. codex/views/browser/base.py +90 -42
  407. codex/views/browser/browser.py +371 -92
  408. codex/views/browser/{annotations.py → browser_annotations.py} +121 -67
  409. codex/views/browser/browser_breadcrumbs.py +175 -0
  410. codex/views/browser/browser_order_by.py +63 -0
  411. codex/views/browser/choices.py +85 -38
  412. codex/views/browser/const.py +3 -0
  413. codex/views/browser/filters/annotations.py +19 -87
  414. codex/views/browser/filters/bookmark.py +12 -24
  415. codex/views/browser/filters/field.py +6 -8
  416. codex/views/browser/filters/group.py +14 -35
  417. codex/views/browser/filters/search.py +20 -31
  418. codex/views/browser/metadata.py +73 -112
  419. codex/views/browser/session.py +12 -0
  420. codex/views/const.py +0 -140
  421. codex/views/cover.py +77 -0
  422. codex/views/download.py +8 -5
  423. codex/views/frontend.py +2 -4
  424. codex/views/opds/authentication_v1.py +45 -46
  425. codex/views/opds/binary.py +10 -5
  426. codex/views/opds/const.py +0 -13
  427. codex/views/opds/urls.py +4 -6
  428. codex/views/opds/util.py +12 -4
  429. codex/views/opds/v1/entry/links.py +33 -18
  430. codex/views/opds/v1/facets.py +7 -7
  431. codex/views/opds/v1/feed.py +45 -55
  432. codex/views/opds/v1/links.py +5 -7
  433. codex/views/opds/v1/opensearch_v1.py +6 -2
  434. codex/views/opds/v2/feed.py +26 -25
  435. codex/views/opds/v2/links.py +2 -4
  436. codex/views/opds/v2/publications.py +54 -34
  437. codex/views/opds/v2/top_links.py +2 -2
  438. codex/views/reader/page.py +8 -15
  439. codex/views/reader/reader.py +322 -19
  440. codex/views/reader/{settings.py → session.py} +2 -4
  441. codex/views/session.py +102 -83
  442. codex/views/template.py +3 -3
  443. codex/views/version.py +2 -2
  444. codex/websockets/consumers.py +10 -14
  445. {codex-1.6.0.dist-info → codex-1.6.0a0.dist-info}/METADATA +15 -22
  446. {codex-1.6.0.dist-info → codex-1.6.0a0.dist-info}/RECORD +449 -467
  447. codex/librarian/importer/cache.py +0 -93
  448. codex/librarian/importer/create_covers.py +0 -96
  449. codex/librarian/importer/importer.py +0 -96
  450. codex/librarian/importer/init.py +0 -265
  451. codex/librarian/importer/link_covers.py +0 -73
  452. codex/librarian/importer/query_covers.py +0 -52
  453. codex/migrations/0027_import_order_and_covers.py +0 -280
  454. codex/serializers/browser/mtime.py +0 -21
  455. codex/serializers/fields.py +0 -149
  456. codex/serializers/settings.py +0 -12
  457. codex/static_root/assets/VCheckbox-DanrzdHo.8ec5e2094cbf.js +0 -1
  458. codex/static_root/assets/VCheckbox-DanrzdHo.8ec5e2094cbf.js.br +0 -0
  459. codex/static_root/assets/VCheckbox-DanrzdHo.8ec5e2094cbf.js.gz +0 -0
  460. codex/static_root/assets/VCheckbox-DanrzdHo.js +0 -1
  461. codex/static_root/assets/VCheckbox-DanrzdHo.js.br +0 -0
  462. codex/static_root/assets/VCheckbox-DanrzdHo.js.gz +0 -0
  463. codex/static_root/assets/VCheckboxBtn-DxNOKONG.5ab34c4c47aa.js.br +0 -0
  464. codex/static_root/assets/VCheckboxBtn-DxNOKONG.5ab34c4c47aa.js.gz +0 -0
  465. codex/static_root/assets/VCheckboxBtn-DxNOKONG.js.br +0 -0
  466. codex/static_root/assets/VCheckboxBtn-DxNOKONG.js.gz +0 -0
  467. codex/static_root/assets/VCombobox-DDvdoPTG.11d080e8edd7.js +0 -1
  468. codex/static_root/assets/VCombobox-DDvdoPTG.11d080e8edd7.js.br +0 -0
  469. codex/static_root/assets/VCombobox-DDvdoPTG.11d080e8edd7.js.gz +0 -0
  470. codex/static_root/assets/VCombobox-DDvdoPTG.js +0 -1
  471. codex/static_root/assets/VCombobox-DDvdoPTG.js.br +0 -0
  472. codex/static_root/assets/VCombobox-DDvdoPTG.js.gz +0 -0
  473. codex/static_root/assets/VDialog-Bd5dN_E1.457666d7fce1.js +0 -1
  474. codex/static_root/assets/VDialog-Bd5dN_E1.457666d7fce1.js.br +0 -0
  475. codex/static_root/assets/VDialog-Bd5dN_E1.457666d7fce1.js.gz +0 -0
  476. codex/static_root/assets/VDialog-Bd5dN_E1.js +0 -1
  477. codex/static_root/assets/VDialog-Bd5dN_E1.js.br +0 -0
  478. codex/static_root/assets/VDialog-Bd5dN_E1.js.gz +0 -0
  479. codex/static_root/assets/VDialog-lQ13FnRR.1c801ad756b2.css.br +0 -0
  480. codex/static_root/assets/VDialog-lQ13FnRR.1c801ad756b2.css.gz +0 -0
  481. codex/static_root/assets/VDialog-lQ13FnRR.css.br +0 -0
  482. codex/static_root/assets/VDialog-lQ13FnRR.css.gz +0 -0
  483. codex/static_root/assets/VExpansionPanels-DqTuYpTR.12673cf9f391.js +0 -1
  484. codex/static_root/assets/VExpansionPanels-DqTuYpTR.12673cf9f391.js.br +0 -0
  485. codex/static_root/assets/VExpansionPanels-DqTuYpTR.12673cf9f391.js.gz +0 -0
  486. codex/static_root/assets/VExpansionPanels-DqTuYpTR.js +0 -1
  487. codex/static_root/assets/VExpansionPanels-DqTuYpTR.js.br +0 -0
  488. codex/static_root/assets/VExpansionPanels-DqTuYpTR.js.gz +0 -0
  489. codex/static_root/assets/VRadioGroup-DKb8XPr-.3cf6bf5bf3bc.js +0 -1
  490. codex/static_root/assets/VRadioGroup-DKb8XPr-.3cf6bf5bf3bc.js.br +0 -0
  491. codex/static_root/assets/VRadioGroup-DKb8XPr-.3cf6bf5bf3bc.js.gz +0 -0
  492. codex/static_root/assets/VRadioGroup-DKb8XPr-.js +0 -1
  493. codex/static_root/assets/VRadioGroup-DKb8XPr-.js.br +0 -0
  494. codex/static_root/assets/VRadioGroup-DKb8XPr-.js.gz +0 -0
  495. codex/static_root/assets/VSelect-C_yPbyCG.08bd6b53a7ce.js +0 -1
  496. codex/static_root/assets/VSelect-C_yPbyCG.08bd6b53a7ce.js.br +0 -0
  497. codex/static_root/assets/VSelect-C_yPbyCG.08bd6b53a7ce.js.gz +0 -0
  498. codex/static_root/assets/VSelect-C_yPbyCG.js +0 -1
  499. codex/static_root/assets/VSelect-C_yPbyCG.js.br +0 -0
  500. codex/static_root/assets/VSelect-C_yPbyCG.js.gz +0 -0
  501. codex/static_root/assets/VSelectionControl-CmFPvGMS.802c9b3e6e28.js +0 -1
  502. codex/static_root/assets/VSelectionControl-CmFPvGMS.802c9b3e6e28.js.br +0 -0
  503. codex/static_root/assets/VSelectionControl-CmFPvGMS.802c9b3e6e28.js.gz +0 -0
  504. codex/static_root/assets/VSelectionControl-CmFPvGMS.js +0 -1
  505. codex/static_root/assets/VSelectionControl-CmFPvGMS.js.br +0 -0
  506. codex/static_root/assets/VSelectionControl-CmFPvGMS.js.gz +0 -0
  507. codex/static_root/assets/VSlideGroup-D5FZWsM1.a47491fe3e6d.js +0 -1
  508. codex/static_root/assets/VSlideGroup-D5FZWsM1.a47491fe3e6d.js.br +0 -0
  509. codex/static_root/assets/VSlideGroup-D5FZWsM1.a47491fe3e6d.js.gz +0 -0
  510. codex/static_root/assets/VSlideGroup-D5FZWsM1.js +0 -1
  511. codex/static_root/assets/VSlideGroup-D5FZWsM1.js.br +0 -0
  512. codex/static_root/assets/VSlideGroup-D5FZWsM1.js.gz +0 -0
  513. codex/static_root/assets/VTable-2RHFqfg6.f0f2106b158b.js.br +0 -0
  514. codex/static_root/assets/VTable-2RHFqfg6.f0f2106b158b.js.gz +0 -0
  515. codex/static_root/assets/VTable-2RHFqfg6.js.br +0 -0
  516. codex/static_root/assets/VTable-2RHFqfg6.js.gz +0 -0
  517. codex/static_root/assets/VTextField-BssVoDhB.4cc388b4aa3c.css +0 -1
  518. codex/static_root/assets/VTextField-BssVoDhB.4cc388b4aa3c.css.br +0 -0
  519. codex/static_root/assets/VTextField-BssVoDhB.4cc388b4aa3c.css.gz +0 -0
  520. codex/static_root/assets/VTextField-BssVoDhB.css +0 -1
  521. codex/static_root/assets/VTextField-BssVoDhB.css.br +0 -0
  522. codex/static_root/assets/VTextField-BssVoDhB.css.gz +0 -0
  523. codex/static_root/assets/VTextField-o1N9ylIb.7fffaeff8d40.js +0 -1
  524. codex/static_root/assets/VTextField-o1N9ylIb.7fffaeff8d40.js.br +0 -0
  525. codex/static_root/assets/VTextField-o1N9ylIb.7fffaeff8d40.js.gz +0 -0
  526. codex/static_root/assets/VTextField-o1N9ylIb.js +0 -1
  527. codex/static_root/assets/VTextField-o1N9ylIb.js.br +0 -0
  528. codex/static_root/assets/VTextField-o1N9ylIb.js.gz +0 -0
  529. codex/static_root/assets/VWindowItem-C_zvuz9C.663fa48efea4.js +0 -1
  530. codex/static_root/assets/VWindowItem-C_zvuz9C.663fa48efea4.js.br +0 -0
  531. codex/static_root/assets/VWindowItem-C_zvuz9C.663fa48efea4.js.gz +0 -0
  532. codex/static_root/assets/VWindowItem-C_zvuz9C.js +0 -1
  533. codex/static_root/assets/VWindowItem-C_zvuz9C.js.br +0 -0
  534. codex/static_root/assets/VWindowItem-C_zvuz9C.js.gz +0 -0
  535. codex/static_root/assets/admin-B8Bp2Uih.82c98714bcf1.css.br +0 -0
  536. codex/static_root/assets/admin-B8Bp2Uih.82c98714bcf1.css.gz +0 -0
  537. codex/static_root/assets/admin-B8Bp2Uih.css.br +0 -0
  538. codex/static_root/assets/admin-B8Bp2Uih.css.gz +0 -0
  539. codex/static_root/assets/admin-DHyHEWZ3.7a8015456c0f.js +0 -1
  540. codex/static_root/assets/admin-DHyHEWZ3.7a8015456c0f.js.br +0 -0
  541. codex/static_root/assets/admin-DHyHEWZ3.7a8015456c0f.js.gz +0 -0
  542. codex/static_root/assets/admin-DHyHEWZ3.js +0 -1
  543. codex/static_root/assets/admin-DHyHEWZ3.js.br +0 -0
  544. codex/static_root/assets/admin-DHyHEWZ3.js.gz +0 -0
  545. codex/static_root/assets/admin-drawer-panel-BXpIDQXM.19507a95375b.js +0 -30
  546. codex/static_root/assets/admin-drawer-panel-BXpIDQXM.19507a95375b.js.br +0 -0
  547. codex/static_root/assets/admin-drawer-panel-BXpIDQXM.19507a95375b.js.gz +0 -0
  548. codex/static_root/assets/admin-drawer-panel-BXpIDQXM.js +0 -30
  549. codex/static_root/assets/admin-drawer-panel-BXpIDQXM.js.br +0 -0
  550. codex/static_root/assets/admin-drawer-panel-BXpIDQXM.js.gz +0 -0
  551. codex/static_root/assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css +0 -1
  552. codex/static_root/assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css.br +0 -0
  553. codex/static_root/assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css.gz +0 -0
  554. codex/static_root/assets/admin-drawer-panel-mne3FIj6.css +0 -1
  555. codex/static_root/assets/admin-drawer-panel-mne3FIj6.css.br +0 -0
  556. codex/static_root/assets/admin-drawer-panel-mne3FIj6.css.gz +0 -0
  557. codex/static_root/assets/browser-D0Vjmmp_.a1bfaf48d65f.js +0 -1
  558. codex/static_root/assets/browser-D0Vjmmp_.a1bfaf48d65f.js.br +0 -0
  559. codex/static_root/assets/browser-D0Vjmmp_.a1bfaf48d65f.js.gz +0 -0
  560. codex/static_root/assets/browser-D0Vjmmp_.js +0 -1
  561. codex/static_root/assets/browser-D0Vjmmp_.js.br +0 -0
  562. codex/static_root/assets/browser-D0Vjmmp_.js.gz +0 -0
  563. codex/static_root/assets/browser-D7QQDneO.155cb612ed0c.css +0 -1
  564. codex/static_root/assets/browser-D7QQDneO.155cb612ed0c.css.br +0 -0
  565. codex/static_root/assets/browser-D7QQDneO.155cb612ed0c.css.gz +0 -0
  566. codex/static_root/assets/browser-D7QQDneO.css +0 -1
  567. codex/static_root/assets/browser-D7QQDneO.css.br +0 -0
  568. codex/static_root/assets/browser-D7QQDneO.css.gz +0 -0
  569. codex/static_root/assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css +0 -1
  570. codex/static_root/assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css.br +0 -0
  571. codex/static_root/assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css.gz +0 -0
  572. codex/static_root/assets/change-password-dialog-0u6IJA87.css +0 -1
  573. codex/static_root/assets/change-password-dialog-0u6IJA87.css.br +0 -0
  574. codex/static_root/assets/change-password-dialog-0u6IJA87.css.gz +0 -0
  575. codex/static_root/assets/change-password-dialog-BBsJLPXZ.e642f7e2b96f.js +0 -1
  576. codex/static_root/assets/change-password-dialog-BBsJLPXZ.e642f7e2b96f.js.br +0 -0
  577. codex/static_root/assets/change-password-dialog-BBsJLPXZ.e642f7e2b96f.js.gz +0 -0
  578. codex/static_root/assets/change-password-dialog-BBsJLPXZ.js +0 -1
  579. codex/static_root/assets/change-password-dialog-BBsJLPXZ.js.br +0 -0
  580. codex/static_root/assets/change-password-dialog-BBsJLPXZ.js.gz +0 -0
  581. codex/static_root/assets/confirm-dialog-DCKvg3ai.2a3277b3c147.js +0 -1
  582. codex/static_root/assets/confirm-dialog-DCKvg3ai.2a3277b3c147.js.br +0 -0
  583. codex/static_root/assets/confirm-dialog-DCKvg3ai.2a3277b3c147.js.gz +0 -0
  584. codex/static_root/assets/confirm-dialog-DCKvg3ai.js +0 -1
  585. codex/static_root/assets/confirm-dialog-DCKvg3ai.js.br +0 -0
  586. codex/static_root/assets/confirm-dialog-DCKvg3ai.js.gz +0 -0
  587. codex/static_root/assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js +0 -1
  588. codex/static_root/assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js.br +0 -0
  589. codex/static_root/assets/copy-to-clipboard-DoUvDJVx.js +0 -1
  590. codex/static_root/assets/copy-to-clipboard-DoUvDJVx.js.br +0 -0
  591. codex/static_root/assets/datetime-column-DeCthByU.1f3bf499e063.css +0 -1
  592. codex/static_root/assets/datetime-column-DeCthByU.css +0 -1
  593. codex/static_root/assets/datetime-column-jHKA_uNm.039c7da2036f.js +0 -1
  594. codex/static_root/assets/datetime-column-jHKA_uNm.039c7da2036f.js.br +0 -0
  595. codex/static_root/assets/datetime-column-jHKA_uNm.039c7da2036f.js.gz +0 -0
  596. codex/static_root/assets/datetime-column-jHKA_uNm.js +0 -1
  597. codex/static_root/assets/datetime-column-jHKA_uNm.js.br +0 -0
  598. codex/static_root/assets/datetime-column-jHKA_uNm.js.gz +0 -0
  599. codex/static_root/assets/filter-DgPg2ts9.af0fcf0888c6.js +0 -1
  600. codex/static_root/assets/filter-DgPg2ts9.af0fcf0888c6.js.br +0 -0
  601. codex/static_root/assets/filter-DgPg2ts9.af0fcf0888c6.js.gz +0 -0
  602. codex/static_root/assets/filter-DgPg2ts9.js +0 -1
  603. codex/static_root/assets/filter-DgPg2ts9.js.br +0 -0
  604. codex/static_root/assets/filter-DgPg2ts9.js.gz +0 -0
  605. codex/static_root/assets/flag-tab-9qxOALxP.f89bc9891671.js +0 -1
  606. codex/static_root/assets/flag-tab-9qxOALxP.f89bc9891671.js.br +0 -0
  607. codex/static_root/assets/flag-tab-9qxOALxP.f89bc9891671.js.gz +0 -0
  608. codex/static_root/assets/flag-tab-9qxOALxP.js +0 -1
  609. codex/static_root/assets/flag-tab-9qxOALxP.js.br +0 -0
  610. codex/static_root/assets/flag-tab-9qxOALxP.js.gz +0 -0
  611. codex/static_root/assets/flag-tab-BNwbLfrN.b755a99fff7e.css +0 -1
  612. codex/static_root/assets/flag-tab-BNwbLfrN.b755a99fff7e.css.br +0 -0
  613. codex/static_root/assets/flag-tab-BNwbLfrN.b755a99fff7e.css.gz +0 -0
  614. codex/static_root/assets/flag-tab-BNwbLfrN.css +0 -1
  615. codex/static_root/assets/flag-tab-BNwbLfrN.css.br +0 -0
  616. codex/static_root/assets/flag-tab-BNwbLfrN.css.gz +0 -0
  617. codex/static_root/assets/group-tab-D5vWrihT.1afb2ce453ff.js.br +0 -0
  618. codex/static_root/assets/group-tab-D5vWrihT.1afb2ce453ff.js.gz +0 -0
  619. codex/static_root/assets/group-tab-D5vWrihT.js.br +0 -0
  620. codex/static_root/assets/group-tab-D5vWrihT.js.gz +0 -0
  621. codex/static_root/assets/http-error-B4FHoKfs.141fdae409bc.js +0 -1
  622. codex/static_root/assets/http-error-B4FHoKfs.141fdae409bc.js.br +0 -0
  623. codex/static_root/assets/http-error-B4FHoKfs.141fdae409bc.js.gz +0 -0
  624. codex/static_root/assets/http-error-B4FHoKfs.js +0 -1
  625. codex/static_root/assets/http-error-B4FHoKfs.js.br +0 -0
  626. codex/static_root/assets/http-error-B4FHoKfs.js.gz +0 -0
  627. codex/static_root/assets/http-error-DKulXuTl.95e42988d5d5.css +0 -1
  628. codex/static_root/assets/http-error-DKulXuTl.95e42988d5d5.css.gz +0 -0
  629. codex/static_root/assets/http-error-DKulXuTl.css +0 -1
  630. codex/static_root/assets/http-error-DKulXuTl.css.gz +0 -0
  631. codex/static_root/assets/library-tab-BN0SfPcH.913e236f625e.css +0 -1
  632. codex/static_root/assets/library-tab-BN0SfPcH.913e236f625e.css.br +0 -0
  633. codex/static_root/assets/library-tab-BN0SfPcH.913e236f625e.css.gz +0 -0
  634. codex/static_root/assets/library-tab-BN0SfPcH.css +0 -1
  635. codex/static_root/assets/library-tab-BN0SfPcH.css.br +0 -0
  636. codex/static_root/assets/library-tab-BN0SfPcH.css.gz +0 -0
  637. codex/static_root/assets/library-tab-BWo0cmzk.0e3d67d0c41a.js +0 -1
  638. codex/static_root/assets/library-tab-BWo0cmzk.0e3d67d0c41a.js.br +0 -0
  639. codex/static_root/assets/library-tab-BWo0cmzk.0e3d67d0c41a.js.gz +0 -0
  640. codex/static_root/assets/library-tab-BWo0cmzk.js +0 -1
  641. codex/static_root/assets/library-tab-BWo0cmzk.js.br +0 -0
  642. codex/static_root/assets/library-tab-BWo0cmzk.js.gz +0 -0
  643. codex/static_root/assets/main-Ztp855PW.css.br +0 -0
  644. codex/static_root/assets/main-Ztp855PW.d46d718fac45.css.br +0 -0
  645. codex/static_root/assets/main-ipmlipkF.5e60e6e8e447.js +0 -32
  646. codex/static_root/assets/main-ipmlipkF.5e60e6e8e447.js.br +0 -0
  647. codex/static_root/assets/main-ipmlipkF.5e60e6e8e447.js.gz +0 -0
  648. codex/static_root/assets/main-ipmlipkF.js +0 -32
  649. codex/static_root/assets/main-ipmlipkF.js.br +0 -0
  650. codex/static_root/assets/main-ipmlipkF.js.gz +0 -0
  651. codex/static_root/assets/pagination-toolbar-BA9ifTed.b4865334ee08.css +0 -1
  652. codex/static_root/assets/pagination-toolbar-BA9ifTed.b4865334ee08.css.br +0 -0
  653. codex/static_root/assets/pagination-toolbar-BA9ifTed.b4865334ee08.css.gz +0 -0
  654. codex/static_root/assets/pagination-toolbar-BA9ifTed.css +0 -1
  655. codex/static_root/assets/pagination-toolbar-BA9ifTed.css.br +0 -0
  656. codex/static_root/assets/pagination-toolbar-BA9ifTed.css.gz +0 -0
  657. codex/static_root/assets/pagination-toolbar-kZ-Xdv8c.b3341b8028df.js +0 -1
  658. codex/static_root/assets/pagination-toolbar-kZ-Xdv8c.b3341b8028df.js.br +0 -0
  659. codex/static_root/assets/pagination-toolbar-kZ-Xdv8c.b3341b8028df.js.gz +0 -0
  660. codex/static_root/assets/pagination-toolbar-kZ-Xdv8c.js +0 -1
  661. codex/static_root/assets/pagination-toolbar-kZ-Xdv8c.js.br +0 -0
  662. codex/static_root/assets/pagination-toolbar-kZ-Xdv8c.js.gz +0 -0
  663. codex/static_root/assets/pdf-doc-C2StaYUz.cb848834dbe1.js +0 -305
  664. codex/static_root/assets/pdf-doc-C2StaYUz.cb848834dbe1.js.br +0 -0
  665. codex/static_root/assets/pdf-doc-C2StaYUz.cb848834dbe1.js.gz +0 -0
  666. codex/static_root/assets/pdf-doc-C2StaYUz.js +0 -305
  667. codex/static_root/assets/pdf-doc-C2StaYUz.js.br +0 -0
  668. codex/static_root/assets/pdf-doc-C2StaYUz.js.gz +0 -0
  669. codex/static_root/assets/reader-CCnq3j1-.b6b38ed5521e.js +0 -2
  670. codex/static_root/assets/reader-CCnq3j1-.b6b38ed5521e.js.br +0 -0
  671. codex/static_root/assets/reader-CCnq3j1-.b6b38ed5521e.js.gz +0 -0
  672. codex/static_root/assets/reader-CCnq3j1-.js +0 -2
  673. codex/static_root/assets/reader-CCnq3j1-.js.br +0 -0
  674. codex/static_root/assets/reader-CCnq3j1-.js.gz +0 -0
  675. codex/static_root/assets/reader-CqXFa_gE.78267e9de0c2.css +0 -1
  676. codex/static_root/assets/reader-CqXFa_gE.78267e9de0c2.css.br +0 -0
  677. codex/static_root/assets/reader-CqXFa_gE.78267e9de0c2.css.gz +0 -0
  678. codex/static_root/assets/reader-CqXFa_gE.css +0 -1
  679. codex/static_root/assets/reader-CqXFa_gE.css.br +0 -0
  680. codex/static_root/assets/reader-CqXFa_gE.css.gz +0 -0
  681. codex/static_root/assets/relation-chips-Bsc-gUxE.98e65384c3c9.css.br +0 -0
  682. codex/static_root/assets/relation-chips-Bsc-gUxE.98e65384c3c9.css.gz +0 -0
  683. codex/static_root/assets/relation-chips-Bsc-gUxE.css.br +0 -0
  684. codex/static_root/assets/relation-chips-Bsc-gUxE.css.gz +0 -0
  685. codex/static_root/assets/relation-chips-C9ysW0tU.670f1d1f273f.js +0 -1
  686. codex/static_root/assets/relation-chips-C9ysW0tU.670f1d1f273f.js.br +0 -0
  687. codex/static_root/assets/relation-chips-C9ysW0tU.670f1d1f273f.js.gz +0 -0
  688. codex/static_root/assets/relation-chips-C9ysW0tU.js +0 -1
  689. codex/static_root/assets/relation-chips-C9ysW0tU.js.br +0 -0
  690. codex/static_root/assets/relation-chips-C9ysW0tU.js.gz +0 -0
  691. codex/static_root/assets/settings-drawer-C0ofzAhW.c0def8f383cb.js +0 -2
  692. codex/static_root/assets/settings-drawer-C0ofzAhW.c0def8f383cb.js.br +0 -0
  693. codex/static_root/assets/settings-drawer-C0ofzAhW.c0def8f383cb.js.gz +0 -0
  694. codex/static_root/assets/settings-drawer-C0ofzAhW.js +0 -2
  695. codex/static_root/assets/settings-drawer-C0ofzAhW.js.br +0 -0
  696. codex/static_root/assets/settings-drawer-C0ofzAhW.js.gz +0 -0
  697. codex/static_root/assets/settings-drawer-nZ9HvKSZ.01744e131806.css +0 -1
  698. codex/static_root/assets/settings-drawer-nZ9HvKSZ.01744e131806.css.br +0 -0
  699. codex/static_root/assets/settings-drawer-nZ9HvKSZ.01744e131806.css.gz +0 -0
  700. codex/static_root/assets/settings-drawer-nZ9HvKSZ.css +0 -1
  701. codex/static_root/assets/settings-drawer-nZ9HvKSZ.css.br +0 -0
  702. codex/static_root/assets/settings-drawer-nZ9HvKSZ.css.gz +0 -0
  703. codex/static_root/assets/stats-tab-B4yKuY0c.a5728396494b.css +0 -1
  704. codex/static_root/assets/stats-tab-B4yKuY0c.a5728396494b.css.br +0 -0
  705. codex/static_root/assets/stats-tab-B4yKuY0c.a5728396494b.css.gz +0 -0
  706. codex/static_root/assets/stats-tab-B4yKuY0c.css +0 -1
  707. codex/static_root/assets/stats-tab-B4yKuY0c.css.br +0 -0
  708. codex/static_root/assets/stats-tab-B4yKuY0c.css.gz +0 -0
  709. codex/static_root/assets/stats-tab-BqJj7j1w.38a3459d61ea.js +0 -1
  710. codex/static_root/assets/stats-tab-BqJj7j1w.38a3459d61ea.js.br +0 -0
  711. codex/static_root/assets/stats-tab-BqJj7j1w.38a3459d61ea.js.gz +0 -0
  712. codex/static_root/assets/stats-tab-BqJj7j1w.js +0 -1
  713. codex/static_root/assets/stats-tab-BqJj7j1w.js.br +0 -0
  714. codex/static_root/assets/stats-tab-BqJj7j1w.js.gz +0 -0
  715. codex/static_root/assets/task-tab-BsPzNk8S.e00630a60b43.js +0 -1
  716. codex/static_root/assets/task-tab-BsPzNk8S.e00630a60b43.js.br +0 -0
  717. codex/static_root/assets/task-tab-BsPzNk8S.e00630a60b43.js.gz +0 -0
  718. codex/static_root/assets/task-tab-BsPzNk8S.js +0 -1
  719. codex/static_root/assets/task-tab-BsPzNk8S.js.br +0 -0
  720. codex/static_root/assets/task-tab-BsPzNk8S.js.gz +0 -0
  721. codex/static_root/assets/to-case-KvqtSug2.9c02da2e47c7.js +0 -1
  722. codex/static_root/assets/to-case-KvqtSug2.9c02da2e47c7.js.br +0 -0
  723. codex/static_root/assets/to-case-KvqtSug2.js +0 -1
  724. codex/static_root/assets/to-case-KvqtSug2.js.br +0 -0
  725. codex/static_root/assets/unauthorized-CibJYD8o.4c2de98c2b53.css.br +0 -0
  726. codex/static_root/assets/unauthorized-CibJYD8o.4c2de98c2b53.css.gz +0 -0
  727. codex/static_root/assets/unauthorized-CibJYD8o.css.br +0 -0
  728. codex/static_root/assets/unauthorized-CibJYD8o.css.gz +0 -0
  729. codex/static_root/assets/unauthorized-DwSdNzX2.f418e69f3afe.js +0 -1
  730. codex/static_root/assets/unauthorized-DwSdNzX2.f418e69f3afe.js.br +0 -0
  731. codex/static_root/assets/unauthorized-DwSdNzX2.f418e69f3afe.js.gz +0 -0
  732. codex/static_root/assets/unauthorized-DwSdNzX2.js +0 -1
  733. codex/static_root/assets/unauthorized-DwSdNzX2.js.br +0 -0
  734. codex/static_root/assets/unauthorized-DwSdNzX2.js.gz +0 -0
  735. codex/static_root/assets/user-tab-DrJOb9Ys.083d993726d8.js +0 -1
  736. codex/static_root/assets/user-tab-DrJOb9Ys.083d993726d8.js.br +0 -0
  737. codex/static_root/assets/user-tab-DrJOb9Ys.083d993726d8.js.gz +0 -0
  738. codex/static_root/assets/user-tab-DrJOb9Ys.js +0 -1
  739. codex/static_root/assets/user-tab-DrJOb9Ys.js.br +0 -0
  740. codex/static_root/assets/user-tab-DrJOb9Ys.js.gz +0 -0
  741. codex/static_root/js/choices-admin.3521e2a863df.json +0 -1
  742. codex/static_root/js/choices-admin.3521e2a863df.json.br +0 -0
  743. codex/static_root/js/choices-admin.3521e2a863df.json.gz +0 -0
  744. codex/static_root/js/choices.2f6b0359e1ef.json +0 -1
  745. codex/static_root/js/choices.2f6b0359e1ef.json.br +0 -0
  746. codex/static_root/js/choices.2f6b0359e1ef.json.gz +0 -0
  747. codex/static_root/manifest.1c84116d9a0a.json +0 -622
  748. codex/static_root/manifest.1c84116d9a0a.json.br +0 -0
  749. codex/static_root/manifest.1c84116d9a0a.json.gz +0 -0
  750. codex/util.py +0 -12
  751. codex/views/admin/auth.py +0 -28
  752. codex/views/browser/breadcrumbs.py +0 -202
  753. codex/views/browser/cover.py +0 -165
  754. codex/views/browser/mtime.py +0 -61
  755. codex/views/browser/order_by.py +0 -65
  756. codex/views/browser/paginate.py +0 -106
  757. codex/views/browser/settings.py +0 -66
  758. codex/views/browser/title.py +0 -48
  759. codex/views/browser/validate.py +0 -161
  760. codex/views/opds/auth.py +0 -17
  761. codex/views/public.py +0 -36
  762. codex/views/reader/arcs.py +0 -92
  763. codex/views/reader/books.py +0 -181
  764. codex/views/reader/init.py +0 -125
  765. codex/views/settings.py +0 -47
  766. codex/views/util.py +0 -77
  767. {codex-1.6.0.dist-info → codex-1.6.0a0.dist-info}/LICENSE +0 -0
  768. {codex-1.6.0.dist-info → codex-1.6.0a0.dist-info}/WHEEL +0 -0
  769. {codex-1.6.0.dist-info → codex-1.6.0a0.dist-info}/entry_points.txt +0 -0
codex/models/library.py CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  from datetime import timedelta
4
4
  from pathlib import Path
5
- from types import MappingProxyType
6
5
 
7
6
  from django.contrib.auth.models import Group
8
7
  from django.core.exceptions import ValidationError
@@ -33,14 +32,7 @@ class Library(BaseModel):
33
32
 
34
33
  DEFAULT_POLL_EVERY_SECONDS = 60 * 60
35
34
  DEFAULT_POLL_EVERY = timedelta(seconds=DEFAULT_POLL_EVERY_SECONDS)
36
- CUSTOM_COVERS_DIR_DEFAULTS = MappingProxyType(
37
- {
38
- "covers_only": True,
39
- "events": False,
40
- "poll": False,
41
- }
42
- )
43
- covers_only = BooleanField(db_index=True, default=False)
35
+
44
36
  path = CharField(
45
37
  unique=True,
46
38
  db_index=True,
@@ -54,9 +46,9 @@ class Library(BaseModel):
54
46
  update_in_progress = BooleanField(default=False)
55
47
  groups = ManyToManyField(Group, blank=True)
56
48
 
57
- def __str__(self) -> str:
49
+ def __str__(self):
58
50
  """Return the path."""
59
- return str(self.path)
51
+ return self.path
60
52
 
61
53
  class Meta(BaseModel.Meta):
62
54
  """Pluralize."""
codex/models/paths.py CHANGED
@@ -1,35 +1,32 @@
1
1
  """Watched Path models."""
2
2
 
3
3
  from pathlib import Path
4
- from types import MappingProxyType
5
4
 
6
5
  from django.db.models import CASCADE, CharField, ForeignKey, JSONField
7
- from django.db.models.enums import Choices
8
6
 
9
- from codex.models.base import MAX_NAME_LEN, BaseModel
7
+ from codex.models.base import MAX_NAME_LEN
8
+ from codex.models.groups import BrowserGroupModel
10
9
  from codex.models.library import MAX_PATH_LEN, Library
11
- from codex.models.util import get_sort_name
12
10
 
13
- __all__ = ("CustomCover", "FailedImport")
11
+ __all__ = ("WatchedPath", "Folder", "FailedImport")
14
12
 
15
13
 
16
- class WatchedPath(BaseModel):
14
+ class WatchedPath(BrowserGroupModel):
17
15
  """A filesystem path with data for Watchdog."""
18
16
 
19
17
  library = ForeignKey(Library, on_delete=CASCADE, db_index=True)
18
+ path = CharField(max_length=MAX_PATH_LEN, db_index=True)
19
+ stat = JSONField(null=True)
20
20
  parent_folder = ForeignKey(
21
21
  "Folder",
22
22
  on_delete=CASCADE,
23
23
  null=True,
24
24
  )
25
- path = CharField(max_length=MAX_PATH_LEN, db_index=True)
26
- stat = JSONField(null=True)
27
25
  ZERO_STAT = (0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0)
28
26
 
29
27
  def set_stat(self):
30
28
  """Set select stat params from the filesystem."""
31
- path = Path(str(self.path))
32
- st_record = path.stat()
29
+ st_record = Path(self.path).stat()
33
30
  # Converting os.stat directly to a list or tuple saves
34
31
  # mtime as an int and causes problems.
35
32
  st = list(self.ZERO_STAT)
@@ -46,28 +43,27 @@ class WatchedPath(BaseModel):
46
43
 
47
44
  def presave(self):
48
45
  """Save stat."""
46
+ super().presave()
49
47
  self.set_stat()
50
48
 
51
49
  def __str__(self):
52
50
  """Return the full path."""
53
- return str(self.path)
51
+ return self.path
54
52
 
55
- class Meta(BaseModel.Meta):
56
- """Use Mixin Meta."""
53
+ class Meta(BrowserGroupModel.Meta):
54
+ """Constraints."""
57
55
 
58
56
  unique_together = ("library", "path")
59
57
  abstract = True
60
58
 
61
- def search_path(self) -> str:
62
- """Relative path for search index."""
63
- return self.path.removeprefix(self.library.path)
59
+
60
+ class Folder(WatchedPath):
61
+ """File system folder."""
64
62
 
65
63
 
66
64
  class FailedImport(WatchedPath):
67
65
  """Failed Comic Imports. Displayed in Admin Panel."""
68
66
 
69
- name = CharField(db_index=True, max_length=MAX_NAME_LEN, default="")
70
-
71
67
  def set_reason(self, exc):
72
68
  """Can't do this in save() because it breaks update_or_create."""
73
69
  reason = str(exc)
@@ -76,46 +72,3 @@ class FailedImport(WatchedPath):
76
72
  reason = reason.removesuffix(suffix)
77
73
  reason = reason[:MAX_NAME_LEN]
78
74
  self.name = reason.strip()
79
-
80
-
81
- class CustomCover(WatchedPath):
82
- """Custom Cover Image."""
83
-
84
- class GroupChoice(Choices):
85
- """Reading direction choices."""
86
-
87
- P = "p"
88
- I = "i" # noqa: E741
89
- S = "s"
90
- A = "a"
91
- F = "f"
92
-
93
- FOLDER_COVER_STEM = ".codex-cover"
94
- DIR_GROUP_CHOICE_MAP = MappingProxyType(
95
- {
96
- "publishers": GroupChoice.P,
97
- "imprints": GroupChoice.I,
98
- "series": GroupChoice.S,
99
- "story-arcs": GroupChoice.A,
100
- }
101
- )
102
-
103
- parent_folder = None
104
- group = CharField(max_length=1, db_index=True, choices=GroupChoice.choices)
105
- sort_name = CharField(max_length=MAX_NAME_LEN, db_index=True, default="")
106
-
107
- def _set_group_and_sort_name(self):
108
- """Set group and sort_name from path."""
109
- path = Path(self.path)
110
- stem = path.stem
111
- if stem == self.FOLDER_COVER_STEM:
112
- self.group = self.GroupChoice.F.value
113
- else:
114
- choice = self.DIR_GROUP_CHOICE_MAP[path.parent.name]
115
- self.group = choice.value
116
- self.sort_name = get_sort_name(stem)
117
-
118
- def presave(self):
119
- """Presave group and sort_name."""
120
- super().presave()
121
- self._set_group_and_sort_name()
codex/permissions.py CHANGED
@@ -8,7 +8,7 @@ from codex.models import Timestamp
8
8
  class HasAPIKeyOrIsAdminUser(BasePermission):
9
9
  """Does the request have the current api key."""
10
10
 
11
- def has_permission(self, request, view): # type: ignore
11
+ def has_permission(self, request, view):
12
12
  """Test the request api key against the database."""
13
13
  data = request.GET if request.method == "GET" else request.POST
14
14
  api_key = data.get("apiKey")
@@ -3,6 +3,14 @@
3
3
  import warnings
4
4
  from datetime import date, datetime
5
5
 
6
+ from _vendor.haystack.backends import (
7
+ log_query,
8
+ )
9
+ from _vendor.haystack.constants import (
10
+ DJANGO_CT,
11
+ )
12
+ from _vendor.haystack.exceptions import SearchBackendError
13
+ from _vendor.haystack.utils import get_model_ct
6
14
  from django.conf import settings
7
15
  from django.utils.encoding import force_str
8
16
 
@@ -10,11 +18,6 @@ from django.utils.encoding import force_str
10
18
  from whoosh.sorting import Count, DateRangeFacet, FieldFacet
11
19
  from whoosh.support.relativedelta import relativedelta as RelativeDelta
12
20
 
13
- from codex._vendor.haystack.backends import log_query
14
- from codex._vendor.haystack.constants import DJANGO_CT
15
- from codex._vendor.haystack.exceptions import SearchBackendError
16
- from codex._vendor.haystack.utils import get_model_ct
17
-
18
21
 
19
22
  class CodexBackendSearchMixin:
20
23
  @log_query
codex/search/query.py CHANGED
@@ -3,7 +3,6 @@
3
3
  from codex._vendor.haystack.backends.whoosh_backend import (
4
4
  WhooshSearchQuery,
5
5
  )
6
- from codex._vendor.haystack.constants import DJANGO_ID
7
6
  from codex._vendor.haystack.query import SearchQuerySet
8
7
 
9
8
 
@@ -13,8 +12,7 @@ class CodexSearchQuery(WhooshSearchQuery):
13
12
  def __init__(self, *args, **kwargs):
14
13
  """Give CodexSearchQuery a reverse attribute."""
15
14
  super().__init__(*args, **kwargs)
16
- self._reverse: bool = False
17
- self._filter_comic_ids: frozenset | None = None
15
+ self._reverse = False
18
16
 
19
17
  def clean(self, query_fragment):
20
18
  """Optimize to noop because RESERVED_ consts are empty in the backend."""
@@ -24,23 +22,9 @@ class CodexSearchQuery(WhooshSearchQuery):
24
22
  """Invert the reverse attribute."""
25
23
  self._reverse = not self._reverse
26
24
 
27
- def filter_comic_ids(self, ids):
28
- """Set a filter for the query."""
29
- self._filter_comic_ids = frozenset(ids)
30
-
31
25
  def get_results(self, **kwargs):
32
26
  """Send custom get results the reverse flag."""
33
- custom_params = {}
34
- if self._reverse:
35
- custom_params["reverse"] = self._reverse
36
-
37
- if self._filter_comic_ids:
38
- filter_query = " OR ".join(
39
- [f"{DJANGO_ID}:{pk}" for pk in self._filter_comic_ids]
40
- )
41
- custom_params["narrow_queries"] = {filter_query}
42
-
43
- return super().get_results(**custom_params, **kwargs)
27
+ return super().get_results(reverse=self._reverse, **kwargs)
44
28
 
45
29
 
46
30
  class CodexSearchQuerySet(SearchQuerySet):
@@ -52,16 +36,9 @@ class CodexSearchQuerySet(SearchQuerySet):
52
36
  clone.query.order_reverse() # type: ignore
53
37
  return clone
54
38
 
55
- def filter_comic_ids(self, ids):
56
- """Filter search by comic ids."""
57
- clone = self._clone()
58
- clone.query.filter_comic_ids(ids) # type: ignore
59
- return clone
60
-
61
39
  def values_list(self, *args, **kwargs):
62
40
  """Copy reverse setting into CodexSearchQuery."""
63
41
  clone = super().values_list(*args, **kwargs)
64
42
  if clone.query and self.query:
65
43
  clone.query._reverse = self.query._reverse # noqa: SLF001
66
- clone.query._filter_comic_ids = self.query._filter_comic_ids # noqa: SLF001
67
44
  return clone
codex/search/writing.py CHANGED
@@ -16,7 +16,7 @@ class CodexWriter(BufferedWriter):
16
16
  """MP safe Buffered Writer that locks the index writer much more granularly.
17
17
 
18
18
  XXX The period and limit args are ignored and this writer behaves more like the
19
- AsycWriter. The AsyncWriter could possibly be extended to not lock until commit
19
+ AsycnWriter. The AsyncWriter could possibly be extended to not lock until commit
20
20
  time like this one and use less code.
21
21
  """
22
22
 
@@ -101,17 +101,8 @@ class LibrarySerializer(BaseModelSerializer):
101
101
  """Specify Model."""
102
102
 
103
103
  model = Library
104
- fields = (
105
- "pk",
106
- "path",
107
- "events",
108
- "last_poll",
109
- "poll",
110
- "poll_every",
111
- "groups",
112
- "covers_only",
113
- )
114
- read_only_fields = ("last_poll", "pk", "covers_only")
104
+ fields = ("pk", "events", "groups", "last_poll", "path", "poll", "poll_every")
105
+ read_only_fields = ("last_poll", "pk")
115
106
 
116
107
  def validate_path(self, path):
117
108
  """Validate new library paths."""
@@ -173,7 +164,8 @@ class AdminFolderSerializer(Serializer):
173
164
  def validate_show_hidden(self, show_hidden):
174
165
  """Snakecase the showHidden field."""
175
166
  return (
176
- show_hidden == "true" or self.initial_data.get("showHidden") == "true" # type: ignore
167
+ show_hidden == "true"
168
+ or self.initial_data.get("showHidden", False) == "true"
177
169
  )
178
170
 
179
171
 
@@ -181,68 +173,67 @@ class AdminGroupSerializer(Serializer):
181
173
  """Group Counts."""
182
174
 
183
175
  publishers_count = IntegerField(required=False, read_only=True)
184
- imprints_count = IntegerField(required=False, read_only=True)
185
- series_count = IntegerField(required=False, read_only=True)
186
- volumes_count = IntegerField(required=False, read_only=True)
187
- issues_count = IntegerField(required=False, read_only=True)
188
- folders_count = IntegerField(required=False, read_only=True)
189
- story_arcs_count = IntegerField(required=False, read_only=True)
176
+ imprints_count = IntegerField(required=False)
177
+ series_count = IntegerField(required=False)
178
+ volumes_count = IntegerField(required=False)
179
+ issues_count = IntegerField(required=False)
180
+ folders_count = IntegerField(required=False)
190
181
 
191
182
 
192
183
  class AdminFileTypeSerializer(Serializer):
193
184
  """File Type Counts."""
194
185
 
195
- pdf_count = IntegerField(required=False, read_only=True)
196
- cbz_count = IntegerField(required=False, read_only=True)
197
- cbr_count = IntegerField(required=False, read_only=True)
198
- cbt_count = IntegerField(required=False, read_only=True)
199
- unknown_count = IntegerField(required=False, read_only=True)
186
+ pdf_count = IntegerField(required=False)
187
+ cbz_count = IntegerField(required=False)
188
+ cbr_count = IntegerField(required=False)
189
+ cbt_count = IntegerField(required=False)
190
+ unknown_count = IntegerField(required=False)
200
191
 
201
192
 
202
193
  class AdminComicMetadataSerializer(Serializer):
203
194
  """Metadata Counts."""
204
195
 
205
- age_ratings_count = IntegerField(required=False, read_only=True)
206
- characters_count = IntegerField(required=False, read_only=True)
207
- contributors_count = IntegerField(required=False, read_only=True)
208
- contributor_persons_count = IntegerField(required=False, read_only=True)
209
- contributor_roles_count = IntegerField(required=False, read_only=True)
210
- countries_count = IntegerField(required=False, read_only=True)
211
- genres_count = IntegerField(required=False, read_only=True)
212
- identifiers_count = IntegerField(required=False, read_only=True)
213
- identifier_types_count = IntegerField(required=False, read_only=True)
214
- languages_count = IntegerField(required=False, read_only=True)
215
- locations_count = IntegerField(required=False, read_only=True)
216
- original_formats_count = IntegerField(required=False, read_only=True)
217
- series_groups_count = IntegerField(required=False, read_only=True)
218
- scan_infos_count = IntegerField(required=False, read_only=True)
196
+ age_ratings_count = IntegerField(required=False)
197
+ characters_count = IntegerField(required=False)
198
+ contributors_count = IntegerField(required=False)
199
+ contributor_persons_count = IntegerField(required=False)
200
+ contributor_roles_count = IntegerField(required=False)
201
+ countries_count = IntegerField(required=False)
202
+ genres_count = IntegerField(required=False)
203
+ identifiers_count = IntegerField(required=False)
204
+ identifier_types_count = IntegerField(required=False)
205
+ languages_count = IntegerField(required=False)
206
+ locations_count = IntegerField(required=False)
207
+ original_formats_count = IntegerField(required=False)
208
+ series_groups_count = IntegerField(required=False)
209
+ scan_infos_count = IntegerField(required=False)
219
210
  story_arcs_count = IntegerField(required=False)
220
- story_arc_numbers_count = IntegerField(required=False, read_only=True)
221
- tags_count = IntegerField(required=False, read_only=True)
222
- taggers_count = IntegerField(required=False, read_only=True)
223
- teams_count = IntegerField(required=False, read_only=True)
211
+ story_arc_numbers_count = IntegerField(required=False)
212
+ tags_count = IntegerField(required=False)
213
+ taggers_count = IntegerField(required=False)
214
+ teams_count = IntegerField(required=False)
224
215
 
225
216
 
226
217
  class AdminConfigSerializer(Serializer):
227
218
  """Config Information."""
228
219
 
229
- api_key = CharField(required=False, read_only=True)
230
- groups_count = IntegerField(required=False, read_only=True)
231
- libraries_count = IntegerField(required=False, read_only=True)
232
- sessions_anon_count = IntegerField(required=False, read_only=True)
233
- sessions_count = IntegerField(required=False, read_only=True)
234
- users_count = IntegerField(required=False, read_only=True)
220
+ api_key = CharField(required=False)
221
+ groups_count = IntegerField(required=False)
222
+ libraries_count = IntegerField(required=False)
223
+ sessions_anon_count = IntegerField(required=False)
224
+ sessions_count = IntegerField(required=False)
225
+ users_count = IntegerField(required=False)
235
226
 
236
227
 
237
228
  class AdminPlatformSerializer(Serializer):
238
229
  """Platform Information."""
239
230
 
240
- docker = BooleanField(read_only=True)
241
- machine = CharField(read_only=True)
242
- system = CharField(read_only=True)
243
- system_release = CharField(read_only=True)
244
- python = CharField(read_only=True)
245
- codex = CharField(read_only=True)
231
+ docker = BooleanField()
232
+ machine = CharField()
233
+ system = CharField()
234
+ system_release = CharField()
235
+ python = CharField()
236
+ codex = CharField()
246
237
 
247
238
 
248
239
  class AdminStatsSerializer(Serializer):
@@ -2,60 +2,65 @@
2
2
 
3
3
  from types import MappingProxyType
4
4
 
5
- from rest_framework.fields import SerializerMethodField
6
5
  from rest_framework.serializers import (
6
+ BooleanField,
7
7
  CharField,
8
+ ChoiceField,
9
+ FloatField,
10
+ IntegerField,
8
11
  Serializer,
9
12
  )
10
- from rest_framework.utils.serializer_helpers import ReturnList
11
13
 
12
- from codex.serializers.browser.filters import BrowserSettingsFilterSerializer
13
- from codex.serializers.fields import (
14
- VuetifyCharField,
15
- VuetifyIntegerField,
14
+ from codex.serializers.browser.filters import (
15
+ BooleanListField,
16
+ BrowserSettingsFilterSerializer,
17
+ CharListField,
18
+ DecadeListField,
19
+ FloatListField,
20
+ IntListField,
16
21
  )
17
- from codex.serializers.models.pycountry import CountrySerializer, LanguageSerializer
18
22
 
19
23
 
20
24
  class BrowserChoicesCharPkSerializer(Serializer):
21
- """Named Model Serializer."""
25
+ """Named Model Serailizer with pk = char hack for languages & countries."""
22
26
 
23
- pk = VuetifyCharField(read_only=True)
27
+ pk = CharField(read_only=True)
24
28
  name = CharField(read_only=True)
25
29
 
26
30
 
27
- class BrowserChoicesIntegerPkSerializer(BrowserChoicesCharPkSerializer):
31
+ class BrowserChoicesBoolPkSerializer(BrowserChoicesCharPkSerializer):
28
32
  """Named Model Serailizer with pk = char hack for languages & countries."""
29
33
 
30
- pk = VuetifyIntegerField(read_only=True)
34
+ pk = BooleanField(read_only=True)
35
+
36
+
37
+ class BrowserChoicesIntPkSerializer(BrowserChoicesCharPkSerializer):
38
+ """Named Model Serailizer with pk = char hack for languages & countries."""
31
39
 
40
+ pk = IntegerField(read_only=True)
41
+
42
+
43
+ class BrowserChoicesFloatPkSerializer(BrowserChoicesCharPkSerializer):
44
+ """Named Model Serailizer with pk = char hack for languages & countries."""
45
+
46
+ pk = FloatField(read_only=True)
47
+
48
+
49
+ _CHOICES_TYPE_SERIALIZER_MAP = MappingProxyType(
50
+ {
51
+ BooleanListField: BrowserChoicesBoolPkSerializer,
52
+ CharListField: BrowserChoicesCharPkSerializer,
53
+ ChoiceField: BrowserChoicesCharPkSerializer,
54
+ DecadeListField: BrowserChoicesIntPkSerializer,
55
+ FloatListField: BrowserChoicesFloatPkSerializer,
56
+ IntListField: BrowserChoicesIntPkSerializer,
57
+ }
58
+ )
32
59
 
33
- _CHOICES_NAME_SERIALIZER_MAP = MappingProxyType(
60
+ _BSFS = BrowserSettingsFilterSerializer
61
+ CHOICES_SERIALIZER_CLASS_MAP = MappingProxyType(
34
62
  {
35
- "bookmark": BrowserChoicesCharPkSerializer,
36
- "country": CountrySerializer,
37
- "language": LanguageSerializer,
63
+ name: _CHOICES_TYPE_SERIALIZER_MAP[field.__class__]
64
+ for name, field in _BSFS().fields.items() # type: ignore
38
65
  }
39
66
  )
40
- _LIST_FIELDS = frozenset({"decade", "monochrome", "reading_direction", "year"})
41
-
42
-
43
- class BrowserChoicesFilterSerializer(Serializer):
44
- """Dynamic Serializer response by field type."""
45
-
46
- choices = SerializerMethodField(read_only=True)
47
-
48
- def get_choices(self, obj) -> ReturnList:
49
- """Dynamic Serializer response by field type."""
50
- field_name = obj.get("field_name", "")
51
- choices = obj.get("choices", [])
52
- serializer_class = _CHOICES_NAME_SERIALIZER_MAP.get(field_name)
53
- value: ReturnList
54
- if serializer_class:
55
- value = serializer_class(choices, many=True).data # type: ignore
56
- elif not serializer_class and field_name in _LIST_FIELDS:
57
- field = BrowserSettingsFilterSerializer().get_fields().get(field_name) # type: ignore
58
- value = field.to_representation(choices)
59
- else:
60
- value = BrowserChoicesIntegerPkSerializer(choices, many=True).data # type: ignore
61
- return value