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.
- codex/choices/admin.py +4 -4
- codex/choices/statii.py +1 -1
- codex/librarian/covers/status.py +1 -1
- codex/librarian/librariand.py +2 -0
- codex/librarian/scribe/importer/const.py +8 -0
- codex/librarian/scribe/importer/create/foreign_keys.py +1 -1
- codex/librarian/scribe/importer/delete/covers.py +3 -1
- codex/librarian/scribe/importer/failed/__init__.py +1 -0
- codex/librarian/scribe/importer/failed/create.py +97 -0
- codex/librarian/scribe/importer/failed/failed.py +54 -0
- codex/librarian/scribe/importer/failed/query.py +100 -0
- codex/librarian/scribe/importer/init.py +2 -2
- codex/librarian/scribe/importer/link/covers.py +1 -1
- codex/librarian/scribe/importer/read/aggregate_path.py +4 -2
- codex/librarian/scribe/importer/search/__init__.py +1 -1
- codex/librarian/scribe/importer/search/update.py +20 -9
- codex/librarian/scribe/importer/statii/__init__.py +2 -0
- codex/librarian/scribe/importer/statii/failed.py +50 -0
- codex/librarian/scribe/importer/status.py +0 -12
- codex/librarian/scribe/janitor/janitor.py +13 -5
- codex/librarian/scribe/janitor/status.py +3 -2
- codex/librarian/scribe/search/optimize.py +1 -2
- codex/librarian/scribe/search/remove.py +2 -2
- codex/librarian/scribe/search/status.py +8 -8
- codex/librarian/scribe/search/sync.py +10 -3
- codex/librarian/scribe/status.py +2 -1
- codex/librarian/status.py +5 -5
- codex/librarian/status_controller.py +41 -20
- codex/librarian/watchdog/const.py +30 -1
- codex/librarian/watchdog/emitter.py +26 -34
- codex/librarian/watchdog/event_batcherd.py +18 -14
- codex/librarian/watchdog/observers.py +11 -15
- codex/migrations/0035_alter_librarianstatus_status_type.py +72 -0
- codex/startup/__init__.py +1 -1
- codex/static_root/assets/{VCheckbox-DSndl51k.1e28c443c3cb.js → VCheckbox-DOvv8UEO.e3653c1670c8.js} +1 -1
- codex/static_root/assets/VCheckbox-DOvv8UEO.e3653c1670c8.js.br +0 -0
- codex/static_root/assets/VCheckbox-DOvv8UEO.e3653c1670c8.js.gz +0 -0
- codex/static_root/assets/{VCheckbox-DSndl51k.js → VCheckbox-DOvv8UEO.js} +1 -1
- codex/static_root/assets/VCheckbox-DOvv8UEO.js.br +0 -0
- codex/static_root/assets/VCheckbox-DOvv8UEO.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-Bu2Pf64q.d7463473d7a2.js → VCheckboxBtn-BeZZDumo.59731a32657e.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-BeZZDumo.59731a32657e.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-BeZZDumo.59731a32657e.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-Bu2Pf64q.js → VCheckboxBtn-BeZZDumo.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-BeZZDumo.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-BeZZDumo.js.gz +0 -0
- codex/static_root/assets/{VCombobox-Uogv6Ckp.9f900e703605.js → VCombobox-BRJRW2px.369544360b22.js} +1 -1
- codex/static_root/assets/VCombobox-BRJRW2px.369544360b22.js.br +0 -0
- codex/static_root/assets/VCombobox-BRJRW2px.369544360b22.js.gz +0 -0
- codex/static_root/assets/{VCombobox-Uogv6Ckp.js → VCombobox-BRJRW2px.js} +1 -1
- codex/static_root/assets/VCombobox-BRJRW2px.js.br +0 -0
- codex/static_root/assets/VCombobox-BRJRW2px.js.gz +0 -0
- codex/static_root/assets/{VDialog-BzaGu1HN.34f52763c3f8.js → VDialog-D_vkvatj.83e078fa850c.js} +1 -1
- codex/static_root/assets/VDialog-D_vkvatj.83e078fa850c.js.br +0 -0
- codex/static_root/assets/VDialog-D_vkvatj.83e078fa850c.js.gz +0 -0
- codex/static_root/assets/{VDialog-BzaGu1HN.js → VDialog-D_vkvatj.js} +1 -1
- codex/static_root/assets/VDialog-D_vkvatj.js.br +0 -0
- codex/static_root/assets/VDialog-D_vkvatj.js.gz +0 -0
- codex/static_root/assets/{VDivider-C3ikm0Ko.4938e9ced53e.js → VDivider-BH2Oj58Z.83d2c907faff.js} +1 -1
- codex/static_root/assets/VDivider-BH2Oj58Z.83d2c907faff.js.br +0 -0
- codex/static_root/assets/VDivider-BH2Oj58Z.83d2c907faff.js.gz +0 -0
- codex/static_root/assets/{VDivider-C3ikm0Ko.js → VDivider-BH2Oj58Z.js} +1 -1
- codex/static_root/assets/VDivider-BH2Oj58Z.js.br +0 -0
- codex/static_root/assets/VDivider-BH2Oj58Z.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-AmsInZN0.5cb7c833de3d.js → VExpansionPanels-Ccv4gBFD.ed063db2e518.js} +1 -1
- codex/static_root/assets/VExpansionPanels-Ccv4gBFD.ed063db2e518.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-Ccv4gBFD.ed063db2e518.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-AmsInZN0.js → VExpansionPanels-Ccv4gBFD.js} +1 -1
- codex/static_root/assets/VExpansionPanels-Ccv4gBFD.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-Ccv4gBFD.js.gz +0 -0
- codex/static_root/assets/{VForm-CyCdgusw.c737973a1e85.js → VForm-S5eiHGJ0.d304a07dc6d1.js} +1 -1
- codex/static_root/assets/VForm-S5eiHGJ0.d304a07dc6d1.js.br +0 -0
- codex/static_root/assets/VForm-S5eiHGJ0.d304a07dc6d1.js.gz +0 -0
- codex/static_root/assets/{VForm-CyCdgusw.js → VForm-S5eiHGJ0.js} +1 -1
- codex/static_root/assets/VForm-S5eiHGJ0.js.br +0 -0
- codex/static_root/assets/VForm-S5eiHGJ0.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-BF0Xjrzi.e54d2bf41bb2.js → VRadioGroup-CyCYk3Z_.4309dbf0173c.js} +1 -1
- codex/static_root/assets/VRadioGroup-CyCYk3Z_.4309dbf0173c.js.br +0 -0
- codex/static_root/assets/VRadioGroup-CyCYk3Z_.4309dbf0173c.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-BF0Xjrzi.js → VRadioGroup-CyCYk3Z_.js} +1 -1
- codex/static_root/assets/VRadioGroup-CyCYk3Z_.js.br +0 -0
- codex/static_root/assets/VRadioGroup-CyCYk3Z_.js.gz +0 -0
- codex/static_root/assets/{VSelect-Dv50OIkN.js → VSelect-BOhtkCV1.057479737b7f.js} +1 -1
- codex/static_root/assets/VSelect-BOhtkCV1.057479737b7f.js.br +0 -0
- codex/static_root/assets/VSelect-BOhtkCV1.057479737b7f.js.gz +0 -0
- codex/static_root/assets/{VSelect-Dv50OIkN.390adb1fe7fa.js → VSelect-BOhtkCV1.js} +1 -1
- codex/static_root/assets/VSelect-BOhtkCV1.js.br +0 -0
- codex/static_root/assets/VSelect-BOhtkCV1.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-DbKYScD5.js → VSelectionControl-CmXEFw20.e256f0d0f97d.js} +1 -1
- codex/static_root/assets/VSelectionControl-CmXEFw20.e256f0d0f97d.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CmXEFw20.e256f0d0f97d.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-DbKYScD5.8d2ab1ebe546.js → VSelectionControl-CmXEFw20.js} +1 -1
- codex/static_root/assets/VSelectionControl-CmXEFw20.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CmXEFw20.js.gz +0 -0
- codex/static_root/assets/{VTable-BmOfHc7J.b2e1311009d1.js → VTable-BDxzw_rH.24ce227e6076.js} +1 -1
- codex/static_root/assets/VTable-BDxzw_rH.24ce227e6076.js.br +0 -0
- codex/static_root/assets/VTable-BDxzw_rH.24ce227e6076.js.gz +0 -0
- codex/static_root/assets/{VTable-BmOfHc7J.js → VTable-BDxzw_rH.js} +1 -1
- codex/static_root/assets/VTable-BDxzw_rH.js.br +0 -0
- codex/static_root/assets/VTable-BDxzw_rH.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-BLEDgagD.4b67c4a63c59.js → VWindowItem-CuDwxsEy.4d68002250ae.js} +1 -1
- codex/static_root/assets/VWindowItem-CuDwxsEy.4d68002250ae.js.br +0 -0
- codex/static_root/assets/VWindowItem-CuDwxsEy.4d68002250ae.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-BLEDgagD.js → VWindowItem-CuDwxsEy.js} +1 -1
- codex/static_root/assets/VWindowItem-CuDwxsEy.js.br +0 -0
- codex/static_root/assets/VWindowItem-CuDwxsEy.js.gz +0 -0
- codex/static_root/assets/{admin-kjMoKlqD.55a1dd908124.js → admin-BZQmoFts.d8e6303f8aee.js} +1 -1
- codex/static_root/assets/admin-BZQmoFts.d8e6303f8aee.js.br +0 -0
- codex/static_root/assets/admin-BZQmoFts.d8e6303f8aee.js.gz +0 -0
- codex/static_root/assets/{admin-kjMoKlqD.js → admin-BZQmoFts.js} +1 -1
- codex/static_root/assets/admin-BZQmoFts.js.br +0 -0
- codex/static_root/assets/admin-BZQmoFts.js.gz +0 -0
- codex/static_root/assets/{admin-Bv40vYZw.8179e1ece835.js → admin-U3AawSbo.f171316d0a93.js} +1 -1
- codex/static_root/assets/admin-U3AawSbo.f171316d0a93.js.br +0 -0
- codex/static_root/assets/admin-U3AawSbo.f171316d0a93.js.gz +0 -0
- codex/static_root/assets/{admin-Bv40vYZw.js → admin-U3AawSbo.js} +1 -1
- codex/static_root/assets/admin-U3AawSbo.js.br +0 -0
- codex/static_root/assets/admin-U3AawSbo.js.gz +0 -0
- codex/static_root/assets/admin-menu-D9RDVBlr.3b62ee7a8b95.js +1 -0
- codex/static_root/assets/admin-menu-D9RDVBlr.3b62ee7a8b95.js.br +0 -0
- codex/static_root/assets/admin-menu-D9RDVBlr.3b62ee7a8b95.js.gz +0 -0
- codex/static_root/assets/admin-menu-D9RDVBlr.js +1 -0
- codex/static_root/assets/admin-menu-D9RDVBlr.js.br +0 -0
- codex/static_root/assets/admin-menu-D9RDVBlr.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-RfwaqLl2.4cdd37d0dd16.js → admin-settings-button-progress-DwWq9uM1.fbacafc0db08.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-DwWq9uM1.fbacafc0db08.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-DwWq9uM1.fbacafc0db08.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-RfwaqLl2.js → admin-settings-button-progress-DwWq9uM1.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-DwWq9uM1.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-DwWq9uM1.js.gz +0 -0
- codex/static_root/assets/{browser-plYso4v5.js → browser-DFM_JsAK.bffd4eb259d8.js} +1 -1
- codex/static_root/assets/browser-DFM_JsAK.bffd4eb259d8.js.br +0 -0
- codex/static_root/assets/browser-DFM_JsAK.bffd4eb259d8.js.gz +0 -0
- codex/static_root/assets/{browser-plYso4v5.87ef04b44d37.js → browser-DFM_JsAK.js} +1 -1
- codex/static_root/assets/browser-DFM_JsAK.js.br +0 -0
- codex/static_root/assets/browser-DFM_JsAK.js.gz +0 -0
- codex/static_root/assets/{change-password-dialog-DyhQwNv1.26383853ccc0.js → change-password-dialog-yLNkzMp9.50da9f352709.js} +1 -1
- codex/static_root/assets/change-password-dialog-yLNkzMp9.50da9f352709.js.br +0 -0
- codex/static_root/assets/change-password-dialog-yLNkzMp9.50da9f352709.js.gz +0 -0
- codex/static_root/assets/{change-password-dialog-DyhQwNv1.js → change-password-dialog-yLNkzMp9.js} +1 -1
- codex/static_root/assets/change-password-dialog-yLNkzMp9.js.br +0 -0
- codex/static_root/assets/change-password-dialog-yLNkzMp9.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-B7ndwV5M.d1f0728d4bd0.js → confirm-dialog-q6RAb_qs.120460c84883.js} +1 -1
- codex/static_root/assets/confirm-dialog-q6RAb_qs.120460c84883.js.br +0 -0
- codex/static_root/assets/confirm-dialog-q6RAb_qs.120460c84883.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-B7ndwV5M.js → confirm-dialog-q6RAb_qs.js} +1 -1
- codex/static_root/assets/confirm-dialog-q6RAb_qs.js.br +0 -0
- codex/static_root/assets/confirm-dialog-q6RAb_qs.js.gz +0 -0
- codex/static_root/assets/{datetime-column-DANpNGGe.13985ff7d484.js → datetime-column-HJ5dvW99.ba0a30b3fc0d.js} +1 -1
- codex/static_root/assets/datetime-column-HJ5dvW99.ba0a30b3fc0d.js.br +0 -0
- codex/static_root/assets/datetime-column-HJ5dvW99.ba0a30b3fc0d.js.gz +0 -0
- codex/static_root/assets/{datetime-column-DANpNGGe.js → datetime-column-HJ5dvW99.js} +1 -1
- codex/static_root/assets/datetime-column-HJ5dvW99.js.br +0 -0
- codex/static_root/assets/datetime-column-HJ5dvW99.js.gz +0 -0
- codex/static_root/assets/{filter-Dhe8cVmt.ad92d3b618e3.js → filter-r_zFj-tS.161a85ef1860.js} +1 -1
- codex/static_root/assets/filter-r_zFj-tS.161a85ef1860.js.br +0 -0
- codex/static_root/assets/filter-r_zFj-tS.161a85ef1860.js.gz +0 -0
- codex/static_root/assets/{filter-Dhe8cVmt.js → filter-r_zFj-tS.js} +1 -1
- codex/static_root/assets/filter-r_zFj-tS.js.br +0 -0
- codex/static_root/assets/filter-r_zFj-tS.js.gz +0 -0
- codex/static_root/assets/{flag-tab-BZ9S7U8D.0b814b215567.js → flag-tab-D0Z4uhsg.06e720e71319.js} +1 -1
- codex/static_root/assets/flag-tab-D0Z4uhsg.06e720e71319.js.br +0 -0
- codex/static_root/assets/flag-tab-D0Z4uhsg.06e720e71319.js.gz +0 -0
- codex/static_root/assets/{flag-tab-BZ9S7U8D.js → flag-tab-D0Z4uhsg.js} +1 -1
- codex/static_root/assets/flag-tab-D0Z4uhsg.js.br +0 -0
- codex/static_root/assets/flag-tab-D0Z4uhsg.js.gz +0 -0
- codex/static_root/assets/{forwardRefs-Z0d4Mnc7.js → forwardRefs-Nj5UEeg5.50a55d7d8b68.js} +1 -1
- codex/static_root/assets/forwardRefs-Nj5UEeg5.50a55d7d8b68.js.br +0 -0
- codex/static_root/assets/forwardRefs-Nj5UEeg5.50a55d7d8b68.js.gz +0 -0
- codex/static_root/assets/{forwardRefs-Z0d4Mnc7.deb4e7a1b8b5.js → forwardRefs-Nj5UEeg5.js} +1 -1
- codex/static_root/assets/forwardRefs-Nj5UEeg5.js.br +0 -0
- codex/static_root/assets/forwardRefs-Nj5UEeg5.js.gz +0 -0
- codex/static_root/assets/{group-tab-B0ASBB3_.8e10b90ff052.js → group-tab-lamd9pcq.604a78bd4e4f.js} +1 -1
- codex/static_root/assets/group-tab-lamd9pcq.604a78bd4e4f.js.br +0 -0
- codex/static_root/assets/group-tab-lamd9pcq.604a78bd4e4f.js.gz +0 -0
- codex/static_root/assets/{group-tab-B0ASBB3_.js → group-tab-lamd9pcq.js} +1 -1
- codex/static_root/assets/group-tab-lamd9pcq.js.br +0 -0
- codex/static_root/assets/group-tab-lamd9pcq.js.gz +0 -0
- codex/static_root/assets/{http-error-BP-mMZsK.72c4d00b40d2.js → http-error-DRYA5ir1.46f4babacf15.js} +1 -1
- codex/static_root/assets/http-error-DRYA5ir1.46f4babacf15.js.br +0 -0
- codex/static_root/assets/http-error-DRYA5ir1.46f4babacf15.js.gz +0 -0
- codex/static_root/assets/{http-error-BP-mMZsK.js → http-error-DRYA5ir1.js} +1 -1
- codex/static_root/assets/http-error-DRYA5ir1.js.br +0 -0
- codex/static_root/assets/http-error-DRYA5ir1.js.gz +0 -0
- codex/static_root/assets/{index-Cu9nQXJD.49795921eada.js → index-Cl7tPJIx.c0a239cf7069.js} +1 -1
- codex/static_root/assets/index-Cl7tPJIx.c0a239cf7069.js.br +0 -0
- codex/static_root/assets/index-Cl7tPJIx.c0a239cf7069.js.gz +0 -0
- codex/static_root/assets/{index-Cu9nQXJD.js → index-Cl7tPJIx.js} +1 -1
- codex/static_root/assets/index-Cl7tPJIx.js.br +0 -0
- codex/static_root/assets/index-Cl7tPJIx.js.gz +0 -0
- codex/static_root/assets/library-tab-2UucZZAW.f4541a086231.js +1 -0
- codex/static_root/assets/library-tab-2UucZZAW.f4541a086231.js.br +0 -0
- codex/static_root/assets/library-tab-2UucZZAW.f4541a086231.js.gz +0 -0
- codex/static_root/assets/library-tab-2UucZZAW.js +1 -0
- codex/static_root/assets/library-tab-2UucZZAW.js.br +0 -0
- codex/static_root/assets/library-tab-2UucZZAW.js.gz +0 -0
- codex/static_root/assets/{library-tab-D9lxhAqv.02f7064c20f3.css → library-tab-5StL67ei.0fad8998a237.css} +1 -1
- codex/static_root/assets/library-tab-5StL67ei.0fad8998a237.css.br +0 -0
- codex/static_root/assets/library-tab-5StL67ei.0fad8998a237.css.gz +0 -0
- codex/static_root/assets/{library-tab-D9lxhAqv.css → library-tab-5StL67ei.css} +1 -1
- codex/static_root/assets/library-tab-5StL67ei.css.br +0 -0
- codex/static_root/assets/library-tab-5StL67ei.css.gz +0 -0
- codex/static_root/assets/main-BX4TjIpG.dc79406e2a7b.js +39 -0
- codex/static_root/assets/main-BX4TjIpG.dc79406e2a7b.js.br +0 -0
- codex/static_root/assets/main-BX4TjIpG.dc79406e2a7b.js.gz +0 -0
- codex/static_root/assets/main-BX4TjIpG.js +39 -0
- codex/static_root/assets/main-BX4TjIpG.js.br +0 -0
- codex/static_root/assets/main-BX4TjIpG.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-KI4NQUMe.762b6bef9373.js +1 -0
- codex/static_root/assets/pager-full-pdf-KI4NQUMe.762b6bef9373.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-KI4NQUMe.762b6bef9373.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-KI4NQUMe.js +1 -0
- codex/static_root/assets/pager-full-pdf-KI4NQUMe.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-KI4NQUMe.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-DGfRDeRW.c3f463ad6edd.js → pagination-toolbar-48pwYEe_.892375c5aa51.js} +1 -1
- codex/static_root/assets/pagination-toolbar-48pwYEe_.892375c5aa51.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-48pwYEe_.892375c5aa51.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-DGfRDeRW.js → pagination-toolbar-48pwYEe_.js} +1 -1
- codex/static_root/assets/pagination-toolbar-48pwYEe_.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-48pwYEe_.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-D6Meu4vZ.91b43d057670.js → pdf-doc-GyrCvyP5.54b26ba8d93c.js} +14 -14
- codex/static_root/assets/pdf-doc-GyrCvyP5.54b26ba8d93c.js.br +0 -0
- codex/static_root/assets/pdf-doc-GyrCvyP5.54b26ba8d93c.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-D6Meu4vZ.js → pdf-doc-GyrCvyP5.js} +14 -14
- codex/static_root/assets/pdf-doc-GyrCvyP5.js.br +0 -0
- codex/static_root/assets/pdf-doc-GyrCvyP5.js.gz +0 -0
- codex/static_root/assets/{reader-LwL05rgA.c022ad3b7b94.css → reader-HE07eoaG.8626eeb7c718.css} +1 -1
- codex/static_root/assets/reader-HE07eoaG.8626eeb7c718.css.br +0 -0
- codex/static_root/assets/reader-HE07eoaG.8626eeb7c718.css.gz +0 -0
- codex/static_root/assets/{reader-LwL05rgA.css → reader-HE07eoaG.css} +1 -1
- codex/static_root/assets/reader-HE07eoaG.css.br +0 -0
- codex/static_root/assets/reader-HE07eoaG.css.gz +0 -0
- codex/static_root/assets/reader-lmk4MiSj.9239243e1be1.js +2 -0
- codex/static_root/assets/reader-lmk4MiSj.9239243e1be1.js.br +0 -0
- codex/static_root/assets/reader-lmk4MiSj.9239243e1be1.js.gz +0 -0
- codex/static_root/assets/reader-lmk4MiSj.js +2 -0
- codex/static_root/assets/reader-lmk4MiSj.js.br +0 -0
- codex/static_root/assets/reader-lmk4MiSj.js.gz +0 -0
- codex/static_root/assets/{relation-chips-CAXZIswb.e991a259ce59.js → relation-chips-Dgb6LQdZ.c028ab2df979.js} +1 -1
- codex/static_root/assets/relation-chips-Dgb6LQdZ.c028ab2df979.js.br +0 -0
- codex/static_root/assets/relation-chips-Dgb6LQdZ.c028ab2df979.js.gz +0 -0
- codex/static_root/assets/{relation-chips-CAXZIswb.js → relation-chips-Dgb6LQdZ.js} +1 -1
- codex/static_root/assets/relation-chips-Dgb6LQdZ.js.br +0 -0
- codex/static_root/assets/relation-chips-Dgb6LQdZ.js.gz +0 -0
- codex/static_root/assets/{settings-drawer-B4gD41g6.js → settings-drawer-CRmLEncr.6937d45e18af.js} +2 -2
- codex/static_root/assets/settings-drawer-CRmLEncr.6937d45e18af.js.br +0 -0
- codex/static_root/assets/settings-drawer-CRmLEncr.6937d45e18af.js.gz +0 -0
- codex/static_root/assets/{settings-drawer-B4gD41g6.82718694498e.js → settings-drawer-CRmLEncr.js} +2 -2
- codex/static_root/assets/settings-drawer-CRmLEncr.js.br +0 -0
- codex/static_root/assets/settings-drawer-CRmLEncr.js.gz +0 -0
- codex/static_root/assets/{ssrBoot-O6yTJ_UV.7180d77d283e.js → ssrBoot-CCKPlpgB.c90fa83e0817.js} +1 -1
- codex/static_root/assets/ssrBoot-CCKPlpgB.c90fa83e0817.js.br +0 -0
- codex/static_root/assets/ssrBoot-CCKPlpgB.c90fa83e0817.js.gz +0 -0
- codex/static_root/assets/{ssrBoot-O6yTJ_UV.js → ssrBoot-CCKPlpgB.js} +1 -1
- codex/static_root/assets/ssrBoot-CCKPlpgB.js.br +0 -0
- codex/static_root/assets/ssrBoot-CCKPlpgB.js.gz +0 -0
- codex/static_root/assets/{stats-tab-BZjOg19A.afb2e6b0d648.js → stats-tab-CrU_p2gC.e12768f9423d.js} +1 -1
- codex/static_root/assets/stats-tab-CrU_p2gC.e12768f9423d.js.br +0 -0
- codex/static_root/assets/stats-tab-CrU_p2gC.e12768f9423d.js.gz +0 -0
- codex/static_root/assets/{stats-tab-BZjOg19A.js → stats-tab-CrU_p2gC.js} +1 -1
- codex/static_root/assets/stats-tab-CrU_p2gC.js.br +0 -0
- codex/static_root/assets/stats-tab-CrU_p2gC.js.gz +0 -0
- codex/static_root/assets/task-tab-Bp0wsH4V.2a5135c30818.js +1 -0
- codex/static_root/assets/task-tab-Bp0wsH4V.2a5135c30818.js.br +0 -0
- codex/static_root/assets/task-tab-Bp0wsH4V.2a5135c30818.js.gz +0 -0
- codex/static_root/assets/task-tab-Bp0wsH4V.js +1 -0
- codex/static_root/assets/task-tab-Bp0wsH4V.js.br +0 -0
- codex/static_root/assets/task-tab-Bp0wsH4V.js.gz +0 -0
- codex/static_root/assets/{unauthorized-Bo3ThIrX.12d2efd95d7d.js → unauthorized-DObmibd6.b47434919de7.js} +1 -1
- codex/static_root/assets/unauthorized-DObmibd6.b47434919de7.js.br +0 -0
- codex/static_root/assets/unauthorized-DObmibd6.b47434919de7.js.gz +0 -0
- codex/static_root/assets/{unauthorized-Bo3ThIrX.js → unauthorized-DObmibd6.js} +1 -1
- codex/static_root/assets/unauthorized-DObmibd6.js.br +0 -0
- codex/static_root/assets/unauthorized-DObmibd6.js.gz +0 -0
- codex/static_root/assets/{user-tab-BQ82qBg3.17190dc83452.js → user-tab-DedY8MbN.624af3a6a978.js} +1 -1
- codex/static_root/assets/user-tab-DedY8MbN.624af3a6a978.js.br +0 -0
- codex/static_root/assets/user-tab-DedY8MbN.624af3a6a978.js.gz +0 -0
- codex/static_root/assets/{user-tab-BQ82qBg3.js → user-tab-DedY8MbN.js} +1 -1
- codex/static_root/assets/user-tab-DedY8MbN.js.br +0 -0
- codex/static_root/assets/user-tab-DedY8MbN.js.gz +0 -0
- codex/static_root/{manifest.0dc91d0dee6d.json → manifest.4217bf6f9edb.json} +313 -313
- codex/static_root/manifest.4217bf6f9edb.json.br +0 -0
- codex/static_root/manifest.4217bf6f9edb.json.gz +0 -0
- codex/static_root/manifest.json +313 -313
- codex/static_root/manifest.json.br +0 -0
- codex/static_root/manifest.json.gz +0 -0
- codex/static_root/staticfiles.json +1 -1
- codex/views/admin/library.py +4 -1
- codex/views/browser/params.py +21 -17
- codex/views/reader/arcs.py +16 -6
- codex/views/reader/params.py +4 -1
- codex/views/session.py +1 -0
- {codex-1.8.0a2.dist-info → codex-1.8.0a3.dist-info}/METADATA +2 -2
- {codex-1.8.0a2.dist-info → codex-1.8.0a3.dist-info}/RECORD +297 -293
- codex/librarian/scribe/importer/failed_imports.py +0 -168
- codex/librarian/scribe/importer/statii/1 +0 -27
- codex/static_root/assets/VCheckbox-DSndl51k.1e28c443c3cb.js.br +0 -0
- codex/static_root/assets/VCheckbox-DSndl51k.1e28c443c3cb.js.gz +0 -0
- codex/static_root/assets/VCheckbox-DSndl51k.js.br +0 -0
- codex/static_root/assets/VCheckbox-DSndl51k.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-Bu2Pf64q.d7463473d7a2.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-Bu2Pf64q.d7463473d7a2.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-Bu2Pf64q.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-Bu2Pf64q.js.gz +0 -0
- codex/static_root/assets/VCombobox-Uogv6Ckp.9f900e703605.js.br +0 -0
- codex/static_root/assets/VCombobox-Uogv6Ckp.9f900e703605.js.gz +0 -0
- codex/static_root/assets/VCombobox-Uogv6Ckp.js.br +0 -0
- codex/static_root/assets/VCombobox-Uogv6Ckp.js.gz +0 -0
- codex/static_root/assets/VDialog-BzaGu1HN.34f52763c3f8.js.br +0 -0
- codex/static_root/assets/VDialog-BzaGu1HN.34f52763c3f8.js.gz +0 -0
- codex/static_root/assets/VDialog-BzaGu1HN.js.br +0 -0
- codex/static_root/assets/VDialog-BzaGu1HN.js.gz +0 -0
- codex/static_root/assets/VDivider-C3ikm0Ko.4938e9ced53e.js.br +0 -0
- codex/static_root/assets/VDivider-C3ikm0Ko.4938e9ced53e.js.gz +0 -0
- codex/static_root/assets/VDivider-C3ikm0Ko.js.br +0 -0
- codex/static_root/assets/VDivider-C3ikm0Ko.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-AmsInZN0.5cb7c833de3d.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-AmsInZN0.5cb7c833de3d.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-AmsInZN0.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-AmsInZN0.js.gz +0 -0
- codex/static_root/assets/VForm-CyCdgusw.c737973a1e85.js.br +0 -0
- codex/static_root/assets/VForm-CyCdgusw.c737973a1e85.js.gz +0 -0
- codex/static_root/assets/VForm-CyCdgusw.js.br +0 -0
- codex/static_root/assets/VForm-CyCdgusw.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-BF0Xjrzi.e54d2bf41bb2.js.br +0 -0
- codex/static_root/assets/VRadioGroup-BF0Xjrzi.e54d2bf41bb2.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-BF0Xjrzi.js.br +0 -0
- codex/static_root/assets/VRadioGroup-BF0Xjrzi.js.gz +0 -0
- codex/static_root/assets/VSelect-Dv50OIkN.390adb1fe7fa.js.br +0 -0
- codex/static_root/assets/VSelect-Dv50OIkN.390adb1fe7fa.js.gz +0 -0
- codex/static_root/assets/VSelect-Dv50OIkN.js.br +0 -0
- codex/static_root/assets/VSelect-Dv50OIkN.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-DbKYScD5.8d2ab1ebe546.js.br +0 -0
- codex/static_root/assets/VSelectionControl-DbKYScD5.8d2ab1ebe546.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-DbKYScD5.js.br +0 -0
- codex/static_root/assets/VSelectionControl-DbKYScD5.js.gz +0 -0
- codex/static_root/assets/VTable-BmOfHc7J.b2e1311009d1.js.br +0 -0
- codex/static_root/assets/VTable-BmOfHc7J.b2e1311009d1.js.gz +0 -0
- codex/static_root/assets/VTable-BmOfHc7J.js.br +0 -0
- codex/static_root/assets/VTable-BmOfHc7J.js.gz +0 -0
- codex/static_root/assets/VWindowItem-BLEDgagD.4b67c4a63c59.js.br +0 -0
- codex/static_root/assets/VWindowItem-BLEDgagD.4b67c4a63c59.js.gz +0 -0
- codex/static_root/assets/VWindowItem-BLEDgagD.js.br +0 -0
- codex/static_root/assets/VWindowItem-BLEDgagD.js.gz +0 -0
- codex/static_root/assets/admin-Bv40vYZw.8179e1ece835.js.br +0 -0
- codex/static_root/assets/admin-Bv40vYZw.8179e1ece835.js.gz +0 -0
- codex/static_root/assets/admin-Bv40vYZw.js.br +0 -0
- codex/static_root/assets/admin-Bv40vYZw.js.gz +0 -0
- codex/static_root/assets/admin-kjMoKlqD.55a1dd908124.js.br +0 -0
- codex/static_root/assets/admin-kjMoKlqD.55a1dd908124.js.gz +0 -0
- codex/static_root/assets/admin-kjMoKlqD.js.br +0 -0
- codex/static_root/assets/admin-kjMoKlqD.js.gz +0 -0
- codex/static_root/assets/admin-menu-BNpuOmbI.e1f62ba483cd.js +0 -1
- codex/static_root/assets/admin-menu-BNpuOmbI.e1f62ba483cd.js.br +0 -0
- codex/static_root/assets/admin-menu-BNpuOmbI.e1f62ba483cd.js.gz +0 -0
- codex/static_root/assets/admin-menu-BNpuOmbI.js +0 -1
- codex/static_root/assets/admin-menu-BNpuOmbI.js.br +0 -0
- codex/static_root/assets/admin-menu-BNpuOmbI.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-RfwaqLl2.4cdd37d0dd16.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-RfwaqLl2.4cdd37d0dd16.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-RfwaqLl2.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-RfwaqLl2.js.gz +0 -0
- codex/static_root/assets/browser-plYso4v5.87ef04b44d37.js.br +0 -0
- codex/static_root/assets/browser-plYso4v5.87ef04b44d37.js.gz +0 -0
- codex/static_root/assets/browser-plYso4v5.js.br +0 -0
- codex/static_root/assets/browser-plYso4v5.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-DyhQwNv1.26383853ccc0.js.br +0 -0
- codex/static_root/assets/change-password-dialog-DyhQwNv1.26383853ccc0.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-DyhQwNv1.js.br +0 -0
- codex/static_root/assets/change-password-dialog-DyhQwNv1.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-B7ndwV5M.d1f0728d4bd0.js.br +0 -0
- codex/static_root/assets/confirm-dialog-B7ndwV5M.d1f0728d4bd0.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-B7ndwV5M.js.br +0 -0
- codex/static_root/assets/confirm-dialog-B7ndwV5M.js.gz +0 -0
- codex/static_root/assets/datetime-column-DANpNGGe.13985ff7d484.js.br +0 -0
- codex/static_root/assets/datetime-column-DANpNGGe.13985ff7d484.js.gz +0 -0
- codex/static_root/assets/datetime-column-DANpNGGe.js.br +0 -0
- codex/static_root/assets/datetime-column-DANpNGGe.js.gz +0 -0
- codex/static_root/assets/filter-Dhe8cVmt.ad92d3b618e3.js.br +0 -0
- codex/static_root/assets/filter-Dhe8cVmt.ad92d3b618e3.js.gz +0 -0
- codex/static_root/assets/filter-Dhe8cVmt.js.br +0 -0
- codex/static_root/assets/filter-Dhe8cVmt.js.gz +0 -0
- codex/static_root/assets/flag-tab-BZ9S7U8D.0b814b215567.js.br +0 -0
- codex/static_root/assets/flag-tab-BZ9S7U8D.0b814b215567.js.gz +0 -0
- codex/static_root/assets/flag-tab-BZ9S7U8D.js.br +0 -0
- codex/static_root/assets/flag-tab-BZ9S7U8D.js.gz +0 -0
- codex/static_root/assets/forwardRefs-Z0d4Mnc7.deb4e7a1b8b5.js.br +0 -0
- codex/static_root/assets/forwardRefs-Z0d4Mnc7.deb4e7a1b8b5.js.gz +0 -0
- codex/static_root/assets/forwardRefs-Z0d4Mnc7.js.br +0 -0
- codex/static_root/assets/forwardRefs-Z0d4Mnc7.js.gz +0 -0
- codex/static_root/assets/group-tab-B0ASBB3_.8e10b90ff052.js.br +0 -0
- codex/static_root/assets/group-tab-B0ASBB3_.8e10b90ff052.js.gz +0 -0
- codex/static_root/assets/group-tab-B0ASBB3_.js.br +0 -0
- codex/static_root/assets/group-tab-B0ASBB3_.js.gz +0 -0
- codex/static_root/assets/http-error-BP-mMZsK.72c4d00b40d2.js.br +0 -0
- codex/static_root/assets/http-error-BP-mMZsK.72c4d00b40d2.js.gz +0 -0
- codex/static_root/assets/http-error-BP-mMZsK.js.br +0 -0
- codex/static_root/assets/http-error-BP-mMZsK.js.gz +0 -0
- codex/static_root/assets/index-Cu9nQXJD.49795921eada.js.br +0 -0
- codex/static_root/assets/index-Cu9nQXJD.49795921eada.js.gz +0 -0
- codex/static_root/assets/index-Cu9nQXJD.js.br +0 -0
- codex/static_root/assets/index-Cu9nQXJD.js.gz +0 -0
- codex/static_root/assets/library-tab-8g2eSuGN.846cc1674a67.js +0 -1
- codex/static_root/assets/library-tab-8g2eSuGN.846cc1674a67.js.br +0 -0
- codex/static_root/assets/library-tab-8g2eSuGN.846cc1674a67.js.gz +0 -0
- codex/static_root/assets/library-tab-8g2eSuGN.js +0 -1
- codex/static_root/assets/library-tab-8g2eSuGN.js.br +0 -0
- codex/static_root/assets/library-tab-8g2eSuGN.js.gz +0 -0
- codex/static_root/assets/library-tab-D9lxhAqv.02f7064c20f3.css.br +0 -0
- codex/static_root/assets/library-tab-D9lxhAqv.02f7064c20f3.css.gz +0 -0
- codex/static_root/assets/library-tab-D9lxhAqv.css.br +0 -0
- codex/static_root/assets/library-tab-D9lxhAqv.css.gz +0 -0
- codex/static_root/assets/main-BoAlbVoF.e41ba211717d.js +0 -39
- codex/static_root/assets/main-BoAlbVoF.e41ba211717d.js.br +0 -0
- codex/static_root/assets/main-BoAlbVoF.e41ba211717d.js.gz +0 -0
- codex/static_root/assets/main-BoAlbVoF.js +0 -39
- codex/static_root/assets/main-BoAlbVoF.js.br +0 -0
- codex/static_root/assets/main-BoAlbVoF.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-DShiSKPO.026946648650.js +0 -1
- codex/static_root/assets/pager-full-pdf-DShiSKPO.026946648650.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-DShiSKPO.026946648650.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-DShiSKPO.js +0 -1
- codex/static_root/assets/pager-full-pdf-DShiSKPO.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-DShiSKPO.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-DGfRDeRW.c3f463ad6edd.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-DGfRDeRW.c3f463ad6edd.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-DGfRDeRW.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-DGfRDeRW.js.gz +0 -0
- codex/static_root/assets/pdf-doc-D6Meu4vZ.91b43d057670.js.br +0 -0
- codex/static_root/assets/pdf-doc-D6Meu4vZ.91b43d057670.js.gz +0 -0
- codex/static_root/assets/pdf-doc-D6Meu4vZ.js.br +0 -0
- codex/static_root/assets/pdf-doc-D6Meu4vZ.js.gz +0 -0
- codex/static_root/assets/reader-CptqnqBZ.340bc756e164.js +0 -2
- codex/static_root/assets/reader-CptqnqBZ.340bc756e164.js.br +0 -0
- codex/static_root/assets/reader-CptqnqBZ.340bc756e164.js.gz +0 -0
- codex/static_root/assets/reader-CptqnqBZ.js +0 -2
- codex/static_root/assets/reader-CptqnqBZ.js.br +0 -0
- codex/static_root/assets/reader-CptqnqBZ.js.gz +0 -0
- codex/static_root/assets/reader-LwL05rgA.c022ad3b7b94.css.br +0 -0
- codex/static_root/assets/reader-LwL05rgA.c022ad3b7b94.css.gz +0 -0
- codex/static_root/assets/reader-LwL05rgA.css.br +0 -0
- codex/static_root/assets/reader-LwL05rgA.css.gz +0 -0
- codex/static_root/assets/relation-chips-CAXZIswb.e991a259ce59.js.br +0 -0
- codex/static_root/assets/relation-chips-CAXZIswb.e991a259ce59.js.gz +0 -0
- codex/static_root/assets/relation-chips-CAXZIswb.js.br +0 -0
- codex/static_root/assets/relation-chips-CAXZIswb.js.gz +0 -0
- codex/static_root/assets/settings-drawer-B4gD41g6.82718694498e.js.br +0 -0
- codex/static_root/assets/settings-drawer-B4gD41g6.82718694498e.js.gz +0 -0
- codex/static_root/assets/settings-drawer-B4gD41g6.js.br +0 -0
- codex/static_root/assets/settings-drawer-B4gD41g6.js.gz +0 -0
- codex/static_root/assets/ssrBoot-O6yTJ_UV.7180d77d283e.js.br +0 -0
- codex/static_root/assets/ssrBoot-O6yTJ_UV.7180d77d283e.js.gz +0 -0
- codex/static_root/assets/ssrBoot-O6yTJ_UV.js.br +0 -0
- codex/static_root/assets/ssrBoot-O6yTJ_UV.js.gz +0 -0
- codex/static_root/assets/stats-tab-BZjOg19A.afb2e6b0d648.js.br +0 -0
- codex/static_root/assets/stats-tab-BZjOg19A.afb2e6b0d648.js.gz +0 -0
- codex/static_root/assets/stats-tab-BZjOg19A.js.br +0 -0
- codex/static_root/assets/stats-tab-BZjOg19A.js.gz +0 -0
- codex/static_root/assets/task-tab-GP2jPkRE.cfdfb9396ec4.js +0 -1
- codex/static_root/assets/task-tab-GP2jPkRE.cfdfb9396ec4.js.br +0 -0
- codex/static_root/assets/task-tab-GP2jPkRE.cfdfb9396ec4.js.gz +0 -0
- codex/static_root/assets/task-tab-GP2jPkRE.js +0 -1
- codex/static_root/assets/task-tab-GP2jPkRE.js.br +0 -0
- codex/static_root/assets/task-tab-GP2jPkRE.js.gz +0 -0
- codex/static_root/assets/unauthorized-Bo3ThIrX.12d2efd95d7d.js.br +0 -0
- codex/static_root/assets/unauthorized-Bo3ThIrX.12d2efd95d7d.js.gz +0 -0
- codex/static_root/assets/unauthorized-Bo3ThIrX.js.br +0 -0
- codex/static_root/assets/unauthorized-Bo3ThIrX.js.gz +0 -0
- codex/static_root/assets/user-tab-BQ82qBg3.17190dc83452.js.br +0 -0
- codex/static_root/assets/user-tab-BQ82qBg3.17190dc83452.js.gz +0 -0
- codex/static_root/assets/user-tab-BQ82qBg3.js.br +0 -0
- codex/static_root/assets/user-tab-BQ82qBg3.js.gz +0 -0
- codex/static_root/manifest.0dc91d0dee6d.json.br +0 -0
- codex/static_root/manifest.0dc91d0dee6d.json.gz +0 -0
- {codex-1.8.0a2.dist-info → codex-1.8.0a3.dist-info}/WHEEL +0 -0
- {codex-1.8.0a2.dist-info → codex-1.8.0a3.dist-info}/entry_points.txt +0 -0
- {codex-1.8.0a2.dist-info → codex-1.8.0a3.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
|
|
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.
|
|
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
|
|
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
|
codex/librarian/covers/status.py
CHANGED
codex/librarian/librariand.py
CHANGED
|
@@ -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=
|
|
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(
|
|
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,100 @@
|
|
|
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 and need to be replaced
|
|
43
|
+
# with a recursive level by level matcher.
|
|
44
|
+
for path_obj in Path(path).parent.iterdir():
|
|
45
|
+
if path_obj.name.casefold() == name:
|
|
46
|
+
break
|
|
47
|
+
else:
|
|
48
|
+
missing_failed_import_paths.add(path)
|
|
49
|
+
|
|
50
|
+
return succeeded_failed_imports | missing_failed_import_paths
|
|
51
|
+
|
|
52
|
+
def _query_failed_imports(
|
|
53
|
+
self,
|
|
54
|
+
) -> tuple[
|
|
55
|
+
ImporterFailedImportsUpdateStatus | None,
|
|
56
|
+
ImporterFailedImportsCreateStatus | None,
|
|
57
|
+
ImporterFailedImportsDeleteStatus | None,
|
|
58
|
+
]:
|
|
59
|
+
"""Determine what to do with failed imports."""
|
|
60
|
+
status = ImporterFailedImportsQueryStatus(0)
|
|
61
|
+
update_status = create_status = delete_status = None
|
|
62
|
+
try:
|
|
63
|
+
self.status_controller.start(status)
|
|
64
|
+
# Calculate creates and updates
|
|
65
|
+
fis = self.metadata.pop(FIS, {})
|
|
66
|
+
existing_failed_import_paths = set(
|
|
67
|
+
FailedImport.objects.filter(library=self.library).values_list(
|
|
68
|
+
"path", flat=True
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
status.total = len(fis) + len(existing_failed_import_paths)
|
|
72
|
+
self.status_controller.update(status)
|
|
73
|
+
self.metadata[UPDATE_FIS] = {}
|
|
74
|
+
self.metadata[CREATE_FIS] = {}
|
|
75
|
+
for path, exc in fis.items():
|
|
76
|
+
if path in existing_failed_import_paths:
|
|
77
|
+
self.metadata[UPDATE_FIS][path] = exc
|
|
78
|
+
else:
|
|
79
|
+
self.metadata[CREATE_FIS][path] = exc
|
|
80
|
+
status.increment_complete()
|
|
81
|
+
self.status_controller.update(status)
|
|
82
|
+
if num_update := len(self.metadata[UPDATE_FIS]):
|
|
83
|
+
update_status = ImporterFailedImportsUpdateStatus(0, num_update)
|
|
84
|
+
self.status_controller.update(update_status)
|
|
85
|
+
if num_create := len(self.metadata[CREATE_FIS]):
|
|
86
|
+
create_status = ImporterFailedImportsCreateStatus(0, num_create)
|
|
87
|
+
self.status_controller.update(create_status)
|
|
88
|
+
|
|
89
|
+
if DELETE_FI_PATHS not in self.metadata:
|
|
90
|
+
self.metadata[DELETE_FI_PATHS] = set()
|
|
91
|
+
self.metadata[DELETE_FI_PATHS] |= self._query_failed_import_deletes(
|
|
92
|
+
existing_failed_import_paths, fis.keys()
|
|
93
|
+
)
|
|
94
|
+
status.increment_complete(len(existing_failed_import_paths))
|
|
95
|
+
if num_delete := len(self.metadata[DELETE_FI_PATHS]):
|
|
96
|
+
delete_status = ImporterFailedImportsDeleteStatus(0, num_delete)
|
|
97
|
+
self.status_controller.update(delete_status)
|
|
98
|
+
finally:
|
|
99
|
+
self.status_controller.finish(status, notify=True)
|
|
100
|
+
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
|
-
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
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."""
|
|
@@ -128,7 +128,7 @@ class SearchIndexCreateUpdateImporter(SearchIndexSyncManyToManyImporter):
|
|
|
128
128
|
*,
|
|
129
129
|
create: bool,
|
|
130
130
|
):
|
|
131
|
-
if self.abort_event.is_set():
|
|
131
|
+
if not obj_list or self.abort_event.is_set():
|
|
132
132
|
return
|
|
133
133
|
verb = "create" if create else "update"
|
|
134
134
|
verbing = (verb[:-1] + "ing").capitalize()
|
|
@@ -161,6 +161,10 @@ class SearchIndexCreateUpdateImporter(SearchIndexSyncManyToManyImporter):
|
|
|
161
161
|
self.log.debug(f"No search entries to {verb}.")
|
|
162
162
|
return updated_pks
|
|
163
163
|
self.status_controller.start(status)
|
|
164
|
+
verbing = "creating" if create else "updating"
|
|
165
|
+
self.log.debug(
|
|
166
|
+
f"Preparing {total_entries} comics for search index {verbing}..."
|
|
167
|
+
)
|
|
164
168
|
|
|
165
169
|
obj_list = []
|
|
166
170
|
if create:
|
|
@@ -173,20 +177,27 @@ class SearchIndexCreateUpdateImporter(SearchIndexSyncManyToManyImporter):
|
|
|
173
177
|
self._create_comicfts_entry(pk, entry, obj_list, status)
|
|
174
178
|
updated_pks = pks
|
|
175
179
|
else:
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
if pks := tuple(self.metadata[FTS_UPDATE].keys()):
|
|
181
|
+
comicftss = ComicFTS.objects.filter(comic_id__in=pks)
|
|
182
|
+
for comicfts in comicftss:
|
|
183
|
+
if self.abort_event.is_set():
|
|
184
|
+
return updated_pks
|
|
185
|
+
self._update_comicfts_entry(comicfts, obj_list, status)
|
|
186
|
+
if self.metadata[FTS_UPDATE]:
|
|
187
|
+
# If updates not popped, turn them into creates.
|
|
188
|
+
if FTS_CREATE not in self.metadata:
|
|
189
|
+
self.metadata[FTS_CREATE] = {}
|
|
190
|
+
self.metadata[FTS_CREATE].update(self.metadata[FTS_UPDATE])
|
|
182
191
|
self.metadata.pop(FTS_UPDATE)
|
|
183
|
-
|
|
184
|
-
|
|
192
|
+
self.log.debug(
|
|
193
|
+
f"Prepared {len(obj_list)} comics for search index {verbing}..."
|
|
194
|
+
)
|
|
185
195
|
self._update_search_index_create_or_update(
|
|
186
196
|
obj_list,
|
|
187
197
|
status,
|
|
188
198
|
create=create,
|
|
189
199
|
)
|
|
200
|
+
updated_pks = pks
|
|
190
201
|
|
|
191
202
|
finally:
|
|
192
203
|
self.status_controller.finish(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
|
-
|
|
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(),
|
|
@@ -44,6 +44,7 @@ class JanitorCodexUpdateStatus(JanitorStatus):
|
|
|
44
44
|
VERB = "Update"
|
|
45
45
|
ITEM_NAME = "Codex server software"
|
|
46
46
|
SINGLE = True
|
|
47
|
+
log_success = True
|
|
47
48
|
|
|
48
49
|
|
|
49
50
|
class JanitorDBOptimizeStatus(JanitorStatus):
|
|
@@ -53,7 +54,7 @@ class JanitorDBOptimizeStatus(JanitorStatus):
|
|
|
53
54
|
VERB = "Optimize"
|
|
54
55
|
ITEM_NAME = "database"
|
|
55
56
|
SINGLE = True
|
|
56
|
-
|
|
57
|
+
log_success = True
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
class JanitorDBBackupStatus(JanitorStatus):
|
|
@@ -131,7 +132,7 @@ class JanitorDBFTSRebuildStatus(JanitorStatus):
|
|
|
131
132
|
_verbed = "Rebuilt"
|
|
132
133
|
ITEM_NAME = "full text search virtual table"
|
|
133
134
|
SINGLE = True
|
|
134
|
-
|
|
135
|
+
log_success = True
|
|
135
136
|
|
|
136
137
|
|
|
137
138
|
JANITOR_STATII = (
|
|
@@ -21,8 +21,7 @@ class SearchIndexerOptimize(WorkerStatusMixin):
|
|
|
21
21
|
"""Remove records not in the database from the index, trapping exceptions."""
|
|
22
22
|
status = SearchIndexOptimizeStatus()
|
|
23
23
|
try:
|
|
24
|
-
self.status_controller.
|
|
25
|
-
self.log.debug("Optimizing search index...")
|
|
24
|
+
self.status_controller.start(status)
|
|
26
25
|
with connection.cursor() as cursor:
|
|
27
26
|
cursor.execute(_OPTIMIZE_SQL)
|
|
28
27
|
except Exception:
|
|
@@ -31,10 +31,10 @@ class SearchIndexerRemove(SearchIndexerOptimize):
|
|
|
31
31
|
status.complete = count
|
|
32
32
|
return count
|
|
33
33
|
|
|
34
|
-
def remove_stale_records(self) -> int:
|
|
34
|
+
def remove_stale_records(self, *, log_success: bool = True) -> int:
|
|
35
35
|
"""Remove records not in the database from the index, trapping exceptions."""
|
|
36
36
|
count = 0
|
|
37
|
-
status = SearchIndexCleanStatus()
|
|
37
|
+
status = SearchIndexCleanStatus(log_success=log_success)
|
|
38
38
|
try:
|
|
39
39
|
count = self._remove_stale_records(status)
|
|
40
40
|
except Exception:
|