codex 1.8.5__py3-none-any.whl → 1.8.8__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 (542) hide show
  1. codex/choices/admin.py +1 -0
  2. codex/librarian/scribe/importer/const.py +7 -3
  3. codex/librarian/scribe/importer/create/comics.py +0 -3
  4. codex/librarian/scribe/importer/delete/comics.py +7 -4
  5. codex/librarian/scribe/importer/delete/folders.py +2 -1
  6. codex/librarian/scribe/importer/read/aggregate_path.py +53 -13
  7. codex/librarian/scribe/importer/read/extract.py +16 -13
  8. codex/librarian/scribe/importer/search/prepare.py +0 -7
  9. codex/librarian/scribe/importer/search/sync_m2m.py +2 -1
  10. codex/librarian/scribe/importer/search/update.py +18 -81
  11. codex/librarian/scribe/scribed.py +2 -13
  12. codex/librarian/scribe/{importer/search → search}/const.py +1 -13
  13. codex/librarian/scribe/search/prepare.py +162 -0
  14. codex/librarian/scribe/search/remove.py +22 -2
  15. codex/librarian/scribe/search/sync.py +88 -179
  16. codex/librarian/status_controller.py +25 -27
  17. codex/librarian/watchdog/event_batcherd.py +1 -1
  18. codex/migrations/0035_fts_optmize.py +136 -0
  19. codex/models/comic.py +0 -16
  20. codex/models/functions.py +3 -1
  21. codex/serializers/admin/tasks.py +1 -1
  22. codex/settings/__init__.py +26 -11
  23. codex/static_root/assets/VCheckbox-MwE_xq11.b2e2086608d9.js +1 -0
  24. codex/static_root/assets/VCheckbox-MwE_xq11.b2e2086608d9.js.br +0 -0
  25. codex/static_root/assets/VCheckbox-MwE_xq11.b2e2086608d9.js.gz +0 -0
  26. codex/static_root/assets/VCheckbox-MwE_xq11.js +1 -0
  27. codex/static_root/assets/VCheckbox-MwE_xq11.js.br +0 -0
  28. codex/static_root/assets/VCheckbox-MwE_xq11.js.gz +0 -0
  29. codex/static_root/assets/{VCheckboxBtn-BE6yrQ80.4a42f2c068f5.js → VCheckboxBtn-HUjl2ti_.f3e7b85503c6.js} +1 -1
  30. codex/static_root/assets/VCheckboxBtn-HUjl2ti_.f3e7b85503c6.js.br +0 -0
  31. codex/static_root/assets/VCheckboxBtn-HUjl2ti_.f3e7b85503c6.js.gz +0 -0
  32. codex/static_root/assets/{VCheckboxBtn-BE6yrQ80.js → VCheckboxBtn-HUjl2ti_.js} +1 -1
  33. codex/static_root/assets/VCheckboxBtn-HUjl2ti_.js.br +0 -0
  34. codex/static_root/assets/VCheckboxBtn-HUjl2ti_.js.gz +0 -0
  35. codex/static_root/assets/VCombobox-C1Osy24P.73168f28d07b.js +1 -0
  36. codex/static_root/assets/VCombobox-C1Osy24P.73168f28d07b.js.br +0 -0
  37. codex/static_root/assets/VCombobox-C1Osy24P.73168f28d07b.js.gz +0 -0
  38. codex/static_root/assets/VCombobox-C1Osy24P.js +1 -0
  39. codex/static_root/assets/VCombobox-C1Osy24P.js.br +0 -0
  40. codex/static_root/assets/VCombobox-C1Osy24P.js.gz +0 -0
  41. codex/static_root/assets/VDialog-c2XXqNJH.a4156ca20133.js +1 -0
  42. codex/static_root/assets/VDialog-c2XXqNJH.a4156ca20133.js.br +0 -0
  43. codex/static_root/assets/VDialog-c2XXqNJH.a4156ca20133.js.gz +0 -0
  44. codex/static_root/assets/VDialog-c2XXqNJH.js +1 -0
  45. codex/static_root/assets/VDialog-c2XXqNJH.js.br +0 -0
  46. codex/static_root/assets/VDialog-c2XXqNJH.js.gz +0 -0
  47. codex/static_root/assets/{VDivider-BEpvozL4.c9fd95940cb5.js → VDivider-C06z3Tn-.d5e3ed421a68.js} +1 -1
  48. codex/static_root/assets/VDivider-C06z3Tn-.d5e3ed421a68.js.br +0 -0
  49. codex/static_root/assets/VDivider-C06z3Tn-.d5e3ed421a68.js.gz +0 -0
  50. codex/static_root/assets/{VDivider-BEpvozL4.js → VDivider-C06z3Tn-.js} +1 -1
  51. codex/static_root/assets/VDivider-C06z3Tn-.js.br +0 -0
  52. codex/static_root/assets/VDivider-C06z3Tn-.js.gz +0 -0
  53. codex/static_root/assets/{VExpansionPanels-BzyHQUL4.7e54cedf021c.js → VExpansionPanels-B8gzbonk.3532c6d08817.js} +1 -1
  54. codex/static_root/assets/VExpansionPanels-B8gzbonk.3532c6d08817.js.br +0 -0
  55. codex/static_root/assets/VExpansionPanels-B8gzbonk.3532c6d08817.js.gz +0 -0
  56. codex/static_root/assets/{VExpansionPanels-BzyHQUL4.js → VExpansionPanels-B8gzbonk.js} +1 -1
  57. codex/static_root/assets/VExpansionPanels-B8gzbonk.js.br +0 -0
  58. codex/static_root/assets/VExpansionPanels-B8gzbonk.js.gz +0 -0
  59. codex/static_root/assets/{VForm-CmVlbmJK.887eb47d3534.js → VForm-Chf0FU2x.3e8425bff3d0.js} +1 -1
  60. codex/static_root/assets/VForm-Chf0FU2x.3e8425bff3d0.js.br +0 -0
  61. codex/static_root/assets/VForm-Chf0FU2x.3e8425bff3d0.js.gz +0 -0
  62. codex/static_root/assets/{VForm-CmVlbmJK.js → VForm-Chf0FU2x.js} +1 -1
  63. codex/static_root/assets/VForm-Chf0FU2x.js.br +0 -0
  64. codex/static_root/assets/VForm-Chf0FU2x.js.gz +0 -0
  65. codex/static_root/assets/{VRadioGroup-DWzKkq9W.daaabd353889.js → VRadioGroup-CHteIFqx.23cb51ee43e1.js} +1 -1
  66. codex/static_root/assets/VRadioGroup-CHteIFqx.23cb51ee43e1.js.br +0 -0
  67. codex/static_root/assets/VRadioGroup-CHteIFqx.23cb51ee43e1.js.gz +0 -0
  68. codex/static_root/assets/{VRadioGroup-DWzKkq9W.js → VRadioGroup-CHteIFqx.js} +1 -1
  69. codex/static_root/assets/VRadioGroup-CHteIFqx.js.br +0 -0
  70. codex/static_root/assets/VRadioGroup-CHteIFqx.js.gz +0 -0
  71. codex/static_root/assets/VSelect-BqS1Prvd.36bbebae4f0d.js +1 -0
  72. codex/static_root/assets/VSelect-BqS1Prvd.36bbebae4f0d.js.br +0 -0
  73. codex/static_root/assets/VSelect-BqS1Prvd.36bbebae4f0d.js.gz +0 -0
  74. codex/static_root/assets/VSelect-BqS1Prvd.js +1 -0
  75. codex/static_root/assets/VSelect-BqS1Prvd.js.br +0 -0
  76. codex/static_root/assets/VSelect-BqS1Prvd.js.gz +0 -0
  77. codex/static_root/assets/VSelectionControl-BRWozKsT.d10531c1a243.js +1 -0
  78. codex/static_root/assets/VSelectionControl-BRWozKsT.d10531c1a243.js.br +0 -0
  79. codex/static_root/assets/VSelectionControl-BRWozKsT.d10531c1a243.js.gz +0 -0
  80. codex/static_root/assets/VSelectionControl-BRWozKsT.js +1 -0
  81. codex/static_root/assets/VSelectionControl-BRWozKsT.js.br +0 -0
  82. codex/static_root/assets/VSelectionControl-BRWozKsT.js.gz +0 -0
  83. codex/static_root/assets/VTable-BT6w_ifJ.ee6b710fb398.js +1 -0
  84. codex/static_root/assets/VTable-BT6w_ifJ.ee6b710fb398.js.br +0 -0
  85. codex/static_root/assets/VTable-BT6w_ifJ.ee6b710fb398.js.gz +0 -0
  86. codex/static_root/assets/VTable-BT6w_ifJ.js +1 -0
  87. codex/static_root/assets/VTable-BT6w_ifJ.js.br +0 -0
  88. codex/static_root/assets/VTable-BT6w_ifJ.js.gz +0 -0
  89. codex/static_root/assets/VTable-BsI6FsWH.css +1 -0
  90. codex/static_root/assets/VTable-BsI6FsWH.css.br +0 -0
  91. codex/static_root/assets/VTable-BsI6FsWH.css.gz +0 -0
  92. codex/static_root/assets/VTable-BsI6FsWH.d4c54d44a5ab.css +1 -0
  93. codex/static_root/assets/VTable-BsI6FsWH.d4c54d44a5ab.css.br +0 -0
  94. codex/static_root/assets/VTable-BsI6FsWH.d4c54d44a5ab.css.gz +0 -0
  95. codex/static_root/assets/VWindowItem-QQWUVqMX.c22e707ac99c.css +1 -0
  96. codex/static_root/assets/VWindowItem-QQWUVqMX.c22e707ac99c.css.br +5 -0
  97. codex/static_root/assets/VWindowItem-QQWUVqMX.c22e707ac99c.css.gz +0 -0
  98. codex/static_root/assets/VWindowItem-QQWUVqMX.css +1 -0
  99. codex/static_root/assets/VWindowItem-QQWUVqMX.css.br +5 -0
  100. codex/static_root/assets/VWindowItem-QQWUVqMX.css.gz +0 -0
  101. codex/static_root/assets/{VWindowItem-DBU8ce0X.4bbcffa75b9a.js → VWindowItem-sfdsG_YK.ee17f6723988.js} +1 -1
  102. codex/static_root/assets/VWindowItem-sfdsG_YK.ee17f6723988.js.br +0 -0
  103. codex/static_root/assets/VWindowItem-sfdsG_YK.ee17f6723988.js.gz +0 -0
  104. codex/static_root/assets/{VWindowItem-DBU8ce0X.js → VWindowItem-sfdsG_YK.js} +1 -1
  105. codex/static_root/assets/VWindowItem-sfdsG_YK.js.br +0 -0
  106. codex/static_root/assets/VWindowItem-sfdsG_YK.js.gz +0 -0
  107. codex/static_root/assets/{admin-CfqMNEyt.bebc609836d0.js → admin-DuEKXO1g.5c6bfe166705.js} +1 -1
  108. codex/static_root/assets/admin-DuEKXO1g.5c6bfe166705.js.br +0 -0
  109. codex/static_root/assets/admin-DuEKXO1g.5c6bfe166705.js.gz +0 -0
  110. codex/static_root/assets/{admin-CfqMNEyt.js → admin-DuEKXO1g.js} +1 -1
  111. codex/static_root/assets/admin-DuEKXO1g.js.br +0 -0
  112. codex/static_root/assets/admin-DuEKXO1g.js.gz +0 -0
  113. codex/static_root/assets/admin-menu-DBce75Uy.be45a0a53c1a.js +1 -0
  114. codex/static_root/assets/admin-menu-DBce75Uy.be45a0a53c1a.js.br +0 -0
  115. codex/static_root/assets/admin-menu-DBce75Uy.be45a0a53c1a.js.gz +0 -0
  116. codex/static_root/assets/admin-menu-DBce75Uy.js +1 -0
  117. codex/static_root/assets/admin-menu-DBce75Uy.js.br +0 -0
  118. codex/static_root/assets/admin-menu-DBce75Uy.js.gz +0 -0
  119. codex/static_root/assets/{admin-Bt81XU3H.ca36b1a1b799.js → admin-pnPIiLQj.b791e7869cf5.js} +1 -1
  120. codex/static_root/assets/admin-pnPIiLQj.b791e7869cf5.js.br +0 -0
  121. codex/static_root/assets/admin-pnPIiLQj.b791e7869cf5.js.gz +0 -0
  122. codex/static_root/assets/{admin-Bt81XU3H.js → admin-pnPIiLQj.js} +1 -1
  123. codex/static_root/assets/admin-pnPIiLQj.js.br +0 -0
  124. codex/static_root/assets/admin-pnPIiLQj.js.gz +0 -0
  125. codex/static_root/assets/{admin-settings-button-progress-BPQGNinn.53e05963f557.js → admin-settings-button-progress-C4VmW80I.c8d9033b8bc5.js} +1 -1
  126. codex/static_root/assets/admin-settings-button-progress-C4VmW80I.c8d9033b8bc5.js.br +0 -0
  127. codex/static_root/assets/admin-settings-button-progress-C4VmW80I.c8d9033b8bc5.js.gz +0 -0
  128. codex/static_root/assets/{admin-settings-button-progress-BPQGNinn.js → admin-settings-button-progress-C4VmW80I.js} +1 -1
  129. codex/static_root/assets/admin-settings-button-progress-C4VmW80I.js.br +0 -0
  130. codex/static_root/assets/admin-settings-button-progress-C4VmW80I.js.gz +0 -0
  131. codex/static_root/assets/browser-DOuRKBxy.c9a72e4f9498.js +1 -0
  132. codex/static_root/assets/browser-DOuRKBxy.c9a72e4f9498.js.br +0 -0
  133. codex/static_root/assets/browser-DOuRKBxy.c9a72e4f9498.js.gz +0 -0
  134. codex/static_root/assets/browser-DOuRKBxy.js +1 -0
  135. codex/static_root/assets/browser-DOuRKBxy.js.br +0 -0
  136. codex/static_root/assets/browser-DOuRKBxy.js.gz +0 -0
  137. codex/static_root/assets/{browser-Cdi7U5ku.bab9fccf0326.css → browser-TRzEFz_k.css} +1 -1
  138. codex/static_root/assets/browser-TRzEFz_k.css.br +0 -0
  139. codex/static_root/assets/browser-TRzEFz_k.css.gz +0 -0
  140. codex/static_root/assets/{browser-Cdi7U5ku.css → browser-TRzEFz_k.e8ae750c4a41.css} +1 -1
  141. codex/static_root/assets/browser-TRzEFz_k.e8ae750c4a41.css.br +0 -0
  142. codex/static_root/assets/browser-TRzEFz_k.e8ae750c4a41.css.gz +0 -0
  143. codex/static_root/assets/change-password-dialog-B4tB0bVX.5b476ac6a873.js +1 -0
  144. codex/static_root/assets/change-password-dialog-B4tB0bVX.5b476ac6a873.js.br +0 -0
  145. codex/static_root/assets/change-password-dialog-B4tB0bVX.5b476ac6a873.js.gz +0 -0
  146. codex/static_root/assets/change-password-dialog-B4tB0bVX.js +1 -0
  147. codex/static_root/assets/change-password-dialog-B4tB0bVX.js.br +0 -0
  148. codex/static_root/assets/change-password-dialog-B4tB0bVX.js.gz +0 -0
  149. codex/static_root/assets/{confirm-dialog-CgSU27R5.0127ce62d24c.js → confirm-dialog-C0DHEcnB.e2d9968f6fea.js} +1 -1
  150. codex/static_root/assets/confirm-dialog-C0DHEcnB.e2d9968f6fea.js.br +0 -0
  151. codex/static_root/assets/confirm-dialog-C0DHEcnB.e2d9968f6fea.js.gz +0 -0
  152. codex/static_root/assets/{confirm-dialog-CgSU27R5.js → confirm-dialog-C0DHEcnB.js} +1 -1
  153. codex/static_root/assets/confirm-dialog-C0DHEcnB.js.br +0 -0
  154. codex/static_root/assets/confirm-dialog-C0DHEcnB.js.gz +0 -0
  155. codex/static_root/assets/{datetime-column-Dw9zxZLR.cd8791cda91b.js → datetime-column-j_CRGEuQ.cc499deb52f7.js} +1 -1
  156. codex/static_root/assets/datetime-column-j_CRGEuQ.cc499deb52f7.js.br +4 -0
  157. codex/static_root/assets/datetime-column-j_CRGEuQ.cc499deb52f7.js.gz +0 -0
  158. codex/static_root/assets/{datetime-column-Dw9zxZLR.js → datetime-column-j_CRGEuQ.js} +1 -1
  159. codex/static_root/assets/datetime-column-j_CRGEuQ.js.br +4 -0
  160. codex/static_root/assets/datetime-column-j_CRGEuQ.js.gz +0 -0
  161. codex/static_root/assets/{filter-BNTCrH8l.c00298a8fccf.js → filter-Baea_DNH.985ef541d6af.js} +1 -1
  162. codex/static_root/assets/filter-Baea_DNH.985ef541d6af.js.br +0 -0
  163. codex/static_root/assets/filter-Baea_DNH.985ef541d6af.js.gz +0 -0
  164. codex/static_root/assets/{filter-BNTCrH8l.js → filter-Baea_DNH.js} +1 -1
  165. codex/static_root/assets/filter-Baea_DNH.js.br +0 -0
  166. codex/static_root/assets/filter-Baea_DNH.js.gz +0 -0
  167. codex/static_root/assets/{flag-tab-Xpq_xAF5.3f14de61afcc.js → flag-tab-DefdNLmr.0cf5a73c1c8c.js} +1 -1
  168. codex/static_root/assets/flag-tab-DefdNLmr.0cf5a73c1c8c.js.br +0 -0
  169. codex/static_root/assets/flag-tab-DefdNLmr.0cf5a73c1c8c.js.gz +0 -0
  170. codex/static_root/assets/{flag-tab-Xpq_xAF5.js → flag-tab-DefdNLmr.js} +1 -1
  171. codex/static_root/assets/flag-tab-DefdNLmr.js.br +0 -0
  172. codex/static_root/assets/flag-tab-DefdNLmr.js.gz +0 -0
  173. codex/static_root/assets/forwardRefs-Bvy6478W.409df679a82f.js +1 -0
  174. codex/static_root/assets/forwardRefs-Bvy6478W.409df679a82f.js.br +0 -0
  175. codex/static_root/assets/forwardRefs-Bvy6478W.409df679a82f.js.gz +0 -0
  176. codex/static_root/assets/forwardRefs-Bvy6478W.js +1 -0
  177. codex/static_root/assets/forwardRefs-Bvy6478W.js.br +0 -0
  178. codex/static_root/assets/forwardRefs-Bvy6478W.js.gz +0 -0
  179. codex/static_root/assets/{forwardRefs-B_sUWZn6.5114f206ca9c.css → forwardRefs-C3Z4qL85.48fb131ece85.css} +1 -1
  180. codex/static_root/assets/forwardRefs-C3Z4qL85.48fb131ece85.css.br +0 -0
  181. codex/static_root/assets/forwardRefs-C3Z4qL85.48fb131ece85.css.gz +0 -0
  182. codex/static_root/assets/{forwardRefs-B_sUWZn6.css → forwardRefs-C3Z4qL85.css} +1 -1
  183. codex/static_root/assets/forwardRefs-C3Z4qL85.css.br +0 -0
  184. codex/static_root/assets/forwardRefs-C3Z4qL85.css.gz +0 -0
  185. codex/static_root/assets/{group-tab-E_R0glEI.82e1d92be747.js → group-tab-C71MBY7x.483482eaaf8c.js} +1 -1
  186. codex/static_root/assets/group-tab-C71MBY7x.483482eaaf8c.js.br +0 -0
  187. codex/static_root/assets/group-tab-C71MBY7x.483482eaaf8c.js.gz +0 -0
  188. codex/static_root/assets/{group-tab-E_R0glEI.js → group-tab-C71MBY7x.js} +1 -1
  189. codex/static_root/assets/group-tab-C71MBY7x.js.br +0 -0
  190. codex/static_root/assets/group-tab-C71MBY7x.js.gz +0 -0
  191. codex/static_root/assets/http-error-mPrHO762.70c41cde5ee1.js +1 -0
  192. codex/static_root/assets/http-error-mPrHO762.70c41cde5ee1.js.br +0 -0
  193. codex/static_root/assets/http-error-mPrHO762.70c41cde5ee1.js.gz +0 -0
  194. codex/static_root/assets/http-error-mPrHO762.js +1 -0
  195. codex/static_root/assets/http-error-mPrHO762.js.br +0 -0
  196. codex/static_root/assets/http-error-mPrHO762.js.gz +0 -0
  197. codex/static_root/assets/{index-j9jeRHe0.294b614eaea1.js → index-Bxqss4CY.5f797cedb404.js} +1 -1
  198. codex/static_root/assets/index-Bxqss4CY.5f797cedb404.js.br +0 -0
  199. codex/static_root/assets/index-Bxqss4CY.5f797cedb404.js.gz +0 -0
  200. codex/static_root/assets/{index-j9jeRHe0.js → index-Bxqss4CY.js} +1 -1
  201. codex/static_root/assets/index-Bxqss4CY.js.br +0 -0
  202. codex/static_root/assets/index-Bxqss4CY.js.gz +0 -0
  203. codex/static_root/assets/library-tab-DG2bhQ_A.e831e11418e2.js +1 -0
  204. codex/static_root/assets/library-tab-DG2bhQ_A.e831e11418e2.js.br +0 -0
  205. codex/static_root/assets/library-tab-DG2bhQ_A.e831e11418e2.js.gz +0 -0
  206. codex/static_root/assets/library-tab-DG2bhQ_A.js +1 -0
  207. codex/static_root/assets/library-tab-DG2bhQ_A.js.br +0 -0
  208. codex/static_root/assets/library-tab-DG2bhQ_A.js.gz +0 -0
  209. codex/static_root/assets/main-RxUHaWll.d7d671319f8d.js +39 -0
  210. codex/static_root/assets/main-RxUHaWll.d7d671319f8d.js.br +0 -0
  211. codex/static_root/assets/main-RxUHaWll.d7d671319f8d.js.gz +0 -0
  212. codex/static_root/assets/main-RxUHaWll.js +39 -0
  213. codex/static_root/assets/main-RxUHaWll.js.br +0 -0
  214. codex/static_root/assets/main-RxUHaWll.js.gz +0 -0
  215. codex/static_root/assets/pager-full-pdf-DYbA0-qc.b66019cafd05.js +1 -0
  216. codex/static_root/assets/pager-full-pdf-DYbA0-qc.b66019cafd05.js.br +0 -0
  217. codex/static_root/assets/pager-full-pdf-DYbA0-qc.b66019cafd05.js.gz +0 -0
  218. codex/static_root/assets/pager-full-pdf-DYbA0-qc.js +1 -0
  219. codex/static_root/assets/pager-full-pdf-DYbA0-qc.js.br +0 -0
  220. codex/static_root/assets/pager-full-pdf-DYbA0-qc.js.gz +0 -0
  221. codex/static_root/assets/pagination-toolbar-ChW-jj1Q.0cf6985b630e.js +1 -0
  222. codex/static_root/assets/pagination-toolbar-ChW-jj1Q.0cf6985b630e.js.br +0 -0
  223. codex/static_root/assets/pagination-toolbar-ChW-jj1Q.0cf6985b630e.js.gz +0 -0
  224. codex/static_root/assets/pagination-toolbar-ChW-jj1Q.js +1 -0
  225. codex/static_root/assets/pagination-toolbar-ChW-jj1Q.js.br +0 -0
  226. codex/static_root/assets/pagination-toolbar-ChW-jj1Q.js.gz +0 -0
  227. codex/static_root/assets/{pagination-toolbar-741OafNw.4f9155469274.css → pagination-toolbar-rUdD4-Qi.3a224c7806a5.css} +1 -1
  228. codex/static_root/assets/pagination-toolbar-rUdD4-Qi.3a224c7806a5.css.br +0 -0
  229. codex/static_root/assets/pagination-toolbar-rUdD4-Qi.3a224c7806a5.css.gz +0 -0
  230. codex/static_root/assets/{pagination-toolbar-741OafNw.css → pagination-toolbar-rUdD4-Qi.css} +1 -1
  231. codex/static_root/assets/pagination-toolbar-rUdD4-Qi.css.br +0 -0
  232. codex/static_root/assets/pagination-toolbar-rUdD4-Qi.css.gz +0 -0
  233. codex/static_root/assets/{pdf-doc-XAg2nqnS.5a33f918a28a.js → pdf-doc-CfiAAYT8.c4fb1945d1c5.js} +1 -1
  234. codex/static_root/assets/pdf-doc-CfiAAYT8.c4fb1945d1c5.js.br +0 -0
  235. codex/static_root/assets/{pdf-doc-XAg2nqnS.5a33f918a28a.js.gz → pdf-doc-CfiAAYT8.c4fb1945d1c5.js.gz} +0 -0
  236. codex/static_root/assets/{pdf-doc-XAg2nqnS.js → pdf-doc-CfiAAYT8.js} +1 -1
  237. codex/static_root/assets/pdf-doc-CfiAAYT8.js.br +0 -0
  238. codex/static_root/assets/{pdf-doc-XAg2nqnS.js.gz → pdf-doc-CfiAAYT8.js.gz} +0 -0
  239. codex/static_root/assets/reader-BNwsMjad.78e4ad034141.js +2 -0
  240. codex/static_root/assets/reader-BNwsMjad.78e4ad034141.js.br +0 -0
  241. codex/static_root/assets/reader-BNwsMjad.78e4ad034141.js.gz +0 -0
  242. codex/static_root/assets/reader-BNwsMjad.js +2 -0
  243. codex/static_root/assets/reader-BNwsMjad.js.br +0 -0
  244. codex/static_root/assets/reader-BNwsMjad.js.gz +0 -0
  245. codex/static_root/assets/relation-chips-Cfk3FVE5.eadbc380a353.js +1 -0
  246. codex/static_root/assets/relation-chips-Cfk3FVE5.eadbc380a353.js.br +0 -0
  247. codex/static_root/assets/relation-chips-Cfk3FVE5.eadbc380a353.js.gz +0 -0
  248. codex/static_root/assets/relation-chips-Cfk3FVE5.js +1 -0
  249. codex/static_root/assets/relation-chips-Cfk3FVE5.js.br +0 -0
  250. codex/static_root/assets/relation-chips-Cfk3FVE5.js.gz +0 -0
  251. codex/static_root/assets/{relation-chips-CcFgPQOM.0b468249b62e.css → relation-chips-CpiT_4k-.b72d78f512e6.css} +1 -1
  252. codex/static_root/assets/relation-chips-CpiT_4k-.b72d78f512e6.css.br +0 -0
  253. codex/static_root/assets/relation-chips-CpiT_4k-.b72d78f512e6.css.gz +0 -0
  254. codex/static_root/assets/{relation-chips-CcFgPQOM.css → relation-chips-CpiT_4k-.css} +1 -1
  255. codex/static_root/assets/relation-chips-CpiT_4k-.css.br +0 -0
  256. codex/static_root/assets/relation-chips-CpiT_4k-.css.gz +0 -0
  257. codex/static_root/assets/{settings-drawer-CpS_aX4Z.9d4d9533d033.css → settings-drawer-B-pwZRSy.8fc8b237bb52.css} +1 -1
  258. codex/static_root/assets/settings-drawer-B-pwZRSy.8fc8b237bb52.css.br +0 -0
  259. codex/static_root/assets/settings-drawer-B-pwZRSy.8fc8b237bb52.css.gz +0 -0
  260. codex/static_root/assets/{settings-drawer-CpS_aX4Z.css → settings-drawer-B-pwZRSy.css} +1 -1
  261. codex/static_root/assets/settings-drawer-B-pwZRSy.css.br +0 -0
  262. codex/static_root/assets/settings-drawer-B-pwZRSy.css.gz +0 -0
  263. codex/static_root/assets/settings-drawer-BvHMmEFL.6b6d9bf0e2ad.js +2 -0
  264. codex/static_root/assets/settings-drawer-BvHMmEFL.6b6d9bf0e2ad.js.br +0 -0
  265. codex/static_root/assets/settings-drawer-BvHMmEFL.6b6d9bf0e2ad.js.gz +0 -0
  266. codex/static_root/assets/settings-drawer-BvHMmEFL.js +2 -0
  267. codex/static_root/assets/settings-drawer-BvHMmEFL.js.br +0 -0
  268. codex/static_root/assets/settings-drawer-BvHMmEFL.js.gz +0 -0
  269. codex/static_root/assets/{ssrBoot-CoIsTnhp.ab2c4669478d.js → ssrBoot-BBuVfjys.ee6df7695a63.js} +1 -1
  270. codex/static_root/assets/ssrBoot-BBuVfjys.ee6df7695a63.js.br +0 -0
  271. codex/static_root/assets/ssrBoot-BBuVfjys.ee6df7695a63.js.gz +0 -0
  272. codex/static_root/assets/{ssrBoot-CoIsTnhp.js → ssrBoot-BBuVfjys.js} +1 -1
  273. codex/static_root/assets/ssrBoot-BBuVfjys.js.br +0 -0
  274. codex/static_root/assets/ssrBoot-BBuVfjys.js.gz +0 -0
  275. codex/static_root/assets/{stats-tab-Bncgetpc.94f90b6a111b.js → stats-tab-BW725H_T.61e34db4cc39.js} +1 -1
  276. codex/static_root/assets/stats-tab-BW725H_T.61e34db4cc39.js.br +0 -0
  277. codex/static_root/assets/stats-tab-BW725H_T.61e34db4cc39.js.gz +0 -0
  278. codex/static_root/assets/{stats-tab-Bncgetpc.js → stats-tab-BW725H_T.js} +1 -1
  279. codex/static_root/assets/stats-tab-BW725H_T.js.br +0 -0
  280. codex/static_root/assets/stats-tab-BW725H_T.js.gz +0 -0
  281. codex/static_root/assets/task-tab-P3x-M3d5.59e0479f2f1e.js +1 -0
  282. codex/static_root/assets/task-tab-P3x-M3d5.59e0479f2f1e.js.br +0 -0
  283. codex/static_root/assets/task-tab-P3x-M3d5.59e0479f2f1e.js.gz +0 -0
  284. codex/static_root/assets/task-tab-P3x-M3d5.js +1 -0
  285. codex/static_root/assets/task-tab-P3x-M3d5.js.br +0 -0
  286. codex/static_root/assets/task-tab-P3x-M3d5.js.gz +0 -0
  287. codex/static_root/assets/{unauthorized-IXAh-oLS.be484d21eb2a.js → unauthorized-CC6sHmUB.394dffd78457.js} +1 -1
  288. codex/static_root/assets/unauthorized-CC6sHmUB.394dffd78457.js.br +0 -0
  289. codex/static_root/assets/unauthorized-CC6sHmUB.394dffd78457.js.gz +0 -0
  290. codex/static_root/assets/{unauthorized-IXAh-oLS.js → unauthorized-CC6sHmUB.js} +1 -1
  291. codex/static_root/assets/unauthorized-CC6sHmUB.js.br +0 -0
  292. codex/static_root/assets/unauthorized-CC6sHmUB.js.gz +0 -0
  293. codex/static_root/assets/user-tab-OaDKeq2f.ac3d682c35f1.js +1 -0
  294. codex/static_root/assets/user-tab-OaDKeq2f.ac3d682c35f1.js.br +0 -0
  295. codex/static_root/assets/user-tab-OaDKeq2f.ac3d682c35f1.js.gz +0 -0
  296. codex/static_root/assets/user-tab-OaDKeq2f.js +1 -0
  297. codex/static_root/assets/user-tab-OaDKeq2f.js.br +0 -0
  298. codex/static_root/assets/user-tab-OaDKeq2f.js.gz +0 -0
  299. codex/static_root/{manifest.92b1b461eee2.json → manifest.d51267c3637d.json} +310 -310
  300. codex/static_root/manifest.d51267c3637d.json.br +0 -0
  301. codex/static_root/manifest.d51267c3637d.json.gz +0 -0
  302. codex/static_root/manifest.json +310 -310
  303. codex/static_root/manifest.json.br +0 -0
  304. codex/static_root/manifest.json.gz +0 -0
  305. codex/static_root/staticfiles.json +1 -1
  306. codex/views/browser/filters/filter.py +1 -1
  307. codex/views/browser/filters/search/field/column.py +3 -3
  308. codex/views/browser/filters/search/parse.py +15 -10
  309. {codex-1.8.5.dist-info → codex-1.8.8.dist-info}/METADATA +5 -5
  310. {codex-1.8.5.dist-info → codex-1.8.8.dist-info}/RECORD +314 -312
  311. codex/static_root/assets/VCheckbox-DxJUMufz.9a175cfa72c8.js +0 -1
  312. codex/static_root/assets/VCheckbox-DxJUMufz.9a175cfa72c8.js.br +0 -0
  313. codex/static_root/assets/VCheckbox-DxJUMufz.9a175cfa72c8.js.gz +0 -0
  314. codex/static_root/assets/VCheckbox-DxJUMufz.js +0 -1
  315. codex/static_root/assets/VCheckbox-DxJUMufz.js.br +0 -0
  316. codex/static_root/assets/VCheckbox-DxJUMufz.js.gz +0 -0
  317. codex/static_root/assets/VCheckboxBtn-BE6yrQ80.4a42f2c068f5.js.br +0 -0
  318. codex/static_root/assets/VCheckboxBtn-BE6yrQ80.4a42f2c068f5.js.gz +0 -0
  319. codex/static_root/assets/VCheckboxBtn-BE6yrQ80.js.br +0 -0
  320. codex/static_root/assets/VCheckboxBtn-BE6yrQ80.js.gz +0 -0
  321. codex/static_root/assets/VCombobox-Bfyp0szs.b51553d29c8c.js +0 -1
  322. codex/static_root/assets/VCombobox-Bfyp0szs.b51553d29c8c.js.br +0 -0
  323. codex/static_root/assets/VCombobox-Bfyp0szs.b51553d29c8c.js.gz +0 -0
  324. codex/static_root/assets/VCombobox-Bfyp0szs.js +0 -1
  325. codex/static_root/assets/VCombobox-Bfyp0szs.js.br +0 -0
  326. codex/static_root/assets/VCombobox-Bfyp0szs.js.gz +0 -0
  327. codex/static_root/assets/VDialog-Cy6wFjb9.9253a3f54f22.js +0 -1
  328. codex/static_root/assets/VDialog-Cy6wFjb9.9253a3f54f22.js.br +0 -0
  329. codex/static_root/assets/VDialog-Cy6wFjb9.9253a3f54f22.js.gz +0 -0
  330. codex/static_root/assets/VDialog-Cy6wFjb9.js +0 -1
  331. codex/static_root/assets/VDialog-Cy6wFjb9.js.br +0 -0
  332. codex/static_root/assets/VDialog-Cy6wFjb9.js.gz +0 -0
  333. codex/static_root/assets/VDivider-BEpvozL4.c9fd95940cb5.js.br +0 -0
  334. codex/static_root/assets/VDivider-BEpvozL4.c9fd95940cb5.js.gz +0 -0
  335. codex/static_root/assets/VDivider-BEpvozL4.js.br +0 -0
  336. codex/static_root/assets/VDivider-BEpvozL4.js.gz +0 -0
  337. codex/static_root/assets/VExpansionPanels-BzyHQUL4.7e54cedf021c.js.br +0 -0
  338. codex/static_root/assets/VExpansionPanels-BzyHQUL4.7e54cedf021c.js.gz +0 -0
  339. codex/static_root/assets/VExpansionPanels-BzyHQUL4.js.br +0 -0
  340. codex/static_root/assets/VExpansionPanels-BzyHQUL4.js.gz +0 -0
  341. codex/static_root/assets/VForm-CmVlbmJK.887eb47d3534.js.br +0 -0
  342. codex/static_root/assets/VForm-CmVlbmJK.887eb47d3534.js.gz +0 -0
  343. codex/static_root/assets/VForm-CmVlbmJK.js.br +0 -0
  344. codex/static_root/assets/VForm-CmVlbmJK.js.gz +0 -0
  345. codex/static_root/assets/VRadioGroup-DWzKkq9W.daaabd353889.js.br +0 -0
  346. codex/static_root/assets/VRadioGroup-DWzKkq9W.daaabd353889.js.gz +0 -0
  347. codex/static_root/assets/VRadioGroup-DWzKkq9W.js.br +0 -0
  348. codex/static_root/assets/VRadioGroup-DWzKkq9W.js.gz +0 -0
  349. codex/static_root/assets/VSelect-Cqjdw0PV.ab01020c5ef4.js +0 -1
  350. codex/static_root/assets/VSelect-Cqjdw0PV.ab01020c5ef4.js.br +0 -0
  351. codex/static_root/assets/VSelect-Cqjdw0PV.ab01020c5ef4.js.gz +0 -0
  352. codex/static_root/assets/VSelect-Cqjdw0PV.js +0 -1
  353. codex/static_root/assets/VSelect-Cqjdw0PV.js.br +0 -0
  354. codex/static_root/assets/VSelect-Cqjdw0PV.js.gz +0 -0
  355. codex/static_root/assets/VSelectionControl-Dk52iIPb.fe2504c50db4.js +0 -1
  356. codex/static_root/assets/VSelectionControl-Dk52iIPb.fe2504c50db4.js.br +0 -0
  357. codex/static_root/assets/VSelectionControl-Dk52iIPb.fe2504c50db4.js.gz +0 -0
  358. codex/static_root/assets/VSelectionControl-Dk52iIPb.js +0 -1
  359. codex/static_root/assets/VSelectionControl-Dk52iIPb.js.br +0 -0
  360. codex/static_root/assets/VSelectionControl-Dk52iIPb.js.gz +0 -0
  361. codex/static_root/assets/VTable-CQyv0wyO.1740239d481b.css +0 -1
  362. codex/static_root/assets/VTable-CQyv0wyO.1740239d481b.css.br +0 -0
  363. codex/static_root/assets/VTable-CQyv0wyO.1740239d481b.css.gz +0 -0
  364. codex/static_root/assets/VTable-CQyv0wyO.css +0 -1
  365. codex/static_root/assets/VTable-CQyv0wyO.css.br +0 -0
  366. codex/static_root/assets/VTable-CQyv0wyO.css.gz +0 -0
  367. codex/static_root/assets/VTable-Ch5ZSNsk.c38a2cb589fa.js +0 -1
  368. codex/static_root/assets/VTable-Ch5ZSNsk.c38a2cb589fa.js.br +0 -0
  369. codex/static_root/assets/VTable-Ch5ZSNsk.c38a2cb589fa.js.gz +0 -0
  370. codex/static_root/assets/VTable-Ch5ZSNsk.js +0 -1
  371. codex/static_root/assets/VTable-Ch5ZSNsk.js.br +0 -0
  372. codex/static_root/assets/VTable-Ch5ZSNsk.js.gz +0 -0
  373. codex/static_root/assets/VWindowItem-ChYLiXSE.a9c679a2977e.css +0 -1
  374. codex/static_root/assets/VWindowItem-ChYLiXSE.a9c679a2977e.css.br +0 -0
  375. codex/static_root/assets/VWindowItem-ChYLiXSE.a9c679a2977e.css.gz +0 -0
  376. codex/static_root/assets/VWindowItem-ChYLiXSE.css +0 -1
  377. codex/static_root/assets/VWindowItem-ChYLiXSE.css.br +0 -0
  378. codex/static_root/assets/VWindowItem-ChYLiXSE.css.gz +0 -0
  379. codex/static_root/assets/VWindowItem-DBU8ce0X.4bbcffa75b9a.js.br +0 -0
  380. codex/static_root/assets/VWindowItem-DBU8ce0X.4bbcffa75b9a.js.gz +0 -0
  381. codex/static_root/assets/VWindowItem-DBU8ce0X.js.br +0 -0
  382. codex/static_root/assets/VWindowItem-DBU8ce0X.js.gz +0 -0
  383. codex/static_root/assets/admin-Bt81XU3H.ca36b1a1b799.js.br +0 -0
  384. codex/static_root/assets/admin-Bt81XU3H.ca36b1a1b799.js.gz +0 -0
  385. codex/static_root/assets/admin-Bt81XU3H.js.br +0 -0
  386. codex/static_root/assets/admin-Bt81XU3H.js.gz +0 -0
  387. codex/static_root/assets/admin-CfqMNEyt.bebc609836d0.js.br +0 -0
  388. codex/static_root/assets/admin-CfqMNEyt.bebc609836d0.js.gz +0 -0
  389. codex/static_root/assets/admin-CfqMNEyt.js.br +0 -0
  390. codex/static_root/assets/admin-CfqMNEyt.js.gz +0 -0
  391. codex/static_root/assets/admin-menu-Db5b3nba.09d034934b88.js +0 -1
  392. codex/static_root/assets/admin-menu-Db5b3nba.09d034934b88.js.br +0 -0
  393. codex/static_root/assets/admin-menu-Db5b3nba.09d034934b88.js.gz +0 -0
  394. codex/static_root/assets/admin-menu-Db5b3nba.js +0 -1
  395. codex/static_root/assets/admin-menu-Db5b3nba.js.br +0 -0
  396. codex/static_root/assets/admin-menu-Db5b3nba.js.gz +0 -0
  397. codex/static_root/assets/admin-settings-button-progress-BPQGNinn.53e05963f557.js.br +0 -0
  398. codex/static_root/assets/admin-settings-button-progress-BPQGNinn.53e05963f557.js.gz +0 -0
  399. codex/static_root/assets/admin-settings-button-progress-BPQGNinn.js.br +0 -0
  400. codex/static_root/assets/admin-settings-button-progress-BPQGNinn.js.gz +0 -0
  401. codex/static_root/assets/browser-C19hTg9r.9b5d0eadd6d4.js +0 -1
  402. codex/static_root/assets/browser-C19hTg9r.9b5d0eadd6d4.js.br +0 -0
  403. codex/static_root/assets/browser-C19hTg9r.9b5d0eadd6d4.js.gz +0 -0
  404. codex/static_root/assets/browser-C19hTg9r.js +0 -1
  405. codex/static_root/assets/browser-C19hTg9r.js.br +0 -0
  406. codex/static_root/assets/browser-C19hTg9r.js.gz +0 -0
  407. codex/static_root/assets/browser-Cdi7U5ku.bab9fccf0326.css.br +0 -0
  408. codex/static_root/assets/browser-Cdi7U5ku.bab9fccf0326.css.gz +0 -0
  409. codex/static_root/assets/browser-Cdi7U5ku.css.br +0 -0
  410. codex/static_root/assets/browser-Cdi7U5ku.css.gz +0 -0
  411. codex/static_root/assets/change-password-dialog-DPAIPGJa.7c4c436e259e.js +0 -1
  412. codex/static_root/assets/change-password-dialog-DPAIPGJa.7c4c436e259e.js.br +0 -0
  413. codex/static_root/assets/change-password-dialog-DPAIPGJa.7c4c436e259e.js.gz +0 -0
  414. codex/static_root/assets/change-password-dialog-DPAIPGJa.js +0 -1
  415. codex/static_root/assets/change-password-dialog-DPAIPGJa.js.br +0 -0
  416. codex/static_root/assets/change-password-dialog-DPAIPGJa.js.gz +0 -0
  417. codex/static_root/assets/confirm-dialog-CgSU27R5.0127ce62d24c.js.br +0 -0
  418. codex/static_root/assets/confirm-dialog-CgSU27R5.0127ce62d24c.js.gz +0 -0
  419. codex/static_root/assets/confirm-dialog-CgSU27R5.js.br +0 -0
  420. codex/static_root/assets/confirm-dialog-CgSU27R5.js.gz +0 -0
  421. codex/static_root/assets/datetime-column-Dw9zxZLR.cd8791cda91b.js.br +0 -0
  422. codex/static_root/assets/datetime-column-Dw9zxZLR.cd8791cda91b.js.gz +0 -0
  423. codex/static_root/assets/datetime-column-Dw9zxZLR.js.br +0 -0
  424. codex/static_root/assets/datetime-column-Dw9zxZLR.js.gz +0 -0
  425. codex/static_root/assets/filter-BNTCrH8l.c00298a8fccf.js.br +0 -0
  426. codex/static_root/assets/filter-BNTCrH8l.c00298a8fccf.js.gz +0 -0
  427. codex/static_root/assets/filter-BNTCrH8l.js.br +0 -0
  428. codex/static_root/assets/filter-BNTCrH8l.js.gz +0 -0
  429. codex/static_root/assets/flag-tab-Xpq_xAF5.3f14de61afcc.js.br +0 -0
  430. codex/static_root/assets/flag-tab-Xpq_xAF5.3f14de61afcc.js.gz +0 -0
  431. codex/static_root/assets/flag-tab-Xpq_xAF5.js.br +0 -0
  432. codex/static_root/assets/flag-tab-Xpq_xAF5.js.gz +0 -0
  433. codex/static_root/assets/forwardRefs-B_sUWZn6.5114f206ca9c.css.br +0 -0
  434. codex/static_root/assets/forwardRefs-B_sUWZn6.5114f206ca9c.css.gz +0 -0
  435. codex/static_root/assets/forwardRefs-B_sUWZn6.css.br +0 -0
  436. codex/static_root/assets/forwardRefs-B_sUWZn6.css.gz +0 -0
  437. codex/static_root/assets/forwardRefs-fUake9mW.12c1018cd1e3.js +0 -1
  438. codex/static_root/assets/forwardRefs-fUake9mW.12c1018cd1e3.js.br +0 -0
  439. codex/static_root/assets/forwardRefs-fUake9mW.12c1018cd1e3.js.gz +0 -0
  440. codex/static_root/assets/forwardRefs-fUake9mW.js +0 -1
  441. codex/static_root/assets/forwardRefs-fUake9mW.js.br +0 -0
  442. codex/static_root/assets/forwardRefs-fUake9mW.js.gz +0 -0
  443. codex/static_root/assets/group-tab-E_R0glEI.82e1d92be747.js.br +0 -0
  444. codex/static_root/assets/group-tab-E_R0glEI.82e1d92be747.js.gz +0 -0
  445. codex/static_root/assets/group-tab-E_R0glEI.js.br +0 -0
  446. codex/static_root/assets/group-tab-E_R0glEI.js.gz +0 -0
  447. codex/static_root/assets/http-error-C6bKTzfv.168d047d5219.js +0 -1
  448. codex/static_root/assets/http-error-C6bKTzfv.168d047d5219.js.br +0 -5
  449. codex/static_root/assets/http-error-C6bKTzfv.168d047d5219.js.gz +0 -0
  450. codex/static_root/assets/http-error-C6bKTzfv.js +0 -1
  451. codex/static_root/assets/http-error-C6bKTzfv.js.br +0 -5
  452. codex/static_root/assets/http-error-C6bKTzfv.js.gz +0 -0
  453. codex/static_root/assets/index-j9jeRHe0.294b614eaea1.js.br +0 -0
  454. codex/static_root/assets/index-j9jeRHe0.294b614eaea1.js.gz +0 -0
  455. codex/static_root/assets/index-j9jeRHe0.js.br +0 -0
  456. codex/static_root/assets/index-j9jeRHe0.js.gz +0 -0
  457. codex/static_root/assets/library-tab-DPYjRIWp.58e434354594.js +0 -1
  458. codex/static_root/assets/library-tab-DPYjRIWp.58e434354594.js.br +0 -0
  459. codex/static_root/assets/library-tab-DPYjRIWp.58e434354594.js.gz +0 -0
  460. codex/static_root/assets/library-tab-DPYjRIWp.js +0 -1
  461. codex/static_root/assets/library-tab-DPYjRIWp.js.br +0 -0
  462. codex/static_root/assets/library-tab-DPYjRIWp.js.gz +0 -0
  463. codex/static_root/assets/main-Cnq2ldv_.1c0766500281.js +0 -39
  464. codex/static_root/assets/main-Cnq2ldv_.1c0766500281.js.br +0 -0
  465. codex/static_root/assets/main-Cnq2ldv_.1c0766500281.js.gz +0 -0
  466. codex/static_root/assets/main-Cnq2ldv_.js +0 -39
  467. codex/static_root/assets/main-Cnq2ldv_.js.br +0 -0
  468. codex/static_root/assets/main-Cnq2ldv_.js.gz +0 -0
  469. codex/static_root/assets/pager-full-pdf-CdHAL6P3.cb6bc541ca5c.js +0 -1
  470. codex/static_root/assets/pager-full-pdf-CdHAL6P3.cb6bc541ca5c.js.br +0 -0
  471. codex/static_root/assets/pager-full-pdf-CdHAL6P3.cb6bc541ca5c.js.gz +0 -0
  472. codex/static_root/assets/pager-full-pdf-CdHAL6P3.js +0 -1
  473. codex/static_root/assets/pager-full-pdf-CdHAL6P3.js.br +0 -0
  474. codex/static_root/assets/pager-full-pdf-CdHAL6P3.js.gz +0 -0
  475. codex/static_root/assets/pagination-toolbar-741OafNw.4f9155469274.css.br +0 -0
  476. codex/static_root/assets/pagination-toolbar-741OafNw.4f9155469274.css.gz +0 -0
  477. codex/static_root/assets/pagination-toolbar-741OafNw.css.br +0 -0
  478. codex/static_root/assets/pagination-toolbar-741OafNw.css.gz +0 -0
  479. codex/static_root/assets/pagination-toolbar-BFBKOWOc.3355103910ff.js +0 -1
  480. codex/static_root/assets/pagination-toolbar-BFBKOWOc.3355103910ff.js.br +0 -0
  481. codex/static_root/assets/pagination-toolbar-BFBKOWOc.3355103910ff.js.gz +0 -0
  482. codex/static_root/assets/pagination-toolbar-BFBKOWOc.js +0 -1
  483. codex/static_root/assets/pagination-toolbar-BFBKOWOc.js.br +0 -0
  484. codex/static_root/assets/pagination-toolbar-BFBKOWOc.js.gz +0 -0
  485. codex/static_root/assets/pdf-doc-XAg2nqnS.5a33f918a28a.js.br +0 -0
  486. codex/static_root/assets/pdf-doc-XAg2nqnS.js.br +0 -0
  487. codex/static_root/assets/reader-BZ4Dp-_5.ecd9d42077af.js +0 -2
  488. codex/static_root/assets/reader-BZ4Dp-_5.ecd9d42077af.js.br +0 -0
  489. codex/static_root/assets/reader-BZ4Dp-_5.ecd9d42077af.js.gz +0 -0
  490. codex/static_root/assets/reader-BZ4Dp-_5.js +0 -2
  491. codex/static_root/assets/reader-BZ4Dp-_5.js.br +0 -0
  492. codex/static_root/assets/reader-BZ4Dp-_5.js.gz +0 -0
  493. codex/static_root/assets/relation-chips-B_z9ixOK.8f144f1cf119.js +0 -1
  494. codex/static_root/assets/relation-chips-B_z9ixOK.8f144f1cf119.js.br +0 -0
  495. codex/static_root/assets/relation-chips-B_z9ixOK.8f144f1cf119.js.gz +0 -0
  496. codex/static_root/assets/relation-chips-B_z9ixOK.js +0 -1
  497. codex/static_root/assets/relation-chips-B_z9ixOK.js.br +0 -0
  498. codex/static_root/assets/relation-chips-B_z9ixOK.js.gz +0 -0
  499. codex/static_root/assets/relation-chips-CcFgPQOM.0b468249b62e.css.br +0 -0
  500. codex/static_root/assets/relation-chips-CcFgPQOM.0b468249b62e.css.gz +0 -0
  501. codex/static_root/assets/relation-chips-CcFgPQOM.css.br +0 -0
  502. codex/static_root/assets/relation-chips-CcFgPQOM.css.gz +0 -0
  503. codex/static_root/assets/settings-drawer-Cd3M0s-h.c5216209feb4.js +0 -2
  504. codex/static_root/assets/settings-drawer-Cd3M0s-h.c5216209feb4.js.br +0 -0
  505. codex/static_root/assets/settings-drawer-Cd3M0s-h.c5216209feb4.js.gz +0 -0
  506. codex/static_root/assets/settings-drawer-Cd3M0s-h.js +0 -2
  507. codex/static_root/assets/settings-drawer-Cd3M0s-h.js.br +0 -0
  508. codex/static_root/assets/settings-drawer-Cd3M0s-h.js.gz +0 -0
  509. codex/static_root/assets/settings-drawer-CpS_aX4Z.9d4d9533d033.css.br +0 -0
  510. codex/static_root/assets/settings-drawer-CpS_aX4Z.9d4d9533d033.css.gz +0 -0
  511. codex/static_root/assets/settings-drawer-CpS_aX4Z.css.br +0 -0
  512. codex/static_root/assets/settings-drawer-CpS_aX4Z.css.gz +0 -0
  513. codex/static_root/assets/ssrBoot-CoIsTnhp.ab2c4669478d.js.br +0 -0
  514. codex/static_root/assets/ssrBoot-CoIsTnhp.ab2c4669478d.js.gz +0 -0
  515. codex/static_root/assets/ssrBoot-CoIsTnhp.js.br +0 -0
  516. codex/static_root/assets/ssrBoot-CoIsTnhp.js.gz +0 -0
  517. codex/static_root/assets/stats-tab-Bncgetpc.94f90b6a111b.js.br +0 -0
  518. codex/static_root/assets/stats-tab-Bncgetpc.94f90b6a111b.js.gz +0 -0
  519. codex/static_root/assets/stats-tab-Bncgetpc.js.br +0 -0
  520. codex/static_root/assets/stats-tab-Bncgetpc.js.gz +0 -0
  521. codex/static_root/assets/task-tab-BWkw24-u.0e981a767773.js +0 -1
  522. codex/static_root/assets/task-tab-BWkw24-u.0e981a767773.js.br +0 -0
  523. codex/static_root/assets/task-tab-BWkw24-u.0e981a767773.js.gz +0 -0
  524. codex/static_root/assets/task-tab-BWkw24-u.js +0 -1
  525. codex/static_root/assets/task-tab-BWkw24-u.js.br +0 -0
  526. codex/static_root/assets/task-tab-BWkw24-u.js.gz +0 -0
  527. codex/static_root/assets/unauthorized-IXAh-oLS.be484d21eb2a.js.br +0 -0
  528. codex/static_root/assets/unauthorized-IXAh-oLS.be484d21eb2a.js.gz +0 -0
  529. codex/static_root/assets/unauthorized-IXAh-oLS.js.br +0 -0
  530. codex/static_root/assets/unauthorized-IXAh-oLS.js.gz +0 -0
  531. codex/static_root/assets/user-tab-CtQh6PJE.6b9a1d0e733a.js +0 -1
  532. codex/static_root/assets/user-tab-CtQh6PJE.6b9a1d0e733a.js.br +0 -0
  533. codex/static_root/assets/user-tab-CtQh6PJE.6b9a1d0e733a.js.gz +0 -0
  534. codex/static_root/assets/user-tab-CtQh6PJE.js +0 -1
  535. codex/static_root/assets/user-tab-CtQh6PJE.js.br +0 -0
  536. codex/static_root/assets/user-tab-CtQh6PJE.js.gz +0 -0
  537. codex/static_root/manifest.92b1b461eee2.json.br +0 -0
  538. codex/static_root/manifest.92b1b461eee2.json.gz +0 -0
  539. /codex/librarian/{watchdog/memory.py → memory.py} +0 -0
  540. {codex-1.8.5.dist-info → codex-1.8.8.dist-info}/WHEEL +0 -0
  541. {codex-1.8.5.dist-info → codex-1.8.8.dist-info}/entry_points.txt +0 -0
  542. {codex-1.8.5.dist-info → codex-1.8.8.dist-info}/licenses/LICENSE +0 -0
codex/choices/admin.py CHANGED
@@ -109,6 +109,7 @@ ADMIN_TASK_GROUPS: MappingProxyType[
109
109
  "value": "search_index_clear",
110
110
  "title": "Clear Search Index",
111
111
  "desc": "of all entries",
112
+ "confirm": "Are you sure? Resyncing the search index can take a while.",
112
113
  },
113
114
  {
114
115
  "value": "db_fts_integrity_check",
@@ -52,24 +52,29 @@ PARENT_FOLDER_FIELD_NAME = "parent_folder"
52
52
  VOLUME_COUNT_FIELD_NAME = "volume_count"
53
53
  ISSUE_COUNT_FIELD_NAME = "issue_count"
54
54
  PATH_FIELD_NAME = "path"
55
+ IDENTIFIERS_FIELD_NAME = "identifiers"
55
56
  NON_FTS_FIELDS = frozenset(
56
57
  {
57
58
  # Attributes
58
59
  "critical_rating",
59
60
  "day",
61
+ "file_type",
62
+ "issue_number",
63
+ "issue_suffix",
60
64
  "metadata_mtime",
61
65
  "monochrome",
62
66
  "month",
67
+ "notes",
63
68
  "page_count",
64
69
  "path",
70
+ "reading_direction",
65
71
  "year",
66
- "issue_number",
67
- "issue_suffix",
68
72
  # FKs
69
73
  PARENT_FOLDER_FIELD_NAME,
70
74
  VOLUME_FIELD_NAME,
71
75
  # M2Ms
72
76
  FOLDERS_FIELD_NAME,
77
+ IDENTIFIERS_FIELD_NAME,
73
78
  }
74
79
  )
75
80
 
@@ -127,7 +132,6 @@ CREDIT_ROLE_FIELD_NAME = "role"
127
132
  STORY_ARC_NUMBERS_FIELD_NAME = "story_arc_numbers"
128
133
  STORY_ARC_FIELD_NAME = "story_arc"
129
134
  NUMBER_FIELD_NAME = "number"
130
- IDENTIFIERS_FIELD_NAME = "identifiers"
131
135
  IDENTIFIER_SOURCE_FIELD_NAME = "source"
132
136
  IDENTIFIER_TYPE_FIELD_NAME = "id_type"
133
137
  IDENTIFIER_ID_KEY_FIELD_NAME = "key"
@@ -34,9 +34,6 @@ class CreateComicsImporter(CreateForeignKeyLinksImporter):
34
34
  if field_name not in NON_FTS_FIELDS:
35
35
  self.metadata[key][sub_key][field_name] = (value,)
36
36
 
37
- issue = (str(md.get("issue_number", "")) + md.get("issue_suffix", ""),)
38
- self.metadata[key][sub_key]["issue"] = issue
39
-
40
37
  def _update_comic_values(self, comic: Comic, update_comics: list, comic_pks: list):
41
38
  md = self.metadata[UPDATE_COMICS].pop(comic.pk, {})
42
39
  for field_name, value in md.items():
@@ -4,7 +4,7 @@ from codex.librarian.scribe.importer.const import ALL_COMIC_GROUP_FIELD_NAMES
4
4
  from codex.librarian.scribe.importer.delete.covers import DeletedCoversImporter
5
5
  from codex.librarian.scribe.importer.statii.delete import ImporterRemoveComicsStatus
6
6
  from codex.models import Comic, Folder, StoryArc
7
- from codex.settings import MAX_CHUNK_SIZE
7
+ from codex.settings import DELETE_MAX_CHUNK_SIZE
8
8
 
9
9
 
10
10
  class DeletedComicsImporter(DeletedCoversImporter):
@@ -29,7 +29,7 @@ class DeletedComicsImporter(DeletedCoversImporter):
29
29
  comics_deleted_qs = delete_qs.only(
30
30
  *ALL_COMIC_GROUP_FIELD_NAMES
31
31
  ).prefetch_related("story_arc_numbers__story_arc")
32
- for comic in comics_deleted_qs.iterator(chunk_size=MAX_CHUNK_SIZE):
32
+ for comic in comics_deleted_qs.iterator(chunk_size=DELETE_MAX_CHUNK_SIZE):
33
33
  for field_name in ALL_COMIC_GROUP_FIELD_NAMES:
34
34
  if field_name == "story_arc_numbers":
35
35
  for san in comic.story_arc_numbers.select_related("story_arc").only(
@@ -47,10 +47,12 @@ class DeletedComicsImporter(DeletedCoversImporter):
47
47
 
48
48
  def bulk_comics_deleted(self, **kwargs) -> tuple[int, dict]:
49
49
  """Bulk delete comics found missing from the filesystem."""
50
+ count = 0
51
+ deleted_comic_groups = {}
50
52
  status = ImporterRemoveComicsStatus(0, len(self.task.files_deleted))
51
53
  try:
52
54
  if not self.task.files_deleted:
53
- return 0, {}
55
+ return count, deleted_comic_groups
54
56
  self.status_controller.start(status)
55
57
  delete_qs = Comic.objects.filter(
56
58
  library=self.library, path__in=self.task.files_deleted
@@ -60,7 +62,8 @@ class DeletedComicsImporter(DeletedCoversImporter):
60
62
  deleted_comic_groups = self._populate_deleted_comic_groups(delete_qs)
61
63
 
62
64
  delete_comic_pks = frozenset(delete_qs.values_list("pk", flat=True))
63
- count, _ = delete_qs.delete()
65
+ delete_qs.delete()
66
+ count = len(delete_comic_pks)
64
67
 
65
68
  self.remove_covers(delete_comic_pks, custom=False)
66
69
  finally:
@@ -25,7 +25,8 @@ class DeletedFoldersImporter(DeletedComicsImporter):
25
25
  .distinct()
26
26
  .values_list("pk", flat=True)
27
27
  )
28
- count, _ = folders.delete()
28
+ folders.delete()
29
+ count = len(delete_comic_pks)
29
30
 
30
31
  self.remove_covers(delete_comic_pks, custom=False)
31
32
  finally:
@@ -23,17 +23,56 @@ from codex.librarian.scribe.importer.statii.failed import (
23
23
  )
24
24
  from codex.librarian.scribe.importer.statii.read import ImporterAggregateStatus
25
25
 
26
- _UNUSED_COMICBOX_FIELDS = (
27
- "alternate_images",
28
- "bookmark",
29
- "credit_primaries",
30
- "ext",
31
- "manga",
32
- "pages",
33
- "prices",
34
- "remainders",
35
- "reprints",
36
- "updated_at",
26
+ _USED_COMICBOX_FIELDS = frozenset(
27
+ {
28
+ # "alternate_images",
29
+ "age_rating",
30
+ "arcs",
31
+ # "bookmark",
32
+ "characters",
33
+ "collection_title",
34
+ "country",
35
+ "credits",
36
+ # "credit_primaries",
37
+ "critical_rating",
38
+ "date",
39
+ # "ext",
40
+ "file_type", # extra
41
+ "genres",
42
+ "identifiers",
43
+ # "identifier_primary_source",
44
+ "imprint",
45
+ "issue",
46
+ "language",
47
+ "locations",
48
+ "metadata_mtime", # extra
49
+ "monochrome",
50
+ "notes",
51
+ "original_format",
52
+ "path", # extra
53
+ # "pages",
54
+ "page_count",
55
+ "protagonist",
56
+ # "prices",
57
+ "publisher",
58
+ "reading_direction",
59
+ # "remainders",
60
+ # "reprints",
61
+ "review",
62
+ # "rights",
63
+ "scan_info",
64
+ "series",
65
+ "series_groups",
66
+ "stories",
67
+ "summary",
68
+ "tagger",
69
+ "tags",
70
+ "teams",
71
+ "title",
72
+ "universes",
73
+ # "updated_at",
74
+ "volume",
75
+ }
37
76
  )
38
77
 
39
78
 
@@ -42,8 +81,9 @@ class AggregateMetadataImporter(AggregatePathMetadataImporter):
42
81
 
43
82
  @staticmethod
44
83
  def _transform_metadata(md):
45
- for key in _UNUSED_COMICBOX_FIELDS:
46
- md.pop(key, None)
84
+ for key in tuple(md.keys()):
85
+ if key not in _USED_COMICBOX_FIELDS:
86
+ md.pop(key, None)
47
87
 
48
88
  if date := md.pop(DATE_KEY, None):
49
89
  date.pop(COVER_DATE_KEY, None)
@@ -1,6 +1,6 @@
1
1
  """Extract metadata from comic archive."""
2
2
 
3
- from datetime import datetime
3
+ from datetime import datetime, timezone
4
4
  from tarfile import TarError
5
5
  from zipfile import BadZipFile, LargeZipFile
6
6
 
@@ -29,7 +29,10 @@ class ExtractMetadataImporter(AggregateMetadataImporter):
29
29
  comic = Comic.objects.get(path=path)
30
30
  except Comic.DoesNotExist:
31
31
  return None
32
- return comic.metadata_mtime
32
+ mtime = comic.metadata_mtime
33
+ if mtime and (mtime.tzinfo is None or mtime.tzinfo.utcoffset(mtime) is None):
34
+ mtime = mtime.replace(tzinfo=timezone.utc)
35
+ return mtime
33
36
 
34
37
  def _set_import_metadata_flag(self):
35
38
  """Set import_metadata flag."""
@@ -50,17 +53,17 @@ class ExtractMetadataImporter(AggregateMetadataImporter):
50
53
  with Comicbox(path, config=COMICBOX_CONFIG, logger=self.log) as cb:
51
54
  if import_metadata:
52
55
  new_md_mtime = cb.get_metadata_mtime()
53
- if self.task.check_metadata_mtime:
54
- old_md_mtime = self._metadata_mtime(path)
55
- if (
56
- old_md_mtime
57
- and new_md_mtime
58
- and new_md_mtime <= old_md_mtime
59
- ):
60
- return md
61
- md = cb.to_dict()
62
- md = md.get("comicbox", {})
63
- md["metadata_mtime"] = new_md_mtime
56
+ if (
57
+ not self.task.check_metadata_mtime
58
+ or not new_md_mtime
59
+ or not (old_md_mtime := self._metadata_mtime(path))
60
+ or (new_md_mtime > old_md_mtime)
61
+ ):
62
+ md = cb.to_dict()
63
+ md = md.get("comicbox", {})
64
+ md["metadata_mtime"] = new_md_mtime
65
+ else:
66
+ md["page_count"] = cb.get_page_count()
64
67
  else:
65
68
  md["page_count"] = cb.get_page_count()
66
69
  md["file_type"] = cb.get_file_type()
@@ -6,7 +6,6 @@ from codex.librarian.scribe.importer.const import (
6
6
  FTS_CREATED_M2MS,
7
7
  FTS_EXISTING_M2MS,
8
8
  FTS_UPDATE,
9
- IDENTIFIERS_FIELD_NAME,
10
9
  NON_FTS_FIELDS,
11
10
  STORY_ARC_FIELD_NAME,
12
11
  STORY_ARC_NUMBERS_FIELD_NAME,
@@ -25,8 +24,6 @@ class SearchIndexPrepareImporter(SearchIndexCreateUpdateImporter):
25
24
  """Only store the fts relevant parts of complex links."""
26
25
  if field_name == CREDITS_FIELD_NAME:
27
26
  values = tuple(subvalues[0] for subvalues in values)
28
- if field_name == IDENTIFIERS_FIELD_NAME:
29
- values = tuple(subvalues[-1] for subvalues in values)
30
27
  elif field_name == STORY_ARC_NUMBERS_FIELD_NAME:
31
28
  field_name = STORY_ARC_FIELD_NAME + "s"
32
29
  return field_name, tuple(values)
@@ -41,10 +38,6 @@ class SearchIndexPrepareImporter(SearchIndexCreateUpdateImporter):
41
38
  """Add the existing values for creating a changed search entry."""
42
39
  if field_name in NON_FTS_FIELDS or not values:
43
40
  return
44
- if field_name == IDENTIFIERS_FIELD_NAME:
45
- # sources extracton must come before identifiers is minified
46
- sources = tuple(subvalues[0] for subvalues in values)
47
- self.add_to_fts_existing(pk, "sources", sources)
48
41
  field_name, values = self.minify_complex_link_to_fts_tuple(field_name, values)
49
42
  fts_values = self._to_fts_tuple(values)
50
43
  if not fts_values:
@@ -52,7 +52,8 @@ class SearchIndexSyncManyToManyImporter(FinishImporter):
52
52
  .only(*update_fields)
53
53
  )
54
54
  for comicfts in comicftss:
55
- setattr(comicfts, field_name, comicfts.fts_value) # pyright: ignore[reportAttributeAccessIssue]
55
+ value = comicfts.fts_value.strip(",") # pyright: ignore[reportAttributeAccessIssue]
56
+ setattr(comicfts, field_name, value)
56
57
  comicfts.updated_at = Now()
57
58
  update_objs.append(comicfts)
58
59
 
@@ -1,11 +1,7 @@
1
1
  """Search Index update."""
2
2
 
3
- from contextlib import suppress
4
3
  from time import time
5
4
 
6
- from comicbox.enums.comicbox import IdSources
7
- from comicbox.enums.maps.identifiers import ID_SOURCE_NAME_MAP
8
- from django.db.models.functions.datetime import Now
9
5
  from humanize import naturaldelta
10
6
 
11
7
  from codex.librarian.scribe.importer.const import (
@@ -13,10 +9,6 @@ from codex.librarian.scribe.importer.const import (
13
9
  FTS_EXISTING_M2MS,
14
10
  FTS_UPDATE,
15
11
  )
16
- from codex.librarian.scribe.importer.search.const import (
17
- COMICFTS_UPDATE_FIELDS,
18
- PYCOUNTRY_FIELDS,
19
- )
20
12
  from codex.librarian.scribe.importer.search.sync_m2m import (
21
13
  SearchIndexSyncManyToManyImporter,
22
14
  )
@@ -25,6 +17,8 @@ from codex.librarian.scribe.importer.statii.search import (
25
17
  ImporterFTSStatus,
26
18
  ImporterFTSUpdateStatus,
27
19
  )
20
+ from codex.librarian.scribe.search.const import COMICFTS_UPDATE_FIELDS
21
+ from codex.librarian.scribe.search.prepare import SearchEntryPrepare
28
22
  from codex.librarian.status import Status
29
23
  from codex.models.comic import ComicFTS
30
24
 
@@ -32,73 +26,17 @@ from codex.models.comic import ComicFTS
32
26
  class SearchIndexCreateUpdateImporter(SearchIndexSyncManyToManyImporter):
33
27
  """Search Index update methods."""
34
28
 
35
- @staticmethod
36
- def _get_pycountry_fts_field(entry, field_name) -> str:
37
- iso_code = entry.get(field_name)
38
- if not iso_code:
39
- return ""
40
- field = PYCOUNTRY_FIELDS[field_name]
41
- return ",".join((iso_code, field.to_representation(iso_code)))
42
-
43
- @staticmethod
44
- def _get_sources_fts_field(entry) -> tuple[str, ...]:
45
- sources = entry.get("sources", ())
46
- names = []
47
- for source_str in sources:
48
- names.append(source_str)
49
- with suppress(ValueError):
50
- id_source = IdSources(source_str)
51
- if long_name := ID_SOURCE_NAME_MAP.get(id_source):
52
- names.append(long_name)
53
- return tuple(names)
54
-
55
- @staticmethod
56
- def _create_comicfts_entry_attributes(entry, *, create: bool):
57
- now = Now()
58
- entry["updated_at"] = now
59
- if create:
60
- entry["created_at"] = now
61
-
62
- @classmethod
63
- def _create_comicfts_entry_fks(cls, entry):
64
- entry["country"] = cls._get_pycountry_fts_field(entry, "country")
65
- entry["language"] = cls._get_pycountry_fts_field(entry, "language")
66
-
67
- @staticmethod
68
- def _to_fts_values(value):
69
- """Create a tuple of fts value strings."""
70
- return tuple(
71
- subvalue
72
- for values_tuple in value
73
- for subvalue in values_tuple
74
- if isinstance(subvalue, str)
75
- )
76
-
77
- def _create_comicfts_entry_m2ms(self, pk: int, entry):
78
- if sources := self._get_sources_fts_field(entry):
79
- entry["sources"] = sources
80
- if existing_values := self.metadata[FTS_EXISTING_M2MS].get(pk):
81
- for field_name in tuple(existing_values.keys()):
82
- if values := existing_values.get(field_name):
83
- entry[field_name] = entry.get(field_name, ()) + values
84
-
85
29
  def _create_comicfts_entry(
86
30
  self,
87
- pk,
88
- entry,
31
+ pk: int,
32
+ entry: dict,
89
33
  obj_list: list[ComicFTS],
90
34
  status: Status,
91
35
  ):
92
- self._create_comicfts_entry_m2ms(pk, entry)
93
- for field_name in entry:
94
- value = entry[field_name]
95
- if isinstance(value, tuple):
96
- entry[field_name] = ",".join(sorted(value))
97
- self._create_comicfts_entry_attributes(entry, create=True)
98
- self._create_comicfts_entry_fks(entry)
99
- comicfts = ComicFTS(comic_id=pk, **entry)
100
- obj_list.append(comicfts)
101
- status.increment_complete()
36
+ existing_m2m_values = self.metadata[FTS_EXISTING_M2MS].get(pk)
37
+ SearchEntryPrepare.prepare_import_fts_entry(
38
+ pk, entry, existing_m2m_values, None, obj_list, status, create=True
39
+ )
102
40
  self.status_controller.update(status)
103
41
 
104
42
  def _update_comicfts_entry(
@@ -109,17 +47,16 @@ class SearchIndexCreateUpdateImporter(SearchIndexSyncManyToManyImporter):
109
47
  ):
110
48
  comic_id = comicfts.comic_id # pyright:ignore[reportAttributeAccessIssue], # ty: ignore[unresolved-attribute]
111
49
  entry = self.metadata[FTS_UPDATE].pop(comic_id)
112
- self._create_comicfts_entry_m2ms(comic_id, entry)
113
- for field_name in entry:
114
- value = entry[field_name]
115
- if isinstance(value, tuple):
116
- entry[field_name] = ",".join(sorted(value))
117
- self._create_comicfts_entry_attributes(entry, create=True)
118
- self._create_comicfts_entry_fks(entry)
119
- for field_name, value in entry.items():
120
- setattr(comicfts, field_name, value)
121
- obj_list.append(comicfts)
122
- status.increment_complete()
50
+ existing_m2m_values = self.metadata[FTS_EXISTING_M2MS].get(comic_id)
51
+ SearchEntryPrepare.prepare_import_fts_entry(
52
+ comic_id,
53
+ entry,
54
+ existing_m2m_values,
55
+ comicfts,
56
+ obj_list,
57
+ status,
58
+ create=False,
59
+ )
123
60
  self.status_controller.update(status)
124
61
 
125
62
  def _update_search_index_operate_get_status(
@@ -29,23 +29,12 @@ from codex.librarian.scribe.tasks import (
29
29
  )
30
30
  from codex.librarian.scribe.timestamp_update import TimestampUpdater
31
31
  from codex.librarian.threads import QueuedThread
32
- from codex.settings import SEARCH_INDEX_BATCH_SIZE
33
32
 
34
- _ABORT_SEARCH_UPDATE_TASKS = (
33
+ ABORT_SEARCH_UPDATE_TASKS = (
35
34
  SearchIndexClearTask,
36
35
  SearchIndexSyncAbortTask,
37
36
  JanitorFTSRebuildTask,
38
37
  )
39
- _ABORT_SEARCH_UPDATE_ON_IMPORT_TASKS = (
40
- ImportTask,
41
- JanitorAdoptOrphanFoldersTask,
42
- )
43
- _ABORT_SEARCH_UPDATE_ON_IMPORT_BATCH_SIZE = 1000
44
- ABORT_SEARCH_UPDATE_TASKS = (
45
- _ABORT_SEARCH_UPDATE_TASKS + _ABORT_SEARCH_UPDATE_ON_IMPORT_TASKS
46
- if SEARCH_INDEX_BATCH_SIZE <= _ABORT_SEARCH_UPDATE_ON_IMPORT_BATCH_SIZE
47
- else _ABORT_SEARCH_UPDATE_TASKS
48
- )
49
38
 
50
39
 
51
40
  class ScribeThread(QueuedThread):
@@ -118,7 +107,7 @@ class ScribeThread(QueuedThread):
118
107
  self.log.debug("Abort cleanup db signal given.")
119
108
  elif isinstance(task, SearchIndexSyncAbortTask):
120
109
  self.log.debug(
121
- "Search Index Update abort signal given. May take a bit for the current import subtask to finish."
110
+ "Search Index Sync abort signal given. It may take a while for the current import chunk to finish."
122
111
  )
123
112
  return
124
113
  elif isinstance(task, ImportAbortTask):
@@ -1,16 +1,8 @@
1
- """Search import consts."""
2
-
3
- from types import MappingProxyType
4
-
5
- from codex.serializers.fields.browser import CountryField, LanguageField
1
+ """FTS constants."""
6
2
 
7
3
  _COMICFTS_ATTRIBUTES = (
8
4
  "collection_title",
9
- "file_type",
10
- "issue",
11
5
  "name",
12
- "notes",
13
- "reading_direction",
14
6
  "review",
15
7
  "summary",
16
8
  "updated_at",
@@ -30,7 +22,6 @@ _COMICFTS_M2MS = (
30
22
  "characters",
31
23
  "credits",
32
24
  "genres",
33
- "identifiers",
34
25
  "locations",
35
26
  "series_groups",
36
27
  "sources",
@@ -45,6 +36,3 @@ COMICFTS_UPDATE_FIELDS = (
45
36
  *_COMICFTS_FKS,
46
37
  *_COMICFTS_M2MS,
47
38
  )
48
- PYCOUNTRY_FIELDS = MappingProxyType(
49
- {"country": CountryField(), "language": LanguageField()}
50
- )
@@ -0,0 +1,162 @@
1
+ """Prepare ComicFTS objects."""
2
+
3
+ from contextlib import suppress
4
+ from types import MappingProxyType
5
+
6
+ from comicbox.enums.comicbox import IdSources
7
+ from comicbox.enums.maps.identifiers import ID_SOURCE_NAME_MAP
8
+ from django.db.models.functions.datetime import Now
9
+
10
+ from codex.librarian.status import Status
11
+ from codex.models.comic import ComicFTS
12
+ from codex.serializers.fields.browser import CountryField, LanguageField
13
+
14
+ _PYCOUNTRY_FIELDS = MappingProxyType(
15
+ {"country": CountryField(), "language": LanguageField()}
16
+ )
17
+ _COMIC_KEYS = (
18
+ "collection_title",
19
+ "country",
20
+ "language",
21
+ "name",
22
+ "review",
23
+ "summary",
24
+ "fts_publisher",
25
+ "fts_imprint",
26
+ "fts_series",
27
+ "fts_age_rating",
28
+ "fts_original_format",
29
+ "fts_scan_info",
30
+ "fts_tagger",
31
+ "fts_characters",
32
+ "fts_credits",
33
+ "fts_country",
34
+ "fts_genres",
35
+ "fts_sources",
36
+ "fts_language",
37
+ "fts_locations",
38
+ "fts_series_groups",
39
+ "fts_stories",
40
+ "fts_story_arcs",
41
+ "fts_tags",
42
+ "fts_teams",
43
+ "fts_universes",
44
+ )
45
+
46
+
47
+ class SearchEntryPrepare:
48
+ """Prepare ComicFTS objects."""
49
+
50
+ @staticmethod
51
+ def _get_entry_str_value(entry: dict, key: str) -> str:
52
+ value = entry.get(key)
53
+ if not value:
54
+ return ""
55
+ if isinstance(value, tuple):
56
+ value = value[0]
57
+ if not value:
58
+ return ""
59
+ return value
60
+
61
+ @staticmethod
62
+ def _get_sources_fts_field(entry: dict) -> str:
63
+ sources = entry.get("sources", ())
64
+ if not sources:
65
+ return ""
66
+ if isinstance(sources, str):
67
+ sources = (sources,)
68
+ names = set()
69
+ for source_str in sources:
70
+ if not source_str:
71
+ continue
72
+ names.add(source_str)
73
+ with suppress(ValueError):
74
+ id_source = IdSources(source_str)
75
+ if long_name := ID_SOURCE_NAME_MAP.get(id_source):
76
+ names.add(long_name)
77
+ return ",".join(sorted(names))
78
+
79
+ @classmethod
80
+ def _get_pycountry_fts_field(cls, entry, field_name) -> str:
81
+ iso_code = cls._get_entry_str_value(entry, field_name)
82
+ if not iso_code:
83
+ return ""
84
+ field = _PYCOUNTRY_FIELDS[field_name]
85
+ return ",".join((iso_code, field.to_representation(iso_code)))
86
+
87
+ @classmethod
88
+ def _create_comicfts_entry_attributes(cls, entry, *, create: bool):
89
+ now = Now()
90
+ entry["updated_at"] = now
91
+ if create:
92
+ entry["created_at"] = now
93
+
94
+ @classmethod
95
+ def _create_comicfts_entry_fks(cls, entry):
96
+ entry["country"] = cls._get_pycountry_fts_field(entry, "country")
97
+ entry["language"] = cls._get_pycountry_fts_field(entry, "language")
98
+
99
+ @classmethod
100
+ def _create_comicfts_entry_m2ms(cls, entry, existing_values: dict | None):
101
+ if sources := cls._get_sources_fts_field(entry):
102
+ entry["sources"] = sources
103
+ if existing_values:
104
+ for field_name in tuple(existing_values.keys()):
105
+ if values := existing_values.get(field_name):
106
+ entry[field_name] = entry.get(field_name, ()) + values
107
+
108
+ @classmethod
109
+ def prepare_import_fts_entry( # noqa: PLR0913
110
+ cls,
111
+ comic_id: int,
112
+ entry: dict,
113
+ existing_m2m_values: dict | None,
114
+ comicfts: ComicFTS | None,
115
+ obj_list: list[ComicFTS],
116
+ status: Status,
117
+ *,
118
+ create: bool,
119
+ ):
120
+ """Prepare ComicFTS object from import data."""
121
+ cls._create_comicfts_entry_m2ms(entry, existing_m2m_values)
122
+ cls._create_comicfts_entry_fks(entry)
123
+ for field_name in entry: # noqa: PLC0206
124
+ value = entry[field_name]
125
+ if isinstance(value, tuple):
126
+ entry[field_name] = ",".join(sorted(value))
127
+
128
+ cls._create_comicfts_entry_attributes(entry, create=create)
129
+
130
+ if comicfts:
131
+ for field_name, value in entry.items():
132
+ setattr(comicfts, field_name, value)
133
+ else:
134
+ entry["comic_id"] = comic_id
135
+ comicfts = ComicFTS(**entry)
136
+
137
+ obj_list.append(comicfts)
138
+ status.increment_complete()
139
+
140
+ @classmethod
141
+ def prepare_sync_fts_entry(
142
+ cls,
143
+ comic: dict,
144
+ obj_list: list[ComicFTS],
145
+ *,
146
+ create: bool,
147
+ ):
148
+ """Prepare ComicFTS object from sync query data."""
149
+ entry = {
150
+ key.removeprefix("fts_"): comic.get(key, "")
151
+ for key in _COMIC_KEYS
152
+ if comic.get(key)
153
+ }
154
+ if sources := cls._get_sources_fts_field(entry):
155
+ entry["sources"] = sources
156
+ cls._create_comicfts_entry_fks(entry)
157
+ entry["universes"] = entry["universes"].strip(",")
158
+ cls._create_comicfts_entry_attributes(entry, create=create)
159
+ entry["comic_id"] = comic["id"]
160
+
161
+ comicfts: ComicFTS = ComicFTS(**entry)
162
+ obj_list.append(comicfts)