typing: type plugins.send and BeetsPlugin.register_listener explicitly - #6886
Open
snejus wants to merge 6 commits into
Open
typing: type plugins.send and BeetsPlugin.register_listener explicitly#6886snejus wants to merge 6 commits into
plugins.send and BeetsPlugin.register_listener explicitly#6886snejus wants to merge 6 commits into
Conversation
snejus
requested review from
a team,
asardaes,
henry-oberholtzer and
semohr
as code owners
July 29, 2026 09:44
|
Thank you for the PR! The changelog has not been updated, so here is a friendly reminder to check if you need to add an entry. |
❌ 9 Tests Failed:
View the top 3 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
Contributor
There was a problem hiding this comment.
Pull request overview
grug see PR make plugin event system more typed. grug like clearer contracts, less guess. but grug also see one real runtime footgun now.
Changes:
- add explicit typing for plugin event names + per-event args/return types in
beets.plugins(register_listener,send) - update many plugins to match typed listener signatures (args + return types) and add
TYPE_CHECKINGimports - small correctness cleanups found by typing pass (path/query typing, config parsing, handler return shapes)
Reviewed changes
Copilot reviewed 41 out of 41 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| beetsplug/zero.py | add future annotations + type listener args for importer/write hooks |
| beetsplug/titlecase.py | make handler return type explicit |
| beetsplug/tidal/init.py | type import_begin auth hook to take session |
| beetsplug/thumbnails.py | add future annotations + type album processing hooks |
| beetsplug/subsonicupdate.py | type db/exit hooks and expected args |
| beetsplug/sonosupdate.py | type db/exit hooks and expected args |
| beetsplug/smartplaylist.py | tighten model type to shared LibModel for db-change/matching |
| beetsplug/scrub.py | add future annotations + type importer hook args |
| beetsplug/replaygain.py | add missing -> None annotations, type import_end args |
| beetsplug/plexupdate.py | type db/exit hooks and expected args |
| beetsplug/playlist.py | type config parsing and listener args; refine relative_to handling |
| beetsplug/play.py | add future annotations + type importer choice hook return |
| beetsplug/permissions.py | split item vs album handlers; type listener args |
| beetsplug/mpdupdate.py | add future annotations + type db/exit hooks; annotate helpers |
| beetsplug/mbsubmit.py | type importer hook return; normalize to always return list |
| beetsplug/mbpseudo.py | add explicit -> None where needed |
| beetsplug/loadext.py | type library_opened; iterate config as sequence explicitly |
| beetsplug/kodiupdate.py | type db/exit hooks and expected args |
| beetsplug/importsource.py | fix path query bytes + use public item.db access |
| beetsplug/importfeeds.py | add future annotations + type importer/library hooks |
| beetsplug/importadded.py | type import hooks + switch some handlers to list returns (introduces bug) |
| beetsplug/ihate.py | add future annotations + type importer hook args |
| beetsplug/hook.py | type nested hook function return |
| beetsplug/fromfilename.py | type importer hook args; use task.items list directly |
| beetsplug/filefilter.py | type import_task_created handler to return task list |
| beetsplug/fetchart.py | add missing -> None annotations; typed config template usage |
| beetsplug/embyupdate.py | add future annotations + type db/exit hooks |
| beetsplug/edit.py | type importer choice hook return |
| beetsplug/chroma.py | type importer hook args; use task.items list directly |
| beetsplug/beatport.py | add missing -> None annotations |
| beetsplug/badfiles.py | add config default + type importer hooks and action types |
| beetsplug/advancedrewrite.py | refactor rule parsing into helpers + typed config shapes |
| beetsplug/acousticbrainz.py | add future annotations + type importer hook args |
| beets/util/color.py | widen colorize input to StrPath and normalize via os.fspath |
| beets/ui/commands/import_/session.py | rely on typed send return for import_task_before_choice |
| beets/plugins.py | define typed event unions + typed event arg TypedDicts; overload listener/send APIs |
| beets/dbcore/queryparse.py | tighten query type params/return for query construction |
| beets/dbcore/query.py | simplify relative path join under bytes-only music_dir context |
Comments suppressed due to low confidence (1)
beetsplug/importadded.py:85
- grug see same drop-task bug. This
import_task_createdlistener alwaysreturn []at end, so it tells importer "no tasks" and importer drop work. Should returnNonewhen only side effects.
for item in items:
self.record_import_mtime(item, item.path, item.path)
return []
Comment on lines
+51
to
+55
| def check_config( | ||
| self, task: ImportTask, session: ImportSession | ||
| ) -> list[ImportTask]: | ||
| self.config["preserve_mtimes"].get(bool) | ||
| return [] |
Comment on lines
+467
to
+472
| @overload | ||
| def register_listener( | ||
| self, | ||
| event: ImportTaskCreatedEventType, | ||
| func: Callable[[Unpack[ImportTaskEventArgs]], list[ImportTask]], | ||
| ) -> None: ... |
snejus
force-pushed
the
simplify-util
branch
3 times, most recently
from
July 29, 2026 23:53
9d08f90 to
da5f7dd
Compare
snejus
force-pushed
the
type-handlers-and-listeners-explicitly
branch
3 times, most recently
from
July 30, 2026 02:08
f2f60d0 to
662fd13
Compare
snejus
force-pushed
the
type-handlers-and-listeners-explicitly
branch
from
July 30, 2026 02:13
662fd13 to
bbb95df
Compare
snejus
force-pushed
the
type-handlers-and-listeners-explicitly
branch
from
July 30, 2026 07:15
bbb95df to
4ee7cca
Compare
snejus
force-pushed
the
simplify-util
branch
2 times, most recently
from
July 30, 2026 11:21
527d072 to
eab29f5
Compare
snejus
force-pushed
the
type-handlers-and-listeners-explicitly
branch
from
July 30, 2026 11:21
4ee7cca to
c61e61d
Compare
snejus
force-pushed
the
type-handlers-and-listeners-explicitly
branch
from
July 30, 2026 12:17
c61e61d to
0f25d52
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds explicit typing to the plugin event system in
beets.plugins, including per-event argument shapes and return types forregister_listener()andsend(). This makes the listener API much clearer and turns implicit plugin contracts into checked interfaces.Updates all plugins to match those typed event signatures, by adding concrete parameter/return types and aligning handlers with the events they subscribe to. The architectural effect is better consistency across plugin boundaries, especially around importer hooks and metadata callbacks.
Includes a small set of follow-up fixes uncovered by the typing work in places like
advancedrewrite,badfiles,playlist,permissions,importsource, and query/path handling. These are mostly correctness and config/path-type cleanups rather than new features.High-level impact: this change improves maintainability and static analysis across the plugin layer, reduces ambiguity in hook behavior, and makes future plugin changes safer without changing the overall architecture or user-facing workflows in a major way.