Repository: beetbox/beets
Issue: fetchart: Catch PIL file type exception (KeyError) when resizing art

### Problem

(Describe your problem, feature request, or discussion topic here. If you're reporting a bug, please fill out this and the "Setup" section below. Otherwise, you can delete them.)

Running this command in verbose (`-vv`) mode:

```sh
$ beet -vv fetchart -f albumartist:"KMFDM" album:"Amnesia"
user configuration: /home/mycah/.config/beets/config.yaml
data directory: /home/mycah/.config/beets
plugin paths:
Sending event: pluginload
inline: adding item field cdtitle
inline: adding item field multidisc
inline: adding item field initial
inline: adding item field nicelength
inline: adding album field cdtype
inline: adding album field notalbum
library database: /home/mmattox/.beets.db
library directory: /home/mmattox/convertedMusic
Sending event: library_opened
fetchart: trying source filesystem for album KMFDM - Amnesia
fetchart: trying source coverart for album KMFDM - Amnesia
ImageMagick check `convert --version` failed: [Errno 2] No such file or directory: 'convert'
artresizer: method is (1, (0,))
fetchart: downloading image: https://coverartarchive.org/release/b0682581-89f9-430a-8d89-8fc931107a41/front
fetchart: not a supported image: image/x-None
fetchart: downloading image: https://coverartarchive.org/release-group/c9a6bd02-3045-4e9c-a61d-3b41dd2fcf65/front
fetchart: downloaded art to: /tmp/tmp3i69k972.jpg
fetchart: image size: (700, 700)
fetchart: image needs resizing (700 > 600)
fetchart: using remote image /tmp/tmp3i69k972.jpg
artresizer: PIL resizing /tmp/tmp3i69k972.jpg to /tmp/tmpc9k_0qbc.jpg
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/PIL/Image.py", line 1447, in save
    format = EXTENSION[ext]
KeyError: b'.jpg'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/PIL/Image.py", line 1451, in save
    format = EXTENSION[ext]
KeyError: b'.jpg'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/beet", line 9, in <module>
    load_entry_point('beets==1.4.4', 'console_scripts', 'beet')()
  File "/usr/local/lib/python3.4/dist-packages/beets-1.4.4-py3.4.egg/beets/ui/__init__.py", line 1221, in main
    _raw_main(args)
  File "/usr/local/lib/python3.4/dist-packages/beets-1.4.4-py3.4.egg/beets/ui/__init__.py", line 1208, in _raw_main
    subcommand.func(lib, suboptions, subargs)
  File "/usr/local/lib/python3.4/dist-packages/beets-1.4.4-py3.4.egg/beetsplug/fetchart.py", line 829, in func
    self.batch_fetch_art(lib, lib.albums(ui.decargs(args)), opts.force)
  File "/usr/local/lib/python3.4/dist-packages/beets-1.4.4-py3.4.egg/beetsplug/fetchart.py", line 882, in batch_fetch_art
    candidate = self.art_for_album(album, local_paths)
  File "/usr/local/lib/python3.4/dist-packages/beets-1.4.4-py3.4.egg/beetsplug/fetchart.py", line 865, in art_for_album
    out.resize(self)
  File "/usr/local/lib/python3.4/dist-packages/beets-1.4.4-py3.4.egg/beetsplug/fetchart.py", line 143, in resize
    self.path = ArtResizer.shared.resize(plugin.maxwidth, self.path)
  File "/usr/local/lib/python3.4/dist-packages/beets-1.4.4-py3.4.egg/beets/util/artresizer.py", line 184, in resize
    return func(maxwidth, path_in, path_out)
  File "/usr/local/lib/python3.4/dist-packages/beets-1.4.4-py3.4.egg/beets/util/artresizer.py", line 75, in pil_resize
    im.save(path_out)
  File "/usr/lib/python3/dist-packages/PIL/Image.py", line 1453, in save
    raise KeyError(ext) # unknown extension
KeyError: b'.jpg'

```

Led to this problem:

```
in my config:

fetchart:
    auto: yes
    minwidth: 350
    maxwidth: 600

```

Here's a link to the music files that trigger the bug (if relevant): 


### Setup

* OS: ubuntu 14.04
* Python version: python 3.4.3
* beets version: 1.4.4
* Turning off plugins made problem go away (yes/no): plugin issue

My configuration (output of `beet config`) is:

```yaml
$ beet config
library: ~/.beets.db

match:
    preferred:
        countries: [US, GB|UK]
        original_year: yes

replace:
    "\\u2018": ''''
    "\\u2019": ''''
    "\\u201C": '"'
    "\\u201D": '"'
    "\\u2010": '-'
    "\\u2011": '-'
    "\\u2012": '-'
    "\\u2013": '-'
    "\\u2014": '-'
    "\\u2015": '-'
    "\\u2016": '-'
    "\\u2026": '...'
item_fields:
    cdtitle: u' - %s' % (disctitle) if disctitle else u''
    multidisc: 1 if disctotal > 1 else 0
    initial: artist.lower().lstrip('[]*')[0]
    nicelength: 'm, s = divmod(length, 60)

        h, m = divmod(m, 60)

        return "%d:%02d:%02d" % (h, m, s)

        '

import:
    log: ~/beets.log
    write: yes
    copy: yes
album_fields:
    cdtype: u'[%s]' % (albumtype.lower()) if albumtype else u''
    notalbum: 0 if albumtype and albumtype.lower() == 'album' else 1
convert:
    formats:
        alac:
            extension: m4a
            command: avconv -i $source -y -vn -acodec alac $dest
        ogg: avconv -i $source -y -vn -acodec libvorbis -aq 3 $dest
        flac: avconv -i $source -y -vn -acodec flac $dest
        wma: avconv -i $source -y -vn -acodec wmav2 -vn $dest
        mp3: avconv -i $source -y -vn -qscale:a 0 $dest
        aac:
            extension: m4a
            command: avconv -i $source -y -vn -acodec libfaac -aq 100 $dest
        opus: avconv -i $source -y -vn -acodec libopus -ab 96k $dest
    max_bitrate: 500
    embed: yes
    dest:
    copy_album_art: yes
    threads: 4
    never_convert_lossy_files: no
    pretend: no
    format: mp3
    tmpdir:
    quiet: no

    paths: {}
    auto: yes
    album_art_maxwidth: 0
pathfields: {}
per_disc_numbering: yes
web:
    include_paths: no
    cors: ''
    port: 8337
    host: 127.0.0.1

paths:
    default: albums/$albumartist/%if{$year,$year - }$album%aunique{albumdisambig label catalognum}%if{$multidisc, (disc$disc$cdtitle)}%if{$notalbum, $cdtype}/$track - $title
    comp: albums/000 Various Artists/%if{$year,$year - }$album%aunique{albumdisambig label catalognum}%if{$multidisc, (disc$disc$cdtitle)}%if{$notalbum, $cdtype}/$track - $artist - $title
    singleton: singles/$initial/$artist - $title

plugins:
- convert
- duplicates
- fromfilename
- fuzzy
- info
- inline
- lastgenre
- mbsync
- random
- scrub
- the
- fetchart
- embedart
asciify_paths: no
directory: ~/convertedMusic
embedart:
    auto: yes
    maxwidth: 0
    compare_threshold: 0
    ifempty: no
    remove_art_file: no
original_date: yes
fetchart:
    auto: yes
    minwidth: 350
    maxwidth: 600
    store_source: no
    sources:
    - filesystem
    - coverart
    - itunes
    - amazon
    - albumart
    enforce_ratio: no
    google_key: REDACTED
    cover_names:
    - cover
    - front
    - art
    - album
    - folder
    fanarttv_key: REDACTED
    cautious: no
    google_engine: 001442825323518660753:hrh5ch1gjzm
fuzzy:
    threshold: 0.7
    prefix: '~'
lastgenre:
    fallback:
    source: album
    force: yes
    count: 1
    prefer_specific: no
    min_weight: 10
    canonical: no
    auto: yes
    whitelist: yes
    separator: ', '
the:
    a: yes
    format: '{0}, {1}'
    strip: no
    patterns: []
    the: yes
scrub:
    auto: yes
duplicates:
    path: no
    copy: ''
    move: ''
    merge: no
    checksum: ''
    strict: no
    tiebreak: {}
    full: no
    delete: no
    count: no
    album: no
    format: ''
    tag: ''
    keys: []
```


Changed files:
beets/util/artresizer.py

diff --git a/beets/util/artresizer.py b/beets/util/artresizer.py
index e5117a6af..e58b356be 100644
--- a/beets/util/artresizer.py
+++ b/beets/util/artresizer.py
@@ -72,7 +72,7 @@ def pil_resize(maxwidth, path_in, path_out=None):
         im = Image.open(util.syspath(path_in))
         size = maxwidth, maxwidth
         im.thumbnail(size, Image.ANTIALIAS)
-        im.save(path_out)
+        im.save(util.py3_path(path_out))
         return path_out
     except IOError:
         log.error(u"PIL cannot create thumbnail for '{0}'",