Hide keyboard shortcuts

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