Repository: beetbox/beets
Issue: Beets crashes on Python 3.8

### Problem

Beets crashes when running any command.

```sh
$ beet
Traceback (most recent call last):
  File "C:\\Python38\\Scripts\\beet-script.py", line 11, in <module>
    load_entry_point('beets==1.4.8', 'console_scripts', 'beet')()
  File "C:\\Python38\\lib\\site-packages\\beets-1.4.8-py3.8.egg\\beets\\ui\\__init__.py
", line 1266, in main
    _raw_main(args)
  File "C:\\Python38\\lib\\site-packages\\beets-1.4.8-py3.8.egg\\beets\\ui\\__init__.py
", line 1249, in _raw_main
    subcommands, plugins, lib = _setup(options, lib)
  File "C:\\Python38\\lib\\site-packages\\beets-1.4.8-py3.8.egg\\beets\\ui\\__init__.py
", line 1144, in _setup
    lib = _open_library(config)
  File "C:\\Python38\\lib\\site-packages\\beets-1.4.8-py3.8.egg\\beets\\ui\\__init__.py
", line 1201, in _open_library
    get_path_formats(),
  File "C:\\Python38\\lib\\site-packages\\beets-1.4.8-py3.8.egg\\beets\\ui\\__init__.py
", line 619, in get_path_formats
    path_formats.append((query, Template(view.as_str())))
  File "C:\\Python38\\lib\\site-packages\\beets-1.4.8-py3.8.egg\\beets\\util\\functempl
ate.py", line 558, in __init__
    self.compiled = self.translate()
  File "C:\\Python38\\lib\\site-packages\\beets-1.4.8-py3.8.egg\\beets\\util\\functempl
ate.py", line 591, in translate
    func = compile_func(
  File "C:\\Python38\\lib\\site-packages\\beets-1.4.8-py3.8.egg\\beets\\util\\functempl
ate.py", line 147, in compile_func
    prog = compile(mod, '<generated>', 'exec')
TypeError: required field "type_ignores" missing from Module
```

### Setup

* OS: Windows 10 64-bit
* Python version: Python 3.8a3
* beets version: 1.4.8 (git-master)
* Turning off plugins made problem go away (yes/no): no

My configuration (output of `beet config`) is:

```yaml
empty
```

I've also compiled the wheel from git master obviously, I was having this issue from just installing it from pip normally, so I thought doing this manually would solve my issues, but it didn't. I don't really understand why this error occurs, but I imagine it has something to do with the dependencies of this project.

Changed files:
beetsplug/metasync/itunes.py, beetsplug/lyrics.py, beets/dbcore/db.py, beets/util/confit.py, beetsplug/discogs.py

diff --git a/beets/dbcore/db.py b/beets/dbcore/db.py
index 24c20ef1a..b0c29e84c 100755
--- a/beets/dbcore/db.py
+++ b/beets/dbcore/db.py
@@ -23,7 +23,6 @@ from collections import defaultdict
 import threading
 import sqlite3
 import contextlib
-import collections
 
 import beets
 from beets.util.functemplate import Template
@@ -31,6 +30,10 @@ from beets.util import py3_path
 from beets.dbcore import types
 from .query import MatchQuery, NullSort, TrueQuery
 import six
+if six.PY2:
+    from collections import Mapping
+else:
+    from collections.abc import Mapping
 
 
 class DBAccessError(Exception):
@@ -42,7 +45,7 @@ class DBAccessError(Exception):
     """
 
 
-class FormattedMapping(collections.Mapping):
+class FormattedMapping(Mapping):
     """A `dict`-like formatted view of a model.
 
     The accessor `mapping[key]` returns the formatted version of
diff --git a/beets/util/confit.py b/beets/util/confit.py
index 5f4d862ea..a5e522552 100644
--- a/beets/util/confit.py
+++ b/beets/util/confit.py
@@ -22,9 +22,13 @@ import os
 import pkgutil
 import sys
 import yaml
-import collections
 import re
+import six
 from collections import OrderedDict
+if six.PY2:
+    from collections import Mapping, Sequence
+else:
+    from collections.abc import Mapping, Sequence
 
 UNIX_DIR_VAR = 'XDG_CONFIG_HOME'
 UNIX_DIR_FALLBACK = '~/.config'
@@ -1165,7 +1169,7 @@ class Choice(Template):
                 view
             )
 
-        if isinstance(self.choices, collections.Mapping):
+        if isinstance(self.choices, Mapping):
             return self.choices[value]
         else:
             return value
@@ -1306,11 +1310,11 @@ class Pairs(StrSeq):
             return (super(Pairs, self)._convert_value(x, view),
                     self.default_value)
         except ConfigTypeError:
-            if isinstance(x, collections.Mapping):
+            if isinstance(x, Mapping):
                 if len(x) != 1:
                     self.fail(u'must be a single-element mapping', view, True)
                 k, v = iter_first(x.items())
-            elif isinstance(x, collections.Sequence):
+            elif isinstance(x, Sequence):
                 if len(x) != 2:
                     self.fail(u'must be a two-element list', view, True)
                 k, v = x
@@ -1367,7 +1371,7 @@ class Filename(Template):
         return 'Filename({0})'.format(', '.join(args))
 
     def resolve_relative_to(self, view, template):
-        if not isinstance(template, (collections.Mapping, MappingTemplate)):
+        if not isinstance(template, (Mapping, MappingTemplate)):
             # disallow config.get(Filename(relative_to='foo'))
             raise ConfigTemplateError(
                 u'relative_to may only be used when getting multiple values.'
@@ -1486,7 +1490,7 @@ def as_template(value):
     if isinstance(value, Template):
         # If it's already a Template, pass it through.
         return value
-    elif isinstance(value, collections.Mapping):
+    elif isinstance(value, Mapping):
         # Dictionaries work as templates.
         return MappingTemplate(value)
     elif value is int:
@@ -1507,9 +1511,9 @@ def as_template(value):
     elif value is None:
         return Template()
     elif value is dict:
-        return TypeTemplate(collections.Mapping)
+        return TypeTemplate(Mapping)
     elif value is list:
-        return TypeTemplate(collections.Sequence)
+        return TypeTemplate(Sequence)
     elif isinstance(value, type):
         return TypeTemplate(value)
     else:
diff --git a/beetsplug/discogs.py b/beetsplug/discogs.py
index d7797e409..5a2bf57e0 100644
--- a/beetsplug/discogs.py
+++ b/beetsplug/discogs.py
@@ -284,7 +284,7 @@ class DiscogsPlugin(BeetsPlugin):
         # https://www.discogs.com/help/doc/submission-guidelines-general-rules
         if not all([result.data.get(k) for k in ['artists', 'title', 'id',
                                                  'tracklist']]):
-            self._log.warn(u"Release does not contain the required fields")
+            self._log.warning(u"Release does not contain the required fields")
             return None
 
         artist, artist_id = self.get_artist([a.data for a in result.artists])
diff --git a/beetsplug/lyrics.py b/beetsplug/lyrics.py
index 6ecdbd1d0..9e44eeef6 100644
--- a/beetsplug/lyrics.py
+++ b/beetsplug/lyrics.py
@@ -446,7 +446,7 @@ def _scrape_strip_cruft(html, plain_text_out=False):
     html = html.replace('\\r', '\\n')  # Normalize EOL.
     html = re.sub(r' +', ' ', html)  # Whitespaces collapse.
     html = BREAK_RE.sub('\\n', html)  # <br> eats up surrounding '\\n'.
-    html = re.sub(r'<(script).*?</\\1>(?s)', '', html)  # Strip script tags.
+    html = re.sub(r'(?s)<(script).*?</\\1>', '', html)  # Strip script tags.
 
     if plain_text_out:  # Strip remaining HTML tags
         html = COMMENT_RE.sub('', html)
diff --git a/beetsplug/metasync/itunes.py b/beetsplug/metasync/itunes.py
index 17ab1637f..d594fa591 100644
--- a/beetsplug/metasync/itunes.py
+++ b/beetsplug/metasync/itunes.py
@@ -24,6 +24,7 @@ import shutil
 import tempfile
 import plistlib
 
+import six
 from six.moves.urllib.parse import urlparse, unquote
 from time import mktime
 
@@ -84,7 +85,11 @@ class Itunes(MetaSource):
             self._log.debug(
                 u'loading iTunes library from {0}'.format(library_path))
             with create_temporary_copy(library_path) as library_copy:
-                raw_library = plistlib.readPlist(library_copy)
+                if six.PY2:
+                    raw_library = plistlib.readPlist(library_copy)
+                else:
+                    with open(library_copy, 'rb') as library_copy_f:
+                        raw_library = plistlib.load(library_copy_f)
         except IOError as e:
             raise ConfigValueError(u'invalid iTunes library: ' + e.strerror)
         except Exception: