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