In particular, SealedDate's class methods always return an instance
of the class they're invoked through (i.e., `SealedDate.from_date_parts`
intentionally never returns `MonthSeal` or `YearSeal`).
To propertly annotate this, a type variable is needed (or the much
simpler `Self` in Python 3.11).
Note that Django forms _already_ have suppport for partial date data; we
just need to extend it when converting to Python (using SealedDate instead
of returning an error).
In most cases, we want to return back to where we came from after
performing an action. It's not safe to return to an arbitrary referer,
so this streamlines using the util validator to verify the redirect and
fall back on regular redirect params if the referer is outside our
domain.
This should be quicker, because it queries the users in one go instead
of jumping straight to iterating over them, and it checks if a user
blocks the poster before allowing them to be tagged.
- use activitypub.Author instead of custom dict
- prefer to display "Author of [title]" from ISNI data instead of short description
- merge isni and db authors for edit_book display
- fix edit_book template to use changed data
- rename some functions in utils/isni.py
- add timeout to isni API call
- use activitypub.Author dataclass instead of bespoke dict
- display isni authors as "Author of" first title in ISNI record if possible
- sensible fallbacks if title info unavailable in isni record
When an existing author is selected as a new author when editing a book,
if they have an ISNI ID recorded we check the record and augment the local
database record from the ISNI data.
Also dedupes author aliases for this feature and when adding a completely
new author.