From b140f249c146113e165078c40111a228f04e7a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Koutensk=C3=BD?= Date: Mon, 19 Feb 2018 10:45:47 +0100 Subject: [PATCH 1/5] Allow plugins to define early import stage functions --- beets/importer.py | 2 ++ beets/plugins.py | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/beets/importer.py b/beets/importer.py index aac21d77f0..4e4084eec0 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -313,6 +313,8 @@ def run(self): stages += [import_asis(self)] # Plugin stages. + for stage_func in plugins.early_import_stages(): + stages.append(plugin_stage(self, stage_func)) for stage_func in plugins.import_stages(): stages.append(plugin_stage(self, stage_func)) diff --git a/beets/plugins.py b/beets/plugins.py index d62f3c011e..ace5170e31 100644 --- a/beets/plugins.py +++ b/beets/plugins.py @@ -81,6 +81,7 @@ def __init__(self, name=None): self.template_fields = {} if not self.album_template_fields: self.album_template_fields = {} + self.early_import_stages = [] self.import_stages = [] self._log = log.getChild(self.name) @@ -94,6 +95,17 @@ def commands(self): """ return () + def get_early_import_stages(self): + """Return a list of functions that should be called as importer + pipelines stages early in the pipeline. + + The callables are wrapped versions of the functions in + `self.early_import_stages`. Wrapping provides some bookkeeping for the + plugin: specifically, the logging level is adjusted to WARNING. + """ + return [self._set_log_level_and_params(logging.WARNING, import_stage) + for import_stage in self.early_import_stages] + def get_import_stages(self): """Return a list of functions that should be called as importer pipelines stages. @@ -393,6 +405,14 @@ def template_funcs(): return funcs +def early_import_stages(): + """Get a list of early import stage functions defined by plugins.""" + stages = [] + for plugin in find_plugins(): + stages += plugin.get_early_import_stages() + return stages + + def import_stages(): """Get a list of import stage functions defined by plugins.""" stages = [] From d4625bced068bfd0cadff9e4a644bab2a8500eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Koutensk=C3=BD?= Date: Mon, 19 Feb 2018 10:46:06 +0100 Subject: [PATCH 2/5] Have convert plugin run early in the pipeline --- beetsplug/convert.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beetsplug/convert.py b/beetsplug/convert.py index 3800612482..d1223596fd 100644 --- a/beetsplug/convert.py +++ b/beetsplug/convert.py @@ -146,7 +146,7 @@ def __init__(self): u'copy_album_art': False, u'album_art_maxwidth': 0, }) - self.import_stages = [self.auto_convert] + self.early_import_stages = [self.auto_convert] self.register_listener('import_task_files', self._cleanup) From 1bb1bca77911198bc31223d52737bf8dd964c7f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Koutensk=C3=BD?= Date: Wed, 21 Feb 2018 15:54:37 +0100 Subject: [PATCH 3/5] Move the logging wrapper code into a helper function --- beets/plugins.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/beets/plugins.py b/beets/plugins.py index ace5170e31..4a2475f503 100644 --- a/beets/plugins.py +++ b/beets/plugins.py @@ -95,6 +95,12 @@ def commands(self): """ return () + def _set_stage_log_level(self, stages): + """Adjust all the stages in `stages` to WARNING logging level. + """ + return [self._set_log_level_and_params(logging.WARNING, stage) + for stage in stages] + def get_early_import_stages(self): """Return a list of functions that should be called as importer pipelines stages early in the pipeline. @@ -103,8 +109,7 @@ def get_early_import_stages(self): `self.early_import_stages`. Wrapping provides some bookkeeping for the plugin: specifically, the logging level is adjusted to WARNING. """ - return [self._set_log_level_and_params(logging.WARNING, import_stage) - for import_stage in self.early_import_stages] + return self._set_stage_log_level(self.early_import_stages) def get_import_stages(self): """Return a list of functions that should be called as importer @@ -114,8 +119,7 @@ def get_import_stages(self): `self.import_stages`. Wrapping provides some bookkeeping for the plugin: specifically, the logging level is adjusted to WARNING. """ - return [self._set_log_level_and_params(logging.WARNING, import_stage) - for import_stage in self.import_stages] + return self._set_stage_log_level(self.import_stages) def _set_log_level_and_params(self, base_log_level, func): """Wrap `func` to temporarily set this plugin's logger level to From 305f9f2dfb30c1148889da1cbba06bfef42725da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Koutensk=C3=BD?= Date: Wed, 21 Feb 2018 16:01:26 +0100 Subject: [PATCH 4/5] Document 'early_import_stages' in the docs --- docs/dev/plugins.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/dev/plugins.rst b/docs/dev/plugins.rst index 4d41c89718..5b0e4d08ba 100644 --- a/docs/dev/plugins.rst +++ b/docs/dev/plugins.rst @@ -432,6 +432,11 @@ to register it:: def stage(self, session, task): print('Importing something!') +It is also possible to request your function to run early in the pipeline by +adding the function to the plugin's ``early_import_stages`` field instead.:: + + self.early_import_stages = [self.stage] + .. _extend-query: Extend the Query Syntax From bbadb5f5e1cc2040c465330c7562affa4ed9031d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Koutensk=C3=BD?= Date: Wed, 21 Feb 2018 16:07:58 +0100 Subject: [PATCH 5/5] Changelog for #2814 --- docs/changelog.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 4381edeeb1..44558675b1 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -46,6 +46,11 @@ Fixes: * Avoid a crash when importing a non-ASCII filename when using an ASCII locale on Unix under Python 3. :bug:`2793` :bug:`2803` +* Convert plugin now runs before all others in the pipeline to solve an issue + with generating ReplayGain data incompatible between the source and target + file formats. This option to request (part of) your plugin to run early in the + pipeline has been exposed in the plugin API as well (```early_import_stages```). + Thanks to :user:`autrimpo`. 1.4.6 (December 21, 2017)