1""" 2A selection of cross-compatible functions for Python 2 and 3. 3 4This module exports useful functions for 2/3 compatible code: 5 6 * bind_method: binds functions to classes 7 * ``native_str_to_bytes`` and ``bytes_to_native_str`` 8 * ``native_str``: always equal to the native platform string object (because 9 this may be shadowed by imports from future.builtins) 10 * lists: lrange(), lmap(), lzip(), lfilter() 11 * iterable method compatibility: 12 - iteritems, iterkeys, itervalues 13 - viewitems, viewkeys, viewvalues 14 15 These use the original method if available, otherwise they use items, 16 keys, values. 17 18 * types: 19 20 * text_type: unicode in Python 2, str in Python 3 21 * string_types: basestring in Python 2, str in Python 3 22 * binary_type: str in Python 2, bytes in Python 3 23 * integer_types: (int, long) in Python 2, int in Python 3 24 * class_types: (type, types.ClassType) in Python 2, type in Python 3 25 26 * bchr(c): 27 Take an integer and make a 1-character byte string 28 * bord(c) 29 Take the result of indexing on a byte string and make an integer 30 * tobytes(s) 31 Take a text string, a byte string, or a sequence of characters taken 32 from a byte string, and make a byte string. 33 34 * raise_from() 35 * raise_with_traceback() 36 37This module also defines these decorators: 38 39 * ``python_2_unicode_compatible`` 40 * ``with_metaclass`` 41 * ``implements_iterator`` 42 43Some of the functions in this module come from the following sources: 44 45 * Jinja2 (BSD licensed: see 46 https://github.com/mitsuhiko/jinja2/blob/master/LICENSE) 47 * Pandas compatibility module pandas.compat 48 * six.py by Benjamin Peterson 49 * Django 50""" 51 52import types 53import sys 54import numbers 55import functools 56import copy 57import inspect 58 59 60PY3 = sys.version_info[0] >= 3 61PY34_PLUS = sys.version_info[0:2] >= (3, 4) 62PY35_PLUS = sys.version_info[0:2] >= (3, 5) 63PY36_PLUS = sys.version_info[0:2] >= (3, 6) 64PY2 = sys.version_info[0] == 2 65PY26 = sys.version_info[0:2] == (2, 6) 66PY27 = sys.version_info[0:2] == (2, 7) 67PYPY = hasattr(sys, 'pypy_translation_info') 68 69 70def python_2_unicode_compatible(cls): 71 """ 72 A decorator that defines __unicode__ and __str__ methods under Python 73 2. Under Python 3, this decorator is a no-op. 74 75 To support Python 2 and 3 with a single code base, define a __str__ 76 method returning unicode text and apply this decorator to the class, like 77 this:: 78 79 >>> from future.utils import python_2_unicode_compatible 80 81 >>> @python_2_unicode_compatible 82 ... class MyClass(object): 83 ... def __str__(self): 84 ... return u'Unicode string: \u5b54\u5b50' 85 86 >>> a = MyClass() 87 88 Then, after this import: 89 90 >>> from future.builtins import str 91 92 the following is ``True`` on both Python 3 and 2:: 93 94 >>> str(a) == a.encode('utf-8').decode('utf-8') 95 True 96 97 and, on a Unicode-enabled terminal with the right fonts, these both print the 98 Chinese characters for Confucius:: 99 100 >>> print(a) 101 >>> print(str(a)) 102 103 The implementation comes from django.utils.encoding. 104 """ 105 if not PY3: 106 cls.__unicode__ = cls.__str__ 107 cls.__str__ = lambda self: self.__unicode__().encode('utf-8') 108 return cls 109 110 111def with_metaclass(meta, *bases): 112 """ 113 Function from jinja2/_compat.py. License: BSD. 114 115 Use it like this:: 116 117 class BaseForm(object): 118 pass 119 120 class FormType(type): 121 pass 122 123 class Form(with_metaclass(FormType, BaseForm)): 124 pass 125 126 This requires a bit of explanation: the basic idea is to make a 127 dummy metaclass for one level of class instantiation that replaces 128 itself with the actual metaclass. Because of internal type checks 129 we also need to make sure that we downgrade the custom metaclass 130 for one level to something closer to type (that's why __call__ and 131 __init__ comes back from type etc.). 132 133 This has the advantage over six.with_metaclass of not introducing 134 dummy classes into the final MRO. 135 """ 136 class metaclass(meta): 137 __call__ = type.__call__ 138 __init__ = type.__init__ 139 def __new__(cls, name, this_bases, d): 140 if this_bases is None: 141 return type.__new__(cls, name, (), d) 142 return meta(name, bases, d) 143 return metaclass('temporary_class', None, {}) 144 145 146# Definitions from pandas.compat and six.py follow: 147if PY3: 148 def bchr(s): 149 return bytes([s]) 150 def bstr(s): 151 if isinstance(s, str): 152 return bytes(s, 'latin-1') 153 else: 154 return bytes(s) 155 def bord(s): 156 return s 157 158 string_types = str, 159 integer_types = int, 160 class_types = type, 161 text_type = str 162 binary_type = bytes 163 164else: 165 # Python 2 166 def bchr(s): 167 return chr(s) 168 def bstr(s): 169 return str(s) 170 def bord(s): 171 return ord(s) 172 173 string_types = basestring, 174 integer_types = (int, long) 175 class_types = (type, types.ClassType) 176 text_type = unicode 177 binary_type = str 178 179### 180 181if PY3: 182 def tobytes(s): 183 if isinstance(s, bytes): 184 return s 185 else: 186 if isinstance(s, str): 187 return s.encode('latin-1') 188 else: 189 return bytes(s) 190else: 191 # Python 2 192 def tobytes(s): 193 if isinstance(s, unicode): 194 return s.encode('latin-1') 195 else: 196 return ''.join(s) 197 198tobytes.__doc__ = """ 199 Encodes to latin-1 (where the first 256 chars are the same as 200 ASCII.) 201 """ 202 203if PY3: 204 def native_str_to_bytes(s, encoding='utf-8'): 205 return s.encode(encoding) 206 207 def bytes_to_native_str(b, encoding='utf-8'): 208 return b.decode(encoding) 209 210 def text_to_native_str(t, encoding=None): 211 return t 212else: 213 # Python 2 214 def native_str_to_bytes(s, encoding=None): 215 from future.types import newbytes # to avoid a circular import 216 return newbytes(s) 217 218 def bytes_to_native_str(b, encoding=None): 219 return native(b) 220 221 def text_to_native_str(t, encoding='ascii'): 222 """ 223 Use this to create a Py2 native string when "from __future__ import 224 unicode_literals" is in effect. 225 """ 226 return unicode(t).encode(encoding) 227 228native_str_to_bytes.__doc__ = """ 229 On Py3, returns an encoded string. 230 On Py2, returns a newbytes type, ignoring the ``encoding`` argument. 231 """ 232 233if PY3: 234 # list-producing versions of the major Python iterating functions 235 def lrange(*args, **kwargs): 236 return list(range(*args, **kwargs)) 237 238 def lzip(*args, **kwargs): 239 return list(zip(*args, **kwargs)) 240 241 def lmap(*args, **kwargs): 242 return list(map(*args, **kwargs)) 243 244 def lfilter(*args, **kwargs): 245 return list(filter(*args, **kwargs)) 246else: 247 import __builtin__ 248 # Python 2-builtin ranges produce lists 249 lrange = __builtin__.range 250 lzip = __builtin__.zip 251 lmap = __builtin__.map 252 lfilter = __builtin__.filter 253 254 255def isidentifier(s, dotted=False): 256 ''' 257 A function equivalent to the str.isidentifier method on Py3 258 ''' 259 if dotted: 260 return all(isidentifier(a) for a in s.split('.')) 261 if PY3: 262 return s.isidentifier() 263 else: 264 import re 265 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") 266 return bool(_name_re.match(s)) 267 268 269def viewitems(obj, **kwargs): 270 """ 271 Function for iterating over dictionary items with the same set-like 272 behaviour on Py2.7 as on Py3. 273 274 Passes kwargs to method.""" 275 func = getattr(obj, "viewitems", None) 276 if not func: 277 func = obj.items 278 return func(**kwargs) 279 280 281def viewkeys(obj, **kwargs): 282 """ 283 Function for iterating over dictionary keys with the same set-like 284 behaviour on Py2.7 as on Py3. 285 286 Passes kwargs to method.""" 287 func = getattr(obj, "viewkeys", None) 288 if not func: 289 func = obj.keys 290 return func(**kwargs) 291 292 293def viewvalues(obj, **kwargs): 294 """ 295 Function for iterating over dictionary values with the same set-like 296 behaviour on Py2.7 as on Py3. 297 298 Passes kwargs to method.""" 299 func = getattr(obj, "viewvalues", None) 300 if not func: 301 func = obj.values 302 return func(**kwargs) 303 304 305def iteritems(obj, **kwargs): 306 """Use this only if compatibility with Python versions before 2.7 is 307 required. Otherwise, prefer viewitems(). 308 """ 309 func = getattr(obj, "iteritems", None) 310 if not func: 311 func = obj.items 312 return func(**kwargs) 313 314 315def iterkeys(obj, **kwargs): 316 """Use this only if compatibility with Python versions before 2.7 is 317 required. Otherwise, prefer viewkeys(). 318 """ 319 func = getattr(obj, "iterkeys", None) 320 if not func: 321 func = obj.keys 322 return func(**kwargs) 323 324 325def itervalues(obj, **kwargs): 326 """Use this only if compatibility with Python versions before 2.7 is 327 required. Otherwise, prefer viewvalues(). 328 """ 329 func = getattr(obj, "itervalues", None) 330 if not func: 331 func = obj.values 332 return func(**kwargs) 333 334 335def bind_method(cls, name, func): 336 """Bind a method to class, python 2 and python 3 compatible. 337 338 Parameters 339 ---------- 340 341 cls : type 342 class to receive bound method 343 name : basestring 344 name of method on class instance 345 func : function 346 function to be bound as method 347 348 Returns 349 ------- 350 None 351 """ 352 # only python 2 has an issue with bound/unbound methods 353 if not PY3: 354 setattr(cls, name, types.MethodType(func, None, cls)) 355 else: 356 setattr(cls, name, func) 357 358 359def getexception(): 360 return sys.exc_info()[1] 361 362 363def _get_caller_globals_and_locals(): 364 """ 365 Returns the globals and locals of the calling frame. 366 367 Is there an alternative to frame hacking here? 368 """ 369 caller_frame = inspect.stack()[2] 370 myglobals = caller_frame[0].f_globals 371 mylocals = caller_frame[0].f_locals 372 return myglobals, mylocals 373 374 375def _repr_strip(mystring): 376 """ 377 Returns the string without any initial or final quotes. 378 """ 379 r = repr(mystring) 380 if r.startswith("'") and r.endswith("'"): 381 return r[1:-1] 382 else: 383 return r 384 385 386if PY3: 387 def raise_from(exc, cause): 388 """ 389 Equivalent to: 390 391 raise EXCEPTION from CAUSE 392 393 on Python 3. (See PEP 3134). 394 """ 395 myglobals, mylocals = _get_caller_globals_and_locals() 396 397 # We pass the exception and cause along with other globals 398 # when we exec(): 399 myglobals = myglobals.copy() 400 myglobals['__python_future_raise_from_exc'] = exc 401 myglobals['__python_future_raise_from_cause'] = cause 402 execstr = "raise __python_future_raise_from_exc from __python_future_raise_from_cause" 403 exec(execstr, myglobals, mylocals) 404 405 def raise_(tp, value=None, tb=None): 406 """ 407 A function that matches the Python 2.x ``raise`` statement. This 408 allows re-raising exceptions with the cls value and traceback on 409 Python 2 and 3. 410 """ 411 if isinstance(tp, BaseException): 412 # If the first object is an instance, the type of the exception 413 # is the class of the instance, the instance itself is the value, 414 # and the second object must be None. 415 if value is not None: 416 raise TypeError("instance exception may not have a separate value") 417 exc = tp 418 elif isinstance(tp, type) and not issubclass(tp, BaseException): 419 # If the first object is a class, it becomes the type of the 420 # exception. 421 raise TypeError("class must derive from BaseException, not %s" % tp.__name__) 422 else: 423 # The second object is used to determine the exception value: If it 424 # is an instance of the class, the instance becomes the exception 425 # value. If the second object is a tuple, it is used as the argument 426 # list for the class constructor; if it is None, an empty argument 427 # list is used, and any other object is treated as a single argument 428 # to the constructor. The instance so created by calling the 429 # constructor is used as the exception value. 430 if isinstance(value, tp): 431 exc = value 432 elif isinstance(value, tuple): 433 exc = tp(*value) 434 elif value is None: 435 exc = tp() 436 else: 437 exc = tp(value) 438 439 if exc.__traceback__ is not tb: 440 raise exc.with_traceback(tb) 441 raise exc 442 443 def raise_with_traceback(exc, traceback=Ellipsis): 444 if traceback == Ellipsis: 445 _, _, traceback = sys.exc_info() 446 raise exc.with_traceback(traceback) 447 448else: 449 def raise_from(exc, cause): 450 """ 451 Equivalent to: 452 453 raise EXCEPTION from CAUSE 454 455 on Python 3. (See PEP 3134). 456 """ 457 # Is either arg an exception class (e.g. IndexError) rather than 458 # instance (e.g. IndexError('my message here')? If so, pass the 459 # name of the class undisturbed through to "raise ... from ...". 460 if isinstance(exc, type) and issubclass(exc, Exception): 461 e = exc() 462 # exc = exc.__name__ 463 # execstr = "e = " + _repr_strip(exc) + "()" 464 # myglobals, mylocals = _get_caller_globals_and_locals() 465 # exec(execstr, myglobals, mylocals) 466 else: 467 e = exc 468 e.__suppress_context__ = False 469 if isinstance(cause, type) and issubclass(cause, Exception): 470 e.__cause__ = cause() 471 e.__cause__.__traceback__ = sys.exc_info()[2] 472 e.__suppress_context__ = True 473 elif cause is None: 474 e.__cause__ = None 475 e.__suppress_context__ = True 476 elif isinstance(cause, BaseException): 477 e.__cause__ = cause 478 object.__setattr__(e.__cause__, '__traceback__', sys.exc_info()[2]) 479 e.__suppress_context__ = True 480 else: 481 raise TypeError("exception causes must derive from BaseException") 482 e.__context__ = sys.exc_info()[1] 483 raise e 484 485 exec(''' 486def raise_(tp, value=None, tb=None): 487 raise tp, value, tb 488 489def raise_with_traceback(exc, traceback=Ellipsis): 490 if traceback == Ellipsis: 491 _, _, traceback = sys.exc_info() 492 raise exc, None, traceback 493'''.strip()) 494 495 496raise_with_traceback.__doc__ = ( 497"""Raise exception with existing traceback. 498If traceback is not passed, uses sys.exc_info() to get traceback.""" 499) 500 501 502# Deprecated alias for backward compatibility with ``future`` versions < 0.11: 503reraise = raise_ 504 505 506def implements_iterator(cls): 507 ''' 508 From jinja2/_compat.py. License: BSD. 509 510 Use as a decorator like this:: 511 512 @implements_iterator 513 class UppercasingIterator(object): 514 def __init__(self, iterable): 515 self._iter = iter(iterable) 516 def __iter__(self): 517 return self 518 def __next__(self): 519 return next(self._iter).upper() 520 521 ''' 522 if PY3: 523 return cls 524 else: 525 cls.next = cls.__next__ 526 del cls.__next__ 527 return cls 528 529if PY3: 530 get_next = lambda x: x.next 531else: 532 get_next = lambda x: x.__next__ 533 534 535def encode_filename(filename): 536 if PY3: 537 return filename 538 else: 539 if isinstance(filename, unicode): 540 return filename.encode('utf-8') 541 return filename 542 543 544def is_new_style(cls): 545 """ 546 Python 2.7 has both new-style and old-style classes. Old-style classes can 547 be pesky in some circumstances, such as when using inheritance. Use this 548 function to test for whether a class is new-style. (Python 3 only has 549 new-style classes.) 550 """ 551 return hasattr(cls, '__class__') and ('__dict__' in dir(cls) 552 or hasattr(cls, '__slots__')) 553 554# The native platform string and bytes types. Useful because ``str`` and 555# ``bytes`` are redefined on Py2 by ``from future.builtins import *``. 556native_str = str 557native_bytes = bytes 558 559 560def istext(obj): 561 """ 562 Deprecated. Use:: 563 >>> isinstance(obj, str) 564 after this import: 565 >>> from future.builtins import str 566 """ 567 return isinstance(obj, type(u'')) 568 569 570def isbytes(obj): 571 """ 572 Deprecated. Use:: 573 >>> isinstance(obj, bytes) 574 after this import: 575 >>> from future.builtins import bytes 576 """ 577 return isinstance(obj, type(b'')) 578 579 580def isnewbytes(obj): 581 """ 582 Equivalent to the result of ``type(obj) == type(newbytes)`` 583 in other words, it is REALLY a newbytes instance, not a Py2 native str 584 object? 585 586 Note that this does not cover subclasses of newbytes, and it is not 587 equivalent to ininstance(obj, newbytes) 588 """ 589 return type(obj).__name__ == 'newbytes' 590 591 592def isint(obj): 593 """ 594 Deprecated. Tests whether an object is a Py3 ``int`` or either a Py2 ``int`` or 595 ``long``. 596 597 Instead of using this function, you can use: 598 599 >>> from future.builtins import int 600 >>> isinstance(obj, int) 601 602 The following idiom is equivalent: 603 604 >>> from numbers import Integral 605 >>> isinstance(obj, Integral) 606 """ 607 608 return isinstance(obj, numbers.Integral) 609 610 611def native(obj): 612 """ 613 On Py3, this is a no-op: native(obj) -> obj 614 615 On Py2, returns the corresponding native Py2 types that are 616 superclasses for backported objects from Py3: 617 618 >>> from builtins import str, bytes, int 619 620 >>> native(str(u'ABC')) 621 u'ABC' 622 >>> type(native(str(u'ABC'))) 623 unicode 624 625 >>> native(bytes(b'ABC')) 626 b'ABC' 627 >>> type(native(bytes(b'ABC'))) 628 bytes 629 630 >>> native(int(10**20)) 631 100000000000000000000L 632 >>> type(native(int(10**20))) 633 long 634 635 Existing native types on Py2 will be returned unchanged: 636 637 >>> type(native(u'ABC')) 638 unicode 639 """ 640 if hasattr(obj, '__native__'): 641 return obj.__native__() 642 else: 643 return obj 644 645 646# Implementation of exec_ is from ``six``: 647if PY3: 648 import builtins 649 exec_ = getattr(builtins, "exec") 650else: 651 def exec_(code, globs=None, locs=None): 652 """Execute code in a namespace.""" 653 if globs is None: 654 frame = sys._getframe(1) 655 globs = frame.f_globals 656 if locs is None: 657 locs = frame.f_locals 658 del frame 659 elif locs is None: 660 locs = globs 661 exec("""exec code in globs, locs""") 662 663 664# Defined here for backward compatibility: 665def old_div(a, b): 666 """ 667 DEPRECATED: import ``old_div`` from ``past.utils`` instead. 668 669 Equivalent to ``a / b`` on Python 2 without ``from __future__ import 670 division``. 671 672 TODO: generalize this to other objects (like arrays etc.) 673 """ 674 if isinstance(a, numbers.Integral) and isinstance(b, numbers.Integral): 675 return a // b 676 else: 677 return a / b 678 679 680def as_native_str(encoding='utf-8'): 681 ''' 682 A decorator to turn a function or method call that returns text, i.e. 683 unicode, into one that returns a native platform str. 684 685 Use it as a decorator like this:: 686 687 from __future__ import unicode_literals 688 689 class MyClass(object): 690 @as_native_str(encoding='ascii') 691 def __repr__(self): 692 return next(self._iter).upper() 693 ''' 694 if PY3: 695 return lambda f: f 696 else: 697 def encoder(f): 698 @functools.wraps(f) 699 def wrapper(*args, **kwargs): 700 return f(*args, **kwargs).encode(encoding=encoding) 701 return wrapper 702 return encoder 703 704# listvalues and listitems definitions from Nick Coghlan's (withdrawn) 705# PEP 496: 706try: 707 dict.iteritems 708except AttributeError: 709 # Python 3 710 def listvalues(d): 711 return list(d.values()) 712 def listitems(d): 713 return list(d.items()) 714else: 715 # Python 2 716 def listvalues(d): 717 return d.values() 718 def listitems(d): 719 return d.items() 720 721if PY3: 722 def ensure_new_type(obj): 723 return obj 724else: 725 def ensure_new_type(obj): 726 from future.types.newbytes import newbytes 727 from future.types.newstr import newstr 728 from future.types.newint import newint 729 from future.types.newdict import newdict 730 731 native_type = type(native(obj)) 732 733 # Upcast only if the type is already a native (non-future) type 734 if issubclass(native_type, type(obj)): 735 # Upcast 736 if native_type == str: # i.e. Py2 8-bit str 737 return newbytes(obj) 738 elif native_type == unicode: 739 return newstr(obj) 740 elif native_type == int: 741 return newint(obj) 742 elif native_type == long: 743 return newint(obj) 744 elif native_type == dict: 745 return newdict(obj) 746 else: 747 return obj 748 else: 749 # Already a new type 750 assert type(obj) in [newbytes, newstr] 751 return obj 752 753 754__all__ = ['PY2', 'PY26', 'PY3', 'PYPY', 755 'as_native_str', 'binary_type', 'bind_method', 'bord', 'bstr', 756 'bytes_to_native_str', 'class_types', 'encode_filename', 757 'ensure_new_type', 'exec_', 'get_next', 'getexception', 758 'implements_iterator', 'integer_types', 'is_new_style', 'isbytes', 759 'isidentifier', 'isint', 'isnewbytes', 'istext', 'iteritems', 760 'iterkeys', 'itervalues', 'lfilter', 'listitems', 'listvalues', 761 'lmap', 'lrange', 'lzip', 'native', 'native_bytes', 'native_str', 762 'native_str_to_bytes', 'old_div', 763 'python_2_unicode_compatible', 'raise_', 764 'raise_with_traceback', 'reraise', 'string_types', 765 'text_to_native_str', 'text_type', 'tobytes', 'viewitems', 766 'viewkeys', 'viewvalues', 'with_metaclass' 767 ] 768