1# -*- coding: utf-8 -*-
2# flake8: noqa
3import marshal
4import sys
5
6PY2 = sys.version_info[0] == 2
7PYPY = hasattr(sys, "pypy_translation_info")
8_identity = lambda x: x
9
10if not PY2:
11    unichr = chr
12    range_type = range
13    text_type = str
14    string_types = (str,)
15    integer_types = (int,)
16
17    iterkeys = lambda d: iter(d.keys())
18    itervalues = lambda d: iter(d.values())
19    iteritems = lambda d: iter(d.items())
20
21    import pickle
22    from io import BytesIO, StringIO
23
24    NativeStringIO = StringIO
25
26    def reraise(tp, value, tb=None):
27        if value.__traceback__ is not tb:
28            raise value.with_traceback(tb)
29        raise value
30
31    ifilter = filter
32    imap = map
33    izip = zip
34    intern = sys.intern
35
36    implements_iterator = _identity
37    implements_to_string = _identity
38    encode_filename = _identity
39
40    marshal_dump = marshal.dump
41    marshal_load = marshal.load
42
43else:
44    unichr = unichr
45    text_type = unicode
46    range_type = xrange
47    string_types = (str, unicode)
48    integer_types = (int, long)
49
50    iterkeys = lambda d: d.iterkeys()
51    itervalues = lambda d: d.itervalues()
52    iteritems = lambda d: d.iteritems()
53
54    import cPickle as pickle
55    from cStringIO import StringIO as BytesIO, StringIO
56
57    NativeStringIO = BytesIO
58
59    exec("def reraise(tp, value, tb=None):\n raise tp, value, tb")
60
61    from itertools import imap, izip, ifilter
62
63    intern = intern
64
65    def implements_iterator(cls):
66        cls.next = cls.__next__
67        del cls.__next__
68        return cls
69
70    def implements_to_string(cls):
71        cls.__unicode__ = cls.__str__
72        cls.__str__ = lambda x: x.__unicode__().encode("utf-8")
73        return cls
74
75    def encode_filename(filename):
76        if isinstance(filename, unicode):
77            return filename.encode("utf-8")
78        return filename
79
80    def marshal_dump(code, f):
81        if isinstance(f, file):
82            marshal.dump(code, f)
83        else:
84            f.write(marshal.dumps(code))
85
86    def marshal_load(f):
87        if isinstance(f, file):
88            return marshal.load(f)
89        return marshal.loads(f.read())
90
91
92def with_metaclass(meta, *bases):
93    """Create a base class with a metaclass."""
94    # This requires a bit of explanation: the basic idea is to make a
95    # dummy metaclass for one level of class instantiation that replaces
96    # itself with the actual metaclass.
97    class metaclass(type):
98        def __new__(cls, name, this_bases, d):
99            return meta(name, bases, d)
100
101    return type.__new__(metaclass, "temporary_class", (), {})
102
103
104try:
105    from urllib.parse import quote_from_bytes as url_quote
106except ImportError:
107    from urllib import quote as url_quote
108
109
110try:
111    from collections import abc
112except ImportError:
113    import collections as abc
114
115
116try:
117    from os import fspath
118except ImportError:
119    try:
120        from pathlib import PurePath
121    except ImportError:
122        PurePath = None
123
124    def fspath(path):
125        if hasattr(path, "__fspath__"):
126            return path.__fspath__()
127
128        # Python 3.5 doesn't have __fspath__ yet, use str.
129        if PurePath is not None and isinstance(path, PurePath):
130            return str(path)
131
132        return path
133