1# mako/compat.py 2# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file> 3# 4# This module is part of Mako and is released under 5# the MIT License: http://www.opensource.org/licenses/mit-license.php 6 7import collections 8import inspect 9import sys 10 11py3k = sys.version_info >= (3, 0) 12py2k = sys.version_info < (3,) 13py27 = sys.version_info >= (2, 7) 14jython = sys.platform.startswith("java") 15win32 = sys.platform.startswith("win") 16pypy = hasattr(sys, "pypy_version_info") 17 18ArgSpec = collections.namedtuple( 19 "ArgSpec", ["args", "varargs", "keywords", "defaults"] 20) 21 22 23def inspect_getargspec(func): 24 """getargspec based on fully vendored getfullargspec from Python 3.3.""" 25 26 if inspect.ismethod(func): 27 func = func.__func__ 28 if not inspect.isfunction(func): 29 raise TypeError("{!r} is not a Python function".format(func)) 30 31 co = func.__code__ 32 if not inspect.iscode(co): 33 raise TypeError("{!r} is not a code object".format(co)) 34 35 nargs = co.co_argcount 36 names = co.co_varnames 37 nkwargs = co.co_kwonlyargcount if py3k else 0 38 args = list(names[:nargs]) 39 40 nargs += nkwargs 41 varargs = None 42 if co.co_flags & inspect.CO_VARARGS: 43 varargs = co.co_varnames[nargs] 44 nargs = nargs + 1 45 varkw = None 46 if co.co_flags & inspect.CO_VARKEYWORDS: 47 varkw = co.co_varnames[nargs] 48 49 return ArgSpec(args, varargs, varkw, func.__defaults__) 50 51 52if py3k: 53 from io import StringIO 54 import builtins as compat_builtins 55 from urllib.parse import quote_plus, unquote_plus 56 from html.entities import codepoint2name, name2codepoint 57 58 string_types = (str,) 59 binary_type = bytes 60 text_type = str 61 62 from io import BytesIO as byte_buffer 63 64 def u(s): 65 return s 66 67 def b(s): 68 return s.encode("latin-1") 69 70 def octal(lit): 71 return eval("0o" + lit) 72 73 74else: 75 import __builtin__ as compat_builtins # noqa 76 77 try: 78 from cStringIO import StringIO 79 except: 80 from StringIO import StringIO 81 82 byte_buffer = StringIO 83 84 from urllib import quote_plus, unquote_plus # noqa 85 from htmlentitydefs import codepoint2name, name2codepoint # noqa 86 87 string_types = (basestring,) # noqa 88 binary_type = str 89 text_type = unicode # noqa 90 91 def u(s): 92 return unicode(s, "utf-8") # noqa 93 94 def b(s): 95 return s 96 97 def octal(lit): 98 return eval("0" + lit) 99 100 101if py3k: 102 from importlib import machinery, util 103 104 if hasattr(util, 'module_from_spec'): 105 # Python 3.5+ 106 def load_module(module_id, path): 107 spec = util.spec_from_file_location(module_id, path) 108 module = util.module_from_spec(spec) 109 spec.loader.exec_module(module) 110 return module 111 else: 112 def load_module(module_id, path): 113 module = machinery.SourceFileLoader(module_id, path).load_module() 114 del sys.modules[module_id] 115 return module 116 117else: 118 import imp 119 120 def load_module(module_id, path): 121 fp = open(path, "rb") 122 try: 123 module = imp.load_source(module_id, path, fp) 124 del sys.modules[module_id] 125 return module 126 finally: 127 fp.close() 128 129 130if py3k: 131 132 def reraise(tp, value, tb=None, cause=None): 133 if cause is not None: 134 value.__cause__ = cause 135 if value.__traceback__ is not tb: 136 raise value.with_traceback(tb) 137 raise value 138 139 140else: 141 exec( 142 "def reraise(tp, value, tb=None, cause=None):\n" 143 " raise tp, value, tb\n" 144 ) 145 146 147def exception_as(): 148 return sys.exc_info()[1] 149 150 151all = all # noqa 152 153 154def exception_name(exc): 155 return exc.__class__.__name__ 156 157 158################################################ 159# cross-compatible metaclass implementation 160# Copyright (c) 2010-2012 Benjamin Peterson 161def with_metaclass(meta, base=object): 162 """Create a base class with a metaclass.""" 163 return meta("%sBase" % meta.__name__, (base,), {}) 164 165 166################################################ 167 168 169def arg_stringname(func_arg): 170 """Gets the string name of a kwarg or vararg 171 In Python3.4 a function's args are 172 of _ast.arg type not _ast.name 173 """ 174 if hasattr(func_arg, "arg"): 175 return func_arg.arg 176 else: 177 return str(func_arg) 178