# coding: utf-8 """Compatibility tricks for Python 3. Mainly to do with unicode.""" import __builtin__ import functools import sys import re import types import locale orig_open = open def no_code(x, encoding=None): return x # to deal with the possibility of sys.std* not being a stream at all def get_stream_enc(stream, default=None): if not hasattr(stream, 'encoding') or not stream.encoding: return default else: return stream.encoding # Less conservative replacement for sys.getdefaultencoding, that will try # to match the environment. # Defined here as central function, so if we find better choices, we # won't need to make changes all over IPython. def getdefaultencoding(): """Return IPython's guess for the default encoding for bytes as text. Asks for stdin.encoding first, to match the calling Terminal, but that is often None for subprocesses. Fall back on locale.getpreferredencoding() which should be a sensible platform default (that respects LANG environment), and finally to sys.getdefaultencoding() which is the most conservative option, and usually ASCII. """ enc = get_stream_enc(sys.stdin) if not enc or enc=='ascii': try: # There are reports of getpreferredencoding raising errors # in some cases, which may well be fixed, but let's be conservative here. enc = locale.getpreferredencoding() except Exception: pass return enc or sys.getdefaultencoding() def decode(s, encoding=None): encoding = encoding or getdefaultencoding() return s.decode(encoding, "replace") def encode(u, encoding=None): encoding = encoding or getdefaultencoding() return u.encode(encoding, "replace") def cast_unicode(s, encoding=None): if isinstance(s, bytes): return decode(s, encoding) return s def cast_bytes(s, encoding=None): if not isinstance(s, bytes): return encode(s, encoding) return s def _modify_str_or_docstring(str_change_func): @functools.wraps(str_change_func) def wrapper(func_or_str): if isinstance(func_or_str, basestring): func = None doc = func_or_str else: func = func_or_str doc = func.__doc__ doc = str_change_func(doc) if func: func.__doc__ = doc return func return doc return wrapper if sys.version_info[0] >= 3: PY3 = True input = input builtin_mod_name = "builtins" str_to_unicode = no_code unicode_to_str = no_code str_to_bytes = encode bytes_to_str = decode cast_bytes_py2 = no_code def isidentifier(s, dotted=False): if dotted: return all(isidentifier(a) for a in s.split(".")) return s.isidentifier() open = orig_open MethodType = types.MethodType def execfile(fname, glob, loc=None): loc = loc if (loc is not None) else glob exec compile(open(fname, 'rb').read(), fname, 'exec') in glob, loc # Refactor print statements in doctests. _print_statement_re = re.compile(r"\bprint (?P.*)$", re.MULTILINE) def _print_statement_sub(match): expr = match.groups('expr') return "print(%s)" % expr @_modify_str_or_docstring def doctest_refactor_print(doc): """Refactor 'print x' statements in a doctest to print(x) style. 2to3 unfortunately doesn't pick up on our doctests. Can accept a string or a function, so it can be used as a decorator.""" return _print_statement_re.sub(_print_statement_sub, doc) # Abstract u'abc' syntax: @_modify_str_or_docstring def u_format(s): """"{u}'abc'" --> "'abc'" (Python 3) Accepts a string or a function, so it can be used as a decorator.""" return s.format(u='') else: PY3 = False input = raw_input builtin_mod_name = "__builtin__" str_to_unicode = decode unicode_to_str = encode str_to_bytes = no_code bytes_to_str = no_code cast_bytes_py2 = cast_bytes import re _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") def isidentifier(s, dotted=False): if dotted: return all(isidentifier(a) for a in s.split(".")) return bool(_name_re.match(s)) class open(object): """Wrapper providing key part of Python 3 open() interface.""" def __init__(self, fname, mode="r", encoding="utf-8"): self.f = orig_open(fname, mode) self.enc = encoding def write(self, s): return self.f.write(s.encode(self.enc)) def read(self, size=-1): return self.f.read(size).decode(self.enc) def close(self): return self.f.close() def __enter__(self): return self def __exit__(self, etype, value, traceback): self.f.close() def MethodType(func, instance): return types.MethodType(func, instance, type(instance)) # don't override system execfile on 2.x: execfile = execfile def doctest_refactor_print(func_or_str): return func_or_str # Abstract u'abc' syntax: @_modify_str_or_docstring def u_format(s): """"{u}'abc'" --> "u'abc'" (Python 2) Accepts a string or a function, so it can be used as a decorator.""" return s.format(u='u') if sys.platform == 'win32': def execfile(fname, glob=None, loc=None): loc = loc if (loc is not None) else glob # The rstrip() is necessary b/c trailing whitespace in files will # cause an IndentationError in Python 2.6 (this was fixed in 2.7, # but we still support 2.6). See issue 1027. scripttext = __builtin__.open(fname).read().rstrip() + '\n' # compile converts unicode filename to str assuming # ascii. Let's do the conversion before calling compile if isinstance(fname, unicode): filename = unicode_to_str(fname) else: filename = fname exec compile(scripttext, filename, 'exec') in glob, loc else: def execfile(fname, *where): if isinstance(fname, unicode): filename = fname.encode(sys.getfilesystemencoding()) else: filename = fname __builtin__.execfile(filename, *where)