comparison env/lib/python3.9/site-packages/attr/_compat.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 from __future__ import absolute_import, division, print_function
2
3 import platform
4 import sys
5 import types
6 import warnings
7
8
9 PY2 = sys.version_info[0] == 2
10 PYPY = platform.python_implementation() == "PyPy"
11
12
13 if PYPY or sys.version_info[:2] >= (3, 6):
14 ordered_dict = dict
15 else:
16 from collections import OrderedDict
17
18 ordered_dict = OrderedDict
19
20
21 if PY2:
22 from collections import Mapping, Sequence
23
24 from UserDict import IterableUserDict
25
26 # We 'bundle' isclass instead of using inspect as importing inspect is
27 # fairly expensive (order of 10-15 ms for a modern machine in 2016)
28 def isclass(klass):
29 return isinstance(klass, (type, types.ClassType))
30
31 # TYPE is used in exceptions, repr(int) is different on Python 2 and 3.
32 TYPE = "type"
33
34 def iteritems(d):
35 return d.iteritems()
36
37 # Python 2 is bereft of a read-only dict proxy, so we make one!
38 class ReadOnlyDict(IterableUserDict):
39 """
40 Best-effort read-only dict wrapper.
41 """
42
43 def __setitem__(self, key, val):
44 # We gently pretend we're a Python 3 mappingproxy.
45 raise TypeError(
46 "'mappingproxy' object does not support item assignment"
47 )
48
49 def update(self, _):
50 # We gently pretend we're a Python 3 mappingproxy.
51 raise AttributeError(
52 "'mappingproxy' object has no attribute 'update'"
53 )
54
55 def __delitem__(self, _):
56 # We gently pretend we're a Python 3 mappingproxy.
57 raise TypeError(
58 "'mappingproxy' object does not support item deletion"
59 )
60
61 def clear(self):
62 # We gently pretend we're a Python 3 mappingproxy.
63 raise AttributeError(
64 "'mappingproxy' object has no attribute 'clear'"
65 )
66
67 def pop(self, key, default=None):
68 # We gently pretend we're a Python 3 mappingproxy.
69 raise AttributeError(
70 "'mappingproxy' object has no attribute 'pop'"
71 )
72
73 def popitem(self):
74 # We gently pretend we're a Python 3 mappingproxy.
75 raise AttributeError(
76 "'mappingproxy' object has no attribute 'popitem'"
77 )
78
79 def setdefault(self, key, default=None):
80 # We gently pretend we're a Python 3 mappingproxy.
81 raise AttributeError(
82 "'mappingproxy' object has no attribute 'setdefault'"
83 )
84
85 def __repr__(self):
86 # Override to be identical to the Python 3 version.
87 return "mappingproxy(" + repr(self.data) + ")"
88
89 def metadata_proxy(d):
90 res = ReadOnlyDict()
91 res.data.update(d) # We blocked update, so we have to do it like this.
92 return res
93
94 def just_warn(*args, **kw): # pragma: no cover
95 """
96 We only warn on Python 3 because we are not aware of any concrete
97 consequences of not setting the cell on Python 2.
98 """
99
100
101 else: # Python 3 and later.
102 from collections.abc import Mapping, Sequence # noqa
103
104 def just_warn(*args, **kw):
105 """
106 We only warn on Python 3 because we are not aware of any concrete
107 consequences of not setting the cell on Python 2.
108 """
109 warnings.warn(
110 "Running interpreter doesn't sufficiently support code object "
111 "introspection. Some features like bare super() or accessing "
112 "__class__ will not work with slotted classes.",
113 RuntimeWarning,
114 stacklevel=2,
115 )
116
117 def isclass(klass):
118 return isinstance(klass, type)
119
120 TYPE = "class"
121
122 def iteritems(d):
123 return d.items()
124
125 def metadata_proxy(d):
126 return types.MappingProxyType(dict(d))
127
128
129 def make_set_closure_cell():
130 """Return a function of two arguments (cell, value) which sets
131 the value stored in the closure cell `cell` to `value`.
132 """
133 # pypy makes this easy. (It also supports the logic below, but
134 # why not do the easy/fast thing?)
135 if PYPY:
136
137 def set_closure_cell(cell, value):
138 cell.__setstate__((value,))
139
140 return set_closure_cell
141
142 # Otherwise gotta do it the hard way.
143
144 # Create a function that will set its first cellvar to `value`.
145 def set_first_cellvar_to(value):
146 x = value
147 return
148
149 # This function will be eliminated as dead code, but
150 # not before its reference to `x` forces `x` to be
151 # represented as a closure cell rather than a local.
152 def force_x_to_be_a_cell(): # pragma: no cover
153 return x
154
155 try:
156 # Extract the code object and make sure our assumptions about
157 # the closure behavior are correct.
158 if PY2:
159 co = set_first_cellvar_to.func_code
160 else:
161 co = set_first_cellvar_to.__code__
162 if co.co_cellvars != ("x",) or co.co_freevars != ():
163 raise AssertionError # pragma: no cover
164
165 # Convert this code object to a code object that sets the
166 # function's first _freevar_ (not cellvar) to the argument.
167 if sys.version_info >= (3, 8):
168 # CPython 3.8+ has an incompatible CodeType signature
169 # (added a posonlyargcount argument) but also added
170 # CodeType.replace() to do this without counting parameters.
171 set_first_freevar_code = co.replace(
172 co_cellvars=co.co_freevars, co_freevars=co.co_cellvars
173 )
174 else:
175 args = [co.co_argcount]
176 if not PY2:
177 args.append(co.co_kwonlyargcount)
178 args.extend(
179 [
180 co.co_nlocals,
181 co.co_stacksize,
182 co.co_flags,
183 co.co_code,
184 co.co_consts,
185 co.co_names,
186 co.co_varnames,
187 co.co_filename,
188 co.co_name,
189 co.co_firstlineno,
190 co.co_lnotab,
191 # These two arguments are reversed:
192 co.co_cellvars,
193 co.co_freevars,
194 ]
195 )
196 set_first_freevar_code = types.CodeType(*args)
197
198 def set_closure_cell(cell, value):
199 # Create a function using the set_first_freevar_code,
200 # whose first closure cell is `cell`. Calling it will
201 # change the value of that cell.
202 setter = types.FunctionType(
203 set_first_freevar_code, {}, "setter", (), (cell,)
204 )
205 # And call it to set the cell.
206 setter(value)
207
208 # Make sure it works on this interpreter:
209 def make_func_with_cell():
210 x = None
211
212 def func():
213 return x # pragma: no cover
214
215 return func
216
217 if PY2:
218 cell = make_func_with_cell().func_closure[0]
219 else:
220 cell = make_func_with_cell().__closure__[0]
221 set_closure_cell(cell, 100)
222 if cell.cell_contents != 100:
223 raise AssertionError # pragma: no cover
224
225 except Exception:
226 return just_warn
227 else:
228 return set_closure_cell
229
230
231 set_closure_cell = make_set_closure_cell()