reader 3.10__tar.gz → 3.12__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.
- {reader-3.10 → reader-3.12}/CHANGES.rst +31 -0
- {reader-3.10/src/reader.egg-info → reader-3.12}/PKG-INFO +3 -1
- {reader-3.10 → reader-3.12}/docs/api.rst +1 -0
- {reader-3.10 → reader-3.12}/docs/dev.rst +46 -3
- {reader-3.10 → reader-3.12}/docs/guide.rst +24 -12
- {reader-3.10 → reader-3.12}/docs/internal.rst +26 -3
- {reader-3.10 → reader-3.12}/docs/plugins.rst +4 -4
- {reader-3.10 → reader-3.12}/pyproject.toml +3 -0
- {reader-3.10 → reader-3.12}/run.sh +1 -1
- reader-3.12/scripts/bench.py +453 -0
- {reader-3.10 → reader-3.12}/src/reader/__init__.py +1 -1
- {reader-3.10 → reader-3.12}/src/reader/_app/cli.py +0 -3
- {reader-3.10 → reader-3.12}/src/reader/_cli.py +3 -30
- reader-3.12/src/reader/_storage/__init__.py +39 -0
- reader-3.12/src/reader/_storage/_base.py +110 -0
- reader-3.12/src/reader/_storage/_changes.py +213 -0
- reader-3.12/src/reader/_storage/_entries.py +654 -0
- reader-3.12/src/reader/_storage/_feeds.py +404 -0
- {reader-3.10/src/reader → reader-3.12/src/reader/_storage}/_html_utils.py +3 -1
- reader-3.12/src/reader/_storage/_schema.py +284 -0
- reader-3.12/src/reader/_storage/_search.py +643 -0
- {reader-3.10/src/reader → reader-3.12/src/reader/_storage}/_sql_utils.py +99 -31
- {reader-3.10/src/reader → reader-3.12/src/reader/_storage}/_sqlite_utils.py +123 -104
- reader-3.12/src/reader/_storage/_tags.py +250 -0
- {reader-3.10 → reader-3.12}/src/reader/_types.py +191 -7
- {reader-3.10 → reader-3.12}/src/reader/_utils.py +0 -60
- {reader-3.10 → reader-3.12}/src/reader/core.py +50 -70
- {reader-3.10 → reader-3.12}/src/reader/exceptions.py +12 -0
- {reader-3.10 → reader-3.12}/src/reader/plugins/readtime.py +2 -2
- {reader-3.10 → reader-3.12}/src/reader/types.py +77 -15
- {reader-3.10 → reader-3.12/src/reader.egg-info}/PKG-INFO +3 -1
- {reader-3.10 → reader-3.12}/src/reader.egg-info/SOURCES.txt +14 -5
- {reader-3.10 → reader-3.12}/src/reader.egg-info/requires.txt +3 -0
- {reader-3.10 → reader-3.12}/tests/conftest.py +19 -3
- {reader-3.10 → reader-3.12}/tests/fakeparser.py +40 -30
- {reader-3.10 → reader-3.12}/tests/reader_methods.py +6 -11
- {reader-3.10 → reader-3.12}/tests/test__types.py +14 -1
- {reader-3.10 → reader-3.12}/tests/test_app.py +0 -6
- {reader-3.10 → reader-3.12}/tests/test_bench.py +17 -6
- reader-3.12/tests/test_changes.py +427 -0
- {reader-3.10 → reader-3.12}/tests/test_html_utils.py +1 -1
- {reader-3.10 → reader-3.12}/tests/test_reader.py +25 -617
- {reader-3.10 → reader-3.12}/tests/test_reader_context.py +4 -2
- reader-3.12/tests/test_reader_counts.py +288 -0
- reader-3.12/tests/test_reader_filter.py +326 -0
- {reader-3.10 → reader-3.12}/tests/test_reader_hooks.py +4 -9
- {reader-3.10 → reader-3.12}/tests/test_reader_search.py +114 -272
- reader-3.12/tests/test_search.py +218 -0
- {reader-3.10 → reader-3.12}/tests/test_sql_utils.py +2 -2
- {reader-3.10 → reader-3.12}/tests/test_sqlite_utils.py +124 -89
- {reader-3.10 → reader-3.12}/tests/test_storage.py +41 -60
- {reader-3.10 → reader-3.12}/tox.ini +4 -4
- reader-3.10/scripts/bench.py +0 -498
- reader-3.10/src/reader/_search.py +0 -990
- reader-3.10/src/reader/_storage.py +0 -1769
- reader-3.10/tests/test_search.py +0 -204
- {reader-3.10 → reader-3.12}/LICENSE +0 -0
- {reader-3.10 → reader-3.12}/MANIFEST.in +0 -0
- {reader-3.10 → reader-3.12}/README.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/Makefile +0 -0
- {reader-3.10 → reader-3.12}/docs/app.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/changelog.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/cli.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/conf.py +0 -0
- {reader-3.10 → reader-3.12}/docs/config.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/contributing.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/dev-app.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/images/redesign-01.png +0 -0
- {reader-3.10 → reader-3.12}/docs/index.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/install.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/make.bat +0 -0
- {reader-3.10 → reader-3.12}/docs/screenshots/dillo.png +0 -0
- {reader-3.10 → reader-3.12}/docs/screenshots/entries-feed.png +0 -0
- {reader-3.10 → reader-3.12}/docs/screenshots/entries.png +0 -0
- {reader-3.10 → reader-3.12}/docs/screenshots/entry-one.png +0 -0
- {reader-3.10 → reader-3.12}/docs/screenshots/entry-two.png +0 -0
- {reader-3.10 → reader-3.12}/docs/screenshots/feeds.png +0 -0
- {reader-3.10 → reader-3.12}/docs/screenshots/lynx.png +0 -0
- {reader-3.10 → reader-3.12}/docs/screenshots/search.png +0 -0
- {reader-3.10 → reader-3.12}/docs/tutorial.rst +0 -0
- {reader-3.10 → reader-3.12}/docs/why.rst +0 -0
- {reader-3.10 → reader-3.12}/examples/config.yaml +0 -0
- {reader-3.10 → reader-3.12}/examples/parser_only.py +0 -0
- {reader-3.10 → reader-3.12}/examples/podcast.py +0 -0
- {reader-3.10 → reader-3.12}/examples/terminal.py +0 -0
- {reader-3.10 → reader-3.12}/scripts/.coverage +0 -0
- {reader-3.10 → reader-3.12}/scripts/backup.sh +0 -0
- {reader-3.10 → reader-3.12}/scripts/debug_storage_stats.py +0 -0
- {reader-3.10 → reader-3.12}/scripts/generate_import_all.py +0 -0
- {reader-3.10 → reader-3.12}/scripts/jscontrols.html +0 -0
- {reader-3.10 → reader-3.12}/scripts/jscontrols.py +0 -0
- {reader-3.10 → reader-3.12}/scripts/lines.sh +0 -0
- {reader-3.10 → reader-3.12}/scripts/release.py +0 -0
- {reader-3.10 → reader-3.12}/setup.cfg +0 -0
- {reader-3.10 → reader-3.12}/src/reader/__main__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/api_thing.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/static/controls.js +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/static/style.css +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/templates/add_entry.html +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/templates/entries.html +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/templates/entry.html +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/templates/feeds.html +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/templates/layout.html +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/templates/macros.html +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/templates/metadata.html +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/templates/tags.html +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_app/wsgi.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_config.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_hash_utils.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/_http_utils.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/_lazy.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/_url_utils.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/feedparser.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/file.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/http.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/jsonfeed.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/requests/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_parser/requests/_lazy.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_plugins/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_plugins/cli_status.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_plugins/enclosure_tags.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_plugins/preview_feed_list.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_plugins/share.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_plugins/sqlite_releases.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_plugins/templates/preview_feed_list.html +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_plugins/timer.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_update.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/api.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/datetimes/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/datetimes/asctime.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/datetimes/greek.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/datetimes/hungarian.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/datetimes/iso8601.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/datetimes/korean.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/datetimes/perforce.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/datetimes/rfc822.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/datetimes/w3dtf.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/encodings.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/exceptions.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/html.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/http.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/mixin.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/namespaces/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/namespaces/_base.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/namespaces/admin.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/namespaces/cc.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/namespaces/dc.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/namespaces/georss.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/namespaces/itunes.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/namespaces/mediarss.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/namespaces/psc.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/parsers/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/parsers/json.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/parsers/loose.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/parsers/strict.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/py.typed +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/sanitizer.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/sgml.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/urls.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/_vendor/feedparser/util.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/plugins/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/plugins/enclosure_dedupe.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/plugins/entry_dedupe.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/plugins/mark_as_read.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/plugins/ua_fallback.py +0 -0
- {reader-3.10 → reader-3.12}/src/reader/py.typed +0 -0
- {reader-3.10 → reader-3.12}/src/reader.egg-info/dependency_links.txt +0 -0
- {reader-3.10 → reader-3.12}/src/reader.egg-info/top_level.txt +0 -0
- {reader-3.10 → reader-3.12}/tests/data/10.json +0 -0
- {reader-3.10 → reader-3.12}/tests/data/10.json.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/custom +0 -0
- {reader-3.10 → reader-3.12}/tests/data/empty.atom +0 -0
- {reader-3.10 → reader-3.12}/tests/data/empty.atom.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/empty.json +0 -0
- {reader-3.10 → reader-3.12}/tests/data/empty.json.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/empty.rss +0 -0
- {reader-3.10 → reader-3.12}/tests/data/empty.rss.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/full.atom +0 -0
- {reader-3.10 → reader-3.12}/tests/data/full.atom.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/full.json +0 -0
- {reader-3.10 → reader-3.12}/tests/data/full.json.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/full.rss +0 -0
- {reader-3.10 → reader-3.12}/tests/data/full.rss.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/invalid.json +0 -0
- {reader-3.10 → reader-3.12}/tests/data/invalid.json.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/relative.atom +0 -0
- {reader-3.10 → reader-3.12}/tests/data/relative.atom.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/relative.rss +0 -0
- {reader-3.10 → reader-3.12}/tests/data/relative.rss.py +0 -0
- {reader-3.10 → reader-3.12}/tests/data/sqlite_releases.html +0 -0
- {reader-3.10 → reader-3.12}/tests/data/unknown.json +0 -0
- {reader-3.10 → reader-3.12}/tests/data/unknown.json.py +0 -0
- {reader-3.10 → reader-3.12}/tests/reader_test_plugins/__init__.py +0 -0
- {reader-3.10 → reader-3.12}/tests/reader_test_plugins/good.py +0 -0
- {reader-3.10 → reader-3.12}/tests/reader_test_plugins/init_error.py +0 -0
- {reader-3.10 → reader-3.12}/tests/reader_test_plugins/missing_dependency.py +0 -0
- {reader-3.10 → reader-3.12}/tests/reader_test_plugins/missing_entry_point.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_app_wsgi.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_cli.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_config.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_exceptions.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_hash_utils.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_lazy_imports.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_parser.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_plugins_cli_status.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_plugins_enclosure_dedupe.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_plugins_entry_dedupe.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_plugins_mark_as_read.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_plugins_preview_feed_list.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_plugins_readtime.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_plugins_sqlite_releases.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_plugins_ua_fallback.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_reader_deprecations.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_reader_integration.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_reader_plugins.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_reader_private.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_reader_sort.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_tags.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_test_utils.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_types.py +0 -0
- {reader-3.10 → reader-3.12}/tests/test_utils.py +0 -0
- {reader-3.10 → reader-3.12}/tests/utils.py +0 -0
|
@@ -6,6 +6,37 @@ Changelog
|
|
|
6
6
|
:noindex:
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
Version 3.12
|
|
10
|
+
------------
|
|
11
|
+
|
|
12
|
+
Released 2024-03-05
|
|
13
|
+
|
|
14
|
+
* Split the :ref:`full-text search <fts>` index into a separate,
|
|
15
|
+
attached database.
|
|
16
|
+
(:issue:`323`)
|
|
17
|
+
* Require at least SQLite 3.18.
|
|
18
|
+
Previously, *reader* core required 3.15,
|
|
19
|
+
and only :meth:`~Reader.update_search` required 3.18.
|
|
20
|
+
(:issue:`323`)
|
|
21
|
+
* Enable `write-ahead logging`_ only once, when the database is created,
|
|
22
|
+
instead of every time it is opened.
|
|
23
|
+
(:issue:`323`)
|
|
24
|
+
* Vacuum the main database after migrations. (:issue:`323`)
|
|
25
|
+
* Add an internal :ref:`change tracking API <changes>`
|
|
26
|
+
to formalize how search keeps in sync with storage.
|
|
27
|
+
(:issue:`323`)
|
|
28
|
+
* Refactor storage internals. (:issue:`323`)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
Version 3.11
|
|
32
|
+
------------
|
|
33
|
+
|
|
34
|
+
Released 2023-12-30
|
|
35
|
+
|
|
36
|
+
* Allow filtering entries by their (entry) tags. (:issue:`328`)
|
|
37
|
+
* Support Python 3.12. (:issue:`326`)
|
|
38
|
+
|
|
39
|
+
|
|
9
40
|
Version 3.10
|
|
10
41
|
------------
|
|
11
42
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: reader
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.12
|
|
4
4
|
Summary: A Python feed reader library.
|
|
5
5
|
Author: lemon24
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
21
21
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
22
|
Classifier: Programming Language :: Python :: 3.10
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
25
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
25
26
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
26
27
|
Classifier: Topic :: Internet
|
|
@@ -68,6 +69,7 @@ Requires-Dist: mechanicalsoup; (implementation_name != "pypy" or python_version
|
|
|
68
69
|
Requires-Dist: requests-wsgi-adapter; extra == "tests"
|
|
69
70
|
Requires-Dist: lxml; (implementation_name != "pypy" or python_version <= "3.9") and extra == "tests"
|
|
70
71
|
Requires-Dist: html5lib; extra == "tests"
|
|
72
|
+
Requires-Dist: numpy; (implementation_name != "pypy" and os_name == "posix") and extra == "tests"
|
|
71
73
|
Requires-Dist: mypy; implementation_name != "pypy" and extra == "tests"
|
|
72
74
|
Requires-Dist: types-requests; extra == "tests"
|
|
73
75
|
Requires-Dist: types-beautifulsoup4; extra == "tests"
|
|
@@ -34,7 +34,7 @@ but I will prioritize supporting :doc:`contributors <contributing>`
|
|
|
34
34
|
|
|
35
35
|
* OPML support, :issue:`165`
|
|
36
36
|
* :ref:`deleting entries <deleting entries>`
|
|
37
|
-
*
|
|
37
|
+
* :ref:`feed interaction statistics <counts api>`
|
|
38
38
|
|
|
39
39
|
* security
|
|
40
40
|
|
|
@@ -57,7 +57,6 @@ but I will prioritize supporting :doc:`contributors <contributing>`
|
|
|
57
57
|
|
|
58
58
|
* :ref:`searchable tag values <searchable tags>`, e.g. for comments
|
|
59
59
|
* :ref:`unification with entry.read/important <entry flag unification>`
|
|
60
|
-
* filter entries by entry tags
|
|
61
60
|
* optimistic locking, :issue:`308`
|
|
62
61
|
* filter tags by prefix, :issue:`309`
|
|
63
62
|
|
|
@@ -339,6 +338,28 @@ Detailed requirements and API discussion: :issue:`168#issuecomment-642002049`.
|
|
|
339
338
|
|
|
340
339
|
Minimal work needed to support alternate storages: :issue:`168#issuecomment-1383127564`.
|
|
341
340
|
|
|
341
|
+
Storage internal API documented in version 3.10 (November 2023) in :issue:`325`.
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
Database optimization
|
|
345
|
+
~~~~~~~~~~~~~~~~~~~~~
|
|
346
|
+
|
|
347
|
+
Optimization lessons learned while fixing "database is locked" errors: :issue:`175#issuecomment-657495233`.
|
|
348
|
+
|
|
349
|
+
Some general guidance on schema/index design: :issue:`327#issuecomment-1859147186`.
|
|
350
|
+
|
|
351
|
+
Speeding up ``get_entries(sort='recent')``:
|
|
352
|
+
|
|
353
|
+
* first attempt at adding indexes: :issue:`134`
|
|
354
|
+
* using a computed column (``recent_sort``) didn't change things very much: :issue:`279`
|
|
355
|
+
* an index on ``recent_sort`` alone is not enough for pagination,
|
|
356
|
+
the index needs to match 1:1 the WHERE clause: :issue:`330`.
|
|
357
|
+
|
|
358
|
+
Speeding up ``get_entry_counts(feed=...)``:
|
|
359
|
+
|
|
360
|
+
* having an index on entries(feed) yielded a 4x improvement: :issue:`251`
|
|
361
|
+
* even better, we should cache commonly-used counts: :issue:`306#issuecomment-1694655504`
|
|
362
|
+
|
|
342
363
|
|
|
343
364
|
Parser
|
|
344
365
|
~~~~~~
|
|
@@ -429,7 +450,8 @@ https://death.andgravity.com/query-builder
|
|
|
429
450
|
Pagination for methods that return iterators
|
|
430
451
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
431
452
|
|
|
432
|
-
Why do it for the private implementation: :issue:`167#issuecomment-626753299
|
|
453
|
+
Why do it for the private implementation: :issue:`167#issuecomment-626753299`;
|
|
454
|
+
|
|
433
455
|
|
|
434
456
|
Detailed requirements and API discussion for public pagination: :issue:`196#issuecomment-706038363`.
|
|
435
457
|
|
|
@@ -444,6 +466,9 @@ From the initial issue:
|
|
|
444
466
|
|
|
445
467
|
Enabling search by default, and alternative search APIs: :issue:`252`.
|
|
446
468
|
|
|
469
|
+
Change tracking API: :issue:`323#issuecomment-1930756417`, model validated in
|
|
470
|
+
`this gist <https://gist.github.com/lemon24/558955ad82ba2e4f50c0184c630c668c>`_.
|
|
471
|
+
|
|
447
472
|
External resources:
|
|
448
473
|
|
|
449
474
|
* Comprehensive, although a bit old (2017): `What every software engineer should know about search <https://medium.com/startup-grind/what-every-software-engineer-should-know-about-search-27d1df99f80d>`_ (`full version <http://webcache.googleusercontent.com/search?q=cache:https://medium.com/startup-grind/what-every-software-engineer-should-know-about-search-27d1df99f80d&sca_esv=570067020&prmd=ivn&strip=1&vwsrc=0>`_)
|
|
@@ -522,12 +547,17 @@ and why I want more use-cases before implementing them (basically, YAGNI):
|
|
|
522
547
|
|
|
523
548
|
:issue:`253` discusses using entry tags to implement the current entry flags
|
|
524
549
|
(read, important); tl;dr: it's not worth adding entry tags just for this.
|
|
550
|
+
:issue:`327` discusses using entry tags for ``has_enclosures``; tl;dr:
|
|
551
|
+
it wouldn't save a lot of code, it would be only *a bit* slower,
|
|
552
|
+
and it reconfirms that read and important are integral to the data model,
|
|
553
|
+
so we still want them as regular columns.
|
|
525
554
|
|
|
526
555
|
After closing :issue:`228` with `wontfix` in late 2021,
|
|
527
556
|
in early 2022 (following the :issue:`266` tag/metadata unification)
|
|
528
557
|
I implemented entry and global tags in :issue:`272`;
|
|
529
558
|
there's a list of known use cases in the issue description.
|
|
530
559
|
|
|
560
|
+
|
|
531
561
|
Resource tags
|
|
532
562
|
^^^^^^^^^^^^^
|
|
533
563
|
|
|
@@ -581,6 +611,8 @@ Requirements, open questions, and how it interacts with :mod:`~reader.plugins.en
|
|
|
581
611
|
A summary of why it isn't easy to do: :issue:`301#issuecomment-1442423151`.
|
|
582
612
|
|
|
583
613
|
|
|
614
|
+
.. _counts api:
|
|
615
|
+
|
|
584
616
|
Counts API
|
|
585
617
|
~~~~~~~~~~
|
|
586
618
|
|
|
@@ -589,6 +621,11 @@ Detailed requirements and API discussion: :issue:`185#issuecomment-731743327`.
|
|
|
589
621
|
Tracking additional statistics (e.g. :attr:`~Entry.read_modified`): :issue:`254`;
|
|
590
622
|
how to expose said statistics: :issue:`254#issuecomment-1807064610`.
|
|
591
623
|
|
|
624
|
+
Notebook with a successful attempt to determine a feed "usefulness" score
|
|
625
|
+
based on how many entries I mark as read / important / don't care;
|
|
626
|
+
highlights a number of gaps in the *reader* API:
|
|
627
|
+
https://gist.github.com/lemon24/93222ef4bc4a775092b56546a6e6cd0f
|
|
628
|
+
|
|
592
629
|
|
|
593
630
|
Using None as a special argument value
|
|
594
631
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -622,6 +659,12 @@ Using a single Reader objects from multiple threads
|
|
|
622
659
|
|
|
623
660
|
Some thoughts on why it's difficult to do: :issue:`206#issuecomment-751383418`.
|
|
624
661
|
|
|
662
|
+
Requirements and use cases: :issue:`206#issuecomment-1179739301`.
|
|
663
|
+
|
|
664
|
+
When/how to run ``pragma optimize``: :issue:`206#issuecomment-1183660880`.
|
|
665
|
+
|
|
666
|
+
Full support added in version 2.16 (July 2022).
|
|
667
|
+
|
|
625
668
|
|
|
626
669
|
Plugins
|
|
627
670
|
~~~~~~~
|
|
@@ -127,6 +127,8 @@ since each connection would be to a *different* database::
|
|
|
127
127
|
reader.exceptions.StorageError: usage error: cannot use a private database from threads other than the creating thread
|
|
128
128
|
|
|
129
129
|
|
|
130
|
+
.. _backups:
|
|
131
|
+
|
|
130
132
|
Back-ups
|
|
131
133
|
~~~~~~~~
|
|
132
134
|
|
|
@@ -439,16 +441,27 @@ the entries that changed since the last call,
|
|
|
439
441
|
so it is OK to call it relatively often.
|
|
440
442
|
|
|
441
443
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
444
|
+
Search can be turned on/off through the
|
|
445
|
+
:meth:`~Reader.enable_search()` / :meth:`~Reader.disable_search()` methods
|
|
446
|
+
(persistent across instances using the same database),
|
|
447
|
+
or the ``search_enabled`` argument of :func:`make_reader`;
|
|
448
|
+
by default, search is enabled automatically
|
|
449
|
+
on the first :meth:`~Reader.update_search()` call.
|
|
450
|
+
If search is enabled,
|
|
451
|
+
you should call :meth:`~Reader.update_search()` regularly
|
|
452
|
+
to prevent unprocesses changes from accumulating over time.
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
Because the search index can be almost as large as the main database,
|
|
456
|
+
the default implementation splits it into a separate, attached database,
|
|
457
|
+
which allows :ref:`backing up <backups>` the main database separately;
|
|
458
|
+
for a reader created with ``make_reader('db.sqlite')``,
|
|
459
|
+
the search index will be in ``db.sqlite.search``.
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
.. versionchanged:: 3.12
|
|
463
|
+
Split the full-text search index into a separate database.
|
|
464
|
+
|
|
452
465
|
|
|
453
466
|
|
|
454
467
|
|
|
@@ -493,8 +506,7 @@ in which case the behavior is to ensure the tag exists
|
|
|
493
506
|
|
|
494
507
|
Besides storing resource metadata,
|
|
495
508
|
tags can be used for filtering feeds and entries
|
|
496
|
-
(
|
|
497
|
-
see the :meth:`~Reader.get_feeds()` documentation for more complex examples)::
|
|
509
|
+
(see :data:`.TagFilterInput` for more complex examples)::
|
|
498
510
|
|
|
499
511
|
>>> # feeds that have the tag "one"
|
|
500
512
|
>>> [f.title for f in reader.get_feeds(tags=['one'])]
|
|
@@ -143,9 +143,11 @@ but at least one other implementation needs to exists before that.
|
|
|
143
143
|
|
|
144
144
|
Currently, search is tightly-bound to a storage implementation
|
|
145
145
|
(see :meth:`~.BoundSearchStorageType.make_search`).
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
While the :ref:`change tracking API <changes>` allows
|
|
147
|
+
search implementations to keep in sync with text content changes,
|
|
148
|
+
there is no convenient way for :meth:`SearchType.search_entries`
|
|
149
|
+
to filter/sort results without storage cooperation;
|
|
150
|
+
:class:`StorageType` will need
|
|
149
151
|
additional capabilities to support this.
|
|
150
152
|
|
|
151
153
|
|
|
@@ -167,6 +169,27 @@ but at least one other implementation needs to exists before that.
|
|
|
167
169
|
:members:
|
|
168
170
|
|
|
169
171
|
|
|
172
|
+
.. _changes:
|
|
173
|
+
|
|
174
|
+
.. autoclass:: ChangeTrackingStorageType()
|
|
175
|
+
:members:
|
|
176
|
+
:show-inheritance:
|
|
177
|
+
|
|
178
|
+
.. autoclass:: ChangeTrackerType()
|
|
179
|
+
:members:
|
|
180
|
+
|
|
181
|
+
.. autoclass:: Change
|
|
182
|
+
:members:
|
|
183
|
+
|
|
184
|
+
.. autoclass:: Action
|
|
185
|
+
:members:
|
|
186
|
+
|
|
187
|
+
.. autoattribute:: reader.Entry._sequence
|
|
188
|
+
|
|
189
|
+
.. autoexception:: reader.exceptions.ChangeTrackingNotEnabledError
|
|
190
|
+
:show-inheritance:
|
|
191
|
+
|
|
192
|
+
|
|
170
193
|
Data objects
|
|
171
194
|
~~~~~~~~~~~~
|
|
172
195
|
|
|
@@ -67,8 +67,8 @@ However, the plugin used the internal :ref:`parser` API
|
|
|
67
67
|
and stored old tweets alongside the rendered HTML content
|
|
68
68
|
to avoid retrieving them again when updating the thread/entry.
|
|
69
69
|
|
|
70
|
-
You can still find the code
|
|
71
|
-
`
|
|
70
|
+
You can still find the code on GitHub:
|
|
71
|
+
`twitter.py <https://github.com/lemon24/reader/blob/3.6/src/reader/_plugins/twitter.py>`_.
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
.. _tumblr_gdpr:
|
|
@@ -84,8 +84,8 @@ including machine-readable RSS feeds).
|
|
|
84
84
|
This plugin is a good example of how to set cookies
|
|
85
85
|
on the Requests session used to retrieve feeds.
|
|
86
86
|
|
|
87
|
-
You can still find the code
|
|
88
|
-
`
|
|
87
|
+
You can still find the code on GitHub:
|
|
88
|
+
`tumblr_gdpr.py <https://github.com/lemon24/reader/blob/3.6/src/reader/_plugins/tumblr_gdpr.py>`_.
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
|
|
@@ -25,6 +25,7 @@ classifiers = [
|
|
|
25
25
|
"Programming Language :: Python :: 3 :: Only",
|
|
26
26
|
"Programming Language :: Python :: 3.10",
|
|
27
27
|
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
28
29
|
"Programming Language :: Python :: Implementation :: CPython",
|
|
29
30
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
30
31
|
"Topic :: Internet",
|
|
@@ -112,6 +113,8 @@ tests = [
|
|
|
112
113
|
# lxml does not have a PyPy 3.10+ wheel.
|
|
113
114
|
'lxml; (implementation_name != "pypy" or python_version <= "3.9")',
|
|
114
115
|
"html5lib",
|
|
116
|
+
# for bench.py
|
|
117
|
+
'numpy; (implementation_name != "pypy" and os_name == "posix")',
|
|
115
118
|
# mypy does not work on pypy (yet).
|
|
116
119
|
'mypy; implementation_name != "pypy"',
|
|
117
120
|
"types-requests",
|