mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-18 08:43:37 +00:00
Update attr 22.2.0 (a9960de) → 22.2.0 (683d056).
This commit is contained in:
parent
3e5c399b05
commit
ef2d45c4ca
11 changed files with 386 additions and 181 deletions
|
@ -1,5 +1,6 @@
|
||||||
### 3.29.0 (2023-xx-xx xx:xx:00 UTC)
|
### 3.29.0 (2023-xx-xx xx:xx:00 UTC)
|
||||||
|
|
||||||
|
* Update attr 22.2.0 (a9960de) to 22.2.0 (683d056)
|
||||||
* Update diskcache 5.4.0 (1cb1425) to 5.6.1 (4d30686)
|
* Update diskcache 5.4.0 (1cb1425) to 5.6.1 (4d30686)
|
||||||
* Update filelock 3.9.0 (ce3e891) to 3.11.0 (d3241b9)
|
* Update filelock 3.9.0 (ce3e891) to 3.11.0 (d3241b9)
|
||||||
* Update Msgpack 1.0.4 (b5acfd5) to 1.0.5 (0516c2c)
|
* Update Msgpack 1.0.4 (b5acfd5) to 1.0.5 (0516c2c)
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import sys
|
"""
|
||||||
import warnings
|
Classes Without Boilerplate
|
||||||
|
"""
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
from . import converters, exceptions, filters, setters, validators
|
from . import converters, exceptions, filters, setters, validators
|
||||||
from ._cmp import cmp_using
|
from ._cmp import cmp_using
|
||||||
|
@ -24,30 +26,6 @@ from ._next_gen import define, field, frozen, mutable
|
||||||
from ._version_info import VersionInfo
|
from ._version_info import VersionInfo
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info < (3, 7): # pragma: no cover
|
|
||||||
warnings.warn(
|
|
||||||
"Running attrs on Python 3.6 is deprecated & we intend to drop "
|
|
||||||
"support soon. If that's a problem for you, please let us know why & "
|
|
||||||
"we MAY re-evaluate: <https://github.com/python-attrs/attrs/pull/993>",
|
|
||||||
DeprecationWarning,
|
|
||||||
)
|
|
||||||
|
|
||||||
__version__ = "22.2.0"
|
|
||||||
__version_info__ = VersionInfo._from_version_string(__version__)
|
|
||||||
|
|
||||||
__title__ = "attrs"
|
|
||||||
__description__ = "Classes Without Boilerplate"
|
|
||||||
__url__ = "https://www.attrs.org/"
|
|
||||||
__uri__ = __url__
|
|
||||||
__doc__ = __description__ + " <" + __uri__ + ">"
|
|
||||||
|
|
||||||
__author__ = "Hynek Schlawack"
|
|
||||||
__email__ = "hs@ox.cx"
|
|
||||||
|
|
||||||
__license__ = "MIT"
|
|
||||||
__copyright__ = "Copyright (c) 2015 Hynek Schlawack"
|
|
||||||
|
|
||||||
|
|
||||||
s = attributes = attrs
|
s = attributes = attrs
|
||||||
ib = attr = attrib
|
ib = attr = attrib
|
||||||
dataclass = partial(attrs, auto_attribs=True) # happy Easter ;)
|
dataclass = partial(attrs, auto_attribs=True) # happy Easter ;)
|
||||||
|
@ -91,3 +69,64 @@ __all__ = [
|
||||||
"validate",
|
"validate",
|
||||||
"validators",
|
"validators",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _make_getattr(mod_name: str) -> Callable:
|
||||||
|
"""
|
||||||
|
Create a metadata proxy for packaging information that uses *mod_name* in
|
||||||
|
its warnings and errors.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> str:
|
||||||
|
dunder_to_metadata = {
|
||||||
|
"__title__": "Name",
|
||||||
|
"__copyright__": "",
|
||||||
|
"__version__": "version",
|
||||||
|
"__version_info__": "version",
|
||||||
|
"__description__": "summary",
|
||||||
|
"__uri__": "",
|
||||||
|
"__url__": "",
|
||||||
|
"__author__": "",
|
||||||
|
"__email__": "",
|
||||||
|
"__license__": "license",
|
||||||
|
}
|
||||||
|
if name not in dunder_to_metadata.keys():
|
||||||
|
raise AttributeError(f"module {mod_name} has no attribute {name}")
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
if sys.version_info < (3, 8):
|
||||||
|
from importlib_metadata import metadata
|
||||||
|
else:
|
||||||
|
from importlib.metadata import metadata
|
||||||
|
|
||||||
|
if name != "__version_info__":
|
||||||
|
warnings.warn(
|
||||||
|
f"Accessing {mod_name}.{name} is deprecated and will be "
|
||||||
|
"removed in a future release. Use importlib.metadata directly "
|
||||||
|
"to query for attrs's packaging metadata.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
meta = metadata("attrs")
|
||||||
|
if name == "__license__":
|
||||||
|
return "MIT"
|
||||||
|
elif name == "__copyright__":
|
||||||
|
return "Copyright (c) 2015 Hynek Schlawack"
|
||||||
|
elif name in ("__uri__", "__url__"):
|
||||||
|
return meta["Project-URL"].split(" ", 1)[-1]
|
||||||
|
elif name == "__version_info__":
|
||||||
|
return VersionInfo._from_version_string(meta["version"])
|
||||||
|
elif name == "__author__":
|
||||||
|
return meta["Author-email"].rsplit(" ", 1)[0]
|
||||||
|
elif name == "__email__":
|
||||||
|
return meta["Author-email"].rsplit("<", 1)[1][:-1]
|
||||||
|
|
||||||
|
return meta[dunder_to_metadata[name]]
|
||||||
|
|
||||||
|
return __getattr__
|
||||||
|
|
||||||
|
|
||||||
|
__getattr__ = _make_getattr(__name__)
|
||||||
|
|
|
@ -69,6 +69,7 @@ _ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]]
|
||||||
class AttrsInstance(AttrsInstance_, Protocol):
|
class AttrsInstance(AttrsInstance_, Protocol):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
_A = TypeVar("_A", bound=AttrsInstance)
|
||||||
# _make --
|
# _make --
|
||||||
|
|
||||||
class _Nothing(enum.Enum):
|
class _Nothing(enum.Enum):
|
||||||
|
@ -116,6 +117,7 @@ def __dataclass_transform__(
|
||||||
eq_default: bool = True,
|
eq_default: bool = True,
|
||||||
order_default: bool = False,
|
order_default: bool = False,
|
||||||
kw_only_default: bool = False,
|
kw_only_default: bool = False,
|
||||||
|
frozen_default: bool = False,
|
||||||
field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()),
|
field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()),
|
||||||
) -> Callable[[_T], _T]: ...
|
) -> Callable[[_T], _T]: ...
|
||||||
|
|
||||||
|
@ -257,6 +259,7 @@ def field(
|
||||||
order: Optional[bool] = ...,
|
order: Optional[bool] = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
alias: Optional[str] = ...,
|
alias: Optional[str] = ...,
|
||||||
|
type: Optional[type] = ...,
|
||||||
) -> Any: ...
|
) -> Any: ...
|
||||||
|
|
||||||
# This form catches an explicit None or no default and infers the type from the
|
# This form catches an explicit None or no default and infers the type from the
|
||||||
|
@ -277,6 +280,7 @@ def field(
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: Optional[_EqOrderType] = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
alias: Optional[str] = ...,
|
alias: Optional[str] = ...,
|
||||||
|
type: Optional[type] = ...,
|
||||||
) -> _T: ...
|
) -> _T: ...
|
||||||
|
|
||||||
# This form catches an explicit default argument.
|
# This form catches an explicit default argument.
|
||||||
|
@ -296,6 +300,7 @@ def field(
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: Optional[_EqOrderType] = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
alias: Optional[str] = ...,
|
alias: Optional[str] = ...,
|
||||||
|
type: Optional[type] = ...,
|
||||||
) -> _T: ...
|
) -> _T: ...
|
||||||
|
|
||||||
# This form covers type=non-Type: e.g. forward references (str), Any
|
# This form covers type=non-Type: e.g. forward references (str), Any
|
||||||
|
@ -315,6 +320,7 @@ def field(
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: Optional[_EqOrderType] = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
alias: Optional[str] = ...,
|
alias: Optional[str] = ...,
|
||||||
|
type: Optional[type] = ...,
|
||||||
) -> Any: ...
|
) -> Any: ...
|
||||||
@overload
|
@overload
|
||||||
@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))
|
@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field))
|
||||||
|
@ -426,17 +432,73 @@ def define(
|
||||||
) -> Callable[[_C], _C]: ...
|
) -> Callable[[_C], _C]: ...
|
||||||
|
|
||||||
mutable = define
|
mutable = define
|
||||||
frozen = define # they differ only in their defaults
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
@__dataclass_transform__(
|
||||||
|
frozen_default=True, field_descriptors=(attrib, field)
|
||||||
|
)
|
||||||
|
def frozen(
|
||||||
|
maybe_cls: _C,
|
||||||
|
*,
|
||||||
|
these: Optional[Dict[str, Any]] = ...,
|
||||||
|
repr: bool = ...,
|
||||||
|
unsafe_hash: Optional[bool] = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
slots: bool = ...,
|
||||||
|
frozen: bool = ...,
|
||||||
|
weakref_slot: bool = ...,
|
||||||
|
str: bool = ...,
|
||||||
|
auto_attribs: bool = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
cache_hash: bool = ...,
|
||||||
|
auto_exc: bool = ...,
|
||||||
|
eq: Optional[bool] = ...,
|
||||||
|
order: Optional[bool] = ...,
|
||||||
|
auto_detect: bool = ...,
|
||||||
|
getstate_setstate: Optional[bool] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
field_transformer: Optional[_FieldTransformer] = ...,
|
||||||
|
match_args: bool = ...,
|
||||||
|
) -> _C: ...
|
||||||
|
@overload
|
||||||
|
@__dataclass_transform__(
|
||||||
|
frozen_default=True, field_descriptors=(attrib, field)
|
||||||
|
)
|
||||||
|
def frozen(
|
||||||
|
maybe_cls: None = ...,
|
||||||
|
*,
|
||||||
|
these: Optional[Dict[str, Any]] = ...,
|
||||||
|
repr: bool = ...,
|
||||||
|
unsafe_hash: Optional[bool] = ...,
|
||||||
|
hash: Optional[bool] = ...,
|
||||||
|
init: bool = ...,
|
||||||
|
slots: bool = ...,
|
||||||
|
frozen: bool = ...,
|
||||||
|
weakref_slot: bool = ...,
|
||||||
|
str: bool = ...,
|
||||||
|
auto_attribs: bool = ...,
|
||||||
|
kw_only: bool = ...,
|
||||||
|
cache_hash: bool = ...,
|
||||||
|
auto_exc: bool = ...,
|
||||||
|
eq: Optional[bool] = ...,
|
||||||
|
order: Optional[bool] = ...,
|
||||||
|
auto_detect: bool = ...,
|
||||||
|
getstate_setstate: Optional[bool] = ...,
|
||||||
|
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||||
|
field_transformer: Optional[_FieldTransformer] = ...,
|
||||||
|
match_args: bool = ...,
|
||||||
|
) -> Callable[[_C], _C]: ...
|
||||||
def fields(cls: Type[AttrsInstance]) -> Any: ...
|
def fields(cls: Type[AttrsInstance]) -> Any: ...
|
||||||
def fields_dict(cls: Type[AttrsInstance]) -> Dict[str, Attribute[Any]]: ...
|
def fields_dict(cls: Type[AttrsInstance]) -> Dict[str, Attribute[Any]]: ...
|
||||||
def validate(inst: AttrsInstance) -> None: ...
|
def validate(inst: AttrsInstance) -> None: ...
|
||||||
def resolve_types(
|
def resolve_types(
|
||||||
cls: _C,
|
cls: _A,
|
||||||
globalns: Optional[Dict[str, Any]] = ...,
|
globalns: Optional[Dict[str, Any]] = ...,
|
||||||
localns: Optional[Dict[str, Any]] = ...,
|
localns: Optional[Dict[str, Any]] = ...,
|
||||||
attribs: Optional[List[Attribute[Any]]] = ...,
|
attribs: Optional[List[Attribute[Any]]] = ...,
|
||||||
) -> _C: ...
|
include_extras: bool = ...,
|
||||||
|
) -> _A: ...
|
||||||
|
|
||||||
# TODO: add support for returning a proper attrs class from the mypy plugin
|
# TODO: add support for returning a proper attrs class from the mypy plugin
|
||||||
# we use Any instead of _CountingAttr so that e.g. `make_class('Foo',
|
# we use Any instead of _CountingAttr so that e.g. `make_class('Foo',
|
||||||
|
|
|
@ -20,22 +20,22 @@ def cmp_using(
|
||||||
class_name="Comparable",
|
class_name="Comparable",
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Create a class that can be passed into `attr.ib`'s ``eq``, ``order``, and
|
Create a class that can be passed into `attrs.field`'s ``eq``, ``order``,
|
||||||
``cmp`` arguments to customize field comparison.
|
and ``cmp`` arguments to customize field comparison.
|
||||||
|
|
||||||
The resulting class will have a full set of ordering methods if
|
The resulting class will have a full set of ordering methods if at least
|
||||||
at least one of ``{lt, le, gt, ge}`` and ``eq`` are provided.
|
one of ``{lt, le, gt, ge}`` and ``eq`` are provided.
|
||||||
|
|
||||||
:param Optional[callable] eq: `callable` used to evaluate equality
|
:param Optional[callable] eq: `callable` used to evaluate equality of two
|
||||||
of two objects.
|
objects.
|
||||||
:param Optional[callable] lt: `callable` used to evaluate whether
|
:param Optional[callable] lt: `callable` used to evaluate whether one
|
||||||
one object is less than another object.
|
object is less than another object.
|
||||||
:param Optional[callable] le: `callable` used to evaluate whether
|
:param Optional[callable] le: `callable` used to evaluate whether one
|
||||||
one object is less than or equal to another object.
|
object is less than or equal to another object.
|
||||||
:param Optional[callable] gt: `callable` used to evaluate whether
|
:param Optional[callable] gt: `callable` used to evaluate whether one
|
||||||
one object is greater than another object.
|
object is greater than another object.
|
||||||
:param Optional[callable] ge: `callable` used to evaluate whether
|
:param Optional[callable] ge: `callable` used to evaluate whether one
|
||||||
one object is greater than or equal to another object.
|
object is greater than or equal to another object.
|
||||||
|
|
||||||
:param bool require_same_type: When `True`, equality and ordering methods
|
:param bool require_same_type: When `True`, equality and ordering methods
|
||||||
will return `NotImplemented` if objects are not of the same type.
|
will return `NotImplemented` if objects are not of the same type.
|
||||||
|
|
|
@ -9,9 +9,11 @@ import types
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from collections.abc import Mapping, Sequence # noqa
|
from collections.abc import Mapping, Sequence # noqa
|
||||||
|
from typing import _GenericAlias
|
||||||
|
|
||||||
|
|
||||||
PYPY = platform.python_implementation() == "PyPy"
|
PYPY = platform.python_implementation() == "PyPy"
|
||||||
|
PY_3_9_PLUS = sys.version_info[:2] >= (3, 9)
|
||||||
PY310 = sys.version_info[:2] >= (3, 10)
|
PY310 = sys.version_info[:2] >= (3, 10)
|
||||||
PY_3_12_PLUS = sys.version_info[:2] >= (3, 12)
|
PY_3_12_PLUS = sys.version_info[:2] >= (3, 12)
|
||||||
|
|
||||||
|
@ -81,6 +83,13 @@ def make_set_closure_cell():
|
||||||
|
|
||||||
# Otherwise gotta do it the hard way.
|
# Otherwise gotta do it the hard way.
|
||||||
|
|
||||||
|
try:
|
||||||
|
if sys.version_info >= (3, 8):
|
||||||
|
|
||||||
|
def set_closure_cell(cell, value):
|
||||||
|
cell.cell_contents = value
|
||||||
|
|
||||||
|
else:
|
||||||
# Create a function that will set its first cellvar to `value`.
|
# Create a function that will set its first cellvar to `value`.
|
||||||
def set_first_cellvar_to(value):
|
def set_first_cellvar_to(value):
|
||||||
x = value
|
x = value
|
||||||
|
@ -92,7 +101,6 @@ def make_set_closure_cell():
|
||||||
def force_x_to_be_a_cell(): # pragma: no cover
|
def force_x_to_be_a_cell(): # pragma: no cover
|
||||||
return x
|
return x
|
||||||
|
|
||||||
try:
|
|
||||||
# Extract the code object and make sure our assumptions about
|
# Extract the code object and make sure our assumptions about
|
||||||
# the closure behavior are correct.
|
# the closure behavior are correct.
|
||||||
co = set_first_cellvar_to.__code__
|
co = set_first_cellvar_to.__code__
|
||||||
|
@ -101,12 +109,6 @@ def make_set_closure_cell():
|
||||||
|
|
||||||
# Convert this code object to a code object that sets the
|
# Convert this code object to a code object that sets the
|
||||||
# function's first _freevar_ (not cellvar) to the argument.
|
# function's first _freevar_ (not cellvar) to the argument.
|
||||||
if sys.version_info >= (3, 8):
|
|
||||||
|
|
||||||
def set_closure_cell(cell, value):
|
|
||||||
cell.cell_contents = value
|
|
||||||
|
|
||||||
else:
|
|
||||||
args = [co.co_argcount]
|
args = [co.co_argcount]
|
||||||
args.append(co.co_kwonlyargcount)
|
args.append(co.co_kwonlyargcount)
|
||||||
args.extend(
|
args.extend(
|
||||||
|
@ -174,3 +176,10 @@ set_closure_cell = make_set_closure_cell()
|
||||||
# don't have a direct reference to the thread-local in their globals dict.
|
# don't have a direct reference to the thread-local in their globals dict.
|
||||||
# If they have such a reference, it breaks cloudpickle.
|
# If they have such a reference, it breaks cloudpickle.
|
||||||
repr_context = threading.local()
|
repr_context = threading.local()
|
||||||
|
|
||||||
|
|
||||||
|
def get_generic_base(cl):
|
||||||
|
"""If this is a generic class (A[str]), return the generic base for it."""
|
||||||
|
if cl.__class__ is _GenericAlias:
|
||||||
|
return cl.__origin__
|
||||||
|
return None
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
from ._compat import PY_3_9_PLUS, get_generic_base
|
||||||
from ._make import NOTHING, _obj_setattr, fields
|
from ._make import NOTHING, _obj_setattr, fields
|
||||||
from .exceptions import AttrsAttributeNotFoundError
|
from .exceptions import AttrsAttributeNotFoundError
|
||||||
|
|
||||||
|
@ -16,13 +17,13 @@ def asdict(
|
||||||
value_serializer=None,
|
value_serializer=None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Return the ``attrs`` attribute values of *inst* as a dict.
|
Return the *attrs* attribute values of *inst* as a dict.
|
||||||
|
|
||||||
Optionally recurse into other ``attrs``-decorated classes.
|
Optionally recurse into other *attrs*-decorated classes.
|
||||||
|
|
||||||
:param inst: Instance of an ``attrs``-decorated class.
|
:param inst: Instance of an *attrs*-decorated class.
|
||||||
:param bool recurse: Recurse into classes that are also
|
:param bool recurse: Recurse into classes that are also
|
||||||
``attrs``-decorated.
|
*attrs*-decorated.
|
||||||
:param callable filter: A callable whose return code determines whether an
|
:param callable filter: A callable whose return code determines whether an
|
||||||
attribute or element is included (``True``) or dropped (``False``). Is
|
attribute or element is included (``True``) or dropped (``False``). Is
|
||||||
called with the `attrs.Attribute` as the first argument and the
|
called with the `attrs.Attribute` as the first argument and the
|
||||||
|
@ -40,7 +41,7 @@ def asdict(
|
||||||
|
|
||||||
:rtype: return type of *dict_factory*
|
:rtype: return type of *dict_factory*
|
||||||
|
|
||||||
:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
|
:raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs*
|
||||||
class.
|
class.
|
||||||
|
|
||||||
.. versionadded:: 16.0.0 *dict_factory*
|
.. versionadded:: 16.0.0 *dict_factory*
|
||||||
|
@ -195,13 +196,13 @@ def astuple(
|
||||||
retain_collection_types=False,
|
retain_collection_types=False,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Return the ``attrs`` attribute values of *inst* as a tuple.
|
Return the *attrs* attribute values of *inst* as a tuple.
|
||||||
|
|
||||||
Optionally recurse into other ``attrs``-decorated classes.
|
Optionally recurse into other *attrs*-decorated classes.
|
||||||
|
|
||||||
:param inst: Instance of an ``attrs``-decorated class.
|
:param inst: Instance of an *attrs*-decorated class.
|
||||||
:param bool recurse: Recurse into classes that are also
|
:param bool recurse: Recurse into classes that are also
|
||||||
``attrs``-decorated.
|
*attrs*-decorated.
|
||||||
:param callable filter: A callable whose return code determines whether an
|
:param callable filter: A callable whose return code determines whether an
|
||||||
attribute or element is included (``True``) or dropped (``False``). Is
|
attribute or element is included (``True``) or dropped (``False``). Is
|
||||||
called with the `attrs.Attribute` as the first argument and the
|
called with the `attrs.Attribute` as the first argument and the
|
||||||
|
@ -215,7 +216,7 @@ def astuple(
|
||||||
|
|
||||||
:rtype: return type of *tuple_factory*
|
:rtype: return type of *tuple_factory*
|
||||||
|
|
||||||
:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
|
:raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs*
|
||||||
class.
|
class.
|
||||||
|
|
||||||
.. versionadded:: 16.2.0
|
.. versionadded:: 16.2.0
|
||||||
|
@ -289,28 +290,48 @@ def astuple(
|
||||||
|
|
||||||
def has(cls):
|
def has(cls):
|
||||||
"""
|
"""
|
||||||
Check whether *cls* is a class with ``attrs`` attributes.
|
Check whether *cls* is a class with *attrs* attributes.
|
||||||
|
|
||||||
:param type cls: Class to introspect.
|
:param type cls: Class to introspect.
|
||||||
:raise TypeError: If *cls* is not a class.
|
:raise TypeError: If *cls* is not a class.
|
||||||
|
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
return getattr(cls, "__attrs_attrs__", None) is not None
|
attrs = getattr(cls, "__attrs_attrs__", None)
|
||||||
|
if attrs is not None:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# No attrs, maybe it's a specialized generic (A[str])?
|
||||||
|
generic_base = get_generic_base(cls)
|
||||||
|
if generic_base is not None:
|
||||||
|
generic_attrs = getattr(generic_base, "__attrs_attrs__", None)
|
||||||
|
if generic_attrs is not None:
|
||||||
|
# Stick it on here for speed next time.
|
||||||
|
cls.__attrs_attrs__ = generic_attrs
|
||||||
|
return generic_attrs is not None
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def assoc(inst, **changes):
|
def assoc(inst, **changes):
|
||||||
"""
|
"""
|
||||||
Copy *inst* and apply *changes*.
|
Copy *inst* and apply *changes*.
|
||||||
|
|
||||||
:param inst: Instance of a class with ``attrs`` attributes.
|
This is different from `evolve` that applies the changes to the arguments
|
||||||
|
that create the new instance.
|
||||||
|
|
||||||
|
`evolve`'s behavior is preferable, but there are `edge cases`_ where it
|
||||||
|
doesn't work. Therefore `assoc` is deprecated, but will not be removed.
|
||||||
|
|
||||||
|
.. _`edge cases`: https://github.com/python-attrs/attrs/issues/251
|
||||||
|
|
||||||
|
:param inst: Instance of a class with *attrs* attributes.
|
||||||
:param changes: Keyword changes in the new copy.
|
:param changes: Keyword changes in the new copy.
|
||||||
|
|
||||||
:return: A copy of inst with *changes* incorporated.
|
:return: A copy of inst with *changes* incorporated.
|
||||||
|
|
||||||
:raise attr.exceptions.AttrsAttributeNotFoundError: If *attr_name* couldn't
|
:raise attrs.exceptions.AttrsAttributeNotFoundError: If *attr_name*
|
||||||
be found on *cls*.
|
couldn't be found on *cls*.
|
||||||
:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
|
:raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs*
|
||||||
class.
|
class.
|
||||||
|
|
||||||
.. deprecated:: 17.1.0
|
.. deprecated:: 17.1.0
|
||||||
|
@ -318,13 +339,6 @@ def assoc(inst, **changes):
|
||||||
This function will not be removed du to the slightly different approach
|
This function will not be removed du to the slightly different approach
|
||||||
compared to `attrs.evolve`.
|
compared to `attrs.evolve`.
|
||||||
"""
|
"""
|
||||||
import warnings
|
|
||||||
|
|
||||||
warnings.warn(
|
|
||||||
"assoc is deprecated and will be removed after 2018/01.",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
new = copy.copy(inst)
|
new = copy.copy(inst)
|
||||||
attrs = fields(inst.__class__)
|
attrs = fields(inst.__class__)
|
||||||
for k, v in changes.items():
|
for k, v in changes.items():
|
||||||
|
@ -337,22 +351,55 @@ def assoc(inst, **changes):
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|
||||||
def evolve(inst, **changes):
|
def evolve(*args, **changes):
|
||||||
"""
|
"""
|
||||||
Create a new instance, based on *inst* with *changes* applied.
|
Create a new instance, based on the first positional argument with
|
||||||
|
*changes* applied.
|
||||||
|
|
||||||
:param inst: Instance of a class with ``attrs`` attributes.
|
:param inst: Instance of a class with *attrs* attributes.
|
||||||
:param changes: Keyword changes in the new copy.
|
:param changes: Keyword changes in the new copy.
|
||||||
|
|
||||||
:return: A copy of inst with *changes* incorporated.
|
:return: A copy of inst with *changes* incorporated.
|
||||||
|
|
||||||
:raise TypeError: If *attr_name* couldn't be found in the class
|
:raise TypeError: If *attr_name* couldn't be found in the class
|
||||||
``__init__``.
|
``__init__``.
|
||||||
:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
|
:raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs*
|
||||||
class.
|
class.
|
||||||
|
|
||||||
.. versionadded:: 17.1.0
|
.. versionadded:: 17.1.0
|
||||||
|
.. deprecated:: 23.1.0
|
||||||
|
It is now deprecated to pass the instance using the keyword argument
|
||||||
|
*inst*. It will raise a warning until at least April 2024, after which
|
||||||
|
it will become an error. Always pass the instance as a positional
|
||||||
|
argument.
|
||||||
"""
|
"""
|
||||||
|
# Try to get instance by positional argument first.
|
||||||
|
# Use changes otherwise and warn it'll break.
|
||||||
|
if args:
|
||||||
|
try:
|
||||||
|
(inst,) = args
|
||||||
|
except ValueError:
|
||||||
|
raise TypeError(
|
||||||
|
f"evolve() takes 1 positional argument, but {len(args)} "
|
||||||
|
"were given"
|
||||||
|
) from None
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
inst = changes.pop("inst")
|
||||||
|
except KeyError:
|
||||||
|
raise TypeError(
|
||||||
|
"evolve() missing 1 required positional argument: 'inst'"
|
||||||
|
) from None
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"Passing the instance per keyword argument is deprecated and "
|
||||||
|
"will stop working in, or after, April 2024.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
|
|
||||||
cls = inst.__class__
|
cls = inst.__class__
|
||||||
attrs = fields(cls)
|
attrs = fields(cls)
|
||||||
for a in attrs:
|
for a in attrs:
|
||||||
|
@ -366,7 +413,9 @@ def evolve(inst, **changes):
|
||||||
return cls(**changes)
|
return cls(**changes)
|
||||||
|
|
||||||
|
|
||||||
def resolve_types(cls, globalns=None, localns=None, attribs=None):
|
def resolve_types(
|
||||||
|
cls, globalns=None, localns=None, attribs=None, include_extras=True
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Resolve any strings and forward annotations in type annotations.
|
Resolve any strings and forward annotations in type annotations.
|
||||||
|
|
||||||
|
@ -385,10 +434,14 @@ def resolve_types(cls, globalns=None, localns=None, attribs=None):
|
||||||
:param Optional[dict] localns: Dictionary containing local variables.
|
:param Optional[dict] localns: Dictionary containing local variables.
|
||||||
:param Optional[list] attribs: List of attribs for the given class.
|
:param Optional[list] attribs: List of attribs for the given class.
|
||||||
This is necessary when calling from inside a ``field_transformer``
|
This is necessary when calling from inside a ``field_transformer``
|
||||||
since *cls* is not an ``attrs`` class yet.
|
since *cls* is not an *attrs* class yet.
|
||||||
|
:param bool include_extras: Resolve more accurately, if possible.
|
||||||
|
Pass ``include_extras`` to ``typing.get_hints``, if supported by the
|
||||||
|
typing module. On supported Python versions (3.9+), this resolves the
|
||||||
|
types more accurately.
|
||||||
|
|
||||||
:raise TypeError: If *cls* is not a class.
|
:raise TypeError: If *cls* is not a class.
|
||||||
:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
|
:raise attrs.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.
|
:raise NameError: If types cannot be resolved because of missing variables.
|
||||||
|
|
||||||
|
@ -398,6 +451,7 @@ def resolve_types(cls, globalns=None, localns=None, attribs=None):
|
||||||
|
|
||||||
.. versionadded:: 20.1.0
|
.. versionadded:: 20.1.0
|
||||||
.. versionadded:: 21.1.0 *attribs*
|
.. versionadded:: 21.1.0 *attribs*
|
||||||
|
.. versionadded:: 23.1.0 *include_extras*
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# Since calling get_type_hints is expensive we cache whether we've
|
# Since calling get_type_hints is expensive we cache whether we've
|
||||||
|
@ -405,7 +459,12 @@ def resolve_types(cls, globalns=None, localns=None, attribs=None):
|
||||||
if getattr(cls, "__attrs_types_resolved__", None) != cls:
|
if getattr(cls, "__attrs_types_resolved__", None) != cls:
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
hints = typing.get_type_hints(cls, globalns=globalns, localns=localns)
|
kwargs = {"globalns": globalns, "localns": localns}
|
||||||
|
|
||||||
|
if PY_3_9_PLUS:
|
||||||
|
kwargs["include_extras"] = include_extras
|
||||||
|
|
||||||
|
hints = typing.get_type_hints(cls, **kwargs)
|
||||||
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:
|
if field.name in hints:
|
||||||
# Since fields have been frozen we must work around it.
|
# Since fields have been frozen we must work around it.
|
||||||
|
|
|
@ -12,7 +12,12 @@ from operator import itemgetter
|
||||||
# We need to import _compat itself in addition to the _compat members to avoid
|
# We need to import _compat itself in addition to the _compat members to avoid
|
||||||
# having the thread-local in the globals here.
|
# having the thread-local in the globals here.
|
||||||
from . import _compat, _config, setters
|
from . import _compat, _config, setters
|
||||||
from ._compat import PY310, PYPY, _AnnotationExtractor, set_closure_cell
|
from ._compat import (
|
||||||
|
PY310,
|
||||||
|
_AnnotationExtractor,
|
||||||
|
get_generic_base,
|
||||||
|
set_closure_cell,
|
||||||
|
)
|
||||||
from .exceptions import (
|
from .exceptions import (
|
||||||
DefaultAlreadySetError,
|
DefaultAlreadySetError,
|
||||||
FrozenInstanceError,
|
FrozenInstanceError,
|
||||||
|
@ -109,9 +114,12 @@ def attrib(
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Does *not* do anything unless the class is also decorated with
|
Does *not* do anything unless the class is also decorated with
|
||||||
`attr.s`!
|
`attr.s` / `attrs.define` / et cetera!
|
||||||
|
|
||||||
:param default: A value that is used if an ``attrs``-generated ``__init__``
|
Please consider using `attrs.field` in new code (``attr.ib`` will *never*
|
||||||
|
go away, though).
|
||||||
|
|
||||||
|
:param default: A value that is used if an *attrs*-generated ``__init__``
|
||||||
is used and no value is passed while instantiating or the attribute is
|
is used and no value is passed while instantiating or the attribute is
|
||||||
excluded using ``init=False``.
|
excluded using ``init=False``.
|
||||||
|
|
||||||
|
@ -130,7 +138,7 @@ def attrib(
|
||||||
:param callable factory: Syntactic sugar for
|
:param callable factory: Syntactic sugar for
|
||||||
``default=attr.Factory(factory)``.
|
``default=attr.Factory(factory)``.
|
||||||
|
|
||||||
:param validator: `callable` that is called by ``attrs``-generated
|
:param validator: `callable` that is called by *attrs*-generated
|
||||||
``__init__`` methods after the instance has been initialized. They
|
``__init__`` methods after the instance has been initialized. They
|
||||||
receive the initialized instance, the :func:`~attrs.Attribute`, and the
|
receive the initialized instance, the :func:`~attrs.Attribute`, and the
|
||||||
passed value.
|
passed value.
|
||||||
|
@ -142,7 +150,7 @@ def attrib(
|
||||||
all pass.
|
all pass.
|
||||||
|
|
||||||
Validators can be globally disabled and re-enabled using
|
Validators can be globally disabled and re-enabled using
|
||||||
`get_run_validators`.
|
`attrs.validators.get_disabled` / `attrs.validators.set_disabled`.
|
||||||
|
|
||||||
The validator can also be set using decorator notation as shown below.
|
The validator can also be set using decorator notation as shown below.
|
||||||
|
|
||||||
|
@ -184,7 +192,7 @@ def attrib(
|
||||||
value. In that case this attributed is unconditionally initialized
|
value. In that case this attributed is unconditionally initialized
|
||||||
with the specified default value or factory.
|
with the specified default value or factory.
|
||||||
:param callable converter: `callable` that is called by
|
:param callable converter: `callable` that is called by
|
||||||
``attrs``-generated ``__init__`` methods to convert attribute's value
|
*attrs*-generated ``__init__`` methods to convert attribute's value
|
||||||
to the desired format. It is given the passed-in value, and the
|
to the desired format. It is given the passed-in value, and the
|
||||||
returned value will be used as the new value of the attribute. The
|
returned value will be used as the new value of the attribute. The
|
||||||
value is converted before being passed to the validator, if any.
|
value is converted before being passed to the validator, if any.
|
||||||
|
@ -197,7 +205,7 @@ def attrib(
|
||||||
Regardless of the approach used, the type will be stored on
|
Regardless of the approach used, the type will be stored on
|
||||||
``Attribute.type``.
|
``Attribute.type``.
|
||||||
|
|
||||||
Please note that ``attrs`` doesn't do anything with this metadata by
|
Please note that *attrs* doesn't do anything with this metadata by
|
||||||
itself. You can use it as part of your own code or for
|
itself. You can use it as part of your own code or for
|
||||||
`static type checking <types>`.
|
`static type checking <types>`.
|
||||||
:param kw_only: Make this attribute keyword-only in the generated
|
:param kw_only: Make this attribute keyword-only in the generated
|
||||||
|
@ -582,8 +590,6 @@ def _transform_attrs(
|
||||||
return _Attributes((AttrsClass(attrs), base_attrs, base_attr_map))
|
return _Attributes((AttrsClass(attrs), base_attrs, base_attr_map))
|
||||||
|
|
||||||
|
|
||||||
if PYPY:
|
|
||||||
|
|
||||||
def _frozen_setattrs(self, name, value):
|
def _frozen_setattrs(self, name, value):
|
||||||
"""
|
"""
|
||||||
Attached to frozen classes as __setattr__.
|
Attached to frozen classes as __setattr__.
|
||||||
|
@ -591,20 +597,13 @@ if PYPY:
|
||||||
if isinstance(self, BaseException) and name in (
|
if isinstance(self, BaseException) and name in (
|
||||||
"__cause__",
|
"__cause__",
|
||||||
"__context__",
|
"__context__",
|
||||||
|
"__traceback__",
|
||||||
):
|
):
|
||||||
BaseException.__setattr__(self, name, value)
|
BaseException.__setattr__(self, name, value)
|
||||||
return
|
return
|
||||||
|
|
||||||
raise FrozenInstanceError()
|
raise FrozenInstanceError()
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
def _frozen_setattrs(self, name, value):
|
|
||||||
"""
|
|
||||||
Attached to frozen classes as __setattr__.
|
|
||||||
"""
|
|
||||||
raise FrozenInstanceError()
|
|
||||||
|
|
||||||
|
|
||||||
def _frozen_delattrs(self, name):
|
def _frozen_delattrs(self, name):
|
||||||
"""
|
"""
|
||||||
|
@ -940,6 +939,12 @@ class _ClassBuilder:
|
||||||
Automatically created by attrs.
|
Automatically created by attrs.
|
||||||
"""
|
"""
|
||||||
__bound_setattr = _obj_setattr.__get__(self)
|
__bound_setattr = _obj_setattr.__get__(self)
|
||||||
|
if isinstance(state, tuple):
|
||||||
|
# Backward compatibility with attrs instances pickled with
|
||||||
|
# attrs versions before v22.2.0 which stored tuples.
|
||||||
|
for name, value in zip(state_attr_names, state):
|
||||||
|
__bound_setattr(name, value)
|
||||||
|
else:
|
||||||
for name in state_attr_names:
|
for name in state_attr_names:
|
||||||
if name in state:
|
if name in state:
|
||||||
__bound_setattr(name, state[name])
|
__bound_setattr(name, state[name])
|
||||||
|
@ -1220,12 +1225,15 @@ def attrs(
|
||||||
A class decorator that adds :term:`dunder methods` according to the
|
A class decorator that adds :term:`dunder methods` according to the
|
||||||
specified attributes using `attr.ib` or the *these* argument.
|
specified attributes using `attr.ib` or the *these* argument.
|
||||||
|
|
||||||
|
Please consider using `attrs.define` / `attrs.frozen` in new code
|
||||||
|
(``attr.s`` will *never* go away, though).
|
||||||
|
|
||||||
:param these: A dictionary of name to `attr.ib` mappings. This is
|
:param these: A dictionary of name to `attr.ib` mappings. This is
|
||||||
useful to avoid the definition of your attributes within the class body
|
useful to avoid the definition of your attributes within the class body
|
||||||
because you can't (e.g. if you want to add ``__repr__`` methods to
|
because you can't (e.g. if you want to add ``__repr__`` methods to
|
||||||
Django models) or don't want to.
|
Django models) or don't want to.
|
||||||
|
|
||||||
If *these* is not ``None``, ``attrs`` will *not* search the class body
|
If *these* is not ``None``, *attrs* will *not* search the class body
|
||||||
for attributes and will *not* remove any attributes from it.
|
for attributes and will *not* remove any attributes from it.
|
||||||
|
|
||||||
The order is deduced from the order of the attributes inside *these*.
|
The order is deduced from the order of the attributes inside *these*.
|
||||||
|
@ -1242,14 +1250,14 @@ def attrs(
|
||||||
inherited from some base class).
|
inherited from some base class).
|
||||||
|
|
||||||
So for example by implementing ``__eq__`` on a class yourself,
|
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
|
``__eq__`` *nor* ``__ne__`` (but Python classes come with a sensible
|
||||||
``__ne__`` by default, so it *should* be enough to only implement
|
``__ne__`` by default, so it *should* be enough to only implement
|
||||||
``__eq__`` in most cases).
|
``__eq__`` in most cases).
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
If you prevent ``attrs`` from creating the ordering methods for you
|
If you prevent *attrs* from creating the ordering methods for you
|
||||||
(``order=False``, e.g. by implementing ``__le__``), it becomes
|
(``order=False``, e.g. by implementing ``__le__``), it becomes
|
||||||
*your* responsibility to make sure its ordering is sound. The best
|
*your* responsibility to make sure its ordering is sound. The best
|
||||||
way is to use the `functools.total_ordering` decorator.
|
way is to use the `functools.total_ordering` decorator.
|
||||||
|
@ -1259,14 +1267,14 @@ def attrs(
|
||||||
*cmp*, or *hash* overrides whatever *auto_detect* would determine.
|
*cmp*, or *hash* overrides whatever *auto_detect* would determine.
|
||||||
|
|
||||||
:param bool repr: Create a ``__repr__`` method with a human readable
|
:param bool repr: Create a ``__repr__`` method with a human readable
|
||||||
representation of ``attrs`` attributes..
|
representation of *attrs* attributes..
|
||||||
:param bool str: Create a ``__str__`` method that is identical to
|
:param bool str: Create a ``__str__`` method that is identical to
|
||||||
``__repr__``. This is usually not necessary except for
|
``__repr__``. This is usually not necessary except for
|
||||||
`Exception`\ s.
|
`Exception`\ s.
|
||||||
:param Optional[bool] eq: If ``True`` or ``None`` (default), add ``__eq__``
|
:param Optional[bool] eq: If ``True`` or ``None`` (default), add ``__eq__``
|
||||||
and ``__ne__`` methods that check two instances for equality.
|
and ``__ne__`` methods that check two instances for equality.
|
||||||
|
|
||||||
They compare the instances as if they were tuples of their ``attrs``
|
They compare the instances as if they were tuples of their *attrs*
|
||||||
attributes if and only if the types of both classes are *identical*!
|
attributes if and only if the types of both classes are *identical*!
|
||||||
:param Optional[bool] order: If ``True``, add ``__lt__``, ``__le__``,
|
:param Optional[bool] order: If ``True``, add ``__lt__``, ``__le__``,
|
||||||
``__gt__``, and ``__ge__`` methods that behave like *eq* above and
|
``__gt__``, and ``__ge__`` methods that behave like *eq* above and
|
||||||
|
@ -1277,7 +1285,7 @@ def attrs(
|
||||||
:param Optional[bool] unsafe_hash: If ``None`` (default), the ``__hash__``
|
:param Optional[bool] unsafe_hash: If ``None`` (default), the ``__hash__``
|
||||||
method is generated according how *eq* and *frozen* are set.
|
method is generated according how *eq* and *frozen* are set.
|
||||||
|
|
||||||
1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you.
|
1. If *both* are True, *attrs* will generate a ``__hash__`` for you.
|
||||||
2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to
|
2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to
|
||||||
None, marking it unhashable (which it is).
|
None, marking it unhashable (which it is).
|
||||||
3. If *eq* is False, ``__hash__`` will be left untouched meaning the
|
3. If *eq* is False, ``__hash__`` will be left untouched meaning the
|
||||||
|
@ -1285,7 +1293,7 @@ def attrs(
|
||||||
``object``, this means it will fall back to id-based hashing.).
|
``object``, this means it will fall back to id-based hashing.).
|
||||||
|
|
||||||
Although not recommended, you can decide for yourself and force
|
Although not recommended, you can decide for yourself and force
|
||||||
``attrs`` to create one (e.g. if the class is immutable even though you
|
*attrs* to create one (e.g. if the class is immutable even though you
|
||||||
didn't freeze it programmatically) by passing ``True`` or not. Both of
|
didn't freeze it programmatically) by passing ``True`` or not. Both of
|
||||||
these cases are rather special and should be used carefully.
|
these cases are rather special and should be used carefully.
|
||||||
|
|
||||||
|
@ -1296,7 +1304,7 @@ def attrs(
|
||||||
:param Optional[bool] hash: Alias for *unsafe_hash*. *unsafe_hash* takes
|
:param Optional[bool] hash: Alias for *unsafe_hash*. *unsafe_hash* takes
|
||||||
precedence.
|
precedence.
|
||||||
:param bool init: Create a ``__init__`` method that initializes the
|
:param bool init: Create a ``__init__`` method that initializes the
|
||||||
``attrs`` attributes. Leading underscores are stripped for the argument
|
*attrs* attributes. Leading underscores are stripped for the argument
|
||||||
name. If a ``__attrs_pre_init__`` method exists on the class, it will
|
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__``
|
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
|
method exists on the class, it will be called after the class is fully
|
||||||
|
@ -1312,7 +1320,7 @@ def attrs(
|
||||||
we encourage you to read the :term:`glossary entry <slotted classes>`.
|
we encourage you to read the :term:`glossary entry <slotted classes>`.
|
||||||
:param bool frozen: Make instances immutable after initialization. If
|
:param bool frozen: Make instances immutable after initialization. If
|
||||||
someone attempts to modify a frozen instance,
|
someone attempts to modify a frozen instance,
|
||||||
`attr.exceptions.FrozenInstanceError` is raised.
|
`attrs.exceptions.FrozenInstanceError` is raised.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -1337,7 +1345,7 @@ def attrs(
|
||||||
:param bool auto_attribs: If ``True``, collect :pep:`526`-annotated
|
:param bool auto_attribs: If ``True``, collect :pep:`526`-annotated
|
||||||
attributes from the class body.
|
attributes from the class body.
|
||||||
|
|
||||||
In this case, you **must** annotate every field. If ``attrs``
|
In this case, you **must** annotate every field. If *attrs*
|
||||||
encounters a field that is set to an `attr.ib` but lacks a type
|
encounters a field that is set to an `attr.ib` but lacks a type
|
||||||
annotation, an `attr.exceptions.UnannotatedAttributeError` is
|
annotation, an `attr.exceptions.UnannotatedAttributeError` is
|
||||||
raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't
|
raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't
|
||||||
|
@ -1353,9 +1361,9 @@ def attrs(
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
For features that use the attribute name to create decorators (e.g.
|
For features that use the attribute name to create decorators (e.g.
|
||||||
`validators <validators>`), you still *must* assign `attr.ib` to
|
:ref:`validators <validators>`), you still *must* assign `attr.ib`
|
||||||
them. Otherwise Python will either not find the name or try to use
|
to them. Otherwise Python will either not find the name or try to
|
||||||
the default value to call e.g. ``validator`` on it.
|
use the default value to call e.g. ``validator`` on it.
|
||||||
|
|
||||||
These errors can be quite confusing and probably the most common bug
|
These errors can be quite confusing and probably the most common bug
|
||||||
report on our bug tracker.
|
report on our bug tracker.
|
||||||
|
@ -1376,14 +1384,14 @@ def attrs(
|
||||||
class:
|
class:
|
||||||
|
|
||||||
- the values for *eq*, *order*, and *hash* are ignored and the
|
- the values for *eq*, *order*, and *hash* are ignored and the
|
||||||
instances compare and hash by the instance's ids (N.B. ``attrs`` will
|
instances compare and hash by the instance's ids (N.B. *attrs* will
|
||||||
*not* remove existing implementations of ``__hash__`` or the equality
|
*not* remove existing implementations of ``__hash__`` or the equality
|
||||||
methods. It just won't add own ones.),
|
methods. It just won't add own ones.),
|
||||||
- all attributes that are either passed into ``__init__`` or have a
|
- all attributes that are either passed into ``__init__`` or have a
|
||||||
default value are additionally available as a tuple in the ``args``
|
default value are additionally available as a tuple in the ``args``
|
||||||
attribute,
|
attribute,
|
||||||
- the value of *str* is ignored leaving ``__str__`` to base classes.
|
- the value of *str* is ignored leaving ``__str__`` to base classes.
|
||||||
:param bool collect_by_mro: Setting this to `True` fixes the way ``attrs``
|
:param bool collect_by_mro: Setting this to `True` fixes the way *attrs*
|
||||||
collects attributes from base classes. The default behavior is
|
collects attributes from base classes. The default behavior is
|
||||||
incorrect in certain cases of multiple inheritance. It should be on by
|
incorrect in certain cases of multiple inheritance. It should be on by
|
||||||
default but is kept off for backward-compatibility.
|
default but is kept off for backward-compatibility.
|
||||||
|
@ -1422,7 +1430,7 @@ def attrs(
|
||||||
|
|
||||||
:param Optional[callable] field_transformer:
|
:param Optional[callable] field_transformer:
|
||||||
A function that is called with the original class object and all
|
A function that is called with the original class object and all
|
||||||
fields right before ``attrs`` finalizes the class. You can use
|
fields right before *attrs* finalizes the class. You can use
|
||||||
this, e.g., to automatically add converters or validators to
|
this, e.g., to automatically add converters or validators to
|
||||||
fields based on their types. See `transform-fields` for more details.
|
fields based on their types. See `transform-fields` for more details.
|
||||||
|
|
||||||
|
@ -1900,7 +1908,7 @@ def _add_repr(cls, ns=None, attrs=None):
|
||||||
|
|
||||||
def fields(cls):
|
def fields(cls):
|
||||||
"""
|
"""
|
||||||
Return the tuple of ``attrs`` attributes for a class.
|
Return the tuple of *attrs* attributes for a class.
|
||||||
|
|
||||||
The tuple also allows accessing the fields by their names (see below for
|
The tuple also allows accessing the fields by their names (see below for
|
||||||
examples).
|
examples).
|
||||||
|
@ -1908,31 +1916,45 @@ def fields(cls):
|
||||||
:param type cls: Class to introspect.
|
:param type cls: Class to introspect.
|
||||||
|
|
||||||
:raise TypeError: If *cls* is not a class.
|
:raise TypeError: If *cls* is not a class.
|
||||||
:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
|
:raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs*
|
||||||
class.
|
class.
|
||||||
|
|
||||||
:rtype: tuple (with name accessors) of `attrs.Attribute`
|
:rtype: tuple (with name accessors) of `attrs.Attribute`
|
||||||
|
|
||||||
.. versionchanged:: 16.2.0 Returned tuple allows accessing the fields
|
.. versionchanged:: 16.2.0 Returned tuple allows accessing the fields
|
||||||
by name.
|
by name.
|
||||||
|
.. versionchanged:: 23.1.0 Add support for generic classes.
|
||||||
"""
|
"""
|
||||||
if not isinstance(cls, type):
|
generic_base = get_generic_base(cls)
|
||||||
|
|
||||||
|
if generic_base is None and not isinstance(cls, type):
|
||||||
raise TypeError("Passed object must be a class.")
|
raise TypeError("Passed object must be a class.")
|
||||||
|
|
||||||
attrs = getattr(cls, "__attrs_attrs__", None)
|
attrs = getattr(cls, "__attrs_attrs__", None)
|
||||||
|
|
||||||
if attrs is None:
|
if attrs is None:
|
||||||
|
if generic_base is not None:
|
||||||
|
attrs = getattr(generic_base, "__attrs_attrs__", None)
|
||||||
|
if attrs is not None:
|
||||||
|
# Even though this is global state, stick it on here to speed
|
||||||
|
# it up. We rely on `cls` being cached for this to be
|
||||||
|
# efficient.
|
||||||
|
cls.__attrs_attrs__ = attrs
|
||||||
|
return attrs
|
||||||
raise NotAnAttrsClassError(f"{cls!r} is not an attrs-decorated class.")
|
raise NotAnAttrsClassError(f"{cls!r} is not an attrs-decorated class.")
|
||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
def fields_dict(cls):
|
def fields_dict(cls):
|
||||||
"""
|
"""
|
||||||
Return an ordered dictionary of ``attrs`` attributes for a class, whose
|
Return an ordered dictionary of *attrs* attributes for a class, whose
|
||||||
keys are the attribute names.
|
keys are the attribute names.
|
||||||
|
|
||||||
:param type cls: Class to introspect.
|
:param type cls: Class to introspect.
|
||||||
|
|
||||||
:raise TypeError: If *cls* is not a class.
|
:raise TypeError: If *cls* is not a class.
|
||||||
:raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
|
:raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs*
|
||||||
class.
|
class.
|
||||||
|
|
||||||
:rtype: dict
|
:rtype: dict
|
||||||
|
@ -1953,7 +1975,7 @@ def validate(inst):
|
||||||
|
|
||||||
Leaves all exceptions through.
|
Leaves all exceptions through.
|
||||||
|
|
||||||
:param inst: Instance of a class with ``attrs`` attributes.
|
:param inst: Instance of a class with *attrs* attributes.
|
||||||
"""
|
"""
|
||||||
if _config._run_validators is False:
|
if _config._run_validators is False:
|
||||||
return
|
return
|
||||||
|
@ -2391,6 +2413,10 @@ class Attribute:
|
||||||
"""
|
"""
|
||||||
*Read-only* representation of an attribute.
|
*Read-only* representation of an attribute.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
You should never instantiate this class yourself.
|
||||||
|
|
||||||
The class has *all* arguments of `attr.ib` (except for ``factory``
|
The class has *all* arguments of `attr.ib` (except for ``factory``
|
||||||
which is only syntactic sugar for ``default=Factory(...)`` plus the
|
which is only syntactic sugar for ``default=Factory(...)`` plus the
|
||||||
following:
|
following:
|
||||||
|
@ -2536,13 +2562,13 @@ class Attribute:
|
||||||
**inst_dict,
|
**inst_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Don't use attr.evolve since fields(Attribute) doesn't work
|
# Don't use attrs.evolve since fields(Attribute) doesn't work
|
||||||
def evolve(self, **changes):
|
def evolve(self, **changes):
|
||||||
"""
|
"""
|
||||||
Copy *self* and apply *changes*.
|
Copy *self* and apply *changes*.
|
||||||
|
|
||||||
This works similarly to `attr.evolve` but that function does not work
|
This works similarly to `attrs.evolve` but that function does not work
|
||||||
with ``Attribute``.
|
with `Attribute`.
|
||||||
|
|
||||||
It is mainly meant to be used for `transform-fields`.
|
It is mainly meant to be used for `transform-fields`.
|
||||||
|
|
||||||
|
@ -2777,10 +2803,6 @@ class Factory:
|
||||||
__slots__ = ("factory", "takes_self")
|
__slots__ = ("factory", "takes_self")
|
||||||
|
|
||||||
def __init__(self, factory, takes_self=False):
|
def __init__(self, factory, takes_self=False):
|
||||||
"""
|
|
||||||
`Factory` is part of the default machinery so if we want a default
|
|
||||||
value here, we have to implement it ourselves.
|
|
||||||
"""
|
|
||||||
self.factory = factory
|
self.factory = factory
|
||||||
self.takes_self = takes_self
|
self.takes_self = takes_self
|
||||||
|
|
||||||
|
@ -2818,13 +2840,13 @@ Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f)
|
||||||
|
|
||||||
|
|
||||||
def make_class(name, attrs, bases=(object,), **attributes_arguments):
|
def make_class(name, attrs, bases=(object,), **attributes_arguments):
|
||||||
"""
|
r"""
|
||||||
A quick way to create a new class called *name* with *attrs*.
|
A quick way to create a new class called *name* with *attrs*.
|
||||||
|
|
||||||
:param str name: The name for the new class.
|
:param str name: The name for the new class.
|
||||||
|
|
||||||
:param attrs: A list of names or a dictionary of mappings of names to
|
:param attrs: A list of names or a dictionary of mappings of names to
|
||||||
attributes.
|
`attr.ib`\ s / `attrs.field`\ s.
|
||||||
|
|
||||||
The order is deduced from the order of the names or attributes inside
|
The order is deduced from the order of the names or attributes inside
|
||||||
*attrs*. Otherwise the order of the definition of the attributes is
|
*attrs*. Otherwise the order of the definition of the attributes is
|
||||||
|
|
|
@ -46,7 +46,7 @@ def define(
|
||||||
match_args=True,
|
match_args=True,
|
||||||
):
|
):
|
||||||
r"""
|
r"""
|
||||||
Define an ``attrs`` class.
|
Define an *attrs* class.
|
||||||
|
|
||||||
Differences to the classic `attr.s` that it uses underneath:
|
Differences to the classic `attr.s` that it uses underneath:
|
||||||
|
|
||||||
|
@ -167,6 +167,7 @@ def field(
|
||||||
hash=None,
|
hash=None,
|
||||||
init=True,
|
init=True,
|
||||||
metadata=None,
|
metadata=None,
|
||||||
|
type=None,
|
||||||
converter=None,
|
converter=None,
|
||||||
factory=None,
|
factory=None,
|
||||||
kw_only=False,
|
kw_only=False,
|
||||||
|
@ -179,6 +180,10 @@ def field(
|
||||||
Identical to `attr.ib`, except keyword-only and with some arguments
|
Identical to `attr.ib`, except keyword-only and with some arguments
|
||||||
removed.
|
removed.
|
||||||
|
|
||||||
|
.. versionadded:: 22.3.0
|
||||||
|
The *type* parameter has been re-added; mostly for
|
||||||
|
{func}`attrs.make_class`. Please note that type checkers ignore this
|
||||||
|
metadata.
|
||||||
.. versionadded:: 20.1.0
|
.. versionadded:: 20.1.0
|
||||||
"""
|
"""
|
||||||
return attrib(
|
return attrib(
|
||||||
|
@ -188,6 +193,7 @@ def field(
|
||||||
hash=hash,
|
hash=hash,
|
||||||
init=init,
|
init=init,
|
||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
|
type=type,
|
||||||
converter=converter,
|
converter=converter,
|
||||||
factory=factory,
|
factory=factory,
|
||||||
kw_only=kw_only,
|
kw_only=kw_only,
|
||||||
|
|
|
@ -34,7 +34,7 @@ class FrozenAttributeError(FrozenError):
|
||||||
|
|
||||||
class AttrsAttributeNotFoundError(ValueError):
|
class AttrsAttributeNotFoundError(ValueError):
|
||||||
"""
|
"""
|
||||||
An ``attrs`` function couldn't find an attribute that the user asked for.
|
An *attrs* function couldn't find an attribute that the user asked for.
|
||||||
|
|
||||||
.. versionadded:: 16.2.0
|
.. versionadded:: 16.2.0
|
||||||
"""
|
"""
|
||||||
|
@ -42,7 +42,7 @@ class AttrsAttributeNotFoundError(ValueError):
|
||||||
|
|
||||||
class NotAnAttrsClassError(ValueError):
|
class NotAnAttrsClassError(ValueError):
|
||||||
"""
|
"""
|
||||||
A non-``attrs`` class has been passed into an ``attrs`` function.
|
A non-*attrs* class has been passed into an *attrs* function.
|
||||||
|
|
||||||
.. versionadded:: 16.2.0
|
.. versionadded:: 16.2.0
|
||||||
"""
|
"""
|
||||||
|
@ -50,7 +50,7 @@ class NotAnAttrsClassError(ValueError):
|
||||||
|
|
||||||
class DefaultAlreadySetError(RuntimeError):
|
class DefaultAlreadySetError(RuntimeError):
|
||||||
"""
|
"""
|
||||||
A default has been set using ``attr.ib()`` and is attempted to be reset
|
A default has been set when defining the field and is attempted to be reset
|
||||||
using the decorator.
|
using the decorator.
|
||||||
|
|
||||||
.. versionadded:: 17.1.0
|
.. versionadded:: 17.1.0
|
||||||
|
@ -59,8 +59,7 @@ class DefaultAlreadySetError(RuntimeError):
|
||||||
|
|
||||||
class UnannotatedAttributeError(RuntimeError):
|
class UnannotatedAttributeError(RuntimeError):
|
||||||
"""
|
"""
|
||||||
A class with ``auto_attribs=True`` has an ``attr.ib()`` without a type
|
A class with ``auto_attribs=True`` has a field without a type annotation.
|
||||||
annotation.
|
|
||||||
|
|
||||||
.. versionadded:: 17.3.0
|
.. versionadded:: 17.3.0
|
||||||
"""
|
"""
|
||||||
|
@ -68,7 +67,7 @@ class UnannotatedAttributeError(RuntimeError):
|
||||||
|
|
||||||
class PythonTooOldError(RuntimeError):
|
class PythonTooOldError(RuntimeError):
|
||||||
"""
|
"""
|
||||||
It was attempted to use an ``attrs`` feature that requires a newer Python
|
It was attempted to use an *attrs* feature that requires a newer Python
|
||||||
version.
|
version.
|
||||||
|
|
||||||
.. versionadded:: 18.2.0
|
.. versionadded:: 18.2.0
|
||||||
|
@ -77,8 +76,8 @@ class PythonTooOldError(RuntimeError):
|
||||||
|
|
||||||
class NotCallableError(TypeError):
|
class NotCallableError(TypeError):
|
||||||
"""
|
"""
|
||||||
A ``attr.ib()`` requiring a callable has been set with a value
|
A field requiring a callable has been set with a value that is not
|
||||||
that is not callable.
|
callable.
|
||||||
|
|
||||||
.. versionadded:: 19.2.0
|
.. versionadded:: 19.2.0
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -9,6 +9,7 @@ import operator
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from re import Pattern
|
||||||
|
|
||||||
from ._config import get_run_validators, set_run_validators
|
from ._config import get_run_validators, set_run_validators
|
||||||
from ._make import _AndValidator, and_, attrib, attrs
|
from ._make import _AndValidator, and_, attrib, attrs
|
||||||
|
@ -16,12 +17,6 @@ from .converters import default_if_none
|
||||||
from .exceptions import NotCallableError
|
from .exceptions import NotCallableError
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
Pattern = re.Pattern
|
|
||||||
except AttributeError: # Python <3.7 lacks a Pattern type.
|
|
||||||
Pattern = type(re.compile(""))
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"and_",
|
"and_",
|
||||||
"deep_iterable",
|
"deep_iterable",
|
||||||
|
@ -249,7 +244,17 @@ def provides(interface):
|
||||||
:raises TypeError: With a human readable error message, the attribute
|
:raises TypeError: With a human readable error message, the attribute
|
||||||
(of type `attrs.Attribute`), the expected interface, and the
|
(of type `attrs.Attribute`), the expected interface, and the
|
||||||
value it got.
|
value it got.
|
||||||
|
|
||||||
|
.. deprecated:: 23.1.0
|
||||||
"""
|
"""
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
"attrs's zope-interface support is deprecated and will be removed in, "
|
||||||
|
"or after, April 2024.",
|
||||||
|
DeprecationWarning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
return _ProvidesValidator(interface)
|
return _ProvidesValidator(interface)
|
||||||
|
|
||||||
|
|
||||||
|
@ -275,15 +280,16 @@ def optional(validator):
|
||||||
which can be set to ``None`` in addition to satisfying the requirements of
|
which can be set to ``None`` in addition to satisfying the requirements of
|
||||||
the sub-validator.
|
the sub-validator.
|
||||||
|
|
||||||
:param validator: A validator (or a list of validators) that is used for
|
:param Callable | tuple[Callable] | list[Callable] validator: A validator
|
||||||
non-``None`` values.
|
(or validators) that is used for non-``None`` values.
|
||||||
:type validator: callable or `list` of callables.
|
|
||||||
|
|
||||||
.. versionadded:: 15.1.0
|
.. versionadded:: 15.1.0
|
||||||
.. versionchanged:: 17.1.0 *validator* can be a list of validators.
|
.. versionchanged:: 17.1.0 *validator* can be a list of validators.
|
||||||
|
.. versionchanged:: 23.1.0 *validator* can also be a tuple of validators.
|
||||||
"""
|
"""
|
||||||
if isinstance(validator, list):
|
if isinstance(validator, (list, tuple)):
|
||||||
return _OptionalValidator(_AndValidator(validator))
|
return _OptionalValidator(_AndValidator(validator))
|
||||||
|
|
||||||
return _OptionalValidator(validator)
|
return _OptionalValidator(validator)
|
||||||
|
|
||||||
|
|
||||||
|
@ -359,13 +365,13 @@ class _IsCallableValidator:
|
||||||
|
|
||||||
def is_callable():
|
def is_callable():
|
||||||
"""
|
"""
|
||||||
A validator that raises a `attr.exceptions.NotCallableError` if the
|
A validator that raises a `attrs.exceptions.NotCallableError` if the
|
||||||
initializer is called with a value for this particular attribute
|
initializer is called with a value for this particular attribute
|
||||||
that is not callable.
|
that is not callable.
|
||||||
|
|
||||||
.. versionadded:: 19.1.0
|
.. versionadded:: 19.1.0
|
||||||
|
|
||||||
:raises `attr.exceptions.NotCallableError`: With a human readable error
|
:raises attrs.exceptions.NotCallableError: With a human readable error
|
||||||
message containing the attribute (`attrs.Attribute`) name,
|
message containing the attribute (`attrs.Attribute`) name,
|
||||||
and the value it got.
|
and the value it got.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -51,7 +51,9 @@ def instance_of(
|
||||||
def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ...
|
def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ...
|
||||||
def provides(interface: Any) -> _ValidatorType[Any]: ...
|
def provides(interface: Any) -> _ValidatorType[Any]: ...
|
||||||
def optional(
|
def optional(
|
||||||
validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]]
|
validator: Union[
|
||||||
|
_ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_ValidatorType[_T]]
|
||||||
|
]
|
||||||
) -> _ValidatorType[Optional[_T]]: ...
|
) -> _ValidatorType[Optional[_T]]: ...
|
||||||
def in_(options: Container[_T]) -> _ValidatorType[_T]: ...
|
def in_(options: Container[_T]) -> _ValidatorType[_T]: ...
|
||||||
def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ...
|
def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ...
|
||||||
|
@ -82,5 +84,5 @@ def not_(
|
||||||
validator: _ValidatorType[_T],
|
validator: _ValidatorType[_T],
|
||||||
*,
|
*,
|
||||||
msg: Optional[str] = None,
|
msg: Optional[str] = None,
|
||||||
exc_types: Union[Type[Exception], Iterable[Type[Exception]]] = ...
|
exc_types: Union[Type[Exception], Iterable[Type[Exception]]] = ...,
|
||||||
) -> _ValidatorType[_T]: ...
|
) -> _ValidatorType[_T]: ...
|
||||||
|
|
Loading…
Reference in a new issue