Mercurial > repos > shellac > sam_consensus_v3
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() |