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