codex 1.6.0a10__py3-none-any.whl → 1.6.0a12__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.

Files changed (426) hide show
  1. codex/librarian/covers/create.py +21 -16
  2. codex/serializers/browser/choices.py +23 -44
  3. codex/serializers/browser/filters.py +30 -36
  4. codex/serializers/browser/mixins.py +37 -4
  5. codex/serializers/browser/settings.py +10 -3
  6. codex/serializers/choices.py +4 -0
  7. codex/serializers/fields.py +75 -66
  8. codex/serializers/models/pycountry.py +11 -51
  9. codex/serializers/opds/v2.py +4 -6
  10. codex/serializers/reader.py +1 -0
  11. codex/static_root/assets/{VCheckbox-CY3rcqlS.de5154294920.js → VCheckbox-B3vCf1Vu.e1991f98ab6c.js} +1 -1
  12. codex/static_root/assets/VCheckbox-B3vCf1Vu.e1991f98ab6c.js.br +0 -0
  13. codex/static_root/assets/VCheckbox-B3vCf1Vu.e1991f98ab6c.js.gz +0 -0
  14. codex/static_root/assets/{VCheckbox-CY3rcqlS.js → VCheckbox-B3vCf1Vu.js} +1 -1
  15. codex/static_root/assets/VCheckbox-B3vCf1Vu.js.br +0 -0
  16. codex/static_root/assets/VCheckbox-B3vCf1Vu.js.gz +0 -0
  17. codex/static_root/assets/{VCheckboxBtn-D2tPTt6P.9a90d6818bf6.js → VCheckboxBtn-Cj6bUYmw.196cc43ca1c8.js} +1 -1
  18. codex/static_root/assets/VCheckboxBtn-Cj6bUYmw.196cc43ca1c8.js.br +0 -0
  19. codex/static_root/assets/VCheckboxBtn-Cj6bUYmw.196cc43ca1c8.js.gz +0 -0
  20. codex/static_root/assets/{VCheckboxBtn-D2tPTt6P.js → VCheckboxBtn-Cj6bUYmw.js} +1 -1
  21. codex/static_root/assets/VCheckboxBtn-Cj6bUYmw.js.br +0 -0
  22. codex/static_root/assets/VCheckboxBtn-Cj6bUYmw.js.gz +0 -0
  23. codex/static_root/assets/{VCombobox-aJr--Ou7.f290ccf2ce25.js → VCombobox-wIqJY8no.3547ff73e91e.js} +1 -1
  24. codex/static_root/assets/VCombobox-wIqJY8no.3547ff73e91e.js.br +0 -0
  25. codex/static_root/assets/VCombobox-wIqJY8no.3547ff73e91e.js.gz +0 -0
  26. codex/static_root/assets/{VCombobox-aJr--Ou7.js → VCombobox-wIqJY8no.js} +1 -1
  27. codex/static_root/assets/VCombobox-wIqJY8no.js.br +0 -0
  28. codex/static_root/assets/VCombobox-wIqJY8no.js.gz +0 -0
  29. codex/static_root/assets/{VDialog-61pzfUB2.33f73beb5224.js → VDialog-D6HUFV6a.ac71da510b3f.js} +1 -1
  30. codex/static_root/assets/VDialog-D6HUFV6a.ac71da510b3f.js.br +0 -0
  31. codex/static_root/assets/VDialog-D6HUFV6a.ac71da510b3f.js.gz +0 -0
  32. codex/static_root/assets/{VDialog-61pzfUB2.js → VDialog-D6HUFV6a.js} +1 -1
  33. codex/static_root/assets/VDialog-D6HUFV6a.js.br +0 -0
  34. codex/static_root/assets/VDialog-D6HUFV6a.js.gz +0 -0
  35. codex/static_root/assets/{VExpansionPanels-rewm0P4z.5c7680f815b6.js → VExpansionPanels-BUJaYmzY.44e8a00a2ebe.js} +1 -1
  36. codex/static_root/assets/VExpansionPanels-BUJaYmzY.44e8a00a2ebe.js.br +0 -0
  37. codex/static_root/assets/VExpansionPanels-BUJaYmzY.44e8a00a2ebe.js.gz +0 -0
  38. codex/static_root/assets/{VExpansionPanels-rewm0P4z.js → VExpansionPanels-BUJaYmzY.js} +1 -1
  39. codex/static_root/assets/VExpansionPanels-BUJaYmzY.js.br +0 -0
  40. codex/static_root/assets/VExpansionPanels-BUJaYmzY.js.gz +0 -0
  41. codex/static_root/assets/{VRadioGroup-QFQbK1qo.750a42b1b814.js → VRadioGroup-CayclHra.0a5b1c9a7b71.js} +1 -1
  42. codex/static_root/assets/VRadioGroup-CayclHra.0a5b1c9a7b71.js.br +0 -0
  43. codex/static_root/assets/VRadioGroup-CayclHra.0a5b1c9a7b71.js.gz +0 -0
  44. codex/static_root/assets/{VRadioGroup-QFQbK1qo.js → VRadioGroup-CayclHra.js} +1 -1
  45. codex/static_root/assets/VRadioGroup-CayclHra.js.br +0 -0
  46. codex/static_root/assets/VRadioGroup-CayclHra.js.gz +0 -0
  47. codex/static_root/assets/{VSelect-Dixy6okt.5d53830daa8a.js → VSelect-ou2Q9UaN.8ddd219784e1.js} +1 -1
  48. codex/static_root/assets/VSelect-ou2Q9UaN.8ddd219784e1.js.br +0 -0
  49. codex/static_root/assets/VSelect-ou2Q9UaN.8ddd219784e1.js.gz +0 -0
  50. codex/static_root/assets/{VSelect-Dixy6okt.js → VSelect-ou2Q9UaN.js} +1 -1
  51. codex/static_root/assets/VSelect-ou2Q9UaN.js.br +0 -0
  52. codex/static_root/assets/VSelect-ou2Q9UaN.js.gz +0 -0
  53. codex/static_root/assets/{VSelectionControl-MNmxKc3J.js → VSelectionControl-BOKIwNZb.16e0cdde978c.js} +1 -1
  54. codex/static_root/assets/VSelectionControl-BOKIwNZb.16e0cdde978c.js.br +0 -0
  55. codex/static_root/assets/VSelectionControl-BOKIwNZb.16e0cdde978c.js.gz +0 -0
  56. codex/static_root/assets/{VSelectionControl-MNmxKc3J.08055d00917e.js → VSelectionControl-BOKIwNZb.js} +1 -1
  57. codex/static_root/assets/VSelectionControl-BOKIwNZb.js.br +0 -0
  58. codex/static_root/assets/VSelectionControl-BOKIwNZb.js.gz +0 -0
  59. codex/static_root/assets/{VSlideGroup-DZEV0FoV.5f996daf0e98.js → VSlideGroup-C3XgVg2T.d2b0ee4f596c.js} +1 -1
  60. codex/static_root/assets/VSlideGroup-C3XgVg2T.d2b0ee4f596c.js.br +0 -0
  61. codex/static_root/assets/VSlideGroup-C3XgVg2T.d2b0ee4f596c.js.gz +0 -0
  62. codex/static_root/assets/{VSlideGroup-DZEV0FoV.js → VSlideGroup-C3XgVg2T.js} +1 -1
  63. codex/static_root/assets/VSlideGroup-C3XgVg2T.js.br +0 -0
  64. codex/static_root/assets/VSlideGroup-C3XgVg2T.js.gz +0 -0
  65. codex/static_root/assets/{VTable-lcnYg9Ee.d72927b13c2e.js → VTable-CrIiBr9q.b4669247af45.js} +1 -1
  66. codex/static_root/assets/VTable-CrIiBr9q.b4669247af45.js.br +0 -0
  67. codex/static_root/assets/VTable-CrIiBr9q.b4669247af45.js.gz +0 -0
  68. codex/static_root/assets/{VTable-lcnYg9Ee.js → VTable-CrIiBr9q.js} +1 -1
  69. codex/static_root/assets/VTable-CrIiBr9q.js.br +0 -0
  70. codex/static_root/assets/VTable-CrIiBr9q.js.gz +0 -0
  71. codex/static_root/assets/{VTextField-BkFrjhdV.js → VTextField-HAAxrpNi.6f6dcb50079a.js} +1 -1
  72. codex/static_root/assets/VTextField-HAAxrpNi.6f6dcb50079a.js.br +0 -0
  73. codex/static_root/assets/VTextField-HAAxrpNi.6f6dcb50079a.js.gz +0 -0
  74. codex/static_root/assets/{VTextField-BkFrjhdV.b02653a9b3b7.js → VTextField-HAAxrpNi.js} +1 -1
  75. codex/static_root/assets/VTextField-HAAxrpNi.js.br +0 -0
  76. codex/static_root/assets/VTextField-HAAxrpNi.js.gz +0 -0
  77. codex/static_root/assets/{VWindowItem-C__tAqdc.9791c128c3b7.js → VWindowItem-aal6-Uv4.d178e2af20a7.js} +1 -1
  78. codex/static_root/assets/VWindowItem-aal6-Uv4.d178e2af20a7.js.br +0 -0
  79. codex/static_root/assets/VWindowItem-aal6-Uv4.d178e2af20a7.js.gz +0 -0
  80. codex/static_root/assets/{VWindowItem-C__tAqdc.js → VWindowItem-aal6-Uv4.js} +1 -1
  81. codex/static_root/assets/VWindowItem-aal6-Uv4.js.br +0 -0
  82. codex/static_root/assets/VWindowItem-aal6-Uv4.js.gz +0 -0
  83. codex/static_root/assets/admin-D5JDmLDy.e4df3dd3a3fe.js +1 -0
  84. codex/static_root/assets/admin-D5JDmLDy.e4df3dd3a3fe.js.br +0 -0
  85. codex/static_root/assets/admin-D5JDmLDy.e4df3dd3a3fe.js.gz +0 -0
  86. codex/static_root/assets/admin-D5JDmLDy.js +1 -0
  87. codex/static_root/assets/admin-D5JDmLDy.js.br +0 -0
  88. codex/static_root/assets/admin-D5JDmLDy.js.gz +0 -0
  89. codex/static_root/assets/{admin-drawer-panel-rrNKi_GE.e2b034db7934.js → admin-drawer-panel-BF-h3Wm0.1f372db8d08f.js} +2 -2
  90. codex/static_root/assets/admin-drawer-panel-BF-h3Wm0.1f372db8d08f.js.br +0 -0
  91. codex/static_root/assets/admin-drawer-panel-BF-h3Wm0.1f372db8d08f.js.gz +0 -0
  92. codex/static_root/assets/{admin-drawer-panel-rrNKi_GE.js → admin-drawer-panel-BF-h3Wm0.js} +2 -2
  93. codex/static_root/assets/admin-drawer-panel-BF-h3Wm0.js.br +0 -0
  94. codex/static_root/assets/admin-drawer-panel-BF-h3Wm0.js.gz +0 -0
  95. codex/static_root/assets/browser-B1-dPld9.0b3fa4fdbe22.css +1 -0
  96. codex/static_root/assets/browser-B1-dPld9.0b3fa4fdbe22.css.br +0 -0
  97. codex/static_root/assets/browser-B1-dPld9.0b3fa4fdbe22.css.gz +0 -0
  98. codex/static_root/assets/browser-B1-dPld9.css +1 -0
  99. codex/static_root/assets/browser-B1-dPld9.css.br +0 -0
  100. codex/static_root/assets/browser-B1-dPld9.css.gz +0 -0
  101. codex/static_root/assets/browser-VhFkImB_.9c3b2c746614.js +1 -0
  102. codex/static_root/assets/browser-VhFkImB_.9c3b2c746614.js.br +0 -0
  103. codex/static_root/assets/browser-VhFkImB_.9c3b2c746614.js.gz +0 -0
  104. codex/static_root/assets/browser-VhFkImB_.js +1 -0
  105. codex/static_root/assets/browser-VhFkImB_.js.br +0 -0
  106. codex/static_root/assets/browser-VhFkImB_.js.gz +0 -0
  107. codex/static_root/assets/{change-password-dialog-Bn20jYzD.593c5af1732b.js → change-password-dialog-BCYw5K7E.a8bae0450f20.js} +1 -1
  108. codex/static_root/assets/change-password-dialog-BCYw5K7E.a8bae0450f20.js.br +0 -0
  109. codex/static_root/assets/change-password-dialog-BCYw5K7E.a8bae0450f20.js.gz +0 -0
  110. codex/static_root/assets/{change-password-dialog-Bn20jYzD.js → change-password-dialog-BCYw5K7E.js} +1 -1
  111. codex/static_root/assets/change-password-dialog-BCYw5K7E.js.br +0 -0
  112. codex/static_root/assets/change-password-dialog-BCYw5K7E.js.gz +0 -0
  113. codex/static_root/assets/{confirm-dialog-CWszioQE.859051c35dd9.js → confirm-dialog-c9JOSGSy.3c5788f95f47.js} +1 -1
  114. codex/static_root/assets/confirm-dialog-c9JOSGSy.3c5788f95f47.js.br +3 -0
  115. codex/static_root/assets/confirm-dialog-c9JOSGSy.3c5788f95f47.js.gz +0 -0
  116. codex/static_root/assets/{confirm-dialog-CWszioQE.js → confirm-dialog-c9JOSGSy.js} +1 -1
  117. codex/static_root/assets/confirm-dialog-c9JOSGSy.js.br +3 -0
  118. codex/static_root/assets/confirm-dialog-c9JOSGSy.js.gz +0 -0
  119. codex/static_root/assets/{datetime-column-BSdlLt-4.27ec2df67a0b.js → datetime-column-D-6LPKdI.d46bbd8134df.js} +1 -1
  120. codex/static_root/assets/datetime-column-D-6LPKdI.d46bbd8134df.js.br +0 -0
  121. codex/static_root/assets/datetime-column-D-6LPKdI.d46bbd8134df.js.gz +0 -0
  122. codex/static_root/assets/{datetime-column-BSdlLt-4.js → datetime-column-D-6LPKdI.js} +1 -1
  123. codex/static_root/assets/datetime-column-D-6LPKdI.js.br +0 -0
  124. codex/static_root/assets/datetime-column-D-6LPKdI.js.gz +0 -0
  125. codex/static_root/assets/{filter-D3gaGf87.1f14dbfd9929.js → filter-BOnVoHTU.93c3d0d0d3f6.js} +1 -1
  126. codex/static_root/assets/filter-BOnVoHTU.93c3d0d0d3f6.js.br +0 -0
  127. codex/static_root/assets/filter-BOnVoHTU.93c3d0d0d3f6.js.gz +0 -0
  128. codex/static_root/assets/{filter-D3gaGf87.js → filter-BOnVoHTU.js} +1 -1
  129. codex/static_root/assets/filter-BOnVoHTU.js.br +0 -0
  130. codex/static_root/assets/filter-BOnVoHTU.js.gz +0 -0
  131. codex/static_root/assets/{flag-tab-8vzpdySX.a982c7f0776a.js → flag-tab-IniE-dLy.a02733e359aa.js} +1 -1
  132. codex/static_root/assets/flag-tab-IniE-dLy.a02733e359aa.js.br +0 -0
  133. codex/static_root/assets/flag-tab-IniE-dLy.a02733e359aa.js.gz +0 -0
  134. codex/static_root/assets/{flag-tab-8vzpdySX.js → flag-tab-IniE-dLy.js} +1 -1
  135. codex/static_root/assets/flag-tab-IniE-dLy.js.br +0 -0
  136. codex/static_root/assets/flag-tab-IniE-dLy.js.gz +0 -0
  137. codex/static_root/assets/{group-tab-Cz9t_ECi.a9e8aea79254.js → group-tab-RPa8XC0J.3d483919ea92.js} +1 -1
  138. codex/static_root/assets/group-tab-RPa8XC0J.3d483919ea92.js.br +0 -0
  139. codex/static_root/assets/group-tab-RPa8XC0J.3d483919ea92.js.gz +0 -0
  140. codex/static_root/assets/{group-tab-Cz9t_ECi.js → group-tab-RPa8XC0J.js} +1 -1
  141. codex/static_root/assets/group-tab-RPa8XC0J.js.br +0 -0
  142. codex/static_root/assets/group-tab-RPa8XC0J.js.gz +0 -0
  143. codex/static_root/assets/{http-error-Cqtszzf1.b31df3d9c29f.js → http-error-DBQycf8i.561cde2b4598.js} +1 -1
  144. codex/static_root/assets/http-error-DBQycf8i.561cde2b4598.js.br +0 -0
  145. codex/static_root/assets/http-error-DBQycf8i.561cde2b4598.js.gz +0 -0
  146. codex/static_root/assets/{http-error-Cqtszzf1.js → http-error-DBQycf8i.js} +1 -1
  147. codex/static_root/assets/http-error-DBQycf8i.js.br +0 -0
  148. codex/static_root/assets/http-error-DBQycf8i.js.gz +0 -0
  149. codex/static_root/assets/{library-tab-DMlnswUU.js → library-tab-C5trLvkq.35c7a1b79c71.js} +1 -1
  150. codex/static_root/assets/library-tab-C5trLvkq.35c7a1b79c71.js.br +0 -0
  151. codex/static_root/assets/library-tab-C5trLvkq.35c7a1b79c71.js.gz +0 -0
  152. codex/static_root/assets/{library-tab-DMlnswUU.30f454e84184.js → library-tab-C5trLvkq.js} +1 -1
  153. codex/static_root/assets/library-tab-C5trLvkq.js.br +0 -0
  154. codex/static_root/assets/library-tab-C5trLvkq.js.gz +0 -0
  155. codex/static_root/assets/main-x0Pcl23A.364bfe447c9c.js +32 -0
  156. codex/static_root/assets/main-x0Pcl23A.364bfe447c9c.js.br +0 -0
  157. codex/static_root/assets/main-x0Pcl23A.364bfe447c9c.js.gz +0 -0
  158. codex/static_root/assets/main-x0Pcl23A.js +32 -0
  159. codex/static_root/assets/main-x0Pcl23A.js.br +0 -0
  160. codex/static_root/assets/main-x0Pcl23A.js.gz +0 -0
  161. codex/static_root/assets/pagination-toolbar-BLUoVz2y.50051431acf1.css +1 -0
  162. codex/static_root/assets/pagination-toolbar-BLUoVz2y.50051431acf1.css.br +0 -0
  163. codex/static_root/assets/pagination-toolbar-BLUoVz2y.50051431acf1.css.gz +0 -0
  164. codex/static_root/assets/pagination-toolbar-BLUoVz2y.css +1 -0
  165. codex/static_root/assets/pagination-toolbar-BLUoVz2y.css.br +0 -0
  166. codex/static_root/assets/pagination-toolbar-BLUoVz2y.css.gz +0 -0
  167. codex/static_root/assets/pagination-toolbar-DEgDOzzp.71aa03f525e4.js +1 -0
  168. codex/static_root/assets/pagination-toolbar-DEgDOzzp.71aa03f525e4.js.br +0 -0
  169. codex/static_root/assets/pagination-toolbar-DEgDOzzp.71aa03f525e4.js.gz +0 -0
  170. codex/static_root/assets/pagination-toolbar-DEgDOzzp.js +1 -0
  171. codex/static_root/assets/pagination-toolbar-DEgDOzzp.js.br +0 -0
  172. codex/static_root/assets/pagination-toolbar-DEgDOzzp.js.gz +0 -0
  173. codex/static_root/assets/{pdf-doc-BiamrjRZ.4c9be1ade43c.js → pdf-doc-CkV-xfvG.35c1a6a19a41.js} +1 -1
  174. codex/static_root/assets/pdf-doc-CkV-xfvG.35c1a6a19a41.js.br +0 -0
  175. codex/static_root/assets/pdf-doc-CkV-xfvG.35c1a6a19a41.js.gz +0 -0
  176. codex/static_root/assets/{pdf-doc-BiamrjRZ.js → pdf-doc-CkV-xfvG.js} +1 -1
  177. codex/static_root/assets/pdf-doc-CkV-xfvG.js.br +0 -0
  178. codex/static_root/assets/pdf-doc-CkV-xfvG.js.gz +0 -0
  179. codex/static_root/assets/reader-ClcgSG93.6afe950e70ac.js +2 -0
  180. codex/static_root/assets/reader-ClcgSG93.6afe950e70ac.js.br +0 -0
  181. codex/static_root/assets/reader-ClcgSG93.6afe950e70ac.js.gz +0 -0
  182. codex/static_root/assets/reader-ClcgSG93.js +2 -0
  183. codex/static_root/assets/reader-ClcgSG93.js.br +0 -0
  184. codex/static_root/assets/reader-ClcgSG93.js.gz +0 -0
  185. codex/static_root/assets/{reader-BpsctRsY.5d72e393911a.css → reader-CqXFa_gE.78267e9de0c2.css} +1 -1
  186. codex/static_root/assets/reader-CqXFa_gE.78267e9de0c2.css.br +0 -0
  187. codex/static_root/assets/reader-CqXFa_gE.78267e9de0c2.css.gz +0 -0
  188. codex/static_root/assets/{reader-BpsctRsY.css → reader-CqXFa_gE.css} +1 -1
  189. codex/static_root/assets/reader-CqXFa_gE.css.br +0 -0
  190. codex/static_root/assets/reader-CqXFa_gE.css.gz +0 -0
  191. codex/static_root/assets/{relation-chips-C5acBjpy.dc67d4528868.js → relation-chips-2vga5ApB.d94c344f909b.js} +1 -1
  192. codex/static_root/assets/relation-chips-2vga5ApB.d94c344f909b.js.br +0 -0
  193. codex/static_root/assets/relation-chips-2vga5ApB.d94c344f909b.js.gz +0 -0
  194. codex/static_root/assets/{relation-chips-C5acBjpy.js → relation-chips-2vga5ApB.js} +1 -1
  195. codex/static_root/assets/relation-chips-2vga5ApB.js.br +0 -0
  196. codex/static_root/assets/relation-chips-2vga5ApB.js.gz +0 -0
  197. codex/static_root/assets/{settings-drawer-D_JuRi7F.f02f3f981f8f.js → settings-drawer-BOTI_tHr.03748f801e08.js} +2 -2
  198. codex/static_root/assets/settings-drawer-BOTI_tHr.03748f801e08.js.br +0 -0
  199. codex/static_root/assets/settings-drawer-BOTI_tHr.03748f801e08.js.gz +0 -0
  200. codex/static_root/assets/{settings-drawer-D_JuRi7F.js → settings-drawer-BOTI_tHr.js} +2 -2
  201. codex/static_root/assets/settings-drawer-BOTI_tHr.js.br +0 -0
  202. codex/static_root/assets/settings-drawer-BOTI_tHr.js.gz +0 -0
  203. codex/static_root/assets/{stats-tab-ClqRTk1z.c759ace65a87.js → stats-tab-CBz_jhmH.9bdc41225f06.js} +1 -1
  204. codex/static_root/assets/stats-tab-CBz_jhmH.9bdc41225f06.js.br +0 -0
  205. codex/static_root/assets/stats-tab-CBz_jhmH.9bdc41225f06.js.gz +0 -0
  206. codex/static_root/assets/{stats-tab-ClqRTk1z.js → stats-tab-CBz_jhmH.js} +1 -1
  207. codex/static_root/assets/stats-tab-CBz_jhmH.js.br +0 -0
  208. codex/static_root/assets/stats-tab-CBz_jhmH.js.gz +0 -0
  209. codex/static_root/assets/{task-tab-DF9qa6LO.0b32cafde4ad.js → task-tab-B8sYV6Ia.90a8deec0214.js} +1 -1
  210. codex/static_root/assets/task-tab-B8sYV6Ia.90a8deec0214.js.br +0 -0
  211. codex/static_root/assets/task-tab-B8sYV6Ia.90a8deec0214.js.gz +0 -0
  212. codex/static_root/assets/{task-tab-DF9qa6LO.js → task-tab-B8sYV6Ia.js} +1 -1
  213. codex/static_root/assets/task-tab-B8sYV6Ia.js.br +0 -0
  214. codex/static_root/assets/task-tab-B8sYV6Ia.js.gz +0 -0
  215. codex/static_root/assets/to-case-CnnzURtN.f0e4b42ddb89.js +1 -0
  216. codex/static_root/assets/to-case-CnnzURtN.js +1 -0
  217. codex/static_root/assets/{unauthorized-BjKuLH6k.2ae00ddd79fb.js → unauthorized-D5-FvA2_.61b1cd239b47.js} +1 -1
  218. codex/static_root/assets/unauthorized-D5-FvA2_.61b1cd239b47.js.br +0 -0
  219. codex/static_root/assets/unauthorized-D5-FvA2_.61b1cd239b47.js.gz +0 -0
  220. codex/static_root/assets/{unauthorized-BjKuLH6k.js → unauthorized-D5-FvA2_.js} +1 -1
  221. codex/static_root/assets/unauthorized-D5-FvA2_.js.br +0 -0
  222. codex/static_root/assets/unauthorized-D5-FvA2_.js.gz +0 -0
  223. codex/static_root/assets/{user-tab-Dpxe3ygA.7d90174631f0.js → user-tab-pzFjrggM.97c02ebee729.js} +1 -1
  224. codex/static_root/assets/user-tab-pzFjrggM.97c02ebee729.js.br +0 -0
  225. codex/static_root/assets/user-tab-pzFjrggM.97c02ebee729.js.gz +0 -0
  226. codex/static_root/assets/{user-tab-Dpxe3ygA.js → user-tab-pzFjrggM.js} +1 -1
  227. codex/static_root/assets/user-tab-pzFjrggM.js.br +0 -0
  228. codex/static_root/assets/user-tab-pzFjrggM.js.gz +0 -0
  229. codex/static_root/js/{choices.a0aaaa6c7ef7.json → choices.2f6b0359e1ef.json} +1 -1
  230. codex/static_root/js/choices.2f6b0359e1ef.json.br +0 -0
  231. codex/static_root/js/choices.2f6b0359e1ef.json.gz +0 -0
  232. codex/static_root/js/choices.json +1 -1
  233. codex/static_root/js/choices.json.br +0 -0
  234. codex/static_root/js/choices.json.gz +0 -0
  235. codex/static_root/{manifest.35e46a3ec8fa.json → manifest.a18726680d5f.json} +223 -223
  236. codex/static_root/manifest.a18726680d5f.json.br +0 -0
  237. codex/static_root/manifest.a18726680d5f.json.gz +0 -0
  238. codex/static_root/manifest.json +223 -223
  239. codex/static_root/manifest.json.br +0 -0
  240. codex/static_root/manifest.json.gz +0 -0
  241. codex/static_root/staticfiles.json +1 -1
  242. codex/util.py +8 -6
  243. codex/views/bookmark.py +29 -23
  244. codex/views/browser/annotations.py +9 -45
  245. codex/views/browser/browser.py +26 -6
  246. codex/views/browser/choices.py +4 -22
  247. codex/views/browser/cover.py +35 -11
  248. codex/views/browser/filters/annotations.py +23 -8
  249. codex/views/browser/metadata.py +22 -12
  250. codex/views/const.py +1 -1
  251. codex/views/reader/init.py +16 -12
  252. codex/views/reader/page.py +13 -2
  253. codex/views/session.py +3 -1
  254. codex/views/util.py +13 -0
  255. codex/websockets/consumers.py +1 -1
  256. {codex-1.6.0a10.dist-info → codex-1.6.0a12.dist-info}/METADATA +1 -1
  257. {codex-1.6.0a10.dist-info → codex-1.6.0a12.dist-info}/RECORD +260 -262
  258. codex/static_root/assets/VCheckbox-CY3rcqlS.de5154294920.js.br +0 -0
  259. codex/static_root/assets/VCheckbox-CY3rcqlS.de5154294920.js.gz +0 -0
  260. codex/static_root/assets/VCheckbox-CY3rcqlS.js.br +0 -0
  261. codex/static_root/assets/VCheckbox-CY3rcqlS.js.gz +0 -0
  262. codex/static_root/assets/VCheckboxBtn-D2tPTt6P.9a90d6818bf6.js.br +0 -0
  263. codex/static_root/assets/VCheckboxBtn-D2tPTt6P.9a90d6818bf6.js.gz +0 -0
  264. codex/static_root/assets/VCheckboxBtn-D2tPTt6P.js.br +0 -0
  265. codex/static_root/assets/VCheckboxBtn-D2tPTt6P.js.gz +0 -0
  266. codex/static_root/assets/VCombobox-aJr--Ou7.f290ccf2ce25.js.br +0 -0
  267. codex/static_root/assets/VCombobox-aJr--Ou7.f290ccf2ce25.js.gz +0 -0
  268. codex/static_root/assets/VCombobox-aJr--Ou7.js.br +0 -0
  269. codex/static_root/assets/VCombobox-aJr--Ou7.js.gz +0 -0
  270. codex/static_root/assets/VDialog-61pzfUB2.33f73beb5224.js.br +0 -0
  271. codex/static_root/assets/VDialog-61pzfUB2.33f73beb5224.js.gz +0 -0
  272. codex/static_root/assets/VDialog-61pzfUB2.js.br +0 -0
  273. codex/static_root/assets/VDialog-61pzfUB2.js.gz +0 -0
  274. codex/static_root/assets/VExpansionPanels-rewm0P4z.5c7680f815b6.js.br +0 -0
  275. codex/static_root/assets/VExpansionPanels-rewm0P4z.5c7680f815b6.js.gz +0 -0
  276. codex/static_root/assets/VExpansionPanels-rewm0P4z.js.br +0 -0
  277. codex/static_root/assets/VExpansionPanels-rewm0P4z.js.gz +0 -0
  278. codex/static_root/assets/VRadioGroup-QFQbK1qo.750a42b1b814.js.br +0 -0
  279. codex/static_root/assets/VRadioGroup-QFQbK1qo.750a42b1b814.js.gz +0 -0
  280. codex/static_root/assets/VRadioGroup-QFQbK1qo.js.br +0 -0
  281. codex/static_root/assets/VRadioGroup-QFQbK1qo.js.gz +0 -0
  282. codex/static_root/assets/VSelect-Dixy6okt.5d53830daa8a.js.br +0 -0
  283. codex/static_root/assets/VSelect-Dixy6okt.5d53830daa8a.js.gz +0 -0
  284. codex/static_root/assets/VSelect-Dixy6okt.js.br +0 -0
  285. codex/static_root/assets/VSelect-Dixy6okt.js.gz +0 -0
  286. codex/static_root/assets/VSelectionControl-MNmxKc3J.08055d00917e.js.br +0 -0
  287. codex/static_root/assets/VSelectionControl-MNmxKc3J.08055d00917e.js.gz +0 -0
  288. codex/static_root/assets/VSelectionControl-MNmxKc3J.js.br +0 -0
  289. codex/static_root/assets/VSelectionControl-MNmxKc3J.js.gz +0 -0
  290. codex/static_root/assets/VSlideGroup-DZEV0FoV.5f996daf0e98.js.br +0 -0
  291. codex/static_root/assets/VSlideGroup-DZEV0FoV.5f996daf0e98.js.gz +0 -0
  292. codex/static_root/assets/VSlideGroup-DZEV0FoV.js.br +0 -0
  293. codex/static_root/assets/VSlideGroup-DZEV0FoV.js.gz +0 -0
  294. codex/static_root/assets/VTable-lcnYg9Ee.d72927b13c2e.js.br +0 -0
  295. codex/static_root/assets/VTable-lcnYg9Ee.d72927b13c2e.js.gz +0 -0
  296. codex/static_root/assets/VTable-lcnYg9Ee.js.br +0 -0
  297. codex/static_root/assets/VTable-lcnYg9Ee.js.gz +0 -0
  298. codex/static_root/assets/VTextField-BkFrjhdV.b02653a9b3b7.js.br +0 -0
  299. codex/static_root/assets/VTextField-BkFrjhdV.b02653a9b3b7.js.gz +0 -0
  300. codex/static_root/assets/VTextField-BkFrjhdV.js.br +0 -0
  301. codex/static_root/assets/VTextField-BkFrjhdV.js.gz +0 -0
  302. codex/static_root/assets/VWindowItem-C__tAqdc.9791c128c3b7.js.br +0 -0
  303. codex/static_root/assets/VWindowItem-C__tAqdc.9791c128c3b7.js.gz +0 -0
  304. codex/static_root/assets/VWindowItem-C__tAqdc.js.br +0 -0
  305. codex/static_root/assets/VWindowItem-C__tAqdc.js.gz +0 -0
  306. codex/static_root/assets/admin-CXES2HXe.9e48a9bf84e0.js +0 -1
  307. codex/static_root/assets/admin-CXES2HXe.9e48a9bf84e0.js.br +0 -0
  308. codex/static_root/assets/admin-CXES2HXe.9e48a9bf84e0.js.gz +0 -0
  309. codex/static_root/assets/admin-CXES2HXe.js +0 -1
  310. codex/static_root/assets/admin-CXES2HXe.js.br +0 -0
  311. codex/static_root/assets/admin-CXES2HXe.js.gz +0 -0
  312. codex/static_root/assets/admin-drawer-panel-rrNKi_GE.e2b034db7934.js.br +0 -0
  313. codex/static_root/assets/admin-drawer-panel-rrNKi_GE.e2b034db7934.js.gz +0 -0
  314. codex/static_root/assets/admin-drawer-panel-rrNKi_GE.js.br +0 -0
  315. codex/static_root/assets/admin-drawer-panel-rrNKi_GE.js.gz +0 -0
  316. codex/static_root/assets/browser-BuDeXGEe.css +0 -1
  317. codex/static_root/assets/browser-BuDeXGEe.css.br +0 -0
  318. codex/static_root/assets/browser-BuDeXGEe.css.gz +0 -0
  319. codex/static_root/assets/browser-BuDeXGEe.f60854183b45.css +0 -1
  320. codex/static_root/assets/browser-BuDeXGEe.f60854183b45.css.br +0 -0
  321. codex/static_root/assets/browser-BuDeXGEe.f60854183b45.css.gz +0 -0
  322. codex/static_root/assets/browser-s6mFzrK9.0d2200b451af.js +0 -1
  323. codex/static_root/assets/browser-s6mFzrK9.0d2200b451af.js.br +0 -0
  324. codex/static_root/assets/browser-s6mFzrK9.0d2200b451af.js.gz +0 -0
  325. codex/static_root/assets/browser-s6mFzrK9.js +0 -1
  326. codex/static_root/assets/browser-s6mFzrK9.js.br +0 -0
  327. codex/static_root/assets/browser-s6mFzrK9.js.gz +0 -0
  328. codex/static_root/assets/change-password-dialog-Bn20jYzD.593c5af1732b.js.br +0 -0
  329. codex/static_root/assets/change-password-dialog-Bn20jYzD.593c5af1732b.js.gz +0 -0
  330. codex/static_root/assets/change-password-dialog-Bn20jYzD.js.br +0 -0
  331. codex/static_root/assets/change-password-dialog-Bn20jYzD.js.gz +0 -0
  332. codex/static_root/assets/confirm-dialog-CWszioQE.859051c35dd9.js.br +0 -0
  333. codex/static_root/assets/confirm-dialog-CWszioQE.859051c35dd9.js.gz +0 -0
  334. codex/static_root/assets/confirm-dialog-CWszioQE.js.br +0 -0
  335. codex/static_root/assets/confirm-dialog-CWszioQE.js.gz +0 -0
  336. codex/static_root/assets/datetime-column-BSdlLt-4.27ec2df67a0b.js.br +0 -0
  337. codex/static_root/assets/datetime-column-BSdlLt-4.27ec2df67a0b.js.gz +0 -0
  338. codex/static_root/assets/datetime-column-BSdlLt-4.js.br +0 -0
  339. codex/static_root/assets/datetime-column-BSdlLt-4.js.gz +0 -0
  340. codex/static_root/assets/filter-D3gaGf87.1f14dbfd9929.js.br +0 -0
  341. codex/static_root/assets/filter-D3gaGf87.1f14dbfd9929.js.gz +0 -0
  342. codex/static_root/assets/filter-D3gaGf87.js.br +0 -0
  343. codex/static_root/assets/filter-D3gaGf87.js.gz +0 -0
  344. codex/static_root/assets/flag-tab-8vzpdySX.a982c7f0776a.js.br +0 -0
  345. codex/static_root/assets/flag-tab-8vzpdySX.a982c7f0776a.js.gz +0 -0
  346. codex/static_root/assets/flag-tab-8vzpdySX.js.br +0 -0
  347. codex/static_root/assets/flag-tab-8vzpdySX.js.gz +0 -0
  348. codex/static_root/assets/group-tab-Cz9t_ECi.a9e8aea79254.js.br +0 -0
  349. codex/static_root/assets/group-tab-Cz9t_ECi.a9e8aea79254.js.gz +0 -0
  350. codex/static_root/assets/group-tab-Cz9t_ECi.js.br +0 -0
  351. codex/static_root/assets/group-tab-Cz9t_ECi.js.gz +0 -0
  352. codex/static_root/assets/http-error-Cqtszzf1.b31df3d9c29f.js.br +0 -0
  353. codex/static_root/assets/http-error-Cqtszzf1.b31df3d9c29f.js.gz +0 -0
  354. codex/static_root/assets/http-error-Cqtszzf1.js.br +0 -0
  355. codex/static_root/assets/http-error-Cqtszzf1.js.gz +0 -0
  356. codex/static_root/assets/library-tab-DMlnswUU.30f454e84184.js.br +0 -0
  357. codex/static_root/assets/library-tab-DMlnswUU.30f454e84184.js.gz +0 -0
  358. codex/static_root/assets/library-tab-DMlnswUU.js.br +0 -0
  359. codex/static_root/assets/library-tab-DMlnswUU.js.gz +0 -0
  360. codex/static_root/assets/main-vjXu_QYL.548bd4c38799.js +0 -32
  361. codex/static_root/assets/main-vjXu_QYL.548bd4c38799.js.br +0 -0
  362. codex/static_root/assets/main-vjXu_QYL.548bd4c38799.js.gz +0 -0
  363. codex/static_root/assets/main-vjXu_QYL.js +0 -32
  364. codex/static_root/assets/main-vjXu_QYL.js.br +0 -0
  365. codex/static_root/assets/main-vjXu_QYL.js.gz +0 -0
  366. codex/static_root/assets/pagination-toolbar-DGdMiBRs.5829b01b8a2f.css +0 -1
  367. codex/static_root/assets/pagination-toolbar-DGdMiBRs.5829b01b8a2f.css.br +0 -0
  368. codex/static_root/assets/pagination-toolbar-DGdMiBRs.5829b01b8a2f.css.gz +0 -0
  369. codex/static_root/assets/pagination-toolbar-DGdMiBRs.css +0 -1
  370. codex/static_root/assets/pagination-toolbar-DGdMiBRs.css.br +0 -0
  371. codex/static_root/assets/pagination-toolbar-DGdMiBRs.css.gz +0 -0
  372. codex/static_root/assets/pagination-toolbar-JW78pa0q.91024effdab9.js +0 -1
  373. codex/static_root/assets/pagination-toolbar-JW78pa0q.91024effdab9.js.br +0 -0
  374. codex/static_root/assets/pagination-toolbar-JW78pa0q.91024effdab9.js.gz +0 -0
  375. codex/static_root/assets/pagination-toolbar-JW78pa0q.js +0 -1
  376. codex/static_root/assets/pagination-toolbar-JW78pa0q.js.br +0 -0
  377. codex/static_root/assets/pagination-toolbar-JW78pa0q.js.gz +0 -0
  378. codex/static_root/assets/pdf-doc-BiamrjRZ.4c9be1ade43c.js.br +0 -0
  379. codex/static_root/assets/pdf-doc-BiamrjRZ.4c9be1ade43c.js.gz +0 -0
  380. codex/static_root/assets/pdf-doc-BiamrjRZ.js.br +0 -0
  381. codex/static_root/assets/pdf-doc-BiamrjRZ.js.gz +0 -0
  382. codex/static_root/assets/reader-BpsctRsY.5d72e393911a.css.br +0 -0
  383. codex/static_root/assets/reader-BpsctRsY.5d72e393911a.css.gz +0 -0
  384. codex/static_root/assets/reader-BpsctRsY.css.br +0 -0
  385. codex/static_root/assets/reader-BpsctRsY.css.gz +0 -0
  386. codex/static_root/assets/reader-CDk8oZzB.ad62eebda920.js +0 -2
  387. codex/static_root/assets/reader-CDk8oZzB.ad62eebda920.js.br +0 -0
  388. codex/static_root/assets/reader-CDk8oZzB.ad62eebda920.js.gz +0 -0
  389. codex/static_root/assets/reader-CDk8oZzB.js +0 -2
  390. codex/static_root/assets/reader-CDk8oZzB.js.br +0 -0
  391. codex/static_root/assets/reader-CDk8oZzB.js.gz +0 -0
  392. codex/static_root/assets/relation-chips-C5acBjpy.dc67d4528868.js.br +0 -0
  393. codex/static_root/assets/relation-chips-C5acBjpy.dc67d4528868.js.gz +0 -0
  394. codex/static_root/assets/relation-chips-C5acBjpy.js.br +0 -0
  395. codex/static_root/assets/relation-chips-C5acBjpy.js.gz +0 -0
  396. codex/static_root/assets/settings-drawer-D_JuRi7F.f02f3f981f8f.js.br +0 -0
  397. codex/static_root/assets/settings-drawer-D_JuRi7F.f02f3f981f8f.js.gz +0 -0
  398. codex/static_root/assets/settings-drawer-D_JuRi7F.js.br +0 -0
  399. codex/static_root/assets/settings-drawer-D_JuRi7F.js.gz +0 -0
  400. codex/static_root/assets/stats-tab-ClqRTk1z.c759ace65a87.js.br +0 -0
  401. codex/static_root/assets/stats-tab-ClqRTk1z.c759ace65a87.js.gz +0 -0
  402. codex/static_root/assets/stats-tab-ClqRTk1z.js.br +0 -0
  403. codex/static_root/assets/stats-tab-ClqRTk1z.js.gz +0 -0
  404. codex/static_root/assets/task-tab-DF9qa6LO.0b32cafde4ad.js.br +0 -0
  405. codex/static_root/assets/task-tab-DF9qa6LO.0b32cafde4ad.js.gz +0 -0
  406. codex/static_root/assets/task-tab-DF9qa6LO.js.br +0 -0
  407. codex/static_root/assets/task-tab-DF9qa6LO.js.gz +0 -0
  408. codex/static_root/assets/to-case-CGbULRaE.4c80644f460d.js +0 -1
  409. codex/static_root/assets/to-case-CGbULRaE.4c80644f460d.js.br +0 -0
  410. codex/static_root/assets/to-case-CGbULRaE.js +0 -1
  411. codex/static_root/assets/to-case-CGbULRaE.js.br +0 -0
  412. codex/static_root/assets/unauthorized-BjKuLH6k.2ae00ddd79fb.js.br +0 -0
  413. codex/static_root/assets/unauthorized-BjKuLH6k.2ae00ddd79fb.js.gz +0 -0
  414. codex/static_root/assets/unauthorized-BjKuLH6k.js.br +0 -0
  415. codex/static_root/assets/unauthorized-BjKuLH6k.js.gz +0 -0
  416. codex/static_root/assets/user-tab-Dpxe3ygA.7d90174631f0.js.br +0 -0
  417. codex/static_root/assets/user-tab-Dpxe3ygA.7d90174631f0.js.gz +0 -0
  418. codex/static_root/assets/user-tab-Dpxe3ygA.js.br +0 -0
  419. codex/static_root/assets/user-tab-Dpxe3ygA.js.gz +0 -0
  420. codex/static_root/js/choices.a0aaaa6c7ef7.json.br +0 -0
  421. codex/static_root/js/choices.a0aaaa6c7ef7.json.gz +0 -0
  422. codex/static_root/manifest.35e46a3ec8fa.json.br +0 -0
  423. codex/static_root/manifest.35e46a3ec8fa.json.gz +0 -0
  424. {codex-1.6.0a10.dist-info → codex-1.6.0a12.dist-info}/LICENSE +0 -0
  425. {codex-1.6.0a10.dist-info → codex-1.6.0a12.dist-info}/WHEEL +0 -0
  426. {codex-1.6.0a10.dist-info → codex-1.6.0a12.dist-info}/entry_points.txt +0 -0
@@ -2,7 +2,6 @@
2
2
 
3
3
  from types import MappingProxyType
4
4
 
5
- from django.core.exceptions import FieldDoesNotExist
6
5
  from django.db.models import Count, IntegerField, Sum, Value
7
6
  from drf_spectacular.utils import extend_schema
8
7
  from rest_framework.exceptions import NotFound
@@ -15,6 +14,7 @@ from codex.logger.logging import get_logger
15
14
  from codex.models import AdminFlag, Comic
16
15
  from codex.models.functions import JsonGroupArray
17
16
  from codex.serializers.browser.metadata import PREFETCH_PREFIX, MetadataSerializer
17
+ from codex.serializers.browser.settings import BrowserFilterChoicesInputSerilalizer
18
18
  from codex.views.browser.annotations import BrowserAnnotationsView
19
19
  from codex.views.const import METADATA_GROUP_RELATION
20
20
 
@@ -42,13 +42,28 @@ _COMIC_RELATED_VALUE_FIELDS = frozenset({"series__volume_count", "volume__issue_
42
42
  _PATH_GROUPS = frozenset({"c", "f"})
43
43
  _CONTRIBUTOR_RELATIONS = ("role", "person")
44
44
  _SUM_FIELDS = frozenset({"page_count", "size"})
45
- _GROUP_RELS = frozenset({"publisher", "imprint", "series", "volume"})
45
+ _GROUP_RELS = MappingProxyType(
46
+ {
47
+ "i": ("publisher",),
48
+ "s": (
49
+ "publisher",
50
+ "imprint",
51
+ ),
52
+ "v": (
53
+ "publisher",
54
+ "imprint",
55
+ "series",
56
+ ),
57
+ "c": ("publisher", "imprint", "series", "volume"),
58
+ }
59
+ )
46
60
 
47
61
 
48
62
  class MetadataView(BrowserAnnotationsView):
49
63
  """Comic metadata."""
50
64
 
51
65
  serializer_class = MetadataSerializer
66
+ input_serializer_class = BrowserFilterChoicesInputSerilalizer
52
67
  TARGET = "metadata"
53
68
  ADMIN_FLAG_VALUE_KEY_MAP = MappingProxyType(
54
69
  {
@@ -156,19 +171,15 @@ class MetadataView(BrowserAnnotationsView):
156
171
  pks = self.kwargs["pks"]
157
172
  group_filter = {rel: pks}
158
173
 
159
- for field_name in _GROUP_RELS:
160
- try:
161
- field = self.model._meta.get_field(field_name)
162
- except FieldDoesNotExist:
163
- continue
174
+ for field_name in _GROUP_RELS.get(group, ()):
175
+ field = self.model._meta.get_field(field_name)
164
176
  model = field.related_model
165
177
  if not model:
166
178
  continue
167
179
 
168
180
  qs = model.objects.filter(**group_filter)
169
181
  qs = qs.only("name").distinct()
170
- group_by = self.get_group_by(model)
171
- qs = qs.group_by(group_by)
182
+ qs = qs.group_by("name")
172
183
  qs = qs.annotate(ids=JsonGroupArray("id", distinct=True))
173
184
  qs = qs.values("ids", "name")
174
185
  groups[field_name] = qs
@@ -228,8 +239,7 @@ class MetadataView(BrowserAnnotationsView):
228
239
  if self.model and not self.is_model_comic:
229
240
  # move the name of the group to the correct field
230
241
  field = self.model.__name__.lower() + "_list"
231
- group_obj = {"pk": obj.pk, "name": obj.name}
232
- group_list = [group_obj]
242
+ group_list = self.model.objects.filter(pk__in=obj.ids).values("name")
233
243
  setattr(obj, field, group_list)
234
244
  obj.name = None
235
245
 
@@ -312,7 +322,7 @@ class MetadataView(BrowserAnnotationsView):
312
322
  m2m_intersections = self._query_m2m_intersections(filtered_qs)
313
323
  return self._copy_annotations_into_comic_fields(obj, groups, m2m_intersections) # type: ignore
314
324
 
315
- @extend_schema(parameters=[BrowserAnnotationsView.input_serializer_class])
325
+ @extend_schema(parameters=[input_serializer_class])
316
326
  def get(self, *_args, **_kwargs):
317
327
  """Get metadata for a filtered browse group."""
318
328
  # Init
codex/views/const.py CHANGED
@@ -157,4 +157,4 @@ EPOCH_START = datetime.fromtimestamp(0, tz=timezone.utc)
157
157
  ONE_INTEGERFIELD = Value(1, PositiveSmallIntegerField())
158
158
  NONE_INTEGERFIELD = Value(None, PositiveSmallIntegerField())
159
159
  NONE_DATETIMEFIELD = Value(None, DateTimeField())
160
- EPOCH_START_DATETIMEFILED = Value(EPOCH_START)
160
+ EPOCH_START_DATETIMEFIELD = Value(EPOCH_START)
@@ -107,15 +107,19 @@ class ReaderInitView(SessionView):
107
107
  params["arc"] = arc
108
108
 
109
109
  def _parse_params(self):
110
- data = self.request.GET
111
- data = reparse_json_query_params(self.request.GET, _JSON_KEYS)
112
- serializer = self.input_serializer_class(data=data)
113
- serializer.is_valid(raise_exception=True)
114
-
115
- params = deepcopy(_DEFAULT_PARAMS)
116
- if serializer.validated_data:
117
- params.update(serializer.validated_data) # type: ignore
118
- self._ensure_arc_contains_comic(params)
119
- self._ensure_arc(params)
120
-
121
- self.params = MappingProxyType(params)
110
+ try:
111
+ data = self.request.GET
112
+ data = reparse_json_query_params(self.request.GET, _JSON_KEYS)
113
+ serializer = self.input_serializer_class(data=data)
114
+ serializer.is_valid(raise_exception=True)
115
+
116
+ params = deepcopy(_DEFAULT_PARAMS)
117
+ if serializer.validated_data:
118
+ params.update(serializer.validated_data) # type: ignore
119
+ self._ensure_arc_contains_comic(params)
120
+ self._ensure_arc(params)
121
+
122
+ self.params = MappingProxyType(params)
123
+ except Exception:
124
+ LOG.exception("validate")
125
+ raise
@@ -1,7 +1,9 @@
1
1
  """Views for reading comic books."""
2
2
 
3
+ from io import BytesIO
4
+
3
5
  from comicbox.box import Comicbox
4
- from django.http import HttpResponse
6
+ from django.http.response import StreamingHttpResponse
5
7
  from drf_spectacular.types import OpenApiTypes
6
8
  from drf_spectacular.utils import OpenApiParameter, extend_schema
7
9
  from rest_framework.exceptions import NotFound
@@ -11,9 +13,13 @@ from codex.logger.logging import get_logger
11
13
  from codex.models import Comic
12
14
  from codex.views.bookmark import BookmarkBaseView
13
15
  from codex.views.const import FALSY
16
+ from codex.views.util import chunker
14
17
 
15
18
  LOG = get_logger(__name__)
16
19
  _PDF_MIME_TYPE = "application/pdf"
20
+ # Most pages seem to be 2.5 Mb
21
+ # largest pages I've seen were 9 Mb
22
+ _PAGE_CHUNK_SIZE = (1024**2) * 3 # 3 Mb
17
23
 
18
24
 
19
25
  class IgnoreClientContentNegotiation(BaseContentNegotiation):
@@ -66,8 +72,12 @@ class ReaderPageView(BookmarkBaseView):
66
72
  content_type = _PDF_MIME_TYPE
67
73
  else:
68
74
  content_type = self.content_type
75
+
69
76
  with Comicbox(comic.path) as cb:
70
77
  page_image = cb.get_page_by_index(page, to_pixmap=to_pixmap)
78
+ if not page_image:
79
+ page_image = b""
80
+
71
81
  return page_image, content_type
72
82
 
73
83
  @extend_schema(
@@ -98,4 +108,5 @@ class ReaderPageView(BookmarkBaseView):
98
108
  LOG.warning(exc)
99
109
  raise NotFound(detail="comic page not found") from exc
100
110
  else:
101
- return HttpResponse(page_image, content_type=content_type)
111
+ page_chunker = chunker(BytesIO(page_image), _PAGE_CHUNK_SIZE)
112
+ return StreamingHttpResponse(page_chunker, content_type=content_type)
codex/views/session.py CHANGED
@@ -69,8 +69,10 @@ class SessionView(AuthFilterGenericAPIView, ABC):
69
69
  "top_group": DEFAULTS["topGroup"],
70
70
  },
71
71
  READER_SESSION_KEY: {
72
+ "finish_on_last_page": DEFAULTS["finishOnLastPage"],
72
73
  "fit_to": DEFAULTS["fitTo"],
73
- "two_pages": False,
74
+ "two_pages": DEFAULTS["twoPages"],
75
+ "read_rtl_in_reverse": DEFAULTS["readRtlInReverse"],
74
76
  "reading_direction": DEFAULTS["readingDirection"],
75
77
  },
76
78
  }
codex/views/util.py CHANGED
@@ -10,6 +10,9 @@ from urllib.parse import unquote_plus
10
10
  from djangorestframework_camel_case.settings import api_settings
11
11
  from djangorestframework_camel_case.util import underscoreize
12
12
 
13
+ # Maximum cover size is around 24 Kb
14
+ DEFAULT_CHUNK_SIZE = 64 * 1024 # 64 Kb
15
+
13
16
 
14
17
  @dataclass()
15
18
  class Route(dict):
@@ -62,3 +65,13 @@ def pop_name(kwargs: Mapping):
62
65
  kwargs = dict(kwargs)
63
66
  kwargs.pop("name", None)
64
67
  return kwargs
68
+
69
+
70
+ async def chunker(open_file, chunk_size=DEFAULT_CHUNK_SIZE):
71
+ """Asynchronous iterator for serving files."""
72
+ while True:
73
+ chunk = open_file.read(chunk_size)
74
+ if not chunk:
75
+ open_file.close()
76
+ break
77
+ yield chunk
@@ -48,6 +48,6 @@ class NotifierConsumer(AsyncWebsocketConsumer):
48
48
  """Send message to client."""
49
49
  text = event.get("text")
50
50
  if not text:
51
- LOG.warning("No text in message")
51
+ LOG.warning(f"No text in websockets message: {event}")
52
52
  return
53
53
  await self.send(text)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codex
3
- Version: 1.6.0a10
3
+ Version: 1.6.0a12
4
4
  Summary: A comic archive web server.
5
5
  Home-page: https://github.com/ajslater/codex
6
6
  License: GPL-3.0-only