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

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

"""Tools to assist importing optional external modules.""" 

 

from __future__ import print_function, division 

 

import sys 

 

# Override these in the module to change the default warning behavior. 

# For example, you might set both to False before running the tests so that 

# warnings are not printed to the console, or set both to True for debugging. 

 

WARN_NOT_INSTALLED = None # Default is False 

WARN_OLD_VERSION = None # Default is True 

 

 

def __sympy_debug(): 

# helper function from sympy/__init__.py 

# We don't just import SYMPY_DEBUG from that file because we don't want to 

# import all of sympy just to use this module. 

import os 

debug_str = os.getenv('SYMPY_DEBUG', 'False') 

if debug_str in ('True', 'False'): 

return eval(debug_str) 

else: 

raise RuntimeError("unrecognized value for SYMPY_DEBUG: %s" % 

debug_str) 

 

if __sympy_debug(): 

WARN_OLD_VERSION = True 

WARN_NOT_INSTALLED = True 

 

 

def import_module(module, min_module_version=None, min_python_version=None, 

warn_not_installed=None, warn_old_version=None, 

module_version_attr='__version__', module_version_attr_call_args=None, 

__import__kwargs={}, catch=()): 

""" 

Import and return a module if it is installed. 

 

If the module is not installed, it returns None. 

 

A minimum version for the module can be given as the keyword argument 

min_module_version. This should be comparable against the module version. 

By default, module.__version__ is used to get the module version. To 

override this, set the module_version_attr keyword argument. If the 

attribute of the module to get the version should be called (e.g., 

module.version()), then set module_version_attr_call_args to the args such 

that module.module_version_attr(*module_version_attr_call_args) returns the 

module's version. 

 

If the module version is less than min_module_version using the Python < 

comparison, None will be returned, even if the module is installed. You can 

use this to keep from importing an incompatible older version of a module. 

 

You can also specify a minimum Python version by using the 

min_python_version keyword argument. This should be comparable against 

sys.version_info. 

 

If the keyword argument warn_not_installed is set to True, the function will 

emit a UserWarning when the module is not installed. 

 

If the keyword argument warn_old_version is set to True, the function will 

emit a UserWarning when the library is installed, but cannot be imported 

because of the min_module_version or min_python_version options. 

 

Note that because of the way warnings are handled, a warning will be 

emitted for each module only once. You can change the default warning 

behavior by overriding the values of WARN_NOT_INSTALLED and WARN_OLD_VERSION 

in sympy.external.importtools. By default, WARN_NOT_INSTALLED is False and 

WARN_OLD_VERSION is True. 

 

This function uses __import__() to import the module. To pass additional 

options to __import__(), use the __import__kwargs keyword argument. For 

example, to import a submodule A.B, you must pass a nonempty fromlist option 

to __import__. See the docstring of __import__(). 

 

This catches ImportError to determine if the module is not installed. To 

catch additional errors, pass them as a tuple to the catch keyword 

argument. 

 

Examples 

======== 

 

>>> from sympy.external import import_module 

 

>>> numpy = import_module('numpy') 

 

>>> numpy = import_module('numpy', min_python_version=(2, 7), 

... warn_old_version=False) 

 

>>> numpy = import_module('numpy', min_module_version='1.5', 

... warn_old_version=False) # numpy.__version__ is a string 

 

>>> # gmpy does not have __version__, but it does have gmpy.version() 

 

>>> gmpy = import_module('gmpy', min_module_version='1.14', 

... module_version_attr='version', module_version_attr_call_args=(), 

... warn_old_version=False) 

 

>>> # To import a submodule, you must pass a nonempty fromlist to 

>>> # __import__(). The values do not matter. 

>>> p3 = import_module('mpl_toolkits.mplot3d', 

... __import__kwargs={'fromlist':['something']}) 

 

>>> # matplotlib.pyplot can raise RuntimeError when the display cannot be opened 

>>> matplotlib = import_module('matplotlib', 

... __import__kwargs={'fromlist':['pyplot']}, catch=(RuntimeError,)) 

 

""" 

# keyword argument overrides default, and global variable overrides 

# keyword argument. 

warn_old_version = (WARN_OLD_VERSION if WARN_OLD_VERSION is not None 

else warn_old_version or True) 

warn_not_installed = (WARN_NOT_INSTALLED if WARN_NOT_INSTALLED is not None 

else warn_not_installed or False) 

 

import warnings 

 

# Check Python first so we don't waste time importing a module we can't use 

if min_python_version: 

if sys.version_info < min_python_version: 

if warn_old_version: 

warnings.warn("Python version is too old to use %s " 

"(%s or newer required)" % ( 

module, '.'.join(map(str, min_python_version))), 

UserWarning) 

return 

 

# PyPy 1.6 has rudimentary NumPy support and importing it produces errors, so skip it 

if module == 'numpy' and '__pypy__' in sys.builtin_module_names: 

return 

 

try: 

mod = __import__(module, **__import__kwargs) 

 

## there's something funny about imports with matplotlib and py3k. doing 

## from matplotlib import collections 

## gives python's stdlib collections module. explicitly re-importing 

## the module fixes this. 

from_list = __import__kwargs.get('fromlist', tuple()) 

for submod in from_list: 

if submod == 'collections' and mod.__name__ == 'matplotlib': 

__import__(module + '.' + submod) 

except ImportError: 

if warn_not_installed: 

warnings.warn("%s module is not installed" % module, UserWarning) 

return 

except catch as e: 

if warn_not_installed: 

warnings.warn( 

"%s module could not be used (%s)" % (module, repr(e))) 

return 

 

if min_module_version: 

modversion = getattr(mod, module_version_attr) 

if module_version_attr_call_args is not None: 

modversion = modversion(*module_version_attr_call_args) 

if modversion < min_module_version: 

if warn_old_version: 

# Attempt to create a pretty string version of the version 

if isinstance(min_module_version, basestring): 

verstr = min_module_version 

elif isinstance(min_module_version, (tuple, list)): 

verstr = '.'.join(map(str, min_module_version)) 

else: 

# Either don't know what this is. Hopefully 

# it's something that has a nice str version, like an int. 

verstr = str(min_module_version) 

warnings.warn("%s version is too old to use " 

"(%s or newer required)" % (module, verstr), 

UserWarning) 

return 

 

return mod