1# Copyright 2017 Christoph Reiter
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7
8import sys
9import importlib
10
11
12class RedirectImportHook(object):
13    """Import hook which loads packages as sub packages.
14
15    e.g. "import raven" will import "quodlibet.packages.raven" even
16    if raven uses absolute imports internally.
17    """
18
19    def __init__(self, name, packages):
20        """
21        Args:
22            name (str): The package path to load the packages from
23            packages (List[str]): A list of packages provided
24        """
25
26        for package in packages:
27            if package in sys.modules:
28                raise Exception("%r already loaded, can't redirect" % package)
29
30        self._name = name
31        self._packages = packages
32
33    def find_module(self, fullname, path=None):
34        package = fullname.split(".")[0]
35        if package in self._packages:
36            return self
37
38    def load_module(self, name):
39        mod = None
40        if name in sys.modules:
41            mod = sys.modules[name]
42        loadname = self._name + "." + name
43        if loadname in sys.modules:
44            mod = sys.modules[loadname]
45        if mod is None:
46            mod = importlib.import_module(loadname)
47        sys.modules[name] = mod
48        sys.modules[loadname] = mod
49        return mod
50
51
52def install_redirect_import_hook():
53    """Install the import hook, does not import anything"""
54
55    import_hook = RedirectImportHook(
56        "quodlibet.packages", ["senf", "raven"])
57    sys.meta_path.insert(0, import_hook)
58