codex 1.8.0a2__py3-none-any.whl → 1.8.0a4__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 (477) hide show
  1. codex/choices/admin.py +4 -4
  2. codex/choices/statii.py +1 -1
  3. codex/librarian/covers/status.py +1 -1
  4. codex/librarian/librariand.py +2 -0
  5. codex/librarian/scribe/importer/const.py +8 -0
  6. codex/librarian/scribe/importer/create/foreign_keys.py +1 -1
  7. codex/librarian/scribe/importer/delete/covers.py +3 -1
  8. codex/librarian/scribe/importer/failed/__init__.py +1 -0
  9. codex/librarian/scribe/importer/failed/create.py +97 -0
  10. codex/librarian/scribe/importer/failed/failed.py +54 -0
  11. codex/librarian/scribe/importer/failed/query.py +103 -0
  12. codex/librarian/scribe/importer/init.py +2 -2
  13. codex/librarian/scribe/importer/link/covers.py +1 -1
  14. codex/librarian/scribe/importer/read/aggregate_path.py +4 -2
  15. codex/librarian/scribe/importer/search/__init__.py +1 -1
  16. codex/librarian/scribe/importer/search/update.py +45 -19
  17. codex/librarian/scribe/importer/statii/__init__.py +2 -0
  18. codex/librarian/scribe/importer/statii/failed.py +50 -0
  19. codex/librarian/scribe/importer/status.py +0 -12
  20. codex/librarian/scribe/janitor/janitor.py +13 -5
  21. codex/librarian/scribe/janitor/status.py +3 -2
  22. codex/librarian/scribe/search/optimize.py +1 -2
  23. codex/librarian/scribe/search/remove.py +2 -2
  24. codex/librarian/scribe/search/status.py +8 -8
  25. codex/librarian/scribe/search/sync.py +10 -3
  26. codex/librarian/scribe/status.py +2 -1
  27. codex/librarian/status.py +5 -5
  28. codex/librarian/status_controller.py +55 -25
  29. codex/librarian/watchdog/const.py +26 -2
  30. codex/librarian/watchdog/emitter.py +26 -34
  31. codex/librarian/watchdog/event_batcherd.py +18 -14
  32. codex/librarian/watchdog/observers.py +11 -15
  33. codex/migrations/0035_alter_librarianstatus_status_type.py +72 -0
  34. codex/startup/__init__.py +1 -1
  35. codex/static_root/assets/{VCheckbox-DSndl51k.1e28c443c3cb.js → VCheckbox--x5j8A4a.47af0eec9cc5.js} +1 -1
  36. codex/static_root/assets/VCheckbox--x5j8A4a.47af0eec9cc5.js.br +0 -0
  37. codex/static_root/assets/VCheckbox--x5j8A4a.47af0eec9cc5.js.gz +0 -0
  38. codex/static_root/assets/{VCheckbox-DSndl51k.js → VCheckbox--x5j8A4a.js} +1 -1
  39. codex/static_root/assets/VCheckbox--x5j8A4a.js.br +0 -0
  40. codex/static_root/assets/VCheckbox--x5j8A4a.js.gz +0 -0
  41. codex/static_root/assets/{VCheckboxBtn-Bu2Pf64q.d7463473d7a2.js → VCheckboxBtn-C44aiFUU.3d08a2da4b68.js} +1 -1
  42. codex/static_root/assets/VCheckboxBtn-C44aiFUU.3d08a2da4b68.js.br +0 -0
  43. codex/static_root/assets/VCheckboxBtn-C44aiFUU.3d08a2da4b68.js.gz +0 -0
  44. codex/static_root/assets/{VCheckboxBtn-Bu2Pf64q.js → VCheckboxBtn-C44aiFUU.js} +1 -1
  45. codex/static_root/assets/VCheckboxBtn-C44aiFUU.js.br +0 -0
  46. codex/static_root/assets/VCheckboxBtn-C44aiFUU.js.gz +0 -0
  47. codex/static_root/assets/{VCombobox-Uogv6Ckp.9f900e703605.js → VCombobox-DuJ5WhJs.d4d57278cd15.js} +1 -1
  48. codex/static_root/assets/VCombobox-DuJ5WhJs.d4d57278cd15.js.br +0 -0
  49. codex/static_root/assets/VCombobox-DuJ5WhJs.d4d57278cd15.js.gz +0 -0
  50. codex/static_root/assets/{VCombobox-Uogv6Ckp.js → VCombobox-DuJ5WhJs.js} +1 -1
  51. codex/static_root/assets/VCombobox-DuJ5WhJs.js.br +0 -0
  52. codex/static_root/assets/VCombobox-DuJ5WhJs.js.gz +0 -0
  53. codex/static_root/assets/{VDialog-BzaGu1HN.34f52763c3f8.js → VDialog-BxuI97hb.250bc105e373.js} +1 -1
  54. codex/static_root/assets/VDialog-BxuI97hb.250bc105e373.js.br +0 -0
  55. codex/static_root/assets/VDialog-BxuI97hb.250bc105e373.js.gz +0 -0
  56. codex/static_root/assets/{VDialog-BzaGu1HN.js → VDialog-BxuI97hb.js} +1 -1
  57. codex/static_root/assets/VDialog-BxuI97hb.js.br +0 -0
  58. codex/static_root/assets/VDialog-BxuI97hb.js.gz +0 -0
  59. codex/static_root/assets/{VDivider-C3ikm0Ko.4938e9ced53e.js → VDivider-DSzkVD8n.9346c2b22bde.js} +1 -1
  60. codex/static_root/assets/VDivider-DSzkVD8n.9346c2b22bde.js.br +0 -0
  61. codex/static_root/assets/VDivider-DSzkVD8n.9346c2b22bde.js.gz +0 -0
  62. codex/static_root/assets/{VDivider-C3ikm0Ko.js → VDivider-DSzkVD8n.js} +1 -1
  63. codex/static_root/assets/VDivider-DSzkVD8n.js.br +0 -0
  64. codex/static_root/assets/VDivider-DSzkVD8n.js.gz +0 -0
  65. codex/static_root/assets/{VExpansionPanels-AmsInZN0.5cb7c833de3d.js → VExpansionPanels-7DSA7BWQ.7fc1339ad9d6.js} +1 -1
  66. codex/static_root/assets/VExpansionPanels-7DSA7BWQ.7fc1339ad9d6.js.br +0 -0
  67. codex/static_root/assets/VExpansionPanels-7DSA7BWQ.7fc1339ad9d6.js.gz +0 -0
  68. codex/static_root/assets/{VExpansionPanels-AmsInZN0.js → VExpansionPanels-7DSA7BWQ.js} +1 -1
  69. codex/static_root/assets/VExpansionPanels-7DSA7BWQ.js.br +0 -0
  70. codex/static_root/assets/VExpansionPanels-7DSA7BWQ.js.gz +0 -0
  71. codex/static_root/assets/{VForm-CyCdgusw.c737973a1e85.js → VForm-BZtlScrY.bf87851b598f.js} +1 -1
  72. codex/static_root/assets/VForm-BZtlScrY.bf87851b598f.js.br +0 -0
  73. codex/static_root/assets/VForm-BZtlScrY.bf87851b598f.js.gz +0 -0
  74. codex/static_root/assets/{VForm-CyCdgusw.js → VForm-BZtlScrY.js} +1 -1
  75. codex/static_root/assets/VForm-BZtlScrY.js.br +0 -0
  76. codex/static_root/assets/VForm-BZtlScrY.js.gz +0 -0
  77. codex/static_root/assets/{VRadioGroup-BF0Xjrzi.e54d2bf41bb2.js → VRadioGroup-CRzhTpe9.1fc9e0e7a980.js} +1 -1
  78. codex/static_root/assets/VRadioGroup-CRzhTpe9.1fc9e0e7a980.js.br +0 -0
  79. codex/static_root/assets/VRadioGroup-CRzhTpe9.1fc9e0e7a980.js.gz +0 -0
  80. codex/static_root/assets/{VRadioGroup-BF0Xjrzi.js → VRadioGroup-CRzhTpe9.js} +1 -1
  81. codex/static_root/assets/VRadioGroup-CRzhTpe9.js.br +0 -0
  82. codex/static_root/assets/VRadioGroup-CRzhTpe9.js.gz +0 -0
  83. codex/static_root/assets/{VSelect-Dv50OIkN.js → VSelect-_Cduank3.65530f781519.js} +1 -1
  84. codex/static_root/assets/VSelect-_Cduank3.65530f781519.js.br +0 -0
  85. codex/static_root/assets/VSelect-_Cduank3.65530f781519.js.gz +0 -0
  86. codex/static_root/assets/{VSelect-Dv50OIkN.390adb1fe7fa.js → VSelect-_Cduank3.js} +1 -1
  87. codex/static_root/assets/VSelect-_Cduank3.js.br +0 -0
  88. codex/static_root/assets/VSelect-_Cduank3.js.gz +0 -0
  89. codex/static_root/assets/{VSelectionControl-DbKYScD5.js → VSelectionControl-C0Md0bXa.0b96d6d65ba2.js} +1 -1
  90. codex/static_root/assets/VSelectionControl-C0Md0bXa.0b96d6d65ba2.js.br +0 -0
  91. codex/static_root/assets/VSelectionControl-C0Md0bXa.0b96d6d65ba2.js.gz +0 -0
  92. codex/static_root/assets/{VSelectionControl-DbKYScD5.8d2ab1ebe546.js → VSelectionControl-C0Md0bXa.js} +1 -1
  93. codex/static_root/assets/VSelectionControl-C0Md0bXa.js.br +0 -0
  94. codex/static_root/assets/VSelectionControl-C0Md0bXa.js.gz +0 -0
  95. codex/static_root/assets/{VTable-BmOfHc7J.b2e1311009d1.js → VTable-lswnBwdy.f27115046a94.js} +1 -1
  96. codex/static_root/assets/VTable-lswnBwdy.f27115046a94.js.br +0 -0
  97. codex/static_root/assets/VTable-lswnBwdy.f27115046a94.js.gz +0 -0
  98. codex/static_root/assets/{VTable-BmOfHc7J.js → VTable-lswnBwdy.js} +1 -1
  99. codex/static_root/assets/VTable-lswnBwdy.js.br +0 -0
  100. codex/static_root/assets/VTable-lswnBwdy.js.gz +0 -0
  101. codex/static_root/assets/{VWindowItem-BLEDgagD.4b67c4a63c59.js → VWindowItem-hsPEpCj_.4bf66f9ba4b1.js} +1 -1
  102. codex/static_root/assets/VWindowItem-hsPEpCj_.4bf66f9ba4b1.js.br +0 -0
  103. codex/static_root/assets/VWindowItem-hsPEpCj_.4bf66f9ba4b1.js.gz +0 -0
  104. codex/static_root/assets/{VWindowItem-BLEDgagD.js → VWindowItem-hsPEpCj_.js} +1 -1
  105. codex/static_root/assets/VWindowItem-hsPEpCj_.js.br +0 -0
  106. codex/static_root/assets/VWindowItem-hsPEpCj_.js.gz +0 -0
  107. codex/static_root/assets/{admin-kjMoKlqD.55a1dd908124.js → admin-6qrzqcJO.2b8351e2c2c6.js} +1 -1
  108. codex/static_root/assets/admin-6qrzqcJO.2b8351e2c2c6.js.br +0 -0
  109. codex/static_root/assets/admin-6qrzqcJO.2b8351e2c2c6.js.gz +0 -0
  110. codex/static_root/assets/{admin-kjMoKlqD.js → admin-6qrzqcJO.js} +1 -1
  111. codex/static_root/assets/admin-6qrzqcJO.js.br +0 -0
  112. codex/static_root/assets/admin-6qrzqcJO.js.gz +0 -0
  113. codex/static_root/assets/{admin-Bv40vYZw.8179e1ece835.js → admin-CVe4N6vl.5e8ec2bd60d3.js} +1 -1
  114. codex/static_root/assets/admin-CVe4N6vl.5e8ec2bd60d3.js.br +0 -0
  115. codex/static_root/assets/admin-CVe4N6vl.5e8ec2bd60d3.js.gz +0 -0
  116. codex/static_root/assets/{admin-Bv40vYZw.js → admin-CVe4N6vl.js} +1 -1
  117. codex/static_root/assets/admin-CVe4N6vl.js.br +0 -0
  118. codex/static_root/assets/admin-CVe4N6vl.js.gz +0 -0
  119. codex/static_root/assets/admin-menu-B6raGfpC.790d01e1ec98.js +1 -0
  120. codex/static_root/assets/admin-menu-B6raGfpC.790d01e1ec98.js.br +0 -0
  121. codex/static_root/assets/admin-menu-B6raGfpC.790d01e1ec98.js.gz +0 -0
  122. codex/static_root/assets/admin-menu-B6raGfpC.js +1 -0
  123. codex/static_root/assets/admin-menu-B6raGfpC.js.br +0 -0
  124. codex/static_root/assets/admin-menu-B6raGfpC.js.gz +0 -0
  125. codex/static_root/assets/{admin-settings-button-progress-RfwaqLl2.4cdd37d0dd16.js → admin-settings-button-progress-D0jgpe2z.f9d1511fe4a7.js} +1 -1
  126. codex/static_root/assets/admin-settings-button-progress-D0jgpe2z.f9d1511fe4a7.js.br +0 -0
  127. codex/static_root/assets/admin-settings-button-progress-D0jgpe2z.f9d1511fe4a7.js.gz +0 -0
  128. codex/static_root/assets/{admin-settings-button-progress-RfwaqLl2.js → admin-settings-button-progress-D0jgpe2z.js} +1 -1
  129. codex/static_root/assets/admin-settings-button-progress-D0jgpe2z.js.br +0 -0
  130. codex/static_root/assets/admin-settings-button-progress-D0jgpe2z.js.gz +0 -0
  131. codex/static_root/assets/{browser-plYso4v5.js → browser-DPWgTJvq.aa42fd45fdc5.js} +1 -1
  132. codex/static_root/assets/browser-DPWgTJvq.aa42fd45fdc5.js.br +0 -0
  133. codex/static_root/assets/browser-DPWgTJvq.aa42fd45fdc5.js.gz +0 -0
  134. codex/static_root/assets/{browser-plYso4v5.87ef04b44d37.js → browser-DPWgTJvq.js} +1 -1
  135. codex/static_root/assets/browser-DPWgTJvq.js.br +0 -0
  136. codex/static_root/assets/browser-DPWgTJvq.js.gz +0 -0
  137. codex/static_root/assets/{change-password-dialog-DyhQwNv1.26383853ccc0.js → change-password-dialog-f0bnLsTX.ad5174bfd6b9.js} +1 -1
  138. codex/static_root/assets/change-password-dialog-f0bnLsTX.ad5174bfd6b9.js.br +0 -0
  139. codex/static_root/assets/change-password-dialog-f0bnLsTX.ad5174bfd6b9.js.gz +0 -0
  140. codex/static_root/assets/{change-password-dialog-DyhQwNv1.js → change-password-dialog-f0bnLsTX.js} +1 -1
  141. codex/static_root/assets/change-password-dialog-f0bnLsTX.js.br +0 -0
  142. codex/static_root/assets/change-password-dialog-f0bnLsTX.js.gz +0 -0
  143. codex/static_root/assets/{confirm-dialog-B7ndwV5M.d1f0728d4bd0.js → confirm-dialog-D2RCUHSr.ccb67b05d69e.js} +1 -1
  144. codex/static_root/assets/confirm-dialog-D2RCUHSr.ccb67b05d69e.js.br +0 -0
  145. codex/static_root/assets/confirm-dialog-D2RCUHSr.ccb67b05d69e.js.gz +0 -0
  146. codex/static_root/assets/{confirm-dialog-B7ndwV5M.js → confirm-dialog-D2RCUHSr.js} +1 -1
  147. codex/static_root/assets/confirm-dialog-D2RCUHSr.js.br +0 -0
  148. codex/static_root/assets/confirm-dialog-D2RCUHSr.js.gz +0 -0
  149. codex/static_root/assets/{datetime-column-DANpNGGe.13985ff7d484.js → datetime-column-C544paek.4b5c5cd44e86.js} +1 -1
  150. codex/static_root/assets/datetime-column-C544paek.4b5c5cd44e86.js.br +0 -0
  151. codex/static_root/assets/datetime-column-C544paek.4b5c5cd44e86.js.gz +0 -0
  152. codex/static_root/assets/{datetime-column-DANpNGGe.js → datetime-column-C544paek.js} +1 -1
  153. codex/static_root/assets/datetime-column-C544paek.js.br +0 -0
  154. codex/static_root/assets/datetime-column-C544paek.js.gz +0 -0
  155. codex/static_root/assets/{filter-Dhe8cVmt.ad92d3b618e3.js → filter-C2tmS7Gm.59b3cb2ccc7e.js} +1 -1
  156. codex/static_root/assets/filter-C2tmS7Gm.59b3cb2ccc7e.js.br +0 -0
  157. codex/static_root/assets/filter-C2tmS7Gm.59b3cb2ccc7e.js.gz +0 -0
  158. codex/static_root/assets/{filter-Dhe8cVmt.js → filter-C2tmS7Gm.js} +1 -1
  159. codex/static_root/assets/filter-C2tmS7Gm.js.br +0 -0
  160. codex/static_root/assets/filter-C2tmS7Gm.js.gz +0 -0
  161. codex/static_root/assets/{flag-tab-BZ9S7U8D.0b814b215567.js → flag-tab-BVUqzGNH.307659fba7b5.js} +1 -1
  162. codex/static_root/assets/flag-tab-BVUqzGNH.307659fba7b5.js.br +0 -0
  163. codex/static_root/assets/flag-tab-BVUqzGNH.307659fba7b5.js.gz +0 -0
  164. codex/static_root/assets/{flag-tab-BZ9S7U8D.js → flag-tab-BVUqzGNH.js} +1 -1
  165. codex/static_root/assets/flag-tab-BVUqzGNH.js.br +0 -0
  166. codex/static_root/assets/flag-tab-BVUqzGNH.js.gz +0 -0
  167. codex/static_root/assets/{forwardRefs-Z0d4Mnc7.js → forwardRefs-Byns6lbl.018798a57db2.js} +1 -1
  168. codex/static_root/assets/forwardRefs-Byns6lbl.018798a57db2.js.br +0 -0
  169. codex/static_root/assets/forwardRefs-Byns6lbl.018798a57db2.js.gz +0 -0
  170. codex/static_root/assets/{forwardRefs-Z0d4Mnc7.deb4e7a1b8b5.js → forwardRefs-Byns6lbl.js} +1 -1
  171. codex/static_root/assets/forwardRefs-Byns6lbl.js.br +0 -0
  172. codex/static_root/assets/forwardRefs-Byns6lbl.js.gz +0 -0
  173. codex/static_root/assets/{group-tab-B0ASBB3_.8e10b90ff052.js → group-tab-TNxZJJZ6.6d88969a9263.js} +1 -1
  174. codex/static_root/assets/group-tab-TNxZJJZ6.6d88969a9263.js.br +0 -0
  175. codex/static_root/assets/group-tab-TNxZJJZ6.6d88969a9263.js.gz +0 -0
  176. codex/static_root/assets/{group-tab-B0ASBB3_.js → group-tab-TNxZJJZ6.js} +1 -1
  177. codex/static_root/assets/group-tab-TNxZJJZ6.js.br +0 -0
  178. codex/static_root/assets/group-tab-TNxZJJZ6.js.gz +0 -0
  179. codex/static_root/assets/{http-error-BP-mMZsK.72c4d00b40d2.js → http-error-D3uGBdtN.39e149587f96.js} +1 -1
  180. codex/static_root/assets/http-error-D3uGBdtN.39e149587f96.js.br +0 -0
  181. codex/static_root/assets/http-error-D3uGBdtN.39e149587f96.js.gz +0 -0
  182. codex/static_root/assets/{http-error-BP-mMZsK.js → http-error-D3uGBdtN.js} +1 -1
  183. codex/static_root/assets/http-error-D3uGBdtN.js.br +0 -0
  184. codex/static_root/assets/http-error-D3uGBdtN.js.gz +0 -0
  185. codex/static_root/assets/{index-Cu9nQXJD.49795921eada.js → index-J6F_OMTQ.2a8861f7acc1.js} +1 -1
  186. codex/static_root/assets/index-J6F_OMTQ.2a8861f7acc1.js.br +0 -0
  187. codex/static_root/assets/index-J6F_OMTQ.2a8861f7acc1.js.gz +0 -0
  188. codex/static_root/assets/{index-Cu9nQXJD.js → index-J6F_OMTQ.js} +1 -1
  189. codex/static_root/assets/index-J6F_OMTQ.js.br +0 -0
  190. codex/static_root/assets/index-J6F_OMTQ.js.gz +0 -0
  191. codex/static_root/assets/{library-tab-D9lxhAqv.02f7064c20f3.css → library-tab-5StL67ei.0fad8998a237.css} +1 -1
  192. codex/static_root/assets/library-tab-5StL67ei.0fad8998a237.css.br +0 -0
  193. codex/static_root/assets/library-tab-5StL67ei.0fad8998a237.css.gz +0 -0
  194. codex/static_root/assets/{library-tab-D9lxhAqv.css → library-tab-5StL67ei.css} +1 -1
  195. codex/static_root/assets/library-tab-5StL67ei.css.br +0 -0
  196. codex/static_root/assets/library-tab-5StL67ei.css.gz +0 -0
  197. codex/static_root/assets/library-tab-DX9ZW9uM.8419900ed9b8.js +1 -0
  198. codex/static_root/assets/library-tab-DX9ZW9uM.8419900ed9b8.js.br +0 -0
  199. codex/static_root/assets/library-tab-DX9ZW9uM.8419900ed9b8.js.gz +0 -0
  200. codex/static_root/assets/library-tab-DX9ZW9uM.js +1 -0
  201. codex/static_root/assets/library-tab-DX9ZW9uM.js.br +0 -0
  202. codex/static_root/assets/library-tab-DX9ZW9uM.js.gz +0 -0
  203. codex/static_root/assets/main-CXE4elND.b45c7c290af2.js +39 -0
  204. codex/static_root/assets/main-CXE4elND.b45c7c290af2.js.br +0 -0
  205. codex/static_root/assets/main-CXE4elND.b45c7c290af2.js.gz +0 -0
  206. codex/static_root/assets/main-CXE4elND.js +39 -0
  207. codex/static_root/assets/main-CXE4elND.js.br +0 -0
  208. codex/static_root/assets/main-CXE4elND.js.gz +0 -0
  209. codex/static_root/assets/pager-full-pdf-C8QcluEe.99a4c4dddf53.js +1 -0
  210. codex/static_root/assets/pager-full-pdf-C8QcluEe.99a4c4dddf53.js.br +0 -0
  211. codex/static_root/assets/pager-full-pdf-C8QcluEe.99a4c4dddf53.js.gz +0 -0
  212. codex/static_root/assets/pager-full-pdf-C8QcluEe.js +1 -0
  213. codex/static_root/assets/pager-full-pdf-C8QcluEe.js.br +0 -0
  214. codex/static_root/assets/pager-full-pdf-C8QcluEe.js.gz +0 -0
  215. codex/static_root/assets/{pagination-toolbar-DGfRDeRW.c3f463ad6edd.js → pagination-toolbar-BqvFln9z.d38452f8ce48.js} +1 -1
  216. codex/static_root/assets/pagination-toolbar-BqvFln9z.d38452f8ce48.js.br +0 -0
  217. codex/static_root/assets/pagination-toolbar-BqvFln9z.d38452f8ce48.js.gz +0 -0
  218. codex/static_root/assets/{pagination-toolbar-DGfRDeRW.js → pagination-toolbar-BqvFln9z.js} +1 -1
  219. codex/static_root/assets/pagination-toolbar-BqvFln9z.js.br +0 -0
  220. codex/static_root/assets/pagination-toolbar-BqvFln9z.js.gz +0 -0
  221. codex/static_root/assets/{pdf-doc-D6Meu4vZ.91b43d057670.js → pdf-doc-BeNzjayP.e6b65a74287b.js} +14 -14
  222. codex/static_root/assets/pdf-doc-BeNzjayP.e6b65a74287b.js.br +0 -0
  223. codex/static_root/assets/pdf-doc-BeNzjayP.e6b65a74287b.js.gz +0 -0
  224. codex/static_root/assets/{pdf-doc-D6Meu4vZ.js → pdf-doc-BeNzjayP.js} +14 -14
  225. codex/static_root/assets/pdf-doc-BeNzjayP.js.br +0 -0
  226. codex/static_root/assets/pdf-doc-BeNzjayP.js.gz +0 -0
  227. codex/static_root/assets/reader-DG9FVXqI.366a61e33d8b.js +2 -0
  228. codex/static_root/assets/reader-DG9FVXqI.366a61e33d8b.js.br +0 -0
  229. codex/static_root/assets/reader-DG9FVXqI.366a61e33d8b.js.gz +0 -0
  230. codex/static_root/assets/reader-DG9FVXqI.js +2 -0
  231. codex/static_root/assets/reader-DG9FVXqI.js.br +0 -0
  232. codex/static_root/assets/reader-DG9FVXqI.js.gz +0 -0
  233. codex/static_root/assets/{reader-LwL05rgA.c022ad3b7b94.css → reader-HE07eoaG.8626eeb7c718.css} +1 -1
  234. codex/static_root/assets/reader-HE07eoaG.8626eeb7c718.css.br +0 -0
  235. codex/static_root/assets/reader-HE07eoaG.8626eeb7c718.css.gz +0 -0
  236. codex/static_root/assets/{reader-LwL05rgA.css → reader-HE07eoaG.css} +1 -1
  237. codex/static_root/assets/reader-HE07eoaG.css.br +0 -0
  238. codex/static_root/assets/reader-HE07eoaG.css.gz +0 -0
  239. codex/static_root/assets/{relation-chips-CAXZIswb.e991a259ce59.js → relation-chips-BrO8HnXq.fa4a7390c640.js} +1 -1
  240. codex/static_root/assets/relation-chips-BrO8HnXq.fa4a7390c640.js.br +0 -0
  241. codex/static_root/assets/relation-chips-BrO8HnXq.fa4a7390c640.js.gz +0 -0
  242. codex/static_root/assets/{relation-chips-CAXZIswb.js → relation-chips-BrO8HnXq.js} +1 -1
  243. codex/static_root/assets/relation-chips-BrO8HnXq.js.br +0 -0
  244. codex/static_root/assets/relation-chips-BrO8HnXq.js.gz +0 -0
  245. codex/static_root/assets/{settings-drawer-B4gD41g6.js → settings-drawer-a2xwlRQb.41475006862d.js} +2 -2
  246. codex/static_root/assets/settings-drawer-a2xwlRQb.41475006862d.js.br +0 -0
  247. codex/static_root/assets/settings-drawer-a2xwlRQb.41475006862d.js.gz +0 -0
  248. codex/static_root/assets/{settings-drawer-B4gD41g6.82718694498e.js → settings-drawer-a2xwlRQb.js} +2 -2
  249. codex/static_root/assets/settings-drawer-a2xwlRQb.js.br +0 -0
  250. codex/static_root/assets/settings-drawer-a2xwlRQb.js.gz +0 -0
  251. codex/static_root/assets/{ssrBoot-O6yTJ_UV.7180d77d283e.js → ssrBoot-BUdwZUw6.964a0734eff2.js} +1 -1
  252. codex/static_root/assets/ssrBoot-BUdwZUw6.964a0734eff2.js.br +0 -0
  253. codex/static_root/assets/ssrBoot-BUdwZUw6.964a0734eff2.js.gz +0 -0
  254. codex/static_root/assets/{ssrBoot-O6yTJ_UV.js → ssrBoot-BUdwZUw6.js} +1 -1
  255. codex/static_root/assets/ssrBoot-BUdwZUw6.js.br +0 -0
  256. codex/static_root/assets/ssrBoot-BUdwZUw6.js.gz +0 -0
  257. codex/static_root/assets/{stats-tab-BZjOg19A.afb2e6b0d648.js → stats-tab-D_Sf0W-w.7dd721aef1d7.js} +1 -1
  258. codex/static_root/assets/stats-tab-D_Sf0W-w.7dd721aef1d7.js.br +0 -0
  259. codex/static_root/assets/stats-tab-D_Sf0W-w.7dd721aef1d7.js.gz +0 -0
  260. codex/static_root/assets/{stats-tab-BZjOg19A.js → stats-tab-D_Sf0W-w.js} +1 -1
  261. codex/static_root/assets/stats-tab-D_Sf0W-w.js.br +0 -0
  262. codex/static_root/assets/stats-tab-D_Sf0W-w.js.gz +0 -0
  263. codex/static_root/assets/task-tab-CuZPm55f.827f36543dcc.js +1 -0
  264. codex/static_root/assets/task-tab-CuZPm55f.827f36543dcc.js.br +0 -0
  265. codex/static_root/assets/task-tab-CuZPm55f.827f36543dcc.js.gz +0 -0
  266. codex/static_root/assets/task-tab-CuZPm55f.js +1 -0
  267. codex/static_root/assets/task-tab-CuZPm55f.js.br +0 -0
  268. codex/static_root/assets/task-tab-CuZPm55f.js.gz +0 -0
  269. codex/static_root/assets/{unauthorized-Bo3ThIrX.12d2efd95d7d.js → unauthorized-Bx_I2aj6.4846dbaf53c3.js} +1 -1
  270. codex/static_root/assets/unauthorized-Bx_I2aj6.4846dbaf53c3.js.br +0 -0
  271. codex/static_root/assets/unauthorized-Bx_I2aj6.4846dbaf53c3.js.gz +0 -0
  272. codex/static_root/assets/{unauthorized-Bo3ThIrX.js → unauthorized-Bx_I2aj6.js} +1 -1
  273. codex/static_root/assets/unauthorized-Bx_I2aj6.js.br +0 -0
  274. codex/static_root/assets/unauthorized-Bx_I2aj6.js.gz +0 -0
  275. codex/static_root/assets/{user-tab-BQ82qBg3.17190dc83452.js → user-tab-6FMrYQKf.ac405e881ade.js} +1 -1
  276. codex/static_root/assets/user-tab-6FMrYQKf.ac405e881ade.js.br +0 -0
  277. codex/static_root/assets/user-tab-6FMrYQKf.ac405e881ade.js.gz +0 -0
  278. codex/static_root/assets/{user-tab-BQ82qBg3.js → user-tab-6FMrYQKf.js} +1 -1
  279. codex/static_root/assets/user-tab-6FMrYQKf.js.br +0 -0
  280. codex/static_root/assets/user-tab-6FMrYQKf.js.gz +0 -0
  281. codex/static_root/{manifest.0dc91d0dee6d.json → manifest.dfd8ee684697.json} +297 -297
  282. codex/static_root/manifest.dfd8ee684697.json.br +0 -0
  283. codex/static_root/manifest.dfd8ee684697.json.gz +0 -0
  284. codex/static_root/manifest.json +297 -297
  285. codex/static_root/manifest.json.br +0 -0
  286. codex/static_root/manifest.json.gz +0 -0
  287. codex/static_root/staticfiles.json +1 -1
  288. codex/views/admin/library.py +4 -1
  289. codex/views/browser/params.py +21 -17
  290. codex/views/reader/arcs.py +16 -6
  291. codex/views/reader/params.py +4 -1
  292. codex/views/session.py +1 -0
  293. {codex-1.8.0a2.dist-info → codex-1.8.0a4.dist-info}/METADATA +2 -2
  294. {codex-1.8.0a2.dist-info → codex-1.8.0a4.dist-info}/RECORD +297 -293
  295. codex/librarian/scribe/importer/failed_imports.py +0 -168
  296. codex/librarian/scribe/importer/statii/1 +0 -27
  297. codex/static_root/assets/VCheckbox-DSndl51k.1e28c443c3cb.js.br +0 -0
  298. codex/static_root/assets/VCheckbox-DSndl51k.1e28c443c3cb.js.gz +0 -0
  299. codex/static_root/assets/VCheckbox-DSndl51k.js.br +0 -0
  300. codex/static_root/assets/VCheckbox-DSndl51k.js.gz +0 -0
  301. codex/static_root/assets/VCheckboxBtn-Bu2Pf64q.d7463473d7a2.js.br +0 -0
  302. codex/static_root/assets/VCheckboxBtn-Bu2Pf64q.d7463473d7a2.js.gz +0 -0
  303. codex/static_root/assets/VCheckboxBtn-Bu2Pf64q.js.br +0 -0
  304. codex/static_root/assets/VCheckboxBtn-Bu2Pf64q.js.gz +0 -0
  305. codex/static_root/assets/VCombobox-Uogv6Ckp.9f900e703605.js.br +0 -0
  306. codex/static_root/assets/VCombobox-Uogv6Ckp.9f900e703605.js.gz +0 -0
  307. codex/static_root/assets/VCombobox-Uogv6Ckp.js.br +0 -0
  308. codex/static_root/assets/VCombobox-Uogv6Ckp.js.gz +0 -0
  309. codex/static_root/assets/VDialog-BzaGu1HN.34f52763c3f8.js.br +0 -0
  310. codex/static_root/assets/VDialog-BzaGu1HN.34f52763c3f8.js.gz +0 -0
  311. codex/static_root/assets/VDialog-BzaGu1HN.js.br +0 -0
  312. codex/static_root/assets/VDialog-BzaGu1HN.js.gz +0 -0
  313. codex/static_root/assets/VDivider-C3ikm0Ko.4938e9ced53e.js.br +0 -0
  314. codex/static_root/assets/VDivider-C3ikm0Ko.4938e9ced53e.js.gz +0 -0
  315. codex/static_root/assets/VDivider-C3ikm0Ko.js.br +0 -0
  316. codex/static_root/assets/VDivider-C3ikm0Ko.js.gz +0 -0
  317. codex/static_root/assets/VExpansionPanels-AmsInZN0.5cb7c833de3d.js.br +0 -0
  318. codex/static_root/assets/VExpansionPanels-AmsInZN0.5cb7c833de3d.js.gz +0 -0
  319. codex/static_root/assets/VExpansionPanels-AmsInZN0.js.br +0 -0
  320. codex/static_root/assets/VExpansionPanels-AmsInZN0.js.gz +0 -0
  321. codex/static_root/assets/VForm-CyCdgusw.c737973a1e85.js.br +0 -0
  322. codex/static_root/assets/VForm-CyCdgusw.c737973a1e85.js.gz +0 -0
  323. codex/static_root/assets/VForm-CyCdgusw.js.br +0 -0
  324. codex/static_root/assets/VForm-CyCdgusw.js.gz +0 -0
  325. codex/static_root/assets/VRadioGroup-BF0Xjrzi.e54d2bf41bb2.js.br +0 -0
  326. codex/static_root/assets/VRadioGroup-BF0Xjrzi.e54d2bf41bb2.js.gz +0 -0
  327. codex/static_root/assets/VRadioGroup-BF0Xjrzi.js.br +0 -0
  328. codex/static_root/assets/VRadioGroup-BF0Xjrzi.js.gz +0 -0
  329. codex/static_root/assets/VSelect-Dv50OIkN.390adb1fe7fa.js.br +0 -0
  330. codex/static_root/assets/VSelect-Dv50OIkN.390adb1fe7fa.js.gz +0 -0
  331. codex/static_root/assets/VSelect-Dv50OIkN.js.br +0 -0
  332. codex/static_root/assets/VSelect-Dv50OIkN.js.gz +0 -0
  333. codex/static_root/assets/VSelectionControl-DbKYScD5.8d2ab1ebe546.js.br +0 -0
  334. codex/static_root/assets/VSelectionControl-DbKYScD5.8d2ab1ebe546.js.gz +0 -0
  335. codex/static_root/assets/VSelectionControl-DbKYScD5.js.br +0 -0
  336. codex/static_root/assets/VSelectionControl-DbKYScD5.js.gz +0 -0
  337. codex/static_root/assets/VTable-BmOfHc7J.b2e1311009d1.js.br +0 -0
  338. codex/static_root/assets/VTable-BmOfHc7J.b2e1311009d1.js.gz +0 -0
  339. codex/static_root/assets/VTable-BmOfHc7J.js.br +0 -0
  340. codex/static_root/assets/VTable-BmOfHc7J.js.gz +0 -0
  341. codex/static_root/assets/VWindowItem-BLEDgagD.4b67c4a63c59.js.br +0 -0
  342. codex/static_root/assets/VWindowItem-BLEDgagD.4b67c4a63c59.js.gz +0 -0
  343. codex/static_root/assets/VWindowItem-BLEDgagD.js.br +0 -0
  344. codex/static_root/assets/VWindowItem-BLEDgagD.js.gz +0 -0
  345. codex/static_root/assets/admin-Bv40vYZw.8179e1ece835.js.br +0 -0
  346. codex/static_root/assets/admin-Bv40vYZw.8179e1ece835.js.gz +0 -0
  347. codex/static_root/assets/admin-Bv40vYZw.js.br +0 -0
  348. codex/static_root/assets/admin-Bv40vYZw.js.gz +0 -0
  349. codex/static_root/assets/admin-kjMoKlqD.55a1dd908124.js.br +0 -0
  350. codex/static_root/assets/admin-kjMoKlqD.55a1dd908124.js.gz +0 -0
  351. codex/static_root/assets/admin-kjMoKlqD.js.br +0 -0
  352. codex/static_root/assets/admin-kjMoKlqD.js.gz +0 -0
  353. codex/static_root/assets/admin-menu-BNpuOmbI.e1f62ba483cd.js +0 -1
  354. codex/static_root/assets/admin-menu-BNpuOmbI.e1f62ba483cd.js.br +0 -0
  355. codex/static_root/assets/admin-menu-BNpuOmbI.e1f62ba483cd.js.gz +0 -0
  356. codex/static_root/assets/admin-menu-BNpuOmbI.js +0 -1
  357. codex/static_root/assets/admin-menu-BNpuOmbI.js.br +0 -0
  358. codex/static_root/assets/admin-menu-BNpuOmbI.js.gz +0 -0
  359. codex/static_root/assets/admin-settings-button-progress-RfwaqLl2.4cdd37d0dd16.js.br +0 -0
  360. codex/static_root/assets/admin-settings-button-progress-RfwaqLl2.4cdd37d0dd16.js.gz +0 -0
  361. codex/static_root/assets/admin-settings-button-progress-RfwaqLl2.js.br +0 -0
  362. codex/static_root/assets/admin-settings-button-progress-RfwaqLl2.js.gz +0 -0
  363. codex/static_root/assets/browser-plYso4v5.87ef04b44d37.js.br +0 -0
  364. codex/static_root/assets/browser-plYso4v5.87ef04b44d37.js.gz +0 -0
  365. codex/static_root/assets/browser-plYso4v5.js.br +0 -0
  366. codex/static_root/assets/browser-plYso4v5.js.gz +0 -0
  367. codex/static_root/assets/change-password-dialog-DyhQwNv1.26383853ccc0.js.br +0 -0
  368. codex/static_root/assets/change-password-dialog-DyhQwNv1.26383853ccc0.js.gz +0 -0
  369. codex/static_root/assets/change-password-dialog-DyhQwNv1.js.br +0 -0
  370. codex/static_root/assets/change-password-dialog-DyhQwNv1.js.gz +0 -0
  371. codex/static_root/assets/confirm-dialog-B7ndwV5M.d1f0728d4bd0.js.br +0 -0
  372. codex/static_root/assets/confirm-dialog-B7ndwV5M.d1f0728d4bd0.js.gz +0 -0
  373. codex/static_root/assets/confirm-dialog-B7ndwV5M.js.br +0 -0
  374. codex/static_root/assets/confirm-dialog-B7ndwV5M.js.gz +0 -0
  375. codex/static_root/assets/datetime-column-DANpNGGe.13985ff7d484.js.br +0 -0
  376. codex/static_root/assets/datetime-column-DANpNGGe.13985ff7d484.js.gz +0 -0
  377. codex/static_root/assets/datetime-column-DANpNGGe.js.br +0 -0
  378. codex/static_root/assets/datetime-column-DANpNGGe.js.gz +0 -0
  379. codex/static_root/assets/filter-Dhe8cVmt.ad92d3b618e3.js.br +0 -0
  380. codex/static_root/assets/filter-Dhe8cVmt.ad92d3b618e3.js.gz +0 -0
  381. codex/static_root/assets/filter-Dhe8cVmt.js.br +0 -0
  382. codex/static_root/assets/filter-Dhe8cVmt.js.gz +0 -0
  383. codex/static_root/assets/flag-tab-BZ9S7U8D.0b814b215567.js.br +0 -0
  384. codex/static_root/assets/flag-tab-BZ9S7U8D.0b814b215567.js.gz +0 -0
  385. codex/static_root/assets/flag-tab-BZ9S7U8D.js.br +0 -0
  386. codex/static_root/assets/flag-tab-BZ9S7U8D.js.gz +0 -0
  387. codex/static_root/assets/forwardRefs-Z0d4Mnc7.deb4e7a1b8b5.js.br +0 -0
  388. codex/static_root/assets/forwardRefs-Z0d4Mnc7.deb4e7a1b8b5.js.gz +0 -0
  389. codex/static_root/assets/forwardRefs-Z0d4Mnc7.js.br +0 -0
  390. codex/static_root/assets/forwardRefs-Z0d4Mnc7.js.gz +0 -0
  391. codex/static_root/assets/group-tab-B0ASBB3_.8e10b90ff052.js.br +0 -0
  392. codex/static_root/assets/group-tab-B0ASBB3_.8e10b90ff052.js.gz +0 -0
  393. codex/static_root/assets/group-tab-B0ASBB3_.js.br +0 -0
  394. codex/static_root/assets/group-tab-B0ASBB3_.js.gz +0 -0
  395. codex/static_root/assets/http-error-BP-mMZsK.72c4d00b40d2.js.br +0 -0
  396. codex/static_root/assets/http-error-BP-mMZsK.72c4d00b40d2.js.gz +0 -0
  397. codex/static_root/assets/http-error-BP-mMZsK.js.br +0 -0
  398. codex/static_root/assets/http-error-BP-mMZsK.js.gz +0 -0
  399. codex/static_root/assets/index-Cu9nQXJD.49795921eada.js.br +0 -0
  400. codex/static_root/assets/index-Cu9nQXJD.49795921eada.js.gz +0 -0
  401. codex/static_root/assets/index-Cu9nQXJD.js.br +0 -0
  402. codex/static_root/assets/index-Cu9nQXJD.js.gz +0 -0
  403. codex/static_root/assets/library-tab-8g2eSuGN.846cc1674a67.js +0 -1
  404. codex/static_root/assets/library-tab-8g2eSuGN.846cc1674a67.js.br +0 -0
  405. codex/static_root/assets/library-tab-8g2eSuGN.846cc1674a67.js.gz +0 -0
  406. codex/static_root/assets/library-tab-8g2eSuGN.js +0 -1
  407. codex/static_root/assets/library-tab-8g2eSuGN.js.br +0 -0
  408. codex/static_root/assets/library-tab-8g2eSuGN.js.gz +0 -0
  409. codex/static_root/assets/library-tab-D9lxhAqv.02f7064c20f3.css.br +0 -0
  410. codex/static_root/assets/library-tab-D9lxhAqv.02f7064c20f3.css.gz +0 -0
  411. codex/static_root/assets/library-tab-D9lxhAqv.css.br +0 -0
  412. codex/static_root/assets/library-tab-D9lxhAqv.css.gz +0 -0
  413. codex/static_root/assets/main-BoAlbVoF.e41ba211717d.js +0 -39
  414. codex/static_root/assets/main-BoAlbVoF.e41ba211717d.js.br +0 -0
  415. codex/static_root/assets/main-BoAlbVoF.e41ba211717d.js.gz +0 -0
  416. codex/static_root/assets/main-BoAlbVoF.js +0 -39
  417. codex/static_root/assets/main-BoAlbVoF.js.br +0 -0
  418. codex/static_root/assets/main-BoAlbVoF.js.gz +0 -0
  419. codex/static_root/assets/pager-full-pdf-DShiSKPO.026946648650.js +0 -1
  420. codex/static_root/assets/pager-full-pdf-DShiSKPO.026946648650.js.br +0 -0
  421. codex/static_root/assets/pager-full-pdf-DShiSKPO.026946648650.js.gz +0 -0
  422. codex/static_root/assets/pager-full-pdf-DShiSKPO.js +0 -1
  423. codex/static_root/assets/pager-full-pdf-DShiSKPO.js.br +0 -0
  424. codex/static_root/assets/pager-full-pdf-DShiSKPO.js.gz +0 -0
  425. codex/static_root/assets/pagination-toolbar-DGfRDeRW.c3f463ad6edd.js.br +0 -0
  426. codex/static_root/assets/pagination-toolbar-DGfRDeRW.c3f463ad6edd.js.gz +0 -0
  427. codex/static_root/assets/pagination-toolbar-DGfRDeRW.js.br +0 -0
  428. codex/static_root/assets/pagination-toolbar-DGfRDeRW.js.gz +0 -0
  429. codex/static_root/assets/pdf-doc-D6Meu4vZ.91b43d057670.js.br +0 -0
  430. codex/static_root/assets/pdf-doc-D6Meu4vZ.91b43d057670.js.gz +0 -0
  431. codex/static_root/assets/pdf-doc-D6Meu4vZ.js.br +0 -0
  432. codex/static_root/assets/pdf-doc-D6Meu4vZ.js.gz +0 -0
  433. codex/static_root/assets/reader-CptqnqBZ.340bc756e164.js +0 -2
  434. codex/static_root/assets/reader-CptqnqBZ.340bc756e164.js.br +0 -0
  435. codex/static_root/assets/reader-CptqnqBZ.340bc756e164.js.gz +0 -0
  436. codex/static_root/assets/reader-CptqnqBZ.js +0 -2
  437. codex/static_root/assets/reader-CptqnqBZ.js.br +0 -0
  438. codex/static_root/assets/reader-CptqnqBZ.js.gz +0 -0
  439. codex/static_root/assets/reader-LwL05rgA.c022ad3b7b94.css.br +0 -0
  440. codex/static_root/assets/reader-LwL05rgA.c022ad3b7b94.css.gz +0 -0
  441. codex/static_root/assets/reader-LwL05rgA.css.br +0 -0
  442. codex/static_root/assets/reader-LwL05rgA.css.gz +0 -0
  443. codex/static_root/assets/relation-chips-CAXZIswb.e991a259ce59.js.br +0 -0
  444. codex/static_root/assets/relation-chips-CAXZIswb.e991a259ce59.js.gz +0 -0
  445. codex/static_root/assets/relation-chips-CAXZIswb.js.br +0 -0
  446. codex/static_root/assets/relation-chips-CAXZIswb.js.gz +0 -0
  447. codex/static_root/assets/settings-drawer-B4gD41g6.82718694498e.js.br +0 -0
  448. codex/static_root/assets/settings-drawer-B4gD41g6.82718694498e.js.gz +0 -0
  449. codex/static_root/assets/settings-drawer-B4gD41g6.js.br +0 -0
  450. codex/static_root/assets/settings-drawer-B4gD41g6.js.gz +0 -0
  451. codex/static_root/assets/ssrBoot-O6yTJ_UV.7180d77d283e.js.br +0 -0
  452. codex/static_root/assets/ssrBoot-O6yTJ_UV.7180d77d283e.js.gz +0 -0
  453. codex/static_root/assets/ssrBoot-O6yTJ_UV.js.br +0 -0
  454. codex/static_root/assets/ssrBoot-O6yTJ_UV.js.gz +0 -0
  455. codex/static_root/assets/stats-tab-BZjOg19A.afb2e6b0d648.js.br +0 -0
  456. codex/static_root/assets/stats-tab-BZjOg19A.afb2e6b0d648.js.gz +0 -0
  457. codex/static_root/assets/stats-tab-BZjOg19A.js.br +0 -0
  458. codex/static_root/assets/stats-tab-BZjOg19A.js.gz +0 -0
  459. codex/static_root/assets/task-tab-GP2jPkRE.cfdfb9396ec4.js +0 -1
  460. codex/static_root/assets/task-tab-GP2jPkRE.cfdfb9396ec4.js.br +0 -0
  461. codex/static_root/assets/task-tab-GP2jPkRE.cfdfb9396ec4.js.gz +0 -0
  462. codex/static_root/assets/task-tab-GP2jPkRE.js +0 -1
  463. codex/static_root/assets/task-tab-GP2jPkRE.js.br +0 -0
  464. codex/static_root/assets/task-tab-GP2jPkRE.js.gz +0 -0
  465. codex/static_root/assets/unauthorized-Bo3ThIrX.12d2efd95d7d.js.br +0 -0
  466. codex/static_root/assets/unauthorized-Bo3ThIrX.12d2efd95d7d.js.gz +0 -0
  467. codex/static_root/assets/unauthorized-Bo3ThIrX.js.br +0 -0
  468. codex/static_root/assets/unauthorized-Bo3ThIrX.js.gz +0 -0
  469. codex/static_root/assets/user-tab-BQ82qBg3.17190dc83452.js.br +0 -0
  470. codex/static_root/assets/user-tab-BQ82qBg3.17190dc83452.js.gz +0 -0
  471. codex/static_root/assets/user-tab-BQ82qBg3.js.br +0 -0
  472. codex/static_root/assets/user-tab-BQ82qBg3.js.gz +0 -0
  473. codex/static_root/manifest.0dc91d0dee6d.json.br +0 -0
  474. codex/static_root/manifest.0dc91d0dee6d.json.gz +0 -0
  475. {codex-1.8.0a2.dist-info → codex-1.8.0a4.dist-info}/WHEEL +0 -0
  476. {codex-1.8.0a2.dist-info → codex-1.8.0a4.dist-info}/entry_points.txt +0 -0
  477. {codex-1.8.0a2.dist-info → codex-1.8.0a4.dist-info}/licenses/LICENSE +0 -0
codex/choices/admin.py CHANGED
@@ -118,23 +118,23 @@ ADMIN_TASK_GROUPS: MappingProxyType[
118
118
  {
119
119
  "value": "db_fts_rebuild",
120
120
  "title": "Repair Search Index",
121
- "desc": "Probably faster than Rebuild if integrity check fails.",
121
+ "desc": "Probably faster than Rebuild if the integrity check fails.",
122
122
  },
123
123
  {
124
124
  "value": "search_index_abort",
125
- "title": "Abort Legacy Search Index Sync",
125
+ "title": "Abort Search Index Sync",
126
126
  "desc": "Aborts search index sync tasks.",
127
127
  },
128
128
  {
129
129
  "value": "search_index_update",
130
130
  "title": "Sync Search Index",
131
- "desc": "with recently changed comics. This should not need to be run.",
131
+ "desc": "with recently changed comics.",
132
132
  "confirm": "This can take a long time",
133
133
  },
134
134
  {
135
135
  "value": "search_index_rebuild",
136
136
  "title": "Rebuild Search Index Using Sync.",
137
- "desc": "Delete and rebuild the search index from scratch using the legacy syncer. This should not need to be run.",
137
+ "desc": "Delete and rebuild the search index from scratch using the syncer.",
138
138
  "confirm": "This can take a long time",
139
139
  },
140
140
  ),
codex/choices/statii.py CHANGED
@@ -8,11 +8,11 @@ from codex.librarian.covers.status import COVERS_STATII
8
8
  from codex.librarian.restarter.status import RESTARTER_STATII
9
9
  from codex.librarian.scribe.importer.statii.create import CREATE_STATII
10
10
  from codex.librarian.scribe.importer.statii.delete import REMOVE_STATII
11
+ from codex.librarian.scribe.importer.statii.failed import FAILED_IMPORTS_STATII
11
12
  from codex.librarian.scribe.importer.statii.link import LINK_STATII
12
13
  from codex.librarian.scribe.importer.statii.query import QUERY_STATII
13
14
  from codex.librarian.scribe.importer.statii.read import READ_STATII
14
15
  from codex.librarian.scribe.importer.statii.search import IMPORTER_SEARCH_INDEX_STATII
15
- from codex.librarian.scribe.importer.status import FAILED_IMPORTS_STATII
16
16
  from codex.librarian.scribe.janitor.status import JANITOR_STATII
17
17
  from codex.librarian.scribe.search.status import SEARCH_INDEX_STATII
18
18
  from codex.librarian.scribe.status import SCRIBE_STATII
@@ -23,7 +23,7 @@ class RemoveCoversStatus(CoversStatus):
23
23
 
24
24
  CODE = "CRC"
25
25
  VERB = "Remove"
26
- LOG_SUCCESS = True
26
+ log_success = True
27
27
 
28
28
 
29
29
  class FindOrphanCoversStatus(CoversStatus):
@@ -21,6 +21,7 @@ from codex.librarian.restarter.restarter import CodexRestarter
21
21
  from codex.librarian.restarter.tasks import CodexRestarterTask
22
22
  from codex.librarian.scribe.janitor.tasks import JanitorAdoptOrphanFoldersTask
23
23
  from codex.librarian.scribe.scribed import ScribeThread
24
+ from codex.librarian.scribe.search.tasks import SearchIndexSyncTask
24
25
  from codex.librarian.scribe.tasks import ScribeTask
25
26
  from codex.librarian.tasks import LibrarianShutdownTask, WakeCronTask
26
27
  from codex.librarian.watchdog.event_batcherd import WatchdogEventBatcherThread
@@ -63,6 +64,7 @@ class LibrarianDaemon(Process):
63
64
  startup_tasks = (
64
65
  JanitorAdoptOrphanFoldersTask(),
65
66
  WatchdogSyncTask(),
67
+ SearchIndexSyncTask(),
66
68
  )
67
69
 
68
70
  for task in startup_tasks:
@@ -359,3 +359,11 @@ ALL_COMIC_GROUP_FIELD_NAMES = (
359
359
  "story_arc_numbers",
360
360
  "folders",
361
361
  )
362
+
363
+ ##########
364
+ # Failed #
365
+ ##########
366
+ UPDATE_FIS = "update_fis"
367
+ CREATE_FIS = "create_fis"
368
+ DELETE_FI_PATHS = "delete_fi_paths"
369
+ BULK_UPDATE_FAILED_IMPORT_FIELDS = ("name", "stat", "updated_at")
@@ -174,7 +174,7 @@ class CreateForeignKeysCreateUpdateImporter(CreateForeignKeysFolderImporter):
174
174
  self.status_controller.update(status)
175
175
  key_args_map, update_args_map = MODEL_CREATE_ARGS_MAP[model]
176
176
  update_objs = []
177
- update_tuples = sorted(update_tuples, key=lambda t: str(t))
177
+ update_tuples = sorted(update_tuples, key=str)
178
178
  fts_update_pks = set()
179
179
  for values_tuple in update_tuples:
180
180
  key_args, update_args = self._get_create_update_args(
@@ -16,7 +16,9 @@ class DeletedCoversImporter(SearchIndexImporter):
16
16
 
17
17
  def bulk_covers_deleted(self, **kwargs):
18
18
  """Bulk delete comics found missing from the filesystem."""
19
- status = ImporterRemoveCoversStatus(0, len(self.task.covers_deleted))
19
+ status = ImporterRemoveCoversStatus(
20
+ 0, len(self.task.covers_deleted), log_success=False
21
+ )
20
22
  try:
21
23
  if not self.task.covers_deleted:
22
24
  return 0
@@ -0,0 +1 @@
1
+ """Failed imports."""
@@ -0,0 +1,97 @@
1
+ """Update and create failed imports."""
2
+
3
+ from django.db.models.functions import Now
4
+
5
+ from codex.librarian.scribe.importer.const import (
6
+ BULK_UPDATE_FAILED_IMPORT_FIELDS,
7
+ CREATE_FIS,
8
+ UPDATE_FIS,
9
+ )
10
+ from codex.librarian.scribe.importer.failed.query import FailedImportsQueryImporter
11
+ from codex.librarian.scribe.importer.statii.failed import (
12
+ ImporterFailedImportsCreateStatus,
13
+ ImporterFailedImportsUpdateStatus,
14
+ )
15
+ from codex.models import FailedImport
16
+
17
+
18
+ class FailedImportsCreateUpdateImporter(FailedImportsQueryImporter):
19
+ """Methods for failed imports."""
20
+
21
+ def _bulk_update_failed_imports(
22
+ self, status: ImporterFailedImportsUpdateStatus | None
23
+ ):
24
+ """Bulk update failed imports."""
25
+ update_failed_imports = self.metadata.pop(UPDATE_FIS, None)
26
+ try:
27
+ if not update_failed_imports:
28
+ return
29
+ if status:
30
+ self.status_controller.start(status)
31
+ update_failed_import_objs = FailedImport.objects.filter(
32
+ library=self.library, path__in=update_failed_imports.keys()
33
+ ).only(*BULK_UPDATE_FAILED_IMPORT_FIELDS)
34
+ if not update_failed_import_objs:
35
+ return
36
+ for fi in update_failed_import_objs:
37
+ try:
38
+ exc = update_failed_imports.pop(fi.path)
39
+ fi.set_reason(exc)
40
+ fi.updated_at = Now()
41
+ fi.presave()
42
+ except OSError as exc:
43
+ self.log.warning(f"Presaving failed import {fi.path}: {exc}")
44
+ except Exception:
45
+ self.log.exception(
46
+ f"Error preparing failed import update for {fi.path}"
47
+ )
48
+
49
+ FailedImport.objects.bulk_update(
50
+ update_failed_import_objs, fields=BULK_UPDATE_FAILED_IMPORT_FIELDS
51
+ )
52
+ count = len(update_failed_import_objs)
53
+ level = "INFO" if count else "DEBUG"
54
+ self.log.log(level, f"Updated {count} old failed imports.")
55
+ finally:
56
+ self.status_controller.finish(status)
57
+
58
+ def _bulk_create_failed_imports(
59
+ self, status: ImporterFailedImportsCreateStatus | None
60
+ ):
61
+ """Bulk create failed imports."""
62
+ create_failed_imports = self.metadata.pop(CREATE_FIS, None)
63
+ try:
64
+ if not create_failed_imports:
65
+ return 0
66
+ if status:
67
+ self.status_controller.start(status)
68
+ create_objs = []
69
+ for path, exc in create_failed_imports.items():
70
+ try:
71
+ fi = FailedImport(
72
+ library=self.library, path=path, parent_folder=None
73
+ )
74
+ fi.set_reason(exc)
75
+ create_objs.append(fi)
76
+ fi.presave()
77
+ except OSError:
78
+ self.log.warning(
79
+ f"Error preparing failed import create for {path}: {exc}"
80
+ )
81
+ except Exception:
82
+ self.log.exception(
83
+ f"Error preparing failed import create for {path}"
84
+ )
85
+ count = len(create_objs)
86
+ if count:
87
+ FailedImport.objects.bulk_create(
88
+ create_objs,
89
+ update_conflicts=True,
90
+ update_fields=BULK_UPDATE_FAILED_IMPORT_FIELDS,
91
+ unique_fields=FailedImport._meta.unique_together[0],
92
+ )
93
+ level = "INFO" if count else "DEBUG"
94
+ self.log.log(level, f"Added {count} comics to failed imports.")
95
+ finally:
96
+ self.status_controller.finish(status)
97
+ return count
@@ -0,0 +1,54 @@
1
+ """Update and create failed imports."""
2
+
3
+ from codex.librarian.scribe.importer.const import DELETE_FI_PATHS
4
+ from codex.librarian.scribe.importer.failed.create import (
5
+ FailedImportsCreateUpdateImporter,
6
+ )
7
+ from codex.librarian.scribe.importer.statii.failed import (
8
+ ImporterFailedImportsDeleteStatus,
9
+ )
10
+ from codex.models import FailedImport
11
+
12
+
13
+ class FailedImportsImporter(FailedImportsCreateUpdateImporter):
14
+ """Methods for failed imports."""
15
+
16
+ def _bulk_cleanup_failed_imports(
17
+ self, status: ImporterFailedImportsDeleteStatus | None
18
+ ):
19
+ """Remove FailedImport objects that have since succeeded."""
20
+ delete_failed_imports_paths = self.metadata.pop(DELETE_FI_PATHS, None)
21
+ try:
22
+ if not delete_failed_imports_paths:
23
+ return 0
24
+ if status:
25
+ self.status_controller.start(status)
26
+ # Cleanup FailedImports that were actually successful
27
+ qs = FailedImport.objects.filter(library=self.library).filter(
28
+ path__in=delete_failed_imports_paths
29
+ )
30
+ count, _ = qs.delete()
31
+ level = "INFO" if count else "DEBUG"
32
+ self.log.log(
33
+ level, f"Cleaned up {count} failed imports from {self.library.path}"
34
+ )
35
+ return count
36
+ finally:
37
+ self.status_controller.finish(status)
38
+
39
+ def fail_imports(self):
40
+ """Handle failed imports."""
41
+ created_count = 0
42
+ update_status = create_status = delete_status = None
43
+ try:
44
+ update_status, create_status, delete_status = self._query_failed_imports()
45
+ self._bulk_update_failed_imports(update_status)
46
+ created_count += self._bulk_create_failed_imports(create_status)
47
+ self._bulk_cleanup_failed_imports(delete_status)
48
+ except Exception:
49
+ self.log.exception("Processing failed imports")
50
+ finally:
51
+ self.status_controller.finish_many(
52
+ (update_status, create_status, delete_status)
53
+ )
54
+ self.counts.failed_imports = created_count
@@ -0,0 +1,103 @@
1
+ """Update and create failed imports."""
2
+
3
+ from pathlib import Path
4
+
5
+ from codex.librarian.scribe.importer.const import (
6
+ CREATE_FIS,
7
+ DELETE_FI_PATHS,
8
+ FIS,
9
+ UPDATE_FIS,
10
+ )
11
+ from codex.librarian.scribe.importer.delete import DeletedImporter
12
+ from codex.librarian.scribe.importer.statii.failed import (
13
+ ImporterFailedImportsCreateStatus,
14
+ ImporterFailedImportsDeleteStatus,
15
+ ImporterFailedImportsQueryStatus,
16
+ ImporterFailedImportsUpdateStatus,
17
+ )
18
+ from codex.models import Comic, FailedImport
19
+
20
+
21
+ class FailedImportsQueryImporter(DeletedImporter):
22
+ """Methods for failed imports."""
23
+
24
+ def _query_failed_import_deletes(self, existing_failed_import_paths, new_fis_paths):
25
+ """Calculate Deletes."""
26
+ untouched_failed_import_paths = existing_failed_import_paths - frozenset(
27
+ new_fis_paths
28
+ )
29
+
30
+ qs = Comic.objects.filter(
31
+ library=self.library, path__in=untouched_failed_import_paths
32
+ ).only("path")
33
+ succeeded_failed_imports = frozenset(qs.values_list("path", flat=True))
34
+
35
+ possibly_missing_failed_import_paths = (
36
+ untouched_failed_import_paths - succeeded_failed_imports
37
+ )
38
+ missing_failed_import_paths = set()
39
+ for path in possibly_missing_failed_import_paths:
40
+ name = path.casefold()
41
+ # Case sensitive matching. exists() and is_file() are case insensitive.
42
+ # This will fail if there is a parent directory case mismatch.
43
+ # Rather than do a recursive solution, add it to missing if it fails.
44
+ try:
45
+ for path_obj in Path(path).parent.iterdir():
46
+ if path_obj.name.casefold() == name:
47
+ break
48
+ else:
49
+ missing_failed_import_paths.add(path)
50
+ except FileNotFoundError:
51
+ missing_failed_import_paths.add(path)
52
+
53
+ return succeeded_failed_imports | missing_failed_import_paths
54
+
55
+ def _query_failed_imports(
56
+ self,
57
+ ) -> tuple[
58
+ ImporterFailedImportsUpdateStatus | None,
59
+ ImporterFailedImportsCreateStatus | None,
60
+ ImporterFailedImportsDeleteStatus | None,
61
+ ]:
62
+ """Determine what to do with failed imports."""
63
+ status = ImporterFailedImportsQueryStatus(0)
64
+ update_status = create_status = delete_status = None
65
+ try:
66
+ self.status_controller.start(status)
67
+ # Calculate creates and updates
68
+ fis = self.metadata.pop(FIS, {})
69
+ existing_failed_import_paths = set(
70
+ FailedImport.objects.filter(library=self.library).values_list(
71
+ "path", flat=True
72
+ )
73
+ )
74
+ status.total = len(fis) + len(existing_failed_import_paths)
75
+ self.status_controller.update(status)
76
+ self.metadata[UPDATE_FIS] = {}
77
+ self.metadata[CREATE_FIS] = {}
78
+ for path, exc in fis.items():
79
+ if path in existing_failed_import_paths:
80
+ self.metadata[UPDATE_FIS][path] = exc
81
+ else:
82
+ self.metadata[CREATE_FIS][path] = exc
83
+ status.increment_complete()
84
+ self.status_controller.update(status)
85
+ if num_update := len(self.metadata[UPDATE_FIS]):
86
+ update_status = ImporterFailedImportsUpdateStatus(0, num_update)
87
+ self.status_controller.update(update_status)
88
+ if num_create := len(self.metadata[CREATE_FIS]):
89
+ create_status = ImporterFailedImportsCreateStatus(0, num_create)
90
+ self.status_controller.update(create_status)
91
+
92
+ if DELETE_FI_PATHS not in self.metadata:
93
+ self.metadata[DELETE_FI_PATHS] = set()
94
+ self.metadata[DELETE_FI_PATHS] |= self._query_failed_import_deletes(
95
+ existing_failed_import_paths, fis.keys()
96
+ )
97
+ status.increment_complete(len(existing_failed_import_paths))
98
+ if num_delete := len(self.metadata[DELETE_FI_PATHS]):
99
+ delete_status = ImporterFailedImportsDeleteStatus(0, num_delete)
100
+ self.status_controller.update(delete_status)
101
+ finally:
102
+ self.status_controller.finish(status, notify=True)
103
+ return update_status, create_status, delete_status
@@ -38,7 +38,7 @@ from codex.librarian.scribe.importer.statii.query import (
38
38
  )
39
39
  from codex.librarian.scribe.importer.statii.read import (
40
40
  ImporterAggregateStatus,
41
- ImporterReadStatus,
41
+ ImporterReadComicsStatus,
42
42
  )
43
43
  from codex.librarian.scribe.importer.statii.search import (
44
44
  ImporterFTSCreateStatus,
@@ -214,7 +214,7 @@ class InitImporter(WorkerStatusMixin):
214
214
  """Initialize librarian statuses for modified or created ops."""
215
215
  total_paths = len(self.task.files_modified) + len(self.task.files_created)
216
216
  status_list += [
217
- ImporterReadStatus(0, total_paths, subtitle=path),
217
+ ImporterReadComicsStatus(0, total_paths, subtitle=path),
218
218
  ImporterAggregateStatus(0, total_paths, subtitle=path),
219
219
  ImporterQueryMissingTagsStatus(subtitle=path),
220
220
  ImporterQueryComicUpdatesStatus(subtitle=path),
@@ -6,7 +6,7 @@ from codex.librarian.scribe.importer.const import (
6
6
  CLASS_CUSTOM_COVER_GROUP_MAP,
7
7
  LINK_COVER_PKS,
8
8
  )
9
- from codex.librarian.scribe.importer.failed_imports import FailedImportsImporter
9
+ from codex.librarian.scribe.importer.failed.failed import FailedImportsImporter
10
10
  from codex.librarian.scribe.importer.statii.link import ImporterLinkCoversStatus
11
11
  from codex.models import CustomCover, Folder
12
12
 
@@ -18,8 +18,10 @@ from codex.librarian.scribe.importer.const import (
18
18
  QUERY_MODELS,
19
19
  )
20
20
  from codex.librarian.scribe.importer.read.folders import AggregatePathMetadataImporter
21
+ from codex.librarian.scribe.importer.statii.failed import (
22
+ ImporterFailedImportsQueryStatus,
23
+ )
21
24
  from codex.librarian.scribe.importer.statii.read import ImporterAggregateStatus
22
- from codex.librarian.scribe.importer.status import ImporterFailedImportsStatus
23
25
 
24
26
  _UNUSED_COMICBOX_FIELDS = (
25
27
  "alternate_images",
@@ -102,7 +104,7 @@ class AggregateMetadataImporter(AggregatePathMetadataImporter):
102
104
  fis = self.metadata[FIS].keys()
103
105
 
104
106
  # Set statii
105
- fi_status = ImporterFailedImportsStatus(0, len(fis))
107
+ fi_status = ImporterFailedImportsQueryStatus(0, len(fis))
106
108
  self.status_controller.update(fi_status, notify=False)
107
109
  self.status_controller.finish(status)
108
110
  return status.complete
@@ -21,7 +21,7 @@ class SearchIndexImporter(SearchIndexPrepareImporter):
21
21
  indexer = SearchIndexer(
22
22
  self.log, self.librarian_queue, self.db_write_lock, event=self.abort_event
23
23
  )
24
- return indexer.remove_stale_records()
24
+ return indexer.remove_stale_records(log_success=False)
25
25
 
26
26
  def full_text_search(self):
27
27
  """Sync the fts index with the imported database."""
@@ -22,6 +22,7 @@ from codex.librarian.scribe.importer.search.sync_m2m import (
22
22
  )
23
23
  from codex.librarian.scribe.importer.statii.search import (
24
24
  ImporterFTSCreateStatus,
25
+ ImporterFTSStatus,
25
26
  ImporterFTSUpdateStatus,
26
27
  )
27
28
  from codex.librarian.status import Status
@@ -128,7 +129,7 @@ class SearchIndexCreateUpdateImporter(SearchIndexSyncManyToManyImporter):
128
129
  *,
129
130
  create: bool,
130
131
  ):
131
- if self.abort_event.is_set():
132
+ if not obj_list or self.abort_event.is_set():
132
133
  return
133
134
  verb = "create" if create else "update"
134
135
  verbing = (verb[:-1] + "ing").capitalize()
@@ -144,10 +145,40 @@ class SearchIndexCreateUpdateImporter(SearchIndexSyncManyToManyImporter):
144
145
 
145
146
  def _update_search_index_operate_get_status(
146
147
  self, total_entries: int, *, create: bool
147
- ):
148
+ ) -> ImporterFTSStatus:
148
149
  status_class = ImporterFTSCreateStatus if create else ImporterFTSUpdateStatus
149
150
  return status_class(total=total_entries)
150
151
 
152
+ def _update_search_index_operate_create(
153
+ self, obj_list: list, status: ImporterFTSStatus
154
+ ):
155
+ entries = self.metadata.pop(FTS_CREATE, {})
156
+ pks = tuple(entries.keys())
157
+ for pk in pks:
158
+ if self.abort_event.is_set():
159
+ return ()
160
+
161
+ entry = entries.pop(pk)
162
+ self._create_comicfts_entry(pk, entry, obj_list, status)
163
+ return pks
164
+
165
+ def _update_search_index_operate_update(
166
+ self, obj_list: list, status: ImporterFTSStatus
167
+ ):
168
+ if pks := tuple(self.metadata.get(FTS_UPDATE, {}).keys()):
169
+ comicftss = ComicFTS.objects.filter(comic_id__in=pks)
170
+ for comicfts in comicftss:
171
+ if self.abort_event.is_set():
172
+ return ()
173
+ self._update_comicfts_entry(comicfts, obj_list, status)
174
+ if self.metadata[FTS_UPDATE]:
175
+ # If updates not popped, turn them into creates.
176
+ if FTS_CREATE not in self.metadata:
177
+ self.metadata[FTS_CREATE] = {}
178
+ self.metadata[FTS_CREATE].update(self.metadata[FTS_UPDATE])
179
+ self.metadata.pop(FTS_UPDATE)
180
+ return pks
181
+
151
182
  def _update_search_index_operate(self, *, create: bool) -> tuple[int, ...]:
152
183
  key = FTS_CREATE if create else FTS_UPDATE
153
184
  total_entries = len(self.metadata.get(key, {}))
@@ -161,27 +192,22 @@ class SearchIndexCreateUpdateImporter(SearchIndexSyncManyToManyImporter):
161
192
  self.log.debug(f"No search entries to {verb}.")
162
193
  return updated_pks
163
194
  self.status_controller.start(status)
195
+ verbing = "creating" if create else "updating"
196
+ self.log.debug(
197
+ f"Preparing {total_entries} comics for search index {verbing}..."
198
+ )
164
199
 
165
200
  obj_list = []
166
201
  if create:
167
- entries = self.metadata.pop(FTS_CREATE, {})
168
- pks = tuple(entries.keys())
169
- for pk in pks:
170
- if self.abort_event.is_set():
171
- return updated_pks
172
- entry = entries.pop(pk)
173
- self._create_comicfts_entry(pk, entry, obj_list, status)
174
- updated_pks = pks
202
+ updated_pks = self._update_search_index_operate_create(obj_list, status)
175
203
  else:
176
- comic_ids = tuple(self.metadata[FTS_UPDATE].keys())
177
- comicftss = ComicFTS.objects.filter(comic_id__in=comic_ids)
178
- for comicfts in comicftss:
179
- if self.abort_event.is_set():
180
- return tuple(updated_pks)
181
- self._update_comicfts_entry(comicfts, obj_list, status)
182
- self.metadata.pop(FTS_UPDATE)
183
-
184
- self.log.debug(f"Preparing {total_entries} comics for search indexing...")
204
+ updated_pks = self._update_search_index_operate_update(obj_list, status)
205
+ self.log.debug(
206
+ f"Prepared {len(obj_list)} comics for search index {verbing}..."
207
+ )
208
+ if self.abort_event.is_set():
209
+ return updated_pks
210
+
185
211
  self._update_search_index_create_or_update(
186
212
  obj_list,
187
213
  status,
@@ -2,6 +2,7 @@
2
2
 
3
3
  from codex.librarian.scribe.importer.statii.create import CREATE_STATII
4
4
  from codex.librarian.scribe.importer.statii.delete import REMOVE_STATII
5
+ from codex.librarian.scribe.importer.statii.failed import FAILED_IMPORTS_STATII
5
6
  from codex.librarian.scribe.importer.statii.link import LINK_STATII
6
7
  from codex.librarian.scribe.importer.statii.moved import MOVED_STATII
7
8
  from codex.librarian.scribe.importer.statii.query import QUERY_STATII
@@ -16,4 +17,5 @@ IMPORTER_STATII = (
16
17
  *QUERY_STATII,
17
18
  *READ_STATII,
18
19
  *IMPORTER_SEARCH_INDEX_STATII,
20
+ *FAILED_IMPORTS_STATII,
19
21
  )
@@ -0,0 +1,50 @@
1
+ """Importer Failed Imports Sattii."""
2
+
3
+ from abc import ABC
4
+
5
+ from codex.librarian.scribe.importer.status import ImporterStatus
6
+
7
+
8
+ class ImporterFailedImportStatus(ImporterStatus, ABC):
9
+ """Importer Failed Imports Statii."""
10
+
11
+ ITEM_NAME = "failed imports"
12
+
13
+
14
+ class ImporterFailedImportsQueryStatus(ImporterFailedImportStatus, ABC):
15
+ """Importer Failed Imports Query Statii."""
16
+
17
+ CODE = "IFQ"
18
+ VERB = "Query"
19
+ _verbed = "Queried"
20
+
21
+
22
+ class ImporterFailedImportsUpdateStatus(ImporterFailedImportStatus, ABC):
23
+ """Importer Failed Imports Update Statii."""
24
+
25
+ CODE = "IFU"
26
+ VERB = "Update"
27
+
28
+
29
+ class ImporterFailedImportsCreateStatus(ImporterFailedImportStatus, ABC):
30
+ """Importer Failed Imports Create Statii."""
31
+
32
+ CODE = "IFC"
33
+ VERB = "Mark Failed"
34
+ _verbed = "Marked Failed"
35
+
36
+
37
+ class ImporterFailedImportsDeleteStatus(ImporterFailedImportStatus, ABC):
38
+ """Importer Failed Imports Create Statii."""
39
+
40
+ CODE = "IFD"
41
+ VERB = "Clean up"
42
+ _verbed = "Cleaned up"
43
+
44
+
45
+ FAILED_IMPORTS_STATII = (
46
+ ImporterFailedImportsQueryStatus,
47
+ ImporterFailedImportsUpdateStatus,
48
+ ImporterFailedImportsCreateStatus,
49
+ ImporterFailedImportsDeleteStatus,
50
+ )
@@ -7,15 +7,3 @@ from codex.librarian.scribe.status import ScribeStatus
7
7
 
8
8
  class ImporterStatus(ScribeStatus, ABC):
9
9
  """Importer Status."""
10
-
11
-
12
- class ImporterFailedImportsStatus(ImporterStatus):
13
- """Importer Failed Imports Status."""
14
-
15
- CODE = "IFI"
16
- VERB = "Mark"
17
- _verbed = "Marked"
18
- ITEM_NAME = "failed imports"
19
-
20
-
21
- FAILED_IMPORTS_STATII = (ImporterFailedImportsStatus,)
@@ -13,6 +13,7 @@ from codex.librarian.scribe.janitor.status import (
13
13
  JanitorCodexLatestVersionStatus,
14
14
  JanitorDBBackupStatus,
15
15
  JanitorDBFKIntegrityStatus,
16
+ JanitorDBFTSIntegrityStatus,
16
17
  JanitorDBIntegrityStatus,
17
18
  JanitorDBOptimizeStatus,
18
19
  )
@@ -36,28 +37,34 @@ from codex.librarian.scribe.janitor.update import JanitorCodexUpdate
36
37
  from codex.librarian.scribe.search.status import (
37
38
  SearchIndexCleanStatus,
38
39
  SearchIndexOptimizeStatus,
40
+ SearchIndexSyncCreateStatus,
41
+ SearchIndexSyncUpdateStatus,
39
42
  )
40
43
  from codex.librarian.scribe.search.tasks import (
41
44
  SearchIndexOptimizeTask,
45
+ SearchIndexSyncTask,
42
46
  )
43
47
  from codex.models import Timestamp
44
48
 
45
49
  _JANITOR_STATII = (
46
50
  JanitorCodexLatestVersionStatus,
51
+ JanitorAdoptOrphanFoldersStatus,
52
+ ImporterMoveFoldersStatus,
47
53
  JanitorDBFKIntegrityStatus,
48
54
  JanitorDBIntegrityStatus,
49
- JanitorCleanupCoversStatus,
55
+ JanitorDBFTSIntegrityStatus,
50
56
  JanitorCleanupTagsStatus,
57
+ JanitorCleanupCoversStatus,
51
58
  JanitorCleanupSessionsStatus,
52
59
  JanitorCleanupBookmarksStatus,
60
+ SearchIndexCleanStatus,
61
+ SearchIndexSyncUpdateStatus,
62
+ SearchIndexSyncCreateStatus,
63
+ SearchIndexOptimizeStatus,
53
64
  JanitorDBOptimizeStatus,
54
65
  JanitorDBBackupStatus,
55
66
  FindOrphanCoversStatus,
56
67
  RemoveCoversStatus,
57
- JanitorAdoptOrphanFoldersStatus,
58
- ImporterMoveFoldersStatus,
59
- SearchIndexCleanStatus,
60
- SearchIndexOptimizeStatus,
61
68
  )
62
69
 
63
70
 
@@ -78,6 +85,7 @@ class Janitor(JanitorCodexUpdate):
78
85
  JanitorCleanCoversTask(),
79
86
  JanitorCleanupSessionsTask(),
80
87
  JanitorCleanupBookmarksTask(),
88
+ SearchIndexSyncTask(),
81
89
  SearchIndexOptimizeTask(),
82
90
  JanitorVacuumTask(),
83
91
  JanitorBackupTask(),