Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/attr/_funcs.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 copy | |
4 | |
5 from ._compat import iteritems | |
6 from ._make import NOTHING, _obj_setattr, fields | |
7 from .exceptions import AttrsAttributeNotFoundError | |
8 | |
9 | |
10 def asdict( | |
11 inst, | |
12 recurse=True, | |
13 filter=None, | |
14 dict_factory=dict, | |
15 retain_collection_types=False, | |
16 value_serializer=None, | |
17 ): | |
18 """ | |
19 Return the ``attrs`` attribute values of *inst* as a dict. | |
20 | |
21 Optionally recurse into other ``attrs``-decorated classes. | |
22 | |
23 :param inst: Instance of an ``attrs``-decorated class. | |
24 :param bool recurse: Recurse into classes that are also | |
25 ``attrs``-decorated. | |
26 :param callable filter: A callable whose return code determines whether an | |
27 attribute or element is included (``True``) or dropped (``False``). Is | |
28 called with the `attr.Attribute` as the first argument and the | |
29 value as the second argument. | |
30 :param callable dict_factory: A callable to produce dictionaries from. For | |
31 example, to produce ordered dictionaries instead of normal Python | |
32 dictionaries, pass in ``collections.OrderedDict``. | |
33 :param bool retain_collection_types: Do not convert to ``list`` when | |
34 encountering an attribute whose type is ``tuple`` or ``set``. Only | |
35 meaningful if ``recurse`` is ``True``. | |
36 :param Optional[callable] value_serializer: A hook that is called for every | |
37 attribute or dict key/value. It receives the current instance, field | |
38 and value and must return the (updated) value. The hook is run *after* | |
39 the optional *filter* has been applied. | |
40 | |
41 :rtype: return type of *dict_factory* | |
42 | |
43 :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` | |
44 class. | |
45 | |
46 .. versionadded:: 16.0.0 *dict_factory* | |
47 .. versionadded:: 16.1.0 *retain_collection_types* | |
48 .. versionadded:: 20.3.0 *value_serializer* | |
49 """ | |
50 attrs = fields(inst.__class__) | |
51 rv = dict_factory() | |
52 for a in attrs: | |
53 v = getattr(inst, a.name) | |
54 if filter is not None and not filter(a, v): | |
55 continue | |
56 | |
57 if value_serializer is not None: | |
58 v = value_serializer(inst, a, v) | |
59 | |
60 if recurse is True: | |
61 if has(v.__class__): | |
62 rv[a.name] = asdict( | |
63 v, | |
64 True, | |
65 filter, | |
66 dict_factory, | |
67 retain_collection_types, | |
68 value_serializer, | |
69 ) | |
70 elif isinstance(v, (tuple, list, set, frozenset)): | |
71 cf = v.__class__ if retain_collection_types is True else list | |
72 rv[a.name] = cf( | |
73 [ | |
74 _asdict_anything( | |
75 i, | |
76 filter, | |
77 dict_factory, | |
78 retain_collection_types, | |
79 value_serializer, | |
80 ) | |
81 for i in v | |
82 ] | |
83 ) | |
84 elif isinstance(v, dict): | |
85 df = dict_factory | |
86 rv[a.name] = df( | |
87 ( | |
88 _asdict_anything( | |
89 kk, | |
90 filter, | |
91 df, | |
92 retain_collection_types, | |
93 value_serializer, | |
94 ), | |
95 _asdict_anything( | |
96 vv, | |
97 filter, | |
98 df, | |
99 retain_collection_types, | |
100 value_serializer, | |
101 ), | |
102 ) | |
103 for kk, vv in iteritems(v) | |
104 ) | |
105 else: | |
106 rv[a.name] = v | |
107 else: | |
108 rv[a.name] = v | |
109 return rv | |
110 | |
111 | |
112 def _asdict_anything( | |
113 val, | |
114 filter, | |
115 dict_factory, | |
116 retain_collection_types, | |
117 value_serializer, | |
118 ): | |
119 """ | |
120 ``asdict`` only works on attrs instances, this works on anything. | |
121 """ | |
122 if getattr(val.__class__, "__attrs_attrs__", None) is not None: | |
123 # Attrs class. | |
124 rv = asdict( | |
125 val, | |
126 True, | |
127 filter, | |
128 dict_factory, | |
129 retain_collection_types, | |
130 value_serializer, | |
131 ) | |
132 elif isinstance(val, (tuple, list, set, frozenset)): | |
133 cf = val.__class__ if retain_collection_types is True else list | |
134 rv = cf( | |
135 [ | |
136 _asdict_anything( | |
137 i, | |
138 filter, | |
139 dict_factory, | |
140 retain_collection_types, | |
141 value_serializer, | |
142 ) | |
143 for i in val | |
144 ] | |
145 ) | |
146 elif isinstance(val, dict): | |
147 df = dict_factory | |
148 rv = df( | |
149 ( | |
150 _asdict_anything( | |
151 kk, filter, df, retain_collection_types, value_serializer | |
152 ), | |
153 _asdict_anything( | |
154 vv, filter, df, retain_collection_types, value_serializer | |
155 ), | |
156 ) | |
157 for kk, vv in iteritems(val) | |
158 ) | |
159 else: | |
160 rv = val | |
161 if value_serializer is not None: | |
162 rv = value_serializer(None, None, rv) | |
163 | |
164 return rv | |
165 | |
166 | |
167 def astuple( | |
168 inst, | |
169 recurse=True, | |
170 filter=None, | |
171 tuple_factory=tuple, | |
172 retain_collection_types=False, | |
173 ): | |
174 """ | |
175 Return the ``attrs`` attribute values of *inst* as a tuple. | |
176 | |
177 Optionally recurse into other ``attrs``-decorated classes. | |
178 | |
179 :param inst: Instance of an ``attrs``-decorated class. | |
180 :param bool recurse: Recurse into classes that are also | |
181 ``attrs``-decorated. | |
182 :param callable filter: A callable whose return code determines whether an | |
183 attribute or element is included (``True``) or dropped (``False``). Is | |
184 called with the `attr.Attribute` as the first argument and the | |
185 value as the second argument. | |
186 :param callable tuple_factory: A callable to produce tuples from. For | |
187 example, to produce lists instead of tuples. | |
188 :param bool retain_collection_types: Do not convert to ``list`` | |
189 or ``dict`` when encountering an attribute which type is | |
190 ``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is | |
191 ``True``. | |
192 | |
193 :rtype: return type of *tuple_factory* | |
194 | |
195 :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` | |
196 class. | |
197 | |
198 .. versionadded:: 16.2.0 | |
199 """ | |
200 attrs = fields(inst.__class__) | |
201 rv = [] | |
202 retain = retain_collection_types # Very long. :/ | |
203 for a in attrs: | |
204 v = getattr(inst, a.name) | |
205 if filter is not None and not filter(a, v): | |
206 continue | |
207 if recurse is True: | |
208 if has(v.__class__): | |
209 rv.append( | |
210 astuple( | |
211 v, | |
212 recurse=True, | |
213 filter=filter, | |
214 tuple_factory=tuple_factory, | |
215 retain_collection_types=retain, | |
216 ) | |
217 ) | |
218 elif isinstance(v, (tuple, list, set, frozenset)): | |
219 cf = v.__class__ if retain is True else list | |
220 rv.append( | |
221 cf( | |
222 [ | |
223 astuple( | |
224 j, | |
225 recurse=True, | |
226 filter=filter, | |
227 tuple_factory=tuple_factory, | |
228 retain_collection_types=retain, | |
229 ) | |
230 if has(j.__class__) | |
231 else j | |
232 for j in v | |
233 ] | |
234 ) | |
235 ) | |
236 elif isinstance(v, dict): | |
237 df = v.__class__ if retain is True else dict | |
238 rv.append( | |
239 df( | |
240 ( | |
241 astuple( | |
242 kk, | |
243 tuple_factory=tuple_factory, | |
244 retain_collection_types=retain, | |
245 ) | |
246 if has(kk.__class__) | |
247 else kk, | |
248 astuple( | |
249 vv, | |
250 tuple_factory=tuple_factory, | |
251 retain_collection_types=retain, | |
252 ) | |
253 if has(vv.__class__) | |
254 else vv, | |
255 ) | |
256 for kk, vv in iteritems(v) | |
257 ) | |
258 ) | |
259 else: | |
260 rv.append(v) | |
261 else: | |
262 rv.append(v) | |
263 | |
264 return rv if tuple_factory is list else tuple_factory(rv) | |
265 | |
266 | |
267 def has(cls): | |
268 """ | |
269 Check whether *cls* is a class with ``attrs`` attributes. | |
270 | |
271 :param type cls: Class to introspect. | |
272 :raise TypeError: If *cls* is not a class. | |
273 | |
274 :rtype: bool | |
275 """ | |
276 return getattr(cls, "__attrs_attrs__", None) is not None | |
277 | |
278 | |
279 def assoc(inst, **changes): | |
280 """ | |
281 Copy *inst* and apply *changes*. | |
282 | |
283 :param inst: Instance of a class with ``attrs`` attributes. | |
284 :param changes: Keyword changes in the new copy. | |
285 | |
286 :return: A copy of inst with *changes* incorporated. | |
287 | |
288 :raise attr.exceptions.AttrsAttributeNotFoundError: If *attr_name* couldn't | |
289 be found on *cls*. | |
290 :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` | |
291 class. | |
292 | |
293 .. deprecated:: 17.1.0 | |
294 Use `evolve` instead. | |
295 """ | |
296 import warnings | |
297 | |
298 warnings.warn( | |
299 "assoc is deprecated and will be removed after 2018/01.", | |
300 DeprecationWarning, | |
301 stacklevel=2, | |
302 ) | |
303 new = copy.copy(inst) | |
304 attrs = fields(inst.__class__) | |
305 for k, v in iteritems(changes): | |
306 a = getattr(attrs, k, NOTHING) | |
307 if a is NOTHING: | |
308 raise AttrsAttributeNotFoundError( | |
309 "{k} is not an attrs attribute on {cl}.".format( | |
310 k=k, cl=new.__class__ | |
311 ) | |
312 ) | |
313 _obj_setattr(new, k, v) | |
314 return new | |
315 | |
316 | |
317 def evolve(inst, **changes): | |
318 """ | |
319 Create a new instance, based on *inst* with *changes* applied. | |
320 | |
321 :param inst: Instance of a class with ``attrs`` attributes. | |
322 :param changes: Keyword changes in the new copy. | |
323 | |
324 :return: A copy of inst with *changes* incorporated. | |
325 | |
326 :raise TypeError: If *attr_name* couldn't be found in the class | |
327 ``__init__``. | |
328 :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` | |
329 class. | |
330 | |
331 .. versionadded:: 17.1.0 | |
332 """ | |
333 cls = inst.__class__ | |
334 attrs = fields(cls) | |
335 for a in attrs: | |
336 if not a.init: | |
337 continue | |
338 attr_name = a.name # To deal with private attributes. | |
339 init_name = attr_name if attr_name[0] != "_" else attr_name[1:] | |
340 if init_name not in changes: | |
341 changes[init_name] = getattr(inst, attr_name) | |
342 | |
343 return cls(**changes) | |
344 | |
345 | |
346 def resolve_types(cls, globalns=None, localns=None): | |
347 """ | |
348 Resolve any strings and forward annotations in type annotations. | |
349 | |
350 This is only required if you need concrete types in `Attribute`'s *type* | |
351 field. In other words, you don't need to resolve your types if you only | |
352 use them for static type checking. | |
353 | |
354 With no arguments, names will be looked up in the module in which the class | |
355 was created. If this is not what you want, e.g. if the name only exists | |
356 inside a method, you may pass *globalns* or *localns* to specify other | |
357 dictionaries in which to look up these names. See the docs of | |
358 `typing.get_type_hints` for more details. | |
359 | |
360 :param type cls: Class to resolve. | |
361 :param Optional[dict] globalns: Dictionary containing global variables. | |
362 :param Optional[dict] localns: Dictionary containing local variables. | |
363 | |
364 :raise TypeError: If *cls* is not a class. | |
365 :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` | |
366 class. | |
367 :raise NameError: If types cannot be resolved because of missing variables. | |
368 | |
369 :returns: *cls* so you can use this function also as a class decorator. | |
370 Please note that you have to apply it **after** `attr.s`. That means | |
371 the decorator has to come in the line **before** `attr.s`. | |
372 | |
373 .. versionadded:: 20.1.0 | |
374 """ | |
375 try: | |
376 # Since calling get_type_hints is expensive we cache whether we've | |
377 # done it already. | |
378 cls.__attrs_types_resolved__ | |
379 except AttributeError: | |
380 import typing | |
381 | |
382 hints = typing.get_type_hints(cls, globalns=globalns, localns=localns) | |
383 for field in fields(cls): | |
384 if field.name in hints: | |
385 # Since fields have been frozen we must work around it. | |
386 _obj_setattr(field, "type", hints[field.name]) | |
387 cls.__attrs_types_resolved__ = True | |
388 | |
389 # Return the class so you can use it as a decorator too. | |
390 return cls |