patch 8.1.0201: newer Python uses "importlib" instead of "imp"

Problem:    Newer Python uses "importlib" instead of "imp".
Solution:   Use "importlib" for newer Python versions. (closes #3163)
diff --git a/src/testdir/test87.in b/src/testdir/test87.in
index ac04109..31de37b 100644
--- a/src/testdir/test87.in
+++ b/src/testdir/test87.in
@@ -219,6 +219,7 @@
 import re
 
 py33_type_error_pattern = re.compile('^__call__\(\) takes (\d+) positional argument but (\d+) were given$')
+py37_exception_repr = re.compile(r'([^\(\),])(\)+)$')
 
 def ee(expr, g=globals(), l=locals()):
     cb = vim.current.buffer
@@ -227,17 +228,17 @@
             exec(expr, g, l)
         except Exception as e:
             if sys.version_info >= (3, 3) and e.__class__ is AttributeError and str(e).find('has no attribute')>=0 and not str(e).startswith("'vim."):
-                cb.append(expr + ':' + repr((e.__class__, AttributeError(str(e)[str(e).rfind(" '") + 2:-1]))))
+                msg = repr((e.__class__, AttributeError(str(e)[str(e).rfind(" '") + 2:-1])))
             elif sys.version_info >= (3, 3) and e.__class__ is ImportError and str(e).find('No module named \'') >= 0:
-                cb.append(expr + ':' + repr((e.__class__, ImportError(str(e).replace("'", '')))))
+                msg = repr((e.__class__, ImportError(str(e).replace("'", ''))))
             elif sys.version_info >= (3, 6) and e.__class__ is ModuleNotFoundError:
                 # Python 3.6 gives ModuleNotFoundError, change it to an ImportError
-                cb.append(expr + ':' + repr((ImportError, ImportError(str(e).replace("'", '')))))
+                msg = repr((ImportError, ImportError(str(e).replace("'", ''))))
             elif sys.version_info >= (3, 3) and e.__class__ is TypeError:
                 m = py33_type_error_pattern.search(str(e))
                 if m:
                     msg = '__call__() takes exactly {0} positional argument ({1} given)'.format(m.group(1), m.group(2))
-                    cb.append(expr + ':' + repr((e.__class__, TypeError(msg))))
+                    msg = repr((e.__class__, TypeError(msg)))
                 else:
                     msg = repr((e.__class__, e))
                     # Messages changed with Python 3.6, change new to old.
@@ -249,9 +250,8 @@
                     oldmsg2 = '''"Can't convert 'int' object to str implicitly"'''
                     if msg.find(newmsg2) > -1:
                         msg = msg.replace(newmsg2, oldmsg2)
-                    cb.append(expr + ':' + msg)
             elif sys.version_info >= (3, 5) and e.__class__ is ValueError and str(e) == 'embedded null byte':
-                cb.append(expr + ':' + repr((TypeError, TypeError('expected bytes with no null'))))
+                msg = repr((TypeError, TypeError('expected bytes with no null')))
             else:
                 msg = repr((e.__class__, e))
                 # Some Python versions say can't, others cannot.
@@ -262,11 +262,16 @@
                     msg = msg.replace('"cannot ', '\'cannot ')
                 if msg.find(' attributes"') > -1:
                     msg = msg.replace(' attributes"', ' attributes\'')
-                cb.append(expr + ':' + msg)
+            if sys.version_info >= (3, 7):
+                msg = py37_exception_repr.sub(r'\1,\2', msg)
+            cb.append(expr + ':' + msg)
         else:
             cb.append(expr + ':NOT FAILED')
     except Exception as e:
-        cb.append(expr + '::' + repr((e.__class__, e)))
+        msg = repr((e.__class__, e))
+        if sys.version_info >= (3, 7):
+            msg = py37_exception_repr.sub(r'\1,\2', msg)
+        cb.append(expr + '::' + msg)
 EOF
 :fun New(...)
 :   return ['NewStart']+a:000+['NewEnd']