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
@@ -1,6 +1,5 @@
1
1
  """Query the missing foreign keys for comics and contributors."""
2
2
 
3
- from itertools import chain
4
3
  from logging import DEBUG, INFO
5
4
  from pathlib import Path
6
5
  from types import MappingProxyType
@@ -14,16 +13,6 @@ from codex.librarian.importer.const import (
14
13
  DICT_MODEL_CLASS_FIELDS_MAP,
15
14
  DICT_MODEL_FIELD_MODEL_MAP,
16
15
  DICT_MODEL_REL_MAP,
17
- FK_CREATE,
18
- FKC_CONTRIBUTORS,
19
- FKC_CREATE_FKS,
20
- FKC_CREATE_GROUPS,
21
- FKC_FOLDER_PATHS,
22
- FKC_IDENTIFIERS,
23
- FKC_STORY_ARC_NUMBERS,
24
- FKC_TOTAL_FKS,
25
- FKC_UPDATE_GROUPS,
26
- FKS,
27
16
  GROUP_COMPARE_FIELDS,
28
17
  GROUP_TREES,
29
18
  IDENTIFIERS_FIELD_NAME,
@@ -33,8 +22,7 @@ from codex.librarian.importer.const import (
33
22
  SERIES,
34
23
  STORY_ARCS_METADATA_KEY,
35
24
  )
36
- from codex.librarian.importer.query_covers import QueryCustomCoversImporter
37
- from codex.librarian.importer.status import ImportStatusTypes
25
+ from codex.librarian.importer.status import ImportStatusTypes, status_notify
38
26
  from codex.logger.logging import get_logger
39
27
  from codex.models import (
40
28
  Comic,
@@ -49,7 +37,10 @@ from codex.models import (
49
37
  from codex.models.named import Identifier
50
38
  from codex.settings.settings import FILTER_BATCH_SIZE
51
39
  from codex.status import Status
40
+ from codex.threads import QueuedThread
52
41
 
42
+ _CREATE_GROUPS = "create_groups"
43
+ _UPDATE_GROUPS = "update_groups"
53
44
  _CLASS_QUERY_FIELDS_MAP = MappingProxyType(
54
45
  {
55
46
  Contributor: ("role__name", "person__name"),
@@ -65,23 +56,18 @@ _DEFAULT_QUERY_FIELDS = ("name",)
65
56
  _EXTRA_UPDATE_FIELDS_MAP = MappingProxyType(
66
57
  {Series: ("volume_count",), Volume: ("issue_count",)}
67
58
  )
68
- _DICT_MODEL_KEY_MAP = MappingProxyType(
69
- {
70
- CONTRIBUTORS_FIELD_NAME: FKC_CONTRIBUTORS,
71
- STORY_ARCS_METADATA_KEY: FKC_STORY_ARC_NUMBERS,
72
- IDENTIFIERS_FIELD_NAME: FKC_IDENTIFIERS,
73
- }
74
- )
59
+
75
60
  LOG = get_logger(__name__)
76
61
 
77
62
 
78
- class QueryForeignKeysImporter(QueryCustomCoversImporter):
63
+ class QueryForeignKeysMixin(QueuedThread):
79
64
  """Methods for querying what fks are missing."""
80
65
 
81
- def _get_query_fks_totals(self):
66
+ @staticmethod
67
+ def _get_query_fks_totals(fks):
82
68
  """Get the query foreign keys totals."""
83
69
  fks_total = 0
84
- for key, objs in self.metadata[FKS].items():
70
+ for key, objs in fks.items():
85
71
  if key == GROUP_TREES:
86
72
  for groups in objs.values():
87
73
  fks_total += len(groups)
@@ -106,11 +92,11 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
106
92
  update_mds,
107
93
  q_obj: Q,
108
94
  status,
109
- and_q_obj: Q | None = None,
110
95
  ):
111
96
  """Get create metadata by comparing proposed meatada to existing rows."""
112
- vnp = fk_cls._meta.verbose_name_plural.title()
113
- status.subtitle = vnp
97
+ if status:
98
+ vnp = fk_cls._meta.verbose_name_plural.title()
99
+ status.subtitle = vnp
114
100
  offset = 0
115
101
  num_qs = len(q_obj.children)
116
102
  while offset < num_qs:
@@ -118,8 +104,6 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
118
104
  # django.db.utils.OperationalError: Expression tree is too large (maximum depth 1000)
119
105
  children_chunk = q_obj.children[offset : offset + FILTER_BATCH_SIZE]
120
106
  filter_chunk = Q(*children_chunk, _connector=Q.OR)
121
- if and_q_obj:
122
- filter_chunk = and_q_obj & filter_chunk
123
107
 
124
108
  existing_mds = self._query_existing_mds(fk_cls, filter_chunk)
125
109
  create_mds.difference_update(existing_mds)
@@ -131,12 +115,13 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
131
115
  )
132
116
  update_mds.difference_update(match_with_extra_fields_mds)
133
117
 
134
- status.add_complete(len(filter_chunk))
118
+ status.complete += len(filter_chunk)
135
119
  self.status_controller.update(status)
136
120
 
137
121
  offset += FILTER_BATCH_SIZE
138
122
 
139
- status.subtitle = ""
123
+ if status:
124
+ status.subtitle = ""
140
125
 
141
126
  return num_qs
142
127
 
@@ -185,11 +170,11 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
185
170
  update_group_set.update(update_groups)
186
171
  return count
187
172
 
173
+ @classmethod
188
174
  def _update_action_group(
189
- self, group_cls, action_groups_key, group_tree, count_value: int | None
175
+ cls, group_cls, action_groups, group_tree, count_value: int | None
190
176
  ):
191
177
  """Update the create or update group dict with the count dict."""
192
- action_groups = self.metadata[FK_CREATE][action_groups_key]
193
178
  if group_cls not in action_groups:
194
179
  action_groups[group_cls] = {}
195
180
  if group_tree not in action_groups[group_cls]:
@@ -202,12 +187,13 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
202
187
  create_group_set,
203
188
  update_group_set,
204
189
  group_cls,
190
+ create_and_update_groups,
205
191
  status,
206
192
  ) = data
207
193
  if group_tree in create_group_set:
208
194
  self._update_action_group(
209
195
  group_cls,
210
- FKC_CREATE_GROUPS,
196
+ create_and_update_groups[_CREATE_GROUPS],
211
197
  group_tree,
212
198
  count_value,
213
199
  )
@@ -215,11 +201,14 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
215
201
  # This always updates Volume or Series
216
202
  self._update_action_group(
217
203
  group_cls,
218
- FKC_UPDATE_GROUPS,
204
+ create_and_update_groups[_UPDATE_GROUPS],
219
205
  group_tree,
220
206
  count_value,
221
207
  )
222
- status.add_complete(1)
208
+ if status:
209
+ status.complete = status.complete or 0
210
+ status.complete += 1
211
+ self.status_controller.update(status)
223
212
 
224
213
  @staticmethod
225
214
  def _prune_group_updates_get_filter(group_cls, update_group_trees):
@@ -290,19 +279,22 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
290
279
  prune_count = len(update_group_trees) - len(pruned_update_group_trees)
291
280
  self.log.debug(f"Pruned {prune_count} {vnp} from updates.")
292
281
 
282
+ @status_notify()
293
283
  def _query_missing_group(
294
284
  self,
295
285
  groups,
296
286
  group_cls,
297
- status,
287
+ create_and_update_groups,
288
+ status=None,
298
289
  ):
299
290
  """Get missing groups from proposed groups to create."""
300
291
  count = 0
301
292
  if not groups:
302
293
  return count
303
294
 
304
- vnp = group_cls._meta.verbose_name_plural.title()
305
- status.subtitle = vnp
295
+ if status:
296
+ vnp = group_cls._meta.verbose_name_plural.title()
297
+ status.subtitle = vnp
306
298
 
307
299
  create_group_set = set()
308
300
  update_group_set = set()
@@ -314,23 +306,24 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
314
306
  create_group_set,
315
307
  update_group_set,
316
308
  group_cls,
309
+ create_and_update_groups,
317
310
  status,
318
311
  )
319
312
  for group_tree, count_value in groups.items():
320
313
  self._query_group_tree(data, group_tree, count_value)
321
- self.status_controller.update(status)
322
314
 
323
315
  # after counts have been tallied, prune the ones that don't need an update.
324
- update_groups = self.metadata[FK_CREATE][FKC_UPDATE_GROUPS]
316
+ update_groups = create_and_update_groups.get(_UPDATE_GROUPS)
325
317
  self._prune_group_updates(group_cls, update_groups)
326
318
 
327
- status.subtitle = ""
319
+ if status:
320
+ status.subtitle = ""
328
321
 
329
322
  create_count = len(
330
- self.metadata[FK_CREATE][FKC_CREATE_GROUPS].get(group_cls, {})
323
+ create_and_update_groups.get(_CREATE_GROUPS, {}).get(group_cls, {})
331
324
  )
332
325
  update_count = len(
333
- self.metadata[FK_CREATE][FKC_UPDATE_GROUPS].get(group_cls, {})
326
+ create_and_update_groups.get(_UPDATE_GROUPS, {}).get(group_cls, {})
334
327
  )
335
328
  count = create_count + update_count
336
329
  if count:
@@ -419,16 +412,16 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
419
412
  ):
420
413
  """Restore urls to only the identifier create objs."""
421
414
  if field_name != "identifiers":
422
- return possible_create_objs
415
+ return
423
416
  restored_create_objs = []
424
417
  for create_obj in possible_create_objs:
425
418
  url = url_restore_map.get(create_obj)
426
419
  restored_create_objs.append((*create_obj, url))
427
- return restored_create_objs
420
+ possible_create_objs = restored_create_objs
428
421
 
429
- def _query_missing_dict_model(self, field_name, create_objs_key, status):
422
+ def _query_missing_dict_model(self, field_name, fks, create_objs, status):
430
423
  """Find missing dict type m2m models."""
431
- possible_objs = self.metadata[FKS].pop(field_name, None)
424
+ possible_objs = fks.pop(field_name, None)
432
425
  if not possible_objs:
433
426
  return 0
434
427
 
@@ -448,51 +441,38 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
448
441
  )
449
442
 
450
443
  # Build combined query object from the value_filter
451
- model = DICT_MODEL_FIELD_MODEL_MAP[field_name]
452
- if model == Identifier:
453
- for filter_and_prefix, value_filter in query_filter_map.items():
454
- self._query_create_metadata(
455
- model,
456
- possible_create_objs,
457
- None,
458
- value_filter,
459
- status,
460
- and_q_obj=filter_and_prefix,
461
- )
462
- else:
463
- combined_q_obj = Q()
464
- for filter_and_prefix, value_filter in query_filter_map.items():
465
- combined_q_obj |= filter_and_prefix & value_filter
466
- self._query_create_metadata(
467
- model,
468
- possible_create_objs,
469
- None,
470
- combined_q_obj,
471
- status,
472
- )
444
+ combined_q_obj = Q()
445
+ for filter_and_prefix, value_filter in query_filter_map.items():
446
+ combined_q_obj |= filter_and_prefix & value_filter
473
447
 
474
448
  # Finally run the query and get only the correct create_objs
475
- possible_create_objs = self._query_missing_dict_model_identifiers_restore_urls(
449
+ model = DICT_MODEL_FIELD_MODEL_MAP[field_name]
450
+ self._query_create_metadata(
451
+ model, possible_create_objs, None, combined_q_obj, status
452
+ )
453
+ self._query_missing_dict_model_identifiers_restore_urls(
476
454
  field_name, possible_create_objs, url_restore_map
477
455
  )
478
456
 
479
457
  # Final Cleanup
480
- self.metadata[FK_CREATE][create_objs_key].update(possible_create_objs)
481
- count = len(self.metadata[FK_CREATE][create_objs_key])
458
+ create_objs.update(possible_create_objs)
459
+ count = len(create_objs)
482
460
  if count:
483
461
  model = DICT_MODEL_FIELD_MODEL_MAP[field_name]
484
462
  vnp = model._meta.verbose_name_plural
485
463
  vnp = vnp.title() if vnp else "Nothings"
486
464
  self.log.info(f"Prepared {count} new {vnp}.")
487
- status.add_complete(count)
488
- self.status_controller.update(status, notify=False)
465
+ if status:
466
+ status.complete = status.complete or 0
467
+ status.complete += count
489
468
  return count
490
469
 
491
470
  ##########
492
471
  # SIMPLE #
493
472
  ##########
494
473
 
495
- def _query_missing_simple_models(self, names, fk_data, status):
474
+ @status_notify()
475
+ def _query_missing_simple_models(self, names, fk_data, status=None):
496
476
  """Find missing named models and folders."""
497
477
  # count = 0
498
478
  if not names:
@@ -506,8 +486,9 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
506
486
  create_names = set(names)
507
487
  num_proposed_names = len(proposed_names)
508
488
 
509
- vnp = fk_cls._meta.verbose_name_plural.title()
510
- status.subtitle = vnp
489
+ if status:
490
+ vnp = fk_cls._meta.verbose_name_plural.title()
491
+ status.subtitle = vnp
511
492
  while start < num_proposed_names:
512
493
  # Do this in batches so as not to exceed the 1k line sqlite limit
513
494
  end = start + FILTER_BATCH_SIZE
@@ -516,8 +497,11 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
516
497
  fk_filter = Q(**filter_args)
517
498
  create_names -= self._query_existing_mds(fk_cls, fk_filter)
518
499
  num_in_batch = len(batch_proposed_names)
519
- status.add_complete(num_in_batch)
520
- self.status_controller.update(status)
500
+ # count += num_in_batch
501
+ if status:
502
+ status.complete = status.complete or 0
503
+ status.complete += num_in_batch
504
+ self.status_controller.update(status)
521
505
  start += FILTER_BATCH_SIZE
522
506
 
523
507
  if status:
@@ -534,7 +518,7 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
534
518
  self.log.log(level, f"Prepared {len(create_names)} new {vnp}.")
535
519
  return len(names)
536
520
 
537
- def _query_one_simple_model(self, fk_field, status):
521
+ def _query_one_simple_model(self, fk_field, fks, create_fks, status):
538
522
  """Batch query one simple model name."""
539
523
  for cls, names in DICT_MODEL_CLASS_FIELDS_MAP.items():
540
524
  if fk_field in names:
@@ -542,24 +526,25 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
542
526
  break
543
527
  else:
544
528
  base_cls = Comic
545
- fk_data = self.metadata[FK_CREATE][FKC_CREATE_FKS], base_cls, fk_field, "name"
546
- names = self.metadata[FKS].pop(fk_field)
547
- status.add_complete(
548
- self._query_missing_simple_models(
549
- names,
550
- fk_data,
551
- status,
552
- )
529
+ fk_data = create_fks, base_cls, fk_field, "name"
530
+ names = fks.pop(fk_field)
531
+ status.complete += self._query_missing_simple_models(
532
+ names,
533
+ fk_data,
534
+ status=status,
553
535
  )
554
- self.status_controller.update(status, notify=False)
555
536
 
556
537
  ###########
557
538
  # FOLDERS #
558
539
  ###########
559
- def query_missing_folder_paths(self, comic_paths, status):
540
+
541
+ @status_notify()
542
+ def query_missing_folder_paths(
543
+ self, comic_paths, library_path, create_folder_paths, status=None
544
+ ):
560
545
  """Find missing folder paths."""
561
546
  # Get the proposed folder_paths
562
- library_path = Path(self.library.path)
547
+ library_path = Path(library_path)
563
548
  proposed_folder_paths = set()
564
549
  for comic_path in comic_paths:
565
550
  for path in Path(comic_path).parents:
@@ -572,79 +557,74 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
572
557
  self._query_missing_simple_models(
573
558
  proposed_folder_paths,
574
559
  fk_data,
575
- status,
560
+ status=status,
576
561
  )
577
- create_folder_paths = create_folder_paths_dict.get(Folder, set())
578
- if FK_CREATE not in self.metadata:
579
- self.metadata[FK_CREATE] = {}
580
- if FKC_FOLDER_PATHS not in self.metadata[FK_CREATE]:
581
- self.metadata[FK_CREATE][FKC_FOLDER_PATHS] = set()
582
- self.metadata[FK_CREATE][FKC_FOLDER_PATHS] |= create_folder_paths
562
+ folder_paths_set = create_folder_paths_dict.get(Folder, set())
563
+ create_folder_paths |= folder_paths_set
583
564
  count = len(create_folder_paths)
584
565
  if count:
585
566
  self.log.info(f"Prepared {count} new Folders.")
586
567
  return count
587
568
 
588
- def _get_create_fks_totals(self):
589
- fkc = self.metadata[FK_CREATE]
590
- total_fks = 0
591
- for data_group in chain(
592
- fkc[FKC_CREATE_GROUPS].values(),
593
- fkc[FKC_UPDATE_GROUPS].values(),
594
- fkc[FKC_CREATE_FKS].values(),
595
- ):
596
- total_fks += len(data_group)
597
- total_fks += (
598
- len(fkc[FKC_FOLDER_PATHS])
599
- + len(fkc[FKC_CONTRIBUTORS])
600
- + len(fkc[FKC_STORY_ARC_NUMBERS])
601
- + len(fkc[FKC_IDENTIFIERS])
602
- )
603
- return total_fks
604
-
605
- def query_all_missing_fks(self):
569
+ def query_all_missing_fks(self, library_path, fks):
606
570
  """Get objects to create by querying existing objects for the proposed fks."""
607
- if FKS not in self.metadata:
608
- return
609
- self.metadata[FK_CREATE] = {
610
- FKC_CONTRIBUTORS: set(),
611
- FKC_STORY_ARC_NUMBERS: set(),
612
- FKC_IDENTIFIERS: set(),
613
- FKC_CREATE_GROUPS: {},
614
- FKC_UPDATE_GROUPS: {},
615
- FKC_FOLDER_PATHS: set(),
616
- FKC_CREATE_FKS: {},
617
- }
618
- self.log.debug(
619
- f"Querying existing foreign keys for comics in {self.library.path}"
571
+ create_contributors = set()
572
+ create_story_arc_numbers = set()
573
+ create_identifiers = set()
574
+ create_groups = {}
575
+ update_groups = {}
576
+ create_folder_paths = set()
577
+ create_fks = {}
578
+ self.log.debug(f"Querying existing foreign keys for comics in {library_path}")
579
+ fks_total = self._get_query_fks_totals(fks)
580
+ dict_model_map = MappingProxyType(
581
+ {
582
+ CONTRIBUTORS_FIELD_NAME: create_contributors,
583
+ STORY_ARCS_METADATA_KEY: create_story_arc_numbers,
584
+ IDENTIFIERS_FIELD_NAME: create_identifiers,
585
+ }
620
586
  )
621
- status = Status(ImportStatusTypes.QUERY_MISSING_FKS)
587
+ status = Status(ImportStatusTypes.QUERY_MISSING_FKS, 0, fks_total)
622
588
  try:
623
589
  self.status_controller.start(status)
624
- for field_name, create_objs_key in _DICT_MODEL_KEY_MAP.items():
590
+ for field_name, create_objs in dict_model_map.items():
625
591
  self._query_missing_dict_model(
626
592
  field_name,
627
- create_objs_key,
593
+ fks,
594
+ create_objs,
628
595
  status,
629
596
  )
630
- for group_class, groups in self.metadata[FKS].pop(GROUP_TREES, {}).items():
597
+
598
+ create_and_update_groups = {
599
+ _CREATE_GROUPS: create_groups,
600
+ _UPDATE_GROUPS: update_groups,
601
+ }
602
+ for group_class, groups in fks.pop(GROUP_TREES, {}).items():
631
603
  self._query_missing_group(
632
604
  groups,
633
605
  group_class,
634
- status,
606
+ create_and_update_groups,
607
+ status=status,
635
608
  )
636
609
 
637
610
  self.query_missing_folder_paths(
638
- self.metadata[FKS].pop(COMIC_PATHS, ()), status
611
+ fks.pop(COMIC_PATHS, ()),
612
+ library_path,
613
+ create_folder_paths,
614
+ status=status,
639
615
  )
640
616
 
641
- for fk_field in sorted(self.metadata[FKS].keys()):
642
- self._query_one_simple_model(fk_field, status)
643
- self.metadata.pop(FKS)
617
+ for fk_field in sorted(fks.keys()):
618
+ self._query_one_simple_model(fk_field, fks, create_fks, status)
644
619
  finally:
645
620
  self.status_controller.finish(status)
646
621
 
647
- total_fks = self._get_create_fks_totals()
648
- status = Status(ImportStatusTypes.CREATE_FKS, 0, total_fks)
649
- self.status_controller.update(status, notify=False)
650
- self.metadata[FK_CREATE][FKC_TOTAL_FKS] = total_fks
622
+ return (
623
+ create_groups,
624
+ update_groups,
625
+ create_folder_paths,
626
+ create_fks,
627
+ create_contributors,
628
+ create_story_arc_numbers,
629
+ create_identifiers,
630
+ )
@@ -1,7 +1,13 @@
1
1
  """Librarian Status for imports."""
2
2
 
3
+ from collections.abc import Callable
4
+ from enum import Enum
5
+ from time import time
6
+
3
7
  from django.db.models import Choices
4
8
 
9
+ from codex.status import Status
10
+
5
11
 
6
12
  class ImportStatusTypes(Choices):
7
13
  """Keys for Import tasks."""
@@ -19,11 +25,36 @@ class ImportStatusTypes(Choices):
19
25
  DIRS_DELETED = "IDD"
20
26
  FILES_DELETED = "IFD"
21
27
  FAILED_IMPORTS = "IFI"
22
- QUERY_MISSING_COVERS = "ICQ"
23
- COVERS_MOVED = "ICM"
24
- COVERS_MODIFIED = "ICU"
25
- COVERS_CREATED = "ICC"
26
- COVERS_DELETED = "ICD"
27
- COVERS_LINK = "ICL"
28
- GROUP_UPDATE = "IGU"
29
- ADOPT_FOLDERS = "IAF"
28
+
29
+
30
+ def status_notify(status_type: str | Enum = "", updates=True):
31
+ """Wrap a function with status changes."""
32
+ # https://stackoverflow.com/questions/5929107/decorators-with-parameters
33
+
34
+ def decorator(func) -> Callable[..., int]:
35
+ def wrapper(self, data, *args, status=None, **kwargs) -> int:
36
+ """Run a function bracketed by status changes."""
37
+ num_elements = len(data)
38
+ if not num_elements:
39
+ return 0
40
+
41
+ if status:
42
+ finish = False
43
+ else:
44
+ complete = 0 if updates else None
45
+ status = Status(status_type, complete, num_elements, time())
46
+ self.status_controller.start(status)
47
+ finish = True
48
+
49
+ kwargs["status"] = status
50
+ try:
51
+ count = func(self, data, *args, **kwargs)
52
+ finally:
53
+ if finish:
54
+ self.status_controller.finish(status)
55
+
56
+ return count
57
+
58
+ return wrapper
59
+
60
+ return decorator
@@ -1,8 +1,6 @@
1
1
  """DB Import Tasks."""
2
2
 
3
- from collections.abc import Mapping
4
- from dataclasses import dataclass, field
5
- from datetime import datetime
3
+ from dataclasses import dataclass
6
4
 
7
5
 
8
6
  @dataclass
@@ -15,22 +13,14 @@ class ImportDBDiffTask(ImportTask):
15
13
  """For sending to the updater."""
16
14
 
17
15
  library_id: int
18
-
19
- dirs_moved: Mapping[str, str] = field(default_factory=dict)
20
- dirs_modified: frozenset[str] = frozenset()
21
- # dirs_created: frozenset[str] | None = frozenset()
22
- dirs_deleted: frozenset[str] = frozenset()
23
-
24
- files_moved: Mapping[str, str] = field(default_factory=dict)
25
- files_modified: frozenset[str] = frozenset()
26
- files_created: frozenset[str] = frozenset()
27
- files_deleted: frozenset[str] = frozenset()
28
-
29
- covers_moved: Mapping[str, str] = field(default_factory=dict)
30
- covers_modified: frozenset[str] = frozenset()
31
- covers_created: frozenset[str] = frozenset()
32
- covers_deleted: frozenset[str] = frozenset()
33
-
16
+ dirs_moved: dict[str, str]
17
+ files_moved: dict[str, str]
18
+ dirs_modified: frozenset[str]
19
+ files_modified: frozenset[str]
20
+ # dirs_created
21
+ files_created: frozenset[str]
22
+ dirs_deleted: frozenset[str]
23
+ files_deleted: frozenset[str]
34
24
  force_import_metadata: bool = False
35
25
 
36
26
 
@@ -44,10 +34,3 @@ class LazyImportComicsTask(ImportTask):
44
34
  @dataclass
45
35
  class AdoptOrphanFoldersTask(ImportTask):
46
36
  """Move orphaned folders into a correct tree position."""
47
-
48
-
49
- @dataclass
50
- class UpdateGroupsTask(ImportTask):
51
- """Force the update of group timestamp."""
52
-
53
- start_time: datetime | None = None