codex 1.6.19__py3-none-any.whl → 1.7.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 (576) hide show
  1. codex/db.py +119 -0
  2. codex/librarian/covers/purge.py +1 -1
  3. codex/librarian/importer/const.py +7 -1
  4. codex/librarian/importer/create_fks.py +5 -2
  5. codex/librarian/importer/importerd.py +17 -12
  6. codex/librarian/importer/moved.py +44 -13
  7. codex/librarian/importer/tasks.py +2 -0
  8. codex/librarian/janitor/cleanup.py +21 -8
  9. codex/librarian/janitor/integrity.py +369 -0
  10. codex/librarian/janitor/janitor.py +50 -15
  11. codex/librarian/janitor/latest_version.py +2 -1
  12. codex/librarian/janitor/status.py +5 -0
  13. codex/librarian/janitor/tasks.py +37 -0
  14. codex/librarian/janitor/update.py +1 -1
  15. codex/librarian/librariand.py +32 -24
  16. codex/librarian/search/optimize.py +43 -0
  17. codex/librarian/search/remove.py +18 -46
  18. codex/librarian/search/searchd.py +14 -17
  19. codex/librarian/search/status.py +2 -1
  20. codex/librarian/search/tasks.py +4 -9
  21. codex/librarian/search/update.py +223 -301
  22. codex/librarian/watchdog/observers.py +2 -1
  23. codex/migrations/0029_comicfts.py +58 -0
  24. codex/migrations/0030_nocase_collation_day_month_indexes_status_types.py +198 -0
  25. codex/models/admin.py +15 -6
  26. codex/models/base.py +9 -0
  27. codex/models/bookmark.py +3 -3
  28. codex/models/comic.py +68 -16
  29. codex/models/functions.py +59 -2
  30. codex/models/groups.py +6 -1
  31. codex/models/library.py +1 -3
  32. codex/models/paths.py +9 -3
  33. codex/serializers/browser/page.py +2 -0
  34. codex/settings/settings.py +16 -17
  35. codex/signals/django_signals.py +4 -10
  36. codex/startup.py +1 -35
  37. codex/static_root/assets/{VCheckbox-Cko1sQK-.170726b3b8a1.js → VCheckbox-CWiqcZ7a.3feebd47daab.js} +1 -1
  38. codex/static_root/assets/VCheckbox-CWiqcZ7a.3feebd47daab.js.br +0 -0
  39. codex/static_root/assets/VCheckbox-CWiqcZ7a.3feebd47daab.js.gz +0 -0
  40. codex/static_root/assets/{VCheckbox-Cko1sQK-.js → VCheckbox-CWiqcZ7a.js} +1 -1
  41. codex/static_root/assets/VCheckbox-CWiqcZ7a.js.br +0 -0
  42. codex/static_root/assets/VCheckbox-CWiqcZ7a.js.gz +0 -0
  43. codex/static_root/assets/{VCheckboxBtn-CO3-aqQL.c9b8062fd66f.js → VCheckboxBtn-Dk3iB62X.bc66d5351baa.js} +1 -1
  44. codex/static_root/assets/VCheckboxBtn-Dk3iB62X.bc66d5351baa.js.br +0 -0
  45. codex/static_root/assets/VCheckboxBtn-Dk3iB62X.bc66d5351baa.js.gz +0 -0
  46. codex/static_root/assets/{VCheckboxBtn-CO3-aqQL.js → VCheckboxBtn-Dk3iB62X.js} +1 -1
  47. codex/static_root/assets/VCheckboxBtn-Dk3iB62X.js.br +0 -0
  48. codex/static_root/assets/VCheckboxBtn-Dk3iB62X.js.gz +0 -0
  49. codex/static_root/assets/{VCombobox-Bjp6lffE.js → VCombobox-D1_KU27A.b1d30587a973.js} +1 -1
  50. codex/static_root/assets/VCombobox-D1_KU27A.b1d30587a973.js.br +0 -0
  51. codex/static_root/assets/VCombobox-D1_KU27A.b1d30587a973.js.gz +0 -0
  52. codex/static_root/assets/{VCombobox-Bjp6lffE.caf59fba486e.js → VCombobox-D1_KU27A.js} +1 -1
  53. codex/static_root/assets/VCombobox-D1_KU27A.js.br +0 -0
  54. codex/static_root/assets/VCombobox-D1_KU27A.js.gz +0 -0
  55. codex/static_root/assets/{VDialog-BkpVGB70.6eea3ca762a5.js → VDialog-GbxvFMMN.594fb3a39ced.js} +1 -1
  56. codex/static_root/assets/VDialog-GbxvFMMN.594fb3a39ced.js.br +0 -0
  57. codex/static_root/assets/VDialog-GbxvFMMN.594fb3a39ced.js.gz +0 -0
  58. codex/static_root/assets/{VDialog-BkpVGB70.js → VDialog-GbxvFMMN.js} +1 -1
  59. codex/static_root/assets/VDialog-GbxvFMMN.js.br +0 -0
  60. codex/static_root/assets/VDialog-GbxvFMMN.js.gz +0 -0
  61. codex/static_root/assets/{VExpansionPanels-Ci2-j8XX.9c55db4ef49e.js → VExpansionPanels-Cywv_bEj.a762e63858e5.js} +1 -1
  62. codex/static_root/assets/VExpansionPanels-Cywv_bEj.a762e63858e5.js.br +0 -0
  63. codex/static_root/assets/VExpansionPanels-Cywv_bEj.a762e63858e5.js.gz +0 -0
  64. codex/static_root/assets/{VExpansionPanels-Ci2-j8XX.js → VExpansionPanels-Cywv_bEj.js} +1 -1
  65. codex/static_root/assets/VExpansionPanels-Cywv_bEj.js.br +0 -0
  66. codex/static_root/assets/VExpansionPanels-Cywv_bEj.js.gz +0 -0
  67. codex/static_root/assets/{VRadioGroup-D3Py5BfQ.a4f25edb86d3.js → VRadioGroup-C0etmxpZ.0eb3009a6300.js} +1 -1
  68. codex/static_root/assets/VRadioGroup-C0etmxpZ.0eb3009a6300.js.br +0 -0
  69. codex/static_root/assets/VRadioGroup-C0etmxpZ.0eb3009a6300.js.gz +0 -0
  70. codex/static_root/assets/{VRadioGroup-D3Py5BfQ.js → VRadioGroup-C0etmxpZ.js} +1 -1
  71. codex/static_root/assets/VRadioGroup-C0etmxpZ.js.br +0 -0
  72. codex/static_root/assets/VRadioGroup-C0etmxpZ.js.gz +0 -0
  73. codex/static_root/assets/{VSelect-DtvZsYZz.e98745d858eb.js → VSelect-txrnRiNJ.a5625760018c.js} +1 -1
  74. codex/static_root/assets/VSelect-txrnRiNJ.a5625760018c.js.br +0 -0
  75. codex/static_root/assets/VSelect-txrnRiNJ.a5625760018c.js.gz +0 -0
  76. codex/static_root/assets/{VSelect-DtvZsYZz.js → VSelect-txrnRiNJ.js} +1 -1
  77. codex/static_root/assets/VSelect-txrnRiNJ.js.br +0 -0
  78. codex/static_root/assets/VSelect-txrnRiNJ.js.gz +0 -0
  79. codex/static_root/assets/{VSelectionControl-D6kmykQW.1e1fda62ceba.js → VSelectionControl-CY6RmcvW.7e8824224f6c.js} +1 -1
  80. codex/static_root/assets/VSelectionControl-CY6RmcvW.7e8824224f6c.js.br +0 -0
  81. codex/static_root/assets/VSelectionControl-CY6RmcvW.7e8824224f6c.js.gz +0 -0
  82. codex/static_root/assets/{VSelectionControl-D6kmykQW.js → VSelectionControl-CY6RmcvW.js} +1 -1
  83. codex/static_root/assets/VSelectionControl-CY6RmcvW.js.br +0 -0
  84. codex/static_root/assets/VSelectionControl-CY6RmcvW.js.gz +0 -0
  85. codex/static_root/assets/{VSlideGroup-UGZWxpF5.360bdefcd215.js → VSlideGroup-DtEQMwY1.6c72325635ed.js} +1 -1
  86. codex/static_root/assets/VSlideGroup-DtEQMwY1.6c72325635ed.js.br +0 -0
  87. codex/static_root/assets/VSlideGroup-DtEQMwY1.6c72325635ed.js.gz +0 -0
  88. codex/static_root/assets/{VSlideGroup-UGZWxpF5.js → VSlideGroup-DtEQMwY1.js} +1 -1
  89. codex/static_root/assets/VSlideGroup-DtEQMwY1.js.br +0 -0
  90. codex/static_root/assets/VSlideGroup-DtEQMwY1.js.gz +0 -0
  91. codex/static_root/assets/{VTable-DXH_yQ0o.1149f56ad566.js → VTable-2af995xo.6c5bf36631b2.js} +1 -1
  92. codex/static_root/assets/VTable-2af995xo.6c5bf36631b2.js.br +0 -0
  93. codex/static_root/assets/VTable-2af995xo.6c5bf36631b2.js.gz +0 -0
  94. codex/static_root/assets/{VTable-DXH_yQ0o.js → VTable-2af995xo.js} +1 -1
  95. codex/static_root/assets/VTable-2af995xo.js.br +0 -0
  96. codex/static_root/assets/VTable-2af995xo.js.gz +0 -0
  97. codex/static_root/assets/{VTextField-Blqy56_L.26d8761e0155.js → VTextField-G6CMj7yO.657a130dd302.js} +1 -1
  98. codex/static_root/assets/VTextField-G6CMj7yO.657a130dd302.js.br +0 -0
  99. codex/static_root/assets/VTextField-G6CMj7yO.657a130dd302.js.gz +0 -0
  100. codex/static_root/assets/{VTextField-Blqy56_L.js → VTextField-G6CMj7yO.js} +1 -1
  101. codex/static_root/assets/VTextField-G6CMj7yO.js.br +0 -0
  102. codex/static_root/assets/VTextField-G6CMj7yO.js.gz +0 -0
  103. codex/static_root/assets/{VWindowItem-C8_ovV7e.afbc08414765.js → VWindowItem-CzoGd6Ul.721e5da11ad4.js} +1 -1
  104. codex/static_root/assets/VWindowItem-CzoGd6Ul.721e5da11ad4.js.br +0 -0
  105. codex/static_root/assets/VWindowItem-CzoGd6Ul.721e5da11ad4.js.gz +0 -0
  106. codex/static_root/assets/{VWindowItem-C8_ovV7e.js → VWindowItem-CzoGd6Ul.js} +1 -1
  107. codex/static_root/assets/VWindowItem-CzoGd6Ul.js.br +0 -0
  108. codex/static_root/assets/VWindowItem-CzoGd6Ul.js.gz +0 -0
  109. codex/static_root/assets/{admin-DTRn8bBs.d031ea42d8d0.js → admin-CsPAIQeG.5175467148a3.js} +1 -1
  110. codex/static_root/assets/admin-CsPAIQeG.5175467148a3.js.br +0 -0
  111. codex/static_root/assets/admin-CsPAIQeG.5175467148a3.js.gz +0 -0
  112. codex/static_root/assets/{admin-DTRn8bBs.js → admin-CsPAIQeG.js} +1 -1
  113. codex/static_root/assets/admin-CsPAIQeG.js.br +0 -0
  114. codex/static_root/assets/admin-CsPAIQeG.js.gz +0 -0
  115. codex/static_root/assets/{admin-drawer-panel-BaXFOcru.b1a44b05f482.js → admin-drawer-panel-BAT7GA64.73a064628c19.js} +11 -11
  116. codex/static_root/assets/admin-drawer-panel-BAT7GA64.73a064628c19.js.br +0 -0
  117. codex/static_root/assets/admin-drawer-panel-BAT7GA64.73a064628c19.js.gz +0 -0
  118. codex/static_root/assets/{admin-drawer-panel-BaXFOcru.js → admin-drawer-panel-BAT7GA64.js} +11 -11
  119. codex/static_root/assets/admin-drawer-panel-BAT7GA64.js.br +0 -0
  120. codex/static_root/assets/admin-drawer-panel-BAT7GA64.js.gz +0 -0
  121. codex/static_root/assets/browser-C18l93yc.923860009ef4.js +1 -0
  122. codex/static_root/assets/browser-C18l93yc.923860009ef4.js.br +0 -0
  123. codex/static_root/assets/browser-C18l93yc.923860009ef4.js.gz +0 -0
  124. codex/static_root/assets/browser-C18l93yc.js +1 -0
  125. codex/static_root/assets/browser-C18l93yc.js.br +0 -0
  126. codex/static_root/assets/browser-C18l93yc.js.gz +0 -0
  127. codex/static_root/assets/browser-DaAqlBYO.708ecf0904bb.css +1 -0
  128. codex/static_root/assets/browser-DaAqlBYO.708ecf0904bb.css.br +0 -0
  129. codex/static_root/assets/browser-DaAqlBYO.708ecf0904bb.css.gz +0 -0
  130. codex/static_root/assets/browser-DaAqlBYO.css +1 -0
  131. codex/static_root/assets/browser-DaAqlBYO.css.br +0 -0
  132. codex/static_root/assets/browser-DaAqlBYO.css.gz +0 -0
  133. codex/static_root/assets/change-password-dialog-BazJdNs9.0a4e02656a35.js +1 -0
  134. codex/static_root/assets/change-password-dialog-BazJdNs9.0a4e02656a35.js.br +0 -0
  135. codex/static_root/assets/change-password-dialog-BazJdNs9.0a4e02656a35.js.gz +0 -0
  136. codex/static_root/assets/change-password-dialog-BazJdNs9.js +1 -0
  137. codex/static_root/assets/change-password-dialog-BazJdNs9.js.br +0 -0
  138. codex/static_root/assets/change-password-dialog-BazJdNs9.js.gz +0 -0
  139. codex/static_root/assets/change-password-dialog-Mlmvz8_4.111421f51e79.css +1 -0
  140. codex/static_root/assets/change-password-dialog-Mlmvz8_4.111421f51e79.css.br +0 -0
  141. codex/static_root/assets/change-password-dialog-Mlmvz8_4.111421f51e79.css.gz +0 -0
  142. codex/static_root/assets/change-password-dialog-Mlmvz8_4.css +1 -0
  143. codex/static_root/assets/change-password-dialog-Mlmvz8_4.css.br +0 -0
  144. codex/static_root/assets/change-password-dialog-Mlmvz8_4.css.gz +0 -0
  145. codex/static_root/assets/{confirm-dialog-D3_s2DQy.9dde66036c72.js → confirm-dialog-CbW3hlOp.9dd39b443c31.js} +1 -1
  146. codex/static_root/assets/confirm-dialog-CbW3hlOp.9dd39b443c31.js.br +0 -0
  147. codex/static_root/assets/confirm-dialog-CbW3hlOp.9dd39b443c31.js.gz +0 -0
  148. codex/static_root/assets/{confirm-dialog-D3_s2DQy.js → confirm-dialog-CbW3hlOp.js} +1 -1
  149. codex/static_root/assets/confirm-dialog-CbW3hlOp.js.br +0 -0
  150. codex/static_root/assets/confirm-dialog-CbW3hlOp.js.gz +0 -0
  151. codex/static_root/assets/{datetime-column-BxC1Li9e.3dc314b3295d.js → datetime-column-uSqKZU37.b157b0743db5.js} +1 -1
  152. codex/static_root/assets/datetime-column-uSqKZU37.b157b0743db5.js.br +0 -0
  153. codex/static_root/assets/datetime-column-uSqKZU37.b157b0743db5.js.gz +0 -0
  154. codex/static_root/assets/{datetime-column-BxC1Li9e.js → datetime-column-uSqKZU37.js} +1 -1
  155. codex/static_root/assets/datetime-column-uSqKZU37.js.br +0 -0
  156. codex/static_root/assets/datetime-column-uSqKZU37.js.gz +0 -0
  157. codex/static_root/assets/{filter-Bzk7x841.d0c3b602e62d.js → filter-CBl5KEsB.845a81573c2e.js} +1 -1
  158. codex/static_root/assets/filter-CBl5KEsB.845a81573c2e.js.br +0 -0
  159. codex/static_root/assets/filter-CBl5KEsB.845a81573c2e.js.gz +0 -0
  160. codex/static_root/assets/{filter-Bzk7x841.js → filter-CBl5KEsB.js} +1 -1
  161. codex/static_root/assets/filter-CBl5KEsB.js.br +0 -0
  162. codex/static_root/assets/filter-CBl5KEsB.js.gz +0 -0
  163. codex/static_root/assets/flag-tab-CT8pqM4r.ecb6eee2e7a0.js +1 -0
  164. codex/static_root/assets/flag-tab-CT8pqM4r.ecb6eee2e7a0.js.br +0 -0
  165. codex/static_root/assets/flag-tab-CT8pqM4r.ecb6eee2e7a0.js.gz +0 -0
  166. codex/static_root/assets/flag-tab-CT8pqM4r.js +1 -0
  167. codex/static_root/assets/flag-tab-CT8pqM4r.js.br +0 -0
  168. codex/static_root/assets/flag-tab-CT8pqM4r.js.gz +0 -0
  169. codex/static_root/assets/{group-tab-5esH4lwX.a81fdd258117.js → group-tab-BOW9kigw.7e5007596367.js} +1 -1
  170. codex/static_root/assets/group-tab-BOW9kigw.7e5007596367.js.br +0 -0
  171. codex/static_root/assets/group-tab-BOW9kigw.7e5007596367.js.gz +0 -0
  172. codex/static_root/assets/{group-tab-5esH4lwX.js → group-tab-BOW9kigw.js} +1 -1
  173. codex/static_root/assets/group-tab-BOW9kigw.js.br +0 -0
  174. codex/static_root/assets/group-tab-BOW9kigw.js.gz +0 -0
  175. codex/static_root/assets/{http-error-BTOBfcGY.52ced6f28420.js → http-error-C6yuLApo.45cf99eb7a70.js} +1 -1
  176. codex/static_root/assets/http-error-C6yuLApo.45cf99eb7a70.js.br +4 -0
  177. codex/static_root/assets/http-error-C6yuLApo.45cf99eb7a70.js.gz +0 -0
  178. codex/static_root/assets/{http-error-BTOBfcGY.js → http-error-C6yuLApo.js} +1 -1
  179. codex/static_root/assets/http-error-C6yuLApo.js.br +4 -0
  180. codex/static_root/assets/http-error-C6yuLApo.js.gz +0 -0
  181. codex/static_root/assets/{library-tab-DiPEdOF7.ece2d642a9dc.js → library-tab-D3WOtpE0.9af34e6e7235.js} +1 -1
  182. codex/static_root/assets/library-tab-D3WOtpE0.9af34e6e7235.js.br +0 -0
  183. codex/static_root/assets/library-tab-D3WOtpE0.9af34e6e7235.js.gz +0 -0
  184. codex/static_root/assets/{library-tab-DiPEdOF7.js → library-tab-D3WOtpE0.js} +1 -1
  185. codex/static_root/assets/library-tab-D3WOtpE0.js.br +0 -0
  186. codex/static_root/assets/library-tab-D3WOtpE0.js.gz +0 -0
  187. codex/static_root/assets/main-CmjU2oTp.6a471f6900e5.js +6 -0
  188. codex/static_root/assets/main-CmjU2oTp.6a471f6900e5.js.br +0 -0
  189. codex/static_root/assets/main-CmjU2oTp.6a471f6900e5.js.gz +0 -0
  190. codex/static_root/assets/main-CmjU2oTp.js +6 -0
  191. codex/static_root/assets/main-CmjU2oTp.js.br +0 -0
  192. codex/static_root/assets/main-CmjU2oTp.js.gz +0 -0
  193. codex/static_root/assets/pager-full-pdf-BH54_5f6.6e92d0555cd7.js +1 -0
  194. codex/static_root/assets/pager-full-pdf-BH54_5f6.6e92d0555cd7.js.br +0 -0
  195. codex/static_root/assets/pager-full-pdf-BH54_5f6.6e92d0555cd7.js.gz +0 -0
  196. codex/static_root/assets/pager-full-pdf-BH54_5f6.js +1 -0
  197. codex/static_root/assets/pager-full-pdf-BH54_5f6.js.br +0 -0
  198. codex/static_root/assets/pager-full-pdf-BH54_5f6.js.gz +0 -0
  199. codex/static_root/assets/{pagination-toolbar-C45-onwe.4722195bb60b.css → pagination-toolbar-DGrxp2OD.css} +1 -1
  200. codex/static_root/assets/pagination-toolbar-DGrxp2OD.css.br +0 -0
  201. codex/static_root/assets/pagination-toolbar-DGrxp2OD.css.gz +0 -0
  202. codex/static_root/assets/{pagination-toolbar-C45-onwe.css → pagination-toolbar-DGrxp2OD.f960a624f04f.css} +1 -1
  203. codex/static_root/assets/pagination-toolbar-DGrxp2OD.f960a624f04f.css.br +0 -0
  204. codex/static_root/assets/pagination-toolbar-DGrxp2OD.f960a624f04f.css.gz +0 -0
  205. codex/static_root/assets/{pagination-toolbar-CkIzuyx1.00c354a82e6e.js → pagination-toolbar-JH3Kbffr.451171f7ac33.js} +1 -1
  206. codex/static_root/assets/pagination-toolbar-JH3Kbffr.451171f7ac33.js.br +0 -0
  207. codex/static_root/assets/pagination-toolbar-JH3Kbffr.451171f7ac33.js.gz +0 -0
  208. codex/static_root/assets/{pagination-toolbar-CkIzuyx1.js → pagination-toolbar-JH3Kbffr.js} +1 -1
  209. codex/static_root/assets/pagination-toolbar-JH3Kbffr.js.br +0 -0
  210. codex/static_root/assets/pagination-toolbar-JH3Kbffr.js.gz +0 -0
  211. codex/static_root/assets/{pdf-doc-BjlRPuf4.0f056fa321b6.js → pdf-doc-BcRNpoaW.882f6e967869.js} +1 -1
  212. codex/static_root/assets/pdf-doc-BcRNpoaW.882f6e967869.js.br +0 -0
  213. codex/static_root/assets/pdf-doc-BcRNpoaW.882f6e967869.js.gz +0 -0
  214. codex/static_root/assets/{pdf-doc-BjlRPuf4.js → pdf-doc-BcRNpoaW.js} +1 -1
  215. codex/static_root/assets/pdf-doc-BcRNpoaW.js.br +0 -0
  216. codex/static_root/assets/pdf-doc-BcRNpoaW.js.gz +0 -0
  217. codex/static_root/assets/reader-DIPRg2VB.900370e097aa.js +2 -0
  218. codex/static_root/assets/reader-DIPRg2VB.900370e097aa.js.br +0 -0
  219. codex/static_root/assets/reader-DIPRg2VB.900370e097aa.js.gz +0 -0
  220. codex/static_root/assets/reader-DIPRg2VB.js +2 -0
  221. codex/static_root/assets/reader-DIPRg2VB.js.br +0 -0
  222. codex/static_root/assets/reader-DIPRg2VB.js.gz +0 -0
  223. codex/static_root/assets/reader-DveZZr9x.7b21b9f8f628.css +1 -0
  224. codex/static_root/assets/reader-DveZZr9x.7b21b9f8f628.css.br +0 -0
  225. codex/static_root/assets/reader-DveZZr9x.7b21b9f8f628.css.gz +0 -0
  226. codex/static_root/assets/reader-DveZZr9x.css +1 -0
  227. codex/static_root/assets/reader-DveZZr9x.css.br +0 -0
  228. codex/static_root/assets/reader-DveZZr9x.css.gz +0 -0
  229. codex/static_root/assets/{relation-chips-CUSatZET.js → relation-chips-3tTlR5QH.71f18bc92adc.js} +1 -1
  230. codex/static_root/assets/relation-chips-3tTlR5QH.71f18bc92adc.js.br +0 -0
  231. codex/static_root/assets/relation-chips-3tTlR5QH.71f18bc92adc.js.gz +0 -0
  232. codex/static_root/assets/{relation-chips-CUSatZET.a58031ff8141.js → relation-chips-3tTlR5QH.js} +1 -1
  233. codex/static_root/assets/relation-chips-3tTlR5QH.js.br +0 -0
  234. codex/static_root/assets/relation-chips-3tTlR5QH.js.gz +0 -0
  235. codex/static_root/assets/{settings-drawer-BSHTAsJ9.js → settings-drawer-BdyFhA_r.151f4c3061ed.js} +2 -2
  236. codex/static_root/assets/settings-drawer-BdyFhA_r.151f4c3061ed.js.br +0 -0
  237. codex/static_root/assets/settings-drawer-BdyFhA_r.151f4c3061ed.js.gz +0 -0
  238. codex/static_root/assets/{settings-drawer-BSHTAsJ9.1d07ce084fc9.js → settings-drawer-BdyFhA_r.js} +2 -2
  239. codex/static_root/assets/settings-drawer-BdyFhA_r.js.br +0 -0
  240. codex/static_root/assets/settings-drawer-BdyFhA_r.js.gz +0 -0
  241. codex/static_root/assets/stats-tab-DeKjwvmh.7557c71b4cfa.js +1 -0
  242. codex/static_root/assets/stats-tab-DeKjwvmh.7557c71b4cfa.js.br +0 -0
  243. codex/static_root/assets/stats-tab-DeKjwvmh.7557c71b4cfa.js.gz +0 -0
  244. codex/static_root/assets/stats-tab-DeKjwvmh.js +1 -0
  245. codex/static_root/assets/stats-tab-DeKjwvmh.js.br +0 -0
  246. codex/static_root/assets/stats-tab-DeKjwvmh.js.gz +0 -0
  247. codex/static_root/assets/{stats-tab-BXGisn5N.9b7a71e7fe28.css → stats-tab-DpfGsVX3.1cb66f2649a9.css} +1 -1
  248. codex/static_root/assets/stats-tab-DpfGsVX3.1cb66f2649a9.css.br +0 -0
  249. codex/static_root/assets/stats-tab-DpfGsVX3.1cb66f2649a9.css.gz +0 -0
  250. codex/static_root/assets/{stats-tab-BXGisn5N.css → stats-tab-DpfGsVX3.css} +1 -1
  251. codex/static_root/assets/stats-tab-DpfGsVX3.css.br +0 -0
  252. codex/static_root/assets/stats-tab-DpfGsVX3.css.gz +0 -0
  253. codex/static_root/assets/{task-tab-NORFAa9p.97e07e366ddd.js → task-tab-C8D0qRP_.d4ab174c69a3.js} +1 -1
  254. codex/static_root/assets/task-tab-C8D0qRP_.d4ab174c69a3.js.br +0 -0
  255. codex/static_root/assets/task-tab-C8D0qRP_.d4ab174c69a3.js.gz +0 -0
  256. codex/static_root/assets/{task-tab-NORFAa9p.js → task-tab-C8D0qRP_.js} +1 -1
  257. codex/static_root/assets/task-tab-C8D0qRP_.js.br +0 -0
  258. codex/static_root/assets/task-tab-C8D0qRP_.js.gz +0 -0
  259. codex/static_root/assets/unauthorized-BHgBRF4z.8e5c1b9e52b0.js +1 -0
  260. codex/static_root/assets/unauthorized-BHgBRF4z.8e5c1b9e52b0.js.br +0 -0
  261. codex/static_root/assets/unauthorized-BHgBRF4z.8e5c1b9e52b0.js.gz +0 -0
  262. codex/static_root/assets/unauthorized-BHgBRF4z.js +1 -0
  263. codex/static_root/assets/unauthorized-BHgBRF4z.js.br +0 -0
  264. codex/static_root/assets/unauthorized-BHgBRF4z.js.gz +0 -0
  265. codex/static_root/assets/{unauthorized-muDsv-rC.css → unauthorized-BjhIc97q.728511c92cd0.css} +1 -1
  266. codex/static_root/assets/unauthorized-BjhIc97q.728511c92cd0.css.br +0 -0
  267. codex/static_root/assets/unauthorized-BjhIc97q.728511c92cd0.css.gz +0 -0
  268. codex/static_root/assets/{unauthorized-muDsv-rC.2166ec8b3a32.css → unauthorized-BjhIc97q.css} +1 -1
  269. codex/static_root/assets/unauthorized-BjhIc97q.css.br +0 -0
  270. codex/static_root/assets/unauthorized-BjhIc97q.css.gz +0 -0
  271. codex/static_root/assets/{user-tab-CHbyN1EW.e7206db08680.js → user-tab-BU31Z92y.35613c713faf.js} +1 -1
  272. codex/static_root/assets/user-tab-BU31Z92y.35613c713faf.js.br +0 -0
  273. codex/static_root/assets/user-tab-BU31Z92y.35613c713faf.js.gz +0 -0
  274. codex/static_root/assets/{user-tab-CHbyN1EW.js → user-tab-BU31Z92y.js} +1 -1
  275. codex/static_root/assets/user-tab-BU31Z92y.js.br +0 -0
  276. codex/static_root/assets/user-tab-BU31Z92y.js.gz +0 -0
  277. codex/static_root/js/choices-admin.8aa64c911203.json +1 -0
  278. codex/static_root/js/choices-admin.8aa64c911203.json.br +0 -0
  279. codex/static_root/js/choices-admin.8aa64c911203.json.gz +0 -0
  280. codex/static_root/js/choices-admin.json +1 -1
  281. codex/static_root/js/choices-admin.json.br +0 -0
  282. codex/static_root/js/choices-admin.json.gz +0 -0
  283. codex/static_root/manifest.45cb46e19686.json +635 -0
  284. codex/static_root/manifest.45cb46e19686.json.br +0 -0
  285. codex/static_root/manifest.45cb46e19686.json.gz +0 -0
  286. codex/static_root/manifest.json +248 -248
  287. codex/static_root/manifest.json.br +0 -0
  288. codex/static_root/manifest.json.gz +0 -0
  289. codex/static_root/staticfiles.json +1 -1
  290. codex/status_controller.py +10 -4
  291. codex/views/admin/tasks.py +46 -40
  292. codex/views/auth.py +15 -4
  293. codex/views/browser/annotations.py +94 -51
  294. codex/views/browser/base.py +1 -2
  295. codex/views/browser/browser.py +52 -21
  296. codex/views/browser/cover.py +8 -4
  297. codex/views/browser/filters/annotations.py +28 -6
  298. codex/views/browser/filters/search/__init__.py +1 -0
  299. codex/views/browser/filters/search/aliases.py +81 -0
  300. codex/views/browser/filters/search/field/__init__.py +1 -0
  301. codex/views/browser/filters/search/field/column.py +53 -0
  302. codex/views/browser/filters/search/field/expression.py +177 -0
  303. codex/views/browser/filters/search/field/filter.py +70 -0
  304. codex/views/browser/filters/search/field/optimize.py +71 -0
  305. codex/views/browser/filters/search/field/parse.py +187 -0
  306. codex/views/browser/filters/search/fts.py +38 -0
  307. codex/views/browser/filters/search/parse.py +220 -0
  308. codex/views/browser/order_by.py +8 -2
  309. codex/views/browser/page_in_bounds.py +88 -0
  310. codex/views/browser/paginate.py +28 -113
  311. codex/views/const.py +0 -1
  312. codex/views/opds/v1/feed.py +2 -1
  313. codex/views/opds/v2/feed.py +2 -1
  314. codex/views/opds/v2/links.py +1 -1
  315. codex/views/reader/books.py +1 -1
  316. codex/views/reader/page.py +3 -3
  317. {codex-1.6.19.dist-info → codex-1.7.0a0.dist-info}/METADATA +18 -10
  318. {codex-1.6.19.dist-info → codex-1.7.0a0.dist-info}/RECORD +321 -372
  319. codex/_vendor/__init__.py +0 -0
  320. codex/_vendor/django_haystack-3.2.1.dist-info/AUTHORS +0 -127
  321. codex/_vendor/django_haystack-3.2.1.dist-info/INSTALLER +0 -1
  322. codex/_vendor/django_haystack-3.2.1.dist-info/LICENSE +0 -31
  323. codex/_vendor/django_haystack-3.2.1.dist-info/METADATA +0 -98
  324. codex/_vendor/django_haystack-3.2.1.dist-info/RECORD +0 -97
  325. codex/_vendor/django_haystack-3.2.1.dist-info/REQUESTED +0 -0
  326. codex/_vendor/django_haystack-3.2.1.dist-info/WHEEL +0 -5
  327. codex/_vendor/django_haystack-3.2.1.dist-info/top_level.txt +0 -1
  328. codex/_vendor/haystack/__init__.py +0 -80
  329. codex/_vendor/haystack/admin.py +0 -163
  330. codex/_vendor/haystack/apps.py +0 -31
  331. codex/_vendor/haystack/backends/__init__.py +0 -1109
  332. codex/_vendor/haystack/backends/elasticsearch2_backend.py +0 -390
  333. codex/_vendor/haystack/backends/elasticsearch5_backend.py +0 -483
  334. codex/_vendor/haystack/backends/elasticsearch7_backend.py +0 -586
  335. codex/_vendor/haystack/backends/elasticsearch_backend.py +0 -1141
  336. codex/_vendor/haystack/backends/simple_backend.py +0 -132
  337. codex/_vendor/haystack/backends/solr_backend.py +0 -991
  338. codex/_vendor/haystack/backends/whoosh_backend.py +0 -1104
  339. codex/_vendor/haystack/constants.py +0 -57
  340. codex/_vendor/haystack/exceptions.py +0 -57
  341. codex/_vendor/haystack/fields.py +0 -562
  342. codex/_vendor/haystack/forms.py +0 -135
  343. codex/_vendor/haystack/generic_views.py +0 -141
  344. codex/_vendor/haystack/indexes.py +0 -548
  345. codex/_vendor/haystack/inputs.py +0 -169
  346. codex/_vendor/haystack/management/__init__.py +0 -0
  347. codex/_vendor/haystack/management/commands/__init__.py +0 -0
  348. codex/_vendor/haystack/management/commands/build_solr_schema.py +0 -187
  349. codex/_vendor/haystack/management/commands/clear_index.py +0 -67
  350. codex/_vendor/haystack/management/commands/haystack_info.py +0 -22
  351. codex/_vendor/haystack/management/commands/rebuild_index.py +0 -65
  352. codex/_vendor/haystack/management/commands/update_index.py +0 -438
  353. codex/_vendor/haystack/manager.py +0 -105
  354. codex/_vendor/haystack/models.py +0 -257
  355. codex/_vendor/haystack/panels.py +0 -89
  356. codex/_vendor/haystack/query.py +0 -771
  357. codex/_vendor/haystack/routers.py +0 -14
  358. codex/_vendor/haystack/signals.py +0 -88
  359. codex/_vendor/haystack/templates/panels/haystack.html +0 -33
  360. codex/_vendor/haystack/templates/search_configuration/schema.xml +0 -1056
  361. codex/_vendor/haystack/templates/search_configuration/solrconfig.xml +0 -1446
  362. codex/_vendor/haystack/templatetags/__init__.py +0 -0
  363. codex/_vendor/haystack/templatetags/highlight.py +0 -131
  364. codex/_vendor/haystack/templatetags/more_like_this.py +0 -119
  365. codex/_vendor/haystack/urls.py +0 -5
  366. codex/_vendor/haystack/utils/__init__.py +0 -84
  367. codex/_vendor/haystack/utils/app_loading.py +0 -34
  368. codex/_vendor/haystack/utils/geo.py +0 -71
  369. codex/_vendor/haystack/utils/highlighting.py +0 -165
  370. codex/_vendor/haystack/utils/loading.py +0 -374
  371. codex/_vendor/haystack/utils/log.py +0 -21
  372. codex/_vendor/haystack/version.py +0 -16
  373. codex/_vendor/haystack/views.py +0 -253
  374. codex/integrity.py +0 -492
  375. codex/librarian/search/merge.py +0 -86
  376. codex/librarian/search/version.py +0 -63
  377. codex/search/__init__.py +0 -1
  378. codex/search/backend.py +0 -524
  379. codex/search/backend_search.py +0 -229
  380. codex/search/engine.py +0 -33
  381. codex/search/indexes.py +0 -79
  382. codex/search/query.py +0 -67
  383. codex/search/writing.py +0 -180
  384. codex/static_root/assets/VCheckbox-Cko1sQK-.170726b3b8a1.js.br +0 -0
  385. codex/static_root/assets/VCheckbox-Cko1sQK-.170726b3b8a1.js.gz +0 -0
  386. codex/static_root/assets/VCheckbox-Cko1sQK-.js.br +0 -0
  387. codex/static_root/assets/VCheckbox-Cko1sQK-.js.gz +0 -0
  388. codex/static_root/assets/VCheckboxBtn-CO3-aqQL.c9b8062fd66f.js.br +0 -0
  389. codex/static_root/assets/VCheckboxBtn-CO3-aqQL.c9b8062fd66f.js.gz +0 -0
  390. codex/static_root/assets/VCheckboxBtn-CO3-aqQL.js.br +0 -0
  391. codex/static_root/assets/VCheckboxBtn-CO3-aqQL.js.gz +0 -0
  392. codex/static_root/assets/VCombobox-Bjp6lffE.caf59fba486e.js.br +0 -0
  393. codex/static_root/assets/VCombobox-Bjp6lffE.caf59fba486e.js.gz +0 -0
  394. codex/static_root/assets/VCombobox-Bjp6lffE.js.br +0 -0
  395. codex/static_root/assets/VCombobox-Bjp6lffE.js.gz +0 -0
  396. codex/static_root/assets/VDialog-BkpVGB70.6eea3ca762a5.js.br +0 -0
  397. codex/static_root/assets/VDialog-BkpVGB70.6eea3ca762a5.js.gz +0 -0
  398. codex/static_root/assets/VDialog-BkpVGB70.js.br +0 -0
  399. codex/static_root/assets/VDialog-BkpVGB70.js.gz +0 -0
  400. codex/static_root/assets/VExpansionPanels-Ci2-j8XX.9c55db4ef49e.js.br +0 -0
  401. codex/static_root/assets/VExpansionPanels-Ci2-j8XX.9c55db4ef49e.js.gz +0 -0
  402. codex/static_root/assets/VExpansionPanels-Ci2-j8XX.js.br +0 -0
  403. codex/static_root/assets/VExpansionPanels-Ci2-j8XX.js.gz +0 -0
  404. codex/static_root/assets/VRadioGroup-D3Py5BfQ.a4f25edb86d3.js.br +0 -0
  405. codex/static_root/assets/VRadioGroup-D3Py5BfQ.a4f25edb86d3.js.gz +0 -0
  406. codex/static_root/assets/VRadioGroup-D3Py5BfQ.js.br +0 -0
  407. codex/static_root/assets/VRadioGroup-D3Py5BfQ.js.gz +0 -0
  408. codex/static_root/assets/VSelect-DtvZsYZz.e98745d858eb.js.br +0 -0
  409. codex/static_root/assets/VSelect-DtvZsYZz.e98745d858eb.js.gz +0 -0
  410. codex/static_root/assets/VSelect-DtvZsYZz.js.br +0 -0
  411. codex/static_root/assets/VSelect-DtvZsYZz.js.gz +0 -0
  412. codex/static_root/assets/VSelectionControl-D6kmykQW.1e1fda62ceba.js.br +0 -0
  413. codex/static_root/assets/VSelectionControl-D6kmykQW.1e1fda62ceba.js.gz +0 -0
  414. codex/static_root/assets/VSelectionControl-D6kmykQW.js.br +0 -0
  415. codex/static_root/assets/VSelectionControl-D6kmykQW.js.gz +0 -0
  416. codex/static_root/assets/VSlideGroup-UGZWxpF5.360bdefcd215.js.br +0 -0
  417. codex/static_root/assets/VSlideGroup-UGZWxpF5.360bdefcd215.js.gz +0 -0
  418. codex/static_root/assets/VSlideGroup-UGZWxpF5.js.br +0 -0
  419. codex/static_root/assets/VSlideGroup-UGZWxpF5.js.gz +0 -0
  420. codex/static_root/assets/VTable-DXH_yQ0o.1149f56ad566.js.br +0 -0
  421. codex/static_root/assets/VTable-DXH_yQ0o.1149f56ad566.js.gz +0 -0
  422. codex/static_root/assets/VTable-DXH_yQ0o.js.br +0 -0
  423. codex/static_root/assets/VTable-DXH_yQ0o.js.gz +0 -0
  424. codex/static_root/assets/VTextField-Blqy56_L.26d8761e0155.js.br +0 -0
  425. codex/static_root/assets/VTextField-Blqy56_L.26d8761e0155.js.gz +0 -0
  426. codex/static_root/assets/VTextField-Blqy56_L.js.br +0 -0
  427. codex/static_root/assets/VTextField-Blqy56_L.js.gz +0 -0
  428. codex/static_root/assets/VWindowItem-C8_ovV7e.afbc08414765.js.br +0 -0
  429. codex/static_root/assets/VWindowItem-C8_ovV7e.afbc08414765.js.gz +0 -0
  430. codex/static_root/assets/VWindowItem-C8_ovV7e.js.br +0 -0
  431. codex/static_root/assets/VWindowItem-C8_ovV7e.js.gz +0 -0
  432. codex/static_root/assets/admin-DTRn8bBs.d031ea42d8d0.js.br +0 -0
  433. codex/static_root/assets/admin-DTRn8bBs.d031ea42d8d0.js.gz +0 -0
  434. codex/static_root/assets/admin-DTRn8bBs.js.br +0 -0
  435. codex/static_root/assets/admin-DTRn8bBs.js.gz +0 -0
  436. codex/static_root/assets/admin-drawer-panel-BaXFOcru.b1a44b05f482.js.br +0 -0
  437. codex/static_root/assets/admin-drawer-panel-BaXFOcru.b1a44b05f482.js.gz +0 -0
  438. codex/static_root/assets/admin-drawer-panel-BaXFOcru.js.br +0 -0
  439. codex/static_root/assets/admin-drawer-panel-BaXFOcru.js.gz +0 -0
  440. codex/static_root/assets/browser-BBpUyGmz.c1cb9e2d463b.js +0 -1
  441. codex/static_root/assets/browser-BBpUyGmz.c1cb9e2d463b.js.br +0 -0
  442. codex/static_root/assets/browser-BBpUyGmz.c1cb9e2d463b.js.gz +0 -0
  443. codex/static_root/assets/browser-BBpUyGmz.js +0 -1
  444. codex/static_root/assets/browser-BBpUyGmz.js.br +0 -0
  445. codex/static_root/assets/browser-BBpUyGmz.js.gz +0 -0
  446. codex/static_root/assets/browser-Binc3n9H.313722d27ca3.css +0 -1
  447. codex/static_root/assets/browser-Binc3n9H.313722d27ca3.css.br +0 -0
  448. codex/static_root/assets/browser-Binc3n9H.313722d27ca3.css.gz +0 -0
  449. codex/static_root/assets/browser-Binc3n9H.css +0 -1
  450. codex/static_root/assets/browser-Binc3n9H.css.br +0 -0
  451. codex/static_root/assets/browser-Binc3n9H.css.gz +0 -0
  452. codex/static_root/assets/change-password-dialog-Cebek1-c.aff2975e31f8.css +0 -1
  453. codex/static_root/assets/change-password-dialog-Cebek1-c.aff2975e31f8.css.br +0 -0
  454. codex/static_root/assets/change-password-dialog-Cebek1-c.aff2975e31f8.css.gz +0 -0
  455. codex/static_root/assets/change-password-dialog-Cebek1-c.css +0 -1
  456. codex/static_root/assets/change-password-dialog-Cebek1-c.css.br +0 -0
  457. codex/static_root/assets/change-password-dialog-Cebek1-c.css.gz +0 -0
  458. codex/static_root/assets/change-password-dialog-DlHoLhDF.76ab4a29bb9b.js +0 -1
  459. codex/static_root/assets/change-password-dialog-DlHoLhDF.76ab4a29bb9b.js.br +0 -0
  460. codex/static_root/assets/change-password-dialog-DlHoLhDF.76ab4a29bb9b.js.gz +0 -0
  461. codex/static_root/assets/change-password-dialog-DlHoLhDF.js +0 -1
  462. codex/static_root/assets/change-password-dialog-DlHoLhDF.js.br +0 -0
  463. codex/static_root/assets/change-password-dialog-DlHoLhDF.js.gz +0 -0
  464. codex/static_root/assets/confirm-dialog-D3_s2DQy.9dde66036c72.js.br +0 -0
  465. codex/static_root/assets/confirm-dialog-D3_s2DQy.9dde66036c72.js.gz +0 -0
  466. codex/static_root/assets/confirm-dialog-D3_s2DQy.js.br +0 -0
  467. codex/static_root/assets/confirm-dialog-D3_s2DQy.js.gz +0 -0
  468. codex/static_root/assets/datetime-column-BxC1Li9e.3dc314b3295d.js.br +0 -0
  469. codex/static_root/assets/datetime-column-BxC1Li9e.3dc314b3295d.js.gz +0 -0
  470. codex/static_root/assets/datetime-column-BxC1Li9e.js.br +0 -0
  471. codex/static_root/assets/datetime-column-BxC1Li9e.js.gz +0 -0
  472. codex/static_root/assets/filter-Bzk7x841.d0c3b602e62d.js.br +0 -0
  473. codex/static_root/assets/filter-Bzk7x841.d0c3b602e62d.js.gz +0 -0
  474. codex/static_root/assets/filter-Bzk7x841.js.br +0 -0
  475. codex/static_root/assets/filter-Bzk7x841.js.gz +0 -0
  476. codex/static_root/assets/flag-tab-C2bI5zq3.8f8c297600a6.js +0 -1
  477. codex/static_root/assets/flag-tab-C2bI5zq3.8f8c297600a6.js.br +0 -0
  478. codex/static_root/assets/flag-tab-C2bI5zq3.8f8c297600a6.js.gz +0 -0
  479. codex/static_root/assets/flag-tab-C2bI5zq3.js +0 -1
  480. codex/static_root/assets/flag-tab-C2bI5zq3.js.br +0 -0
  481. codex/static_root/assets/flag-tab-C2bI5zq3.js.gz +0 -0
  482. codex/static_root/assets/group-tab-5esH4lwX.a81fdd258117.js.br +0 -0
  483. codex/static_root/assets/group-tab-5esH4lwX.a81fdd258117.js.gz +0 -0
  484. codex/static_root/assets/group-tab-5esH4lwX.js.br +0 -0
  485. codex/static_root/assets/group-tab-5esH4lwX.js.gz +0 -0
  486. codex/static_root/assets/http-error-BTOBfcGY.52ced6f28420.js.br +0 -0
  487. codex/static_root/assets/http-error-BTOBfcGY.52ced6f28420.js.gz +0 -0
  488. codex/static_root/assets/http-error-BTOBfcGY.js.br +0 -0
  489. codex/static_root/assets/http-error-BTOBfcGY.js.gz +0 -0
  490. codex/static_root/assets/library-tab-DiPEdOF7.ece2d642a9dc.js.br +0 -0
  491. codex/static_root/assets/library-tab-DiPEdOF7.ece2d642a9dc.js.gz +0 -0
  492. codex/static_root/assets/library-tab-DiPEdOF7.js.br +0 -0
  493. codex/static_root/assets/library-tab-DiPEdOF7.js.gz +0 -0
  494. codex/static_root/assets/main-BPIPjzsc.66def8991e38.js +0 -6
  495. codex/static_root/assets/main-BPIPjzsc.66def8991e38.js.br +0 -0
  496. codex/static_root/assets/main-BPIPjzsc.66def8991e38.js.gz +0 -0
  497. codex/static_root/assets/main-BPIPjzsc.js +0 -6
  498. codex/static_root/assets/main-BPIPjzsc.js.br +0 -0
  499. codex/static_root/assets/main-BPIPjzsc.js.gz +0 -0
  500. codex/static_root/assets/pager-full-pdf-CiyC6Al9.278b9978f36f.js +0 -1
  501. codex/static_root/assets/pager-full-pdf-CiyC6Al9.278b9978f36f.js.br +0 -0
  502. codex/static_root/assets/pager-full-pdf-CiyC6Al9.278b9978f36f.js.gz +0 -0
  503. codex/static_root/assets/pager-full-pdf-CiyC6Al9.js +0 -1
  504. codex/static_root/assets/pager-full-pdf-CiyC6Al9.js.br +0 -0
  505. codex/static_root/assets/pager-full-pdf-CiyC6Al9.js.gz +0 -0
  506. codex/static_root/assets/pagination-toolbar-C45-onwe.4722195bb60b.css.br +0 -0
  507. codex/static_root/assets/pagination-toolbar-C45-onwe.4722195bb60b.css.gz +0 -0
  508. codex/static_root/assets/pagination-toolbar-C45-onwe.css.br +0 -0
  509. codex/static_root/assets/pagination-toolbar-C45-onwe.css.gz +0 -0
  510. codex/static_root/assets/pagination-toolbar-CkIzuyx1.00c354a82e6e.js.br +0 -0
  511. codex/static_root/assets/pagination-toolbar-CkIzuyx1.00c354a82e6e.js.gz +0 -0
  512. codex/static_root/assets/pagination-toolbar-CkIzuyx1.js.br +0 -0
  513. codex/static_root/assets/pagination-toolbar-CkIzuyx1.js.gz +0 -0
  514. codex/static_root/assets/pdf-doc-BjlRPuf4.0f056fa321b6.js.br +0 -0
  515. codex/static_root/assets/pdf-doc-BjlRPuf4.0f056fa321b6.js.gz +0 -0
  516. codex/static_root/assets/pdf-doc-BjlRPuf4.js.br +0 -0
  517. codex/static_root/assets/pdf-doc-BjlRPuf4.js.gz +0 -0
  518. codex/static_root/assets/reader-_stAWL-4.5089e9144795.css +0 -1
  519. codex/static_root/assets/reader-_stAWL-4.5089e9144795.css.br +0 -0
  520. codex/static_root/assets/reader-_stAWL-4.5089e9144795.css.gz +0 -0
  521. codex/static_root/assets/reader-_stAWL-4.css +0 -1
  522. codex/static_root/assets/reader-_stAWL-4.css.br +0 -0
  523. codex/static_root/assets/reader-_stAWL-4.css.gz +0 -0
  524. codex/static_root/assets/reader-ucxnLi2K.d0fbce0f03c1.js +0 -2
  525. codex/static_root/assets/reader-ucxnLi2K.d0fbce0f03c1.js.br +0 -0
  526. codex/static_root/assets/reader-ucxnLi2K.d0fbce0f03c1.js.gz +0 -0
  527. codex/static_root/assets/reader-ucxnLi2K.js +0 -2
  528. codex/static_root/assets/reader-ucxnLi2K.js.br +0 -0
  529. codex/static_root/assets/reader-ucxnLi2K.js.gz +0 -0
  530. codex/static_root/assets/relation-chips-CUSatZET.a58031ff8141.js.br +0 -0
  531. codex/static_root/assets/relation-chips-CUSatZET.a58031ff8141.js.gz +0 -0
  532. codex/static_root/assets/relation-chips-CUSatZET.js.br +0 -0
  533. codex/static_root/assets/relation-chips-CUSatZET.js.gz +0 -0
  534. codex/static_root/assets/settings-drawer-BSHTAsJ9.1d07ce084fc9.js.br +0 -0
  535. codex/static_root/assets/settings-drawer-BSHTAsJ9.1d07ce084fc9.js.gz +0 -0
  536. codex/static_root/assets/settings-drawer-BSHTAsJ9.js.br +0 -0
  537. codex/static_root/assets/settings-drawer-BSHTAsJ9.js.gz +0 -0
  538. codex/static_root/assets/stats-tab-BXGisn5N.9b7a71e7fe28.css.br +0 -0
  539. codex/static_root/assets/stats-tab-BXGisn5N.9b7a71e7fe28.css.gz +0 -0
  540. codex/static_root/assets/stats-tab-BXGisn5N.css.br +0 -0
  541. codex/static_root/assets/stats-tab-BXGisn5N.css.gz +0 -0
  542. codex/static_root/assets/stats-tab-DKXVB2Cc.0a3de58bf5ee.js +0 -1
  543. codex/static_root/assets/stats-tab-DKXVB2Cc.0a3de58bf5ee.js.br +0 -0
  544. codex/static_root/assets/stats-tab-DKXVB2Cc.0a3de58bf5ee.js.gz +0 -0
  545. codex/static_root/assets/stats-tab-DKXVB2Cc.js +0 -1
  546. codex/static_root/assets/stats-tab-DKXVB2Cc.js.br +0 -0
  547. codex/static_root/assets/stats-tab-DKXVB2Cc.js.gz +0 -0
  548. codex/static_root/assets/task-tab-NORFAa9p.97e07e366ddd.js.br +0 -0
  549. codex/static_root/assets/task-tab-NORFAa9p.97e07e366ddd.js.gz +0 -0
  550. codex/static_root/assets/task-tab-NORFAa9p.js.br +0 -0
  551. codex/static_root/assets/task-tab-NORFAa9p.js.gz +0 -0
  552. codex/static_root/assets/unauthorized-RHaQZRfr.a234e9403f60.js +0 -1
  553. codex/static_root/assets/unauthorized-RHaQZRfr.a234e9403f60.js.br +0 -0
  554. codex/static_root/assets/unauthorized-RHaQZRfr.a234e9403f60.js.gz +0 -0
  555. codex/static_root/assets/unauthorized-RHaQZRfr.js +0 -1
  556. codex/static_root/assets/unauthorized-RHaQZRfr.js.br +0 -0
  557. codex/static_root/assets/unauthorized-RHaQZRfr.js.gz +0 -0
  558. codex/static_root/assets/unauthorized-muDsv-rC.2166ec8b3a32.css.br +0 -0
  559. codex/static_root/assets/unauthorized-muDsv-rC.2166ec8b3a32.css.gz +0 -0
  560. codex/static_root/assets/unauthorized-muDsv-rC.css.br +0 -0
  561. codex/static_root/assets/unauthorized-muDsv-rC.css.gz +0 -0
  562. codex/static_root/assets/user-tab-CHbyN1EW.e7206db08680.js.br +0 -0
  563. codex/static_root/assets/user-tab-CHbyN1EW.e7206db08680.js.gz +0 -0
  564. codex/static_root/assets/user-tab-CHbyN1EW.js.br +0 -0
  565. codex/static_root/assets/user-tab-CHbyN1EW.js.gz +0 -0
  566. codex/static_root/js/choices-admin.1a20a5648f20.json +0 -1
  567. codex/static_root/js/choices-admin.1a20a5648f20.json.br +0 -0
  568. codex/static_root/js/choices-admin.1a20a5648f20.json.gz +0 -0
  569. codex/static_root/manifest.0fe31a6cb99f.json +0 -635
  570. codex/static_root/manifest.0fe31a6cb99f.json.br +0 -0
  571. codex/static_root/manifest.0fe31a6cb99f.json.gz +0 -0
  572. codex/templates/search/indexes/codex/comic_text.txt +0 -47
  573. codex/views/browser/filters/search.py +0 -196
  574. {codex-1.6.19.dist-info → codex-1.7.0a0.dist-info}/LICENSE +0 -0
  575. {codex-1.6.19.dist-info → codex-1.7.0a0.dist-info}/WHEEL +0 -0
  576. {codex-1.6.19.dist-info → codex-1.7.0a0.dist-info}/entry_points.txt +0 -0
codex/search/backend.py DELETED
@@ -1,524 +0,0 @@
1
- """Custom Haystack Search Backend."""
2
-
3
- from math import ceil
4
- from multiprocessing import cpu_count
5
- from pathlib import Path
6
- from types import MappingProxyType
7
-
8
- from django.utils.timezone import now
9
- from humanfriendly import InvalidSize, parse_size
10
- from whoosh.analysis import (
11
- CharsetFilter,
12
- StemFilter,
13
- StemmingAnalyzer,
14
- )
15
- from whoosh.fields import BOOLEAN, DATETIME, NUMERIC, TEXT, FieldType, Schema
16
- from whoosh.filedb.filestore import FileStorage
17
- from whoosh.index import EmptyIndexError
18
- from whoosh.qparser import (
19
- CopyFieldPlugin,
20
- FieldAliasPlugin,
21
- GtLtPlugin,
22
- OperatorsPlugin,
23
- WhitespacePlugin,
24
- )
25
- from whoosh.qparser.dateparse import DateParserPlugin
26
- from whoosh.query import Or, Term
27
- from whoosh.support.charset import accent_map
28
-
29
- from codex._vendor.haystack.backends.whoosh_backend import (
30
- WHOOSH_ID,
31
- WhooshSearchBackend,
32
- )
33
- from codex._vendor.haystack.constants import DJANGO_CT, DJANGO_ID, ID
34
- from codex._vendor.haystack.exceptions import SearchBackendError, SkipDocument
35
- from codex.librarian.search.status import SearchIndexStatusTypes
36
- from codex.logger.logging import get_logger
37
- from codex.memory import get_mem_limit
38
- from codex.models import AdminFlag, Comic
39
- from codex.search.backend_search import CodexBackendSearchMixin
40
- from codex.search.indexes import ComicIndex
41
- from codex.search.writing import CodexWriter
42
- from codex.settings.settings import (
43
- CHUNK_PER_GB,
44
- CPU_MULTIPLIER,
45
- MAX_CHUNK_SIZE,
46
- MMAP_RATIO,
47
- WRITER_MEMORY_PERCENT,
48
- )
49
- from codex.worker_base import WorkerBaseMixin
50
-
51
-
52
- def gen_multipart_field_aliases(field):
53
- """Generate aliases for fields made of snake_case words."""
54
- bits = field.split("_")
55
- aliases = []
56
-
57
- # Singular from plural
58
- if field.endswith("s"):
59
- aliases += [field[:-1]]
60
-
61
- # Alternate delimiters
62
- for connector in ("", "-"):
63
- joined = connector.join(bits)
64
- aliases += [joined, joined[:-1]]
65
-
66
- return tuple(sorted(frozenset(aliases)))
67
-
68
-
69
- class FILESIZE(NUMERIC):
70
- """NUMERIC class with humanized filesize parser."""
71
-
72
- LOG = get_logger("FILESIZE")
73
-
74
- @classmethod
75
- def _parse_size(cls, value):
76
- """Parse the value for size suffixes."""
77
- try:
78
- value = str(parse_size(value))
79
- except InvalidSize as exc:
80
- cls.LOG.debug(exc)
81
- return value
82
-
83
- def parse_query(self, fieldname, qstring, boost=1.0):
84
- """Parse one term."""
85
- qstring = self._parse_size(qstring)
86
- return super().parse_query(fieldname, qstring, boost=boost)
87
-
88
- def parse_range( # noqa PLR0913
89
- self, fieldname, start, end, startexcl, endexcl, boost=1.0
90
- ):
91
- """Parse range terms."""
92
- if start:
93
- start = self._parse_size(start)
94
- if end:
95
- end = self._parse_size(end)
96
- return super().parse_range(
97
- fieldname, start, end, startexcl, endexcl, boost=boost
98
- )
99
-
100
-
101
- TEXT_ANALYZER = (
102
- # StandardAnalyzer() | CharsetFilter(accent_map) | StemFilter(cachesize=-1)
103
- StemmingAnalyzer(minsize=1) | CharsetFilter(accent_map) | StemFilter(cachesize=-1)
104
- )
105
-
106
-
107
- class CodexSearchBackend(CodexBackendSearchMixin, WhooshSearchBackend, WorkerBaseMixin):
108
- """Custom Whoosh Backend."""
109
-
110
- FIELDMAP = MappingProxyType(
111
- {
112
- "characters": ("category", "character"),
113
- "community_rating": gen_multipart_field_aliases("community_rating"),
114
- "contributors": (
115
- *gen_multipart_field_aliases("authors"),
116
- "contributor",
117
- *gen_multipart_field_aliases("creators"),
118
- *gen_multipart_field_aliases("credits"),
119
- *gen_multipart_field_aliases("people"),
120
- *gen_multipart_field_aliases("persons"),
121
- ),
122
- "created_at": ("created",),
123
- "critical_rating": gen_multipart_field_aliases("critical_rating"),
124
- "genres": ("genre",),
125
- "file_type": (
126
- "filetype",
127
- "type",
128
- ),
129
- "identifier": ("id", "nss"),
130
- "identifier_type": ("idtype", "id_type", "nid"),
131
- "issue_number": ("number",),
132
- "locations": ("location",),
133
- "monochrome": gen_multipart_field_aliases("black_and_white"),
134
- "name": ("title",),
135
- "original_format": ("format",),
136
- "page_count": ("pages",),
137
- "reading_direction": ("direction",),
138
- "search_path": (
139
- "path",
140
- "filename",
141
- *gen_multipart_field_aliases("folders"),
142
- ),
143
- "series_groups": gen_multipart_field_aliases("series_groups"),
144
- "scan_info": ("scan",),
145
- "stories": ("story",),
146
- "story_arcs": gen_multipart_field_aliases("story_arcs"),
147
- "summary": ("comments", "description"),
148
- "tags": ("tag",),
149
- "teams": ("team",),
150
- "updated_at": ("updated",),
151
- }
152
- )
153
- RESERVED_CHARACTERS = ()
154
- RESERVED_WORDS = ()
155
- FIELD_ALIAS_PLUGIN = FieldAliasPlugin(FIELDMAP)
156
- COPY_FIELD_PLUGIN = CopyFieldPlugin({"issue_number": "issue_suffix"})
157
- OPERATORS_PLUGIN = OperatorsPlugin(
158
- ops=None,
159
- clean=False,
160
- And=r"(?i)(?<=\s)AND(?=\s)",
161
- Or=r"(?i)(?<=\s)OR(?=\s)",
162
- AndNot=r"(?i)(?<=\s)ANDNOT(?=\s)",
163
- AndMaybe=r"(?i)(?<=\s)ANDMAYBE(?=\s)",
164
- Not=r"(?i)(^|(?<=(\s|[()])))NOT(?=\s)",
165
- Require=r"(?i)(^|(?<=\s))REQUIRE(?=\s)",
166
- )
167
- STATUS_FINISH_TYPES = frozenset(
168
- (
169
- SearchIndexStatusTypes.SEARCH_INDEX_CLEAR,
170
- SearchIndexStatusTypes.SEARCH_INDEX_UPDATE,
171
- )
172
- )
173
- WRITER_PERIOD = 0 # No period timer.
174
- WRITER_LIMIT = 1000
175
- COMMITARGS_MERGE_SMALL = MappingProxyType({"merge": True})
176
- COMMITARGS_NO_MERGE = MappingProxyType({"merge": False})
177
- _SELECT_RELATED_FIELDS = ("publisher", "imprint", "series", "volume")
178
- _PREFETCH_RELATED_FIELDS = (
179
- "characters",
180
- "contributors",
181
- "genres",
182
- "locations",
183
- "series_groups",
184
- "story_arc_numbers__story_arc",
185
- "tags",
186
- "teams",
187
- "contributors__person",
188
- )
189
- _DEFERRED_FIELDS = (
190
- "parent_folder",
191
- "library",
192
- "path",
193
- "stat",
194
- # "folders", # don't explicitly defer m2m
195
- )
196
- _ONEMB = 1024**2
197
- ###################
198
- # MEMORY CONTROLS #
199
- ###################
200
- # Magic number determined by tests
201
- # The perfect number may be larger than this but is below 369
202
- _MMAP_RATIO = MMAP_RATIO
203
- _WRITER_MEMORY_PERCENT = WRITER_MEMORY_PERCENT
204
- _CPU_MULTIPLIER = CPU_MULTIPLIER
205
- _CHUNK_PER_GB = CHUNK_PER_GB
206
- _MAX_CHUNK_SIZE = MAX_CHUNK_SIZE
207
- _DECIMAL_FIELD_NAMES = frozenset({"decimal", "float"})
208
- _DATETIME_FIELD_NAMES = frozenset({"date", "datetime"})
209
-
210
- def __init__(self, connection_alias, **connection_options):
211
- """Init worker queues."""
212
- super().__init__(connection_alias, **connection_options)
213
- # XXX will only connect to the log listener on Linux with fork
214
- self.log = get_logger(self.__class__.__name__)
215
- self.log.propagate = False
216
- self._set_writerargs()
217
-
218
- def _set_writerargs(self):
219
- """Get writerargs for this machine's cpu & memory config."""
220
- mem_limit_mb = get_mem_limit("m")
221
- mem_limit_gb = mem_limit_mb / 1024
222
- cpu_max = ceil(mem_limit_gb * self._CPU_MULTIPLIER)
223
- procs = min(cpu_count(), cpu_max)
224
- limitmb = mem_limit_mb * self._WRITER_MEMORY_PERCENT / procs
225
- limitmb = int(limitmb)
226
- self.writerargs = {"limitmb": limitmb, "procs": procs, "multisegment": True}
227
- self.chunk_size = min(
228
- int(mem_limit_gb * self._CHUNK_PER_GB), self._MAX_CHUNK_SIZE
229
- )
230
-
231
- def build_schema(self, fields):
232
- """Customize Codex Schema.
233
-
234
- custom size field,
235
- 64 bit unsigned ints.
236
- 16 bit unsigned flaots.
237
- unsortable text and datetime fields.
238
- """
239
- schema_fields: dict[str, FieldType] = {
240
- ID: WHOOSH_ID(stored=True, unique=True),
241
- DJANGO_CT: WHOOSH_ID(stored=True),
242
- DJANGO_ID: WHOOSH_ID(stored=True),
243
- }
244
-
245
- initial_key_count = len(schema_fields)
246
- content_field_name = ""
247
-
248
- for field_class in fields.values():
249
- index_fieldname = field_class.index_fieldname
250
- if field_class.field_type == "integer":
251
- schema_field_class = FILESIZE if index_fieldname == "size" else NUMERIC
252
- schema_fields[index_fieldname] = schema_field_class(
253
- numtype=int,
254
- bits=64,
255
- field_boost=field_class.boost,
256
- signed=False,
257
- stored=field_class.stored,
258
- )
259
- elif field_class.field_type in self._DECIMAL_FIELD_NAMES:
260
- schema_fields[index_fieldname] = NUMERIC(
261
- numtype=float, # type: ignore
262
- field_boost=field_class.boost,
263
- stored=field_class.stored,
264
- )
265
- elif field_class.field_type in self._DATETIME_FIELD_NAMES:
266
- schema_fields[index_fieldname] = DATETIME(
267
- stored=field_class.stored,
268
- )
269
- elif field_class.field_type == "boolean":
270
- # Field boost isn't supported on BOOLEAN as of 1.8.2.
271
- schema_fields[index_fieldname] = BOOLEAN(stored=field_class.stored)
272
- else:
273
- schema_fields[index_fieldname] = TEXT(
274
- stored=True,
275
- analyzer=TEXT_ANALYZER,
276
- field_boost=field_class.boost,
277
- )
278
- if field_class.document:
279
- content_field_name = index_fieldname
280
-
281
- # Fail more gracefully than relying on the backend to die if no fields
282
- # are found.
283
- if len(schema_fields) <= initial_key_count:
284
- reason = (
285
- "No fields were found in any search_indexes."
286
- " Please correct this before attempting to search."
287
- )
288
- raise SearchBackendError(reason)
289
-
290
- return (content_field_name, Schema(**schema_fields))
291
-
292
- def _setup_storage_patch(self):
293
- """Adapt FileStorage to not use mmap in low memory environments."""
294
- if not self.use_file_storage:
295
- return
296
-
297
- # Get sizes
298
- total_size = 0
299
- if self.path:
300
- for path in Path(self.path).glob("*.seg"):
301
- total_size += path.stat().st_size
302
- total_size_mb = total_size / self._ONEMB
303
- mem_limit_gb = get_mem_limit("g")
304
-
305
- # Decide
306
- ratio = total_size_mb / mem_limit_gb
307
- use_mmap = ratio < self._MMAP_RATIO
308
-
309
- if use_mmap:
310
- # Don't replace storage and index.
311
- return
312
-
313
- # Replace storage and index disabling mmap
314
- self.storage = FileStorage(self.path, supports_mmap=use_mmap)
315
- try:
316
- self.index = self.storage.open_index(schema=self.schema)
317
- except EmptyIndexError:
318
- self.index = self.storage.create_index(self.schema)
319
- self.log.debug("Memory limited. Disabled search index mmap")
320
-
321
- def _setup_parser_plugin_patch(self):
322
- """Set up codex plugins."""
323
- # Fix duplicate plugin bug:
324
- # https://github.com/mchaput/whoosh/pull/11
325
- self.parser.remove_plugin_class(WhitespacePlugin)
326
- self.parser.replace_plugin(self.OPERATORS_PLUGIN)
327
- plugins = [
328
- WhitespacePlugin,
329
- self.COPY_FIELD_PLUGIN,
330
- self.FIELD_ALIAS_PLUGIN,
331
- GtLtPlugin,
332
- ]
333
- plugins += [DateParserPlugin(basedate=now())]
334
- self.parser.add_plugins(plugins)
335
-
336
- def setup(self, patch_plugins=True):
337
- """Add extra plugins."""
338
- super().setup()
339
- self._setup_storage_patch()
340
- if patch_plugins:
341
- # The dateparser plugin won't pickle for
342
- # multiprocessing
343
- self._setup_parser_plugin_patch()
344
-
345
- def get_writer(self, commitargs=COMMITARGS_NO_MERGE):
346
- """Get a writer."""
347
- return CodexWriter(
348
- self.index.refresh(),
349
- writerargs=self.writerargs,
350
- commitargs=commitargs,
351
- )
352
-
353
- def _update_obj(self, index, writer, batch_num, obj):
354
- """Update one object."""
355
- try:
356
- doc = index.full_prepare(obj)
357
- # Really make sure it's unicode, because Whoosh won't have it any
358
- # other way.
359
- for key in doc:
360
- doc[key] = self._from_python(doc[key])
361
- except SkipDocument:
362
- self.log.debug(f"Indexing for object {obj} skipped in batch {batch_num}")
363
- except Exception as exc:
364
- self.log.warning(
365
- f"Preparing object for indexing: {exc}"
366
- f" in batch {batch_num}: {obj.path}"
367
- )
368
- raise
369
- else:
370
- # Document boosts aren't supported in Whoosh 2.5.0+.
371
- if "boost" in doc:
372
- del doc["boost"]
373
-
374
- try:
375
- # add instead of update because of above batch remove
376
- writer.add_document(**doc)
377
- except Exception as exc:
378
- if not self.silently_fail:
379
- raise
380
-
381
- # We'll log the object identifier but won't include the actual
382
- # object to avoid the possibility of that generating encoding
383
- # errors while processing the log message:
384
- self.log.warning(
385
- f"Search index adding document {exc}"
386
- f" in batch {batch_num}: {obj.path}",
387
- )
388
- raise
389
- else:
390
- return 1
391
- return 0
392
-
393
- def _update_init(self, index, batch_pks):
394
- if not self.setup_complete:
395
- self.setup(False)
396
-
397
- if not index:
398
- index = ComicIndex()
399
-
400
- writer = self.get_writer()
401
-
402
- try:
403
- self.remove_django_ids(batch_pks, writer=writer)
404
- except Exception as exc:
405
- self.log.warning(
406
- f"Couldn't delete search index records before replacing: {exc}"
407
- )
408
- writer.cancel()
409
- writer = self.get_writer()
410
-
411
- # prefetch is not pickleable, create the query here from pks.
412
- iterable = (
413
- Comic.objects.filter(pk__in=batch_pks)
414
- .defer(*self._DEFERRED_FIELDS)
415
- .select_related(*self._SELECT_RELATED_FIELDS)
416
- .prefetch_related(*self._PREFETCH_RELATED_FIELDS)
417
- .iterator(chunk_size=self.chunk_size)
418
- )
419
- return index, writer, iterable
420
-
421
- def _update_finish(self, count, batch_num, writer):
422
- """Finish the update by committing or canceling."""
423
- try:
424
- if count:
425
- msg = f"Search index starting final commit for batch {batch_num}."
426
- else:
427
- msg = (
428
- "Search index update cancelling batch"
429
- f" {batch_num} nothing to update."
430
- )
431
- writer.cancel()
432
- self.log.debug(msg)
433
-
434
- writer.close()
435
- except Exception as exc:
436
- self.log.debug(f"Writing batch {batch_num} failed: {exc}")
437
- writer.cancel()
438
- raise
439
- return count
440
-
441
- def update( # type: ignore
442
- self,
443
- index,
444
- iterable,
445
- commit=True, # noqa: ARG002
446
- batch_num=0,
447
- abort_event=None,
448
- ):
449
- """Update index, but with writer options."""
450
- batch_pks = iterable
451
- count = 0
452
- if abort_event and abort_event.is_set():
453
- self.log.debug(
454
- f"Stopped search index update batch {batch_num} before it started."
455
- )
456
- return count
457
- num_objs = len(batch_pks)
458
- if not num_objs:
459
- self.log.debug("Search index nothing to update.")
460
- return count
461
-
462
- index, writer, iterable = self._update_init(index, batch_pks)
463
-
464
- if abort_event and abort_event.is_set():
465
- self.log.debug(
466
- f"Stopped search index update batch {batch_num}"
467
- " after removing old records."
468
- )
469
- return count
470
-
471
- folder_view_enabled = AdminFlag.objects.get(
472
- key=AdminFlag.FlagChoices.FOLDER_VIEW.value
473
- ).on
474
- for obj in iterable:
475
- if abort_event and abort_event.is_set():
476
- self.log.debug(
477
- f"Stopped search index update batch {batch_num} at {count} updates."
478
- )
479
- break
480
- if not folder_view_enabled:
481
- # Hide path if folder view is disabled.
482
- # This also affects field search.
483
- obj.search_path = "" # type: ignore
484
- count += self._update_obj(index, writer, batch_num, obj)
485
- return self._update_finish(count, batch_num, writer)
486
-
487
- def remove_django_ids(self, pks, writer, searcher=None):
488
- """Remove a large batch of docs by pk from the index."""
489
- # Does not benefit from multiprocessing.
490
- if not len(pks):
491
- return 0
492
- query = Or([Term(DJANGO_ID, str(pk)) for pk in pks])
493
- return writer.delete_by_query(query, searcher=searcher)
494
-
495
- def remove_docnums(self, docnums):
496
- """Remove a batch of docnums from the index.."""
497
- writer = self.get_writer()
498
- count = 0
499
- try:
500
- count = writer.delete_batch_documents(docnums)
501
- except Exception as exc:
502
- self.log.warning(f"Search index removing documents by docnums {exc}")
503
- writer.cancel()
504
- finally:
505
- writer.close()
506
- return count
507
-
508
- def optimize(self):
509
- """Optimize the index."""
510
- if not self.setup_complete:
511
- self.setup(False)
512
- try:
513
- self.index.refresh().optimize(**self.writerargs)
514
- except Exception as exc:
515
- self.log.warn(
516
- f"Search Index unable to optimize '{exc}', it may work next time."
517
- )
518
-
519
- def merge_small(self):
520
- """Merge small segments of the index."""
521
- if not self.setup_complete:
522
- self.setup(False)
523
- writer = self.get_writer(MappingProxyType({"merge": True}))
524
- writer.close()