This rolls back the places in #2094 where `six.text_type(s)` was used where
`s` might be a bytestring. We almost never want that conversion, because it
uses the default encoding (almost always ASCII). The need for it indicates a
problem somewhere else, where bytes were produced when we were expecting
unicode strings.
If `medium_index` is missing, as it is from the Beatport source, the display
would show "None" instead of the global index (a fallback). This is half of
the problem in #2085.
* Fix docstring and `plugins.rst` regarding how the PromptChoices that
use the same short letter are handled (they are discarded instead of
raising an Exception).
* Rename the importer argument and related variables to make it more
generic, as the feature should be independent of the backend used and
not restricted to MusicBrainz.
* Update documentation and docstrings accordingly.
* Add changelog entry.
* Style cleanup and fixes for the "--musicbrainzid" import argument.
* Allow the input of several IDs (separated by spaces) on the "enter Id"
importer prompt.
* Add basic documentation.
* Modify the "--musicbrainzid" argument to the importer so multiple IDs can be
specified by the user instead of a single one.
* Revise autotag.match.tag_album and autotag.match.tag_item signature to expect
a list of IDs (search_ids) instead of a single one (search_id), and add logic
for handling and returning multiple matches for those IDs.
* Update calls to those functions in other parts of the code.
* Add '-m', '--musicbrainzid' option to the import command, allowing the user
to specify a single MusicBrainz ID to be used for the candidate lookup instead
of trying to find suitable candidates.
* Modify lookup_candidates() of ImportTask and SingletonImportTask to use the
musicbrainz id if present.
* Simplify PromptChoice so "plugin" and "id" fields are removed, updating the
loops and the rest of the code to reflect this change.
* Solve short letter conflicts by keeping one of the choices and removing the
rest, instead of by raising an Exception.
* Misc cleanups as suggested on #1758 discussion.
* Rename "ExtraChoice" to "PromptChoice", and add an attribute for the short
letter used by the choice (short).
* Add TerminalImportSession._get_plugin_options() for isolating the sending
of the event and the processing of the returned values (flattening, check for
letter conflicts).
* Remove unnecessary TODO lines and other style cleanups.
* Add "before_choose_candidate" event, sent to the plugins during
TerminalImportSession.choose_match(). This event allows plugins to append
additional choice to the user prompt during importer.
* The event is sent on the main loop of choose_match(), with session and task
parameters. The plugins are responsible for checking the task status in order
to append choices in a sensible way.
* Add "ExtraChoice" namedtuple to improve readability and encapsulate the
concept of a single extra choice.
The idea is that it is so common to check whether we need to write tags (or
move files), and we're constantly re-implementing the same logic everywhere.
It's not even the prettiest logic, as it commingles the importer settings with
general settings. So it's important that we encapsulate the decision so we can
make it better in the future.
This should fix#1652, which found that this code did the wrong thing when
there were *no* `found_duplicates`: that is, when the duplicate actually came
from the `seen_keys` list, so the album is not in the database yet. This
handling was confusing "no non-empty duplicates" with "no in-database
duplicates", and incorrectly bypassing the duplicates prompt.
Since having empty albums in the database is a rare case (it should be
impossible!), and we should no longer *crash* when it happens, I am
considering it unnecessary to handle it specially. The user will now just see
"Old: 0 items" and that's that.
interactive_open should now be invoked with at least the list of
targets and optionally the command to open the targets with.
This allows beets-play to pass multiple file paths directly to
the configured command.
The changes to the existing invocations are pretty trivial in
order to comply to this refactor.
Rather than the ad-hoc one on library classes. This also avoids some confusing
duplication in the `beet fields` output, at the cost of turning off the plugin
distinction.
Running `beet config -e` with a non-existing configuration file
does not always work (e.g., OSX uses `open` by default, which requires
the file to exist). This could occur during e.g. initial setup.
Resolve#1480
This is most pertinently important for interacting with nose's
output-capturing, which crashes when we mix bytes and unicode output. It's
also nice to have just for consistency.
Maybe we should enforce in the future that `print_` only gets Unicode
arguments. It's a pain supporting bytes calls and we should really only be
outputting text.
Python 3 can't come soon enough. 😢
- `config -r` will show 'REDACTED' instead of the actual value
- Has a default list of field names that should be redacted (e.g., 'password')
- Plugins can add redacted fields that they introduce
Add a new OptionParser subclass: CommonOptionsOptionParser, which
provides facilities for adding --album, --path and --format options. The
last one is quite versatile.
Update base commands (from beets.ui.commands) to use those.
interactive_open() takes a target and an optional command, if it does not
receive a command then it uses open_anything().
It parses command and lexes it with shlex.split(), revieling the client
from that task.
"config -e" command uses it, and gives a better error message in case of
problem. "play" plugin uses it as well, as side-effect being that the
command is now interactive, as requested in issue #1321.
Fix issue #1321.
E.g., `colorize('text_success', 'hello world')`
To ensure compatibility with 3rd party plugins, a valid color ('red') can still be passed,
but it will be logged.
- Colors are mapped on to a dictionary using abstract names (e.g., text_success)
- Add `colors` option under `ui` to allow users to choose their own color scheme
- Move configuration option `color` from top-level to `ui`
- Show deprecation warning if top-level `color` configuration is used (but respect it)
Fix#1238
Code now relies on `format()` for items and albums displaying/logging.
`ui.print_()` calls `unicode()` or `str()` on the strings so for most
usages calling `ui.print_(obj)` replaces `ui.print_(obj, lib, None)`.
Where there is a special format `ui.print_(format(obj, fmt))` is fine,
but when `fmt` can be None then one has to call
`ui.print_(ui.format_(obj, fmt))` -- which is what `ui.print_obj` now
does.
Include import of __future__ features division, absolute_imports and
print_function everywhere. Don't add unicode_literals yet for it is
harder to convert.
Goal is smoothing the transition to python 3.
This was well-intentioned but ended up being more confusing than it was worth.
It's always confused me when one digit gets un-highlighted in one of these
displays. The straw that broke the camel's back was when I got a "#1 -> #16"
change where the numeral "1" was un-highlighted. To fix this right would be
way more trouble than it's worth; I'm glad to be rid of this detail.
Conflicts:
docs/changelog.rst
This makes sure we store the updated file `mtime`. By providing the
same interface on `Album` and `item` we can also reduce some code
duplication in the `modify` command.
Items might have the `album` field set without belonging to an album in
the beets database. We only count the albums that are represented in
the database.
Forces a write of tags to file even if the file's tags match the database.
This is useful to force plugins that respond to write (e.g., Scrub and Zero) to run on those tags.
This may also make the TODO comment in zero.py less important since creates a way to manually run the zero plugin on a file imported as-is.
Added a one-line summary of each album (in lib, and import target) so
you can easily tell if (for example) you are about to overwrite your
FLAC copy with a low-bitrate mp3 from somewhere else.
* Control flow and implementation of help command is now
similar to the other commands.
* Simplifies and flattens some code and removes unused method.
* Makes SubcommandOptionParser agnostic of Subcommand.parser.
This groups together all of the optparse setup calls separately from the
functions. This comes at the expense of showing the command-line options above
the code that interprets them.
Making me wish for a more declarative CLI setup style...
Many commands and plugins use `item.write()` to update tags. Since the success
of the call is not critical to the functionality of most consumers we want to
catch any exceptions, log an error and continue with our task. The new method
encapsulates this logic.
This fixes#675.
This puts the OrderedEnum generic class next to where it is actually used. It
also refers to the recipe it is taken from on docs.python.org. I also took the
opportunity to give this a capitalized name (since it's a proper type).
Following the convention of the other field sets and such. This helps avoid
any confusion with user-specified fields (although it's unlikely people will
want to name a flexible field "media_fields" :).
This makes the errors fully self-descriptive, which simplifies logging them as
errors (you just have to `log.error(exc)` to get a reasonable message). We
also now handle these at the top level in case someone forgets to add a
handler. But in this case, we also send the full traceback to the debug log.