From 1f356d66a694ba5fe68d7b38ab59fc16e6233d5a Mon Sep 17 00:00:00 2001 From: David Logie Date: Fri, 25 Jan 2019 14:06:30 +0000 Subject: [PATCH 01/10] First attempt at fixing #3132. Add a new `no_clobber` config option that contains a list of "miscellaneous" metadata fields not to be overwritten by empty values. I'm not entirely happy with the `no_clobber` name. Suggestions welcome. --- beets/autotag/__init__.py | 9 +++++++-- beets/config_default.yaml | 13 +++++++++++++ docs/changelog.rst | 3 +++ docs/reference/config.rst | 25 +++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index 90d294c61..6783929cd 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -154,9 +154,14 @@ def apply_metadata(album_info, mapping): 'albumdisambig', 'releasegroupdisambig', 'data_source',): + # Don't overwrite fields with empty values unless the + # field is explicitly allowed to be overwritten + clobber = field not in config['no_clobber'].get() value = getattr(album_info, field) - if value is not None: - item[field] = value + if value is None and not clobber: + continue + item[field] = value + if track_info.disctitle is not None: item.disctitle = track_info.disctitle diff --git a/beets/config_default.yaml b/beets/config_default.yaml index 26babde55..0e6e01efa 100644 --- a/beets/config_default.yaml +++ b/beets/config_default.yaml @@ -30,6 +30,19 @@ import: bell: no set_fields: {} +no_clobber: + - albumtype + - label + - asin + - catalognum + - script + - language + - country + - albumstatus + - albumdisambig + - releasegroupdisambig + - data_source + clutter: ["Thumbs.DB", ".DS_Store"] ignore: [".*", "*~", "System Volume Information", "lost+found"] ignore_hidden: yes diff --git a/docs/changelog.rst b/docs/changelog.rst index b896604c2..746a3f5be 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -63,6 +63,9 @@ New features: provider: you can match tracks and albums using the Spotify database. Thanks to :user:`rhlahuja`. :bug:`3123` +* A new ``no_clobber`` configuration option allows setting a list of + fields not to be overwritten by empty values upon re-importing items. + :bug:`3132` Changes: diff --git a/docs/reference/config.rst b/docs/reference/config.rst index 57cb6c295..44f7dd576 100644 --- a/docs/reference/config.rst +++ b/docs/reference/config.rst @@ -303,6 +303,31 @@ The defaults look like this:: See :ref:`aunique` for more details. + +.. _no_clobber: + +no_clobber +~~~~~~~~~~ + +A list of fields that should not be overwritten by empty values when +re-importing items. + +The default is:: + + no_clobber: + - albumtype + - label + - asin + - catalognum + - script + - language + - country + - albumstatus + - albumdisambig + - releasegroupdisambig + - data_source + + .. _terminal_encoding: terminal_encoding From 2ef74999ea5e8e1a8aa1d6a0eefc699ded31e606 Mon Sep 17 00:00:00 2001 From: David Logie Date: Fri, 25 Jan 2019 17:11:15 +0000 Subject: [PATCH 02/10] Use .as_str_seq() instead of .get(). --- beets/autotag/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index 6783929cd..f0c73d3c0 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -156,7 +156,7 @@ def apply_metadata(album_info, mapping): 'data_source',): # Don't overwrite fields with empty values unless the # field is explicitly allowed to be overwritten - clobber = field not in config['no_clobber'].get() + clobber = field not in config['no_clobber'].as_str_seq() value = getattr(album_info, field) if value is None and not clobber: continue From 604616050b845d5b0bb858f634e3c19ab295e18d Mon Sep 17 00:00:00 2001 From: David Logie Date: Sat, 26 Jan 2019 11:17:17 +0000 Subject: [PATCH 03/10] Address PR comments. - Rename config option to overwrite_null - Leave overwrite_null empty by default - Handle more potentially null fields for both album and tracks - Remove documentation and changelog entries for now --- beets/autotag/__init__.py | 68 ++++++++++++++++++++++----------------- beets/config_default.yaml | 16 ++------- docs/changelog.rst | 3 -- docs/reference/config.rst | 24 -------------- 4 files changed, 41 insertions(+), 70 deletions(-) diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index f0c73d3c0..bf347b1e0 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -142,39 +142,47 @@ def apply_metadata(album_info, mapping): # Compilation flag. item.comp = album_info.va - # Miscellaneous metadata. - for field in ('albumtype', - 'label', - 'asin', - 'catalognum', - 'script', - 'language', - 'country', - 'albumstatus', - 'albumdisambig', - 'releasegroupdisambig', - 'data_source',): - # Don't overwrite fields with empty values unless the - # field is explicitly allowed to be overwritten - clobber = field not in config['no_clobber'].as_str_seq() + # Track alt. + item.track_alt = track_info.track_alt + + # Miscellaneous/nullable metadata. + misc_fields = { + 'album': ( + 'albumtype', + 'label', + 'asin', + 'catalognum', + 'script', + 'language', + 'country', + 'albumstatus', + 'albumdisambig', + 'releasegroupdisambig', + 'data_source', + ), + 'track': ( + 'disctitle', + 'lyricist', + 'media', + 'composer', + 'composer_sort', + 'arranger', + ) + } + + # Don't overwrite fields with empty values unless the + # field is explicitly allowed to be overwritten + for field in misc_fields['album']: + clobber = field in config['overwrite_null']['album'].as_str_seq() value = getattr(album_info, field) if value is None and not clobber: continue item[field] = value - if track_info.disctitle is not None: - item.disctitle = track_info.disctitle + for field in misc_fields['track']: + clobber = field in config['overwrite_null']['track'].as_str_seq() + value = getattr(track_info, field) + if value is None and not clobber: + continue + item[field] = value - if track_info.media is not None: - item.media = track_info.media - - if track_info.lyricist is not None: - item.lyricist = track_info.lyricist - if track_info.composer is not None: - item.composer = track_info.composer - if track_info.composer_sort is not None: - item.composer_sort = track_info.composer_sort - if track_info.arranger is not None: - item.arranger = track_info.arranger - - item.track_alt = track_info.track_alt diff --git a/beets/config_default.yaml b/beets/config_default.yaml index 0e6e01efa..cf9ae6bf9 100644 --- a/beets/config_default.yaml +++ b/beets/config_default.yaml @@ -30,19 +30,6 @@ import: bell: no set_fields: {} -no_clobber: - - albumtype - - label - - asin - - catalognum - - script - - language - - country - - albumstatus - - albumdisambig - - releasegroupdisambig - - data_source - clutter: ["Thumbs.DB", ".DS_Store"] ignore: [".*", "*~", "System Volume Information", "lost+found"] ignore_hidden: yes @@ -66,6 +53,9 @@ aunique: disambiguators: albumtype year label catalognum albumdisambig releasegroupdisambig bracket: '[]' +overwrite_null: + album: [] + track: [] plugins: [] pluginpath: [] diff --git a/docs/changelog.rst b/docs/changelog.rst index 746a3f5be..b896604c2 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -63,9 +63,6 @@ New features: provider: you can match tracks and albums using the Spotify database. Thanks to :user:`rhlahuja`. :bug:`3123` -* A new ``no_clobber`` configuration option allows setting a list of - fields not to be overwritten by empty values upon re-importing items. - :bug:`3132` Changes: diff --git a/docs/reference/config.rst b/docs/reference/config.rst index 44f7dd576..684dea20c 100644 --- a/docs/reference/config.rst +++ b/docs/reference/config.rst @@ -304,30 +304,6 @@ The defaults look like this:: See :ref:`aunique` for more details. -.. _no_clobber: - -no_clobber -~~~~~~~~~~ - -A list of fields that should not be overwritten by empty values when -re-importing items. - -The default is:: - - no_clobber: - - albumtype - - label - - asin - - catalognum - - script - - language - - country - - albumstatus - - albumdisambig - - releasegroupdisambig - - data_source - - .. _terminal_encoding: terminal_encoding From 19db67c6425c5931c28919205b76e4c4628254b3 Mon Sep 17 00:00:00 2001 From: David Logie Date: Sat, 26 Jan 2019 18:35:37 +0000 Subject: [PATCH 04/10] Remove extra trailing blank line. --- beets/autotag/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index bf347b1e0..a71b9b0a6 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -185,4 +185,3 @@ def apply_metadata(album_info, mapping): if value is None and not clobber: continue item[field] = value - From 2b82831b7b081128c788423e9ce1382db4b66c37 Mon Sep 17 00:00:00 2001 From: Iris Wildthyme <46726098+wildthyme@users.noreply.github.com> Date: Wed, 30 Jan 2019 16:36:46 -0500 Subject: [PATCH 05/10] added --nocopy support --- beetsplug/ipfs.py | 11 +++++++++-- docs/plugins/ipfs.rst | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/beetsplug/ipfs.py b/beetsplug/ipfs.py index 9a9d6aa50..90ba5fdd0 100644 --- a/beetsplug/ipfs.py +++ b/beetsplug/ipfs.py @@ -32,6 +32,7 @@ class IPFSPlugin(BeetsPlugin): super(IPFSPlugin, self).__init__() self.config.add({ 'auto': True, + 'nocopy': False, }) if self.config['auto']: @@ -116,7 +117,10 @@ class IPFSPlugin(BeetsPlugin): self._log.info('Adding {0} to ipfs', album_dir) - cmd = "ipfs add -q -r".split() + if self.config['nocopy']: + cmd = "ipfs add --nocopy -q -r".split() + else: + cmd = "ipfs add -q -r".split() cmd.append(album_dir) try: output = util.command_output(cmd).split() @@ -174,7 +178,10 @@ class IPFSPlugin(BeetsPlugin): with tempfile.NamedTemporaryFile() as tmp: self.ipfs_added_albums(lib, tmp.name) try: - cmd = "ipfs add -q ".split() + if self.config['nocopy']: + cmd = "ipfs add --nocopy -q ".split() + else: + cmd = "ipfs add -q ".split() cmd.append(tmp.name) output = util.command_output(cmd) except (OSError, subprocess.CalledProcessError) as err: diff --git a/docs/plugins/ipfs.rst b/docs/plugins/ipfs.rst index a9b5538df..141143ae7 100644 --- a/docs/plugins/ipfs.rst +++ b/docs/plugins/ipfs.rst @@ -70,3 +70,5 @@ Configuration The ipfs plugin will automatically add imported albums to ipfs and add those hashes to the database. This can be turned off by setting the ``auto`` option in the ``ipfs:`` section of the config to ``no``. + +If the setting ``nocopy`` is true (defaults false) then the plugin will pass the ``--nocopy`` option when adding things to ipfs. If the filestore option of ipfs is enabled this will mean files are neither removed from beets nor copied somewhere else. From 367bb3026fa7b558bde29d59179afe7345f7c758 Mon Sep 17 00:00:00 2001 From: Iris Wildthyme <46726098+wildthyme@users.noreply.github.com> Date: Wed, 30 Jan 2019 17:13:12 -0500 Subject: [PATCH 06/10] added to changelog --- docs/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index b896604c2..242279583 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -63,6 +63,8 @@ New features: provider: you can match tracks and albums using the Spotify database. Thanks to :user:`rhlahuja`. :bug:`3123` +* :doc:`/plugins/ipfs`: The plugin now supports a ``nocopy`` option which passes that flag to ipfs. + THanks to :user:`wildthyme`. Changes: From 768770d56158224ee5073dbe26f84b227ad714ea Mon Sep 17 00:00:00 2001 From: Jack Wilsdon Date: Thu, 31 Jan 2019 00:15:42 +0000 Subject: [PATCH 07/10] Fix incorrect indentation --- beets/art.py | 4 ++-- beetsplug/discogs.py | 2 +- beetsplug/filefilter.py | 4 ++-- beetsplug/hook.py | 36 ++++++++++++++++++------------------ beetsplug/replaygain.py | 8 ++++---- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/beets/art.py b/beets/art.py index 979a6f722..84c3a02d5 100644 --- a/beets/art.py +++ b/beets/art.py @@ -60,8 +60,8 @@ def embed_item(log, item, imagepath, maxwidth=None, itempath=None, log.info(u'Image not similar; skipping.') return if ifempty and get_art(log, item): - log.info(u'media file already contained art') - return + log.info(u'media file already contained art') + return if maxwidth and not as_album: imagepath = resize_image(log, imagepath, maxwidth) diff --git a/beetsplug/discogs.py b/beetsplug/discogs.py index eeb87d311..5b11b9617 100644 --- a/beetsplug/discogs.py +++ b/beetsplug/discogs.py @@ -286,7 +286,7 @@ class DiscogsPlugin(BeetsPlugin): if va: artist = config['va_name'].as_str() if catalogno == 'none': - catalogno = None + catalogno = None # Explicitly set the `media` for the tracks, since it is expected by # `autotag.apply_metadata`, and set `medium_total`. for track in tracks: diff --git a/beetsplug/filefilter.py b/beetsplug/filefilter.py index 23dac5746..ea521d5f6 100644 --- a/beetsplug/filefilter.py +++ b/beetsplug/filefilter.py @@ -43,8 +43,8 @@ class FileFilterPlugin(BeetsPlugin): bytestring_path(self.config['album_path'].get())) if 'singleton_path' in self.config: - self.path_singleton_regex = re.compile( - bytestring_path(self.config['singleton_path'].get())) + self.path_singleton_regex = re.compile( + bytestring_path(self.config['singleton_path'].get())) def import_task_created_event(self, session, task): if task.items and len(task.items) > 0: diff --git a/beetsplug/hook.py b/beetsplug/hook.py index b6270fd50..de44c1b81 100644 --- a/beetsplug/hook.py +++ b/beetsplug/hook.py @@ -91,28 +91,28 @@ class HookPlugin(BeetsPlugin): def create_and_register_hook(self, event, command): def hook_function(**kwargs): - if command is None or len(command) == 0: - self._log.error('invalid command "{0}"', command) - return + if command is None or len(command) == 0: + self._log.error('invalid command "{0}"', command) + return - # Use a string formatter that works on Unicode strings. - if six.PY2: - formatter = CodingFormatter(arg_encoding()) - else: - formatter = string.Formatter() + # Use a string formatter that works on Unicode strings. + if six.PY2: + formatter = CodingFormatter(arg_encoding()) + else: + formatter = string.Formatter() - command_pieces = shlex_split(command) + command_pieces = shlex_split(command) - for i, piece in enumerate(command_pieces): - command_pieces[i] = formatter.format(piece, event=event, - **kwargs) + for i, piece in enumerate(command_pieces): + command_pieces[i] = formatter.format(piece, event=event, + **kwargs) - self._log.debug(u'running command "{0}" for event {1}', - u' '.join(command_pieces), event) + self._log.debug(u'running command "{0}" for event {1}', + u' '.join(command_pieces), event) - try: - subprocess.Popen(command_pieces).wait() - except OSError as exc: - self._log.error(u'hook for {0} failed: {1}', event, exc) + try: + subprocess.Popen(command_pieces).wait() + except OSError as exc: + self._log.error(u'hook for {0} failed: {1}', event, exc) self.register_listener(event, hook_function) diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py index ac45aa4f8..4168c61b9 100644 --- a/beetsplug/replaygain.py +++ b/beetsplug/replaygain.py @@ -935,10 +935,10 @@ class ReplayGainPlugin(BeetsPlugin): if (any([self.should_use_r128(item) for item in album.items()]) and not all(([self.should_use_r128(item) for item in album.items()]))): - raise ReplayGainError( - u"Mix of ReplayGain and EBU R128 detected" - u" for some tracks in album {0}".format(album) - ) + raise ReplayGainError( + u"Mix of ReplayGain and EBU R128 detected" + u" for some tracks in album {0}".format(album) + ) if any([self.should_use_r128(item) for item in album.items()]): if self.r128_backend_instance == '': From 2bc04bb60570f3c5a7b4e327787d2441250e5a36 Mon Sep 17 00:00:00 2001 From: Jack Wilsdon Date: Thu, 31 Jan 2019 00:15:55 +0000 Subject: [PATCH 08/10] Use "==" when comparing strings --- beetsplug/subsonicupdate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beetsplug/subsonicupdate.py b/beetsplug/subsonicupdate.py index 93c47e2de..bb9e8a952 100644 --- a/beetsplug/subsonicupdate.py +++ b/beetsplug/subsonicupdate.py @@ -78,7 +78,7 @@ class SubsonicUpdate(BeetsPlugin): 'v': '1.15.0', # Subsonic 6.1 and newer. 'c': 'beets' } - if contextpath is '/': + if contextpath == '/': contextpath = '' url = "http://{}:{}{}/rest/startScan".format(host, port, contextpath) response = requests.post(url, params=payload) From 2564db905581bb14403bf6259278e05631536ace Mon Sep 17 00:00:00 2001 From: Jack Wilsdon Date: Thu, 31 Jan 2019 00:16:11 +0000 Subject: [PATCH 09/10] Lock pep8-naming to 0.7.x --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 154cd7655..eeacf2af5 100644 --- a/tox.ini +++ b/tox.ini @@ -31,7 +31,7 @@ deps = flake8-coding flake8-future-import flake8-blind-except - pep8-naming + pep8-naming~=0.7.0 files = beets beetsplug beet test setup.py docs [testenv] From c20c3a439858b7584104835abd250887e36a222e Mon Sep 17 00:00:00 2001 From: Iris Wildthyme <46726098+wildthyme@users.noreply.github.com> Date: Fri, 1 Feb 2019 09:36:51 -0500 Subject: [PATCH 10/10] fixed typo --- docs/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 242279583..9cab4a1e0 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -64,7 +64,7 @@ New features: Thanks to :user:`rhlahuja`. :bug:`3123` * :doc:`/plugins/ipfs`: The plugin now supports a ``nocopy`` option which passes that flag to ipfs. - THanks to :user:`wildthyme`. + Thanks to :user:`wildthyme`. Changes: