reader 3.26__tar.gz → 3.27__tar.gz

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.
Files changed (262) hide show
  1. {reader-3.26 → reader-3.27}/CHANGES.rst +24 -1
  2. {reader-3.26/src/reader.egg-info → reader-3.27}/PKG-INFO +3 -3
  3. {reader-3.26 → reader-3.27}/docs/api.rst +9 -10
  4. {reader-3.26 → reader-3.27}/docs/conf.py +15 -1
  5. {reader-3.26 → reader-3.27}/docs/guide.rst +10 -0
  6. {reader-3.26 → reader-3.27}/docs/install.rst +6 -8
  7. {reader-3.26 → reader-3.27}/docs/internal.rst +1 -1
  8. {reader-3.26 → reader-3.27}/pyproject.toml +5 -3
  9. {reader-3.26 → reader-3.27}/scripts/release.py +1 -11
  10. {reader-3.26 → reader-3.27}/src/reader/__init__.py +1 -1
  11. {reader-3.26 → reader-3.27}/src/reader/_cli.py +8 -1
  12. {reader-3.26 → reader-3.27}/src/reader/_parser/__init__.py +57 -140
  13. {reader-3.26 → reader-3.27}/src/reader/_parser/_url_utils.py +18 -0
  14. {reader-3.26 → reader-3.27}/src/reader/_parser/feedparser.py +3 -8
  15. {reader-3.26 → reader-3.27}/src/reader/_parser/file.py +2 -2
  16. {reader-3.26 → reader-3.27}/src/reader/_parser/http.py +69 -17
  17. {reader-3.26 → reader-3.27}/src/reader/_parser/jsonfeed.py +5 -14
  18. {reader-3.26 → reader-3.27}/src/reader/_storage/__init__.py +6 -2
  19. {reader-3.26 → reader-3.27}/src/reader/_storage/_base.py +21 -10
  20. {reader-3.26 → reader-3.27}/src/reader/_storage/_changes.py +1 -1
  21. {reader-3.26 → reader-3.27}/src/reader/_storage/_entries.py +8 -4
  22. {reader-3.26 → reader-3.27}/src/reader/_storage/_feeds.py +1 -1
  23. {reader-3.26 → reader-3.27}/src/reader/_storage/_html_utils.py +1 -1
  24. {reader-3.26 → reader-3.27}/src/reader/_storage/_search.py +1 -5
  25. {reader-3.26 → reader-3.27}/src/reader/_storage/_sql_utils.py +10 -16
  26. {reader-3.26 → reader-3.27}/src/reader/_storage/_sqlite_utils.py +3 -8
  27. {reader-3.26 → reader-3.27}/src/reader/_storage/_tags.py +7 -11
  28. {reader-3.26 → reader-3.27}/src/reader/_types.py +17 -26
  29. {reader-3.26 → reader-3.27}/src/reader/_update/__init__.py +4 -3
  30. {reader-3.26 → reader-3.27}/src/reader/_update/base.py +14 -20
  31. {reader-3.26 → reader-3.27}/src/reader/_update/hooks.py +2 -5
  32. {reader-3.26 → reader-3.27}/src/reader/_utils.py +17 -37
  33. {reader-3.26 → reader-3.27}/src/reader/core.py +48 -83
  34. {reader-3.26 → reader-3.27}/src/reader/discover.py +4 -2
  35. {reader-3.26 → reader-3.27}/src/reader/exceptions.py +5 -14
  36. {reader-3.26 → reader-3.27}/src/reader/plugins/__init__.py +1 -8
  37. {reader-3.26 → reader-3.27}/src/reader/plugins/_loader.py +8 -12
  38. {reader-3.26 → reader-3.27}/src/reader/plugins/autodiscover.py +7 -16
  39. {reader-3.26 → reader-3.27}/src/reader/types.py +33 -59
  40. {reader-3.26 → reader-3.27/src/reader.egg-info}/PKG-INFO +3 -3
  41. {reader-3.26 → reader-3.27}/src/reader.egg-info/SOURCES.txt +0 -35
  42. {reader-3.26 → reader-3.27}/tests/fakeparser.py +3 -3
  43. {reader-3.26 → reader-3.27}/tests/test_lazy_imports.py +4 -4
  44. {reader-3.26 → reader-3.27}/tests/test_parser.py +93 -44
  45. {reader-3.26 → reader-3.27}/tests/test_plugins_autodiscover.py +1 -1
  46. {reader-3.26 → reader-3.27}/tests/test_reader_hooks.py +3 -4
  47. {reader-3.26 → reader-3.27}/tests/test_reader_lifecycle.py +26 -0
  48. {reader-3.26 → reader-3.27}/tests/test_reader_private.py +1 -0
  49. {reader-3.26 → reader-3.27}/tests/test_reader_update.py +29 -76
  50. {reader-3.26 → reader-3.27}/tests/test_types.py +16 -0
  51. {reader-3.26 → reader-3.27}/tox.ini +5 -4
  52. reader-3.26/src/reader/_vendor/feedparser/__init__.py +0 -88
  53. reader-3.26/src/reader/_vendor/feedparser/api.py +0 -377
  54. reader-3.26/src/reader/_vendor/feedparser/datetimes/__init__.py +0 -73
  55. reader-3.26/src/reader/_vendor/feedparser/datetimes/asctime.py +0 -80
  56. reader-3.26/src/reader/_vendor/feedparser/datetimes/greek.py +0 -90
  57. reader-3.26/src/reader/_vendor/feedparser/datetimes/hungarian.py +0 -66
  58. reader-3.26/src/reader/_vendor/feedparser/datetimes/iso8601.py +0 -160
  59. reader-3.26/src/reader/_vendor/feedparser/datetimes/korean.py +0 -94
  60. reader-3.26/src/reader/_vendor/feedparser/datetimes/perforce.py +0 -63
  61. reader-3.26/src/reader/_vendor/feedparser/datetimes/rfc822.py +0 -179
  62. reader-3.26/src/reader/_vendor/feedparser/datetimes/w3dtf.py +0 -128
  63. reader-3.26/src/reader/_vendor/feedparser/encodings.py +0 -649
  64. reader-3.26/src/reader/_vendor/feedparser/exceptions.py +0 -55
  65. reader-3.26/src/reader/_vendor/feedparser/html.py +0 -352
  66. reader-3.26/src/reader/_vendor/feedparser/http.py +0 -78
  67. reader-3.26/src/reader/_vendor/feedparser/mixin.py +0 -842
  68. reader-3.26/src/reader/_vendor/feedparser/namespaces/__init__.py +0 -0
  69. reader-3.26/src/reader/_vendor/feedparser/namespaces/_base.py +0 -547
  70. reader-3.26/src/reader/_vendor/feedparser/namespaces/admin.py +0 -53
  71. reader-3.26/src/reader/_vendor/feedparser/namespaces/cc.py +0 -70
  72. reader-3.26/src/reader/_vendor/feedparser/namespaces/dc.py +0 -138
  73. reader-3.26/src/reader/_vendor/feedparser/namespaces/georss.py +0 -683
  74. reader-3.26/src/reader/_vendor/feedparser/namespaces/itunes.py +0 -113
  75. reader-3.26/src/reader/_vendor/feedparser/namespaces/mediarss.py +0 -142
  76. reader-3.26/src/reader/_vendor/feedparser/namespaces/psc.py +0 -74
  77. reader-3.26/src/reader/_vendor/feedparser/parsers/__init__.py +0 -0
  78. reader-3.26/src/reader/_vendor/feedparser/parsers/json.py +0 -135
  79. reader-3.26/src/reader/_vendor/feedparser/parsers/loose.py +0 -75
  80. reader-3.26/src/reader/_vendor/feedparser/parsers/strict.py +0 -141
  81. reader-3.26/src/reader/_vendor/feedparser/sanitizer.py +0 -974
  82. reader-3.26/src/reader/_vendor/feedparser/sgml.py +0 -98
  83. reader-3.26/src/reader/_vendor/feedparser/urls.py +0 -174
  84. reader-3.26/src/reader/_vendor/feedparser/util.py +0 -158
  85. reader-3.26/src/reader/py.typed +0 -0
  86. reader-3.26/tests/_plugins/__init__.py +0 -0
  87. {reader-3.26 → reader-3.27}/LICENSE +0 -0
  88. {reader-3.26 → reader-3.27}/MANIFEST.in +0 -0
  89. {reader-3.26 → reader-3.27}/README.rst +0 -0
  90. {reader-3.26 → reader-3.27}/docs/app.rst +0 -0
  91. {reader-3.26 → reader-3.27}/docs/changelog.rst +0 -0
  92. {reader-3.26 → reader-3.27}/docs/cli.rst +0 -0
  93. {reader-3.26 → reader-3.27}/docs/config.rst +0 -0
  94. {reader-3.26 → reader-3.27}/docs/contributing.rst +0 -0
  95. {reader-3.26 → reader-3.27}/docs/dev.rst +0 -0
  96. {reader-3.26 → reader-3.27}/docs/index.rst +0 -0
  97. {reader-3.26 → reader-3.27}/docs/plugins.rst +0 -0
  98. {reader-3.26 → reader-3.27}/docs/screenshots/autodiscovery.png +0 -0
  99. {reader-3.26 → reader-3.27}/docs/screenshots/empty.png +0 -0
  100. {reader-3.26 → reader-3.27}/docs/screenshots/entries-filters-light.png +0 -0
  101. {reader-3.26 → reader-3.27}/docs/screenshots/entries.png +0 -0
  102. {reader-3.26 → reader-3.27}/docs/screenshots/entry-image-light.png +0 -0
  103. {reader-3.26 → reader-3.27}/docs/screenshots/entry.png +0 -0
  104. {reader-3.26 → reader-3.27}/docs/screenshots/export-database.png +0 -0
  105. {reader-3.26 → reader-3.27}/docs/screenshots/feed.png +0 -0
  106. {reader-3.26 → reader-3.27}/docs/screenshots/feeds.png +0 -0
  107. {reader-3.26 → reader-3.27}/docs/screenshots/help.png +0 -0
  108. {reader-3.26 → reader-3.27}/docs/screenshots/import-result.png +0 -0
  109. {reader-3.26 → reader-3.27}/docs/screenshots/import-select.png +0 -0
  110. {reader-3.26 → reader-3.27}/docs/tutorial.rst +0 -0
  111. {reader-3.26 → reader-3.27}/docs/why.rst +0 -0
  112. {reader-3.26 → reader-3.27}/examples/config.toml +0 -0
  113. {reader-3.26 → reader-3.27}/examples/custom_headers.py +0 -0
  114. {reader-3.26 → reader-3.27}/examples/feed_slugs.py +0 -0
  115. {reader-3.26 → reader-3.27}/examples/parser_only.py +0 -0
  116. {reader-3.26 → reader-3.27}/examples/podcast.py +0 -0
  117. {reader-3.26 → reader-3.27}/examples/terminal.py +0 -0
  118. {reader-3.26 → reader-3.27}/run.sh +0 -0
  119. {reader-3.26 → reader-3.27}/scripts/bench.py +0 -0
  120. {reader-3.26 → reader-3.27}/scripts/debug_storage_stats.py +0 -0
  121. {reader-3.26 → reader-3.27}/scripts/entry_dedupe_backtest.py +0 -0
  122. {reader-3.26 → reader-3.27}/scripts/jscontrols.html +0 -0
  123. {reader-3.26 → reader-3.27}/scripts/jscontrols.py +0 -0
  124. {reader-3.26 → reader-3.27}/scripts/lines.sh +0 -0
  125. {reader-3.26 → reader-3.27}/scripts/vendor_app_stuff.py +0 -0
  126. {reader-3.26 → reader-3.27}/setup.cfg +0 -0
  127. {reader-3.26 → reader-3.27}/src/reader/__main__.py +0 -0
  128. {reader-3.26 → reader-3.27}/src/reader/_app/__init__.py +0 -0
  129. {reader-3.26 → reader-3.27}/src/reader/_app/cli.py +0 -0
  130. {reader-3.26 → reader-3.27}/src/reader/_app/exports.py +0 -0
  131. {reader-3.26 → reader-3.27}/src/reader/_app/ext.py +0 -0
  132. {reader-3.26 → reader-3.27}/src/reader/_app/forms.py +0 -0
  133. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/__init__.py +0 -0
  134. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/api_thing.py +0 -0
  135. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/static/controls.js +0 -0
  136. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/static/style.css +0 -0
  137. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/templates/add_entry.html +0 -0
  138. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/templates/entries.html +0 -0
  139. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/templates/entry.html +0 -0
  140. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/templates/feeds.html +0 -0
  141. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/templates/layout.html +0 -0
  142. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/templates/macros.html +0 -0
  143. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/templates/metadata.html +0 -0
  144. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/templates/tags.html +0 -0
  145. {reader-3.26 → reader-3.27}/src/reader/_app/legacy/wsgi.py +0 -0
  146. {reader-3.26 → reader-3.27}/src/reader/_app/static/style.css +0 -0
  147. {reader-3.26 → reader-3.27}/src/reader/_app/static/theme.js +0 -0
  148. {reader-3.26 → reader-3.27}/src/reader/_app/static/vendor/README +0 -0
  149. {reader-3.26 → reader-3.27}/src/reader/_app/static/vendor/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css +0 -0
  150. {reader-3.26 → reader-3.27}/src/reader/_app/static/vendor/bootstrap-icons@1.13.1/font/fonts/bootstrap-icons.woff +0 -0
  151. {reader-3.26 → reader-3.27}/src/reader/_app/static/vendor/bootstrap-icons@1.13.1/font/fonts/bootstrap-icons.woff2 +0 -0
  152. {reader-3.26 → reader-3.27}/src/reader/_app/static/vendor/bootstrap@5.3.8/dist/css/bootstrap.min.css +0 -0
  153. {reader-3.26 → reader-3.27}/src/reader/_app/static/vendor/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js +0 -0
  154. {reader-3.26 → reader-3.27}/src/reader/_app/static/vendor/htmx-ext-response-targets@2.0.4/dist/response-targets.min.js +0 -0
  155. {reader-3.26 → reader-3.27}/src/reader/_app/static/vendor/htmx.org@2.0.8/dist/htmx.min.js +0 -0
  156. {reader-3.26 → reader-3.27}/src/reader/_app/templates/add_feed.html +0 -0
  157. {reader-3.26 → reader-3.27}/src/reader/_app/templates/change_feed_title.html +0 -0
  158. {reader-3.26 → reader-3.27}/src/reader/_app/templates/delete_feed.html +0 -0
  159. {reader-3.26 → reader-3.27}/src/reader/_app/templates/entries.html +0 -0
  160. {reader-3.26 → reader-3.27}/src/reader/_app/templates/entry.html +0 -0
  161. {reader-3.26 → reader-3.27}/src/reader/_app/templates/feeds.html +0 -0
  162. {reader-3.26 → reader-3.27}/src/reader/_app/templates/help.html +0 -0
  163. {reader-3.26 → reader-3.27}/src/reader/_app/templates/import_feeds.html +0 -0
  164. {reader-3.26 → reader-3.27}/src/reader/_app/templates/layout.html +0 -0
  165. {reader-3.26 → reader-3.27}/src/reader/_app/templates/layout_base.html +0 -0
  166. {reader-3.26 → reader-3.27}/src/reader/_app/templates/macros.html +0 -0
  167. {reader-3.26 → reader-3.27}/src/reader/_app/templates/settings.html +0 -0
  168. {reader-3.26 → reader-3.27}/src/reader/_app/templates/settings_base.html +0 -0
  169. {reader-3.26 → reader-3.27}/src/reader/_app/wsgi.py +0 -0
  170. {reader-3.26 → reader-3.27}/src/reader/_config_utils.py +0 -0
  171. {reader-3.26 → reader-3.27}/src/reader/_hash_utils.py +0 -0
  172. {reader-3.26 → reader-3.27}/src/reader/_logging.py +0 -0
  173. {reader-3.26 → reader-3.27}/src/reader/_parser/_http_utils.py +0 -0
  174. {reader-3.26 → reader-3.27}/src/reader/_plugins/__init__.py +0 -0
  175. {reader-3.26 → reader-3.27}/src/reader/_plugins/cli_status.py +0 -0
  176. {reader-3.26 → reader-3.27}/src/reader/_plugins/legacy/__init__.py +0 -0
  177. {reader-3.26 → reader-3.27}/src/reader/_plugins/legacy/enclosure_tags.py +0 -0
  178. {reader-3.26 → reader-3.27}/src/reader/_plugins/legacy/preview_feed_list.py +0 -0
  179. {reader-3.26 → reader-3.27}/src/reader/_plugins/legacy/share.py +0 -0
  180. {reader-3.26 → reader-3.27}/src/reader/_plugins/legacy/templates/preview_feed_list.html +0 -0
  181. {reader-3.26 → reader-3.27}/src/reader/_plugins/sqlite_releases.py +0 -0
  182. {reader-3.26 → reader-3.27}/src/reader/_plugins/timer.py +0 -0
  183. {reader-3.26 → reader-3.27}/src/reader/_storage/_schema.py +0 -0
  184. {reader-3.26 → reader-3.27}/src/reader/opml.py +0 -0
  185. {reader-3.26 → reader-3.27}/src/reader/plugins/enclosure_dedupe.py +0 -0
  186. {reader-3.26 → reader-3.27}/src/reader/plugins/entry_dedupe.py +0 -0
  187. {reader-3.26 → reader-3.27}/src/reader/plugins/mark_as_read.py +0 -0
  188. {reader-3.26 → reader-3.27}/src/reader/plugins/readtime.py +0 -0
  189. {reader-3.26 → reader-3.27}/src/reader/plugins/ua_fallback.py +0 -0
  190. {reader-3.26/src/reader/_vendor/feedparser → reader-3.27/src/reader}/py.typed +0 -0
  191. {reader-3.26 → reader-3.27}/src/reader/utils.py +0 -0
  192. {reader-3.26 → reader-3.27}/src/reader.egg-info/dependency_links.txt +0 -0
  193. {reader-3.26 → reader-3.27}/src/reader.egg-info/requires.txt +0 -0
  194. {reader-3.26 → reader-3.27}/src/reader.egg-info/top_level.txt +0 -0
  195. {reader-3.26/src/reader/_vendor → reader-3.27/tests/_plugins}/__init__.py +0 -0
  196. {reader-3.26 → reader-3.27}/tests/_plugins/builtin.py +0 -0
  197. {reader-3.26 → reader-3.27}/tests/_plugins/error_during_import.py +0 -0
  198. {reader-3.26 → reader-3.27}/tests/_plugins/error_import_error.py +0 -0
  199. {reader-3.26 → reader-3.27}/tests/conftest.py +0 -0
  200. {reader-3.26 → reader-3.27}/tests/data/10.json +0 -0
  201. {reader-3.26 → reader-3.27}/tests/data/10.json.py +0 -0
  202. {reader-3.26 → reader-3.27}/tests/data/custom +0 -0
  203. {reader-3.26 → reader-3.27}/tests/data/empty.atom +0 -0
  204. {reader-3.26 → reader-3.27}/tests/data/empty.atom.py +0 -0
  205. {reader-3.26 → reader-3.27}/tests/data/empty.json +0 -0
  206. {reader-3.26 → reader-3.27}/tests/data/empty.json.py +0 -0
  207. {reader-3.26 → reader-3.27}/tests/data/empty.rss +0 -0
  208. {reader-3.26 → reader-3.27}/tests/data/empty.rss.py +0 -0
  209. {reader-3.26 → reader-3.27}/tests/data/full.atom +0 -0
  210. {reader-3.26 → reader-3.27}/tests/data/full.atom.py +0 -0
  211. {reader-3.26 → reader-3.27}/tests/data/full.json +0 -0
  212. {reader-3.26 → reader-3.27}/tests/data/full.json.py +0 -0
  213. {reader-3.26 → reader-3.27}/tests/data/full.rss +0 -0
  214. {reader-3.26 → reader-3.27}/tests/data/full.rss.py +0 -0
  215. {reader-3.26 → reader-3.27}/tests/data/invalid.json +0 -0
  216. {reader-3.26 → reader-3.27}/tests/data/invalid.json.py +0 -0
  217. {reader-3.26 → reader-3.27}/tests/data/relative.atom +0 -0
  218. {reader-3.26 → reader-3.27}/tests/data/relative.atom.py +0 -0
  219. {reader-3.26 → reader-3.27}/tests/data/relative.rss +0 -0
  220. {reader-3.26 → reader-3.27}/tests/data/relative.rss.py +0 -0
  221. {reader-3.26 → reader-3.27}/tests/data/sqlite_releases.html +0 -0
  222. {reader-3.26 → reader-3.27}/tests/data/unknown.json +0 -0
  223. {reader-3.26 → reader-3.27}/tests/data/unknown.json.py +0 -0
  224. {reader-3.26 → reader-3.27}/tests/fixtures.py +0 -0
  225. {reader-3.26 → reader-3.27}/tests/reader_methods.py +0 -0
  226. {reader-3.26 → reader-3.27}/tests/test__types.py +0 -0
  227. {reader-3.26 → reader-3.27}/tests/test__utils.py +0 -0
  228. {reader-3.26 → reader-3.27}/tests/test_app_legacy.py +0 -0
  229. {reader-3.26 → reader-3.27}/tests/test_app_wsgi.py +0 -0
  230. {reader-3.26 → reader-3.27}/tests/test_bench.py +0 -0
  231. {reader-3.26 → reader-3.27}/tests/test_changes.py +0 -0
  232. {reader-3.26 → reader-3.27}/tests/test_cli.py +0 -0
  233. {reader-3.26 → reader-3.27}/tests/test_config_utils.py +0 -0
  234. {reader-3.26 → reader-3.27}/tests/test_discover.py +0 -0
  235. {reader-3.26 → reader-3.27}/tests/test_exceptions.py +0 -0
  236. {reader-3.26 → reader-3.27}/tests/test_hash_utils.py +0 -0
  237. {reader-3.26 → reader-3.27}/tests/test_html_utils.py +0 -0
  238. {reader-3.26 → reader-3.27}/tests/test_logging.py +0 -0
  239. {reader-3.26 → reader-3.27}/tests/test_opml.py +0 -0
  240. {reader-3.26 → reader-3.27}/tests/test_plugins_cli_status.py +0 -0
  241. {reader-3.26 → reader-3.27}/tests/test_plugins_enclosure_dedupe.py +0 -0
  242. {reader-3.26 → reader-3.27}/tests/test_plugins_entry_dedupe.py +0 -0
  243. {reader-3.26 → reader-3.27}/tests/test_plugins_loader.py +0 -0
  244. {reader-3.26 → reader-3.27}/tests/test_plugins_mark_as_read.py +0 -0
  245. {reader-3.26 → reader-3.27}/tests/test_plugins_preview_feed_list.py +0 -0
  246. {reader-3.26 → reader-3.27}/tests/test_plugins_readtime.py +0 -0
  247. {reader-3.26 → reader-3.27}/tests/test_plugins_sqlite_releases.py +0 -0
  248. {reader-3.26 → reader-3.27}/tests/test_plugins_ua_fallback.py +0 -0
  249. {reader-3.26 → reader-3.27}/tests/test_reader.py +0 -0
  250. {reader-3.26 → reader-3.27}/tests/test_reader_counts.py +0 -0
  251. {reader-3.26 → reader-3.27}/tests/test_reader_deprecations.py +0 -0
  252. {reader-3.26 → reader-3.27}/tests/test_reader_filter.py +0 -0
  253. {reader-3.26 → reader-3.27}/tests/test_reader_integration.py +0 -0
  254. {reader-3.26 → reader-3.27}/tests/test_reader_search.py +0 -0
  255. {reader-3.26 → reader-3.27}/tests/test_reader_sort.py +0 -0
  256. {reader-3.26 → reader-3.27}/tests/test_reader_utils.py +0 -0
  257. {reader-3.26 → reader-3.27}/tests/test_search.py +0 -0
  258. {reader-3.26 → reader-3.27}/tests/test_sql_utils.py +0 -0
  259. {reader-3.26 → reader-3.27}/tests/test_sqlite_utils.py +0 -0
  260. {reader-3.26 → reader-3.27}/tests/test_storage.py +0 -0
  261. {reader-3.26 → reader-3.27}/tests/test_tags.py +0 -0
  262. {reader-3.26 → reader-3.27}/tests/utils.py +0 -0
@@ -6,6 +6,29 @@ Changelog
6
6
  :no-index:
7
7
 
8
8
 
9
+ Version 3.27
10
+ ------------
11
+
12
+ Released 2026-10-11
13
+
14
+ * Add the ``migrate`` :func:`make_reader` argument.
15
+ Thanks to `Divyanshi Purohit`_ for the PR.
16
+ (:issue:`403`)
17
+ * Add :attr:`~EntryCounts.unread` property to
18
+ :class:`EntryCounts` and :class:`EntrySearchCounts`.
19
+ (:issue:`283`)
20
+
21
+ * Support Python 3.15. (:issue:`418`)
22
+ * Support PyPy 3.12. (:issue:`419`)
23
+ * Drop Python 3.11 support. (:issue:`419`)
24
+
25
+ * Stop vendoring `feedparser`_ and
26
+ :ref:`recommend installing it from GitHub instead <no-vendored-feedparser>`.
27
+ * Pin GitHub Actions and add zizmor to CI.
28
+
29
+ .. _Divyanshi Purohit: https://github.com/divyanshi555
30
+
31
+
9
32
  Version 3.26
10
33
  ------------
11
34
 
@@ -592,7 +615,7 @@ Released 2023-08-20
592
615
 
593
616
  * Make :exc:`ReaderWarning` inherit from :exc:`ReaderError`.
594
617
 
595
- * Include a diagram of the :ref:`exctree` in the :doc:`api`.
618
+ * Include a diagram of the :ref:`exception hierarchy <exctree>` in the :doc:`api`.
596
619
 
597
620
  * Add werkzeug dependency,
598
621
  instead of vendoring selected :mod:`werkzeug.http` utilities.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reader
3
- Version: 3.26
3
+ Version: 3.27
4
4
  Summary: A Python feed reader library.
5
5
  Author: lemon24
6
6
  License: BSD-3-Clause
@@ -19,10 +19,10 @@ Classifier: Operating System :: OS Independent
19
19
  Classifier: Programming Language :: Python
20
20
  Classifier: Programming Language :: Python :: 3
21
21
  Classifier: Programming Language :: Python :: 3 :: Only
22
- Classifier: Programming Language :: Python :: 3.11
23
22
  Classifier: Programming Language :: Python :: 3.12
24
23
  Classifier: Programming Language :: Python :: 3.13
25
24
  Classifier: Programming Language :: Python :: 3.14
25
+ Classifier: Programming Language :: Python :: 3.15
26
26
  Classifier: Programming Language :: Python :: Implementation :: CPython
27
27
  Classifier: Programming Language :: Python :: Implementation :: PyPy
28
28
  Classifier: Topic :: Internet
@@ -32,7 +32,7 @@ Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
32
32
  Classifier: Topic :: Software Development :: Libraries
33
33
  Classifier: Topic :: Utilities
34
34
  Classifier: Typing :: Typed
35
- Requires-Python: >=3.11
35
+ Requires-Python: >=3.12
36
36
  Description-Content-Type: text/x-rst
37
37
  License-File: LICENSE
38
38
  Requires-Dist: typing-extensions>=4
@@ -60,9 +60,11 @@ Data objects
60
60
 
61
61
  .. autoclass:: EntryCounts
62
62
  :members:
63
+ :inherited-members:
63
64
 
64
65
  .. autoclass:: EntrySearchCounts
65
66
  :members:
67
+ :inherited-members:
66
68
 
67
69
  .. autoclass:: UpdateResult
68
70
  :members:
@@ -85,9 +87,16 @@ Data objects
85
87
 
86
88
 
87
89
 
90
+ .. _exctree:
91
+
88
92
  Exceptions
89
93
  ----------
90
94
 
95
+ The class hierarchy for :mod:`reader` exceptions is:
96
+
97
+ .. classtree:: ReaderError
98
+
99
+
91
100
  .. autoexception:: ReaderError
92
101
  :members:
93
102
 
@@ -180,16 +189,6 @@ Exceptions
180
189
  :show-inheritance:
181
190
 
182
191
 
183
- .. _exctree:
184
-
185
- Exception hierarchy
186
- ~~~~~~~~~~~~~~~~~~~
187
-
188
- The class hierarchy for :mod:`reader` exceptions is:
189
-
190
- .. classtree:: ReaderError
191
-
192
-
193
192
 
194
193
  Enumerations
195
194
  ------------
@@ -78,7 +78,7 @@ autodoc_typehints_description_target = 'documented'
78
78
  autodoc_type_aliases = {
79
79
  'ResourceInput': 'reader.types.ResourceInput',
80
80
  'AnyResourceInput': 'reader.types.AnyResourceInput',
81
- 'JSONType': 'reader.types.JSONType',
81
+ 'JSON': 'reader.types.JSON',
82
82
  'TagFilter': 'reader._types.TagFilter',
83
83
  'TristateFilter': 'reader._types.TristateFilter',
84
84
  }
@@ -226,5 +226,19 @@ def class_tree(cls):
226
226
  return '\n'.join(output(classes)) + '\n'
227
227
 
228
228
 
229
+ import builtins
230
+
231
+ std_dir = builtins.dir
232
+
233
+
234
+ def source_order_dir(obj):
235
+ if isinstance(obj, type):
236
+ return [name for cls in obj.mro() for name in cls.__dict__.keys()]
237
+ return std_dir(obj)
238
+
239
+
229
240
  def setup(app):
230
241
  app.add_directive("classtree", ClassTree)
242
+
243
+ # TODO: remove when https://github.com/sphinx-doc/sphinx/issues/628 is resolved
244
+ builtins.dir = source_order_dir
@@ -137,6 +137,16 @@ since each connection would be to a *different* database::
137
137
  .. _temporary: https://sqlite.org/inmemorydb.html#temp_db
138
138
 
139
139
 
140
+ Migrations
141
+ ~~~~~~~~~~
142
+
143
+ Schema migrations depend on the storage used.
144
+
145
+ For the default SQLite storage,
146
+ migrations happen automatically during :func:`make_reader`,
147
+ unless you pass ``migrate=False``.
148
+
149
+
140
150
  .. _backups:
141
151
 
142
152
  Backups
@@ -28,14 +28,12 @@ These packages will be installed automatically when installing *reader*:
28
28
 
29
29
  .. note::
30
30
 
31
- Because `feedparser`_ makes PyPI releases at a lower cadence,
32
- *reader* uses a vendored version of feedparser's `develop`_ branch
33
- by default since :ref:`version 2.9`.
34
- To opt out of this behavior, and make *reader* use
35
- the installed ``feedparser`` package,
36
- set the ``READER_NO_VENDORED_FEEDPARSER`` environment variable to ``1``.
37
-
38
- .. _develop: https://github.com/kurtmckee/feedparser
31
+ The `feedparser`_ ``main`` branch contains a `change`_
32
+ that decreases memory usage by ~35% during feed updates;
33
+ as of feedparser 6.0.14, this change is not yet included in PyPI releases;
34
+ to benefit from it, install feedparser directly from GitHub.
35
+
36
+ .. _change: https://github.com/kurtmckee/feedparser/pull/302
39
37
 
40
38
 
41
39
  .. _optional dependencies:
@@ -87,7 +87,7 @@ Data objects
87
87
  .. autoclass:: ParsedFeed
88
88
  :members:
89
89
 
90
- .. autoclass:: HTTPInfo
90
+ .. autoclass:: RetrieveMetadata
91
91
  :members:
92
92
 
93
93
 
@@ -19,10 +19,10 @@ classifiers = [
19
19
  "Programming Language :: Python",
20
20
  "Programming Language :: Python :: 3",
21
21
  "Programming Language :: Python :: 3 :: Only",
22
- "Programming Language :: Python :: 3.11",
23
22
  "Programming Language :: Python :: 3.12",
24
23
  "Programming Language :: Python :: 3.13",
25
24
  "Programming Language :: Python :: 3.14",
25
+ "Programming Language :: Python :: 3.15",
26
26
  "Programming Language :: Python :: Implementation :: CPython",
27
27
  "Programming Language :: Python :: Implementation :: PyPy",
28
28
  "Topic :: Internet",
@@ -33,7 +33,7 @@ classifiers = [
33
33
  "Topic :: Utilities",
34
34
  "Typing :: Typed",
35
35
  ]
36
- requires-python = ">=3.11"
36
+ requires-python = ">=3.12"
37
37
  dependencies = [
38
38
  "typing-extensions>=4",
39
39
  "feedparser>=6",
@@ -176,6 +176,9 @@ files = ["src"]
176
176
  show_error_codes = true
177
177
  pretty = true
178
178
  strict = true
179
+ strict_equality_for_none = true
180
+ warn_unreachable = true
181
+
179
182
  [[tool.mypy.overrides]]
180
183
  module = [
181
184
  "reader.__main__",
@@ -190,7 +193,6 @@ module = [
190
193
  "reader.plugins.readtime",
191
194
  "reader.plugins.mark_as_read",
192
195
  "reader.plugins.autodiscover",
193
- "reader._vendor.feedparser.*",
194
196
  ]
195
197
  ignore_errors = true
196
198
 
@@ -20,18 +20,8 @@ def run(*args, **kwargs):
20
20
  return subprocess.run(*args, check=True, **kwargs)
21
21
 
22
22
 
23
- def run_no_venv(*args, **kwargs):
24
- env = os.environ.copy()
25
- virtual_env = env.pop('VIRTUAL_ENV', None)
26
- if virtual_env:
27
- env['PATH'] = ':'.join(
28
- p for p in env['PATH'].split(':') if not p.startswith(virtual_env)
29
- )
30
- return run(*args, env=env, **kwargs)
31
-
32
-
33
23
  def run_tox():
34
- run_no_venv('tox -p all', shell=True)
24
+ run('tox -p all', shell=True)
35
25
 
36
26
 
37
27
  def path_sub(pattern, repl, path):
@@ -37,7 +37,7 @@ Print the titles of the unread entries::
37
37
 
38
38
  """
39
39
 
40
- __version__ = '3.26'
40
+ __version__ = '3.27'
41
41
 
42
42
  # isort: off
43
43
 
@@ -169,6 +169,11 @@ class MapParamType(click.ParamType):
169
169
  ),
170
170
  )
171
171
  @click.option('--read-only/--no-read-only', help="Do not modify storage.")
172
+ @click.option(
173
+ '--migrate/--no-migrate',
174
+ default=True,
175
+ help="Enable or disable automatic schema migrations (default: enabled).",
176
+ )
172
177
  @click.option(
173
178
  '--plugin',
174
179
  'plugins',
@@ -202,7 +207,9 @@ class MapParamType(click.ParamType):
202
207
  )
203
208
  @click.version_option(reader.__version__, message='%(prog)s %(version)s')
204
209
  @click.pass_context
205
- def cli(ctx, url, feed_root, read_only, plugins, cli_plugins, reserved_name_scheme):
210
+ def cli(
211
+ ctx, url, feed_root, read_only, migrate, plugins, cli_plugins, reserved_name_scheme
212
+ ):
206
213
  """reader command-line interface.
207
214
 
208
215
  Option defaults can be set via environment variables;