diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/python/attrs/attr | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/attrs/attr')
-rw-r--r-- | contrib/python/attrs/attr/__init__.py | 8 | ||||
-rw-r--r-- | contrib/python/attrs/attr/__init__.pyi | 188 | ||||
-rw-r--r-- | contrib/python/attrs/attr/_cmp.py | 304 | ||||
-rw-r--r-- | contrib/python/attrs/attr/_cmp.pyi | 28 | ||||
-rw-r--r-- | contrib/python/attrs/attr/_compat.py | 66 | ||||
-rw-r--r-- | contrib/python/attrs/attr/_funcs.py | 144 | ||||
-rw-r--r-- | contrib/python/attrs/attr/_make.py | 980 | ||||
-rw-r--r-- | contrib/python/attrs/attr/_next_gen.py | 12 | ||||
-rw-r--r-- | contrib/python/attrs/attr/_version_info.py | 170 | ||||
-rw-r--r-- | contrib/python/attrs/attr/_version_info.pyi | 18 | ||||
-rw-r--r-- | contrib/python/attrs/attr/converters.py | 54 | ||||
-rw-r--r-- | contrib/python/attrs/attr/converters.pyi | 6 | ||||
-rw-r--r-- | contrib/python/attrs/attr/exceptions.py | 2 | ||||
-rw-r--r-- | contrib/python/attrs/attr/exceptions.pyi | 2 | ||||
-rw-r--r-- | contrib/python/attrs/attr/filters.pyi | 6 | ||||
-rw-r--r-- | contrib/python/attrs/attr/setters.pyi | 10 | ||||
-rw-r--r-- | contrib/python/attrs/attr/validators.py | 216 | ||||
-rw-r--r-- | contrib/python/attrs/attr/validators.pyi | 22 |
18 files changed, 1118 insertions, 1118 deletions
diff --git a/contrib/python/attrs/attr/__init__.py b/contrib/python/attrs/attr/__init__.py index b1ce7fe248..c4db8e6f1e 100644 --- a/contrib/python/attrs/attr/__init__.py +++ b/contrib/python/attrs/attr/__init__.py @@ -5,7 +5,7 @@ import sys from functools import partial from . import converters, exceptions, filters, setters, validators -from ._cmp import cmp_using +from ._cmp import cmp_using from ._config import get_run_validators, set_run_validators from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types from ._make import ( @@ -19,10 +19,10 @@ from ._make import ( make_class, validate, ) -from ._version_info import VersionInfo +from ._version_info import VersionInfo -__version__ = "21.2.0" +__version__ = "21.2.0" __version_info__ = VersionInfo._from_version_string(__version__) __title__ = "attrs" @@ -53,7 +53,7 @@ __all__ = [ "attrib", "attributes", "attrs", - "cmp_using", + "cmp_using", "converters", "evolve", "exceptions", diff --git a/contrib/python/attrs/attr/__init__.pyi b/contrib/python/attrs/attr/__init__.pyi index 3503b073b4..78cffbddf6 100644 --- a/contrib/python/attrs/attr/__init__.pyi +++ b/contrib/python/attrs/attr/__init__.pyi @@ -1,12 +1,12 @@ -import sys - +import sys + from typing import ( Any, Callable, Dict, Generic, List, - Mapping, + Mapping, Optional, Sequence, Tuple, @@ -17,14 +17,14 @@ from typing import ( ) # `import X as X` is required to make these public -from . import converters as converters +from . import converters as converters from . import exceptions as exceptions from . import filters as filters from . import setters as setters from . import validators as validators -from ._version_info import VersionInfo - +from ._version_info import VersionInfo + __version__: str __version_info__: VersionInfo __title__: str @@ -39,7 +39,7 @@ __copyright__: str _T = TypeVar("_T") _C = TypeVar("_C", bound=type) -_EqOrderType = Union[bool, Callable[[Any], Any]] +_EqOrderType = Union[bool, Callable[[Any], Any]] _ValidatorType = Callable[[Any, Attribute[_T], _T], Any] _ConverterType = Callable[[Any], Any] _FilterType = Callable[[Attribute[_T], _T], bool] @@ -49,7 +49,7 @@ _OnSetAttrType = Callable[[Any, Attribute[Any], Any], Any] _OnSetAttrArgType = Union[ _OnSetAttrType, List[_OnSetAttrType], setters._NoOpType ] -_FieldTransformer = Callable[[type, List[Attribute[Any]]], List[Attribute[Any]]] +_FieldTransformer = Callable[[type, List[Attribute[Any]]], List[Attribute[Any]]] # FIXME: in reality, if multiple validators are passed they must be in a list # or tuple, but those are invariant and so would prevent subtypes of # _ValidatorType from working when passed in a list or tuple. @@ -62,54 +62,54 @@ NOTHING: object # NOTE: Factory lies about its return type to make this possible: # `x: List[int] # = Factory(list)` # Work around mypy issue #4554 in the common case by using an overload. -if sys.version_info >= (3, 8): - from typing import Literal - - @overload - def Factory(factory: Callable[[], _T]) -> _T: ... - @overload - def Factory( - factory: Callable[[Any], _T], - takes_self: Literal[True], - ) -> _T: ... - @overload - def Factory( - factory: Callable[[], _T], - takes_self: Literal[False], - ) -> _T: ... -else: - @overload - def Factory(factory: Callable[[], _T]) -> _T: ... - @overload - def Factory( - factory: Union[Callable[[Any], _T], Callable[[], _T]], - takes_self: bool = ..., - ) -> _T: ... - -# Static type inference support via __dataclass_transform__ implemented as per: -# https://github.com/microsoft/pyright/blob/1.1.135/specs/dataclass_transforms.md -# This annotation must be applied to all overloads of "define" and "attrs" -# -# NOTE: This is a typing construct and does not exist at runtime. Extensions -# wrapping attrs decorators should declare a separate __dataclass_transform__ -# signature in the extension module using the specification linked above to -# provide pyright support. -def __dataclass_transform__( - *, - eq_default: bool = True, - order_default: bool = False, - kw_only_default: bool = False, - field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()), -) -> Callable[[_T], _T]: ... - +if sys.version_info >= (3, 8): + from typing import Literal + + @overload + def Factory(factory: Callable[[], _T]) -> _T: ... + @overload + def Factory( + factory: Callable[[Any], _T], + takes_self: Literal[True], + ) -> _T: ... + @overload + def Factory( + factory: Callable[[], _T], + takes_self: Literal[False], + ) -> _T: ... +else: + @overload + def Factory(factory: Callable[[], _T]) -> _T: ... + @overload + def Factory( + factory: Union[Callable[[Any], _T], Callable[[], _T]], + takes_self: bool = ..., + ) -> _T: ... + +# Static type inference support via __dataclass_transform__ implemented as per: +# https://github.com/microsoft/pyright/blob/1.1.135/specs/dataclass_transforms.md +# This annotation must be applied to all overloads of "define" and "attrs" +# +# NOTE: This is a typing construct and does not exist at runtime. Extensions +# wrapping attrs decorators should declare a separate __dataclass_transform__ +# signature in the extension module using the specification linked above to +# provide pyright support. +def __dataclass_transform__( + *, + eq_default: bool = True, + order_default: bool = False, + kw_only_default: bool = False, + field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()), +) -> Callable[[_T], _T]: ... + class Attribute(Generic[_T]): name: str default: Optional[_T] validator: Optional[_ValidatorType[_T]] repr: _ReprArgType - cmp: _EqOrderType - eq: _EqOrderType - order: _EqOrderType + cmp: _EqOrderType + eq: _EqOrderType + order: _EqOrderType hash: Optional[bool] init: bool converter: Optional[_ConverterType] @@ -118,8 +118,8 @@ class Attribute(Generic[_T]): kw_only: bool on_setattr: _OnSetAttrType - def evolve(self, **changes: Any) -> "Attribute[Any]": ... - + def evolve(self, **changes: Any) -> "Attribute[Any]": ... + # NOTE: We had several choices for the annotation to use for type arg: # 1) Type[_T] # - Pros: Handles simple cases correctly @@ -149,7 +149,7 @@ def attrib( default: None = ..., validator: None = ..., repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., @@ -157,8 +157,8 @@ def attrib( converter: None = ..., factory: None = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> Any: ... @@ -169,7 +169,7 @@ def attrib( default: None = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., @@ -177,8 +177,8 @@ def attrib( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> _T: ... @@ -188,7 +188,7 @@ def attrib( default: _T, validator: Optional[_ValidatorArgType[_T]] = ..., repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., @@ -196,8 +196,8 @@ def attrib( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> _T: ... @@ -207,7 +207,7 @@ def attrib( default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., @@ -215,8 +215,8 @@ def attrib( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> Any: ... @overload @@ -250,8 +250,8 @@ def field( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> _T: ... @@ -268,8 +268,8 @@ def field( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> _T: ... @@ -286,18 +286,18 @@ def field( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> Any: ... @overload -@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) +@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) def attrs( maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., - cmp: Optional[_EqOrderType] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., @@ -308,22 +308,22 @@ def attrs( kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., auto_detect: bool = ..., - collect_by_mro: bool = ..., + collect_by_mro: bool = ..., getstate_setstate: Optional[bool] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., + field_transformer: Optional[_FieldTransformer] = ..., ) -> _C: ... @overload -@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) +@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) def attrs( maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., - cmp: Optional[_EqOrderType] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., @@ -334,16 +334,16 @@ def attrs( kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., auto_detect: bool = ..., - collect_by_mro: bool = ..., + collect_by_mro: bool = ..., getstate_setstate: Optional[bool] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., + field_transformer: Optional[_FieldTransformer] = ..., ) -> Callable[[_C], _C]: ... @overload -@__dataclass_transform__(field_descriptors=(attrib, field)) +@__dataclass_transform__(field_descriptors=(attrib, field)) def define( maybe_cls: _C, *, @@ -364,10 +364,10 @@ def define( auto_detect: bool = ..., getstate_setstate: Optional[bool] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., + field_transformer: Optional[_FieldTransformer] = ..., ) -> _C: ... @overload -@__dataclass_transform__(field_descriptors=(attrib, field)) +@__dataclass_transform__(field_descriptors=(attrib, field)) def define( maybe_cls: None = ..., *, @@ -388,7 +388,7 @@ def define( auto_detect: bool = ..., getstate_setstate: Optional[bool] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., + field_transformer: Optional[_FieldTransformer] = ..., ) -> Callable[[_C], _C]: ... mutable = define @@ -405,7 +405,7 @@ def resolve_types( cls: _C, globalns: Optional[Dict[str, Any]] = ..., localns: Optional[Dict[str, Any]] = ..., - attribs: Optional[List[Attribute[Any]]] = ..., + attribs: Optional[List[Attribute[Any]]] = ..., ) -> _C: ... # TODO: add support for returning a proper attrs class from the mypy plugin @@ -417,7 +417,7 @@ def make_class( bases: Tuple[type, ...] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., - cmp: Optional[_EqOrderType] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., @@ -428,11 +428,11 @@ def make_class( kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - collect_by_mro: bool = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., + collect_by_mro: bool = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., + field_transformer: Optional[_FieldTransformer] = ..., ) -> type: ... # _funcs -- @@ -448,7 +448,7 @@ def asdict( filter: Optional[_FilterType[Any]] = ..., dict_factory: Type[Mapping[Any, Any]] = ..., retain_collection_types: bool = ..., - value_serializer: Optional[Callable[[type, Attribute[Any], Any], Any]] = ..., + value_serializer: Optional[Callable[[type, Attribute[Any], Any], Any]] = ..., ) -> Dict[str, Any]: ... # TODO: add support for returning NamedTuple from the mypy plugin diff --git a/contrib/python/attrs/attr/_cmp.py b/contrib/python/attrs/attr/_cmp.py index b747b603f1..f7e59f2784 100644 --- a/contrib/python/attrs/attr/_cmp.py +++ b/contrib/python/attrs/attr/_cmp.py @@ -1,152 +1,152 @@ -from __future__ import absolute_import, division, print_function - -import functools - -from ._compat import new_class -from ._make import _make_ne - - -_operation_names = {"eq": "==", "lt": "<", "le": "<=", "gt": ">", "ge": ">="} - - -def cmp_using( - eq=None, - lt=None, - le=None, - gt=None, - ge=None, - require_same_type=True, - class_name="Comparable", -): - """ - Create a class that can be passed into `attr.ib`'s ``eq``, ``order``, and - ``cmp`` arguments to customize field comparison. - - The resulting class will have a full set of ordering methods if - at least one of ``{lt, le, gt, ge}`` and ``eq`` are provided. - - :param Optional[callable] eq: `callable` used to evaluate equality - of two objects. - :param Optional[callable] lt: `callable` used to evaluate whether - one object is less than another object. - :param Optional[callable] le: `callable` used to evaluate whether - one object is less than or equal to another object. - :param Optional[callable] gt: `callable` used to evaluate whether - one object is greater than another object. - :param Optional[callable] ge: `callable` used to evaluate whether - one object is greater than or equal to another object. - - :param bool require_same_type: When `True`, equality and ordering methods - will return `NotImplemented` if objects are not of the same type. - - :param Optional[str] class_name: Name of class. Defaults to 'Comparable'. - - See `comparison` for more details. - - .. versionadded:: 21.1.0 - """ - - body = { - "__slots__": ["value"], - "__init__": _make_init(), - "_requirements": [], - "_is_comparable_to": _is_comparable_to, - } - - # Add operations. - num_order_functions = 0 - has_eq_function = False - - if eq is not None: - has_eq_function = True - body["__eq__"] = _make_operator("eq", eq) - body["__ne__"] = _make_ne() - - if lt is not None: - num_order_functions += 1 - body["__lt__"] = _make_operator("lt", lt) - - if le is not None: - num_order_functions += 1 - body["__le__"] = _make_operator("le", le) - - if gt is not None: - num_order_functions += 1 - body["__gt__"] = _make_operator("gt", gt) - - if ge is not None: - num_order_functions += 1 - body["__ge__"] = _make_operator("ge", ge) - - type_ = new_class(class_name, (object,), {}, lambda ns: ns.update(body)) - - # Add same type requirement. - if require_same_type: - type_._requirements.append(_check_same_type) - - # Add total ordering if at least one operation was defined. - if 0 < num_order_functions < 4: - if not has_eq_function: - # functools.total_ordering requires __eq__ to be defined, - # so raise early error here to keep a nice stack. - raise ValueError( - "eq must be define is order to complete ordering from " - "lt, le, gt, ge." - ) - type_ = functools.total_ordering(type_) - - return type_ - - -def _make_init(): - """ - Create __init__ method. - """ - - def __init__(self, value): - """ - Initialize object with *value*. - """ - self.value = value - - return __init__ - - -def _make_operator(name, func): - """ - Create operator method. - """ - - def method(self, other): - if not self._is_comparable_to(other): - return NotImplemented - - result = func(self.value, other.value) - if result is NotImplemented: - return NotImplemented - - return result - - method.__name__ = "__%s__" % (name,) - method.__doc__ = "Return a %s b. Computed by attrs." % ( - _operation_names[name], - ) - - return method - - -def _is_comparable_to(self, other): - """ - Check whether `other` is comparable to `self`. - """ - for func in self._requirements: - if not func(self, other): - return False - return True - - -def _check_same_type(self, other): - """ - Return True if *self* and *other* are of the same type, False otherwise. - """ - return other.value.__class__ is self.value.__class__ +from __future__ import absolute_import, division, print_function + +import functools + +from ._compat import new_class +from ._make import _make_ne + + +_operation_names = {"eq": "==", "lt": "<", "le": "<=", "gt": ">", "ge": ">="} + + +def cmp_using( + eq=None, + lt=None, + le=None, + gt=None, + ge=None, + require_same_type=True, + class_name="Comparable", +): + """ + Create a class that can be passed into `attr.ib`'s ``eq``, ``order``, and + ``cmp`` arguments to customize field comparison. + + The resulting class will have a full set of ordering methods if + at least one of ``{lt, le, gt, ge}`` and ``eq`` are provided. + + :param Optional[callable] eq: `callable` used to evaluate equality + of two objects. + :param Optional[callable] lt: `callable` used to evaluate whether + one object is less than another object. + :param Optional[callable] le: `callable` used to evaluate whether + one object is less than or equal to another object. + :param Optional[callable] gt: `callable` used to evaluate whether + one object is greater than another object. + :param Optional[callable] ge: `callable` used to evaluate whether + one object is greater than or equal to another object. + + :param bool require_same_type: When `True`, equality and ordering methods + will return `NotImplemented` if objects are not of the same type. + + :param Optional[str] class_name: Name of class. Defaults to 'Comparable'. + + See `comparison` for more details. + + .. versionadded:: 21.1.0 + """ + + body = { + "__slots__": ["value"], + "__init__": _make_init(), + "_requirements": [], + "_is_comparable_to": _is_comparable_to, + } + + # Add operations. + num_order_functions = 0 + has_eq_function = False + + if eq is not None: + has_eq_function = True + body["__eq__"] = _make_operator("eq", eq) + body["__ne__"] = _make_ne() + + if lt is not None: + num_order_functions += 1 + body["__lt__"] = _make_operator("lt", lt) + + if le is not None: + num_order_functions += 1 + body["__le__"] = _make_operator("le", le) + + if gt is not None: + num_order_functions += 1 + body["__gt__"] = _make_operator("gt", gt) + + if ge is not None: + num_order_functions += 1 + body["__ge__"] = _make_operator("ge", ge) + + type_ = new_class(class_name, (object,), {}, lambda ns: ns.update(body)) + + # Add same type requirement. + if require_same_type: + type_._requirements.append(_check_same_type) + + # Add total ordering if at least one operation was defined. + if 0 < num_order_functions < 4: + if not has_eq_function: + # functools.total_ordering requires __eq__ to be defined, + # so raise early error here to keep a nice stack. + raise ValueError( + "eq must be define is order to complete ordering from " + "lt, le, gt, ge." + ) + type_ = functools.total_ordering(type_) + + return type_ + + +def _make_init(): + """ + Create __init__ method. + """ + + def __init__(self, value): + """ + Initialize object with *value*. + """ + self.value = value + + return __init__ + + +def _make_operator(name, func): + """ + Create operator method. + """ + + def method(self, other): + if not self._is_comparable_to(other): + return NotImplemented + + result = func(self.value, other.value) + if result is NotImplemented: + return NotImplemented + + return result + + method.__name__ = "__%s__" % (name,) + method.__doc__ = "Return a %s b. Computed by attrs." % ( + _operation_names[name], + ) + + return method + + +def _is_comparable_to(self, other): + """ + Check whether `other` is comparable to `self`. + """ + for func in self._requirements: + if not func(self, other): + return False + return True + + +def _check_same_type(self, other): + """ + Return True if *self* and *other* are of the same type, False otherwise. + """ + return other.value.__class__ is self.value.__class__ diff --git a/contrib/python/attrs/attr/_cmp.pyi b/contrib/python/attrs/attr/_cmp.pyi index 7093550f0f..ba1fe4edb2 100644 --- a/contrib/python/attrs/attr/_cmp.pyi +++ b/contrib/python/attrs/attr/_cmp.pyi @@ -1,14 +1,14 @@ -from typing import Type - -from . import _CompareWithType - - -def cmp_using( - eq: Optional[_CompareWithType], - lt: Optional[_CompareWithType], - le: Optional[_CompareWithType], - gt: Optional[_CompareWithType], - ge: Optional[_CompareWithType], - require_same_type: bool, - class_name: str, -) -> Type: ... +from typing import Type + +from . import _CompareWithType + + +def cmp_using( + eq: Optional[_CompareWithType], + lt: Optional[_CompareWithType], + le: Optional[_CompareWithType], + gt: Optional[_CompareWithType], + ge: Optional[_CompareWithType], + require_same_type: bool, + class_name: str, +) -> Type: ... diff --git a/contrib/python/attrs/attr/_compat.py b/contrib/python/attrs/attr/_compat.py index 6939f338da..fdcc36ff88 100644 --- a/contrib/python/attrs/attr/_compat.py +++ b/contrib/python/attrs/attr/_compat.py @@ -28,15 +28,15 @@ if PY2: def isclass(klass): return isinstance(klass, (type, types.ClassType)) - def new_class(name, bases, kwds, exec_body): - """ - A minimal stub of types.new_class that we need for make_class. - """ - ns = {} - exec_body(ns) - - return type(name, bases, ns) - + def new_class(name, bases, kwds, exec_body): + """ + A minimal stub of types.new_class that we need for make_class. + """ + ns = {} + exec_body(ns) + + return type(name, bases, ns) + # TYPE is used in exceptions, repr(int) is different on Python 2 and 3. TYPE = "type" @@ -100,29 +100,29 @@ if PY2: res.data.update(d) # We blocked update, so we have to do it like this. return res - def just_warn(*args, **kw): # pragma: no cover - """ - We only warn on Python 3 because we are not aware of any concrete - consequences of not setting the cell on Python 2. - """ - - -else: # Python 3 and later. - from collections.abc import Mapping, Sequence # noqa - - def just_warn(*args, **kw): - """ - We only warn on Python 3 because we are not aware of any concrete - consequences of not setting the cell on Python 2. - """ - warnings.warn( + def just_warn(*args, **kw): # pragma: no cover + """ + We only warn on Python 3 because we are not aware of any concrete + consequences of not setting the cell on Python 2. + """ + + +else: # Python 3 and later. + from collections.abc import Mapping, Sequence # noqa + + def just_warn(*args, **kw): + """ + We only warn on Python 3 because we are not aware of any concrete + consequences of not setting the cell on Python 2. + """ + warnings.warn( "Running interpreter doesn't sufficiently support code object " "introspection. Some features like bare super() or accessing " - "__class__ will not work with slotted classes.", - RuntimeWarning, - stacklevel=2, - ) - + "__class__ will not work with slotted classes.", + RuntimeWarning, + stacklevel=2, + ) + def isclass(klass): return isinstance(klass, type) @@ -131,8 +131,8 @@ else: # Python 3 and later. def iteritems(d): return d.items() - new_class = types.new_class - + new_class = types.new_class + def metadata_proxy(d): return types.MappingProxyType(dict(d)) @@ -143,7 +143,7 @@ def make_set_closure_cell(): """ # pypy makes this easy. (It also supports the logic below, but # why not do the easy/fast thing?) - if PYPY: + if PYPY: def set_closure_cell(cell, value): cell.__setstate__((value,)) diff --git a/contrib/python/attrs/attr/_funcs.py b/contrib/python/attrs/attr/_funcs.py index fda508c5c4..027072b7ed 100644 --- a/contrib/python/attrs/attr/_funcs.py +++ b/contrib/python/attrs/attr/_funcs.py @@ -13,7 +13,7 @@ def asdict( filter=None, dict_factory=dict, retain_collection_types=False, - value_serializer=None, + value_serializer=None, ): """ Return the ``attrs`` attribute values of *inst* as a dict. @@ -33,10 +33,10 @@ def asdict( :param bool retain_collection_types: Do not convert to ``list`` when encountering an attribute whose type is ``tuple`` or ``set``. Only meaningful if ``recurse`` is ``True``. - :param Optional[callable] value_serializer: A hook that is called for every - attribute or dict key/value. It receives the current instance, field - and value and must return the (updated) value. The hook is run *after* - the optional *filter* has been applied. + :param Optional[callable] value_serializer: A hook that is called for every + attribute or dict key/value. It receives the current instance, field + and value and must return the (updated) value. The hook is run *after* + the optional *filter* has been applied. :rtype: return type of *dict_factory* @@ -45,7 +45,7 @@ def asdict( .. versionadded:: 16.0.0 *dict_factory* .. versionadded:: 16.1.0 *retain_collection_types* - .. versionadded:: 20.3.0 *value_serializer* + .. versionadded:: 20.3.0 *value_serializer* """ attrs = fields(inst.__class__) rv = dict_factory() @@ -53,30 +53,30 @@ def asdict( v = getattr(inst, a.name) if filter is not None and not filter(a, v): continue - - if value_serializer is not None: - v = value_serializer(inst, a, v) - + + if value_serializer is not None: + v = value_serializer(inst, a, v) + if recurse is True: if has(v.__class__): rv[a.name] = asdict( - v, - True, - filter, - dict_factory, - retain_collection_types, - value_serializer, + v, + True, + filter, + dict_factory, + retain_collection_types, + value_serializer, ) - elif isinstance(v, (tuple, list, set, frozenset)): + elif isinstance(v, (tuple, list, set, frozenset)): cf = v.__class__ if retain_collection_types is True else list rv[a.name] = cf( [ _asdict_anything( - i, - filter, - dict_factory, - retain_collection_types, - value_serializer, + i, + filter, + dict_factory, + retain_collection_types, + value_serializer, ) for i in v ] @@ -86,18 +86,18 @@ def asdict( rv[a.name] = df( ( _asdict_anything( - kk, - filter, - df, - retain_collection_types, - value_serializer, + kk, + filter, + df, + retain_collection_types, + value_serializer, ), _asdict_anything( - vv, - filter, - df, - retain_collection_types, - value_serializer, + vv, + filter, + df, + retain_collection_types, + value_serializer, ), ) for kk, vv in iteritems(v) @@ -109,36 +109,36 @@ def asdict( return rv -def _asdict_anything( - val, - filter, - dict_factory, - retain_collection_types, - value_serializer, -): +def _asdict_anything( + val, + filter, + dict_factory, + retain_collection_types, + value_serializer, +): """ ``asdict`` only works on attrs instances, this works on anything. """ if getattr(val.__class__, "__attrs_attrs__", None) is not None: # Attrs class. - rv = asdict( - val, - True, - filter, - dict_factory, - retain_collection_types, - value_serializer, - ) - elif isinstance(val, (tuple, list, set, frozenset)): + rv = asdict( + val, + True, + filter, + dict_factory, + retain_collection_types, + value_serializer, + ) + elif isinstance(val, (tuple, list, set, frozenset)): cf = val.__class__ if retain_collection_types is True else list rv = cf( [ _asdict_anything( - i, - filter, - dict_factory, - retain_collection_types, - value_serializer, + i, + filter, + dict_factory, + retain_collection_types, + value_serializer, ) for i in val ] @@ -147,20 +147,20 @@ def _asdict_anything( df = dict_factory rv = df( ( - _asdict_anything( - kk, filter, df, retain_collection_types, value_serializer - ), - _asdict_anything( - vv, filter, df, retain_collection_types, value_serializer - ), + _asdict_anything( + kk, filter, df, retain_collection_types, value_serializer + ), + _asdict_anything( + vv, filter, df, retain_collection_types, value_serializer + ), ) for kk, vv in iteritems(val) ) else: rv = val - if value_serializer is not None: - rv = value_serializer(None, None, rv) - + if value_serializer is not None: + rv = value_serializer(None, None, rv) + return rv @@ -215,7 +215,7 @@ def astuple( retain_collection_types=retain, ) ) - elif isinstance(v, (tuple, list, set, frozenset)): + elif isinstance(v, (tuple, list, set, frozenset)): cf = v.__class__ if retain is True else list rv.append( cf( @@ -260,7 +260,7 @@ def astuple( rv.append(v) else: rv.append(v) - + return rv if tuple_factory is list else tuple_factory(rv) @@ -343,7 +343,7 @@ def evolve(inst, **changes): return cls(**changes) -def resolve_types(cls, globalns=None, localns=None, attribs=None): +def resolve_types(cls, globalns=None, localns=None, attribs=None): """ Resolve any strings and forward annotations in type annotations. @@ -360,13 +360,13 @@ def resolve_types(cls, globalns=None, localns=None, attribs=None): :param type cls: Class to resolve. :param Optional[dict] globalns: Dictionary containing global variables. :param Optional[dict] localns: Dictionary containing local variables. - :param Optional[list] attribs: List of attribs for the given class. - This is necessary when calling from inside a ``field_transformer`` - since *cls* is not an ``attrs`` class yet. + :param Optional[list] attribs: List of attribs for the given class. + This is necessary when calling from inside a ``field_transformer`` + since *cls* is not an ``attrs`` class yet. :raise TypeError: If *cls* is not a class. :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` - class and you didn't pass any attribs. + class and you didn't pass any attribs. :raise NameError: If types cannot be resolved because of missing variables. :returns: *cls* so you can use this function also as a class decorator. @@ -374,8 +374,8 @@ def resolve_types(cls, globalns=None, localns=None, attribs=None): the decorator has to come in the line **before** `attr.s`. .. versionadded:: 20.1.0 - .. versionadded:: 21.1.0 *attribs* - + .. versionadded:: 21.1.0 *attribs* + """ try: # Since calling get_type_hints is expensive we cache whether we've @@ -385,7 +385,7 @@ def resolve_types(cls, globalns=None, localns=None, attribs=None): import typing hints = typing.get_type_hints(cls, globalns=globalns, localns=localns) - for field in fields(cls) if attribs is None else attribs: + for field in fields(cls) if attribs is None else attribs: if field.name in hints: # Since fields have been frozen we must work around it. _obj_setattr(field, "type", hints[field.name]) diff --git a/contrib/python/attrs/attr/_make.py b/contrib/python/attrs/attr/_make.py index a1912b1233..067a25d3f9 100644 --- a/contrib/python/attrs/attr/_make.py +++ b/contrib/python/attrs/attr/_make.py @@ -1,7 +1,7 @@ from __future__ import absolute_import, division, print_function import copy -import inspect +import inspect import linecache import sys import threading @@ -13,11 +13,11 @@ from operator import itemgetter from . import _config, setters from ._compat import ( PY2, - PYPY, + PYPY, isclass, iteritems, metadata_proxy, - new_class, + new_class, ordered_dict, set_closure_cell, ) @@ -30,10 +30,10 @@ from .exceptions import ( ) -if not PY2: - import typing - - +if not PY2: + import typing + + # This is used at least twice, so cache it here. _obj_setattr = object.__setattr__ _init_converter_pat = "__attr_converter_%s" @@ -41,12 +41,12 @@ _init_factory_pat = "__attr_factory_{}" _tuple_property_pat = ( " {attr_name} = _attrs_property(_attrs_itemgetter({index}))" ) -_classvar_prefixes = ( - "typing.ClassVar", - "t.ClassVar", - "ClassVar", - "typing_extensions.ClassVar", -) +_classvar_prefixes = ( + "typing.ClassVar", + "t.ClassVar", + "ClassVar", + "typing_extensions.ClassVar", +) # we don't use a double-underscore prefix because that triggers # name mangling when trying to create a slot for the field # (when slots=True) @@ -63,8 +63,8 @@ class _Nothing(object): Sentinel class to indicate the lack of a value when ``None`` is ambiguous. ``_Nothing`` is a singleton. There is only ever one of it. - - .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False. + + .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False. """ _singleton = None @@ -77,13 +77,13 @@ class _Nothing(object): def __repr__(self): return "NOTHING" - def __bool__(self): - return False - - def __len__(self): - return 0 # __bool__ for Python 2 - + def __bool__(self): + return False + def __len__(self): + return 0 # __bool__ for Python 2 + + NOTHING = _Nothing() """ Sentinel to indicate the lack of a value when ``None`` is ambiguous. @@ -184,25 +184,25 @@ def attrib( as-is, i.e. it will be used directly *instead* of calling ``repr()`` (the default). :type repr: a `bool` or a `callable` to use a custom function. - - :param eq: If ``True`` (default), include this attribute in the + + :param eq: If ``True`` (default), include this attribute in the generated ``__eq__`` and ``__ne__`` methods that check two instances - for equality. To override how the attribute value is compared, - pass a ``callable`` that takes a single value and returns the value - to be compared. - :type eq: a `bool` or a `callable`. - - :param order: If ``True`` (default), include this attributes in the + for equality. To override how the attribute value is compared, + pass a ``callable`` that takes a single value and returns the value + to be compared. + :type eq: a `bool` or a `callable`. + + :param order: If ``True`` (default), include this attributes in the generated ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods. - To override how the attribute value is ordered, - pass a ``callable`` that takes a single value and returns the value - to be ordered. - :type order: a `bool` or a `callable`. - - :param cmp: Setting *cmp* is equivalent to setting *eq* and *order* to the - same value. Must not be mixed with *eq* or *order*. - :type cmp: a `bool` or a `callable`. - + To override how the attribute value is ordered, + pass a ``callable`` that takes a single value and returns the value + to be ordered. + :type order: a `bool` or a `callable`. + + :param cmp: Setting *cmp* is equivalent to setting *eq* and *order* to the + same value. Must not be mixed with *eq* or *order*. + :type cmp: a `bool` or a `callable`. + :param Optional[bool] hash: Include this attribute in the generated ``__hash__`` method. If ``None`` (default), mirror *eq*'s value. This is the correct behavior according the Python spec. Setting this value @@ -250,19 +250,19 @@ def attrib( .. versionadded:: 18.1.0 ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``. .. versionadded:: 18.2.0 *kw_only* - .. versionchanged:: 19.2.0 *convert* keyword argument removed. + .. versionchanged:: 19.2.0 *convert* keyword argument removed. .. versionchanged:: 19.2.0 *repr* also accepts a custom callable. .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. .. versionadded:: 19.2.0 *eq* and *order* .. versionadded:: 20.1.0 *on_setattr* - .. versionchanged:: 20.3.0 *kw_only* backported to Python 2 - .. versionchanged:: 21.1.0 - *eq*, *order*, and *cmp* also accept a custom callable - .. versionchanged:: 21.1.0 *cmp* undeprecated + .. versionchanged:: 20.3.0 *kw_only* backported to Python 2 + .. versionchanged:: 21.1.0 + *eq*, *order*, and *cmp* also accept a custom callable + .. versionchanged:: 21.1.0 *cmp* undeprecated """ - eq, eq_key, order, order_key = _determine_attrib_eq_order( - cmp, eq, order, True - ) + eq, eq_key, order, order_key = _determine_attrib_eq_order( + cmp, eq, order, True + ) if hash is not None and hash is not True and hash is not False: raise TypeError( @@ -304,43 +304,43 @@ def attrib( type=type, kw_only=kw_only, eq=eq, - eq_key=eq_key, + eq_key=eq_key, order=order, - order_key=order_key, + order_key=order_key, on_setattr=on_setattr, ) -def _compile_and_eval(script, globs, locs=None, filename=""): - """ - "Exec" the script with the given global (globs) and local (locs) variables. - """ - bytecode = compile(script, filename, "exec") - eval(bytecode, globs, locs) - - -def _make_method(name, script, filename, globs=None): - """ - Create the method with the script given and return the method object. - """ - locs = {} - if globs is None: - globs = {} - - _compile_and_eval(script, globs, locs, filename) - - # In order of debuggers like PDB being able to step through the code, - # we add a fake linecache entry. - linecache.cache[filename] = ( - len(script), - None, - script.splitlines(True), - filename, - ) - - return locs[name] - - +def _compile_and_eval(script, globs, locs=None, filename=""): + """ + "Exec" the script with the given global (globs) and local (locs) variables. + """ + bytecode = compile(script, filename, "exec") + eval(bytecode, globs, locs) + + +def _make_method(name, script, filename, globs=None): + """ + Create the method with the script given and return the method object. + """ + locs = {} + if globs is None: + globs = {} + + _compile_and_eval(script, globs, locs, filename) + + # In order of debuggers like PDB being able to step through the code, + # we add a fake linecache entry. + linecache.cache[filename] = ( + len(script), + None, + script.splitlines(True), + filename, + ) + + return locs[name] + + def _make_attr_tuple_class(cls_name, attr_names): """ Create a tuple subclass to hold `Attribute`s for an `attrs` class. @@ -364,7 +364,7 @@ def _make_attr_tuple_class(cls_name, attr_names): else: attr_class_template.append(" pass") globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property} - _compile_and_eval("\n".join(attr_class_template), globs) + _compile_and_eval("\n".join(attr_class_template), globs) return globs[attr_class_name] @@ -391,15 +391,15 @@ def _is_class_var(annot): annotations which would put attrs-based classes at a performance disadvantage compared to plain old classes. """ - annot = str(annot) - - # Annotation can be quoted. - if annot.startswith(("'", '"')) and annot.endswith(("'", '"')): - annot = annot[1:-1] - - return annot.startswith(_classvar_prefixes) + annot = str(annot) + # Annotation can be quoted. + if annot.startswith(("'", '"')) and annot.endswith(("'", '"')): + annot = annot[1:-1] + return annot.startswith(_classvar_prefixes) + + def _has_own_attribute(cls, attrib_name): """ Check whether *cls* defines *attrib_name* (and doesn't just inherit it). @@ -448,7 +448,7 @@ def _collect_base_attrs(cls, taken_attr_names): if a.inherited or a.name in taken_attr_names: continue - a = a.evolve(inherited=True) + a = a.evolve(inherited=True) base_attrs.append(a) base_attr_map[a.name] = base_cls @@ -486,7 +486,7 @@ def _collect_base_attrs_broken(cls, taken_attr_names): if a.name in taken_attr_names: continue - a = a.evolve(inherited=True) + a = a.evolve(inherited=True) taken_attr_names.add(a.name) base_attrs.append(a) base_attr_map[a.name] = base_cls @@ -494,9 +494,9 @@ def _collect_base_attrs_broken(cls, taken_attr_names): return base_attrs, base_attr_map -def _transform_attrs( - cls, these, auto_attribs, kw_only, collect_by_mro, field_transformer -): +def _transform_attrs( + cls, these, auto_attribs, kw_only, collect_by_mro, field_transformer +): """ Transform all `_CountingAttr`s on a class into `Attribute`s. @@ -528,7 +528,7 @@ def _transform_attrs( continue annot_names.add(attr_name) a = cd.get(attr_name, NOTHING) - + if not isinstance(a, _CountingAttr): if a is NOTHING: a = attrib() @@ -576,8 +576,8 @@ def _transform_attrs( AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names) if kw_only: - own_attrs = [a.evolve(kw_only=True) for a in own_attrs] - base_attrs = [a.evolve(kw_only=True) for a in base_attrs] + own_attrs = [a.evolve(kw_only=True) for a in own_attrs] + base_attrs = [a.evolve(kw_only=True) for a in base_attrs] attrs = AttrsClass(base_attrs + own_attrs) @@ -596,36 +596,36 @@ def _transform_attrs( if had_default is False and a.default is not NOTHING: had_default = True - if field_transformer is not None: - attrs = field_transformer(cls, attrs) + if field_transformer is not None: + attrs = field_transformer(cls, attrs) return _Attributes((attrs, base_attrs, base_attr_map)) -if PYPY: - - def _frozen_setattrs(self, name, value): - """ - Attached to frozen classes as __setattr__. - """ - if isinstance(self, BaseException) and name in ( - "__cause__", - "__context__", - ): - BaseException.__setattr__(self, name, value) - return - - raise FrozenInstanceError() - - -else: - - def _frozen_setattrs(self, name, value): - """ - Attached to frozen classes as __setattr__. - """ - raise FrozenInstanceError() - - +if PYPY: + + def _frozen_setattrs(self, name, value): + """ + Attached to frozen classes as __setattr__. + """ + if isinstance(self, BaseException) and name in ( + "__cause__", + "__context__", + ): + BaseException.__setattr__(self, name, value) + return + + raise FrozenInstanceError() + + +else: + + def _frozen_setattrs(self, name, value): + """ + Attached to frozen classes as __setattr__. + """ + raise FrozenInstanceError() + + def _frozen_delattrs(self, name): """ Attached to frozen classes as __delattr__. @@ -648,9 +648,9 @@ class _ClassBuilder(object): "_cls_dict", "_delete_attribs", "_frozen", - "_has_pre_init", + "_has_pre_init", "_has_post_init", - "_is_exc", + "_is_exc", "_on_setattr", "_slots", "_weakref_slot", @@ -669,19 +669,19 @@ class _ClassBuilder(object): auto_attribs, kw_only, cache_hash, - is_exc, + is_exc, collect_by_mro, on_setattr, has_custom_setattr, - field_transformer, + field_transformer, ): attrs, base_attrs, base_map = _transform_attrs( - cls, - these, - auto_attribs, - kw_only, - collect_by_mro, - field_transformer, + cls, + these, + auto_attribs, + kw_only, + collect_by_mro, + field_transformer, ) self._cls = cls @@ -694,10 +694,10 @@ class _ClassBuilder(object): self._frozen = frozen self._weakref_slot = weakref_slot self._cache_hash = cache_hash - self._has_pre_init = bool(getattr(cls, "__attrs_pre_init__", False)) + self._has_pre_init = bool(getattr(cls, "__attrs_pre_init__", False)) self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False)) self._delete_attribs = not bool(these) - self._is_exc = is_exc + self._is_exc = is_exc self._on_setattr = on_setattr self._has_custom_setattr = has_custom_setattr @@ -743,7 +743,7 @@ class _ClassBuilder(object): for name in self._attr_names: if ( name not in base_names - and getattr(cls, name, _sentinel) is not _sentinel + and getattr(cls, name, _sentinel) is not _sentinel ): try: delattr(cls, name) @@ -763,10 +763,10 @@ class _ClassBuilder(object): cls, "__attrs_own_setattr__", False ): cls.__attrs_own_setattr__ = False - + if not self._has_custom_setattr: cls.__setattr__ = object.__setattr__ - + return cls def _create_slots_class(self): @@ -796,22 +796,22 @@ class _ClassBuilder(object): cd["__setattr__"] = object.__setattr__ break - # Traverse the MRO to collect existing slots - # and check for an existing __weakref__. - existing_slots = dict() + # Traverse the MRO to collect existing slots + # and check for an existing __weakref__. + existing_slots = dict() weakref_inherited = False for base_cls in self._cls.__mro__[1:-1]: if base_cls.__dict__.get("__weakref__", None) is not None: weakref_inherited = True - existing_slots.update( - { - name: getattr(base_cls, name) - for name in getattr(base_cls, "__slots__", []) - } - ) - - base_names = set(self._base_names) - + existing_slots.update( + { + name: getattr(base_cls, name) + for name in getattr(base_cls, "__slots__", []) + } + ) + + base_names = set(self._base_names) + names = self._attr_names if ( self._weakref_slot @@ -824,17 +824,17 @@ class _ClassBuilder(object): # We only add the names of attributes that aren't inherited. # Setting __slots__ to inherited attributes wastes memory. slot_names = [name for name in names if name not in base_names] - # There are slots for attributes from current class - # that are defined in parent classes. - # As their descriptors may be overriden by a child class, - # we collect them here and update the class dict - reused_slots = { - slot: slot_descriptor - for slot, slot_descriptor in iteritems(existing_slots) - if slot in slot_names - } - slot_names = [name for name in slot_names if name not in reused_slots] - cd.update(reused_slots) + # There are slots for attributes from current class + # that are defined in parent classes. + # As their descriptors may be overriden by a child class, + # we collect them here and update the class dict + reused_slots = { + slot: slot_descriptor + for slot, slot_descriptor in iteritems(existing_slots) + if slot in slot_names + } + slot_names = [name for name in slot_names if name not in reused_slots] + cd.update(reused_slots) if self._cache_hash: slot_names.append(_hash_cache_field) cd["__slots__"] = tuple(slot_names) @@ -857,10 +857,10 @@ class _ClassBuilder(object): # Class- and staticmethods hide their functions inside. # These might need to be rewritten as well. closure_cells = getattr(item.__func__, "__closure__", None) - elif isinstance(item, property): - # Workaround for property `super()` shortcut (PY3-only). - # There is no universal way for other descriptors. - closure_cells = getattr(item.fget, "__closure__", None) + elif isinstance(item, property): + # Workaround for property `super()` shortcut (PY3-only). + # There is no universal way for other descriptors. + closure_cells = getattr(item.fget, "__closure__", None) else: closure_cells = getattr(item, "__closure__", None) @@ -951,41 +951,41 @@ class _ClassBuilder(object): _make_init( self._cls, self._attrs, - self._has_pre_init, + self._has_pre_init, self._has_post_init, self._frozen, self._slots, self._cache_hash, self._base_attr_map, - self._is_exc, + self._is_exc, self._on_setattr is not None and self._on_setattr is not setters.NO_OP, - attrs_init=False, - ) - ) - - return self - - def add_attrs_init(self): - self._cls_dict["__attrs_init__"] = self._add_method_dunders( - _make_init( - self._cls, - self._attrs, - self._has_pre_init, - self._has_post_init, - self._frozen, - self._slots, - self._cache_hash, - self._base_attr_map, - self._is_exc, - self._on_setattr is not None - and self._on_setattr is not setters.NO_OP, - attrs_init=True, + attrs_init=False, ) ) return self + def add_attrs_init(self): + self._cls_dict["__attrs_init__"] = self._add_method_dunders( + _make_init( + self._cls, + self._attrs, + self._has_pre_init, + self._has_post_init, + self._frozen, + self._slots, + self._cache_hash, + self._base_attr_map, + self._is_exc, + self._on_setattr is not None + and self._on_setattr is not setters.NO_OP, + attrs_init=True, + ) + ) + + return self + def add_eq(self): cd = self._cls_dict @@ -1074,7 +1074,7 @@ _CMP_DEPRECATION = ( ) -def _determine_attrs_eq_order(cmp, eq, order, default_eq): +def _determine_attrs_eq_order(cmp, eq, order, default_eq): """ Validate the combination of *cmp*, *eq*, and *order*. Derive the effective values of eq and order. If *eq* is None, set it to *default_eq*. @@ -1100,47 +1100,47 @@ def _determine_attrs_eq_order(cmp, eq, order, default_eq): return eq, order -def _determine_attrib_eq_order(cmp, eq, order, default_eq): - """ - Validate the combination of *cmp*, *eq*, and *order*. Derive the effective - values of eq and order. If *eq* is None, set it to *default_eq*. - """ - if cmp is not None and any((eq is not None, order is not None)): - raise ValueError("Don't mix `cmp` with `eq' and `order`.") - - def decide_callable_or_boolean(value): - """ - Decide whether a key function is used. - """ - if callable(value): - value, key = True, value - else: - key = None - return value, key - - # cmp takes precedence due to bw-compatibility. - if cmp is not None: - cmp, cmp_key = decide_callable_or_boolean(cmp) - return cmp, cmp_key, cmp, cmp_key - - # If left None, equality is set to the specified default and ordering - # mirrors equality. - if eq is None: - eq, eq_key = default_eq, None - else: - eq, eq_key = decide_callable_or_boolean(eq) - - if order is None: - order, order_key = eq, eq_key - else: - order, order_key = decide_callable_or_boolean(order) - - if eq is False and order is True: - raise ValueError("`order` can only be True if `eq` is True too.") - - return eq, eq_key, order, order_key - - +def _determine_attrib_eq_order(cmp, eq, order, default_eq): + """ + Validate the combination of *cmp*, *eq*, and *order*. Derive the effective + values of eq and order. If *eq* is None, set it to *default_eq*. + """ + if cmp is not None and any((eq is not None, order is not None)): + raise ValueError("Don't mix `cmp` with `eq' and `order`.") + + def decide_callable_or_boolean(value): + """ + Decide whether a key function is used. + """ + if callable(value): + value, key = True, value + else: + key = None + return value, key + + # cmp takes precedence due to bw-compatibility. + if cmp is not None: + cmp, cmp_key = decide_callable_or_boolean(cmp) + return cmp, cmp_key, cmp, cmp_key + + # If left None, equality is set to the specified default and ordering + # mirrors equality. + if eq is None: + eq, eq_key = default_eq, None + else: + eq, eq_key = decide_callable_or_boolean(eq) + + if order is None: + order, order_key = eq, eq_key + else: + order, order_key = decide_callable_or_boolean(order) + + if eq is False and order is True: + raise ValueError("`order` can only be True if `eq` is True too.") + + return eq, eq_key, order, order_key + + def _determine_whether_to_implement( cls, flag, auto_detect, dunders, default=True ): @@ -1184,14 +1184,14 @@ def attrs( auto_attribs=False, kw_only=False, cache_hash=False, - auto_exc=False, + auto_exc=False, eq=None, order=None, auto_detect=False, collect_by_mro=False, getstate_setstate=None, on_setattr=None, - field_transformer=None, + field_transformer=None, ): r""" A class decorator that adds `dunder @@ -1223,7 +1223,7 @@ def attrs( inherited from some base class). So for example by implementing ``__eq__`` on a class yourself, - ``attrs`` will deduce ``eq=False`` and will create *neither* + ``attrs`` will deduce ``eq=False`` and will create *neither* ``__eq__`` *nor* ``__ne__`` (but Python classes come with a sensible ``__ne__`` by default, so it *should* be enough to only implement ``__eq__`` in most cases). @@ -1256,8 +1256,8 @@ def attrs( ``__gt__``, and ``__ge__`` methods that behave like *eq* above and allow instances to be ordered. If ``None`` (default) mirror value of *eq*. - :param Optional[bool] cmp: Setting *cmp* is equivalent to setting *eq* - and *order* to the same value. Must not be mixed with *eq* or *order*. + :param Optional[bool] cmp: Setting *cmp* is equivalent to setting *eq* + and *order* to the same value. Must not be mixed with *eq* or *order*. :param Optional[bool] hash: If ``None`` (default), the ``__hash__`` method is generated according how *eq* and *frozen* are set. @@ -1278,28 +1278,28 @@ def attrs( behavior <https://github.com/python-attrs/attrs/issues/136>`_ for more details. :param bool init: Create a ``__init__`` method that initializes the - ``attrs`` attributes. Leading underscores are stripped for the argument - name. If a ``__attrs_pre_init__`` method exists on the class, it will - be called before the class is initialized. If a ``__attrs_post_init__`` - method exists on the class, it will be called after the class is fully - initialized. - - If ``init`` is ``False``, an ``__attrs_init__`` method will be - injected instead. This allows you to define a custom ``__init__`` - method that can do pre-init work such as ``super().__init__()``, - and then call ``__attrs_init__()`` and ``__attrs_post_init__()``. + ``attrs`` attributes. Leading underscores are stripped for the argument + name. If a ``__attrs_pre_init__`` method exists on the class, it will + be called before the class is initialized. If a ``__attrs_post_init__`` + method exists on the class, it will be called after the class is fully + initialized. + + If ``init`` is ``False``, an ``__attrs_init__`` method will be + injected instead. This allows you to define a custom ``__init__`` + method that can do pre-init work such as ``super().__init__()``, + and then call ``__attrs_init__()`` and ``__attrs_post_init__()``. :param bool slots: Create a `slotted class <slotted classes>` that's more - memory-efficient. Slotted classes are generally superior to the default - dict classes, but have some gotchas you should know about, so we - encourage you to read the `glossary entry <slotted classes>`. + memory-efficient. Slotted classes are generally superior to the default + dict classes, but have some gotchas you should know about, so we + encourage you to read the `glossary entry <slotted classes>`. :param bool frozen: Make instances immutable after initialization. If someone attempts to modify a frozen instance, `attr.exceptions.FrozenInstanceError` is raised. - .. note:: + .. note:: 1. This is achieved by installing a custom ``__setattr__`` method - on your class, so you can't implement your own. + on your class, so you can't implement your own. 2. True immutability is impossible in Python. @@ -1328,20 +1328,20 @@ def attrs( If you assign a value to those attributes (e.g. ``x: int = 42``), that value becomes the default value like if it were passed using ``attr.ib(default=42)``. Passing an instance of `Factory` also - works as expected in most cases (see warning below). + works as expected in most cases (see warning below). Attributes annotated as `typing.ClassVar`, and attributes that are neither annotated nor set to an `attr.ib` are **ignored**. - .. warning:: - For features that use the attribute name to create decorators (e.g. - `validators <validators>`), you still *must* assign `attr.ib` to - them. Otherwise Python will either not find the name or try to use - the default value to call e.g. ``validator`` on it. - - These errors can be quite confusing and probably the most common bug - report on our bug tracker. - + .. warning:: + For features that use the attribute name to create decorators (e.g. + `validators <validators>`), you still *must* assign `attr.ib` to + them. Otherwise Python will either not find the name or try to use + the default value to call e.g. ``validator`` on it. + + These errors can be quite confusing and probably the most common bug + report on our bug tracker. + .. _`PEP 526`: https://www.python.org/dev/peps/pep-0526/ :param bool kw_only: Make all attributes keyword-only (Python 3+) in the generated ``__init__`` (if ``init`` is ``False``, this @@ -1349,23 +1349,23 @@ def attrs( :param bool cache_hash: Ensure that the object's hash code is computed only once and stored on the object. If this is set to ``True``, hashing must be either explicitly or implicitly enabled for this - class. If the hash code is cached, avoid any reassignments of - fields involved in hash code computation or mutations of the objects - those fields point to after object creation. If such changes occur, - the behavior of the object's hash code is undefined. + class. If the hash code is cached, avoid any reassignments of + fields involved in hash code computation or mutations of the objects + those fields point to after object creation. If such changes occur, + the behavior of the object's hash code is undefined. :param bool auto_exc: If the class subclasses `BaseException` - (which implicitly includes any subclass of any exception), the - following happens to behave like a well-behaved Python exceptions - class: + (which implicitly includes any subclass of any exception), the + following happens to behave like a well-behaved Python exceptions + class: - the values for *eq*, *order*, and *hash* are ignored and the instances compare and hash by the instance's ids (N.B. ``attrs`` will *not* remove existing implementations of ``__hash__`` or the equality methods. It just won't add own ones.), - - all attributes that are either passed into ``__init__`` or have a - default value are additionally available as a tuple in the ``args`` - attribute, - - the value of *str* is ignored leaving ``__str__`` to base classes. + - all attributes that are either passed into ``__init__`` or have a + default value are additionally available as a tuple in the ``args`` + attribute, + - the value of *str* is ignored leaving ``__str__`` to base classes. :param bool collect_by_mro: Setting this to `True` fixes the way ``attrs`` collects attributes from base classes. The default behavior is incorrect in certain cases of multiple inheritance. It should be on by @@ -1391,7 +1391,7 @@ def attrs( :param on_setattr: A callable that is run whenever the user attempts to set an attribute (either by assignment like ``i.x = 42`` or by using - `setattr` like ``setattr(i, "x", 42)``). It receives the same arguments + `setattr` like ``setattr(i, "x", 42)``). It receives the same arguments as validators: the instance, the attribute that is being modified, and the new value. @@ -1401,11 +1401,11 @@ def attrs( If a list of callables is passed, they're automatically wrapped in an `attr.setters.pipe`. - :param Optional[callable] field_transformer: - A function that is called with the original class object and all - fields right before ``attrs`` finalizes the class. You can use - this, e.g., to automatically add converters or validators to - fields based on their types. See `transform-fields` for more details. + :param Optional[callable] field_transformer: + A function that is called with the original class object and all + fields right before ``attrs`` finalizes the class. You can use + this, e.g., to automatically add converters or validators to + fields based on their types. See `transform-fields` for more details. .. versionadded:: 16.0.0 *slots* .. versionadded:: 16.1.0 *frozen* @@ -1428,41 +1428,41 @@ def attrs( subclasses comparable anymore. .. versionadded:: 18.2.0 *kw_only* .. versionadded:: 18.2.0 *cache_hash* - .. versionadded:: 19.1.0 *auto_exc* + .. versionadded:: 19.1.0 *auto_exc* .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. .. versionadded:: 19.2.0 *eq* and *order* .. versionadded:: 20.1.0 *auto_detect* .. versionadded:: 20.1.0 *collect_by_mro* .. versionadded:: 20.1.0 *getstate_setstate* .. versionadded:: 20.1.0 *on_setattr* - .. versionadded:: 20.3.0 *field_transformer* - .. versionchanged:: 21.1.0 - ``init=False`` injects ``__attrs_init__`` - .. versionchanged:: 21.1.0 Support for ``__attrs_pre_init__`` - .. versionchanged:: 21.1.0 *cmp* undeprecated + .. versionadded:: 20.3.0 *field_transformer* + .. versionchanged:: 21.1.0 + ``init=False`` injects ``__attrs_init__`` + .. versionchanged:: 21.1.0 Support for ``__attrs_pre_init__`` + .. versionchanged:: 21.1.0 *cmp* undeprecated """ if auto_detect and PY2: raise PythonTooOldError( "auto_detect only works on Python 3 and later." ) - eq_, order_ = _determine_attrs_eq_order(cmp, eq, order, None) + eq_, order_ = _determine_attrs_eq_order(cmp, eq, order, None) hash_ = hash # work around the lack of nonlocal if isinstance(on_setattr, (list, tuple)): on_setattr = setters.pipe(*on_setattr) def wrap(cls): - + if getattr(cls, "__class__", None) is None: raise TypeError("attrs only works with new-style classes.") is_frozen = frozen or _has_frozen_base_class(cls) - is_exc = auto_exc is True and issubclass(cls, BaseException) + is_exc = auto_exc is True and issubclass(cls, BaseException) has_own_setattr = auto_detect and _has_own_attribute( cls, "__setattr__" ) - + if has_own_setattr and is_frozen: raise ValueError("Can't freeze a class with a custom __setattr__.") @@ -1482,11 +1482,11 @@ def attrs( auto_attribs, kw_only, cache_hash, - is_exc, + is_exc, collect_by_mro, on_setattr, has_own_setattr, - field_transformer, + field_transformer, ) if _determine_whether_to_implement( cls, repr, auto_detect, ("__repr__",) @@ -1549,7 +1549,7 @@ def attrs( ): builder.add_init() else: - builder.add_attrs_init() + builder.add_attrs_init() if cache_hash: raise TypeError( "Invalid value for cache_hash. To use hash caching," @@ -1690,7 +1690,7 @@ def _make_hash(cls, attrs, frozen, cache_hash): append_hash_computation_lines("return ", tab) script = "\n".join(method_lines) - return _make_method("__hash__", script, unique_filename) + return _make_method("__hash__", script, unique_filename) def _add_hash(cls, attrs): @@ -1732,36 +1732,36 @@ def _make_eq(cls, attrs): " if other.__class__ is not self.__class__:", " return NotImplemented", ] - + # We can't just do a big self.x = other.x and... clause due to # irregularities like nan == nan is false but (nan,) == (nan,) is true. - globs = {} + globs = {} if attrs: lines.append(" return (") others = [" ) == ("] for a in attrs: - if a.eq_key: - cmp_name = "_%s_key" % (a.name,) - # Add the key function to the global namespace - # of the evaluated function. - globs[cmp_name] = a.eq_key - lines.append( - " %s(self.%s)," - % ( - cmp_name, - a.name, - ) - ) - others.append( - " %s(other.%s)," - % ( - cmp_name, - a.name, - ) - ) - else: - lines.append(" self.%s," % (a.name,)) - others.append(" other.%s," % (a.name,)) + if a.eq_key: + cmp_name = "_%s_key" % (a.name,) + # Add the key function to the global namespace + # of the evaluated function. + globs[cmp_name] = a.eq_key + lines.append( + " %s(self.%s)," + % ( + cmp_name, + a.name, + ) + ) + others.append( + " %s(other.%s)," + % ( + cmp_name, + a.name, + ) + ) + else: + lines.append(" self.%s," % (a.name,)) + others.append(" other.%s," % (a.name,)) lines += others + [" )"] else: @@ -1769,7 +1769,7 @@ def _make_eq(cls, attrs): script = "\n".join(lines) - return _make_method("__eq__", script, unique_filename, globs) + return _make_method("__eq__", script, unique_filename, globs) def _make_order(cls, attrs): @@ -1782,12 +1782,12 @@ def _make_order(cls, attrs): """ Save us some typing. """ - return tuple( - key(value) if key else value - for value, key in ( - (getattr(obj, a.name), a.order_key) for a in attrs - ) - ) + return tuple( + key(value) if key else value + for value, key in ( + (getattr(obj, a.name), a.order_key) for a in attrs + ) + ) def __lt__(self, other): """ @@ -2001,7 +2001,7 @@ def _is_slot_attr(a_name, base_attr_map): def _make_init( cls, attrs, - pre_init, + pre_init, post_init, frozen, slots, @@ -2009,7 +2009,7 @@ def _make_init( base_attr_map, is_exc, has_global_on_setattr, - attrs_init, + attrs_init, ): if frozen and has_global_on_setattr: raise ValueError("Frozen classes can't use on_setattr.") @@ -2040,19 +2040,19 @@ def _make_init( filtered_attrs, frozen, slots, - pre_init, + pre_init, post_init, cache_hash, base_attr_map, is_exc, needs_cached_setattr, has_global_on_setattr, - attrs_init, + attrs_init, ) - if cls.__module__ in sys.modules: - # This makes typing.get_type_hints(CLS.__init__) resolve string types. - globs.update(sys.modules[cls.__module__].__dict__) - + if cls.__module__ in sys.modules: + # This makes typing.get_type_hints(CLS.__init__) resolve string types. + globs.update(sys.modules[cls.__module__].__dict__) + globs.update({"NOTHING": NOTHING, "attr_dict": attr_dict}) if needs_cached_setattr: @@ -2060,15 +2060,15 @@ def _make_init( # setattr hooks. globs["_cached_setattr"] = _obj_setattr - init = _make_method( - "__attrs_init__" if attrs_init else "__init__", - script, + init = _make_method( + "__attrs_init__" if attrs_init else "__init__", + script, unique_filename, - globs, + globs, ) - init.__annotations__ = annotations + init.__annotations__ = annotations - return init + return init def _setattr(attr_name, value_var, has_on_setattr): @@ -2135,12 +2135,12 @@ if PY2: def _unpack_kw_only_lines_py2(kw_only_args): """ Unpack all *kw_only_args* from _kw_only dict and handle errors. - + Given a list of strings "{attr_name}" and "{attr_name}={default}" generates list of lines of code that pop attrs from _kw_only dict and raise TypeError similar to builtin if required attr is missing or extra key is passed. - + >>> print("\n".join(_unpack_kw_only_lines_py2(["a", "b=42"]))) try: a = _kw_only.pop('a') @@ -2177,14 +2177,14 @@ def _attrs_to_init_script( attrs, frozen, slots, - pre_init, + pre_init, post_init, cache_hash, base_attr_map, is_exc, needs_cached_setattr, has_global_on_setattr, - attrs_init, + attrs_init, ): """ Return a script of an initializer for *attrs* and a dict of globals. @@ -2195,9 +2195,9 @@ def _attrs_to_init_script( a cached ``object.__setattr__``. """ lines = [] - if pre_init: - lines.append("self.__attrs_pre_init__()") - + if pre_init: + lines.append("self.__attrs_pre_init__()") + if needs_cached_setattr: lines.append( # Circumvent the __setattr__ descriptor to save one lookup per @@ -2387,24 +2387,24 @@ def _attrs_to_init_script( else: lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) - if a.init is True: - if a.type is not None and a.converter is None: - annotations[arg_name] = a.type - elif a.converter is not None and not PY2: - # Try to get the type from the converter. - sig = None - try: - sig = inspect.signature(a.converter) - except (ValueError, TypeError): # inspect failed - pass - if sig: - sig_params = list(sig.parameters.values()) - if ( - sig_params - and sig_params[0].annotation - is not inspect.Parameter.empty - ): - annotations[arg_name] = sig_params[0].annotation + if a.init is True: + if a.type is not None and a.converter is None: + annotations[arg_name] = a.type + elif a.converter is not None and not PY2: + # Try to get the type from the converter. + sig = None + try: + sig = inspect.signature(a.converter) + except (ValueError, TypeError): # inspect failed + pass + if sig: + sig_params = list(sig.parameters.values()) + if ( + sig_params + and sig_params[0].annotation + is not inspect.Parameter.empty + ): + annotations[arg_name] = sig_params[0].annotation if attrs_to_validate: # we can skip this if there are no validators. names_for_globals["_config"] = _config @@ -2438,13 +2438,13 @@ def _attrs_to_init_script( init_hash_cache = "self.%s = %s" lines.append(init_hash_cache % (_hash_cache_field, "None")) - # For exceptions we rely on BaseException.__init__ for proper - # initialization. - if is_exc: - vals = ",".join("self." + a.name for a in attrs if a.init) - - lines.append("BaseException.__init__(self, %s)" % (vals,)) - + # For exceptions we rely on BaseException.__init__ for proper + # initialization. + if is_exc: + vals = ",".join("self." + a.name for a in attrs if a.init) + + lines.append("BaseException.__init__(self, %s)" % (vals,)) + args = ", ".join(args) if kw_only_args: if PY2: @@ -2458,12 +2458,12 @@ def _attrs_to_init_script( ) return ( """\ -def {init_name}(self, {args}): +def {init_name}(self, {args}): {lines} """.format( - init_name=("__attrs_init__" if attrs_init else "__init__"), - args=args, - lines="\n ".join(lines) if lines else "pass", + init_name=("__attrs_init__" if attrs_init else "__init__"), + args=args, + lines="\n ".join(lines) if lines else "pass", ), names_for_globals, annotations, @@ -2474,13 +2474,13 @@ class Attribute(object): """ *Read-only* representation of an attribute. - Instances of this class are frequently used for introspection purposes - like: - - - `fields` returns a tuple of them. - - Validators get them passed as the first argument. - - The *field transformer* hook receives a list of them. - + Instances of this class are frequently used for introspection purposes + like: + + - `fields` returns a tuple of them. + - Validators get them passed as the first argument. + - The *field transformer* hook receives a list of them. + :attribute name: The name of the attribute. :attribute inherited: Whether or not that attribute has been inherited from a base class. @@ -2492,7 +2492,7 @@ class Attribute(object): .. versionadded:: 20.1.0 *on_setattr* .. versionchanged:: 20.2.0 *inherited* is not taken into account for equality checks and hashing anymore. - .. versionadded:: 21.1.0 *eq_key* and *order_key* + .. versionadded:: 21.1.0 *eq_key* and *order_key* For the full version history of the fields, see `attr.ib`. """ @@ -2503,9 +2503,9 @@ class Attribute(object): "validator", "repr", "eq", - "eq_key", + "eq_key", "order", - "order_key", + "order_key", "hash", "init", "metadata", @@ -2531,14 +2531,14 @@ class Attribute(object): converter=None, kw_only=False, eq=None, - eq_key=None, + eq_key=None, order=None, - order_key=None, + order_key=None, on_setattr=None, ): - eq, eq_key, order, order_key = _determine_attrib_eq_order( - cmp, eq_key or eq, order_key or order, True - ) + eq, eq_key, order, order_key = _determine_attrib_eq_order( + cmp, eq_key or eq, order_key or order, True + ) # Cache this descriptor here to speed things up later. bound_setattr = _obj_setattr.__get__(self, Attribute) @@ -2550,9 +2550,9 @@ class Attribute(object): bound_setattr("validator", validator) bound_setattr("repr", repr) bound_setattr("eq", eq) - bound_setattr("eq_key", eq_key) + bound_setattr("eq_key", eq_key) bound_setattr("order", order) - bound_setattr("order_key", order_key) + bound_setattr("order_key", order_key) bound_setattr("hash", hash) bound_setattr("init", init) bound_setattr("converter", converter) @@ -2612,17 +2612,17 @@ class Attribute(object): return self.eq and self.order - # Don't use attr.evolve since fields(Attribute) doesn't work - def evolve(self, **changes): + # Don't use attr.evolve since fields(Attribute) doesn't work + def evolve(self, **changes): """ Copy *self* and apply *changes*. - - This works similarly to `attr.evolve` but that function does not work - with ``Attribute``. - - It is mainly meant to be used for `transform-fields`. - - .. versionadded:: 20.3.0 + + This works similarly to `attr.evolve` but that function does not work + with ``Attribute``. + + It is mainly meant to be used for `transform-fields`. + + .. versionadded:: 20.3.0 """ new = copy.copy(self) @@ -2699,9 +2699,9 @@ class _CountingAttr(object): "_default", "repr", "eq", - "eq_key", + "eq_key", "order", - "order_key", + "order_key", "hash", "init", "metadata", @@ -2722,9 +2722,9 @@ class _CountingAttr(object): init=True, kw_only=False, eq=True, - eq_key=None, + eq_key=None, order=False, - order_key=None, + order_key=None, inherited=False, on_setattr=None, ) @@ -2749,9 +2749,9 @@ class _CountingAttr(object): init=True, kw_only=False, eq=True, - eq_key=None, + eq_key=None, order=False, - order_key=None, + order_key=None, inherited=False, on_setattr=None, ), @@ -2763,7 +2763,7 @@ class _CountingAttr(object): default, validator, repr, - cmp, + cmp, hash, init, converter, @@ -2771,9 +2771,9 @@ class _CountingAttr(object): type, kw_only, eq, - eq_key, + eq_key, order, - order_key, + order_key, on_setattr, ): _CountingAttr.cls_counter += 1 @@ -2783,9 +2783,9 @@ class _CountingAttr(object): self.converter = converter self.repr = repr self.eq = eq - self.eq_key = eq_key + self.eq_key = eq_key self.order = order - self.order_key = order_key + self.order_key = order_key self.hash = hash self.init = init self.metadata = metadata @@ -2843,7 +2843,7 @@ class Factory(object): .. versionadded:: 17.1.0 *takes_self* """ - __slots__ = ("factory", "takes_self") + __slots__ = ("factory", "takes_self") def __init__(self, factory, takes_self=False): """ @@ -2853,39 +2853,39 @@ class Factory(object): self.factory = factory self.takes_self = takes_self - def __getstate__(self): - """ - Play nice with pickle. - """ - return tuple(getattr(self, name) for name in self.__slots__) - - def __setstate__(self, state): - """ - Play nice with pickle. - """ - for name, value in zip(self.__slots__, state): - setattr(self, name, value) - - -_f = [ - Attribute( - name=name, - default=NOTHING, - validator=None, - repr=True, - cmp=None, - eq=True, - order=False, - hash=True, - init=True, - inherited=False, - ) - for name in Factory.__slots__ -] - -Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f) - - + def __getstate__(self): + """ + Play nice with pickle. + """ + return tuple(getattr(self, name) for name in self.__slots__) + + def __setstate__(self, state): + """ + Play nice with pickle. + """ + for name, value in zip(self.__slots__, state): + setattr(self, name, value) + + +_f = [ + Attribute( + name=name, + default=NOTHING, + validator=None, + repr=True, + cmp=None, + eq=True, + order=False, + hash=True, + init=True, + inherited=False, + ) + for name in Factory.__slots__ +] + +Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f) + + def make_class(name, attrs, bases=(object,), **attributes_arguments): """ A quick way to create a new class called *name* with *attrs*. @@ -2918,20 +2918,20 @@ def make_class(name, attrs, bases=(object,), **attributes_arguments): else: raise TypeError("attrs argument must be a dict or a list.") - pre_init = cls_dict.pop("__attrs_pre_init__", None) + pre_init = cls_dict.pop("__attrs_pre_init__", None) post_init = cls_dict.pop("__attrs_post_init__", None) - user_init = cls_dict.pop("__init__", None) - - body = {} - if pre_init is not None: - body["__attrs_pre_init__"] = pre_init - if post_init is not None: - body["__attrs_post_init__"] = post_init - if user_init is not None: - body["__init__"] = user_init - - type_ = new_class(name, bases, {}, lambda ns: ns.update(body)) - + user_init = cls_dict.pop("__init__", None) + + body = {} + if pre_init is not None: + body["__attrs_pre_init__"] = pre_init + if post_init is not None: + body["__attrs_post_init__"] = post_init + if user_init is not None: + body["__init__"] = user_init + + type_ = new_class(name, bases, {}, lambda ns: ns.update(body)) + # For pickling to work, the __module__ variable needs to be set to the # frame where the class is created. Bypass this step in environments where # sys._getframe is not defined (Jython for example) or sys._getframe is not @@ -2948,7 +2948,7 @@ def make_class(name, attrs, bases=(object,), **attributes_arguments): ( attributes_arguments["eq"], attributes_arguments["order"], - ) = _determine_attrs_eq_order( + ) = _determine_attrs_eq_order( cmp, attributes_arguments.get("eq"), attributes_arguments.get("order"), @@ -3003,9 +3003,9 @@ def pipe(*converters): When called on a value, it runs all wrapped converters, returning the *last* value. - Type annotations will be inferred from the wrapped converters', if - they have any. - + Type annotations will be inferred from the wrapped converters', if + they have any. + :param callables converters: Arbitrary number of converters. .. versionadded:: 20.1.0 @@ -3017,36 +3017,36 @@ def pipe(*converters): return val - if not PY2: - if not converters: - # If the converter list is empty, pipe_converter is the identity. - A = typing.TypeVar("A") - pipe_converter.__annotations__ = {"val": A, "return": A} - else: - # Get parameter type. - sig = None - try: - sig = inspect.signature(converters[0]) - except (ValueError, TypeError): # inspect failed - pass - if sig: - params = list(sig.parameters.values()) - if ( - params - and params[0].annotation is not inspect.Parameter.empty - ): - pipe_converter.__annotations__["val"] = params[ - 0 - ].annotation - # Get return type. - sig = None - try: - sig = inspect.signature(converters[-1]) - except (ValueError, TypeError): # inspect failed - pass - if sig and sig.return_annotation is not inspect.Signature().empty: - pipe_converter.__annotations__[ - "return" - ] = sig.return_annotation - + if not PY2: + if not converters: + # If the converter list is empty, pipe_converter is the identity. + A = typing.TypeVar("A") + pipe_converter.__annotations__ = {"val": A, "return": A} + else: + # Get parameter type. + sig = None + try: + sig = inspect.signature(converters[0]) + except (ValueError, TypeError): # inspect failed + pass + if sig: + params = list(sig.parameters.values()) + if ( + params + and params[0].annotation is not inspect.Parameter.empty + ): + pipe_converter.__annotations__["val"] = params[ + 0 + ].annotation + # Get return type. + sig = None + try: + sig = inspect.signature(converters[-1]) + except (ValueError, TypeError): # inspect failed + pass + if sig and sig.return_annotation is not inspect.Signature().empty: + pipe_converter.__annotations__[ + "return" + ] = sig.return_annotation + return pipe_converter diff --git a/contrib/python/attrs/attr/_next_gen.py b/contrib/python/attrs/attr/_next_gen.py index fab0af966a..fb4ceba605 100644 --- a/contrib/python/attrs/attr/_next_gen.py +++ b/contrib/python/attrs/attr/_next_gen.py @@ -1,6 +1,6 @@ """ -These are Python 3.6+-only and keyword-only APIs that call `attr.s` and -`attr.ib` with different default values. +These are Python 3.6+-only and keyword-only APIs that call `attr.s` and +`attr.ib` with different default values. """ from functools import partial @@ -31,7 +31,7 @@ def define( auto_detect=True, getstate_setstate=None, on_setattr=None, - field_transformer=None, + field_transformer=None, ): r""" The only behavioral differences are the handling of the *auto_attribs* @@ -40,8 +40,8 @@ def define( :param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves exactly like `attr.s`. If left `None`, `attr.s` will try to guess: - 1. If any attributes are annotated and no unannotated `attr.ib`\ s - are found, it assumes *auto_attribs=True*. + 1. If any attributes are annotated and no unannotated `attr.ib`\ s + are found, it assumes *auto_attribs=True*. 2. Otherwise it assumes *auto_attribs=False* and tries to collect `attr.ib`\ s. @@ -71,7 +71,7 @@ def define( collect_by_mro=True, getstate_setstate=getstate_setstate, on_setattr=on_setattr, - field_transformer=field_transformer, + field_transformer=field_transformer, ) def wrap(cls): diff --git a/contrib/python/attrs/attr/_version_info.py b/contrib/python/attrs/attr/_version_info.py index 014e78a1b4..62188e6e1f 100644 --- a/contrib/python/attrs/attr/_version_info.py +++ b/contrib/python/attrs/attr/_version_info.py @@ -1,85 +1,85 @@ -from __future__ import absolute_import, division, print_function - -from functools import total_ordering - -from ._funcs import astuple -from ._make import attrib, attrs - - -@total_ordering -@attrs(eq=False, order=False, slots=True, frozen=True) -class VersionInfo(object): - """ - A version object that can be compared to tuple of length 1--4: - - >>> attr.VersionInfo(19, 1, 0, "final") <= (19, 2) - True - >>> attr.VersionInfo(19, 1, 0, "final") < (19, 1, 1) - True - >>> vi = attr.VersionInfo(19, 2, 0, "final") - >>> vi < (19, 1, 1) - False - >>> vi < (19,) - False - >>> vi == (19, 2,) - True - >>> vi == (19, 2, 1) - False - - .. versionadded:: 19.2 - """ - - year = attrib(type=int) - minor = attrib(type=int) - micro = attrib(type=int) - releaselevel = attrib(type=str) - - @classmethod - def _from_version_string(cls, s): - """ - Parse *s* and return a _VersionInfo. - """ - v = s.split(".") - if len(v) == 3: - v.append("final") - - return cls( - year=int(v[0]), minor=int(v[1]), micro=int(v[2]), releaselevel=v[3] - ) - - def _ensure_tuple(self, other): - """ - Ensure *other* is a tuple of a valid length. - - Returns a possibly transformed *other* and ourselves as a tuple of - the same length as *other*. - """ - - if self.__class__ is other.__class__: - other = astuple(other) - - if not isinstance(other, tuple): - raise NotImplementedError - - if not (1 <= len(other) <= 4): - raise NotImplementedError - - return astuple(self)[: len(other)], other - - def __eq__(self, other): - try: - us, them = self._ensure_tuple(other) - except NotImplementedError: - return NotImplemented - - return us == them - - def __lt__(self, other): - try: - us, them = self._ensure_tuple(other) - except NotImplementedError: - return NotImplemented - - # Since alphabetically "dev0" < "final" < "post1" < "post2", we don't - # have to do anything special with releaselevel for now. - return us < them +from __future__ import absolute_import, division, print_function + +from functools import total_ordering + +from ._funcs import astuple +from ._make import attrib, attrs + + +@total_ordering +@attrs(eq=False, order=False, slots=True, frozen=True) +class VersionInfo(object): + """ + A version object that can be compared to tuple of length 1--4: + + >>> attr.VersionInfo(19, 1, 0, "final") <= (19, 2) + True + >>> attr.VersionInfo(19, 1, 0, "final") < (19, 1, 1) + True + >>> vi = attr.VersionInfo(19, 2, 0, "final") + >>> vi < (19, 1, 1) + False + >>> vi < (19,) + False + >>> vi == (19, 2,) + True + >>> vi == (19, 2, 1) + False + + .. versionadded:: 19.2 + """ + + year = attrib(type=int) + minor = attrib(type=int) + micro = attrib(type=int) + releaselevel = attrib(type=str) + + @classmethod + def _from_version_string(cls, s): + """ + Parse *s* and return a _VersionInfo. + """ + v = s.split(".") + if len(v) == 3: + v.append("final") + + return cls( + year=int(v[0]), minor=int(v[1]), micro=int(v[2]), releaselevel=v[3] + ) + + def _ensure_tuple(self, other): + """ + Ensure *other* is a tuple of a valid length. + + Returns a possibly transformed *other* and ourselves as a tuple of + the same length as *other*. + """ + + if self.__class__ is other.__class__: + other = astuple(other) + + if not isinstance(other, tuple): + raise NotImplementedError + + if not (1 <= len(other) <= 4): + raise NotImplementedError + + return astuple(self)[: len(other)], other + + def __eq__(self, other): + try: + us, them = self._ensure_tuple(other) + except NotImplementedError: + return NotImplemented + + return us == them + + def __lt__(self, other): + try: + us, them = self._ensure_tuple(other) + except NotImplementedError: + return NotImplemented + + # Since alphabetically "dev0" < "final" < "post1" < "post2", we don't + # have to do anything special with releaselevel for now. + return us < them diff --git a/contrib/python/attrs/attr/_version_info.pyi b/contrib/python/attrs/attr/_version_info.pyi index 45ced08633..5881d172ed 100644 --- a/contrib/python/attrs/attr/_version_info.pyi +++ b/contrib/python/attrs/attr/_version_info.pyi @@ -1,9 +1,9 @@ -class VersionInfo: - @property - def year(self) -> int: ... - @property - def minor(self) -> int: ... - @property - def micro(self) -> int: ... - @property - def releaselevel(self) -> str: ... +class VersionInfo: + @property + def year(self) -> int: ... + @property + def minor(self) -> int: ... + @property + def micro(self) -> int: ... + @property + def releaselevel(self) -> str: ... diff --git a/contrib/python/attrs/attr/converters.py b/contrib/python/attrs/attr/converters.py index 2777db6d0a..dd1441ce4c 100644 --- a/contrib/python/attrs/attr/converters.py +++ b/contrib/python/attrs/attr/converters.py @@ -4,15 +4,15 @@ Commonly useful converters. from __future__ import absolute_import, division, print_function -from ._compat import PY2 +from ._compat import PY2 from ._make import NOTHING, Factory, pipe -if not PY2: - import inspect - import typing - - +if not PY2: + import inspect + import typing + + __all__ = [ "pipe", "optional", @@ -25,9 +25,9 @@ def optional(converter): A converter that allows an attribute to be optional. An optional attribute is one which can be set to ``None``. - Type annotations will be inferred from the wrapped converter's, if it - has any. - + Type annotations will be inferred from the wrapped converter's, if it + has any. + :param callable converter: the converter that is used for non-``None`` values. @@ -39,23 +39,23 @@ def optional(converter): return None return converter(val) - if not PY2: - sig = None - try: - sig = inspect.signature(converter) - except (ValueError, TypeError): # inspect failed - pass - if sig: - params = list(sig.parameters.values()) - if params and params[0].annotation is not inspect.Parameter.empty: - optional_converter.__annotations__["val"] = typing.Optional[ - params[0].annotation - ] - if sig.return_annotation is not inspect.Signature.empty: - optional_converter.__annotations__["return"] = typing.Optional[ - sig.return_annotation - ] - + if not PY2: + sig = None + try: + sig = inspect.signature(converter) + except (ValueError, TypeError): # inspect failed + pass + if sig: + params = list(sig.parameters.values()) + if params and params[0].annotation is not inspect.Parameter.empty: + optional_converter.__annotations__["val"] = typing.Optional[ + params[0].annotation + ] + if sig.return_annotation is not inspect.Signature.empty: + optional_converter.__annotations__["return"] = typing.Optional[ + sig.return_annotation + ] + return optional_converter @@ -67,7 +67,7 @@ def default_if_none(default=NOTHING, factory=None): :param default: Value to be used if ``None`` is passed. Passing an instance of `attr.Factory` is supported, however the ``takes_self`` option is *not*. - :param callable factory: A callable that takes no parameters whose result + :param callable factory: A callable that takes no parameters whose result is used if ``None`` is passed. :raises TypeError: If **neither** *default* or *factory* is passed. diff --git a/contrib/python/attrs/attr/converters.pyi b/contrib/python/attrs/attr/converters.pyi index 84a57590b0..d2f44acf25 100644 --- a/contrib/python/attrs/attr/converters.pyi +++ b/contrib/python/attrs/attr/converters.pyi @@ -1,8 +1,8 @@ -from typing import Callable, Optional, TypeVar, overload - +from typing import Callable, Optional, TypeVar, overload + from . import _ConverterType - + _T = TypeVar("_T") def pipe(*validators: _ConverterType) -> _ConverterType: ... diff --git a/contrib/python/attrs/attr/exceptions.py b/contrib/python/attrs/attr/exceptions.py index f6f9861bea..6cabec24ea 100644 --- a/contrib/python/attrs/attr/exceptions.py +++ b/contrib/python/attrs/attr/exceptions.py @@ -3,7 +3,7 @@ from __future__ import absolute_import, division, print_function class FrozenError(AttributeError): """ - A frozen/immutable instance or attribute have been attempted to be + A frozen/immutable instance or attribute have been attempted to be modified. It mirrors the behavior of ``namedtuples`` by using the same error message diff --git a/contrib/python/attrs/attr/exceptions.pyi b/contrib/python/attrs/attr/exceptions.pyi index a800fb26bb..312a80b2b7 100644 --- a/contrib/python/attrs/attr/exceptions.pyi +++ b/contrib/python/attrs/attr/exceptions.pyi @@ -1,6 +1,6 @@ from typing import Any - + class FrozenError(AttributeError): msg: str = ... diff --git a/contrib/python/attrs/attr/filters.pyi b/contrib/python/attrs/attr/filters.pyi index f7b63f1bb4..664797bb2a 100644 --- a/contrib/python/attrs/attr/filters.pyi +++ b/contrib/python/attrs/attr/filters.pyi @@ -1,7 +1,7 @@ -from typing import Any, Union - +from typing import Any, Union + from . import Attribute, _FilterType - + def include(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... def exclude(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... diff --git a/contrib/python/attrs/attr/setters.pyi b/contrib/python/attrs/attr/setters.pyi index a921e07deb..8f4ca8c0f8 100644 --- a/contrib/python/attrs/attr/setters.pyi +++ b/contrib/python/attrs/attr/setters.pyi @@ -1,12 +1,12 @@ -from typing import Any, NewType, NoReturn, TypeVar, cast - -from . import Attribute, _OnSetAttrType - +from typing import Any, NewType, NoReturn, TypeVar, cast +from . import Attribute, _OnSetAttrType + + _T = TypeVar("_T") def frozen( - instance: Any, attribute: Attribute[Any], new_value: Any + instance: Any, attribute: Attribute[Any], new_value: Any ) -> NoReturn: ... def pipe(*setters: _OnSetAttrType) -> _OnSetAttrType: ... def validate(instance: Any, attribute: Attribute[_T], new_value: _T) -> _T: ... diff --git a/contrib/python/attrs/attr/validators.py b/contrib/python/attrs/attr/validators.py index b9a73054e9..4bb1935f68 100644 --- a/contrib/python/attrs/attr/validators.py +++ b/contrib/python/attrs/attr/validators.py @@ -222,7 +222,7 @@ class _InValidator(object): def __call__(self, inst, attr, value): try: in_options = value in self.options - except TypeError: # e.g. `1 in "abc"` + except TypeError: # e.g. `1 in "abc"` in_options = False if not in_options: @@ -254,15 +254,15 @@ def in_(options): .. versionadded:: 17.1.0 """ return _InValidator(options) - - -@attrs(repr=False, slots=False, hash=True) -class _IsCallableValidator(object): - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if not callable(value): + + +@attrs(repr=False, slots=False, hash=True) +class _IsCallableValidator(object): + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not callable(value): message = ( "'{name}' must be callable " "(got {value!r} that is a {actual!r})." @@ -273,107 +273,107 @@ class _IsCallableValidator(object): ), value=value, ) - - def __repr__(self): - return "<is_callable validator>" - - -def is_callable(): - """ + + def __repr__(self): + return "<is_callable validator>" + + +def is_callable(): + """ A validator that raises a `attr.exceptions.NotCallableError` if the initializer is called with a value for this particular attribute that is not callable. - - .. versionadded:: 19.1.0 - + + .. versionadded:: 19.1.0 + :raises `attr.exceptions.NotCallableError`: With a human readable error message containing the attribute (`attr.Attribute`) name, and the value it got. - """ - return _IsCallableValidator() - - -@attrs(repr=False, slots=True, hash=True) -class _DeepIterable(object): - member_validator = attrib(validator=is_callable()) - iterable_validator = attrib( - default=None, validator=optional(is_callable()) - ) - - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if self.iterable_validator is not None: - self.iterable_validator(inst, attr, value) - - for member in value: - self.member_validator(inst, attr, member) - - def __repr__(self): - iterable_identifier = ( - "" - if self.iterable_validator is None - else " {iterable!r}".format(iterable=self.iterable_validator) - ) - return ( - "<deep_iterable validator for{iterable_identifier}" - " iterables of {member!r}>" - ).format( - iterable_identifier=iterable_identifier, - member=self.member_validator, - ) - - -def deep_iterable(member_validator, iterable_validator=None): - """ - A validator that performs deep validation of an iterable. - - :param member_validator: Validator to apply to iterable members - :param iterable_validator: Validator to apply to iterable itself - (optional) - - .. versionadded:: 19.1.0 - - :raises TypeError: if any sub-validators fail - """ - return _DeepIterable(member_validator, iterable_validator) - - -@attrs(repr=False, slots=True, hash=True) -class _DeepMapping(object): - key_validator = attrib(validator=is_callable()) - value_validator = attrib(validator=is_callable()) - mapping_validator = attrib(default=None, validator=optional(is_callable())) - - def __call__(self, inst, attr, value): - """ - We use a callable class to be able to change the ``__repr__``. - """ - if self.mapping_validator is not None: - self.mapping_validator(inst, attr, value) - - for key in value: - self.key_validator(inst, attr, key) - self.value_validator(inst, attr, value[key]) - - def __repr__(self): - return ( - "<deep_mapping validator for objects mapping {key!r} to {value!r}>" - ).format(key=self.key_validator, value=self.value_validator) - - -def deep_mapping(key_validator, value_validator, mapping_validator=None): - """ - A validator that performs deep validation of a dictionary. - - :param key_validator: Validator to apply to dictionary keys - :param value_validator: Validator to apply to dictionary values - :param mapping_validator: Validator to apply to top-level mapping - attribute (optional) - - .. versionadded:: 19.1.0 - - :raises TypeError: if any sub-validators fail - """ - return _DeepMapping(key_validator, value_validator, mapping_validator) + """ + return _IsCallableValidator() + + +@attrs(repr=False, slots=True, hash=True) +class _DeepIterable(object): + member_validator = attrib(validator=is_callable()) + iterable_validator = attrib( + default=None, validator=optional(is_callable()) + ) + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if self.iterable_validator is not None: + self.iterable_validator(inst, attr, value) + + for member in value: + self.member_validator(inst, attr, member) + + def __repr__(self): + iterable_identifier = ( + "" + if self.iterable_validator is None + else " {iterable!r}".format(iterable=self.iterable_validator) + ) + return ( + "<deep_iterable validator for{iterable_identifier}" + " iterables of {member!r}>" + ).format( + iterable_identifier=iterable_identifier, + member=self.member_validator, + ) + + +def deep_iterable(member_validator, iterable_validator=None): + """ + A validator that performs deep validation of an iterable. + + :param member_validator: Validator to apply to iterable members + :param iterable_validator: Validator to apply to iterable itself + (optional) + + .. versionadded:: 19.1.0 + + :raises TypeError: if any sub-validators fail + """ + return _DeepIterable(member_validator, iterable_validator) + + +@attrs(repr=False, slots=True, hash=True) +class _DeepMapping(object): + key_validator = attrib(validator=is_callable()) + value_validator = attrib(validator=is_callable()) + mapping_validator = attrib(default=None, validator=optional(is_callable())) + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if self.mapping_validator is not None: + self.mapping_validator(inst, attr, value) + + for key in value: + self.key_validator(inst, attr, key) + self.value_validator(inst, attr, value[key]) + + def __repr__(self): + return ( + "<deep_mapping validator for objects mapping {key!r} to {value!r}>" + ).format(key=self.key_validator, value=self.value_validator) + + +def deep_mapping(key_validator, value_validator, mapping_validator=None): + """ + A validator that performs deep validation of a dictionary. + + :param key_validator: Validator to apply to dictionary keys + :param value_validator: Validator to apply to dictionary values + :param mapping_validator: Validator to apply to top-level mapping + attribute (optional) + + .. versionadded:: 19.1.0 + + :raises TypeError: if any sub-validators fail + """ + return _DeepMapping(key_validator, value_validator, mapping_validator) diff --git a/contrib/python/attrs/attr/validators.pyi b/contrib/python/attrs/attr/validators.pyi index fe92aac421..dc010511c0 100644 --- a/contrib/python/attrs/attr/validators.pyi +++ b/contrib/python/attrs/attr/validators.pyi @@ -1,23 +1,23 @@ from typing import ( - Any, - AnyStr, - Callable, + Any, + AnyStr, + Callable, Container, - Iterable, + Iterable, List, - Mapping, - Match, + Mapping, + Match, Optional, Tuple, - Type, - TypeVar, - Union, + Type, + TypeVar, + Union, overload, ) - + from . import _ValidatorType - + _T = TypeVar("_T") _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") |