_compat.py
4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# -*- coding: utf-8 -*-
"""
flask._compat
~~~~~~~~~~~~~
Some py2/py3 compatibility support based on a stripped down
version of six so we don't have to depend on a specific version
of it.
:copyright: 2010 Pallets
:license: BSD-3-Clause
"""
import sys
PY2 = sys.version_info[0] == 2
_identity = lambda x: x
try: # Python 2
text_type = unicode
string_types = (str, unicode)
integer_types = (int, long)
except NameError: # Python 3
text_type = str
string_types = (str,)
integer_types = (int,)
if not PY2:
iterkeys = lambda d: iter(d.keys())
itervalues = lambda d: iter(d.values())
iteritems = lambda d: iter(d.items())
from inspect import getfullargspec as getargspec
from io import StringIO
import collections.abc as collections_abc
def reraise(tp, value, tb=None):
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
implements_to_string = _identity
else:
iterkeys = lambda d: d.iterkeys()
itervalues = lambda d: d.itervalues()
iteritems = lambda d: d.iteritems()
from inspect import getargspec
from cStringIO import StringIO
import collections as collections_abc
exec("def reraise(tp, value, tb=None):\n raise tp, value, tb")
def implements_to_string(cls):
cls.__unicode__ = cls.__str__
cls.__str__ = lambda x: x.__unicode__().encode("utf-8")
return cls
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# This requires a bit of explanation: the basic idea is to make a
# dummy metaclass for one level of class instantiation that replaces
# itself with the actual metaclass.
class metaclass(type):
def __new__(metacls, name, this_bases, d):
return meta(name, bases, d)
return type.__new__(metaclass, "temporary_class", (), {})
# Certain versions of pypy have a bug where clearing the exception stack
# breaks the __exit__ function in a very peculiar way. The second level of
# exception blocks is necessary because pypy seems to forget to check if an
# exception happened until the next bytecode instruction?
#
# Relevant PyPy bugfix commit:
# https://bitbucket.org/pypy/pypy/commits/77ecf91c635a287e88e60d8ddb0f4e9df4003301
# According to ronan on #pypy IRC, it is released in PyPy2 2.3 and later
# versions.
#
# Ubuntu 14.04 has PyPy 2.2.1, which does exhibit this bug.
BROKEN_PYPY_CTXMGR_EXIT = False
if hasattr(sys, "pypy_version_info"):
class _Mgr(object):
def __enter__(self):
return self
def __exit__(self, *args):
if hasattr(sys, "exc_clear"):
# Python 3 (PyPy3) doesn't have exc_clear
sys.exc_clear()
try:
try:
with _Mgr():
raise AssertionError()
except: # noqa: B001
# We intentionally use a bare except here. See the comment above
# regarding a pypy bug as to why.
raise
except TypeError:
BROKEN_PYPY_CTXMGR_EXIT = True
except AssertionError:
pass
try:
from os import fspath
except ImportError:
# Backwards compatibility as proposed in PEP 0519:
# https://www.python.org/dev/peps/pep-0519/#backwards-compatibility
def fspath(path):
return path.__fspath__() if hasattr(path, "__fspath__") else path
class _DeprecatedBool(object):
def __init__(self, name, version, value):
self.message = "'{}' is deprecated and will be removed in version {}.".format(
name, version
)
self.value = value
def _warn(self):
import warnings
warnings.warn(self.message, DeprecationWarning, stacklevel=2)
def __eq__(self, other):
self._warn()
return other == self.value
def __ne__(self, other):
self._warn()
return other != self.value
def __bool__(self):
self._warn()
return self.value
__nonzero__ = __bool__
json_available = _DeprecatedBool("flask.json_available", "2.0.0", True)