-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fetchart: defer file removal config option evaluation #5244
Merged
snejus
merged 2 commits into
beetbox:master
from
mgoltzsche:defer-fetchart-delete-src-evaluation
Sep 16, 2024
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of editing the config try patching it (or the relevant method in
fetchart.py
):There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, I am not sure I follow you here:
should_delete
property or method within theFetchArtPlugin
that could be mocked this way.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for linking up the reason why it's needed - this makes more sense now.
I'm concerned about the idea of a plugin overriding global settings, especially a setting like
move
. I'm not sure whether this would be the expected behaviour for users that have setups withmove: false
.Meanwhile, I think I see why this may be required for your plugin which firstly downloads and only then imports music.
If your plugin functionality completely depends on
move
being set to True, have you considered validating it instead?Ultimately, from
beets
implementation perspective, allowing global config adjustments in flight is an anti-pattern and in my opinion should be avoided.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user is not calling
beet import
butbeet ytimport
which has its own configuration (that it also applies to the import operation). Thus, the ytimport plugin overwriting some import parameters is not really unexpected to the user imho.Also, ytimport downloads into and imports from a temporary directory that it manages itself. As a user I don't want to edit/switch my import configuration every time I perform a different import operation - I have different CLI commands for that.
I agree it is not great. For instance if somebody wanted to run multiple imports in parallel they couldn't do that within a single Python process, each with different configuration like this.
However, as of now there is no need to run multiple in parallel and the alternative is to start a separate
beet import
Python process and overwrite the configuration via CLI options.Also, the other configuration options can be temporarily overwritten this way already.
Therefore why not allow a plugin the workaround of also overwriting the
move
configuration option this way within its CLI?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me as a user this is unexpected in the following ways:
move
configuration and always moves music into my library is not documented (didn't see it in the readme nor the command help).--move
nor--no-move
flag)Based on other commands that may move files, what I'm used to is
--move
,--write
etc.My previous
beets
configuration hadmove: no
andcopy: no
preventing any path adjustments during import. After the import, I did some additional processing on the files, and only then ran a command to move the files to my library directory.I'm struggling to think of a use case where I'd have to switch the configuration, i.e. want to have
move: no
for theimport
command andmove: yes
forytimport
. I presume users may want the same configuration to apply for both commands consistently?This makes sense. It sounds like once
ytimport
downloads a file to the temp directory, the situation is more or less equivalent to a user importing a local file manually. Did you consider delegating the import to thebeet import
command?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True but like I said: ytimport is importing from a temporary directory that it manages itself. In a way the fact that ihe ytimport plugin uses the beets' import plugin under the hood is more of an implementation detail.
You kind of have that control: the ytimport plugin supports a
--no-import
option which makes it download the files but not import them yet. Callingbeet ytimport
imports all files within the temp download directory that weren't imported previously and that weren't skipped explicitly. Leaving the files in the temp dir after they were imported makes no sense to me. The additional postprocessing and renaming of files after the import that you mentioned sounds more of a hacky workaround than a well designed/clean workflow to me. Either way your workflow would also work with the ytimport plugin if you call it with--no-import
and then run your custom import command(s) afterwards.Here's an example use-case: I am importing from another library. Because I don't want that to be a destructive operation, I just copy the files but leave the source files untouched. Because of the destructiveness of the move operation, I'd actually like it to be set to false in my beets configuration and just have the ytimport plugin enable it temporarily for its managed temp dir import.
Yes, in fact it was like that initially before I changed it to using the Python API as opposed to the CLI. This was to avoid spawning a new Python process for the import. Apart from the unnecessary overhead, spawning a new Python process comes with the disadvantage that global beets CLI options are not applied to the beets child process oob and would each have to be passed through to the child process explicitly, covering all beets options exhaustively, ideally. E.g. when beets' config file option is not passed through, it can result in the child process using a different beets configuration than its parent process unexpectedly. Even with the option being passed through the configuration could change during execution of the
ytimport
command since the child process reloads it. To give another example: the log verbosity (-vvv
) of the parent process is not applied to the child process oob. In this matter it is beneficial to be able to call a Python API from within the same Python process as opposed to having to call a CLI, spawning a new process.After all why is beets'
import_files
method public when it shouldn't be called by 3rd party Python code? Now that it is public, why would you still want to force users to call the CLI and be fine with the CLI overwriting the--move
option but not allow doing the same via the Python API (especially given the fact that this already works with all the other config options but themove
option)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition to this it also by default manages my library directory even when beets is configured not to do so.
It may have been hacky, but that's the beauty of beets with the flexibility it provides.
Sorry, I should have clarified that I meant using the Python API, but instead of the
import_files
function, using the importSubcommand
(I think it's found inbeets.commands
asimport_cmd
variable) and extending it with flags custom toytimport
. This would ensure consistent import behaviour.I imagine you'd also want to adjust
import_cmd.func
which runsbeets.commands::import_func
to something likeThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is calling the
import_func
better than calling theimport_files
function that the former function delegates to? I think the approach you're suggesting is disadvantageous: It would require the ytimport plugin to write all options it needs to overwrite into the opts dict just to have theimport_func
copy it into the config as opposed to letting the ytimport plugin do that directly. Theimport_func
function also doesn't treat these config changes as temporary but permanent ones, still requiring the ytimport plugin to restore the original configuration afterwards which is less obvious to maintain and more error-prone when it does not make the config changes directly but via theopts
but then still has to access the config directly to restore its original values. (The latter is actually optional since usually no other code/plugin is run within the same Python process after theytimport
CLI command terminates but it leaves the door open for another 3rd party plugin to call the ytimport plugin via its Python API directly and run additional code afterwards within the same Python process based on the original user-specified configuration.)Also, the problem this PR is solving still exists in the approach you're describing (the global config is modified after the fetchart plugin was initialized) and as I understand it also exists within Beets internally when you look at e.g. the import plugin overwriting the
move
option explicitly after the fetchart plugin was already initialized with the original/previous value of that option, resulting in the fetchart plugin not honouring the new value.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that these options are only relevant for the import, and importing is delegated to beets, why should it be partly reimplemented in ytimport? I am assuming that
ytimport
does not overwrite any import-specific options but it has flags--import
and--no-import
to control whether theimport_func
is called.The global config object is updated this way since the flags override what is specified in the configuration file. This way plugins that run during the import respect whatever is configured by the flags.
Let's consider the example I used above
Assuming that the global configuration is adjusted by
import_func
only, the case you described can only happen if the 3rd party plugin extendsytimport
command with some functionality that runs after the import is complete. Following my suggestion, we would have a command likeIf it happens to depend on
import
configuration, I believe it is a good idea to keep the configuration thatimport_func
overrides, which would happen if the user runsbeet post-ytimport --move
, for example.Realistically, though, I think, it is more likely that a 3rd party plugin is going to be more interested in the functionality specific to your plugin: the
download
function in my example above (everything except the import).Have just checked this - you're completely right. Fetchart has essentially been using the default configuration all this time.
I'm going to approve this in a second, just going to quickly scan whether this issue has been reported before and add them to the PR.
Thanks for your patience!