Transparent package redirection without loader.load_module?

Scenario: rootpkg.oldpkg.subpkg.mod used to contain ClsInMod, but we decide rootpkg.oldpkg needs to be moved to newpkg. Can this be done without prior users needing to change their code when they upgrade?

I tried a variety of different things, but I finally arrived at this:

Working code
# (C)2020 Dustin Spicuzza, MIT license
# To redirect your own modules:
# * Copy this file to your 'old' package as ``
# * Change 'import newpkg' to 'import my_new_pkg as newpkg'
# * Everything else should 'just work'

import newpkg

import importlib
import importlib.util
import sys
import warnings

class LoaderWrapper:
    def __init__(self, name): = name

    # Use deprecated load_module precisely because we *don't* want to
    # set the import-related attributes properly, as we're just passing
    # the other module through without modification
    # TODO: file a bug to get this undeprecated or find a better way

    def load_module(self, fullname):
        sys.modules[fullname] = importlib.import_module(

class PackageFinder:

    oldpkg = __name__ + "."
    newpkg = newpkg.__name__ + "."

    def find_spec(cls, fullname, path, target=None):
        if fullname.startswith(cls.oldpkg):
            newfullname = cls.newpkg + fullname[len(cls.oldpkg) :]
            loader = LoaderWrapper(newfullname)
            return importlib.util.spec_from_loader(fullname, loader)

    __name__ + " is deprecated, use " + newpkg.__name__ + " instead", DeprecationWarning

sys.meta_path.insert(0, PackageFinder)
sys.modules[__name__] = newpkg
del newpkg

It’s pretty neat, and I’ve put a working demonstration of my idea here if you want to play with it:

The one thing that’s a bit troubling is that the load_module method of an importlib loader is deprecated, so eventually my implementation will no longer work. It says that should instead use create_module and exec_module to implement it. However, by using those methods, that causes the module’s __name__ and __path__ to be modified, which causes the module’s name to change depending on the order you import things – eg, exactly what I don’t want. I want the new package and the old package to be identical.

Is there another way to accomplish this without using the deprecated load_module?