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 import ConfigParser as configparser 50 try: 51 import _winreg as winreg 52 except ImportError: 53 pass 54 from sys import maxint as maxsize 55 try: 56 import CStringIO as io 57 except ImportError: 58 import StringIO as io 59 try: 60 import cPickle as pickle 61 except ImportError: 62 import pickle 63 from UserDict import DictMixin as MutableMapping 64 import thread as _thread 65 import repr as reprlib 66else: 67 # Python 3 68 import builtins 69 import configparser 70 try: 71 import winreg 72 except ImportError: 73 pass 74 from sys import maxsize 75 import io 76 import pickle 77 if PY33: 78 from collections.abc import MutableMapping 79 else: 80 from collections import MutableMapping 81 import _thread 82 import reprlib 83 84 85# ============================================================================= 86# Strings 87# ============================================================================= 88if PY2: 89 # Python 2 90 import codecs 91 92 def u(obj): 93 """Make unicode object""" 94 return codecs.unicode_escape_decode(obj)[0] 95else: 96 # Python 3 97 def u(obj): 98 """Return string as it is""" 99 return obj 100 101 102def is_text_string(obj): 103 """Return True if `obj` is a text string, False if it is anything else, 104 like binary data (Python 3) or QString (Python 2, PyQt API #1)""" 105 if PY2: 106 # Python 2 107 return isinstance(obj, basestring) 108 else: 109 # Python 3 110 return isinstance(obj, str) 111 112 113def is_binary_string(obj): 114 """Return True if `obj` is a binary string, False if it is anything else""" 115 if PY2: 116 # Python 2 117 return isinstance(obj, str) 118 else: 119 # Python 3 120 return isinstance(obj, bytes) 121 122 123def is_string(obj): 124 """Return True if `obj` is a text or binary Python string object, 125 False if it is anything else, like a QString (Python 2, PyQt API #1)""" 126 return is_text_string(obj) or is_binary_string(obj) 127 128 129def is_unicode(obj): 130 """Return True if `obj` is unicode""" 131 if PY2: 132 # Python 2 133 return isinstance(obj, unicode) 134 else: 135 # Python 3 136 return isinstance(obj, str) 137 138 139def to_text_string(obj, encoding=None): 140 """Convert `obj` to (unicode) text string""" 141 if PY2: 142 # Python 2 143 if encoding is None: 144 return unicode(obj) 145 else: 146 return unicode(obj, encoding) 147 else: 148 # Python 3 149 if encoding is None: 150 return str(obj) 151 elif isinstance(obj, str): 152 # In case this function is not used properly, this could happen 153 return obj 154 else: 155 return str(obj, encoding) 156 157 158def to_binary_string(obj, encoding=None): 159 """Convert `obj` to binary string (bytes in Python 3, str in Python 2)""" 160 if PY2: 161 # Python 2 162 if encoding is None: 163 return str(obj) 164 else: 165 return obj.encode(encoding) 166 else: 167 # Python 3 168 return bytes(obj, 'utf-8' if encoding is None else encoding) 169 170 171# ============================================================================= 172# Function attributes 173# ============================================================================= 174def get_func_code(func): 175 """Return function code object""" 176 if PY2: 177 # Python 2 178 return func.func_code 179 else: 180 # Python 3 181 return func.__code__ 182 183 184def get_func_name(func): 185 """Return function name""" 186 if PY2: 187 # Python 2 188 return func.func_name 189 else: 190 # Python 3 191 return func.__name__ 192 193 194def get_func_defaults(func): 195 """Return function default argument values""" 196 if PY2: 197 # Python 2 198 return func.func_defaults 199 else: 200 # Python 3 201 return func.__defaults__ 202 203 204# ============================================================================= 205# Special method attributes 206# ============================================================================= 207def get_meth_func(obj): 208 """Return method function object""" 209 if PY2: 210 # Python 2 211 return obj.im_func 212 else: 213 # Python 3 214 return obj.__func__ 215 216 217def get_meth_class_inst(obj): 218 """Return method class instance""" 219 if PY2: 220 # Python 2 221 return obj.im_self 222 else: 223 # Python 3 224 return obj.__self__ 225 226 227def get_meth_class(obj): 228 """Return method class""" 229 if PY2: 230 # Python 2 231 return obj.im_class 232 else: 233 # Python 3 234 return obj.__self__.__class__ 235 236 237# ============================================================================= 238# Misc. 239# ============================================================================= 240if PY2: 241 # Python 2 242 input = raw_input 243 getcwd = os.getcwdu 244 cmp = cmp 245 import string 246 str_lower = string.lower 247 from itertools import izip_longest as zip_longest 248else: 249 # Python 3 250 input = input 251 getcwd = os.getcwd 252 253 def cmp(a, b): 254 return (a > b) - (a < b) 255 str_lower = str.lower 256 from itertools import zip_longest 257 258 259def qbytearray_to_str(qba): 260 """Convert QByteArray object to str in a way compatible with Python 2/3""" 261 return str(bytes(qba.toHex().data()).decode()) 262