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""" 

2Python 3.X compatibility tools. 

3 

4While this file was originally intended for Python 2 -> 3 transition, 

5it is now used to create a compatibility layer between different 

6minor versions of Python 3. 

7 

8While the active version of numpy may not support a given version of python, we 

9allow downstream libraries to continue to use these shims for forward 

10compatibility with numpy while they transition their code to newer versions of 

11Python. 

12""" 

13__all__ = ['bytes', 'asbytes', 'isfileobj', 'getexception', 'strchar', 

14 'unicode', 'asunicode', 'asbytes_nested', 'asunicode_nested', 

15 'asstr', 'open_latin1', 'long', 'basestring', 'sixu', 

16 'integer_types', 'is_pathlib_path', 'npy_load_module', 'Path', 

17 'pickle', 'contextlib_nullcontext', 'os_fspath', 'os_PathLike'] 

18 

19import sys 

20import os 

21from pathlib import Path, PurePath 

22import io 

23 

24import abc 

25from abc import ABC as abc_ABC 

26 

27try: 

28 import pickle5 as pickle 

29except ImportError: 

30 import pickle 

31 

32long = int 

33integer_types = (int,) 

34basestring = str 

35unicode = str 

36bytes = bytes 

37 

38def asunicode(s): 

39 if isinstance(s, bytes): 

40 return s.decode('latin1') 

41 return str(s) 

42 

43def asbytes(s): 

44 if isinstance(s, bytes): 

45 return s 

46 return str(s).encode('latin1') 

47 

48def asstr(s): 

49 if isinstance(s, bytes): 

50 return s.decode('latin1') 

51 return str(s) 

52 

53def isfileobj(f): 

54 return isinstance(f, (io.FileIO, io.BufferedReader, io.BufferedWriter)) 

55 

56def open_latin1(filename, mode='r'): 

57 return open(filename, mode=mode, encoding='iso-8859-1') 

58 

59def sixu(s): 

60 return s 

61 

62strchar = 'U' 

63 

64def getexception(): 

65 return sys.exc_info()[1] 

66 

67def asbytes_nested(x): 

68 if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)): 

69 return [asbytes_nested(y) for y in x] 

70 else: 

71 return asbytes(x) 

72 

73def asunicode_nested(x): 

74 if hasattr(x, '__iter__') and not isinstance(x, (bytes, unicode)): 

75 return [asunicode_nested(y) for y in x] 

76 else: 

77 return asunicode(x) 

78 

79def is_pathlib_path(obj): 

80 """ 

81 Check whether obj is a pathlib.Path object. 

82 

83 Prefer using `isinstance(obj, os_PathLike)` instead of this function. 

84 """ 

85 return Path is not None and isinstance(obj, Path) 

86 

87# from Python 3.7 

88class contextlib_nullcontext: 

89 """Context manager that does no additional processing. 

90 

91 Used as a stand-in for a normal context manager, when a particular 

92 block of code is only sometimes used with a normal context manager: 

93 

94 cm = optional_cm if condition else nullcontext() 

95 with cm: 

96 # Perform operation, using optional_cm if condition is True 

97 """ 

98 

99 def __init__(self, enter_result=None): 

100 self.enter_result = enter_result 

101 

102 def __enter__(self): 

103 return self.enter_result 

104 

105 def __exit__(self, *excinfo): 

106 pass 

107 

108 

109def npy_load_module(name, fn, info=None): 

110 """ 

111 Load a module. 

112 

113 .. versionadded:: 1.11.2 

114 

115 Parameters 

116 ---------- 

117 name : str 

118 Full module name. 

119 fn : str 

120 Path to module file. 

121 info : tuple, optional 

122 Only here for backward compatibility with Python 2.*. 

123 

124 Returns 

125 ------- 

126 mod : module 

127 

128 """ 

129 # Explicitly lazy import this to avoid paying the cost 

130 # of importing importlib at startup 

131 from importlib.machinery import SourceFileLoader 

132 return SourceFileLoader(name, fn).load_module() 

133 

134 

135# Backport os.fs_path, os.PathLike, and PurePath.__fspath__ 

136if sys.version_info[:2] >= (3, 6): 

137 os_fspath = os.fspath 

138 os_PathLike = os.PathLike 

139else: 

140 def _PurePath__fspath__(self): 

141 return str(self) 

142 

143 class os_PathLike(abc_ABC): 

144 """Abstract base class for implementing the file system path protocol.""" 

145 

146 @abc.abstractmethod 

147 def __fspath__(self): 

148 """Return the file system path representation of the object.""" 

149 raise NotImplementedError 

150 

151 @classmethod 

152 def __subclasshook__(cls, subclass): 

153 if PurePath is not None and issubclass(subclass, PurePath): 

154 return True 

155 return hasattr(subclass, '__fspath__') 

156 

157 

158 def os_fspath(path): 

159 """Return the path representation of a path-like object. 

160 If str or bytes is passed in, it is returned unchanged. Otherwise the 

161 os.PathLike interface is used to get the path representation. If the 

162 path representation is not str or bytes, TypeError is raised. If the 

163 provided path is not str, bytes, or os.PathLike, TypeError is raised. 

164 """ 

165 if isinstance(path, (str, bytes)): 

166 return path 

167 

168 # Work from the object's type to match method resolution of other magic 

169 # methods. 

170 path_type = type(path) 

171 try: 

172 path_repr = path_type.__fspath__(path) 

173 except AttributeError: 

174 if hasattr(path_type, '__fspath__'): 

175 raise 

176 elif PurePath is not None and issubclass(path_type, PurePath): 

177 return _PurePath__fspath__(path) 

178 else: 

179 raise TypeError("expected str, bytes or os.PathLike object, " 

180 "not " + path_type.__name__) 

181 if isinstance(path_repr, (str, bytes)): 

182 return path_repr 

183 else: 

184 raise TypeError("expected {}.__fspath__() to return str or bytes, " 

185 "not {}".format(path_type.__name__, 

186 type(path_repr).__name__))