# -*- coding: utf-8 -*-
# (c) 2009-2021 Martin Wendt and contributors; see WsgiDAV https://github.com/mar10/wsgidav
# Licensed under the MIT license:
# http://www.opensource.org/licenses/mit-license.php
"""
Tool functions to support Python 2 and 3.
Inspired by six https://pythonhosted.org/six/
TODO: since it is now based on six, we should remove this module eventually.
"""
# flake8: noqa
import sys
import six
from six import PY2, PY3, BytesIO
from six.moves import cStringIO as StringIO
from six.moves import input as console_input
from six.moves import queue, xrange
from six.moves.urllib.parse import quote, unquote, urlparse
# See #174: `collections_abc` would be part of six.moves, but only for
# six v1.13+ but we don't want to force users to update their system python's six
try:
import collections.abc as collections_abc # Python 3.3+
except ImportError:
import collections as collections_abc
__docformat__ = "reStructuredText"
_filesystemencoding = sys.getfilesystemencoding()
# String Abstractions
if PY2:
from base64 import decodestring as base64_decodebytes
from base64 import encodestring as base64_encodebytes
from cgi import escape as html_escape
def is_basestring(s):
"""Return True for any string type (for str/unicode on Py2 and bytes/str on Py3)."""
return isinstance(s, basestring)
def is_bytes(s):
"""Return True for bytestrings (for str on Py2 and bytes on Py3)."""
return isinstance(s, str)
def is_native(s):
"""Return True for native strings (for str on Py2 and Py3)."""
return isinstance(s, str)
def is_unicode(s):
"""Return True for unicode strings (for unicode on Py2 and str on Py3)."""
return isinstance(s, unicode)
def to_bytes(s, encoding="utf8"):
"""Convert unicode (text strings) to binary data (str on Py2 and bytes on Py3)."""
if type(s) is unicode:
s = s.encode(encoding)
elif type(s) is not str:
s = str(s)
return s
to_native = to_bytes
"""Convert data to native str type (bytestring on Py2 and unicode on Py3)."""
[docs] def to_unicode(s, encoding="utf8"):
"""Convert data to unicode text (unicode on Py2 and str on Py3)."""
if type(s) is not unicode:
s = unicode(s, encoding)
return s
else: # Python 3
from base64 import decodebytes as base64_decodebytes
from base64 import encodebytes as base64_encodebytes
from html import escape as html_escape
[docs] def is_basestring(s):
"""Return True for any string type (for str/unicode on Py2 and bytes/str on Py3)."""
return isinstance(s, (str, bytes))
[docs] def is_bytes(s):
"""Return True for bytestrings (for str on Py2 and bytes on Py3)."""
return isinstance(s, bytes)
[docs] def is_native(s):
"""Return True for native strings (for str on Py2 and Py3)."""
return isinstance(s, str)
[docs] def is_unicode(s):
"""Return True for unicode strings (for unicode on Py2 and str on Py3)."""
return isinstance(s, str)
[docs] def to_bytes(s, encoding="utf8"):
"""Convert a text string (unicode) to bytestring (str on Py2 and bytes on Py3)."""
if type(s) is not bytes:
s = bytes(s, encoding)
return s
[docs] def to_native(s, encoding="utf8"):
"""Convert data to native str type (bytestring on Py2 and unicode on Py3)."""
if type(s) is bytes:
s = str(s, encoding)
elif type(s) is not str:
s = str(s)
return s
to_unicode = to_native
"""Convert binary data to unicode (text strings) on Python 2 and 3."""
# Binary Strings
b_empty = to_bytes("")
b_slash = to_bytes("/")
# WSGI support
[docs]def unicode_to_wsgi(u):
"""Convert an environment variable to a WSGI 'bytes-as-unicode' string."""
# Taken from PEP3333; the server should already have performed this, when
# passing environ to the WSGI application
return u.encode(_filesystemencoding, "surrogateescape").decode("iso-8859-1")
[docs]def wsgi_to_bytes(s):
"""Convert a native string to a WSGI / HTTP compatible byte string."""
# Taken from PEP3333
return s.encode("iso-8859-1")