1import sys
2
3try:  # Python 2
4    long = long
5    unicode = unicode
6    basestring = basestring
7except NameError:  # Python 3
8    long = int
9    unicode = str
10    basestring = str
11
12
13PY2 = sys.version_info[0] == 2
14PY35 = sys.version_info >= (3, 5)
15PY36 = sys.version_info >= (3, 6)
16PY38 = sys.version_info >= (3, 8)
17
18if not PY36:
19    from collections import OrderedDict
20else:
21    OrderedDict = dict
22
23WINDOWS = sys.platform == "win32"
24
25
26def decode(string, encodings=None):
27    if not PY2 and not isinstance(string, bytes):
28        return string
29
30    if PY2 and isinstance(string, unicode):
31        return string
32
33    encodings = encodings or ["utf-8", "latin1", "ascii"]
34
35    for encoding in encodings:
36        try:
37            return string.decode(encoding)
38        except (UnicodeEncodeError, UnicodeDecodeError):
39            pass
40
41    return string.decode(encodings[0], errors="ignore")
42
43
44def encode(string, encodings=None):
45    if not PY2 and isinstance(string, bytes):
46        return string
47
48    if PY2 and isinstance(string, str):
49        return string
50
51    encodings = encodings or ["utf-8", "latin1", "ascii"]
52
53    for encoding in encodings:
54        try:
55            return string.encode(encoding)
56        except (UnicodeEncodeError, UnicodeDecodeError):
57            pass
58
59    return string.encode(encodings[0], errors="ignore")
60
61
62def to_str(string):
63    if isinstance(string, str) or not isinstance(string, (unicode, bytes)):
64        return string
65
66    if PY2:
67        method = "encode"
68    else:
69        method = "decode"
70
71    encodings = ["utf-8", "latin1", "ascii"]
72
73    for encoding in encodings:
74        try:
75            return getattr(string, method)(encoding)
76        except (UnicodeEncodeError, UnicodeDecodeError):
77            pass
78
79    return getattr(string, method)(encodings[0], errors="ignore")
80