codex 1.7.3a2__py3-none-any.whl → 1.7.5__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/__init__.py +1 -0
- codex/{choices.py → choices/admin.py} +47 -146
- codex/choices/browser.py +85 -0
- codex/{choices_to_json.py → choices/choices_to_json.py} +25 -19
- codex/choices/notifications.py +16 -0
- codex/choices/reader.py +33 -0
- codex/db.py +2 -2
- codex/exceptions.py +7 -8
- codex/librarian/bookmark/bookmarkd.py +8 -4
- codex/librarian/bookmark/update.py +84 -49
- codex/librarian/covers/create.py +10 -8
- codex/librarian/covers/path.py +6 -5
- codex/librarian/covers/purge.py +4 -4
- 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 +56 -37
- codex/librarian/importer/failed_imports.py +1 -1
- codex/librarian/importer/importer.py +8 -3
- 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 +1 -4
- codex/librarian/importer/tasks.py +1 -1
- codex/librarian/janitor/integrity.py +27 -20
- codex/librarian/janitor/janitor.py +1 -1
- codex/librarian/janitor/latest_version.py +1 -1
- codex/librarian/janitor/update.py +5 -2
- codex/librarian/janitor/vacuum.py +1 -1
- codex/librarian/librariand.py +3 -2
- codex/librarian/notifier/notifierd.py +2 -1
- codex/librarian/notifier/tasks.py +17 -3
- codex/librarian/search/optimize.py +1 -1
- codex/librarian/search/remove.py +1 -1
- codex/librarian/search/update.py +4 -4
- 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/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/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/libraries.py +1 -3
- codex/serializers/admin/stats.py +4 -4
- codex/serializers/admin/tasks.py +12 -2
- codex/serializers/auth.py +4 -2
- codex/serializers/browser/choices.py +87 -9
- codex/serializers/browser/filters.py +9 -37
- codex/serializers/browser/metadata.py +2 -1
- codex/serializers/browser/mixins.py +7 -3
- codex/serializers/browser/mtime.py +3 -5
- codex/serializers/browser/page.py +5 -4
- codex/serializers/browser/settings.py +8 -6
- codex/serializers/fields/__init__.py +37 -0
- codex/serializers/fields/auth.py +45 -0
- codex/serializers/fields/browser.py +85 -0
- codex/serializers/fields/group.py +13 -0
- codex/serializers/fields/reader.py +22 -0
- codex/serializers/fields/sanitized.py +13 -0
- codex/serializers/fields/session.py +16 -0
- codex/serializers/fields/stats.py +36 -0
- codex/serializers/fields/vuetify.py +62 -0
- codex/serializers/models/base.py +1 -1
- codex/serializers/models/comic.py +2 -2
- codex/serializers/models/groups.py +0 -2
- codex/serializers/models/named.py +1 -1
- codex/serializers/models/pycountry.py +1 -1
- codex/serializers/opds/authentication.py +4 -2
- codex/serializers/opds/urls.py +2 -1
- codex/serializers/opds/v1.py +4 -3
- codex/serializers/opds/v2/feed.py +2 -1
- codex/serializers/opds/v2/links.py +23 -21
- codex/serializers/opds/v2/metadata.py +4 -8
- codex/serializers/opds/v2/progression.py +5 -3
- codex/serializers/opds/v2/publication.py +16 -18
- codex/serializers/opds/v2/unused.py +15 -8
- codex/serializers/reader.py +16 -14
- codex/serializers/redirect.py +2 -1
- codex/serializers/route.py +6 -4
- codex/serializers/settings.py +5 -3
- codex/serializers/versions.py +2 -1
- codex/settings/settings.py +4 -3
- codex/signals/django_signals.py +1 -1
- codex/startup.py +2 -2
- codex/static_root/assets/{VCheckbox-FaT6MGfu.f6732060f734.js → VCheckbox-CWBDr4kF.6da5bf3a4d90.js} +1 -1
- codex/static_root/assets/VCheckbox-CWBDr4kF.6da5bf3a4d90.js.br +0 -0
- codex/static_root/assets/VCheckbox-CWBDr4kF.6da5bf3a4d90.js.gz +0 -0
- codex/static_root/assets/{VCheckbox-FaT6MGfu.js → VCheckbox-CWBDr4kF.js} +1 -1
- codex/static_root/assets/VCheckbox-CWBDr4kF.js.br +0 -0
- codex/static_root/assets/VCheckbox-CWBDr4kF.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-CZ_P-qUM.847452d574cf.js → VCheckboxBtn-COaoh3uF.fc880a386827.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-COaoh3uF.fc880a386827.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-COaoh3uF.fc880a386827.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-CZ_P-qUM.js → VCheckboxBtn-COaoh3uF.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-COaoh3uF.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-COaoh3uF.js.gz +0 -0
- codex/static_root/assets/{VCombobox-C8QLNlSl.6f431e19a453.js → VCombobox-DkOruNH0.f30f163ee632.js} +1 -1
- codex/static_root/assets/VCombobox-DkOruNH0.f30f163ee632.js.br +0 -0
- codex/static_root/assets/VCombobox-DkOruNH0.f30f163ee632.js.gz +0 -0
- codex/static_root/assets/{VCombobox-C8QLNlSl.js → VCombobox-DkOruNH0.js} +1 -1
- codex/static_root/assets/VCombobox-DkOruNH0.js.br +0 -0
- codex/static_root/assets/VCombobox-DkOruNH0.js.gz +0 -0
- codex/static_root/assets/{VDialog-RVLeW7je.c0c7eef71eec.js → VDialog-Dr7SuC2S.b6ec7df390f4.js} +1 -1
- codex/static_root/assets/VDialog-Dr7SuC2S.b6ec7df390f4.js.br +0 -0
- codex/static_root/assets/VDialog-Dr7SuC2S.b6ec7df390f4.js.gz +0 -0
- codex/static_root/assets/{VDialog-RVLeW7je.js → VDialog-Dr7SuC2S.js} +1 -1
- codex/static_root/assets/VDialog-Dr7SuC2S.js.br +0 -0
- codex/static_root/assets/VDialog-Dr7SuC2S.js.gz +0 -0
- codex/static_root/assets/{VDivider-D1Ot4vR2.9dbee744fb3c.js → VDivider-By4u2EsM.fd5ee9cce906.js} +1 -1
- codex/static_root/assets/VDivider-By4u2EsM.fd5ee9cce906.js.br +0 -0
- codex/static_root/assets/VDivider-By4u2EsM.fd5ee9cce906.js.gz +0 -0
- codex/static_root/assets/{VDivider-D1Ot4vR2.js → VDivider-By4u2EsM.js} +1 -1
- codex/static_root/assets/VDivider-By4u2EsM.js.br +0 -0
- codex/static_root/assets/VDivider-By4u2EsM.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-DQilGHZk.43f06d0a45e0.js → VExpansionPanels-BhO9oj0a.e99bea455c78.js} +1 -1
- codex/static_root/assets/VExpansionPanels-BhO9oj0a.e99bea455c78.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-BhO9oj0a.e99bea455c78.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-DQilGHZk.js → VExpansionPanels-BhO9oj0a.js} +1 -1
- codex/static_root/assets/VExpansionPanels-BhO9oj0a.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-BhO9oj0a.js.gz +0 -0
- codex/static_root/assets/VForm-XhA6T0Lc.70c9c6fcb9e3.js +1 -0
- codex/static_root/assets/VForm-XhA6T0Lc.70c9c6fcb9e3.js.br +0 -0
- codex/static_root/assets/VForm-XhA6T0Lc.70c9c6fcb9e3.js.gz +0 -0
- codex/static_root/assets/VForm-XhA6T0Lc.js +1 -0
- codex/static_root/assets/VForm-XhA6T0Lc.js.br +0 -0
- codex/static_root/assets/VForm-XhA6T0Lc.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DoayJpcS.fe5e0e74ffee.js → VRadioGroup-C1WCG0rO.6ebc88e4f144.js} +1 -1
- codex/static_root/assets/VRadioGroup-C1WCG0rO.6ebc88e4f144.js.br +3 -0
- codex/static_root/assets/VRadioGroup-C1WCG0rO.6ebc88e4f144.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DoayJpcS.js → VRadioGroup-C1WCG0rO.js} +1 -1
- codex/static_root/assets/VRadioGroup-C1WCG0rO.js.br +3 -0
- codex/static_root/assets/VRadioGroup-C1WCG0rO.js.gz +0 -0
- codex/static_root/assets/VSelect-Bbt1vrBg.ec45ee26818a.js +1 -0
- codex/static_root/assets/VSelect-Bbt1vrBg.ec45ee26818a.js.br +0 -0
- codex/static_root/assets/VSelect-Bbt1vrBg.ec45ee26818a.js.gz +0 -0
- codex/static_root/assets/VSelect-Bbt1vrBg.js +1 -0
- codex/static_root/assets/VSelect-Bbt1vrBg.js.br +0 -0
- codex/static_root/assets/VSelect-Bbt1vrBg.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-TaKCeZgb.ad6c96efe57c.js → VSelectionControl-BkZZAsWo.ba6eca944e2e.js} +1 -1
- codex/static_root/assets/VSelectionControl-BkZZAsWo.ba6eca944e2e.js.br +0 -0
- codex/static_root/assets/VSelectionControl-BkZZAsWo.ba6eca944e2e.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-TaKCeZgb.js → VSelectionControl-BkZZAsWo.js} +1 -1
- codex/static_root/assets/VSelectionControl-BkZZAsWo.js.br +0 -0
- codex/static_root/assets/VSelectionControl-BkZZAsWo.js.gz +0 -0
- codex/static_root/assets/{VTable-BfcOiEpa.77ef3973bb54.js → VTable-D7P2eIc2.5e94bf2a515b.js} +1 -1
- codex/static_root/assets/VTable-D7P2eIc2.5e94bf2a515b.js.br +0 -0
- codex/static_root/assets/VTable-D7P2eIc2.5e94bf2a515b.js.gz +0 -0
- codex/static_root/assets/{VTable-BfcOiEpa.js → VTable-D7P2eIc2.js} +1 -1
- codex/static_root/assets/VTable-D7P2eIc2.js.br +0 -0
- codex/static_root/assets/VTable-D7P2eIc2.js.gz +0 -0
- codex/static_root/assets/VWindowItem-Dm2szrjK.e77444188aa3.js +1 -0
- codex/static_root/assets/VWindowItem-Dm2szrjK.e77444188aa3.js.br +0 -0
- codex/static_root/assets/VWindowItem-Dm2szrjK.e77444188aa3.js.gz +0 -0
- codex/static_root/assets/VWindowItem-Dm2szrjK.js +1 -0
- codex/static_root/assets/VWindowItem-Dm2szrjK.js.br +0 -0
- codex/static_root/assets/VWindowItem-Dm2szrjK.js.gz +0 -0
- codex/static_root/assets/{admin-80eqCqtz.d6deb9edb8cb.js → admin-B4z2nA5P.da0c92500311.js} +1 -1
- codex/static_root/assets/admin-B4z2nA5P.da0c92500311.js.br +0 -0
- codex/static_root/assets/admin-B4z2nA5P.da0c92500311.js.gz +0 -0
- codex/static_root/assets/{admin-80eqCqtz.js → admin-B4z2nA5P.js} +1 -1
- codex/static_root/assets/admin-B4z2nA5P.js.br +0 -0
- codex/static_root/assets/admin-B4z2nA5P.js.gz +0 -0
- codex/static_root/assets/admin-BhW3PNO0.e444048e548d.js +1 -0
- codex/static_root/assets/admin-BhW3PNO0.e444048e548d.js.br +0 -0
- codex/static_root/assets/admin-BhW3PNO0.e444048e548d.js.gz +0 -0
- codex/static_root/assets/admin-BhW3PNO0.js +1 -0
- codex/static_root/assets/admin-BhW3PNO0.js.br +0 -0
- codex/static_root/assets/admin-BhW3PNO0.js.gz +0 -0
- codex/static_root/assets/{admin-menu-_aAGknKO.0c08c9bd2e7d.js → admin-menu-CL7S-xqR.92b6d84c4b70.js} +1 -1
- codex/static_root/assets/admin-menu-CL7S-xqR.92b6d84c4b70.js.br +0 -0
- codex/static_root/assets/admin-menu-CL7S-xqR.92b6d84c4b70.js.gz +0 -0
- codex/static_root/assets/{admin-menu-_aAGknKO.js → admin-menu-CL7S-xqR.js} +1 -1
- codex/static_root/assets/admin-menu-CL7S-xqR.js.br +0 -0
- codex/static_root/assets/admin-menu-CL7S-xqR.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-BqRFyhjf.2bb1194b21e2.js → admin-settings-button-progress-BgBgdELw.52d052e38bc1.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-BgBgdELw.52d052e38bc1.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BgBgdELw.52d052e38bc1.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-BqRFyhjf.js → admin-settings-button-progress-BgBgdELw.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-BgBgdELw.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BgBgdELw.js.gz +0 -0
- codex/static_root/assets/browser-Bi5ov5k8.a4af87c2a667.js +1 -0
- codex/static_root/assets/browser-Bi5ov5k8.a4af87c2a667.js.br +0 -0
- codex/static_root/assets/browser-Bi5ov5k8.a4af87c2a667.js.gz +0 -0
- codex/static_root/assets/browser-Bi5ov5k8.js +1 -0
- codex/static_root/assets/browser-Bi5ov5k8.js.br +0 -0
- codex/static_root/assets/browser-Bi5ov5k8.js.gz +0 -0
- codex/static_root/assets/{browser-chTZ1CM4.521193ab0710.css → browser-DNzQvgkY.aea8b7d7ca40.css} +1 -1
- 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-chTZ1CM4.css → browser-DNzQvgkY.css} +1 -1
- codex/static_root/assets/browser-DNzQvgkY.css.br +0 -0
- codex/static_root/assets/browser-DNzQvgkY.css.gz +0 -0
- codex/static_root/assets/{change-password-dialog-1ZVP_Q2w.ae0d9e5bd42b.js → change-password-dialog-BKar2Bhb.3dbc2feb3c5a.js} +1 -1
- codex/static_root/assets/change-password-dialog-BKar2Bhb.3dbc2feb3c5a.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BKar2Bhb.3dbc2feb3c5a.js.gz +0 -0
- codex/static_root/assets/{change-password-dialog-1ZVP_Q2w.js → change-password-dialog-BKar2Bhb.js} +1 -1
- codex/static_root/assets/change-password-dialog-BKar2Bhb.js.br +0 -0
- codex/static_root/assets/change-password-dialog-BKar2Bhb.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-DqCey9Iq.e315d7f8f752.js → confirm-dialog-BoBL4OoS.abef9614fea9.js} +1 -1
- codex/static_root/assets/confirm-dialog-BoBL4OoS.abef9614fea9.js.br +0 -0
- codex/static_root/assets/confirm-dialog-BoBL4OoS.abef9614fea9.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-DqCey9Iq.js → confirm-dialog-BoBL4OoS.js} +1 -1
- codex/static_root/assets/confirm-dialog-BoBL4OoS.js.br +0 -0
- codex/static_root/assets/confirm-dialog-BoBL4OoS.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CBA8bYeO.17a31f189d66.js → datetime-column-BsiYRUKO.cadd764c06f4.js} +1 -1
- codex/static_root/assets/datetime-column-BsiYRUKO.cadd764c06f4.js.br +0 -0
- codex/static_root/assets/datetime-column-BsiYRUKO.cadd764c06f4.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CBA8bYeO.js → datetime-column-BsiYRUKO.js} +1 -1
- codex/static_root/assets/datetime-column-BsiYRUKO.js.br +0 -0
- codex/static_root/assets/datetime-column-BsiYRUKO.js.gz +0 -0
- codex/static_root/assets/{filter-mnO3lLPo.659442401b16.js → filter-HnY0knto.07f807227dcc.js} +1 -1
- codex/static_root/assets/filter-HnY0knto.07f807227dcc.js.br +0 -0
- codex/static_root/assets/filter-HnY0knto.07f807227dcc.js.gz +0 -0
- codex/static_root/assets/{filter-mnO3lLPo.js → filter-HnY0knto.js} +1 -1
- codex/static_root/assets/filter-HnY0knto.js.br +0 -0
- codex/static_root/assets/filter-HnY0knto.js.gz +0 -0
- codex/static_root/assets/{flag-tab-Bc677pNb.1b8a2f7c0dc3.js → flag-tab-CcS5pve2.a1df5d92e222.js} +1 -1
- codex/static_root/assets/flag-tab-CcS5pve2.a1df5d92e222.js.br +0 -0
- codex/static_root/assets/flag-tab-CcS5pve2.a1df5d92e222.js.gz +0 -0
- codex/static_root/assets/{flag-tab-Bc677pNb.js → flag-tab-CcS5pve2.js} +1 -1
- codex/static_root/assets/flag-tab-CcS5pve2.js.br +0 -0
- codex/static_root/assets/flag-tab-CcS5pve2.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-DPRKg5wq.6f09e9d22fa6.js → forwardRefs-i80xmxX3.db393aeef392.js} +1 -1
- codex/static_root/assets/forwardRefs-i80xmxX3.db393aeef392.js.br +0 -0
- codex/static_root/assets/forwardRefs-i80xmxX3.db393aeef392.js.gz +0 -0
- codex/static_root/assets/{forwardRefs-DPRKg5wq.js → forwardRefs-i80xmxX3.js} +1 -1
- codex/static_root/assets/forwardRefs-i80xmxX3.js.br +0 -0
- codex/static_root/assets/forwardRefs-i80xmxX3.js.gz +0 -0
- codex/static_root/assets/group-tab-SY0gxmHW.f72e944c0ff1.js +1 -0
- codex/static_root/assets/group-tab-SY0gxmHW.f72e944c0ff1.js.br +0 -0
- codex/static_root/assets/group-tab-SY0gxmHW.f72e944c0ff1.js.gz +0 -0
- codex/static_root/assets/group-tab-SY0gxmHW.js +1 -0
- codex/static_root/assets/group-tab-SY0gxmHW.js.br +0 -0
- codex/static_root/assets/group-tab-SY0gxmHW.js.gz +0 -0
- codex/static_root/assets/http-error-EE8gtq5A.07e291d9d955.js +1 -0
- codex/static_root/assets/http-error-EE8gtq5A.07e291d9d955.js.br +0 -0
- codex/static_root/assets/http-error-EE8gtq5A.07e291d9d955.js.gz +0 -0
- codex/static_root/assets/http-error-EE8gtq5A.js +1 -0
- codex/static_root/assets/http-error-EE8gtq5A.js.br +0 -0
- codex/static_root/assets/http-error-EE8gtq5A.js.gz +0 -0
- codex/static_root/assets/{index-9nBCksDQ.4561d2608773.js → index-gVdawuuE.a940fadbac00.js} +1 -1
- codex/static_root/assets/index-gVdawuuE.a940fadbac00.js.br +0 -0
- codex/static_root/assets/index-gVdawuuE.a940fadbac00.js.gz +0 -0
- codex/static_root/assets/{index-9nBCksDQ.js → index-gVdawuuE.js} +1 -1
- codex/static_root/assets/index-gVdawuuE.js.br +0 -0
- codex/static_root/assets/index-gVdawuuE.js.gz +0 -0
- codex/static_root/assets/library-tab-BkDIAvyS.4b4c606b77d6.js +1 -0
- codex/static_root/assets/library-tab-BkDIAvyS.4b4c606b77d6.js.br +0 -0
- codex/static_root/assets/library-tab-BkDIAvyS.4b4c606b77d6.js.gz +0 -0
- codex/static_root/assets/library-tab-BkDIAvyS.js +1 -0
- codex/static_root/assets/library-tab-BkDIAvyS.js.br +0 -0
- codex/static_root/assets/library-tab-BkDIAvyS.js.gz +0 -0
- codex/static_root/assets/main-B5uflU6E.77f3fcd6873f.js +35 -0
- codex/static_root/assets/main-B5uflU6E.77f3fcd6873f.js.br +0 -0
- codex/static_root/assets/main-B5uflU6E.77f3fcd6873f.js.gz +0 -0
- codex/static_root/assets/main-B5uflU6E.js +35 -0
- codex/static_root/assets/main-B5uflU6E.js.br +0 -0
- codex/static_root/assets/main-B5uflU6E.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-wuQbceLs.111d9b9d4133.js +1 -0
- codex/static_root/assets/pager-full-pdf-wuQbceLs.111d9b9d4133.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-wuQbceLs.111d9b9d4133.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-wuQbceLs.js +1 -0
- codex/static_root/assets/pager-full-pdf-wuQbceLs.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-wuQbceLs.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-Dx5JwWG-.ba0e8b645dfa.js → pagination-toolbar-D3JQmDiD.8513a4db85f0.js} +1 -1
- codex/static_root/assets/pagination-toolbar-D3JQmDiD.8513a4db85f0.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-D3JQmDiD.8513a4db85f0.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-Dx5JwWG-.js → pagination-toolbar-D3JQmDiD.js} +1 -1
- codex/static_root/assets/pagination-toolbar-D3JQmDiD.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-D3JQmDiD.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-6ZE_HmLT.10d1e16abc78.js → pdf-doc-DRBtl9_2.225a6d89e842.js} +1 -1
- codex/static_root/assets/pdf-doc-DRBtl9_2.225a6d89e842.js.br +0 -0
- codex/static_root/assets/pdf-doc-DRBtl9_2.225a6d89e842.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-6ZE_HmLT.js → pdf-doc-DRBtl9_2.js} +1 -1
- codex/static_root/assets/pdf-doc-DRBtl9_2.js.br +0 -0
- codex/static_root/assets/pdf-doc-DRBtl9_2.js.gz +0 -0
- codex/static_root/assets/reader-DycvjN42.3e2b4f43235e.js +2 -0
- codex/static_root/assets/reader-DycvjN42.3e2b4f43235e.js.br +0 -0
- codex/static_root/assets/reader-DycvjN42.3e2b4f43235e.js.gz +0 -0
- codex/static_root/assets/reader-DycvjN42.js +2 -0
- codex/static_root/assets/reader-DycvjN42.js.br +0 -0
- codex/static_root/assets/reader-DycvjN42.js.gz +0 -0
- codex/static_root/assets/{relation-chips-C96hi5jm.js → relation-chips-CeHIEjvZ.04d302f4fa89.js} +1 -1
- codex/static_root/assets/relation-chips-CeHIEjvZ.04d302f4fa89.js.br +0 -0
- codex/static_root/assets/relation-chips-CeHIEjvZ.04d302f4fa89.js.gz +0 -0
- codex/static_root/assets/{relation-chips-C96hi5jm.9f07c9eb533a.js → relation-chips-CeHIEjvZ.js} +1 -1
- codex/static_root/assets/relation-chips-CeHIEjvZ.js.br +0 -0
- codex/static_root/assets/relation-chips-CeHIEjvZ.js.gz +0 -0
- codex/static_root/assets/settings-drawer-DY8o-jF3.48dfaafaa00e.js +2 -0
- codex/static_root/assets/settings-drawer-DY8o-jF3.48dfaafaa00e.js.br +0 -0
- codex/static_root/assets/settings-drawer-DY8o-jF3.48dfaafaa00e.js.gz +0 -0
- codex/static_root/assets/settings-drawer-DY8o-jF3.js +2 -0
- codex/static_root/assets/settings-drawer-DY8o-jF3.js.br +0 -0
- codex/static_root/assets/settings-drawer-DY8o-jF3.js.gz +0 -0
- codex/static_root/assets/ssrBoot-DRKt_yWP.3b5868abdd61.js +1 -0
- codex/static_root/assets/ssrBoot-DRKt_yWP.3b5868abdd61.js.br +0 -0
- codex/static_root/assets/ssrBoot-DRKt_yWP.3b5868abdd61.js.gz +0 -0
- codex/static_root/assets/ssrBoot-DRKt_yWP.js +1 -0
- codex/static_root/assets/ssrBoot-DRKt_yWP.js.br +0 -0
- codex/static_root/assets/ssrBoot-DRKt_yWP.js.gz +0 -0
- codex/static_root/assets/{stats-tab-CkT2ZGUQ.b704fa46dc88.js → stats-tab-C1XYGBKj.812896e1d09c.js} +1 -1
- codex/static_root/assets/stats-tab-C1XYGBKj.812896e1d09c.js.br +0 -0
- codex/static_root/assets/stats-tab-C1XYGBKj.812896e1d09c.js.gz +0 -0
- codex/static_root/assets/{stats-tab-CkT2ZGUQ.js → stats-tab-C1XYGBKj.js} +1 -1
- codex/static_root/assets/stats-tab-C1XYGBKj.js.br +0 -0
- codex/static_root/assets/stats-tab-C1XYGBKj.js.gz +0 -0
- codex/static_root/assets/task-tab-CW4DQ3KN.81812f9208e5.css +1 -0
- codex/static_root/assets/{task-tab-DfdUY9Rc.478e74041f80.css.br → task-tab-CW4DQ3KN.81812f9208e5.css.br} +1 -1
- codex/static_root/assets/task-tab-CW4DQ3KN.81812f9208e5.css.gz +0 -0
- codex/static_root/assets/task-tab-CW4DQ3KN.css +1 -0
- codex/static_root/assets/{task-tab-DfdUY9Rc.css.br → task-tab-CW4DQ3KN.css.br} +1 -1
- codex/static_root/assets/task-tab-CW4DQ3KN.css.gz +0 -0
- codex/static_root/assets/task-tab-lFRZ0NMd.6b90f40a1a9f.js +1 -0
- codex/static_root/assets/task-tab-lFRZ0NMd.6b90f40a1a9f.js.br +0 -0
- codex/static_root/assets/task-tab-lFRZ0NMd.6b90f40a1a9f.js.gz +0 -0
- codex/static_root/assets/task-tab-lFRZ0NMd.js +1 -0
- codex/static_root/assets/task-tab-lFRZ0NMd.js.br +0 -0
- codex/static_root/assets/task-tab-lFRZ0NMd.js.gz +0 -0
- codex/static_root/assets/unauthorized-Dld9cV8d.4e675fd9991c.js +1 -0
- codex/static_root/assets/unauthorized-Dld9cV8d.4e675fd9991c.js.br +0 -0
- codex/static_root/assets/unauthorized-Dld9cV8d.4e675fd9991c.js.gz +0 -0
- codex/static_root/assets/unauthorized-Dld9cV8d.js +1 -0
- codex/static_root/assets/unauthorized-Dld9cV8d.js.br +0 -0
- codex/static_root/assets/unauthorized-Dld9cV8d.js.gz +0 -0
- codex/static_root/assets/user-tab-CN9nBOMS.f88d8b1c8afe.js +1 -0
- codex/static_root/assets/user-tab-CN9nBOMS.f88d8b1c8afe.js.br +0 -0
- codex/static_root/assets/user-tab-CN9nBOMS.f88d8b1c8afe.js.gz +0 -0
- codex/static_root/assets/user-tab-CN9nBOMS.js +1 -0
- codex/static_root/assets/user-tab-CN9nBOMS.js.br +0 -0
- codex/static_root/assets/user-tab-CN9nBOMS.js.gz +0 -0
- codex/static_root/{manifest.225989a17f49.json → manifest.66d7229aa07a.json} +297 -277
- codex/static_root/manifest.66d7229aa07a.json.br +0 -0
- codex/static_root/manifest.66d7229aa07a.json.gz +0 -0
- codex/static_root/manifest.json +297 -277
- 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 +10 -13
- codex/urls/root.py +4 -3
- codex/views/admin/api_key.py +1 -4
- codex/views/admin/flag.py +2 -2
- codex/views/admin/group.py +2 -2
- codex/views/admin/library.py +4 -4
- codex/views/admin/stats.py +10 -10
- codex/views/admin/tasks.py +32 -13
- codex/views/admin/user.py +36 -10
- codex/views/auth.py +3 -8
- codex/views/bookmark.py +3 -3
- codex/views/browser/annotate/card.py +2 -2
- codex/views/browser/annotate/order.py +6 -7
- codex/views/browser/bookmark.py +3 -1
- codex/views/browser/breadcrumbs.py +6 -5
- codex/views/browser/browser.py +2 -2
- codex/views/browser/choices.py +7 -8
- codex/views/browser/cover.py +6 -3
- codex/views/browser/download.py +2 -1
- codex/views/browser/filters/bookmark.py +1 -1
- codex/views/browser/filters/field.py +1 -1
- codex/views/browser/filters/filter.py +6 -8
- codex/views/browser/filters/group.py +8 -8
- 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 +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 +3 -5
- codex/views/browser/params.py +1 -1
- codex/views/browser/settings.py +1 -1
- codex/views/browser/validate.py +9 -6
- codex/views/const.py +0 -3
- codex/views/frontend.py +1 -1
- codex/views/mixins.py +3 -2
- codex/views/opds/authentication_v1.py +1 -1
- codex/views/opds/const.py +4 -4
- codex/views/opds/urls.py +1 -1
- codex/views/opds/util.py +4 -4
- codex/views/opds/v1/entry/entry.py +4 -2
- codex/views/opds/v1/entry/links.py +4 -5
- 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 +3 -3
- codex/views/opds/v2/links.py +18 -11
- codex/views/opds/v2/progression.py +8 -9
- codex/views/opds/v2/publications.py +10 -20
- codex/views/public.py +2 -2
- codex/views/reader/books.py +3 -2
- 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 +10 -3
- 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.3a2.dist-info → codex-1.7.5.dist-info}/METADATA +3 -1
- {codex-1.7.3a2.dist-info → codex-1.7.5.dist-info}/RECORD +433 -415
- {codex-1.7.3a2.dist-info → codex-1.7.5.dist-info}/WHEEL +1 -1
- codex/serializers/fields.py +0 -183
- codex/static_root/assets/VCheckbox-FaT6MGfu.f6732060f734.js.br +0 -0
- codex/static_root/assets/VCheckbox-FaT6MGfu.f6732060f734.js.gz +0 -0
- codex/static_root/assets/VCheckbox-FaT6MGfu.js.br +0 -0
- codex/static_root/assets/VCheckbox-FaT6MGfu.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-CZ_P-qUM.847452d574cf.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-CZ_P-qUM.847452d574cf.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-CZ_P-qUM.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-CZ_P-qUM.js.gz +0 -0
- codex/static_root/assets/VCombobox-C8QLNlSl.6f431e19a453.js.br +0 -0
- codex/static_root/assets/VCombobox-C8QLNlSl.6f431e19a453.js.gz +0 -0
- codex/static_root/assets/VCombobox-C8QLNlSl.js.br +0 -0
- codex/static_root/assets/VCombobox-C8QLNlSl.js.gz +0 -0
- codex/static_root/assets/VDialog-RVLeW7je.c0c7eef71eec.js.br +0 -0
- codex/static_root/assets/VDialog-RVLeW7je.c0c7eef71eec.js.gz +0 -0
- codex/static_root/assets/VDialog-RVLeW7je.js.br +0 -0
- codex/static_root/assets/VDialog-RVLeW7je.js.gz +0 -0
- codex/static_root/assets/VDivider-D1Ot4vR2.9dbee744fb3c.js.br +0 -0
- codex/static_root/assets/VDivider-D1Ot4vR2.9dbee744fb3c.js.gz +0 -0
- codex/static_root/assets/VDivider-D1Ot4vR2.js.br +0 -0
- codex/static_root/assets/VDivider-D1Ot4vR2.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-DQilGHZk.43f06d0a45e0.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-DQilGHZk.43f06d0a45e0.js.gz +0 -0
- codex/static_root/assets/VExpansionPanels-DQilGHZk.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-DQilGHZk.js.gz +0 -0
- codex/static_root/assets/VForm-DNmY-qFJ.81f3a5ff7ec3.js +0 -1
- codex/static_root/assets/VForm-DNmY-qFJ.81f3a5ff7ec3.js.br +0 -0
- codex/static_root/assets/VForm-DNmY-qFJ.81f3a5ff7ec3.js.gz +0 -0
- codex/static_root/assets/VForm-DNmY-qFJ.js +0 -1
- codex/static_root/assets/VForm-DNmY-qFJ.js.br +0 -0
- codex/static_root/assets/VForm-DNmY-qFJ.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DoayJpcS.fe5e0e74ffee.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DoayJpcS.fe5e0e74ffee.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DoayJpcS.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DoayJpcS.js.gz +0 -0
- codex/static_root/assets/VSelect-BSLmHX_P.9ab865ec0fad.js +0 -1
- codex/static_root/assets/VSelect-BSLmHX_P.9ab865ec0fad.js.br +0 -0
- codex/static_root/assets/VSelect-BSLmHX_P.9ab865ec0fad.js.gz +0 -0
- codex/static_root/assets/VSelect-BSLmHX_P.js +0 -1
- codex/static_root/assets/VSelect-BSLmHX_P.js.br +0 -0
- codex/static_root/assets/VSelect-BSLmHX_P.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-TaKCeZgb.ad6c96efe57c.js.br +0 -0
- codex/static_root/assets/VSelectionControl-TaKCeZgb.ad6c96efe57c.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-TaKCeZgb.js.br +0 -0
- codex/static_root/assets/VSelectionControl-TaKCeZgb.js.gz +0 -0
- codex/static_root/assets/VTable-BfcOiEpa.77ef3973bb54.js.br +0 -0
- codex/static_root/assets/VTable-BfcOiEpa.77ef3973bb54.js.gz +0 -0
- codex/static_root/assets/VTable-BfcOiEpa.js.br +0 -0
- codex/static_root/assets/VTable-BfcOiEpa.js.gz +0 -0
- codex/static_root/assets/VWindowItem-D8lWcbQY.e4c75ad78718.js +0 -1
- codex/static_root/assets/VWindowItem-D8lWcbQY.e4c75ad78718.js.br +0 -0
- codex/static_root/assets/VWindowItem-D8lWcbQY.e4c75ad78718.js.gz +0 -0
- codex/static_root/assets/VWindowItem-D8lWcbQY.js +0 -1
- codex/static_root/assets/VWindowItem-D8lWcbQY.js.br +0 -0
- codex/static_root/assets/VWindowItem-D8lWcbQY.js.gz +0 -0
- codex/static_root/assets/admin-80eqCqtz.d6deb9edb8cb.js.br +0 -0
- codex/static_root/assets/admin-80eqCqtz.d6deb9edb8cb.js.gz +0 -0
- codex/static_root/assets/admin-80eqCqtz.js.br +0 -0
- codex/static_root/assets/admin-80eqCqtz.js.gz +0 -0
- codex/static_root/assets/admin-CBLHOrM9.8c3c2268bc96.js +0 -1
- codex/static_root/assets/admin-CBLHOrM9.8c3c2268bc96.js.br +0 -0
- codex/static_root/assets/admin-CBLHOrM9.8c3c2268bc96.js.gz +0 -0
- codex/static_root/assets/admin-CBLHOrM9.js +0 -1
- codex/static_root/assets/admin-CBLHOrM9.js.br +0 -0
- codex/static_root/assets/admin-CBLHOrM9.js.gz +0 -0
- codex/static_root/assets/admin-menu-_aAGknKO.0c08c9bd2e7d.js.br +0 -0
- codex/static_root/assets/admin-menu-_aAGknKO.0c08c9bd2e7d.js.gz +0 -0
- codex/static_root/assets/admin-menu-_aAGknKO.js.br +0 -0
- codex/static_root/assets/admin-menu-_aAGknKO.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-BqRFyhjf.2bb1194b21e2.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BqRFyhjf.2bb1194b21e2.js.gz +0 -0
- codex/static_root/assets/admin-settings-button-progress-BqRFyhjf.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-BqRFyhjf.js.gz +0 -0
- codex/static_root/assets/browser-DAprXYuP.8bb92965dd9d.js +0 -1
- codex/static_root/assets/browser-DAprXYuP.8bb92965dd9d.js.br +0 -0
- codex/static_root/assets/browser-DAprXYuP.8bb92965dd9d.js.gz +0 -0
- codex/static_root/assets/browser-DAprXYuP.js +0 -1
- codex/static_root/assets/browser-DAprXYuP.js.br +0 -0
- codex/static_root/assets/browser-DAprXYuP.js.gz +0 -0
- codex/static_root/assets/browser-chTZ1CM4.521193ab0710.css.br +0 -0
- codex/static_root/assets/browser-chTZ1CM4.521193ab0710.css.gz +0 -0
- codex/static_root/assets/browser-chTZ1CM4.css.br +0 -0
- codex/static_root/assets/browser-chTZ1CM4.css.gz +0 -0
- codex/static_root/assets/change-password-dialog-1ZVP_Q2w.ae0d9e5bd42b.js.br +0 -0
- codex/static_root/assets/change-password-dialog-1ZVP_Q2w.ae0d9e5bd42b.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-1ZVP_Q2w.js.br +0 -0
- codex/static_root/assets/change-password-dialog-1ZVP_Q2w.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-DqCey9Iq.e315d7f8f752.js.br +0 -0
- codex/static_root/assets/confirm-dialog-DqCey9Iq.e315d7f8f752.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-DqCey9Iq.js.br +0 -0
- codex/static_root/assets/confirm-dialog-DqCey9Iq.js.gz +0 -0
- codex/static_root/assets/datetime-column-CBA8bYeO.17a31f189d66.js.br +0 -0
- codex/static_root/assets/datetime-column-CBA8bYeO.17a31f189d66.js.gz +0 -0
- codex/static_root/assets/datetime-column-CBA8bYeO.js.br +0 -0
- codex/static_root/assets/datetime-column-CBA8bYeO.js.gz +0 -0
- codex/static_root/assets/filter-mnO3lLPo.659442401b16.js.br +0 -0
- codex/static_root/assets/filter-mnO3lLPo.659442401b16.js.gz +0 -0
- codex/static_root/assets/filter-mnO3lLPo.js.br +0 -0
- codex/static_root/assets/filter-mnO3lLPo.js.gz +0 -0
- codex/static_root/assets/flag-tab-Bc677pNb.1b8a2f7c0dc3.js.br +0 -0
- codex/static_root/assets/flag-tab-Bc677pNb.1b8a2f7c0dc3.js.gz +0 -0
- codex/static_root/assets/flag-tab-Bc677pNb.js.br +0 -0
- codex/static_root/assets/flag-tab-Bc677pNb.js.gz +0 -0
- codex/static_root/assets/flag-tab-glFvEgEl.be8eed14384e.css +0 -1
- codex/static_root/assets/flag-tab-glFvEgEl.be8eed14384e.css.br +0 -0
- codex/static_root/assets/flag-tab-glFvEgEl.be8eed14384e.css.gz +0 -0
- codex/static_root/assets/flag-tab-glFvEgEl.css +0 -1
- codex/static_root/assets/flag-tab-glFvEgEl.css.br +0 -0
- codex/static_root/assets/flag-tab-glFvEgEl.css.gz +0 -0
- codex/static_root/assets/forwardRefs-DPRKg5wq.6f09e9d22fa6.js.br +0 -0
- codex/static_root/assets/forwardRefs-DPRKg5wq.6f09e9d22fa6.js.gz +0 -0
- codex/static_root/assets/forwardRefs-DPRKg5wq.js.br +0 -0
- codex/static_root/assets/forwardRefs-DPRKg5wq.js.gz +0 -0
- codex/static_root/assets/group-tab-BVlBrMwo.1127b51be6e7.js +0 -1
- codex/static_root/assets/group-tab-BVlBrMwo.1127b51be6e7.js.br +0 -0
- codex/static_root/assets/group-tab-BVlBrMwo.1127b51be6e7.js.gz +0 -0
- codex/static_root/assets/group-tab-BVlBrMwo.js +0 -1
- codex/static_root/assets/group-tab-BVlBrMwo.js.br +0 -0
- codex/static_root/assets/group-tab-BVlBrMwo.js.gz +0 -0
- codex/static_root/assets/http-error-C9-_aEBF.d29b164e80de.js +0 -1
- codex/static_root/assets/http-error-C9-_aEBF.d29b164e80de.js.br +0 -0
- codex/static_root/assets/http-error-C9-_aEBF.d29b164e80de.js.gz +0 -0
- codex/static_root/assets/http-error-C9-_aEBF.js +0 -1
- codex/static_root/assets/http-error-C9-_aEBF.js.br +0 -0
- codex/static_root/assets/http-error-C9-_aEBF.js.gz +0 -0
- codex/static_root/assets/index-9nBCksDQ.4561d2608773.js.br +0 -0
- codex/static_root/assets/index-9nBCksDQ.4561d2608773.js.gz +0 -0
- codex/static_root/assets/index-9nBCksDQ.js.br +0 -0
- codex/static_root/assets/index-9nBCksDQ.js.gz +0 -0
- codex/static_root/assets/library-tab-BMe3dKzy.22b6e123ecfb.js +0 -1
- codex/static_root/assets/library-tab-BMe3dKzy.22b6e123ecfb.js.br +0 -0
- codex/static_root/assets/library-tab-BMe3dKzy.22b6e123ecfb.js.gz +0 -0
- codex/static_root/assets/library-tab-BMe3dKzy.js +0 -1
- codex/static_root/assets/library-tab-BMe3dKzy.js.br +0 -0
- codex/static_root/assets/library-tab-BMe3dKzy.js.gz +0 -0
- codex/static_root/assets/main-BbNUiWEb.565b616eb122.js +0 -35
- codex/static_root/assets/main-BbNUiWEb.565b616eb122.js.br +0 -0
- codex/static_root/assets/main-BbNUiWEb.565b616eb122.js.gz +0 -0
- codex/static_root/assets/main-BbNUiWEb.js +0 -35
- codex/static_root/assets/main-BbNUiWEb.js.br +0 -0
- codex/static_root/assets/main-BbNUiWEb.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.6d4ec47c14f7.js +0 -1
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.6d4ec47c14f7.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.6d4ec47c14f7.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.js +0 -1
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.js.br +0 -0
- codex/static_root/assets/pager-full-pdf-JwAUlsNI.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Dx5JwWG-.ba0e8b645dfa.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-Dx5JwWG-.ba0e8b645dfa.js.gz +0 -0
- codex/static_root/assets/pagination-toolbar-Dx5JwWG-.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-Dx5JwWG-.js.gz +0 -0
- codex/static_root/assets/pdf-doc-6ZE_HmLT.10d1e16abc78.js.br +0 -0
- codex/static_root/assets/pdf-doc-6ZE_HmLT.10d1e16abc78.js.gz +0 -0
- codex/static_root/assets/pdf-doc-6ZE_HmLT.js.br +0 -0
- codex/static_root/assets/pdf-doc-6ZE_HmLT.js.gz +0 -0
- codex/static_root/assets/reader-DdPKDuh5.0c55cef1e98b.js +0 -2
- codex/static_root/assets/reader-DdPKDuh5.0c55cef1e98b.js.br +0 -0
- codex/static_root/assets/reader-DdPKDuh5.0c55cef1e98b.js.gz +0 -0
- codex/static_root/assets/reader-DdPKDuh5.js +0 -2
- codex/static_root/assets/reader-DdPKDuh5.js.br +0 -0
- codex/static_root/assets/reader-DdPKDuh5.js.gz +0 -0
- codex/static_root/assets/relation-chips-C96hi5jm.9f07c9eb533a.js.br +0 -0
- codex/static_root/assets/relation-chips-C96hi5jm.9f07c9eb533a.js.gz +0 -0
- codex/static_root/assets/relation-chips-C96hi5jm.js.br +0 -0
- codex/static_root/assets/relation-chips-C96hi5jm.js.gz +0 -0
- codex/static_root/assets/settings-drawer-CqbT1rid.5639fa00b301.js +0 -2
- codex/static_root/assets/settings-drawer-CqbT1rid.5639fa00b301.js.br +0 -0
- codex/static_root/assets/settings-drawer-CqbT1rid.5639fa00b301.js.gz +0 -0
- codex/static_root/assets/settings-drawer-CqbT1rid.js +0 -2
- codex/static_root/assets/settings-drawer-CqbT1rid.js.br +0 -0
- codex/static_root/assets/settings-drawer-CqbT1rid.js.gz +0 -0
- codex/static_root/assets/stats-tab-CkT2ZGUQ.b704fa46dc88.js.br +0 -0
- codex/static_root/assets/stats-tab-CkT2ZGUQ.b704fa46dc88.js.gz +0 -0
- codex/static_root/assets/stats-tab-CkT2ZGUQ.js.br +0 -0
- codex/static_root/assets/stats-tab-CkT2ZGUQ.js.gz +0 -0
- codex/static_root/assets/task-tab-DfdUY9Rc.478e74041f80.css +0 -1
- codex/static_root/assets/task-tab-DfdUY9Rc.478e74041f80.css.gz +0 -0
- codex/static_root/assets/task-tab-DfdUY9Rc.css +0 -1
- codex/static_root/assets/task-tab-DfdUY9Rc.css.gz +0 -0
- codex/static_root/assets/task-tab-a-DcU3Tj.8c2f7bf3c4c9.js +0 -1
- codex/static_root/assets/task-tab-a-DcU3Tj.8c2f7bf3c4c9.js.br +0 -0
- codex/static_root/assets/task-tab-a-DcU3Tj.8c2f7bf3c4c9.js.gz +0 -0
- codex/static_root/assets/task-tab-a-DcU3Tj.js +0 -1
- codex/static_root/assets/task-tab-a-DcU3Tj.js.br +0 -0
- codex/static_root/assets/task-tab-a-DcU3Tj.js.gz +0 -0
- codex/static_root/assets/unauthorized-BOl5YpL3.f3c4b52718d5.js +0 -1
- codex/static_root/assets/unauthorized-BOl5YpL3.f3c4b52718d5.js.br +0 -0
- codex/static_root/assets/unauthorized-BOl5YpL3.f3c4b52718d5.js.gz +0 -0
- codex/static_root/assets/unauthorized-BOl5YpL3.js +0 -1
- codex/static_root/assets/unauthorized-BOl5YpL3.js.br +0 -0
- codex/static_root/assets/unauthorized-BOl5YpL3.js.gz +0 -0
- codex/static_root/assets/user-tab-BBDZvD8G.aa4263a68b22.js +0 -1
- codex/static_root/assets/user-tab-BBDZvD8G.aa4263a68b22.js.br +0 -0
- codex/static_root/assets/user-tab-BBDZvD8G.aa4263a68b22.js.gz +0 -0
- codex/static_root/assets/user-tab-BBDZvD8G.js +0 -1
- codex/static_root/assets/user-tab-BBDZvD8G.js.br +0 -0
- codex/static_root/assets/user-tab-BBDZvD8G.js.gz +0 -0
- codex/static_root/manifest.225989a17f49.json.br +0 -0
- codex/static_root/manifest.225989a17f49.json.gz +0 -0
- {codex-1.7.3a2.dist-info → codex-1.7.5.dist-info}/LICENSE +0 -0
- {codex-1.7.3a2.dist-info → codex-1.7.5.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Custom Serializer Fields."""
|
|
2
|
+
|
|
3
|
+
from codex.serializers.fields.auth import TimestampField, TimezoneField
|
|
4
|
+
from codex.serializers.fields.group import BrowseGroupField
|
|
5
|
+
from codex.serializers.fields.reader import FitToField, ReadingDirectionField
|
|
6
|
+
from codex.serializers.fields.sanitized import SanitizedCharField
|
|
7
|
+
from codex.serializers.fields.session import SessionKeyField
|
|
8
|
+
from codex.serializers.fields.stats import (
|
|
9
|
+
CountDictField,
|
|
10
|
+
SerializerChoicesField,
|
|
11
|
+
StringListMultipleChoiceField,
|
|
12
|
+
)
|
|
13
|
+
from codex.serializers.fields.vuetify import (
|
|
14
|
+
VuetifyBooleanField,
|
|
15
|
+
VuetifyCharField,
|
|
16
|
+
VuetifyDecadeField,
|
|
17
|
+
VuetifyFloatField,
|
|
18
|
+
VuetifyIntegerField,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = (
|
|
22
|
+
"TimestampField",
|
|
23
|
+
"TimezoneField",
|
|
24
|
+
"BrowseGroupField",
|
|
25
|
+
"SanitizedCharField",
|
|
26
|
+
"StringListMultipleChoiceField",
|
|
27
|
+
"SerializerChoicesField",
|
|
28
|
+
"CountDictField",
|
|
29
|
+
"VuetifyFloatField",
|
|
30
|
+
"VuetifyIntegerField",
|
|
31
|
+
"VuetifyCharField",
|
|
32
|
+
"VuetifyBooleanField",
|
|
33
|
+
"VuetifyDecadeField",
|
|
34
|
+
"FitToField",
|
|
35
|
+
"ReadingDirectionField",
|
|
36
|
+
"SessionKeyField",
|
|
37
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Custom fields."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
|
5
|
+
|
|
6
|
+
from rest_framework.exceptions import ValidationError
|
|
7
|
+
from rest_framework.serializers import (
|
|
8
|
+
CharField,
|
|
9
|
+
IntegerField,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from codex.logger.logging import get_logger
|
|
13
|
+
|
|
14
|
+
LOG = get_logger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TimestampField(IntegerField):
|
|
18
|
+
"""IntegerTimestampField."""
|
|
19
|
+
|
|
20
|
+
def to_representation(self, value) -> int:
|
|
21
|
+
"""Convert to Jascript millisecond int timestamp from datetime, or castable."""
|
|
22
|
+
if isinstance(value, datetime):
|
|
23
|
+
value = value.timestamp()
|
|
24
|
+
return int(float(value) * 1000)
|
|
25
|
+
|
|
26
|
+
def to_internal_value(self, data) -> datetime: # type: ignore[reportIncompatibleMethodOverride]
|
|
27
|
+
"""Convert from castable, likely string to datetime."""
|
|
28
|
+
return datetime.fromtimestamp(float(data) / 1000, tz=timezone.utc)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def validate_timezone(data):
|
|
32
|
+
"""Validate Timezone."""
|
|
33
|
+
try:
|
|
34
|
+
ZoneInfo(data)
|
|
35
|
+
except ZoneInfoNotFoundError as exc:
|
|
36
|
+
raise ValidationError from exc
|
|
37
|
+
return data
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TimezoneField(CharField):
|
|
41
|
+
"""Timezone field."""
|
|
42
|
+
|
|
43
|
+
def __init__(self, *args, **kwargs):
|
|
44
|
+
"""Call Charfield with defaults."""
|
|
45
|
+
super().__init__(*args, min_length=2, validators=[validate_timezone], **kwargs)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Custom fields."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC
|
|
4
|
+
|
|
5
|
+
import pycountry
|
|
6
|
+
from rest_framework.serializers import (
|
|
7
|
+
ChoiceField,
|
|
8
|
+
ListField,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from codex.choices.browser import (
|
|
12
|
+
BROWSER_BOOKMARK_FILTER_CHOICES,
|
|
13
|
+
BROWSER_TOP_GROUP_CHOICES,
|
|
14
|
+
DUMMY_NULL_NAME,
|
|
15
|
+
)
|
|
16
|
+
from codex.logger.logging import get_logger
|
|
17
|
+
from codex.serializers.fields.sanitized import SanitizedCharField
|
|
18
|
+
from codex.serializers.route import RouteSerializer
|
|
19
|
+
|
|
20
|
+
LOG = get_logger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TopGroupField(ChoiceField):
|
|
24
|
+
"""Valid Top Groups Only."""
|
|
25
|
+
|
|
26
|
+
class_choices = tuple(BROWSER_TOP_GROUP_CHOICES.keys())
|
|
27
|
+
|
|
28
|
+
def __init__(self, *args, **kwargs):
|
|
29
|
+
"""Initialize with choices."""
|
|
30
|
+
super().__init__(*args, choices=self.class_choices, **kwargs)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class BookmarkFilterField(ChoiceField):
|
|
34
|
+
"""Bookmark Choice Field."""
|
|
35
|
+
|
|
36
|
+
def __init__(self, *args, **kwargs):
|
|
37
|
+
"""Use bookmark filter choices."""
|
|
38
|
+
super().__init__(
|
|
39
|
+
*args, choices=tuple(BROWSER_BOOKMARK_FILTER_CHOICES.keys()), **kwargs
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class PyCountryField(SanitizedCharField, ABC):
|
|
44
|
+
"""Serialize to a long pycountry name."""
|
|
45
|
+
|
|
46
|
+
LOOKUP_MODULE = pycountry.countries
|
|
47
|
+
_ALPHA_2_LEN = 2
|
|
48
|
+
|
|
49
|
+
def to_representation(self, value):
|
|
50
|
+
"""Lookup the name with pycountry, just copy the value on fail."""
|
|
51
|
+
if not value:
|
|
52
|
+
return ""
|
|
53
|
+
if value == DUMMY_NULL_NAME:
|
|
54
|
+
return value
|
|
55
|
+
try:
|
|
56
|
+
# fix for https://github.com/flyingcircusio/pycountry/issues/41
|
|
57
|
+
lookup_obj = (
|
|
58
|
+
self.LOOKUP_MODULE.get(alpha_2=value)
|
|
59
|
+
if len(value) == self._ALPHA_2_LEN
|
|
60
|
+
else self.LOOKUP_MODULE.lookup(value)
|
|
61
|
+
)
|
|
62
|
+
# If lookup fails, return the key as the name
|
|
63
|
+
except Exception:
|
|
64
|
+
LOG.warning(f"Could not serialize name with pycountry {value}")
|
|
65
|
+
return value
|
|
66
|
+
else:
|
|
67
|
+
return lookup_obj.name if lookup_obj else value
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class CountryField(PyCountryField):
|
|
71
|
+
"""Serializer to long country name."""
|
|
72
|
+
|
|
73
|
+
LOOKUP_MODULE = pycountry.countries
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class LanguageField(PyCountryField):
|
|
77
|
+
"""Serializer to long language name."""
|
|
78
|
+
|
|
79
|
+
LOOKUP_MODULE = pycountry.languages
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class BreadcrumbsField(ListField):
|
|
83
|
+
"""And Array of Routes."""
|
|
84
|
+
|
|
85
|
+
child = RouteSerializer()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Browser Group Field."""
|
|
2
|
+
|
|
3
|
+
from rest_framework.fields import ChoiceField
|
|
4
|
+
|
|
5
|
+
from codex.choices.browser import BROWSER_GROUP_CHOICES
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BrowseGroupField(ChoiceField):
|
|
9
|
+
"""BrowseGroup Field."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, *args, **kwargs):
|
|
12
|
+
"""Add choices."""
|
|
13
|
+
super().__init__(*args, choices=tuple(BROWSER_GROUP_CHOICES.keys()), **kwargs)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Reader Fields."""
|
|
2
|
+
|
|
3
|
+
from rest_framework.serializers import ChoiceField
|
|
4
|
+
|
|
5
|
+
from codex.models import Bookmark
|
|
6
|
+
from codex.models.comic import ReadingDirection
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FitToField(ChoiceField):
|
|
10
|
+
"""Bookmark FitTo Fieild."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, *args, **kwargs):
|
|
13
|
+
"""Add Choices."""
|
|
14
|
+
super().__init__(*args, choices=Bookmark.FitTo.values, **kwargs)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ReadingDirectionField(ChoiceField):
|
|
18
|
+
"""Reading Direction Field."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, *args, **kwargs):
|
|
21
|
+
"""Add Choices."""
|
|
22
|
+
super().__init__(*args, choices=ReadingDirection.values, **kwargs)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Sanitied Fields."""
|
|
2
|
+
|
|
3
|
+
from nh3 import clean
|
|
4
|
+
from rest_framework.fields import CharField
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SanitizedCharField(CharField):
|
|
8
|
+
"""Sanitize CharField using NH3."""
|
|
9
|
+
|
|
10
|
+
def to_internal_value(self, data):
|
|
11
|
+
"""Sanitize CharField using NH3."""
|
|
12
|
+
sanitized_data = clean(data)
|
|
13
|
+
return super().to_internal_value(sanitized_data)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Session Custom Fields."""
|
|
2
|
+
|
|
3
|
+
from rest_framework.fields import ChoiceField
|
|
4
|
+
|
|
5
|
+
from codex.choices.browser import BROWSER_DEFAULTS
|
|
6
|
+
from codex.choices.reader import READER_DEFAULTS
|
|
7
|
+
|
|
8
|
+
_SESSION_KEYS = (*READER_DEFAULTS.keys(), *BROWSER_DEFAULTS.keys(), "filters")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SessionKeyField(ChoiceField):
|
|
12
|
+
"""Session Key Field."""
|
|
13
|
+
|
|
14
|
+
def __init__(self, *args, **kwargs):
|
|
15
|
+
"""Add choices."""
|
|
16
|
+
super().__init__(*args, choices=_SESSION_KEYS, **kwargs)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Custom Vuetify fields."""
|
|
2
|
+
|
|
3
|
+
from rest_framework.fields import DictField, IntegerField
|
|
4
|
+
from rest_framework.serializers import MultipleChoiceField
|
|
5
|
+
|
|
6
|
+
from codex.logger.logging import get_logger
|
|
7
|
+
|
|
8
|
+
LOG = get_logger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class StringListMultipleChoiceField(MultipleChoiceField):
|
|
12
|
+
"""A Multiple Choice Field expressed as as a comma delimited string."""
|
|
13
|
+
|
|
14
|
+
def to_internal_value(self, data):
|
|
15
|
+
"""Convert comma delimited strings to sets."""
|
|
16
|
+
if isinstance(data, str):
|
|
17
|
+
data = frozenset(data.split(","))
|
|
18
|
+
return super().to_internal_value(data) # type: ignore[reportIncompatibleMethodOverride]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SerializerChoicesField(StringListMultipleChoiceField):
|
|
22
|
+
"""A String List Multiple Choice Field limited to a specified serializer's fields."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, *args, serializer=None, **kwargs):
|
|
25
|
+
"""Limit choices to fields from serializers."""
|
|
26
|
+
if not serializer:
|
|
27
|
+
reason = "serializer required for this field."
|
|
28
|
+
raise ValueError(reason)
|
|
29
|
+
choices = serializer().get_fields().keys()
|
|
30
|
+
super().__init__(*args, choices=choices, **kwargs)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class CountDictField(DictField):
|
|
34
|
+
"""Dict for counting things."""
|
|
35
|
+
|
|
36
|
+
child = IntegerField(read_only=True)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Custom Vuetify fields."""
|
|
2
|
+
|
|
3
|
+
from django.utils.translation import gettext_lazy as _
|
|
4
|
+
from rest_framework.exceptions import ValidationError
|
|
5
|
+
from rest_framework.serializers import (
|
|
6
|
+
BooleanField,
|
|
7
|
+
CharField,
|
|
8
|
+
FloatField,
|
|
9
|
+
IntegerField,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from codex.choices.browser import VUETIFY_NULL_CODE
|
|
13
|
+
from codex.logger.logging import get_logger
|
|
14
|
+
|
|
15
|
+
LOG = get_logger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class VuetifyNullCodeFieldMixin:
|
|
19
|
+
"""Convert Vuetify null codes to None."""
|
|
20
|
+
|
|
21
|
+
NULL_CODE = VUETIFY_NULL_CODE
|
|
22
|
+
|
|
23
|
+
def to_internal_value(self, data):
|
|
24
|
+
"""Convert numeric null code to None."""
|
|
25
|
+
return None if data == self.NULL_CODE else data
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class VuetifyFloatField(VuetifyNullCodeFieldMixin, FloatField): # type: ignore[reportIncompatibleMethodOverride]
|
|
29
|
+
"""Float Field with null code conversion."""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class VuetifyIntegerField(VuetifyNullCodeFieldMixin, IntegerField): # type: ignore[reportIncompatibleMethodOverride]
|
|
33
|
+
"""Integer Field with null code conversion."""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class VuetifyCharField(VuetifyNullCodeFieldMixin, CharField): # type: ignore[reportIncompatibleMethodOverride]
|
|
37
|
+
"""Char Field with null code conversion."""
|
|
38
|
+
|
|
39
|
+
NULL_CODE = str(VUETIFY_NULL_CODE)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class VuetifyBooleanField(VuetifyNullCodeFieldMixin, BooleanField): # type: ignore[reportIncompatibleMethodOverride]
|
|
43
|
+
"""Boolean Field with null code conversion."""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def validate_decade(decade):
|
|
47
|
+
"""Validate decades."""
|
|
48
|
+
# * We don't need a whole db call just to be perfectly accurate
|
|
49
|
+
# * -1s are decoded back into None before validation
|
|
50
|
+
if decade is not None and decade % 10 != 0:
|
|
51
|
+
raise ValidationError(_("Invalid decade: ") + f"{decade}")
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class VuetifyDecadeField(VuetifyIntegerField):
|
|
56
|
+
"""Integer field with null code conversion and decade validation."""
|
|
57
|
+
|
|
58
|
+
VALIDATORS = (validate_decade,)
|
|
59
|
+
|
|
60
|
+
def __init__(self, *args, **kwargs):
|
|
61
|
+
"""Use decade validator."""
|
|
62
|
+
super().__init__(*args, validators=self.VALIDATORS, **kwargs)
|
codex/serializers/models/base.py
CHANGED
|
@@ -6,7 +6,7 @@ from rest_framework.serializers import ModelSerializer, SerializerMetaclass
|
|
|
6
6
|
class BaseModelSerializer(ModelSerializer):
|
|
7
7
|
"""BaseModel Serializer for inheritance."""
|
|
8
8
|
|
|
9
|
-
class Meta(SerializerMetaclass): # type: ignore
|
|
9
|
+
class Meta(SerializerMetaclass): # type: ignore[reportIncompatibleVariableOverride]
|
|
10
10
|
"""Use explicit metaclass instead of python 3 method."""
|
|
11
11
|
|
|
12
12
|
abstract = True
|
|
@@ -38,8 +38,8 @@ class ComicSerializer(BaseModelSerializer):
|
|
|
38
38
|
pk = IntegerField(source="id")
|
|
39
39
|
|
|
40
40
|
# Annotations
|
|
41
|
-
# issue_count = IntegerField(allow_null=True)
|
|
42
|
-
# volume_count = IntegerField(allow_null=True)
|
|
41
|
+
# issue_count = IntegerField(allow_null=True) could be 1
|
|
42
|
+
# volume_count = IntegerField(allow_null=True) could be 1
|
|
43
43
|
|
|
44
44
|
# Group FKs
|
|
45
45
|
publisher = PublisherSerializer(allow_null=True)
|
|
@@ -43,7 +43,6 @@ class SeriesSerializer(GroupModelSerializer):
|
|
|
43
43
|
"""Configure model."""
|
|
44
44
|
|
|
45
45
|
model = Series
|
|
46
|
-
# fields = (*NamedModelMeta.fields, "volume_count")
|
|
47
46
|
|
|
48
47
|
|
|
49
48
|
class VolumeSerializer(GroupModelSerializer):
|
|
@@ -53,4 +52,3 @@ class VolumeSerializer(GroupModelSerializer):
|
|
|
53
52
|
"""Configure model."""
|
|
54
53
|
|
|
55
54
|
model = Volume
|
|
56
|
-
# fields = (*NamedModelMeta.fields, "issue_count")
|
|
@@ -5,7 +5,7 @@ from codex.models import (
|
|
|
5
5
|
Country,
|
|
6
6
|
Language,
|
|
7
7
|
)
|
|
8
|
-
from codex.serializers.fields import CountryField, LanguageField
|
|
8
|
+
from codex.serializers.fields.browser import CountryField, LanguageField
|
|
9
9
|
from codex.serializers.models.named import NamedModelSerializer
|
|
10
10
|
|
|
11
11
|
LOG = get_logger(__name__)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
OPDS Authentication 1.0 Serializer.
|
|
2
3
|
|
|
3
4
|
https://drafts.opds.io/schema/authentication.schema.json
|
|
4
5
|
"""
|
|
5
6
|
|
|
6
|
-
from rest_framework.
|
|
7
|
+
from rest_framework.fields import CharField
|
|
8
|
+
from rest_framework.serializers import IntegerField, Serializer
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
class OPDSAuth1LinksSerializer(Serializer):
|
codex/serializers/opds/urls.py
CHANGED
codex/serializers/opds/v1.py
CHANGED
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
from zoneinfo import ZoneInfo
|
|
4
4
|
|
|
5
|
-
from rest_framework.
|
|
5
|
+
from rest_framework.fields import (
|
|
6
6
|
BooleanField,
|
|
7
7
|
CharField,
|
|
8
8
|
DateField,
|
|
9
9
|
DateTimeField,
|
|
10
10
|
DictField,
|
|
11
11
|
IntegerField,
|
|
12
|
-
Serializer,
|
|
13
12
|
)
|
|
13
|
+
from rest_framework.serializers import Serializer
|
|
14
14
|
|
|
15
|
+
from codex.serializers.fields.browser import TopGroupField
|
|
15
16
|
from codex.serializers.models.pycountry import LanguageSerializer
|
|
16
17
|
|
|
17
18
|
UTC_TZ = ZoneInfo("UTC")
|
|
@@ -25,7 +26,7 @@ class OPDS1TemplateLinkSerializer(Serializer):
|
|
|
25
26
|
mime_type = CharField(read_only=True)
|
|
26
27
|
title = CharField(read_only=True, required=False)
|
|
27
28
|
length = IntegerField(read_only=True, required=False)
|
|
28
|
-
facet_group =
|
|
29
|
+
facet_group = TopGroupField(read_only=True, required=False)
|
|
29
30
|
facet_active = BooleanField(read_only=True, required=False)
|
|
30
31
|
thr_count = IntegerField(read_only=True, required=False)
|
|
31
32
|
pse_count = IntegerField(read_only=True, required=False)
|
|
@@ -13,16 +13,12 @@ from rest_framework.serializers import Serializer
|
|
|
13
13
|
class OPSD2AuthenticateSerializer(Serializer):
|
|
14
14
|
"""Minimal Link Serializer for Authenticate."""
|
|
15
15
|
|
|
16
|
-
href = CharField(
|
|
17
|
-
|
|
18
|
-
)
|
|
19
|
-
rel = SerializerMethodField(
|
|
20
|
-
read_only=True,
|
|
21
|
-
)
|
|
16
|
+
href = CharField(read_only=True)
|
|
17
|
+
rel = SerializerMethodField(read_only=True)
|
|
22
18
|
type = CharField(read_only=True, required=False)
|
|
23
19
|
|
|
24
20
|
def get_rel(self, obj) -> str | None:
|
|
25
|
-
"""Allow for
|
|
21
|
+
"""Allow for SanitizedCharField or CharListField types."""
|
|
26
22
|
rel = obj.get("rel")
|
|
27
23
|
if not isinstance(rel, list | str):
|
|
28
24
|
reason = "OPDS2LinkSerializer.rel is not a list or a string."
|
|
@@ -31,24 +27,26 @@ class OPSD2AuthenticateSerializer(Serializer):
|
|
|
31
27
|
|
|
32
28
|
|
|
33
29
|
class OPDS2LinkPropertiesSerializer(Serializer):
|
|
34
|
-
"""
|
|
30
|
+
"""
|
|
31
|
+
Link Properties.
|
|
35
32
|
|
|
36
33
|
https://drafts.opds.io/schema/properties.schema.json
|
|
37
34
|
"""
|
|
38
35
|
|
|
39
36
|
number_of_items = IntegerField(read_only=True, required=False)
|
|
40
|
-
# price = OPDS2PriceSerializer(read_only=True, required=False)
|
|
41
|
-
# indirect_aquisition = OPDS2AcquisitionObjectSerializer(
|
|
42
|
-
# read_only=True, many=True, required=False
|
|
43
|
-
# )
|
|
44
|
-
# holds = OPDS2HoldsSerializer(read_only=True, required=False)
|
|
45
|
-
# copies = OPDS2CopiesSerializer(read_only=True, required=False)
|
|
46
|
-
# availability = OPDS2AvailabilitySerializer(read_only=True, required=False)
|
|
37
|
+
# price = OPDS2PriceSerializer(read_only=True, required=False) unused
|
|
38
|
+
# indirect_aquisition = OPDS2AcquisitionObjectSerializer( unused
|
|
39
|
+
# read_only=True, many=True, required=False unused
|
|
40
|
+
# ) unused
|
|
41
|
+
# holds = OPDS2HoldsSerializer(read_only=True, required=False) unused
|
|
42
|
+
# copies = OPDS2CopiesSerializer(read_only=True, required=False) unused
|
|
43
|
+
# availability = OPDS2AvailabilitySerializer(read_only=True, required=False) unused
|
|
47
44
|
authenticate = OPSD2AuthenticateSerializer(required=False)
|
|
48
45
|
|
|
49
46
|
|
|
50
47
|
class OPDS2LinkSerializer(OPSD2AuthenticateSerializer):
|
|
51
|
-
"""
|
|
48
|
+
"""
|
|
49
|
+
Link.
|
|
52
50
|
|
|
53
51
|
https://readium.org/webpub-manifest/schema/link.schema.json
|
|
54
52
|
"""
|
|
@@ -59,11 +57,15 @@ class OPDS2LinkSerializer(OPSD2AuthenticateSerializer):
|
|
|
59
57
|
# Uncommon
|
|
60
58
|
height = IntegerField(read_only=True, required=False)
|
|
61
59
|
width = IntegerField(read_only=True, required=False)
|
|
62
|
-
# bitrate = IntegerField(read_only=True, required=False)
|
|
63
|
-
# duration = IntegerField(read_only=True, required=False)
|
|
64
|
-
# language = CharField(many=True, read_only=True, required=False)
|
|
65
|
-
alternate = ListField(
|
|
66
|
-
|
|
60
|
+
# bitrate = IntegerField(read_only=True, required=False) unused
|
|
61
|
+
# duration = IntegerField(read_only=True, required=False) unused
|
|
62
|
+
# language = CharField(many=True, read_only=True, required=False) unused
|
|
63
|
+
alternate = ListField(
|
|
64
|
+
child=CharField(read_only=True), read_only=True, required=False
|
|
65
|
+
)
|
|
66
|
+
children = ListField(
|
|
67
|
+
child=CharField(read_only=True), read_only=True, required=False
|
|
68
|
+
)
|
|
67
69
|
properties = OPDS2LinkPropertiesSerializer(read_only=True, required=False)
|
|
68
70
|
|
|
69
71
|
|
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
"""OPDS 2.0 Metadata Serializer."""
|
|
2
2
|
|
|
3
|
-
from rest_framework.fields import
|
|
4
|
-
CharField,
|
|
5
|
-
DateTimeField,
|
|
6
|
-
)
|
|
3
|
+
from rest_framework.fields import CharField, DateTimeField
|
|
7
4
|
from rest_framework.serializers import Serializer
|
|
8
5
|
|
|
9
6
|
|
|
10
7
|
class OPDS2MetadataSerializer(Serializer):
|
|
11
|
-
"""
|
|
8
|
+
"""
|
|
9
|
+
Metadata.
|
|
12
10
|
|
|
13
11
|
https://drafts.opds.io/schema/feed-metadata.schema.json
|
|
14
12
|
"""
|
|
15
13
|
|
|
16
14
|
identifier = CharField(read_only=True, required=False)
|
|
17
|
-
title = CharField(
|
|
18
|
-
read_only=True,
|
|
19
|
-
)
|
|
15
|
+
title = CharField(read_only=True)
|
|
20
16
|
subtitle = CharField(read_only=True, required=False)
|
|
21
17
|
modified = DateTimeField(read_only=True, required=False)
|
|
22
18
|
description = CharField(read_only=True, required=False)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
OPDS v2 Progression Serializer.
|
|
2
3
|
|
|
3
4
|
https://github.com/opds-community/drafts/discussions/67
|
|
4
5
|
"""
|
|
@@ -25,7 +26,7 @@ class OPDS2ProgressionDeviceSerializer(Serializer):
|
|
|
25
26
|
class OPDS2ProgressionLocationsSerializer(Serializer):
|
|
26
27
|
"""Progression Location Element."""
|
|
27
28
|
|
|
28
|
-
fragments = ListField(child=CharField(), read_only=True)
|
|
29
|
+
fragments = ListField(child=CharField(read_only=True), read_only=True)
|
|
29
30
|
position = IntegerField(read_only=True)
|
|
30
31
|
progression = DecimalField(
|
|
31
32
|
max_digits=7,
|
|
@@ -53,7 +54,8 @@ class OPDS2ProgressionLocatorSerializer(Serializer):
|
|
|
53
54
|
|
|
54
55
|
|
|
55
56
|
class OPDS2ProgressionSerializer(Serializer):
|
|
56
|
-
"""
|
|
57
|
+
"""
|
|
58
|
+
Progression.
|
|
57
59
|
|
|
58
60
|
https://github.com/opds-community/drafts/discussions/67#discussioncomment-6414507
|
|
59
61
|
"""
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
"""OPDS 2 Publication Serializers."""
|
|
2
2
|
|
|
3
|
-
from rest_framework.fields import
|
|
4
|
-
CharField,
|
|
5
|
-
DateField,
|
|
6
|
-
IntegerField,
|
|
7
|
-
ListField,
|
|
8
|
-
)
|
|
3
|
+
from rest_framework.fields import CharField, DateField, IntegerField, ListField
|
|
9
4
|
from rest_framework.serializers import Serializer
|
|
10
5
|
|
|
11
6
|
from codex.serializers.opds.v2.facet import OPDS2FacetSerializer
|
|
@@ -22,22 +17,24 @@ class OPDS2FeedMetadataSerializer(OPDS2MetadataSerializer):
|
|
|
22
17
|
|
|
23
18
|
|
|
24
19
|
class OPDS2ContributorObjectSerializer(Serializer):
|
|
25
|
-
"""
|
|
20
|
+
"""
|
|
21
|
+
Contributor Object.
|
|
26
22
|
|
|
27
23
|
https://readium.org/webpub-manifest/schema/contributor-object.schema.json
|
|
28
24
|
"""
|
|
29
25
|
|
|
30
26
|
name = CharField(read_only=True)
|
|
31
|
-
# identifier= CharField(read_only=True, required=False)
|
|
32
|
-
# sort_as = CharField(read_only=True, required=False)
|
|
27
|
+
# identifier= CharField(read_only=True, required=False) unused
|
|
28
|
+
# sort_as = CharField(read_only=True, required=False) unused
|
|
33
29
|
role = CharField(read_only=True, source="role_name")
|
|
34
|
-
# role = CharListField(read_only=True)
|
|
35
|
-
# position = IntegerField(read_only=True, required=False)
|
|
36
|
-
# links = LinkListField(read_only=True)
|
|
30
|
+
# role = CharListField(read_only=True) unused
|
|
31
|
+
# position = IntegerField(read_only=True, required=False) unused
|
|
32
|
+
# links = LinkListField(read_only=True) unused
|
|
37
33
|
|
|
38
34
|
|
|
39
35
|
class OPDS2PublicationMetadataSerializer(OPDS2MetadataSerializer):
|
|
40
|
-
"""
|
|
36
|
+
"""
|
|
37
|
+
Metadata for publications.
|
|
41
38
|
|
|
42
39
|
https://readium.org/webpub-manifest/schema/metadata.schema.json
|
|
43
40
|
"""
|
|
@@ -49,17 +46,17 @@ class OPDS2PublicationMetadataSerializer(OPDS2MetadataSerializer):
|
|
|
49
46
|
language = CharField(read_only=True, required=False)
|
|
50
47
|
published = DateField(read_only=True, required=False)
|
|
51
48
|
number_of_pages = IntegerField(read_only=True, required=False)
|
|
52
|
-
# reading_progression = ChoiceField()
|
|
49
|
+
# reading_progression = ChoiceField() unused
|
|
53
50
|
|
|
54
51
|
#####################
|
|
55
52
|
# Extended metadata #
|
|
56
53
|
#####################
|
|
57
|
-
subject = ListField(child=CharField(), read_only=True, required=False)
|
|
54
|
+
subject = ListField(child=CharField(read_only=True), read_only=True, required=False)
|
|
58
55
|
author = OPDS2ContributorObjectSerializer(many=True, required=False)
|
|
59
|
-
# translator = OPDS2ContributorObjectSerializer(many=True, required=False)
|
|
56
|
+
# translator = OPDS2ContributorObjectSerializer(many=True, required=False) unused
|
|
60
57
|
editor = OPDS2ContributorObjectSerializer(many=True, required=False)
|
|
61
58
|
artist = OPDS2ContributorObjectSerializer(many=True, required=False)
|
|
62
|
-
# illustrator = OPDS2ContributorObjectSerializer(many=True, required=False)
|
|
59
|
+
# illustrator = OPDS2ContributorObjectSerializer(many=True, required=False) unused
|
|
63
60
|
letterer = OPDS2ContributorObjectSerializer(many=True, required=False)
|
|
64
61
|
peniciller = OPDS2ContributorObjectSerializer(many=True, required=False)
|
|
65
62
|
colorist = OPDS2ContributorObjectSerializer(many=True, required=False)
|
|
@@ -68,7 +65,8 @@ class OPDS2PublicationMetadataSerializer(OPDS2MetadataSerializer):
|
|
|
68
65
|
|
|
69
66
|
|
|
70
67
|
class OPDS2PublicationSerializer(OPDS2FacetSerializer):
|
|
71
|
-
"""
|
|
68
|
+
"""
|
|
69
|
+
Publication.
|
|
72
70
|
|
|
73
71
|
https://drafts.opds.io/schema/publication.schema.json
|
|
74
72
|
"""
|