Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/attr/_funcs.py
7763 views
# SPDX-License-Identifier: MIT12from __future__ import absolute_import, division, print_function34import copy56from ._compat import iteritems7from ._make import NOTHING, _obj_setattr, fields8from .exceptions import AttrsAttributeNotFoundError91011def asdict(12inst,13recurse=True,14filter=None,15dict_factory=dict,16retain_collection_types=False,17value_serializer=None,18):19"""20Return the ``attrs`` attribute values of *inst* as a dict.2122Optionally recurse into other ``attrs``-decorated classes.2324:param inst: Instance of an ``attrs``-decorated class.25:param bool recurse: Recurse into classes that are also26``attrs``-decorated.27:param callable filter: A callable whose return code determines whether an28attribute or element is included (``True``) or dropped (``False``). Is29called with the `attrs.Attribute` as the first argument and the30value as the second argument.31:param callable dict_factory: A callable to produce dictionaries from. For32example, to produce ordered dictionaries instead of normal Python33dictionaries, pass in ``collections.OrderedDict``.34:param bool retain_collection_types: Do not convert to ``list`` when35encountering an attribute whose type is ``tuple`` or ``set``. Only36meaningful if ``recurse`` is ``True``.37:param Optional[callable] value_serializer: A hook that is called for every38attribute or dict key/value. It receives the current instance, field39and value and must return the (updated) value. The hook is run *after*40the optional *filter* has been applied.4142:rtype: return type of *dict_factory*4344:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``45class.4647.. versionadded:: 16.0.0 *dict_factory*48.. versionadded:: 16.1.0 *retain_collection_types*49.. versionadded:: 20.3.0 *value_serializer*50.. versionadded:: 21.3.0 If a dict has a collection for a key, it is51serialized as a tuple.52"""53attrs = fields(inst.__class__)54rv = dict_factory()55for a in attrs:56v = getattr(inst, a.name)57if filter is not None and not filter(a, v):58continue5960if value_serializer is not None:61v = value_serializer(inst, a, v)6263if recurse is True:64if has(v.__class__):65rv[a.name] = asdict(66v,67recurse=True,68filter=filter,69dict_factory=dict_factory,70retain_collection_types=retain_collection_types,71value_serializer=value_serializer,72)73elif isinstance(v, (tuple, list, set, frozenset)):74cf = v.__class__ if retain_collection_types is True else list75rv[a.name] = cf(76[77_asdict_anything(78i,79is_key=False,80filter=filter,81dict_factory=dict_factory,82retain_collection_types=retain_collection_types,83value_serializer=value_serializer,84)85for i in v86]87)88elif isinstance(v, dict):89df = dict_factory90rv[a.name] = df(91(92_asdict_anything(93kk,94is_key=True,95filter=filter,96dict_factory=df,97retain_collection_types=retain_collection_types,98value_serializer=value_serializer,99),100_asdict_anything(101vv,102is_key=False,103filter=filter,104dict_factory=df,105retain_collection_types=retain_collection_types,106value_serializer=value_serializer,107),108)109for kk, vv in iteritems(v)110)111else:112rv[a.name] = v113else:114rv[a.name] = v115return rv116117118def _asdict_anything(119val,120is_key,121filter,122dict_factory,123retain_collection_types,124value_serializer,125):126"""127``asdict`` only works on attrs instances, this works on anything.128"""129if getattr(val.__class__, "__attrs_attrs__", None) is not None:130# Attrs class.131rv = asdict(132val,133recurse=True,134filter=filter,135dict_factory=dict_factory,136retain_collection_types=retain_collection_types,137value_serializer=value_serializer,138)139elif isinstance(val, (tuple, list, set, frozenset)):140if retain_collection_types is True:141cf = val.__class__142elif is_key:143cf = tuple144else:145cf = list146147rv = cf(148[149_asdict_anything(150i,151is_key=False,152filter=filter,153dict_factory=dict_factory,154retain_collection_types=retain_collection_types,155value_serializer=value_serializer,156)157for i in val158]159)160elif isinstance(val, dict):161df = dict_factory162rv = df(163(164_asdict_anything(165kk,166is_key=True,167filter=filter,168dict_factory=df,169retain_collection_types=retain_collection_types,170value_serializer=value_serializer,171),172_asdict_anything(173vv,174is_key=False,175filter=filter,176dict_factory=df,177retain_collection_types=retain_collection_types,178value_serializer=value_serializer,179),180)181for kk, vv in iteritems(val)182)183else:184rv = val185if value_serializer is not None:186rv = value_serializer(None, None, rv)187188return rv189190191def astuple(192inst,193recurse=True,194filter=None,195tuple_factory=tuple,196retain_collection_types=False,197):198"""199Return the ``attrs`` attribute values of *inst* as a tuple.200201Optionally recurse into other ``attrs``-decorated classes.202203:param inst: Instance of an ``attrs``-decorated class.204:param bool recurse: Recurse into classes that are also205``attrs``-decorated.206:param callable filter: A callable whose return code determines whether an207attribute or element is included (``True``) or dropped (``False``). Is208called with the `attrs.Attribute` as the first argument and the209value as the second argument.210:param callable tuple_factory: A callable to produce tuples from. For211example, to produce lists instead of tuples.212:param bool retain_collection_types: Do not convert to ``list``213or ``dict`` when encountering an attribute which type is214``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is215``True``.216217:rtype: return type of *tuple_factory*218219:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``220class.221222.. versionadded:: 16.2.0223"""224attrs = fields(inst.__class__)225rv = []226retain = retain_collection_types # Very long. :/227for a in attrs:228v = getattr(inst, a.name)229if filter is not None and not filter(a, v):230continue231if recurse is True:232if has(v.__class__):233rv.append(234astuple(235v,236recurse=True,237filter=filter,238tuple_factory=tuple_factory,239retain_collection_types=retain,240)241)242elif isinstance(v, (tuple, list, set, frozenset)):243cf = v.__class__ if retain is True else list244rv.append(245cf(246[247astuple(248j,249recurse=True,250filter=filter,251tuple_factory=tuple_factory,252retain_collection_types=retain,253)254if has(j.__class__)255else j256for j in v257]258)259)260elif isinstance(v, dict):261df = v.__class__ if retain is True else dict262rv.append(263df(264(265astuple(266kk,267tuple_factory=tuple_factory,268retain_collection_types=retain,269)270if has(kk.__class__)271else kk,272astuple(273vv,274tuple_factory=tuple_factory,275retain_collection_types=retain,276)277if has(vv.__class__)278else vv,279)280for kk, vv in iteritems(v)281)282)283else:284rv.append(v)285else:286rv.append(v)287288return rv if tuple_factory is list else tuple_factory(rv)289290291def has(cls):292"""293Check whether *cls* is a class with ``attrs`` attributes.294295:param type cls: Class to introspect.296:raise TypeError: If *cls* is not a class.297298:rtype: bool299"""300return getattr(cls, "__attrs_attrs__", None) is not None301302303def assoc(inst, **changes):304"""305Copy *inst* and apply *changes*.306307:param inst: Instance of a class with ``attrs`` attributes.308:param changes: Keyword changes in the new copy.309310:return: A copy of inst with *changes* incorporated.311312:raise attr.exceptions.AttrsAttributeNotFoundError: If *attr_name* couldn't313be found on *cls*.314:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``315class.316317.. deprecated:: 17.1.0318Use `attrs.evolve` instead if you can.319This function will not be removed du to the slightly different approach320compared to `attrs.evolve`.321"""322import warnings323324warnings.warn(325"assoc is deprecated and will be removed after 2018/01.",326DeprecationWarning,327stacklevel=2,328)329new = copy.copy(inst)330attrs = fields(inst.__class__)331for k, v in iteritems(changes):332a = getattr(attrs, k, NOTHING)333if a is NOTHING:334raise AttrsAttributeNotFoundError(335"{k} is not an attrs attribute on {cl}.".format(336k=k, cl=new.__class__337)338)339_obj_setattr(new, k, v)340return new341342343def evolve(inst, **changes):344"""345Create a new instance, based on *inst* with *changes* applied.346347:param inst: Instance of a class with ``attrs`` attributes.348:param changes: Keyword changes in the new copy.349350:return: A copy of inst with *changes* incorporated.351352:raise TypeError: If *attr_name* couldn't be found in the class353``__init__``.354:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``355class.356357.. versionadded:: 17.1.0358"""359cls = inst.__class__360attrs = fields(cls)361for a in attrs:362if not a.init:363continue364attr_name = a.name # To deal with private attributes.365init_name = attr_name if attr_name[0] != "_" else attr_name[1:]366if init_name not in changes:367changes[init_name] = getattr(inst, attr_name)368369return cls(**changes)370371372def resolve_types(cls, globalns=None, localns=None, attribs=None):373"""374Resolve any strings and forward annotations in type annotations.375376This is only required if you need concrete types in `Attribute`'s *type*377field. In other words, you don't need to resolve your types if you only378use them for static type checking.379380With no arguments, names will be looked up in the module in which the class381was created. If this is not what you want, e.g. if the name only exists382inside a method, you may pass *globalns* or *localns* to specify other383dictionaries in which to look up these names. See the docs of384`typing.get_type_hints` for more details.385386:param type cls: Class to resolve.387:param Optional[dict] globalns: Dictionary containing global variables.388:param Optional[dict] localns: Dictionary containing local variables.389:param Optional[list] attribs: List of attribs for the given class.390This is necessary when calling from inside a ``field_transformer``391since *cls* is not an ``attrs`` class yet.392393:raise TypeError: If *cls* is not a class.394:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``395class and you didn't pass any attribs.396:raise NameError: If types cannot be resolved because of missing variables.397398:returns: *cls* so you can use this function also as a class decorator.399Please note that you have to apply it **after** `attrs.define`. That400means the decorator has to come in the line **before** `attrs.define`.401402.. versionadded:: 20.1.0403.. versionadded:: 21.1.0 *attribs*404405"""406# Since calling get_type_hints is expensive we cache whether we've407# done it already.408if getattr(cls, "__attrs_types_resolved__", None) != cls:409import typing410411hints = typing.get_type_hints(cls, globalns=globalns, localns=localns)412for field in fields(cls) if attribs is None else attribs:413if field.name in hints:414# Since fields have been frozen we must work around it.415_obj_setattr(field, "type", hints[field.name])416# We store the class we resolved so that subclasses know they haven't417# been resolved.418cls.__attrs_types_resolved__ = cls419420# Return the class so you can use it as a decorator too.421return cls422423424