Skip to content
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

Add auto_keep option to convert plugin - attempt to fix #1840 #4302

Merged
merged 5 commits into from
Mar 11, 2022

Conversation

DucNg
Copy link
Contributor

@DucNg DucNg commented Feb 28, 2022

Description

Fixes #1840

My idea was to add a new option so people using the old option won't have to change anything. This way it's a non breaking change. Even if being the default for the auto option would make more sens.

I don't think option naming is ideal so I'm very open to suggestions on this.

Using beet-alternatives to do exactly that is also a possibility but seemed a little overkill for my use case. Figured could be nice to have it build in.

To Do

  • Documentation. (If you've add a new command-line flag, for example, find the appropriate page under docs/ to describe it.)
  • Changelog. (Add an entry to docs/changelog.rst near the top of the document.)
  • Tests. (Encouraged but not strictly required.)

Should I had tests for this? Changes seems minimal.

@sampsyo
Copy link
Member

sampsyo commented Mar 1, 2022

Thanks for getting this started; this seems like a good approach! (That is, an entirely separate option that's like auto but does the other thing with the generated files.)

I actually don't mind the name. auto_keep seems perfectly serviceable to me.

Here is an ill-posed question, if you don't mind: I'm curious about why there is so much code in the new auto_convert_keep method. It needs to cover all the configuration bases, of course. But I wonder if this would be a good opportunity to refactor some of that stuff out so that it can share setup/configuration logic with the other two modes (auto and explicitly with the beet convert command). But how to do this is not immediately obvious and would require some creativity…

@DucNg
Copy link
Contributor Author

DucNg commented Mar 1, 2022 via email

convert items after imports but also keep original files intact
link = self.config['link'].get(bool)

threads = self.config['threads'].get(int)
empty_opts = self.commands()[0].parser.get_default_values()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to do this? It doesn't feel quite right.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very creative! While it doesn't bother me too much, it does seem a little odd that we'd be using the CLI arguments here even though this method doesn't have anything to do with the command itself.

It's not exactly very clean, but one option would be to let _get_opts_and_config's argument be None. I think all of the conditionals in there would end up ignoring the opts value for this mode anyway, right? At least it would make it clear that we are using only the configuration values, nothing from the command line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually that was my first attempt but it doesn't work.

For example for dest it will do:
dest = None.dest ....
Resulting in: 'NoneType' object has no attribute 'dest'

A elegant workaround would have been to to this: dest = opts?.dest for every options. But unfortunately safe navigation operator is not available in python.

The only option left then would be to manually check if opts is None for every option witch is not very elegant in my opinion. What do you think? I think parser.get_default_values() works well in this context but looks very hacky at the same time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, the opts.foo if opts else config[‘foo’].get() dance was pretty much what I was recommending here. But you make a good point that this would bring a high complexity tax for something that doesn’t seem worth it.

I think a better solution would probably be to use Confuse’s support for argparse options. But maybe the best route would be to note that this is the next step and merge this PR as-is, hoping to tackle the Confuse-based alternative in a subsequent PR (since it will involve some refactoring of its own)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine with me

@DucNg
Copy link
Contributor Author

DucNg commented Mar 4, 2022

@sampsyo I tried to refactor common code as best as I could.

Copy link
Member

@sampsyo sampsyo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome; looking good!! Here are a few granular suggestions.

Comment on lines 69 to 72
- **auto_keep**: As opposite to **auto**, import non transcoded versions of
your files but still convert them to **dest**. It uses the default format
you have defined in your config file.
Default: ``no``.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should be slightly more explicit that this does this automatically on import? In that sense, it is similar to (rather than solely different from) auto.

hardlink = self.config['hardlink'].get(bool)
link = self.config['link'].get(bool)

return (dest, threads, path_formats, fmt, pretend, hardlink, link)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No parentheses are necessary here.

@@ -546,3 +526,45 @@ def _cleanup(self, task, session):
if os.path.isfile(path):
util.remove(path)
_temp_files.remove(path)

def _get_opts_and_config(self, opts):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quick docstring on this new method would be super helpful. (No need to even list all the options exhaustively, IMO—just giving the gist of what this does would be useful.)

Comment on lines +559 to +560
def _parallel_convert(self, dest, keep_new, path_formats, fmt,
pretend, link, hardlink, threads, items):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A docstring here could be really useful too.

link = self.config['link'].get(bool)

threads = self.config['threads'].get(int)
empty_opts = self.commands()[0].parser.get_default_values()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very creative! While it doesn't bother me too much, it does seem a little odd that we'd be using the CLI arguments here even though this method doesn't have anything to do with the command itself.

It's not exactly very clean, but one option would be to let _get_opts_and_config's argument be None. I think all of the conditionals in there would end up ignoring the opts value for this mode anyway, right? At least it would make it clear that we are using only the configuration values, nothing from the command line.

@DucNg DucNg requested a review from sampsyo March 9, 2022 17:35
Copy link
Member

@sampsyo sampsyo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, this is good to go! Seeking volunteers for a broader refactoring of the way configuration works for this plugin…

@sampsyo sampsyo merged commit bf66895 into beetbox:master Mar 11, 2022
@DucNg DucNg deleted the auto_keep branch March 11, 2022 18:02
@mannp
Copy link

mannp commented Mar 12, 2022

Thanks for the additional option... I wondered if the new option respects if auto convert is disabled?

I have the following config, which I would not expect to convert new imported items, but it is?

convert:
    auto: no
    auto_keep: True,

@sampsyo
Copy link
Member

sampsyo commented Mar 12, 2022

It's a good point; it might be nice to document the interaction between the two options. The intent is that they're mutually exclusive; you enable one or the other. Care to expand on that in the docs at all, @DucNg?

@mannp
Copy link

mannp commented Mar 12, 2022

I'd understood 'auto' was to convert or not to convert on import... while I convert by running the convert command... if it's working the same as auto, it would still keep the originals in place, but only do it when the convert command is issued.

Will auto_keep: 'no' also work, to keep it the same as auto?

Just observations, but thanks again for making the changes :)

@sampsyo
Copy link
Member

sampsyo commented Mar 12, 2022

Yes! The default for auto_keep is no, so you don't to change anything if you don't want to use it. But keeping it off will let you manually convert stuff by typing beet convert.

@DucNg
Copy link
Contributor Author

DucNg commented Mar 14, 2022

It's a good point; it might be nice to document the interaction between the two options. The intent is that they're mutually exclusive; you enable one or the other. Care to expand on that in the docs at all, @DucNg?

Yes that might be a good idea. Even if enabling both is theoretically possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

convert: In auto mode, option to keep originals instead of converted files
3 participants