codex 1.8.0a2__py3-none-any.whl → 1.8.0a3__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 +100 -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 +20 -9
  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 +41 -20
  29. codex/librarian/watchdog/const.py +30 -1
  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-DOvv8UEO.e3653c1670c8.js} +1 -1
  36. codex/static_root/assets/VCheckbox-DOvv8UEO.e3653c1670c8.js.br +0 -0
  37. codex/static_root/assets/VCheckbox-DOvv8UEO.e3653c1670c8.js.gz +0 -0
  38. codex/static_root/assets/{VCheckbox-DSndl51k.js → VCheckbox-DOvv8UEO.js} +1 -1
  39. codex/static_root/assets/VCheckbox-DOvv8UEO.js.br +0 -0
  40. codex/static_root/assets/VCheckbox-DOvv8UEO.js.gz +0 -0
  41. codex/static_root/assets/{VCheckboxBtn-Bu2Pf64q.d7463473d7a2.js → VCheckboxBtn-BeZZDumo.59731a32657e.js} +1 -1
  42. codex/static_root/assets/VCheckboxBtn-BeZZDumo.59731a32657e.js.br +0 -0
  43. codex/static_root/assets/VCheckboxBtn-BeZZDumo.59731a32657e.js.gz +0 -0
  44. codex/static_root/assets/{VCheckboxBtn-Bu2Pf64q.js → VCheckboxBtn-BeZZDumo.js} +1 -1
  45. codex/static_root/assets/VCheckboxBtn-BeZZDumo.js.br +0 -0
  46. codex/static_root/assets/VCheckboxBtn-BeZZDumo.js.gz +0 -0
  47. codex/static_root/assets/{VCombobox-Uogv6Ckp.9f900e703605.js → VCombobox-BRJRW2px.369544360b22.js} +1 -1
  48. codex/static_root/assets/VCombobox-BRJRW2px.369544360b22.js.br +0 -0
  49. codex/static_root/assets/VCombobox-BRJRW2px.369544360b22.js.gz +0 -0
  50. codex/static_root/assets/{VCombobox-Uogv6Ckp.js → VCombobox-BRJRW2px.js} +1 -1
  51. codex/static_root/assets/VCombobox-BRJRW2px.js.br +0 -0
  52. codex/static_root/assets/VCombobox-BRJRW2px.js.gz +0 -0
  53. codex/static_root/assets/{VDialog-BzaGu1HN.34f52763c3f8.js → VDialog-D_vkvatj.83e078fa850c.js} +1 -1
  54. codex/static_root/assets/VDialog-D_vkvatj.83e078fa850c.js.br +0 -0
  55. codex/static_root/assets/VDialog-D_vkvatj.83e078fa850c.js.gz +0 -0
  56. codex/static_root/assets/{VDialog-BzaGu1HN.js → VDialog-D_vkvatj.js} +1 -1
  57. codex/static_root/assets/VDialog-D_vkvatj.js.br +0 -0
  58. codex/static_root/assets/VDialog-D_vkvatj.js.gz +0 -0
  59. codex/static_root/assets/{VDivider-C3ikm0Ko.4938e9ced53e.js → VDivider-BH2Oj58Z.83d2c907faff.js} +1 -1
  60. codex/static_root/assets/VDivider-BH2Oj58Z.83d2c907faff.js.br +0 -0
  61. codex/static_root/assets/VDivider-BH2Oj58Z.83d2c907faff.js.gz +0 -0
  62. codex/static_root/assets/{VDivider-C3ikm0Ko.js → VDivider-BH2Oj58Z.js} +1 -1
  63. codex/static_root/assets/VDivider-BH2Oj58Z.js.br +0 -0
  64. codex/static_root/assets/VDivider-BH2Oj58Z.js.gz +0 -0
  65. codex/static_root/assets/{VExpansionPanels-AmsInZN0.5cb7c833de3d.js → VExpansionPanels-Ccv4gBFD.ed063db2e518.js} +1 -1
  66. codex/static_root/assets/VExpansionPanels-Ccv4gBFD.ed063db2e518.js.br +0 -0
  67. codex/static_root/assets/VExpansionPanels-Ccv4gBFD.ed063db2e518.js.gz +0 -0
  68. codex/static_root/assets/{VExpansionPanels-AmsInZN0.js → VExpansionPanels-Ccv4gBFD.js} +1 -1
  69. codex/static_root/assets/VExpansionPanels-Ccv4gBFD.js.br +0 -0
  70. codex/static_root/assets/VExpansionPanels-Ccv4gBFD.js.gz +0 -0
  71. codex/static_root/assets/{VForm-CyCdgusw.c737973a1e85.js → VForm-S5eiHGJ0.d304a07dc6d1.js} +1 -1
  72. codex/static_root/assets/VForm-S5eiHGJ0.d304a07dc6d1.js.br +0 -0
  73. codex/static_root/assets/VForm-S5eiHGJ0.d304a07dc6d1.js.gz +0 -0
  74. codex/static_root/assets/{VForm-CyCdgusw.js → VForm-S5eiHGJ0.js} +1 -1
  75. codex/static_root/assets/VForm-S5eiHGJ0.js.br +0 -0
  76. codex/static_root/assets/VForm-S5eiHGJ0.js.gz +0 -0
  77. codex/static_root/assets/{VRadioGroup-BF0Xjrzi.e54d2bf41bb2.js → VRadioGroup-CyCYk3Z_.4309dbf0173c.js} +1 -1
  78. codex/static_root/assets/VRadioGroup-CyCYk3Z_.4309dbf0173c.js.br +0 -0
  79. codex/static_root/assets/VRadioGroup-CyCYk3Z_.4309dbf0173c.js.gz +0 -0
  80. codex/static_root/assets/{VRadioGroup-BF0Xjrzi.js → VRadioGroup-CyCYk3Z_.js} +1 -1
  81. codex/static_root/assets/VRadioGroup-CyCYk3Z_.js.br +0 -0
  82. codex/static_root/assets/VRadioGroup-CyCYk3Z_.js.gz +0 -0
  83. codex/static_root/assets/{VSelect-Dv50OIkN.js → VSelect-BOhtkCV1.057479737b7f.js} +1 -1
  84. codex/static_root/assets/VSelect-BOhtkCV1.057479737b7f.js.br +0 -0
  85. codex/static_root/assets/VSelect-BOhtkCV1.057479737b7f.js.gz +0 -0
  86. codex/static_root/assets/{VSelect-Dv50OIkN.390adb1fe7fa.js → VSelect-BOhtkCV1.js} +1 -1
  87. codex/static_root/assets/VSelect-BOhtkCV1.js.br +0 -0
  88. codex/static_root/assets/VSelect-BOhtkCV1.js.gz +0 -0
  89. codex/static_root/assets/{VSelectionControl-DbKYScD5.js → VSelectionControl-CmXEFw20.e256f0d0f97d.js} +1 -1
  90. codex/static_root/assets/VSelectionControl-CmXEFw20.e256f0d0f97d.js.br +0 -0
  91. codex/static_root/assets/VSelectionControl-CmXEFw20.e256f0d0f97d.js.gz +0 -0
  92. codex/static_root/assets/{VSelectionControl-DbKYScD5.8d2ab1ebe546.js → VSelectionControl-CmXEFw20.js} +1 -1
  93. codex/static_root/assets/VSelectionControl-CmXEFw20.js.br +0 -0
  94. codex/static_root/assets/VSelectionControl-CmXEFw20.js.gz +0 -0
  95. codex/static_root/assets/{VTable-BmOfHc7J.b2e1311009d1.js → VTable-BDxzw_rH.24ce227e6076.js} +1 -1
  96. codex/static_root/assets/VTable-BDxzw_rH.24ce227e6076.js.br +0 -0
  97. codex/static_root/assets/VTable-BDxzw_rH.24ce227e6076.js.gz +0 -0
  98. codex/static_root/assets/{VTable-BmOfHc7J.js → VTable-BDxzw_rH.js} +1 -1
  99. codex/static_root/assets/VTable-BDxzw_rH.js.br +0 -0
  100. codex/static_root/assets/VTable-BDxzw_rH.js.gz +0 -0
  101. codex/static_root/assets/{VWindowItem-BLEDgagD.4b67c4a63c59.js → VWindowItem-CuDwxsEy.4d68002250ae.js} +1 -1
  102. codex/static_root/assets/VWindowItem-CuDwxsEy.4d68002250ae.js.br +0 -0
  103. codex/static_root/assets/VWindowItem-CuDwxsEy.4d68002250ae.js.gz +0 -0
  104. codex/static_root/assets/{VWindowItem-BLEDgagD.js → VWindowItem-CuDwxsEy.js} +1 -1
  105. codex/static_root/assets/VWindowItem-CuDwxsEy.js.br +0 -0
  106. codex/static_root/assets/VWindowItem-CuDwxsEy.js.gz +0 -0
  107. codex/static_root/assets/{admin-kjMoKlqD.55a1dd908124.js → admin-BZQmoFts.d8e6303f8aee.js} +1 -1
  108. codex/static_root/assets/admin-BZQmoFts.d8e6303f8aee.js.br +0 -0
  109. codex/static_root/assets/admin-BZQmoFts.d8e6303f8aee.js.gz +0 -0
  110. codex/static_root/assets/{admin-kjMoKlqD.js → admin-BZQmoFts.js} +1 -1
  111. codex/static_root/assets/admin-BZQmoFts.js.br +0 -0
  112. codex/static_root/assets/admin-BZQmoFts.js.gz +0 -0
  113. codex/static_root/assets/{admin-Bv40vYZw.8179e1ece835.js → admin-U3AawSbo.f171316d0a93.js} +1 -1
  114. codex/static_root/assets/admin-U3AawSbo.f171316d0a93.js.br +0 -0
  115. codex/static_root/assets/admin-U3AawSbo.f171316d0a93.js.gz +0 -0
  116. codex/static_root/assets/{admin-Bv40vYZw.js → admin-U3AawSbo.js} +1 -1
  117. codex/static_root/assets/admin-U3AawSbo.js.br +0 -0
  118. codex/static_root/assets/admin-U3AawSbo.js.gz +0 -0
  119. codex/static_root/assets/admin-menu-D9RDVBlr.3b62ee7a8b95.js +1 -0
  120. codex/static_root/assets/admin-menu-D9RDVBlr.3b62ee7a8b95.js.br +0 -0
  121. codex/static_root/assets/admin-menu-D9RDVBlr.3b62ee7a8b95.js.gz +0 -0
  122. codex/static_root/assets/admin-menu-D9RDVBlr.js +1 -0
  123. codex/static_root/assets/admin-menu-D9RDVBlr.js.br +0 -0
  124. codex/static_root/assets/admin-menu-D9RDVBlr.js.gz +0 -0
  125. codex/static_root/assets/{admin-settings-button-progress-RfwaqLl2.4cdd37d0dd16.js → admin-settings-button-progress-DwWq9uM1.fbacafc0db08.js} +1 -1
  126. codex/static_root/assets/admin-settings-button-progress-DwWq9uM1.fbacafc0db08.js.br +0 -0
  127. codex/static_root/assets/admin-settings-button-progress-DwWq9uM1.fbacafc0db08.js.gz +0 -0
  128. codex/static_root/assets/{admin-settings-button-progress-RfwaqLl2.js → admin-settings-button-progress-DwWq9uM1.js} +1 -1
  129. codex/static_root/assets/admin-settings-button-progress-DwWq9uM1.js.br +0 -0
  130. codex/static_root/assets/admin-settings-button-progress-DwWq9uM1.js.gz +0 -0
  131. codex/static_root/assets/{browser-plYso4v5.js → browser-DFM_JsAK.bffd4eb259d8.js} +1 -1
  132. codex/static_root/assets/browser-DFM_JsAK.bffd4eb259d8.js.br +0 -0
  133. codex/static_root/assets/browser-DFM_JsAK.bffd4eb259d8.js.gz +0 -0
  134. codex/static_root/assets/{browser-plYso4v5.87ef04b44d37.js → browser-DFM_JsAK.js} +1 -1
  135. codex/static_root/assets/browser-DFM_JsAK.js.br +0 -0
  136. codex/static_root/assets/browser-DFM_JsAK.js.gz +0 -0
  137. codex/static_root/assets/{change-password-dialog-DyhQwNv1.26383853ccc0.js → change-password-dialog-yLNkzMp9.50da9f352709.js} +1 -1
  138. codex/static_root/assets/change-password-dialog-yLNkzMp9.50da9f352709.js.br +0 -0
  139. codex/static_root/assets/change-password-dialog-yLNkzMp9.50da9f352709.js.gz +0 -0
  140. codex/static_root/assets/{change-password-dialog-DyhQwNv1.js → change-password-dialog-yLNkzMp9.js} +1 -1
  141. codex/static_root/assets/change-password-dialog-yLNkzMp9.js.br +0 -0
  142. codex/static_root/assets/change-password-dialog-yLNkzMp9.js.gz +0 -0
  143. codex/static_root/assets/{confirm-dialog-B7ndwV5M.d1f0728d4bd0.js → confirm-dialog-q6RAb_qs.120460c84883.js} +1 -1
  144. codex/static_root/assets/confirm-dialog-q6RAb_qs.120460c84883.js.br +0 -0
  145. codex/static_root/assets/confirm-dialog-q6RAb_qs.120460c84883.js.gz +0 -0
  146. codex/static_root/assets/{confirm-dialog-B7ndwV5M.js → confirm-dialog-q6RAb_qs.js} +1 -1
  147. codex/static_root/assets/confirm-dialog-q6RAb_qs.js.br +0 -0
  148. codex/static_root/assets/confirm-dialog-q6RAb_qs.js.gz +0 -0
  149. codex/static_root/assets/{datetime-column-DANpNGGe.13985ff7d484.js → datetime-column-HJ5dvW99.ba0a30b3fc0d.js} +1 -1
  150. codex/static_root/assets/datetime-column-HJ5dvW99.ba0a30b3fc0d.js.br +0 -0
  151. codex/static_root/assets/datetime-column-HJ5dvW99.ba0a30b3fc0d.js.gz +0 -0
  152. codex/static_root/assets/{datetime-column-DANpNGGe.js → datetime-column-HJ5dvW99.js} +1 -1
  153. codex/static_root/assets/datetime-column-HJ5dvW99.js.br +0 -0
  154. codex/static_root/assets/datetime-column-HJ5dvW99.js.gz +0 -0
  155. codex/static_root/assets/{filter-Dhe8cVmt.ad92d3b618e3.js → filter-r_zFj-tS.161a85ef1860.js} +1 -1
  156. codex/static_root/assets/filter-r_zFj-tS.161a85ef1860.js.br +0 -0
  157. codex/static_root/assets/filter-r_zFj-tS.161a85ef1860.js.gz +0 -0
  158. codex/static_root/assets/{filter-Dhe8cVmt.js → filter-r_zFj-tS.js} +1 -1
  159. codex/static_root/assets/filter-r_zFj-tS.js.br +0 -0
  160. codex/static_root/assets/filter-r_zFj-tS.js.gz +0 -0
  161. codex/static_root/assets/{flag-tab-BZ9S7U8D.0b814b215567.js → flag-tab-D0Z4uhsg.06e720e71319.js} +1 -1
  162. codex/static_root/assets/flag-tab-D0Z4uhsg.06e720e71319.js.br +0 -0
  163. codex/static_root/assets/flag-tab-D0Z4uhsg.06e720e71319.js.gz +0 -0
  164. codex/static_root/assets/{flag-tab-BZ9S7U8D.js → flag-tab-D0Z4uhsg.js} +1 -1
  165. codex/static_root/assets/flag-tab-D0Z4uhsg.js.br +0 -0
  166. codex/static_root/assets/flag-tab-D0Z4uhsg.js.gz +0 -0
  167. codex/static_root/assets/{forwardRefs-Z0d4Mnc7.js → forwardRefs-Nj5UEeg5.50a55d7d8b68.js} +1 -1
  168. codex/static_root/assets/forwardRefs-Nj5UEeg5.50a55d7d8b68.js.br +0 -0
  169. codex/static_root/assets/forwardRefs-Nj5UEeg5.50a55d7d8b68.js.gz +0 -0
  170. codex/static_root/assets/{forwardRefs-Z0d4Mnc7.deb4e7a1b8b5.js → forwardRefs-Nj5UEeg5.js} +1 -1
  171. codex/static_root/assets/forwardRefs-Nj5UEeg5.js.br +0 -0
  172. codex/static_root/assets/forwardRefs-Nj5UEeg5.js.gz +0 -0
  173. codex/static_root/assets/{group-tab-B0ASBB3_.8e10b90ff052.js → group-tab-lamd9pcq.604a78bd4e4f.js} +1 -1
  174. codex/static_root/assets/group-tab-lamd9pcq.604a78bd4e4f.js.br +0 -0
  175. codex/static_root/assets/group-tab-lamd9pcq.604a78bd4e4f.js.gz +0 -0
  176. codex/static_root/assets/{group-tab-B0ASBB3_.js → group-tab-lamd9pcq.js} +1 -1
  177. codex/static_root/assets/group-tab-lamd9pcq.js.br +0 -0
  178. codex/static_root/assets/group-tab-lamd9pcq.js.gz +0 -0
  179. codex/static_root/assets/{http-error-BP-mMZsK.72c4d00b40d2.js → http-error-DRYA5ir1.46f4babacf15.js} +1 -1
  180. codex/static_root/assets/http-error-DRYA5ir1.46f4babacf15.js.br +0 -0
  181. codex/static_root/assets/http-error-DRYA5ir1.46f4babacf15.js.gz +0 -0
  182. codex/static_root/assets/{http-error-BP-mMZsK.js → http-error-DRYA5ir1.js} +1 -1
  183. codex/static_root/assets/http-error-DRYA5ir1.js.br +0 -0
  184. codex/static_root/assets/http-error-DRYA5ir1.js.gz +0 -0
  185. codex/static_root/assets/{index-Cu9nQXJD.49795921eada.js → index-Cl7tPJIx.c0a239cf7069.js} +1 -1
  186. codex/static_root/assets/index-Cl7tPJIx.c0a239cf7069.js.br +0 -0
  187. codex/static_root/assets/index-Cl7tPJIx.c0a239cf7069.js.gz +0 -0
  188. codex/static_root/assets/{index-Cu9nQXJD.js → index-Cl7tPJIx.js} +1 -1
  189. codex/static_root/assets/index-Cl7tPJIx.js.br +0 -0
  190. codex/static_root/assets/index-Cl7tPJIx.js.gz +0 -0
  191. codex/static_root/assets/library-tab-2UucZZAW.f4541a086231.js +1 -0
  192. codex/static_root/assets/library-tab-2UucZZAW.f4541a086231.js.br +0 -0
  193. codex/static_root/assets/library-tab-2UucZZAW.f4541a086231.js.gz +0 -0
  194. codex/static_root/assets/library-tab-2UucZZAW.js +1 -0
  195. codex/static_root/assets/library-tab-2UucZZAW.js.br +0 -0
  196. codex/static_root/assets/library-tab-2UucZZAW.js.gz +0 -0
  197. codex/static_root/assets/{library-tab-D9lxhAqv.02f7064c20f3.css → library-tab-5StL67ei.0fad8998a237.css} +1 -1
  198. codex/static_root/assets/library-tab-5StL67ei.0fad8998a237.css.br +0 -0
  199. codex/static_root/assets/library-tab-5StL67ei.0fad8998a237.css.gz +0 -0
  200. codex/static_root/assets/{library-tab-D9lxhAqv.css → library-tab-5StL67ei.css} +1 -1
  201. codex/static_root/assets/library-tab-5StL67ei.css.br +0 -0
  202. codex/static_root/assets/library-tab-5StL67ei.css.gz +0 -0
  203. codex/static_root/assets/main-BX4TjIpG.dc79406e2a7b.js +39 -0
  204. codex/static_root/assets/main-BX4TjIpG.dc79406e2a7b.js.br +0 -0
  205. codex/static_root/assets/main-BX4TjIpG.dc79406e2a7b.js.gz +0 -0
  206. codex/static_root/assets/main-BX4TjIpG.js +39 -0
  207. codex/static_root/assets/main-BX4TjIpG.js.br +0 -0
  208. codex/static_root/assets/main-BX4TjIpG.js.gz +0 -0
  209. codex/static_root/assets/pager-full-pdf-KI4NQUMe.762b6bef9373.js +1 -0
  210. codex/static_root/assets/pager-full-pdf-KI4NQUMe.762b6bef9373.js.br +0 -0
  211. codex/static_root/assets/pager-full-pdf-KI4NQUMe.762b6bef9373.js.gz +0 -0
  212. codex/static_root/assets/pager-full-pdf-KI4NQUMe.js +1 -0
  213. codex/static_root/assets/pager-full-pdf-KI4NQUMe.js.br +0 -0
  214. codex/static_root/assets/pager-full-pdf-KI4NQUMe.js.gz +0 -0
  215. codex/static_root/assets/{pagination-toolbar-DGfRDeRW.c3f463ad6edd.js → pagination-toolbar-48pwYEe_.892375c5aa51.js} +1 -1
  216. codex/static_root/assets/pagination-toolbar-48pwYEe_.892375c5aa51.js.br +0 -0
  217. codex/static_root/assets/pagination-toolbar-48pwYEe_.892375c5aa51.js.gz +0 -0
  218. codex/static_root/assets/{pagination-toolbar-DGfRDeRW.js → pagination-toolbar-48pwYEe_.js} +1 -1
  219. codex/static_root/assets/pagination-toolbar-48pwYEe_.js.br +0 -0
  220. codex/static_root/assets/pagination-toolbar-48pwYEe_.js.gz +0 -0
  221. codex/static_root/assets/{pdf-doc-D6Meu4vZ.91b43d057670.js → pdf-doc-GyrCvyP5.54b26ba8d93c.js} +14 -14
  222. codex/static_root/assets/pdf-doc-GyrCvyP5.54b26ba8d93c.js.br +0 -0
  223. codex/static_root/assets/pdf-doc-GyrCvyP5.54b26ba8d93c.js.gz +0 -0
  224. codex/static_root/assets/{pdf-doc-D6Meu4vZ.js → pdf-doc-GyrCvyP5.js} +14 -14
  225. codex/static_root/assets/pdf-doc-GyrCvyP5.js.br +0 -0
  226. codex/static_root/assets/pdf-doc-GyrCvyP5.js.gz +0 -0
  227. codex/static_root/assets/{reader-LwL05rgA.c022ad3b7b94.css → reader-HE07eoaG.8626eeb7c718.css} +1 -1
  228. codex/static_root/assets/reader-HE07eoaG.8626eeb7c718.css.br +0 -0
  229. codex/static_root/assets/reader-HE07eoaG.8626eeb7c718.css.gz +0 -0
  230. codex/static_root/assets/{reader-LwL05rgA.css → reader-HE07eoaG.css} +1 -1
  231. codex/static_root/assets/reader-HE07eoaG.css.br +0 -0
  232. codex/static_root/assets/reader-HE07eoaG.css.gz +0 -0
  233. codex/static_root/assets/reader-lmk4MiSj.9239243e1be1.js +2 -0
  234. codex/static_root/assets/reader-lmk4MiSj.9239243e1be1.js.br +0 -0
  235. codex/static_root/assets/reader-lmk4MiSj.9239243e1be1.js.gz +0 -0
  236. codex/static_root/assets/reader-lmk4MiSj.js +2 -0
  237. codex/static_root/assets/reader-lmk4MiSj.js.br +0 -0
  238. codex/static_root/assets/reader-lmk4MiSj.js.gz +0 -0
  239. codex/static_root/assets/{relation-chips-CAXZIswb.e991a259ce59.js → relation-chips-Dgb6LQdZ.c028ab2df979.js} +1 -1
  240. codex/static_root/assets/relation-chips-Dgb6LQdZ.c028ab2df979.js.br +0 -0
  241. codex/static_root/assets/relation-chips-Dgb6LQdZ.c028ab2df979.js.gz +0 -0
  242. codex/static_root/assets/{relation-chips-CAXZIswb.js → relation-chips-Dgb6LQdZ.js} +1 -1
  243. codex/static_root/assets/relation-chips-Dgb6LQdZ.js.br +0 -0
  244. codex/static_root/assets/relation-chips-Dgb6LQdZ.js.gz +0 -0
  245. codex/static_root/assets/{settings-drawer-B4gD41g6.js → settings-drawer-CRmLEncr.6937d45e18af.js} +2 -2
  246. codex/static_root/assets/settings-drawer-CRmLEncr.6937d45e18af.js.br +0 -0
  247. codex/static_root/assets/settings-drawer-CRmLEncr.6937d45e18af.js.gz +0 -0
  248. codex/static_root/assets/{settings-drawer-B4gD41g6.82718694498e.js → settings-drawer-CRmLEncr.js} +2 -2
  249. codex/static_root/assets/settings-drawer-CRmLEncr.js.br +0 -0
  250. codex/static_root/assets/settings-drawer-CRmLEncr.js.gz +0 -0
  251. codex/static_root/assets/{ssrBoot-O6yTJ_UV.7180d77d283e.js → ssrBoot-CCKPlpgB.c90fa83e0817.js} +1 -1
  252. codex/static_root/assets/ssrBoot-CCKPlpgB.c90fa83e0817.js.br +0 -0
  253. codex/static_root/assets/ssrBoot-CCKPlpgB.c90fa83e0817.js.gz +0 -0
  254. codex/static_root/assets/{ssrBoot-O6yTJ_UV.js → ssrBoot-CCKPlpgB.js} +1 -1
  255. codex/static_root/assets/ssrBoot-CCKPlpgB.js.br +0 -0
  256. codex/static_root/assets/ssrBoot-CCKPlpgB.js.gz +0 -0
  257. codex/static_root/assets/{stats-tab-BZjOg19A.afb2e6b0d648.js → stats-tab-CrU_p2gC.e12768f9423d.js} +1 -1
  258. codex/static_root/assets/stats-tab-CrU_p2gC.e12768f9423d.js.br +0 -0
  259. codex/static_root/assets/stats-tab-CrU_p2gC.e12768f9423d.js.gz +0 -0
  260. codex/static_root/assets/{stats-tab-BZjOg19A.js → stats-tab-CrU_p2gC.js} +1 -1
  261. codex/static_root/assets/stats-tab-CrU_p2gC.js.br +0 -0
  262. codex/static_root/assets/stats-tab-CrU_p2gC.js.gz +0 -0
  263. codex/static_root/assets/task-tab-Bp0wsH4V.2a5135c30818.js +1 -0
  264. codex/static_root/assets/task-tab-Bp0wsH4V.2a5135c30818.js.br +0 -0
  265. codex/static_root/assets/task-tab-Bp0wsH4V.2a5135c30818.js.gz +0 -0
  266. codex/static_root/assets/task-tab-Bp0wsH4V.js +1 -0
  267. codex/static_root/assets/task-tab-Bp0wsH4V.js.br +0 -0
  268. codex/static_root/assets/task-tab-Bp0wsH4V.js.gz +0 -0
  269. codex/static_root/assets/{unauthorized-Bo3ThIrX.12d2efd95d7d.js → unauthorized-DObmibd6.b47434919de7.js} +1 -1
  270. codex/static_root/assets/unauthorized-DObmibd6.b47434919de7.js.br +0 -0
  271. codex/static_root/assets/unauthorized-DObmibd6.b47434919de7.js.gz +0 -0
  272. codex/static_root/assets/{unauthorized-Bo3ThIrX.js → unauthorized-DObmibd6.js} +1 -1
  273. codex/static_root/assets/unauthorized-DObmibd6.js.br +0 -0
  274. codex/static_root/assets/unauthorized-DObmibd6.js.gz +0 -0
  275. codex/static_root/assets/{user-tab-BQ82qBg3.17190dc83452.js → user-tab-DedY8MbN.624af3a6a978.js} +1 -1
  276. codex/static_root/assets/user-tab-DedY8MbN.624af3a6a978.js.br +0 -0
  277. codex/static_root/assets/user-tab-DedY8MbN.624af3a6a978.js.gz +0 -0
  278. codex/static_root/assets/{user-tab-BQ82qBg3.js → user-tab-DedY8MbN.js} +1 -1
  279. codex/static_root/assets/user-tab-DedY8MbN.js.br +0 -0
  280. codex/static_root/assets/user-tab-DedY8MbN.js.gz +0 -0
  281. codex/static_root/{manifest.0dc91d0dee6d.json → manifest.4217bf6f9edb.json} +313 -313
  282. codex/static_root/manifest.4217bf6f9edb.json.br +0 -0
  283. codex/static_root/manifest.4217bf6f9edb.json.gz +0 -0
  284. codex/static_root/manifest.json +313 -313
  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.0a3.dist-info}/METADATA +2 -2
  294. {codex-1.8.0a2.dist-info → codex-1.8.0a3.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.0a3.dist-info}/WHEEL +0 -0
  476. {codex-1.8.0a2.dist-info → codex-1.8.0a3.dist-info}/entry_points.txt +0 -0
  477. {codex-1.8.0a2.dist-info → codex-1.8.0a3.dist-info}/licenses/LICENSE +0 -0
@@ -17,7 +17,7 @@ class SearchIndexClearStatus(SearchIndexStatus):
17
17
  _verbed = "Cleared"
18
18
  ITEM_NAME = "full text search table"
19
19
  SINGLE = True
20
- LOG_SUCCESS = True
20
+ log_success = True
21
21
 
22
22
 
23
23
  class SearchIndexCleanStatus(SearchIndexStatus):
@@ -36,25 +36,25 @@ class SearchIndexOptimizeStatus(SearchIndexStatus):
36
36
  VERB = "Optimize"
37
37
  ITEM_NAME = "search virtual table"
38
38
  SINGLE = True
39
- LOG_SUCCESS = True
39
+ log_success = True
40
40
 
41
41
 
42
42
  class SearchIndexSyncUpdateStatus(SearchIndexStatus):
43
43
  """Search Index Sync Update Status."""
44
44
 
45
45
  CODE = "SSU"
46
- VERB = "Sync old"
47
- _verbed = "Synced old"
48
- ITEM_NAME = "search entries"
46
+ VERB = "Sync"
47
+ _verbed = "Synced"
48
+ ITEM_NAME = "old search entries"
49
49
 
50
50
 
51
51
  class SearchIndexSyncCreateStatus(SearchIndexStatus):
52
52
  """Search Index Sync Create Status."""
53
53
 
54
54
  CODE = "SSC"
55
- VERB = "Sync new"
56
- _verbed = "Synced new"
57
- ITEM_NAME = "search entries"
55
+ VERB = "Sync"
56
+ _verbed = "Synced"
57
+ ITEM_NAME = "new search entries"
58
58
 
59
59
 
60
60
  SEARCH_INDEX_STATII = (
@@ -98,7 +98,7 @@ class SearchIndexerSync(SearchIndexerRemove):
98
98
  self.log.info("Rebuilding search index...")
99
99
  self.clear_search_index()
100
100
  else:
101
- self.remove_stale_records()
101
+ self.remove_stale_records(log_success=False)
102
102
 
103
103
  @staticmethod
104
104
  def _select_related_fts_query(qs):
@@ -360,7 +360,7 @@ class SearchIndexerSync(SearchIndexerRemove):
360
360
 
361
361
  if self.abort_event.is_set():
362
362
  return
363
- self._update_search_index_clean(rebuild)
363
+ cleaned_count = self._update_search_index_clean(rebuild)
364
364
  if self.abort_event.is_set():
365
365
  return
366
366
  updated_count = self._update_search_index_update()
@@ -370,11 +370,18 @@ class SearchIndexerSync(SearchIndexerRemove):
370
370
 
371
371
  elapsed_time = time() - start_time
372
372
  elapsed = naturaldelta(elapsed_time)
373
- cleaned = "cleared" if rebuild else "cleaned"
373
+ if rebuild:
374
+ cleaned = "cleared entire search index"
375
+ elif cleaned_count:
376
+ cleaned = f"cleaned {cleaned_count} stale entries"
377
+ else:
378
+ cleaned = ""
374
379
  updated = f"{updated_count} entries updated by sync" if updated_count else ""
375
380
  created = f"{created_count} entries created by sync" if created_count else ""
376
381
  summary_parts = filter(None, (cleaned, updated, created))
377
382
  summary = ", ".join(summary_parts)
383
+ if not summary:
384
+ summary = "found to be already synced"
378
385
  self.log.success(f"Search index {summary} in {elapsed}.")
379
386
 
380
387
  def update_search_index(self, *, rebuild: bool):
@@ -13,7 +13,8 @@ class UpdateGroupTimestampsStatus(ScribeStatus):
13
13
  """Update Group Timestamps Status."""
14
14
 
15
15
  CODE = "IGU"
16
- PURAL = "browser groups"
16
+ ITEM_NAME = "browser groups"
17
+ VERB = "Update timestamps for"
17
18
  _verbed = "Updated timestamps for"
18
19
 
19
20
 
codex/librarian/status.py CHANGED
@@ -9,14 +9,13 @@ from humanize import intword, naturaldelta
9
9
 
10
10
 
11
11
  @dataclass
12
- class Status(ABC): # noqa: B024
12
+ class Status(ABC):
13
13
  """Keep track of librarians status in memory."""
14
14
 
15
- CODE: ClassVar[str] = "UNASSIGNED"
16
- VERB: ClassVar[str] = "Operate"
17
- ITEM_NAME: ClassVar[str] = "items"
15
+ CODE: ClassVar[str]
16
+ VERB: ClassVar[str]
17
+ ITEM_NAME: ClassVar[str]
18
18
  SINGLE: ClassVar[bool] = False
19
- LOG_SUCCESS: ClassVar[bool] = False
20
19
  _title: ClassVar[str] = ""
21
20
  _verbed: ClassVar[str] = ""
22
21
 
@@ -25,6 +24,7 @@ class Status(ABC): # noqa: B024
25
24
  since_updated: float = 0.0
26
25
  subtitle: str = ""
27
26
  start_time: float | None = None
27
+ log_success: bool = False
28
28
 
29
29
  @classmethod
30
30
  def title(cls):
@@ -4,9 +4,11 @@ from collections.abc import Iterable
4
4
  from inspect import isclass
5
5
  from multiprocessing import Queue
6
6
  from time import time
7
+ from types import MappingProxyType
7
8
  from typing import Any
8
9
 
9
10
  from django.db.models.functions.datetime import Now
11
+ from django.db.models.query import Q
10
12
  from django.utils.timezone import datetime, now, timedelta
11
13
  from loguru._logger import Logger
12
14
 
@@ -113,50 +115,69 @@ class StatusController:
113
115
  """Log finish of status with stats."""
114
116
  level = "INFO"
115
117
  suffix = ""
116
- if count := status.complete:
117
- if elapsed := status.elapsed():
118
- suffix = f" in {elapsed}"
118
+ if elapsed := status.elapsed():
119
+ suffix += f" in {elapsed}"
120
+ if status.SINGLE:
121
+ count = ""
122
+ elif count := status.complete:
123
+ count = str(count)
119
124
  if persecond := status.per_second():
120
125
  suffix += f" at a rate of {persecond}"
121
- elif count == 0:
126
+ else:
122
127
  count = "no"
123
128
  level = "DEBUG"
124
- if status.SINGLE or count is None:
125
- count = ""
126
129
 
127
- prefix_parts = (status.verbed(), str(count), status.ITEM_NAME)
128
- prefix = " ".join(filter(None, prefix_parts))
129
-
130
- if status.LOG_SUCCESS:
130
+ if status.log_success:
131
131
  level = "SUCCESS"
132
132
 
133
+ prefix_parts = [status.verbed()]
134
+ if count:
135
+ prefix_parts.append(count)
136
+ prefix_parts.append(status.ITEM_NAME)
137
+ prefix = " ".join(prefix_parts)
138
+
133
139
  self.log.log(level, f"{prefix}{suffix}.")
134
140
 
135
141
  def finish_many(
136
- self, statii: Iterable[Status | type[Status]], *, notify: bool = True
142
+ self, statii: Iterable[Status | type[Status] | None], *, notify: bool = True
137
143
  ):
138
144
  """Finish all librarian statuses."""
145
+ positive_statii: MappingProxyType[str, Status | type[Status]] = (
146
+ MappingProxyType({status.CODE: status for status in statii if status})
147
+ )
139
148
  try:
140
- type_codes = frozenset(status.CODE for status in statii)
141
- ls_filter = {"status_type__in": type_codes} if type_codes else {}
149
+ if statii and not positive_statii:
150
+ # if statii has elements but they were all None, this is a noop.
151
+ # But if statii was empty this is a finish all command.
152
+ return
153
+ # Filter on submitted codes or all statii if nothing.
154
+ ls_filter_dict: dict[str, Any] = (
155
+ {"status_type__in": positive_statii.keys()} if positive_statii else {}
156
+ )
157
+ # Filter all active or preactive statii
158
+ ls_filter = (Q(active__isnull=False) | Q(preactive__isnull=False)) & Q(
159
+ **ls_filter_dict
160
+ )
142
161
  updates = {**STATUS_DEFAULTS, "updated_at": Now()}
143
- lses = LibrarianStatus.objects.filter(**ls_filter)
162
+ lses = LibrarianStatus.objects.filter(ls_filter)
144
163
  update_ls = []
164
+ log_statii = []
145
165
  for ls in lses.iterator():
146
166
  for key, value in updates.items():
147
167
  setattr(ls, key, value)
148
168
  update_ls.append(ls)
169
+ log_statii.append(positive_statii[ls.status_type])
170
+
149
171
  LibrarianStatus.objects.bulk_update(update_ls, tuple(updates.keys()))
150
172
  self._enqueue_notifier_task(notify=notify)
151
- if not ls_filter:
173
+ if not ls_filter_dict:
152
174
  self.log.info("Cleared all librarian statuses")
153
- for status in statii:
154
- if isinstance(status, Status):
155
- self._log_finish(status)
175
+ for status in log_statii:
176
+ self._log_finish(status)
156
177
  except Exception as exc:
157
- self.log.warning(f"Finish status {statii}: {exc}")
178
+ self.log.warning(f"Finish status {positive_statii}: {exc}")
158
179
 
159
- def finish(self, status: Status, *, notify: bool = True):
180
+ def finish(self, status: Status | None, *, notify: bool = True):
160
181
  """Finish a librarian status."""
161
182
  try:
162
183
  self.finish_many((status,), notify=notify)
@@ -9,17 +9,22 @@ from watchdog.events import (
9
9
  EVENT_TYPE_CREATED,
10
10
  EVENT_TYPE_DELETED,
11
11
  EVENT_TYPE_MODIFIED,
12
+ DirCreatedEvent,
12
13
  DirDeletedEvent,
13
14
  DirModifiedEvent,
14
15
  DirMovedEvent,
16
+ FileClosedEvent,
17
+ FileClosedNoWriteEvent,
15
18
  FileCreatedEvent,
16
19
  FileDeletedEvent,
17
20
  FileModifiedEvent,
18
21
  FileMovedEvent,
22
+ FileOpenedEvent,
19
23
  FileSystemEvent,
20
24
  )
21
25
 
22
26
  from codex.librarian.watchdog.events import (
27
+ CodexPollEvent,
23
28
  CoverCreatedEvent,
24
29
  CoverDeletedEvent,
25
30
  CoverModifiedEvent,
@@ -40,7 +45,31 @@ ATTR_EVENT_MAP = MappingProxyType(
40
45
  "dirs_moved": DirMovedEvent,
41
46
  }
42
47
  )
48
+ DIR_NOT_FOUND_TIMEOUT = 15 * 60
49
+ POLLING_EVENT_FILTER: tuple[type[FileSystemEvent], ...] = (
50
+ FileMovedEvent,
51
+ FileModifiedEvent,
52
+ FileCreatedEvent,
53
+ FileDeletedEvent,
54
+ # FileClosedEvent,
55
+ # FileOpenedEvent,
56
+ DirMovedEvent,
57
+ DirModifiedEvent,
58
+ DirDeletedEvent,
59
+ # DirCreatedEvent,
60
+ CodexPollEvent,
61
+ )
62
+ DOCKER_UNMOUNTED_FN = "DOCKER_UNMOUNTED_VOLUME"
43
63
 
64
+ #############
65
+ # Observers #
66
+ #############
67
+ EVENT_FILTER: tuple[type[FileSystemEvent], ...] = (
68
+ DirCreatedEvent,
69
+ FileClosedEvent,
70
+ FileClosedNoWriteEvent,
71
+ FileOpenedEvent,
72
+ )
44
73
 
45
74
  ############
46
75
  # Handlers #
@@ -48,7 +77,7 @@ ATTR_EVENT_MAP = MappingProxyType(
48
77
 
49
78
 
50
79
  def _get_comic_matcher():
51
- comic_regex = r"\.(cb[zt"
80
+ comic_regex = r"\.(cb[zt7"
52
81
  unsupported = []
53
82
  if Comicbox.is_unrar_supported():
54
83
  comic_regex += r"r"
@@ -8,16 +8,7 @@ from django.db.models.functions import Now
8
8
  from django.utils import timezone
9
9
  from humanize import naturaldelta
10
10
  from typing_extensions import override
11
- from watchdog.events import (
12
- DirDeletedEvent,
13
- DirModifiedEvent,
14
- DirMovedEvent,
15
- FileCreatedEvent,
16
- FileDeletedEvent,
17
- FileModifiedEvent,
18
- FileMovedEvent,
19
- FileSystemEvent,
20
- )
11
+ from watchdog.events import FileSystemEvent
21
12
  from watchdog.observers.api import (
22
13
  DEFAULT_EMITTER_TIMEOUT,
23
14
  EventEmitter,
@@ -26,11 +17,15 @@ from watchdog.observers.api import (
26
17
  )
27
18
  from watchdog.utils.dirsnapshot import DirectorySnapshot
28
19
 
29
- from codex.librarian.watchdog.const import ATTR_EVENT_MAP
20
+ from codex.librarian.watchdog.const import (
21
+ ATTR_EVENT_MAP,
22
+ DIR_NOT_FOUND_TIMEOUT,
23
+ DOCKER_UNMOUNTED_FN,
24
+ POLLING_EVENT_FILTER,
25
+ )
30
26
  from codex.librarian.watchdog.db_snapshot import CodexDatabaseSnapshot
31
27
  from codex.librarian.watchdog.dir_snapshot_diff import CodexDirectorySnapshotDiff
32
28
  from codex.librarian.watchdog.events import (
33
- CodexPollEvent,
34
29
  FinishPollEvent,
35
30
  StartPollEvent,
36
31
  )
@@ -42,21 +37,17 @@ from codex.librarian.watchdog.status import WatchdogPollStatus
42
37
  from codex.librarian.worker import WorkerStatusMixin
43
38
  from codex.models import Library
44
39
 
45
- _DIR_NOT_FOUND_TIMEOUT = 15 * 60
46
- _CODEX_EVENT_FILTER: list[type[FileSystemEvent]] = [
47
- FileMovedEvent,
48
- FileModifiedEvent,
49
- FileCreatedEvent,
50
- FileDeletedEvent,
51
- # FileClosedEvent,
52
- # FileOpenedEvent,
53
- DirMovedEvent,
54
- DirModifiedEvent,
55
- DirDeletedEvent,
56
- # DirCreatedEvent,
57
- CodexPollEvent,
58
- ]
59
- _DOCKER_UNMOUNTED_FN = "DOCKER_UNMOUNTED_VOLUME"
40
+
41
+ def extend_event_filter(
42
+ event_filter: list[type[FileSystemEvent]] | None,
43
+ extended_event_filter: tuple[type[FileSystemEvent], ...],
44
+ ):
45
+ """Initialize event filter with a some constant types."""
46
+ if event_filter is None:
47
+ event_filter = []
48
+ for event_type in extended_event_filter:
49
+ if event_type not in event_filter:
50
+ event_filter.append(event_type)
60
51
 
61
52
 
62
53
  class DatabasePollingEmitter(EventEmitter, WorkerStatusMixin):
@@ -73,6 +64,7 @@ class DatabasePollingEmitter(EventEmitter, WorkerStatusMixin):
73
64
  covers_only=False,
74
65
  library_id: int,
75
66
  db_write_lock,
67
+ event_filter: list[type[FileSystemEvent]] | None = None,
76
68
  ):
77
69
  """Initialize snapshot methods."""
78
70
  self.init_worker(logger_, librarian_queue, db_write_lock)
@@ -80,15 +72,15 @@ class DatabasePollingEmitter(EventEmitter, WorkerStatusMixin):
80
72
  self._force = False
81
73
  self._manual_poll = False
82
74
  self._watch_path = Path(watch.path)
83
- self._watch_path_unmounted = self._watch_path / _DOCKER_UNMOUNTED_FN
75
+ self._watch_path_unmounted = self._watch_path / DOCKER_UNMOUNTED_FN
84
76
  self._covers_only = covers_only
85
77
  self._handler = (
86
78
  CodexCustomCoverEventHandler if covers_only else CodexLibraryEventHandler
87
79
  )
88
80
  self._library_id = library_id
89
- super().__init__(
90
- event_queue, watch, timeout=timeout, event_filter=_CODEX_EVENT_FILTER
91
- )
81
+
82
+ event_filter = extend_event_filter(event_filter, POLLING_EVENT_FILTER)
83
+ super().__init__(event_queue, watch, timeout=timeout, event_filter=event_filter)
92
84
 
93
85
  self._take_dir_snapshot = lambda: DirectorySnapshot(
94
86
  self._watch.path,
@@ -116,15 +108,15 @@ class DatabasePollingEmitter(EventEmitter, WorkerStatusMixin):
116
108
  timeout = None
117
109
  elif not self._watch_path.is_dir():
118
110
  msg = f"Library {self._watch_path} not found. Not Polling."
119
- timeout = _DIR_NOT_FOUND_TIMEOUT
111
+ timeout = DIR_NOT_FOUND_TIMEOUT
120
112
  elif self._watch_path_unmounted.exists():
121
113
  # Maybe overkill of caution here
122
114
  msg = f"Library {self._watch_path} looks like an unmounted docker volume. Not polling."
123
- timeout = _DIR_NOT_FOUND_TIMEOUT
115
+ timeout = DIR_NOT_FOUND_TIMEOUT
124
116
  elif not tuple(self._watch_path.iterdir()):
125
117
  # Maybe overkill of caution here too
126
118
  msg = f"{self._watch_path} is empty. Suspect it may be unmounted. Not polling."
127
- timeout = _DIR_NOT_FOUND_TIMEOUT
119
+ timeout = DIR_NOT_FOUND_TIMEOUT
128
120
  elif library.update_in_progress:
129
121
  log_level = "DEBUG"
130
122
  msg = f"Library {library.path} update in progress. Not polling."
@@ -46,8 +46,8 @@ class WatchdogEventBatcherThread(AggregateMessageQueuedThread):
46
46
  MAX_DELAY = 60.0
47
47
  MAX_ITEMS_PER_GB = 50000
48
48
 
49
- @classmethod
50
- def create_import_task_args(cls, library_id: int) -> dict:
49
+ @staticmethod
50
+ def create_import_task_args(library_id: int) -> dict:
51
51
  """Create import task args."""
52
52
  args = deepcopy(dict(_IMPORT_TASK_PARAMS))
53
53
  args["library_id"] = library_id # pyright: ignore[reportArgumentType]
@@ -94,26 +94,30 @@ class WatchdogEventBatcherThread(AggregateMessageQueuedThread):
94
94
  mem_limit_gb = get_mem_limit("g")
95
95
  self.max_items = int(self.MAX_ITEMS_PER_GB * mem_limit_gb)
96
96
 
97
- def _args_field_by_event(self, library_id, event):
97
+ def _args_field_by_event(self, library_id: int, event: FileSystemEvent):
98
98
  """Translate event class names into field names."""
99
99
  if library_id not in self.cache:
100
100
  self.cache[library_id] = self.create_import_task_args(library_id)
101
- key = EVENT_CLASS_DIFF_ALL_MAP[type(event)]
102
- return self.cache[library_id].get(key)
101
+ if key := EVENT_CLASS_DIFF_ALL_MAP.get(type(event)):
102
+ args_field = self.cache[library_id].get(key)
103
+ else:
104
+ reason = f"Unhandled event, not batching: {event}"
105
+ raise ValueError(reason)
106
+ return args_field
103
107
 
104
108
  @override
105
109
  def aggregate_items(self, item):
106
110
  """Aggregate events into cache by library."""
107
111
  event = item.event
108
- args_field = self._args_field_by_event(item.library_id, event)
109
- if args_field is None:
110
- self.log.debug(f"Unhandled event, not batching: {event}")
111
- return
112
- if event.event_type == EVENT_TYPE_MOVED:
113
- args_field[event.src_path] = event.dest_path
114
- else:
115
- args_field.add(event.src_path)
116
- self._total_items += 1
112
+ try:
113
+ args_field = self._args_field_by_event(item.library_id, event)
114
+ if event.event_type == EVENT_TYPE_MOVED:
115
+ args_field[event.src_path] = event.dest_path
116
+ else:
117
+ args_field.add(event.src_path)
118
+ self._total_items += 1
119
+ except ValueError as exc:
120
+ self.log.debug(exc)
117
121
  if self._total_items > self.max_items:
118
122
  reason = (
119
123
  "Event batcher hit size limit."
@@ -4,10 +4,6 @@ from multiprocessing.queues import Queue
4
4
 
5
5
  from typing_extensions import override
6
6
  from watchdog.events import (
7
- DirCreatedEvent,
8
- FileClosedEvent,
9
- FileClosedNoWriteEvent,
10
- FileOpenedEvent,
11
7
  FileSystemEvent,
12
8
  FileSystemEventHandler,
13
9
  )
@@ -19,7 +15,8 @@ from watchdog.observers.api import (
19
15
  ObservedWatch,
20
16
  )
21
17
 
22
- from codex.librarian.watchdog.emitter import DatabasePollingEmitter
18
+ from codex.librarian.watchdog.const import EVENT_FILTER
19
+ from codex.librarian.watchdog.emitter import DatabasePollingEmitter, extend_event_filter
23
20
  from codex.librarian.watchdog.handlers import (
24
21
  CodexCustomCoverEventHandler,
25
22
  CodexLibraryEventHandler,
@@ -27,16 +24,9 @@ from codex.librarian.watchdog.handlers import (
27
24
  from codex.librarian.worker import WorkerMixin
28
25
  from codex.models import Library
29
26
 
30
- _IGNORED_EVENTS: tuple[type[FileSystemEvent], ...] = (
31
- DirCreatedEvent,
32
- FileClosedEvent,
33
- FileClosedNoWriteEvent,
34
- FileOpenedEvent,
35
- )
36
-
37
27
 
38
28
  class UatuObserver(WorkerMixin, BaseObserver):
39
- """Watch over librarys from the blue area of the moon."""
29
+ """Watch over libraries from the blue area of the moon."""
40
30
 
41
31
  ENABLE_FIELD: str = ""
42
32
  ALWAYS_WATCH: bool = False
@@ -134,13 +124,19 @@ class UatuObserver(WorkerMixin, BaseObserver):
134
124
 
135
125
  @override
136
126
  def schedule(
137
- self, event_handler: FileSystemEventHandler, path: str, **kwargs
127
+ self,
128
+ event_handler: FileSystemEventHandler,
129
+ path: str,
130
+ *,
131
+ event_filter: list[type[FileSystemEvent]] | None = None,
132
+ **kwargs,
138
133
  ) -> ObservedWatch:
139
134
  """Override BaseObserver for Codex emitter class."""
140
135
  if self._emitter_class != DatabasePollingEmitter:
141
136
  return super().schedule(event_handler, path, **kwargs)
142
137
  with self._lock:
143
- watch = ObservedWatch(path, **kwargs)
138
+ event_filter = extend_event_filter(event_filter, EVENT_FILTER)
139
+ watch = ObservedWatch(path, event_filter=event_filter, **kwargs)
144
140
  self._add_handler_for_watch(event_handler, watch)
145
141
  if self._emitter_for_watch.get(watch) is None:
146
142
  self._add_emitter_for_watch(event_handler, watch)
@@ -0,0 +1,72 @@
1
+ """Generated by Django 5.2.4 on 2025-07-12 23:23."""
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+ """Migrate db."""
8
+
9
+ dependencies = [
10
+ ("codex", "0034_comicbox2"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name="librarianstatus",
16
+ name="status_type",
17
+ field=models.CharField(
18
+ choices=[
19
+ ("CCC", "Create Covers"),
20
+ ("CFO", "Find Orphan Covers"),
21
+ ("CRC", "Remove Covers"),
22
+ ("IAT", "Aggregate Tags From Comics"),
23
+ ("ICC", "Create Comics"),
24
+ ("ICT", "Create Tags"),
25
+ ("ICV", "Create Custom Covers"),
26
+ ("IFC", "Mark Failed Failed Imports"),
27
+ ("IFD", "Clean Up Failed Imports"),
28
+ ("IFQ", "Query Failed Imports"),
29
+ ("IFU", "Update Failed Imports"),
30
+ ("IGU", "Update Timestamps For Browser Groups"),
31
+ ("ILT", "Link Tags"),
32
+ ("ILV", "Link Custom Covers"),
33
+ ("IQC", "Query Comics"),
34
+ ("IQL", "Query Tag Links"),
35
+ ("IQT", "Query Missing Tags"),
36
+ ("IQV", "Query Missing Custom Covers"),
37
+ ("IRC", "Remove Comics"),
38
+ ("IRF", "Remove Folders"),
39
+ ("IRT", "Read Tags From Comics"),
40
+ ("IRV", "Remove Custom Covers"),
41
+ ("ISC", "Create Search Index Entries"),
42
+ ("ISU", "Update Search Index Entries"),
43
+ ("IUC", "Update Comics"),
44
+ ("IUT", "Update Tags"),
45
+ ("IUV", "Update Custom Covers"),
46
+ ("JAF", "Adopt Orphan Folders"),
47
+ ("JCT", "Cleanup Orphan Tags"),
48
+ ("JCU", "Update Codex Server Software"),
49
+ ("JDB", "Backup Database"),
50
+ ("JDO", "Optimize Database"),
51
+ ("JID", "Check Integrity Of Entire Database"),
52
+ ("JIF", "Check Integrtity Of Database Foreign Keys"),
53
+ ("JIS", "Check Integrity Of Full Text Virtual Table"),
54
+ ("JLV", "Check Codex Latest Version"),
55
+ ("JRB", "Cleanup Orphan Bookmarks"),
56
+ ("JRS", "Cleanup Old Sessions"),
57
+ ("JRV", "Cleanup Orphan Covers"),
58
+ ("JSR", "Rebuild Full Text Search Virtual Table"),
59
+ ("RCR", "Restart Codex Server"),
60
+ ("RCS", "Stop Codex Server"),
61
+ ("SIO", "Optimize Search Virtual Table"),
62
+ ("SIR", "Clean Orphan Search Entries"),
63
+ ("SIX", "Clear Full Text Search Table"),
64
+ ("SSC", "Sync New Search Entries"),
65
+ ("SSU", "Sync Old Search Entries"),
66
+ ("WPO", "Poll Library"),
67
+ ],
68
+ db_index=True,
69
+ max_length=3,
70
+ ),
71
+ ),
72
+ ]
codex/startup/__init__.py CHANGED
@@ -71,7 +71,7 @@ def init_timestamps():
71
71
 
72
72
  def init_librarian_statuses():
73
73
  """Init librarian statuses."""
74
- _delete_orphans(LibrarianStatus, "status_type", LibrarianStatus.CHOICES.labels)
74
+ _delete_orphans(LibrarianStatus, "status_type", LibrarianStatus.CHOICES.values)
75
75
 
76
76
  for status_type, title in LibrarianStatus.CHOICES.choices:
77
77
  _, created = LibrarianStatus.objects.update_or_create(
@@ -1 +1 @@
1
- import{m as I,V as r}from"./VCheckboxBtn-Bu2Pf64q.js";import{u as A,m as F,g as u}from"./VSelectionControl-DbKYScD5.js";import{f as R}from"./forwardRefs-Z0d4Mnc7.js";import{g as B,p as U,e as w,r as D,u as M,o as N,bt as $,bu as j,a as l,m as d}from"./main-BoAlbVoF.js";const q=U({...F(),...N(I(),["inline"])},"VCheckbox"),J=B()({name:"VCheckbox",inheritAttrs:!1,props:q(),emits:{"update:modelValue":e=>!0,"update:focused":e=>!0},setup(e,c){let{attrs:n,slots:a}=c;const s=w(e,"modelValue"),{isFocused:i,focus:m,blur:f}=A(e),t=D(),V=$();return M(()=>{const[p,b]=j(n),k=u.filterProps(e),v=r.filterProps(e);return l(u,d({ref:t,class:["v-checkbox",e.class]},p,k,{modelValue:s.value,"onUpdate:modelValue":o=>s.value=o,id:e.id||`checkbox-${V}`,focused:i.value,style:e.style}),{...a,default:o=>{let{id:x,messagesId:h,isDisabled:P,isReadonly:C,isValid:y}=o;return l(r,d(v,{id:x.value,"aria-describedby":h.value,disabled:P.value,readonly:C.value},b,{error:y.value===!1,modelValue:s.value,"onUpdate:modelValue":g=>s.value=g,onFocus:m,onBlur:f}),a)}})}),R({},t)}});export{J as V};
1
+ import{m as I,V as r}from"./VCheckboxBtn-BeZZDumo.js";import{u as A,m as F,g as u}from"./VSelectionControl-CmXEFw20.js";import{f as R}from"./forwardRefs-Nj5UEeg5.js";import{g as B,p as U,e as w,r as D,u as M,o as N,bt as $,bu as j,a as l,m as d}from"./main-BX4TjIpG.js";const q=U({...F(),...N(I(),["inline"])},"VCheckbox"),J=B()({name:"VCheckbox",inheritAttrs:!1,props:q(),emits:{"update:modelValue":e=>!0,"update:focused":e=>!0},setup(e,c){let{attrs:n,slots:a}=c;const s=w(e,"modelValue"),{isFocused:i,focus:m,blur:f}=A(e),t=D(),V=$();return M(()=>{const[p,b]=j(n),k=u.filterProps(e),v=r.filterProps(e);return l(u,d({ref:t,class:["v-checkbox",e.class]},p,k,{modelValue:s.value,"onUpdate:modelValue":o=>s.value=o,id:e.id||`checkbox-${V}`,focused:i.value,style:e.style}),{...a,default:o=>{let{id:x,messagesId:h,isDisabled:P,isReadonly:C,isValid:y}=o;return l(r,d(v,{id:x.value,"aria-describedby":h.value,disabled:P.value,readonly:C.value},b,{error:y.value===!1,modelValue:s.value,"onUpdate:modelValue":g=>s.value=g,onFocus:m,onBlur:f}),a)}})}),R({},t)}});export{J as V};
@@ -1 +1 @@
1
- import{m as I,V as r}from"./VCheckboxBtn-Bu2Pf64q.js";import{u as A,m as F,g as u}from"./VSelectionControl-DbKYScD5.js";import{f as R}from"./forwardRefs-Z0d4Mnc7.js";import{g as B,p as U,e as w,r as D,u as M,o as N,bt as $,bu as j,a as l,m as d}from"./main-BoAlbVoF.js";const q=U({...F(),...N(I(),["inline"])},"VCheckbox"),J=B()({name:"VCheckbox",inheritAttrs:!1,props:q(),emits:{"update:modelValue":e=>!0,"update:focused":e=>!0},setup(e,c){let{attrs:n,slots:a}=c;const s=w(e,"modelValue"),{isFocused:i,focus:m,blur:f}=A(e),t=D(),V=$();return M(()=>{const[p,b]=j(n),k=u.filterProps(e),v=r.filterProps(e);return l(u,d({ref:t,class:["v-checkbox",e.class]},p,k,{modelValue:s.value,"onUpdate:modelValue":o=>s.value=o,id:e.id||`checkbox-${V}`,focused:i.value,style:e.style}),{...a,default:o=>{let{id:x,messagesId:h,isDisabled:P,isReadonly:C,isValid:y}=o;return l(r,d(v,{id:x.value,"aria-describedby":h.value,disabled:P.value,readonly:C.value},b,{error:y.value===!1,modelValue:s.value,"onUpdate:modelValue":g=>s.value=g,onFocus:m,onBlur:f}),a)}})}),R({},t)}});export{J as V};
1
+ import{m as I,V as r}from"./VCheckboxBtn-BeZZDumo.js";import{u as A,m as F,g as u}from"./VSelectionControl-CmXEFw20.js";import{f as R}from"./forwardRefs-Nj5UEeg5.js";import{g as B,p as U,e as w,r as D,u as M,o as N,bt as $,bu as j,a as l,m as d}from"./main-BX4TjIpG.js";const q=U({...F(),...N(I(),["inline"])},"VCheckbox"),J=B()({name:"VCheckbox",inheritAttrs:!1,props:q(),emits:{"update:modelValue":e=>!0,"update:focused":e=>!0},setup(e,c){let{attrs:n,slots:a}=c;const s=w(e,"modelValue"),{isFocused:i,focus:m,blur:f}=A(e),t=D(),V=$();return M(()=>{const[p,b]=j(n),k=u.filterProps(e),v=r.filterProps(e);return l(u,d({ref:t,class:["v-checkbox",e.class]},p,k,{modelValue:s.value,"onUpdate:modelValue":o=>s.value=o,id:e.id||`checkbox-${V}`,focused:i.value,style:e.style}),{...a,default:o=>{let{id:x,messagesId:h,isDisabled:P,isReadonly:C,isValid:y}=o;return l(r,d(v,{id:x.value,"aria-describedby":h.value,disabled:P.value,readonly:C.value},b,{error:y.value===!1,modelValue:s.value,"onUpdate:modelValue":g=>s.value=g,onFocus:m,onBlur:f}),a)}})}),R({},t)}});export{J as V};
@@ -1 +1 @@
1
- import{l as f,k as a}from"./VSelectionControl-DbKYScD5.js";import{p as V,K as k,g as v,e as c,t as l,u as I,o as x,a as h,m as b}from"./main-BoAlbVoF.js";const C=V({indeterminate:Boolean,indeterminateIcon:{type:k,default:"$checkboxIndeterminate"},...f({falseIcon:"$checkboxOff",trueIcon:"$checkboxOn"})},"VCheckboxBtn"),B=v()({name:"VCheckboxBtn",props:C(),emits:{"update:modelValue":e=>!0,"update:indeterminate":e=>!0},setup(e,r){let{slots:s}=r;const t=c(e,"indeterminate"),n=c(e,"modelValue");function u(o){t.value&&(t.value=!1)}const i=l(()=>t.value?e.indeterminateIcon:e.falseIcon),m=l(()=>t.value?e.indeterminateIcon:e.trueIcon);return I(()=>{const o=x(a.filterProps(e),["modelValue"]);return h(a,b(o,{modelValue:n.value,"onUpdate:modelValue":[d=>n.value=d,u],class:["v-checkbox-btn",e.class],style:e.style,type:"checkbox",falseIcon:i.value,trueIcon:m.value,"aria-checked":t.value?"mixed":void 0}),s)}),{}}});export{B as V,C as m};
1
+ import{l as f,k as a}from"./VSelectionControl-CmXEFw20.js";import{p as V,K as k,g as v,e as c,t as l,u as I,o as x,a as h,m as b}from"./main-BX4TjIpG.js";const C=V({indeterminate:Boolean,indeterminateIcon:{type:k,default:"$checkboxIndeterminate"},...f({falseIcon:"$checkboxOff",trueIcon:"$checkboxOn"})},"VCheckboxBtn"),B=v()({name:"VCheckboxBtn",props:C(),emits:{"update:modelValue":e=>!0,"update:indeterminate":e=>!0},setup(e,r){let{slots:s}=r;const t=c(e,"indeterminate"),n=c(e,"modelValue");function u(o){t.value&&(t.value=!1)}const i=l(()=>t.value?e.indeterminateIcon:e.falseIcon),m=l(()=>t.value?e.indeterminateIcon:e.trueIcon);return I(()=>{const o=x(a.filterProps(e),["modelValue"]);return h(a,b(o,{modelValue:n.value,"onUpdate:modelValue":[d=>n.value=d,u],class:["v-checkbox-btn",e.class],style:e.style,type:"checkbox",falseIcon:i.value,trueIcon:m.value,"aria-checked":t.value?"mixed":void 0}),s)}),{}}});export{B as V,C as m};
@@ -1 +1 @@
1
- import{l as f,k as a}from"./VSelectionControl-DbKYScD5.js";import{p as V,K as k,g as v,e as c,t as l,u as I,o as x,a as h,m as b}from"./main-BoAlbVoF.js";const C=V({indeterminate:Boolean,indeterminateIcon:{type:k,default:"$checkboxIndeterminate"},...f({falseIcon:"$checkboxOff",trueIcon:"$checkboxOn"})},"VCheckboxBtn"),B=v()({name:"VCheckboxBtn",props:C(),emits:{"update:modelValue":e=>!0,"update:indeterminate":e=>!0},setup(e,r){let{slots:s}=r;const t=c(e,"indeterminate"),n=c(e,"modelValue");function u(o){t.value&&(t.value=!1)}const i=l(()=>t.value?e.indeterminateIcon:e.falseIcon),m=l(()=>t.value?e.indeterminateIcon:e.trueIcon);return I(()=>{const o=x(a.filterProps(e),["modelValue"]);return h(a,b(o,{modelValue:n.value,"onUpdate:modelValue":[d=>n.value=d,u],class:["v-checkbox-btn",e.class],style:e.style,type:"checkbox",falseIcon:i.value,trueIcon:m.value,"aria-checked":t.value?"mixed":void 0}),s)}),{}}});export{B as V,C as m};
1
+ import{l as f,k as a}from"./VSelectionControl-CmXEFw20.js";import{p as V,K as k,g as v,e as c,t as l,u as I,o as x,a as h,m as b}from"./main-BX4TjIpG.js";const C=V({indeterminate:Boolean,indeterminateIcon:{type:k,default:"$checkboxIndeterminate"},...f({falseIcon:"$checkboxOff",trueIcon:"$checkboxOn"})},"VCheckboxBtn"),B=v()({name:"VCheckboxBtn",props:C(),emits:{"update:modelValue":e=>!0,"update:indeterminate":e=>!0},setup(e,r){let{slots:s}=r;const t=c(e,"indeterminate"),n=c(e,"modelValue");function u(o){t.value&&(t.value=!1)}const i=l(()=>t.value?e.indeterminateIcon:e.falseIcon),m=l(()=>t.value?e.indeterminateIcon:e.trueIcon);return I(()=>{const o=x(a.filterProps(e),["modelValue"]);return h(a,b(o,{modelValue:n.value,"onUpdate:modelValue":[d=>n.value=d,u],class:["v-checkbox-btn",e.class],style:e.style,type:"checkbox",falseIcon:i.value,trueIcon:m.value,"aria-checked":t.value?"mixed":void 0}),s)}),{}}});export{B as V,C as m};