codex 1.7.3a2__py3-none-any.whl → 1.7.4__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 +12 -12
- codex/choices_to_json.py +8 -8
- codex/db.py +2 -2
- codex/exceptions.py +6 -7
- codex/librarian/bookmark/bookmarkd.py +8 -4
- codex/librarian/bookmark/update.py +82 -48
- codex/librarian/covers/create.py +10 -8
- codex/librarian/covers/path.py +6 -5
- codex/librarian/covers/purge.py +2 -2
- 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 +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 +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 +2 -2
- codex/librarian/janitor/vacuum.py +1 -1
- codex/librarian/librariand.py +3 -2
- 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 +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/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 +7 -5
- 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 +15 -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/static_root/assets/{VCheckbox-FaT6MGfu.f6732060f734.js → VCheckbox-CtTi6T7d.87331fa7e77f.js} +1 -1
- codex/static_root/assets/VCheckbox-CtTi6T7d.87331fa7e77f.js.br +0 -0
- codex/static_root/assets/VCheckbox-CtTi6T7d.87331fa7e77f.js.gz +0 -0
- codex/static_root/assets/{VCheckbox-FaT6MGfu.js → VCheckbox-CtTi6T7d.js} +1 -1
- codex/static_root/assets/VCheckbox-CtTi6T7d.js.br +0 -0
- codex/static_root/assets/VCheckbox-CtTi6T7d.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-CZ_P-qUM.847452d574cf.js → VCheckboxBtn-DQafuWTH.dada5e0634ef.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-DQafuWTH.dada5e0634ef.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DQafuWTH.dada5e0634ef.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-CZ_P-qUM.js → VCheckboxBtn-DQafuWTH.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-DQafuWTH.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-DQafuWTH.js.gz +0 -0
- codex/static_root/assets/{VCombobox-C8QLNlSl.6f431e19a453.js → VCombobox-C6TX3Dhp.e619423a6463.js} +1 -1
- codex/static_root/assets/VCombobox-C6TX3Dhp.e619423a6463.js.br +0 -0
- codex/static_root/assets/VCombobox-C6TX3Dhp.e619423a6463.js.gz +0 -0
- codex/static_root/assets/{VCombobox-C8QLNlSl.js → VCombobox-C6TX3Dhp.js} +1 -1
- codex/static_root/assets/VCombobox-C6TX3Dhp.js.br +0 -0
- codex/static_root/assets/VCombobox-C6TX3Dhp.js.gz +0 -0
- codex/static_root/assets/{VDialog-RVLeW7je.c0c7eef71eec.js → VDialog-CknWq2kd.b2d301ec6ac5.js} +1 -1
- codex/static_root/assets/VDialog-CknWq2kd.b2d301ec6ac5.js.br +0 -0
- codex/static_root/assets/VDialog-CknWq2kd.b2d301ec6ac5.js.gz +0 -0
- codex/static_root/assets/{VDialog-RVLeW7je.js → VDialog-CknWq2kd.js} +1 -1
- codex/static_root/assets/VDialog-CknWq2kd.js.br +0 -0
- codex/static_root/assets/VDialog-CknWq2kd.js.gz +0 -0
- codex/static_root/assets/{VDivider-D1Ot4vR2.9dbee744fb3c.js → VDivider-F4DUgr74.62bc92cab97d.js} +1 -1
- codex/static_root/assets/VDivider-F4DUgr74.62bc92cab97d.js.br +0 -0
- codex/static_root/assets/VDivider-F4DUgr74.62bc92cab97d.js.gz +0 -0
- codex/static_root/assets/{VDivider-D1Ot4vR2.js → VDivider-F4DUgr74.js} +1 -1
- codex/static_root/assets/VDivider-F4DUgr74.js.br +0 -0
- codex/static_root/assets/VDivider-F4DUgr74.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-DQilGHZk.43f06d0a45e0.js → VExpansionPanels-CprYUTGT.39b8a50cde43.js} +1 -1
- codex/static_root/assets/VExpansionPanels-CprYUTGT.39b8a50cde43.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-CprYUTGT.39b8a50cde43.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanels-DQilGHZk.js → VExpansionPanels-CprYUTGT.js} +1 -1
- codex/static_root/assets/VExpansionPanels-CprYUTGT.js.br +0 -0
- codex/static_root/assets/VExpansionPanels-CprYUTGT.js.gz +0 -0
- codex/static_root/assets/{VForm-DNmY-qFJ.81f3a5ff7ec3.js → VForm-DnWAUsrl.4ab0786d658e.js} +1 -1
- codex/static_root/assets/VForm-DnWAUsrl.4ab0786d658e.js.br +0 -0
- codex/static_root/assets/VForm-DnWAUsrl.4ab0786d658e.js.gz +0 -0
- codex/static_root/assets/{VForm-DNmY-qFJ.js → VForm-DnWAUsrl.js} +1 -1
- codex/static_root/assets/VForm-DnWAUsrl.js.br +0 -0
- codex/static_root/assets/VForm-DnWAUsrl.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DoayJpcS.fe5e0e74ffee.js → VRadioGroup-D71Rszum.befc87b0c476.js} +1 -1
- codex/static_root/assets/VRadioGroup-D71Rszum.befc87b0c476.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D71Rszum.befc87b0c476.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DoayJpcS.js → VRadioGroup-D71Rszum.js} +1 -1
- codex/static_root/assets/VRadioGroup-D71Rszum.js.br +0 -0
- codex/static_root/assets/VRadioGroup-D71Rszum.js.gz +0 -0
- codex/static_root/assets/{VSelect-BSLmHX_P.9ab865ec0fad.js → VSelect-CbPDrHNj.4809fbbf00f0.js} +1 -1
- codex/static_root/assets/VSelect-CbPDrHNj.4809fbbf00f0.js.br +0 -0
- codex/static_root/assets/VSelect-CbPDrHNj.4809fbbf00f0.js.gz +0 -0
- codex/static_root/assets/{VSelect-BSLmHX_P.js → VSelect-CbPDrHNj.js} +1 -1
- codex/static_root/assets/VSelect-CbPDrHNj.js.br +0 -0
- codex/static_root/assets/VSelect-CbPDrHNj.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-TaKCeZgb.ad6c96efe57c.js → VSelectionControl-It389cbo.ac75aee480a0.js} +1 -1
- codex/static_root/assets/VSelectionControl-It389cbo.ac75aee480a0.js.br +0 -0
- codex/static_root/assets/VSelectionControl-It389cbo.ac75aee480a0.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-TaKCeZgb.js → VSelectionControl-It389cbo.js} +1 -1
- codex/static_root/assets/VSelectionControl-It389cbo.js.br +0 -0
- codex/static_root/assets/VSelectionControl-It389cbo.js.gz +0 -0
- codex/static_root/assets/{VTable-BfcOiEpa.77ef3973bb54.js → VTable-D9e3lKk6.7cd0760008c7.js} +1 -1
- codex/static_root/assets/VTable-D9e3lKk6.7cd0760008c7.js.br +0 -0
- codex/static_root/assets/VTable-D9e3lKk6.7cd0760008c7.js.gz +0 -0
- codex/static_root/assets/{VTable-BfcOiEpa.js → VTable-D9e3lKk6.js} +1 -1
- codex/static_root/assets/VTable-D9e3lKk6.js.br +0 -0
- codex/static_root/assets/VTable-D9e3lKk6.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-D8lWcbQY.e4c75ad78718.js → VWindowItem-B4VZ37cq.e45c5018cc73.js} +1 -1
- codex/static_root/assets/VWindowItem-B4VZ37cq.e45c5018cc73.js.br +0 -0
- codex/static_root/assets/VWindowItem-B4VZ37cq.e45c5018cc73.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-D8lWcbQY.js → VWindowItem-B4VZ37cq.js} +1 -1
- codex/static_root/assets/VWindowItem-B4VZ37cq.js.br +0 -0
- codex/static_root/assets/VWindowItem-B4VZ37cq.js.gz +0 -0
- codex/static_root/assets/{admin-CBLHOrM9.8c3c2268bc96.js → admin-Bkd8zuSF.2a29386f3488.js} +1 -1
- codex/static_root/assets/admin-Bkd8zuSF.2a29386f3488.js.br +0 -0
- codex/static_root/assets/admin-Bkd8zuSF.2a29386f3488.js.gz +0 -0
- codex/static_root/assets/{admin-CBLHOrM9.js → admin-Bkd8zuSF.js} +1 -1
- codex/static_root/assets/admin-Bkd8zuSF.js.br +0 -0
- codex/static_root/assets/admin-Bkd8zuSF.js.gz +0 -0
- codex/static_root/assets/{admin-80eqCqtz.d6deb9edb8cb.js → admin-CFTKGwmx.18915c5df4d3.js} +1 -1
- codex/static_root/assets/admin-CFTKGwmx.18915c5df4d3.js.br +0 -0
- codex/static_root/assets/admin-CFTKGwmx.18915c5df4d3.js.gz +0 -0
- codex/static_root/assets/{admin-80eqCqtz.js → admin-CFTKGwmx.js} +1 -1
- codex/static_root/assets/admin-CFTKGwmx.js.br +0 -0
- codex/static_root/assets/admin-CFTKGwmx.js.gz +0 -0
- codex/static_root/assets/{admin-menu-_aAGknKO.0c08c9bd2e7d.js → admin-menu-CxZqtPES.7b3a06ce4b92.js} +1 -1
- codex/static_root/assets/admin-menu-CxZqtPES.7b3a06ce4b92.js.br +0 -0
- codex/static_root/assets/admin-menu-CxZqtPES.7b3a06ce4b92.js.gz +0 -0
- codex/static_root/assets/{admin-menu-_aAGknKO.js → admin-menu-CxZqtPES.js} +1 -1
- codex/static_root/assets/admin-menu-CxZqtPES.js.br +0 -0
- codex/static_root/assets/admin-menu-CxZqtPES.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-BqRFyhjf.2bb1194b21e2.js → admin-settings-button-progress-D2TfW_5T.8a9d411ee79d.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-D2TfW_5T.8a9d411ee79d.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-D2TfW_5T.8a9d411ee79d.js.gz +0 -0
- codex/static_root/assets/{admin-settings-button-progress-BqRFyhjf.js → admin-settings-button-progress-D2TfW_5T.js} +1 -1
- codex/static_root/assets/admin-settings-button-progress-D2TfW_5T.js.br +0 -0
- codex/static_root/assets/admin-settings-button-progress-D2TfW_5T.js.gz +0 -0
- codex/static_root/assets/browser-Br2DgAdi.433cca495d61.js +1 -0
- codex/static_root/assets/browser-Br2DgAdi.433cca495d61.js.br +0 -0
- codex/static_root/assets/browser-Br2DgAdi.433cca495d61.js.gz +0 -0
- codex/static_root/assets/browser-Br2DgAdi.js +1 -0
- codex/static_root/assets/browser-Br2DgAdi.js.br +0 -0
- codex/static_root/assets/browser-Br2DgAdi.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-CSylx5Qb.319466c891c9.js} +1 -1
- codex/static_root/assets/change-password-dialog-CSylx5Qb.319466c891c9.js.br +0 -0
- codex/static_root/assets/change-password-dialog-CSylx5Qb.319466c891c9.js.gz +0 -0
- codex/static_root/assets/{change-password-dialog-1ZVP_Q2w.js → change-password-dialog-CSylx5Qb.js} +1 -1
- codex/static_root/assets/change-password-dialog-CSylx5Qb.js.br +0 -0
- codex/static_root/assets/change-password-dialog-CSylx5Qb.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-DqCey9Iq.e315d7f8f752.js → confirm-dialog-Bx2R2vgR.d42b6449c495.js} +1 -1
- codex/static_root/assets/confirm-dialog-Bx2R2vgR.d42b6449c495.js.br +0 -0
- codex/static_root/assets/confirm-dialog-Bx2R2vgR.d42b6449c495.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-DqCey9Iq.js → confirm-dialog-Bx2R2vgR.js} +1 -1
- codex/static_root/assets/confirm-dialog-Bx2R2vgR.js.br +0 -0
- codex/static_root/assets/confirm-dialog-Bx2R2vgR.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CBA8bYeO.17a31f189d66.js → datetime-column-sOrWMDcU.9ad225af18db.js} +1 -1
- codex/static_root/assets/datetime-column-sOrWMDcU.9ad225af18db.js.br +2 -0
- codex/static_root/assets/datetime-column-sOrWMDcU.9ad225af18db.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CBA8bYeO.js → datetime-column-sOrWMDcU.js} +1 -1
- codex/static_root/assets/datetime-column-sOrWMDcU.js.br +2 -0
- codex/static_root/assets/datetime-column-sOrWMDcU.js.gz +0 -0
- codex/static_root/assets/{filter-mnO3lLPo.659442401b16.js → filter-SgjvoAvL.094069d6978d.js} +1 -1
- codex/static_root/assets/filter-SgjvoAvL.094069d6978d.js.br +0 -0
- codex/static_root/assets/filter-SgjvoAvL.094069d6978d.js.gz +0 -0
- codex/static_root/assets/{filter-mnO3lLPo.js → filter-SgjvoAvL.js} +1 -1
- codex/static_root/assets/filter-SgjvoAvL.js.br +0 -0
- codex/static_root/assets/filter-SgjvoAvL.js.gz +0 -0
- codex/static_root/assets/{flag-tab-Bc677pNb.1b8a2f7c0dc3.js → flag-tab-B_0tGWPg.e46d1782b327.js} +1 -1
- codex/static_root/assets/flag-tab-B_0tGWPg.e46d1782b327.js.br +0 -0
- codex/static_root/assets/flag-tab-B_0tGWPg.e46d1782b327.js.gz +0 -0
- codex/static_root/assets/{flag-tab-Bc677pNb.js → flag-tab-B_0tGWPg.js} +1 -1
- codex/static_root/assets/flag-tab-B_0tGWPg.js.br +0 -0
- codex/static_root/assets/flag-tab-B_0tGWPg.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-DqbPK1-k.bb9d6863ac16.js} +1 -1
- codex/static_root/assets/forwardRefs-DqbPK1-k.bb9d6863ac16.js.br +0 -0
- codex/static_root/assets/forwardRefs-DqbPK1-k.bb9d6863ac16.js.gz +0 -0
- codex/static_root/assets/{forwardRefs-DPRKg5wq.js → forwardRefs-DqbPK1-k.js} +1 -1
- codex/static_root/assets/forwardRefs-DqbPK1-k.js.br +0 -0
- codex/static_root/assets/forwardRefs-DqbPK1-k.js.gz +0 -0
- codex/static_root/assets/{group-tab-BVlBrMwo.1127b51be6e7.js → group-tab-DXxQUa6C.f1f12f39b167.js} +1 -1
- codex/static_root/assets/group-tab-DXxQUa6C.f1f12f39b167.js.br +0 -0
- codex/static_root/assets/group-tab-DXxQUa6C.f1f12f39b167.js.gz +0 -0
- codex/static_root/assets/{group-tab-BVlBrMwo.js → group-tab-DXxQUa6C.js} +1 -1
- codex/static_root/assets/group-tab-DXxQUa6C.js.br +0 -0
- codex/static_root/assets/group-tab-DXxQUa6C.js.gz +0 -0
- codex/static_root/assets/{http-error-C9-_aEBF.d29b164e80de.js → http-error-BVMwwrFo.a7be6a26c9eb.js} +1 -1
- codex/static_root/assets/http-error-BVMwwrFo.a7be6a26c9eb.js.br +0 -0
- codex/static_root/assets/http-error-BVMwwrFo.a7be6a26c9eb.js.gz +0 -0
- codex/static_root/assets/{http-error-C9-_aEBF.js → http-error-BVMwwrFo.js} +1 -1
- codex/static_root/assets/http-error-BVMwwrFo.js.br +0 -0
- codex/static_root/assets/http-error-BVMwwrFo.js.gz +0 -0
- codex/static_root/assets/{index-9nBCksDQ.4561d2608773.js → index-DK0lSHDP.86f18c078fa9.js} +1 -1
- codex/static_root/assets/index-DK0lSHDP.86f18c078fa9.js.br +0 -0
- codex/static_root/assets/index-DK0lSHDP.86f18c078fa9.js.gz +0 -0
- codex/static_root/assets/{index-9nBCksDQ.js → index-DK0lSHDP.js} +1 -1
- codex/static_root/assets/index-DK0lSHDP.js.br +0 -0
- codex/static_root/assets/index-DK0lSHDP.js.gz +0 -0
- codex/static_root/assets/{library-tab-BMe3dKzy.22b6e123ecfb.js → library-tab-NhXuvZ4F.1e8ac3b7c168.js} +1 -1
- codex/static_root/assets/library-tab-NhXuvZ4F.1e8ac3b7c168.js.br +0 -0
- codex/static_root/assets/library-tab-NhXuvZ4F.1e8ac3b7c168.js.gz +0 -0
- codex/static_root/assets/{library-tab-BMe3dKzy.js → library-tab-NhXuvZ4F.js} +1 -1
- codex/static_root/assets/library-tab-NhXuvZ4F.js.br +0 -0
- codex/static_root/assets/library-tab-NhXuvZ4F.js.gz +0 -0
- codex/static_root/assets/{main-BbNUiWEb.565b616eb122.js → main-CYgubU7H.50aa39cf9565.js} +3 -3
- codex/static_root/assets/main-CYgubU7H.50aa39cf9565.js.br +0 -0
- codex/static_root/assets/main-CYgubU7H.50aa39cf9565.js.gz +0 -0
- codex/static_root/assets/{main-BbNUiWEb.js → main-CYgubU7H.js} +3 -3
- codex/static_root/assets/main-CYgubU7H.js.br +0 -0
- codex/static_root/assets/main-CYgubU7H.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.a6269ab85085.js +1 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.a6269ab85085.js.br +0 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.a6269ab85085.js.gz +0 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.js +1 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.js.br +0 -0
- codex/static_root/assets/pager-full-pdf---TZiAf5.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-Dx5JwWG-.ba0e8b645dfa.js → pagination-toolbar-CeWXU_qA.abe0805da1cc.js} +1 -1
- codex/static_root/assets/pagination-toolbar-CeWXU_qA.abe0805da1cc.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-CeWXU_qA.abe0805da1cc.js.gz +0 -0
- codex/static_root/assets/{pagination-toolbar-Dx5JwWG-.js → pagination-toolbar-CeWXU_qA.js} +1 -1
- codex/static_root/assets/pagination-toolbar-CeWXU_qA.js.br +0 -0
- codex/static_root/assets/pagination-toolbar-CeWXU_qA.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-6ZE_HmLT.10d1e16abc78.js → pdf-doc-Dws_otkd.d215eca27da5.js} +1 -1
- codex/static_root/assets/pdf-doc-Dws_otkd.d215eca27da5.js.br +0 -0
- codex/static_root/assets/pdf-doc-Dws_otkd.d215eca27da5.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-6ZE_HmLT.js → pdf-doc-Dws_otkd.js} +1 -1
- codex/static_root/assets/pdf-doc-Dws_otkd.js.br +0 -0
- codex/static_root/assets/pdf-doc-Dws_otkd.js.gz +0 -0
- codex/static_root/assets/{reader-DdPKDuh5.0c55cef1e98b.js → reader-BCxYgZHF.dde3c4ac39a5.js} +2 -2
- codex/static_root/assets/reader-BCxYgZHF.dde3c4ac39a5.js.br +0 -0
- codex/static_root/assets/reader-BCxYgZHF.dde3c4ac39a5.js.gz +0 -0
- codex/static_root/assets/{reader-DdPKDuh5.js → reader-BCxYgZHF.js} +2 -2
- codex/static_root/assets/reader-BCxYgZHF.js.br +0 -0
- codex/static_root/assets/reader-BCxYgZHF.js.gz +0 -0
- codex/static_root/assets/{relation-chips-C96hi5jm.js → relation-chips-DNRRCvrw.b1bc75fb9349.js} +1 -1
- codex/static_root/assets/relation-chips-DNRRCvrw.b1bc75fb9349.js.br +0 -0
- codex/static_root/assets/relation-chips-DNRRCvrw.b1bc75fb9349.js.gz +0 -0
- codex/static_root/assets/{relation-chips-C96hi5jm.9f07c9eb533a.js → relation-chips-DNRRCvrw.js} +1 -1
- codex/static_root/assets/relation-chips-DNRRCvrw.js.br +0 -0
- codex/static_root/assets/relation-chips-DNRRCvrw.js.gz +0 -0
- codex/static_root/assets/{settings-drawer-CqbT1rid.js → settings-drawer-BuB29L5p.fe2eeea0058f.js} +2 -2
- codex/static_root/assets/settings-drawer-BuB29L5p.fe2eeea0058f.js.br +0 -0
- codex/static_root/assets/settings-drawer-BuB29L5p.fe2eeea0058f.js.gz +0 -0
- codex/static_root/assets/{settings-drawer-CqbT1rid.5639fa00b301.js → settings-drawer-BuB29L5p.js} +2 -2
- codex/static_root/assets/settings-drawer-BuB29L5p.js.br +0 -0
- codex/static_root/assets/settings-drawer-BuB29L5p.js.gz +0 -0
- codex/static_root/assets/{stats-tab-CkT2ZGUQ.b704fa46dc88.js → stats-tab-D0zymxU6.d5267113b51e.js} +1 -1
- codex/static_root/assets/stats-tab-D0zymxU6.d5267113b51e.js.br +0 -0
- codex/static_root/assets/stats-tab-D0zymxU6.d5267113b51e.js.gz +0 -0
- codex/static_root/assets/{stats-tab-CkT2ZGUQ.js → stats-tab-D0zymxU6.js} +1 -1
- codex/static_root/assets/stats-tab-D0zymxU6.js.br +0 -0
- codex/static_root/assets/stats-tab-D0zymxU6.js.gz +0 -0
- codex/static_root/assets/{task-tab-a-DcU3Tj.8c2f7bf3c4c9.js → task-tab-CI9RLdMS.120f395dc9c6.js} +1 -1
- codex/static_root/assets/task-tab-CI9RLdMS.120f395dc9c6.js.br +0 -0
- codex/static_root/assets/task-tab-CI9RLdMS.120f395dc9c6.js.gz +0 -0
- codex/static_root/assets/{task-tab-a-DcU3Tj.js → task-tab-CI9RLdMS.js} +1 -1
- codex/static_root/assets/task-tab-CI9RLdMS.js.br +0 -0
- codex/static_root/assets/task-tab-CI9RLdMS.js.gz +0 -0
- codex/static_root/assets/{unauthorized-BOl5YpL3.f3c4b52718d5.js → unauthorized-BNwg_Xvu.a894b96156e0.js} +1 -1
- codex/static_root/assets/unauthorized-BNwg_Xvu.a894b96156e0.js.br +0 -0
- codex/static_root/assets/unauthorized-BNwg_Xvu.a894b96156e0.js.gz +0 -0
- codex/static_root/assets/{unauthorized-BOl5YpL3.js → unauthorized-BNwg_Xvu.js} +1 -1
- codex/static_root/assets/unauthorized-BNwg_Xvu.js.br +0 -0
- codex/static_root/assets/unauthorized-BNwg_Xvu.js.gz +0 -0
- codex/static_root/assets/{user-tab-BBDZvD8G.aa4263a68b22.js → user-tab-w9LgIMMi.4a89c7b37486.js} +1 -1
- codex/static_root/assets/user-tab-w9LgIMMi.4a89c7b37486.js.br +0 -0
- codex/static_root/assets/user-tab-w9LgIMMi.4a89c7b37486.js.gz +0 -0
- codex/static_root/assets/{user-tab-BBDZvD8G.js → user-tab-w9LgIMMi.js} +1 -1
- codex/static_root/assets/user-tab-w9LgIMMi.js.br +0 -0
- codex/static_root/assets/user-tab-w9LgIMMi.js.gz +0 -0
- codex/static_root/{manifest.225989a17f49.json → manifest.514e63b9f805.json} +253 -253
- codex/static_root/manifest.514e63b9f805.json.br +0 -0
- codex/static_root/manifest.514e63b9f805.json.gz +0 -0
- codex/static_root/manifest.json +253 -253
- 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/urls/root.py +4 -3
- codex/views/admin/api_key.py +1 -4
- 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 +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 +6 -7
- 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 +8 -5
- 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/util.py +3 -3
- 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/progression.py +8 -9
- codex/views/opds/v2/publications.py +10 -20
- codex/views/public.py +1 -1
- 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 +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.3a2.dist-info → codex-1.7.4.dist-info}/METADATA +3 -1
- {codex-1.7.3a2.dist-info → codex-1.7.4.dist-info}/RECORD +409 -401
- {codex-1.7.3a2.dist-info → codex-1.7.4.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.br +0 -0
- codex/static_root/assets/VForm-DNmY-qFJ.81f3a5ff7ec3.js.gz +0 -0
- 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.br +0 -0
- codex/static_root/assets/VSelect-BSLmHX_P.9ab865ec0fad.js.gz +0 -0
- 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.br +0 -0
- codex/static_root/assets/VWindowItem-D8lWcbQY.e4c75ad78718.js.gz +0 -0
- 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.br +0 -0
- codex/static_root/assets/admin-CBLHOrM9.8c3c2268bc96.js.gz +0 -0
- 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.br +0 -0
- codex/static_root/assets/group-tab-BVlBrMwo.1127b51be6e7.js.gz +0 -0
- 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.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.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.br +0 -0
- codex/static_root/assets/library-tab-BMe3dKzy.22b6e123ecfb.js.gz +0 -0
- 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.br +0 -0
- codex/static_root/assets/main-BbNUiWEb.565b616eb122.js.gz +0 -0
- 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.br +0 -0
- codex/static_root/assets/reader-DdPKDuh5.0c55cef1e98b.js.gz +0 -0
- 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.br +0 -0
- codex/static_root/assets/settings-drawer-CqbT1rid.5639fa00b301.js.gz +0 -0
- 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-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.br +0 -0
- codex/static_root/assets/task-tab-a-DcU3Tj.js.gz +0 -0
- 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.br +0 -0
- codex/static_root/assets/unauthorized-BOl5YpL3.js.gz +0 -0
- 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.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.4.dist-info}/LICENSE +0 -0
- {codex-1.7.3a2.dist-info → codex-1.7.4.dist-info}/entry_points.txt +0 -0
|
@@ -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:
|
codex/logger/logging.py
CHANGED
codex/memory.py
CHANGED
|
@@ -26,7 +26,7 @@ def get_cgroups1_mem_limit():
|
|
|
26
26
|
with Path(MEMORY_STAT_PATH).open("r") as mem_stat_file:
|
|
27
27
|
for line in mem_stat_file:
|
|
28
28
|
parts = line.split()
|
|
29
|
-
if not parts or len(parts) < 2: # noqa PLR2004
|
|
29
|
+
if not parts or len(parts) < 2: # noqa: PLR2004
|
|
30
30
|
continue
|
|
31
31
|
if "hierarchical_memory_limit" in parts[0]:
|
|
32
32
|
return int(parts[1])
|
|
@@ -34,7 +34,8 @@ def get_cgroups1_mem_limit():
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def get_mem_limit(divisor="b"):
|
|
37
|
-
"""
|
|
37
|
+
"""
|
|
38
|
+
Get the current memlimit.
|
|
38
39
|
|
|
39
40
|
If we're in a container set the limit too.
|
|
40
41
|
"""
|
codex/migrations/0001_init.py
CHANGED
|
@@ -632,8 +632,7 @@ class Migration(migrations.Migration):
|
|
|
632
632
|
default=None,
|
|
633
633
|
max_length=6,
|
|
634
634
|
null=True,
|
|
635
|
-
#
|
|
636
|
-
# validators=[codex.models.validate_fit_to_choice],
|
|
635
|
+
# Old code dependent validators removed in the future
|
|
637
636
|
),
|
|
638
637
|
),
|
|
639
638
|
("two_pages", models.BooleanField(default=None, null=True)),
|
|
@@ -151,8 +151,7 @@ class Migration(migrations.Migration):
|
|
|
151
151
|
field=models.CharField(
|
|
152
152
|
default="comic",
|
|
153
153
|
max_length=5,
|
|
154
|
-
#
|
|
155
|
-
# validators=[codex.models.validate_file_format_choice],
|
|
154
|
+
# codex dependent validators removed in the future
|
|
156
155
|
),
|
|
157
156
|
),
|
|
158
157
|
migrations.AddField(
|
|
@@ -28,8 +28,7 @@ class Migration(migrations.Migration):
|
|
|
28
28
|
blank=True,
|
|
29
29
|
default="",
|
|
30
30
|
max_length=6,
|
|
31
|
-
# removed in the future
|
|
32
|
-
# validators=[codex.models.validate_fit_to_choice],
|
|
31
|
+
# Code dependent validators removed in the future
|
|
33
32
|
),
|
|
34
33
|
),
|
|
35
34
|
migrations.AlterField(
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
"""Generated by Django 5.0.6 on 2024-07-02 21:01."""
|
|
2
2
|
|
|
3
|
-
from typing import ClassVar
|
|
4
|
-
|
|
5
3
|
from django.db import migrations, models
|
|
6
4
|
|
|
7
5
|
|
|
8
6
|
class Migration(migrations.Migration):
|
|
9
7
|
"""Migrate db."""
|
|
10
8
|
|
|
11
|
-
dependencies
|
|
12
|
-
("codex", "0027_import_order_and_covers"),
|
|
13
|
-
]
|
|
9
|
+
dependencies = [("codex", "0027_import_order_and_covers")]
|
|
14
10
|
|
|
15
11
|
operations = [
|
|
16
12
|
migrations.AlterField(
|
codex/models/base.py
CHANGED
|
@@ -27,9 +27,11 @@ class BaseModel(Model):
|
|
|
27
27
|
updated_at = DateTimeField(auto_now=True)
|
|
28
28
|
objects = GroupByManager()
|
|
29
29
|
|
|
30
|
-
class Meta(ModelBase): # type: ignore
|
|
30
|
+
class Meta(ModelBase): # type: ignore[reportIncompatibleVariableOverride]
|
|
31
31
|
"""Without this a real table is created and joined to."""
|
|
32
32
|
|
|
33
|
+
# Model.Meta is not inheritable.
|
|
34
|
+
|
|
33
35
|
abstract = True
|
|
34
36
|
get_latest_by = "updated_at"
|
|
35
37
|
|
codex/models/bookmark.py
CHANGED
|
@@ -23,18 +23,15 @@ def cascade_if_user_null(
|
|
|
23
23
|
sub_objs,
|
|
24
24
|
using, # noqa: ARG001
|
|
25
25
|
):
|
|
26
|
-
"""
|
|
26
|
+
"""
|
|
27
|
+
Cascade only if the user field is null.
|
|
27
28
|
|
|
28
29
|
Do this to keep deleting ephemeral session data from Bookmark table.
|
|
29
30
|
Adapted from:
|
|
30
31
|
https://github.com/django/django/blob/master/django/db/models/deletion.py#L23
|
|
31
32
|
"""
|
|
32
|
-
|
|
33
|
-
for sub_obj in sub_objs
|
|
34
|
-
# only cascade the ones with null user fields.
|
|
35
|
-
if sub_obj.user is None:
|
|
36
|
-
null_user_sub_objs.append(sub_obj)
|
|
37
|
-
|
|
33
|
+
# only cascade the ones with null user fields.
|
|
34
|
+
null_user_sub_objs = [sub_obj for sub_obj in sub_objs if sub_obj.user is None]
|
|
38
35
|
if null_user_sub_objs:
|
|
39
36
|
collector.collect(
|
|
40
37
|
null_user_sub_objs,
|
codex/models/comic.py
CHANGED
|
@@ -263,7 +263,7 @@ class Comic(WatchedPathBrowserGroup):
|
|
|
263
263
|
|
|
264
264
|
@classmethod
|
|
265
265
|
def get_title(
|
|
266
|
-
cls, obj, volume
|
|
266
|
+
cls, obj, volume: bool, name: bool, filename_fallback: bool, zero_pad=None
|
|
267
267
|
):
|
|
268
268
|
"""Create the comic title for display."""
|
|
269
269
|
names = []
|
|
@@ -293,7 +293,7 @@ class Comic(WatchedPathBrowserGroup):
|
|
|
293
293
|
|
|
294
294
|
def __str__(self):
|
|
295
295
|
"""Most common text representation for logging."""
|
|
296
|
-
return self.get_title(self, filename_fallback=True)
|
|
296
|
+
return self.get_title(self, volume=True, name=True, filename_fallback=True)
|
|
297
297
|
|
|
298
298
|
def issue(self) -> str:
|
|
299
299
|
"""Combine issue parts for search."""
|
codex/models/functions.py
CHANGED
|
@@ -14,7 +14,10 @@ class JsonGroupArray(Aggregate):
|
|
|
14
14
|
allow_distinct = True
|
|
15
15
|
function = "JSON_GROUP_ARRAY"
|
|
16
16
|
name = "JsonGroupArray"
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
def __init__(self, *args, **kwargs):
|
|
19
|
+
"""output_field is set in the constructor."""
|
|
20
|
+
super().__init__(*args, output_field=JSONField(), **kwargs)
|
|
18
21
|
|
|
19
22
|
|
|
20
23
|
class GroupConcat(Aggregate):
|
|
@@ -25,7 +28,10 @@ class GroupConcat(Aggregate):
|
|
|
25
28
|
allow_distinct = True
|
|
26
29
|
function = "GROUP_CONCAT"
|
|
27
30
|
name = "GroupConcat"
|
|
28
|
-
|
|
31
|
+
|
|
32
|
+
def __init__(self, *args, **kwargs):
|
|
33
|
+
"""output_field is set in the constructor."""
|
|
34
|
+
super().__init__(*args, output_field=CharField(), **kwargs)
|
|
29
35
|
|
|
30
36
|
|
|
31
37
|
@OneToOneField.register_lookup
|
|
@@ -36,8 +42,6 @@ class FTS5Match(Lookup):
|
|
|
36
42
|
|
|
37
43
|
def as_sql(self, compiler, connection):
|
|
38
44
|
"""Generate MATCH sql."""
|
|
39
|
-
# lhs, lhs_params = self.process_lhs(compiler, connection)
|
|
40
|
-
# fts_table = lhs.split(".")[0]
|
|
41
45
|
rhs, rhs_params = self.process_rhs(compiler, connection)
|
|
42
46
|
# MATCH works on the table itself not the one_to_one rel.
|
|
43
47
|
# Force the table name without substitutions by the optimizer
|
|
@@ -67,4 +71,7 @@ class ComicFTSRank(Func):
|
|
|
67
71
|
|
|
68
72
|
function = "rank"
|
|
69
73
|
template = '("codex_comicfts"."rank" * -1)'
|
|
70
|
-
|
|
74
|
+
|
|
75
|
+
def __init__(self, *args, **kwargs):
|
|
76
|
+
"""output_field is set in the constructor."""
|
|
77
|
+
super().__init__(*args, output_field=FloatField(), **kwargs)
|
codex/models/groups.py
CHANGED
|
@@ -136,7 +136,7 @@ class WatchedPathBrowserGroup(BrowserGroupModel, WatchedPath):
|
|
|
136
136
|
super().presave()
|
|
137
137
|
WatchedPath.presave(self)
|
|
138
138
|
|
|
139
|
-
class Meta(WatchedPath.Meta):
|
|
139
|
+
class Meta(BrowserGroupModel.Meta, WatchedPath.Meta):
|
|
140
140
|
"""Use Mixin Meta."""
|
|
141
141
|
|
|
142
142
|
abstract = True
|
codex/models/library.py
CHANGED
|
@@ -23,7 +23,7 @@ __all__ = ("Library", "validate_dir_exists")
|
|
|
23
23
|
def validate_dir_exists(path):
|
|
24
24
|
"""Validate that a library exists."""
|
|
25
25
|
if not Path(path).is_dir():
|
|
26
|
-
raise ValidationError(_(
|
|
26
|
+
raise ValidationError(_("{path} is not a directory"), params={"path": path})
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class Library(BaseModel):
|
codex/models/paths.py
CHANGED
|
@@ -36,11 +36,11 @@ class WatchedPath(BaseModel):
|
|
|
36
36
|
st[0] = st_record.st_mode
|
|
37
37
|
st[1] = st_record.st_ino
|
|
38
38
|
# st[2] = st_record.st_dev is ignored by diff
|
|
39
|
-
# st[3] = st_record.st_nlink
|
|
40
|
-
# st[4] = st_record.st_uid
|
|
41
|
-
# st[5] = st_record.st_gid
|
|
39
|
+
# st[3] = st_record.st_nlink ignored
|
|
40
|
+
# st[4] = st_record.st_uid ignored
|
|
41
|
+
# st[5] = st_record.st_gid ignored
|
|
42
42
|
st[6] = st_record.st_size
|
|
43
|
-
# st[7] = st_record.st_atime
|
|
43
|
+
# st[7] = st_record.st_atime ignored
|
|
44
44
|
st[8] = st_record.st_mtime
|
|
45
45
|
self.stat = st
|
|
46
46
|
|
codex/models/query.py
CHANGED
|
@@ -45,7 +45,7 @@ class GroupByQuery(Query):
|
|
|
45
45
|
self.force_group_by_table = ""
|
|
46
46
|
self.force_group_by_fields = ()
|
|
47
47
|
|
|
48
|
-
def get_compiler(self, using=None, connection=None, elide_empty=True):
|
|
48
|
+
def get_compiler(self, using=None, connection=None, elide_empty=True): # noqa: FBT002
|
|
49
49
|
"""Use the custom compiler instead of SQLCompiler."""
|
|
50
50
|
if self.compiler == "SQLCompiler":
|
|
51
51
|
if using is None and connection is None:
|
|
@@ -59,7 +59,11 @@ class GroupByQuery(Query):
|
|
|
59
59
|
)
|
|
60
60
|
else:
|
|
61
61
|
# Normal super() operation.
|
|
62
|
-
compiler = super().get_compiler(
|
|
62
|
+
compiler = super().get_compiler(
|
|
63
|
+
using=using,
|
|
64
|
+
connection=connection,
|
|
65
|
+
elide_empty=elide_empty, # type: ignore[reportCallIssue]
|
|
66
|
+
)
|
|
63
67
|
|
|
64
68
|
return compiler
|
|
65
69
|
|
|
@@ -82,13 +86,13 @@ class GroupByQuerySet(QuerySet):
|
|
|
82
86
|
|
|
83
87
|
def group_by(self, *fields, model=None):
|
|
84
88
|
"""Force group_by operator."""
|
|
85
|
-
obj = self._chain() # type: ignore
|
|
89
|
+
obj = self._chain() # type: ignore[reportAttributeAccessIssue]
|
|
86
90
|
obj.query.set_force_group_by(fields, model=model)
|
|
87
91
|
return obj
|
|
88
92
|
|
|
89
93
|
def demote_joins(self, tables):
|
|
90
94
|
"""Force INNER JOINS."""
|
|
91
|
-
obj = self._chain() # type: ignore
|
|
95
|
+
obj = self._chain() # type: ignore[reportAttributeAccessIssue]
|
|
92
96
|
obj.query.demote_joins(tables)
|
|
93
97
|
return obj
|
|
94
98
|
|
codex/models/util.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Utilities for models."""
|
|
2
2
|
|
|
3
3
|
_ARTICLES = frozenset(
|
|
4
|
-
("a", "an", "the") # en # noqa RUF005
|
|
4
|
+
("a", "an", "the") # en # noqa: RUF005
|
|
5
5
|
+ ("un", "unos", "unas", "el", "los", "la", "las") # es
|
|
6
6
|
+ ("un", "une", "le", "les", "la", "les", "l'") # fr
|
|
7
7
|
+ ("o", "a", "os") # pt
|
codex/permissions.py
CHANGED
|
@@ -8,7 +8,7 @@ from codex.models import Timestamp
|
|
|
8
8
|
class HasAPIKeyOrIsAdminUser(BasePermission):
|
|
9
9
|
"""Does the request have the current api key."""
|
|
10
10
|
|
|
11
|
-
def has_permission(self, request, view):
|
|
11
|
+
def has_permission(self, request, view):
|
|
12
12
|
"""Test the request api key against the database."""
|
|
13
13
|
data = request.GET if request.method == "GET" else request.POST
|
|
14
14
|
api_key = data.get("apiKey")
|
codex/run.py
CHANGED
|
@@ -85,6 +85,4 @@ class AdminFolderSerializer(Serializer):
|
|
|
85
85
|
|
|
86
86
|
def validate_show_hidden(self, show_hidden):
|
|
87
87
|
"""Snakecase the showHidden field."""
|
|
88
|
-
return (
|
|
89
|
-
show_hidden == "true" or self.initial_data.get("showHidden") == "true" # type: ignore
|
|
90
|
-
)
|
|
88
|
+
return show_hidden == "true" or self.initial_data.get("showHidden") == "true"
|
codex/serializers/admin/stats.py
CHANGED
|
@@ -19,8 +19,8 @@ FILE_TYPES_CHOICES = ("CBZ", "CBR", "CBT", "PDF", "UNKNOWN")
|
|
|
19
19
|
class StatsSystemSerializer(Serializer):
|
|
20
20
|
"""Platform System Information."""
|
|
21
21
|
|
|
22
|
-
name = CharField(
|
|
23
|
-
release = CharField(
|
|
22
|
+
name = CharField(read_only=True, required=False)
|
|
23
|
+
release = CharField(read_only=True, required=False)
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class StatsPlatformSerializer(Serializer):
|
|
@@ -42,7 +42,7 @@ class StatsConfigSerializer(Serializer):
|
|
|
42
42
|
user_registered_count = IntegerField(required=False, read_only=True)
|
|
43
43
|
auth_group_count = IntegerField(required=False, read_only=True)
|
|
44
44
|
# Only for api
|
|
45
|
-
api_key = CharField(
|
|
45
|
+
api_key = CharField(read_only=True, required=False)
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
class StatsSessionsSerializer(Serializer):
|
|
@@ -123,4 +123,4 @@ class AdminStatsRequestSerializer(Serializer):
|
|
|
123
123
|
class APIKeySerializer(Serializer):
|
|
124
124
|
"""API Key."""
|
|
125
125
|
|
|
126
|
-
api_key = CharField(source="name")
|
|
126
|
+
api_key = CharField(source="name", read_only=True)
|
codex/serializers/auth.py
CHANGED
|
@@ -8,6 +8,8 @@ from rest_framework.serializers import (
|
|
|
8
8
|
)
|
|
9
9
|
|
|
10
10
|
from codex.models import AdminFlag
|
|
11
|
+
from codex.serializers.fields.auth import TimezoneField
|
|
12
|
+
from codex.serializers.fields.sanitized import SanitizedCharField
|
|
11
13
|
from codex.serializers.models.base import BaseModelSerializer
|
|
12
14
|
|
|
13
15
|
|
|
@@ -49,7 +51,7 @@ class UserSerializer(BaseModelSerializer):
|
|
|
49
51
|
class TimezoneSerializer(Serializer):
|
|
50
52
|
"""Serialize Timezone submission from front end."""
|
|
51
53
|
|
|
52
|
-
timezone =
|
|
54
|
+
timezone = TimezoneField(write_only=True)
|
|
53
55
|
|
|
54
56
|
|
|
55
57
|
class UserCreateSerializer(BaseModelSerializer, TimezoneSerializer):
|
|
@@ -67,7 +69,7 @@ class UserLoginSerializer(UserCreateSerializer):
|
|
|
67
69
|
"""Serialize user login input."""
|
|
68
70
|
|
|
69
71
|
# specify this so it doesn't trigger the username unique constraint.
|
|
70
|
-
username =
|
|
72
|
+
username = SanitizedCharField(min_length=2)
|
|
71
73
|
|
|
72
74
|
class Meta(UserCreateSerializer.Meta):
|
|
73
75
|
"""Explicit meta inheritance required."""
|
|
@@ -2,28 +2,106 @@
|
|
|
2
2
|
|
|
3
3
|
from types import MappingProxyType
|
|
4
4
|
|
|
5
|
-
from rest_framework.fields import
|
|
6
|
-
|
|
5
|
+
from rest_framework.fields import (
|
|
6
|
+
BooleanField,
|
|
7
|
+
CharField,
|
|
8
|
+
ListField,
|
|
9
|
+
SerializerMethodField,
|
|
10
|
+
)
|
|
11
|
+
from rest_framework.serializers import Serializer
|
|
7
12
|
|
|
8
|
-
from codex.serializers.browser.filters import BrowserSettingsFilterSerializer
|
|
9
13
|
from codex.serializers.fields import (
|
|
14
|
+
VuetifyBooleanField,
|
|
10
15
|
VuetifyCharField,
|
|
16
|
+
VuetifyDecadeField,
|
|
17
|
+
VuetifyFloatField,
|
|
11
18
|
VuetifyIntegerField,
|
|
12
19
|
)
|
|
20
|
+
from codex.serializers.fields.browser import BookmarkFilterField
|
|
13
21
|
from codex.serializers.models.pycountry import CountrySerializer, LanguageSerializer
|
|
14
22
|
|
|
15
23
|
|
|
16
|
-
class
|
|
24
|
+
class BrowserFilterChoicesSerializer(Serializer):
|
|
25
|
+
"""All dynamic filters."""
|
|
26
|
+
|
|
27
|
+
age_rating = BooleanField(read_only=True)
|
|
28
|
+
community_rating = BooleanField(read_only=True)
|
|
29
|
+
characters = BooleanField(read_only=True)
|
|
30
|
+
country = BooleanField(read_only=True)
|
|
31
|
+
critical_rating = BooleanField(read_only=True)
|
|
32
|
+
contributors = BooleanField(read_only=True)
|
|
33
|
+
decade = BooleanField(read_only=True)
|
|
34
|
+
genres = BooleanField(read_only=True)
|
|
35
|
+
file_type = BooleanField(read_only=True)
|
|
36
|
+
identifier_type = BooleanField(read_only=True)
|
|
37
|
+
monochrome = BooleanField(read_only=True)
|
|
38
|
+
language = BooleanField(read_only=True)
|
|
39
|
+
locations = BooleanField(read_only=True)
|
|
40
|
+
original_format = BooleanField(read_only=True)
|
|
41
|
+
reading_direction = BooleanField(read_only=True)
|
|
42
|
+
series_groups = BooleanField(read_only=True)
|
|
43
|
+
stories = BooleanField(read_only=True)
|
|
44
|
+
story_arcs = BooleanField(read_only=True)
|
|
45
|
+
tagger = BooleanField(read_only=True)
|
|
46
|
+
tags = BooleanField(read_only=True)
|
|
47
|
+
teams = BooleanField(read_only=True)
|
|
48
|
+
year = BooleanField(read_only=True)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class BrowserSettingsFilterSerializer(Serializer):
|
|
52
|
+
"""Filter values for settings."""
|
|
53
|
+
|
|
54
|
+
bookmark = BookmarkFilterField(required=False, read_only=True)
|
|
55
|
+
# Dynamic filters
|
|
56
|
+
age_rating = ListField(child=VuetifyCharField(), required=False, read_only=True)
|
|
57
|
+
characters = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
58
|
+
community_rating = ListField(
|
|
59
|
+
child=VuetifyFloatField(), required=False, read_only=True
|
|
60
|
+
)
|
|
61
|
+
country = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
62
|
+
contributors = ListField(
|
|
63
|
+
child=VuetifyIntegerField(), required=False, read_only=True
|
|
64
|
+
)
|
|
65
|
+
critical_rating = ListField(
|
|
66
|
+
child=VuetifyFloatField(), required=False, read_only=True
|
|
67
|
+
)
|
|
68
|
+
decade = ListField(child=VuetifyDecadeField(), required=False, read_only=True)
|
|
69
|
+
file_type = ListField(child=VuetifyCharField(), required=False, read_only=True)
|
|
70
|
+
genres = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
71
|
+
identifier_type = ListField(
|
|
72
|
+
child=VuetifyCharField(), required=False, read_only=True
|
|
73
|
+
)
|
|
74
|
+
language = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
75
|
+
locations = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
76
|
+
monochrome = ListField(child=VuetifyBooleanField(), required=False, read_only=True)
|
|
77
|
+
original_format = ListField(
|
|
78
|
+
child=VuetifyCharField(), required=False, read_only=True
|
|
79
|
+
)
|
|
80
|
+
reading_direction = ListField(
|
|
81
|
+
child=VuetifyCharField(), required=False, read_only=True
|
|
82
|
+
)
|
|
83
|
+
series_groups = ListField(
|
|
84
|
+
child=VuetifyIntegerField(), required=False, read_only=True
|
|
85
|
+
)
|
|
86
|
+
stories = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
87
|
+
story_arcs = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
88
|
+
tagger = ListField(child=VuetifyCharField(), required=False, read_only=True)
|
|
89
|
+
tags = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
90
|
+
teams = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
91
|
+
year = ListField(child=VuetifyIntegerField(), required=False, read_only=True)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class BrowserChoicesIntegerPkSerializer(Serializer):
|
|
17
95
|
"""Named Model Serializer."""
|
|
18
96
|
|
|
19
|
-
pk =
|
|
97
|
+
pk = VuetifyIntegerField(read_only=True)
|
|
20
98
|
name = CharField(read_only=True)
|
|
21
99
|
|
|
22
100
|
|
|
23
|
-
class BrowserChoicesIntegerPkSerializer
|
|
101
|
+
class BrowserChoicesCharPkSerializer(BrowserChoicesIntegerPkSerializer):
|
|
24
102
|
"""Named Model Serailizer with pk = char hack for languages & countries."""
|
|
25
103
|
|
|
26
|
-
pk =
|
|
104
|
+
pk = VuetifyCharField(read_only=True)
|
|
27
105
|
|
|
28
106
|
|
|
29
107
|
_CHOICES_NAME_SERIALIZER_MAP = MappingProxyType(
|
|
@@ -50,9 +128,9 @@ class BrowserChoicesFilterSerializer(Serializer):
|
|
|
50
128
|
if serializer_class:
|
|
51
129
|
value = serializer_class(choices, many=True).data
|
|
52
130
|
elif not serializer_class and field_name in _LIST_FIELDS:
|
|
53
|
-
field: ListField = (
|
|
131
|
+
field: ListField = ( # type: ignore[reportAssignmentType]
|
|
54
132
|
BrowserSettingsFilterSerializer().get_fields().get(field_name)
|
|
55
|
-
)
|
|
133
|
+
)
|
|
56
134
|
value = field.to_representation(choices)
|
|
57
135
|
else:
|
|
58
136
|
value = BrowserChoicesIntegerPkSerializer(choices, many=True).data
|