context manager to suppress package and module deprecation warnings when importing them if ignore is false this context manager has no effect forget a module was ever imported this removes the module from sys modules and deletes any pep 3147488 or legacy pyc files it doesn t matter if they exist or not unlink all possible combinations of pep 3147488 and legacy pyc files move a pep 3147488 pyc file to its legacy pyc location param source the file system path to the source file the source file does not need to exist however the pep 3147488 pyc file must exist return the file system path to the legacy pyc file import and return the module to be tested raising skiptest if it is not available if deprecated is true any module or package deprecation messages will be suppressed if a module is required on a platform but optional for others set requiredon to an iterable of platform prefixes which will be compared against sys platform force frozen modules to be used or not this only applies to modules that haven t been imported yet also some essential modules will always be imported frozen force legacy modules to be allowed in subinterpreters or not legacy singlephase init this only applies to modules that haven t been imported yet it overrides the pyinterpreterconfig checkmultiinterpextensions setting see support runinsubinterpwithconfig and xxsubinterpreters create also see importlib utils allowingallextensions import and return a module deliberately bypassing sys modules this function imports and returns a fresh copy of the named python module by removing the named module from sys modules before doing the import note that unlike reload the original module is not affected by this operation fresh is an iterable of additional module names that are also removed from the sys modules cache before doing the import if one of these modules can t be imported none is returned blocked is an iterable of module names that are replaced with none in the module cache during the import to ensure that attempts to import them raise importerror the named module and any modules named in the fresh and blocked parameters are saved before starting the import and then reinserted into sys modules when the fresh import is complete module and package deprecation messages are suppressed during this import if deprecated is true this function will raise importerror if the named module cannot be imported if usefrozen is false the default then the frozen importer is disabled except for essential modules like importlib bootstrap note testheapq testjson and testwarnings include extra sanity checks to make sure that this utility function is working as expected keep track of modules saved for later restoration as well as those which just need a blocking entry removed return none when one of the fresh modules can not be imported context manager to force import to return a new module reference this is useful for testing modulelevel behaviours such as the emission of a deprecationwarning on import use like this with cleanimportfoo importlib importmodulefoo new reference if usefrozen is false the default then the frozen importer is disabled except for essential modules like importlib bootstrap it is possible that modulename is just an alias for another module e g stub for modules renamed in 3 x in that case we also need delete the real module to clear the import cache context manager to temporarily add directories to sys path this makes a copy of sys path appends any directories given as positional arguments then reverts sys path to the copied settings when the context ends note that all sys path modifications in the body of the context manager including replacement of the object will be reverted at the end of the block encodersdecoders are registered permanently within the internal codec cache if we destroy the corresponding modules their globals will be set to none which will trip up the cached functions xxx this kind of problem can affect more than just encodings in particular extension modules such as ssl don t cope with reloading properly really test modules should be cleaning out the test specific modules they know they added ala testrunpy rather than relying on this function as testimporthooks and testpkg do currently implicitly imported real modules should be left alone see issue 10556 bpo30599 mock os registeratfork when importing the random module since this function doesn t allow to unregister callbacks and would leak memory 1 sets up a temporary directory and removes it afterwards 2 creates the module file 3 temporarily clears the module from sys modules if any 4 reverts or removes the module when cleaning up context manager to suppress package and module deprecation warnings when importing them if ignore is false this context manager has no effect forget a module was ever imported this removes the module from sys modules and deletes any pep 3147 488 or legacy pyc files it doesn t matter if they exist or not unlink all possible combinations of pep 3147 488 and legacy pyc files move a pep 3147 488 pyc file to its legacy pyc location param source the file system path to the source file the source file does not need to exist however the pep 3147 488 pyc file must exist return the file system path to the legacy pyc file import and return the module to be tested raising skiptest if it is not available if deprecated is true any module or package deprecation messages will be suppressed if a module is required on a platform but optional for others set required_on to an iterable of platform prefixes which will be compared against sys platform force frozen modules to be used or not this only applies to modules that haven t been imported yet also some essential modules will always be imported frozen force legacy modules to be allowed in subinterpreters or not legacy single phase init this only applies to modules that haven t been imported yet it overrides the pyinterpreterconfig check_multi_interp_extensions setting see support run_in_subinterp_with_config and _xxsubinterpreters create also see importlib utils allowing_all_extensions import and return a module deliberately bypassing sys modules this function imports and returns a fresh copy of the named python module by removing the named module from sys modules before doing the import note that unlike reload the original module is not affected by this operation fresh is an iterable of additional module names that are also removed from the sys modules cache before doing the import if one of these modules can t be imported none is returned blocked is an iterable of module names that are replaced with none in the module cache during the import to ensure that attempts to import them raise importerror the named module and any modules named in the fresh and blocked parameters are saved before starting the import and then reinserted into sys modules when the fresh import is complete module and package deprecation messages are suppressed during this import if deprecated is true this function will raise importerror if the named module cannot be imported if usefrozen is false the default then the frozen importer is disabled except for essential modules like importlib _bootstrap note test_heapq test_json and test_warnings include extra sanity checks to make sure that this utility function is working as expected keep track of modules saved for later restoration as well as those which just need a blocking entry removed return none when one of the fresh modules can not be imported context manager to force import to return a new module reference this is useful for testing module level behaviours such as the emission of a deprecationwarning on import use like this with cleanimport foo importlib import_module foo new reference if usefrozen is false the default then the frozen importer is disabled except for essential modules like importlib _bootstrap it is possible that module_name is just an alias for another module e g stub for modules renamed in 3 x in that case we also need delete the real module to clear the import cache context manager to temporarily add directories to sys path this makes a copy of sys path appends any directories given as positional arguments then reverts sys path to the copied settings when the context ends note that all sys path modifications in the body of the context manager including replacement of the object will be reverted at the end of the block encoders decoders are registered permanently within the internal codec cache if we destroy the corresponding modules their globals will be set to none which will trip up the cached functions xxx this kind of problem can affect more than just encodings in particular extension modules such as _ssl don t cope with reloading properly really test modules should be cleaning out the test specific modules they know they added ala test_runpy rather than relying on this function as test_importhooks and test_pkg do currently implicitly imported real modules should be left alone see issue 10556 bpo 30599 mock os register_at_fork when importing the random module since this function doesn t allow to unregister callbacks and would leak memory 1 sets up a temporary directory and removes it afterwards 2 creates the module file 3 temporarily clears the module from sys modules if any 4 reverts or removes the module when cleaning up
import contextlib
import _imp
import importlib
import importlib.util
import os
import shutil
import sys
import unittest
import warnings

from .os_helper import unlink, temp_dir


@contextlib.contextmanager
def _ignore_deprecated_imports(ignore=True):
    
    if ignore:
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore", ".+ (module|package)",
                                    DeprecationWarning)
            yield
    else:
        yield


def unload(name):
    try:
        del sys.modules[name]
    except KeyError:
        pass


def forget(modname):
    
    unload(modname)
    for dirname in sys.path:
        source = os.path.join(dirname, modname + '.py')
        
        
        unlink(source + 'c')
        for opt in ('', 1, 2):
            unlink(importlib.util.cache_from_source(source, optimization=opt))


def make_legacy_pyc(source):
    
    pyc_file = importlib.util.cache_from_source(source)
    up_one = os.path.dirname(os.path.abspath(source))
    legacy_pyc = os.path.join(up_one, source + 'c')
    shutil.move(pyc_file, legacy_pyc)
    return legacy_pyc


def import_module(name, deprecated=False, *, required_on=()):
    
    with _ignore_deprecated_imports(deprecated):
        try:
            return importlib.import_module(name)
        except ImportError as msg:
            if sys.platform.startswith(tuple(required_on)):
                raise
            raise unittest.SkipTest(str(msg))


def _save_and_remove_modules(names):
    orig_modules = {}
    prefixes = tuple(name + '.' for name in names)
    for modname in list(sys.modules):
        if modname in names or modname.startswith(prefixes):
            orig_modules[modname] = sys.modules.pop(modname)
    return orig_modules


@contextlib.contextmanager
def frozen_modules(enabled=True):
    
    _imp._override_frozen_modules_for_tests(1 if enabled else -1)
    try:
        yield
    finally:
        _imp._override_frozen_modules_for_tests(0)


@contextlib.contextmanager
def multi_interp_extensions_check(enabled=True):
    
    old = _imp._override_multi_interp_extensions_check(1 if enabled else -1)
    try:
        yield
    finally:
        _imp._override_multi_interp_extensions_check(old)


def import_fresh_module(name, fresh=(), blocked=(), *,
                        deprecated=False,
                        usefrozen=False,
                        ):
    
    
    
    with _ignore_deprecated_imports(deprecated):
        
        
        fresh = list(fresh)
        blocked = list(blocked)
        names = {name, *fresh, *blocked}
        orig_modules = _save_and_remove_modules(names)
        for modname in blocked:
            sys.modules[modname] = None

        try:
            with frozen_modules(usefrozen):
                
                try:
                    for modname in fresh:
                        __import__(modname)
                except ImportError:
                    return None
                return importlib.import_module(name)
        finally:
            _save_and_remove_modules(names)
            sys.modules.update(orig_modules)


class CleanImport(object):
    

    def __init__(self, *module_names, usefrozen=False):
        self.original_modules = sys.modules.copy()
        for module_name in module_names:
            if module_name in sys.modules:
                module = sys.modules[module_name]
                
                
                
                
                if module.__name__ != module_name:
                    del sys.modules[module.__name__]
                del sys.modules[module_name]
        self._frozen_modules = frozen_modules(usefrozen)

    def __enter__(self):
        self._frozen_modules.__enter__()
        return self

    def __exit__(self, *ignore_exc):
        sys.modules.update(self.original_modules)
        self._frozen_modules.__exit__(*ignore_exc)


class DirsOnSysPath(object):
    

    def __init__(self, *paths):
        self.original_value = sys.path[:]
        self.original_object = sys.path
        sys.path.extend(paths)

    def __enter__(self):
        return self

    def __exit__(self, *ignore_exc):
        sys.path = self.original_object
        sys.path[:] = self.original_value


def modules_setup():
    return sys.modules.copy(),


def modules_cleanup(oldmodules):
    
    
    
    encodings = [(k, v) for k, v in sys.modules.items()
                 if k.startswith('encodings.')]
    sys.modules.clear()
    sys.modules.update(encodings)
    
    
    
    
    
    
    
    sys.modules.update(oldmodules)


def mock_register_at_fork(func):
    
    
    
    from unittest import mock
    return mock.patch('os.register_at_fork', create=True)(func)


@contextlib.contextmanager
def ready_to_import(name=None, source=""):
    from test.support import script_helper

    
    
    
    
    name = name or "spam"
    with temp_dir() as tempdir:
        path = script_helper.make_script(tempdir, name, source)
        old_module = sys.modules.pop(name, None)
        try:
            sys.path.insert(0, tempdir)
            yield name, path
            sys.path.remove(tempdir)
        finally:
            if old_module is not None:
                sys.modules[name] = old_module
            else:
                sys.modules.pop(name, None)