Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/alembic/util/compat.py : 42%

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
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)
13ArgSpec = collections.namedtuple(
14 "ArgSpec", ["args", "varargs", "keywords", "defaults"]
15)
18def inspect_getargspec(func):
19 """getargspec based on fully vendored getfullargspec from Python 3.3."""
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))
26 co = func.__code__
27 if not inspect.iscode(co):
28 raise TypeError("{!r} is not a code object".format(co))
30 nargs = co.co_argcount
31 names = co.co_varnames
32 nkwargs = co.co_kwonlyargcount if py3k else 0
33 args = list(names[:nargs])
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]
44 return ArgSpec(args, varargs, varkw, func.__defaults__)
47if py3k:
48 from io import StringIO
49else:
50 # accepts strings
51 from StringIO import StringIO # noqa
53if py3k:
54 import builtins as compat_builtins
56 string_types = (str,)
57 binary_type = bytes
58 text_type = str
60 def callable(fn): # noqa
61 return hasattr(fn, "__call__")
63 def u(s):
64 return s
66 def ue(s):
67 return s
69 range = range # noqa
70else:
71 import __builtin__ as compat_builtins
73 string_types = (basestring,) # noqa
74 binary_type = str
75 text_type = unicode # noqa
76 callable = callable # noqa
78 def u(s):
79 return unicode(s, "utf-8") # noqa
81 def ue(s):
82 return unicode(s, "unicode_escape") # noqa
84 range = xrange # noqa
86if py3k:
87 import collections.abc as collections_abc
88else:
89 import collections as collections_abc # noqa
91if py35:
93 def _formatannotation(annotation, base_module=None):
94 """vendored from python 3.7
95 """
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)
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.
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.
128 """
130 def formatargandannotation(arg):
131 result = formatarg(arg)
132 if arg in annotations:
133 result += ": " + formatannotation(annotations[arg])
134 return result
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
163else:
164 from inspect import formatargspec as inspect_formatargspec # noqa
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
174if py2k:
175 from mako.util import parse_encoding
177if py35:
178 import importlib.util
179 import importlib.machinery
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
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
194elif py3k:
195 import importlib.machinery
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
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
212if py3k:
214 def get_bytecode_suffixes():
215 try:
216 return importlib.machinery.BYTECODE_SUFFIXES
217 except AttributeError:
218 return importlib.machinery.DEBUG_BYTECODE_SUFFIXES
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
229 return suffixes
231 def has_pep3147():
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
242 return hasattr(imp, "get_tag")
245else:
246 import imp
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
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
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
271 def has_pep3147():
272 return False
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")
283################################################
284# cross-compatible metaclass implementation
285# Copyright (c) 2010-2012 Benjamin Peterson
288def with_metaclass(meta, base=object):
289 """Create a base class with a metaclass."""
290 return meta("%sBase" % meta.__name__, (base,), {})
293################################################
295if py3k:
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
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)
311else:
312 exec(
313 "def reraise(tp, value, tb=None, cause=None):\n"
314 " raise tp, value, tb\n"
315 )
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)
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
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.
341 class ActLikePy3kIO(object):
343 """Produce an object capable of wrapping either
344 sys.stdout (e.g. file) *or* StringIO.StringIO().
346 """
348 def _false(self):
349 return False
351 def _true(self):
352 return True
354 readable = seekable = _false
355 writable = _true
356 closed = False
358 def __init__(self, file_):
359 self.file_ = file_
361 def write(self, text):
362 return self.file_.write(text)
364 def flush(self):
365 return self.file_.flush()
367 class EncodedIO(EncodedIO):
368 def __init__(self, file_, encoding):
369 super(EncodedIO, self).__init__(
370 ActLikePy3kIO(file_), encoding=encoding
371 )