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
Binary file
Binary file
@@ -1 +1 @@
1
- {"paths": {"rest_framework/docs/js/api.js": "rest_framework/docs/js/api.18a5ba8a1bd8.js", "rest_framework/docs/js/jquery.json-view.min.js": "rest_framework/docs/js/jquery.json-view.min.b7c2d6981377.js", "rest_framework/docs/js/highlight.pack.js": "rest_framework/docs/js/highlight.pack.479b5f21dcba.js", "rest_framework/docs/img/favicon.ico": "rest_framework/docs/img/favicon.5195b4d0f3eb.ico", "rest_framework/docs/img/grid.png": "rest_framework/docs/img/grid.a4b938cf382b.png", "rest_framework/docs/css/jquery.json-view.min.css": "rest_framework/docs/css/jquery.json-view.min.a2e6beeb6710.css", "rest_framework/docs/css/highlight.css": "rest_framework/docs/css/highlight.e0e4d973c6d7.css", "rest_framework/docs/css/base.css": "rest_framework/docs/css/base.e630f8f4990e.css", "rest_framework/js/ajax-form.js": "rest_framework/js/ajax-form.4e1cdcb7acab.js", "rest_framework/js/csrf.js": "rest_framework/js/csrf.455080a7b2ce.js", "rest_framework/js/prettify-min.js": "rest_framework/js/prettify-min.709bfcc456c6.js", "rest_framework/js/jquery-3.7.1.min.js": "rest_framework/js/jquery-3.7.1.min.2c872dbe60f4.js", "rest_framework/js/default.js": "rest_framework/js/default.5b08897dbdc3.js", "rest_framework/js/bootstrap.min.js": "rest_framework/js/bootstrap.min.2f34b630ffe3.js", "rest_framework/js/coreapi-0.1.1.js": "rest_framework/js/coreapi-0.1.1.8851fb9336c9.js", "rest_framework/js/load-ajax-form.js": "rest_framework/js/load-ajax-form.8cdb3a9f3466.js", "rest_framework/fonts/fontawesome-webfont.woff": "rest_framework/fonts/fontawesome-webfont.3293616ec0c6.woff", "rest_framework/fonts/glyphicons-halflings-regular.eot": "rest_framework/fonts/glyphicons-halflings-regular.f4769f9bdb74.eot", "rest_framework/fonts/glyphicons-halflings-regular.ttf": "rest_framework/fonts/glyphicons-halflings-regular.e18bbf611f2a.ttf", "rest_framework/fonts/fontawesome-webfont.ttf": "rest_framework/fonts/fontawesome-webfont.dcb26c7239d8.ttf", "rest_framework/fonts/glyphicons-halflings-regular.woff2": "rest_framework/fonts/glyphicons-halflings-regular.448c34a56d69.woff2", "rest_framework/fonts/fontawesome-webfont.svg": "rest_framework/fonts/fontawesome-webfont.83e37a11f9d7.svg", "rest_framework/fonts/glyphicons-halflings-regular.woff": "rest_framework/fonts/glyphicons-halflings-regular.fa2772327f55.woff", "rest_framework/fonts/glyphicons-halflings-regular.svg": "rest_framework/fonts/glyphicons-halflings-regular.08eda92397ae.svg", "rest_framework/fonts/fontawesome-webfont.eot": "rest_framework/fonts/fontawesome-webfont.8b27bc96115c.eot", "rest_framework/img/glyphicons-halflings-white.png": "rest_framework/img/glyphicons-halflings-white.9bbc6e960299.png", "rest_framework/img/glyphicons-halflings.png": "rest_framework/img/glyphicons-halflings.90233c9067e9.png", "rest_framework/img/grid.png": "rest_framework/img/grid.a4b938cf382b.png", "rest_framework/css/bootstrap.min.css.map": "rest_framework/css/bootstrap.min.css.cafbda9c0e9e.map", "rest_framework/css/default.css": "rest_framework/css/default.789dfb5732d7.css", "rest_framework/css/bootstrap.min.css": "rest_framework/css/bootstrap.min.f17d4516b026.css", "rest_framework/css/prettify.css": "rest_framework/css/prettify.a987f72342ee.css", "rest_framework/css/bootstrap-theme.min.css": "rest_framework/css/bootstrap-theme.min.1d4b05b397c3.css", "rest_framework/css/bootstrap-tweaks.css": "rest_framework/css/bootstrap-tweaks.ee4ee6acf9eb.css", "rest_framework/css/font-awesome-4.0.3.css": "rest_framework/css/font-awesome-4.0.3.c1e1ea213abf.css", "rest_framework/css/bootstrap-theme.min.css.map": "rest_framework/css/bootstrap-theme.min.css.51806092cc05.map", "img/publisher.svg": "img/publisher.82d378fcd601.svg", "img/logo-32.webp": "img/logo-32.5688944495bf.webp", "img/logo.svg": "img/logo.0f5344a028ca.svg", "img/story-arc.svg": "img/story-arc.ca10014355ef.svg", "img/missing-cover-165.webp": "img/missing-cover-165.0743171f2148.webp", "img/series.svg": "img/series.ec8a889b8f95.svg", "img/logo-maskable-180.webp": "img/logo-maskable-180.c58d966aa64e.webp", "img/missing-cover.svg": "img/missing-cover.ddb038cc2c56.svg", "img/folder.svg": "img/folder.f28936a3701d.svg", "img/volume.svg": "img/volume.814e4c79461a.svg", "img/logo-maskable.svg": "img/logo-maskable.8f7de7f1c6a8.svg", "img/imprint.svg": "img/imprint.7c2adebb76d6.svg", "pwa/offline.html": "pwa/offline.7bfaf9f94bf9.html", "js/choices.json": "js/choices.a0aaaa6c7ef7.json", "js/choices-admin.json": "js/choices-admin.3521e2a863df.json", "assets/relation-chips-Bsc-gUxE.css": "assets/relation-chips-Bsc-gUxE.98e65384c3c9.css", "assets/group-tab-CBKuS3Iv.css": "assets/group-tab-CBKuS3Iv.7e4746634782.css", "assets/http-error-DKulXuTl.css": "assets/http-error-DKulXuTl.95e42988d5d5.css", "assets/VSelect-ARDhJiQK.css": "assets/VSelect-ARDhJiQK.372c098fb475.css", "assets/flag-tab-BNwbLfrN.css": "assets/flag-tab-BNwbLfrN.b755a99fff7e.css", "assets/VSelect-Dixy6okt.js": "assets/VSelect-Dixy6okt.5d53830daa8a.js", "assets/browser-s6mFzrK9.js": "assets/browser-s6mFzrK9.0d2200b451af.js", "assets/settings-drawer-D_JuRi7F.js": "assets/settings-drawer-D_JuRi7F.f02f3f981f8f.js", "assets/change-password-dialog-Bn20jYzD.js": "assets/change-password-dialog-Bn20jYzD.593c5af1732b.js", "assets/VSelectionControl-BFq--28I.css": "assets/VSelectionControl-BFq--28I.9687c77461fc.css", "assets/pdf-doc-CMzaSV_K.css": "assets/pdf-doc-CMzaSV_K.8cd4b3e65f9a.css", "assets/VSelectionControl-MNmxKc3J.js": "assets/VSelectionControl-MNmxKc3J.08055d00917e.js", "assets/materialdesignicons-webfont-PXm3-2wK.woff": "assets/materialdesignicons-webfont-PXm3-2wK.026b7ac9c43c.woff", "assets/VSlideGroup-Dk_1upHt.css": "assets/VSlideGroup-Dk_1upHt.2c836070ec75.css", "assets/stats-tab-ClqRTk1z.js": "assets/stats-tab-ClqRTk1z.c759ace65a87.js", "assets/admin-drawer-panel-mne3FIj6.css": "assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css", "assets/VTable-DflzroDq.css": "assets/VTable-DflzroDq.160504d82195.css", "assets/settings-drawer-nZ9HvKSZ.css": "assets/settings-drawer-nZ9HvKSZ.01744e131806.css", "assets/VDialog-lQ13FnRR.css": "assets/VDialog-lQ13FnRR.1c801ad756b2.css", "assets/relation-chips-C5acBjpy.js": "assets/relation-chips-C5acBjpy.dc67d4528868.js", "assets/main-Ztp855PW.css": "assets/main-Ztp855PW.d46d718fac45.css", "assets/reader-BpsctRsY.css": "assets/reader-BpsctRsY.5d72e393911a.css", "assets/VTable-lcnYg9Ee.js": "assets/VTable-lcnYg9Ee.d72927b13c2e.js", "assets/reader-CDk8oZzB.js": "assets/reader-CDk8oZzB.ad62eebda920.js", "assets/VRadioGroup-QFQbK1qo.js": "assets/VRadioGroup-QFQbK1qo.750a42b1b814.js", "assets/VRadioGroup-i2qP9Wu9.css": "assets/VRadioGroup-i2qP9Wu9.8e3741381961.css", "assets/unauthorized-BjKuLH6k.js": "assets/unauthorized-BjKuLH6k.2ae00ddd79fb.js", "assets/VWindowItem-C__tAqdc.js": "assets/VWindowItem-C__tAqdc.9791c128c3b7.js", "assets/group-tab-Cz9t_ECi.js": "assets/group-tab-Cz9t_ECi.a9e8aea79254.js", "assets/VTextField-BkFrjhdV.js": "assets/VTextField-BkFrjhdV.b02653a9b3b7.js", "assets/VSlideGroup-DZEV0FoV.js": "assets/VSlideGroup-DZEV0FoV.5f996daf0e98.js", "assets/datetime-column-BSdlLt-4.js": "assets/datetime-column-BSdlLt-4.27ec2df67a0b.js", "assets/change-password-dialog-0u6IJA87.css": "assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css", "assets/VCombobox-aJr--Ou7.js": "assets/VCombobox-aJr--Ou7.f290ccf2ce25.js", "assets/user-tab-Dpxe3ygA.js": "assets/user-tab-Dpxe3ygA.7d90174631f0.js", "assets/copy-to-clipboard-DoUvDJVx.js": "assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js", "assets/library-tab-DMlnswUU.js": "assets/library-tab-DMlnswUU.30f454e84184.js", "assets/VWindowItem-ByIod57Y.css": "assets/VWindowItem-ByIod57Y.f7fb19752bf3.css", "assets/main-vjXu_QYL.js": "assets/main-vjXu_QYL.548bd4c38799.js", "assets/pagination-toolbar-DGdMiBRs.css": "assets/pagination-toolbar-DGdMiBRs.5829b01b8a2f.css", "assets/pagination-toolbar-JW78pa0q.js": "assets/pagination-toolbar-JW78pa0q.91024effdab9.js", "assets/flag-tab-8vzpdySX.js": "assets/flag-tab-8vzpdySX.a982c7f0776a.js", "assets/admin-drawer-panel-rrNKi_GE.js": "assets/admin-drawer-panel-rrNKi_GE.e2b034db7934.js", "assets/VDialog-61pzfUB2.js": "assets/VDialog-61pzfUB2.33f73beb5224.js", "assets/confirm-dialog-CWszioQE.js": "assets/confirm-dialog-CWszioQE.859051c35dd9.js", "assets/VCheckbox-CY3rcqlS.js": "assets/VCheckbox-CY3rcqlS.de5154294920.js", "assets/library-tab-BN0SfPcH.css": "assets/library-tab-BN0SfPcH.913e236f625e.css", "assets/VExpansionPanels-rewm0P4z.js": "assets/VExpansionPanels-rewm0P4z.5c7680f815b6.js", "assets/confirm-dialog-BmhedLCx.css": "assets/confirm-dialog-BmhedLCx.7c2103d319d4.css", "assets/materialdesignicons-webfont-B7mPwVP_.ttf": "assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf", "assets/VCombobox-BksEr4D_.css": "assets/VCombobox-BksEr4D_.73429bb75f42.css", "assets/to-case-CGbULRaE.js": "assets/to-case-CGbULRaE.4c80644f460d.js", "assets/admin-CXES2HXe.js": "assets/admin-CXES2HXe.9e48a9bf84e0.js", "assets/pdf-doc-BiamrjRZ.js": "assets/pdf-doc-BiamrjRZ.4c9be1ade43c.js", "assets/admin-B8Bp2Uih.css": "assets/admin-B8Bp2Uih.82c98714bcf1.css", "assets/task-tab-1XiWn9xP.css": "assets/task-tab-1XiWn9xP.06cb8e1b794d.css", "assets/stats-tab-B4yKuY0c.css": "assets/stats-tab-B4yKuY0c.a5728396494b.css", "assets/browser-BuDeXGEe.css": "assets/browser-BuDeXGEe.f60854183b45.css", "assets/datetime-column-DeCthByU.css": "assets/datetime-column-DeCthByU.1f3bf499e063.css", "assets/materialdesignicons-webfont-CSr8KVlo.eot": "assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot", "assets/task-tab-DF9qa6LO.js": "assets/task-tab-DF9qa6LO.0b32cafde4ad.js", "assets/http-error-Cqtszzf1.js": "assets/http-error-Cqtszzf1.b31df3d9c29f.js", "assets/VCheckboxBtn-D2tPTt6P.js": "assets/VCheckboxBtn-D2tPTt6P.9a90d6818bf6.js", "assets/VExpansionPanels-DsEXVcCv.css": "assets/VExpansionPanels-DsEXVcCv.20b475255e66.css", "assets/unauthorized-CibJYD8o.css": "assets/unauthorized-CibJYD8o.4c2de98c2b53.css", "assets/VCheckbox-CMKdyl0R.css": "assets/VCheckbox-CMKdyl0R.016ed8d222c4.css", "assets/filter-D3gaGf87.js": "assets/filter-D3gaGf87.1f14dbfd9929.js", "assets/VTextField-BssVoDhB.css": "assets/VTextField-BssVoDhB.4cc388b4aa3c.css", "assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "assets/materialdesignicons-webfont-Dp5v-WZN.1d7bcee1b302.woff2", "robots.txt": "robots.b6216d61c03e.txt", "manifest.json": "manifest.35e46a3ec8fa.json"}, "version": "1.1", "hash": "3eaef7cc048e"}
1
+ {"paths": {"rest_framework/docs/js/api.js": "rest_framework/docs/js/api.18a5ba8a1bd8.js", "rest_framework/docs/js/jquery.json-view.min.js": "rest_framework/docs/js/jquery.json-view.min.b7c2d6981377.js", "rest_framework/docs/js/highlight.pack.js": "rest_framework/docs/js/highlight.pack.479b5f21dcba.js", "rest_framework/docs/img/favicon.ico": "rest_framework/docs/img/favicon.5195b4d0f3eb.ico", "rest_framework/docs/img/grid.png": "rest_framework/docs/img/grid.a4b938cf382b.png", "rest_framework/docs/css/jquery.json-view.min.css": "rest_framework/docs/css/jquery.json-view.min.a2e6beeb6710.css", "rest_framework/docs/css/highlight.css": "rest_framework/docs/css/highlight.e0e4d973c6d7.css", "rest_framework/docs/css/base.css": "rest_framework/docs/css/base.e630f8f4990e.css", "rest_framework/js/ajax-form.js": "rest_framework/js/ajax-form.4e1cdcb7acab.js", "rest_framework/js/csrf.js": "rest_framework/js/csrf.455080a7b2ce.js", "rest_framework/js/prettify-min.js": "rest_framework/js/prettify-min.709bfcc456c6.js", "rest_framework/js/jquery-3.7.1.min.js": "rest_framework/js/jquery-3.7.1.min.2c872dbe60f4.js", "rest_framework/js/default.js": "rest_framework/js/default.5b08897dbdc3.js", "rest_framework/js/bootstrap.min.js": "rest_framework/js/bootstrap.min.2f34b630ffe3.js", "rest_framework/js/coreapi-0.1.1.js": "rest_framework/js/coreapi-0.1.1.8851fb9336c9.js", "rest_framework/js/load-ajax-form.js": "rest_framework/js/load-ajax-form.8cdb3a9f3466.js", "rest_framework/fonts/fontawesome-webfont.woff": "rest_framework/fonts/fontawesome-webfont.3293616ec0c6.woff", "rest_framework/fonts/glyphicons-halflings-regular.eot": "rest_framework/fonts/glyphicons-halflings-regular.f4769f9bdb74.eot", "rest_framework/fonts/glyphicons-halflings-regular.ttf": "rest_framework/fonts/glyphicons-halflings-regular.e18bbf611f2a.ttf", "rest_framework/fonts/fontawesome-webfont.ttf": "rest_framework/fonts/fontawesome-webfont.dcb26c7239d8.ttf", "rest_framework/fonts/glyphicons-halflings-regular.woff2": "rest_framework/fonts/glyphicons-halflings-regular.448c34a56d69.woff2", "rest_framework/fonts/fontawesome-webfont.svg": "rest_framework/fonts/fontawesome-webfont.83e37a11f9d7.svg", "rest_framework/fonts/glyphicons-halflings-regular.woff": "rest_framework/fonts/glyphicons-halflings-regular.fa2772327f55.woff", "rest_framework/fonts/glyphicons-halflings-regular.svg": "rest_framework/fonts/glyphicons-halflings-regular.08eda92397ae.svg", "rest_framework/fonts/fontawesome-webfont.eot": "rest_framework/fonts/fontawesome-webfont.8b27bc96115c.eot", "rest_framework/img/glyphicons-halflings-white.png": "rest_framework/img/glyphicons-halflings-white.9bbc6e960299.png", "rest_framework/img/glyphicons-halflings.png": "rest_framework/img/glyphicons-halflings.90233c9067e9.png", "rest_framework/img/grid.png": "rest_framework/img/grid.a4b938cf382b.png", "rest_framework/css/bootstrap.min.css.map": "rest_framework/css/bootstrap.min.css.cafbda9c0e9e.map", "rest_framework/css/default.css": "rest_framework/css/default.789dfb5732d7.css", "rest_framework/css/bootstrap.min.css": "rest_framework/css/bootstrap.min.f17d4516b026.css", "rest_framework/css/prettify.css": "rest_framework/css/prettify.a987f72342ee.css", "rest_framework/css/bootstrap-theme.min.css": "rest_framework/css/bootstrap-theme.min.1d4b05b397c3.css", "rest_framework/css/bootstrap-tweaks.css": "rest_framework/css/bootstrap-tweaks.ee4ee6acf9eb.css", "rest_framework/css/font-awesome-4.0.3.css": "rest_framework/css/font-awesome-4.0.3.c1e1ea213abf.css", "rest_framework/css/bootstrap-theme.min.css.map": "rest_framework/css/bootstrap-theme.min.css.51806092cc05.map", "img/publisher.svg": "img/publisher.82d378fcd601.svg", "img/logo-32.webp": "img/logo-32.5688944495bf.webp", "img/logo.svg": "img/logo.0f5344a028ca.svg", "img/story-arc.svg": "img/story-arc.ca10014355ef.svg", "img/missing-cover-165.webp": "img/missing-cover-165.0743171f2148.webp", "img/series.svg": "img/series.ec8a889b8f95.svg", "img/logo-maskable-180.webp": "img/logo-maskable-180.c58d966aa64e.webp", "img/missing-cover.svg": "img/missing-cover.ddb038cc2c56.svg", "img/folder.svg": "img/folder.f28936a3701d.svg", "img/volume.svg": "img/volume.814e4c79461a.svg", "img/logo-maskable.svg": "img/logo-maskable.8f7de7f1c6a8.svg", "img/imprint.svg": "img/imprint.7c2adebb76d6.svg", "pwa/offline.html": "pwa/offline.7bfaf9f94bf9.html", "js/choices.json": "js/choices.2f6b0359e1ef.json", "js/choices-admin.json": "js/choices-admin.3521e2a863df.json", "assets/relation-chips-Bsc-gUxE.css": "assets/relation-chips-Bsc-gUxE.98e65384c3c9.css", "assets/change-password-dialog-BCYw5K7E.js": "assets/change-password-dialog-BCYw5K7E.a8bae0450f20.js", "assets/group-tab-CBKuS3Iv.css": "assets/group-tab-CBKuS3Iv.7e4746634782.css", "assets/http-error-DKulXuTl.css": "assets/http-error-DKulXuTl.95e42988d5d5.css", "assets/VSelect-ARDhJiQK.css": "assets/VSelect-ARDhJiQK.372c098fb475.css", "assets/pdf-doc-CkV-xfvG.js": "assets/pdf-doc-CkV-xfvG.35c1a6a19a41.js", "assets/flag-tab-BNwbLfrN.css": "assets/flag-tab-BNwbLfrN.b755a99fff7e.css", "assets/VSelectionControl-BFq--28I.css": "assets/VSelectionControl-BFq--28I.9687c77461fc.css", "assets/library-tab-C5trLvkq.js": "assets/library-tab-C5trLvkq.35c7a1b79c71.js", "assets/http-error-DBQycf8i.js": "assets/http-error-DBQycf8i.561cde2b4598.js", "assets/user-tab-pzFjrggM.js": "assets/user-tab-pzFjrggM.97c02ebee729.js", "assets/VDialog-D6HUFV6a.js": "assets/VDialog-D6HUFV6a.ac71da510b3f.js", "assets/pdf-doc-CMzaSV_K.css": "assets/pdf-doc-CMzaSV_K.8cd4b3e65f9a.css", "assets/materialdesignicons-webfont-PXm3-2wK.woff": "assets/materialdesignicons-webfont-PXm3-2wK.026b7ac9c43c.woff", "assets/VSlideGroup-Dk_1upHt.css": "assets/VSlideGroup-Dk_1upHt.2c836070ec75.css", "assets/admin-drawer-panel-mne3FIj6.css": "assets/admin-drawer-panel-mne3FIj6.561b3f75fe65.css", "assets/VTable-DflzroDq.css": "assets/VTable-DflzroDq.160504d82195.css", "assets/settings-drawer-nZ9HvKSZ.css": "assets/settings-drawer-nZ9HvKSZ.01744e131806.css", "assets/VDialog-lQ13FnRR.css": "assets/VDialog-lQ13FnRR.1c801ad756b2.css", "assets/confirm-dialog-c9JOSGSy.js": "assets/confirm-dialog-c9JOSGSy.3c5788f95f47.js", "assets/main-Ztp855PW.css": "assets/main-Ztp855PW.d46d718fac45.css", "assets/VRadioGroup-i2qP9Wu9.css": "assets/VRadioGroup-i2qP9Wu9.8e3741381961.css", "assets/datetime-column-D-6LPKdI.js": "assets/datetime-column-D-6LPKdI.d46bbd8134df.js", "assets/change-password-dialog-0u6IJA87.css": "assets/change-password-dialog-0u6IJA87.5f9a9aa573b7.css", "assets/task-tab-B8sYV6Ia.js": "assets/task-tab-B8sYV6Ia.90a8deec0214.js", "assets/copy-to-clipboard-DoUvDJVx.js": "assets/copy-to-clipboard-DoUvDJVx.bec27f144aca.js", "assets/VWindowItem-ByIod57Y.css": "assets/VWindowItem-ByIod57Y.f7fb19752bf3.css", "assets/VSelect-ou2Q9UaN.js": "assets/VSelect-ou2Q9UaN.8ddd219784e1.js", "assets/admin-D5JDmLDy.js": "assets/admin-D5JDmLDy.e4df3dd3a3fe.js", "assets/browser-VhFkImB_.js": "assets/browser-VhFkImB_.9c3b2c746614.js", "assets/VSlideGroup-C3XgVg2T.js": "assets/VSlideGroup-C3XgVg2T.d2b0ee4f596c.js", "assets/flag-tab-IniE-dLy.js": "assets/flag-tab-IniE-dLy.a02733e359aa.js", "assets/VCombobox-wIqJY8no.js": "assets/VCombobox-wIqJY8no.3547ff73e91e.js", "assets/VTextField-HAAxrpNi.js": "assets/VTextField-HAAxrpNi.6f6dcb50079a.js", "assets/pagination-toolbar-DEgDOzzp.js": "assets/pagination-toolbar-DEgDOzzp.71aa03f525e4.js", "assets/library-tab-BN0SfPcH.css": "assets/library-tab-BN0SfPcH.913e236f625e.css", "assets/browser-B1-dPld9.css": "assets/browser-B1-dPld9.0b3fa4fdbe22.css", "assets/stats-tab-CBz_jhmH.js": "assets/stats-tab-CBz_jhmH.9bdc41225f06.js", "assets/confirm-dialog-BmhedLCx.css": "assets/confirm-dialog-BmhedLCx.7c2103d319d4.css", "assets/materialdesignicons-webfont-B7mPwVP_.ttf": "assets/materialdesignicons-webfont-B7mPwVP_.6e435534bd35.ttf", "assets/VCombobox-BksEr4D_.css": "assets/VCombobox-BksEr4D_.73429bb75f42.css", "assets/VTable-CrIiBr9q.js": "assets/VTable-CrIiBr9q.b4669247af45.js", "assets/admin-B8Bp2Uih.css": "assets/admin-B8Bp2Uih.82c98714bcf1.css", "assets/VCheckbox-B3vCf1Vu.js": "assets/VCheckbox-B3vCf1Vu.e1991f98ab6c.js", "assets/task-tab-1XiWn9xP.css": "assets/task-tab-1XiWn9xP.06cb8e1b794d.css", "assets/stats-tab-B4yKuY0c.css": "assets/stats-tab-B4yKuY0c.a5728396494b.css", "assets/reader-CqXFa_gE.css": "assets/reader-CqXFa_gE.78267e9de0c2.css", "assets/VExpansionPanels-BUJaYmzY.js": "assets/VExpansionPanels-BUJaYmzY.44e8a00a2ebe.js", "assets/datetime-column-DeCthByU.css": "assets/datetime-column-DeCthByU.1f3bf499e063.css", "assets/relation-chips-2vga5ApB.js": "assets/relation-chips-2vga5ApB.d94c344f909b.js", "assets/materialdesignicons-webfont-CSr8KVlo.eot": "assets/materialdesignicons-webfont-CSr8KVlo.8ced95a05e3c.eot", "assets/main-x0Pcl23A.js": "assets/main-x0Pcl23A.364bfe447c9c.js", "assets/group-tab-RPa8XC0J.js": "assets/group-tab-RPa8XC0J.3d483919ea92.js", "assets/VRadioGroup-CayclHra.js": "assets/VRadioGroup-CayclHra.0a5b1c9a7b71.js", "assets/VCheckboxBtn-Cj6bUYmw.js": "assets/VCheckboxBtn-Cj6bUYmw.196cc43ca1c8.js", "assets/VSelectionControl-BOKIwNZb.js": "assets/VSelectionControl-BOKIwNZb.16e0cdde978c.js", "assets/admin-drawer-panel-BF-h3Wm0.js": "assets/admin-drawer-panel-BF-h3Wm0.1f372db8d08f.js", "assets/VWindowItem-aal6-Uv4.js": "assets/VWindowItem-aal6-Uv4.d178e2af20a7.js", "assets/VExpansionPanels-DsEXVcCv.css": "assets/VExpansionPanels-DsEXVcCv.20b475255e66.css", "assets/pagination-toolbar-BLUoVz2y.css": "assets/pagination-toolbar-BLUoVz2y.50051431acf1.css", "assets/reader-ClcgSG93.js": "assets/reader-ClcgSG93.6afe950e70ac.js", "assets/unauthorized-D5-FvA2_.js": "assets/unauthorized-D5-FvA2_.61b1cd239b47.js", "assets/unauthorized-CibJYD8o.css": "assets/unauthorized-CibJYD8o.4c2de98c2b53.css", "assets/VCheckbox-CMKdyl0R.css": "assets/VCheckbox-CMKdyl0R.016ed8d222c4.css", "assets/settings-drawer-BOTI_tHr.js": "assets/settings-drawer-BOTI_tHr.03748f801e08.js", "assets/VTextField-BssVoDhB.css": "assets/VTextField-BssVoDhB.4cc388b4aa3c.css", "assets/filter-BOnVoHTU.js": "assets/filter-BOnVoHTU.93c3d0d0d3f6.js", "assets/to-case-CnnzURtN.js": "assets/to-case-CnnzURtN.f0e4b42ddb89.js", "assets/materialdesignicons-webfont-Dp5v-WZN.woff2": "assets/materialdesignicons-webfont-Dp5v-WZN.1d7bcee1b302.woff2", "robots.txt": "robots.b6216d61c03e.txt", "manifest.json": "manifest.a18726680d5f.json"}, "version": "1.1", "hash": "8941f2cb0fed"}
codex/util.py CHANGED
@@ -1,10 +1,12 @@
1
1
  """Utility functions."""
2
2
 
3
3
 
4
- def max_none(a, b):
4
+ def max_none(*args):
5
5
  """None aware math.max."""
6
- if a is not None and b is not None:
7
- return max(a, b)
8
- if a is None:
9
- return b
10
- return a
6
+ max_arg = None
7
+ for arg in args:
8
+ if max_arg is None:
9
+ max_arg = arg
10
+ elif arg is not None:
11
+ max_arg = max(max_arg, arg)
12
+ return max_arg
codex/views/bookmark.py CHANGED
@@ -88,8 +88,10 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
88
88
 
89
89
  def _update_bookmarks(self, search_kwargs, updates):
90
90
  """Update existing bookmarks."""
91
+ count = 0
92
+ finished = False
91
93
  if not updates:
92
- return 0
94
+ return count, finished
93
95
  group_acl_filter = self.get_group_acl_filter(Bookmark)
94
96
  update_fields = set(updates.keys()) & _BOOKMARK_UPDATE_FIELDS
95
97
  update_fields.add("updated_at")
@@ -106,14 +108,16 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
106
108
  for bm in existing_bookmarks:
107
109
  self._update_bookmarks_validate_page(bm, updates)
108
110
  self._update_bookmarks_validate_two_pages(bm, updates)
111
+ old_finished = bm.finished
109
112
  for key, value in updates.items():
110
113
  setattr(bm, key, value)
111
114
  bm.updated_at = Now()
112
115
  update_bookmarks.append(bm)
116
+ finished = finished or old_finished != bm.finished
113
117
  count = len(update_bookmarks)
114
118
  if count:
115
119
  Bookmark.objects.bulk_update(update_bookmarks, tuple(update_fields))
116
- return count
120
+ return count, finished
117
121
  # LOG.debug(f"Updated {count} bookmarks.")
118
122
 
119
123
  @staticmethod
@@ -127,9 +131,11 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
127
131
 
128
132
  def _create_bookmarks(self, comic_filter, search_kwargs, updates):
129
133
  """Create new bookmarks for comics that don't exist yet."""
134
+ count = 0
135
+ finished = False
130
136
  self._create_bookmarks_validate_two_pages(updates)
131
137
  if not updates:
132
- return 0
138
+ return count, finished
133
139
  create_bookmarks = []
134
140
  group_acl_filter = self.get_group_acl_filter(Comic)
135
141
  exclude = {}
@@ -141,6 +147,7 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
141
147
  .exclude(**exclude)
142
148
  .only(*_COMIC_ONLY_FIELDS)
143
149
  )
150
+ finished = False
144
151
  for comic in create_bookmark_comics:
145
152
  defaults = {"comic": comic}
146
153
  defaults.update(updates)
@@ -149,10 +156,6 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
149
156
  defaults[key] = value
150
157
 
151
158
  bm = Bookmark(**defaults)
152
- if updates.get("page") == comic.max_page:
153
- # Auto finish on bookmark last page
154
- # This almost never happens. Possibly never.
155
- bm.finished = True
156
159
  create_bookmarks.append(bm)
157
160
  count = len(create_bookmarks)
158
161
  if count:
@@ -161,15 +164,20 @@ class BookmarkBaseView(AuthFilterGenericAPIView):
161
164
  update_fields=tuple(_BOOKMARK_UPDATE_FIELDS),
162
165
  unique_fields=Bookmark._meta.unique_together[0], # type: ignore
163
166
  )
167
+ finished = updates.get("finished", False)
164
168
  # LOG.debug(f"Create {count} bookmarks.")
165
- return count
169
+ return count, finished
166
170
 
167
171
  def update_bookmarks(self, updates, comic_filter):
168
172
  """Update a user bookmark."""
169
173
  search_kwargs = self.get_bookmark_search_kwargs(comic_filter)
170
- count = self._update_bookmarks(search_kwargs, updates)
171
- count += self._create_bookmarks(comic_filter, search_kwargs, updates)
172
- if count and "finished" in updates:
174
+ count, finished = self._update_bookmarks(search_kwargs, updates)
175
+ create_count, create_finished = self._create_bookmarks(
176
+ comic_filter, search_kwargs, updates
177
+ )
178
+ count += create_count
179
+ finished = finished or create_finished
180
+ if count and finished:
173
181
  self.notify_library_changed()
174
182
 
175
183
 
@@ -178,8 +186,12 @@ class BookmarkView(BookmarkBaseView):
178
186
 
179
187
  serializer_class = BookmarkSerializer
180
188
 
181
- def _validate(self, serializer_class):
189
+ def _parse_params(self):
182
190
  """Validate and translate the submitted data."""
191
+ group = self.kwargs.get("group")
192
+ # If the target is recursive, strip everything but finished state data.
193
+ serializer_class = None if group == "c" else BookmarkFinishedSerializer
194
+
183
195
  data = self.request.data # type: ignore
184
196
  if serializer_class:
185
197
  serializer = serializer_class(data=data, partial=True)
@@ -191,18 +203,12 @@ class BookmarkView(BookmarkBaseView):
191
203
  @extend_schema(request=serializer_class, responses=None)
192
204
  def patch(self, *_args, **_kwargs):
193
205
  """Update bookmarks recursively."""
194
- group = self.kwargs.get("group")
195
- # If the target is recursive, strip everything but finished state data.
196
- serializer_class = None if group == "c" else BookmarkFinishedSerializer
197
-
198
- updates = self._validate(serializer_class)
206
+ updates = self._parse_params()
199
207
 
208
+ group = self.kwargs.get("group")
200
209
  pks = self.kwargs.get("pks")
210
+ rel = "folders__in" if group == FOLDER_GROUP else GROUP_RELATION[group] + "__in"
211
+ comic_filter = {rel: pks}
201
212
 
202
- relation = (
203
- "folders__in" if group == FOLDER_GROUP else GROUP_RELATION[group] + "__in"
204
- )
205
- comic_filter = {relation: pks}
206
-
207
- self.update_bookmarks(updates, comic_filter=comic_filter)
213
+ self.update_bookmarks(updates, comic_filter)
208
214
  return Response()
@@ -9,17 +9,14 @@ from django.db.models import (
9
9
  Case,
10
10
  F,
11
11
  FilteredRelation,
12
- Max,
13
12
  Min,
14
13
  Q,
15
14
  Sum,
16
15
  Value,
17
16
  When,
18
17
  )
19
- from django.db.models.expressions import OuterRef
20
18
  from django.db.models.fields import CharField, PositiveSmallIntegerField
21
- from django.db.models.functions import Coalesce, Least, Reverse, Right, StrIndex
22
- from django.db.models.functions.comparison import Greatest
19
+ from django.db.models.functions import Least, Reverse, Right, StrIndex
23
20
 
24
21
  from codex.logger.logging import get_logger
25
22
  from codex.models import (
@@ -34,7 +31,6 @@ from codex.views.browser.order_by import (
34
31
  BrowserOrderByView,
35
32
  )
36
33
  from codex.views.const import (
37
- EPOCH_START,
38
34
  NONE_DATETIMEFIELD,
39
35
  NONE_INTEGERFIELD,
40
36
  STORY_ARC_GROUP,
@@ -161,28 +157,15 @@ class BrowserAnnotationsView(BrowserOrderByView, SharedAnnotationsMixin):
161
157
  qs = qs.annotate(page_count=page_count_sum)
162
158
  return qs
163
159
 
164
- def get_bookmark_updated_at_aggregate(self, model, always_max=False):
165
- """Get The aggregate function for relevant bookmark.updated_at."""
160
+ def _annotate_bookmark_updated_at(self, qs, model):
161
+ if not self.is_opds_1_acquisition and self.order_key != "bookmark_updated_at":
162
+ return qs
166
163
  bm_rel, bm_filter = self.get_bookmark_rel_and_filter(model)
167
-
168
164
  bm_updated_at_rel = f"{bm_rel}__updated_at"
169
- agg_func = Max if always_max else self.order_agg_func
170
- return agg_func(bm_updated_at_rel, default=NONE_DATETIMEFIELD, filter=bm_filter)
171
-
172
- def _annotate_bookmark_updated_at(self, qs, model):
173
- if (
174
- self.is_opds_1_acquisition
175
- or self.order_key == "bookmark_updated_at"
176
- or self.is_bookmark_filtered
177
- ):
178
- bookmark_updated_at_aggregate = self.get_bookmark_updated_at_aggregate(
179
- model
180
- )
181
- if self.TARGET == "opds1" or self.is_bookmark_filtered:
182
- qs = qs.annotate(bookmark_updated_at=bookmark_updated_at_aggregate)
183
- else:
184
- qs = qs.alias(bookmark_updated_at=bookmark_updated_at_aggregate)
185
- return qs
165
+ bmua_agg = self.order_agg_func(
166
+ bm_updated_at_rel, default=NONE_DATETIMEFIELD, filter=bm_filter
167
+ )
168
+ return qs.annotate(bookmark_updated_at=bmua_agg)
186
169
 
187
170
  def _annotate_order_value(self, qs, model):
188
171
  """Annotate a main key for sorting and browser card display."""
@@ -208,7 +191,6 @@ class BrowserAnnotationsView(BrowserOrderByView, SharedAnnotationsMixin):
208
191
 
209
192
  def annotate_order_aggregates(self, qs, model):
210
193
  """Annotate common aggregates between browser and metadata."""
211
- # ids coming first or before cover_qs works.
212
194
  qs = qs.annotate(ids=JsonGroupArray("id", distinct=True))
213
195
  qs = self._alias_sort_names(qs, model)
214
196
  qs = self._alias_filename(qs, model)
@@ -299,24 +281,6 @@ class BrowserAnnotationsView(BrowserOrderByView, SharedAnnotationsMixin):
299
281
  progress = Case(When(page_count__gt=0, then=then), default=0.0)
300
282
  return qs.annotate(progress=progress)
301
283
 
302
- def _annotate_mtime(self, qs, model):
303
- """Annotations mtime."""
304
- if self.is_bookmark_filtered:
305
- sub_qs = self.get_filtered_queryset(model, bookmark_filter=False)
306
- bm_rel, bm_filter = self.get_bookmark_rel_and_filter(model)
307
- ua_rel = bm_rel + "__updated_at"
308
- qs = qs.annotate(
309
- bmu_max=Max(
310
- sub_qs.filter(pk=OuterRef("pk")).values_list(ua_rel, flat=True),
311
- default=NONE_DATETIMEFIELD,
312
- filter=bm_filter,
313
- )
314
- )
315
- mtime = Greatest(Coalesce("bmu_max", Value(EPOCH_START)), "updated_at")
316
- else:
317
- mtime = F("updated_at")
318
- return qs.annotate(mtime=mtime)
319
-
320
284
  def annotate_card_aggregates(self, qs, model):
321
285
  """Annotate aggregates that appear the browser card."""
322
286
  if model == Comic:
@@ -326,4 +290,4 @@ class BrowserAnnotationsView(BrowserOrderByView, SharedAnnotationsMixin):
326
290
  qs = self.annotate_group_names(qs, model)
327
291
  qs = self._annotate_bookmarks(qs, model)
328
292
  qs = self._annotate_progress(qs)
329
- return self._annotate_mtime(qs, model)
293
+ return qs.annotate(updated_ats=JsonGroupArray("updated_at", distinct=True))
@@ -23,6 +23,7 @@ from codex.views.browser.title import BrowserTitleView
23
23
  from codex.views.const import (
24
24
  COMIC_GROUP,
25
25
  FOLDER_GROUP,
26
+ NONE_DATETIMEFIELD,
26
27
  STORY_ARC_GROUP,
27
28
  )
28
29
 
@@ -149,13 +150,23 @@ class BrowserView(BrowserTitleView):
149
150
  count = 0
150
151
  return qs, count
151
152
 
152
- def _get_page_mtime(self):
153
- if not self.is_bookmark_filtered and self.group_instance:
154
- # Nice optimization if we can get get it.
155
- return self.group_instance.updated_at
153
+ def _requery_max_bookmark_updated_at(self, group_qs):
154
+ """Get max updated at without bookmark filter and aware of multi-groups."""
155
+ if not self.is_bookmark_filtered:
156
+ return group_qs
156
157
 
157
- group_model = self.group_class if self.group_class else self.model
158
- return self.get_group_mtime(group_model, page_mtime=True)
158
+ bm_rel, bm_filter = self.get_bookmark_rel_and_filter(self.model)
159
+ bm_updated_at_rel = f"{bm_rel}__updated_at"
160
+ max_bmua = Max(bm_updated_at_rel, default=NONE_DATETIMEFIELD, filter=bm_filter)
161
+
162
+ group_list = []
163
+ for group in group_qs:
164
+ qs = self.get_filtered_queryset(
165
+ self.model, bookmark_filter=False, group_filter=False
166
+ )
167
+ group.max_bookmark_updated_at = qs.aggregate(max=max_bmua)["max"]
168
+ group_list.append(group)
169
+ return group_list
159
170
 
160
171
  @staticmethod
161
172
  def _get_zero_pad(book_qs):
@@ -168,6 +179,14 @@ class BrowserView(BrowserTitleView):
168
179
  zero_pad += floor(log10(issue_number_max))
169
180
  return zero_pad
170
181
 
182
+ def _get_page_mtime(self):
183
+ if not self.is_bookmark_filtered and self.group_instance:
184
+ # Nice optimization if we can get get it.
185
+ return self.group_instance.updated_at
186
+
187
+ group_model = self.group_class if self.group_class else self.model
188
+ return self.get_group_mtime(group_model, page_mtime=True)
189
+
171
190
  def _get_group_and_books(self):
172
191
  """Create the main queries with filters, annotation and pagination."""
173
192
  group_qs, group_count = self._get_group_queryset()
@@ -178,6 +197,7 @@ class BrowserView(BrowserTitleView):
178
197
  )
179
198
  if page_group_count:
180
199
  group_qs = self.annotate_card_aggregates(group_qs, self.model)
200
+ group_qs = self._requery_max_bookmark_updated_at(group_qs)
181
201
  if page_book_count:
182
202
  zero_pad = self._get_zero_pad(book_qs)
183
203
  book_qs = self.annotate_card_aggregates(book_qs, Comic)
@@ -2,7 +2,6 @@
2
2
 
3
3
  from types import MappingProxyType
4
4
 
5
- import pycountry
6
5
  from caseconverter import snakecase
7
6
  from django.db.models import QuerySet
8
7
  from drf_spectacular.utils import extend_schema
@@ -22,7 +21,7 @@ from codex.serializers.browser.filters import (
22
21
  BrowserFilterChoicesSerializer,
23
22
  )
24
23
  from codex.serializers.browser.settings import BrowserFilterChoicesInputSerilalizer
25
- from codex.serializers.models.pycountry import PyCountrySerializer
24
+ from codex.serializers.choices import DUMMY_NULL_NAME, VUETIFY_NULL_CODE
26
25
  from codex.views.browser.filters.annotations import (
27
26
  BrowserAnnotationsFilterView,
28
27
  )
@@ -52,7 +51,7 @@ _BACK_REL_MAP = MappingProxyType(
52
51
  IdentifierType: "identifier__",
53
52
  }
54
53
  )
55
- _NULL_NAMED_ROW = MappingProxyType({"pk": -1, "name": "_none_"})
54
+ _NULL_NAMED_ROW = MappingProxyType({"pk": VUETIFY_NULL_CODE, "name": DUMMY_NULL_NAME})
56
55
 
57
56
 
58
57
  class BrowserChoicesViewBase(BrowserAnnotationsFilterView):
@@ -170,24 +169,6 @@ class BrowserChoicesView(BrowserChoicesViewBase):
170
169
 
171
170
  serializer_class = BrowserChoicesFilterSerializer
172
171
 
173
- def _get_field_choices(self, comic_qs, field_name):
174
- """Create a pk:name object for fields without tables."""
175
- qs = self.get_field_choices_query(comic_qs, field_name)
176
-
177
- if field_name == "country":
178
- lookup = pycountry.countries
179
- elif field_name == "language":
180
- lookup = pycountry.languages
181
- else:
182
- lookup = None
183
-
184
- choices = []
185
- for val in qs:
186
- name = PyCountrySerializer.lookup_name(lookup, val) if lookup else val
187
- choices.append({"pk": val, "name": name})
188
-
189
- return choices
190
-
191
172
  def _get_m2m_field_choices(self, model, comic_qs, rel):
192
173
  """Get choices with nulls where there are nulls."""
193
174
  qs = self.get_m2m_field_query(model, comic_qs)
@@ -216,7 +197,8 @@ class BrowserChoicesView(BrowserChoicesViewBase):
216
197
  if m2m_model:
217
198
  choices = self._get_m2m_field_choices(m2m_model, qs, rel)
218
199
  else:
219
- choices = self._get_field_choices(qs, rel)
200
+ choices = self.get_field_choices_query(qs, field_name)
201
+
220
202
  return {
221
203
  "field_name": field_name,
222
204
  "choices": choices,
@@ -1,6 +1,7 @@
1
1
  """Comic cover thumbnail view."""
2
2
 
3
- from django.http import HttpResponse
3
+ from django.db.models.query import Q
4
+ from django.http.response import StreamingHttpResponse
4
5
  from drf_spectacular.types import OpenApiTypes
5
6
  from drf_spectacular.utils import extend_schema
6
7
  from rest_framework.renderers import BaseRenderer
@@ -15,10 +16,12 @@ from codex.serializers.browser.settings import BrowserCoverInputSerializer
15
16
  from codex.views.browser.annotations import BrowserAnnotationsView
16
17
  from codex.views.const import (
17
18
  CUSTOM_COVER_GROUP_RELATION,
19
+ GROUP_RELATION,
18
20
  MISSING_COVER_FN,
19
21
  MISSING_COVER_NAME_MAP,
20
22
  STATIC_IMG_PATH,
21
23
  )
24
+ from codex.views.util import chunker
22
25
 
23
26
  LOG = get_logger(__name__)
24
27
 
@@ -43,6 +46,29 @@ class CoverView(BrowserAnnotationsView):
43
46
  renderer_classes = (WEBPRenderer,)
44
47
  content_type = "image/webp"
45
48
  TARGET = "cover"
49
+ REPARSE_JSON_FIELDS = frozenset(
50
+ BrowserAnnotationsView.REPARSE_JSON_FIELDS | {"parent"}
51
+ )
52
+
53
+ def get_group_filter(self, group=None, pks=None, page_mtime=False):
54
+ """Get group filter for First Cover View."""
55
+ if self.params.get("dynamic_covers") or self.model == Volume:
56
+ return super().get_group_filter(group=group, pks=pks, page_mtime=page_mtime)
57
+
58
+ # First cover group filter relies on sort names to look outside the browser supplied pks
59
+ # For multi_groups not in the browser query.
60
+ pks = self.kwargs["pks"]
61
+ qs = self.model.objects.filter(pk__in=pks) # type: ignore
62
+ sort_names = qs.values_list("sort_name", flat=True).distinct()
63
+ model_rel = GROUP_RELATION[self.model_group]
64
+ group_filter = {f"{model_rel}__sort_name__in": sort_names}
65
+
66
+ parent = self.params["parent"]
67
+ parent_pks = parent.get("pks", ())
68
+ if parent_pks:
69
+ parent_rel = GROUP_RELATION[parent["group"]]
70
+ group_filter[f"{parent_rel}__pk__in"] = parent_pks
71
+ return Q(**group_filter)
46
72
 
47
73
  def get_model_group(self):
48
74
  """Return the url group."""
@@ -107,24 +133,21 @@ class CoverView(BrowserAnnotationsView):
107
133
  return cover_path, content_type
108
134
 
109
135
  def _get_cover_data(self, pk, custom):
110
- thumb_image_data = None
136
+ thumb_buffer = None
111
137
  content_type = "image/webp"
112
138
 
113
139
  cover_path = CoverPathMixin.get_cover_path(pk, custom)
114
140
  if not cover_path.exists():
115
- thumb_image_data = CoverCreateMixin.create_cover_from_path(
141
+ thumb_buffer = CoverCreateMixin.create_cover_from_path(
116
142
  pk, cover_path, LOG, LIBRARIAN_QUEUE, custom
117
143
  )
118
- if not thumb_image_data:
144
+ if not thumb_buffer:
119
145
  cover_path, content_type = self._get_missing_cover_path()
120
146
  elif cover_path.stat().st_size == 0:
121
147
  cover_path, content_type = self._get_missing_cover_path()
122
148
 
123
- if not thumb_image_data:
124
- # if not thumb_image_data:
125
- with cover_path.open("rb") as f:
126
- thumb_image_data = f.read()
127
- return thumb_image_data, content_type
149
+ cover_file = thumb_buffer if thumb_buffer else cover_path.open("rb")
150
+ return cover_file, content_type
128
151
 
129
152
  @extend_schema(
130
153
  parameters=[BrowserAnnotationsView.input_serializer_class],
@@ -135,7 +158,8 @@ class CoverView(BrowserAnnotationsView):
135
158
  try:
136
159
  self.init_request()
137
160
  pk, custom = self._get_cover_pk()
138
- thumb_image_data, content_type = self._get_cover_data(pk, custom)
139
- return HttpResponse(thumb_image_data, content_type=content_type)
161
+ cover_file, content_type = self._get_cover_data(pk, custom)
162
+
163
+ return StreamingHttpResponse(chunker(cover_file), content_type=content_type)
140
164
  except Exception:
141
165
  LOG.exception("get")
@@ -7,7 +7,7 @@ from codex.models.comic import Comic
7
7
  from codex.views.browser.filters.bookmark import BookmarkFilterMixin
8
8
  from codex.views.browser.validate import BrowserValidateView
9
9
  from codex.views.const import (
10
- EPOCH_START_DATETIMEFILED,
10
+ EPOCH_START_DATETIMEFIELD,
11
11
  ONE_INTEGERFIELD,
12
12
  )
13
13
 
@@ -20,13 +20,17 @@ class BrowserAnnotationsFilterView(BrowserValidateView, BookmarkFilterMixin):
20
20
  super().__init__(*args, **kwargs)
21
21
  self.init_bookmark_data()
22
22
 
23
- def _get_query_filters(self, model, group, pks, bookmark_filter, page_mtime=False): # noqa: PLR0913
23
+ def _get_query_filters( # noqa: PLR0913
24
+ self, model, group, pks, bookmark_filter, page_mtime=False, group_filter=True
25
+ ):
24
26
  """Return all the filters except the group filter."""
27
+ # TODO all these ifs and flags are awful
25
28
  object_filter = self.get_group_acl_filter(model)
26
- object_filter &= self.get_group_filter(group, pks, page_mtime=page_mtime)
29
+ if group_filter:
30
+ object_filter &= self.get_group_filter(group, pks, page_mtime=page_mtime)
27
31
  object_filter &= self.get_comic_field_filter(model)
28
32
  if bookmark_filter:
29
- # not needed because OuterRef is applied next
33
+ # not needed when used by outerrefl OuterRef is applied next
30
34
  object_filter &= self.get_bookmark_filter(model)
31
35
  return object_filter
32
36
 
@@ -46,11 +50,22 @@ class BrowserAnnotationsFilterView(BrowserValidateView, BookmarkFilterMixin):
46
50
  return qs
47
51
 
48
52
  def get_filtered_queryset( # noqa: PLR0913
49
- self, model, group=None, pks=None, bookmark_filter=True, page_mtime=False
53
+ self,
54
+ model,
55
+ group=None,
56
+ pks=None,
57
+ bookmark_filter=True,
58
+ page_mtime=False,
59
+ group_filter=True,
50
60
  ):
51
61
  """Get a filtered queryset for the model."""
52
62
  object_filter = self._get_query_filters(
53
- model, group, pks, bookmark_filter, page_mtime=page_mtime
63
+ model,
64
+ group,
65
+ pks,
66
+ bookmark_filter,
67
+ page_mtime=page_mtime,
68
+ group_filter=group_filter,
54
69
  )
55
70
  qs = model.objects.filter(object_filter)
56
71
  qs = self.apply_search_filter(qs, model)
@@ -73,12 +88,12 @@ class BrowserAnnotationsFilterView(BrowserValidateView, BookmarkFilterMixin):
73
88
  ua_rel = bm_rel + "__updated_at"
74
89
  mbua = Max(ua_rel)
75
90
  else:
76
- mbua = EPOCH_START_DATETIMEFILED
91
+ mbua = EPOCH_START_DATETIMEFIELD
77
92
  qs = qs.annotate(max_bookmark_updated_at=mbua)
78
93
 
79
94
  mtime = qs.aggregate(
80
95
  max=Greatest(
81
- Coalesce("max_bookmark_updated_at", EPOCH_START_DATETIMEFILED),
96
+ Coalesce("max_bookmark_updated_at", EPOCH_START_DATETIMEFIELD),
82
97
  "max_updated_at",
83
98
  )
84
99
  )["max"]