Coverage for gi/importer.py: 0%

# Coverage for gi/importer.py : 0%

## 61 statements 0 run 61 missing 0 excluded

Hot-keys on this page

r m x p toggle line displays

j k next/prev highlighted chunk

0 (zero) top of page

1 (one) first highlighted chunk

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | # -*- Mode: Python; py-indent-offset: 4 -*- # vim: tabstop=4 shiftwidth=4 expandtab # # Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org> # 2015 Christoph Reiter # # importer.py: dynamic importer for introspected libraries. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 # USA from __future__ import absolute_import import sys import warnings import importlib from contextlib import contextmanager import gi from ._gi import Repository, RepositoryError from ._gi import PyGIWarning from .module import get_introspection_module from .overrides import load_overrides repository = Repository.get_default() # only for backwards compatibility modules = {} @contextmanager def _check_require_version(namespace, stacklevel): """A context manager which tries to give helpful warnings about missing gi.require_version() which could potentially break code if only an older version than expected is installed or a new version gets introduced. :: with _check_require_version("Gtk", stacklevel): load_namespace_and_overrides() """ was_loaded = repository.is_registered(namespace) yield if was_loaded: # it was loaded before by another import which depended on this # namespace or by C code like libpeas return if namespace in ("GLib", "GObject", "Gio"): # part of glib (we have bigger problems if versions change there) return if gi.get_required_version(namespace) is not None: # the version was forced using require_version() return version = repository.get_version(namespace) warnings.warn( "%(namespace)s was imported without specifying a version first. " "Use gi.require_version('%(namespace)s', '%(version)s') before " "import to ensure that the right version gets loaded." % {"namespace": namespace, "version": version}, PyGIWarning, stacklevel=stacklevel) def get_import_stacklevel(import_hook): """Returns the stacklevel value for warnings.warn() for when the warning gets emitted by an imported module, but the warning should point at the code doing the import. Pass import_hook=True if the warning gets generated by an import hook (warn() gets called in load_module(), see PEP302) """ py_version = sys.version_info[:2] if py_version <= (3, 2): # 2.7 included return 4 if import_hook else 2 elif py_version == (3, 3): return 8 if import_hook else 10 elif py_version == (3, 4): return 10 if import_hook else 8 else: # fixed again in 3.5+, see https://bugs.python.org/issue24305 return 4 if import_hook else 2 class DynamicImporter(object): # Note: see PEP302 for the Importer Protocol implemented below. def __init__(self, path): self.path = path def find_module(self, fullname, path=None): if not fullname.startswith(self.path): return path, namespace = fullname.rsplit('.', 1) if path != self.path: return # is_registered() is faster than enumerate_versions() and # in the common case of a namespace getting loaded before its # dependencies, is_registered() returns True for all dependencies. if repository.is_registered(namespace) or \ repository.enumerate_versions(namespace): return self else: raise ImportError('cannot import name %s, ' 'introspection typelib not found' % namespace) def load_module(self, fullname): if fullname in sys.modules: return sys.modules[fullname] path, namespace = fullname.rsplit('.', 1) stacklevel = get_import_stacklevel(import_hook=True) with _check_require_version(namespace, stacklevel=stacklevel): try: introspection_module = get_introspection_module(namespace) except RepositoryError as e: raise ImportError(e) # Import all dependencies first so their init functions # (gdk_init, ..) in overrides get called. # https://bugzilla.gnome.org/show_bug.cgi?id=656314 for dep in repository.get_immediate_dependencies(namespace): importlib.import_module('gi.repository.' + dep.split("-")[0]) dynamic_module = load_overrides(introspection_module) dynamic_module.__file__ = '<%s>' % fullname dynamic_module.__loader__ = self sys.modules[fullname] = dynamic_module return dynamic_module