Issue #13959: Have
importlib.abc.FileLoader.load_module()/get_filename() and
importlib.machinery.ExtensionFileLoader.load_module() have their
single argument be optional as the loader's constructor has all the
ncessary information.

This allows for the deprecation of
imp.load_source()/load_compile()/load_package().
diff --git a/Lib/imp.py b/Lib/imp.py
index f60f050..edef0be 100644
--- a/Lib/imp.py
+++ b/Lib/imp.py
@@ -24,8 +24,7 @@
 import warnings
 
 
-# XXX "deprecate" once find_module(), load_module(), and get_suffixes() are
-#     deprecated.
+# DEPRECATED
 SEARCH_ERROR = 0
 PY_SOURCE = 1
 PY_COMPILED = 2
@@ -112,8 +111,11 @@
     """Compatibility support for implementing load_source()."""
 
 
-# XXX deprecate after better API exposed in importlib
 def load_source(name, pathname, file=None):
+    msg = ('imp.load_source() is deprecated; use '
+           'importlib.machinery.SourceFileLoader(name, pathname).load_module()'
+           ' instead')
+    warnings.warn(msg, DeprecationWarning, 2)
     return _LoadSourceCompatibility(name, pathname, file).load_module(name)
 
 
@@ -123,15 +125,22 @@
     """Compatibility support for implementing load_compiled()."""
 
 
-# XXX deprecate
 def load_compiled(name, pathname, file=None):
+    msg = ('imp.load_compiled() is deprecated; use '
+           'importlib.machinery.SourcelessFileLoader(name, pathname).'
+           'load_module() instead ')
+    warnings.warn(msg, DeprecationWarning, 2)
     return _LoadCompiledCompatibility(name, pathname, file).load_module(name)
 
 
-# XXX deprecate
 def load_package(name, path):
+    msg = ('imp.load_package() is deprecated; use either '
+           'importlib.machinery.SourceFileLoader() or '
+           'importlib.machinery.SourcelessFileLoader() instead')
+    warnings.warn(msg, DeprecationWarning, 2)
     if os.path.isdir(path):
-        extensions = machinery.SOURCE_SUFFIXES[:] + [machinery.BYTECODE_SUFFIXES]
+        extensions = (machinery.SOURCE_SUFFIXES[:] +
+                      machinery.BYTECODE_SUFFIXES[:])
         for extension in extensions:
             path = os.path.join(path, '__init__'+extension)
             if os.path.exists(path):
@@ -149,26 +158,29 @@
 
     """
     suffix, mode, type_ = details
-    if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
-        raise ValueError('invalid file open mode {!r}'.format(mode))
-    elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
-        msg = 'file object required for import (type code {})'.format(type_)
-        raise ValueError(msg)
-    elif type_ == PY_SOURCE:
-        return load_source(name, filename, file)
-    elif type_ == PY_COMPILED:
-        return load_compiled(name, filename, file)
-    elif type_ == PKG_DIRECTORY:
-        return load_package(name, filename)
-    elif type_ == C_BUILTIN:
-        return init_builtin(name)
-    elif type_ == PY_FROZEN:
-        return init_frozen(name)
-    else:
-        msg =  "Don't know how to import {} (type code {}".format(name, type_)
-        raise ImportError(msg, name=name)
+    with warnings.catch_warnings():
+        warnings.simplefilter('ignore')
+        if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
+            raise ValueError('invalid file open mode {!r}'.format(mode))
+        elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
+            msg = 'file object required for import (type code {})'.format(type_)
+            raise ValueError(msg)
+        elif type_ == PY_SOURCE:
+            return load_source(name, filename, file)
+        elif type_ == PY_COMPILED:
+            return load_compiled(name, filename, file)
+        elif type_ == PKG_DIRECTORY:
+            return load_package(name, filename)
+        elif type_ == C_BUILTIN:
+            return init_builtin(name)
+        elif type_ == PY_FROZEN:
+            return init_frozen(name)
+        else:
+            msg =  "Don't know how to import {} (type code {}".format(name, type_)
+            raise ImportError(msg, name=name)
 
 
+# XXX deprecate
 def find_module(name, path=None):
     """Search for a module.
 
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index ce23043..41b96a9 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -282,8 +282,10 @@
     compared against. If the comparison fails then ImportError is raised.
 
     """
-    def _check_name_wrapper(self, name, *args, **kwargs):
-        if self.name != name:
+    def _check_name_wrapper(self, name=None, *args, **kwargs):
+        if name is None:
+            name = self.name
+        elif self.name != name:
             raise ImportError("loader cannot handle %s" % name, name=name)
         return method(self, name, *args, **kwargs)
     _wrap(_check_name_wrapper, method)
@@ -614,6 +616,11 @@
         self.path = path
 
     @_check_name
+    def load_module(self, fullname):
+        """Load a module from a file."""
+        return super().load_module(fullname)
+
+    @_check_name
     def get_filename(self, fullname):
         """Return the path to the source file as found by the finder."""
         return self.path
@@ -713,17 +720,14 @@
                 del sys.modules[fullname]
             raise
 
-    @_check_name
     def is_package(self, fullname):
         """Return False as an extension module can never be a package."""
         return False
 
-    @_check_name
     def get_code(self, fullname):
         """Return None as an extension module cannot create a code object."""
         return None
 
-    @_check_name
     def get_source(self, fullname):
         """Return None as extension modules have no source code."""
         return None
diff --git a/Lib/importlib/test/extension/test_loader.py b/Lib/importlib/test/extension/test_loader.py
index ab2b686..4f486ce 100644
--- a/Lib/importlib/test/extension/test_loader.py
+++ b/Lib/importlib/test/extension/test_loader.py
@@ -1,4 +1,4 @@
-from importlib import _bootstrap
+from importlib import machinery
 from . import util as ext_util
 from .. import abc
 from .. import util
@@ -11,10 +11,20 @@
 
     """Test load_module() for extension modules."""
 
+    def setUp(self):
+        self.loader = machinery.ExtensionFileLoader(ext_util.NAME,
+                                                     ext_util.FILEPATH)
+
     def load_module(self, fullname):
-        loader = _bootstrap.ExtensionFileLoader(ext_util.NAME,
-                                                ext_util.FILEPATH)
-        return loader.load_module(fullname)
+        return self.loader.load_module(fullname)
+
+    def test_load_module_API(self):
+        # Test the default argument for load_module().
+        self.loader.load_module()
+        self.loader.load_module(None)
+        with self.assertRaises(ImportError):
+            self.load_module('XXX')
+
 
     def test_module(self):
         with util.uncache(ext_util.NAME):
@@ -25,7 +35,7 @@
                 self.assertEqual(getattr(module, attr), value)
             self.assertTrue(ext_util.NAME in sys.modules)
             self.assertTrue(isinstance(module.__loader__,
-                                    _bootstrap.ExtensionFileLoader))
+                                    machinery.ExtensionFileLoader))
 
     def test_package(self):
         # Extensions are not found in packages.
diff --git a/Lib/importlib/test/source/test_file_loader.py b/Lib/importlib/test/source/test_file_loader.py
index c4c7545..ffa0c24 100644
--- a/Lib/importlib/test/source/test_file_loader.py
+++ b/Lib/importlib/test/source/test_file_loader.py
@@ -1,5 +1,6 @@
 from ... import _bootstrap
 import importlib
+import importlib.abc
 from .. import abc
 from .. import util
 from . import util as source_util
@@ -24,6 +25,40 @@
 
     """
 
+    def test_load_module_API(self):
+        # If fullname is not specified that assume self.name is desired.
+        class TesterMixin(importlib.abc.Loader):
+            def load_module(self, fullname): return fullname
+
+        class Tester(importlib.abc.FileLoader, TesterMixin):
+            def get_code(self, _): pass
+            def get_source(self, _): pass
+            def is_package(self, _): pass
+
+        name = 'mod_name'
+        loader = Tester(name, 'some_path')
+        self.assertEqual(name, loader.load_module())
+        self.assertEqual(name, loader.load_module(None))
+        self.assertEqual(name, loader.load_module(name))
+        with self.assertRaises(ImportError):
+            loader.load_module(loader.name + 'XXX')
+
+    def test_get_filename_API(self):
+        # If fullname is not set then assume self.path is desired.
+        class Tester(importlib.abc.FileLoader):
+            def get_code(self, _): pass
+            def get_source(self, _): pass
+            def is_package(self, _): pass
+
+        path = 'some_path'
+        name = 'some_name'
+        loader = Tester(name, path)
+        self.assertEqual(path, loader.get_filename(name))
+        self.assertEqual(path, loader.get_filename())
+        self.assertEqual(path, loader.get_filename(None))
+        with self.assertRaises(ImportError):
+            loader.get_filename(name + 'XXX')
+
     # [basic]
     def test_module(self):
         with source_util.create_modules('_temp') as mapping:
diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py
index 5b285fc..3f419b7 100644
--- a/Lib/test/test_imp.py
+++ b/Lib/test/test_imp.py
@@ -1,11 +1,12 @@
 import imp
+import importlib
 import os
 import os.path
 import shutil
 import sys
-import unittest
 from test import support
-import importlib
+import unittest
+import warnings
 
 class LockTests(unittest.TestCase):
 
@@ -154,18 +155,24 @@
                 mod = imp.load_module(temp_mod_name, file, filename, info)
                 self.assertEqual(mod.a, 1)
 
-            mod = imp.load_source(temp_mod_name, temp_mod_name + '.py')
+            with warnings.catch_warnings():
+                warnings.simplefilter('ignore')
+                mod = imp.load_source(temp_mod_name, temp_mod_name + '.py')
             self.assertEqual(mod.a, 1)
 
-            mod = imp.load_compiled(
-                temp_mod_name, imp.cache_from_source(temp_mod_name + '.py'))
+            with warnings.catch_warnings():
+                warnings.simplefilter('ignore')
+                mod = imp.load_compiled(
+                    temp_mod_name, imp.cache_from_source(temp_mod_name + '.py'))
             self.assertEqual(mod.a, 1)
 
             if not os.path.exists(test_package_name):
                 os.mkdir(test_package_name)
             with open(init_file_name, 'w') as file:
                 file.write('b = 2\n')
-            package = imp.load_package(test_package_name, test_package_name)
+            with warnings.catch_warnings():
+                warnings.simplefilter('ignore')
+                package = imp.load_package(test_package_name, test_package_name)
             self.assertEqual(package.b, 2)
         finally:
             del sys.path[0]
diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py
index bc2672d..cbe6d80 100644
--- a/Lib/test/test_tools.py
+++ b/Lib/test/test_tools.py
@@ -6,7 +6,7 @@
 
 import os
 import sys
-import imp
+import importlib.machinery
 import unittest
 from unittest import mock
 import sysconfig
@@ -80,7 +80,8 @@
     @classmethod
     def setUpClass(self):
         path = os.path.join(scriptsdir, 'pdeps.py')
-        self.pdeps = imp.load_source('pdeps', path)
+        loader = importlib.machinery.SourceFileLoader('pdeps', path)
+        self.pdeps = loader.load_module()
 
     @classmethod
     def tearDownClass(self):
@@ -104,7 +105,8 @@
 
     def setUp(self):
         path = os.path.join(scriptsdir, 'gprof2html.py')
-        self.gprof = imp.load_source('gprof2html', path)
+        loader = importlib.machinery.SourceFileLoader('gprof2html', path)
+        self.gprof = loader.load_module()
         oldargv = sys.argv
         def fixup():
             sys.argv = oldargv