1import sys 2 3 4PY3 = sys.version_info[0] >= 3 5 6if PY3: 7 text_type = basestring = str 8 iterbytes = iter 9else: # PY2 10 text_type = unicode 11 basestring = basestring 12 import itertools 13 import functools 14 iterbytes = functools.partial(itertools.imap, ord) 15 16 17def ensure_binary(s, encoding="ascii", errors="strict"): 18 if isinstance(s, text_type): 19 return s.encode(encoding, errors) 20 elif isinstance(s, bytes): 21 return s 22 else: 23 raise TypeError("not expecting type '%s'" % type(s)) 24 25 26def ensure_text(s, encoding="ascii", errors="strict"): 27 if isinstance(s, bytes): 28 return s.decode(encoding, errors) 29 elif isinstance(s, text_type): 30 return s 31 else: 32 raise TypeError("not expecting type '%s'" % type(s)) 33 34 35# for python 2 on Windows we need to wrap the io.open function in order 36# to be able to reopen the standard stdin/stout streams in binary mode. 37# By detault, they are opened in 'text' mode by the MSVC runtime, so 38# we need to call setmode with the O_BINARY flag. 39# In Python 3 the binary flag is always set (python itself takes care 40# of the newline translation of standard streams) 41if PY3: 42 open = open 43else: 44 import io 45 try: 46 from msvcrt import setmode # only available on Windows 47 except ImportError: 48 # on non-Windows platforms we can use the regular io.open 49 open = io.open 50 else: 51 import os 52 53 def open(file, mode='r', buffering=-1, encoding=None, errors=None, 54 newline=None, closefd=True): 55 if isinstance(file, int): 56 # the 'file' argument is an integer file descriptor 57 fd = file 58 if fd < 0: 59 raise ValueError('negative file descriptor') 60 if setmode: 61 # `setmode` function sets the line-end translation and 62 # returns the value of the previous mode 63 fdcopy = os.dup(fd) 64 current_mode = setmode(fdcopy, os.O_BINARY) 65 if not (current_mode & os.O_BINARY): 66 # the binary mode was not set: use the copy 67 file = fdcopy 68 if closefd: 69 # close the original file descriptor 70 os.close(fd) 71 else: 72 # ensure the copy is closed when file is closed 73 closefd = True 74 else: 75 # original file already had binary flag, close copy 76 os.close(fdcopy) 77 78 return io.open( 79 file, mode, buffering, encoding, errors, newline, closefd) 80 81 82try: 83 from enum import IntEnum 84except ImportError: 85 from collections import OrderedDict, namedtuple 86 87 # make do without the real Enum type, python3 only... :( 88 def IntEnum(typename, field_names, start=1): 89 90 @property 91 def __members__(self): 92 return OrderedDict([(k, getattr(self, k)) 93 for k in self._fields]) 94 95 def __call__(self, value): 96 if value not in self: 97 raise ValueError("%s is not a valid %s" % (value, typename)) 98 return value 99 100 base = namedtuple(typename, field_names) 101 attributes = {"__members__": __members__, 102 "__call__": __call__} 103 klass = type(typename, (base,), attributes) 104 return klass._make(range(start, len(field_names) + start)) 105