From f051d6794744ef83944c52bd3b8cc8aadbcf010c Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sat, 18 Mar 2023 18:23:53 -0400 Subject: [PATCH 01/29] Add option to import using URL --- beetsplug/embedart.py | 45 ++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 6db46f8c1..1832eb03d 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -15,14 +15,16 @@ """Allows beets to embed album art into file metadata.""" import os.path +from io import BytesIO +import requests +from PIL import Image + +from beets import art, config, ui from beets.plugins import BeetsPlugin -from beets import ui -from beets.ui import print_, decargs -from beets.util import syspath, normpath, displayable_path, bytestring_path +from beets.ui import decargs, print_ +from beets.util import bytestring_path, displayable_path, normpath, syspath from beets.util.artresizer import ArtResizer -from beets import config -from beets import art def _confirm(objs, album): @@ -78,12 +80,13 @@ class EmbedCoverArtPlugin(BeetsPlugin): embed_cmd = ui.Subcommand( 'embedart', help='embed image files into file metadata' ) - embed_cmd.parser.add_option( - '-f', '--file', metavar='PATH', help='the image file to embed' - ) - embed_cmd.parser.add_option( - "-y", "--yes", action="store_true", help="skip confirmation" - ) + embed_cmd.parser.add_option('-f', '--file', metavar='PATH', + help='the image file to embed') + embed_cmd.parser.add_option("-y", "--yes", action="store_true", + help="skip confirmation") + embed_cmd.parser.add_option('-u', '--url', metavar='URL', + help='the URL of the image file to embed') + maxwidth = self.config['maxwidth'].get(int) quality = self.config['quality'].get(int) compare_threshold = self.config['compare_threshold'].get(int) @@ -107,13 +110,29 @@ class EmbedCoverArtPlugin(BeetsPlugin): art.embed_item(self._log, item, imagepath, maxwidth, None, compare_threshold, ifempty, quality=quality) + elif opts.url: + response = requests.get(opts.url) + img = Image.open(BytesIO(response.content)) + if img.format: + with open('temp.jpg', 'wb') as f: + f.write(response.content) + opts.file = 'temp.jpg' + # Confirm with user. + if not opts.yes and not _confirm(items, not opts.url): + return + for item in items: + art.embed_item(self._log, item, opts.file, maxwidth, + None, compare_threshold, ifempty, + quality=quality) + os.remove(opts.file) + else: + self._log.error('Invalid image file') + return else: albums = lib.albums(decargs(args)) - # Confirm with user. if not opts.yes and not _confirm(albums, not opts.file): return - for album in albums: art.embed_album(self._log, album, maxwidth, False, compare_threshold, ifempty, From feeeb4080c3a6637b16c0e40d61c9f2bd9c55a0e Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sat, 18 Mar 2023 18:58:32 -0400 Subject: [PATCH 02/29] Update embedart.py --- beetsplug/embedart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 1832eb03d..c3142f175 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -84,7 +84,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): help='the image file to embed') embed_cmd.parser.add_option("-y", "--yes", action="store_true", help="skip confirmation") - embed_cmd.parser.add_option('-u', '--url', metavar='URL', + embed_cmd.parser.add_option('-u', '--url', help='the URL of the image file to embed') maxwidth = self.config['maxwidth'].get(int) From 4dd165495ff5cc8f516a571017c7f786e4f717dc Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sat, 18 Mar 2023 19:00:28 -0400 Subject: [PATCH 03/29] Update embedart.py --- beetsplug/embedart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index c3142f175..4bb635950 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -84,7 +84,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): help='the image file to embed') embed_cmd.parser.add_option("-y", "--yes", action="store_true", help="skip confirmation") - embed_cmd.parser.add_option('-u', '--url', + embed_cmd.parser.add_option('-u', '--url', action="store_true", help='the URL of the image file to embed') maxwidth = self.config['maxwidth'].get(int) From 81835b0721e3580a883e4106efc7afe3cf6c45a8 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sat, 18 Mar 2023 19:08:46 -0400 Subject: [PATCH 04/29] Update embedart.py --- beetsplug/embedart.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 4bb635950..a6c858502 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -82,8 +82,10 @@ class EmbedCoverArtPlugin(BeetsPlugin): ) embed_cmd.parser.add_option('-f', '--file', metavar='PATH', help='the image file to embed') + embed_cmd.parser.add_option("-y", "--yes", action="store_true", help="skip confirmation") + embed_cmd.parser.add_option('-u', '--url', action="store_true", help='the URL of the image file to embed') From 64c2ae138d0735af530a325ce773308519556bef Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sat, 18 Mar 2023 19:11:24 -0400 Subject: [PATCH 05/29] Update embedart.py --- beetsplug/embedart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index a6c858502..39d0ca0f4 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -86,7 +86,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): embed_cmd.parser.add_option("-y", "--yes", action="store_true", help="skip confirmation") - embed_cmd.parser.add_option('-u', '--url', action="store_true", + embed_cmd.parser.add_option('-u', '--url', metavar='URL', help='the URL of the image file to embed') maxwidth = self.config['maxwidth'].get(int) From 59d5d23bb3645f151a510e7ae0b8ecb8e2ec2ce9 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sat, 18 Mar 2023 19:12:29 -0400 Subject: [PATCH 06/29] Update embedart.py --- beetsplug/embedart.py | 1 + 1 file changed, 1 insertion(+) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 39d0ca0f4..10f179afc 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -119,6 +119,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): with open('temp.jpg', 'wb') as f: f.write(response.content) opts.file = 'temp.jpg' + items = lib.items(decargs(args)) # Confirm with user. if not opts.yes and not _confirm(items, not opts.url): return From 2d942ce722a0c510f5b99f0ba84b8a433bea76dd Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sun, 19 Mar 2023 09:15:38 -0400 Subject: [PATCH 07/29] Move import inside the function --- beetsplug/embedart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 10f179afc..6f46efb87 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -18,7 +18,6 @@ import os.path from io import BytesIO import requests -from PIL import Image from beets import art, config, ui from beets.plugins import BeetsPlugin @@ -113,6 +112,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): None, compare_threshold, ifempty, quality=quality) elif opts.url: + from PIL import Image response = requests.get(opts.url) img = Image.open(BytesIO(response.content)) if img.format: From 2060e047d2dbfa71e3cc3e42ed8b0bf0af0f3620 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sun, 19 Mar 2023 10:21:32 -0400 Subject: [PATCH 08/29] Update parser options --- beetsplug/embedart.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 6f46efb87..3ac1a1e25 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -76,16 +76,15 @@ class EmbedCoverArtPlugin(BeetsPlugin): def commands(self): # Embed command. - embed_cmd = ui.Subcommand( - 'embedart', help='embed image files into file metadata' - ) + embed_cmd = ui.Subcommand('embedart', + help='embed image files into file metadata') embed_cmd.parser.add_option('-f', '--file', metavar='PATH', help='the image file to embed') embed_cmd.parser.add_option("-y", "--yes", action="store_true", help="skip confirmation") - embed_cmd.parser.add_option('-u', '--url', metavar='URL', + embed_cmd.parser.add_option('-u', '--url', action="store_true", help='the URL of the image file to embed') maxwidth = self.config['maxwidth'].get(int) From 2e2a3bf2239e8b073e5541c752b08779b7014f01 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Mon, 27 Mar 2023 11:56:26 -0400 Subject: [PATCH 09/29] Add additional error handling --- beetsplug/embedart.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 3ac1a1e25..5df9f2e5a 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -112,8 +112,15 @@ class EmbedCoverArtPlugin(BeetsPlugin): quality=quality) elif opts.url: from PIL import Image - response = requests.get(opts.url) - img = Image.open(BytesIO(response.content)) + try: + response = requests.get(opts.url, timeout=5) + response.raise_for_status() + except requests.exceptions.RequestException as e: + self._log.error("Error: {}".format(e)) + try: + img = Image.open(BytesIO(response.content)) + except OSError as e: + self._log.error("Error: {}".format(e)) if img.format: with open('temp.jpg', 'wb') as f: f.write(response.content) From a4b4df8b125af7afd75c54cfd391c1a29275e412 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Mon, 27 Mar 2023 19:28:09 -0400 Subject: [PATCH 10/29] More error handling --- beetsplug/embedart.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 5df9f2e5a..d623c9942 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -122,8 +122,12 @@ class EmbedCoverArtPlugin(BeetsPlugin): except OSError as e: self._log.error("Error: {}".format(e)) if img.format: - with open('temp.jpg', 'wb') as f: - f.write(response.content) + try: + with open('temp.jpg', 'wb') as f: + f.write(response.content) + except Exception as e: + self._log.error(f"Error writing file: {e}" + ) opts.file = 'temp.jpg' items = lib.items(decargs(args)) # Confirm with user. From 6626b7618223adfd69a9fb73f40507a2cd9aa7a2 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Mon, 27 Mar 2023 20:03:31 -0400 Subject: [PATCH 11/29] Update documents and add changelog entry --- docs/changelog.rst | 2 ++ docs/plugins/embedart.rst | 3 +++ 2 files changed, 5 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 9071f8831..fbd28b0f7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -11,6 +11,8 @@ for Python 3.6). New features: +* Added option to specify a URL in the `embedart` plugin. + :bug:`83` * Added additional error handling for `spotify` plugin. :bug:`4686` * We now import the remixer field from Musicbrainz into the library. diff --git a/docs/plugins/embedart.rst b/docs/plugins/embedart.rst index defd3fa4b..ecef58ee6 100644 --- a/docs/plugins/embedart.rst +++ b/docs/plugins/embedart.rst @@ -91,6 +91,9 @@ embedded album art: its own currently associated album art. The command prompts for confirmation before making the change unless you specify the ``-y`` (``--yes``) option. +* ``beet embedart [-u IMAGE_URL] QUERY``: embed image specified in the URL + into every track of the albums matching the query. The ``-u`` (``--url``) option can be used to specify the URL of the image to be used. The command prompts for confirmation before making the change unless you specify the ``-y`` (``--yes``) option. + * ``beet extractart [-a] [-n FILE] QUERY``: extracts the images for all albums matching the query. The images are placed inside the album folder. You can specify the destination file name using the ``-n`` option, but leave off the From 2fcdb8c2ca9e821098d75cecb13c4350c0a6b15e Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Tue, 28 Mar 2023 09:22:51 -0400 Subject: [PATCH 12/29] Add FilesystemError handling --- beetsplug/embedart.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index d623c9942..6a068a16a 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -19,7 +19,7 @@ from io import BytesIO import requests -from beets import art, config, ui +from beets import art, config, ui, util from beets.plugins import BeetsPlugin from beets.ui import decargs, print_ from beets.util import bytestring_path, displayable_path, normpath, syspath @@ -125,9 +125,8 @@ class EmbedCoverArtPlugin(BeetsPlugin): try: with open('temp.jpg', 'wb') as f: f.write(response.content) - except Exception as e: - self._log.error(f"Error writing file: {e}" - ) + except util.FilesystemError as exc: + self._log.error('Error writing file: {}', exc) opts.file = 'temp.jpg' items = lib.items(decargs(args)) # Confirm with user. From 3b39a4fe66c43eecc88596f6a72a058a21c037b5 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Tue, 28 Mar 2023 13:23:26 -0400 Subject: [PATCH 13/29] Raise OSError --- beetsplug/embedart.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 6a068a16a..6387ddc60 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -15,6 +15,7 @@ """Allows beets to embed album art into file metadata.""" import os.path +import traceback from io import BytesIO import requests @@ -84,7 +85,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): embed_cmd.parser.add_option("-y", "--yes", action="store_true", help="skip confirmation") - embed_cmd.parser.add_option('-u', '--url', action="store_true", + embed_cmd.parser.add_option('-u', '--url', metavar='URL', help='the URL of the image file to embed') maxwidth = self.config['maxwidth'].get(int) @@ -125,8 +126,10 @@ class EmbedCoverArtPlugin(BeetsPlugin): try: with open('temp.jpg', 'wb') as f: f.write(response.content) - except util.FilesystemError as exc: - self._log.error('Error writing file: {}', exc) + except OSError as exc: + raise util.FilesystemError(exc, 'write', + bytestring_path('temp.jpg'), + traceback.format_exc()) opts.file = 'temp.jpg' items = lib.items(decargs(args)) # Confirm with user. From 93f4068cca9b7a43d8ee7c5d5590cbde76f8110e Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sat, 8 Apr 2023 21:01:10 -0400 Subject: [PATCH 14/29] Address review comments --- beetsplug/embedart.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 6387ddc60..90d748050 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -118,28 +118,24 @@ class EmbedCoverArtPlugin(BeetsPlugin): response.raise_for_status() except requests.exceptions.RequestException as e: self._log.error("Error: {}".format(e)) + return try: img = Image.open(BytesIO(response.content)) except OSError as e: self._log.error("Error: {}".format(e)) + return if img.format: - try: - with open('temp.jpg', 'wb') as f: - f.write(response.content) - except OSError as exc: - raise util.FilesystemError(exc, 'write', - bytestring_path('temp.jpg'), - traceback.format_exc()) - opts.file = 'temp.jpg' + img.save('temp.jpg', format='JPEG') + tempimg = 'temp.jpg' items = lib.items(decargs(args)) # Confirm with user. if not opts.yes and not _confirm(items, not opts.url): return for item in items: - art.embed_item(self._log, item, opts.file, maxwidth, + art.embed_item(self._log, item, tempimg, maxwidth, None, compare_threshold, ifempty, quality=quality) - os.remove(opts.file) + os.remove(tempimg) else: self._log.error('Invalid image file') return From b3008b74b81632822276bcc6a770d943f0677453 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sat, 8 Apr 2023 21:12:23 -0400 Subject: [PATCH 15/29] Remove unused imports --- beetsplug/embedart.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 90d748050..a355c722b 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -15,12 +15,11 @@ """Allows beets to embed album art into file metadata.""" import os.path -import traceback from io import BytesIO import requests -from beets import art, config, ui, util +from beets import art, config, ui from beets.plugins import BeetsPlugin from beets.ui import decargs, print_ from beets.util import bytestring_path, displayable_path, normpath, syspath From 9c3f4a4ac8252450d53efc686962f6b68fc19d6e Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sat, 8 Apr 2023 22:03:59 -0400 Subject: [PATCH 16/29] Change image format to PNG --- beetsplug/embedart.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index a355c722b..e662f5fa0 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -124,8 +124,8 @@ class EmbedCoverArtPlugin(BeetsPlugin): self._log.error("Error: {}".format(e)) return if img.format: - img.save('temp.jpg', format='JPEG') - tempimg = 'temp.jpg' + img.save('temp.png', format='PNG') + tempimg = 'temp.png' items = lib.items(decargs(args)) # Confirm with user. if not opts.yes and not _confirm(items, not opts.url): From 99ca3e96d494d374c3e90a9383715468786ceeeb Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sun, 9 Apr 2023 09:58:31 -0400 Subject: [PATCH 17/29] Add more error handling for the img.save function --- beetsplug/embedart.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index e662f5fa0..a5fc9e358 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -124,7 +124,11 @@ class EmbedCoverArtPlugin(BeetsPlugin): self._log.error("Error: {}".format(e)) return if img.format: - img.save('temp.png', format='PNG') + try: + img.save('temp.png', format='PNG') + except IOError as e: + self._log.error("Cannot save image: {}".format(e)) + return tempimg = 'temp.png' items = lib.items(decargs(args)) # Confirm with user. From 34a4e7be5fb3618c7594127f42b97392de87d2fd Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sun, 9 Apr 2023 13:58:26 -0400 Subject: [PATCH 18/29] Move away from PIL and use mimetypes instead --- beetsplug/embedart.py | 45 ++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index a5fc9e358..bea43712a 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -15,7 +15,7 @@ """Allows beets to embed album art into file metadata.""" import os.path -from io import BytesIO +from mimetypes import guess_extension import requests @@ -111,37 +111,34 @@ class EmbedCoverArtPlugin(BeetsPlugin): None, compare_threshold, ifempty, quality=quality) elif opts.url: - from PIL import Image try: response = requests.get(opts.url, timeout=5) response.raise_for_status() except requests.exceptions.RequestException as e: self._log.error("Error: {}".format(e)) return - try: - img = Image.open(BytesIO(response.content)) - except OSError as e: - self._log.error("Error: {}".format(e)) - return - if img.format: - try: - img.save('temp.png', format='PNG') - except IOError as e: - self._log.error("Cannot save image: {}".format(e)) - return - tempimg = 'temp.png' - items = lib.items(decargs(args)) - # Confirm with user. - if not opts.yes and not _confirm(items, not opts.url): - return - for item in items: - art.embed_item(self._log, item, tempimg, maxwidth, - None, compare_threshold, ifempty, - quality=quality) - os.remove(tempimg) - else: + extension = guess_extension(response.headers + ['Content-Type']) + if extension is None: self._log.error('Invalid image file') return + tempimg = f'image{extension}' + self._log.error(tempimg) + try: + with open(tempimg, 'wb') as f: + f.write(response.content) + except Exception as e: + self._log.error("Unable to save image: {}".format(e)) + return + items = lib.items(decargs(args)) + # Confirm with user. + if not opts.yes and not _confirm(items, not opts.url): + return + for item in items: + art.embed_item(self._log, item, tempimg, maxwidth, + None, compare_threshold, ifempty, + quality=quality) + os.remove(tempimg) else: albums = lib.albums(decargs(args)) # Confirm with user. From 8357617f0205752a133b04c63a83fa26e6d44455 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sun, 9 Apr 2023 14:02:10 -0400 Subject: [PATCH 19/29] Change indentation --- beetsplug/embedart.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index bea43712a..93fe0bae4 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -136,8 +136,8 @@ class EmbedCoverArtPlugin(BeetsPlugin): return for item in items: art.embed_item(self._log, item, tempimg, maxwidth, - None, compare_threshold, ifempty, - quality=quality) + None, compare_threshold, ifempty, + quality=quality) os.remove(tempimg) else: albums = lib.albums(decargs(args)) From 3a1e4bd8458bf848a22fb18672be37e4952f998b Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Sun, 9 Apr 2023 14:07:55 -0400 Subject: [PATCH 20/29] Remove temporary logging --- beetsplug/embedart.py | 1 - 1 file changed, 1 deletion(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 93fe0bae4..7bab567f1 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -123,7 +123,6 @@ class EmbedCoverArtPlugin(BeetsPlugin): self._log.error('Invalid image file') return tempimg = f'image{extension}' - self._log.error(tempimg) try: with open(tempimg, 'wb') as f: f.write(response.content) From 1e3fee84953ddcc6c942e3d045ecc720d73c7184 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Fri, 14 Apr 2023 08:08:59 -0400 Subject: [PATCH 21/29] Use temp folder instead of cwd --- beetsplug/embedart.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 7bab567f1..a821b33a4 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -15,6 +15,7 @@ """Allows beets to embed album art into file metadata.""" import os.path +import tempfile from mimetypes import guess_extension import requests @@ -122,7 +123,9 @@ class EmbedCoverArtPlugin(BeetsPlugin): if extension is None: self._log.error('Invalid image file') return - tempimg = f'image{extension}' + file = f'image{extension}' + tempimg = os.path.join(tempfile.gettempdir(), file) + print(tempimg) try: with open(tempimg, 'wb') as f: f.write(response.content) @@ -132,6 +135,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): items = lib.items(decargs(args)) # Confirm with user. if not opts.yes and not _confirm(items, not opts.url): + os.remove(tempimg) return for item in items: art.embed_item(self._log, item, tempimg, maxwidth, From 0492f1f2148bc86ced0cd207a7af56ee002fd44c Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Fri, 14 Apr 2023 08:10:13 -0400 Subject: [PATCH 22/29] Address comments --- beetsplug/embedart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index a821b33a4..7c41380d9 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -116,7 +116,7 @@ class EmbedCoverArtPlugin(BeetsPlugin): response = requests.get(opts.url, timeout=5) response.raise_for_status() except requests.exceptions.RequestException as e: - self._log.error("Error: {}".format(e)) + self._log.error("{}".format(e)) return extension = guess_extension(response.headers ['Content-Type']) From bb2ce02e07e45e5a99b5b15a169b272ade968e4e Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Tue, 18 Apr 2023 20:54:43 -0400 Subject: [PATCH 23/29] Remove logging --- beetsplug/embedart.py | 1 - 1 file changed, 1 deletion(-) diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 7c41380d9..48580a844 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -125,7 +125,6 @@ class EmbedCoverArtPlugin(BeetsPlugin): return file = f'image{extension}' tempimg = os.path.join(tempfile.gettempdir(), file) - print(tempimg) try: with open(tempimg, 'wb') as f: f.write(response.content) From 3dd32c93dc9a660e7d72ed6200c319b27d7b8b72 Mon Sep 17 00:00:00 2001 From: J0J0 Todos Date: Fri, 21 Apr 2023 07:59:14 +0200 Subject: [PATCH 24/29] Add test for embedart -u fetching jpeg from url --- test/test_embedart.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test/test_embedart.py b/test/test_embedart.py index 6cf5bfa56..2f2e7459b 100644 --- a/test/test_embedart.py +++ b/test/test_embedart.py @@ -28,6 +28,7 @@ from beets import config, logging, ui from beets.util import syspath, displayable_path from beets.util.artresizer import ArtResizer from beets import art +from test.test_art import FetchImageHelper def require_artresizer_compare(test): @@ -42,7 +43,7 @@ def require_artresizer_compare(test): return wrapper -class EmbedartCliTest(_common.TestCase, TestHelper): +class EmbedartCliTest(TestHelper, FetchImageHelper): small_artpath = os.path.join(_common.RSRC, b'image-2x3.jpg') abbey_artpath = os.path.join(_common.RSRC, b'abbey.jpg') @@ -74,6 +75,19 @@ class EmbedartCliTest(_common.TestCase, TestHelper): mediafile = MediaFile(syspath(item.path)) self.assertEqual(mediafile.images[0].data, self.image_data) + def test_embed_art_from_url_with_yes_input(self): + self._setup_data() + album = self.add_album_fixture() + item = album.items()[0] + self.mock_response('http://example.com/test.jpg', 'image/jpeg') + self.io.addinput('y') + self.run_command('embedart', '-u', 'http://example.com/test.jpg') + mediafile = MediaFile(syspath(item.path)) + self.assertEqual( + mediafile.images[0].data, + self.IMAGEHEADER.get('image/jpeg').ljust(32, b'\x00') + ) + def test_embed_art_from_file_with_no_input(self): self._setup_data() album = self.add_album_fixture() From d48eab9ac1eaf188135b74ee7a37b304b328f7b1 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Fri, 21 Apr 2023 07:58:37 -0400 Subject: [PATCH 25/29] Updated language --- docs/plugins/embedart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plugins/embedart.rst b/docs/plugins/embedart.rst index ecef58ee6..f87fabc71 100644 --- a/docs/plugins/embedart.rst +++ b/docs/plugins/embedart.rst @@ -85,7 +85,7 @@ Manually Embedding and Extracting Art The ``embedart`` plugin provides a couple of commands for manually managing embedded album art: -* ``beet embedart [-f IMAGE] QUERY``: embed images into the every track on the +* ``beet embedart [-f IMAGE] QUERY``: embed images in every track of the albums matching the query. If the ``-f`` (``--file``) option is given, then use a specific image file from the filesystem; otherwise, each album embeds its own currently associated album art. The command prompts for confirmation From 919f326400ee85f361d65eca56aed29fddd6e868 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Fri, 21 Apr 2023 08:23:12 -0400 Subject: [PATCH 26/29] Add test for png image --- test/test_embedart.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/test_embedart.py b/test/test_embedart.py index 2f2e7459b..0b7277068 100644 --- a/test/test_embedart.py +++ b/test/test_embedart.py @@ -88,6 +88,18 @@ class EmbedartCliTest(TestHelper, FetchImageHelper): self.IMAGEHEADER.get('image/jpeg').ljust(32, b'\x00') ) + def test_embed_art_png_from_file_with_yes_input(self): + self._setup_data() + album = self.add_album_fixture() + item = album.items()[0] + self.mock_response('http://example.com/test.png', 'image/png') + self.io.addinput('y') + self.run_command('embedart', '-u', 'http://example.com/test.png') + mediafile = MediaFile(syspath(item.path)) + self.assertEqual( + mediafile.images[0].data, + self.IMAGEHEADER.get('image/png').ljust(32, b'\x00')) + def test_embed_art_from_file_with_no_input(self): self._setup_data() album = self.add_album_fixture() From 47cb11bad71e1325c4ef446e2146a6a60361dbd9 Mon Sep 17 00:00:00 2001 From: Alok Saboo Date: Fri, 21 Apr 2023 08:31:36 -0400 Subject: [PATCH 27/29] Add test for invalid URL --- test/test_embedart.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_embedart.py b/test/test_embedart.py index 0b7277068..222fc36fa 100644 --- a/test/test_embedart.py +++ b/test/test_embedart.py @@ -100,6 +100,17 @@ class EmbedartCliTest(TestHelper, FetchImageHelper): mediafile.images[0].data, self.IMAGEHEADER.get('image/png').ljust(32, b'\x00')) + # test embedart with url that does not have a valid image + def test_embed_art_from_url_with_yes_input_not_image(self): + self._setup_data() + album = self.add_album_fixture() + item = album.items()[0] + self.mock_response('http://example.com/test.txt', 'text/html') + self.io.addinput('y') + self.run_command('embedart', '-u', 'http://example.com/test.txt') + mediafile = MediaFile(syspath(item.path)) + self.assertFalse(mediafile.images) + def test_embed_art_from_file_with_no_input(self): self._setup_data() album = self.add_album_fixture() From f3d4929638b6bb6dbf2788a0ea1df1e57ed9b542 Mon Sep 17 00:00:00 2001 From: J0J0 Todos Date: Fri, 21 Apr 2023 19:51:09 +0200 Subject: [PATCH 28/29] Fix embedart -u test names and shorten second and third test a little by providing -y cli flag. Enough to test with interactive input once. Move all 3 tests to the very bottom of the test class. --- test/test_embedart.py | 70 +++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/test/test_embedart.py b/test/test_embedart.py index 222fc36fa..814340e17 100644 --- a/test/test_embedart.py +++ b/test/test_embedart.py @@ -75,42 +75,6 @@ class EmbedartCliTest(TestHelper, FetchImageHelper): mediafile = MediaFile(syspath(item.path)) self.assertEqual(mediafile.images[0].data, self.image_data) - def test_embed_art_from_url_with_yes_input(self): - self._setup_data() - album = self.add_album_fixture() - item = album.items()[0] - self.mock_response('http://example.com/test.jpg', 'image/jpeg') - self.io.addinput('y') - self.run_command('embedart', '-u', 'http://example.com/test.jpg') - mediafile = MediaFile(syspath(item.path)) - self.assertEqual( - mediafile.images[0].data, - self.IMAGEHEADER.get('image/jpeg').ljust(32, b'\x00') - ) - - def test_embed_art_png_from_file_with_yes_input(self): - self._setup_data() - album = self.add_album_fixture() - item = album.items()[0] - self.mock_response('http://example.com/test.png', 'image/png') - self.io.addinput('y') - self.run_command('embedart', '-u', 'http://example.com/test.png') - mediafile = MediaFile(syspath(item.path)) - self.assertEqual( - mediafile.images[0].data, - self.IMAGEHEADER.get('image/png').ljust(32, b'\x00')) - - # test embedart with url that does not have a valid image - def test_embed_art_from_url_with_yes_input_not_image(self): - self._setup_data() - album = self.add_album_fixture() - item = album.items()[0] - self.mock_response('http://example.com/test.txt', 'text/html') - self.io.addinput('y') - self.run_command('embedart', '-u', 'http://example.com/test.txt') - mediafile = MediaFile(syspath(item.path)) - self.assertFalse(mediafile.images) - def test_embed_art_from_file_with_no_input(self): self._setup_data() album = self.add_album_fixture() @@ -253,6 +217,40 @@ class EmbedartCliTest(TestHelper, FetchImageHelper): mediafile = MediaFile(syspath(item.path)) self.assertEqual(mediafile.images[0].data, self.image_data) + def test_embed_art_from_url_with_yes_input(self): + self._setup_data() + album = self.add_album_fixture() + item = album.items()[0] + self.mock_response('http://example.com/test.jpg', 'image/jpeg') + self.io.addinput('y') + self.run_command('embedart', '-u', 'http://example.com/test.jpg') + mediafile = MediaFile(syspath(item.path)) + self.assertEqual( + mediafile.images[0].data, + self.IMAGEHEADER.get('image/jpeg').ljust(32, b'\x00') + ) + + def test_embed_art_from_url_png(self): + self._setup_data() + album = self.add_album_fixture() + item = album.items()[0] + self.mock_response('http://example.com/test.png', 'image/png') + self.run_command('embedart', '-y', '-u', 'http://example.com/test.png') + mediafile = MediaFile(syspath(item.path)) + self.assertEqual( + mediafile.images[0].data, + self.IMAGEHEADER.get('image/png').ljust(32, b'\x00') + ) + + def test_embed_art_from_url_not_image(self): + self._setup_data() + album = self.add_album_fixture() + item = album.items()[0] + self.mock_response('http://example.com/test.txt', 'text/html') + self.run_command('embedart', '-y', '-u', 'http://example.com/test.txt') + mediafile = MediaFile(syspath(item.path)) + self.assertFalse(mediafile.images) + class DummyArtResizer(ArtResizer): """An `ArtResizer` which pretends that ImageMagick is available, and has From 56adba719b81329424be9d9177badc798f6ec203 Mon Sep 17 00:00:00 2001 From: J0J0 Todos Date: Fri, 21 Apr 2023 21:20:34 +0200 Subject: [PATCH 29/29] Fix text/html file ending in embedart -u test Makes it more clear what we are doing. --- test/test_embedart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_embedart.py b/test/test_embedart.py index 814340e17..1797c790a 100644 --- a/test/test_embedart.py +++ b/test/test_embedart.py @@ -246,7 +246,7 @@ class EmbedartCliTest(TestHelper, FetchImageHelper): self._setup_data() album = self.add_album_fixture() item = album.items()[0] - self.mock_response('http://example.com/test.txt', 'text/html') + self.mock_response('http://example.com/test.html', 'text/html') self.run_command('embedart', '-y', '-u', 'http://example.com/test.txt') mediafile = MediaFile(syspath(item.path)) self.assertFalse(mediafile.images)