codex 1.7.3__py3-none-any.whl → 1.7.3a0__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/asgi.py +1 -2
- codex/choices.py +12 -3
- codex/choices_to_json.py +8 -8
- codex/db.py +2 -2
- codex/exceptions.py +6 -5
- codex/librarian/bookmark/bookmarkd.py +4 -8
- codex/librarian/bookmark/update.py +2 -2
- codex/librarian/covers/create.py +8 -10
- codex/librarian/covers/path.py +5 -6
- codex/librarian/covers/purge.py +2 -2
- codex/librarian/importer/aggregate.py +2 -2
- codex/librarian/importer/cache.py +4 -1
- codex/librarian/importer/create_comics.py +2 -2
- codex/librarian/importer/create_covers.py +1 -1
- codex/librarian/importer/create_fks.py +3 -4
- codex/librarian/importer/deleted.py +3 -3
- codex/librarian/importer/extract.py +2 -2
- codex/librarian/importer/failed_imports.py +1 -1
- codex/librarian/importer/importer.py +1 -3
- codex/librarian/importer/importerd.py +3 -3
- codex/librarian/importer/link_comics.py +1 -2
- codex/librarian/importer/moved.py +7 -2
- codex/librarian/importer/query_fks.py +4 -1
- codex/librarian/importer/tasks.py +1 -1
- codex/librarian/janitor/integrity.py +20 -27
- codex/librarian/janitor/janitor.py +8 -1
- codex/librarian/janitor/latest_version.py +1 -1
- codex/librarian/janitor/log_compress.py +77 -0
- codex/librarian/janitor/status.py +1 -0
- codex/librarian/janitor/tasks.py +5 -0
- codex/librarian/janitor/update.py +2 -2
- codex/librarian/janitor/vacuum.py +1 -1
- codex/librarian/librariand.py +7 -3
- codex/librarian/notifier/notifierd.py +1 -2
- codex/librarian/search/optimize.py +1 -1
- codex/librarian/search/remove.py +1 -1
- codex/librarian/search/update.py +3 -3
- codex/librarian/telemeter/stats.py +6 -7
- codex/librarian/telemeter/telemeter.py +1 -0
- codex/librarian/watchdog/db_snapshot.py +3 -3
- codex/librarian/watchdog/dir_snapshot_diff.py +4 -3
- codex/librarian/watchdog/emitter.py +4 -4
- codex/librarian/watchdog/event_batcherd.py +1 -2
- codex/librarian/watchdog/events.py +2 -1
- codex/librarian/watchdog/observers.py +10 -15
- codex/logger/loggerd.py +17 -40
- codex/logger/logging.py +1 -1
- codex/memory.py +2 -3
- codex/migrations/0001_init.py +2 -1
- codex/migrations/0014_pdf_issue_suffix_remove_cover_image_sort_name.py +2 -1
- codex/migrations/0018_rename_userbookmark_bookmark.py +2 -1
- codex/migrations/0028_telemeter.py +5 -1
- codex/migrations/0031_adminflag_banner.py +1 -1
- codex/models/admin.py +1 -1
- codex/models/base.py +1 -3
- codex/models/bookmark.py +7 -4
- codex/models/comic.py +2 -2
- codex/models/functions.py +5 -12
- codex/models/groups.py +1 -1
- codex/models/library.py +1 -1
- codex/models/paths.py +4 -4
- codex/models/query.py +4 -8
- codex/models/util.py +1 -1
- codex/permissions.py +1 -1
- codex/run.py +1 -1
- codex/serializers/admin/libraries.py +3 -1
- codex/serializers/browser/choices.py +2 -2
- codex/serializers/browser/mixins.py +1 -5
- codex/serializers/browser/settings.py +2 -2
- codex/serializers/fields.py +7 -7
- codex/serializers/models/base.py +1 -1
- codex/serializers/models/comic.py +2 -2
- codex/serializers/models/groups.py +2 -0
- codex/serializers/opds/authentication.py +1 -2
- codex/serializers/opds/v2/feed.py +1 -2
- codex/serializers/opds/v2/links.py +12 -14
- codex/serializers/opds/v2/metadata.py +1 -2
- codex/serializers/opds/v2/progression.py +2 -4
- codex/serializers/opds/v2/publication.py +11 -14
- codex/serializers/opds/v2/unused.py +8 -15
- codex/serializers/route.py +2 -2
- codex/settings/settings.py +4 -4
- codex/signals/django_signals.py +1 -1
- codex/static_root/assets/{VCheckbox-Dv6fwaDb.56abbfb00c8a.js → VCheckbox-pHjSEgdV.176f3c1f4191.js} +1 -1
- codex/static_root/assets/VCheckbox-pHjSEgdV.176f3c1f4191.js.br +0 -0
- codex/static_root/assets/VCheckbox-pHjSEgdV.176f3c1f4191.js.gz +0 -0
- codex/static_root/assets/{VCheckbox-Dv6fwaDb.js → VCheckbox-pHjSEgdV.js} +1 -1
- codex/static_root/assets/VCheckbox-pHjSEgdV.js.br +0 -0
- codex/static_root/assets/VCheckbox-pHjSEgdV.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-CNMFahfF.4ee9778a562e.js → VCheckboxBtn-DBKqrZGq.467e75859b62.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.467e75859b62.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.467e75859b62.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-CNMFahfF.js → VCheckboxBtn-DBKqrZGq.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DBKqrZGq.js.gz +0 -0
- codex/static_root/assets/{VCombobox-DqBFki-9.2806f95c938d.js → VCombobox-Bg7uOTbF.2fc6073b789f.js} +1 -1
- codex/static_root/assets/VCombobox-Bg7uOTbF.2fc6073b789f.js.br +0 -0
- codex/static_root/assets/VCombobox-Bg7uOTbF.2fc6073b789f.js.gz +0 -0
- codex/static_root/assets/{VCombobox-DqBFki-9.js → VCombobox-Bg7uOTbF.js} +1 -1
- codex/static_root/assets/VCombobox-Bg7uOTbF.js.br +0 -0
- codex/static_root/assets/VCombobox-Bg7uOTbF.js.gz +0 -0
- codex/static_root/assets/{VDialog-CQXjBvDZ.1a576c5e472f.js → VDialog-IrbBYFLM.91a058d572c4.js} +1 -1
- codex/static_root/assets/VDialog-IrbBYFLM.91a058d572c4.js.br +0 -0
- codex/static_root/assets/VDialog-IrbBYFLM.91a058d572c4.js.gz +0 -0
- codex/static_root/assets/{VDialog-CQXjBvDZ.js → VDialog-IrbBYFLM.js} +1 -1
- codex/static_root/assets/VDialog-IrbBYFLM.js.br +0 -0
- codex/static_root/assets/VDialog-IrbBYFLM.js.gz +0 -0
- codex/static_root/assets/{VDivider-DUxQu-IZ.73d92ae2a07e.js → VDivider-CuRohbVQ.3c12b040aed7.js} +1 -1
- codex/static_root/assets/VDivider-CuRohbVQ.3c12b040aed7.js.br +0 -0
- codex/static_root/assets/VDivider-CuRohbVQ.3c12b040aed7.js.gz +0 -0
- codex/static_root/assets/{VDivider-DUxQu-IZ.js → VDivider-CuRohbVQ.js} +1 -1
- codex/static_root/assets/VDivider-CuRohbVQ.js.br +0 -0
- codex/static_root/assets/VDivider-CuRohbVQ.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-BaYzHUJp.5346826103eb.js → VExpansionPanels-b0xWLH75.bff6ea8b4055.js} +1 -1
- codex/static_root/assets/VExpansionPanels-b0xWLH75.bff6ea8b4055.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-b0xWLH75.bff6ea8b4055.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-BaYzHUJp.js → VExpansionPanels-b0xWLH75.js} +1 -1
- codex/static_root/assets/VExpansionPanels-b0xWLH75.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-b0xWLH75.js.gz +0 -0
- codex/static_root/assets/{VForm-hB4C5jVd.a2b90ddcd8ee.js → VForm-B4hkqnS8.afbd5cf0908a.js} +1 -1
- codex/static_root/assets/VForm-B4hkqnS8.afbd5cf0908a.js.br +0 -0
- codex/static_root/assets/VForm-B4hkqnS8.afbd5cf0908a.js.gz +0 -0
- codex/static_root/assets/{VForm-hB4C5jVd.js → VForm-B4hkqnS8.js} +1 -1
- codex/static_root/assets/VForm-B4hkqnS8.js.br +0 -0
- codex/static_root/assets/VForm-B4hkqnS8.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DOjw38qB.cbf2922d05af.js → VRadioGroup-Cbayik6d.034f0f275265.js} +1 -1
- codex/static_root/assets/VRadioGroup-Cbayik6d.034f0f275265.js.br +0 -0
- codex/static_root/assets/VRadioGroup-Cbayik6d.034f0f275265.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DOjw38qB.js → VRadioGroup-Cbayik6d.js} +1 -1
- codex/static_root/assets/VRadioGroup-Cbayik6d.js.br +0 -0
- codex/static_root/assets/VRadioGroup-Cbayik6d.js.gz +0 -0
- codex/static_root/assets/{VSelect-L4v_m3ag.db9fb8348617.js → VSelect-BsuB-2P1.abe187c8b53f.js} +1 -1
- codex/static_root/assets/VSelect-BsuB-2P1.abe187c8b53f.js.br +0 -0
- codex/static_root/assets/VSelect-BsuB-2P1.abe187c8b53f.js.gz +0 -0
- codex/static_root/assets/{VSelect-L4v_m3ag.js → VSelect-BsuB-2P1.js} +1 -1
- codex/static_root/assets/VSelect-BsuB-2P1.js.br +0 -0
- codex/static_root/assets/VSelect-BsuB-2P1.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-BqB1JeKa.2fb68a673402.js → VSelectionControl-L41n5bnX.f4674bb62425.js} +1 -1
- codex/static_root/assets/VSelectionControl-L41n5bnX.f4674bb62425.js.br +0 -0
- codex/static_root/assets/VSelectionControl-L41n5bnX.f4674bb62425.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-BqB1JeKa.js → VSelectionControl-L41n5bnX.js} +1 -1
- codex/static_root/assets/VSelectionControl-L41n5bnX.js.br +0 -0
- codex/static_root/assets/VSelectionControl-L41n5bnX.js.gz +0 -0
- codex/static_root/assets/{VTable-CtorAbOx.bbda450cbd73.js → VTable-CYv4gUUt.76e4658abeb3.js} +1 -1
- codex/static_root/assets/VTable-CYv4gUUt.76e4658abeb3.js.br +0 -0
- codex/static_root/assets/VTable-CYv4gUUt.76e4658abeb3.js.gz +0 -0
- codex/static_root/assets/{VTable-CtorAbOx.js → VTable-CYv4gUUt.js} +1 -1
- codex/static_root/assets/VTable-CYv4gUUt.js.br +0 -0
- codex/static_root/assets/VTable-CYv4gUUt.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-Bl-fa3ss.334e6b813775.js → VWindowItem-f8UkxXa_.1d3e9e78fc9b.js} +1 -1
- codex/static_root/assets/VWindowItem-f8UkxXa_.1d3e9e78fc9b.js.br +0 -0
- codex/static_root/assets/VWindowItem-f8UkxXa_.1d3e9e78fc9b.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-Bl-fa3ss.js → VWindowItem-f8UkxXa_.js} +1 -1
- codex/static_root/assets/VWindowItem-f8UkxXa_.js.br +0 -0
- codex/static_root/assets/VWindowItem-f8UkxXa_.js.gz +0 -0
- codex/static_root/assets/{admin-BAVKNREt.23c0966bd683.js → admin-BmuWJcAB.b0b253aefd88.js} +1 -1
- codex/static_root/assets/admin-BmuWJcAB.b0b253aefd88.js.br +0 -0
- codex/static_root/assets/admin-BmuWJcAB.b0b253aefd88.js.gz +0 -0
- codex/static_root/assets/{admin-BAVKNREt.js → admin-BmuWJcAB.js} +1 -1
- codex/static_root/assets/admin-BmuWJcAB.js.br +0 -0
- codex/static_root/assets/admin-BmuWJcAB.js.gz +0 -0
- codex/static_root/assets/{admin-CHuFhx_t.a54700f97fc8.js → admin-Izb24SXM.504ea9d9515c.js} +1 -1
- codex/static_root/assets/admin-Izb24SXM.504ea9d9515c.js.br +0 -0
- codex/static_root/assets/admin-Izb24SXM.504ea9d9515c.js.gz +0 -0
- codex/static_root/assets/{admin-CHuFhx_t.js → admin-Izb24SXM.js} +1 -1
- codex/static_root/assets/admin-Izb24SXM.js.br +0 -0
- codex/static_root/assets/admin-Izb24SXM.js.gz +0 -0
- codex/static_root/assets/admin-dm3bSP7O.ae1234cc0beb.css +1 -0
- codex/static_root/assets/admin-dm3bSP7O.ae1234cc0beb.css.br +0 -0
- codex/static_root/assets/admin-dm3bSP7O.ae1234cc0beb.css.gz +0 -0
- codex/static_root/assets/admin-dm3bSP7O.css +1 -0
- codex/static_root/assets/admin-dm3bSP7O.css.br +0 -0
- codex/static_root/assets/admin-dm3bSP7O.css.gz +0 -0
- codex/static_root/assets/admin-menu-C712OV-9.ecd1f2af4cf4.js +1 -0
- codex/static_root/assets/admin-menu-C712OV-9.ecd1f2af4cf4.js.br +0 -0
- codex/static_root/assets/admin-menu-C712OV-9.ecd1f2af4cf4.js.gz +0 -0
- codex/static_root/assets/admin-menu-C712OV-9.js +1 -0
- codex/static_root/assets/admin-menu-C712OV-9.js.br +0 -0
- codex/static_root/assets/admin-menu-C712OV-9.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-w_CqTSMl.7b36216f68b5.js → admin-settings-button-progress-Clv9yQ7G.2536580dece1.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.2536580dece1.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.2536580dece1.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-w_CqTSMl.js → admin-settings-button-progress-Clv9yQ7G.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-Clv9yQ7G.js.gz +0 -0
- codex/static_root/assets/{browser-DNzQvgkY.aea8b7d7ca40.css → browser-CReWGhn_.521193ab0710.css} +1 -1
- codex/static_root/assets/browser-CReWGhn_.521193ab0710.css.br +0 -0
- codex/static_root/assets/browser-CReWGhn_.521193ab0710.css.gz +0 -0
- codex/static_root/assets/{browser-DNzQvgkY.css → browser-CReWGhn_.css} +1 -1
- codex/static_root/assets/browser-CReWGhn_.css.br +0 -0
- codex/static_root/assets/browser-CReWGhn_.css.gz +0 -0
- codex/static_root/assets/browser-DiAN9Ipo.a5b62a3cbe1d.js +1 -0
- codex/static_root/assets/browser-DiAN9Ipo.a5b62a3cbe1d.js.br +0 -0
- codex/static_root/assets/browser-DiAN9Ipo.a5b62a3cbe1d.js.gz +0 -0
- codex/static_root/assets/browser-DiAN9Ipo.js +1 -0
- codex/static_root/assets/browser-DiAN9Ipo.js.br +0 -0
- codex/static_root/assets/browser-DiAN9Ipo.js.gz +0 -0
- codex/static_root/assets/{change-password-dialog-Cy1tU-tj.416ef5bdfd46.js → change-password-dialog-BZPmAOML.73fdc23e13a4.js} +1 -1
- codex/static_root/assets/change-password-dialog-BZPmAOML.73fdc23e13a4.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BZPmAOML.73fdc23e13a4.js.gz +0 -0
- codex/static_root/assets/{change-password-dialog-Cy1tU-tj.js → change-password-dialog-BZPmAOML.js} +1 -1
- codex/static_root/assets/change-password-dialog-BZPmAOML.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BZPmAOML.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-B_Y3KKiL.1070d18f6b2d.js → confirm-dialog-CBLQOik_.f53acd0c622a.js} +1 -1
- codex/static_root/assets/confirm-dialog-CBLQOik_.f53acd0c622a.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CBLQOik_.f53acd0c622a.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-B_Y3KKiL.js → confirm-dialog-CBLQOik_.js} +1 -1
- codex/static_root/assets/confirm-dialog-CBLQOik_.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CBLQOik_.js.gz +0 -0
- codex/static_root/assets/{datetime-column-DVC0YqHC.03bb52c198e9.js → datetime-column-CU19rCbi.9edc0d2da736.js} +1 -1
- codex/static_root/assets/datetime-column-CU19rCbi.9edc0d2da736.js.br +1 -0
- codex/static_root/assets/datetime-column-CU19rCbi.9edc0d2da736.js.gz +0 -0
- codex/static_root/assets/{datetime-column-DVC0YqHC.js → datetime-column-CU19rCbi.js} +1 -1
- codex/static_root/assets/datetime-column-CU19rCbi.js.br +1 -0
- codex/static_root/assets/datetime-column-CU19rCbi.js.gz +0 -0
- codex/static_root/assets/{filter-xcEcgcIx.be1bb4725c89.js → filter-CZ7kkBLq.171b4fcba146.js} +1 -1
- codex/static_root/assets/filter-CZ7kkBLq.171b4fcba146.js.br +0 -0
- codex/static_root/assets/filter-CZ7kkBLq.171b4fcba146.js.gz +0 -0
- codex/static_root/assets/{filter-xcEcgcIx.js → filter-CZ7kkBLq.js} +1 -1
- codex/static_root/assets/filter-CZ7kkBLq.js.br +0 -0
- codex/static_root/assets/filter-CZ7kkBLq.js.gz +0 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.2b7ef394b850.css +1 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.2b7ef394b850.css.br +0 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.2b7ef394b850.css.gz +0 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.css +1 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.css.br +0 -0
- codex/static_root/assets/flag-tab-DHGfv0Q3.css.gz +0 -0
- codex/static_root/assets/flag-tab-kcBN36xe.631c48ab75fd.js +1 -0
- codex/static_root/assets/flag-tab-kcBN36xe.631c48ab75fd.js.br +0 -0
- codex/static_root/assets/flag-tab-kcBN36xe.631c48ab75fd.js.gz +0 -0
- codex/static_root/assets/flag-tab-kcBN36xe.js +1 -0
- codex/static_root/assets/flag-tab-kcBN36xe.js.br +0 -0
- codex/static_root/assets/flag-tab-kcBN36xe.js.gz +0 -0
- codex/static_root/assets/{forwardRefs-D1ZDjzWx.96fccf773093.js → forwardRefs-DNAemYUk.06a315272ed9.js} +1 -1
- codex/static_root/assets/forwardRefs-DNAemYUk.06a315272ed9.js.br +0 -0
- codex/static_root/assets/forwardRefs-DNAemYUk.06a315272ed9.js.gz +0 -0
- codex/static_root/assets/{forwardRefs-D1ZDjzWx.js → forwardRefs-DNAemYUk.js} +1 -1
- codex/static_root/assets/forwardRefs-DNAemYUk.js.br +0 -0
- codex/static_root/assets/forwardRefs-DNAemYUk.js.gz +0 -0
- codex/static_root/assets/{group-tab-DkAIGL8z.527cad03c21d.js → group-tab-D9gwAdJc.60fb0ffa734c.js} +1 -1
- codex/static_root/assets/group-tab-D9gwAdJc.60fb0ffa734c.js.br +0 -0
- codex/static_root/assets/group-tab-D9gwAdJc.60fb0ffa734c.js.gz +0 -0
- codex/static_root/assets/{group-tab-DkAIGL8z.js → group-tab-D9gwAdJc.js} +1 -1
- codex/static_root/assets/group-tab-D9gwAdJc.js.br +0 -0
- codex/static_root/assets/group-tab-D9gwAdJc.js.gz +0 -0
- codex/static_root/assets/{http-error-CjSb8orc.ad6fc5733ed8.js → http-error-DmFqD2Xz.593d626b5f1b.js} +1 -1
- codex/static_root/assets/http-error-DmFqD2Xz.593d626b5f1b.js.br +0 -0
- codex/static_root/assets/http-error-DmFqD2Xz.593d626b5f1b.js.gz +0 -0
- codex/static_root/assets/{http-error-CjSb8orc.js → http-error-DmFqD2Xz.js} +1 -1
- codex/static_root/assets/http-error-DmFqD2Xz.js.br +0 -0
- codex/static_root/assets/http-error-DmFqD2Xz.js.gz +0 -0
- codex/static_root/assets/{index-CoFXW6I0.27f397e1425e.js → index-hvGLIBbY.30ce8cca0c6d.js} +1 -1
- codex/static_root/assets/index-hvGLIBbY.30ce8cca0c6d.js.br +0 -0
- codex/static_root/assets/index-hvGLIBbY.30ce8cca0c6d.js.gz +0 -0
- codex/static_root/assets/{index-CoFXW6I0.js → index-hvGLIBbY.js} +1 -1
- codex/static_root/assets/index-hvGLIBbY.js.br +0 -0
- codex/static_root/assets/index-hvGLIBbY.js.gz +0 -0
- codex/static_root/assets/{library-tab-hkMMBz1x.02270491d822.js → library-tab-CF-RAEgP.a0ad816fb994.js} +1 -1
- codex/static_root/assets/library-tab-CF-RAEgP.a0ad816fb994.js.br +0 -0
- codex/static_root/assets/library-tab-CF-RAEgP.a0ad816fb994.js.gz +0 -0
- codex/static_root/assets/{library-tab-hkMMBz1x.js → library-tab-CF-RAEgP.js} +1 -1
- codex/static_root/assets/library-tab-CF-RAEgP.js.br +0 -0
- codex/static_root/assets/library-tab-CF-RAEgP.js.gz +0 -0
- codex/static_root/assets/{main-DCaPxp2h.076707ddd123.js → main-Dv8e0bMI.bd74f1ba1627.js} +10 -10
- codex/static_root/assets/main-Dv8e0bMI.bd74f1ba1627.js.br +0 -0
- codex/static_root/assets/main-Dv8e0bMI.bd74f1ba1627.js.gz +0 -0
- codex/static_root/assets/{main-DCaPxp2h.js → main-Dv8e0bMI.js} +10 -10
- codex/static_root/assets/main-Dv8e0bMI.js.br +0 -0
- codex/static_root/assets/main-Dv8e0bMI.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.04a4f5c451b4.js +1 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.04a4f5c451b4.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.04a4f5c451b4.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.js +1 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-BXd9Y5oQ.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-DoqxSygU.f985bc705fe5.js → pagination-toolbar-D_whea1o.9bbd927058f1.js} +1 -1
- codex/static_root/assets/pagination-toolbar-D_whea1o.9bbd927058f1.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-D_whea1o.9bbd927058f1.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-DoqxSygU.js → pagination-toolbar-D_whea1o.js} +1 -1
- codex/static_root/assets/pagination-toolbar-D_whea1o.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-D_whea1o.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-BwxvAx1z.96cbc39c321d.js → pdf-doc-dnr5fHbU.fa1d7ed9255b.js} +1 -1
- codex/static_root/assets/pdf-doc-dnr5fHbU.fa1d7ed9255b.js.br +0 -0
- codex/static_root/assets/pdf-doc-dnr5fHbU.fa1d7ed9255b.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-BwxvAx1z.js → pdf-doc-dnr5fHbU.js} +1 -1
- codex/static_root/assets/pdf-doc-dnr5fHbU.js.br +0 -0
- codex/static_root/assets/pdf-doc-dnr5fHbU.js.gz +0 -0
- codex/static_root/assets/{reader-hHIonVbA.4c12219242a9.js → reader-Cn-ra_Dv.f38c0b419dec.js} +2 -2
- codex/static_root/assets/reader-Cn-ra_Dv.f38c0b419dec.js.br +0 -0
- codex/static_root/assets/reader-Cn-ra_Dv.f38c0b419dec.js.gz +0 -0
- codex/static_root/assets/{reader-hHIonVbA.js → reader-Cn-ra_Dv.js} +2 -2
- codex/static_root/assets/reader-Cn-ra_Dv.js.br +0 -0
- codex/static_root/assets/reader-Cn-ra_Dv.js.gz +0 -0
- codex/static_root/assets/{relation-chips-D7-5kPem.4443b085aca2.js → relation-chips-fOPxWAMU.78e5fe70c014.js} +1 -1
- codex/static_root/assets/relation-chips-fOPxWAMU.78e5fe70c014.js.br +0 -0
- codex/static_root/assets/relation-chips-fOPxWAMU.78e5fe70c014.js.gz +0 -0
- codex/static_root/assets/{relation-chips-D7-5kPem.js → relation-chips-fOPxWAMU.js} +1 -1
- codex/static_root/assets/relation-chips-fOPxWAMU.js.br +0 -0
- codex/static_root/assets/relation-chips-fOPxWAMU.js.gz +0 -0
- codex/static_root/assets/{settings-drawer-CdFmOhnd.f7dcd12b3ebc.js → settings-drawer-1UEq8JY1.d95cee9aefb5.js} +2 -2
- codex/static_root/assets/settings-drawer-1UEq8JY1.d95cee9aefb5.js.br +0 -0
- codex/static_root/assets/settings-drawer-1UEq8JY1.d95cee9aefb5.js.gz +0 -0
- codex/static_root/assets/{settings-drawer-CdFmOhnd.js → settings-drawer-1UEq8JY1.js} +2 -2
- codex/static_root/assets/settings-drawer-1UEq8JY1.js.br +0 -0
- codex/static_root/assets/settings-drawer-1UEq8JY1.js.gz +0 -0
- codex/static_root/assets/{stats-tab-BzaipD0m.b6bf627ea860.js → stats-tab-0ptRCeKw.5514d3508e37.js} +1 -1
- codex/static_root/assets/stats-tab-0ptRCeKw.5514d3508e37.js.br +0 -0
- codex/static_root/assets/stats-tab-0ptRCeKw.5514d3508e37.js.gz +0 -0
- codex/static_root/assets/{stats-tab-BzaipD0m.js → stats-tab-0ptRCeKw.js} +1 -1
- codex/static_root/assets/stats-tab-0ptRCeKw.js.br +0 -0
- codex/static_root/assets/stats-tab-0ptRCeKw.js.gz +0 -0
- codex/static_root/assets/{task-tab-DCnS1sM9.44d8435b4989.js → task-tab-CG9_bi6Z.ad9f647f8e5f.js} +1 -1
- codex/static_root/assets/task-tab-CG9_bi6Z.ad9f647f8e5f.js.br +0 -0
- codex/static_root/assets/task-tab-CG9_bi6Z.ad9f647f8e5f.js.gz +0 -0
- codex/static_root/assets/{task-tab-DCnS1sM9.js → task-tab-CG9_bi6Z.js} +1 -1
- codex/static_root/assets/task-tab-CG9_bi6Z.js.br +0 -0
- codex/static_root/assets/task-tab-CG9_bi6Z.js.gz +0 -0
- codex/static_root/assets/{unauthorized-DJSr03Dw.7555cbcf1064.js → unauthorized-vG1Lh0m_.0c4bae81ee09.js} +1 -1
- codex/static_root/assets/unauthorized-vG1Lh0m_.0c4bae81ee09.js.br +0 -0
- codex/static_root/assets/unauthorized-vG1Lh0m_.0c4bae81ee09.js.gz +0 -0
- codex/static_root/assets/{unauthorized-DJSr03Dw.js → unauthorized-vG1Lh0m_.js} +1 -1
- codex/static_root/assets/unauthorized-vG1Lh0m_.js.br +0 -0
- codex/static_root/assets/unauthorized-vG1Lh0m_.js.gz +0 -0
- codex/static_root/assets/{user-tab-DAK_Deoh.1832877d449a.js → user-tab-BOxWlpY7.1a94280a799b.js} +1 -1
- codex/static_root/assets/user-tab-BOxWlpY7.1a94280a799b.js.br +0 -0
- codex/static_root/assets/user-tab-BOxWlpY7.1a94280a799b.js.gz +0 -0
- codex/static_root/assets/{user-tab-DAK_Deoh.js → user-tab-BOxWlpY7.js} +1 -1
- codex/static_root/assets/user-tab-BOxWlpY7.js.br +0 -0
- codex/static_root/assets/user-tab-BOxWlpY7.js.gz +0 -0
- codex/static_root/manifest.9b3479a6a4a6.json +735 -0
- codex/static_root/manifest.9b3479a6a4a6.json.br +0 -0
- codex/static_root/manifest.9b3479a6a4a6.json.gz +0 -0
- codex/static_root/manifest.json +305 -305
- codex/static_root/manifest.json.br +0 -0
- codex/static_root/manifest.json.gz +0 -0
- codex/static_root/staticfiles.json +1 -1
- codex/status_controller.py +12 -9
- codex/threads.py +5 -0
- codex/urls/api/admin.py +3 -3
- codex/urls/root.py +3 -4
- codex/views/admin/api_key.py +4 -1
- codex/views/admin/library.py +4 -4
- codex/views/admin/stats.py +10 -10
- codex/views/admin/tasks.py +11 -9
- codex/views/auth.py +8 -3
- codex/views/bookmark.py +3 -3
- codex/views/browser/annotate/card.py +2 -2
- codex/views/browser/annotate/order.py +7 -6
- codex/views/browser/bookmark.py +1 -1
- codex/views/browser/breadcrumbs.py +5 -6
- codex/views/browser/browser.py +2 -2
- codex/views/browser/choices.py +5 -6
- codex/views/browser/cover.py +3 -6
- codex/views/browser/download.py +1 -2
- codex/views/browser/filters/bookmark.py +1 -1
- codex/views/browser/filters/field.py +1 -1
- codex/views/browser/filters/filter.py +8 -6
- codex/views/browser/filters/group.py +4 -5
- codex/views/browser/filters/search/field/expression.py +2 -1
- codex/views/browser/filters/search/field/optimize.py +1 -1
- codex/views/browser/filters/search/field/parse.py +2 -2
- codex/views/browser/filters/search/parse.py +19 -4
- codex/views/browser/group_mtime.py +1 -1
- codex/views/browser/metadata/copy_intersections.py +1 -1
- codex/views/browser/metadata/metadata.py +1 -1
- codex/views/browser/mtime.py +1 -1
- codex/views/browser/order_by.py +5 -3
- codex/views/browser/params.py +1 -1
- codex/views/browser/settings.py +1 -1
- codex/views/browser/validate.py +5 -8
- codex/views/const.py +3 -0
- codex/views/frontend.py +1 -1
- codex/views/mixins.py +2 -3
- codex/views/opds/authentication_v1.py +1 -1
- codex/views/opds/const.py +4 -4
- codex/views/opds/util.py +3 -3
- codex/views/opds/v1/entry/entry.py +2 -4
- codex/views/opds/v1/entry/links.py +5 -4
- codex/views/opds/v1/facets.py +4 -8
- codex/views/opds/v1/feed.py +5 -5
- codex/views/opds/v1/links.py +6 -11
- codex/views/opds/v2/const.py +2 -5
- codex/views/opds/v2/feed.py +3 -3
- codex/views/opds/v2/progression.py +9 -8
- codex/views/opds/v2/publications.py +20 -10
- codex/views/public.py +1 -1
- codex/views/reader/books.py +2 -3
- codex/views/reader/page.py +3 -3
- codex/views/reader/params.py +2 -2
- codex/views/reader/reader.py +6 -6
- codex/views/reader/settings.py +1 -1
- codex/views/session.py +2 -8
- codex/views/settings.py +2 -2
- codex/views/timezone.py +2 -2
- codex/views/util.py +9 -10
- codex/views/version.py +1 -1
- {codex-1.7.3.dist-info → codex-1.7.3a0.dist-info}/METADATA +2 -2
- {codex-1.7.3.dist-info → codex-1.7.3a0.dist-info}/RECORD +571 -570
- {codex-1.7.3.dist-info → codex-1.7.3a0.dist-info}/WHEEL +1 -1
- codex/static_root/assets/VCheckbox-Dv6fwaDb.56abbfb00c8a.js.br +0 -0
- codex/static_root/assets/VCheckbox-Dv6fwaDb.56abbfb00c8a.js.gz +0 -0
- codex/static_root/assets/VCheckbox-Dv6fwaDb.js.br +0 -0
- codex/static_root/assets/VCheckbox-Dv6fwaDb.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-CNMFahfF.4ee9778a562e.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-CNMFahfF.4ee9778a562e.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-CNMFahfF.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-CNMFahfF.js.gz +0 -0
- codex/static_root/assets/VCombobox-DqBFki-9.2806f95c938d.js.br +0 -0
- codex/static_root/assets/VCombobox-DqBFki-9.2806f95c938d.js.gz +0 -0
- codex/static_root/assets/VCombobox-DqBFki-9.js.br +0 -0
- codex/static_root/assets/VCombobox-DqBFki-9.js.gz +0 -0
- codex/static_root/assets/VDialog-CQXjBvDZ.1a576c5e472f.js.br +0 -0
- codex/static_root/assets/VDialog-CQXjBvDZ.1a576c5e472f.js.gz +0 -0
- codex/static_root/assets/VDialog-CQXjBvDZ.js.br +0 -0
- codex/static_root/assets/VDialog-CQXjBvDZ.js.gz +0 -0
- codex/static_root/assets/VDivider-DUxQu-IZ.73d92ae2a07e.js.br +0 -0
- codex/static_root/assets/VDivider-DUxQu-IZ.73d92ae2a07e.js.gz +0 -0
- codex/static_root/assets/VDivider-DUxQu-IZ.js.br +0 -0
- codex/static_root/assets/VDivider-DUxQu-IZ.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-BaYzHUJp.5346826103eb.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-BaYzHUJp.5346826103eb.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-BaYzHUJp.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-BaYzHUJp.js.gz +0 -0
- codex/static_root/assets/VForm-hB4C5jVd.a2b90ddcd8ee.js.br +0 -0
- codex/static_root/assets/VForm-hB4C5jVd.a2b90ddcd8ee.js.gz +0 -0
- codex/static_root/assets/VForm-hB4C5jVd.js.br +0 -0
- codex/static_root/assets/VForm-hB4C5jVd.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DOjw38qB.cbf2922d05af.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DOjw38qB.cbf2922d05af.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DOjw38qB.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DOjw38qB.js.gz +0 -0
- codex/static_root/assets/VSelect-L4v_m3ag.db9fb8348617.js.br +0 -0
- codex/static_root/assets/VSelect-L4v_m3ag.db9fb8348617.js.gz +0 -0
- codex/static_root/assets/VSelect-L4v_m3ag.js.br +0 -0
- codex/static_root/assets/VSelect-L4v_m3ag.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-BqB1JeKa.2fb68a673402.js.br +0 -0
- codex/static_root/assets/VSelectionControl-BqB1JeKa.2fb68a673402.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-BqB1JeKa.js.br +0 -0
- codex/static_root/assets/VSelectionControl-BqB1JeKa.js.gz +0 -0
- codex/static_root/assets/VTable-CtorAbOx.bbda450cbd73.js.br +0 -0
- codex/static_root/assets/VTable-CtorAbOx.bbda450cbd73.js.gz +0 -0
- codex/static_root/assets/VTable-CtorAbOx.js.br +0 -0
- codex/static_root/assets/VTable-CtorAbOx.js.gz +0 -0
- codex/static_root/assets/VWindowItem-Bl-fa3ss.334e6b813775.js.br +0 -0
- codex/static_root/assets/VWindowItem-Bl-fa3ss.334e6b813775.js.gz +0 -0
- codex/static_root/assets/VWindowItem-Bl-fa3ss.js.br +0 -0
- codex/static_root/assets/VWindowItem-Bl-fa3ss.js.gz +0 -0
- codex/static_root/assets/admin-BAVKNREt.23c0966bd683.js.br +0 -0
- codex/static_root/assets/admin-BAVKNREt.23c0966bd683.js.gz +0 -0
- codex/static_root/assets/admin-BAVKNREt.js.br +0 -0
- codex/static_root/assets/admin-BAVKNREt.js.gz +0 -0
- codex/static_root/assets/admin-C3iCIUnm.06cb213f624d.css +0 -1
- codex/static_root/assets/admin-C3iCIUnm.06cb213f624d.css.br +0 -0
- codex/static_root/assets/admin-C3iCIUnm.06cb213f624d.css.gz +0 -0
- codex/static_root/assets/admin-C3iCIUnm.css +0 -1
- codex/static_root/assets/admin-C3iCIUnm.css.br +0 -0
- codex/static_root/assets/admin-C3iCIUnm.css.gz +0 -0
- codex/static_root/assets/admin-CHuFhx_t.a54700f97fc8.js.br +0 -0
- codex/static_root/assets/admin-CHuFhx_t.a54700f97fc8.js.gz +0 -0
- codex/static_root/assets/admin-CHuFhx_t.js.br +0 -0
- codex/static_root/assets/admin-CHuFhx_t.js.gz +0 -0
- codex/static_root/assets/admin-menu-T8WJ_x0C.4f011540bb4c.js +0 -1
- codex/static_root/assets/admin-menu-T8WJ_x0C.4f011540bb4c.js.br +0 -0
- codex/static_root/assets/admin-menu-T8WJ_x0C.4f011540bb4c.js.gz +0 -0
- codex/static_root/assets/admin-menu-T8WJ_x0C.js +0 -1
- codex/static_root/assets/admin-menu-T8WJ_x0C.js.br +0 -0
- codex/static_root/assets/admin-menu-T8WJ_x0C.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.7b36216f68b5.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.7b36216f68b5.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-w_CqTSMl.js.gz +0 -0
- codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css.br +0 -0
- codex/static_root/assets/browser-DNzQvgkY.aea8b7d7ca40.css.gz +0 -0
- codex/static_root/assets/browser-DNzQvgkY.css.br +0 -0
- codex/static_root/assets/browser-DNzQvgkY.css.gz +0 -0
- codex/static_root/assets/browser-DdLCtUlr.380b79bea4a7.js +0 -1
- codex/static_root/assets/browser-DdLCtUlr.380b79bea4a7.js.br +0 -0
- codex/static_root/assets/browser-DdLCtUlr.380b79bea4a7.js.gz +0 -0
- codex/static_root/assets/browser-DdLCtUlr.js +0 -1
- codex/static_root/assets/browser-DdLCtUlr.js.br +0 -0
- codex/static_root/assets/browser-DdLCtUlr.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-Cy1tU-tj.416ef5bdfd46.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Cy1tU-tj.416ef5bdfd46.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-Cy1tU-tj.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Cy1tU-tj.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-B_Y3KKiL.1070d18f6b2d.js.br +0 -0
- codex/static_root/assets/confirm-dialog-B_Y3KKiL.1070d18f6b2d.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-B_Y3KKiL.js.br +0 -0
- codex/static_root/assets/confirm-dialog-B_Y3KKiL.js.gz +0 -0
- codex/static_root/assets/datetime-column-DVC0YqHC.03bb52c198e9.js.br +0 -0
- codex/static_root/assets/datetime-column-DVC0YqHC.03bb52c198e9.js.gz +0 -0
- codex/static_root/assets/datetime-column-DVC0YqHC.js.br +0 -0
- codex/static_root/assets/datetime-column-DVC0YqHC.js.gz +0 -0
- codex/static_root/assets/filter-xcEcgcIx.be1bb4725c89.js.br +0 -0
- codex/static_root/assets/filter-xcEcgcIx.be1bb4725c89.js.gz +0 -0
- codex/static_root/assets/filter-xcEcgcIx.js.br +0 -0
- codex/static_root/assets/filter-xcEcgcIx.js.gz +0 -0
- codex/static_root/assets/flag-tab-BOyQb0kr.842fca93f19c.js +0 -1
- codex/static_root/assets/flag-tab-BOyQb0kr.842fca93f19c.js.br +0 -0
- codex/static_root/assets/flag-tab-BOyQb0kr.842fca93f19c.js.gz +0 -0
- codex/static_root/assets/flag-tab-BOyQb0kr.js +0 -1
- codex/static_root/assets/flag-tab-BOyQb0kr.js.br +0 -0
- codex/static_root/assets/flag-tab-BOyQb0kr.js.gz +0 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css +0 -1
- codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css.br +0 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.0f57e109c01b.css.gz +0 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.css +0 -1
- codex/static_root/assets/flag-tab-D2MYXCHk.css.br +0 -0
- codex/static_root/assets/flag-tab-D2MYXCHk.css.gz +0 -0
- codex/static_root/assets/forwardRefs-D1ZDjzWx.96fccf773093.js.br +0 -0
- codex/static_root/assets/forwardRefs-D1ZDjzWx.96fccf773093.js.gz +0 -0
- codex/static_root/assets/forwardRefs-D1ZDjzWx.js.br +0 -0
- codex/static_root/assets/forwardRefs-D1ZDjzWx.js.gz +0 -0
- codex/static_root/assets/group-tab-DkAIGL8z.527cad03c21d.js.br +0 -0
- codex/static_root/assets/group-tab-DkAIGL8z.527cad03c21d.js.gz +0 -0
- codex/static_root/assets/group-tab-DkAIGL8z.js.br +0 -0
- codex/static_root/assets/group-tab-DkAIGL8z.js.gz +0 -0
- codex/static_root/assets/http-error-CjSb8orc.ad6fc5733ed8.js.br +0 -0
- codex/static_root/assets/http-error-CjSb8orc.ad6fc5733ed8.js.gz +0 -0
- codex/static_root/assets/http-error-CjSb8orc.js.br +0 -0
- codex/static_root/assets/http-error-CjSb8orc.js.gz +0 -0
- codex/static_root/assets/index-CoFXW6I0.27f397e1425e.js.br +0 -0
- codex/static_root/assets/index-CoFXW6I0.27f397e1425e.js.gz +0 -0
- codex/static_root/assets/index-CoFXW6I0.js.br +0 -0
- codex/static_root/assets/index-CoFXW6I0.js.gz +0 -0
- codex/static_root/assets/library-tab-hkMMBz1x.02270491d822.js.br +0 -0
- codex/static_root/assets/library-tab-hkMMBz1x.02270491d822.js.gz +0 -0
- codex/static_root/assets/library-tab-hkMMBz1x.js.br +0 -0
- codex/static_root/assets/library-tab-hkMMBz1x.js.gz +0 -0
- codex/static_root/assets/main-DCaPxp2h.076707ddd123.js.br +0 -0
- codex/static_root/assets/main-DCaPxp2h.076707ddd123.js.gz +0 -0
- codex/static_root/assets/main-DCaPxp2h.js.br +0 -0
- codex/static_root/assets/main-DCaPxp2h.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-CwmA9y3l.e7dfdd2a6937.js +0 -1
- codex/static_root/assets/pager-full-pdf-CwmA9y3l.e7dfdd2a6937.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-CwmA9y3l.e7dfdd2a6937.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-CwmA9y3l.js +0 -1
- codex/static_root/assets/pager-full-pdf-CwmA9y3l.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-CwmA9y3l.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-DoqxSygU.f985bc705fe5.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-DoqxSygU.f985bc705fe5.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-DoqxSygU.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-DoqxSygU.js.gz +0 -0
- codex/static_root/assets/pdf-doc-BwxvAx1z.96cbc39c321d.js.br +0 -0
- codex/static_root/assets/pdf-doc-BwxvAx1z.96cbc39c321d.js.gz +0 -0
- codex/static_root/assets/pdf-doc-BwxvAx1z.js.br +0 -0
- codex/static_root/assets/pdf-doc-BwxvAx1z.js.gz +0 -0
- codex/static_root/assets/reader-hHIonVbA.4c12219242a9.js.br +0 -0
- codex/static_root/assets/reader-hHIonVbA.4c12219242a9.js.gz +0 -0
- codex/static_root/assets/reader-hHIonVbA.js.br +0 -0
- codex/static_root/assets/reader-hHIonVbA.js.gz +0 -0
- codex/static_root/assets/relation-chips-D7-5kPem.4443b085aca2.js.br +0 -0
- codex/static_root/assets/relation-chips-D7-5kPem.4443b085aca2.js.gz +0 -0
- codex/static_root/assets/relation-chips-D7-5kPem.js.br +0 -0
- codex/static_root/assets/relation-chips-D7-5kPem.js.gz +0 -0
- codex/static_root/assets/settings-drawer-CdFmOhnd.f7dcd12b3ebc.js.br +0 -0
- codex/static_root/assets/settings-drawer-CdFmOhnd.f7dcd12b3ebc.js.gz +0 -0
- codex/static_root/assets/settings-drawer-CdFmOhnd.js.br +0 -0
- codex/static_root/assets/settings-drawer-CdFmOhnd.js.gz +0 -0
- codex/static_root/assets/stats-tab-BzaipD0m.b6bf627ea860.js.br +0 -0
- codex/static_root/assets/stats-tab-BzaipD0m.b6bf627ea860.js.gz +0 -0
- codex/static_root/assets/stats-tab-BzaipD0m.js.br +0 -0
- codex/static_root/assets/stats-tab-BzaipD0m.js.gz +0 -0
- codex/static_root/assets/task-tab-DCnS1sM9.44d8435b4989.js.br +0 -0
- codex/static_root/assets/task-tab-DCnS1sM9.44d8435b4989.js.gz +0 -0
- codex/static_root/assets/task-tab-DCnS1sM9.js.br +0 -0
- codex/static_root/assets/task-tab-DCnS1sM9.js.gz +0 -0
- codex/static_root/assets/unauthorized-DJSr03Dw.7555cbcf1064.js.br +0 -0
- codex/static_root/assets/unauthorized-DJSr03Dw.7555cbcf1064.js.gz +0 -0
- codex/static_root/assets/unauthorized-DJSr03Dw.js.br +0 -0
- codex/static_root/assets/unauthorized-DJSr03Dw.js.gz +0 -0
- codex/static_root/assets/user-tab-DAK_Deoh.1832877d449a.js.br +0 -0
- codex/static_root/assets/user-tab-DAK_Deoh.1832877d449a.js.gz +0 -0
- codex/static_root/assets/user-tab-DAK_Deoh.js.br +0 -0
- codex/static_root/assets/user-tab-DAK_Deoh.js.gz +0 -0
- codex/static_root/manifest.cbc39bca88fc.json +0 -735
- codex/static_root/manifest.cbc39bca88fc.json.br +0 -0
- codex/static_root/manifest.cbc39bca88fc.json.gz +0 -0
- /codex/static_root/assets/{VCheckbox-CvH8ekHL.016ed8d222c4.css → VCheckbox-CMKdyl0R.016ed8d222c4.css} +0 -0
- /codex/static_root/assets/{VCheckbox-CvH8ekHL.016ed8d222c4.css.br → VCheckbox-CMKdyl0R.016ed8d222c4.css.br} +0 -0
- /codex/static_root/assets/{VCheckbox-CvH8ekHL.016ed8d222c4.css.gz → VCheckbox-CMKdyl0R.016ed8d222c4.css.gz} +0 -0
- /codex/static_root/assets/{VCheckbox-CvH8ekHL.css → VCheckbox-CMKdyl0R.css} +0 -0
- /codex/static_root/assets/{VCheckbox-CvH8ekHL.css.br → VCheckbox-CMKdyl0R.css.br} +0 -0
- /codex/static_root/assets/{VCheckbox-CvH8ekHL.css.gz → VCheckbox-CMKdyl0R.css.gz} +0 -0
- /codex/static_root/assets/{VCombobox-BQHELb_o.9f25a34994e2.css → VCombobox-bwEYrXCg.9f25a34994e2.css} +0 -0
- /codex/static_root/assets/{VCombobox-BQHELb_o.9f25a34994e2.css.br → VCombobox-bwEYrXCg.9f25a34994e2.css.br} +0 -0
- /codex/static_root/assets/{VCombobox-BQHELb_o.9f25a34994e2.css.gz → VCombobox-bwEYrXCg.9f25a34994e2.css.gz} +0 -0
- /codex/static_root/assets/{VCombobox-BQHELb_o.css → VCombobox-bwEYrXCg.css} +0 -0
- /codex/static_root/assets/{VCombobox-BQHELb_o.css.br → VCombobox-bwEYrXCg.css.br} +0 -0
- /codex/static_root/assets/{VCombobox-BQHELb_o.css.gz → VCombobox-bwEYrXCg.css.gz} +0 -0
- /codex/static_root/assets/{VDialog-DWos4S54.b07aca713774.css → VDialog-Dyd05WHA.b07aca713774.css} +0 -0
- /codex/static_root/assets/{VDialog-DWos4S54.b07aca713774.css.br → VDialog-Dyd05WHA.b07aca713774.css.br} +0 -0
- /codex/static_root/assets/{VDialog-DWos4S54.b07aca713774.css.gz → VDialog-Dyd05WHA.b07aca713774.css.gz} +0 -0
- /codex/static_root/assets/{VDialog-DWos4S54.css → VDialog-Dyd05WHA.css} +0 -0
- /codex/static_root/assets/{VDialog-DWos4S54.css.br → VDialog-Dyd05WHA.css.br} +0 -0
- /codex/static_root/assets/{VDialog-DWos4S54.css.gz → VDialog-Dyd05WHA.css.gz} +0 -0
- /codex/static_root/assets/{VDivider-DU47sRrT.3d2e17799e5c.css → VDivider-DE8MJPGz.3d2e17799e5c.css} +0 -0
- /codex/static_root/assets/{VDivider-DU47sRrT.3d2e17799e5c.css.br → VDivider-DE8MJPGz.3d2e17799e5c.css.br} +0 -0
- /codex/static_root/assets/{VDivider-DU47sRrT.3d2e17799e5c.css.gz → VDivider-DE8MJPGz.3d2e17799e5c.css.gz} +0 -0
- /codex/static_root/assets/{VDivider-DU47sRrT.css → VDivider-DE8MJPGz.css} +0 -0
- /codex/static_root/assets/{VDivider-DU47sRrT.css.br → VDivider-DE8MJPGz.css.br} +0 -0
- /codex/static_root/assets/{VDivider-DU47sRrT.css.gz → VDivider-DE8MJPGz.css.gz} +0 -0
- /codex/static_root/assets/{VExpansionPanels-RsCANmDP.5b17872981df.css → VExpansionPanels-6G1AUajL.5b17872981df.css} +0 -0
- /codex/static_root/assets/{VExpansionPanels-RsCANmDP.5b17872981df.css.br → VExpansionPanels-6G1AUajL.5b17872981df.css.br} +0 -0
- /codex/static_root/assets/{VExpansionPanels-RsCANmDP.5b17872981df.css.gz → VExpansionPanels-6G1AUajL.5b17872981df.css.gz} +0 -0
- /codex/static_root/assets/{VExpansionPanels-RsCANmDP.css → VExpansionPanels-6G1AUajL.css} +0 -0
- /codex/static_root/assets/{VExpansionPanels-RsCANmDP.css.br → VExpansionPanels-6G1AUajL.css.br} +0 -0
- /codex/static_root/assets/{VExpansionPanels-RsCANmDP.css.gz → VExpansionPanels-6G1AUajL.css.gz} +0 -0
- /codex/static_root/assets/{VForm-DxBt30-N.138c0b89b6fc.css → VForm-v1Gmu6E1.138c0b89b6fc.css} +0 -0
- /codex/static_root/assets/{VForm-DxBt30-N.138c0b89b6fc.css.br → VForm-v1Gmu6E1.138c0b89b6fc.css.br} +0 -0
- /codex/static_root/assets/{VForm-DxBt30-N.138c0b89b6fc.css.gz → VForm-v1Gmu6E1.138c0b89b6fc.css.gz} +0 -0
- /codex/static_root/assets/{VForm-DxBt30-N.css → VForm-v1Gmu6E1.css} +0 -0
- /codex/static_root/assets/{VForm-DxBt30-N.css.br → VForm-v1Gmu6E1.css.br} +0 -0
- /codex/static_root/assets/{VForm-DxBt30-N.css.gz → VForm-v1Gmu6E1.css.gz} +0 -0
- /codex/static_root/assets/{VRadioGroup-Cp9mZ7cb.8e3741381961.css → VRadioGroup-i2qP9Wu9.8e3741381961.css} +0 -0
- /codex/static_root/assets/{VRadioGroup-Cp9mZ7cb.8e3741381961.css.br → VRadioGroup-i2qP9Wu9.8e3741381961.css.br} +0 -0
- /codex/static_root/assets/{VRadioGroup-Cp9mZ7cb.8e3741381961.css.gz → VRadioGroup-i2qP9Wu9.8e3741381961.css.gz} +0 -0
- /codex/static_root/assets/{VRadioGroup-Cp9mZ7cb.css → VRadioGroup-i2qP9Wu9.css} +0 -0
- /codex/static_root/assets/{VRadioGroup-Cp9mZ7cb.css.br → VRadioGroup-i2qP9Wu9.css.br} +0 -0
- /codex/static_root/assets/{VRadioGroup-Cp9mZ7cb.css.gz → VRadioGroup-i2qP9Wu9.css.gz} +0 -0
- /codex/static_root/assets/{VSelect-CP_CVb8s.6309f7bf17bb.css → VSelect-8MFoaOUz.6309f7bf17bb.css} +0 -0
- /codex/static_root/assets/{VSelect-CP_CVb8s.6309f7bf17bb.css.br → VSelect-8MFoaOUz.6309f7bf17bb.css.br} +0 -0
- /codex/static_root/assets/{VSelect-CP_CVb8s.6309f7bf17bb.css.gz → VSelect-8MFoaOUz.6309f7bf17bb.css.gz} +0 -0
- /codex/static_root/assets/{VSelect-CP_CVb8s.css → VSelect-8MFoaOUz.css} +0 -0
- /codex/static_root/assets/{VSelect-CP_CVb8s.css.br → VSelect-8MFoaOUz.css.br} +0 -0
- /codex/static_root/assets/{VSelect-CP_CVb8s.css.gz → VSelect-8MFoaOUz.css.gz} +0 -0
- /codex/static_root/assets/{VSelectionControl-DPpfgCW2.cc18de4e83f6.css → VSelectionControl-DLxcLoTI.cc18de4e83f6.css} +0 -0
- /codex/static_root/assets/{VSelectionControl-DPpfgCW2.cc18de4e83f6.css.br → VSelectionControl-DLxcLoTI.cc18de4e83f6.css.br} +0 -0
- /codex/static_root/assets/{VSelectionControl-DPpfgCW2.cc18de4e83f6.css.gz → VSelectionControl-DLxcLoTI.cc18de4e83f6.css.gz} +0 -0
- /codex/static_root/assets/{VSelectionControl-DPpfgCW2.css → VSelectionControl-DLxcLoTI.css} +0 -0
- /codex/static_root/assets/{VSelectionControl-DPpfgCW2.css.br → VSelectionControl-DLxcLoTI.css.br} +0 -0
- /codex/static_root/assets/{VSelectionControl-DPpfgCW2.css.gz → VSelectionControl-DLxcLoTI.css.gz} +0 -0
- /codex/static_root/assets/{VTable-BnxSZ_W5.c36f0a6a30cf.css → VTable-Y5Sc3hJd.c36f0a6a30cf.css} +0 -0
- /codex/static_root/assets/{VTable-BnxSZ_W5.c36f0a6a30cf.css.br → VTable-Y5Sc3hJd.c36f0a6a30cf.css.br} +0 -0
- /codex/static_root/assets/{VTable-BnxSZ_W5.c36f0a6a30cf.css.gz → VTable-Y5Sc3hJd.c36f0a6a30cf.css.gz} +0 -0
- /codex/static_root/assets/{VTable-BnxSZ_W5.css → VTable-Y5Sc3hJd.css} +0 -0
- /codex/static_root/assets/{VTable-BnxSZ_W5.css.br → VTable-Y5Sc3hJd.css.br} +0 -0
- /codex/static_root/assets/{VTable-BnxSZ_W5.css.gz → VTable-Y5Sc3hJd.css.gz} +0 -0
- /codex/static_root/assets/{VWindowItem-CWBhiE_Y.css → VWindowItem-ByIod57Y.css} +0 -0
- /codex/static_root/assets/{VWindowItem-CWBhiE_Y.css.br → VWindowItem-ByIod57Y.css.br} +0 -0
- /codex/static_root/assets/{VWindowItem-CWBhiE_Y.css.gz → VWindowItem-ByIod57Y.css.gz} +0 -0
- /codex/static_root/assets/{VWindowItem-CWBhiE_Y.f7fb19752bf3.css → VWindowItem-ByIod57Y.f7fb19752bf3.css} +0 -0
- /codex/static_root/assets/{VWindowItem-CWBhiE_Y.f7fb19752bf3.css.br → VWindowItem-ByIod57Y.f7fb19752bf3.css.br} +0 -0
- /codex/static_root/assets/{VWindowItem-CWBhiE_Y.f7fb19752bf3.css.gz → VWindowItem-ByIod57Y.f7fb19752bf3.css.gz} +0 -0
- /codex/static_root/assets/{admin-menu-B3iXsOyy.c13b7df2ff57.css → admin-menu-B9bzD6hV.c13b7df2ff57.css} +0 -0
- /codex/static_root/assets/{admin-menu-B3iXsOyy.c13b7df2ff57.css.br → admin-menu-B9bzD6hV.c13b7df2ff57.css.br} +0 -0
- /codex/static_root/assets/{admin-menu-B3iXsOyy.c13b7df2ff57.css.gz → admin-menu-B9bzD6hV.c13b7df2ff57.css.gz} +0 -0
- /codex/static_root/assets/{admin-menu-B3iXsOyy.css → admin-menu-B9bzD6hV.css} +0 -0
- /codex/static_root/assets/{admin-menu-B3iXsOyy.css.br → admin-menu-B9bzD6hV.css.br} +0 -0
- /codex/static_root/assets/{admin-menu-B3iXsOyy.css.gz → admin-menu-B9bzD6hV.css.gz} +0 -0
- /codex/static_root/assets/{admin-settings-button-progress-BGB22oTD.2548c49a853e.css → admin-settings-button-progress-DUUQfVsZ.2548c49a853e.css} +0 -0
- /codex/static_root/assets/{admin-settings-button-progress-BGB22oTD.css → admin-settings-button-progress-DUUQfVsZ.css} +0 -0
- /codex/static_root/assets/{change-password-dialog-D0ymWcl_.a30e68c6e303.css → change-password-dialog-C_EOKOn9.a30e68c6e303.css} +0 -0
- /codex/static_root/assets/{change-password-dialog-D0ymWcl_.a30e68c6e303.css.br → change-password-dialog-C_EOKOn9.a30e68c6e303.css.br} +0 -0
- /codex/static_root/assets/{change-password-dialog-D0ymWcl_.a30e68c6e303.css.gz → change-password-dialog-C_EOKOn9.a30e68c6e303.css.gz} +0 -0
- /codex/static_root/assets/{change-password-dialog-D0ymWcl_.css → change-password-dialog-C_EOKOn9.css} +0 -0
- /codex/static_root/assets/{change-password-dialog-D0ymWcl_.css.br → change-password-dialog-C_EOKOn9.css.br} +0 -0
- /codex/static_root/assets/{change-password-dialog-D0ymWcl_.css.gz → change-password-dialog-C_EOKOn9.css.gz} +0 -0
- /codex/static_root/assets/{confirm-dialog-B1ABbGMU.9b5915b112c0.css → confirm-dialog-54rblwf7.9b5915b112c0.css} +0 -0
- /codex/static_root/assets/{confirm-dialog-B1ABbGMU.9b5915b112c0.css.br → confirm-dialog-54rblwf7.9b5915b112c0.css.br} +0 -0
- /codex/static_root/assets/{confirm-dialog-B1ABbGMU.css → confirm-dialog-54rblwf7.css} +0 -0
- /codex/static_root/assets/{confirm-dialog-B1ABbGMU.css.br → confirm-dialog-54rblwf7.css.br} +0 -0
- /codex/static_root/assets/{datetime-column-BavtvLnf.1f3bf499e063.css → datetime-column-DeCthByU.1f3bf499e063.css} +0 -0
- /codex/static_root/assets/{datetime-column-BavtvLnf.css → datetime-column-DeCthByU.css} +0 -0
- /codex/static_root/assets/{forwardRefs-CFNX6kJ2.9b56b4459240.css → forwardRefs-zKOZsbbr.9b56b4459240.css} +0 -0
- /codex/static_root/assets/{forwardRefs-CFNX6kJ2.9b56b4459240.css.br → forwardRefs-zKOZsbbr.9b56b4459240.css.br} +0 -0
- /codex/static_root/assets/{forwardRefs-CFNX6kJ2.9b56b4459240.css.gz → forwardRefs-zKOZsbbr.9b56b4459240.css.gz} +0 -0
- /codex/static_root/assets/{forwardRefs-CFNX6kJ2.css → forwardRefs-zKOZsbbr.css} +0 -0
- /codex/static_root/assets/{forwardRefs-CFNX6kJ2.css.br → forwardRefs-zKOZsbbr.css.br} +0 -0
- /codex/static_root/assets/{forwardRefs-CFNX6kJ2.css.gz → forwardRefs-zKOZsbbr.css.gz} +0 -0
- /codex/static_root/assets/{group-tab-_vKWzoyd.948e907b1e6b.css → group-tab-DkIN1Heu.948e907b1e6b.css} +0 -0
- /codex/static_root/assets/{group-tab-_vKWzoyd.948e907b1e6b.css.br → group-tab-DkIN1Heu.948e907b1e6b.css.br} +0 -0
- /codex/static_root/assets/{group-tab-_vKWzoyd.948e907b1e6b.css.gz → group-tab-DkIN1Heu.948e907b1e6b.css.gz} +0 -0
- /codex/static_root/assets/{group-tab-_vKWzoyd.css → group-tab-DkIN1Heu.css} +0 -0
- /codex/static_root/assets/{group-tab-_vKWzoyd.css.br → group-tab-DkIN1Heu.css.br} +0 -0
- /codex/static_root/assets/{group-tab-_vKWzoyd.css.gz → group-tab-DkIN1Heu.css.gz} +0 -0
- /codex/static_root/assets/{http-error-CODU7jcH.8c13689ae574.css → http-error-DEJmFobt.8c13689ae574.css} +0 -0
- /codex/static_root/assets/{http-error-CODU7jcH.8c13689ae574.css.br → http-error-DEJmFobt.8c13689ae574.css.br} +0 -0
- /codex/static_root/assets/{http-error-CODU7jcH.8c13689ae574.css.gz → http-error-DEJmFobt.8c13689ae574.css.gz} +0 -0
- /codex/static_root/assets/{http-error-CODU7jcH.css → http-error-DEJmFobt.css} +0 -0
- /codex/static_root/assets/{http-error-CODU7jcH.css.br → http-error-DEJmFobt.css.br} +0 -0
- /codex/static_root/assets/{http-error-CODU7jcH.css.gz → http-error-DEJmFobt.css.gz} +0 -0
- /codex/static_root/assets/{index-BHXJTQ4V.523d7b3d350f.css → index-CL_6g4tJ.523d7b3d350f.css} +0 -0
- /codex/static_root/assets/{index-BHXJTQ4V.523d7b3d350f.css.br → index-CL_6g4tJ.523d7b3d350f.css.br} +0 -0
- /codex/static_root/assets/{index-BHXJTQ4V.523d7b3d350f.css.gz → index-CL_6g4tJ.523d7b3d350f.css.gz} +0 -0
- /codex/static_root/assets/{index-BHXJTQ4V.css → index-CL_6g4tJ.css} +0 -0
- /codex/static_root/assets/{index-BHXJTQ4V.css.br → index-CL_6g4tJ.css.br} +0 -0
- /codex/static_root/assets/{index-BHXJTQ4V.css.gz → index-CL_6g4tJ.css.gz} +0 -0
- /codex/static_root/assets/{library-tab-CgsXOX_r.75baedb7e976.css → library-tab-Ce6qaeCV.75baedb7e976.css} +0 -0
- /codex/static_root/assets/{library-tab-CgsXOX_r.75baedb7e976.css.br → library-tab-Ce6qaeCV.75baedb7e976.css.br} +0 -0
- /codex/static_root/assets/{library-tab-CgsXOX_r.75baedb7e976.css.gz → library-tab-Ce6qaeCV.75baedb7e976.css.gz} +0 -0
- /codex/static_root/assets/{library-tab-CgsXOX_r.css → library-tab-Ce6qaeCV.css} +0 -0
- /codex/static_root/assets/{library-tab-CgsXOX_r.css.br → library-tab-Ce6qaeCV.css.br} +0 -0
- /codex/static_root/assets/{library-tab-CgsXOX_r.css.gz → library-tab-Ce6qaeCV.css.gz} +0 -0
- /codex/static_root/assets/{main-K8cER0IH.css → main-BZ73p_WW.css} +0 -0
- /codex/static_root/assets/{main-K8cER0IH.css.br → main-BZ73p_WW.css.br} +0 -0
- /codex/static_root/assets/{main-K8cER0IH.css.gz → main-BZ73p_WW.css.gz} +0 -0
- /codex/static_root/assets/{main-K8cER0IH.d529e8b3f52a.css → main-BZ73p_WW.d529e8b3f52a.css} +0 -0
- /codex/static_root/assets/{main-K8cER0IH.d529e8b3f52a.css.br → main-BZ73p_WW.d529e8b3f52a.css.br} +0 -0
- /codex/static_root/assets/{main-K8cER0IH.d529e8b3f52a.css.gz → main-BZ73p_WW.d529e8b3f52a.css.gz} +0 -0
- /codex/static_root/assets/{pagination-toolbar-D5VQREy5.css → pagination-toolbar-DSe0TkMm.css} +0 -0
- /codex/static_root/assets/{pagination-toolbar-D5VQREy5.css.br → pagination-toolbar-DSe0TkMm.css.br} +0 -0
- /codex/static_root/assets/{pagination-toolbar-D5VQREy5.css.gz → pagination-toolbar-DSe0TkMm.css.gz} +0 -0
- /codex/static_root/assets/{pagination-toolbar-D5VQREy5.dcb0eba65827.css → pagination-toolbar-DSe0TkMm.dcb0eba65827.css} +0 -0
- /codex/static_root/assets/{pagination-toolbar-D5VQREy5.dcb0eba65827.css.br → pagination-toolbar-DSe0TkMm.dcb0eba65827.css.br} +0 -0
- /codex/static_root/assets/{pagination-toolbar-D5VQREy5.dcb0eba65827.css.gz → pagination-toolbar-DSe0TkMm.dcb0eba65827.css.gz} +0 -0
- /codex/static_root/assets/{pdf-doc-B4cGW_Hl.b94aac7e3313.css → pdf-doc-CG5-AZ2M.b94aac7e3313.css} +0 -0
- /codex/static_root/assets/{pdf-doc-B4cGW_Hl.b94aac7e3313.css.br → pdf-doc-CG5-AZ2M.b94aac7e3313.css.br} +0 -0
- /codex/static_root/assets/{pdf-doc-B4cGW_Hl.b94aac7e3313.css.gz → pdf-doc-CG5-AZ2M.b94aac7e3313.css.gz} +0 -0
- /codex/static_root/assets/{pdf-doc-B4cGW_Hl.css → pdf-doc-CG5-AZ2M.css} +0 -0
- /codex/static_root/assets/{pdf-doc-B4cGW_Hl.css.br → pdf-doc-CG5-AZ2M.css.br} +0 -0
- /codex/static_root/assets/{pdf-doc-B4cGW_Hl.css.gz → pdf-doc-CG5-AZ2M.css.gz} +0 -0
- /codex/static_root/assets/{reader-D_3ruSqa.2ed32f08e906.css → reader-B3hgta6g.2ed32f08e906.css} +0 -0
- /codex/static_root/assets/{reader-D_3ruSqa.2ed32f08e906.css.br → reader-B3hgta6g.2ed32f08e906.css.br} +0 -0
- /codex/static_root/assets/{reader-D_3ruSqa.2ed32f08e906.css.gz → reader-B3hgta6g.2ed32f08e906.css.gz} +0 -0
- /codex/static_root/assets/{reader-D_3ruSqa.css → reader-B3hgta6g.css} +0 -0
- /codex/static_root/assets/{reader-D_3ruSqa.css.br → reader-B3hgta6g.css.br} +0 -0
- /codex/static_root/assets/{reader-D_3ruSqa.css.gz → reader-B3hgta6g.css.gz} +0 -0
- /codex/static_root/assets/{relation-chips-DpbzrZxT.01269a188e01.css → relation-chips-ByfWwuQc.01269a188e01.css} +0 -0
- /codex/static_root/assets/{relation-chips-DpbzrZxT.01269a188e01.css.br → relation-chips-ByfWwuQc.01269a188e01.css.br} +0 -0
- /codex/static_root/assets/{relation-chips-DpbzrZxT.01269a188e01.css.gz → relation-chips-ByfWwuQc.01269a188e01.css.gz} +0 -0
- /codex/static_root/assets/{relation-chips-DpbzrZxT.css → relation-chips-ByfWwuQc.css} +0 -0
- /codex/static_root/assets/{relation-chips-DpbzrZxT.css.br → relation-chips-ByfWwuQc.css.br} +0 -0
- /codex/static_root/assets/{relation-chips-DpbzrZxT.css.gz → relation-chips-ByfWwuQc.css.gz} +0 -0
- /codex/static_root/assets/{settings-drawer-DMSsWF8c.75a6ea969e71.css → settings-drawer-CqJ4gXLq.75a6ea969e71.css} +0 -0
- /codex/static_root/assets/{settings-drawer-DMSsWF8c.75a6ea969e71.css.br → settings-drawer-CqJ4gXLq.75a6ea969e71.css.br} +0 -0
- /codex/static_root/assets/{settings-drawer-DMSsWF8c.75a6ea969e71.css.gz → settings-drawer-CqJ4gXLq.75a6ea969e71.css.gz} +0 -0
- /codex/static_root/assets/{settings-drawer-DMSsWF8c.css → settings-drawer-CqJ4gXLq.css} +0 -0
- /codex/static_root/assets/{settings-drawer-DMSsWF8c.css.br → settings-drawer-CqJ4gXLq.css.br} +0 -0
- /codex/static_root/assets/{settings-drawer-DMSsWF8c.css.gz → settings-drawer-CqJ4gXLq.css.gz} +0 -0
- /codex/static_root/assets/{stats-tab-WvF2acoZ.9fdb0106124d.css → stats-tab-BlXGStge.9fdb0106124d.css} +0 -0
- /codex/static_root/assets/{stats-tab-WvF2acoZ.9fdb0106124d.css.br → stats-tab-BlXGStge.9fdb0106124d.css.br} +0 -0
- /codex/static_root/assets/{stats-tab-WvF2acoZ.9fdb0106124d.css.gz → stats-tab-BlXGStge.9fdb0106124d.css.gz} +0 -0
- /codex/static_root/assets/{stats-tab-WvF2acoZ.css → stats-tab-BlXGStge.css} +0 -0
- /codex/static_root/assets/{stats-tab-WvF2acoZ.css.br → stats-tab-BlXGStge.css.br} +0 -0
- /codex/static_root/assets/{stats-tab-WvF2acoZ.css.gz → stats-tab-BlXGStge.css.gz} +0 -0
- /codex/static_root/assets/{task-tab-DfdUY9Rc.478e74041f80.css → task-tab-EGlhcKTH.478e74041f80.css} +0 -0
- /codex/static_root/assets/{task-tab-DfdUY9Rc.478e74041f80.css.br → task-tab-EGlhcKTH.478e74041f80.css.br} +0 -0
- /codex/static_root/assets/{task-tab-DfdUY9Rc.478e74041f80.css.gz → task-tab-EGlhcKTH.478e74041f80.css.gz} +0 -0
- /codex/static_root/assets/{task-tab-DfdUY9Rc.css → task-tab-EGlhcKTH.css} +0 -0
- /codex/static_root/assets/{task-tab-DfdUY9Rc.css.br → task-tab-EGlhcKTH.css.br} +0 -0
- /codex/static_root/assets/{task-tab-DfdUY9Rc.css.gz → task-tab-EGlhcKTH.css.gz} +0 -0
- /codex/static_root/assets/{unauthorized-CsSak07X.c5536d9dae75.css → unauthorized-VnIXUO1w.c5536d9dae75.css} +0 -0
- /codex/static_root/assets/{unauthorized-CsSak07X.c5536d9dae75.css.br → unauthorized-VnIXUO1w.c5536d9dae75.css.br} +0 -0
- /codex/static_root/assets/{unauthorized-CsSak07X.c5536d9dae75.css.gz → unauthorized-VnIXUO1w.c5536d9dae75.css.gz} +0 -0
- /codex/static_root/assets/{unauthorized-CsSak07X.css → unauthorized-VnIXUO1w.css} +0 -0
- /codex/static_root/assets/{unauthorized-CsSak07X.css.br → unauthorized-VnIXUO1w.css.br} +0 -0
- /codex/static_root/assets/{unauthorized-CsSak07X.css.gz → unauthorized-VnIXUO1w.css.gz} +0 -0
- {codex-1.7.3.dist-info → codex-1.7.3a0.dist-info}/LICENSE +0 -0
- {codex-1.7.3.dist-info → codex-1.7.3a0.dist-info}/entry_points.txt +0 -0
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
# Uses app.get_model() because functions may also be called before the models are ready on startup.
|
|
3
3
|
|
|
4
4
|
import re
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
5
|
|
|
7
6
|
from django.apps import apps
|
|
8
7
|
from django.db import DEFAULT_DB_ALIAS, connections
|
|
@@ -20,13 +19,6 @@ from codex.settings.settings import (
|
|
|
20
19
|
from codex.status import Status
|
|
21
20
|
from codex.worker_base import WorkerBaseMixin
|
|
22
21
|
|
|
23
|
-
if TYPE_CHECKING:
|
|
24
|
-
from django.db.models.manager import BaseManager
|
|
25
|
-
|
|
26
|
-
from codex.models.base import BaseModel
|
|
27
|
-
from codex.models.comic import Comic
|
|
28
|
-
|
|
29
|
-
|
|
30
22
|
REPAIR_FLAG_PATH = CONFIG_PATH / "rebuild_db"
|
|
31
23
|
REBUILT_DB_PATH = DB_PATH.parent / (DB_PATH.name + ".rebuilt")
|
|
32
24
|
BACKUP_DB_PATH = DB_PATH.parent / (DB_PATH.name + ".bak")
|
|
@@ -113,7 +105,7 @@ def _null_bad_fk_rels_table(table_name, bad_rows, log):
|
|
|
113
105
|
fields = model._meta.fields
|
|
114
106
|
field_names = {}
|
|
115
107
|
update_objs = []
|
|
116
|
-
objs
|
|
108
|
+
objs = model.objects.filter(pk__in=bad_rows.keys())
|
|
117
109
|
update_fields = {"updated_at"}
|
|
118
110
|
now = Now()
|
|
119
111
|
for obj in objs:
|
|
@@ -127,7 +119,7 @@ def _null_bad_fk_rels_table(table_name, bad_rows, log):
|
|
|
127
119
|
field_name = field_names[fkid]
|
|
128
120
|
setattr(obj, field_name, None)
|
|
129
121
|
update_fields.add(field_name)
|
|
130
|
-
obj.updated_at = now
|
|
122
|
+
obj.updated_at = now # type: ignore
|
|
131
123
|
update_objs.append(obj)
|
|
132
124
|
except Exception as exc:
|
|
133
125
|
log.warning(
|
|
@@ -150,10 +142,10 @@ def _null_bad_fk_rels(bad_fk_rels, log):
|
|
|
150
142
|
for table_name, bad_rows in bad_fk_rels.items():
|
|
151
143
|
try:
|
|
152
144
|
fix_comic_pks |= _null_bad_fk_rels_table(table_name, bad_rows, log)
|
|
153
|
-
except Exception:
|
|
145
|
+
except Exception as exc:
|
|
154
146
|
pks = sorted(bad_rows.keys())
|
|
155
|
-
log.
|
|
156
|
-
f"Unable to null {len(pks)} {table_name} rows with bad foreign keys"
|
|
147
|
+
log.error( # noqa: TRY400
|
|
148
|
+
f"Unable to null {len(pks)} {table_name} rows with bad foreign keys - {exc}"
|
|
157
149
|
)
|
|
158
150
|
log.error(f"{table_name}: {pks}") # noqa: TRY400
|
|
159
151
|
return fix_comic_pks
|
|
@@ -183,8 +175,10 @@ def _delete_bad_m2m_rows(bad_m2m_rows, log):
|
|
|
183
175
|
for table_name, ids in bad_m2m_rows.items():
|
|
184
176
|
try:
|
|
185
177
|
count += _delete_bad_m2m_rows_table(table_name, ids, fix_comic_pks, log)
|
|
186
|
-
except Exception:
|
|
187
|
-
log.
|
|
178
|
+
except Exception as exc:
|
|
179
|
+
log.error( # noqa: TRY400
|
|
180
|
+
f"Could not delete bad foreign keys in table {table_name} - {exc}"
|
|
181
|
+
)
|
|
188
182
|
if count:
|
|
189
183
|
log.info(f"Removed {count} bad foreign key relations.")
|
|
190
184
|
return fix_comic_pks
|
|
@@ -195,9 +189,7 @@ def _mark_comics_for_update(fix_comic_pks, log):
|
|
|
195
189
|
if not fix_comic_pks:
|
|
196
190
|
return
|
|
197
191
|
comic_model = apps.get_model(app_label="codex", model_name="comic")
|
|
198
|
-
outdated_comics
|
|
199
|
-
pk__in=fix_comic_pks
|
|
200
|
-
).only( # type: ignore[reportAssignmentType]
|
|
192
|
+
outdated_comics = comic_model.objects.filter(pk__in=fix_comic_pks).only(
|
|
201
193
|
"stat", "updated_at"
|
|
202
194
|
)
|
|
203
195
|
if not outdated_comics:
|
|
@@ -206,12 +198,12 @@ def _mark_comics_for_update(fix_comic_pks, log):
|
|
|
206
198
|
update_comics = []
|
|
207
199
|
now = Now()
|
|
208
200
|
for comic in outdated_comics:
|
|
209
|
-
stat_list = comic.stat
|
|
201
|
+
stat_list = comic.stat # type: ignore
|
|
210
202
|
if not stat_list:
|
|
211
203
|
continue
|
|
212
204
|
stat_list[8] = 0.0
|
|
213
|
-
comic.stat = stat_list # type: ignore
|
|
214
|
-
comic.updated_at = now
|
|
205
|
+
comic.stat = stat_list # type: ignore
|
|
206
|
+
comic.updated_at = now # type: ignore
|
|
215
207
|
update_comics.append(comic)
|
|
216
208
|
|
|
217
209
|
if update_comics:
|
|
@@ -235,8 +227,8 @@ def fix_foreign_keys(log=None):
|
|
|
235
227
|
fix_comic_pks |= _delete_bad_m2m_rows(bad_m2m_rows, log)
|
|
236
228
|
try:
|
|
237
229
|
_mark_comics_for_update(fix_comic_pks, log)
|
|
238
|
-
except Exception:
|
|
239
|
-
LOG.
|
|
230
|
+
except Exception as exc:
|
|
231
|
+
LOG.warning(f"Could not mark comics with bad relations for update: {exc}")
|
|
240
232
|
|
|
241
233
|
|
|
242
234
|
def _repair_extra_custom_cover_libraries(library_model, log):
|
|
@@ -285,7 +277,7 @@ def _is_integrity_ok(results):
|
|
|
285
277
|
)
|
|
286
278
|
|
|
287
279
|
|
|
288
|
-
def integrity_check(long, log=None):
|
|
280
|
+
def integrity_check(long=True, log=None):
|
|
289
281
|
"""Run sqlite3 integrity check."""
|
|
290
282
|
if not log:
|
|
291
283
|
log = LOG
|
|
@@ -326,8 +318,9 @@ def fts_integrity_check(log=None):
|
|
|
326
318
|
if results:
|
|
327
319
|
# I'm not sure if this raises or puts the error in the results.
|
|
328
320
|
raise ValueError(results) # noqa: TRY301
|
|
329
|
-
except Exception:
|
|
330
|
-
log.
|
|
321
|
+
except Exception as exc:
|
|
322
|
+
log.warning("Full Text Search Index failed integrity check.")
|
|
323
|
+
log.warning(exc)
|
|
331
324
|
else:
|
|
332
325
|
log.info("Full Text Search Index passed integrity check.")
|
|
333
326
|
success = True
|
|
@@ -347,7 +340,7 @@ class IntegrityMixin(WorkerBaseMixin):
|
|
|
347
340
|
finally:
|
|
348
341
|
self.status_controller.finish(status)
|
|
349
342
|
|
|
350
|
-
def integrity_check(self, long
|
|
343
|
+
def integrity_check(self, long=False):
|
|
351
344
|
"""Integrity check task."""
|
|
352
345
|
subtitle = "" if long else "Quick"
|
|
353
346
|
status = Status(JanitorStatusTypes.INTEGRITY_CHECK, subtitle=subtitle)
|
|
@@ -10,6 +10,7 @@ from codex.librarian.janitor.cleanup import TOTAL_NUM_FK_CLASSES, CleanupMixin
|
|
|
10
10
|
from codex.librarian.janitor.failed_imports import UpdateFailedImportsMixin
|
|
11
11
|
from codex.librarian.janitor.integrity import IntegrityMixin
|
|
12
12
|
from codex.librarian.janitor.latest_version import LatestVersionMixin
|
|
13
|
+
from codex.librarian.janitor.log_compress import LogCompressMixin
|
|
13
14
|
from codex.librarian.janitor.status import JanitorStatusTypes
|
|
14
15
|
from codex.librarian.janitor.tasks import (
|
|
15
16
|
ForceUpdateAllFailedImportsTask,
|
|
@@ -20,6 +21,7 @@ from codex.librarian.janitor.tasks import (
|
|
|
20
21
|
JanitorCleanupBookmarksTask,
|
|
21
22
|
JanitorCleanupSessionsTask,
|
|
22
23
|
JanitorClearStatusTask,
|
|
24
|
+
JanitorCompressOldLogs,
|
|
23
25
|
JanitorForeignKeyCheck,
|
|
24
26
|
JanitorFTSIntegrityCheck,
|
|
25
27
|
JanitorFTSRebuildTask,
|
|
@@ -61,6 +63,7 @@ _JANITOR_STATII = (
|
|
|
61
63
|
Status(SearchIndexStatusTypes.SEARCH_INDEX_UPDATE),
|
|
62
64
|
Status(SearchIndexStatusTypes.SEARCH_INDEX_REMOVE),
|
|
63
65
|
Status(SearchIndexStatusTypes.SEARCH_INDEX_OPTIMIZE),
|
|
66
|
+
Status(JanitorStatusTypes.COMPRESS_LOGS),
|
|
64
67
|
)
|
|
65
68
|
|
|
66
69
|
|
|
@@ -71,6 +74,7 @@ class Janitor(
|
|
|
71
74
|
UpdateFailedImportsMixin,
|
|
72
75
|
VacuumMixin,
|
|
73
76
|
IntegrityMixin,
|
|
77
|
+
LogCompressMixin,
|
|
74
78
|
):
|
|
75
79
|
"""Janitor inline task runner."""
|
|
76
80
|
|
|
@@ -109,7 +113,7 @@ class Janitor(
|
|
|
109
113
|
case JanitorVacuumTask():
|
|
110
114
|
self.vacuum_db()
|
|
111
115
|
case JanitorBackupTask():
|
|
112
|
-
self.backup_db(
|
|
116
|
+
self.backup_db()
|
|
113
117
|
case JanitorLatestVersionTask():
|
|
114
118
|
self.update_latest_version(task.force)
|
|
115
119
|
case JanitorUpdateTask():
|
|
@@ -152,9 +156,12 @@ class Janitor(
|
|
|
152
156
|
next_tasks = (
|
|
153
157
|
JanitorVacuumTask(),
|
|
154
158
|
JanitorBackupTask(),
|
|
159
|
+
JanitorCompressOldLogs(),
|
|
155
160
|
)
|
|
156
161
|
for next_task in next_tasks:
|
|
157
162
|
self.librarian_queue.put(next_task)
|
|
163
|
+
case JanitorCompressOldLogs():
|
|
164
|
+
self.log_compress()
|
|
158
165
|
case _:
|
|
159
166
|
self.log.warning(f"Janitor received unknown task {task}")
|
|
160
167
|
except Exception:
|
|
@@ -28,7 +28,7 @@ class LatestVersionMixin(WorkerBaseMixin):
|
|
|
28
28
|
response = requests.get(_REPO_URL, timeout=_REPO_TIMEOUT)
|
|
29
29
|
return json.loads(response.text)["info"]["version"]
|
|
30
30
|
|
|
31
|
-
def update_latest_version(self, force
|
|
31
|
+
def update_latest_version(self, force=False):
|
|
32
32
|
"""Get the latest version from a remote repo using a cache."""
|
|
33
33
|
status = Status(JanitorStatusTypes.CODEX_LATEST_VERSION)
|
|
34
34
|
try:
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Rotate logs."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from lzma import LZMAFile
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from humanize import naturalsize
|
|
8
|
+
|
|
9
|
+
from codex.librarian.janitor.status import JanitorStatusTypes
|
|
10
|
+
from codex.settings.settings import LOG_DIR
|
|
11
|
+
from codex.status import Status
|
|
12
|
+
from codex.worker_base import WorkerBaseMixin
|
|
13
|
+
|
|
14
|
+
_LOG_GLOB = "codex.log.*"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class LogStats:
|
|
19
|
+
"""Collect stats for compressed logs."""
|
|
20
|
+
|
|
21
|
+
count = 0
|
|
22
|
+
old_size = 0
|
|
23
|
+
new_size = 0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class LogCompressMixin(WorkerBaseMixin):
|
|
27
|
+
"""Rotate logs with janitor."""
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def _get_old_log_paths():
|
|
31
|
+
"""Get old log paths to compress and sort them by reverse age."""
|
|
32
|
+
old_log_paths = {}
|
|
33
|
+
for path_str in LOG_DIR.glob(_LOG_GLOB):
|
|
34
|
+
old_path = Path(path_str)
|
|
35
|
+
try:
|
|
36
|
+
log_number = int(old_path.suffix[1:])
|
|
37
|
+
if log_number == 1:
|
|
38
|
+
continue
|
|
39
|
+
except ValueError:
|
|
40
|
+
continue
|
|
41
|
+
old_log_paths[log_number] = old_path
|
|
42
|
+
return dict(sorted(old_log_paths.items(), reverse=True)).values()
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def _rotate_log(old_path, stats):
|
|
46
|
+
"""Rotate one log file."""
|
|
47
|
+
new_path = Path(str(old_path) + ".xz")
|
|
48
|
+
if new_path.exists():
|
|
49
|
+
return
|
|
50
|
+
with (
|
|
51
|
+
LZMAFile(new_path, mode="w", preset=9) as log_archive,
|
|
52
|
+
old_path.open("r") as log_file,
|
|
53
|
+
):
|
|
54
|
+
data = log_file.read()
|
|
55
|
+
log_archive.write(data.encode())
|
|
56
|
+
stats.count += 1
|
|
57
|
+
stats.old_size += old_path.stat().st_size
|
|
58
|
+
stats.new_size += new_path.stat().st_size
|
|
59
|
+
if new_path.exists():
|
|
60
|
+
old_path.unlink(missing_ok=True)
|
|
61
|
+
|
|
62
|
+
def log_compress(self):
|
|
63
|
+
"""Compress old log files and report on savings."""
|
|
64
|
+
status = Status(JanitorStatusTypes.COMPRESS_LOGS)
|
|
65
|
+
try:
|
|
66
|
+
self.status_controller.start(status)
|
|
67
|
+
old_log_paths = self._get_old_log_paths()
|
|
68
|
+
stats = LogStats()
|
|
69
|
+
for old_path in old_log_paths:
|
|
70
|
+
self._rotate_log(old_path, stats)
|
|
71
|
+
if stats.count:
|
|
72
|
+
saved = naturalsize(stats.old_size - stats.new_size)
|
|
73
|
+
self.log.info(f"Compressed logs. Saved {saved}.")
|
|
74
|
+
else:
|
|
75
|
+
self.log.debug("No logs compressed.")
|
|
76
|
+
finally:
|
|
77
|
+
self.status_controller.finish(status)
|
codex/librarian/janitor/tasks.py
CHANGED
|
@@ -107,3 +107,8 @@ class JanitorAdoptOrphanFoldersFinishedTask(JanitorTask):
|
|
|
107
107
|
@dataclass
|
|
108
108
|
class JanitorSearchOptimizeFinishedTask(JanitorTask):
|
|
109
109
|
"""Signals to the Janitor that the Search Optimize task is finished."""
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@dataclass
|
|
113
|
+
class JanitorCompressOldLogs(JanitorTask):
|
|
114
|
+
"""Compress old logs."""
|
|
@@ -27,7 +27,7 @@ class UpdateMixin(WorkerBaseMixin):
|
|
|
27
27
|
versio_latest_version = Version(latest_version)
|
|
28
28
|
|
|
29
29
|
installed_versio_version = Version(VERSION)
|
|
30
|
-
if versio_latest_version.parts[1] and not installed_versio_version.parts[1]: # type: ignore
|
|
30
|
+
if versio_latest_version.parts[1] and not installed_versio_version.parts[1]: # type: ignore
|
|
31
31
|
pre_blurb = "latest version is a prerelease. But installed version is not."
|
|
32
32
|
else:
|
|
33
33
|
result = versio_latest_version > installed_versio_version
|
|
@@ -35,7 +35,7 @@ class UpdateMixin(WorkerBaseMixin):
|
|
|
35
35
|
self.log.debug(f"{latest_version=} > {VERSION=} = {result}{pre_blurb}")
|
|
36
36
|
return result
|
|
37
37
|
|
|
38
|
-
def update_codex(self, force
|
|
38
|
+
def update_codex(self, force=False):
|
|
39
39
|
"""Update the package and restart everything if the version changed."""
|
|
40
40
|
status = Status(JanitorStatusTypes.CODEX_UPDATE)
|
|
41
41
|
try:
|
|
@@ -30,7 +30,7 @@ class VacuumMixin(WorkerBaseMixin):
|
|
|
30
30
|
finally:
|
|
31
31
|
self.status_controller.finish(status)
|
|
32
32
|
|
|
33
|
-
def backup_db(self,
|
|
33
|
+
def backup_db(self, backup_path=BACKUP_DB_PATH, show_status=True):
|
|
34
34
|
"""Backup the database."""
|
|
35
35
|
status = Status(JanitorStatusTypes.DB_BACKUP) if show_status else ""
|
|
36
36
|
try:
|
codex/librarian/librariand.py
CHANGED
|
@@ -42,6 +42,7 @@ from codex.librarian.watchdog.tasks import (
|
|
|
42
42
|
WatchdogSyncTask,
|
|
43
43
|
)
|
|
44
44
|
from codex.logger_base import LoggerBaseMixin
|
|
45
|
+
from codex.settings.settings import SET_PROC_TITLE
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
class LibrarianDaemon(Process, LoggerBaseMixin):
|
|
@@ -79,7 +80,7 @@ class LibrarianDaemon(Process, LoggerBaseMixin):
|
|
|
79
80
|
startup_tasks = (
|
|
80
81
|
AdoptOrphanFoldersTask(),
|
|
81
82
|
WatchdogSyncTask(),
|
|
82
|
-
SearchIndexUpdateTask(
|
|
83
|
+
SearchIndexUpdateTask(False),
|
|
83
84
|
)
|
|
84
85
|
|
|
85
86
|
for task in startup_tasks:
|
|
@@ -157,6 +158,10 @@ class LibrarianDaemon(Process, LoggerBaseMixin):
|
|
|
157
158
|
|
|
158
159
|
def _startup(self):
|
|
159
160
|
"""Initialize threads."""
|
|
161
|
+
if SET_PROC_TITLE:
|
|
162
|
+
from setproctitle import setproctitle
|
|
163
|
+
|
|
164
|
+
setproctitle("Codex" + self.name)
|
|
160
165
|
self.init_logger(self.log_queue)
|
|
161
166
|
self.log.debug(f"Started {self.name}.")
|
|
162
167
|
self.janitor = Janitor(self.log_queue, self.queue)
|
|
@@ -193,8 +198,7 @@ class LibrarianDaemon(Process, LoggerBaseMixin):
|
|
|
193
198
|
self.log_queue.join_thread()
|
|
194
199
|
|
|
195
200
|
def run(self):
|
|
196
|
-
"""
|
|
197
|
-
Process tasks from the queue.
|
|
201
|
+
"""Process tasks from the queue.
|
|
198
202
|
|
|
199
203
|
This process also runs the crond thread and the Watchdog Observer
|
|
200
204
|
threads.
|
|
@@ -16,8 +16,7 @@ class NotifierThread(AggregateMessageQueuedThread):
|
|
|
16
16
|
self.cache[item.text] = item
|
|
17
17
|
|
|
18
18
|
def _send_task(self, task):
|
|
19
|
-
"""
|
|
20
|
-
Send a group_send message to the mulitprocess broadcast channel.
|
|
19
|
+
"""Send a group_send message to the mulitprocess broadcast channel.
|
|
21
20
|
|
|
22
21
|
A random consumer awaiting the broadcast channel will consume it,
|
|
23
22
|
and do a group_send with it's message.
|
|
@@ -22,7 +22,7 @@ class OptimizeMixin(QueuedThread):
|
|
|
22
22
|
self.abort_event = abort_event
|
|
23
23
|
super().__init__(*args, **kwargs)
|
|
24
24
|
|
|
25
|
-
def optimize(self, janitor
|
|
25
|
+
def optimize(self, janitor=False):
|
|
26
26
|
"""Remove records not in the database from the index, trapping exceptions."""
|
|
27
27
|
start_time = time()
|
|
28
28
|
status = Status(SearchIndexStatusTypes.SEARCH_INDEX_OPTIMIZE)
|
codex/librarian/search/remove.py
CHANGED
|
@@ -21,7 +21,7 @@ class RemoveMixin(OptimizeMixin):
|
|
|
21
21
|
self.status_controller.finish(clear_status)
|
|
22
22
|
self.log.info("Old search index cleared.")
|
|
23
23
|
|
|
24
|
-
def _remove_stale_records(self, status):
|
|
24
|
+
def _remove_stale_records(self, status): # type: ignore
|
|
25
25
|
"""Remove records not in the database from the index."""
|
|
26
26
|
start_time = time()
|
|
27
27
|
delete_comicfts = ComicFTS.objects.filter(comic__isnull=True)
|
codex/librarian/search/update.py
CHANGED
|
@@ -159,7 +159,7 @@ class FTSUpdateMixin(RemoveMixin):
|
|
|
159
159
|
obj_list.append(comicfts)
|
|
160
160
|
self.log.debug(f"{len(obj_list)}/{comics.count()} entries prepped.")
|
|
161
161
|
|
|
162
|
-
def _get_comicfts_list(self, comics, create
|
|
162
|
+
def _get_comicfts_list(self, comics, create=False):
|
|
163
163
|
"""Create a ComicFTS object for bulk_create or bulk_update."""
|
|
164
164
|
country_field = CountryField()
|
|
165
165
|
language_field = LanguageField()
|
|
@@ -178,7 +178,7 @@ class FTSUpdateMixin(RemoveMixin):
|
|
|
178
178
|
self.log.debug(f"{verb} no search entries.")
|
|
179
179
|
self.status_controller.finish(status)
|
|
180
180
|
|
|
181
|
-
def _update_search_index_operate(self, comics_qs, create
|
|
181
|
+
def _update_search_index_operate(self, comics_qs, create=False):
|
|
182
182
|
count = comics_qs.count()
|
|
183
183
|
verb = "create" if create else "update"
|
|
184
184
|
if not count:
|
|
@@ -285,7 +285,7 @@ class FTSUpdateMixin(RemoveMixin):
|
|
|
285
285
|
elapsed = naturaldelta(elapsed_time)
|
|
286
286
|
self.log.info(f"Search index updated in {elapsed}.")
|
|
287
287
|
|
|
288
|
-
def update_search_index(self, rebuild
|
|
288
|
+
def update_search_index(self, rebuild=False):
|
|
289
289
|
"""Update or Rebuild the search index."""
|
|
290
290
|
start_time = time()
|
|
291
291
|
self.abort_event.clear()
|
|
@@ -62,12 +62,11 @@ class CodexStats:
|
|
|
62
62
|
request_model_set = self.params.get(key, {})
|
|
63
63
|
all_models = _KEY_MODELS_MAP[key]
|
|
64
64
|
if request_model_set:
|
|
65
|
-
models = [
|
|
66
|
-
|
|
67
|
-
for model in all_models
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
]
|
|
65
|
+
models = []
|
|
66
|
+
for model_name in request_model_set:
|
|
67
|
+
for model in all_models:
|
|
68
|
+
if model.__name__.lower() == model_name.lower():
|
|
69
|
+
models.append(model)
|
|
71
70
|
else:
|
|
72
71
|
models = all_models
|
|
73
72
|
return tuple(models)
|
|
@@ -150,7 +149,7 @@ class CodexStats:
|
|
|
150
149
|
|
|
151
150
|
def _add_file_types(self, obj):
|
|
152
151
|
"""Query for file types."""
|
|
153
|
-
if self.params and "
|
|
152
|
+
if self.params and "fileTypes" not in self.params:
|
|
154
153
|
return
|
|
155
154
|
file_types = {}
|
|
156
155
|
qs = (
|
|
@@ -61,12 +61,12 @@ class CodexDatabaseSnapshot(DirectorySnapshot, LoggerBaseMixin):
|
|
|
61
61
|
def __init__(
|
|
62
62
|
self,
|
|
63
63
|
path,
|
|
64
|
-
_recursive=True, #
|
|
64
|
+
_recursive=True, # unused, always recursive
|
|
65
65
|
stat=os.stat,
|
|
66
66
|
_listdir=os.listdir, # unused for database
|
|
67
|
-
force=False,
|
|
67
|
+
force=False,
|
|
68
68
|
log_queue=None,
|
|
69
|
-
covers_only=False,
|
|
69
|
+
covers_only=False,
|
|
70
70
|
):
|
|
71
71
|
"""Initialize like DirectorySnapshot but use a database walk."""
|
|
72
72
|
self._covers_only = covers_only
|
|
@@ -33,8 +33,7 @@ class CodexDirectorySnapshotDiff(DirectorySnapshotDiff):
|
|
|
33
33
|
return self._get_inode(data.ref, path) == self._get_inode(data.snapshot, path)
|
|
34
34
|
|
|
35
35
|
def _is_stats_equal(self, data, old_path, new_path):
|
|
36
|
-
"""
|
|
37
|
-
Return if the mtime and size are equal.
|
|
36
|
+
"""Return if the mtime and size are equal.
|
|
38
37
|
|
|
39
38
|
For old paths in the ref and new paths in the snapshot.
|
|
40
39
|
"""
|
|
@@ -85,7 +84,9 @@ class CodexDirectorySnapshotDiff(DirectorySnapshotDiff):
|
|
|
85
84
|
if not self._is_stats_equal(data, old_path, new_path):
|
|
86
85
|
data.modified.add(new_path)
|
|
87
86
|
|
|
88
|
-
def __init__(
|
|
87
|
+
def __init__( # C901, PLR0912
|
|
88
|
+
self, ref, snapshot, ignore_device=False, inode_only_modified=False
|
|
89
|
+
):
|
|
89
90
|
"""Create diff object."""
|
|
90
91
|
self._ignore_device = ignore_device
|
|
91
92
|
self._inode_only_modified = inode_only_modified
|
|
@@ -46,14 +46,14 @@ class DatabasePollingEmitter(EventEmitter, WorkerBaseMixin):
|
|
|
46
46
|
|
|
47
47
|
_DIR_NOT_FOUND_TIMEOUT = 15 * 60
|
|
48
48
|
|
|
49
|
-
def __init__( # noqa
|
|
49
|
+
def __init__( # noqa PLR0913
|
|
50
50
|
self,
|
|
51
51
|
event_queue,
|
|
52
52
|
watch,
|
|
53
53
|
timeout=DEFAULT_EMITTER_TIMEOUT,
|
|
54
54
|
log_queue=None,
|
|
55
55
|
librarian_queue=None,
|
|
56
|
-
covers_only=False,
|
|
56
|
+
covers_only=False,
|
|
57
57
|
):
|
|
58
58
|
"""Initialize snapshot methods."""
|
|
59
59
|
self.init_worker(log_queue, librarian_queue)
|
|
@@ -72,7 +72,7 @@ class DatabasePollingEmitter(EventEmitter, WorkerBaseMixin):
|
|
|
72
72
|
# default stat and listdir params
|
|
73
73
|
)
|
|
74
74
|
|
|
75
|
-
def poll(self, force
|
|
75
|
+
def poll(self, force=False):
|
|
76
76
|
"""Poll now, sooner than timeout."""
|
|
77
77
|
self._force = force
|
|
78
78
|
with self._poll_cond:
|
|
@@ -118,7 +118,7 @@ class DatabasePollingEmitter(EventEmitter, WorkerBaseMixin):
|
|
|
118
118
|
return ok
|
|
119
119
|
|
|
120
120
|
@property
|
|
121
|
-
def timeout(self) -> int | None: # type: ignore
|
|
121
|
+
def timeout(self) -> int | None: # type: ignore
|
|
122
122
|
"""Get the timeout for this emitter from its library."""
|
|
123
123
|
# The timeout from the constructor, self._timeout, is thrown away in favor
|
|
124
124
|
# of a dynamic timeout from the database.
|
|
@@ -198,7 +198,8 @@ class CodexLibraryEventHandler(CodexEventHandlerBase):
|
|
|
198
198
|
task = WatchdogEventTask(self.library_pk, sub_event)
|
|
199
199
|
self.librarian_queue.put(task)
|
|
200
200
|
|
|
201
|
-
#
|
|
201
|
+
# Calls stub event dispatchers
|
|
202
|
+
# super().dispatch(event)
|
|
202
203
|
except Exception:
|
|
203
204
|
self.log.exception(f"{self.__class__.__name__} dispatch")
|
|
204
205
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""The Codex Library Watchdog Observer threads."""
|
|
2
2
|
|
|
3
|
-
from watchdog.events import FileSystemEvent, FileSystemEventHandler
|
|
4
3
|
from watchdog.observers import Observer
|
|
5
4
|
from watchdog.observers.api import (
|
|
6
5
|
DEFAULT_OBSERVER_TIMEOUT,
|
|
@@ -99,16 +98,14 @@ class UatuMixin(BaseObserver, WorkerBaseMixin):
|
|
|
99
98
|
except Exception:
|
|
100
99
|
self.log.exception(f"{self.__class__.__name__} sync library watches")
|
|
101
100
|
|
|
102
|
-
def schedule(
|
|
101
|
+
def schedule( # type: ignore
|
|
103
102
|
self,
|
|
104
|
-
event_handler
|
|
105
|
-
path
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"""
|
|
111
|
-
Override BaseObserver for Codex emitter class.
|
|
103
|
+
event_handler,
|
|
104
|
+
path,
|
|
105
|
+
recursive=False,
|
|
106
|
+
_event_filter=None,
|
|
107
|
+
):
|
|
108
|
+
"""Override BaseObserver for Codex emitter class.
|
|
112
109
|
|
|
113
110
|
https://pythonhosted.org/watchdog/_modules/watchdog/observers/api.html#BaseObserver
|
|
114
111
|
"""
|
|
@@ -140,11 +137,9 @@ class UatuMixin(BaseObserver, WorkerBaseMixin):
|
|
|
140
137
|
# watchdog class structure doesn't work that way.
|
|
141
138
|
|
|
142
139
|
|
|
143
|
-
class LibraryEventObserver(UatuMixin, Observer): # type: ignore
|
|
140
|
+
class LibraryEventObserver(UatuMixin, Observer): # type: ignore
|
|
144
141
|
"""Regular observer."""
|
|
145
142
|
|
|
146
|
-
# Observer is a dynamically generated class by platform at runtime.
|
|
147
|
-
|
|
148
143
|
ENABLE_FIELD = "events"
|
|
149
144
|
|
|
150
145
|
|
|
@@ -161,7 +156,7 @@ class LibraryPollingObserver(UatuMixin):
|
|
|
161
156
|
*args, emitter_class=DatabasePollingEmitter, timeout=timeout, **kwargs
|
|
162
157
|
)
|
|
163
158
|
|
|
164
|
-
def poll(self, library_pks, force
|
|
159
|
+
def poll(self, library_pks, force=False):
|
|
165
160
|
"""Poll each requested emitter."""
|
|
166
161
|
try:
|
|
167
162
|
qs = Library.objects.all()
|
|
@@ -170,7 +165,7 @@ class LibraryPollingObserver(UatuMixin):
|
|
|
170
165
|
paths = frozenset(qs.values_list("path", flat=True))
|
|
171
166
|
|
|
172
167
|
for emitter in self.emitters:
|
|
173
|
-
polling_emitter: DatabasePollingEmitter = emitter # type: ignore
|
|
168
|
+
polling_emitter: DatabasePollingEmitter = emitter # type: ignore
|
|
174
169
|
if emitter.watch.path in paths:
|
|
175
170
|
polling_emitter.poll(force)
|
|
176
171
|
except Exception:
|