codex 1.6.18__py3-none-any.whl → 1.7.0__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 (849) hide show
  1. codex/choices.py +419 -0
  2. codex/choices_to_json.py +122 -0
  3. codex/db.py +134 -0
  4. codex/exceptions.py +2 -3
  5. codex/librarian/bookmark/__init__.py +1 -0
  6. codex/librarian/bookmark/bookmarkd.py +38 -0
  7. codex/librarian/bookmark/tasks.py +19 -0
  8. codex/librarian/bookmark/update.py +154 -0
  9. codex/librarian/covers/coverd.py +3 -4
  10. codex/librarian/covers/create.py +8 -7
  11. codex/librarian/covers/path.py +1 -2
  12. codex/librarian/covers/purge.py +3 -3
  13. codex/librarian/importer/const.py +7 -1
  14. codex/librarian/importer/create_fks.py +5 -2
  15. codex/librarian/importer/importerd.py +17 -12
  16. codex/librarian/importer/moved.py +44 -13
  17. codex/librarian/importer/tasks.py +2 -0
  18. codex/librarian/janitor/cleanup.py +21 -8
  19. codex/librarian/janitor/integrity.py +371 -0
  20. codex/librarian/janitor/janitor.py +50 -15
  21. codex/librarian/janitor/latest_version.py +2 -1
  22. codex/librarian/janitor/status.py +5 -0
  23. codex/librarian/janitor/tasks.py +37 -0
  24. codex/librarian/janitor/update.py +1 -1
  25. codex/librarian/librariand.py +37 -24
  26. codex/librarian/search/optimize.py +43 -0
  27. codex/librarian/search/remove.py +18 -46
  28. codex/librarian/search/searchd.py +14 -17
  29. codex/librarian/search/status.py +2 -1
  30. codex/librarian/search/tasks.py +4 -9
  31. codex/librarian/search/update.py +223 -301
  32. codex/librarian/watchdog/emitter.py +21 -19
  33. codex/librarian/watchdog/event_batcherd.py +0 -1
  34. codex/librarian/watchdog/events.py +4 -1
  35. codex/librarian/watchdog/observers.py +2 -1
  36. codex/migrations/0029_comicfts.py +58 -0
  37. codex/migrations/0030_nocase_collation_day_month_indexes_status_types.py +202 -0
  38. codex/models/admin.py +15 -11
  39. codex/models/base.py +9 -0
  40. codex/models/bookmark.py +3 -3
  41. codex/models/comic.py +68 -16
  42. codex/models/functions.py +60 -2
  43. codex/models/groups.py +6 -1
  44. codex/models/library.py +1 -3
  45. codex/models/paths.py +9 -3
  46. codex/models/query.py +6 -0
  47. codex/run.py +11 -9
  48. codex/serializers/admin/tasks.py +2 -2
  49. codex/serializers/browser/mixins.py +18 -14
  50. codex/serializers/browser/page.py +2 -0
  51. codex/serializers/browser/settings.py +4 -4
  52. codex/serializers/fields.py +9 -5
  53. codex/settings/settings.py +16 -17
  54. codex/signals/django_signals.py +4 -10
  55. codex/startup.py +7 -39
  56. codex/static_root/assets/VCheckbox-D_CWEmqR.84f2b49311e8.js +1 -0
  57. codex/static_root/assets/VCheckbox-D_CWEmqR.84f2b49311e8.js.br +0 -0
  58. codex/static_root/assets/VCheckbox-D_CWEmqR.84f2b49311e8.js.gz +0 -0
  59. codex/static_root/assets/VCheckbox-D_CWEmqR.js +1 -0
  60. codex/static_root/assets/VCheckbox-D_CWEmqR.js.br +0 -0
  61. codex/static_root/assets/VCheckbox-D_CWEmqR.js.gz +0 -0
  62. codex/static_root/assets/VCheckboxBtn-B1BhcFvi.0eaf3c516474.js +1 -0
  63. codex/static_root/assets/VCheckboxBtn-B1BhcFvi.0eaf3c516474.js.br +0 -0
  64. codex/static_root/assets/VCheckboxBtn-B1BhcFvi.0eaf3c516474.js.gz +0 -0
  65. codex/static_root/assets/VCheckboxBtn-B1BhcFvi.js +1 -0
  66. codex/static_root/assets/VCheckboxBtn-B1BhcFvi.js.br +0 -0
  67. codex/static_root/assets/VCheckboxBtn-B1BhcFvi.js.gz +0 -0
  68. codex/static_root/assets/VCombobox-CZAW6_3Q.0e2401e819a5.js +1 -0
  69. codex/static_root/assets/VCombobox-CZAW6_3Q.0e2401e819a5.js.br +0 -0
  70. codex/static_root/assets/VCombobox-CZAW6_3Q.0e2401e819a5.js.gz +0 -0
  71. codex/static_root/assets/VCombobox-CZAW6_3Q.js +1 -0
  72. codex/static_root/assets/VCombobox-CZAW6_3Q.js.br +0 -0
  73. codex/static_root/assets/VCombobox-CZAW6_3Q.js.gz +0 -0
  74. codex/static_root/assets/VDialog-CSHgHIlG.a0bcd336cb7b.js +1 -0
  75. codex/static_root/assets/VDialog-CSHgHIlG.a0bcd336cb7b.js.br +0 -0
  76. codex/static_root/assets/VDialog-CSHgHIlG.a0bcd336cb7b.js.gz +0 -0
  77. codex/static_root/assets/VDialog-CSHgHIlG.js +1 -0
  78. codex/static_root/assets/VDialog-CSHgHIlG.js.br +0 -0
  79. codex/static_root/assets/VDialog-CSHgHIlG.js.gz +0 -0
  80. codex/static_root/assets/VDialog-CSvrKKb2.css +1 -0
  81. codex/static_root/assets/VDialog-CSvrKKb2.css.br +0 -0
  82. codex/static_root/assets/VDialog-CSvrKKb2.css.gz +0 -0
  83. codex/static_root/assets/VDialog-CSvrKKb2.fd4d50904b17.css +1 -0
  84. codex/static_root/assets/VDialog-CSvrKKb2.fd4d50904b17.css.br +0 -0
  85. codex/static_root/assets/VDialog-CSvrKKb2.fd4d50904b17.css.gz +0 -0
  86. codex/static_root/assets/VExpansionPanels-CG6MpdMC.e96ae8afad97.js +1 -0
  87. codex/static_root/assets/VExpansionPanels-CG6MpdMC.e96ae8afad97.js.br +0 -0
  88. codex/static_root/assets/VExpansionPanels-CG6MpdMC.e96ae8afad97.js.gz +0 -0
  89. codex/static_root/assets/VExpansionPanels-CG6MpdMC.js +1 -0
  90. codex/static_root/assets/VExpansionPanels-CG6MpdMC.js.br +0 -0
  91. codex/static_root/assets/VExpansionPanels-CG6MpdMC.js.gz +0 -0
  92. codex/static_root/assets/VRadioGroup-CAgQxkiU.f26ecb0c3e34.js +1 -0
  93. codex/static_root/assets/VRadioGroup-CAgQxkiU.f26ecb0c3e34.js.br +0 -0
  94. codex/static_root/assets/VRadioGroup-CAgQxkiU.f26ecb0c3e34.js.gz +0 -0
  95. codex/static_root/assets/VRadioGroup-CAgQxkiU.js +1 -0
  96. codex/static_root/assets/VRadioGroup-CAgQxkiU.js.br +0 -0
  97. codex/static_root/assets/VRadioGroup-CAgQxkiU.js.gz +0 -0
  98. codex/static_root/assets/VSelect-C1gez8rl.9b11d2f00faf.js +1 -0
  99. codex/static_root/assets/VSelect-C1gez8rl.9b11d2f00faf.js.br +0 -0
  100. codex/static_root/assets/VSelect-C1gez8rl.9b11d2f00faf.js.gz +0 -0
  101. codex/static_root/assets/VSelect-C1gez8rl.js +1 -0
  102. codex/static_root/assets/VSelect-C1gez8rl.js.br +0 -0
  103. codex/static_root/assets/VSelect-C1gez8rl.js.gz +0 -0
  104. codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css +1 -0
  105. codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.br +0 -0
  106. codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.gz +0 -0
  107. codex/static_root/assets/VSelect-DLu8bpcs.css +1 -0
  108. codex/static_root/assets/VSelect-DLu8bpcs.css.br +0 -0
  109. codex/static_root/assets/VSelect-DLu8bpcs.css.gz +0 -0
  110. codex/static_root/assets/VSelectionControl-DBqDlKjK.160beaa1b56c.js +1 -0
  111. codex/static_root/assets/VSelectionControl-DBqDlKjK.160beaa1b56c.js.br +0 -0
  112. codex/static_root/assets/VSelectionControl-DBqDlKjK.160beaa1b56c.js.gz +0 -0
  113. codex/static_root/assets/VSelectionControl-DBqDlKjK.js +1 -0
  114. codex/static_root/assets/VSelectionControl-DBqDlKjK.js.br +0 -0
  115. codex/static_root/assets/VSelectionControl-DBqDlKjK.js.gz +0 -0
  116. codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css +1 -0
  117. codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.br +0 -0
  118. codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.gz +0 -0
  119. codex/static_root/assets/VSlideGroup-BtXPhMOT.css +1 -0
  120. codex/static_root/assets/VSlideGroup-BtXPhMOT.css.br +0 -0
  121. codex/static_root/assets/VSlideGroup-BtXPhMOT.css.gz +0 -0
  122. codex/static_root/assets/VSlideGroup-SqR_NAL1.40ba1d838a6e.js +1 -0
  123. codex/static_root/assets/VSlideGroup-SqR_NAL1.40ba1d838a6e.js.br +0 -0
  124. codex/static_root/assets/VSlideGroup-SqR_NAL1.40ba1d838a6e.js.gz +0 -0
  125. codex/static_root/assets/VSlideGroup-SqR_NAL1.js +1 -0
  126. codex/static_root/assets/VSlideGroup-SqR_NAL1.js.br +0 -0
  127. codex/static_root/assets/VSlideGroup-SqR_NAL1.js.gz +0 -0
  128. codex/static_root/assets/VTable-CYC-wMpk.8f15d66044da.js +1 -0
  129. codex/static_root/assets/VTable-CYC-wMpk.8f15d66044da.js.br +0 -0
  130. codex/static_root/assets/VTable-CYC-wMpk.8f15d66044da.js.gz +0 -0
  131. codex/static_root/assets/VTable-CYC-wMpk.js +1 -0
  132. codex/static_root/assets/VTable-CYC-wMpk.js.br +0 -0
  133. codex/static_root/assets/VTable-CYC-wMpk.js.gz +0 -0
  134. codex/static_root/assets/VTextField-BnCEPZIq.b0c32b2c0b14.css +1 -0
  135. codex/static_root/assets/VTextField-BnCEPZIq.b0c32b2c0b14.css.br +0 -0
  136. codex/static_root/assets/VTextField-BnCEPZIq.b0c32b2c0b14.css.gz +0 -0
  137. codex/static_root/assets/VTextField-BnCEPZIq.css +1 -0
  138. codex/static_root/assets/VTextField-BnCEPZIq.css.br +0 -0
  139. codex/static_root/assets/VTextField-BnCEPZIq.css.gz +0 -0
  140. codex/static_root/assets/VTextField-DMRKRbbT.911ac84d8c9d.js +1 -0
  141. codex/static_root/assets/VTextField-DMRKRbbT.911ac84d8c9d.js.br +0 -0
  142. codex/static_root/assets/VTextField-DMRKRbbT.911ac84d8c9d.js.gz +0 -0
  143. codex/static_root/assets/VTextField-DMRKRbbT.js +1 -0
  144. codex/static_root/assets/VTextField-DMRKRbbT.js.br +0 -0
  145. codex/static_root/assets/VTextField-DMRKRbbT.js.gz +0 -0
  146. codex/static_root/assets/VWindowItem-D0P2xNJl.6a10e3f3a153.js +1 -0
  147. codex/static_root/assets/VWindowItem-D0P2xNJl.6a10e3f3a153.js.br +0 -0
  148. codex/static_root/assets/VWindowItem-D0P2xNJl.6a10e3f3a153.js.gz +0 -0
  149. codex/static_root/assets/VWindowItem-D0P2xNJl.js +1 -0
  150. codex/static_root/assets/VWindowItem-D0P2xNJl.js.br +0 -0
  151. codex/static_root/assets/VWindowItem-D0P2xNJl.js.gz +0 -0
  152. codex/static_root/assets/admin-CD90VMen.4c2b6f2a5111.js +1 -0
  153. codex/static_root/assets/admin-CD90VMen.4c2b6f2a5111.js.br +0 -0
  154. codex/static_root/assets/admin-CD90VMen.4c2b6f2a5111.js.gz +0 -0
  155. codex/static_root/assets/admin-CD90VMen.js +1 -0
  156. codex/static_root/assets/admin-CD90VMen.js.br +0 -0
  157. codex/static_root/assets/admin-CD90VMen.js.gz +0 -0
  158. codex/static_root/assets/{admin-CWEjaFr5.7d4523387384.css → admin-DJ7pIXDQ.css} +1 -1
  159. codex/static_root/assets/admin-DJ7pIXDQ.css.br +0 -0
  160. codex/static_root/assets/admin-DJ7pIXDQ.css.gz +0 -0
  161. codex/static_root/assets/{admin-CWEjaFr5.css → admin-DJ7pIXDQ.e2a77af73ef2.css} +1 -1
  162. codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.br +0 -0
  163. codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.gz +0 -0
  164. codex/static_root/assets/admin-menu-B9bzD6hV.c13b7df2ff57.css +1 -0
  165. codex/static_root/assets/admin-menu-B9bzD6hV.c13b7df2ff57.css.br +0 -0
  166. codex/static_root/assets/admin-menu-B9bzD6hV.c13b7df2ff57.css.gz +0 -0
  167. codex/static_root/assets/admin-menu-B9bzD6hV.css +1 -0
  168. codex/static_root/assets/admin-menu-B9bzD6hV.css.br +0 -0
  169. codex/static_root/assets/admin-menu-B9bzD6hV.css.gz +0 -0
  170. codex/static_root/assets/admin-menu-BpEPGKr_.c9f9178c5a82.js +1 -0
  171. codex/static_root/assets/admin-menu-BpEPGKr_.c9f9178c5a82.js.br +0 -0
  172. codex/static_root/assets/admin-menu-BpEPGKr_.c9f9178c5a82.js.gz +0 -0
  173. codex/static_root/assets/admin-menu-BpEPGKr_.js +1 -0
  174. codex/static_root/assets/admin-menu-BpEPGKr_.js.br +0 -0
  175. codex/static_root/assets/admin-menu-BpEPGKr_.js.gz +0 -0
  176. codex/static_root/assets/admin-settings-button-progress-DDF4rY07.4f1158b650ab.js +1 -0
  177. codex/static_root/assets/admin-settings-button-progress-DDF4rY07.4f1158b650ab.js.br +0 -0
  178. codex/static_root/assets/admin-settings-button-progress-DDF4rY07.4f1158b650ab.js.gz +0 -0
  179. codex/static_root/assets/admin-settings-button-progress-DDF4rY07.js +1 -0
  180. codex/static_root/assets/admin-settings-button-progress-DDF4rY07.js.br +0 -0
  181. codex/static_root/assets/admin-settings-button-progress-DDF4rY07.js.gz +0 -0
  182. codex/static_root/assets/admin-settings-button-progress-DUUQfVsZ.2548c49a853e.css +1 -0
  183. codex/static_root/assets/admin-settings-button-progress-DUUQfVsZ.css +1 -0
  184. codex/static_root/assets/browser-C0KS3g2E.0bf1c9c6319c.js +1 -0
  185. codex/static_root/assets/browser-C0KS3g2E.0bf1c9c6319c.js.br +0 -0
  186. codex/static_root/assets/browser-C0KS3g2E.0bf1c9c6319c.js.gz +0 -0
  187. codex/static_root/assets/browser-C0KS3g2E.js +1 -0
  188. codex/static_root/assets/browser-C0KS3g2E.js.br +0 -0
  189. codex/static_root/assets/browser-C0KS3g2E.js.gz +0 -0
  190. codex/static_root/assets/browser-JFL2hLjt.21cb2f7335f7.css +1 -0
  191. codex/static_root/assets/browser-JFL2hLjt.21cb2f7335f7.css.br +0 -0
  192. codex/static_root/assets/browser-JFL2hLjt.21cb2f7335f7.css.gz +0 -0
  193. codex/static_root/assets/browser-JFL2hLjt.css +1 -0
  194. codex/static_root/assets/browser-JFL2hLjt.css.br +0 -0
  195. codex/static_root/assets/browser-JFL2hLjt.css.gz +0 -0
  196. codex/static_root/assets/change-password-dialog-DXJalgW4.a9f34729599d.js +1 -0
  197. codex/static_root/assets/change-password-dialog-DXJalgW4.a9f34729599d.js.br +0 -0
  198. codex/static_root/assets/change-password-dialog-DXJalgW4.a9f34729599d.js.gz +0 -0
  199. codex/static_root/assets/change-password-dialog-DXJalgW4.js +1 -0
  200. codex/static_root/assets/change-password-dialog-DXJalgW4.js.br +0 -0
  201. codex/static_root/assets/change-password-dialog-DXJalgW4.js.gz +0 -0
  202. codex/static_root/assets/change-password-dialog-DrIXdKUC.217574b45b02.css +1 -0
  203. codex/static_root/assets/change-password-dialog-DrIXdKUC.217574b45b02.css.br +0 -0
  204. codex/static_root/assets/change-password-dialog-DrIXdKUC.217574b45b02.css.gz +0 -0
  205. codex/static_root/assets/change-password-dialog-DrIXdKUC.css +1 -0
  206. codex/static_root/assets/change-password-dialog-DrIXdKUC.css.br +0 -0
  207. codex/static_root/assets/change-password-dialog-DrIXdKUC.css.gz +0 -0
  208. codex/static_root/assets/confirm-dialog-B7w6z2rf.472011c06253.css +1 -0
  209. codex/static_root/assets/confirm-dialog-B7w6z2rf.css +1 -0
  210. codex/static_root/assets/confirm-dialog-CqDEpU9k.e1811488121d.js +1 -0
  211. codex/static_root/assets/confirm-dialog-CqDEpU9k.e1811488121d.js.br +0 -0
  212. codex/static_root/assets/confirm-dialog-CqDEpU9k.e1811488121d.js.gz +0 -0
  213. codex/static_root/assets/confirm-dialog-CqDEpU9k.js +1 -0
  214. codex/static_root/assets/confirm-dialog-CqDEpU9k.js.br +0 -0
  215. codex/static_root/assets/confirm-dialog-CqDEpU9k.js.gz +0 -0
  216. codex/static_root/assets/datetime-column-UxNaJr8b.c06a11531af3.js +1 -0
  217. codex/static_root/assets/datetime-column-UxNaJr8b.c06a11531af3.js.br +0 -0
  218. codex/static_root/assets/datetime-column-UxNaJr8b.c06a11531af3.js.gz +0 -0
  219. codex/static_root/assets/datetime-column-UxNaJr8b.js +1 -0
  220. codex/static_root/assets/datetime-column-UxNaJr8b.js.br +0 -0
  221. codex/static_root/assets/datetime-column-UxNaJr8b.js.gz +0 -0
  222. codex/static_root/assets/filter-DskcqZHA.e707b5a05b4b.js +1 -0
  223. codex/static_root/assets/filter-DskcqZHA.e707b5a05b4b.js.br +0 -0
  224. codex/static_root/assets/filter-DskcqZHA.e707b5a05b4b.js.gz +0 -0
  225. codex/static_root/assets/filter-DskcqZHA.js +1 -0
  226. codex/static_root/assets/filter-DskcqZHA.js.br +0 -0
  227. codex/static_root/assets/filter-DskcqZHA.js.gz +0 -0
  228. codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css +1 -0
  229. codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.br +0 -0
  230. codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.gz +0 -0
  231. codex/static_root/assets/flag-tab-CqWovuBu.css +1 -0
  232. codex/static_root/assets/flag-tab-CqWovuBu.css.br +0 -0
  233. codex/static_root/assets/flag-tab-CqWovuBu.css.gz +0 -0
  234. codex/static_root/assets/flag-tab-xBeWEQ0w.582e77d9e885.js +1 -0
  235. codex/static_root/assets/flag-tab-xBeWEQ0w.582e77d9e885.js.br +0 -0
  236. codex/static_root/assets/flag-tab-xBeWEQ0w.582e77d9e885.js.gz +0 -0
  237. codex/static_root/assets/flag-tab-xBeWEQ0w.js +1 -0
  238. codex/static_root/assets/flag-tab-xBeWEQ0w.js.br +0 -0
  239. codex/static_root/assets/flag-tab-xBeWEQ0w.js.gz +0 -0
  240. codex/static_root/assets/group-tab-Czt2x61x.56e2886b1bac.js +1 -0
  241. codex/static_root/assets/group-tab-Czt2x61x.56e2886b1bac.js.br +0 -0
  242. codex/static_root/assets/group-tab-Czt2x61x.56e2886b1bac.js.gz +0 -0
  243. codex/static_root/assets/group-tab-Czt2x61x.js +1 -0
  244. codex/static_root/assets/group-tab-Czt2x61x.js.br +0 -0
  245. codex/static_root/assets/group-tab-Czt2x61x.js.gz +0 -0
  246. codex/static_root/assets/group-tab-DkIN1Heu.948e907b1e6b.css +1 -0
  247. codex/static_root/assets/group-tab-DkIN1Heu.948e907b1e6b.css.br +0 -0
  248. codex/static_root/assets/group-tab-DkIN1Heu.948e907b1e6b.css.gz +0 -0
  249. codex/static_root/assets/group-tab-DkIN1Heu.css +1 -0
  250. codex/static_root/assets/group-tab-DkIN1Heu.css.br +0 -0
  251. codex/static_root/assets/group-tab-DkIN1Heu.css.gz +0 -0
  252. codex/static_root/assets/http-error-NHcwE5e_.d49089e40589.js +1 -0
  253. codex/static_root/assets/http-error-NHcwE5e_.d49089e40589.js.br +0 -0
  254. codex/static_root/assets/http-error-NHcwE5e_.d49089e40589.js.gz +0 -0
  255. codex/static_root/assets/http-error-NHcwE5e_.js +1 -0
  256. codex/static_root/assets/http-error-NHcwE5e_.js.br +0 -0
  257. codex/static_root/assets/http-error-NHcwE5e_.js.gz +0 -0
  258. codex/static_root/assets/index-CL_6g4tJ.523d7b3d350f.css +1 -0
  259. codex/static_root/assets/index-CL_6g4tJ.523d7b3d350f.css.br +0 -0
  260. codex/static_root/assets/index-CL_6g4tJ.523d7b3d350f.css.gz +0 -0
  261. codex/static_root/assets/index-CL_6g4tJ.css +1 -0
  262. codex/static_root/assets/index-CL_6g4tJ.css.br +0 -0
  263. codex/static_root/assets/index-CL_6g4tJ.css.gz +0 -0
  264. codex/static_root/assets/index-DYNNO5kn.24a2d270253a.js +1 -0
  265. codex/static_root/assets/index-DYNNO5kn.24a2d270253a.js.br +0 -0
  266. codex/static_root/assets/index-DYNNO5kn.24a2d270253a.js.gz +0 -0
  267. codex/static_root/assets/index-DYNNO5kn.js +1 -0
  268. codex/static_root/assets/index-DYNNO5kn.js.br +0 -0
  269. codex/static_root/assets/index-DYNNO5kn.js.gz +0 -0
  270. codex/static_root/assets/library-tab-CgIqcjvj.60327dfa8ecb.js +1 -0
  271. codex/static_root/assets/library-tab-CgIqcjvj.60327dfa8ecb.js.br +0 -0
  272. codex/static_root/assets/library-tab-CgIqcjvj.60327dfa8ecb.js.gz +0 -0
  273. codex/static_root/assets/library-tab-CgIqcjvj.js +1 -0
  274. codex/static_root/assets/library-tab-CgIqcjvj.js.br +0 -0
  275. codex/static_root/assets/library-tab-CgIqcjvj.js.gz +0 -0
  276. codex/static_root/assets/{library-tab-Bh7ErAk7.7c44200ee727.css → library-tab-Wew8YOLv.0c1780a6b68e.css} +1 -1
  277. codex/static_root/assets/library-tab-Wew8YOLv.0c1780a6b68e.css.br +0 -0
  278. codex/static_root/assets/library-tab-Wew8YOLv.0c1780a6b68e.css.gz +0 -0
  279. codex/static_root/assets/{library-tab-Bh7ErAk7.css → library-tab-Wew8YOLv.css} +1 -1
  280. codex/static_root/assets/library-tab-Wew8YOLv.css.br +0 -0
  281. codex/static_root/assets/library-tab-Wew8YOLv.css.gz +0 -0
  282. codex/static_root/assets/main-B3EwXQ3Q.14dfc21e272c.js +35 -0
  283. codex/static_root/assets/main-B3EwXQ3Q.14dfc21e272c.js.br +0 -0
  284. codex/static_root/assets/main-B3EwXQ3Q.14dfc21e272c.js.gz +0 -0
  285. codex/static_root/assets/main-B3EwXQ3Q.js +35 -0
  286. codex/static_root/assets/main-B3EwXQ3Q.js.br +0 -0
  287. codex/static_root/assets/main-B3EwXQ3Q.js.gz +0 -0
  288. codex/static_root/assets/pager-full-pdf-YkzUXx0B.f39d84e2380a.js +1 -0
  289. codex/static_root/assets/pager-full-pdf-YkzUXx0B.f39d84e2380a.js.br +0 -0
  290. codex/static_root/assets/pager-full-pdf-YkzUXx0B.f39d84e2380a.js.gz +0 -0
  291. codex/static_root/assets/pager-full-pdf-YkzUXx0B.js +1 -0
  292. codex/static_root/assets/pager-full-pdf-YkzUXx0B.js.br +0 -0
  293. codex/static_root/assets/pager-full-pdf-YkzUXx0B.js.gz +0 -0
  294. codex/static_root/assets/pagination-toolbar-CrruiVov.3bf9b795350d.js +1 -0
  295. codex/static_root/assets/pagination-toolbar-CrruiVov.3bf9b795350d.js.br +0 -0
  296. codex/static_root/assets/pagination-toolbar-CrruiVov.3bf9b795350d.js.gz +0 -0
  297. codex/static_root/assets/pagination-toolbar-CrruiVov.js +1 -0
  298. codex/static_root/assets/pagination-toolbar-CrruiVov.js.br +0 -0
  299. codex/static_root/assets/pagination-toolbar-CrruiVov.js.gz +0 -0
  300. codex/static_root/assets/{pagination-toolbar-BzruZPpu.css → pagination-toolbar-DGrxp2OD.css} +1 -1
  301. codex/static_root/assets/pagination-toolbar-DGrxp2OD.css.br +0 -0
  302. codex/static_root/assets/pagination-toolbar-DGrxp2OD.css.gz +0 -0
  303. codex/static_root/assets/{pagination-toolbar-BzruZPpu.397ad4e3d029.css → pagination-toolbar-DGrxp2OD.f960a624f04f.css} +1 -1
  304. codex/static_root/assets/pagination-toolbar-DGrxp2OD.f960a624f04f.css.br +0 -0
  305. codex/static_root/assets/pagination-toolbar-DGrxp2OD.f960a624f04f.css.gz +0 -0
  306. codex/static_root/assets/pdf-doc-CG5-AZ2M.b94aac7e3313.css +1 -0
  307. codex/static_root/assets/pdf-doc-CG5-AZ2M.b94aac7e3313.css.br +1 -0
  308. codex/static_root/assets/pdf-doc-CG5-AZ2M.b94aac7e3313.css.gz +0 -0
  309. codex/static_root/assets/pdf-doc-CG5-AZ2M.css +1 -0
  310. codex/static_root/assets/pdf-doc-CG5-AZ2M.css.br +1 -0
  311. codex/static_root/assets/pdf-doc-CG5-AZ2M.css.gz +0 -0
  312. codex/static_root/assets/{pdf-doc-C_RhfgHE.3d82cd502628.js → pdf-doc-ctqZIwOP.7e7b2c815ea4.js} +14 -14
  313. codex/static_root/assets/pdf-doc-ctqZIwOP.7e7b2c815ea4.js.br +0 -0
  314. codex/static_root/assets/pdf-doc-ctqZIwOP.7e7b2c815ea4.js.gz +0 -0
  315. codex/static_root/assets/{pdf-doc-C_RhfgHE.js → pdf-doc-ctqZIwOP.js} +14 -14
  316. codex/static_root/assets/pdf-doc-ctqZIwOP.js.br +0 -0
  317. codex/static_root/assets/pdf-doc-ctqZIwOP.js.gz +0 -0
  318. codex/static_root/assets/reader-DPLhdrJD.268417c618c5.js +2 -0
  319. codex/static_root/assets/reader-DPLhdrJD.268417c618c5.js.br +0 -0
  320. codex/static_root/assets/reader-DPLhdrJD.268417c618c5.js.gz +0 -0
  321. codex/static_root/assets/reader-DPLhdrJD.js +2 -0
  322. codex/static_root/assets/reader-DPLhdrJD.js.br +0 -0
  323. codex/static_root/assets/reader-DPLhdrJD.js.gz +0 -0
  324. codex/static_root/assets/reader-nD70BeEz.06e85e73c391.css +1 -0
  325. codex/static_root/assets/reader-nD70BeEz.06e85e73c391.css.br +0 -0
  326. codex/static_root/assets/reader-nD70BeEz.06e85e73c391.css.gz +0 -0
  327. codex/static_root/assets/reader-nD70BeEz.css +1 -0
  328. codex/static_root/assets/reader-nD70BeEz.css.br +0 -0
  329. codex/static_root/assets/reader-nD70BeEz.css.gz +0 -0
  330. codex/static_root/assets/relation-chips-DOALMcWL.5d3b8100ba03.js +1 -0
  331. codex/static_root/assets/relation-chips-DOALMcWL.5d3b8100ba03.js.br +0 -0
  332. codex/static_root/assets/relation-chips-DOALMcWL.5d3b8100ba03.js.gz +0 -0
  333. codex/static_root/assets/relation-chips-DOALMcWL.js +1 -0
  334. codex/static_root/assets/relation-chips-DOALMcWL.js.br +0 -0
  335. codex/static_root/assets/relation-chips-DOALMcWL.js.gz +0 -0
  336. codex/static_root/assets/settings-drawer-BVj1U_LC.c68369e0c2de.js +2 -0
  337. codex/static_root/assets/settings-drawer-BVj1U_LC.c68369e0c2de.js.br +0 -0
  338. codex/static_root/assets/settings-drawer-BVj1U_LC.c68369e0c2de.js.gz +0 -0
  339. codex/static_root/assets/settings-drawer-BVj1U_LC.js +2 -0
  340. codex/static_root/assets/settings-drawer-BVj1U_LC.js.br +0 -0
  341. codex/static_root/assets/settings-drawer-BVj1U_LC.js.gz +0 -0
  342. codex/static_root/assets/{stats-tab-BXGisn5N.9b7a71e7fe28.css → stats-tab-BAYTqQNg.5f715428c394.css} +1 -1
  343. codex/static_root/assets/stats-tab-BAYTqQNg.5f715428c394.css.br +0 -0
  344. codex/static_root/assets/stats-tab-BAYTqQNg.5f715428c394.css.gz +0 -0
  345. codex/static_root/assets/{stats-tab-BXGisn5N.css → stats-tab-BAYTqQNg.css} +1 -1
  346. codex/static_root/assets/stats-tab-BAYTqQNg.css.br +0 -0
  347. codex/static_root/assets/stats-tab-BAYTqQNg.css.gz +0 -0
  348. codex/static_root/assets/stats-tab-DDLwwwnP.35305258097b.js +1 -0
  349. codex/static_root/assets/stats-tab-DDLwwwnP.35305258097b.js.br +0 -0
  350. codex/static_root/assets/stats-tab-DDLwwwnP.35305258097b.js.gz +0 -0
  351. codex/static_root/assets/stats-tab-DDLwwwnP.js +1 -0
  352. codex/static_root/assets/stats-tab-DDLwwwnP.js.br +0 -0
  353. codex/static_root/assets/stats-tab-DDLwwwnP.js.gz +0 -0
  354. codex/static_root/assets/task-tab--cXi48kg.5dfd6890a1c2.css +1 -0
  355. codex/static_root/assets/{task-tab-1XiWn9xP.06cb8e1b794d.css.br → task-tab--cXi48kg.5dfd6890a1c2.css.br} +1 -1
  356. codex/static_root/assets/task-tab--cXi48kg.5dfd6890a1c2.css.gz +0 -0
  357. codex/static_root/assets/task-tab--cXi48kg.css +1 -0
  358. codex/static_root/assets/{task-tab-1XiWn9xP.css.br → task-tab--cXi48kg.css.br} +1 -1
  359. codex/static_root/assets/task-tab--cXi48kg.css.gz +0 -0
  360. codex/static_root/assets/task-tab-BpP3n2dO.c853eb565200.js +1 -0
  361. codex/static_root/assets/task-tab-BpP3n2dO.c853eb565200.js.br +0 -0
  362. codex/static_root/assets/task-tab-BpP3n2dO.c853eb565200.js.gz +0 -0
  363. codex/static_root/assets/task-tab-BpP3n2dO.js +1 -0
  364. codex/static_root/assets/task-tab-BpP3n2dO.js.br +0 -0
  365. codex/static_root/assets/task-tab-BpP3n2dO.js.gz +0 -0
  366. codex/static_root/assets/transition-3g2arGgl.c6e6f91b7978.js +1 -0
  367. codex/static_root/assets/transition-3g2arGgl.c6e6f91b7978.js.br +0 -0
  368. codex/static_root/assets/transition-3g2arGgl.c6e6f91b7978.js.gz +0 -0
  369. codex/static_root/assets/transition-3g2arGgl.js +1 -0
  370. codex/static_root/assets/transition-3g2arGgl.js.br +0 -0
  371. codex/static_root/assets/transition-3g2arGgl.js.gz +0 -0
  372. codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css +1 -0
  373. codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.br +4 -0
  374. codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.gz +0 -0
  375. codex/static_root/assets/transition-5LRFTPo5.css +1 -0
  376. codex/static_root/assets/transition-5LRFTPo5.css.br +4 -0
  377. codex/static_root/assets/transition-5LRFTPo5.css.gz +0 -0
  378. codex/static_root/assets/{unauthorized-muDsv-rC.2166ec8b3a32.css → unauthorized-BjhIc97q.728511c92cd0.css} +1 -1
  379. codex/static_root/assets/unauthorized-BjhIc97q.728511c92cd0.css.br +0 -0
  380. codex/static_root/assets/unauthorized-BjhIc97q.728511c92cd0.css.gz +0 -0
  381. codex/static_root/assets/{unauthorized-muDsv-rC.css → unauthorized-BjhIc97q.css} +1 -1
  382. codex/static_root/assets/unauthorized-BjhIc97q.css.br +0 -0
  383. codex/static_root/assets/unauthorized-BjhIc97q.css.gz +0 -0
  384. codex/static_root/assets/unauthorized-CdumQ1Vf.79d9a61eb572.js +1 -0
  385. codex/static_root/assets/unauthorized-CdumQ1Vf.79d9a61eb572.js.br +0 -0
  386. codex/static_root/assets/unauthorized-CdumQ1Vf.79d9a61eb572.js.gz +0 -0
  387. codex/static_root/assets/unauthorized-CdumQ1Vf.js +1 -0
  388. codex/static_root/assets/unauthorized-CdumQ1Vf.js.br +0 -0
  389. codex/static_root/assets/unauthorized-CdumQ1Vf.js.gz +0 -0
  390. codex/static_root/assets/user-tab-D6oOKZTP.05944b00c700.js +1 -0
  391. codex/static_root/assets/user-tab-D6oOKZTP.05944b00c700.js.br +0 -0
  392. codex/static_root/assets/user-tab-D6oOKZTP.05944b00c700.js.gz +0 -0
  393. codex/static_root/assets/user-tab-D6oOKZTP.js +1 -0
  394. codex/static_root/assets/user-tab-D6oOKZTP.js.br +0 -0
  395. codex/static_root/assets/user-tab-D6oOKZTP.js.gz +0 -0
  396. codex/static_root/manifest.c5f1de88b1ac.json +712 -0
  397. codex/static_root/manifest.c5f1de88b1ac.json.br +0 -0
  398. codex/static_root/manifest.c5f1de88b1ac.json.gz +0 -0
  399. codex/static_root/manifest.json +395 -294
  400. codex/static_root/manifest.json.br +0 -0
  401. codex/static_root/manifest.json.gz +0 -0
  402. codex/static_root/staticfiles.json +1 -1
  403. codex/status_controller.py +15 -10
  404. codex/threads.py +1 -1
  405. codex/urls/api/auth.py +1 -1
  406. codex/urls/api/browser.py +1 -1
  407. codex/views/admin/library.py +18 -13
  408. codex/views/admin/stats.py +23 -16
  409. codex/views/admin/tasks.py +45 -40
  410. codex/views/auth.py +50 -74
  411. codex/views/bookmark.py +16 -153
  412. codex/views/browser/annotate/__init__.py +1 -0
  413. codex/views/browser/annotate/bookmark.py +112 -0
  414. codex/views/browser/annotate/card.py +61 -0
  415. codex/views/browser/annotate/order.py +247 -0
  416. codex/views/browser/breadcrumbs.py +90 -11
  417. codex/views/browser/browser.py +82 -117
  418. codex/views/browser/choices.py +15 -18
  419. codex/views/browser/cover.py +18 -24
  420. codex/views/browser/filters/bookmark.py +18 -19
  421. codex/views/browser/filters/field.py +8 -3
  422. codex/views/browser/filters/filter.py +69 -0
  423. codex/views/browser/filters/group.py +9 -6
  424. codex/views/browser/filters/search/__init__.py +1 -0
  425. codex/views/browser/filters/search/aliases.py +81 -0
  426. codex/views/browser/filters/search/field/__init__.py +1 -0
  427. codex/views/browser/filters/search/field/column.py +53 -0
  428. codex/views/browser/filters/search/field/expression.py +177 -0
  429. codex/views/browser/filters/search/field/filter.py +70 -0
  430. codex/views/browser/filters/search/field/optimize.py +71 -0
  431. codex/views/browser/filters/search/field/parse.py +187 -0
  432. codex/views/browser/filters/search/fts.py +24 -0
  433. codex/views/browser/filters/search/parse.py +250 -0
  434. codex/views/browser/group_mtime.py +83 -0
  435. codex/views/browser/metadata/__init__.py +1 -0
  436. codex/views/browser/metadata/annotate.py +109 -0
  437. codex/views/browser/metadata/copy_intersections.py +90 -0
  438. codex/views/browser/metadata/metadata.py +83 -0
  439. codex/views/browser/metadata/query_intersections.py +112 -0
  440. codex/views/browser/mtime.py +2 -10
  441. codex/views/browser/order_by.py +22 -16
  442. codex/views/browser/page_in_bounds.py +88 -0
  443. codex/views/browser/paginate.py +32 -123
  444. codex/views/browser/params.py +64 -0
  445. codex/views/browser/title.py +1 -6
  446. codex/views/browser/validate.py +68 -33
  447. codex/views/const.py +0 -1
  448. codex/views/download.py +1 -1
  449. codex/views/mixins.py +27 -15
  450. codex/views/opds/const.py +2 -3
  451. codex/views/opds/urls.py +2 -2
  452. codex/views/opds/util.py +2 -3
  453. codex/views/opds/v1/entry/links.py +3 -1
  454. codex/views/opds/v1/facets.py +65 -12
  455. codex/views/opds/v1/feed.py +7 -65
  456. codex/views/opds/v1/links.py +5 -4
  457. codex/views/opds/v2/feed.py +2 -28
  458. codex/views/opds/v2/links.py +27 -2
  459. codex/views/opds/v2/publications.py +5 -6
  460. codex/views/opds/v2/top_links.py +3 -6
  461. codex/views/public.py +2 -2
  462. codex/views/reader/arcs.py +0 -3
  463. codex/views/reader/books.py +57 -41
  464. codex/views/reader/page.py +13 -7
  465. codex/views/reader/{init.py → params.py} +38 -32
  466. codex/views/reader/reader.py +1 -2
  467. codex/views/session.py +43 -54
  468. codex/views/timezone.py +54 -0
  469. codex/views/version.py +1 -1
  470. {codex-1.6.18.dist-info → codex-1.7.0.dist-info}/METADATA +15 -10
  471. {codex-1.6.18.dist-info → codex-1.7.0.dist-info}/RECORD +474 -485
  472. codex/_vendor/__init__.py +0 -0
  473. codex/_vendor/django_haystack-3.2.1.dist-info/AUTHORS +0 -127
  474. codex/_vendor/django_haystack-3.2.1.dist-info/INSTALLER +0 -1
  475. codex/_vendor/django_haystack-3.2.1.dist-info/LICENSE +0 -31
  476. codex/_vendor/django_haystack-3.2.1.dist-info/METADATA +0 -98
  477. codex/_vendor/django_haystack-3.2.1.dist-info/RECORD +0 -97
  478. codex/_vendor/django_haystack-3.2.1.dist-info/REQUESTED +0 -0
  479. codex/_vendor/django_haystack-3.2.1.dist-info/WHEEL +0 -5
  480. codex/_vendor/django_haystack-3.2.1.dist-info/top_level.txt +0 -1
  481. codex/_vendor/haystack/__init__.py +0 -80
  482. codex/_vendor/haystack/admin.py +0 -163
  483. codex/_vendor/haystack/apps.py +0 -31
  484. codex/_vendor/haystack/backends/__init__.py +0 -1109
  485. codex/_vendor/haystack/backends/elasticsearch2_backend.py +0 -390
  486. codex/_vendor/haystack/backends/elasticsearch5_backend.py +0 -483
  487. codex/_vendor/haystack/backends/elasticsearch7_backend.py +0 -586
  488. codex/_vendor/haystack/backends/elasticsearch_backend.py +0 -1141
  489. codex/_vendor/haystack/backends/simple_backend.py +0 -132
  490. codex/_vendor/haystack/backends/solr_backend.py +0 -991
  491. codex/_vendor/haystack/backends/whoosh_backend.py +0 -1104
  492. codex/_vendor/haystack/constants.py +0 -57
  493. codex/_vendor/haystack/exceptions.py +0 -57
  494. codex/_vendor/haystack/fields.py +0 -562
  495. codex/_vendor/haystack/forms.py +0 -135
  496. codex/_vendor/haystack/generic_views.py +0 -141
  497. codex/_vendor/haystack/indexes.py +0 -548
  498. codex/_vendor/haystack/inputs.py +0 -169
  499. codex/_vendor/haystack/management/__init__.py +0 -0
  500. codex/_vendor/haystack/management/commands/__init__.py +0 -0
  501. codex/_vendor/haystack/management/commands/build_solr_schema.py +0 -187
  502. codex/_vendor/haystack/management/commands/clear_index.py +0 -67
  503. codex/_vendor/haystack/management/commands/haystack_info.py +0 -22
  504. codex/_vendor/haystack/management/commands/rebuild_index.py +0 -65
  505. codex/_vendor/haystack/management/commands/update_index.py +0 -438
  506. codex/_vendor/haystack/manager.py +0 -105
  507. codex/_vendor/haystack/models.py +0 -257
  508. codex/_vendor/haystack/panels.py +0 -89
  509. codex/_vendor/haystack/query.py +0 -771
  510. codex/_vendor/haystack/routers.py +0 -14
  511. codex/_vendor/haystack/signals.py +0 -88
  512. codex/_vendor/haystack/templates/panels/haystack.html +0 -33
  513. codex/_vendor/haystack/templates/search_configuration/schema.xml +0 -1056
  514. codex/_vendor/haystack/templates/search_configuration/solrconfig.xml +0 -1446
  515. codex/_vendor/haystack/templatetags/__init__.py +0 -0
  516. codex/_vendor/haystack/templatetags/highlight.py +0 -131
  517. codex/_vendor/haystack/templatetags/more_like_this.py +0 -119
  518. codex/_vendor/haystack/urls.py +0 -5
  519. codex/_vendor/haystack/utils/__init__.py +0 -84
  520. codex/_vendor/haystack/utils/app_loading.py +0 -34
  521. codex/_vendor/haystack/utils/geo.py +0 -71
  522. codex/_vendor/haystack/utils/highlighting.py +0 -165
  523. codex/_vendor/haystack/utils/loading.py +0 -374
  524. codex/_vendor/haystack/utils/log.py +0 -21
  525. codex/_vendor/haystack/version.py +0 -16
  526. codex/_vendor/haystack/views.py +0 -253
  527. codex/integrity.py +0 -492
  528. codex/librarian/search/merge.py +0 -86
  529. codex/librarian/search/version.py +0 -63
  530. codex/search/__init__.py +0 -1
  531. codex/search/backend.py +0 -524
  532. codex/search/backend_search.py +0 -229
  533. codex/search/engine.py +0 -33
  534. codex/search/indexes.py +0 -79
  535. codex/search/query.py +0 -67
  536. codex/search/writing.py +0 -180
  537. codex/serializers/choices.py +0 -196
  538. codex/static_root/assets/VCheckbox-D_kRyvnz.981ece08698f.js +0 -1
  539. codex/static_root/assets/VCheckbox-D_kRyvnz.981ece08698f.js.br +0 -0
  540. codex/static_root/assets/VCheckbox-D_kRyvnz.981ece08698f.js.gz +0 -0
  541. codex/static_root/assets/VCheckbox-D_kRyvnz.js +0 -1
  542. codex/static_root/assets/VCheckbox-D_kRyvnz.js.br +0 -0
  543. codex/static_root/assets/VCheckbox-D_kRyvnz.js.gz +0 -0
  544. codex/static_root/assets/VCheckboxBtn-CasNFNDK.3c20f8d4f5d9.js +0 -1
  545. codex/static_root/assets/VCheckboxBtn-CasNFNDK.3c20f8d4f5d9.js.br +0 -0
  546. codex/static_root/assets/VCheckboxBtn-CasNFNDK.3c20f8d4f5d9.js.gz +0 -0
  547. codex/static_root/assets/VCheckboxBtn-CasNFNDK.js +0 -1
  548. codex/static_root/assets/VCheckboxBtn-CasNFNDK.js.br +0 -0
  549. codex/static_root/assets/VCheckboxBtn-CasNFNDK.js.gz +0 -0
  550. codex/static_root/assets/VCombobox-BemG8ph3.afde3fec668d.js +0 -1
  551. codex/static_root/assets/VCombobox-BemG8ph3.afde3fec668d.js.br +0 -0
  552. codex/static_root/assets/VCombobox-BemG8ph3.afde3fec668d.js.gz +0 -0
  553. codex/static_root/assets/VCombobox-BemG8ph3.js +0 -1
  554. codex/static_root/assets/VCombobox-BemG8ph3.js.br +0 -0
  555. codex/static_root/assets/VCombobox-BemG8ph3.js.gz +0 -0
  556. codex/static_root/assets/VDialog-38np3TSA.5a0cb7a9e56d.css +0 -1
  557. codex/static_root/assets/VDialog-38np3TSA.5a0cb7a9e56d.css.br +0 -0
  558. codex/static_root/assets/VDialog-38np3TSA.5a0cb7a9e56d.css.gz +0 -0
  559. codex/static_root/assets/VDialog-38np3TSA.css +0 -1
  560. codex/static_root/assets/VDialog-38np3TSA.css.br +0 -0
  561. codex/static_root/assets/VDialog-38np3TSA.css.gz +0 -0
  562. codex/static_root/assets/VDialog-DOm1w6bL.3a8bac3e555f.js +0 -1
  563. codex/static_root/assets/VDialog-DOm1w6bL.3a8bac3e555f.js.br +0 -0
  564. codex/static_root/assets/VDialog-DOm1w6bL.3a8bac3e555f.js.gz +0 -0
  565. codex/static_root/assets/VDialog-DOm1w6bL.js +0 -1
  566. codex/static_root/assets/VDialog-DOm1w6bL.js.br +0 -0
  567. codex/static_root/assets/VDialog-DOm1w6bL.js.gz +0 -0
  568. codex/static_root/assets/VExpansionPanels-BIAAQEIk.536cfca15bf5.js +0 -1
  569. codex/static_root/assets/VExpansionPanels-BIAAQEIk.536cfca15bf5.js.br +0 -0
  570. codex/static_root/assets/VExpansionPanels-BIAAQEIk.536cfca15bf5.js.gz +0 -0
  571. codex/static_root/assets/VExpansionPanels-BIAAQEIk.js +0 -1
  572. codex/static_root/assets/VExpansionPanels-BIAAQEIk.js.br +0 -0
  573. codex/static_root/assets/VExpansionPanels-BIAAQEIk.js.gz +0 -0
  574. codex/static_root/assets/VRadioGroup-CQd2B2cC.5484da094948.js +0 -1
  575. codex/static_root/assets/VRadioGroup-CQd2B2cC.5484da094948.js.br +0 -0
  576. codex/static_root/assets/VRadioGroup-CQd2B2cC.5484da094948.js.gz +0 -0
  577. codex/static_root/assets/VRadioGroup-CQd2B2cC.js +0 -1
  578. codex/static_root/assets/VRadioGroup-CQd2B2cC.js.br +0 -0
  579. codex/static_root/assets/VRadioGroup-CQd2B2cC.js.gz +0 -0
  580. codex/static_root/assets/VSelect-Ca2bIOso.6613989e4c45.css +0 -1
  581. codex/static_root/assets/VSelect-Ca2bIOso.6613989e4c45.css.br +0 -0
  582. codex/static_root/assets/VSelect-Ca2bIOso.6613989e4c45.css.gz +0 -0
  583. codex/static_root/assets/VSelect-Ca2bIOso.css +0 -1
  584. codex/static_root/assets/VSelect-Ca2bIOso.css.br +0 -0
  585. codex/static_root/assets/VSelect-Ca2bIOso.css.gz +0 -0
  586. codex/static_root/assets/VSelect-DhYHkIlU.fcb6b4997b19.js +0 -1
  587. codex/static_root/assets/VSelect-DhYHkIlU.fcb6b4997b19.js.br +0 -0
  588. codex/static_root/assets/VSelect-DhYHkIlU.fcb6b4997b19.js.gz +0 -0
  589. codex/static_root/assets/VSelect-DhYHkIlU.js +0 -1
  590. codex/static_root/assets/VSelect-DhYHkIlU.js.br +0 -0
  591. codex/static_root/assets/VSelect-DhYHkIlU.js.gz +0 -0
  592. codex/static_root/assets/VSelectionControl-DZ7Z3QaY.753a2564123a.js +0 -1
  593. codex/static_root/assets/VSelectionControl-DZ7Z3QaY.753a2564123a.js.br +0 -0
  594. codex/static_root/assets/VSelectionControl-DZ7Z3QaY.753a2564123a.js.gz +0 -0
  595. codex/static_root/assets/VSelectionControl-DZ7Z3QaY.js +0 -1
  596. codex/static_root/assets/VSelectionControl-DZ7Z3QaY.js.br +0 -0
  597. codex/static_root/assets/VSelectionControl-DZ7Z3QaY.js.gz +0 -0
  598. codex/static_root/assets/VSlideGroup-BfZo3lM5.0ffb08d15ccd.js +0 -1
  599. codex/static_root/assets/VSlideGroup-BfZo3lM5.0ffb08d15ccd.js.br +0 -0
  600. codex/static_root/assets/VSlideGroup-BfZo3lM5.0ffb08d15ccd.js.gz +0 -0
  601. codex/static_root/assets/VSlideGroup-BfZo3lM5.js +0 -1
  602. codex/static_root/assets/VSlideGroup-BfZo3lM5.js.br +0 -0
  603. codex/static_root/assets/VSlideGroup-BfZo3lM5.js.gz +0 -0
  604. codex/static_root/assets/VSlideGroup-Dk_1upHt.2c836070ec75.css +0 -1
  605. codex/static_root/assets/VSlideGroup-Dk_1upHt.2c836070ec75.css.br +0 -0
  606. codex/static_root/assets/VSlideGroup-Dk_1upHt.2c836070ec75.css.gz +0 -0
  607. codex/static_root/assets/VSlideGroup-Dk_1upHt.css +0 -1
  608. codex/static_root/assets/VSlideGroup-Dk_1upHt.css.br +0 -0
  609. codex/static_root/assets/VSlideGroup-Dk_1upHt.css.gz +0 -0
  610. codex/static_root/assets/VTable-xJS8rtC3.456750dc5d3f.js +0 -1
  611. codex/static_root/assets/VTable-xJS8rtC3.456750dc5d3f.js.br +0 -0
  612. codex/static_root/assets/VTable-xJS8rtC3.456750dc5d3f.js.gz +0 -0
  613. codex/static_root/assets/VTable-xJS8rtC3.js +0 -1
  614. codex/static_root/assets/VTable-xJS8rtC3.js.br +0 -0
  615. codex/static_root/assets/VTable-xJS8rtC3.js.gz +0 -0
  616. codex/static_root/assets/VTextField-CWKnATIB.7e07951afd27.js +0 -1
  617. codex/static_root/assets/VTextField-CWKnATIB.7e07951afd27.js.br +0 -0
  618. codex/static_root/assets/VTextField-CWKnATIB.7e07951afd27.js.gz +0 -0
  619. codex/static_root/assets/VTextField-CWKnATIB.js +0 -1
  620. codex/static_root/assets/VTextField-CWKnATIB.js.br +0 -0
  621. codex/static_root/assets/VTextField-CWKnATIB.js.gz +0 -0
  622. codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css +0 -1
  623. codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.br +0 -0
  624. codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.gz +0 -0
  625. codex/static_root/assets/VTextField-Crc3gdNh.css +0 -1
  626. codex/static_root/assets/VTextField-Crc3gdNh.css.br +0 -0
  627. codex/static_root/assets/VTextField-Crc3gdNh.css.gz +0 -0
  628. codex/static_root/assets/VWindowItem-COG2FuUz.12a198f11fe7.js +0 -1
  629. codex/static_root/assets/VWindowItem-COG2FuUz.12a198f11fe7.js.br +0 -0
  630. codex/static_root/assets/VWindowItem-COG2FuUz.12a198f11fe7.js.gz +0 -0
  631. codex/static_root/assets/VWindowItem-COG2FuUz.js +0 -1
  632. codex/static_root/assets/VWindowItem-COG2FuUz.js.br +0 -0
  633. codex/static_root/assets/VWindowItem-COG2FuUz.js.gz +0 -0
  634. codex/static_root/assets/admin-CWEjaFr5.7d4523387384.css.br +0 -0
  635. codex/static_root/assets/admin-CWEjaFr5.7d4523387384.css.gz +0 -0
  636. codex/static_root/assets/admin-CWEjaFr5.css.br +0 -0
  637. codex/static_root/assets/admin-CWEjaFr5.css.gz +0 -0
  638. codex/static_root/assets/admin-Dl2A7cx-.5fbd345dbc05.js +0 -1
  639. codex/static_root/assets/admin-Dl2A7cx-.5fbd345dbc05.js.br +0 -0
  640. codex/static_root/assets/admin-Dl2A7cx-.5fbd345dbc05.js.gz +0 -0
  641. codex/static_root/assets/admin-Dl2A7cx-.js +0 -1
  642. codex/static_root/assets/admin-Dl2A7cx-.js.br +0 -0
  643. codex/static_root/assets/admin-Dl2A7cx-.js.gz +0 -0
  644. codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.3cb33056e994.css +0 -1
  645. codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.3cb33056e994.css.br +0 -0
  646. codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.3cb33056e994.css.gz +0 -0
  647. codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.css +0 -1
  648. codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.css.br +0 -0
  649. codex/static_root/assets/admin-drawer-panel-Bs2wgKj3.css.gz +0 -0
  650. codex/static_root/assets/admin-drawer-panel-D4CYCd_H.fd8dcc769daf.js +0 -30
  651. codex/static_root/assets/admin-drawer-panel-D4CYCd_H.fd8dcc769daf.js.br +0 -0
  652. codex/static_root/assets/admin-drawer-panel-D4CYCd_H.fd8dcc769daf.js.gz +0 -0
  653. codex/static_root/assets/admin-drawer-panel-D4CYCd_H.js +0 -30
  654. codex/static_root/assets/admin-drawer-panel-D4CYCd_H.js.br +0 -0
  655. codex/static_root/assets/admin-drawer-panel-D4CYCd_H.js.gz +0 -0
  656. codex/static_root/assets/browser-Binc3n9H.313722d27ca3.css +0 -1
  657. codex/static_root/assets/browser-Binc3n9H.313722d27ca3.css.br +0 -0
  658. codex/static_root/assets/browser-Binc3n9H.313722d27ca3.css.gz +0 -0
  659. codex/static_root/assets/browser-Binc3n9H.css +0 -1
  660. codex/static_root/assets/browser-Binc3n9H.css.br +0 -0
  661. codex/static_root/assets/browser-Binc3n9H.css.gz +0 -0
  662. codex/static_root/assets/browser-DOhldfGx.43465be961b0.js +0 -1
  663. codex/static_root/assets/browser-DOhldfGx.43465be961b0.js.br +0 -0
  664. codex/static_root/assets/browser-DOhldfGx.43465be961b0.js.gz +0 -0
  665. codex/static_root/assets/browser-DOhldfGx.js +0 -1
  666. codex/static_root/assets/browser-DOhldfGx.js.br +0 -0
  667. codex/static_root/assets/browser-DOhldfGx.js.gz +0 -0
  668. codex/static_root/assets/change-password-dialog-Cebek1-c.aff2975e31f8.css +0 -1
  669. codex/static_root/assets/change-password-dialog-Cebek1-c.aff2975e31f8.css.br +0 -0
  670. codex/static_root/assets/change-password-dialog-Cebek1-c.aff2975e31f8.css.gz +0 -0
  671. codex/static_root/assets/change-password-dialog-Cebek1-c.css +0 -1
  672. codex/static_root/assets/change-password-dialog-Cebek1-c.css.br +0 -0
  673. codex/static_root/assets/change-password-dialog-Cebek1-c.css.gz +0 -0
  674. codex/static_root/assets/change-password-dialog-CrIdNi1F.9451b8d8e301.js +0 -1
  675. codex/static_root/assets/change-password-dialog-CrIdNi1F.9451b8d8e301.js.br +0 -0
  676. codex/static_root/assets/change-password-dialog-CrIdNi1F.9451b8d8e301.js.gz +0 -0
  677. codex/static_root/assets/change-password-dialog-CrIdNi1F.js +0 -1
  678. codex/static_root/assets/change-password-dialog-CrIdNi1F.js.br +0 -0
  679. codex/static_root/assets/change-password-dialog-CrIdNi1F.js.gz +0 -0
  680. codex/static_root/assets/confirm-dialog-B8T3Aamf.5d5b5715840a.js +0 -1
  681. codex/static_root/assets/confirm-dialog-B8T3Aamf.5d5b5715840a.js.br +0 -0
  682. codex/static_root/assets/confirm-dialog-B8T3Aamf.5d5b5715840a.js.gz +0 -0
  683. codex/static_root/assets/confirm-dialog-B8T3Aamf.js +0 -1
  684. codex/static_root/assets/confirm-dialog-B8T3Aamf.js.br +0 -0
  685. codex/static_root/assets/confirm-dialog-B8T3Aamf.js.gz +0 -0
  686. codex/static_root/assets/confirm-dialog-BmhedLCx.7c2103d319d4.css +0 -1
  687. codex/static_root/assets/confirm-dialog-BmhedLCx.css +0 -1
  688. codex/static_root/assets/datetime-column-DJjaMFv9.d281fe18446a.js +0 -1
  689. codex/static_root/assets/datetime-column-DJjaMFv9.d281fe18446a.js.br +0 -0
  690. codex/static_root/assets/datetime-column-DJjaMFv9.d281fe18446a.js.gz +0 -0
  691. codex/static_root/assets/datetime-column-DJjaMFv9.js +0 -1
  692. codex/static_root/assets/datetime-column-DJjaMFv9.js.br +0 -0
  693. codex/static_root/assets/datetime-column-DJjaMFv9.js.gz +0 -0
  694. codex/static_root/assets/filter-DMpQdE_u.8d88bbf01ae8.js +0 -1
  695. codex/static_root/assets/filter-DMpQdE_u.8d88bbf01ae8.js.br +0 -0
  696. codex/static_root/assets/filter-DMpQdE_u.8d88bbf01ae8.js.gz +0 -0
  697. codex/static_root/assets/filter-DMpQdE_u.js +0 -1
  698. codex/static_root/assets/filter-DMpQdE_u.js.br +0 -0
  699. codex/static_root/assets/filter-DMpQdE_u.js.gz +0 -0
  700. codex/static_root/assets/flag-tab-C2TvU4CO.7b424d4fedb2.js +0 -1
  701. codex/static_root/assets/flag-tab-C2TvU4CO.7b424d4fedb2.js.br +0 -0
  702. codex/static_root/assets/flag-tab-C2TvU4CO.7b424d4fedb2.js.gz +0 -0
  703. codex/static_root/assets/flag-tab-C2TvU4CO.js +0 -1
  704. codex/static_root/assets/flag-tab-C2TvU4CO.js.br +0 -0
  705. codex/static_root/assets/flag-tab-C2TvU4CO.js.gz +0 -0
  706. codex/static_root/assets/flag-tab-DBqpLKi7.css +0 -1
  707. codex/static_root/assets/flag-tab-DBqpLKi7.css.br +0 -0
  708. codex/static_root/assets/flag-tab-DBqpLKi7.css.gz +0 -0
  709. codex/static_root/assets/flag-tab-DBqpLKi7.dcfef39f541e.css +0 -1
  710. codex/static_root/assets/flag-tab-DBqpLKi7.dcfef39f541e.css.br +0 -0
  711. codex/static_root/assets/flag-tab-DBqpLKi7.dcfef39f541e.css.gz +0 -0
  712. codex/static_root/assets/group-tab-BOX6rJuK.58304d7d9f28.js +0 -1
  713. codex/static_root/assets/group-tab-BOX6rJuK.58304d7d9f28.js.br +0 -0
  714. codex/static_root/assets/group-tab-BOX6rJuK.58304d7d9f28.js.gz +0 -0
  715. codex/static_root/assets/group-tab-BOX6rJuK.js +0 -1
  716. codex/static_root/assets/group-tab-BOX6rJuK.js.br +0 -0
  717. codex/static_root/assets/group-tab-BOX6rJuK.js.gz +0 -0
  718. codex/static_root/assets/group-tab-CBKuS3Iv.7e4746634782.css +0 -1
  719. codex/static_root/assets/group-tab-CBKuS3Iv.7e4746634782.css.br +0 -0
  720. codex/static_root/assets/group-tab-CBKuS3Iv.7e4746634782.css.gz +0 -0
  721. codex/static_root/assets/group-tab-CBKuS3Iv.css +0 -1
  722. codex/static_root/assets/group-tab-CBKuS3Iv.css.br +0 -0
  723. codex/static_root/assets/group-tab-CBKuS3Iv.css.gz +0 -0
  724. codex/static_root/assets/http-error-E90fvnsx.103df54057a6.js +0 -1
  725. codex/static_root/assets/http-error-E90fvnsx.103df54057a6.js.br +0 -0
  726. codex/static_root/assets/http-error-E90fvnsx.103df54057a6.js.gz +0 -0
  727. codex/static_root/assets/http-error-E90fvnsx.js +0 -1
  728. codex/static_root/assets/http-error-E90fvnsx.js.br +0 -0
  729. codex/static_root/assets/http-error-E90fvnsx.js.gz +0 -0
  730. codex/static_root/assets/library-tab-Bh7ErAk7.7c44200ee727.css.br +0 -2
  731. codex/static_root/assets/library-tab-Bh7ErAk7.7c44200ee727.css.gz +0 -0
  732. codex/static_root/assets/library-tab-Bh7ErAk7.css.br +0 -2
  733. codex/static_root/assets/library-tab-Bh7ErAk7.css.gz +0 -0
  734. codex/static_root/assets/library-tab-DoLAFv6A.e504e9181e22.js +0 -1
  735. codex/static_root/assets/library-tab-DoLAFv6A.e504e9181e22.js.br +0 -0
  736. codex/static_root/assets/library-tab-DoLAFv6A.e504e9181e22.js.gz +0 -0
  737. codex/static_root/assets/library-tab-DoLAFv6A.js +0 -1
  738. codex/static_root/assets/library-tab-DoLAFv6A.js.br +0 -0
  739. codex/static_root/assets/library-tab-DoLAFv6A.js.gz +0 -0
  740. codex/static_root/assets/main-BnyyRHtu.383bd5bdf135.js +0 -6
  741. codex/static_root/assets/main-BnyyRHtu.383bd5bdf135.js.br +0 -0
  742. codex/static_root/assets/main-BnyyRHtu.383bd5bdf135.js.gz +0 -0
  743. codex/static_root/assets/main-BnyyRHtu.js +0 -6
  744. codex/static_root/assets/main-BnyyRHtu.js.br +0 -0
  745. codex/static_root/assets/main-BnyyRHtu.js.gz +0 -0
  746. codex/static_root/assets/pagination-toolbar-B-H-BgUh.0485a41335d7.js +0 -1
  747. codex/static_root/assets/pagination-toolbar-B-H-BgUh.0485a41335d7.js.br +0 -0
  748. codex/static_root/assets/pagination-toolbar-B-H-BgUh.0485a41335d7.js.gz +0 -0
  749. codex/static_root/assets/pagination-toolbar-B-H-BgUh.js +0 -1
  750. codex/static_root/assets/pagination-toolbar-B-H-BgUh.js.br +0 -0
  751. codex/static_root/assets/pagination-toolbar-B-H-BgUh.js.gz +0 -0
  752. codex/static_root/assets/pagination-toolbar-BzruZPpu.397ad4e3d029.css.br +0 -0
  753. codex/static_root/assets/pagination-toolbar-BzruZPpu.397ad4e3d029.css.gz +0 -0
  754. codex/static_root/assets/pagination-toolbar-BzruZPpu.css.br +0 -0
  755. codex/static_root/assets/pagination-toolbar-BzruZPpu.css.gz +0 -0
  756. codex/static_root/assets/pdf-doc-C_RhfgHE.3d82cd502628.js.br +0 -0
  757. codex/static_root/assets/pdf-doc-C_RhfgHE.3d82cd502628.js.gz +0 -0
  758. codex/static_root/assets/pdf-doc-C_RhfgHE.js.br +0 -0
  759. codex/static_root/assets/pdf-doc-C_RhfgHE.js.gz +0 -0
  760. codex/static_root/assets/pdf-doc-CkC2e3rI.css +0 -1
  761. codex/static_root/assets/pdf-doc-CkC2e3rI.css.br +0 -0
  762. codex/static_root/assets/pdf-doc-CkC2e3rI.css.gz +0 -0
  763. codex/static_root/assets/pdf-doc-CkC2e3rI.da75c385ebd0.css +0 -1
  764. codex/static_root/assets/pdf-doc-CkC2e3rI.da75c385ebd0.css.br +0 -0
  765. codex/static_root/assets/pdf-doc-CkC2e3rI.da75c385ebd0.css.gz +0 -0
  766. codex/static_root/assets/reader-DkEfQBw-.5e7781a737e6.css +0 -1
  767. codex/static_root/assets/reader-DkEfQBw-.5e7781a737e6.css.br +0 -0
  768. codex/static_root/assets/reader-DkEfQBw-.5e7781a737e6.css.gz +0 -0
  769. codex/static_root/assets/reader-DkEfQBw-.css +0 -1
  770. codex/static_root/assets/reader-DkEfQBw-.css.br +0 -0
  771. codex/static_root/assets/reader-DkEfQBw-.css.gz +0 -0
  772. codex/static_root/assets/reader-K27K1JrT.faa6edbda846.js +0 -2
  773. codex/static_root/assets/reader-K27K1JrT.faa6edbda846.js.br +0 -0
  774. codex/static_root/assets/reader-K27K1JrT.faa6edbda846.js.gz +0 -0
  775. codex/static_root/assets/reader-K27K1JrT.js +0 -2
  776. codex/static_root/assets/reader-K27K1JrT.js.br +0 -0
  777. codex/static_root/assets/reader-K27K1JrT.js.gz +0 -0
  778. codex/static_root/assets/relation-chips-CfHz9Cgt.ce0ab88180d5.js +0 -1
  779. codex/static_root/assets/relation-chips-CfHz9Cgt.ce0ab88180d5.js.br +0 -0
  780. codex/static_root/assets/relation-chips-CfHz9Cgt.ce0ab88180d5.js.gz +0 -0
  781. codex/static_root/assets/relation-chips-CfHz9Cgt.js +0 -1
  782. codex/static_root/assets/relation-chips-CfHz9Cgt.js.br +0 -0
  783. codex/static_root/assets/relation-chips-CfHz9Cgt.js.gz +0 -0
  784. codex/static_root/assets/settings-drawer-CF0z39tG.bb0427409b01.js +0 -2
  785. codex/static_root/assets/settings-drawer-CF0z39tG.bb0427409b01.js.br +0 -0
  786. codex/static_root/assets/settings-drawer-CF0z39tG.bb0427409b01.js.gz +0 -0
  787. codex/static_root/assets/settings-drawer-CF0z39tG.js +0 -2
  788. codex/static_root/assets/settings-drawer-CF0z39tG.js.br +0 -0
  789. codex/static_root/assets/settings-drawer-CF0z39tG.js.gz +0 -0
  790. codex/static_root/assets/stats-tab-BXGisn5N.9b7a71e7fe28.css.br +0 -0
  791. codex/static_root/assets/stats-tab-BXGisn5N.9b7a71e7fe28.css.gz +0 -0
  792. codex/static_root/assets/stats-tab-BXGisn5N.css.br +0 -0
  793. codex/static_root/assets/stats-tab-BXGisn5N.css.gz +0 -0
  794. codex/static_root/assets/stats-tab-m4jtc5tB.fe5a865d950f.js +0 -1
  795. codex/static_root/assets/stats-tab-m4jtc5tB.fe5a865d950f.js.br +0 -0
  796. codex/static_root/assets/stats-tab-m4jtc5tB.fe5a865d950f.js.gz +0 -0
  797. codex/static_root/assets/stats-tab-m4jtc5tB.js +0 -1
  798. codex/static_root/assets/stats-tab-m4jtc5tB.js.br +0 -0
  799. codex/static_root/assets/stats-tab-m4jtc5tB.js.gz +0 -0
  800. codex/static_root/assets/task-tab-1XiWn9xP.06cb8e1b794d.css +0 -1
  801. codex/static_root/assets/task-tab-1XiWn9xP.06cb8e1b794d.css.gz +0 -0
  802. codex/static_root/assets/task-tab-1XiWn9xP.css +0 -1
  803. codex/static_root/assets/task-tab-1XiWn9xP.css.gz +0 -0
  804. codex/static_root/assets/task-tab-Bn04U_1c.3b343f42f0a9.js +0 -1
  805. codex/static_root/assets/task-tab-Bn04U_1c.3b343f42f0a9.js.br +0 -0
  806. codex/static_root/assets/task-tab-Bn04U_1c.3b343f42f0a9.js.gz +0 -0
  807. codex/static_root/assets/task-tab-Bn04U_1c.js +0 -1
  808. codex/static_root/assets/task-tab-Bn04U_1c.js.br +0 -0
  809. codex/static_root/assets/task-tab-Bn04U_1c.js.gz +0 -0
  810. codex/static_root/assets/unauthorized-CFFrmehB.25307184f821.js +0 -1
  811. codex/static_root/assets/unauthorized-CFFrmehB.25307184f821.js.br +0 -0
  812. codex/static_root/assets/unauthorized-CFFrmehB.25307184f821.js.gz +0 -0
  813. codex/static_root/assets/unauthorized-CFFrmehB.js +0 -1
  814. codex/static_root/assets/unauthorized-CFFrmehB.js.br +0 -0
  815. codex/static_root/assets/unauthorized-CFFrmehB.js.gz +0 -0
  816. codex/static_root/assets/unauthorized-muDsv-rC.2166ec8b3a32.css.br +0 -0
  817. codex/static_root/assets/unauthorized-muDsv-rC.2166ec8b3a32.css.gz +0 -0
  818. codex/static_root/assets/unauthorized-muDsv-rC.css.br +0 -0
  819. codex/static_root/assets/unauthorized-muDsv-rC.css.gz +0 -0
  820. codex/static_root/assets/user-tab-Bc0BOX75.96057d32f1e9.js +0 -1
  821. codex/static_root/assets/user-tab-Bc0BOX75.96057d32f1e9.js.br +0 -0
  822. codex/static_root/assets/user-tab-Bc0BOX75.96057d32f1e9.js.gz +0 -0
  823. codex/static_root/assets/user-tab-Bc0BOX75.js +0 -1
  824. codex/static_root/assets/user-tab-Bc0BOX75.js.br +0 -0
  825. codex/static_root/assets/user-tab-Bc0BOX75.js.gz +0 -0
  826. codex/static_root/js/choices-admin.1a20a5648f20.json +0 -1
  827. codex/static_root/js/choices-admin.1a20a5648f20.json.br +0 -0
  828. codex/static_root/js/choices-admin.1a20a5648f20.json.gz +0 -0
  829. codex/static_root/js/choices-admin.json +0 -1
  830. codex/static_root/js/choices-admin.json.br +0 -0
  831. codex/static_root/js/choices-admin.json.gz +0 -0
  832. codex/static_root/js/choices.2f6b0359e1ef.json +0 -1
  833. codex/static_root/js/choices.2f6b0359e1ef.json.br +0 -0
  834. codex/static_root/js/choices.2f6b0359e1ef.json.gz +0 -0
  835. codex/static_root/js/choices.json +0 -1
  836. codex/static_root/js/choices.json.br +0 -0
  837. codex/static_root/js/choices.json.gz +0 -0
  838. codex/static_root/manifest.5127f11299cc.json +0 -611
  839. codex/static_root/manifest.5127f11299cc.json.br +0 -0
  840. codex/static_root/manifest.5127f11299cc.json.gz +0 -0
  841. codex/templates/search/indexes/codex/comic_text.txt +0 -47
  842. codex/views/browser/annotations.py +0 -296
  843. codex/views/browser/base.py +0 -140
  844. codex/views/browser/filters/annotations.py +0 -103
  845. codex/views/browser/filters/search.py +0 -196
  846. codex/views/browser/metadata.py +0 -332
  847. {codex-1.6.18.dist-info → codex-1.7.0.dist-info}/LICENSE +0 -0
  848. {codex-1.6.18.dist-info → codex-1.7.0.dist-info}/WHEEL +0 -0
  849. {codex-1.6.18.dist-info → codex-1.7.0.dist-info}/entry_points.txt +0 -0
codex/integrity.py DELETED
@@ -1,492 +0,0 @@
1
- """Repair Database Integrity Errors."""
2
-
3
- import re
4
- import sqlite3
5
- from types import MappingProxyType
6
-
7
- from django.apps import apps
8
- from django.contrib.auth import get_user_model
9
- from django.contrib.auth.models import Group
10
- from django.contrib.sessions.models import Session
11
- from django.db import DEFAULT_DB_ALIAS, connection, connections
12
- from django.db.migrations.executor import MigrationExecutor
13
- from django.db.migrations.recorder import MigrationRecorder
14
- from django.db.models.functions import Now
15
- from django.db.models.query import Q
16
- from django.db.utils import OperationalError
17
-
18
- from codex.logger.logging import get_logger
19
- from codex.settings.settings import (
20
- CODEX_PATH,
21
- CONFIG_PATH,
22
- CUSTOM_COVERS_DIR,
23
- DB_PATH,
24
- SKIP_INTEGRITY_CHECK,
25
- )
26
-
27
- NO_MIGRATIONS_TABLE_ERROR = "no such table: django_migrations"
28
- REPAIR_FLAG_PATH = CONFIG_PATH / "rebuild_db"
29
- DUMP_LINE_MATCHER = re.compile("TRANSACTION|ROLLBACK|COMMIT")
30
- REBUILT_DB_PATH = DB_PATH.parent / (DB_PATH.name + ".rebuilt")
31
- BACKUP_DB_PATH = DB_PATH.parent / (DB_PATH.name + ".bak")
32
- MIGRATION_0005 = "0005_auto_20200918_0146"
33
- MIGRATION_0007 = "0007_auto_20211210_1710"
34
- MIGRATION_0010 = "0010_haystack"
35
- MIGRATION_0011 = "0010_library_groups_and_metadata_changes"
36
- MIGRATION_0018 = "0018_rename_userbookmark_bookmark"
37
- MIGRATION_0025 = "0025_add_story_arc_number"
38
- MIGRATION_0026 = "0026_comicbox_1"
39
- MIGRATION_0027 = "0027_import_order_and_covers"
40
- M2M_NAMES = MappingProxyType(
41
- {
42
- "Character": "characters",
43
- "Contributor": "contributors",
44
- "Genre": "genres",
45
- "Location": "locations",
46
- "SeriesGroup": "series_groups",
47
- "StoryArcNumber": "story_arc_numbers",
48
- "Tag": "tags",
49
- "Team": "teams",
50
- "Folder": "folders",
51
- }
52
- )
53
- SKIP_M2M_CHECKS = MappingProxyType(
54
- {"Contributor": MIGRATION_0026, "StoryArcNumber": MIGRATION_0025}
55
- )
56
- NULL_SET = frozenset({None})
57
- HAVE_LIBRARY_FKS = ("FailedImport", "Folder", "Comic", "CustomCover")
58
- GROUP_HOSTS = MappingProxyType(
59
- {
60
- "Imprint": ("Publisher",),
61
- "Series": ("Publisher", "Imprint"),
62
- "Volume": ("Publisher", "Imprint", "Series"),
63
- "Comic": ("Publisher", "Imprint", "Series", "Volume"),
64
- }
65
- )
66
- COMIC_FK_FIELDS = MappingProxyType(
67
- {
68
- "AgeRating": "age_rating",
69
- "Country": "country",
70
- "Language": "language",
71
- "OriginalFormat": "original_format",
72
- "ScanInfo": "scan_info",
73
- "Tagger": "tagger",
74
- }
75
- )
76
- WATCHED_PATHS = ("Comic", "Folder")
77
- CONTRIBUTOR_FIELDS = MappingProxyType(
78
- {"ContributorRole": "role", "ContributorPerson": "person"}
79
- )
80
- OPERATIONAL_ERRORS_BEFORE_MIGRATIONS = (
81
- "no such column: codex_comic.name",
82
- "no such column: codex_comic.stat",
83
- "no such column: codex_folder.stat",
84
- "no such table: codex_comic_folders",
85
- # "no such table: codex_comic_contributors",
86
- "'QuerySet' object has no attribute 'stat'",
87
- )
88
- DELETE_BAD_COMIC_FOLDER_RELATIONS_SQL = (
89
- 'DELETE FROM "codex_comic_folder" '
90
- 'WHERE (NOT ("codex_comic_folder"."comic_id" '
91
- 'IN (SELECT "codex_comic"."id" FROM "codex_comic")) '
92
- 'OR NOT ("codex_comic_folder"."folder_id" '
93
- 'IN (SELECT "codex_folder"."id" FROM "codex_folder")))'
94
- )
95
- MIGRATION_DIR = CODEX_PATH / "migrations"
96
- CUSTOM_COVER_MODEL_NAMES = MappingProxyType(
97
- {"publisher": "p", "imprint": "i", "series": "s", "storyarc": "a", "folder": "f"}
98
- )
99
-
100
- LOG = get_logger(__name__)
101
-
102
-
103
- def has_applied_migration(migration_name):
104
- """Check if a specific migration has been applied."""
105
- return MigrationRecorder.Migration.objects.filter(
106
- app="codex", name=migration_name
107
- ).exists()
108
-
109
-
110
- def has_unapplied_migrations():
111
- """Check if any migrations are outstanding."""
112
- try:
113
- connection = connections[DEFAULT_DB_ALIAS]
114
- connection.prepare_database()
115
- executor = MigrationExecutor(connection)
116
- targets = [
117
- key for key in executor.loader.graph.leaf_nodes() if key[0] == "codex"
118
- ]
119
- plan = executor.migration_plan(targets)
120
- except Exception as exc:
121
- LOG.warning(f"has_unapplied_migrations(): {exc}")
122
- return False
123
- else:
124
- return bool(plan)
125
-
126
-
127
- def _delete_old_comic_folder_fks():
128
- if has_applied_migration(MIGRATION_0007):
129
- return
130
-
131
- try:
132
- with connection.cursor() as cursor:
133
- cursor.execute(DELETE_BAD_COMIC_FOLDER_RELATIONS_SQL)
134
- LOG.info("Deleted old comic_folder relations with bad integrity.")
135
- except Exception:
136
- LOG.exception("Deleting old comic folders")
137
-
138
-
139
- def _fix_comic_m2m_integrity_errors(apps, comic_model, m2m_model_name, field_name):
140
- """Fix Comic ManyToMany integrity errors."""
141
- """Delete relations to comics that don't exist and m2ms that don't exist."""
142
- m2m_model = apps.get_model("codex", m2m_model_name)
143
- field = getattr(comic_model, field_name)
144
- through_model = field.through
145
- link_col = field_name[:-1].replace("_", "") + "_id"
146
-
147
- m2m_rels_with_bad_comic_ids = through_model.objects.exclude(
148
- comic_id__in=comic_model.objects.all()
149
- )
150
- count_comic, _ = m2m_rels_with_bad_comic_ids.delete()
151
- m2m_rels_with_bad_m2m_ids = through_model.objects.exclude(
152
- **{f"{link_col}__in": m2m_model.objects.all()}
153
- )
154
- bad_comic_ids = comic_model.objects.filter(
155
- pk__in=m2m_rels_with_bad_m2m_ids.values_list("comic_id", flat=True)
156
- ).values_list("pk", flat=True)
157
- count_m2m, _ = m2m_rels_with_bad_m2m_ids.delete()
158
- count = count_comic + count_m2m
159
- if count:
160
- LOG.info(f"Deleted {count} orphan relations to {field_name}")
161
- return frozenset(bad_comic_ids)
162
-
163
-
164
- def _fix_comic_fk_integrity_errors(apps, comic_model, fk_model_name, field_name):
165
- fk_model = apps.get_model("codex", fk_model_name)
166
- bad_pks = _null_missing_fk(comic_model, fk_model, field_name)
167
- getattr(comic_model, field_name)
168
- count = len(bad_pks)
169
- if count:
170
- LOG.info(f"Deleted {count} {field_name} links to missing rows.")
171
- return frozenset(bad_pks)
172
-
173
-
174
- def _mark_comics_with_bad_rels_for_update(comic_model, bad_comic_ids):
175
- """Mark affected comics for update."""
176
- try:
177
- update_comics = []
178
- bad_comics = comic_model.objects.filter(pk__in=bad_comic_ids).only("stat")
179
-
180
- for comic in bad_comics:
181
- stat_list = comic.stat
182
- if not stat_list:
183
- continue
184
- stat_list[8] = 0.0
185
- comic.stat = stat_list
186
- update_comics.append(comic)
187
-
188
- if not update_comics:
189
- return
190
-
191
- count = comic_model.objects.bulk_update(update_comics, fields=["stat"])
192
- LOG.info(f"Marked {count} comics with bad relations for update by poller.")
193
- except (OperationalError, AttributeError) as exc:
194
- ok = False
195
- for arg in exc.args:
196
- if arg in OPERATIONAL_ERRORS_BEFORE_MIGRATIONS:
197
- LOG.debug(
198
- "Can't mark modified comics for update, "
199
- "but if this happens right before migration 0007, "
200
- "they'll be updated anyway."
201
- )
202
- ok = True
203
- if not ok:
204
- LOG.exception("Mark comics with bad relations for update.")
205
-
206
-
207
- def _find_fk_integrity_errors_with_models(
208
- host_model, fk_model, fk_field_name, log=True
209
- ):
210
- """Find foreign key integrity errors with specified models."""
211
- inner_qs = fk_model.objects.all()
212
- exclude_filter = {f"{fk_field_name}__in": inner_qs}
213
- invalid_host_objs = host_model.objects.exclude(**exclude_filter).only(fk_field_name)
214
- if fk_field_name in ("parent_folder", "role"):
215
- # Special fields can be null
216
- # THIS IS VERY IMPORTANT TO AVOID DELETING ALL TOP LEVEL FOLDERS
217
- not_null_filter = {f"{fk_field_name}__isnull": False}
218
- invalid_host_objs = invalid_host_objs.filter(**not_null_filter)
219
-
220
- count = invalid_host_objs.count()
221
- if count and log:
222
- LOG.info(f"Found {host_model.__name__}s with bad {fk_field_name}: {count}")
223
- return invalid_host_objs
224
-
225
-
226
- def _find_fk_integrity_errors(apps, host_model_name, fk_model_name, fk_field_name):
227
- """Find foreign key integrity errors."""
228
- host_model = apps.get_model("codex", host_model_name)
229
- fk_model = apps.get_model("codex", fk_model_name)
230
- return _find_fk_integrity_errors_with_models(host_model, fk_model, fk_field_name)
231
-
232
-
233
- def _delete_query(query, host_model_name, fk_model_name):
234
- """Execute the delete on the query."""
235
- count, _ = query.delete()
236
- if count:
237
- LOG.info(f"Deleted {count} {host_model_name}s in nonextant {fk_model_name}s.")
238
-
239
-
240
- def _delete_fk_integrity_errors(apps, host_model_name, fk_model_name, fk_field_name):
241
- """Delete objects with bad integrity."""
242
- try:
243
- if not has_applied_migration(MIGRATION_0026) and (
244
- host_model_name == "Contributor"
245
- or fk_model_name == "Contributor"
246
- or fk_field_name == "contributors"
247
- ):
248
- LOG.debug(
249
- "Skipping Contributor integrity check until"
250
- f"migration {MIGRATION_0026} applied."
251
- )
252
- return
253
-
254
- bad_host_objs = _find_fk_integrity_errors(
255
- apps, host_model_name, fk_model_name, fk_field_name
256
- )
257
- _delete_query(bad_host_objs, host_model_name, fk_model_name)
258
- except OperationalError as exc:
259
- ok = False
260
- for arg in exc.args:
261
- if arg in OPERATIONAL_ERRORS_BEFORE_MIGRATIONS:
262
- ok = True
263
- if not ok:
264
- LOG.exception("Operational error before migrations")
265
- except Exception:
266
- LOG.exception("Delete foreign key integrity errors.")
267
-
268
-
269
- def _null_missing_fk(host_model, fk_model, fk_field_name):
270
- """Set missing fks to null."""
271
- query_missing_fks = _find_fk_integrity_errors_with_models(
272
- host_model, fk_model, fk_field_name, log=False
273
- )
274
- not_null_filter = {f"{fk_field_name}__isnull": False}
275
- query_missing_fks = query_missing_fks.filter(**not_null_filter)
276
- count = query_missing_fks.count()
277
- if count:
278
- update_dict = {fk_field_name: None, "updated_at": Now()}
279
- query_missing_fks.update(**update_dict)
280
- LOG.info(f"Fixed {count} {host_model.__name__}s with missing {fk_field_name}")
281
- return query_missing_fks.values_list("pk", flat=True)
282
-
283
-
284
- def _delete_bookmark_integrity_errors(apps):
285
- """Fix Bookmarks with non codex model fields."""
286
- if not has_applied_migration(MIGRATION_0018):
287
- return
288
- # Bookmarks that don't reference a valid comic are useless.
289
- _delete_fk_integrity_errors(apps, "Bookmark", "Comic", "comic")
290
-
291
- # Bookmarks that aren't linked to a valid session or a user are orphans
292
- bm_model = apps.get_model("codex", "Bookmark")
293
- _null_missing_fk(bm_model, Session, "session")
294
- _null_missing_fk(bm_model, get_user_model(), "user")
295
- orphan_bms = bm_model.objects.filter(session=None, user=None)
296
- _delete_query(orphan_bms, "Bookmark", "session or user")
297
-
298
-
299
- def _repair_library_groups(apps):
300
- """Remove non-extant groups from libraries."""
301
- if not has_applied_migration(MIGRATION_0011):
302
- return
303
- library_model = apps.get_model("codex", "library")
304
- through_model = library_model.groups.through
305
- valid_groups = Group.objects.all()
306
- bad_relations = through_model.objects.exclude(group_id__in=valid_groups)
307
- bad_relations.delete()
308
-
309
-
310
- def _delete_extra_custom_cover_libraries(apps):
311
- if not has_applied_migration(MIGRATION_0027):
312
- return
313
- library_model = apps.get_model("codex", "library")
314
- custom_cover_libraries = library_model.objects.filter(covers_only=True)
315
- if custom_cover_libraries.count() <= 1:
316
- return
317
-
318
- # Attempt to remove the bad ones, probably futile
319
- bad_lib_pks = []
320
- for library in custom_cover_libraries:
321
- if library.path != CUSTOM_COVERS_DIR:
322
- bad_lib_pks.append(library.pk)
323
- delete_libs = library_model.object.filter(pk__in=bad_lib_pks)
324
- count = delete_libs.count()
325
- if count:
326
- delete_libs.delete()
327
- LOG.warn(
328
- f"Removed {count} duplicate custom cover libraries pointing to unused custom cover dirs."
329
- )
330
-
331
- custom_cover_libraries = library_model.object.filter(covers_only=True)
332
- count = custom_cover_libraries.count()
333
- if count <= 1:
334
- return
335
- custom_cover_libraries.delete()
336
- LOG.warn(
337
- f"Removed all ({count}) custom cover libraries, Unable to determine valid one. Will recreate upon startup."
338
- )
339
-
340
-
341
- def _repair_groups_with_custom_covers(apps):
342
- if not has_applied_migration(MIGRATION_0027):
343
- return
344
- custom_cover_model = apps.get_model("codex", "customcover")
345
- for model_name, group_letter in CUSTOM_COVER_MODEL_NAMES.items():
346
- valid_covers = custom_cover_model.objects.filter(group=group_letter)
347
- group_model = apps.get_model("codex", model_name)
348
- objs = group_model.objects.exclude(
349
- Q(custom_cover__isnull=True) | Q(custom_cover__in=valid_covers)
350
- )
351
- update_groups = []
352
- for group in objs:
353
- group.custom_cover = None
354
- group.updated_at = Now()
355
- update_groups.append(group)
356
- group_model.objects.bulk_update(update_groups, ["custom_cover"])
357
- count = len(update_groups)
358
- if count:
359
- LOG.warn(f"Removed illegal custom cover links from {count} {model_name}s")
360
-
361
-
362
- def _delete_errors():
363
- """DELETE things we can't fix."""
364
- _delete_extra_custom_cover_libraries(apps)
365
-
366
- for host_model_name in HAVE_LIBRARY_FKS:
367
- if host_model_name == "CustomCover" and not has_applied_migration(
368
- MIGRATION_0027
369
- ):
370
- continue
371
- _delete_fk_integrity_errors(apps, host_model_name, "Library", "library")
372
-
373
- for host_model_name in WATCHED_PATHS:
374
- _delete_fk_integrity_errors(apps, host_model_name, "Folder", "parent_folder")
375
-
376
- for host_model_name, groups in GROUP_HOSTS.items():
377
- for group_model_name in groups:
378
- group_field_name = group_model_name.lower()
379
- _delete_fk_integrity_errors(
380
- apps, host_model_name, group_model_name, group_field_name
381
- )
382
-
383
- if has_applied_migration(MIGRATION_0026):
384
- for fk_model_name in COMIC_FK_FIELDS:
385
- _delete_fk_integrity_errors(apps, fk_model_name, "Comic", "comic")
386
-
387
- for fk_model_name, fk_field_name in CONTRIBUTOR_FIELDS.items():
388
- _delete_fk_integrity_errors(apps, "Contributor", fk_model_name, fk_field_name)
389
-
390
- _delete_bookmark_integrity_errors(apps)
391
-
392
- _delete_old_comic_folder_fks()
393
-
394
-
395
- def _check_field_for_migration(model_name):
396
- """Skip some models before migrations."""
397
- for check_model_name, migration in SKIP_M2M_CHECKS.items():
398
- if model_name == check_model_name and not has_applied_migration(migration):
399
- LOG.debug(
400
- f"Skipping {check_model_name} integrity check until"
401
- f" migration {migration} applied."
402
- )
403
- return True
404
- return False
405
-
406
-
407
- def _repair_integrity():
408
- """REPAIR the objects that are left."""
409
- comic_model = apps.get_model("codex", "Comic")
410
- bad_comic_ids = set()
411
- for m2m_model_name, field_name in M2M_NAMES.items():
412
- if _check_field_for_migration(m2m_model_name):
413
- continue
414
- try:
415
- bad_comic_ids |= _fix_comic_m2m_integrity_errors(
416
- apps, comic_model, m2m_model_name, field_name
417
- )
418
- except OperationalError as exc:
419
- ok = False
420
- for arg in exc.args:
421
- if arg in OPERATIONAL_ERRORS_BEFORE_MIGRATIONS:
422
- ok = True
423
- if ok:
424
- LOG.info(
425
- "Couldn't look for comics with folder integrity problems before "
426
- "migration 0007. We'll get them on the next restart."
427
- )
428
- else:
429
- LOG.exception("Occurred after migration 0007")
430
-
431
- if has_applied_migration(MIGRATION_0026):
432
- for fk_model_name, field_name in COMIC_FK_FIELDS.items():
433
- try:
434
- bad_comic_ids |= _fix_comic_fk_integrity_errors(
435
- apps, comic_model, fk_model_name, field_name
436
- )
437
- except Exception:
438
- LOG.exception(f"Fix fk integrity error {fk_model_name}")
439
-
440
- _mark_comics_with_bad_rels_for_update(comic_model, bad_comic_ids)
441
-
442
- _repair_library_groups(apps)
443
- _repair_groups_with_custom_covers(apps)
444
-
445
-
446
- def repair_db():
447
- """Fix the db but trap errors if it goes wrong."""
448
- try:
449
- if SKIP_INTEGRITY_CHECK:
450
- LOG.info("Skipping integrity check")
451
- return
452
-
453
- if not has_applied_migration(MIGRATION_0005):
454
- LOG.info(
455
- "Not running integrity checks until migration"
456
- f"{MIGRATION_0005} has been applied."
457
- )
458
- return
459
-
460
- LOG.debug("Reparing database integrity...")
461
- _delete_errors()
462
- _repair_integrity()
463
- LOG.info("Database integrity confirmed.")
464
- except OperationalError as exc:
465
- if NO_MIGRATIONS_TABLE_ERROR in exc.args:
466
- LOG.debug("Database not constructed yet, skipping integrity check.")
467
- else:
468
- raise
469
- except Exception:
470
- LOG.exception("Repair DB")
471
-
472
-
473
- def rebuild_db():
474
- """Dump and rebuild the database."""
475
- # Drastic
476
- if not REPAIR_FLAG_PATH.exists():
477
- return
478
-
479
- LOG.warning("REBUILDING DATABASE!!")
480
- with sqlite3.connect(REBUILT_DB_PATH) as new_db_conn:
481
- new_db_cur = new_db_conn.cursor()
482
- with sqlite3.connect(DB_PATH) as old_db_conn:
483
- for line in old_db_conn.iterdump():
484
- if DUMP_LINE_MATCHER.search(line):
485
- continue
486
- new_db_cur.execute(line)
487
-
488
- DB_PATH.rename(BACKUP_DB_PATH)
489
- LOG.info("Backed up old db to %s", BACKUP_DB_PATH)
490
- REBUILT_DB_PATH.replace(DB_PATH)
491
- REPAIR_FLAG_PATH.unlink(missing_ok=True)
492
- LOG.info("Rebuilt database.")
@@ -1,86 +0,0 @@
1
- """Search Index Merging for Read Optimization."""
2
-
3
- from pathlib import Path
4
- from time import time
5
- from typing import TYPE_CHECKING
6
-
7
- from humanize import naturaldelta, naturalsize
8
-
9
- from codex.librarian.search.status import SearchIndexStatusTypes
10
- from codex.librarian.search.version import VersionMixin
11
- from codex.settings.settings import SEARCH_INDEX_PATH
12
- from codex.status import Status
13
-
14
- if TYPE_CHECKING:
15
- from codex.search.backend import CodexSearchBackend
16
-
17
-
18
- class MergeMixin(VersionMixin):
19
- """Search Index Merge Methods."""
20
-
21
- def _is_index_optimized(self, num_segments):
22
- """Is the index already in one segment."""
23
- if num_segments <= 1:
24
- self.log.info("Search index already optimized.")
25
- return True
26
- return False
27
-
28
- @staticmethod
29
- def _get_segments_and_len():
30
- segments = SEARCH_INDEX_PATH.glob("*.seg")
31
- num_segments = len(tuple(segments))
32
- return segments, num_segments
33
-
34
- @staticmethod
35
- def _get_segments_size(segments):
36
- size = 0
37
- for segment in segments:
38
- size += Path(segment).stat().st_size
39
- return size
40
-
41
- def _merge_search_index(self, optimize, status, name):
42
- """Optimize search index."""
43
- self.status_controller.start(status)
44
- start = time()
45
-
46
- segments, old_num_segments = self._get_segments_and_len()
47
- if self._is_index_optimized(old_num_segments):
48
- return
49
- self.status_controller.start(status)
50
- old_size = self._get_segments_size(segments)
51
- # Optimize
52
- self.log.info(
53
- f"Search index found in {old_num_segments} segments," f" merging {name}..."
54
- )
55
- backend: CodexSearchBackend = self.engine.get_backend() # type: ignore
56
- if optimize:
57
- backend.optimize()
58
- else:
59
- backend.merge_small()
60
-
61
- # Finish
62
- segments, new_num_segments = self._get_segments_and_len()
63
- new_size = self._get_segments_size(segments)
64
- saved = naturalsize(old_size - new_size)
65
- num_segments_diff = old_num_segments - new_num_segments
66
- elapsed_time = time() - start
67
- elapsed = naturaldelta(elapsed_time)
68
- if num_segments_diff:
69
- self.log.info(
70
- f"Merged {num_segments_diff} search index segments in {elapsed}."
71
- f"Saved {saved}."
72
- )
73
- else:
74
- self.log.info("No small search index segments found.")
75
-
76
- def merge_search_index(self, optimize=False):
77
- """Optimize search index, trapping exceptions."""
78
- verb = "All" if optimize else "Small"
79
- name = f"Merge {verb} Segments"
80
- status = Status(SearchIndexStatusTypes.SEARCH_INDEX_MERGE, subtitle=name)
81
- try:
82
- self._merge_search_index(optimize, status, name)
83
- except Exception:
84
- self.log.exception("Search index merge.")
85
- finally:
86
- self.status_controller.finish(status)
@@ -1,63 +0,0 @@
1
- """Search Engine to database matching."""
2
-
3
- from uuid import uuid4
4
-
5
- from codex.librarian.search.tasks import SearchIndexUpdateTask
6
- from codex.models import Timestamp
7
- from codex.search.engine import CodexSearchEngine
8
- from codex.settings.settings import SEARCH_INDEX_PATH, SEARCH_INDEX_UUID_PATH
9
- from codex.threads import QueuedThread
10
-
11
-
12
- class VersionMixin(QueuedThread):
13
- """Search Engine to database matching methods."""
14
-
15
- def __init__(self, abort_event, *args, **kwargs):
16
- """Initialize search engine."""
17
- self.abort_event = abort_event
18
- super().__init__(*args, **kwargs)
19
- queue_kwargs = {
20
- "log_queue": self.log_queue,
21
- "librarian_queue": self.librarian_queue,
22
- }
23
- self.engine = CodexSearchEngine(queue_kwargs=queue_kwargs)
24
-
25
- def set_search_index_version(self):
26
- """Set the codex db to search index matching id."""
27
- version = str(uuid4())
28
- try:
29
- lv = Timestamp.objects.get(
30
- key=Timestamp.TimestampChoices.SEARCH_INDEX_UUID.value
31
- )
32
- lv.version = version
33
- lv.save()
34
- SEARCH_INDEX_PATH.mkdir(parents=True, exist_ok=True)
35
- with SEARCH_INDEX_UUID_PATH.open("w") as uuid_file:
36
- uuid_file.write(version)
37
- except Exception:
38
- self.log.exception("Setting search index to db synchronization token")
39
-
40
- def is_search_index_uuid_match(self):
41
- """Is this search index for this database."""
42
- result = False
43
- try:
44
- with SEARCH_INDEX_UUID_PATH.open("r") as uuid_file:
45
- version = uuid_file.read()
46
- result = Timestamp.objects.filter(
47
- key=Timestamp.TimestampChoices.SEARCH_INDEX_UUID.value, version=version
48
- ).exists()
49
- except (FileNotFoundError, Timestamp.DoesNotExist):
50
- pass
51
- except Exception:
52
- self.log.exception("Does search index match database uuid")
53
- if not result:
54
- self.log.warning("Database does not match search index.")
55
- return result
56
-
57
- def rebuild_search_index_if_db_changed(self):
58
- """Rebuild the search index if the db changed."""
59
- if not self.is_search_index_uuid_match():
60
- task = SearchIndexUpdateTask(True)
61
- self.librarian_queue.put(task)
62
- else:
63
- self.log.info("Database matches search index.")
codex/search/__init__.py DELETED
@@ -1 +0,0 @@
1
- """Haystack Search Customizations."""