codex 1.7.2__py3-none-any.whl → 1.7.3__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 +2 -1
- codex/choices.py +10 -11
- codex/choices_to_json.py +8 -8
- codex/db.py +2 -2
- codex/exceptions.py +5 -6
- codex/librarian/bookmark/bookmarkd.py +9 -6
- codex/librarian/bookmark/tasks.py +1 -1
- codex/librarian/bookmark/update.py +17 -31
- codex/librarian/covers/create.py +10 -8
- codex/librarian/covers/path.py +6 -5
- codex/librarian/covers/purge.py +2 -2
- codex/librarian/cron/crond.py +1 -1
- codex/librarian/importer/aggregate.py +2 -2
- codex/librarian/importer/cache.py +1 -4
- codex/librarian/importer/create_comics.py +2 -2
- codex/librarian/importer/create_covers.py +1 -1
- codex/librarian/importer/create_fks.py +4 -3
- 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 +3 -1
- codex/librarian/importer/importerd.py +3 -3
- codex/librarian/importer/link_comics.py +2 -1
- codex/librarian/importer/moved.py +2 -7
- codex/librarian/importer/query_fks.py +3 -6
- codex/librarian/importer/tasks.py +1 -1
- codex/librarian/janitor/integrity.py +27 -20
- codex/librarian/janitor/janitor.py +5 -2
- codex/librarian/janitor/latest_version.py +1 -1
- codex/librarian/janitor/update.py +2 -2
- codex/librarian/janitor/vacuum.py +1 -1
- codex/librarian/librariand.py +16 -15
- codex/librarian/notifier/notifierd.py +2 -1
- codex/librarian/search/optimize.py +1 -1
- codex/librarian/search/remove.py +1 -1
- codex/librarian/search/update.py +11 -7
- codex/librarian/telemeter/stats.py +7 -6
- codex/librarian/telemeter/telemeter.py +0 -1
- codex/librarian/watchdog/db_snapshot.py +3 -3
- codex/librarian/watchdog/dir_snapshot_diff.py +3 -4
- codex/librarian/watchdog/emitter.py +4 -4
- codex/librarian/watchdog/event_batcherd.py +2 -1
- codex/librarian/watchdog/events.py +1 -2
- codex/librarian/watchdog/observers.py +15 -10
- codex/logger/loggerd.py +40 -17
- codex/logger/logging.py +1 -1
- codex/memory.py +3 -2
- codex/migrations/0001_init.py +1 -2
- codex/migrations/0014_pdf_issue_suffix_remove_cover_image_sort_name.py +1 -2
- codex/migrations/0018_rename_userbookmark_bookmark.py +1 -2
- codex/migrations/0028_telemeter.py +1 -5
- codex/migrations/0031_adminflag_banner.py +50 -0
- codex/models/admin.py +4 -3
- codex/models/base.py +3 -1
- codex/models/bookmark.py +4 -7
- codex/models/comic.py +2 -2
- codex/models/functions.py +12 -5
- codex/models/groups.py +1 -1
- codex/models/library.py +1 -1
- codex/models/paths.py +4 -4
- codex/models/query.py +8 -4
- codex/models/util.py +1 -1
- codex/permissions.py +1 -1
- codex/run.py +1 -1
- codex/serializers/admin/flags.py +1 -1
- codex/serializers/admin/libraries.py +1 -3
- codex/serializers/auth.py +1 -0
- codex/serializers/browser/choices.py +2 -2
- codex/serializers/browser/mixins.py +5 -1
- 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 +0 -2
- codex/serializers/opds/authentication.py +2 -1
- codex/serializers/opds/v2/__init__.py +1 -0
- codex/serializers/opds/v2/facet.py +13 -0
- codex/serializers/opds/v2/feed.py +36 -0
- codex/serializers/opds/v2/links.py +75 -0
- codex/serializers/opds/v2/metadata.py +23 -0
- codex/serializers/opds/v2/progression.py +65 -0
- codex/serializers/opds/v2/publication.py +81 -0
- codex/serializers/opds/{v2_unused.py → v2/unused.py} +16 -9
- codex/serializers/route.py +2 -2
- codex/settings/settings.py +4 -3
- codex/signals/django_signals.py +1 -1
- codex/static_root/assets/VCheckbox-Dv6fwaDb.56abbfb00c8a.js +1 -0
- 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 +1 -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 +1 -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 +1 -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 +1 -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 +1 -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 +1 -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 +1 -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/VDialog-DWos4S54.b07aca713774.css +1 -0
- codex/static_root/assets/VDialog-DWos4S54.b07aca713774.css.br +0 -0
- codex/static_root/assets/VDialog-DWos4S54.b07aca713774.css.gz +0 -0
- codex/static_root/assets/VDialog-DWos4S54.css +1 -0
- codex/static_root/assets/VDialog-DWos4S54.css.br +0 -0
- codex/static_root/assets/VDialog-DWos4S54.css.gz +0 -0
- codex/static_root/assets/VDivider-DU47sRrT.3d2e17799e5c.css +1 -0
- codex/static_root/assets/VDivider-DU47sRrT.3d2e17799e5c.css.br +0 -0
- codex/static_root/assets/VDivider-DU47sRrT.3d2e17799e5c.css.gz +0 -0
- codex/static_root/assets/VDivider-DU47sRrT.css +1 -0
- codex/static_root/assets/VDivider-DU47sRrT.css.br +0 -0
- codex/static_root/assets/VDivider-DU47sRrT.css.gz +0 -0
- codex/static_root/assets/VDivider-DUxQu-IZ.73d92ae2a07e.js +1 -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 +1 -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 +1 -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 +1 -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-DxBt30-N.138c0b89b6fc.css +1 -0
- codex/static_root/assets/VForm-DxBt30-N.138c0b89b6fc.css.br +0 -0
- codex/static_root/assets/VForm-DxBt30-N.138c0b89b6fc.css.gz +0 -0
- codex/static_root/assets/VForm-DxBt30-N.css +1 -0
- codex/static_root/assets/VForm-DxBt30-N.css.br +0 -0
- codex/static_root/assets/VForm-DxBt30-N.css.gz +0 -0
- codex/static_root/assets/VForm-hB4C5jVd.a2b90ddcd8ee.js +1 -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 +1 -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 +1 -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 +1 -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-CP_CVb8s.6309f7bf17bb.css +1 -0
- codex/static_root/assets/VSelect-CP_CVb8s.6309f7bf17bb.css.br +0 -0
- codex/static_root/assets/VSelect-CP_CVb8s.6309f7bf17bb.css.gz +0 -0
- codex/static_root/assets/VSelect-CP_CVb8s.css +1 -0
- codex/static_root/assets/VSelect-CP_CVb8s.css.br +0 -0
- codex/static_root/assets/VSelect-CP_CVb8s.css.gz +0 -0
- codex/static_root/assets/VSelect-L4v_m3ag.db9fb8348617.js +1 -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 +1 -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 +1 -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 +1 -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/VSelectionControl-DPpfgCW2.cc18de4e83f6.css +1 -0
- codex/static_root/assets/VSelectionControl-DPpfgCW2.cc18de4e83f6.css.br +0 -0
- codex/static_root/assets/VSelectionControl-DPpfgCW2.cc18de4e83f6.css.gz +0 -0
- codex/static_root/assets/VSelectionControl-DPpfgCW2.css +1 -0
- codex/static_root/assets/VSelectionControl-DPpfgCW2.css.br +0 -0
- codex/static_root/assets/VSelectionControl-DPpfgCW2.css.gz +0 -0
- codex/static_root/assets/VTable-CtorAbOx.bbda450cbd73.js +1 -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 +1 -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 +1 -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 +1 -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 +1 -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 +1 -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 +1 -0
- 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 +1 -0
- 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 +1 -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 +1 -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 +1 -0
- 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 +1 -0
- 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 +1 -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 +1 -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 +1 -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 +1 -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 +1 -0
- 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 +1 -0
- 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 +1 -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 +1 -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 +1 -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 +1 -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 +1 -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 +1 -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-ud5mPZpn.0f0a537959aa.js → filter-xcEcgcIx.be1bb4725c89.js} +1 -1
- 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-ud5mPZpn.js → filter-xcEcgcIx.js} +1 -1
- 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 +1 -0
- 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 +1 -0
- 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 +1 -0
- 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 +1 -0
- 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-CFNX6kJ2.9b56b4459240.css +1 -0
- codex/static_root/assets/forwardRefs-CFNX6kJ2.9b56b4459240.css.br +0 -0
- codex/static_root/assets/forwardRefs-CFNX6kJ2.9b56b4459240.css.gz +0 -0
- codex/static_root/assets/forwardRefs-CFNX6kJ2.css +1 -0
- codex/static_root/assets/forwardRefs-CFNX6kJ2.css.br +0 -0
- codex/static_root/assets/forwardRefs-CFNX6kJ2.css.gz +0 -0
- codex/static_root/assets/forwardRefs-D1ZDjzWx.96fccf773093.js +1 -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 +1 -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 +1 -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 +1 -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-CODU7jcH.8c13689ae574.css +1 -0
- codex/static_root/assets/http-error-CODU7jcH.8c13689ae574.css.br +0 -0
- codex/static_root/assets/http-error-CODU7jcH.8c13689ae574.css.gz +0 -0
- codex/static_root/assets/http-error-CODU7jcH.css +1 -0
- codex/static_root/assets/http-error-CODU7jcH.css.br +0 -0
- codex/static_root/assets/http-error-CODU7jcH.css.gz +0 -0
- codex/static_root/assets/http-error-CjSb8orc.ad6fc5733ed8.js +1 -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 +1 -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 +1 -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 +1 -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-Cat0MAK5.5911f022188e.css → library-tab-CgsXOX_r.75baedb7e976.css} +1 -1
- codex/static_root/assets/library-tab-CgsXOX_r.75baedb7e976.css.br +0 -0
- codex/static_root/assets/library-tab-CgsXOX_r.75baedb7e976.css.gz +0 -0
- codex/static_root/assets/{library-tab-Cat0MAK5.css → library-tab-CgsXOX_r.css} +1 -1
- codex/static_root/assets/library-tab-CgsXOX_r.css.br +0 -0
- codex/static_root/assets/library-tab-CgsXOX_r.css.gz +0 -0
- codex/static_root/assets/library-tab-hkMMBz1x.02270491d822.js +1 -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 +1 -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 +35 -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 +35 -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 +1 -0
- 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 +1 -0
- 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-D5VQREy5.css +1 -0
- codex/static_root/assets/pagination-toolbar-D5VQREy5.css.br +0 -0
- codex/static_root/assets/pagination-toolbar-D5VQREy5.css.gz +0 -0
- codex/static_root/assets/pagination-toolbar-D5VQREy5.dcb0eba65827.css +1 -0
- codex/static_root/assets/pagination-toolbar-D5VQREy5.dcb0eba65827.css.br +0 -0
- codex/static_root/assets/pagination-toolbar-D5VQREy5.dcb0eba65827.css.gz +0 -0
- codex/static_root/assets/pagination-toolbar-DoqxSygU.f985bc705fe5.js +1 -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 +1 -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 +348 -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 +348 -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-Dd2KmdCN.115d4bfe9280.css → reader-D_3ruSqa.2ed32f08e906.css} +1 -1
- codex/static_root/assets/reader-D_3ruSqa.2ed32f08e906.css.br +0 -0
- codex/static_root/assets/reader-D_3ruSqa.2ed32f08e906.css.gz +0 -0
- codex/static_root/assets/{reader-Dd2KmdCN.css → reader-D_3ruSqa.css} +1 -1
- codex/static_root/assets/reader-D_3ruSqa.css.br +0 -0
- codex/static_root/assets/reader-D_3ruSqa.css.gz +0 -0
- codex/static_root/assets/reader-hHIonVbA.4c12219242a9.js +2 -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 +2 -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 +1 -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 +1 -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 +2 -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 +2 -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/settings-drawer-DMSsWF8c.75a6ea969e71.css +1 -0
- codex/static_root/assets/settings-drawer-DMSsWF8c.75a6ea969e71.css.br +0 -0
- codex/static_root/assets/settings-drawer-DMSsWF8c.75a6ea969e71.css.gz +0 -0
- codex/static_root/assets/settings-drawer-DMSsWF8c.css +1 -0
- codex/static_root/assets/settings-drawer-DMSsWF8c.css.br +0 -0
- codex/static_root/assets/settings-drawer-DMSsWF8c.css.gz +0 -0
- codex/static_root/assets/stats-tab-BzaipD0m.b6bf627ea860.js +1 -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 +1 -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 +1 -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 +1 -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-CsSak07X.c5536d9dae75.css +1 -0
- codex/static_root/assets/unauthorized-CsSak07X.c5536d9dae75.css.br +0 -0
- codex/static_root/assets/unauthorized-CsSak07X.c5536d9dae75.css.gz +0 -0
- codex/static_root/assets/unauthorized-CsSak07X.css +1 -0
- codex/static_root/assets/unauthorized-CsSak07X.css.br +0 -0
- codex/static_root/assets/unauthorized-CsSak07X.css.gz +0 -0
- codex/static_root/assets/unauthorized-DJSr03Dw.7555cbcf1064.js +1 -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 +1 -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 +1 -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 +1 -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 +735 -0
- codex/static_root/manifest.cbc39bca88fc.json.br +0 -0
- codex/static_root/manifest.cbc39bca88fc.json.gz +0 -0
- codex/static_root/manifest.json +388 -365
- 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 +9 -12
- codex/templates/index.html +1 -1
- codex/threads.py +3 -3
- codex/urls/api/admin.py +4 -3
- codex/urls/api/browser.py +1 -1
- codex/urls/opds/v2.py +6 -0
- codex/urls/root.py +4 -3
- codex/views/admin/api_key.py +1 -4
- codex/views/admin/flag.py +5 -1
- codex/views/admin/library.py +4 -4
- codex/views/admin/stats.py +10 -10
- codex/views/admin/tasks.py +9 -9
- codex/views/auth.py +3 -8
- codex/views/bookmark.py +53 -41
- codex/views/browser/annotate/bookmark.py +6 -4
- codex/views/browser/annotate/card.py +3 -18
- codex/views/browser/annotate/order.py +51 -25
- codex/views/browser/bookmark.py +53 -0
- codex/views/browser/breadcrumbs.py +6 -5
- codex/views/browser/browser.py +2 -2
- codex/views/browser/choices.py +6 -5
- codex/views/browser/cover.py +6 -3
- codex/views/browser/download.py +4 -1
- codex/views/browser/filters/bookmark.py +5 -33
- codex/views/browser/filters/field.py +1 -1
- codex/views/browser/filters/filter.py +6 -8
- codex/views/browser/filters/group.py +5 -4
- codex/views/browser/filters/search/field/expression.py +1 -2
- 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 +4 -19
- codex/views/browser/group_mtime.py +3 -3
- codex/views/browser/metadata/annotate.py +1 -1
- codex/views/browser/metadata/copy_intersections.py +1 -1
- codex/views/browser/metadata/metadata.py +2 -2
- codex/views/browser/mtime.py +1 -1
- codex/views/browser/order_by.py +9 -6
- codex/views/browser/params.py +1 -1
- codex/views/browser/settings.py +1 -1
- codex/views/browser/validate.py +8 -5
- codex/views/const.py +0 -3
- codex/views/frontend.py +20 -5
- codex/views/mixins.py +19 -30
- codex/views/opds/authentication_v1.py +1 -1
- codex/views/opds/const.py +6 -4
- codex/views/opds/util.py +5 -5
- codex/views/opds/v1/entry/entry.py +4 -2
- codex/views/opds/v1/entry/links.py +5 -7
- codex/views/opds/v1/facets.py +8 -4
- codex/views/opds/v1/feed.py +5 -5
- codex/views/opds/v1/links.py +11 -6
- codex/views/opds/v2/const.py +5 -2
- codex/views/opds/v2/feed.py +6 -5
- codex/views/opds/v2/href.py +60 -0
- codex/views/opds/v2/links.py +13 -47
- codex/views/opds/v2/progression.py +136 -0
- codex/views/opds/v2/publications.py +31 -21
- codex/views/opds/v2/top_links.py +2 -1
- codex/views/public.py +12 -5
- codex/views/reader/books.py +22 -10
- codex/views/reader/page.py +8 -8
- 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 +8 -2
- codex/views/settings.py +2 -2
- codex/views/timezone.py +2 -2
- codex/views/util.py +10 -9
- codex/views/version.py +1 -1
- {codex-1.7.2.dist-info → codex-1.7.3.dist-info}/METADATA +21 -26
- codex-1.7.3.dist-info/RECORD +1031 -0
- {codex-1.7.2.dist-info → codex-1.7.3.dist-info}/WHEEL +1 -1
- codex/serializers/opds/v2.py +0 -178
- codex/static_root/assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js +0 -1
- codex/static_root/assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js.br +0 -0
- codex/static_root/assets/VCheckbox-DLMzIII1.1ff8fc2d9a21.js.gz +0 -0
- codex/static_root/assets/VCheckbox-DLMzIII1.js +0 -1
- codex/static_root/assets/VCheckbox-DLMzIII1.js.br +0 -0
- codex/static_root/assets/VCheckbox-DLMzIII1.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js +0 -1
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.094679a3624b.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.js +0 -1
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-BzoQl8XC.js.gz +0 -0
- codex/static_root/assets/VCombobox-CBY8K5CP.fcf2221a9edd.js +0 -1
- codex/static_root/assets/VCombobox-CBY8K5CP.fcf2221a9edd.js.br +0 -0
- codex/static_root/assets/VCombobox-CBY8K5CP.fcf2221a9edd.js.gz +0 -0
- codex/static_root/assets/VCombobox-CBY8K5CP.js +0 -1
- codex/static_root/assets/VCombobox-CBY8K5CP.js.br +0 -0
- codex/static_root/assets/VCombobox-CBY8K5CP.js.gz +0 -0
- codex/static_root/assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css +0 -1
- codex/static_root/assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css.br +0 -0
- codex/static_root/assets/VDialog-DXQz0Ylp.7b23d86dbd0d.css.gz +0 -0
- codex/static_root/assets/VDialog-DXQz0Ylp.css +0 -1
- codex/static_root/assets/VDialog-DXQz0Ylp.css.br +0 -0
- codex/static_root/assets/VDialog-DXQz0Ylp.css.gz +0 -0
- codex/static_root/assets/VDialog-Db4tJYqR.e21a79a5030e.js +0 -1
- codex/static_root/assets/VDialog-Db4tJYqR.e21a79a5030e.js.br +0 -0
- codex/static_root/assets/VDialog-Db4tJYqR.e21a79a5030e.js.gz +0 -0
- codex/static_root/assets/VDialog-Db4tJYqR.js +0 -1
- codex/static_root/assets/VDialog-Db4tJYqR.js.br +0 -0
- codex/static_root/assets/VDialog-Db4tJYqR.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.163e59e38865.js +0 -1
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.163e59e38865.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.163e59e38865.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.js +0 -1
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-DN4yGbOt.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-D2-PWEfs.ce7644863c25.js +0 -1
- codex/static_root/assets/VRadioGroup-D2-PWEfs.ce7644863c25.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D2-PWEfs.ce7644863c25.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-D2-PWEfs.js +0 -1
- codex/static_root/assets/VRadioGroup-D2-PWEfs.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D2-PWEfs.js.gz +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css +0 -1
- codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.br +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.98bdcf35411c.css.gz +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.css +0 -1
- codex/static_root/assets/VSelect-DLu8bpcs.css.br +0 -0
- codex/static_root/assets/VSelect-DLu8bpcs.css.gz +0 -0
- codex/static_root/assets/VSelect-DqXJ23Pc.a1360cbed050.js +0 -1
- codex/static_root/assets/VSelect-DqXJ23Pc.a1360cbed050.js.br +0 -0
- codex/static_root/assets/VSelect-DqXJ23Pc.a1360cbed050.js.gz +0 -0
- codex/static_root/assets/VSelect-DqXJ23Pc.js +0 -1
- codex/static_root/assets/VSelect-DqXJ23Pc.js.br +0 -0
- codex/static_root/assets/VSelect-DqXJ23Pc.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css +0 -1
- codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css.br +0 -0
- codex/static_root/assets/VSelectionControl-CiViEYoC.c77bb19a4a06.css.gz +0 -0
- codex/static_root/assets/VSelectionControl-CiViEYoC.css +0 -1
- codex/static_root/assets/VSelectionControl-CiViEYoC.css.br +0 -0
- codex/static_root/assets/VSelectionControl-CiViEYoC.css.gz +0 -0
- codex/static_root/assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js +0 -1
- codex/static_root/assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CxhDNufT.dd7ca99567fc.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-CxhDNufT.js +0 -1
- codex/static_root/assets/VSelectionControl-CxhDNufT.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CxhDNufT.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css +0 -1
- codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.br +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.830f136ffd41.css.gz +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.css +0 -1
- codex/static_root/assets/VSlideGroup-BtXPhMOT.css.br +0 -0
- codex/static_root/assets/VSlideGroup-BtXPhMOT.css.gz +0 -0
- codex/static_root/assets/VSlideGroup-DRbthp6q.7365c5542d47.js +0 -1
- codex/static_root/assets/VSlideGroup-DRbthp6q.7365c5542d47.js.br +0 -0
- codex/static_root/assets/VSlideGroup-DRbthp6q.7365c5542d47.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-DRbthp6q.js +0 -1
- codex/static_root/assets/VSlideGroup-DRbthp6q.js.br +0 -0
- codex/static_root/assets/VSlideGroup-DRbthp6q.js.gz +0 -0
- codex/static_root/assets/VTable-Cbq-yJos.c884706cac21.js +0 -1
- codex/static_root/assets/VTable-Cbq-yJos.c884706cac21.js.br +0 -0
- codex/static_root/assets/VTable-Cbq-yJos.c884706cac21.js.gz +0 -0
- codex/static_root/assets/VTable-Cbq-yJos.js +0 -1
- codex/static_root/assets/VTable-Cbq-yJos.js.br +0 -0
- codex/static_root/assets/VTable-Cbq-yJos.js.gz +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css +0 -1
- codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.br +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.39995ccf4d52.css.gz +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.css +0 -1
- codex/static_root/assets/VTextField-Crc3gdNh.css.br +0 -0
- codex/static_root/assets/VTextField-Crc3gdNh.css.gz +0 -0
- codex/static_root/assets/VTextField-X5yAw35c.155e276dd747.js +0 -1
- codex/static_root/assets/VTextField-X5yAw35c.155e276dd747.js.br +0 -0
- codex/static_root/assets/VTextField-X5yAw35c.155e276dd747.js.gz +0 -0
- codex/static_root/assets/VTextField-X5yAw35c.js +0 -1
- codex/static_root/assets/VTextField-X5yAw35c.js.br +0 -0
- codex/static_root/assets/VTextField-X5yAw35c.js.gz +0 -0
- codex/static_root/assets/VWindowItem-CRqhVh-9.cd73d01e0591.js +0 -1
- codex/static_root/assets/VWindowItem-CRqhVh-9.cd73d01e0591.js.br +0 -0
- codex/static_root/assets/VWindowItem-CRqhVh-9.cd73d01e0591.js.gz +0 -0
- codex/static_root/assets/VWindowItem-CRqhVh-9.js +0 -1
- codex/static_root/assets/VWindowItem-CRqhVh-9.js.br +0 -0
- codex/static_root/assets/VWindowItem-CRqhVh-9.js.gz +0 -0
- codex/static_root/assets/admin-BFvQwinN.6cfff21f780a.js +0 -1
- codex/static_root/assets/admin-BFvQwinN.6cfff21f780a.js.br +0 -0
- codex/static_root/assets/admin-BFvQwinN.6cfff21f780a.js.gz +0 -0
- codex/static_root/assets/admin-BFvQwinN.js +0 -1
- codex/static_root/assets/admin-BFvQwinN.js.br +0 -0
- codex/static_root/assets/admin-BFvQwinN.js.gz +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.css +0 -1
- codex/static_root/assets/admin-DJ7pIXDQ.css.br +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.css.gz +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css +0 -1
- codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.br +0 -0
- codex/static_root/assets/admin-DJ7pIXDQ.e2a77af73ef2.css.gz +0 -0
- codex/static_root/assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js +0 -1
- codex/static_root/assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js.br +0 -0
- codex/static_root/assets/admin-menu-Jfmp_Yd8.39fa7a18b3b4.js.gz +0 -0
- codex/static_root/assets/admin-menu-Jfmp_Yd8.js +0 -1
- codex/static_root/assets/admin-menu-Jfmp_Yd8.js.br +0 -0
- codex/static_root/assets/admin-menu-Jfmp_Yd8.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js +0 -1
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.cbf73c71330d.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.js +0 -1
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BAk-B1sR.js.gz +0 -0
- codex/static_root/assets/browser-CctlSJji.css +0 -1
- codex/static_root/assets/browser-CctlSJji.css.br +0 -0
- codex/static_root/assets/browser-CctlSJji.css.gz +0 -0
- codex/static_root/assets/browser-CctlSJji.d42d796476d2.css +0 -1
- codex/static_root/assets/browser-CctlSJji.d42d796476d2.css.br +0 -0
- codex/static_root/assets/browser-CctlSJji.d42d796476d2.css.gz +0 -0
- codex/static_root/assets/browser-DJnEeVHz.a78c47516b08.js +0 -1
- codex/static_root/assets/browser-DJnEeVHz.a78c47516b08.js.br +0 -0
- codex/static_root/assets/browser-DJnEeVHz.a78c47516b08.js.gz +0 -0
- codex/static_root/assets/browser-DJnEeVHz.js +0 -1
- codex/static_root/assets/browser-DJnEeVHz.js.br +0 -0
- codex/static_root/assets/browser-DJnEeVHz.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js +0 -1
- codex/static_root/assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js.br +0 -0
- codex/static_root/assets/change-password-dialog-DJtOQw7K.be7fa5ec653d.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-DJtOQw7K.js +0 -1
- codex/static_root/assets/change-password-dialog-DJtOQw7K.js.br +0 -0
- codex/static_root/assets/change-password-dialog-DJtOQw7K.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CME4gKSZ.1606233e784c.js +0 -1
- codex/static_root/assets/confirm-dialog-CME4gKSZ.1606233e784c.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CME4gKSZ.1606233e784c.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CME4gKSZ.js +0 -1
- codex/static_root/assets/confirm-dialog-CME4gKSZ.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CME4gKSZ.js.gz +0 -0
- codex/static_root/assets/datetime-column-D_F30OLW.09cdce0ef96e.js +0 -1
- codex/static_root/assets/datetime-column-D_F30OLW.09cdce0ef96e.js.br +0 -2
- codex/static_root/assets/datetime-column-D_F30OLW.09cdce0ef96e.js.gz +0 -0
- codex/static_root/assets/datetime-column-D_F30OLW.js +0 -1
- codex/static_root/assets/datetime-column-D_F30OLW.js.br +0 -2
- codex/static_root/assets/datetime-column-D_F30OLW.js.gz +0 -0
- codex/static_root/assets/filter-ud5mPZpn.0f0a537959aa.js.br +0 -0
- codex/static_root/assets/filter-ud5mPZpn.0f0a537959aa.js.gz +0 -0
- codex/static_root/assets/filter-ud5mPZpn.js.br +0 -0
- codex/static_root/assets/filter-ud5mPZpn.js.gz +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css +0 -1
- codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.br +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.4dfc6b251e85.css.gz +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.css +0 -1
- codex/static_root/assets/flag-tab-CqWovuBu.css.br +0 -0
- codex/static_root/assets/flag-tab-CqWovuBu.css.gz +0 -0
- codex/static_root/assets/flag-tab-k2g6u_vi.3e1da9318af9.js +0 -1
- codex/static_root/assets/flag-tab-k2g6u_vi.3e1da9318af9.js.br +0 -0
- codex/static_root/assets/flag-tab-k2g6u_vi.3e1da9318af9.js.gz +0 -0
- codex/static_root/assets/flag-tab-k2g6u_vi.js +0 -1
- codex/static_root/assets/flag-tab-k2g6u_vi.js.br +0 -0
- codex/static_root/assets/flag-tab-k2g6u_vi.js.gz +0 -0
- codex/static_root/assets/group-tab-C6Ykf03Z.ff0cc204013a.js +0 -1
- codex/static_root/assets/group-tab-C6Ykf03Z.ff0cc204013a.js.br +0 -0
- codex/static_root/assets/group-tab-C6Ykf03Z.ff0cc204013a.js.gz +0 -0
- codex/static_root/assets/group-tab-C6Ykf03Z.js +0 -1
- codex/static_root/assets/group-tab-C6Ykf03Z.js.br +0 -0
- codex/static_root/assets/group-tab-C6Ykf03Z.js.gz +0 -0
- codex/static_root/assets/http-error-Ctcws1xe.cfd378a792d2.css +0 -1
- codex/static_root/assets/http-error-Ctcws1xe.cfd378a792d2.css.br +0 -0
- codex/static_root/assets/http-error-Ctcws1xe.cfd378a792d2.css.gz +0 -0
- codex/static_root/assets/http-error-Ctcws1xe.css +0 -1
- codex/static_root/assets/http-error-Ctcws1xe.css.br +0 -0
- codex/static_root/assets/http-error-Ctcws1xe.css.gz +0 -0
- codex/static_root/assets/http-error-DQBHK8v5.aea50b1327fd.js +0 -1
- codex/static_root/assets/http-error-DQBHK8v5.aea50b1327fd.js.br +0 -0
- codex/static_root/assets/http-error-DQBHK8v5.aea50b1327fd.js.gz +0 -0
- codex/static_root/assets/http-error-DQBHK8v5.js +0 -1
- codex/static_root/assets/http-error-DQBHK8v5.js.br +0 -0
- codex/static_root/assets/http-error-DQBHK8v5.js.gz +0 -0
- codex/static_root/assets/index-ClGiHwWc.0717bacf5135.js +0 -1
- codex/static_root/assets/index-ClGiHwWc.0717bacf5135.js.br +0 -0
- codex/static_root/assets/index-ClGiHwWc.0717bacf5135.js.gz +0 -0
- codex/static_root/assets/index-ClGiHwWc.js +0 -1
- codex/static_root/assets/index-ClGiHwWc.js.br +0 -0
- codex/static_root/assets/index-ClGiHwWc.js.gz +0 -0
- codex/static_root/assets/library-tab-BpinbqAu.53fa2625e727.js +0 -1
- codex/static_root/assets/library-tab-BpinbqAu.53fa2625e727.js.br +0 -0
- codex/static_root/assets/library-tab-BpinbqAu.53fa2625e727.js.gz +0 -0
- codex/static_root/assets/library-tab-BpinbqAu.js +0 -1
- codex/static_root/assets/library-tab-BpinbqAu.js.br +0 -0
- codex/static_root/assets/library-tab-BpinbqAu.js.gz +0 -0
- codex/static_root/assets/library-tab-Cat0MAK5.5911f022188e.css.br +0 -0
- codex/static_root/assets/library-tab-Cat0MAK5.5911f022188e.css.gz +0 -0
- codex/static_root/assets/library-tab-Cat0MAK5.css.br +0 -0
- codex/static_root/assets/library-tab-Cat0MAK5.css.gz +0 -0
- codex/static_root/assets/main-BVKrDunc.1c6f8cdc3afb.js +0 -35
- codex/static_root/assets/main-BVKrDunc.1c6f8cdc3afb.js.br +0 -0
- codex/static_root/assets/main-BVKrDunc.1c6f8cdc3afb.js.gz +0 -0
- codex/static_root/assets/main-BVKrDunc.js +0 -35
- codex/static_root/assets/main-BVKrDunc.js.br +0 -0
- codex/static_root/assets/main-BVKrDunc.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js +0 -1
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.f2e95b19621c.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.js +0 -1
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-C1ZSyXfG.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css +0 -1
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css.br +0 -0
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.546121fa7a0d.css.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.css +0 -1
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.css.br +0 -0
- codex/static_root/assets/pagination-toolbar-Cx_9nh6D.css.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Diad0EdD.140911bf86af.js +0 -1
- codex/static_root/assets/pagination-toolbar-Diad0EdD.140911bf86af.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-Diad0EdD.140911bf86af.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Diad0EdD.js +0 -1
- codex/static_root/assets/pagination-toolbar-Diad0EdD.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-Diad0EdD.js.gz +0 -0
- codex/static_root/assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js +0 -305
- codex/static_root/assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js.br +0 -0
- codex/static_root/assets/pdf-doc-b-GyNR6z.c9d18f0d36ed.js.gz +0 -0
- codex/static_root/assets/pdf-doc-b-GyNR6z.js +0 -305
- codex/static_root/assets/pdf-doc-b-GyNR6z.js.br +0 -0
- codex/static_root/assets/pdf-doc-b-GyNR6z.js.gz +0 -0
- codex/static_root/assets/reader-2up6WEuE.c56ad81d14c6.js +0 -2
- codex/static_root/assets/reader-2up6WEuE.c56ad81d14c6.js.br +0 -0
- codex/static_root/assets/reader-2up6WEuE.c56ad81d14c6.js.gz +0 -0
- codex/static_root/assets/reader-2up6WEuE.js +0 -2
- codex/static_root/assets/reader-2up6WEuE.js.br +0 -0
- codex/static_root/assets/reader-2up6WEuE.js.gz +0 -0
- codex/static_root/assets/reader-Dd2KmdCN.115d4bfe9280.css.br +0 -0
- codex/static_root/assets/reader-Dd2KmdCN.115d4bfe9280.css.gz +0 -0
- codex/static_root/assets/reader-Dd2KmdCN.css.br +0 -0
- codex/static_root/assets/reader-Dd2KmdCN.css.gz +0 -0
- codex/static_root/assets/relation-chips-piYv1IcD.f8a2ae79de89.js +0 -1
- codex/static_root/assets/relation-chips-piYv1IcD.f8a2ae79de89.js.br +0 -0
- codex/static_root/assets/relation-chips-piYv1IcD.f8a2ae79de89.js.gz +0 -0
- codex/static_root/assets/relation-chips-piYv1IcD.js +0 -1
- codex/static_root/assets/relation-chips-piYv1IcD.js.br +0 -0
- codex/static_root/assets/relation-chips-piYv1IcD.js.gz +0 -0
- codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css +0 -1
- codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css.br +0 -0
- codex/static_root/assets/settings-drawer-DKncO_vX.0a2cd24cd904.css.gz +0 -0
- codex/static_root/assets/settings-drawer-DKncO_vX.css +0 -1
- codex/static_root/assets/settings-drawer-DKncO_vX.css.br +0 -0
- codex/static_root/assets/settings-drawer-DKncO_vX.css.gz +0 -0
- codex/static_root/assets/settings-drawer-yVoY-WCS.1240cc47a246.js +0 -2
- codex/static_root/assets/settings-drawer-yVoY-WCS.1240cc47a246.js.br +0 -0
- codex/static_root/assets/settings-drawer-yVoY-WCS.1240cc47a246.js.gz +0 -0
- codex/static_root/assets/settings-drawer-yVoY-WCS.js +0 -2
- codex/static_root/assets/settings-drawer-yVoY-WCS.js.br +0 -0
- codex/static_root/assets/settings-drawer-yVoY-WCS.js.gz +0 -0
- codex/static_root/assets/stats-tab-bqSPLvTp.05106cb03ef0.js +0 -1
- codex/static_root/assets/stats-tab-bqSPLvTp.05106cb03ef0.js.br +0 -0
- codex/static_root/assets/stats-tab-bqSPLvTp.05106cb03ef0.js.gz +0 -0
- codex/static_root/assets/stats-tab-bqSPLvTp.js +0 -1
- codex/static_root/assets/stats-tab-bqSPLvTp.js.br +0 -0
- codex/static_root/assets/stats-tab-bqSPLvTp.js.gz +0 -0
- codex/static_root/assets/task-tab-DWPKaGPT.da4df28dde5c.js +0 -1
- codex/static_root/assets/task-tab-DWPKaGPT.da4df28dde5c.js.br +0 -0
- codex/static_root/assets/task-tab-DWPKaGPT.da4df28dde5c.js.gz +0 -0
- codex/static_root/assets/task-tab-DWPKaGPT.js +0 -1
- codex/static_root/assets/task-tab-DWPKaGPT.js.br +0 -0
- codex/static_root/assets/task-tab-DWPKaGPT.js.gz +0 -0
- codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css +0 -1
- codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.br +0 -4
- codex/static_root/assets/transition-5LRFTPo5.3d726f9bbcb0.css.gz +0 -0
- codex/static_root/assets/transition-5LRFTPo5.css +0 -1
- codex/static_root/assets/transition-5LRFTPo5.css.br +0 -4
- codex/static_root/assets/transition-5LRFTPo5.css.gz +0 -0
- codex/static_root/assets/transition-DWVQ2EZ3.0bdfaa37b937.js +0 -1
- codex/static_root/assets/transition-DWVQ2EZ3.0bdfaa37b937.js.br +0 -0
- codex/static_root/assets/transition-DWVQ2EZ3.0bdfaa37b937.js.gz +0 -0
- codex/static_root/assets/transition-DWVQ2EZ3.js +0 -1
- codex/static_root/assets/transition-DWVQ2EZ3.js.br +0 -0
- codex/static_root/assets/transition-DWVQ2EZ3.js.gz +0 -0
- codex/static_root/assets/unauthorized-CEGD20tR.064b0993a944.js +0 -1
- codex/static_root/assets/unauthorized-CEGD20tR.064b0993a944.js.br +0 -0
- codex/static_root/assets/unauthorized-CEGD20tR.064b0993a944.js.gz +0 -0
- codex/static_root/assets/unauthorized-CEGD20tR.js +0 -1
- codex/static_root/assets/unauthorized-CEGD20tR.js.br +0 -0
- codex/static_root/assets/unauthorized-CEGD20tR.js.gz +0 -0
- codex/static_root/assets/unauthorized-DyojW2ic.css +0 -1
- codex/static_root/assets/unauthorized-DyojW2ic.css.br +0 -0
- codex/static_root/assets/unauthorized-DyojW2ic.css.gz +0 -0
- codex/static_root/assets/unauthorized-DyojW2ic.feefa7628a23.css +0 -1
- codex/static_root/assets/unauthorized-DyojW2ic.feefa7628a23.css.br +0 -0
- codex/static_root/assets/unauthorized-DyojW2ic.feefa7628a23.css.gz +0 -0
- codex/static_root/assets/user-tab-EsokzMCB.b0acc46b56a3.js +0 -1
- codex/static_root/assets/user-tab-EsokzMCB.b0acc46b56a3.js.br +0 -0
- codex/static_root/assets/user-tab-EsokzMCB.b0acc46b56a3.js.gz +0 -0
- codex/static_root/assets/user-tab-EsokzMCB.js +0 -1
- codex/static_root/assets/user-tab-EsokzMCB.js.br +0 -0
- codex/static_root/assets/user-tab-EsokzMCB.js.gz +0 -0
- codex/static_root/manifest.4a38de3db1c5.json +0 -712
- codex/static_root/manifest.4a38de3db1c5.json.br +0 -0
- codex/static_root/manifest.4a38de3db1c5.json.gz +0 -0
- codex-1.7.2.dist-info/RECORD +0 -1015
- /codex/static_root/assets/{VCheckbox-CMKdyl0R.016ed8d222c4.css → VCheckbox-CvH8ekHL.016ed8d222c4.css} +0 -0
- /codex/static_root/assets/{VCheckbox-CMKdyl0R.016ed8d222c4.css.br → VCheckbox-CvH8ekHL.016ed8d222c4.css.br} +0 -0
- /codex/static_root/assets/{VCheckbox-CMKdyl0R.016ed8d222c4.css.gz → VCheckbox-CvH8ekHL.016ed8d222c4.css.gz} +0 -0
- /codex/static_root/assets/{VCheckbox-CMKdyl0R.css → VCheckbox-CvH8ekHL.css} +0 -0
- /codex/static_root/assets/{VCheckbox-CMKdyl0R.css.br → VCheckbox-CvH8ekHL.css.br} +0 -0
- /codex/static_root/assets/{VCheckbox-CMKdyl0R.css.gz → VCheckbox-CvH8ekHL.css.gz} +0 -0
- /codex/static_root/assets/{VCombobox-bwEYrXCg.9f25a34994e2.css → VCombobox-BQHELb_o.9f25a34994e2.css} +0 -0
- /codex/static_root/assets/{VCombobox-bwEYrXCg.9f25a34994e2.css.br → VCombobox-BQHELb_o.9f25a34994e2.css.br} +0 -0
- /codex/static_root/assets/{VCombobox-bwEYrXCg.9f25a34994e2.css.gz → VCombobox-BQHELb_o.9f25a34994e2.css.gz} +0 -0
- /codex/static_root/assets/{VCombobox-bwEYrXCg.css → VCombobox-BQHELb_o.css} +0 -0
- /codex/static_root/assets/{VCombobox-bwEYrXCg.css.br → VCombobox-BQHELb_o.css.br} +0 -0
- /codex/static_root/assets/{VCombobox-bwEYrXCg.css.gz → VCombobox-BQHELb_o.css.gz} +0 -0
- /codex/static_root/assets/{VExpansionPanels-6G1AUajL.5b17872981df.css → VExpansionPanels-RsCANmDP.5b17872981df.css} +0 -0
- /codex/static_root/assets/{VExpansionPanels-6G1AUajL.5b17872981df.css.br → VExpansionPanels-RsCANmDP.5b17872981df.css.br} +0 -0
- /codex/static_root/assets/{VExpansionPanels-6G1AUajL.5b17872981df.css.gz → VExpansionPanels-RsCANmDP.5b17872981df.css.gz} +0 -0
- /codex/static_root/assets/{VExpansionPanels-6G1AUajL.css → VExpansionPanels-RsCANmDP.css} +0 -0
- /codex/static_root/assets/{VExpansionPanels-6G1AUajL.css.br → VExpansionPanels-RsCANmDP.css.br} +0 -0
- /codex/static_root/assets/{VExpansionPanels-6G1AUajL.css.gz → VExpansionPanels-RsCANmDP.css.gz} +0 -0
- /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.8e3741381961.css → VRadioGroup-Cp9mZ7cb.8e3741381961.css} +0 -0
- /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.8e3741381961.css.br → VRadioGroup-Cp9mZ7cb.8e3741381961.css.br} +0 -0
- /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.8e3741381961.css.gz → VRadioGroup-Cp9mZ7cb.8e3741381961.css.gz} +0 -0
- /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.css → VRadioGroup-Cp9mZ7cb.css} +0 -0
- /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.css.br → VRadioGroup-Cp9mZ7cb.css.br} +0 -0
- /codex/static_root/assets/{VRadioGroup-i2qP9Wu9.css.gz → VRadioGroup-Cp9mZ7cb.css.gz} +0 -0
- /codex/static_root/assets/{VTable-Y5Sc3hJd.c36f0a6a30cf.css → VTable-BnxSZ_W5.c36f0a6a30cf.css} +0 -0
- /codex/static_root/assets/{VTable-Y5Sc3hJd.c36f0a6a30cf.css.br → VTable-BnxSZ_W5.c36f0a6a30cf.css.br} +0 -0
- /codex/static_root/assets/{VTable-Y5Sc3hJd.c36f0a6a30cf.css.gz → VTable-BnxSZ_W5.c36f0a6a30cf.css.gz} +0 -0
- /codex/static_root/assets/{VTable-Y5Sc3hJd.css → VTable-BnxSZ_W5.css} +0 -0
- /codex/static_root/assets/{VTable-Y5Sc3hJd.css.br → VTable-BnxSZ_W5.css.br} +0 -0
- /codex/static_root/assets/{VTable-Y5Sc3hJd.css.gz → VTable-BnxSZ_W5.css.gz} +0 -0
- /codex/static_root/assets/{VWindowItem-ByIod57Y.css → VWindowItem-CWBhiE_Y.css} +0 -0
- /codex/static_root/assets/{VWindowItem-ByIod57Y.css.br → VWindowItem-CWBhiE_Y.css.br} +0 -0
- /codex/static_root/assets/{VWindowItem-ByIod57Y.css.gz → VWindowItem-CWBhiE_Y.css.gz} +0 -0
- /codex/static_root/assets/{VWindowItem-ByIod57Y.f7fb19752bf3.css → VWindowItem-CWBhiE_Y.f7fb19752bf3.css} +0 -0
- /codex/static_root/assets/{VWindowItem-ByIod57Y.f7fb19752bf3.css.br → VWindowItem-CWBhiE_Y.f7fb19752bf3.css.br} +0 -0
- /codex/static_root/assets/{VWindowItem-ByIod57Y.f7fb19752bf3.css.gz → VWindowItem-CWBhiE_Y.f7fb19752bf3.css.gz} +0 -0
- /codex/static_root/assets/{admin-menu-B9bzD6hV.c13b7df2ff57.css → admin-menu-B3iXsOyy.c13b7df2ff57.css} +0 -0
- /codex/static_root/assets/{admin-menu-B9bzD6hV.c13b7df2ff57.css.br → admin-menu-B3iXsOyy.c13b7df2ff57.css.br} +0 -0
- /codex/static_root/assets/{admin-menu-B9bzD6hV.c13b7df2ff57.css.gz → admin-menu-B3iXsOyy.c13b7df2ff57.css.gz} +0 -0
- /codex/static_root/assets/{admin-menu-B9bzD6hV.css → admin-menu-B3iXsOyy.css} +0 -0
- /codex/static_root/assets/{admin-menu-B9bzD6hV.css.br → admin-menu-B3iXsOyy.css.br} +0 -0
- /codex/static_root/assets/{admin-menu-B9bzD6hV.css.gz → admin-menu-B3iXsOyy.css.gz} +0 -0
- /codex/static_root/assets/{admin-settings-button-progress-DUUQfVsZ.2548c49a853e.css → admin-settings-button-progress-BGB22oTD.2548c49a853e.css} +0 -0
- /codex/static_root/assets/{admin-settings-button-progress-DUUQfVsZ.css → admin-settings-button-progress-BGB22oTD.css} +0 -0
- /codex/static_root/assets/{change-password-dialog-C_EOKOn9.a30e68c6e303.css → change-password-dialog-D0ymWcl_.a30e68c6e303.css} +0 -0
- /codex/static_root/assets/{change-password-dialog-C_EOKOn9.a30e68c6e303.css.br → change-password-dialog-D0ymWcl_.a30e68c6e303.css.br} +0 -0
- /codex/static_root/assets/{change-password-dialog-C_EOKOn9.a30e68c6e303.css.gz → change-password-dialog-D0ymWcl_.a30e68c6e303.css.gz} +0 -0
- /codex/static_root/assets/{change-password-dialog-C_EOKOn9.css → change-password-dialog-D0ymWcl_.css} +0 -0
- /codex/static_root/assets/{change-password-dialog-C_EOKOn9.css.br → change-password-dialog-D0ymWcl_.css.br} +0 -0
- /codex/static_root/assets/{change-password-dialog-C_EOKOn9.css.gz → change-password-dialog-D0ymWcl_.css.gz} +0 -0
- /codex/static_root/assets/{confirm-dialog-54rblwf7.9b5915b112c0.css → confirm-dialog-B1ABbGMU.9b5915b112c0.css} +0 -0
- /codex/static_root/assets/{confirm-dialog-54rblwf7.9b5915b112c0.css.br → confirm-dialog-B1ABbGMU.9b5915b112c0.css.br} +0 -0
- /codex/static_root/assets/{confirm-dialog-54rblwf7.css → confirm-dialog-B1ABbGMU.css} +0 -0
- /codex/static_root/assets/{confirm-dialog-54rblwf7.css.br → confirm-dialog-B1ABbGMU.css.br} +0 -0
- /codex/static_root/assets/{datetime-column-DeCthByU.1f3bf499e063.css → datetime-column-BavtvLnf.1f3bf499e063.css} +0 -0
- /codex/static_root/assets/{datetime-column-DeCthByU.css → datetime-column-BavtvLnf.css} +0 -0
- /codex/static_root/assets/{group-tab-DkIN1Heu.948e907b1e6b.css → group-tab-_vKWzoyd.948e907b1e6b.css} +0 -0
- /codex/static_root/assets/{group-tab-DkIN1Heu.948e907b1e6b.css.br → group-tab-_vKWzoyd.948e907b1e6b.css.br} +0 -0
- /codex/static_root/assets/{group-tab-DkIN1Heu.948e907b1e6b.css.gz → group-tab-_vKWzoyd.948e907b1e6b.css.gz} +0 -0
- /codex/static_root/assets/{group-tab-DkIN1Heu.css → group-tab-_vKWzoyd.css} +0 -0
- /codex/static_root/assets/{group-tab-DkIN1Heu.css.br → group-tab-_vKWzoyd.css.br} +0 -0
- /codex/static_root/assets/{group-tab-DkIN1Heu.css.gz → group-tab-_vKWzoyd.css.gz} +0 -0
- /codex/static_root/assets/{index-CL_6g4tJ.523d7b3d350f.css → index-BHXJTQ4V.523d7b3d350f.css} +0 -0
- /codex/static_root/assets/{index-CL_6g4tJ.523d7b3d350f.css.br → index-BHXJTQ4V.523d7b3d350f.css.br} +0 -0
- /codex/static_root/assets/{index-CL_6g4tJ.523d7b3d350f.css.gz → index-BHXJTQ4V.523d7b3d350f.css.gz} +0 -0
- /codex/static_root/assets/{index-CL_6g4tJ.css → index-BHXJTQ4V.css} +0 -0
- /codex/static_root/assets/{index-CL_6g4tJ.css.br → index-BHXJTQ4V.css.br} +0 -0
- /codex/static_root/assets/{index-CL_6g4tJ.css.gz → index-BHXJTQ4V.css.gz} +0 -0
- /codex/static_root/assets/{main-BZ73p_WW.css → main-K8cER0IH.css} +0 -0
- /codex/static_root/assets/{main-BZ73p_WW.css.br → main-K8cER0IH.css.br} +0 -0
- /codex/static_root/assets/{main-BZ73p_WW.css.gz → main-K8cER0IH.css.gz} +0 -0
- /codex/static_root/assets/{main-BZ73p_WW.d529e8b3f52a.css → main-K8cER0IH.d529e8b3f52a.css} +0 -0
- /codex/static_root/assets/{main-BZ73p_WW.d529e8b3f52a.css.br → main-K8cER0IH.d529e8b3f52a.css.br} +0 -0
- /codex/static_root/assets/{main-BZ73p_WW.d529e8b3f52a.css.gz → main-K8cER0IH.d529e8b3f52a.css.gz} +0 -0
- /codex/static_root/assets/{pdf-doc-CG5-AZ2M.b94aac7e3313.css → pdf-doc-B4cGW_Hl.b94aac7e3313.css} +0 -0
- /codex/static_root/assets/{pdf-doc-CG5-AZ2M.b94aac7e3313.css.br → pdf-doc-B4cGW_Hl.b94aac7e3313.css.br} +0 -0
- /codex/static_root/assets/{pdf-doc-CG5-AZ2M.b94aac7e3313.css.gz → pdf-doc-B4cGW_Hl.b94aac7e3313.css.gz} +0 -0
- /codex/static_root/assets/{pdf-doc-CG5-AZ2M.css → pdf-doc-B4cGW_Hl.css} +0 -0
- /codex/static_root/assets/{pdf-doc-CG5-AZ2M.css.br → pdf-doc-B4cGW_Hl.css.br} +0 -0
- /codex/static_root/assets/{pdf-doc-CG5-AZ2M.css.gz → pdf-doc-B4cGW_Hl.css.gz} +0 -0
- /codex/static_root/assets/{relation-chips-ByfWwuQc.01269a188e01.css → relation-chips-DpbzrZxT.01269a188e01.css} +0 -0
- /codex/static_root/assets/{relation-chips-ByfWwuQc.01269a188e01.css.br → relation-chips-DpbzrZxT.01269a188e01.css.br} +0 -0
- /codex/static_root/assets/{relation-chips-ByfWwuQc.01269a188e01.css.gz → relation-chips-DpbzrZxT.01269a188e01.css.gz} +0 -0
- /codex/static_root/assets/{relation-chips-ByfWwuQc.css → relation-chips-DpbzrZxT.css} +0 -0
- /codex/static_root/assets/{relation-chips-ByfWwuQc.css.br → relation-chips-DpbzrZxT.css.br} +0 -0
- /codex/static_root/assets/{relation-chips-ByfWwuQc.css.gz → relation-chips-DpbzrZxT.css.gz} +0 -0
- /codex/static_root/assets/{stats-tab-BlXGStge.9fdb0106124d.css → stats-tab-WvF2acoZ.9fdb0106124d.css} +0 -0
- /codex/static_root/assets/{stats-tab-BlXGStge.9fdb0106124d.css.br → stats-tab-WvF2acoZ.9fdb0106124d.css.br} +0 -0
- /codex/static_root/assets/{stats-tab-BlXGStge.9fdb0106124d.css.gz → stats-tab-WvF2acoZ.9fdb0106124d.css.gz} +0 -0
- /codex/static_root/assets/{stats-tab-BlXGStge.css → stats-tab-WvF2acoZ.css} +0 -0
- /codex/static_root/assets/{stats-tab-BlXGStge.css.br → stats-tab-WvF2acoZ.css.br} +0 -0
- /codex/static_root/assets/{stats-tab-BlXGStge.css.gz → stats-tab-WvF2acoZ.css.gz} +0 -0
- /codex/static_root/assets/{task-tab-EGlhcKTH.478e74041f80.css → task-tab-DfdUY9Rc.478e74041f80.css} +0 -0
- /codex/static_root/assets/{task-tab-EGlhcKTH.478e74041f80.css.br → task-tab-DfdUY9Rc.478e74041f80.css.br} +0 -0
- /codex/static_root/assets/{task-tab-EGlhcKTH.478e74041f80.css.gz → task-tab-DfdUY9Rc.478e74041f80.css.gz} +0 -0
- /codex/static_root/assets/{task-tab-EGlhcKTH.css → task-tab-DfdUY9Rc.css} +0 -0
- /codex/static_root/assets/{task-tab-EGlhcKTH.css.br → task-tab-DfdUY9Rc.css.br} +0 -0
- /codex/static_root/assets/{task-tab-EGlhcKTH.css.gz → task-tab-DfdUY9Rc.css.gz} +0 -0
- {codex-1.7.2.dist-info → codex-1.7.3.dist-info}/LICENSE +0 -0
- {codex-1.7.2.dist-info → codex-1.7.3.dist-info}/entry_points.txt +0 -0
|
@@ -46,9 +46,7 @@ class MovedImporter(AggregateMetadataImporter):
|
|
|
46
46
|
new_path = self.task.files_moved[comic.path]
|
|
47
47
|
comic.path = new_path
|
|
48
48
|
new_path = Path(new_path)
|
|
49
|
-
comic.parent_folder = Folder.objects.get(
|
|
50
|
-
path=new_path.parent
|
|
51
|
-
)
|
|
49
|
+
comic.parent_folder = Folder.objects.get(path=new_path.parent)
|
|
52
50
|
comic.updated_at = Now()
|
|
53
51
|
comic.presave()
|
|
54
52
|
folder_m2m_links[comic.pk] = Folder.objects.filter(
|
|
@@ -137,7 +135,7 @@ class MovedImporter(AggregateMetadataImporter):
|
|
|
137
135
|
f"Unlinked {len(unlink_groups)} {model.__name__} moved custom covers."
|
|
138
136
|
)
|
|
139
137
|
|
|
140
|
-
self._remove_covers(unlink_pks, custom=True)
|
|
138
|
+
self._remove_covers(unlink_pks, custom=True)
|
|
141
139
|
|
|
142
140
|
def _bulk_covers_moved(self, status=None):
|
|
143
141
|
"""Move covers."""
|
|
@@ -194,8 +192,6 @@ class MovedImporter(AggregateMetadataImporter):
|
|
|
194
192
|
folder.updated_at = Now()
|
|
195
193
|
update_folders.append(folder)
|
|
196
194
|
|
|
197
|
-
# delete_folders = Folder.objects.filter(library=self.library, path__in=new_paths)
|
|
198
|
-
|
|
199
195
|
update_folders = sorted(update_folders, key=lambda x: len(Path(x.path).parts))
|
|
200
196
|
|
|
201
197
|
Folder.objects.bulk_update(update_folders, MOVED_BULK_FOLDER_UPDATE_FIELDS)
|
|
@@ -212,7 +208,6 @@ class MovedImporter(AggregateMetadataImporter):
|
|
|
212
208
|
"""Move folders under existing folders."""
|
|
213
209
|
while True:
|
|
214
210
|
# Get existing parent folders
|
|
215
|
-
# dest_parent_paths = tuple(str(path) for path in dest_parent_folder_paths_map)
|
|
216
211
|
dest_parent_paths = tuple(dest_parent_folder_paths_map.keys())
|
|
217
212
|
extant_parent_folders = Folder.objects.filter(
|
|
218
213
|
library=self.library, path__in=dest_parent_paths
|
|
@@ -96,7 +96,7 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
|
|
|
96
96
|
if extra_fields:
|
|
97
97
|
fields += extra_fields
|
|
98
98
|
flat = len(fields) == 1 and fk_cls != Publisher
|
|
99
|
-
qs = fk_cls.objects.filter(fk_filter).values_list(*fields, flat=flat)
|
|
99
|
+
qs = fk_cls.objects.filter(fk_filter).distinct().values_list(*fields, flat=flat)
|
|
100
100
|
return frozenset(qs)
|
|
101
101
|
|
|
102
102
|
def _query_create_metadata( # noqa: PLR0913
|
|
@@ -229,9 +229,7 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
|
|
|
229
229
|
|
|
230
230
|
group_filter = Q()
|
|
231
231
|
for group_tree, count_value in update_group_trees.items():
|
|
232
|
-
compare_filter =
|
|
233
|
-
for field_name, value in zip(compare_fields, group_tree, strict=False):
|
|
234
|
-
compare_filter[field_name] = value
|
|
232
|
+
compare_filter = dict(zip(compare_fields, group_tree, strict=False))
|
|
235
233
|
compare_filter[count_field_name] = count_value
|
|
236
234
|
group_filter |= Q(**compare_filter)
|
|
237
235
|
return group_filter
|
|
@@ -449,7 +447,7 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
|
|
|
449
447
|
|
|
450
448
|
# Build combined query object from the value_filter
|
|
451
449
|
model = DICT_MODEL_FIELD_MODEL_MAP[field_name]
|
|
452
|
-
if model
|
|
450
|
+
if model in (Identifier, Contributor):
|
|
453
451
|
for filter_and_prefix, value_filter in query_filter_map.items():
|
|
454
452
|
self._query_create_metadata(
|
|
455
453
|
model,
|
|
@@ -494,7 +492,6 @@ class QueryForeignKeysImporter(QueryCustomCoversImporter):
|
|
|
494
492
|
|
|
495
493
|
def _query_missing_simple_models(self, names, fk_data, status):
|
|
496
494
|
"""Find missing named models and folders."""
|
|
497
|
-
# count = 0
|
|
498
495
|
if not names:
|
|
499
496
|
return 0
|
|
500
497
|
create_fks, base_cls, field, fk_field = fk_data
|
|
@@ -18,7 +18,7 @@ class ImportDBDiffTask(ImportTask):
|
|
|
18
18
|
|
|
19
19
|
dirs_moved: Mapping[str, str] = field(default_factory=dict)
|
|
20
20
|
dirs_modified: frozenset[str] = frozenset()
|
|
21
|
-
# dirs_created: frozenset[str] | None = frozenset()
|
|
21
|
+
# dirs_created: frozenset[str] | None = frozenset() # noqa: ERA001
|
|
22
22
|
dirs_deleted: frozenset[str] = frozenset()
|
|
23
23
|
|
|
24
24
|
files_moved: Mapping[str, str] = field(default_factory=dict)
|
|
@@ -2,6 +2,7 @@
|
|
|
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
|
|
5
6
|
|
|
6
7
|
from django.apps import apps
|
|
7
8
|
from django.db import DEFAULT_DB_ALIAS, connections
|
|
@@ -19,6 +20,13 @@ from codex.settings.settings import (
|
|
|
19
20
|
from codex.status import Status
|
|
20
21
|
from codex.worker_base import WorkerBaseMixin
|
|
21
22
|
|
|
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
|
+
|
|
22
30
|
REPAIR_FLAG_PATH = CONFIG_PATH / "rebuild_db"
|
|
23
31
|
REBUILT_DB_PATH = DB_PATH.parent / (DB_PATH.name + ".rebuilt")
|
|
24
32
|
BACKUP_DB_PATH = DB_PATH.parent / (DB_PATH.name + ".bak")
|
|
@@ -105,7 +113,7 @@ def _null_bad_fk_rels_table(table_name, bad_rows, log):
|
|
|
105
113
|
fields = model._meta.fields
|
|
106
114
|
field_names = {}
|
|
107
115
|
update_objs = []
|
|
108
|
-
objs = model.objects.filter(pk__in=bad_rows.keys())
|
|
116
|
+
objs: BaseManager[BaseModel] = model.objects.filter(pk__in=bad_rows.keys()) # type: ignore[reportAssignmentType]
|
|
109
117
|
update_fields = {"updated_at"}
|
|
110
118
|
now = Now()
|
|
111
119
|
for obj in objs:
|
|
@@ -119,7 +127,7 @@ def _null_bad_fk_rels_table(table_name, bad_rows, log):
|
|
|
119
127
|
field_name = field_names[fkid]
|
|
120
128
|
setattr(obj, field_name, None)
|
|
121
129
|
update_fields.add(field_name)
|
|
122
|
-
obj.updated_at = now
|
|
130
|
+
obj.updated_at = now
|
|
123
131
|
update_objs.append(obj)
|
|
124
132
|
except Exception as exc:
|
|
125
133
|
log.warning(
|
|
@@ -142,10 +150,10 @@ def _null_bad_fk_rels(bad_fk_rels, log):
|
|
|
142
150
|
for table_name, bad_rows in bad_fk_rels.items():
|
|
143
151
|
try:
|
|
144
152
|
fix_comic_pks |= _null_bad_fk_rels_table(table_name, bad_rows, log)
|
|
145
|
-
except Exception
|
|
153
|
+
except Exception:
|
|
146
154
|
pks = sorted(bad_rows.keys())
|
|
147
|
-
log.
|
|
148
|
-
f"Unable to null {len(pks)} {table_name} rows with bad foreign keys
|
|
155
|
+
log.exception(
|
|
156
|
+
f"Unable to null {len(pks)} {table_name} rows with bad foreign keys"
|
|
149
157
|
)
|
|
150
158
|
log.error(f"{table_name}: {pks}") # noqa: TRY400
|
|
151
159
|
return fix_comic_pks
|
|
@@ -175,10 +183,8 @@ def _delete_bad_m2m_rows(bad_m2m_rows, log):
|
|
|
175
183
|
for table_name, ids in bad_m2m_rows.items():
|
|
176
184
|
try:
|
|
177
185
|
count += _delete_bad_m2m_rows_table(table_name, ids, fix_comic_pks, log)
|
|
178
|
-
except Exception
|
|
179
|
-
log.
|
|
180
|
-
f"Could not delete bad foreign keys in table {table_name} - {exc}"
|
|
181
|
-
)
|
|
186
|
+
except Exception:
|
|
187
|
+
log.exception(f"Could not delete bad foreign keys in table {table_name}")
|
|
182
188
|
if count:
|
|
183
189
|
log.info(f"Removed {count} bad foreign key relations.")
|
|
184
190
|
return fix_comic_pks
|
|
@@ -189,7 +195,9 @@ def _mark_comics_for_update(fix_comic_pks, log):
|
|
|
189
195
|
if not fix_comic_pks:
|
|
190
196
|
return
|
|
191
197
|
comic_model = apps.get_model(app_label="codex", model_name="comic")
|
|
192
|
-
outdated_comics = comic_model.objects.filter(
|
|
198
|
+
outdated_comics: BaseManager[Comic] = comic_model.objects.filter(
|
|
199
|
+
pk__in=fix_comic_pks
|
|
200
|
+
).only( # type: ignore[reportAssignmentType]
|
|
193
201
|
"stat", "updated_at"
|
|
194
202
|
)
|
|
195
203
|
if not outdated_comics:
|
|
@@ -198,12 +206,12 @@ def _mark_comics_for_update(fix_comic_pks, log):
|
|
|
198
206
|
update_comics = []
|
|
199
207
|
now = Now()
|
|
200
208
|
for comic in outdated_comics:
|
|
201
|
-
stat_list = comic.stat
|
|
209
|
+
stat_list = comic.stat
|
|
202
210
|
if not stat_list:
|
|
203
211
|
continue
|
|
204
212
|
stat_list[8] = 0.0
|
|
205
|
-
comic.stat = stat_list # type: ignore
|
|
206
|
-
comic.updated_at = now
|
|
213
|
+
comic.stat = stat_list # type: ignore[reportAttributeAccessIssue]
|
|
214
|
+
comic.updated_at = now
|
|
207
215
|
update_comics.append(comic)
|
|
208
216
|
|
|
209
217
|
if update_comics:
|
|
@@ -227,8 +235,8 @@ def fix_foreign_keys(log=None):
|
|
|
227
235
|
fix_comic_pks |= _delete_bad_m2m_rows(bad_m2m_rows, log)
|
|
228
236
|
try:
|
|
229
237
|
_mark_comics_for_update(fix_comic_pks, log)
|
|
230
|
-
except Exception
|
|
231
|
-
LOG.
|
|
238
|
+
except Exception:
|
|
239
|
+
LOG.exception("Could not mark comics with bad relations for update")
|
|
232
240
|
|
|
233
241
|
|
|
234
242
|
def _repair_extra_custom_cover_libraries(library_model, log):
|
|
@@ -277,7 +285,7 @@ def _is_integrity_ok(results):
|
|
|
277
285
|
)
|
|
278
286
|
|
|
279
287
|
|
|
280
|
-
def integrity_check(long
|
|
288
|
+
def integrity_check(long, log=None):
|
|
281
289
|
"""Run sqlite3 integrity check."""
|
|
282
290
|
if not log:
|
|
283
291
|
log = LOG
|
|
@@ -318,9 +326,8 @@ def fts_integrity_check(log=None):
|
|
|
318
326
|
if results:
|
|
319
327
|
# I'm not sure if this raises or puts the error in the results.
|
|
320
328
|
raise ValueError(results) # noqa: TRY301
|
|
321
|
-
except Exception
|
|
322
|
-
log.
|
|
323
|
-
log.warning(exc)
|
|
329
|
+
except Exception:
|
|
330
|
+
log.exception("Full Text Search Index failed integrity check.")
|
|
324
331
|
else:
|
|
325
332
|
log.info("Full Text Search Index passed integrity check.")
|
|
326
333
|
success = True
|
|
@@ -340,7 +347,7 @@ class IntegrityMixin(WorkerBaseMixin):
|
|
|
340
347
|
finally:
|
|
341
348
|
self.status_controller.finish(status)
|
|
342
349
|
|
|
343
|
-
def integrity_check(self, long
|
|
350
|
+
def integrity_check(self, long: bool):
|
|
344
351
|
"""Integrity check task."""
|
|
345
352
|
subtitle = "" if long else "Quick"
|
|
346
353
|
status = Status(JanitorStatusTypes.INTEGRITY_CHECK, subtitle=subtitle)
|
|
@@ -109,7 +109,7 @@ class Janitor(
|
|
|
109
109
|
case JanitorVacuumTask():
|
|
110
110
|
self.vacuum_db()
|
|
111
111
|
case JanitorBackupTask():
|
|
112
|
-
self.backup_db()
|
|
112
|
+
self.backup_db(show_status=True)
|
|
113
113
|
case JanitorLatestVersionTask():
|
|
114
114
|
self.update_latest_version(task.force)
|
|
115
115
|
case JanitorUpdateTask():
|
|
@@ -149,7 +149,10 @@ class Janitor(
|
|
|
149
149
|
for next_task in next_tasks:
|
|
150
150
|
self.librarian_queue.put(next_task)
|
|
151
151
|
case JanitorSearchOptimizeFinishedTask():
|
|
152
|
-
next_tasks = (
|
|
152
|
+
next_tasks = (
|
|
153
|
+
JanitorVacuumTask(),
|
|
154
|
+
JanitorBackupTask(),
|
|
155
|
+
)
|
|
153
156
|
for next_task in next_tasks:
|
|
154
157
|
self.librarian_queue.put(next_task)
|
|
155
158
|
case _:
|
|
@@ -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: bool):
|
|
32
32
|
"""Get the latest version from a remote repo using a cache."""
|
|
33
33
|
status = Status(JanitorStatusTypes.CODEX_LATEST_VERSION)
|
|
34
34
|
try:
|
|
@@ -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[reportIndexIssue]
|
|
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: bool):
|
|
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, backup_path=BACKUP_DB_PATH
|
|
33
|
+
def backup_db(self, show_status: bool, backup_path=BACKUP_DB_PATH):
|
|
34
34
|
"""Backup the database."""
|
|
35
35
|
status = Status(JanitorStatusTypes.DB_BACKUP) if show_status else ""
|
|
36
36
|
try:
|
codex/librarian/librariand.py
CHANGED
|
@@ -79,7 +79,7 @@ class LibrarianDaemon(Process, LoggerBaseMixin):
|
|
|
79
79
|
startup_tasks = (
|
|
80
80
|
AdoptOrphanFoldersTask(),
|
|
81
81
|
WatchdogSyncTask(),
|
|
82
|
-
SearchIndexUpdateTask(False),
|
|
82
|
+
SearchIndexUpdateTask(rebuild=False),
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
for task in startup_tasks:
|
|
@@ -121,7 +121,7 @@ class LibrarianDaemon(Process, LoggerBaseMixin):
|
|
|
121
121
|
case DelayedTasks():
|
|
122
122
|
self._threads.delayed_tasks_thread.queue.put(task)
|
|
123
123
|
case LibrarianShutdownTask():
|
|
124
|
-
self.log.info(f"Shutting down {self.
|
|
124
|
+
self.log.info(f"Shutting down {self.name}...")
|
|
125
125
|
self.run_loop = False
|
|
126
126
|
case _:
|
|
127
127
|
self.log.warning(f"Unhandled Librarian task: {task}")
|
|
@@ -150,34 +150,34 @@ class LibrarianDaemon(Process, LoggerBaseMixin):
|
|
|
150
150
|
|
|
151
151
|
def _start_threads(self):
|
|
152
152
|
"""Start all librarian's threads."""
|
|
153
|
-
self.log.debug(f"{self.
|
|
153
|
+
self.log.debug(f"{self.name} starting all threads.")
|
|
154
154
|
for thread in self._threads:
|
|
155
155
|
thread.start()
|
|
156
|
-
self.log.info(f"{self.
|
|
156
|
+
self.log.info(f"{self.name} started all threads.")
|
|
157
157
|
|
|
158
158
|
def _startup(self):
|
|
159
159
|
"""Initialize threads."""
|
|
160
160
|
self.init_logger(self.log_queue)
|
|
161
|
-
self.log.debug(f"Started {self.
|
|
161
|
+
self.log.debug(f"Started {self.name}.")
|
|
162
162
|
self.janitor = Janitor(self.log_queue, self.queue)
|
|
163
163
|
self._create_threads() # can't do this in init.
|
|
164
164
|
self._start_threads()
|
|
165
165
|
self.run_loop = True
|
|
166
|
-
self.log.info(f"{self.
|
|
166
|
+
self.log.info(f"{self.name} ready for tasks.")
|
|
167
167
|
|
|
168
168
|
def _stop_threads(self):
|
|
169
169
|
"""Stop all librarian's threads."""
|
|
170
|
-
self.log.debug(f"{self.
|
|
170
|
+
self.log.debug(f"{self.name} stopping all threads...")
|
|
171
171
|
for thread in self._reversed_threads:
|
|
172
172
|
thread.stop()
|
|
173
|
-
self.log.debug(f"{self.
|
|
173
|
+
self.log.debug(f"{self.name} stopped all threads.")
|
|
174
174
|
|
|
175
175
|
def _join_threads(self):
|
|
176
176
|
"""Join all librarian threads."""
|
|
177
|
-
self.log.debug(f"{self.
|
|
177
|
+
self.log.debug(f"{self.name} joining all threads...")
|
|
178
178
|
for thread in self._reversed_threads:
|
|
179
179
|
thread.join()
|
|
180
|
-
self.log.info(f"{self.
|
|
180
|
+
self.log.info(f"{self.name} joined all threads.")
|
|
181
181
|
|
|
182
182
|
def _shutdown(self):
|
|
183
183
|
"""Shutdown threads and queues."""
|
|
@@ -188,12 +188,13 @@ class LibrarianDaemon(Process, LoggerBaseMixin):
|
|
|
188
188
|
self.queue.get_nowait()
|
|
189
189
|
self.queue.close()
|
|
190
190
|
self.queue.join_thread()
|
|
191
|
-
self.log.info(f"{self.
|
|
191
|
+
self.log.info(f"{self.name} finished.")
|
|
192
192
|
self.log_queue.close()
|
|
193
193
|
self.log_queue.join_thread()
|
|
194
194
|
|
|
195
195
|
def run(self):
|
|
196
|
-
"""
|
|
196
|
+
"""
|
|
197
|
+
Process tasks from the queue.
|
|
197
198
|
|
|
198
199
|
This process also runs the crond thread and the Watchdog Observer
|
|
199
200
|
threads.
|
|
@@ -205,11 +206,11 @@ class LibrarianDaemon(Process, LoggerBaseMixin):
|
|
|
205
206
|
task = self.queue.get()
|
|
206
207
|
self._process_task(task)
|
|
207
208
|
except Exception:
|
|
208
|
-
self.log.exception(f"In {self.
|
|
209
|
+
self.log.exception(f"In {self.name} loop")
|
|
209
210
|
except Exception:
|
|
210
|
-
self.log.exception(f"{self.
|
|
211
|
+
self.log.exception(f"{self.name} crashed.")
|
|
211
212
|
except KeyboardInterrupt:
|
|
212
|
-
self.log.debug(f"{self.
|
|
213
|
+
self.log.debug(f"{self.name} Keyboard interrupt")
|
|
213
214
|
finally:
|
|
214
215
|
self._shutdown()
|
|
215
216
|
|
|
@@ -16,7 +16,8 @@ class NotifierThread(AggregateMessageQueuedThread):
|
|
|
16
16
|
self.cache[item.text] = item
|
|
17
17
|
|
|
18
18
|
def _send_task(self, task):
|
|
19
|
-
"""
|
|
19
|
+
"""
|
|
20
|
+
Send a group_send message to the mulitprocess broadcast channel.
|
|
20
21
|
|
|
21
22
|
A random consumer awaiting the broadcast channel will consume it,
|
|
22
23
|
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: bool):
|
|
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):
|
|
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
|
@@ -114,7 +114,7 @@ class FTSUpdateMixin(RemoveMixin):
|
|
|
114
114
|
return ""
|
|
115
115
|
return ",".join((iso_code, field_instance.to_representation(iso_code)))
|
|
116
116
|
|
|
117
|
-
def
|
|
117
|
+
def _get_comics_fts_list(
|
|
118
118
|
self, comics, country_field, language_field, obj_list, create
|
|
119
119
|
):
|
|
120
120
|
"""Prepare a batch of search entries."""
|
|
@@ -157,14 +157,15 @@ class FTSUpdateMixin(RemoveMixin):
|
|
|
157
157
|
if create:
|
|
158
158
|
comicfts.created_at = now
|
|
159
159
|
obj_list.append(comicfts)
|
|
160
|
+
self.log.debug(f"{len(obj_list)}/{comics.count()} entries prepped.")
|
|
160
161
|
|
|
161
|
-
def _get_comicfts_list(self, comics, create
|
|
162
|
+
def _get_comicfts_list(self, comics, create: bool):
|
|
162
163
|
"""Create a ComicFTS object for bulk_create or bulk_update."""
|
|
163
164
|
country_field = CountryField()
|
|
164
165
|
language_field = LanguageField()
|
|
165
166
|
obj_list = []
|
|
166
167
|
comics = self._annotate_fts_query(comics)
|
|
167
|
-
self.
|
|
168
|
+
self._get_comics_fts_list(
|
|
168
169
|
comics, country_field, language_field, obj_list, create
|
|
169
170
|
)
|
|
170
171
|
return obj_list
|
|
@@ -177,7 +178,7 @@ class FTSUpdateMixin(RemoveMixin):
|
|
|
177
178
|
self.log.debug(f"{verb} no search entries.")
|
|
178
179
|
self.status_controller.finish(status)
|
|
179
180
|
|
|
180
|
-
def _update_search_index_operate(self, comics_qs, create
|
|
181
|
+
def _update_search_index_operate(self, comics_qs, create: bool):
|
|
181
182
|
count = comics_qs.count()
|
|
182
183
|
verb = "create" if create else "update"
|
|
183
184
|
if not count:
|
|
@@ -205,11 +206,14 @@ class FTSUpdateMixin(RemoveMixin):
|
|
|
205
206
|
batch_start = time()
|
|
206
207
|
batch_to = batch_from + SEARCH_INDEX_BATCH_SIZE
|
|
207
208
|
comics_batch = comics_qs[batch_from:batch_to]
|
|
208
|
-
|
|
209
|
+
self.log.debug(
|
|
210
|
+
f"Checking {comics_batch.count()}/{count} comics for search index operations..."
|
|
211
|
+
)
|
|
209
212
|
if self.abort_event.is_set():
|
|
210
213
|
break
|
|
211
214
|
operate_comicfts = self._get_comicfts_list(comics_batch, create)
|
|
212
215
|
operate_comicfts_count = len(operate_comicfts)
|
|
216
|
+
self.log.debug(f"{verb}ing {operate_comicfts_count} search entries...")
|
|
213
217
|
if self.abort_event.is_set():
|
|
214
218
|
break
|
|
215
219
|
if create:
|
|
@@ -223,7 +227,7 @@ class FTSUpdateMixin(RemoveMixin):
|
|
|
223
227
|
batch_time = time() - batch_start
|
|
224
228
|
eps = round(count / batch_time)
|
|
225
229
|
self.log.debug(
|
|
226
|
-
f"{verb} {
|
|
230
|
+
f"{verb} {operate_comicfts_count}/{count} search entries in {batch_time}, {eps} per second."
|
|
227
231
|
)
|
|
228
232
|
batch_from = batch_to
|
|
229
233
|
finally:
|
|
@@ -281,7 +285,7 @@ class FTSUpdateMixin(RemoveMixin):
|
|
|
281
285
|
elapsed = naturaldelta(elapsed_time)
|
|
282
286
|
self.log.info(f"Search index updated in {elapsed}.")
|
|
283
287
|
|
|
284
|
-
def update_search_index(self, rebuild
|
|
288
|
+
def update_search_index(self, rebuild: bool):
|
|
285
289
|
"""Update or Rebuild the search index."""
|
|
286
290
|
start_time = time()
|
|
287
291
|
self.abort_event.clear()
|
|
@@ -62,11 +62,12 @@ 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
|
-
|
|
65
|
+
models = [
|
|
66
|
+
model
|
|
67
|
+
for model in all_models
|
|
68
|
+
for model_name in request_model_set
|
|
69
|
+
if model.__name__.lower() == model_name.lower()
|
|
70
|
+
]
|
|
70
71
|
else:
|
|
71
72
|
models = all_models
|
|
72
73
|
return tuple(models)
|
|
@@ -149,7 +150,7 @@ class CodexStats:
|
|
|
149
150
|
|
|
150
151
|
def _add_file_types(self, obj):
|
|
151
152
|
"""Query for file types."""
|
|
152
|
-
if self.params and "
|
|
153
|
+
if self.params and "file_types" not in self.params:
|
|
153
154
|
return
|
|
154
155
|
file_types = {}
|
|
155
156
|
qs = (
|
|
@@ -61,12 +61,12 @@ class CodexDatabaseSnapshot(DirectorySnapshot, LoggerBaseMixin):
|
|
|
61
61
|
def __init__(
|
|
62
62
|
self,
|
|
63
63
|
path,
|
|
64
|
-
_recursive=True, # unused, always recursive
|
|
64
|
+
_recursive=True, # noqa: FBT002 unused, always recursive
|
|
65
65
|
stat=os.stat,
|
|
66
66
|
_listdir=os.listdir, # unused for database
|
|
67
|
-
force=False,
|
|
67
|
+
force=False, # noqa: FBT002
|
|
68
68
|
log_queue=None,
|
|
69
|
-
covers_only=False,
|
|
69
|
+
covers_only=False, # noqa: FBT002
|
|
70
70
|
):
|
|
71
71
|
"""Initialize like DirectorySnapshot but use a database walk."""
|
|
72
72
|
self._covers_only = covers_only
|
|
@@ -33,7 +33,8 @@ 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
|
-
"""
|
|
36
|
+
"""
|
|
37
|
+
Return if the mtime and size are equal.
|
|
37
38
|
|
|
38
39
|
For old paths in the ref and new paths in the snapshot.
|
|
39
40
|
"""
|
|
@@ -84,9 +85,7 @@ class CodexDirectorySnapshotDiff(DirectorySnapshotDiff):
|
|
|
84
85
|
if not self._is_stats_equal(data, old_path, new_path):
|
|
85
86
|
data.modified.add(new_path)
|
|
86
87
|
|
|
87
|
-
def __init__(
|
|
88
|
-
self, ref, snapshot, ignore_device=False, inode_only_modified=False
|
|
89
|
-
):
|
|
88
|
+
def __init__(self, ref, snapshot, ignore_device: bool, inode_only_modified: bool):
|
|
90
89
|
"""Create diff object."""
|
|
91
90
|
self._ignore_device = ignore_device
|
|
92
91
|
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 PLR0913
|
|
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, # noqa: FBT002
|
|
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: bool):
|
|
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[reportIncompatibleMethodOverride]
|
|
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,8 +198,7 @@ class CodexLibraryEventHandler(CodexEventHandlerBase):
|
|
|
198
198
|
task = WatchdogEventTask(self.library_pk, sub_event)
|
|
199
199
|
self.librarian_queue.put(task)
|
|
200
200
|
|
|
201
|
-
#
|
|
202
|
-
# super().dispatch(event)
|
|
201
|
+
# Do not call super dispatch to call stub event dispatchers
|
|
203
202
|
except Exception:
|
|
204
203
|
self.log.exception(f"{self.__class__.__name__} dispatch")
|
|
205
204
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""The Codex Library Watchdog Observer threads."""
|
|
2
2
|
|
|
3
|
+
from watchdog.events import FileSystemEvent, FileSystemEventHandler
|
|
3
4
|
from watchdog.observers import Observer
|
|
4
5
|
from watchdog.observers.api import (
|
|
5
6
|
DEFAULT_OBSERVER_TIMEOUT,
|
|
@@ -98,14 +99,16 @@ class UatuMixin(BaseObserver, WorkerBaseMixin):
|
|
|
98
99
|
except Exception:
|
|
99
100
|
self.log.exception(f"{self.__class__.__name__} sync library watches")
|
|
100
101
|
|
|
101
|
-
def schedule(
|
|
102
|
+
def schedule(
|
|
102
103
|
self,
|
|
103
|
-
event_handler,
|
|
104
|
-
path,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
event_handler: FileSystemEventHandler,
|
|
105
|
+
path: str,
|
|
106
|
+
*,
|
|
107
|
+
recursive: bool = False,
|
|
108
|
+
event_filter: list[type[FileSystemEvent]] | None = None, # noqa: ARG002, F841, RUF100
|
|
109
|
+
) -> ObservedWatch:
|
|
110
|
+
"""
|
|
111
|
+
Override BaseObserver for Codex emitter class.
|
|
109
112
|
|
|
110
113
|
https://pythonhosted.org/watchdog/_modules/watchdog/observers/api.html#BaseObserver
|
|
111
114
|
"""
|
|
@@ -137,9 +140,11 @@ class UatuMixin(BaseObserver, WorkerBaseMixin):
|
|
|
137
140
|
# watchdog class structure doesn't work that way.
|
|
138
141
|
|
|
139
142
|
|
|
140
|
-
class LibraryEventObserver(UatuMixin, Observer): # type: ignore
|
|
143
|
+
class LibraryEventObserver(UatuMixin, Observer): # type: ignore[reportGeneralTypeIssues]
|
|
141
144
|
"""Regular observer."""
|
|
142
145
|
|
|
146
|
+
# Observer is a dynamically generated class by platform at runtime.
|
|
147
|
+
|
|
143
148
|
ENABLE_FIELD = "events"
|
|
144
149
|
|
|
145
150
|
|
|
@@ -156,7 +161,7 @@ class LibraryPollingObserver(UatuMixin):
|
|
|
156
161
|
*args, emitter_class=DatabasePollingEmitter, timeout=timeout, **kwargs
|
|
157
162
|
)
|
|
158
163
|
|
|
159
|
-
def poll(self, library_pks, force
|
|
164
|
+
def poll(self, library_pks, force: bool):
|
|
160
165
|
"""Poll each requested emitter."""
|
|
161
166
|
try:
|
|
162
167
|
qs = Library.objects.all()
|
|
@@ -165,7 +170,7 @@ class LibraryPollingObserver(UatuMixin):
|
|
|
165
170
|
paths = frozenset(qs.values_list("path", flat=True))
|
|
166
171
|
|
|
167
172
|
for emitter in self.emitters:
|
|
168
|
-
polling_emitter: DatabasePollingEmitter = emitter # type: ignore
|
|
173
|
+
polling_emitter: DatabasePollingEmitter = emitter # type: ignore[reportAssignmentType]
|
|
169
174
|
if emitter.watch.path in paths:
|
|
170
175
|
polling_emitter.poll(force)
|
|
171
176
|
except Exception:
|