text: """runpy.py - locating and running Python code using the module namespace
  
  Provides support for locating and running Python scripts using the Python
  module namespace instead of the native filesystem.
  
  This allows Python code to play nicely with non-filesystem based PEP 302
  importers when locating support scripts as well as when importing modules.
  """
  # Written by Nick Coghlan <ncoghlan at gmail.com>
  #    to implement PEP 338 (Executing Modules as Scripts)
  
  
  import os
  import sys
  import importlib.machinery # importlib first so we can test #15386 via -m
  import importlib.util
  import types
  from pkgutil import read_code, get_importer
  
  __all__ = [
      "run_module", "run_path",
  ]
  
  class _TempModule(object):
      """Temporarily replace a module in sys.modules with an empty namespace"""
      def __init__(self, mod_name):
          self.mod_name = mod_name
          self.module = types.ModuleType(mod_name)
          self._saved_module = []
  
      def __enter__(self):
          mod_name = self.mod_name
          try:
              self._saved_module.append(sys.modules[mod_name])
          except KeyError:
              pass
          sys.modules[mod_name] = self.module
          return self
  
      def __exit__(self, *args):
          if self._saved_module:
              sys.modules[self.mod_name] = self._saved_module[0]
          else:
              del sys.modules[self.mod_name]
          self._saved_module = []
  
  class _ModifiedArgv0(object):
      def __init__(self, value):
          self.value = value
          self._saved_value = self._sentinel = object()
  
      def __enter__(self):
          if self._saved_value is not self._sentinel:
              raise RuntimeError("Already preserving saved value")
          self._saved_value = sys.argv[0]
          sys.argv[0] = self.value
  
      def __exit__(self, *args):
          self.value = self._sentinel
          sys.argv[0] = self._saved_value
  
  # TODO: Replace these helpers with importlib._bootstrap._SpecMethods
  def _run_code(code, run_globals, init_globals=None,
                mod_name=None, mod_spec=None,
                pkg_name=None, script_name=None):
      """Helper to run code in nominated namespace"""
      if init_globals is not None:
          run_globals.update(init_globals)
      if mod_spec is None:
          loader = None
          fname = script_name
          cached = None
      else:
          loader = mod_spec.loader
          fname = mod_spec.origin
          cached = mod_spec.cached
          if pkg_name is None:
              pkg_name = mod_spec.parent
      run_globals.update(__name__ = mod_name,
                         __file__ = fname,
                         __cached__ = cached,
                         __doc__ = None,
                         __loader__ = loader,
                         __package__ = pkg_name,
                         __spec__ = mod_spec)
      exec(code, run_globals)
      return run_globals
  
  def _run_module_code(code, init_globals=None,
                      mod_name=None, mod_spec=None,
                      pkg_name=None, script_name=None):
      """Helper to run code in new namespace with sys modified"""
      fname = script_name if mod_spec is None else mod_spec.origin
      with _TempModule(mod_name) as temp_module, _ModifiedArgv0(fname):
          mod_globals = temp_module.module.__dict__
          _run_code(code, mod_globals, init_globals,
                    mod_name, mod_spec, pkg_name, script_name)
      # Copy the globals of the temporary module, as they
      # may be cleared when the temporary module goes away
      return mod_globals.copy()
  
  # Helper to get the loader, code and filename for a module
  def _get_module_details(mod_name):
      try:
          spec = importlib.util.find_spec(mod_name)
      except (ImportError, AttributeError, TypeError, ValueError) as ex:
          # This hack fixes an impedance mismatch between pkgutil and
          # importlib, where the latter raises other errors for cases where
          # pkgutil previously raised ImportError
          msg = "Error while finding spec for {!r} ({}: {})"
          raise ImportError(msg.format(mod_name, type(ex), ex)) from ex
      if spec is None:
          raise ImportError("No module named %s" % mod_name)
      if spec.submodule_search_locations is not None:
          if mod_name == "__main__" or mod_name.endswith(".__main__"):
              raise ImportError("Cannot use package as __main__ module")
          try:
              pkg_main_name = mod_name + ".__main__"
              return _get_module_details(pkg_main_name)
          except ImportError as e:
              raise ImportError(("%s; %r is a package and cannot " +
                                 "be directly executed") %(e, mod_name))
      loader = spec.loader
      if loader is None:
          raise ImportError("%r is a namespace package and cannot be executed"
                                                                   % mod_name)
      code = loader.get_code(mod_name)
      if code is None:
          raise ImportError("No code object available for %s" % mod_name)
      return mod_name, spec, code
  
  # XXX ncoghlan: Should this be documented and made public?
  # (Current thoughts: don't repeat the mistake that lead to its
  # creation when run_module() no longer met the needs of
  # mainmodule.c, but couldn't be changed because it was public)
  def _run_module_as_main(mod_name, alter_argv=True):
      """Runs the designated module in the __main__ namespace
  
         Note that the executed module will have full access to the
         __main__ namespace. If this is not desirable, the run_module()
         function should be used to run the module code in a fresh namespace.
  
         At the very least, these variables in __main__ will be overwritten:
             __name__
             __file__
             __cached__
             __loader__
             __package__
      """
      try:
          if alter_argv or mod_name != "__main__": # i.e. -m switch
              mod_name, mod_spec, code = _get_module_details(mod_name)
          else:          # i.e. directory or zipfile execution
              mod_name, mod_spec, code = _get_main_module_details()
      except ImportError as exc:
          # Try to provide a good error message
          # for directories, zip files and the -m switch
          if alter_argv:
              # For -m switch, just display the exception
              info = str(exc)
          else:
              # For directories/zipfiles, let the user
              # know what the code was looking for
              info = "can't find '__main__' module in %r" % sys.argv[0]
          msg = "%s: %s" % (sys.executable, info)
          sys.exit(msg)
      main_globals = sys.modules["__main__"].__dict__
      if alter_argv:
          sys.argv[0] = mod_spec.origin
      return _run_code(code, main_globals, None,
                       "__main__", mod_spec)
  
  def run_module(mod_name, init_globals=None,
                 run_name=None, alter_sys=False):
      """Execute a module's code without importing it
  
         Returns the resulting top level namespace dictionary
      """
      mod_name, mod_spec, code = _get_module_details(mod_name)
      if run_name is None:
          run_name = mod_name
      if alter_sys:
          return _run_module_code(code, init_globals, run_name, mod_spec)
      else:
          # Leave the sys module alone
          return _run_code(code, {}, init_globals, run_name, mod_spec)
  
  def _get_main_module_details():
      # Helper that gives a nicer error message when attempting to
      # execute a zipfile or directory by invoking __main__.py
      # Also moves the standard __main__ out of the way so that the
      # preexisting __loader__ entry doesn't cause issues
      main_name = "__main__"
      saved_main = sys.modules[main_name]
      del sys.modules[main_name]
      try:
          return _get_module_details(main_name)
      except ImportError as exc:
          if main_name in str(exc):
              raise ImportError("can't find %r module in %r" %
                                (main_name, sys.path[0])) from exc
          raise
      finally:
          sys.modules[main_name] = saved_main
  
  
  def _get_code_from_file(run_name, fname):
      # Check for a compiled file first
      with open(fname, "rb") as f:
          code = read_code(f)
      if code is None:
          # That didn't work, so try it as normal source code
          with open(fname, "rb") as f:
              code = compile(f.read(), fname, 'exec')
      return code, fname
  
  def run_path(path_name, init_globals=None, run_name=None):
      """Execute code located at the specified filesystem location
  
         Returns the resulting top level namespace dictionary
  
         The file path may refer directly to a Python script (i.e.
         one that could be directly executed with execfile) or else
         it may refer to a zipfile or directory containing a top
         level __main__.py script.
      """
      if run_name is None:
          run_name = "<run_path>"
      pkg_name = run_name.rpartition(".")[0]
      importer = get_importer(path_name)
      # Trying to avoid importing imp so as to not consume the deprecation warning.
      is_NullImporter = False
      if type(importer).__module__ == 'imp':
          if type(importer).__name__ == 'NullImporter':
              is_NullImporter = True
      if isinstance(importer, type(None)) or is_NullImporter:
          # Not a valid sys.path entry, so run the code directly
          # execfile() doesn't help as we want to allow compiled files
          code, fname = _get_code_from_file(run_name, path_name)
          return _run_module_code(code, init_globals, run_name,
                                  pkg_name=pkg_name, script_name=fname)
      else:
          # Importer is defined for path, so add it to
          # the start of sys.path
          sys.path.insert(0, path_name)
          try:
              # Here's where things are a little different from the run_module
              # case. There, we only had to replace the module in sys while the
              # code was running and doing so was somewhat optional. Here, we
              # have no choice and we have to remove it even while we read the
              # code. If we don't do this, a __loader__ attribute in the
              # existing __main__ module may prevent location of the new module.
              mod_name, mod_spec, code = _get_main_module_details()
              with _TempModule(run_name) as temp_module, \
                   _ModifiedArgv0(path_name):
                  mod_globals = temp_module.module.__dict__
                  return _run_code(code, mod_globals, init_globals,
                                      run_name, mod_spec, pkg_name).copy()
          finally:
              try:
                  sys.path.remove(path_name)
              except ValueError:
                  pass
  
  
  if __name__ == "__main__":
      # Run the module specified as the next command line argument
      if len(sys.argv) < 2:
          print("No module specified for execution", file=sys.stderr)
      else:
          del sys.argv[0] # Make the requested module sys.argv[0]
          _run_module_as_main(sys.argv[0])
  