1# -*- coding: utf-8 -*- 2# 3# Copyright © 2012-2013 Pierre Raybaut 4# Licensed under the terms of the MIT License 5# (see spyderlib/__init__.py for details) 6 7""" 8spyderlib.py3compat 9------------------- 10 11Transitional module providing compatibility functions intended to help 12migrating from Python 2 to Python 3. 13 14This module should be fully compatible with: 15 * Python >=v2.6 16 * Python 3 17""" 18 19from __future__ import print_function 20 21import sys 22import os 23 24PY2 = sys.version_info[0] == 2 25PY3 = sys.version_info[0] == 3 26PY33 = PY3 and sys.version_info[1] >= 3 27 28 29# ============================================================================= 30# Data types 31# ============================================================================= 32if PY2: 33 # Python 2 34 TEXT_TYPES = (str, unicode) 35 INT_TYPES = (int, long) 36else: 37 # Python 3 38 TEXT_TYPES = (str,) 39 INT_TYPES = (int,) 40NUMERIC_TYPES = tuple(list(INT_TYPES) + [float, complex]) 41 42 43# ============================================================================= 44# Renamed/Reorganized modules 45# ============================================================================= 46if PY2: 47 # Python 2 48 import __builtin__ as builtins 49 from collections import Callable, MutableMapping 50 import ConfigParser as configparser 51 try: 52 import _winreg as winreg 53 except ImportError: 54 pass 55 from sys import maxint as maxsize 56 try: 57 import CStringIO as io 58 except ImportError: 59 import StringIO as io 60 try: 61 import cPickle as pickle 62 except ImportError: 63 import pickle 64 from UserDict import DictMixin as MutableMapping 65 import thread as _thread 66 import repr as reprlib 67else: 68 # Python 3 69 import builtins 70 import configparser 71 try: 72 import winreg 73 except ImportError: 74 pass 75 from sys import maxsize 76 import io 77 import pickle 78 if PY33: 79 from collections.abc import Callable, MutableMapping 80 else: 81 from collections import Callable, MutableMapping 82 import _thread 83 import reprlib 84 85 86# ============================================================================= 87# Strings 88# ============================================================================= 89if PY2: 90 # Python 2 91 import codecs 92 93 def u(obj): 94 """Make unicode object""" 95 return codecs.unicode_escape_decode(obj)[0] 96else: 97 # Python 3 98 def u(obj): 99 """Return string as it is""" 100 return obj 101 102 103def is_text_string(obj): 104 """Return True if `obj` is a text string, False if it is anything else, 105 like binary data (Python 3) or QString (Python 2, PyQt API #1)""" 106 if PY2: 107 # Python 2 108 return isinstance(obj, basestring) 109 else: 110 # Python 3 111 return isinstance(obj, str) 112 113 114def is_binary_string(obj): 115 """Return True if `obj` is a binary string, False if it is anything else""" 116 if PY2: 117 # Python 2 118 return isinstance(obj, str) 119 else: 120 # Python 3 121 return isinstance(obj, bytes) 122 123 124def is_string(obj): 125 """Return True if `obj` is a text or binary Python string object, 126 False if it is anything else, like a QString (Python 2, PyQt API #1)""" 127 return is_text_string(obj) or is_binary_string(obj) 128 129 130def is_unicode(obj): 131 """Return True if `obj` is unicode""" 132 if PY2: 133 # Python 2 134 return isinstance(obj, unicode) 135 else: 136 # Python 3 137 return isinstance(obj, str) 138 139 140def to_text_string(obj, encoding=None): 141 """Convert `obj` to (unicode) text string""" 142 if PY2: 143 # Python 2 144 if encoding is None: 145 return unicode(obj) 146 else: 147 return unicode(obj, encoding) 148 else: 149 # Python 3 150 if encoding is None: 151 return str(obj) 152 elif isinstance(obj, str): 153 # In case this function is not used properly, this could happen 154 return obj 155 else: 156 return str(obj, encoding) 157 158 159def to_binary_string(obj, encoding=None): 160 """Convert `obj` to binary string (bytes in Python 3, str in Python 2)""" 161 if PY2: 162 # Python 2 163 if encoding is None: 164 return str(obj) 165 else: 166 return obj.encode(encoding) 167 else: 168 # Python 3 169 return bytes(obj, 'utf-8' if encoding is None else encoding) 170 171 172# ============================================================================= 173# Function attributes 174# ============================================================================= 175def get_func_code(func): 176 """Return function code object""" 177 if PY2: 178 # Python 2 179 return func.func_code 180 else: 181 # Python 3 182 return func.__code__ 183 184 185def get_func_name(func): 186 """Return function name""" 187 if PY2: 188 # Python 2 189 return func.func_name 190 else: 191 # Python 3 192 return func.__name__ 193 194 195def get_func_defaults(func): 196 """Return function default argument values""" 197 if PY2: 198 # Python 2 199 return func.func_defaults 200 else: 201 # Python 3 202 return func.__defaults__ 203 204 205# ============================================================================= 206# Special method attributes 207# ============================================================================= 208def get_meth_func(obj): 209 """Return method function object""" 210 if PY2: 211 # Python 2 212 return obj.im_func 213 else: 214 # Python 3 215 return obj.__func__ 216 217 218def get_meth_class_inst(obj): 219 """Return method class instance""" 220 if PY2: 221 # Python 2 222 return obj.im_self 223 else: 224 # Python 3 225 return obj.__self__ 226 227 228def get_meth_class(obj): 229 """Return method class""" 230 if PY2: 231 # Python 2 232 return obj.im_class 233 else: 234 # Python 3 235 return obj.__self__.__class__ 236 237 238# ============================================================================= 239# Misc. 240# ============================================================================= 241if PY2: 242 # Python 2 243 input = raw_input 244 getcwd = os.getcwdu 245 cmp = cmp 246 import string 247 str_lower = string.lower 248 from itertools import izip_longest as zip_longest 249else: 250 # Python 3 251 input = input 252 getcwd = os.getcwd 253 254 def cmp(a, b): 255 return (a > b) - (a < b) 256 str_lower = str.lower 257 from itertools import zip_longest 258 259 260def qbytearray_to_str(qba): 261 """Convert QByteArray object to str in a way compatible with Python 2/3""" 262 return str(bytes(qba.toHex().data()).decode()) 263