codex 1.5.19__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 (800) hide show
  1. codex/exceptions.py +14 -5
  2. codex/librarian/covers/create.py +2 -1
  3. codex/librarian/covers/path.py +1 -2
  4. codex/librarian/importer/const.py +34 -13
  5. codex/librarian/importer/create_comics.py +0 -1
  6. codex/librarian/importer/create_fks.py +35 -21
  7. codex/librarian/importer/failed_imports.py +2 -2
  8. codex/librarian/importer/moved.py +12 -10
  9. codex/librarian/importer/query_fks.py +124 -78
  10. codex/librarian/importer/update_comics.py +0 -1
  11. codex/librarian/janitor/cleanup.py +35 -14
  12. codex/migrations/0027_sort_name.py +149 -0
  13. codex/models/admin.py +1 -0
  14. codex/models/base.py +3 -0
  15. codex/models/comic.py +32 -35
  16. codex/models/const.py +18 -0
  17. codex/models/functions.py +12 -0
  18. codex/models/groups.py +40 -8
  19. codex/models/paths.py +5 -4
  20. codex/models/query.py +91 -0
  21. codex/search/backend.py +2 -2
  22. codex/search/backend_search.py +232 -0
  23. codex/search/engine.py +1 -9
  24. codex/search/query.py +44 -0
  25. codex/serializers/admin.py +3 -1
  26. codex/serializers/browser/filters.py +3 -8
  27. codex/serializers/{metadata.py → browser/metadata.py} +1 -1
  28. codex/serializers/browser/mixins.py +32 -0
  29. codex/serializers/browser/page.py +6 -18
  30. codex/serializers/browser/settings.py +1 -0
  31. codex/serializers/choices.py +22 -12
  32. codex/serializers/mixins.py +0 -22
  33. codex/serializers/opds/urls.py +10 -0
  34. codex/serializers/reader.py +7 -13
  35. codex/serializers/route.py +36 -0
  36. codex/settings/settings.py +57 -25
  37. codex/signals/django_signals.py +6 -0
  38. codex/static_root/assets/{VCheckbox-D7WF5wMC.c98c1beb207e.js → VCheckbox-Aq_ImMNC.da711f8b6a15.js} +1 -1
  39. codex/static_root/assets/VCheckbox-Aq_ImMNC.da711f8b6a15.js.br +0 -0
  40. codex/static_root/assets/VCheckbox-Aq_ImMNC.da711f8b6a15.js.gz +0 -0
  41. codex/static_root/assets/{VCheckbox-D7WF5wMC.js → VCheckbox-Aq_ImMNC.js} +1 -1
  42. codex/static_root/assets/VCheckbox-Aq_ImMNC.js.br +0 -0
  43. codex/static_root/assets/VCheckbox-Aq_ImMNC.js.gz +0 -0
  44. codex/static_root/assets/{VCheckboxBtn-CzTNt4cV.39d03f0eaf4b.js → VCheckboxBtn-D3izCBa7.54f4d7f48bbf.js} +1 -1
  45. codex/static_root/assets/VCheckboxBtn-D3izCBa7.54f4d7f48bbf.js.br +0 -0
  46. codex/static_root/assets/VCheckboxBtn-D3izCBa7.54f4d7f48bbf.js.gz +0 -0
  47. codex/static_root/assets/{VCheckboxBtn-CzTNt4cV.js → VCheckboxBtn-D3izCBa7.js} +1 -1
  48. codex/static_root/assets/VCheckboxBtn-D3izCBa7.js.br +0 -0
  49. codex/static_root/assets/VCheckboxBtn-D3izCBa7.js.gz +0 -0
  50. codex/static_root/assets/VCombobox-DLL1EsSN.55622a0cd4ab.js +1 -0
  51. codex/static_root/assets/VCombobox-DLL1EsSN.55622a0cd4ab.js.br +0 -0
  52. codex/static_root/assets/VCombobox-DLL1EsSN.55622a0cd4ab.js.gz +0 -0
  53. codex/static_root/assets/VCombobox-DLL1EsSN.js +1 -0
  54. codex/static_root/assets/VCombobox-DLL1EsSN.js.br +0 -0
  55. codex/static_root/assets/VCombobox-DLL1EsSN.js.gz +0 -0
  56. codex/static_root/assets/VDialog-C5Nxd_zP.css +1 -0
  57. codex/static_root/assets/VDialog-C5Nxd_zP.css.br +0 -0
  58. codex/static_root/assets/VDialog-C5Nxd_zP.css.gz +0 -0
  59. codex/static_root/assets/VDialog-C5Nxd_zP.d327f505ef0e.css +1 -0
  60. codex/static_root/assets/VDialog-C5Nxd_zP.d327f505ef0e.css.br +0 -0
  61. codex/static_root/assets/VDialog-C5Nxd_zP.d327f505ef0e.css.gz +0 -0
  62. codex/static_root/assets/VDialog-yDKzaGEj.e8dba78ac8db.js +1 -0
  63. codex/static_root/assets/VDialog-yDKzaGEj.e8dba78ac8db.js.br +0 -0
  64. codex/static_root/assets/VDialog-yDKzaGEj.e8dba78ac8db.js.gz +0 -0
  65. codex/static_root/assets/VDialog-yDKzaGEj.js +1 -0
  66. codex/static_root/assets/VDialog-yDKzaGEj.js.br +0 -0
  67. codex/static_root/assets/VDialog-yDKzaGEj.js.gz +0 -0
  68. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.d733b7906e00.js +1 -0
  69. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.d733b7906e00.js.br +0 -0
  70. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.d733b7906e00.js.gz +0 -0
  71. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.js +1 -0
  72. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.js.br +0 -0
  73. codex/static_root/assets/VExpansionPanels-Cpo8QLLq.js.gz +0 -0
  74. codex/static_root/assets/{VRadioGroup-DGplihzh.3f4a5d26a1cb.js → VRadioGroup-DEezv8bL.4a609e74e507.js} +1 -1
  75. codex/static_root/assets/VRadioGroup-DEezv8bL.4a609e74e507.js.br +0 -0
  76. codex/static_root/assets/VRadioGroup-DEezv8bL.4a609e74e507.js.gz +0 -0
  77. codex/static_root/assets/{VRadioGroup-DGplihzh.js → VRadioGroup-DEezv8bL.js} +1 -1
  78. codex/static_root/assets/VRadioGroup-DEezv8bL.js.br +0 -0
  79. codex/static_root/assets/VRadioGroup-DEezv8bL.js.gz +0 -0
  80. codex/static_root/assets/VSelect-ARDhJiQK.372c098fb475.css +1 -0
  81. codex/static_root/assets/VSelect-ARDhJiQK.372c098fb475.css.br +0 -0
  82. codex/static_root/assets/VSelect-ARDhJiQK.372c098fb475.css.gz +0 -0
  83. codex/static_root/assets/VSelect-ARDhJiQK.css +1 -0
  84. codex/static_root/assets/VSelect-ARDhJiQK.css.br +0 -0
  85. codex/static_root/assets/VSelect-ARDhJiQK.css.gz +0 -0
  86. codex/static_root/assets/VSelect-BKXcujPy.8871035f5634.js +1 -0
  87. codex/static_root/assets/VSelect-BKXcujPy.8871035f5634.js.br +0 -0
  88. codex/static_root/assets/VSelect-BKXcujPy.8871035f5634.js.gz +0 -0
  89. codex/static_root/assets/VSelect-BKXcujPy.js +1 -0
  90. codex/static_root/assets/VSelect-BKXcujPy.js.br +0 -0
  91. codex/static_root/assets/VSelect-BKXcujPy.js.gz +0 -0
  92. codex/static_root/assets/{VSelectionControl-DvHEDoJy.30ca0aef8bd2.js → VSelectionControl-DJAPiluk.402a7ad84a8e.js} +1 -1
  93. codex/static_root/assets/VSelectionControl-DJAPiluk.402a7ad84a8e.js.br +0 -0
  94. codex/static_root/assets/VSelectionControl-DJAPiluk.402a7ad84a8e.js.gz +0 -0
  95. codex/static_root/assets/{VSelectionControl-DvHEDoJy.js → VSelectionControl-DJAPiluk.js} +1 -1
  96. codex/static_root/assets/VSelectionControl-DJAPiluk.js.br +0 -0
  97. codex/static_root/assets/VSelectionControl-DJAPiluk.js.gz +0 -0
  98. codex/static_root/assets/VSlideGroup-C-kO93Va.8c9e31362dc5.js +1 -0
  99. codex/static_root/assets/VSlideGroup-C-kO93Va.8c9e31362dc5.js.br +0 -0
  100. codex/static_root/assets/VSlideGroup-C-kO93Va.8c9e31362dc5.js.gz +0 -0
  101. codex/static_root/assets/VSlideGroup-C-kO93Va.js +1 -0
  102. codex/static_root/assets/VSlideGroup-C-kO93Va.js.br +0 -0
  103. codex/static_root/assets/VSlideGroup-C-kO93Va.js.gz +0 -0
  104. codex/static_root/assets/VSlideGroup-Dk_1upHt.2c836070ec75.css +1 -0
  105. codex/static_root/assets/VSlideGroup-Dk_1upHt.2c836070ec75.css.br +0 -0
  106. codex/static_root/assets/VSlideGroup-Dk_1upHt.2c836070ec75.css.gz +0 -0
  107. codex/static_root/assets/VSlideGroup-Dk_1upHt.css +1 -0
  108. codex/static_root/assets/VSlideGroup-Dk_1upHt.css.br +0 -0
  109. codex/static_root/assets/VSlideGroup-Dk_1upHt.css.gz +0 -0
  110. codex/static_root/assets/{VTable-TEvK4Tmn.c68c176d93db.js → VTable-9vsIQObs.0a135029e924.js} +1 -1
  111. codex/static_root/assets/VTable-9vsIQObs.0a135029e924.js.br +0 -0
  112. codex/static_root/assets/VTable-9vsIQObs.0a135029e924.js.gz +0 -0
  113. codex/static_root/assets/{VTable-TEvK4Tmn.js → VTable-9vsIQObs.js} +1 -1
  114. codex/static_root/assets/VTable-9vsIQObs.js.br +0 -0
  115. codex/static_root/assets/VTable-9vsIQObs.js.gz +0 -0
  116. codex/static_root/assets/VTextField-DI9HAmWh.0de01739bbf9.js +1 -0
  117. codex/static_root/assets/VTextField-DI9HAmWh.0de01739bbf9.js.br +0 -0
  118. codex/static_root/assets/VTextField-DI9HAmWh.0de01739bbf9.js.gz +0 -0
  119. codex/static_root/assets/VTextField-DI9HAmWh.js +1 -0
  120. codex/static_root/assets/VTextField-DI9HAmWh.js.br +0 -0
  121. codex/static_root/assets/VTextField-DI9HAmWh.js.gz +0 -0
  122. codex/static_root/assets/{VSlideGroup-CTW-HJl4.css → VTextField-DuIIp-VY.580110ad24dc.css} +1 -1
  123. codex/static_root/assets/VTextField-DuIIp-VY.580110ad24dc.css.br +0 -0
  124. codex/static_root/assets/VTextField-DuIIp-VY.580110ad24dc.css.gz +0 -0
  125. codex/static_root/assets/{VSlideGroup-CTW-HJl4.8b75b66602c9.css → VTextField-DuIIp-VY.css} +1 -1
  126. codex/static_root/assets/VTextField-DuIIp-VY.css.br +0 -0
  127. codex/static_root/assets/VTextField-DuIIp-VY.css.gz +0 -0
  128. codex/static_root/assets/VWindowItem-DpnYkF3y.017d99c27b7b.js +1 -0
  129. codex/static_root/assets/VWindowItem-DpnYkF3y.017d99c27b7b.js.br +0 -0
  130. codex/static_root/assets/VWindowItem-DpnYkF3y.017d99c27b7b.js.gz +0 -0
  131. codex/static_root/assets/VWindowItem-DpnYkF3y.js +1 -0
  132. codex/static_root/assets/VWindowItem-DpnYkF3y.js.br +0 -0
  133. codex/static_root/assets/VWindowItem-DpnYkF3y.js.gz +0 -0
  134. codex/static_root/assets/admin-2BTkfSQA.e7ef29cb106d.js +1 -0
  135. codex/static_root/assets/admin-2BTkfSQA.e7ef29cb106d.js.br +0 -0
  136. codex/static_root/assets/admin-2BTkfSQA.e7ef29cb106d.js.gz +0 -0
  137. codex/static_root/assets/admin-2BTkfSQA.js +1 -0
  138. codex/static_root/assets/admin-2BTkfSQA.js.br +0 -0
  139. codex/static_root/assets/admin-2BTkfSQA.js.gz +0 -0
  140. codex/static_root/assets/admin-BbrOU9Y9.29936748af9e.css +1 -0
  141. codex/static_root/assets/admin-BbrOU9Y9.29936748af9e.css.br +0 -0
  142. codex/static_root/assets/admin-BbrOU9Y9.29936748af9e.css.gz +0 -0
  143. codex/static_root/assets/admin-BbrOU9Y9.css +1 -0
  144. codex/static_root/assets/admin-BbrOU9Y9.css.br +0 -0
  145. codex/static_root/assets/admin-BbrOU9Y9.css.gz +0 -0
  146. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.1514926c78e8.css +1 -0
  147. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.1514926c78e8.css.br +0 -0
  148. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.1514926c78e8.css.gz +0 -0
  149. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.css +1 -0
  150. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.css.br +0 -0
  151. codex/static_root/assets/admin-drawer-panel-BF0dMvEE.css.gz +0 -0
  152. codex/static_root/assets/admin-drawer-panel-mtdde7vY.c172dbae9463.js +30 -0
  153. codex/static_root/assets/admin-drawer-panel-mtdde7vY.c172dbae9463.js.br +0 -0
  154. codex/static_root/assets/admin-drawer-panel-mtdde7vY.c172dbae9463.js.gz +0 -0
  155. codex/static_root/assets/admin-drawer-panel-mtdde7vY.js +30 -0
  156. codex/static_root/assets/admin-drawer-panel-mtdde7vY.js.br +0 -0
  157. codex/static_root/assets/admin-drawer-panel-mtdde7vY.js.gz +0 -0
  158. codex/static_root/assets/browser-BA-AwUn-.23bb4b2f6a29.js +1 -0
  159. codex/static_root/assets/browser-BA-AwUn-.23bb4b2f6a29.js.br +0 -0
  160. codex/static_root/assets/browser-BA-AwUn-.23bb4b2f6a29.js.gz +0 -0
  161. codex/static_root/assets/browser-BA-AwUn-.js +1 -0
  162. codex/static_root/assets/browser-BA-AwUn-.js.br +0 -0
  163. codex/static_root/assets/browser-BA-AwUn-.js.gz +0 -0
  164. codex/static_root/assets/browser-CZeVqRNy.ccfca9a05bfe.css +1 -0
  165. codex/static_root/assets/browser-CZeVqRNy.ccfca9a05bfe.css.br +0 -0
  166. codex/static_root/assets/browser-CZeVqRNy.ccfca9a05bfe.css.gz +0 -0
  167. codex/static_root/assets/browser-CZeVqRNy.css +1 -0
  168. codex/static_root/assets/browser-CZeVqRNy.css.br +0 -0
  169. codex/static_root/assets/browser-CZeVqRNy.css.gz +0 -0
  170. codex/static_root/assets/change-password-dialog-C8YONrId.49aa6df6a91d.js +1 -0
  171. codex/static_root/assets/change-password-dialog-C8YONrId.49aa6df6a91d.js.br +0 -0
  172. codex/static_root/assets/change-password-dialog-C8YONrId.49aa6df6a91d.js.gz +0 -0
  173. codex/static_root/assets/change-password-dialog-C8YONrId.js +1 -0
  174. codex/static_root/assets/change-password-dialog-C8YONrId.js.br +0 -0
  175. codex/static_root/assets/change-password-dialog-C8YONrId.js.gz +0 -0
  176. codex/static_root/assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css +1 -0
  177. codex/static_root/assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css.br +0 -0
  178. codex/static_root/assets/change-password-dialog-HvIvmmIE.73be0c8a8278.css.gz +0 -0
  179. codex/static_root/assets/change-password-dialog-HvIvmmIE.css +1 -0
  180. codex/static_root/assets/change-password-dialog-HvIvmmIE.css.br +0 -0
  181. codex/static_root/assets/change-password-dialog-HvIvmmIE.css.gz +0 -0
  182. codex/static_root/assets/confirm-dialog-Clg-o2G-.e11d8efef3fb.js +1 -0
  183. codex/static_root/assets/confirm-dialog-Clg-o2G-.e11d8efef3fb.js.br +0 -0
  184. codex/static_root/assets/confirm-dialog-Clg-o2G-.e11d8efef3fb.js.gz +0 -0
  185. codex/static_root/assets/confirm-dialog-Clg-o2G-.js +1 -0
  186. codex/static_root/assets/confirm-dialog-Clg-o2G-.js.br +0 -0
  187. codex/static_root/assets/confirm-dialog-Clg-o2G-.js.gz +0 -0
  188. codex/static_root/assets/{datetime-column-C3t430gN.97e5c5364aef.js → datetime-column-DejrPZxl.9fd36bef6fdd.js} +1 -1
  189. codex/static_root/assets/datetime-column-DejrPZxl.9fd36bef6fdd.js.br +0 -0
  190. codex/static_root/assets/datetime-column-DejrPZxl.9fd36bef6fdd.js.gz +0 -0
  191. codex/static_root/assets/{datetime-column-C3t430gN.js → datetime-column-DejrPZxl.js} +1 -1
  192. codex/static_root/assets/datetime-column-DejrPZxl.js.br +0 -0
  193. codex/static_root/assets/datetime-column-DejrPZxl.js.gz +0 -0
  194. codex/static_root/assets/datetime-column-Dg_RxTVM.1fa7c5cbead7.css +1 -0
  195. codex/static_root/assets/datetime-column-Dg_RxTVM.1fa7c5cbead7.css.br +0 -0
  196. codex/static_root/assets/datetime-column-Dg_RxTVM.css +1 -0
  197. codex/static_root/assets/datetime-column-Dg_RxTVM.css.br +0 -0
  198. codex/static_root/assets/{filter-BQ_FuhIp.ee8b78c4aa55.js → filter-DHo57nTp.4d79a276d806.js} +1 -1
  199. codex/static_root/assets/filter-DHo57nTp.4d79a276d806.js.br +0 -0
  200. codex/static_root/assets/filter-DHo57nTp.4d79a276d806.js.gz +0 -0
  201. codex/static_root/assets/{filter-BQ_FuhIp.js → filter-DHo57nTp.js} +1 -1
  202. codex/static_root/assets/filter-DHo57nTp.js.br +0 -0
  203. codex/static_root/assets/filter-DHo57nTp.js.gz +0 -0
  204. codex/static_root/assets/flag-tab-BacZLlVi.8deba6a5370d.css +1 -0
  205. codex/static_root/assets/flag-tab-BacZLlVi.8deba6a5370d.css.br +0 -0
  206. codex/static_root/assets/flag-tab-BacZLlVi.8deba6a5370d.css.gz +0 -0
  207. codex/static_root/assets/flag-tab-BacZLlVi.css +1 -0
  208. codex/static_root/assets/flag-tab-BacZLlVi.css.br +0 -0
  209. codex/static_root/assets/flag-tab-BacZLlVi.css.gz +0 -0
  210. codex/static_root/assets/flag-tab-CagMLGSE.125739911c45.js +1 -0
  211. codex/static_root/assets/flag-tab-CagMLGSE.125739911c45.js.br +0 -0
  212. codex/static_root/assets/flag-tab-CagMLGSE.125739911c45.js.gz +0 -0
  213. codex/static_root/assets/flag-tab-CagMLGSE.js +1 -0
  214. codex/static_root/assets/flag-tab-CagMLGSE.js.br +0 -0
  215. codex/static_root/assets/flag-tab-CagMLGSE.js.gz +0 -0
  216. codex/static_root/assets/group-tab-BTAjhv32.ac196780d0a9.js +1 -0
  217. codex/static_root/assets/group-tab-BTAjhv32.ac196780d0a9.js.br +0 -0
  218. codex/static_root/assets/group-tab-BTAjhv32.ac196780d0a9.js.gz +0 -0
  219. codex/static_root/assets/group-tab-BTAjhv32.js +1 -0
  220. codex/static_root/assets/group-tab-BTAjhv32.js.br +0 -0
  221. codex/static_root/assets/group-tab-BTAjhv32.js.gz +0 -0
  222. codex/static_root/assets/group-tab-CBKuS3Iv.7e4746634782.css +1 -0
  223. codex/static_root/assets/group-tab-CBKuS3Iv.7e4746634782.css.br +0 -0
  224. codex/static_root/assets/group-tab-CBKuS3Iv.7e4746634782.css.gz +0 -0
  225. codex/static_root/assets/group-tab-CBKuS3Iv.css +1 -0
  226. codex/static_root/assets/group-tab-CBKuS3Iv.css.br +0 -0
  227. codex/static_root/assets/group-tab-CBKuS3Iv.css.gz +0 -0
  228. codex/static_root/assets/http-error-DaHEsKbT.55d56ce2b9b4.js +1 -0
  229. codex/static_root/assets/http-error-DaHEsKbT.55d56ce2b9b4.js.br +0 -0
  230. codex/static_root/assets/http-error-DaHEsKbT.55d56ce2b9b4.js.gz +0 -0
  231. codex/static_root/assets/http-error-DaHEsKbT.js +1 -0
  232. codex/static_root/assets/http-error-DaHEsKbT.js.br +0 -0
  233. codex/static_root/assets/http-error-DaHEsKbT.js.gz +0 -0
  234. codex/static_root/assets/http-error-_wlDqEcp.5b78d3e332c9.css +1 -0
  235. codex/static_root/assets/http-error-_wlDqEcp.5b78d3e332c9.css.br +0 -0
  236. codex/static_root/assets/http-error-_wlDqEcp.5b78d3e332c9.css.gz +0 -0
  237. codex/static_root/assets/http-error-_wlDqEcp.css +1 -0
  238. codex/static_root/assets/http-error-_wlDqEcp.css.br +0 -0
  239. codex/static_root/assets/http-error-_wlDqEcp.css.gz +0 -0
  240. codex/static_root/assets/library-tab-CXbkxNZt.954f2850a439.css +1 -0
  241. codex/static_root/assets/library-tab-CXbkxNZt.954f2850a439.css.br +2 -0
  242. codex/static_root/assets/library-tab-CXbkxNZt.954f2850a439.css.gz +0 -0
  243. codex/static_root/assets/library-tab-CXbkxNZt.css +1 -0
  244. codex/static_root/assets/library-tab-CXbkxNZt.css.br +2 -0
  245. codex/static_root/assets/library-tab-CXbkxNZt.css.gz +0 -0
  246. codex/static_root/assets/library-tab-Cud4639b.7f5a50aaabe8.js +1 -0
  247. codex/static_root/assets/library-tab-Cud4639b.7f5a50aaabe8.js.br +0 -0
  248. codex/static_root/assets/library-tab-Cud4639b.7f5a50aaabe8.js.gz +0 -0
  249. codex/static_root/assets/library-tab-Cud4639b.js +1 -0
  250. codex/static_root/assets/library-tab-Cud4639b.js.br +0 -0
  251. codex/static_root/assets/library-tab-Cud4639b.js.gz +0 -0
  252. codex/static_root/assets/main-BnzL_Byv.22f98ee91990.js +32 -0
  253. codex/static_root/assets/main-BnzL_Byv.22f98ee91990.js.br +0 -0
  254. codex/static_root/assets/main-BnzL_Byv.22f98ee91990.js.gz +0 -0
  255. codex/static_root/assets/main-BnzL_Byv.js +32 -0
  256. codex/static_root/assets/main-BnzL_Byv.js.br +0 -0
  257. codex/static_root/assets/main-BnzL_Byv.js.gz +0 -0
  258. codex/static_root/assets/{main-ED57DJUb.b84231dc384d.css → main-sK7HC5h4.6f04ddfc5f1a.css} +1 -1
  259. codex/static_root/assets/main-sK7HC5h4.6f04ddfc5f1a.css.br +0 -0
  260. codex/static_root/assets/{main-ED57DJUb.b84231dc384d.css.gz → main-sK7HC5h4.6f04ddfc5f1a.css.gz} +0 -0
  261. codex/static_root/assets/{main-ED57DJUb.css → main-sK7HC5h4.css} +1 -1
  262. codex/static_root/assets/main-sK7HC5h4.css.br +0 -0
  263. codex/static_root/assets/{main-ED57DJUb.css.gz → main-sK7HC5h4.css.gz} +0 -0
  264. codex/static_root/assets/pagination-toolbar-B3wS4_7p.7695fafdefce.css +1 -0
  265. codex/static_root/assets/pagination-toolbar-B3wS4_7p.7695fafdefce.css.br +0 -0
  266. codex/static_root/assets/pagination-toolbar-B3wS4_7p.7695fafdefce.css.gz +0 -0
  267. codex/static_root/assets/pagination-toolbar-B3wS4_7p.css +1 -0
  268. codex/static_root/assets/pagination-toolbar-B3wS4_7p.css.br +0 -0
  269. codex/static_root/assets/pagination-toolbar-B3wS4_7p.css.gz +0 -0
  270. codex/static_root/assets/pagination-toolbar-Covpd-k8.b71277bd7a2d.js +1 -0
  271. codex/static_root/assets/pagination-toolbar-Covpd-k8.b71277bd7a2d.js.br +0 -0
  272. codex/static_root/assets/pagination-toolbar-Covpd-k8.b71277bd7a2d.js.gz +0 -0
  273. codex/static_root/assets/pagination-toolbar-Covpd-k8.js +1 -0
  274. codex/static_root/assets/pagination-toolbar-Covpd-k8.js.br +0 -0
  275. codex/static_root/assets/pagination-toolbar-Covpd-k8.js.gz +0 -0
  276. codex/static_root/assets/{pdf-doc-x5fJF5N8.67b5456d222e.js → pdf-doc-CD2lnB32.1cef3bf498be.js} +1 -1
  277. codex/static_root/assets/pdf-doc-CD2lnB32.1cef3bf498be.js.br +0 -0
  278. codex/static_root/assets/pdf-doc-CD2lnB32.1cef3bf498be.js.gz +0 -0
  279. codex/static_root/assets/{pdf-doc-x5fJF5N8.js → pdf-doc-CD2lnB32.js} +1 -1
  280. codex/static_root/assets/pdf-doc-CD2lnB32.js.br +0 -0
  281. codex/static_root/assets/pdf-doc-CD2lnB32.js.gz +0 -0
  282. codex/static_root/assets/reader-Dspy46e8.925a6b05bfcf.css +1 -0
  283. codex/static_root/assets/reader-Dspy46e8.925a6b05bfcf.css.br +0 -0
  284. codex/static_root/assets/reader-Dspy46e8.925a6b05bfcf.css.gz +0 -0
  285. codex/static_root/assets/reader-Dspy46e8.css +1 -0
  286. codex/static_root/assets/reader-Dspy46e8.css.br +0 -0
  287. codex/static_root/assets/reader-Dspy46e8.css.gz +0 -0
  288. codex/static_root/assets/reader-L85y7IXD.6de58f450421.js +2 -0
  289. codex/static_root/assets/reader-L85y7IXD.6de58f450421.js.br +0 -0
  290. codex/static_root/assets/reader-L85y7IXD.6de58f450421.js.gz +0 -0
  291. codex/static_root/assets/reader-L85y7IXD.js +2 -0
  292. codex/static_root/assets/reader-L85y7IXD.js.br +0 -0
  293. codex/static_root/assets/reader-L85y7IXD.js.gz +0 -0
  294. codex/static_root/assets/relation-chips-BpuqEeqM.1372d8a3e6cf.js +1 -0
  295. codex/static_root/assets/relation-chips-BpuqEeqM.1372d8a3e6cf.js.br +0 -0
  296. codex/static_root/assets/relation-chips-BpuqEeqM.1372d8a3e6cf.js.gz +0 -0
  297. codex/static_root/assets/relation-chips-BpuqEeqM.js +1 -0
  298. codex/static_root/assets/relation-chips-BpuqEeqM.js.br +0 -0
  299. codex/static_root/assets/relation-chips-BpuqEeqM.js.gz +0 -0
  300. codex/static_root/assets/relation-chips-D6T6FX7G.css +1 -0
  301. codex/static_root/assets/relation-chips-D6T6FX7G.css.br +0 -0
  302. codex/static_root/assets/relation-chips-D6T6FX7G.css.gz +0 -0
  303. codex/static_root/assets/relation-chips-D6T6FX7G.db095b2497e4.css +1 -0
  304. codex/static_root/assets/relation-chips-D6T6FX7G.db095b2497e4.css.br +0 -0
  305. codex/static_root/assets/relation-chips-D6T6FX7G.db095b2497e4.css.gz +0 -0
  306. codex/static_root/assets/settings-drawer-BgUazs7O.7bbeb1fd98f1.css +1 -0
  307. codex/static_root/assets/settings-drawer-BgUazs7O.7bbeb1fd98f1.css.br +0 -0
  308. codex/static_root/assets/settings-drawer-BgUazs7O.7bbeb1fd98f1.css.gz +0 -0
  309. codex/static_root/assets/settings-drawer-BgUazs7O.css +1 -0
  310. codex/static_root/assets/settings-drawer-BgUazs7O.css.br +0 -0
  311. codex/static_root/assets/settings-drawer-BgUazs7O.css.gz +0 -0
  312. codex/static_root/assets/settings-drawer-CLMcxfVd.b9619341ad48.js +2 -0
  313. codex/static_root/assets/settings-drawer-CLMcxfVd.b9619341ad48.js.br +0 -0
  314. codex/static_root/assets/settings-drawer-CLMcxfVd.b9619341ad48.js.gz +0 -0
  315. codex/static_root/assets/settings-drawer-CLMcxfVd.js +2 -0
  316. codex/static_root/assets/settings-drawer-CLMcxfVd.js.br +0 -0
  317. codex/static_root/assets/settings-drawer-CLMcxfVd.js.gz +0 -0
  318. codex/static_root/assets/stats-tab-CQa3-W05.3d7c61418528.js +1 -0
  319. codex/static_root/assets/stats-tab-CQa3-W05.3d7c61418528.js.br +0 -0
  320. codex/static_root/assets/stats-tab-CQa3-W05.3d7c61418528.js.gz +0 -0
  321. codex/static_root/assets/stats-tab-CQa3-W05.js +1 -0
  322. codex/static_root/assets/stats-tab-CQa3-W05.js.br +0 -0
  323. codex/static_root/assets/stats-tab-CQa3-W05.js.gz +0 -0
  324. codex/static_root/assets/stats-tab-TsyG3wH_.b93c080356fc.css +1 -0
  325. codex/static_root/assets/stats-tab-TsyG3wH_.b93c080356fc.css.br +2 -0
  326. codex/static_root/assets/stats-tab-TsyG3wH_.b93c080356fc.css.gz +0 -0
  327. codex/static_root/assets/stats-tab-TsyG3wH_.css +1 -0
  328. codex/static_root/assets/stats-tab-TsyG3wH_.css.br +2 -0
  329. codex/static_root/assets/stats-tab-TsyG3wH_.css.gz +0 -0
  330. codex/static_root/assets/task-tab-1XiWn9xP.06cb8e1b794d.css +1 -0
  331. codex/static_root/assets/{task-tab-DoX9OA37.9bb355f36dbf.css.br → task-tab-1XiWn9xP.06cb8e1b794d.css.br} +1 -1
  332. codex/static_root/assets/task-tab-1XiWn9xP.06cb8e1b794d.css.gz +0 -0
  333. codex/static_root/assets/task-tab-1XiWn9xP.css +1 -0
  334. codex/static_root/assets/{task-tab-DoX9OA37.css.br → task-tab-1XiWn9xP.css.br} +1 -1
  335. codex/static_root/assets/task-tab-1XiWn9xP.css.gz +0 -0
  336. codex/static_root/assets/task-tab-OPhBm-O2.8f31f4215114.js +1 -0
  337. codex/static_root/assets/task-tab-OPhBm-O2.8f31f4215114.js.br +0 -0
  338. codex/static_root/assets/task-tab-OPhBm-O2.8f31f4215114.js.gz +0 -0
  339. codex/static_root/assets/task-tab-OPhBm-O2.js +1 -0
  340. codex/static_root/assets/task-tab-OPhBm-O2.js.br +0 -0
  341. codex/static_root/assets/task-tab-OPhBm-O2.js.gz +0 -0
  342. codex/static_root/assets/unauthorized-ClQNhRb5.32a8a84d1781.js +1 -0
  343. codex/static_root/assets/unauthorized-ClQNhRb5.32a8a84d1781.js.br +0 -0
  344. codex/static_root/assets/unauthorized-ClQNhRb5.32a8a84d1781.js.gz +0 -0
  345. codex/static_root/assets/unauthorized-ClQNhRb5.js +1 -0
  346. codex/static_root/assets/unauthorized-ClQNhRb5.js.br +0 -0
  347. codex/static_root/assets/unauthorized-ClQNhRb5.js.gz +0 -0
  348. codex/static_root/assets/unauthorized-DWgytUow.ca2f13dbdbf5.css +1 -0
  349. codex/static_root/assets/unauthorized-DWgytUow.ca2f13dbdbf5.css.br +0 -0
  350. codex/static_root/assets/unauthorized-DWgytUow.ca2f13dbdbf5.css.gz +0 -0
  351. codex/static_root/assets/unauthorized-DWgytUow.css +1 -0
  352. codex/static_root/assets/unauthorized-DWgytUow.css.br +0 -0
  353. codex/static_root/assets/unauthorized-DWgytUow.css.gz +0 -0
  354. codex/static_root/assets/user-tab-BKkxa2WL.50d83951c09f.js +1 -0
  355. codex/static_root/assets/user-tab-BKkxa2WL.50d83951c09f.js.br +0 -0
  356. codex/static_root/assets/user-tab-BKkxa2WL.50d83951c09f.js.gz +0 -0
  357. codex/static_root/assets/user-tab-BKkxa2WL.js +1 -0
  358. codex/static_root/assets/user-tab-BKkxa2WL.js.br +0 -0
  359. codex/static_root/assets/user-tab-BKkxa2WL.js.gz +0 -0
  360. codex/static_root/img/folder.f28936a3701d.svg +1 -0
  361. codex/static_root/img/folder.f28936a3701d.svg.br +0 -0
  362. codex/static_root/img/folder.f28936a3701d.svg.gz +0 -0
  363. codex/static_root/img/folder.svg +1 -0
  364. codex/static_root/img/folder.svg.br +0 -0
  365. codex/static_root/img/folder.svg.gz +0 -0
  366. codex/static_root/img/imprint.7c2adebb76d6.svg +1 -0
  367. codex/static_root/img/imprint.7c2adebb76d6.svg.br +0 -0
  368. codex/static_root/img/imprint.7c2adebb76d6.svg.gz +0 -0
  369. codex/static_root/img/imprint.svg +1 -0
  370. codex/static_root/img/imprint.svg.br +0 -0
  371. codex/static_root/img/imprint.svg.gz +0 -0
  372. codex/static_root/img/logo-32.5688944495bf.webp +0 -0
  373. codex/static_root/img/logo-32.webp +0 -0
  374. codex/static_root/img/logo-maskable-180.c58d966aa64e.webp +0 -0
  375. codex/static_root/img/logo-maskable-180.webp +0 -0
  376. codex/static_root/img/logo-maskable.8f7de7f1c6a8.svg +1 -0
  377. codex/static_root/img/logo-maskable.8f7de7f1c6a8.svg.br +0 -0
  378. codex/static_root/img/logo-maskable.8f7de7f1c6a8.svg.gz +0 -0
  379. codex/static_root/img/logo-maskable.svg +1 -83
  380. codex/static_root/img/logo-maskable.svg.br +0 -0
  381. codex/static_root/img/logo-maskable.svg.gz +0 -0
  382. codex/static_root/img/logo.0f5344a028ca.svg +1 -0
  383. codex/static_root/img/logo.0f5344a028ca.svg.br +0 -0
  384. codex/static_root/img/logo.0f5344a028ca.svg.gz +0 -0
  385. codex/static_root/img/logo.svg +1 -80
  386. codex/static_root/img/logo.svg.br +0 -0
  387. codex/static_root/img/logo.svg.gz +0 -0
  388. codex/static_root/img/missing-cover-165.0743171f2148.webp +0 -0
  389. codex/static_root/img/missing-cover-165.webp +0 -0
  390. codex/static_root/img/missing-cover.ddb038cc2c56.svg +1 -0
  391. codex/static_root/img/missing-cover.ddb038cc2c56.svg.br +0 -0
  392. codex/static_root/img/missing-cover.ddb038cc2c56.svg.gz +0 -0
  393. codex/static_root/img/missing-cover.svg +1 -0
  394. codex/static_root/img/missing-cover.svg.br +0 -0
  395. codex/static_root/img/missing-cover.svg.gz +0 -0
  396. codex/static_root/img/publisher.82d378fcd601.svg +1 -0
  397. codex/static_root/img/publisher.82d378fcd601.svg.br +0 -0
  398. codex/static_root/img/publisher.82d378fcd601.svg.gz +0 -0
  399. codex/static_root/img/publisher.svg +1 -0
  400. codex/static_root/img/publisher.svg.br +0 -0
  401. codex/static_root/img/publisher.svg.gz +0 -0
  402. codex/static_root/img/series.ec8a889b8f95.svg +1 -0
  403. codex/static_root/img/series.ec8a889b8f95.svg.br +0 -0
  404. codex/static_root/img/series.ec8a889b8f95.svg.gz +0 -0
  405. codex/static_root/img/series.svg +1 -0
  406. codex/static_root/img/series.svg.br +0 -0
  407. codex/static_root/img/series.svg.gz +0 -0
  408. codex/static_root/img/story-arc.ca10014355ef.svg +1 -0
  409. codex/static_root/img/story-arc.ca10014355ef.svg.br +1 -0
  410. codex/static_root/img/story-arc.ca10014355ef.svg.gz +0 -0
  411. codex/static_root/img/story-arc.svg +1 -0
  412. codex/static_root/img/story-arc.svg.br +1 -0
  413. codex/static_root/img/story-arc.svg.gz +0 -0
  414. codex/static_root/img/volume.814e4c79461a.svg +1 -0
  415. codex/static_root/img/volume.814e4c79461a.svg.br +0 -0
  416. codex/static_root/img/volume.814e4c79461a.svg.gz +0 -0
  417. codex/static_root/img/volume.svg +1 -0
  418. codex/static_root/img/volume.svg.br +0 -0
  419. codex/static_root/img/volume.svg.gz +0 -0
  420. codex/static_root/js/{choices-admin.bb730e4f26ac.json → choices-admin.248384ece3f6.json} +1 -1
  421. codex/static_root/js/choices-admin.248384ece3f6.json.br +0 -0
  422. codex/static_root/js/choices-admin.248384ece3f6.json.gz +0 -0
  423. codex/static_root/js/choices-admin.json +1 -1
  424. codex/static_root/js/choices-admin.json.br +0 -0
  425. codex/static_root/js/choices-admin.json.gz +0 -0
  426. codex/static_root/js/choices.b60817ba0a93.json +1 -0
  427. codex/static_root/js/choices.b60817ba0a93.json.br +0 -0
  428. codex/static_root/js/choices.b60817ba0a93.json.gz +0 -0
  429. codex/static_root/js/choices.json +1 -1
  430. codex/static_root/js/choices.json.br +0 -0
  431. codex/static_root/js/choices.json.gz +0 -0
  432. codex/static_root/manifest.c5fa10a7dfdc.json +641 -0
  433. codex/static_root/manifest.c5fa10a7dfdc.json.br +0 -0
  434. codex/static_root/manifest.c5fa10a7dfdc.json.gz +0 -0
  435. codex/static_root/manifest.json +354 -320
  436. codex/static_root/manifest.json.br +0 -0
  437. codex/static_root/manifest.json.gz +0 -0
  438. codex/static_root/staticfiles.json +1 -1
  439. codex/templates/headers-script-globals.html +1 -4
  440. codex/urls/api/admin.py +5 -7
  441. codex/urls/api/browser.py +5 -5
  442. codex/urls/api/reader.py +3 -3
  443. codex/urls/api/v3.py +2 -0
  444. codex/urls/app.py +8 -3
  445. codex/urls/converters.py +39 -0
  446. codex/urls/opds/root.py +3 -4
  447. codex/urls/opds/v1.py +1 -1
  448. codex/urls/opds/v2.py +6 -1
  449. codex/urls/root.py +2 -1
  450. codex/views/admin/user.py +0 -5
  451. codex/views/auth.py +10 -12
  452. codex/views/bookmark.py +6 -5
  453. codex/views/browser/base.py +88 -26
  454. codex/views/browser/browser.py +245 -319
  455. codex/views/browser/browser_annotations.py +236 -187
  456. codex/views/browser/browser_breadcrumbs.py +175 -0
  457. codex/views/browser/browser_order_by.py +44 -89
  458. codex/views/browser/choices.py +39 -45
  459. codex/views/browser/filters/annotations.py +34 -0
  460. codex/views/browser/filters/group.py +8 -7
  461. codex/views/browser/filters/search.py +157 -24
  462. codex/views/browser/metadata.py +98 -104
  463. codex/views/const.py +17 -0
  464. codex/views/cover.py +22 -4
  465. codex/views/download.py +3 -12
  466. codex/views/error.py +2 -2
  467. codex/views/frontend.py +4 -1
  468. codex/views/mixins.py +76 -0
  469. codex/views/opds/urls.py +28 -0
  470. codex/views/opds/util.py +7 -7
  471. codex/views/opds/v1/entry/data.py +2 -2
  472. codex/views/opds/v1/entry/entry.py +5 -5
  473. codex/views/opds/v1/entry/links.py +69 -44
  474. codex/views/opds/v1/facets.py +4 -4
  475. codex/views/opds/v1/feed.py +32 -21
  476. codex/views/opds/v1/links.py +14 -14
  477. codex/views/opds/v1/opensearch_v1.py +4 -1
  478. codex/views/opds/v2/feed.py +52 -35
  479. codex/views/opds/v2/publications.py +17 -15
  480. codex/views/opds/v2/top_links.py +2 -2
  481. codex/views/reader/page.py +4 -0
  482. codex/views/reader/reader.py +168 -79
  483. codex/views/session.py +21 -12
  484. {codex-1.5.19.dist-info → codex-1.6.0a0.dist-info}/METADATA +22 -11
  485. {codex-1.5.19.dist-info → codex-1.6.0a0.dist-info}/RECORD +488 -429
  486. codex/db_functions.py +0 -25
  487. codex/img/missing-cover.webp +0 -0
  488. codex/static_root/assets/VCheckbox-D7WF5wMC.c98c1beb207e.js.br +0 -0
  489. codex/static_root/assets/VCheckbox-D7WF5wMC.c98c1beb207e.js.gz +0 -0
  490. codex/static_root/assets/VCheckbox-D7WF5wMC.js.br +0 -0
  491. codex/static_root/assets/VCheckbox-D7WF5wMC.js.gz +0 -0
  492. codex/static_root/assets/VCheckboxBtn-CzTNt4cV.39d03f0eaf4b.js.br +0 -0
  493. codex/static_root/assets/VCheckboxBtn-CzTNt4cV.39d03f0eaf4b.js.gz +0 -0
  494. codex/static_root/assets/VCheckboxBtn-CzTNt4cV.js.br +0 -0
  495. codex/static_root/assets/VCheckboxBtn-CzTNt4cV.js.gz +0 -0
  496. codex/static_root/assets/VCombobox-BWrSBDP9.52f0c0067437.js +0 -1
  497. codex/static_root/assets/VCombobox-BWrSBDP9.52f0c0067437.js.br +0 -0
  498. codex/static_root/assets/VCombobox-BWrSBDP9.52f0c0067437.js.gz +0 -0
  499. codex/static_root/assets/VCombobox-BWrSBDP9.js +0 -1
  500. codex/static_root/assets/VCombobox-BWrSBDP9.js.br +0 -0
  501. codex/static_root/assets/VCombobox-BWrSBDP9.js.gz +0 -0
  502. codex/static_root/assets/VDataTableVirtual-BMondxto.8b48739e5470.js +0 -1
  503. codex/static_root/assets/VDataTableVirtual-BMondxto.8b48739e5470.js.br +0 -0
  504. codex/static_root/assets/VDataTableVirtual-BMondxto.8b48739e5470.js.gz +0 -0
  505. codex/static_root/assets/VDataTableVirtual-BMondxto.js +0 -1
  506. codex/static_root/assets/VDataTableVirtual-BMondxto.js.br +0 -0
  507. codex/static_root/assets/VDataTableVirtual-BMondxto.js.gz +0 -0
  508. codex/static_root/assets/VDataTableVirtual-C5zDmmxd.a73a7dd5614a.css +0 -1
  509. codex/static_root/assets/VDataTableVirtual-C5zDmmxd.a73a7dd5614a.css.br +0 -0
  510. codex/static_root/assets/VDataTableVirtual-C5zDmmxd.a73a7dd5614a.css.gz +0 -0
  511. codex/static_root/assets/VDataTableVirtual-C5zDmmxd.css +0 -1
  512. codex/static_root/assets/VDataTableVirtual-C5zDmmxd.css.br +0 -0
  513. codex/static_root/assets/VDataTableVirtual-C5zDmmxd.css.gz +0 -0
  514. codex/static_root/assets/VExpansionPanels-CDS9qp1D.9fdf68e2f68f.js +0 -1
  515. codex/static_root/assets/VExpansionPanels-CDS9qp1D.9fdf68e2f68f.js.br +0 -0
  516. codex/static_root/assets/VExpansionPanels-CDS9qp1D.9fdf68e2f68f.js.gz +0 -0
  517. codex/static_root/assets/VExpansionPanels-CDS9qp1D.js +0 -1
  518. codex/static_root/assets/VExpansionPanels-CDS9qp1D.js.br +0 -0
  519. codex/static_root/assets/VExpansionPanels-CDS9qp1D.js.gz +0 -0
  520. codex/static_root/assets/VMain-8vjSGbNt.4a97ed735dc3.js +0 -1
  521. codex/static_root/assets/VMain-8vjSGbNt.4a97ed735dc3.js.br +0 -0
  522. codex/static_root/assets/VMain-8vjSGbNt.4a97ed735dc3.js.gz +0 -0
  523. codex/static_root/assets/VMain-8vjSGbNt.js +0 -1
  524. codex/static_root/assets/VMain-8vjSGbNt.js.br +0 -0
  525. codex/static_root/assets/VMain-8vjSGbNt.js.gz +0 -0
  526. codex/static_root/assets/VMain-Byt37V4c.a00e206f3cfa.css +0 -1
  527. codex/static_root/assets/VMain-Byt37V4c.a00e206f3cfa.css.br +0 -0
  528. codex/static_root/assets/VMain-Byt37V4c.a00e206f3cfa.css.gz +0 -0
  529. codex/static_root/assets/VMain-Byt37V4c.css +0 -1
  530. codex/static_root/assets/VMain-Byt37V4c.css.br +0 -0
  531. codex/static_root/assets/VMain-Byt37V4c.css.gz +0 -0
  532. codex/static_root/assets/VRadioGroup-DGplihzh.3f4a5d26a1cb.js.br +0 -0
  533. codex/static_root/assets/VRadioGroup-DGplihzh.3f4a5d26a1cb.js.gz +0 -0
  534. codex/static_root/assets/VRadioGroup-DGplihzh.js.br +0 -0
  535. codex/static_root/assets/VRadioGroup-DGplihzh.js.gz +0 -0
  536. codex/static_root/assets/VSelect-DfV5vhqb.d24dcc61a20f.js +0 -1
  537. codex/static_root/assets/VSelect-DfV5vhqb.d24dcc61a20f.js.br +0 -0
  538. codex/static_root/assets/VSelect-DfV5vhqb.d24dcc61a20f.js.gz +0 -0
  539. codex/static_root/assets/VSelect-DfV5vhqb.js +0 -1
  540. codex/static_root/assets/VSelect-DfV5vhqb.js.br +0 -0
  541. codex/static_root/assets/VSelect-DfV5vhqb.js.gz +0 -0
  542. codex/static_root/assets/VSelect-MGVSeLgr.7cabd30bc5e4.css +0 -1
  543. codex/static_root/assets/VSelect-MGVSeLgr.7cabd30bc5e4.css.br +0 -0
  544. codex/static_root/assets/VSelect-MGVSeLgr.7cabd30bc5e4.css.gz +0 -0
  545. codex/static_root/assets/VSelect-MGVSeLgr.css +0 -1
  546. codex/static_root/assets/VSelect-MGVSeLgr.css.br +0 -0
  547. codex/static_root/assets/VSelect-MGVSeLgr.css.gz +0 -0
  548. codex/static_root/assets/VSelectionControl-DvHEDoJy.30ca0aef8bd2.js.br +0 -0
  549. codex/static_root/assets/VSelectionControl-DvHEDoJy.30ca0aef8bd2.js.gz +0 -0
  550. codex/static_root/assets/VSelectionControl-DvHEDoJy.js.br +0 -0
  551. codex/static_root/assets/VSelectionControl-DvHEDoJy.js.gz +0 -0
  552. codex/static_root/assets/VSlideGroup-BdgkaRxE.ba78a4e0efc0.js +0 -1
  553. codex/static_root/assets/VSlideGroup-BdgkaRxE.ba78a4e0efc0.js.br +0 -0
  554. codex/static_root/assets/VSlideGroup-BdgkaRxE.ba78a4e0efc0.js.gz +0 -0
  555. codex/static_root/assets/VSlideGroup-BdgkaRxE.js +0 -1
  556. codex/static_root/assets/VSlideGroup-BdgkaRxE.js.br +0 -0
  557. codex/static_root/assets/VSlideGroup-BdgkaRxE.js.gz +0 -0
  558. codex/static_root/assets/VSlideGroup-CTW-HJl4.8b75b66602c9.css.br +0 -0
  559. codex/static_root/assets/VSlideGroup-CTW-HJl4.8b75b66602c9.css.gz +0 -0
  560. codex/static_root/assets/VSlideGroup-CTW-HJl4.css.br +0 -0
  561. codex/static_root/assets/VSlideGroup-CTW-HJl4.css.gz +0 -0
  562. codex/static_root/assets/VTable-TEvK4Tmn.c68c176d93db.js.br +0 -0
  563. codex/static_root/assets/VTable-TEvK4Tmn.c68c176d93db.js.gz +0 -0
  564. codex/static_root/assets/VTable-TEvK4Tmn.js.br +0 -0
  565. codex/static_root/assets/VTable-TEvK4Tmn.js.gz +0 -0
  566. codex/static_root/assets/VToolbar-D7BgLWdG.css +0 -1
  567. codex/static_root/assets/VToolbar-D7BgLWdG.css.br +0 -0
  568. codex/static_root/assets/VToolbar-D7BgLWdG.css.gz +0 -0
  569. codex/static_root/assets/VToolbar-D7BgLWdG.e4d8a79cc655.css +0 -1
  570. codex/static_root/assets/VToolbar-D7BgLWdG.e4d8a79cc655.css.br +0 -0
  571. codex/static_root/assets/VToolbar-D7BgLWdG.e4d8a79cc655.css.gz +0 -0
  572. codex/static_root/assets/VToolbar-DCXw9xBt.576c107a78d3.js +0 -2
  573. codex/static_root/assets/VToolbar-DCXw9xBt.576c107a78d3.js.br +0 -0
  574. codex/static_root/assets/VToolbar-DCXw9xBt.576c107a78d3.js.gz +0 -0
  575. codex/static_root/assets/VToolbar-DCXw9xBt.js +0 -2
  576. codex/static_root/assets/VToolbar-DCXw9xBt.js.br +0 -0
  577. codex/static_root/assets/VToolbar-DCXw9xBt.js.gz +0 -0
  578. codex/static_root/assets/VWindowItem-CCYriq5i.8a6d4a38dabd.js +0 -1
  579. codex/static_root/assets/VWindowItem-CCYriq5i.8a6d4a38dabd.js.br +0 -0
  580. codex/static_root/assets/VWindowItem-CCYriq5i.8a6d4a38dabd.js.gz +0 -0
  581. codex/static_root/assets/VWindowItem-CCYriq5i.js +0 -1
  582. codex/static_root/assets/VWindowItem-CCYriq5i.js.br +0 -0
  583. codex/static_root/assets/VWindowItem-CCYriq5i.js.gz +0 -0
  584. codex/static_root/assets/admin-A2T028Mn.be3fa80456de.js +0 -1
  585. codex/static_root/assets/admin-A2T028Mn.be3fa80456de.js.br +0 -0
  586. codex/static_root/assets/admin-A2T028Mn.be3fa80456de.js.gz +0 -0
  587. codex/static_root/assets/admin-A2T028Mn.js +0 -1
  588. codex/static_root/assets/admin-A2T028Mn.js.br +0 -0
  589. codex/static_root/assets/admin-A2T028Mn.js.gz +0 -0
  590. codex/static_root/assets/admin-C8Kk7_Ni.255594400b96.css +0 -1
  591. codex/static_root/assets/admin-C8Kk7_Ni.255594400b96.css.br +0 -0
  592. codex/static_root/assets/admin-C8Kk7_Ni.255594400b96.css.gz +0 -0
  593. codex/static_root/assets/admin-C8Kk7_Ni.css +0 -1
  594. codex/static_root/assets/admin-C8Kk7_Ni.css.br +0 -0
  595. codex/static_root/assets/admin-C8Kk7_Ni.css.gz +0 -0
  596. codex/static_root/assets/admin-drawer-panel-DffXGW1d.8f7f39ffb127.js +0 -30
  597. codex/static_root/assets/admin-drawer-panel-DffXGW1d.8f7f39ffb127.js.br +0 -0
  598. codex/static_root/assets/admin-drawer-panel-DffXGW1d.8f7f39ffb127.js.gz +0 -0
  599. codex/static_root/assets/admin-drawer-panel-DffXGW1d.js +0 -30
  600. codex/static_root/assets/admin-drawer-panel-DffXGW1d.js.br +0 -0
  601. codex/static_root/assets/admin-drawer-panel-DffXGW1d.js.gz +0 -0
  602. codex/static_root/assets/admin-drawer-panel-Dv_IY0x2.af4fa9980c09.css +0 -1
  603. codex/static_root/assets/admin-drawer-panel-Dv_IY0x2.af4fa9980c09.css.br +0 -0
  604. codex/static_root/assets/admin-drawer-panel-Dv_IY0x2.af4fa9980c09.css.gz +0 -0
  605. codex/static_root/assets/admin-drawer-panel-Dv_IY0x2.css +0 -1
  606. codex/static_root/assets/admin-drawer-panel-Dv_IY0x2.css.br +0 -0
  607. codex/static_root/assets/admin-drawer-panel-Dv_IY0x2.css.gz +0 -0
  608. codex/static_root/assets/browser-CY9BdW6B.c9c3e5dffcbf.js +0 -1
  609. codex/static_root/assets/browser-CY9BdW6B.c9c3e5dffcbf.js.br +0 -0
  610. codex/static_root/assets/browser-CY9BdW6B.c9c3e5dffcbf.js.gz +0 -0
  611. codex/static_root/assets/browser-CY9BdW6B.js +0 -1
  612. codex/static_root/assets/browser-CY9BdW6B.js.br +0 -0
  613. codex/static_root/assets/browser-CY9BdW6B.js.gz +0 -0
  614. codex/static_root/assets/browser-HtKThxA9.69be059a55f4.css +0 -1
  615. codex/static_root/assets/browser-HtKThxA9.69be059a55f4.css.br +0 -0
  616. codex/static_root/assets/browser-HtKThxA9.69be059a55f4.css.gz +0 -0
  617. codex/static_root/assets/browser-HtKThxA9.css +0 -1
  618. codex/static_root/assets/browser-HtKThxA9.css.br +0 -0
  619. codex/static_root/assets/browser-HtKThxA9.css.gz +0 -0
  620. codex/static_root/assets/change-password-dialog-BRmvkNir.2fead58a78c7.css +0 -1
  621. codex/static_root/assets/change-password-dialog-BRmvkNir.2fead58a78c7.css.br +0 -0
  622. codex/static_root/assets/change-password-dialog-BRmvkNir.2fead58a78c7.css.gz +0 -0
  623. codex/static_root/assets/change-password-dialog-BRmvkNir.css +0 -1
  624. codex/static_root/assets/change-password-dialog-BRmvkNir.css.br +0 -0
  625. codex/static_root/assets/change-password-dialog-BRmvkNir.css.gz +0 -0
  626. codex/static_root/assets/change-password-dialog-Dr1CYQ46.afdd502a985d.js +0 -1
  627. codex/static_root/assets/change-password-dialog-Dr1CYQ46.afdd502a985d.js.br +0 -0
  628. codex/static_root/assets/change-password-dialog-Dr1CYQ46.afdd502a985d.js.gz +0 -0
  629. codex/static_root/assets/change-password-dialog-Dr1CYQ46.js +0 -1
  630. codex/static_root/assets/change-password-dialog-Dr1CYQ46.js.br +0 -0
  631. codex/static_root/assets/change-password-dialog-Dr1CYQ46.js.gz +0 -0
  632. codex/static_root/assets/confirm-dialog-BoVvCI5y.8549e2429bdf.js +0 -1
  633. codex/static_root/assets/confirm-dialog-BoVvCI5y.8549e2429bdf.js.br +0 -0
  634. codex/static_root/assets/confirm-dialog-BoVvCI5y.8549e2429bdf.js.gz +0 -0
  635. codex/static_root/assets/confirm-dialog-BoVvCI5y.js +0 -1
  636. codex/static_root/assets/confirm-dialog-BoVvCI5y.js.br +0 -0
  637. codex/static_root/assets/confirm-dialog-BoVvCI5y.js.gz +0 -0
  638. codex/static_root/assets/confirm-footer-BPuy6r_H.3aa74b8e07c1.css +0 -1
  639. codex/static_root/assets/confirm-footer-BPuy6r_H.3aa74b8e07c1.css.br +0 -0
  640. codex/static_root/assets/confirm-footer-BPuy6r_H.3aa74b8e07c1.css.gz +0 -0
  641. codex/static_root/assets/confirm-footer-BPuy6r_H.css +0 -1
  642. codex/static_root/assets/confirm-footer-BPuy6r_H.css.br +0 -0
  643. codex/static_root/assets/confirm-footer-BPuy6r_H.css.gz +0 -0
  644. codex/static_root/assets/confirm-footer-CIu2tkFD.0aa16c0fc333.js +0 -1
  645. codex/static_root/assets/confirm-footer-CIu2tkFD.0aa16c0fc333.js.br +0 -0
  646. codex/static_root/assets/confirm-footer-CIu2tkFD.0aa16c0fc333.js.gz +0 -0
  647. codex/static_root/assets/confirm-footer-CIu2tkFD.js +0 -1
  648. codex/static_root/assets/confirm-footer-CIu2tkFD.js.br +0 -0
  649. codex/static_root/assets/confirm-footer-CIu2tkFD.js.gz +0 -0
  650. codex/static_root/assets/datetime-column-BWWfvyhn.a4a94ba57c73.css +0 -1
  651. codex/static_root/assets/datetime-column-BWWfvyhn.a4a94ba57c73.css.br +0 -0
  652. codex/static_root/assets/datetime-column-BWWfvyhn.css +0 -1
  653. codex/static_root/assets/datetime-column-BWWfvyhn.css.br +0 -0
  654. codex/static_root/assets/datetime-column-C3t430gN.97e5c5364aef.js.br +0 -0
  655. codex/static_root/assets/datetime-column-C3t430gN.97e5c5364aef.js.gz +0 -0
  656. codex/static_root/assets/datetime-column-C3t430gN.js.br +0 -0
  657. codex/static_root/assets/datetime-column-C3t430gN.js.gz +0 -0
  658. codex/static_root/assets/filter-BQ_FuhIp.ee8b78c4aa55.js.br +0 -0
  659. codex/static_root/assets/filter-BQ_FuhIp.ee8b78c4aa55.js.gz +0 -0
  660. codex/static_root/assets/filter-BQ_FuhIp.js.br +0 -0
  661. codex/static_root/assets/filter-BQ_FuhIp.js.gz +0 -0
  662. codex/static_root/assets/flag-tab-D380D1SI.f4bc34623651.js +0 -1
  663. codex/static_root/assets/flag-tab-D380D1SI.f4bc34623651.js.br +0 -0
  664. codex/static_root/assets/flag-tab-D380D1SI.f4bc34623651.js.gz +0 -0
  665. codex/static_root/assets/flag-tab-D380D1SI.js +0 -1
  666. codex/static_root/assets/flag-tab-D380D1SI.js.br +0 -0
  667. codex/static_root/assets/flag-tab-D380D1SI.js.gz +0 -0
  668. codex/static_root/assets/flag-tab-D_HjkAta.203bedf35ce7.css +0 -1
  669. codex/static_root/assets/flag-tab-D_HjkAta.203bedf35ce7.css.br +0 -0
  670. codex/static_root/assets/flag-tab-D_HjkAta.203bedf35ce7.css.gz +0 -0
  671. codex/static_root/assets/flag-tab-D_HjkAta.css +0 -1
  672. codex/static_root/assets/flag-tab-D_HjkAta.css.br +0 -0
  673. codex/static_root/assets/flag-tab-D_HjkAta.css.gz +0 -0
  674. codex/static_root/assets/group-tab-CDcOyQyw.9c85a4fb987a.js +0 -1
  675. codex/static_root/assets/group-tab-CDcOyQyw.9c85a4fb987a.js.br +0 -0
  676. codex/static_root/assets/group-tab-CDcOyQyw.9c85a4fb987a.js.gz +0 -0
  677. codex/static_root/assets/group-tab-CDcOyQyw.js +0 -1
  678. codex/static_root/assets/group-tab-CDcOyQyw.js.br +0 -0
  679. codex/static_root/assets/group-tab-CDcOyQyw.js.gz +0 -0
  680. codex/static_root/assets/group-tab-GFacGljN.98df9e04f2a7.css +0 -1
  681. codex/static_root/assets/group-tab-GFacGljN.98df9e04f2a7.css.br +0 -0
  682. codex/static_root/assets/group-tab-GFacGljN.98df9e04f2a7.css.gz +0 -0
  683. codex/static_root/assets/group-tab-GFacGljN.css +0 -1
  684. codex/static_root/assets/group-tab-GFacGljN.css.br +0 -0
  685. codex/static_root/assets/group-tab-GFacGljN.css.gz +0 -0
  686. codex/static_root/assets/http-error-C25WdjWC.1c7337ad6e1d.css +0 -1
  687. codex/static_root/assets/http-error-C25WdjWC.1c7337ad6e1d.css.br +0 -0
  688. codex/static_root/assets/http-error-C25WdjWC.1c7337ad6e1d.css.gz +0 -0
  689. codex/static_root/assets/http-error-C25WdjWC.css +0 -1
  690. codex/static_root/assets/http-error-C25WdjWC.css.br +0 -0
  691. codex/static_root/assets/http-error-C25WdjWC.css.gz +0 -0
  692. codex/static_root/assets/http-error-D4BCbtF2.d3d31021f2ca.js +0 -1
  693. codex/static_root/assets/http-error-D4BCbtF2.d3d31021f2ca.js.br +0 -0
  694. codex/static_root/assets/http-error-D4BCbtF2.d3d31021f2ca.js.gz +0 -0
  695. codex/static_root/assets/http-error-D4BCbtF2.js +0 -1
  696. codex/static_root/assets/http-error-D4BCbtF2.js.br +0 -0
  697. codex/static_root/assets/http-error-D4BCbtF2.js.gz +0 -0
  698. codex/static_root/assets/library-tab-BpWTK9vs.b2a752770db5.js +0 -1
  699. codex/static_root/assets/library-tab-BpWTK9vs.b2a752770db5.js.br +0 -0
  700. codex/static_root/assets/library-tab-BpWTK9vs.b2a752770db5.js.gz +0 -0
  701. codex/static_root/assets/library-tab-BpWTK9vs.js +0 -1
  702. codex/static_root/assets/library-tab-BpWTK9vs.js.br +0 -0
  703. codex/static_root/assets/library-tab-BpWTK9vs.js.gz +0 -0
  704. codex/static_root/assets/library-tab-DZKDtQ5v.c8123e4bc5a4.css +0 -1
  705. codex/static_root/assets/library-tab-DZKDtQ5v.c8123e4bc5a4.css.br +0 -3
  706. codex/static_root/assets/library-tab-DZKDtQ5v.c8123e4bc5a4.css.gz +0 -0
  707. codex/static_root/assets/library-tab-DZKDtQ5v.css +0 -1
  708. codex/static_root/assets/library-tab-DZKDtQ5v.css.br +0 -3
  709. codex/static_root/assets/library-tab-DZKDtQ5v.css.gz +0 -0
  710. codex/static_root/assets/main-DB0zDxIA.e71734100695.js +0 -32
  711. codex/static_root/assets/main-DB0zDxIA.e71734100695.js.br +0 -0
  712. codex/static_root/assets/main-DB0zDxIA.e71734100695.js.gz +0 -0
  713. codex/static_root/assets/main-DB0zDxIA.js +0 -32
  714. codex/static_root/assets/main-DB0zDxIA.js.br +0 -0
  715. codex/static_root/assets/main-DB0zDxIA.js.gz +0 -0
  716. codex/static_root/assets/main-ED57DJUb.b84231dc384d.css.br +0 -0
  717. codex/static_root/assets/main-ED57DJUb.css.br +0 -0
  718. codex/static_root/assets/metadata-dialog-BlvHIpPe.aca38025f67b.js +0 -1
  719. codex/static_root/assets/metadata-dialog-BlvHIpPe.aca38025f67b.js.br +0 -0
  720. codex/static_root/assets/metadata-dialog-BlvHIpPe.aca38025f67b.js.gz +0 -0
  721. codex/static_root/assets/metadata-dialog-BlvHIpPe.js +0 -1
  722. codex/static_root/assets/metadata-dialog-BlvHIpPe.js.br +0 -0
  723. codex/static_root/assets/metadata-dialog-BlvHIpPe.js.gz +0 -0
  724. codex/static_root/assets/metadata-dialog-CNrYFyyx.87cbe14f8752.css +0 -1
  725. codex/static_root/assets/metadata-dialog-CNrYFyyx.87cbe14f8752.css.br +0 -0
  726. codex/static_root/assets/metadata-dialog-CNrYFyyx.87cbe14f8752.css.gz +0 -0
  727. codex/static_root/assets/metadata-dialog-CNrYFyyx.css +0 -1
  728. codex/static_root/assets/metadata-dialog-CNrYFyyx.css.br +0 -0
  729. codex/static_root/assets/metadata-dialog-CNrYFyyx.css.gz +0 -0
  730. codex/static_root/assets/pdf-doc-x5fJF5N8.67b5456d222e.js.br +0 -0
  731. codex/static_root/assets/pdf-doc-x5fJF5N8.67b5456d222e.js.gz +0 -0
  732. codex/static_root/assets/pdf-doc-x5fJF5N8.js.br +0 -0
  733. codex/static_root/assets/pdf-doc-x5fJF5N8.js.gz +0 -0
  734. codex/static_root/assets/reader-BDo-P8Ww.46ce70253011.css +0 -1
  735. codex/static_root/assets/reader-BDo-P8Ww.46ce70253011.css.br +0 -0
  736. codex/static_root/assets/reader-BDo-P8Ww.46ce70253011.css.gz +0 -0
  737. codex/static_root/assets/reader-BDo-P8Ww.css +0 -1
  738. codex/static_root/assets/reader-BDo-P8Ww.css.br +0 -0
  739. codex/static_root/assets/reader-BDo-P8Ww.css.gz +0 -0
  740. codex/static_root/assets/reader-CXmsYhy4.3f98149c37d9.js +0 -2
  741. codex/static_root/assets/reader-CXmsYhy4.3f98149c37d9.js.br +0 -0
  742. codex/static_root/assets/reader-CXmsYhy4.3f98149c37d9.js.gz +0 -0
  743. codex/static_root/assets/reader-CXmsYhy4.js +0 -2
  744. codex/static_root/assets/reader-CXmsYhy4.js.br +0 -0
  745. codex/static_root/assets/reader-CXmsYhy4.js.gz +0 -0
  746. codex/static_root/assets/stats-tab-BTZLMBCU.7e0a9547c12e.css +0 -1
  747. codex/static_root/assets/stats-tab-BTZLMBCU.7e0a9547c12e.css.br +0 -0
  748. codex/static_root/assets/stats-tab-BTZLMBCU.7e0a9547c12e.css.gz +0 -0
  749. codex/static_root/assets/stats-tab-BTZLMBCU.css +0 -1
  750. codex/static_root/assets/stats-tab-BTZLMBCU.css.br +0 -0
  751. codex/static_root/assets/stats-tab-BTZLMBCU.css.gz +0 -0
  752. codex/static_root/assets/stats-tab-xK8fU37K.24f65a4c7479.js +0 -1
  753. codex/static_root/assets/stats-tab-xK8fU37K.24f65a4c7479.js.br +0 -0
  754. codex/static_root/assets/stats-tab-xK8fU37K.24f65a4c7479.js.gz +0 -0
  755. codex/static_root/assets/stats-tab-xK8fU37K.js +0 -1
  756. codex/static_root/assets/stats-tab-xK8fU37K.js.br +0 -0
  757. codex/static_root/assets/stats-tab-xK8fU37K.js.gz +0 -0
  758. codex/static_root/assets/task-tab-D-j9C5kb.f8defdafa5d1.js +0 -1
  759. codex/static_root/assets/task-tab-D-j9C5kb.f8defdafa5d1.js.br +0 -0
  760. codex/static_root/assets/task-tab-D-j9C5kb.f8defdafa5d1.js.gz +0 -0
  761. codex/static_root/assets/task-tab-D-j9C5kb.js +0 -1
  762. codex/static_root/assets/task-tab-D-j9C5kb.js.br +0 -0
  763. codex/static_root/assets/task-tab-D-j9C5kb.js.gz +0 -0
  764. codex/static_root/assets/task-tab-DoX9OA37.9bb355f36dbf.css +0 -1
  765. codex/static_root/assets/task-tab-DoX9OA37.9bb355f36dbf.css.gz +0 -0
  766. codex/static_root/assets/task-tab-DoX9OA37.css +0 -1
  767. codex/static_root/assets/task-tab-DoX9OA37.css.gz +0 -0
  768. codex/static_root/assets/user-tab-DMcrO04A.501813c958bd.js +0 -1
  769. codex/static_root/assets/user-tab-DMcrO04A.501813c958bd.js.br +0 -0
  770. codex/static_root/assets/user-tab-DMcrO04A.501813c958bd.js.gz +0 -0
  771. codex/static_root/assets/user-tab-DMcrO04A.js +0 -1
  772. codex/static_root/assets/user-tab-DMcrO04A.js.br +0 -0
  773. codex/static_root/assets/user-tab-DMcrO04A.js.gz +0 -0
  774. codex/static_root/img/logo-32.dbb98f6dfde4.webp +0 -0
  775. codex/static_root/img/logo-maskable-180.201cbde62d55.webp +0 -0
  776. codex/static_root/img/logo-maskable.d618c2d7943f.svg +0 -83
  777. codex/static_root/img/logo-maskable.d618c2d7943f.svg.br +0 -0
  778. codex/static_root/img/logo-maskable.d618c2d7943f.svg.gz +0 -0
  779. codex/static_root/img/logo.3fb129bfbd92.svg +0 -80
  780. codex/static_root/img/logo.3fb129bfbd92.svg.br +0 -0
  781. codex/static_root/img/logo.3fb129bfbd92.svg.gz +0 -0
  782. codex/static_root/img/missing-cover.8c8c1d4f6782.webp +0 -0
  783. codex/static_root/img/missing-cover.webp +0 -0
  784. codex/static_root/img/missing-page.71bb10f7c72a.svg +0 -13
  785. codex/static_root/img/missing-page.71bb10f7c72a.svg.br +0 -0
  786. codex/static_root/img/missing-page.71bb10f7c72a.svg.gz +0 -0
  787. codex/static_root/img/missing-page.svg +0 -13
  788. codex/static_root/img/missing-page.svg.br +0 -0
  789. codex/static_root/img/missing-page.svg.gz +0 -0
  790. codex/static_root/js/choices-admin.bb730e4f26ac.json.br +0 -0
  791. codex/static_root/js/choices-admin.bb730e4f26ac.json.gz +0 -0
  792. codex/static_root/js/choices.fedcbd1ec085.json +0 -1
  793. codex/static_root/js/choices.fedcbd1ec085.json.br +0 -0
  794. codex/static_root/js/choices.fedcbd1ec085.json.gz +0 -0
  795. codex/static_root/manifest.8e6c35516db7.json +0 -607
  796. codex/static_root/manifest.8e6c35516db7.json.br +0 -0
  797. codex/static_root/manifest.8e6c35516db7.json.gz +0 -0
  798. {codex-1.5.19.dist-info → codex-1.6.0a0.dist-info}/LICENSE +0 -0
  799. {codex-1.5.19.dist-info → codex-1.6.0a0.dist-info}/WHEEL +0 -0
  800. {codex-1.5.19.dist-info → codex-1.6.0a0.dist-info}/entry_points.txt +0 -0
@@ -11,11 +11,11 @@ from codex.librarian.importer.const import (
11
11
  CONTRIBUTORS_FIELD_NAME,
12
12
  COUNT_FIELDS,
13
13
  DICT_MODEL_CLASS_FIELDS_MAP,
14
+ DICT_MODEL_FIELD_MODEL_MAP,
14
15
  DICT_MODEL_REL_MAP,
15
16
  GROUP_COMPARE_FIELDS,
16
17
  GROUP_TREES,
17
18
  IDENTIFIERS_FIELD_NAME,
18
- IDENTIFIERS_MODEL_REL_MAP,
19
19
  IMPRINT,
20
20
  PARENT_FOLDER,
21
21
  PUBLISHER,
@@ -41,16 +41,21 @@ from codex.threads import QueuedThread
41
41
 
42
42
  _CREATE_GROUPS = "create_groups"
43
43
  _UPDATE_GROUPS = "update_groups"
44
- _CLASS_QUERY_FIELDS_MAP = {
45
- Contributor: ("role__name", "person__name"),
46
- StoryArcNumber: ("story_arc__name", "number"),
47
- Folder: ("path",),
48
- Imprint: ("publisher__name", "name"),
49
- Series: ("publisher__name", "imprint__name", "name"),
50
- Volume: ("publisher__name", "imprint__name", "series__name", "name"),
51
- Identifier: ("identifier_type__name", "nss", "url"),
52
- }
44
+ _CLASS_QUERY_FIELDS_MAP = MappingProxyType(
45
+ {
46
+ Contributor: ("role__name", "person__name"),
47
+ StoryArcNumber: ("story_arc__name", "number"),
48
+ Folder: ("path",),
49
+ Imprint: ("publisher__name", "name"),
50
+ Series: ("publisher__name", "imprint__name", "name"),
51
+ Volume: ("publisher__name", "imprint__name", "series__name", "name"),
52
+ Identifier: ("identifier_type__name", "nss"),
53
+ }
54
+ )
53
55
  _DEFAULT_QUERY_FIELDS = ("name",)
56
+ _EXTRA_UPDATE_FIELDS_MAP = MappingProxyType(
57
+ {Series: ("volume_count",), Volume: ("issue_count",)}
58
+ )
54
59
 
55
60
  LOG = get_logger(__name__)
56
61
 
@@ -71,24 +76,21 @@ class QueryForeignKeysMixin(QueuedThread):
71
76
  return fks_total
72
77
 
73
78
  @staticmethod
74
- def _query_existing_mds(fk_cls, fk_filter):
79
+ def _query_existing_mds(fk_cls, fk_filter, extra_fields=None):
75
80
  """Query existing metatata tables."""
76
81
  fields = _CLASS_QUERY_FIELDS_MAP.get(fk_cls, _DEFAULT_QUERY_FIELDS)
82
+ if extra_fields:
83
+ fields += extra_fields
77
84
  flat = len(fields) == 1 and fk_cls != Publisher
78
- # print(fk_filter)
79
- qs = (
80
- fk_cls.objects.filter(fk_filter)
81
- .order_by("pk")
82
- .values_list(*fields, flat=flat)
83
- )
85
+ qs = fk_cls.objects.filter(fk_filter).values_list(*fields, flat=flat)
84
86
  return frozenset(qs)
85
87
 
86
88
  def _query_create_metadata( # noqa: PLR0913
87
89
  self,
88
90
  fk_cls,
89
91
  create_mds,
92
+ update_mds,
90
93
  q_obj: Q,
91
- q_and_chunk_prefix,
92
94
  status,
93
95
  ):
94
96
  """Get create metadata by comparing proposed meatada to existing rows."""
@@ -102,11 +104,16 @@ class QueryForeignKeysMixin(QueuedThread):
102
104
  # django.db.utils.OperationalError: Expression tree is too large (maximum depth 1000)
103
105
  children_chunk = q_obj.children[offset : offset + FILTER_BATCH_SIZE]
104
106
  filter_chunk = Q(*children_chunk, _connector=Q.OR)
105
- if q_and_chunk_prefix:
106
- filter_chunk = q_and_chunk_prefix & filter_chunk
107
107
 
108
108
  existing_mds = self._query_existing_mds(fk_cls, filter_chunk)
109
109
  create_mds.difference_update(existing_mds)
110
+ if extra_update_fields := _EXTRA_UPDATE_FIELDS_MAP.get(fk_cls):
111
+ # The mds that are in the existing_mds, but don't match the proposed mds with the extra update fields
112
+ update_mds.update(existing_mds)
113
+ match_with_extra_fields_mds = self._query_existing_mds(
114
+ fk_cls, filter_chunk, extra_update_fields
115
+ )
116
+ update_mds.difference_update(match_with_extra_fields_mds)
110
117
 
111
118
  status.complete += len(filter_chunk)
112
119
  self.status_controller.update(status)
@@ -137,7 +144,9 @@ class QueryForeignKeysMixin(QueuedThread):
137
144
 
138
145
  filter_args[key] = group_name
139
146
 
140
- def _get_create_group_set(self, groups, group_cls, create_group_set, status):
147
+ def _get_create_group_set( # noqa: PLR0913
148
+ self, groups, group_cls, create_group_set, update_group_set, status
149
+ ):
141
150
  """Create the create group set."""
142
151
  all_filters = Q()
143
152
  for group_tree in groups:
@@ -153,10 +162,12 @@ class QueryForeignKeysMixin(QueuedThread):
153
162
  all_filters |= Q(**filter_args)
154
163
 
155
164
  candidate_groups = set(groups.keys())
165
+ update_groups = set()
156
166
  count = self._query_create_metadata(
157
- group_cls, candidate_groups, all_filters, None, status
167
+ group_cls, candidate_groups, update_groups, all_filters, status
158
168
  )
159
169
  create_group_set.update(candidate_groups)
170
+ update_group_set.update(update_groups)
160
171
  return count
161
172
 
162
173
  @classmethod
@@ -174,6 +185,7 @@ class QueryForeignKeysMixin(QueuedThread):
174
185
  """Query missing groups for one group tree depth."""
175
186
  (
176
187
  create_group_set,
188
+ update_group_set,
177
189
  group_cls,
178
190
  create_and_update_groups,
179
191
  status,
@@ -185,7 +197,8 @@ class QueryForeignKeysMixin(QueuedThread):
185
197
  group_tree,
186
198
  count_value,
187
199
  )
188
- elif group_cls in (Series, Volume):
200
+ elif group_cls in update_group_set:
201
+ # This always updates Volume or Series
189
202
  self._update_action_group(
190
203
  group_cls,
191
204
  create_and_update_groups[_UPDATE_GROUPS],
@@ -284,9 +297,18 @@ class QueryForeignKeysMixin(QueuedThread):
284
297
  status.subtitle = vnp
285
298
 
286
299
  create_group_set = set()
287
- self._get_create_group_set(groups, group_cls, create_group_set, status)
300
+ update_group_set = set()
301
+ self._get_create_group_set(
302
+ groups, group_cls, create_group_set, update_group_set, status
303
+ )
288
304
 
289
- data = (create_group_set, group_cls, create_and_update_groups, status)
305
+ data = (
306
+ create_group_set,
307
+ update_group_set,
308
+ group_cls,
309
+ create_and_update_groups,
310
+ status,
311
+ )
290
312
  for group_tree, count_value in groups.items():
291
313
  self._query_group_tree(data, group_tree, count_value)
292
314
 
@@ -317,43 +339,37 @@ class QueryForeignKeysMixin(QueuedThread):
317
339
  #########
318
340
  @staticmethod
319
341
  def _query_missing_identifiers_model_obj(
320
- key_rel, value_rel_map, item, possible_create_objs
342
+ value_rel_map, key, values, possible_create_objs, url_restore_map
321
343
  ):
322
344
  """Update all_filters and possible_create_objs for identifiers."""
323
345
  # identifiers is unique at this time for having more than one value as a dict.
324
- key, values = item
325
- values_list = []
326
- for val in values:
327
- values_list.append(dict(val))
328
-
329
346
  value_filter = Q()
330
- for values_dict in values_list:
347
+ # value filter
348
+ for value in values:
349
+ values_dict = dict(value)
350
+ create_obj = (key, values_dict.get("nss", ""))
351
+ url_restore_map[create_obj] = values_dict.get("url", "")
352
+ possible_create_objs.add(create_obj)
331
353
  value_sub_filter = Q()
332
354
  for value_key, obj_rel in value_rel_map.items():
333
- value = values_dict.get(value_key)
334
- value_sub_filter &= Q(**{f"{obj_rel}": value})
355
+ values_value = values_dict.get(value_key)
356
+ value_sub_filter &= Q(**{f"{obj_rel}": values_value})
335
357
  if value_sub_filter:
336
358
  value_filter |= value_sub_filter
337
359
 
338
- if not value_filter:
339
- return value_filter, None
340
-
341
- obj_filter = Q(**{key_rel: key})
342
-
343
- for value in values:
344
- possible_create_objs.add((key, value))
345
- return value_filter, obj_filter
360
+ return value_filter
346
361
 
347
362
  @staticmethod
348
- def _query_missing_dict_model_obj(key_rel, value_rel, item, possible_create_objs):
363
+ def _query_missing_dict_model_obj(value_rel, key, values, possible_create_objs, _):
349
364
  """Update all_filters and possible_create_objs for this obj."""
350
- key, values = item
365
+ for value in values:
366
+ possible_create_objs.add((key, value))
351
367
 
352
368
  filter_isnull = None in values
353
369
  filter_values = values - {None}
354
370
 
355
371
  if not filter_values and not filter_isnull:
356
- return Q(), None
372
+ return Q()
357
373
 
358
374
  value_filter = (
359
375
  Q(**{f"{value_rel}__in": filter_values}) if filter_values else Q()
@@ -361,58 +377,88 @@ class QueryForeignKeysMixin(QueuedThread):
361
377
  if filter_isnull:
362
378
  value_filter = value_filter | Q(**{f"{value_rel}__isnull": True})
363
379
 
364
- obj_filter = Q(**{key_rel: key})
380
+ return value_filter
365
381
 
366
- for value in values:
367
- possible_create_objs.add((key, value))
368
- return value_filter, obj_filter
382
+ def _query_missing_dict_model_add_to_query_filter_map( # noqa: PLR0913
383
+ self,
384
+ key,
385
+ values,
386
+ field_name,
387
+ possible_create_objs,
388
+ query_filter_map,
389
+ url_restore_map,
390
+ ):
391
+ """Add value filter to query filter map."""
392
+ # Get the value filter
393
+ if field_name == "identifiers":
394
+ query_missing_method = self._query_missing_identifiers_model_obj
395
+ else:
396
+ query_missing_method = self._query_missing_dict_model_obj
397
+ key_rel, value_rel = DICT_MODEL_REL_MAP[field_name]
369
398
 
370
- @staticmethod
371
- def _add_value_filter_map(value_filter, filter_and_prefix, query_filter_map):
372
- """Add a filter_and_prefix and the value filter to the map."""
373
- if not value_filter:
374
- return
399
+ value_filter = query_missing_method(
400
+ value_rel, key, values, possible_create_objs, url_restore_map
401
+ )
402
+
403
+ # Add value_filter to the query_filter_map
404
+ filter_and_prefix = Q(**{key_rel: key})
375
405
  if filter_and_prefix not in query_filter_map:
376
406
  query_filter_map[filter_and_prefix] = Q()
377
407
  query_filter_map[filter_and_prefix] |= value_filter
378
408
 
409
+ @staticmethod
410
+ def _query_missing_dict_model_identifiers_restore_urls(
411
+ field_name, possible_create_objs, url_restore_map
412
+ ):
413
+ """Restore urls to only the identifier create objs."""
414
+ if field_name != "identifiers":
415
+ return
416
+ restored_create_objs = []
417
+ for create_obj in possible_create_objs:
418
+ url = url_restore_map.get(create_obj)
419
+ restored_create_objs.append((*create_obj, url))
420
+ possible_create_objs = restored_create_objs
421
+
379
422
  def _query_missing_dict_model(self, field_name, fks, create_objs, status):
380
- """Find missing dict type m2m models with a supplied filter method."""
381
- count = 0
423
+ """Find missing dict type m2m models."""
382
424
  possible_objs = fks.pop(field_name, None)
383
425
  if not possible_objs:
384
- return count
426
+ return 0
385
427
 
428
+ # Create possible_create_objs & a query filter map and cache the urls for
429
+ # identifiers to be created, but not queried against
386
430
  possible_create_objs = set()
387
431
  query_filter_map = {}
388
- # create the filter
389
-
390
- if field_name == "identifiers":
391
- rel_map = IDENTIFIERS_MODEL_REL_MAP
392
- query_missing_method = self._query_missing_identifiers_model_obj
393
- else:
394
- rel_map = DICT_MODEL_REL_MAP
395
- query_missing_method = self._query_missing_dict_model_obj
396
-
397
- model, key_rel, value_rel = rel_map[field_name]
398
-
399
- for item in possible_objs.items():
400
- value_filter, filter_and_prefix = query_missing_method(
401
- key_rel, value_rel, item, possible_create_objs
402
- )
403
- self._add_value_filter_map(
404
- value_filter, filter_and_prefix, query_filter_map
432
+ url_restore_map = {}
433
+ for key, values in possible_objs.items():
434
+ self._query_missing_dict_model_add_to_query_filter_map(
435
+ key,
436
+ values,
437
+ field_name,
438
+ possible_create_objs,
439
+ query_filter_map,
440
+ url_restore_map,
405
441
  )
406
442
 
407
- # get the obj metadata
443
+ # Build combined query object from the value_filter
444
+ combined_q_obj = Q()
408
445
  for filter_and_prefix, value_filter in query_filter_map.items():
409
- count += self._query_create_metadata(
410
- model, possible_create_objs, value_filter, filter_and_prefix, status
411
- )
446
+ combined_q_obj |= filter_and_prefix & value_filter
447
+
448
+ # Finally run the query and get only the correct create_objs
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(
454
+ field_name, possible_create_objs, url_restore_map
455
+ )
412
456
 
457
+ # Final Cleanup
413
458
  create_objs.update(possible_create_objs)
414
459
  count = len(create_objs)
415
460
  if count:
461
+ model = DICT_MODEL_FIELD_MODEL_MAP[field_name]
416
462
  vnp = model._meta.verbose_name_plural
417
463
  vnp = vnp.title() if vnp else "Nothings"
418
464
  self.log.info(f"Prepared {count} new {vnp}.")
@@ -33,7 +33,6 @@ class UpdateComicsMixin(LinkComicsMixin):
33
33
  value = default_value
34
34
  setattr(comic, field_name, value)
35
35
  comic.presave()
36
- comic.set_stat()
37
36
  comic.updated_at = now
38
37
  update_comics, comic_pks, comic_update_paths = results
39
38
  update_comics.append(comic)
@@ -2,26 +2,35 @@
2
2
 
3
3
  import logging
4
4
  from time import time
5
+ from types import MappingProxyType
5
6
 
6
7
  from django.contrib.sessions.models import Session
7
8
  from django.utils.timezone import now
8
9
 
9
10
  from codex.librarian.janitor.status import JanitorStatusTypes
10
11
  from codex.models import (
12
+ AgeRating,
11
13
  Character,
12
14
  Contributor,
13
15
  ContributorPerson,
14
16
  ContributorRole,
17
+ Country,
15
18
  Folder,
16
19
  Genre,
20
+ Identifier,
21
+ IdentifierType,
17
22
  Imprint,
23
+ Language,
18
24
  Location,
25
+ OriginalFormat,
19
26
  Publisher,
27
+ ScanInfo,
20
28
  Series,
21
29
  SeriesGroup,
22
30
  StoryArc,
23
31
  StoryArcNumber,
24
32
  Tag,
33
+ Tagger,
25
34
  Team,
26
35
  Volume,
27
36
  )
@@ -29,33 +38,45 @@ from codex.status import Status
29
38
  from codex.worker_base import WorkerBaseMixin
30
39
 
31
40
  _COMIC_FK_CLASSES = (
32
- Volume,
33
- Series,
34
- Imprint,
35
- Publisher,
36
- Folder,
41
+ AgeRating,
42
+ Country,
37
43
  Contributor,
38
- Tag,
39
- Team,
40
44
  Character,
45
+ Genre,
46
+ Folder,
47
+ Language,
41
48
  Location,
49
+ Identifier,
50
+ Imprint,
51
+ OriginalFormat,
52
+ Publisher,
53
+ Series,
42
54
  SeriesGroup,
55
+ ScanInfo,
43
56
  StoryArcNumber,
44
- Genre,
57
+ Tagger,
58
+ Tag,
59
+ Team,
60
+ Volume,
45
61
  )
46
62
  _CONTRIBUTOR_FK_CLASSES = (ContributorRole, ContributorPerson)
47
63
  _STORY_ARC_NUMBER_FK_CLASSES = (StoryArc,)
64
+ _IDENTIFIER_FK_CLASSES = (IdentifierType,)
48
65
  TOTAL_NUM_FK_CLASSES = (
49
66
  len(_COMIC_FK_CLASSES)
50
67
  + len(_CONTRIBUTOR_FK_CLASSES)
51
68
  + len(_STORY_ARC_NUMBER_FK_CLASSES)
69
+ + len(_IDENTIFIER_FK_CLASSES)
52
70
  )
53
71
 
54
- CLEANUP_MAP = [
55
- (_COMIC_FK_CLASSES, "comic"),
56
- (_CONTRIBUTOR_FK_CLASSES, "contributor"),
57
- (_STORY_ARC_NUMBER_FK_CLASSES, "storyarcnumber"),
58
- ]
72
+ CLEANUP_MAP = MappingProxyType(
73
+ {
74
+ "comic": _COMIC_FK_CLASSES,
75
+ "contributor": _CONTRIBUTOR_FK_CLASSES,
76
+ "storyarcnumber": _STORY_ARC_NUMBER_FK_CLASSES,
77
+ "identifier": _IDENTIFIER_FK_CLASSES,
78
+ }
79
+ )
59
80
 
60
81
 
61
82
  class CleanupMixin(WorkerBaseMixin):
@@ -79,7 +100,7 @@ class CleanupMixin(WorkerBaseMixin):
79
100
  try:
80
101
  self.status_controller.start(status)
81
102
  self.log.debug("Cleaning up unused foreign keys...")
82
- for classes, field_name in CLEANUP_MAP:
103
+ for field_name, classes in CLEANUP_MAP.items():
83
104
  self._bulk_cleanup_fks(classes, field_name, status)
84
105
  level = logging.INFO if status.complete else logging.DEBUG
85
106
  self.log.log(level, f"Cleaned up {status.complete} unused foreign keys.")
@@ -0,0 +1,149 @@
1
+ """Generated by Django 5.0.4 on 2024-05-05 23:11."""
2
+
3
+ import os
4
+ from contextlib import suppress
5
+ from pathlib import Path
6
+
7
+ from django.db import migrations, models
8
+
9
+ from codex.models.const import ARTICLES
10
+
11
+ CONFIG_PATH = Path(os.environ.get("CODEX_CONFIG_DIR", Path.cwd() / "config"))
12
+ COVER_ROOT = CONFIG_PATH / "cache" / "covers"
13
+ _GROUP_MODEL_NAMES = (
14
+ "publisher",
15
+ "imprint",
16
+ "series",
17
+ "storyarc",
18
+ "folder",
19
+ "comic",
20
+ "failedimport",
21
+ )
22
+
23
+
24
+ def _set_sort_name(obj):
25
+ """Create sort_name for model."""
26
+ # Duplicate code from BaseGroupModel
27
+ sort_name = ""
28
+ lower_name = obj.name.lower()
29
+ sort_name = lower_name
30
+ name_parts = lower_name.split()
31
+ if len(name_parts) > 1:
32
+ first_word = name_parts[0]
33
+ if first_word in ARTICLES:
34
+ sort_name = " ".join(name_parts[1:])
35
+ sort_name += ", " + first_word
36
+ obj.sort_name = sort_name
37
+
38
+
39
+ def _generate_sort_name(apps, _schema_editor):
40
+ """Update new sort_name field."""
41
+ for model_name in _GROUP_MODEL_NAMES:
42
+ model = apps.get_model("codex", model_name)
43
+ update_fields = ("sort_name",)
44
+ only_fields = ("name", *update_fields)
45
+ update_groups = []
46
+ objs = model.objects.only(*only_fields)
47
+ for obj in objs:
48
+ _set_sort_name(obj)
49
+ update_groups.append(obj)
50
+ if update_groups:
51
+ model.objects.bulk_update(update_groups, update_fields)
52
+ print(f"\tUpdated sort_name for {len(update_groups)} {model_name}s")
53
+
54
+
55
+ def _remove_cover_symlinks(_apps, _schema_editor):
56
+ """Remove old missing cover symlinks."""
57
+ # Handled programmatically now.
58
+ count = 0
59
+ for dirpath_str, _, filenames in os.walk(COVER_ROOT):
60
+ dirpath = Path(dirpath_str)
61
+ for filename in filenames:
62
+ full_path = dirpath / filename
63
+ if full_path.is_symlink():
64
+ with suppress(OSError):
65
+ full_path.unlink(missing_ok=True)
66
+ count += 1
67
+ if count:
68
+ print(f"Removed {count} missing-cover symlinks from cover cache.")
69
+
70
+
71
+ class Migration(migrations.Migration):
72
+ """Migrate."""
73
+
74
+ dependencies = [
75
+ ("codex", "0026_comicbox_1"),
76
+ ]
77
+
78
+ operations = [
79
+ migrations.AddField(
80
+ model_name="comic",
81
+ name="sort_name",
82
+ field=models.CharField(db_index=True, default="", max_length=128),
83
+ ),
84
+ migrations.AddField(
85
+ model_name="failedimport",
86
+ name="sort_name",
87
+ field=models.CharField(db_index=True, default="", max_length=128),
88
+ ),
89
+ migrations.AddField(
90
+ model_name="folder",
91
+ name="sort_name",
92
+ field=models.CharField(db_index=True, default="", max_length=128),
93
+ ),
94
+ migrations.AddField(
95
+ model_name="imprint",
96
+ name="sort_name",
97
+ field=models.CharField(db_index=True, default="", max_length=128),
98
+ ),
99
+ migrations.AddField(
100
+ model_name="publisher",
101
+ name="sort_name",
102
+ field=models.CharField(db_index=True, default="", max_length=128),
103
+ ),
104
+ migrations.AddField(
105
+ model_name="series",
106
+ name="sort_name",
107
+ field=models.CharField(db_index=True, default="", max_length=128),
108
+ ),
109
+ migrations.AddField(
110
+ model_name="storyarc",
111
+ name="sort_name",
112
+ field=models.CharField(db_index=True, default="", max_length=128),
113
+ ),
114
+ migrations.AlterField(
115
+ model_name="adminflag",
116
+ name="key",
117
+ field=models.CharField(
118
+ choices=[
119
+ ("FV", "Folder View"),
120
+ ("RG", "Registration"),
121
+ ("NU", "Non Users"),
122
+ ("AU", "Auto Update"),
123
+ ("SO", "Search Index Optimize"),
124
+ ("IM", "Import Metadata"),
125
+ ],
126
+ db_index=True,
127
+ max_length=2,
128
+ ),
129
+ ),
130
+ migrations.AlterField(
131
+ model_name="adminflag",
132
+ name="key",
133
+ field=models.CharField(
134
+ choices=[
135
+ ("FV", "Folder View"),
136
+ ("RG", "Registration"),
137
+ ("NU", "Non Users"),
138
+ ("AU", "Auto Update"),
139
+ ("SO", "Search Index Optimize"),
140
+ ("IM", "Import Metadata"),
141
+ ("DC", "Dynamic Group Covers"),
142
+ ],
143
+ db_index=True,
144
+ max_length=2,
145
+ ),
146
+ ),
147
+ migrations.RunPython(_generate_sort_name),
148
+ migrations.RunPython(_remove_cover_symlinks),
149
+ ]
codex/models/admin.py CHANGED
@@ -39,6 +39,7 @@ class AdminFlag(BaseModel):
39
39
  AUTO_UPDATE = "AU"
40
40
  SEARCH_INDEX_OPTIMIZE = "SO"
41
41
  IMPORT_METADATA = "IM"
42
+ DYNAMIC_GROUP_COVERS = "DC"
42
43
 
43
44
  FALSE_DEFAULTS = frozenset({FlagChoices.AUTO_UPDATE})
44
45
 
codex/models/base.py CHANGED
@@ -3,6 +3,8 @@
3
3
  from django.db.models import DateTimeField, Model
4
4
  from django.db.models.base import ModelBase
5
5
 
6
+ from codex.models.query import GroupByManager
7
+
6
8
  __all__ = ("BaseModel",)
7
9
 
8
10
  MAX_NAME_LEN = 128
@@ -14,6 +16,7 @@ class BaseModel(Model):
14
16
 
15
17
  created_at = DateTimeField(auto_now_add=True)
16
18
  updated_at = DateTimeField(auto_now=True)
19
+ objects = GroupByManager()
17
20
 
18
21
  class Meta(ModelBase): # type: ignore
19
22
  """Without this a real table is created and joined to."""