diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3bf6d56b..c2c3571c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -3,7 +3,7 @@ exclude: ^src/reader/_vendor/.*$
repos:
- repo: https://github.com/pycqa/isort
- rev: 7.0.0
+ rev: 8.0.1
hooks:
- id: isort
@@ -14,7 +14,7 @@ repos:
args: ["--py311-plus"]
- repo: https://github.com/psf/black-pre-commit-mirror
- rev: 25.12.0
+ rev: 26.3.1
hooks:
- id: black
args: ["-S"]
diff --git a/docs/conf.py b/docs/conf.py
index 20554a49..6731bfcb 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -6,7 +6,6 @@
import packaging.version
from setuptools.config.pyprojecttoml import read_configuration
-
sys.path.insert(0, os.path.abspath('../src'))
# mock some things "by hand", so we can import reader below without any dependencies
@@ -25,7 +24,6 @@
import reader
-
extensions = [
'sphinx_rtd_theme',
'sphinx.ext.autodoc',
diff --git a/examples/podcast.py b/examples/podcast.py
index 1591ee1a..097507c3 100644
--- a/examples/podcast.py
+++ b/examples/podcast.py
@@ -14,7 +14,6 @@
from reader import make_reader
-
feed_url = "http://www.hellointernet.fm/podcast?format=rss"
podcasts_dir = "podcasts"
diff --git a/scripts/bench.py b/scripts/bench.py
index 16e2cd7d..47463973 100644
--- a/scripts/bench.py
+++ b/scripts/bench.py
@@ -14,7 +14,6 @@
import click
-
root_dir = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(root_dir, '../src'))
sys.path.insert(0, os.path.join(root_dir, '../tests'))
diff --git a/scripts/debug_storage_stats.py b/scripts/debug_storage_stats.py
index fa28a5cd..c0867dd1 100644
--- a/scripts/debug_storage_stats.py
+++ b/scripts/debug_storage_stats.py
@@ -29,7 +29,6 @@
import numpy as np
from tabulate import tabulate
-
# assumes dict()s are ordered
value_funcs = {
diff --git a/scripts/entry_dedupe_backtest.py b/scripts/entry_dedupe_backtest.py
index 68671fe4..87776011 100644
--- a/scripts/entry_dedupe_backtest.py
+++ b/scripts/entry_dedupe_backtest.py
@@ -21,7 +21,6 @@
from reader import make_reader
from reader.plugins import entry_dedupe
-
DB_ARCHIVE = "_backups/reader.sqlite.2025-10-04.gz"
file = sys.argv[1]
diff --git a/scripts/jscontrols.py b/scripts/jscontrols.py
index 788f7fdf..ddd212d7 100644
--- a/scripts/jscontrols.py
+++ b/scripts/jscontrols.py
@@ -8,14 +8,12 @@
from flask import redirect
from flask import request
-
root_dir = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(root_dir, '../src'))
from reader._app.api_thing import APIError
from reader._app.api_thing import APIThing
-
app = Flask(
__name__,
template_folder='../src/reader/_app/templates',
diff --git a/scripts/vendor_app_stuff.py b/scripts/vendor_app_stuff.py
index 63b27c43..0afe9b0b 100644
--- a/scripts/vendor_app_stuff.py
+++ b/scripts/vendor_app_stuff.py
@@ -3,7 +3,6 @@
import requests
-
STUFF = {
"htmx.org@2.0.8": ["dist/htmx.min.js"],
"htmx-ext-response-targets@2.0.4": ["dist/response-targets.min.js"],
diff --git a/src/reader/__init__.py b/src/reader/__init__.py
index 5c318b14..887bc7a9 100644
--- a/src/reader/__init__.py
+++ b/src/reader/__init__.py
@@ -93,7 +93,6 @@
ReaderWarning as ReaderWarning,
)
-
# Constants.
USER_AGENT = f'python-reader/{__version__} (+https://github.com/lemon24/reader)'
diff --git a/src/reader/__main__.py b/src/reader/__main__.py
index bb60a94d..5479c878 100644
--- a/src/reader/__main__.py
+++ b/src/reader/__main__.py
@@ -1,6 +1,5 @@
import sys
-
CANNOT_IMPORT = """\
Error: cannot import reader._cli
diff --git a/src/reader/_app/__init__.py b/src/reader/_app/__init__.py
index d2c00c31..610d9860 100644
--- a/src/reader/_app/__init__.py
+++ b/src/reader/_app/__init__.py
@@ -38,7 +38,6 @@
from .forms import EntryFilter
from .forms import FeedFilter
-
# for a prototype with tags and search support, see
# https://github.com/lemon24/reader/tree/3.21/src/reader/_app/v2
diff --git a/src/reader/_app/ext.py b/src/reader/_app/ext.py
index 6747cf6b..6bcf4532 100644
--- a/src/reader/_app/ext.py
+++ b/src/reader/_app/ext.py
@@ -10,7 +10,6 @@
from reader import make_reader
from reader.plugins._loader import PluginLoader
-
_plugin_loader = PluginLoader('init_app')
diff --git a/src/reader/_app/legacy/__init__.py b/src/reader/_app/legacy/__init__.py
index 145e7ec6..68fa059b 100644
--- a/src/reader/_app/legacy/__init__.py
+++ b/src/reader/_app/legacy/__init__.py
@@ -44,7 +44,6 @@
from .api_thing import APIError
from .api_thing import APIThing
-
blueprint = Blueprint(
'reader', __name__, static_folder='static', template_folder='templates'
)
diff --git a/src/reader/_app/legacy/wsgi.py b/src/reader/_app/legacy/wsgi.py
index f57e4824..f2284d3c 100644
--- a/src/reader/_app/legacy/wsgi.py
+++ b/src/reader/_app/legacy/wsgi.py
@@ -15,7 +15,6 @@
import reader._app.legacy
import reader._cli
-
config = reader._cli.load_reader_config()
app = reader._app.legacy.create_app(config)
app.config['TRAP_BAD_REQUEST_ERRORS'] = bool(
diff --git a/src/reader/_app/wsgi.py b/src/reader/_app/wsgi.py
index 90bc1fe1..2c9d5c94 100644
--- a/src/reader/_app/wsgi.py
+++ b/src/reader/_app/wsgi.py
@@ -15,7 +15,6 @@
import reader._app
import reader._cli
-
config = reader._cli.load_reader_config()
app = reader._app.create_app(config)
app.config['TRAP_BAD_REQUEST_ERRORS'] = bool(
diff --git a/src/reader/_cli.py b/src/reader/_cli.py
index 2924b060..0c7c5ee2 100644
--- a/src/reader/_cli.py
+++ b/src/reader/_cli.py
@@ -19,7 +19,6 @@
from ._config_utils import load_config_from_context
from .plugins._loader import PluginLoader
-
app_name = reader.__name__
app_dir = click.get_app_dir(app_name)
diff --git a/src/reader/_hash_utils.py b/src/reader/_hash_utils.py
index 88f4816c..78c0454f 100644
--- a/src/reader/_hash_utils.py
+++ b/src/reader/_hash_utils.py
@@ -27,7 +27,6 @@
from collections.abc import Collection
from typing import Any
-
# The first byte of the hash contains its version,
# to allow upgrading the implementation without changing existing hashes.
# (In practice, it's likely we'll just let the hash change and update
diff --git a/src/reader/_parser/__init__.py b/src/reader/_parser/__init__.py
index 3c52a6ee..e7cb0f0c 100644
--- a/src/reader/_parser/__init__.py
+++ b/src/reader/_parser/__init__.py
@@ -33,7 +33,6 @@
from .requests import SessionFactory
from .requests import TimeoutType
-
if TYPE_CHECKING: # pragma: no cover
from werkzeug.datastructures import RequestCacheControl
diff --git a/src/reader/_parser/_http_utils.py b/src/reader/_parser/_http_utils.py
index c6bf8934..1ecaf0f3 100644
--- a/src/reader/_parser/_http_utils.py
+++ b/src/reader/_parser/_http_utils.py
@@ -10,7 +10,6 @@
from werkzeug.datastructures import MIMEAccept
from werkzeug.datastructures import ResponseCacheControl
-
parse_options_header = werkzeug.http.parse_options_header
parse_accept_header = werkzeug.http.parse_accept_header
parse_date = werkzeug.http.parse_date
diff --git a/src/reader/_parser/_lazy.py b/src/reader/_parser/_lazy.py
index e73dc3bc..dbd24fca 100644
--- a/src/reader/_parser/_lazy.py
+++ b/src/reader/_parser/_lazy.py
@@ -36,7 +36,6 @@
from ._url_utils import normalize_url
from .requests import SessionFactory
-
log = logging.getLogger('reader')
diff --git a/src/reader/_parser/feedparser.py b/src/reader/_parser/feedparser.py
index c56b7291..a1c859be 100644
--- a/src/reader/_parser/feedparser.py
+++ b/src/reader/_parser/feedparser.py
@@ -20,7 +20,6 @@
from ._http_utils import parse_accept_header
from ._http_utils import unparse_accept_header
-
if os.environ.get('READER_NO_VENDORED_FEEDPARSER', '') not in ('', '0'):
import feedparser # type: ignore
else:
diff --git a/src/reader/_parser/jsonfeed.py b/src/reader/_parser/jsonfeed.py
index 35f593c4..1f2db285 100644
--- a/src/reader/_parser/jsonfeed.py
+++ b/src/reader/_parser/jsonfeed.py
@@ -18,7 +18,6 @@
from ..types import Content
from ..types import Enclosure
-
if TYPE_CHECKING: # pragma: no cover
from . import FeedAndEntries
from .requests import Headers
diff --git a/src/reader/_parser/requests/__init__.py b/src/reader/_parser/requests/__init__.py
index a4c069ac..26478cae 100644
--- a/src/reader/_parser/requests/__init__.py
+++ b/src/reader/_parser/requests/__init__.py
@@ -21,7 +21,6 @@
from ..._utils import lazy_import
-
if TYPE_CHECKING: # pragma: no cover
import requests
diff --git a/src/reader/_parser/requests/_lazy.py b/src/reader/_parser/requests/_lazy.py
index 2b494c84..85bdeb70 100644
--- a/src/reader/_parser/requests/_lazy.py
+++ b/src/reader/_parser/requests/_lazy.py
@@ -13,7 +13,6 @@
from . import CachingInfo
from . import TimeoutType
-
if TYPE_CHECKING: # pragma: no cover
from . import Headers
from . import RequestHook
diff --git a/src/reader/_plugins/legacy/enclosure_tags.py b/src/reader/_plugins/legacy/enclosure_tags.py
index 6d66e70b..19e8f529 100644
--- a/src/reader/_plugins/legacy/enclosure_tags.py
+++ b/src/reader/_plugins/legacy/enclosure_tags.py
@@ -40,7 +40,6 @@
from flask import url_for
from jinja2.filters import do_striptags as striptags
-
blueprint = Blueprint('enclosure_tags', __name__)
diff --git a/src/reader/_plugins/legacy/preview_feed_list.py b/src/reader/_plugins/legacy/preview_feed_list.py
index b9bcbe7c..495802f9 100644
--- a/src/reader/_plugins/legacy/preview_feed_list.py
+++ b/src/reader/_plugins/legacy/preview_feed_list.py
@@ -36,7 +36,6 @@
from reader._app.legacy import get_reader
from reader._app.legacy import got_preview_parse_error
-
blueprint = Blueprint('preview_feed_list', __name__, template_folder='templates')
diff --git a/src/reader/_plugins/legacy/share.py b/src/reader/_plugins/legacy/share.py
index cc25caad..1b225575 100644
--- a/src/reader/_plugins/legacy/share.py
+++ b/src/reader/_plugins/legacy/share.py
@@ -14,7 +14,6 @@
from urllib.parse import quote
from urllib.parse import urlparse
-
TEMPLATES = {
'Twitter': "https://twitter.com/share?text={title}&url={url}",
'HN': "https://news.ycombinator.com/submitlink?u={url}&t={title}",
diff --git a/src/reader/_plugins/sqlite_releases.py b/src/reader/_plugins/sqlite_releases.py
index 799d01d5..36b36eb0 100644
--- a/src/reader/_plugins/sqlite_releases.py
+++ b/src/reader/_plugins/sqlite_releases.py
@@ -35,7 +35,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
warnings.filterwarnings(
'ignore',
message='No parser was explicitly specified',
diff --git a/src/reader/_storage/__init__.py b/src/reader/_storage/__init__.py
index b34d42da..56696b3e 100644
--- a/src/reader/_storage/__init__.py
+++ b/src/reader/_storage/__init__.py
@@ -8,7 +8,6 @@
from ._feeds import FeedsMixin
from ._tags import TagsMixin
-
# Row value support was added in 3.15.
# pragma_*() tabled-valued functions were added in 3.16.
# last_insert_rowid() support for FTS5 was added in 3.18.
diff --git a/src/reader/_storage/_base.py b/src/reader/_storage/_base.py
index ecbffa57..d91e1a1b 100644
--- a/src/reader/_storage/_base.py
+++ b/src/reader/_storage/_base.py
@@ -15,7 +15,6 @@
from ._sql_utils import paginated_query
from ._sql_utils import Query
-
APPLICATION_ID = b'read'
_T = TypeVar('_T')
diff --git a/src/reader/_storage/_changes.py b/src/reader/_storage/_changes.py
index 41a40617..ab8019f0 100644
--- a/src/reader/_storage/_changes.py
+++ b/src/reader/_storage/_changes.py
@@ -12,7 +12,6 @@
from ._sql_utils import Query
from ._sqlite_utils import ddl_transaction
-
if TYPE_CHECKING: # pragma: no cover
from ._base import StorageBase
@@ -41,12 +40,10 @@ def _enable(cls, db: sqlite3.Connection) -> None:
for object in objects.values():
object.create(db)
db.execute("UPDATE entries SET sequence = randomblob(16)")
- db.execute(
- """
+ db.execute("""
INSERT INTO changes
SELECT sequence, feed, id, '', 1 FROM entries
- """
- )
+ """)
@wrap_exceptions()
def disable(self) -> None:
diff --git a/src/reader/_storage/_entries.py b/src/reader/_storage/_entries.py
index c5fff1ca..a9b1fb9b 100644
--- a/src/reader/_storage/_entries.py
+++ b/src/reader/_storage/_entries.py
@@ -37,7 +37,6 @@
from ._tags import entry_tags_filter
from ._tags import feed_tags_filter
-
if TYPE_CHECKING: # pragma: no cover
from ._base import StorageBase
else:
@@ -404,10 +403,7 @@ def set_entry_recent_sort(
def get_entries_query(
filter: EntryFilter, sort: EntrySort
) -> tuple[Query, dict[str, Any]]:
- query = (
- Query()
- .SELECT(
- *"""
+ query = Query().SELECT(*"""
entries.feed
feeds.updated
feeds.title
@@ -441,11 +437,7 @@ def get_entries_query(
entries.last_updated
entries.original_feed
entries.sequence
- """.split()
- )
- .FROM("entries")
- .JOIN("feeds ON feeds.url = entries.feed")
- )
+ """.split()).FROM("entries").JOIN("feeds ON feeds.url = entries.feed")
context = entry_filter(query, filter)
ENTRIES_SORT[sort](query)
return query, context
@@ -540,13 +532,11 @@ def entry_filter(
add(TRISTATE_FILTER_TO_SQL[important].format(expr='entries.important'))
if has_enclosures is not None:
- add(
- f"""
+ add(f"""
{'NOT' if has_enclosures else ''}
(json_array_length(entries.enclosures) IS NULL
OR json_array_length(entries.enclosures) = 0)
- """
- )
+ """)
if source_url:
add("json_extract(entries.source, '$.url') = :source_url")
diff --git a/src/reader/_storage/_feeds.py b/src/reader/_storage/_feeds.py
index 282511a5..7f27bb7b 100644
--- a/src/reader/_storage/_feeds.py
+++ b/src/reader/_storage/_feeds.py
@@ -28,7 +28,6 @@
from ._sqlite_utils import rowcount_exactly_one
from ._tags import feed_tags_filter
-
if TYPE_CHECKING: # pragma: no cover
from ._base import StorageBase
else:
diff --git a/src/reader/_storage/_html_utils.py b/src/reader/_storage/_html_utils.py
index 331568c0..ae6c02eb 100644
--- a/src/reader/_storage/_html_utils.py
+++ b/src/reader/_storage/_html_utils.py
@@ -8,7 +8,6 @@
import warnings
from typing import TYPE_CHECKING
-
if TYPE_CHECKING: # pragma: no cover
import bs4
diff --git a/src/reader/_storage/_schema.py b/src/reader/_storage/_schema.py
index e74ff6e2..c93305bf 100644
--- a/src/reader/_storage/_schema.py
+++ b/src/reader/_storage/_schema.py
@@ -4,7 +4,6 @@
from ._sqlite_utils import ddl_transaction
from ._sqlite_utils import HeavyMigration
-
SCHEMA = parse_schema("""
CREATE TABLE feeds (
@@ -153,12 +152,10 @@ def create_indexes(db: sqlite3.Connection) -> None:
def update_from_36_to_37(db: sqlite3.Connection, /) -> None: # pragma: no cover
# for https://github.com/lemon24/reader/issues/279
db.execute("ALTER TABLE entries ADD COLUMN recent_sort TIMESTAMP;")
- db.execute(
- """
+ db.execute("""
UPDATE entries
SET recent_sort = coalesce(published, updated, first_updated_epoch);
- """
- )
+ """)
db.execute("DROP INDEX entries_by_kinda_first_updated;")
db.execute("DROP INDEX entries_by_kinda_published;")
entries_by_recent_index.create(db)
@@ -168,8 +165,7 @@ def update_from_37_to_38(db: sqlite3.Connection, /) -> None: # pragma: no cover
# https://github.com/lemon24/reader/issues/254#issuecomment-1404215814
entries_table.create(db, 'new_entries')
- db.execute(
- """
+ db.execute("""
INSERT INTO new_entries (
id,
feed,
@@ -226,8 +222,7 @@ def update_from_37_to_38(db: sqlite3.Connection, /) -> None: # pragma: no cover
feed_order,
recent_sort
FROM entries;
- """
- )
+ """)
# IMPORTANT: this drops ALL indexes and triggers ON entries
db.execute("DROP TABLE entries;")
diff --git a/src/reader/_storage/_search.py b/src/reader/_storage/_search.py
index fd4beff6..d7134693 100644
--- a/src/reader/_storage/_search.py
+++ b/src/reader/_storage/_search.py
@@ -40,7 +40,6 @@
from ._sqlite_utils import ddl_transaction
from ._sqlite_utils import SQLiteType
-
APPLICATION_ID = b'reaD'
_T = TypeVar('_T')
@@ -142,8 +141,7 @@ def _enable(cls, db: sqlite3.Connection, schema: str = 'main') -> None:
# We put the unindexed stuff at the end to avoid having to adjust
# stuff depended on the column index if we add new columns.
#
- db.execute(
- f"""
+ db.execute(f"""
CREATE VIRTUAL TABLE {schema}.entries_search USING fts5(
title, -- entries.title
content, -- entries.summary or one of entries.content
@@ -154,18 +152,14 @@ def _enable(cls, db: sqlite3.Connection, schema: str = 'main') -> None:
_is_feed_user_title UNINDEXED,
tokenize = "porter unicode61 remove_diacritics 1 tokenchars '_'"
);
- """
- )
+ """)
# TODO: we still need to tune the rank weights, these are just guesses
- db.execute(
- """
+ db.execute("""
INSERT INTO entries_search(entries_search, rank)
VALUES ('rank', 'bm25(4, 1, 2)');
- """
- )
+ """)
- db.execute(
- f"""
+ db.execute(f"""
CREATE TABLE {schema}.entries_search_sync_state (
sequence BLOB NOT NULL,
feed TEXT NOT NULL,
@@ -173,8 +167,7 @@ def _enable(cls, db: sqlite3.Connection, schema: str = 'main') -> None:
es_rowids TEXT NOT NULL DEFAULT '[]',
PRIMARY KEY (sequence, feed, id)
);
- """
- )
+ """)
@wrap_exceptions()
def disable(self) -> None:
@@ -532,8 +525,7 @@ def make_search_entries_query(
) -> tuple[Query, dict[str, Any]]:
search = (
Query()
- .SELECT(
- """
+ .SELECT("""
_id,
_feed,
rank,
@@ -545,8 +537,7 @@ def make_search_entries_query(
'value', snippet(entries_search, 1, :before, :after, '...', :tokens),
'rank', rank
) AS content
- """
- )
+ """)
.FROM("entries_search")
.JOIN("entries ON (entries.id, entries.feed) = (_id, _feed)")
.WHERE("entries_search MATCH :query")
diff --git a/src/reader/_storage/_sql_utils.py b/src/reader/_storage/_sql_utils.py
index 6470fbbc..093dfbe3 100644
--- a/src/reader/_storage/_sql_utils.py
+++ b/src/reader/_storage/_sql_utils.py
@@ -39,7 +39,6 @@
from typing import TypeVar
from typing import Union
-
if TYPE_CHECKING: # pragma: no cover
import sqlite3
diff --git a/src/reader/_storage/_sqlite_utils.py b/src/reader/_storage/_sqlite_utils.py
index c9a963d9..14316e41 100644
--- a/src/reader/_storage/_sqlite_utils.py
+++ b/src/reader/_storage/_sqlite_utils.py
@@ -29,7 +29,6 @@
from typing import no_type_check
from typing import TypeVar
-
SQLiteType = TypeVar('SQLiteType', None, int, float, str, bytes)
diff --git a/src/reader/_storage/_tags.py b/src/reader/_storage/_tags.py
index a25ab128..93af4018 100644
--- a/src/reader/_storage/_tags.py
+++ b/src/reader/_storage/_tags.py
@@ -24,7 +24,6 @@
from ._sql_utils import Query
from ._sqlite_utils import rowcount_exactly_one
-
if TYPE_CHECKING: # pragma: no cover
from ._base import StorageBase
else:
diff --git a/src/reader/_types.py b/src/reader/_types.py
index bae593e2..3f021039 100644
--- a/src/reader/_types.py
+++ b/src/reader/_types.py
@@ -56,7 +56,6 @@
from .types import TagFilterInput
from .types import TristateFilterInput
-
log = logging.getLogger("reader")
# Private API
diff --git a/src/reader/_update.py b/src/reader/_update.py
index d8cecb09..98706a6c 100644
--- a/src/reader/_update.py
+++ b/src/reader/_update.py
@@ -34,7 +34,6 @@
from .types import UpdatedFeed
from .types import UpdateResult
-
if TYPE_CHECKING: # pragma: no cover
from ._parser import ParsedFeed
from ._types import FeedFilter
diff --git a/src/reader/_utils.py b/src/reader/_utils.py
index fe729c6d..f8ea1b7a 100644
--- a/src/reader/_utils.py
+++ b/src/reader/_utils.py
@@ -18,7 +18,6 @@
from typing import cast
from typing import TypeVar
-
FuncType = Callable[..., Any]
F = TypeVar('F', bound=FuncType)
diff --git a/src/reader/core.py b/src/reader/core.py
index 2cfa9fb3..f46adf84 100644
--- a/src/reader/core.py
+++ b/src/reader/core.py
@@ -75,7 +75,6 @@
from .types import UpdatedFeed
from .types import UpdateResult
-
if TYPE_CHECKING: # pragma: no cover
from ._parser import Parser
diff --git a/src/reader/plugins/__init__.py b/src/reader/plugins/__init__.py
index 34eefe06..1ac33f54 100644
--- a/src/reader/plugins/__init__.py
+++ b/src/reader/plugins/__init__.py
@@ -13,7 +13,6 @@
from ._loader import PluginLoader
-
if TYPE_CHECKING: # pragma: no cover
from .. import Reader # noqa: F401
diff --git a/src/reader/plugins/_loader.py b/src/reader/plugins/_loader.py
index 7967050a..9eceb792 100644
--- a/src/reader/plugins/_loader.py
+++ b/src/reader/plugins/_loader.py
@@ -11,7 +11,6 @@
from ..exceptions import InvalidPluginError
from ..exceptions import PluginInitError
-
T = TypeVar('T')
PluginFunc = Callable[[T], None]
PluginInput = Union[str, PluginFunc[T]]
diff --git a/src/reader/plugins/entry_dedupe.py b/src/reader/plugins/entry_dedupe.py
index c4b310c7..fe1dcc0e 100644
--- a/src/reader/plugins/entry_dedupe.py
+++ b/src/reader/plugins/entry_dedupe.py
@@ -156,7 +156,6 @@
from reader._utils import BetterStrPartial as partial
from reader.exceptions import EntryNotFoundError
-
log = logging.getLogger(__name__)
@@ -839,8 +838,7 @@ def merge_tags(make_reserved, entry, duplicates):
# text tokenization
-_TOKEN_RE = re.compile(
- r"""(?x)
+_TOKEN_RE = re.compile(r"""(?x)
\b # word boundary
(?:
\d{1,4} (?: [/-] \d{1,4} ){1,2} # dates
@@ -850,8 +848,7 @@ def merge_tags(make_reserved, entry, duplicates):
\w+ # other words
)
\b # word boundary
- """
-)
+ """)
def tokenize(s, preprocessor=lambda x: x):
diff --git a/src/reader/plugins/mark_as_read.py b/src/reader/plugins/mark_as_read.py
index 2c697edb..64539e6a 100644
--- a/src/reader/plugins/mark_as_read.py
+++ b/src/reader/plugins/mark_as_read.py
@@ -63,7 +63,6 @@
from reader.exceptions import TagNotFoundError
from reader.types import EntryUpdateStatus
-
# avoid circular imports
log = logging.getLogger(__name__)
diff --git a/src/reader/plugins/readtime.py b/src/reader/plugins/readtime.py
index 9aeed64b..7a40e34d 100644
--- a/src/reader/plugins/readtime.py
+++ b/src/reader/plugins/readtime.py
@@ -56,7 +56,6 @@
from reader.exceptions import EntryNotFoundError
from reader.types import _get_entry_content
-
log = logging.getLogger('reader.plugins.readtime')
diff --git a/src/reader/plugins/ua_fallback.py b/src/reader/plugins/ua_fallback.py
index 41c7f565..6556280e 100644
--- a/src/reader/plugins/ua_fallback.py
+++ b/src/reader/plugins/ua_fallback.py
@@ -26,7 +26,6 @@
import logging
-
_LOG_HEADERS = ['Server', 'X-Powered-By']
log = logging.getLogger(__name__)
diff --git a/src/reader/types.py b/src/reader/types.py
index 037fa19c..7f6c1f09 100644
--- a/src/reader/types.py
+++ b/src/reader/types.py
@@ -24,7 +24,6 @@
from reader.exceptions import UpdateError
-
# can't be defined here because of circular imports
from reader._utils import MISSING as MISSING # isort: skip # noqa: F401
from reader._utils import MissingType as MissingType # isort: skip # noqa: F401
diff --git a/tests/data/10.json.py b/tests/data/10.json.py
index faafe153..8c7cb174 100644
--- a/tests/data/10.json.py
+++ b/tests/data/10.json.py
@@ -5,7 +5,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(
url=f'{url_base}10.json',
version='json10',
diff --git a/tests/data/empty.atom.py b/tests/data/empty.atom.py
index 258dcb24..c1319ff1 100644
--- a/tests/data/empty.atom.py
+++ b/tests/data/empty.atom.py
@@ -5,7 +5,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(url=f'{url_base}empty.atom', version='atom10')
entries = [
diff --git a/tests/data/empty.json.py b/tests/data/empty.json.py
index e8b22b01..d3396ab3 100644
--- a/tests/data/empty.json.py
+++ b/tests/data/empty.json.py
@@ -5,7 +5,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(
url=f'{url_base}empty.json',
version='json11',
diff --git a/tests/data/empty.rss.py b/tests/data/empty.rss.py
index 047d4a5b..bdf63662 100644
--- a/tests/data/empty.rss.py
+++ b/tests/data/empty.rss.py
@@ -5,7 +5,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(url=f'{url_base}empty.rss', version='rss20')
entries = [
diff --git a/tests/data/full.atom.py b/tests/data/full.atom.py
index 59232cec..30e00446 100644
--- a/tests/data/full.atom.py
+++ b/tests/data/full.atom.py
@@ -6,7 +6,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(
url=f'{url_base}full.atom',
updated=datetime.datetime(2003, 12, 13, 18, 30, 2, tzinfo=datetime.UTC),
diff --git a/tests/data/full.json.py b/tests/data/full.json.py
index 2c39b683..fdc2a48c 100644
--- a/tests/data/full.json.py
+++ b/tests/data/full.json.py
@@ -5,7 +5,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(
url=f'{url_base}full.json',
updated=None,
diff --git a/tests/data/full.rss.py b/tests/data/full.rss.py
index 8db1290b..1afb79e9 100644
--- a/tests/data/full.rss.py
+++ b/tests/data/full.rss.py
@@ -6,7 +6,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(
url=f'{url_base}full.rss',
updated=datetime.datetime(2010, 9, 6, 0, 1, tzinfo=datetime.UTC),
diff --git a/tests/data/invalid.json.py b/tests/data/invalid.json.py
index 22a2bd2a..f195d92c 100644
--- a/tests/data/invalid.json.py
+++ b/tests/data/invalid.json.py
@@ -5,7 +5,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(
url=f'{url_base}invalid.json',
version='json11',
diff --git a/tests/data/relative.atom.py b/tests/data/relative.atom.py
index 12969415..e88a5fb4 100644
--- a/tests/data/relative.atom.py
+++ b/tests/data/relative.atom.py
@@ -5,7 +5,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(
url=f'{url_base}relative.atom',
link=f'{rel_base}file.html',
diff --git a/tests/data/relative.rss.py b/tests/data/relative.rss.py
index 122a4daf..b8eb4c27 100644
--- a/tests/data/relative.rss.py
+++ b/tests/data/relative.rss.py
@@ -5,7 +5,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(
url=f'{url_base}relative.rss',
link=f'{rel_base}file.html',
diff --git a/tests/data/unknown.json.py b/tests/data/unknown.json.py
index f89596c3..61f0a3c4 100644
--- a/tests/data/unknown.json.py
+++ b/tests/data/unknown.json.py
@@ -5,7 +5,6 @@
from reader._types import EntryData
from reader._types import FeedData
-
feed = FeedData(
url=f'{url_base}unknown.json',
version='json',
diff --git a/tests/test__types.py b/tests/test__types.py
index 5fa4ab7f..3ae57d32 100644
--- a/tests/test__types.py
+++ b/tests/test__types.py
@@ -8,7 +8,6 @@
from reader._types import tag_filter_argument
from reader._types import tristate_filter_argument
-
TAG_DATA = [
([], [None, [], (), [[]], ((),), [[], []]]),
([[True]], [True, [True], [[True]]]),
diff --git a/tests/test__utils.py b/tests/test__utils.py
index c2e80eef..15de8278 100644
--- a/tests/test__utils.py
+++ b/tests/test__utils.py
@@ -3,7 +3,6 @@
from reader._utils import deprecated
from reader._utils import deprecated_wrapper
-
# Normally, the stuff in _utils is tested by tests for higher level code,
# but some of the things aren't always used.
diff --git a/tests/test_app_legacy.py b/tests/test_app_legacy.py
index 07294094..2e5df369 100644
--- a/tests/test_app_legacy.py
+++ b/tests/test_app_legacy.py
@@ -8,7 +8,6 @@
from reader._app.legacy import create_app
from utils import utc_datetime as datetime
-
# mechanicalsoup depends on lxml, but we don't have that everywhere.
try:
import mechanicalsoup
diff --git a/tests/test_bench.py b/tests/test_bench.py
index 443aa8c6..39db1928 100644
--- a/tests/test_bench.py
+++ b/tests/test_bench.py
@@ -8,13 +8,11 @@
from test_cli import patch_app_dir
from test_reader_filter import setup_reader_for_tags
-
root_dir = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(root_dir, '../scripts'))
import bench
from bench import cli
-
pytestmark = pytest.mark.slow
pytest.importorskip("numpy")
diff --git a/tests/test_changes.py b/tests/test_changes.py
index f63cf626..1d429ef1 100644
--- a/tests/test_changes.py
+++ b/tests/test_changes.py
@@ -7,7 +7,6 @@
from reader._types import Change
from reader.exceptions import ChangeTrackingNotEnabledError
-
pytestmark = pytest.mark.noscheduled
diff --git a/tests/test_config_utils.py b/tests/test_config_utils.py
index a7aa13d0..15cd41b8 100644
--- a/tests/test_config_utils.py
+++ b/tests/test_config_utils.py
@@ -63,14 +63,12 @@ def test_empty_config(with_config):
def test_config(with_config):
- with_config(
- """\
+ with_config("""\
[cli]
plugin=['config']
[cli.sub]
option='config'
- """
- )
+ """)
expected = {'': {'plugin': ('CONFIG',)}, 'sub': {'option': 'CONFIG'}}
assert invoke(cli, ['sub']) == expected
diff --git a/tests/test_html_utils.py b/tests/test_html_utils.py
index c3ae98d5..575e9c41 100644
--- a/tests/test_html_utils.py
+++ b/tests/test_html_utils.py
@@ -3,7 +3,6 @@
from reader._storage._html_utils import strip_html
-
STRIP_HTML_DATA = [
('', ''),
('
', ''),
diff --git a/tests/test_lazy_imports.py b/tests/test_lazy_imports.py
index e31ba41b..f6859cee 100644
--- a/tests/test_lazy_imports.py
+++ b/tests/test_lazy_imports.py
@@ -14,7 +14,6 @@
import reader.plugins
from utils import parametrize_dict
-
# these tests take ~1s in total
pytestmark = pytest.mark.slow
@@ -65,8 +64,7 @@ def get_imported_modules(code):
return process.stdout.split()
-LAZY_MODULES = frozenset(
- """\
+LAZY_MODULES = frozenset("""\
bs4
requests
feedparser
@@ -74,8 +72,7 @@ def get_imported_modules(code):
urllib.request
multiprocessing
concurrent.futures
- """.split()
-)
+ """.split())
# all in a single script to save time
diff --git a/tests/test_plugins_entry_dedupe.py b/tests/test_plugins_entry_dedupe.py
index 19bb2be7..2dd571bb 100644
--- a/tests/test_plugins_entry_dedupe.py
+++ b/tests/test_plugins_entry_dedupe.py
@@ -20,7 +20,6 @@
from utils import parametrize_dict
from utils import utc_datetime as datetime
-
pytestmark = pytest.mark.noscheduled
diff --git a/tests/test_plugins_mark_as_read.py b/tests/test_plugins_mark_as_read.py
index 5a0ee283..5185a230 100644
--- a/tests/test_plugins_mark_as_read.py
+++ b/tests/test_plugins_mark_as_read.py
@@ -5,7 +5,6 @@
from utils import utc_datetime as datetime
-
pytestmark = pytest.mark.noscheduled
diff --git a/tests/test_plugins_preview_feed_list.py b/tests/test_plugins_preview_feed_list.py
index cc9d9d1e..0436385c 100644
--- a/tests/test_plugins_preview_feed_list.py
+++ b/tests/test_plugins_preview_feed_list.py
@@ -5,7 +5,6 @@
from test_app_legacy import make_browser
from test_app_legacy import pytestmark
-
pytestmark = list(pytestmark)
pytestmark.append(
pytest.mark.filterwarnings("ignore:No parser was explicitly specified")
diff --git a/tests/test_plugins_readtime.py b/tests/test_plugins_readtime.py
index 9f179726..3f223220 100644
--- a/tests/test_plugins_readtime.py
+++ b/tests/test_plugins_readtime.py
@@ -5,7 +5,6 @@
from utils import rename_argument
from utils import utc_datetime as datetime
-
pytestmark = pytest.mark.noscheduled
diff --git a/tests/test_reader_deprecations.py b/tests/test_reader_deprecations.py
index d122302f..ec146d68 100644
--- a/tests/test_reader_deprecations.py
+++ b/tests/test_reader_deprecations.py
@@ -4,5 +4,4 @@
from fakeparser import Parser
-
# Nothing here (yet).
diff --git a/tests/test_reader_hooks.py b/tests/test_reader_hooks.py
index a85fa9d2..229ee64a 100644
--- a/tests/test_reader_hooks.py
+++ b/tests/test_reader_hooks.py
@@ -12,7 +12,6 @@
from test_reader_private import CustomRetriever
from utils import utc_datetime as datetime
-
pytestmark = pytest.mark.noscheduled
diff --git a/tests/test_reader_lifecycle.py b/tests/test_reader_lifecycle.py
index c48804bc..304251d7 100644
--- a/tests/test_reader_lifecycle.py
+++ b/tests/test_reader_lifecycle.py
@@ -21,7 +21,6 @@
from reader import StorageError
from utils import rename_argument
-
pytestmark = pytest.mark.noscheduled
diff --git a/tests/test_reader_private.py b/tests/test_reader_private.py
index 3e947343..01529e67 100644
--- a/tests/test_reader_private.py
+++ b/tests/test_reader_private.py
@@ -19,7 +19,6 @@
from utils import utc_datetime
from utils import utc_datetime as datetime
-
pytestmark = pytest.mark.noscheduled
diff --git a/tests/test_reader_search.py b/tests/test_reader_search.py
index 339559c7..65318b49 100644
--- a/tests/test_reader_search.py
+++ b/tests/test_reader_search.py
@@ -27,7 +27,6 @@
from utils import utc_datetime
from utils import utc_datetime as datetime
-
pytestmark = pytest.mark.noscheduled
@@ -563,14 +562,10 @@ def get_entries_search():
)
def get_entries_search_sync_state():
- return sorted(
- db.execute(
- """
+ return sorted(db.execute("""
select feed, id, sequence, json_array_length(es_rowids)
from entries_search_sync_state
- """
- )
- )
+ """))
reader.update_search()
one, two = sorted(reader.get_entries(), key=lambda e: e.resource_id)
diff --git a/tests/test_reader_sort.py b/tests/test_reader_sort.py
index ecc8b3bb..c7ab4490 100644
--- a/tests/test_reader_sort.py
+++ b/tests/test_reader_sort.py
@@ -6,7 +6,6 @@
from utils import rename_argument
from utils import utc_datetime as datetime
-
pytestmark = pytest.mark.noscheduled
diff --git a/tests/test_reader_update.py b/tests/test_reader_update.py
index 03b96e17..fceec044 100644
--- a/tests/test_reader_update.py
+++ b/tests/test_reader_update.py
@@ -27,7 +27,6 @@
from utils import parametrize_dict
from utils import utc_datetime as datetime
-
# fmt: off
def prepare_feed(reader):
diff --git a/tests/test_reader_utils.py b/tests/test_reader_utils.py
index 1dcdbe40..3e7a08cb 100644
--- a/tests/test_reader_utils.py
+++ b/tests/test_reader_utils.py
@@ -5,7 +5,6 @@
from reader import EntryNotFoundError
from reader.utils import archive_entries
-
pytestmark = pytest.mark.noscheduled
diff --git a/tests/test_search.py b/tests/test_search.py
index 878992d9..9767c5ed 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -16,7 +16,6 @@
from reader._storage._sqlite_utils import require_version
from utils import utc_datetime as datetime
-
STRIP_HTML_DATA = [(i, i) for i in [None, 10, 11.2, b'aabb', b'aa
bb']] + [
('aabb', 'aabb'),
('aa
bb', 'aabb'),
diff --git a/tests/test_sql_utils.py b/tests/test_sql_utils.py
index 1c3db61c..7eb11c76 100644
--- a/tests/test_sql_utils.py
+++ b/tests/test_sql_utils.py
@@ -9,8 +9,7 @@
def test_query_simple():
query = BaseQuery().SELECT('select').FROM('from').JOIN('join').WHERE('where')
- assert str(query) == dedent(
- """\
+ assert str(query) == dedent("""\
SELECT
select
FROM
@@ -19,8 +18,7 @@ def test_query_simple():
join
WHERE
where
- """
- )
+ """)
def test_query_complicated():
@@ -63,8 +61,7 @@ def test_query_complicated():
.SELECT()
.SELECT()
)
- assert str(query) == dedent(
- """\
+ assert str(query) == dedent("""\
WITH
(
first cte
@@ -105,19 +102,16 @@ def test_query_complicated():
third
LIMIT
limit
- """
- )
+ """)
def test_query_flag():
query = BaseQuery().SELECT('one').SELECT('two').SELECT_DISTINCT()
- assert str(query) == dedent(
- """\
+ assert str(query) == dedent("""\
SELECT DISTINCT
one,
two
- """
- )
+ """)
with pytest.raises(ValueError):
BaseQuery().SELECT_MAGIC('one')
@@ -151,39 +145,25 @@ def make_query(cls=Query):
query.scrolling_window_order_by('one')
query.LIMIT('limit')
query.add_last([])
- assert str(query) == str(
- make_query(BaseQuery)
- .WHERE(
- """
+ assert str(query) == str(make_query(BaseQuery).WHERE("""
(
one
) > (
:last_0
)
- """
- )
- .ORDER_BY('one ASC')
- .LIMIT('limit')
- )
+ """).ORDER_BY('one ASC').LIMIT('limit'))
query = make_query()
query.scrolling_window_order_by('one', desc=True, keyword='HAVING')
query.LIMIT('limit')
query.add_last([])
- assert str(query) == str(
- make_query(BaseQuery)
- .HAVING(
- """
+ assert str(query) == str(make_query(BaseQuery).HAVING("""
(
one
) < (
:last_0
)
- """
- )
- .ORDER_BY('one DESC')
- .LIMIT('limit')
- )
+ """).ORDER_BY('one DESC').LIMIT('limit'))
def test_scrolling_window_last():
diff --git a/tests/test_sqlite_utils.py b/tests/test_sqlite_utils.py
index d0b04c0e..0f71ab1f 100644
--- a/tests/test_sqlite_utils.py
+++ b/tests/test_sqlite_utils.py
@@ -22,7 +22,6 @@
from reader._storage._sqlite_utils import wrap_exceptions
from utils import rename_argument
-
original_sqlite3_connect = sqlite3.connect