Skip to content

Commit

Permalink
UpdateHook cleanup (#218).
Browse files Browse the repository at this point in the history
  • Loading branch information
lemon24 committed Aug 15, 2023
1 parent 47b1aa7 commit 0f61c9d
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 33 deletions.
34 changes: 14 additions & 20 deletions src/reader/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from collections.abc import Mapping
from collections.abc import Sequence
from dataclasses import dataclass
from dataclasses import field
from datetime import datetime
from datetime import timezone
from functools import cached_property
Expand All @@ -32,7 +31,6 @@
from .types import Entry
from .types import EntryAddedBy
from .types import EntryInput
from .types import EntryUpdateStatus
from .types import ExceptionInfo
from .types import Feed
from .types import FeedInput
Expand Down Expand Up @@ -569,9 +567,6 @@ def fix_datetime_tzinfo(


UpdateHook = Callable[..., None]
AfterEntryUpdateHook = Callable[[_T, EntryData, EntryUpdateStatus], None]
FeedUpdateHook = Callable[[_T, str], None]
FeedsUpdateHook = Callable[[_T], None]
UpdateHookType = Literal[
'before_feeds_update',
'before_feed_update',
Expand All @@ -581,19 +576,18 @@ def fix_datetime_tzinfo(
]


@dataclass(frozen=True)
class UpdateHooks(Generic[_T]):
target: _T
before_feeds_update: list[FeedsUpdateHook[_T]] = field(default_factory=list)
before_feed_update: list[FeedUpdateHook[_T]] = field(default_factory=list)
after_entry_update: list[AfterEntryUpdateHook[_T]] = field(default_factory=list)
after_feed_update: list[FeedUpdateHook[_T]] = field(default_factory=list)
after_feeds_update: list[FeedsUpdateHook[_T]] = field(default_factory=list)
class UpdateHooks(dict[UpdateHookType, list[UpdateHook]], Generic[_T]):
def __init__(self, target: _T):
super().__init__()
self.target = target

def __missing__(self, key: UpdateHookType) -> list[UpdateHook]:
return self.setdefault(key, [])

def run(
self, when: UpdateHookType, resource_id: tuple[str, ...] | None, *args: Any
) -> None:
for hook in getattr(self, when):
for hook in self[when]:
try:
hook(self.target, *args)
except Exception as e:
Expand All @@ -603,12 +597,12 @@ def group(self, message: str) -> _UpdateHookErrorGrouper:
return _UpdateHookErrorGrouper(self, message)


@dataclass(frozen=True)
class _UpdateHookErrorGrouper:
hooks: UpdateHooks[Any]
message: str
exceptions: list[UpdateHookError] = field(default_factory=list)
seen_dedupe_keys: set[Any] = field(default_factory=set)
def __init__(self, hooks: UpdateHooks[Any], message: str):
self.hooks = hooks
self.message = message
self.exceptions: list[UpdateHookError] = []
self.seen_dedupe_keys: set[Any] = set()

def run(
self,
Expand All @@ -617,7 +611,7 @@ def run(
*args: Any,
limit: int = 0,
) -> None:
for hook in getattr(self.hooks, when):
for hook in self.hooks[when]:
try:
hook(self.hooks.target, *args)
except Exception as e:
Expand Down
29 changes: 16 additions & 13 deletions src/reader/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging
import numbers
import warnings
from collections.abc import Callable
from collections.abc import Iterable
from collections.abc import Mapping
from collections.abc import MutableSequence
Expand All @@ -22,14 +23,12 @@
from ._requests_utils import TimeoutType
from ._search import Search
from ._storage import Storage
from ._types import AfterEntryUpdateHook
from ._types import DEFAULT_RESERVED_NAME_SCHEME
from ._types import entry_data_from_obj
from ._types import EntryData
from ._types import EntryFilterOptions
from ._types import EntryUpdateIntent
from ._types import FeedFilterOptions
from ._types import FeedsUpdateHook
from ._types import FeedUpdateHook
from ._types import fix_datetime_tzinfo
from ._types import NameScheme
from ._types import UpdateHooks
Expand Down Expand Up @@ -85,6 +84,10 @@
# mypy doesn't seem to support Self yet.
_TReader = TypeVar('_TReader', bound='Reader')

AfterEntryUpdateHook = Callable[['Reader', EntryData, EntryUpdateStatus], None]
FeedUpdateHook = Callable[['Reader', str], None]
FeedsUpdateHook = Callable[['Reader'], None]


def make_reader(
url: str,
Expand Down Expand Up @@ -2199,7 +2202,7 @@ def reserved_name_scheme(self, value: Mapping[str, str]) -> None:
raise AttributeError(f"invalid reserved name scheme: {value}") from e

@property
def before_feeds_update_hooks(self) -> MutableSequence[FeedsUpdateHook[Reader]]:
def before_feeds_update_hooks(self) -> MutableSequence[FeedsUpdateHook]:
"""List of functions called *once* before updating any feeds,
at the beginning of :meth:`update_feeds` / :meth:`update_feeds_iter`,
but not :meth:`update_feed`.
Expand All @@ -2220,10 +2223,10 @@ def before_feeds_update_hooks(self) -> MutableSequence[FeedsUpdateHook[Reader]]:
Wrap unexpected exceptions in :exc:`UpdateHookError`.
"""
return self._update_hooks.before_feeds_update
return self._update_hooks['before_feeds_update']

@property
def before_feed_update_hooks(self) -> MutableSequence[FeedUpdateHook[Reader]]:
def before_feed_update_hooks(self) -> MutableSequence[FeedUpdateHook]:
"""List of functions called for each updated feed
before the feed is updated.
Expand All @@ -2244,10 +2247,10 @@ def before_feed_update_hooks(self) -> MutableSequence[FeedUpdateHook[Reader]]:
Wrap unexpected exceptions in :exc:`UpdateHookError`.
"""
return self._update_hooks.before_feed_update
return self._update_hooks['before_feed_update']

@property
def after_entry_update_hooks(self) -> MutableSequence[AfterEntryUpdateHook[Reader]]:
def after_entry_update_hooks(self) -> MutableSequence[AfterEntryUpdateHook]:
"""List of functions called for each updated entry
after the feed is updated.
Expand Down Expand Up @@ -2281,10 +2284,10 @@ def after_entry_update_hooks(self) -> MutableSequence[AfterEntryUpdateHook[Reade
Try to run all hooks, don't stop after one fails.
"""
return self._update_hooks.after_entry_update
return self._update_hooks['after_entry_update']

@property
def after_feed_update_hooks(self) -> MutableSequence[FeedUpdateHook[Reader]]:
def after_feed_update_hooks(self) -> MutableSequence[FeedUpdateHook]:
"""List of functions called for each updated feed
after the feed is updated.
Expand All @@ -2307,10 +2310,10 @@ def after_feed_update_hooks(self) -> MutableSequence[FeedUpdateHook[Reader]]:
Try to run all hooks, don't stop after one fails.
"""
return self._update_hooks.after_feed_update
return self._update_hooks['after_feed_update']

@property
def after_feeds_update_hooks(self) -> MutableSequence[FeedsUpdateHook[Reader]]:
def after_feeds_update_hooks(self) -> MutableSequence[FeedsUpdateHook]:
"""List of functions called *once* after updating all feeds,
at the end of :meth:`update_feeds` / :meth:`update_feeds_iter`,
but not :meth:`update_feed`.
Expand All @@ -2333,4 +2336,4 @@ def after_feeds_update_hooks(self) -> MutableSequence[FeedsUpdateHook[Reader]]:
Try to run all hooks, don't stop after one fails.
"""
return self._update_hooks.after_feeds_update
return self._update_hooks['after_feeds_update']

0 comments on commit 0f61c9d

Please sign in to comment.