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

1import collections 

2import inspect 

3import io 

4import sys 

5 

6py27 = sys.version_info >= (2, 7) 

7py2k = sys.version_info.major < 3 

8py3k = sys.version_info.major >= 3 

9py35 = sys.version_info >= (3, 5) 

10py36 = sys.version_info >= (3, 6) 

11 

12 

13ArgSpec = collections.namedtuple( 

14 "ArgSpec", ["args", "varargs", "keywords", "defaults"] 

15) 

16 

17 

18def inspect_getargspec(func): 

19 """getargspec based on fully vendored getfullargspec from Python 3.3.""" 

20 

21 if inspect.ismethod(func): 

22 func = func.__func__ 

23 if not inspect.isfunction(func): 

24 raise TypeError("{!r} is not a Python function".format(func)) 

25 

26 co = func.__code__ 

27 if not inspect.iscode(co): 

28 raise TypeError("{!r} is not a code object".format(co)) 

29 

30 nargs = co.co_argcount 

31 names = co.co_varnames 

32 nkwargs = co.co_kwonlyargcount if py3k else 0 

33 args = list(names[:nargs]) 

34 

35 nargs += nkwargs 

36 varargs = None 

37 if co.co_flags & inspect.CO_VARARGS: 

38 varargs = co.co_varnames[nargs] 

39 nargs = nargs + 1 

40 varkw = None 

41 if co.co_flags & inspect.CO_VARKEYWORDS: 

42 varkw = co.co_varnames[nargs] 

43 

44 return ArgSpec(args, varargs, varkw, func.__defaults__) 

45 

46 

47if py3k: 

48 from io import StringIO 

49else: 

50 # accepts strings 

51 from StringIO import StringIO # noqa 

52 

53if py3k: 

54 import builtins as compat_builtins 

55 

56 string_types = (str,) 

57 binary_type = bytes 

58 text_type = str 

59 

60 def callable(fn): # noqa 

61 return hasattr(fn, "__call__") 

62 

63 def u(s): 

64 return s 

65 

66 def ue(s): 

67 return s 

68 

69 range = range # noqa 

70else: 

71 import __builtin__ as compat_builtins 

72 

73 string_types = (basestring,) # noqa 

74 binary_type = str 

75 text_type = unicode # noqa 

76 callable = callable # noqa 

77 

78 def u(s): 

79 return unicode(s, "utf-8") # noqa 

80 

81 def ue(s): 

82 return unicode(s, "unicode_escape") # noqa 

83 

84 range = xrange # noqa 

85 

86if py3k: 

87 import collections.abc as collections_abc 

88else: 

89 import collections as collections_abc # noqa 

90 

91if py35: 

92 

93 def _formatannotation(annotation, base_module=None): 

94 """vendored from python 3.7 

95 """ 

96 

97 if getattr(annotation, "__module__", None) == "typing": 

98 return repr(annotation).replace("typing.", "") 

99 if isinstance(annotation, type): 

100 if annotation.__module__ in ("builtins", base_module): 

101 return annotation.__qualname__ 

102 return annotation.__module__ + "." + annotation.__qualname__ 

103 return repr(annotation) 

104 

105 def inspect_formatargspec( 

106 args, 

107 varargs=None, 

108 varkw=None, 

109 defaults=None, 

110 kwonlyargs=(), 

111 kwonlydefaults={}, 

112 annotations={}, 

113 formatarg=str, 

114 formatvarargs=lambda name: "*" + name, 

115 formatvarkw=lambda name: "**" + name, 

116 formatvalue=lambda value: "=" + repr(value), 

117 formatreturns=lambda text: " -> " + text, 

118 formatannotation=_formatannotation, 

119 ): 

120 """Copy formatargspec from python 3.7 standard library. 

121 

122 Python 3 has deprecated formatargspec and requested that Signature 

123 be used instead, however this requires a full reimplementation 

124 of formatargspec() in terms of creating Parameter objects and such. 

125 Instead of introducing all the object-creation overhead and having 

126 to reinvent from scratch, just copy their compatibility routine. 

127 

128 """ 

129 

130 def formatargandannotation(arg): 

131 result = formatarg(arg) 

132 if arg in annotations: 

133 result += ": " + formatannotation(annotations[arg]) 

134 return result 

135 

136 specs = [] 

137 if defaults: 

138 firstdefault = len(args) - len(defaults) 

139 for i, arg in enumerate(args): 

140 spec = formatargandannotation(arg) 

141 if defaults and i >= firstdefault: 

142 spec = spec + formatvalue(defaults[i - firstdefault]) 

143 specs.append(spec) 

144 if varargs is not None: 

145 specs.append(formatvarargs(formatargandannotation(varargs))) 

146 else: 

147 if kwonlyargs: 

148 specs.append("*") 

149 if kwonlyargs: 

150 for kwonlyarg in kwonlyargs: 

151 spec = formatargandannotation(kwonlyarg) 

152 if kwonlydefaults and kwonlyarg in kwonlydefaults: 

153 spec += formatvalue(kwonlydefaults[kwonlyarg]) 

154 specs.append(spec) 

155 if varkw is not None: 

156 specs.append(formatvarkw(formatargandannotation(varkw))) 

157 result = "(" + ", ".join(specs) + ")" 

158 if "return" in annotations: 

159 result += formatreturns(formatannotation(annotations["return"])) 

160 return result 

161 

162 

163else: 

164 from inspect import formatargspec as inspect_formatargspec # noqa 

165 

166 

167if py3k: 

168 from configparser import ConfigParser as SafeConfigParser 

169 import configparser 

170else: 

171 from ConfigParser import SafeConfigParser # noqa 

172 import ConfigParser as configparser # noqa 

173 

174if py2k: 

175 from mako.util import parse_encoding 

176 

177if py35: 

178 import importlib.util 

179 import importlib.machinery 

180 

181 def load_module_py(module_id, path): 

182 spec = importlib.util.spec_from_file_location(module_id, path) 

183 module = importlib.util.module_from_spec(spec) 

184 spec.loader.exec_module(module) 

185 return module 

186 

187 def load_module_pyc(module_id, path): 

188 spec = importlib.util.spec_from_file_location(module_id, path) 

189 module = importlib.util.module_from_spec(spec) 

190 spec.loader.exec_module(module) 

191 return module 

192 

193 

194elif py3k: 

195 import importlib.machinery 

196 

197 def load_module_py(module_id, path): 

198 module = importlib.machinery.SourceFileLoader( 

199 module_id, path 

200 ).load_module(module_id) 

201 del sys.modules[module_id] 

202 return module 

203 

204 def load_module_pyc(module_id, path): 

205 module = importlib.machinery.SourcelessFileLoader( 

206 module_id, path 

207 ).load_module(module_id) 

208 del sys.modules[module_id] 

209 return module 

210 

211 

212if py3k: 

213 

214 def get_bytecode_suffixes(): 

215 try: 

216 return importlib.machinery.BYTECODE_SUFFIXES 

217 except AttributeError: 

218 return importlib.machinery.DEBUG_BYTECODE_SUFFIXES 

219 

220 def get_current_bytecode_suffixes(): 

221 if py35: 

222 suffixes = importlib.machinery.BYTECODE_SUFFIXES 

223 else: 

224 if sys.flags.optimize: 

225 suffixes = importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES 

226 else: 

227 suffixes = importlib.machinery.BYTECODE_SUFFIXES 

228 

229 return suffixes 

230 

231 def has_pep3147(): 

232 

233 if py35: 

234 return True 

235 else: 

236 # TODO: not sure if we are supporting old versions of Python 

237 # the import here emits a deprecation warning which the test 

238 # suite only catches if imp wasn't imported alreadt 

239 # http://www.python.org/dev/peps/pep-3147/#detecting-pep-3147-availability 

240 import imp 

241 

242 return hasattr(imp, "get_tag") 

243 

244 

245else: 

246 import imp 

247 

248 def load_module_py(module_id, path): # noqa 

249 with open(path, "rb") as fp: 

250 mod = imp.load_source(module_id, path, fp) 

251 if py2k: 

252 source_encoding = parse_encoding(fp) 

253 if source_encoding: 

254 mod._alembic_source_encoding = source_encoding 

255 del sys.modules[module_id] 

256 return mod 

257 

258 def load_module_pyc(module_id, path): # noqa 

259 with open(path, "rb") as fp: 

260 mod = imp.load_compiled(module_id, path, fp) 

261 # no source encoding here 

262 del sys.modules[module_id] 

263 return mod 

264 

265 def get_current_bytecode_suffixes(): 

266 if sys.flags.optimize: 

267 return [".pyo"] # e.g. .pyo 

268 else: 

269 return [".pyc"] # e.g. .pyc 

270 

271 def has_pep3147(): 

272 return False 

273 

274 

275try: 

276 exec_ = getattr(compat_builtins, "exec") 

277except AttributeError: 

278 # Python 2 

279 def exec_(func_text, globals_, lcl): 

280 exec("exec func_text in globals_, lcl") 

281 

282 

283################################################ 

284# cross-compatible metaclass implementation 

285# Copyright (c) 2010-2012 Benjamin Peterson 

286 

287 

288def with_metaclass(meta, base=object): 

289 """Create a base class with a metaclass.""" 

290 return meta("%sBase" % meta.__name__, (base,), {}) 

291 

292 

293################################################ 

294 

295if py3k: 

296 

297 def reraise(tp, value, tb=None, cause=None): 

298 if cause is not None: 

299 value.__cause__ = cause 

300 if value.__traceback__ is not tb: 

301 raise value.with_traceback(tb) 

302 raise value 

303 

304 def raise_from_cause(exception, exc_info=None): 

305 if exc_info is None: 

306 exc_info = sys.exc_info() 

307 exc_type, exc_value, exc_tb = exc_info 

308 reraise(type(exception), exception, tb=exc_tb, cause=exc_value) 

309 

310 

311else: 

312 exec( 

313 "def reraise(tp, value, tb=None, cause=None):\n" 

314 " raise tp, value, tb\n" 

315 ) 

316 

317 def raise_from_cause(exception, exc_info=None): 

318 # not as nice as that of Py3K, but at least preserves 

319 # the code line where the issue occurred 

320 if exc_info is None: 

321 exc_info = sys.exc_info() 

322 exc_type, exc_value, exc_tb = exc_info 

323 reraise(type(exception), exception, tb=exc_tb) 

324 

325 

326# produce a wrapper that allows encoded text to stream 

327# into a given buffer, but doesn't close it. 

328# not sure of a more idiomatic approach to this. 

329class EncodedIO(io.TextIOWrapper): 

330 def close(self): 

331 pass 

332 

333 

334if py2k: 

335 # in Py2K, the io.* package is awkward because it does not 

336 # easily wrap the file type (e.g. sys.stdout) and I can't 

337 # figure out at all how to wrap StringIO.StringIO 

338 # and also might be user specified too. So create a full 

339 # adapter. 

340 

341 class ActLikePy3kIO(object): 

342 

343 """Produce an object capable of wrapping either 

344 sys.stdout (e.g. file) *or* StringIO.StringIO(). 

345 

346 """ 

347 

348 def _false(self): 

349 return False 

350 

351 def _true(self): 

352 return True 

353 

354 readable = seekable = _false 

355 writable = _true 

356 closed = False 

357 

358 def __init__(self, file_): 

359 self.file_ = file_ 

360 

361 def write(self, text): 

362 return self.file_.write(text) 

363 

364 def flush(self): 

365 return self.file_.flush() 

366 

367 class EncodedIO(EncodedIO): 

368 def __init__(self, file_, encoding): 

369 super(EncodedIO, self).__init__( 

370 ActLikePy3kIO(file_), encoding=encoding 

371 )