--- /dev/null
+"""Compatibility helpers for the different Python versions."""
+
+import six
+import sys
+
+# Python 2.6 or older?
+PY26 = (sys.version_info < (2, 7))
+
+# Python 3.3 or newer?
+PY33 = (sys.version_info >= (3, 3))
+
+# Python 3.4 or newer?
+PY34 = sys.version_info >= (3, 4)
+
+# Python 3.5 or newer?
+PY35 = sys.version_info >= (3, 5)
+
+if six.PY3:
+ integer_types = (int,)
+ bytes_type = bytes
+ text_type = str
+ string_types = (bytes, str)
+ BYTES_TYPES = (bytes, bytearray, memoryview)
+else:
+ integer_types = (int, long,)
+ bytes_type = str
+ text_type = unicode
+ string_types = basestring
+ if PY26:
+ BYTES_TYPES = (str, bytearray, buffer)
+ else: # Python 2.7
+ BYTES_TYPES = (str, bytearray, memoryview, buffer)
+
+
+if six.PY3:
+ def reraise(tp, value, tb=None):
+ if value.__traceback__ is not tb:
+ raise value.with_traceback(tb)
+ raise value
+else:
+ exec("""def reraise(tp, value, tb=None): raise tp, value, tb""")
+
+
+def flatten_bytes(data):
+ """
+ Convert bytes-like objects (bytes, bytearray, memoryview, buffer) to
+ a bytes string.
+ """
+ if not isinstance(data, BYTES_TYPES):
+ raise TypeError('data argument must be byte-ish (%r)',
+ type(data))
+ if PY34:
+ # In Python 3.4, socket.send() and bytes.join() accept memoryview
+ # and bytearray
+ return data
+ if not data:
+ return b''
+ if six.PY2 and isinstance(data, (buffer, bytearray)):
+ return str(data)
+ elif not PY26 and isinstance(data, memoryview):
+ return data.tobytes()
+ else:
+ return data
+
+
+def flatten_list_bytes(data):
+ """Concatenate a sequence of bytes-like objects."""
+ data = map(flatten_bytes, data)
+ return b''.join(data)