From e848adab0490621cbc5c3b3d7f7dcad0b5932ac3 Mon Sep 17 00:00:00 2001 From: tummychow Date: Thu, 7 Dec 2017 14:46:40 -0500 Subject: [PATCH 1/8] Implement from_scratch option Fixes #934, and also helps with #1173. --- beets/config_default.yaml | 1 + beets/importer.py | 4 ++++ beets/library.py | 5 +++++ beets/ui/commands.py | 4 ++++ docs/reference/cli.rst | 6 ++++++ docs/reference/config.rst | 9 +++++++++ test/test_importer.py | 11 +++++++++++ 7 files changed, 40 insertions(+) diff --git a/beets/config_default.yaml b/beets/config_default.yaml index 439a93f55..942459738 100644 --- a/beets/config_default.yaml +++ b/beets/config_default.yaml @@ -10,6 +10,7 @@ import: delete: no resume: ask incremental: no + from_scratch: no quiet_fallback: skip none_rec_action: ask timid: no diff --git a/beets/importer.py b/beets/importer.py index e91b35656..186d824b6 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -534,6 +534,10 @@ class ImportTask(BaseImportTask): def apply_metadata(self): """Copy metadata from match info to the items. """ + if config['import']['from_scratch']: + for item in self.match.mapping: + item.clear() + autotag.apply_metadata(self.match.info, self.match.mapping) def duplicate_items(self, lib): diff --git a/beets/library.py b/beets/library.py index 597cfe625..64035e642 100644 --- a/beets/library.py +++ b/beets/library.py @@ -561,6 +561,11 @@ class Item(LibModel): if self.mtime == 0 and 'mtime' in values: self.mtime = values['mtime'] + def clear(self): + """Set all key/value pairs to None.""" + for key in self._media_fields: + setattr(self, key, None) + def get_album(self): """Get the Album object that this item belongs to, if any, or None if the item is a singleton or is not associated with a diff --git a/beets/ui/commands.py b/beets/ui/commands.py index c8beb11e2..3a1811cf3 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -1004,6 +1004,10 @@ import_cmd.parser.add_option( u'-I', u'--noincremental', dest='incremental', action='store_false', help=u'do not skip already-imported directories' ) +import_cmd.parser.add_option( + u'--from-scratch', dest='from_scratch', action='store_true', + help=u'erase existing metadata before applying new metadata' +) import_cmd.parser.add_option( u'--flat', dest='flat', action='store_true', help=u'import an entire tree as a single album' diff --git a/docs/reference/cli.rst b/docs/reference/cli.rst index 3e668f013..39a4b3f10 100644 --- a/docs/reference/cli.rst +++ b/docs/reference/cli.rst @@ -111,6 +111,12 @@ Optional command flags: time, when no subdirectories will be skipped. So consider enabling the ``incremental`` configuration option. +* When beets applies metadata to your music, it will retain the value of any + existing tags that weren't overwritten, and import them into the database. You + may prefer to only use existing metadata for finding matches, and to erase it + completely when new metadata is applied. You can enforce this behavior with + the ``--from-scratch`` option, or the ``from_scratch`` configuration option. + * By default, beets will proceed without asking if it finds a very close metadata match. To disable this and have the importer ask you every time, use the ``-t`` (for *timid*) option. diff --git a/docs/reference/config.rst b/docs/reference/config.rst index ce45a94ee..a4ed96699 100644 --- a/docs/reference/config.rst +++ b/docs/reference/config.rst @@ -475,6 +475,15 @@ Either ``yes`` or ``no``, controlling whether imported directories are recorded and whether these recorded directories are skipped. This corresponds to the ``-i`` flag to ``beet import``. +.. _from_scratch: + +from_scratch +~~~~~~~~~~~~ + +Either ``yes`` or ``no`` (default), controlling whether existing metadata is +discarded when a match is applied. This corresponds to the ``-from_scratch`` +flag to ``beet import``. + quiet_fallback ~~~~~~~~~~~~~~ diff --git a/test/test_importer.py b/test/test_importer.py index c6b021f33..e30f5609c 100644 --- a/test/test_importer.py +++ b/test/test_importer.py @@ -633,6 +633,17 @@ class ImportTest(_common.TestCase, ImportHelper): self.assert_file_in_lib( b'Applied Artist', b'Applied Album', b'Applied Title 1.mp3') + def test_apply_from_scratch_removes_other_metadata(self): + config['import']['from_scratch'] = True + + for mediafile in self.import_media: + mediafile.genre = u'Tag Genre' + mediafile.save() + + self.importer.add_choice(importer.action.APPLY) + self.importer.run() + self.assertEqual(self.lib.items().get().genre, u'') + def test_apply_with_move_deletes_import(self): config['import']['move'] = True From c9b4e9b414673ec41de93e4bd70a6bfb0569b73c Mon Sep 17 00:00:00 2001 From: Constantine Evans Date: Sun, 10 Dec 2017 12:28:47 -0800 Subject: [PATCH 2/8] only use tiebreak if tiebreak includes an entry for the kind being considered, otherwise use default (eg, if only items is specified, and -a is being used, use default order of priority --- beetsplug/duplicates.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/beetsplug/duplicates.py b/beetsplug/duplicates.py index 2584e6628..6913aaef6 100644 --- a/beetsplug/duplicates.py +++ b/beetsplug/duplicates.py @@ -253,13 +253,12 @@ class DuplicatesPlugin(BeetsPlugin): "completeness" (objects with more non-null fields come first) and Albums are ordered by their track count. """ - if tiebreak: - kind = 'items' if all(isinstance(o, Item) - for o in objs) else 'albums' + kind = 'items' if all(isinstance(o, Item) for o in objs) else 'albums' + + if tiebreak and kind in tiebreak.keys(): key = lambda x: tuple(getattr(x, k) for k in tiebreak[kind]) else: - kind = Item if all(isinstance(o, Item) for o in objs) else Album - if kind is Item: + if kind is 'items': def truthy(v): # Avoid a Unicode warning by avoiding comparison # between a bytes object and the empty Unicode From dd2b44ef20fd089fb0961a77e913ed6c033b387a Mon Sep 17 00:00:00 2001 From: Constantine Evans Date: Mon, 11 Dec 2017 13:31:40 -0800 Subject: [PATCH 3/8] minor fixes and changelog entry --- beetsplug/duplicates.py | 4 ++-- docs/changelog.rst | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/beetsplug/duplicates.py b/beetsplug/duplicates.py index 6913aaef6..b316cfda6 100644 --- a/beetsplug/duplicates.py +++ b/beetsplug/duplicates.py @@ -258,14 +258,14 @@ class DuplicatesPlugin(BeetsPlugin): if tiebreak and kind in tiebreak.keys(): key = lambda x: tuple(getattr(x, k) for k in tiebreak[kind]) else: - if kind is 'items': + if kind == 'items': def truthy(v): # Avoid a Unicode warning by avoiding comparison # between a bytes object and the empty Unicode # string ''. return v is not None and \ (v != '' if isinstance(v, six.text_type) else True) - fields = kind.all_keys() + fields = Item.all_keys() key = lambda x: sum(1 for f in fields if truthy(getattr(x, f))) else: key = lambda x: len(x.items()) diff --git a/docs/changelog.rst b/docs/changelog.rst index edeaf8140..8752ff910 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -70,6 +70,8 @@ Fixes: Python 3 on Windows with non-ASCII filenames. :bug:`2671` * :doc:`/plugins/absubmit`: Fix an occasional crash on Python 3 when the AB analysis tool produced non-ASCII metadata. :bug:`2673` +* :doc:`/plugins/duplicates`: Use default tiebreak for any kind (item/album) that + does not have a tiebreak specified in the configuration. * :doc:`/plugins/duplicates`: Fix the `--key` command line option, which was ignored. * :doc:`/plugins/replaygain`: Fix album replaygain calculation with the From 2ba3c1bec32b81b22c582e968bcb818803873094 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Tue, 12 Dec 2017 11:57:55 -0500 Subject: [PATCH 4/8] Add thanks & issue number for #2758 --- docs/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 8752ff910..e5ecc2f89 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -72,6 +72,8 @@ Fixes: analysis tool produced non-ASCII metadata. :bug:`2673` * :doc:`/plugins/duplicates`: Use default tiebreak for any kind (item/album) that does not have a tiebreak specified in the configuration. + Thanks to :user:`cgevans`. + :bug:`2758` * :doc:`/plugins/duplicates`: Fix the `--key` command line option, which was ignored. * :doc:`/plugins/replaygain`: Fix album replaygain calculation with the From 0fd27e1c543ab23a4c205ba3913117f9c0fccf6e Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Sat, 16 Dec 2017 15:00:50 -0500 Subject: [PATCH 5/8] Fix tiny typo in #2755 --- docs/reference/config.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/config.rst b/docs/reference/config.rst index a4ed96699..4015a4fc2 100644 --- a/docs/reference/config.rst +++ b/docs/reference/config.rst @@ -481,7 +481,7 @@ from_scratch ~~~~~~~~~~~~ Either ``yes`` or ``no`` (default), controlling whether existing metadata is -discarded when a match is applied. This corresponds to the ``-from_scratch`` +discarded when a match is applied. This corresponds to the ``--from_scratch`` flag to ``beet import``. quiet_fallback From 31642cd7cc9327f84d67294ea0563ef3861b464c Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Sat, 16 Dec 2017 15:02:17 -0500 Subject: [PATCH 6/8] Changelog entry for #2755 (fixes #934) --- docs/changelog.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index e5ecc2f89..b220acc14 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -34,6 +34,10 @@ New features: * :doc:`/plugins/acousticbrainz`: The plugin can now be configured to write only a specific list of tags. Thanks to :user:`woparry`. +* A new :ref:`from_scratch` configuration option makes the importer remove old + metadata before applying new metadata. + Thanks to :user:`tummychow`. + :bug:`934` :bug:`2755` Fixes: From a0643dc5409a6e5b68bdcda36f4708fcf4e799e9 Mon Sep 17 00:00:00 2001 From: Michael Yoo Date: Mon, 18 Dec 2017 17:37:52 +1030 Subject: [PATCH 7/8] Remove unnecessary escape caret in ImageMagick convert argument, Fixes #2729 --- beets/util/artresizer.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/beets/util/artresizer.py b/beets/util/artresizer.py index e84b775dc..c32f0f37d 100644 --- a/beets/util/artresizer.py +++ b/beets/util/artresizer.py @@ -88,14 +88,13 @@ def im_resize(maxwidth, path_in, path_out=None): log.debug(u'artresizer: ImageMagick resizing {0} to {1}', util.displayable_path(path_in), util.displayable_path(path_out)) - # "-resize widthxheight>" shrinks images with dimension(s) larger - # than the corresponding width and/or height dimension(s). The > - # "only shrink" flag is prefixed by ^ escape char for Windows - # compatibility. + # "-resize WIDTHx>" shrinks images with the width larger + # than the given width while maintaining the aspect ratio + # with regards to the height. try: util.command_output([ 'convert', util.syspath(path_in, prefix=False), - '-resize', '{0}x^>'.format(maxwidth), + '-resize', '{0}x>'.format(maxwidth), util.syspath(path_out, prefix=False), ]) except subprocess.CalledProcessError: From 9ef0ec2a0642d9250c34cc2247dfd9dd1ef2f62f Mon Sep 17 00:00:00 2001 From: Michael Yoo Date: Tue, 19 Dec 2017 21:48:55 +1030 Subject: [PATCH 8/8] Add changelog for #2762 --- docs/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index b220acc14..5acd27f1f 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -88,6 +88,8 @@ Fixes: "Edit Candidates" option is used. :bug:`2734` * Fix a crash when numeric metadata fields contain just a minus or plus sign with no following numbers. Thanks to :user:`eigengrau`. :bug:`2741` +* Fixed an issue where images would be resized according to their longest edge, + instead of their width. Thanks to :user:`sekjun9878`. :bug:`2729` For developers: