mirror of
https://github.com/SickGear/SickGear.git
synced 2024-11-24 22:05:05 +00:00
Merge branch 'feature/UpdateAttr' into dev
This commit is contained in:
commit
340c79fcbd
16 changed files with 738 additions and 1002 deletions
|
@ -1,5 +1,6 @@
|
||||||
### 3.32.0 (2024-xx-xx xx:xx:00 UTC)
|
### 3.32.0 (2024-xx-xx xx:xx:00 UTC)
|
||||||
|
|
||||||
|
* Update attr 23.1.0 (67e4ff2) to 23.2.0 (b393d79)
|
||||||
* Update Beautiful Soup 4.12.2 (30c58a1) to 4.12.3 (7fb5175)
|
* Update Beautiful Soup 4.12.2 (30c58a1) to 4.12.3 (7fb5175)
|
||||||
* Update CacheControl 0.13.1 (783a338) to 0.14.0 (e2be0c2)
|
* Update CacheControl 0.13.1 (783a338) to 0.14.0 (e2be0c2)
|
||||||
* Update certifi 2024.02.02 to 2024.06.02
|
* Update certifi 2024.02.02 to 2024.06.02
|
||||||
|
|
|
@ -79,54 +79,21 @@ def _make_getattr(mod_name: str) -> Callable:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __getattr__(name: str) -> str:
|
def __getattr__(name: str) -> str:
|
||||||
dunder_to_metadata = {
|
if name not in ("__version__", "__version_info__"):
|
||||||
"__title__": "Name",
|
|
||||||
"__copyright__": "",
|
|
||||||
"__version__": "version",
|
|
||||||
"__version_info__": "version",
|
|
||||||
"__description__": "summary",
|
|
||||||
"__uri__": "",
|
|
||||||
"__url__": "",
|
|
||||||
"__author__": "",
|
|
||||||
"__email__": "",
|
|
||||||
"__license__": "license",
|
|
||||||
}
|
|
||||||
if name not in dunder_to_metadata:
|
|
||||||
msg = f"module {mod_name} has no attribute {name}"
|
msg = f"module {mod_name} has no attribute {name}"
|
||||||
raise AttributeError(msg)
|
raise AttributeError(msg)
|
||||||
|
|
||||||
import sys
|
try:
|
||||||
import warnings
|
|
||||||
|
|
||||||
if sys.version_info < (3, 8):
|
|
||||||
from importlib_metadata import metadata
|
|
||||||
else:
|
|
||||||
from importlib.metadata import metadata
|
from importlib.metadata import metadata
|
||||||
|
except ImportError:
|
||||||
if name not in ("__version__", "__version_info__"):
|
from importlib_metadata import metadata
|
||||||
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")
|
meta = metadata("attrs")
|
||||||
if name == "__license__":
|
|
||||||
return "MIT"
|
|
||||||
if name == "__copyright__":
|
|
||||||
return "Copyright (c) 2015 Hynek Schlawack"
|
|
||||||
if name in ("__uri__", "__url__"):
|
|
||||||
return meta["Project-URL"].split(" ", 1)[-1]
|
|
||||||
if name == "__version_info__":
|
if name == "__version_info__":
|
||||||
return VersionInfo._from_version_string(meta["version"])
|
return VersionInfo._from_version_string(meta["version"])
|
||||||
if name == "__author__":
|
|
||||||
return meta["Author-email"].rsplit(" ", 1)[0]
|
|
||||||
if name == "__email__":
|
|
||||||
return meta["Author-email"].rsplit("<", 1)[1][:-1]
|
|
||||||
|
|
||||||
return meta[dunder_to_metadata[name]]
|
return meta["version"]
|
||||||
|
|
||||||
return __getattr__
|
return __getattr__
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,11 @@ import sys
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
Callable,
|
Callable,
|
||||||
Dict,
|
|
||||||
Generic,
|
Generic,
|
||||||
List,
|
|
||||||
Mapping,
|
Mapping,
|
||||||
Optional,
|
|
||||||
Protocol,
|
Protocol,
|
||||||
Sequence,
|
Sequence,
|
||||||
Tuple,
|
|
||||||
Type,
|
|
||||||
TypeVar,
|
TypeVar,
|
||||||
Union,
|
|
||||||
overload,
|
overload,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +21,20 @@ from . import validators as validators
|
||||||
from ._cmp import cmp_using as cmp_using
|
from ._cmp import cmp_using as cmp_using
|
||||||
from ._typing_compat import AttrsInstance_
|
from ._typing_compat import AttrsInstance_
|
||||||
from ._version_info import VersionInfo
|
from ._version_info import VersionInfo
|
||||||
|
from attrs import (
|
||||||
|
define as define,
|
||||||
|
field as field,
|
||||||
|
mutable as mutable,
|
||||||
|
frozen as frozen,
|
||||||
|
_EqOrderType,
|
||||||
|
_ValidatorType,
|
||||||
|
_ConverterType,
|
||||||
|
_ReprArgType,
|
||||||
|
_OnSetAttrType,
|
||||||
|
_OnSetAttrArgType,
|
||||||
|
_FieldTransformer,
|
||||||
|
_ValidatorArgType,
|
||||||
|
)
|
||||||
|
|
||||||
if sys.version_info >= (3, 10):
|
if sys.version_info >= (3, 10):
|
||||||
from typing import TypeGuard
|
from typing import TypeGuard
|
||||||
|
@ -52,23 +60,7 @@ __copyright__: str
|
||||||
_T = TypeVar("_T")
|
_T = TypeVar("_T")
|
||||||
_C = TypeVar("_C", bound=type)
|
_C = TypeVar("_C", bound=type)
|
||||||
|
|
||||||
_EqOrderType = Union[bool, Callable[[Any], Any]]
|
|
||||||
_ValidatorType = Callable[[Any, "Attribute[_T]", _T], Any]
|
|
||||||
_ConverterType = Callable[[Any], Any]
|
|
||||||
_FilterType = Callable[["Attribute[_T]", _T], bool]
|
_FilterType = Callable[["Attribute[_T]", _T], bool]
|
||||||
_ReprType = Callable[[Any], str]
|
|
||||||
_ReprArgType = Union[bool, _ReprType]
|
|
||||||
_OnSetAttrType = Callable[[Any, "Attribute[Any]", Any], Any]
|
|
||||||
_OnSetAttrArgType = Union[
|
|
||||||
_OnSetAttrType, List[_OnSetAttrType], setters._NoOpType
|
|
||||||
]
|
|
||||||
_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.
|
|
||||||
_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]]
|
|
||||||
|
|
||||||
# We subclass this here to keep the protocol's qualified name clean.
|
# We subclass this here to keep the protocol's qualified name clean.
|
||||||
class AttrsInstance(AttrsInstance_, Protocol):
|
class AttrsInstance(AttrsInstance_, Protocol):
|
||||||
|
@ -110,20 +102,20 @@ else:
|
||||||
|
|
||||||
class Attribute(Generic[_T]):
|
class Attribute(Generic[_T]):
|
||||||
name: str
|
name: str
|
||||||
default: Optional[_T]
|
default: _T | None
|
||||||
validator: Optional[_ValidatorType[_T]]
|
validator: _ValidatorType[_T] | None
|
||||||
repr: _ReprArgType
|
repr: _ReprArgType
|
||||||
cmp: _EqOrderType
|
cmp: _EqOrderType
|
||||||
eq: _EqOrderType
|
eq: _EqOrderType
|
||||||
order: _EqOrderType
|
order: _EqOrderType
|
||||||
hash: Optional[bool]
|
hash: bool | None
|
||||||
init: bool
|
init: bool
|
||||||
converter: Optional[_ConverterType]
|
converter: _ConverterType | None
|
||||||
metadata: Dict[Any, Any]
|
metadata: dict[Any, Any]
|
||||||
type: Optional[Type[_T]]
|
type: type[_T] | None
|
||||||
kw_only: bool
|
kw_only: bool
|
||||||
on_setattr: _OnSetAttrType
|
on_setattr: _OnSetAttrType
|
||||||
alias: Optional[str]
|
alias: str | None
|
||||||
|
|
||||||
def evolve(self, **changes: Any) -> "Attribute[Any]": ...
|
def evolve(self, **changes: Any) -> "Attribute[Any]": ...
|
||||||
|
|
||||||
|
@ -156,18 +148,18 @@ def attrib(
|
||||||
default: None = ...,
|
default: None = ...,
|
||||||
validator: None = ...,
|
validator: None = ...,
|
||||||
repr: _ReprArgType = ...,
|
repr: _ReprArgType = ...,
|
||||||
cmp: Optional[_EqOrderType] = ...,
|
cmp: _EqOrderType | None = ...,
|
||||||
hash: Optional[bool] = ...,
|
hash: bool | None = ...,
|
||||||
init: bool = ...,
|
init: bool = ...,
|
||||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
metadata: Mapping[Any, Any] | None = ...,
|
||||||
type: None = ...,
|
type: None = ...,
|
||||||
converter: None = ...,
|
converter: None = ...,
|
||||||
factory: None = ...,
|
factory: None = ...,
|
||||||
kw_only: bool = ...,
|
kw_only: bool = ...,
|
||||||
eq: Optional[_EqOrderType] = ...,
|
eq: _EqOrderType | None = ...,
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: _EqOrderType | None = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: _OnSetAttrArgType | None = ...,
|
||||||
alias: Optional[str] = ...,
|
alias: str | None = ...,
|
||||||
) -> 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
|
||||||
|
@ -175,149 +167,70 @@ def attrib(
|
||||||
@overload
|
@overload
|
||||||
def attrib(
|
def attrib(
|
||||||
default: None = ...,
|
default: None = ...,
|
||||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
validator: _ValidatorArgType[_T] | None = ...,
|
||||||
repr: _ReprArgType = ...,
|
repr: _ReprArgType = ...,
|
||||||
cmp: Optional[_EqOrderType] = ...,
|
cmp: _EqOrderType | None = ...,
|
||||||
hash: Optional[bool] = ...,
|
hash: bool | None = ...,
|
||||||
init: bool = ...,
|
init: bool = ...,
|
||||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
metadata: Mapping[Any, Any] | None = ...,
|
||||||
type: Optional[Type[_T]] = ...,
|
type: type[_T] | None = ...,
|
||||||
converter: Optional[_ConverterType] = ...,
|
converter: _ConverterType | None = ...,
|
||||||
factory: Optional[Callable[[], _T]] = ...,
|
factory: Callable[[], _T] | None = ...,
|
||||||
kw_only: bool = ...,
|
kw_only: bool = ...,
|
||||||
eq: Optional[_EqOrderType] = ...,
|
eq: _EqOrderType | None = ...,
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: _EqOrderType | None = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: _OnSetAttrArgType | None = ...,
|
||||||
alias: Optional[str] = ...,
|
alias: str | None = ...,
|
||||||
) -> _T: ...
|
) -> _T: ...
|
||||||
|
|
||||||
# This form catches an explicit default argument.
|
# This form catches an explicit default argument.
|
||||||
@overload
|
@overload
|
||||||
def attrib(
|
def attrib(
|
||||||
default: _T,
|
default: _T,
|
||||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
validator: _ValidatorArgType[_T] | None = ...,
|
||||||
repr: _ReprArgType = ...,
|
repr: _ReprArgType = ...,
|
||||||
cmp: Optional[_EqOrderType] = ...,
|
cmp: _EqOrderType | None = ...,
|
||||||
hash: Optional[bool] = ...,
|
hash: bool | None = ...,
|
||||||
init: bool = ...,
|
init: bool = ...,
|
||||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
metadata: Mapping[Any, Any] | None = ...,
|
||||||
type: Optional[Type[_T]] = ...,
|
type: type[_T] | None = ...,
|
||||||
converter: Optional[_ConverterType] = ...,
|
converter: _ConverterType | None = ...,
|
||||||
factory: Optional[Callable[[], _T]] = ...,
|
factory: Callable[[], _T] | None = ...,
|
||||||
kw_only: bool = ...,
|
kw_only: bool = ...,
|
||||||
eq: Optional[_EqOrderType] = ...,
|
eq: _EqOrderType | None = ...,
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: _EqOrderType | None = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: _OnSetAttrArgType | None = ...,
|
||||||
alias: Optional[str] = ...,
|
alias: str | None = ...,
|
||||||
) -> _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
|
||||||
@overload
|
@overload
|
||||||
def attrib(
|
def attrib(
|
||||||
default: Optional[_T] = ...,
|
default: _T | None = ...,
|
||||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
validator: _ValidatorArgType[_T] | None = ...,
|
||||||
repr: _ReprArgType = ...,
|
repr: _ReprArgType = ...,
|
||||||
cmp: Optional[_EqOrderType] = ...,
|
cmp: _EqOrderType | None = ...,
|
||||||
hash: Optional[bool] = ...,
|
hash: bool | None = ...,
|
||||||
init: bool = ...,
|
init: bool = ...,
|
||||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
metadata: Mapping[Any, Any] | None = ...,
|
||||||
type: object = ...,
|
type: object = ...,
|
||||||
converter: Optional[_ConverterType] = ...,
|
converter: _ConverterType | None = ...,
|
||||||
factory: Optional[Callable[[], _T]] = ...,
|
factory: Callable[[], _T] | None = ...,
|
||||||
kw_only: bool = ...,
|
kw_only: bool = ...,
|
||||||
eq: Optional[_EqOrderType] = ...,
|
eq: _EqOrderType | None = ...,
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: _EqOrderType | None = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: _OnSetAttrArgType | None = ...,
|
||||||
alias: Optional[str] = ...,
|
alias: str | None = ...,
|
||||||
) -> Any: ...
|
|
||||||
@overload
|
|
||||||
def field(
|
|
||||||
*,
|
|
||||||
default: None = ...,
|
|
||||||
validator: None = ...,
|
|
||||||
repr: _ReprArgType = ...,
|
|
||||||
hash: Optional[bool] = ...,
|
|
||||||
init: bool = ...,
|
|
||||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
|
||||||
converter: None = ...,
|
|
||||||
factory: None = ...,
|
|
||||||
kw_only: bool = ...,
|
|
||||||
eq: Optional[bool] = ...,
|
|
||||||
order: Optional[bool] = ...,
|
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
|
||||||
alias: Optional[str] = ...,
|
|
||||||
type: Optional[type] = ...,
|
|
||||||
) -> Any: ...
|
|
||||||
|
|
||||||
# This form catches an explicit None or no default and infers the type from the
|
|
||||||
# other arguments.
|
|
||||||
@overload
|
|
||||||
def field(
|
|
||||||
*,
|
|
||||||
default: None = ...,
|
|
||||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
|
||||||
repr: _ReprArgType = ...,
|
|
||||||
hash: Optional[bool] = ...,
|
|
||||||
init: bool = ...,
|
|
||||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
|
||||||
converter: Optional[_ConverterType] = ...,
|
|
||||||
factory: Optional[Callable[[], _T]] = ...,
|
|
||||||
kw_only: bool = ...,
|
|
||||||
eq: Optional[_EqOrderType] = ...,
|
|
||||||
order: Optional[_EqOrderType] = ...,
|
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
|
||||||
alias: Optional[str] = ...,
|
|
||||||
type: Optional[type] = ...,
|
|
||||||
) -> _T: ...
|
|
||||||
|
|
||||||
# This form catches an explicit default argument.
|
|
||||||
@overload
|
|
||||||
def field(
|
|
||||||
*,
|
|
||||||
default: _T,
|
|
||||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
|
||||||
repr: _ReprArgType = ...,
|
|
||||||
hash: Optional[bool] = ...,
|
|
||||||
init: bool = ...,
|
|
||||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
|
||||||
converter: Optional[_ConverterType] = ...,
|
|
||||||
factory: Optional[Callable[[], _T]] = ...,
|
|
||||||
kw_only: bool = ...,
|
|
||||||
eq: Optional[_EqOrderType] = ...,
|
|
||||||
order: Optional[_EqOrderType] = ...,
|
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
|
||||||
alias: Optional[str] = ...,
|
|
||||||
type: Optional[type] = ...,
|
|
||||||
) -> _T: ...
|
|
||||||
|
|
||||||
# This form covers type=non-Type: e.g. forward references (str), Any
|
|
||||||
@overload
|
|
||||||
def field(
|
|
||||||
*,
|
|
||||||
default: Optional[_T] = ...,
|
|
||||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
|
||||||
repr: _ReprArgType = ...,
|
|
||||||
hash: Optional[bool] = ...,
|
|
||||||
init: bool = ...,
|
|
||||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
|
||||||
converter: Optional[_ConverterType] = ...,
|
|
||||||
factory: Optional[Callable[[], _T]] = ...,
|
|
||||||
kw_only: bool = ...,
|
|
||||||
eq: Optional[_EqOrderType] = ...,
|
|
||||||
order: Optional[_EqOrderType] = ...,
|
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
|
||||||
alias: Optional[str] = ...,
|
|
||||||
type: Optional[type] = ...,
|
|
||||||
) -> Any: ...
|
) -> Any: ...
|
||||||
@overload
|
@overload
|
||||||
@dataclass_transform(order_default=True, field_specifiers=(attrib, field))
|
@dataclass_transform(order_default=True, field_specifiers=(attrib, field))
|
||||||
def attrs(
|
def attrs(
|
||||||
maybe_cls: _C,
|
maybe_cls: _C,
|
||||||
these: Optional[Dict[str, Any]] = ...,
|
these: dict[str, Any] | None = ...,
|
||||||
repr_ns: Optional[str] = ...,
|
repr_ns: str | None = ...,
|
||||||
repr: bool = ...,
|
repr: bool = ...,
|
||||||
cmp: Optional[_EqOrderType] = ...,
|
cmp: _EqOrderType | None = ...,
|
||||||
hash: Optional[bool] = ...,
|
hash: bool | None = ...,
|
||||||
init: bool = ...,
|
init: bool = ...,
|
||||||
slots: bool = ...,
|
slots: bool = ...,
|
||||||
frozen: bool = ...,
|
frozen: bool = ...,
|
||||||
|
@ -327,25 +240,25 @@ def attrs(
|
||||||
kw_only: bool = ...,
|
kw_only: bool = ...,
|
||||||
cache_hash: bool = ...,
|
cache_hash: bool = ...,
|
||||||
auto_exc: bool = ...,
|
auto_exc: bool = ...,
|
||||||
eq: Optional[_EqOrderType] = ...,
|
eq: _EqOrderType | None = ...,
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: _EqOrderType | None = ...,
|
||||||
auto_detect: bool = ...,
|
auto_detect: bool = ...,
|
||||||
collect_by_mro: bool = ...,
|
collect_by_mro: bool = ...,
|
||||||
getstate_setstate: Optional[bool] = ...,
|
getstate_setstate: bool | None = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: _OnSetAttrArgType | None = ...,
|
||||||
field_transformer: Optional[_FieldTransformer] = ...,
|
field_transformer: _FieldTransformer | None = ...,
|
||||||
match_args: bool = ...,
|
match_args: bool = ...,
|
||||||
unsafe_hash: Optional[bool] = ...,
|
unsafe_hash: bool | None = ...,
|
||||||
) -> _C: ...
|
) -> _C: ...
|
||||||
@overload
|
@overload
|
||||||
@dataclass_transform(order_default=True, field_specifiers=(attrib, field))
|
@dataclass_transform(order_default=True, field_specifiers=(attrib, field))
|
||||||
def attrs(
|
def attrs(
|
||||||
maybe_cls: None = ...,
|
maybe_cls: None = ...,
|
||||||
these: Optional[Dict[str, Any]] = ...,
|
these: dict[str, Any] | None = ...,
|
||||||
repr_ns: Optional[str] = ...,
|
repr_ns: str | None = ...,
|
||||||
repr: bool = ...,
|
repr: bool = ...,
|
||||||
cmp: Optional[_EqOrderType] = ...,
|
cmp: _EqOrderType | None = ...,
|
||||||
hash: Optional[bool] = ...,
|
hash: bool | None = ...,
|
||||||
init: bool = ...,
|
init: bool = ...,
|
||||||
slots: bool = ...,
|
slots: bool = ...,
|
||||||
frozen: bool = ...,
|
frozen: bool = ...,
|
||||||
|
@ -355,131 +268,24 @@ def attrs(
|
||||||
kw_only: bool = ...,
|
kw_only: bool = ...,
|
||||||
cache_hash: bool = ...,
|
cache_hash: bool = ...,
|
||||||
auto_exc: bool = ...,
|
auto_exc: bool = ...,
|
||||||
eq: Optional[_EqOrderType] = ...,
|
eq: _EqOrderType | None = ...,
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: _EqOrderType | None = ...,
|
||||||
auto_detect: bool = ...,
|
auto_detect: bool = ...,
|
||||||
collect_by_mro: bool = ...,
|
collect_by_mro: bool = ...,
|
||||||
getstate_setstate: Optional[bool] = ...,
|
getstate_setstate: bool | None = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: _OnSetAttrArgType | None = ...,
|
||||||
field_transformer: Optional[_FieldTransformer] = ...,
|
field_transformer: _FieldTransformer | None = ...,
|
||||||
match_args: bool = ...,
|
match_args: bool = ...,
|
||||||
unsafe_hash: Optional[bool] = ...,
|
unsafe_hash: bool | None = ...,
|
||||||
) -> Callable[[_C], _C]: ...
|
) -> Callable[[_C], _C]: ...
|
||||||
@overload
|
def fields(cls: type[AttrsInstance]) -> Any: ...
|
||||||
@dataclass_transform(field_specifiers=(attrib, field))
|
def fields_dict(cls: type[AttrsInstance]) -> dict[str, Attribute[Any]]: ...
|
||||||
def define(
|
|
||||||
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(field_specifiers=(attrib, field))
|
|
||||||
def define(
|
|
||||||
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]: ...
|
|
||||||
|
|
||||||
mutable = define
|
|
||||||
|
|
||||||
@overload
|
|
||||||
@dataclass_transform(frozen_default=True, field_specifiers=(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_specifiers=(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_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: _A,
|
cls: _A,
|
||||||
globalns: Optional[Dict[str, Any]] = ...,
|
globalns: dict[str, Any] | None = ...,
|
||||||
localns: Optional[Dict[str, Any]] = ...,
|
localns: dict[str, Any] | None = ...,
|
||||||
attribs: Optional[List[Attribute[Any]]] = ...,
|
attribs: list[Attribute[Any]] | None = ...,
|
||||||
include_extras: bool = ...,
|
include_extras: bool = ...,
|
||||||
) -> _A: ...
|
) -> _A: ...
|
||||||
|
|
||||||
|
@ -488,12 +294,13 @@ def resolve_types(
|
||||||
# [attr.ib()])` is valid
|
# [attr.ib()])` is valid
|
||||||
def make_class(
|
def make_class(
|
||||||
name: str,
|
name: str,
|
||||||
attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]],
|
attrs: list[str] | tuple[str, ...] | dict[str, Any],
|
||||||
bases: Tuple[type, ...] = ...,
|
bases: tuple[type, ...] = ...,
|
||||||
repr_ns: Optional[str] = ...,
|
class_body: dict[str, Any] | None = ...,
|
||||||
|
repr_ns: str | None = ...,
|
||||||
repr: bool = ...,
|
repr: bool = ...,
|
||||||
cmp: Optional[_EqOrderType] = ...,
|
cmp: _EqOrderType | None = ...,
|
||||||
hash: Optional[bool] = ...,
|
hash: bool | None = ...,
|
||||||
init: bool = ...,
|
init: bool = ...,
|
||||||
slots: bool = ...,
|
slots: bool = ...,
|
||||||
frozen: bool = ...,
|
frozen: bool = ...,
|
||||||
|
@ -503,11 +310,11 @@ def make_class(
|
||||||
kw_only: bool = ...,
|
kw_only: bool = ...,
|
||||||
cache_hash: bool = ...,
|
cache_hash: bool = ...,
|
||||||
auto_exc: bool = ...,
|
auto_exc: bool = ...,
|
||||||
eq: Optional[_EqOrderType] = ...,
|
eq: _EqOrderType | None = ...,
|
||||||
order: Optional[_EqOrderType] = ...,
|
order: _EqOrderType | None = ...,
|
||||||
collect_by_mro: bool = ...,
|
collect_by_mro: bool = ...,
|
||||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
on_setattr: _OnSetAttrArgType | None = ...,
|
||||||
field_transformer: Optional[_FieldTransformer] = ...,
|
field_transformer: _FieldTransformer | None = ...,
|
||||||
) -> type: ...
|
) -> type: ...
|
||||||
|
|
||||||
# _funcs --
|
# _funcs --
|
||||||
|
@ -521,24 +328,22 @@ def make_class(
|
||||||
def asdict(
|
def asdict(
|
||||||
inst: AttrsInstance,
|
inst: AttrsInstance,
|
||||||
recurse: bool = ...,
|
recurse: bool = ...,
|
||||||
filter: Optional[_FilterType[Any]] = ...,
|
filter: _FilterType[Any] | None = ...,
|
||||||
dict_factory: Type[Mapping[Any, Any]] = ...,
|
dict_factory: type[Mapping[Any, Any]] = ...,
|
||||||
retain_collection_types: bool = ...,
|
retain_collection_types: bool = ...,
|
||||||
value_serializer: Optional[
|
value_serializer: Callable[[type, Attribute[Any], Any], Any] | None = ...,
|
||||||
Callable[[type, Attribute[Any], Any], Any]
|
tuple_keys: bool | None = ...,
|
||||||
] = ...,
|
) -> dict[str, Any]: ...
|
||||||
tuple_keys: Optional[bool] = ...,
|
|
||||||
) -> Dict[str, Any]: ...
|
|
||||||
|
|
||||||
# TODO: add support for returning NamedTuple from the mypy plugin
|
# TODO: add support for returning NamedTuple from the mypy plugin
|
||||||
def astuple(
|
def astuple(
|
||||||
inst: AttrsInstance,
|
inst: AttrsInstance,
|
||||||
recurse: bool = ...,
|
recurse: bool = ...,
|
||||||
filter: Optional[_FilterType[Any]] = ...,
|
filter: _FilterType[Any] | None = ...,
|
||||||
tuple_factory: Type[Sequence[Any]] = ...,
|
tuple_factory: type[Sequence[Any]] = ...,
|
||||||
retain_collection_types: bool = ...,
|
retain_collection_types: bool = ...,
|
||||||
) -> Tuple[Any, ...]: ...
|
) -> tuple[Any, ...]: ...
|
||||||
def has(cls: type) -> TypeGuard[Type[AttrsInstance]]: ...
|
def has(cls: type) -> TypeGuard[type[AttrsInstance]]: ...
|
||||||
def assoc(inst: _T, **changes: Any) -> _T: ...
|
def assoc(inst: _T, **changes: Any) -> _T: ...
|
||||||
def evolve(inst: _T, **changes: Any) -> _T: ...
|
def evolve(inst: _T, **changes: Any) -> _T: ...
|
||||||
|
|
||||||
|
|
|
@ -26,21 +26,21 @@ def cmp_using(
|
||||||
The resulting class will have a full set of ordering methods if at least
|
The resulting class will have a full set of ordering methods if 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 of two
|
:param typing.Callable | None eq: Callable used to evaluate equality of two
|
||||||
objects.
|
objects.
|
||||||
:param Optional[callable] lt: `callable` used to evaluate whether one
|
:param typing.Callable | None lt: Callable used to evaluate whether one
|
||||||
object is less than another object.
|
object is less than another object.
|
||||||
:param Optional[callable] le: `callable` used to evaluate whether one
|
:param typing.Callable | None le: Callable used to evaluate whether 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 one
|
:param typing.Callable | None gt: Callable used to evaluate whether one
|
||||||
object is greater than another object.
|
object is greater than another object.
|
||||||
:param Optional[callable] ge: `callable` used to evaluate whether one
|
:param typing.Callable | None ge: Callable used to evaluate whether 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.
|
||||||
|
|
||||||
:param Optional[str] class_name: Name of class. Defaults to 'Comparable'.
|
:param str | None class_name: Name of class. Defaults to "Comparable".
|
||||||
|
|
||||||
See `comparison` for more details.
|
See `comparison` for more details.
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
from typing import Any, Callable, Optional, Type
|
from typing import Any, Callable
|
||||||
|
|
||||||
_CompareWithType = Callable[[Any, Any], bool]
|
_CompareWithType = Callable[[Any, Any], bool]
|
||||||
|
|
||||||
def cmp_using(
|
def cmp_using(
|
||||||
eq: Optional[_CompareWithType] = ...,
|
eq: _CompareWithType | None = ...,
|
||||||
lt: Optional[_CompareWithType] = ...,
|
lt: _CompareWithType | None = ...,
|
||||||
le: Optional[_CompareWithType] = ...,
|
le: _CompareWithType | None = ...,
|
||||||
gt: Optional[_CompareWithType] = ...,
|
gt: _CompareWithType | None = ...,
|
||||||
ge: Optional[_CompareWithType] = ...,
|
ge: _CompareWithType | None = ...,
|
||||||
require_same_type: bool = ...,
|
require_same_type: bool = ...,
|
||||||
class_name: str = ...,
|
class_name: str = ...,
|
||||||
) -> Type: ...
|
) -> type: ...
|
||||||
|
|
|
@ -4,17 +4,17 @@ import inspect
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import types
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from collections.abc import Mapping, Sequence # noqa: F401
|
from collections.abc import Mapping, Sequence # noqa: F401
|
||||||
from typing import _GenericAlias
|
from typing import _GenericAlias
|
||||||
|
|
||||||
|
|
||||||
PYPY = platform.python_implementation() == "PyPy"
|
PYPY = platform.python_implementation() == "PyPy"
|
||||||
|
PY_3_8_PLUS = sys.version_info[:2] >= (3, 8)
|
||||||
PY_3_9_PLUS = sys.version_info[:2] >= (3, 9)
|
PY_3_9_PLUS = sys.version_info[:2] >= (3, 9)
|
||||||
PY310 = sys.version_info[:2] >= (3, 10)
|
PY_3_10_PLUS = 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)
|
||||||
|
PY_3_13_PLUS = sys.version_info[:2] >= (3, 13)
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info < (3, 8):
|
if sys.version_info < (3, 8):
|
||||||
|
@ -26,16 +26,6 @@ else:
|
||||||
from typing import Protocol # noqa: F401
|
from typing import Protocol # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
def just_warn(*args, **kw):
|
|
||||||
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 _AnnotationExtractor:
|
class _AnnotationExtractor:
|
||||||
"""
|
"""
|
||||||
Extract type annotations from a callable, returning None whenever there
|
Extract type annotations from a callable, returning None whenever there
|
||||||
|
@ -76,101 +66,6 @@ class _AnnotationExtractor:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def make_set_closure_cell():
|
|
||||||
"""Return a function of two arguments (cell, value) which sets
|
|
||||||
the value stored in the closure cell `cell` to `value`.
|
|
||||||
"""
|
|
||||||
# pypy makes this easy. (It also supports the logic below, but
|
|
||||||
# why not do the easy/fast thing?)
|
|
||||||
if PYPY:
|
|
||||||
|
|
||||||
def set_closure_cell(cell, value):
|
|
||||||
cell.__setstate__((value,))
|
|
||||||
|
|
||||||
return set_closure_cell
|
|
||||||
|
|
||||||
# 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`.
|
|
||||||
def set_first_cellvar_to(value):
|
|
||||||
x = value
|
|
||||||
return
|
|
||||||
|
|
||||||
# This function will be eliminated as dead code, but
|
|
||||||
# not before its reference to `x` forces `x` to be
|
|
||||||
# represented as a closure cell rather than a local.
|
|
||||||
def force_x_to_be_a_cell(): # pragma: no cover
|
|
||||||
return x
|
|
||||||
|
|
||||||
# Extract the code object and make sure our assumptions about
|
|
||||||
# the closure behavior are correct.
|
|
||||||
co = set_first_cellvar_to.__code__
|
|
||||||
if co.co_cellvars != ("x",) or co.co_freevars != ():
|
|
||||||
raise AssertionError # pragma: no cover
|
|
||||||
|
|
||||||
# Convert this code object to a code object that sets the
|
|
||||||
# function's first _freevar_ (not cellvar) to the argument.
|
|
||||||
args = [co.co_argcount]
|
|
||||||
args.append(co.co_kwonlyargcount)
|
|
||||||
args.extend(
|
|
||||||
[
|
|
||||||
co.co_nlocals,
|
|
||||||
co.co_stacksize,
|
|
||||||
co.co_flags,
|
|
||||||
co.co_code,
|
|
||||||
co.co_consts,
|
|
||||||
co.co_names,
|
|
||||||
co.co_varnames,
|
|
||||||
co.co_filename,
|
|
||||||
co.co_name,
|
|
||||||
co.co_firstlineno,
|
|
||||||
co.co_lnotab,
|
|
||||||
# These two arguments are reversed:
|
|
||||||
co.co_cellvars,
|
|
||||||
co.co_freevars,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
set_first_freevar_code = types.CodeType(*args)
|
|
||||||
|
|
||||||
def set_closure_cell(cell, value):
|
|
||||||
# Create a function using the set_first_freevar_code,
|
|
||||||
# whose first closure cell is `cell`. Calling it will
|
|
||||||
# change the value of that cell.
|
|
||||||
setter = types.FunctionType(
|
|
||||||
set_first_freevar_code, {}, "setter", (), (cell,)
|
|
||||||
)
|
|
||||||
# And call it to set the cell.
|
|
||||||
setter(value)
|
|
||||||
|
|
||||||
# Make sure it works on this interpreter:
|
|
||||||
def make_func_with_cell():
|
|
||||||
x = None
|
|
||||||
|
|
||||||
def func():
|
|
||||||
return x # pragma: no cover
|
|
||||||
|
|
||||||
return func
|
|
||||||
|
|
||||||
cell = make_func_with_cell().__closure__[0]
|
|
||||||
set_closure_cell(cell, 100)
|
|
||||||
if cell.cell_contents != 100:
|
|
||||||
raise AssertionError # pragma: no cover
|
|
||||||
|
|
||||||
except Exception: # noqa: BLE001
|
|
||||||
return just_warn
|
|
||||||
else:
|
|
||||||
return set_closure_cell
|
|
||||||
|
|
||||||
|
|
||||||
set_closure_cell = make_set_closure_cell()
|
|
||||||
|
|
||||||
# Thread-local global to track attrs instances which are already being repr'd.
|
# Thread-local global to track attrs instances which are already being repr'd.
|
||||||
# This is needed because there is no other (thread-safe) way to pass info
|
# This is needed because there is no other (thread-safe) way to pass info
|
||||||
# about the instances that are already being repr'd through the call stack
|
# about the instances that are already being repr'd through the call stack
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ._compat import PY_3_9_PLUS, get_generic_base
|
from ._compat import PY_3_9_PLUS, get_generic_base
|
||||||
from ._make import NOTHING, _obj_setattr, fields
|
from ._make import _OBJ_SETATTR, NOTHING, fields
|
||||||
from .exceptions import AttrsAttributeNotFoundError
|
from .exceptions import AttrsAttributeNotFoundError
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,22 +22,21 @@ def asdict(
|
||||||
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 ~typing.Callable filter: A callable whose return code determines
|
||||||
:param callable filter: A callable whose return code determines whether an
|
whether an attribute or element is included (`True`) or dropped
|
||||||
attribute or element is included (``True``) or dropped (``False``). Is
|
(`False`). Is called with the `attrs.Attribute` as the first argument
|
||||||
called with the `attrs.Attribute` as the first argument and the
|
and the value as the second argument.
|
||||||
value as the second argument.
|
:param ~typing.Callable dict_factory: A callable to produce dictionaries
|
||||||
:param callable dict_factory: A callable to produce dictionaries from. For
|
from. For example, to produce ordered dictionaries instead of normal
|
||||||
example, to produce ordered dictionaries instead of normal Python
|
Python dictionaries, pass in ``collections.OrderedDict``.
|
||||||
dictionaries, pass in ``collections.OrderedDict``.
|
:param bool retain_collection_types: Do not convert to `list` when
|
||||||
:param bool retain_collection_types: Do not convert to ``list`` when
|
encountering an attribute whose type is `tuple` or `set`. Only
|
||||||
encountering an attribute whose type is ``tuple`` or ``set``. Only
|
meaningful if *recurse* is `True`.
|
||||||
meaningful if ``recurse`` is ``True``.
|
:param typing.Callable | None value_serializer: A hook that is called for
|
||||||
:param Optional[callable] value_serializer: A hook that is called for every
|
every attribute or dict key/value. It receives the current instance,
|
||||||
attribute or dict key/value. It receives the current instance, field
|
field and value and must return the (updated) value. The hook is run
|
||||||
and value and must return the (updated) value. The hook is run *after*
|
*after* the optional *filter* has been applied.
|
||||||
the optional *filter* has been applied.
|
|
||||||
|
|
||||||
:rtype: return type of *dict_factory*
|
:rtype: return type of *dict_factory*
|
||||||
|
|
||||||
|
@ -207,18 +206,16 @@ def astuple(
|
||||||
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 ~typing.Callable filter: A callable whose return code determines
|
||||||
:param callable filter: A callable whose return code determines whether an
|
whether an attribute or element is included (`True`) or dropped
|
||||||
attribute or element is included (``True``) or dropped (``False``). Is
|
(`False`). Is called with the `attrs.Attribute` as the first argument
|
||||||
called with the `attrs.Attribute` as the first argument and the
|
and the value as the second argument.
|
||||||
value as the second argument.
|
:param ~typing.Callable tuple_factory: A callable to produce tuples from.
|
||||||
:param callable tuple_factory: A callable to produce tuples from. For
|
For example, to produce lists instead of tuples.
|
||||||
example, to produce lists instead of tuples.
|
:param bool retain_collection_types: Do not convert to `list` or `dict`
|
||||||
:param bool retain_collection_types: Do not convert to ``list``
|
when encountering an attribute which type is `tuple`, `dict` or `set`.
|
||||||
or ``dict`` when encountering an attribute which type is
|
Only meaningful if *recurse* is `True`.
|
||||||
``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is
|
|
||||||
``True``.
|
|
||||||
|
|
||||||
:rtype: return type of *tuple_factory*
|
:rtype: return type of *tuple_factory*
|
||||||
|
|
||||||
|
@ -248,15 +245,17 @@ def astuple(
|
||||||
elif isinstance(v, (tuple, list, set, frozenset)):
|
elif isinstance(v, (tuple, list, set, frozenset)):
|
||||||
cf = v.__class__ if retain is True else list
|
cf = v.__class__ if retain is True else list
|
||||||
items = [
|
items = [
|
||||||
astuple(
|
(
|
||||||
j,
|
astuple(
|
||||||
recurse=True,
|
j,
|
||||||
filter=filter,
|
recurse=True,
|
||||||
tuple_factory=tuple_factory,
|
filter=filter,
|
||||||
retain_collection_types=retain,
|
tuple_factory=tuple_factory,
|
||||||
|
retain_collection_types=retain,
|
||||||
|
)
|
||||||
|
if has(j.__class__)
|
||||||
|
else j
|
||||||
)
|
)
|
||||||
if has(j.__class__)
|
|
||||||
else j
|
|
||||||
for j in v
|
for j in v
|
||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
|
@ -272,20 +271,24 @@ def astuple(
|
||||||
rv.append(
|
rv.append(
|
||||||
df(
|
df(
|
||||||
(
|
(
|
||||||
astuple(
|
(
|
||||||
kk,
|
astuple(
|
||||||
tuple_factory=tuple_factory,
|
kk,
|
||||||
retain_collection_types=retain,
|
tuple_factory=tuple_factory,
|
||||||
)
|
retain_collection_types=retain,
|
||||||
if has(kk.__class__)
|
)
|
||||||
else kk,
|
if has(kk.__class__)
|
||||||
astuple(
|
else kk
|
||||||
vv,
|
),
|
||||||
tuple_factory=tuple_factory,
|
(
|
||||||
retain_collection_types=retain,
|
astuple(
|
||||||
)
|
vv,
|
||||||
if has(vv.__class__)
|
tuple_factory=tuple_factory,
|
||||||
else vv,
|
retain_collection_types=retain,
|
||||||
|
)
|
||||||
|
if has(vv.__class__)
|
||||||
|
else vv
|
||||||
|
),
|
||||||
)
|
)
|
||||||
for kk, vv in v.items()
|
for kk, vv in v.items()
|
||||||
)
|
)
|
||||||
|
@ -356,7 +359,7 @@ def assoc(inst, **changes):
|
||||||
if a is NOTHING:
|
if a is NOTHING:
|
||||||
msg = f"{k} is not an attrs attribute on {new.__class__}."
|
msg = f"{k} is not an attrs attribute on {new.__class__}."
|
||||||
raise AttrsAttributeNotFoundError(msg)
|
raise AttrsAttributeNotFoundError(msg)
|
||||||
_obj_setattr(new, k, v)
|
_OBJ_SETATTR(new, k, v)
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|
||||||
|
@ -365,7 +368,8 @@ def evolve(*args, **changes):
|
||||||
Create a new instance, based on the first positional argument with
|
Create a new instance, based on the first positional argument with
|
||||||
*changes* applied.
|
*changes* applied.
|
||||||
|
|
||||||
:param inst: Instance of a class with *attrs* attributes.
|
:param inst: Instance of a class with *attrs* attributes. *inst* must be
|
||||||
|
passed as a positional argument.
|
||||||
: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.
|
||||||
|
@ -381,30 +385,16 @@ def evolve(*args, **changes):
|
||||||
*inst*. It will raise a warning until at least April 2024, after which
|
*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
|
it will become an error. Always pass the instance as a positional
|
||||||
argument.
|
argument.
|
||||||
|
.. versionchanged:: 24.1.0
|
||||||
|
*inst* can't be passed as a keyword argument anymore.
|
||||||
"""
|
"""
|
||||||
# Try to get instance by positional argument first.
|
try:
|
||||||
# Use changes otherwise and warn it'll break.
|
(inst,) = args
|
||||||
if args:
|
except ValueError:
|
||||||
try:
|
msg = (
|
||||||
(inst,) = args
|
f"evolve() takes 1 positional argument, but {len(args)} were given"
|
||||||
except ValueError:
|
|
||||||
msg = f"evolve() takes 1 positional argument, but {len(args)} were given"
|
|
||||||
raise TypeError(msg) from None
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
inst = changes.pop("inst")
|
|
||||||
except KeyError:
|
|
||||||
msg = "evolve() missing 1 required positional argument: 'inst'"
|
|
||||||
raise TypeError(msg) 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,
|
|
||||||
)
|
)
|
||||||
|
raise TypeError(msg) from None
|
||||||
|
|
||||||
cls = inst.__class__
|
cls = inst.__class__
|
||||||
attrs = fields(cls)
|
attrs = fields(cls)
|
||||||
|
@ -426,25 +416,25 @@ def resolve_types(
|
||||||
Resolve any strings and forward annotations in type annotations.
|
Resolve any strings and forward annotations in type annotations.
|
||||||
|
|
||||||
This is only required if you need concrete types in `Attribute`'s *type*
|
This is only required if you need concrete types in `Attribute`'s *type*
|
||||||
field. In other words, you don't need to resolve your types if you only
|
field. In other words, you don't need to resolve your types if you only use
|
||||||
use them for static type checking.
|
them for static type checking.
|
||||||
|
|
||||||
With no arguments, names will be looked up in the module in which the class
|
With no arguments, names will be looked up in the module in which the class
|
||||||
was created. If this is not what you want, e.g. if the name only exists
|
was created. If this is not what you want, for example, if the name only
|
||||||
inside a method, you may pass *globalns* or *localns* to specify other
|
exists inside a method, you may pass *globalns* or *localns* to specify
|
||||||
dictionaries in which to look up these names. See the docs of
|
other dictionaries in which to look up these names. See the docs of
|
||||||
`typing.get_type_hints` for more details.
|
`typing.get_type_hints` for more details.
|
||||||
|
|
||||||
:param type cls: Class to resolve.
|
:param type cls: Class to resolve.
|
||||||
:param Optional[dict] globalns: Dictionary containing global variables.
|
:param dict | None globalns: Dictionary containing global variables.
|
||||||
:param Optional[dict] localns: Dictionary containing local variables.
|
:param dict | None localns: Dictionary containing local variables.
|
||||||
:param Optional[list] attribs: List of attribs for the given class.
|
:param list | None attribs: List of attribs for the given class. This is
|
||||||
This is necessary when calling from inside a ``field_transformer``
|
necessary when calling from inside a ``field_transformer`` since *cls*
|
||||||
since *cls* is not an *attrs* class yet.
|
is not an *attrs* class yet.
|
||||||
:param bool include_extras: Resolve more accurately, if possible.
|
:param bool include_extras: Resolve more accurately, if possible. Pass
|
||||||
Pass ``include_extras`` to ``typing.get_hints``, if supported by the
|
``include_extras`` to ``typing.get_hints``, if supported by the typing
|
||||||
typing module. On supported Python versions (3.9+), this resolves the
|
module. On supported Python versions (3.9+), this resolves the types
|
||||||
types more accurately.
|
more accurately.
|
||||||
|
|
||||||
:raise TypeError: If *cls* is not a class.
|
:raise TypeError: If *cls* is not a class.
|
||||||
:raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs*
|
:raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs*
|
||||||
|
@ -458,7 +448,6 @@ def resolve_types(
|
||||||
.. versionadded:: 20.1.0
|
.. versionadded:: 20.1.0
|
||||||
.. versionadded:: 21.1.0 *attribs*
|
.. versionadded:: 21.1.0 *attribs*
|
||||||
.. versionadded:: 23.1.0 *include_extras*
|
.. 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
|
||||||
# done it already.
|
# done it already.
|
||||||
|
@ -474,7 +463,7 @@ def resolve_types(
|
||||||
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.
|
||||||
_obj_setattr(field, "type", hints[field.name])
|
_OBJ_SETATTR(field, "type", hints[field.name])
|
||||||
# We store the class we resolved so that subclasses know they haven't
|
# We store the class we resolved so that subclasses know they haven't
|
||||||
# been resolved.
|
# been resolved.
|
||||||
cls.__attrs_types_resolved__ = cls
|
cls.__attrs_types_resolved__ = cls
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,9 +12,9 @@ from . import setters
|
||||||
from ._funcs import asdict as _asdict
|
from ._funcs import asdict as _asdict
|
||||||
from ._funcs import astuple as _astuple
|
from ._funcs import astuple as _astuple
|
||||||
from ._make import (
|
from ._make import (
|
||||||
|
_DEFAULT_ON_SETATTR,
|
||||||
NOTHING,
|
NOTHING,
|
||||||
_frozen_setattrs,
|
_frozen_setattrs,
|
||||||
_ng_default_on_setattr,
|
|
||||||
attrib,
|
attrib,
|
||||||
attrs,
|
attrs,
|
||||||
)
|
)
|
||||||
|
@ -52,8 +52,8 @@ def define(
|
||||||
|
|
||||||
- Automatically detect whether or not *auto_attribs* should be `True` (c.f.
|
- Automatically detect whether or not *auto_attribs* should be `True` (c.f.
|
||||||
*auto_attribs* parameter).
|
*auto_attribs* parameter).
|
||||||
- If *frozen* is `False`, run converters and validators when setting an
|
- Converters and validators run when attributes are set by default -- if
|
||||||
attribute by default.
|
*frozen* is `False`.
|
||||||
- *slots=True*
|
- *slots=True*
|
||||||
|
|
||||||
.. caution::
|
.. caution::
|
||||||
|
@ -70,7 +70,7 @@ def define(
|
||||||
Please note that these are all defaults and you can change them as you
|
Please note that these are all defaults and you can change them as you
|
||||||
wish.
|
wish.
|
||||||
|
|
||||||
:param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves
|
:param bool | None auto_attribs: If set to `True` or `False`, it behaves
|
||||||
exactly like `attr.s`. If left `None`, `attr.s` will try to guess:
|
exactly like `attr.s`. If left `None`, `attr.s` will try to guess:
|
||||||
|
|
||||||
1. If any attributes are annotated and no unannotated `attrs.fields`\ s
|
1. If any attributes are annotated and no unannotated `attrs.fields`\ s
|
||||||
|
@ -124,7 +124,7 @@ def define(
|
||||||
|
|
||||||
# By default, mutable classes convert & validate on setattr.
|
# By default, mutable classes convert & validate on setattr.
|
||||||
if frozen is False and on_setattr is None:
|
if frozen is False and on_setattr is None:
|
||||||
on_setattr = _ng_default_on_setattr
|
on_setattr = _DEFAULT_ON_SETATTR
|
||||||
|
|
||||||
# However, if we subclass a frozen class, we inherit the immutability
|
# However, if we subclass a frozen class, we inherit the immutability
|
||||||
# and disable on_setattr.
|
# and disable on_setattr.
|
||||||
|
@ -146,7 +146,7 @@ def define(
|
||||||
return do_it(cls, False)
|
return do_it(cls, False)
|
||||||
|
|
||||||
# maybe_cls's type depends on the usage of the decorator. It's a class
|
# maybe_cls's type depends on the usage of the decorator. It's a class
|
||||||
# if it's used as `@attrs` but ``None`` if used as `@attrs()`.
|
# if it's used as `@attrs` but `None` if used as `@attrs()`.
|
||||||
if maybe_cls is None:
|
if maybe_cls is None:
|
||||||
return wrap
|
return wrap
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,12 @@ __all__ = [
|
||||||
def optional(converter):
|
def optional(converter):
|
||||||
"""
|
"""
|
||||||
A converter that allows an attribute to be optional. An optional attribute
|
A converter that allows an attribute to be optional. An optional attribute
|
||||||
is one which can be set to ``None``.
|
is one which can be set to `None`.
|
||||||
|
|
||||||
Type annotations will be inferred from the wrapped converter's, if it
|
Type annotations will be inferred from the wrapped converter's, if it has
|
||||||
has any.
|
any.
|
||||||
|
|
||||||
:param callable converter: the converter that is used for non-``None``
|
:param typing.Callable converter: the converter that is used for non-`None`
|
||||||
values.
|
values.
|
||||||
|
|
||||||
.. versionadded:: 17.1.0
|
.. versionadded:: 17.1.0
|
||||||
|
@ -53,14 +53,14 @@ def optional(converter):
|
||||||
|
|
||||||
def default_if_none(default=NOTHING, factory=None):
|
def default_if_none(default=NOTHING, factory=None):
|
||||||
"""
|
"""
|
||||||
A converter that allows to replace ``None`` values by *default* or the
|
A converter that allows to replace `None` values by *default* or the result
|
||||||
result of *factory*.
|
of *factory*.
|
||||||
|
|
||||||
:param default: Value to be used if ``None`` is passed. Passing an instance
|
:param default: Value to be used if `None` is passed. Passing an instance
|
||||||
of `attrs.Factory` is supported, however the ``takes_self`` option
|
of `attrs.Factory` is supported, however the ``takes_self`` option is
|
||||||
is *not*.
|
*not*.
|
||||||
:param callable factory: A callable that takes no parameters whose result
|
:param typing.Callable factory: A callable that takes no parameters whose
|
||||||
is used if ``None`` is passed.
|
result is used if `None` is passed.
|
||||||
|
|
||||||
:raises TypeError: If **neither** *default* or *factory* is passed.
|
:raises TypeError: If **neither** *default* or *factory* is passed.
|
||||||
:raises TypeError: If **both** *default* and *factory* are passed.
|
:raises TypeError: If **both** *default* and *factory* are passed.
|
||||||
|
@ -104,25 +104,26 @@ def default_if_none(default=NOTHING, factory=None):
|
||||||
|
|
||||||
def to_bool(val):
|
def to_bool(val):
|
||||||
"""
|
"""
|
||||||
Convert "boolean" strings (e.g., from env. vars.) to real booleans.
|
Convert "boolean" strings (for example, from environment variables) to real
|
||||||
|
booleans.
|
||||||
|
|
||||||
Values mapping to :code:`True`:
|
Values mapping to `True`:
|
||||||
|
|
||||||
- :code:`True`
|
- ``True``
|
||||||
- :code:`"true"` / :code:`"t"`
|
- ``"true"`` / ``"t"``
|
||||||
- :code:`"yes"` / :code:`"y"`
|
- ``"yes"`` / ``"y"``
|
||||||
- :code:`"on"`
|
- ``"on"``
|
||||||
- :code:`"1"`
|
- ``"1"``
|
||||||
- :code:`1`
|
- ``1``
|
||||||
|
|
||||||
Values mapping to :code:`False`:
|
Values mapping to `False`:
|
||||||
|
|
||||||
- :code:`False`
|
- ``False``
|
||||||
- :code:`"false"` / :code:`"f"`
|
- ``"false"`` / ``"f"``
|
||||||
- :code:`"no"` / :code:`"n"`
|
- ``"no"`` / ``"n"``
|
||||||
- :code:`"off"`
|
- ``"off"``
|
||||||
- :code:`"0"`
|
- ``"0"``
|
||||||
- :code:`0`
|
- ``0``
|
||||||
|
|
||||||
:raises ValueError: for any other value.
|
:raises ValueError: for any other value.
|
||||||
|
|
||||||
|
@ -130,15 +131,11 @@ def to_bool(val):
|
||||||
"""
|
"""
|
||||||
if isinstance(val, str):
|
if isinstance(val, str):
|
||||||
val = val.lower()
|
val = val.lower()
|
||||||
truthy = {True, "true", "t", "yes", "y", "on", "1", 1}
|
|
||||||
falsy = {False, "false", "f", "no", "n", "off", "0", 0}
|
if val in (True, "true", "t", "yes", "y", "on", "1", 1):
|
||||||
try:
|
return True
|
||||||
if val in truthy:
|
if val in (False, "false", "f", "no", "n", "off", "0", 0):
|
||||||
return True
|
return False
|
||||||
if val in falsy:
|
|
||||||
return False
|
msg = f"Cannot convert value to bool: {val!r}"
|
||||||
except TypeError:
|
|
||||||
# Raised when "val" is not hashable (e.g., lists)
|
|
||||||
pass
|
|
||||||
msg = f"Cannot convert value to bool: {val}"
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from typing import Callable, TypeVar, overload
|
from typing import Callable, TypeVar, overload
|
||||||
|
|
||||||
from . import _ConverterType
|
from attrs import _ConverterType
|
||||||
|
|
||||||
_T = TypeVar("_T")
|
_T = TypeVar("_T")
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from typing import Any, Union
|
from typing import Any
|
||||||
|
|
||||||
from . import Attribute, _FilterType
|
from . import Attribute, _FilterType
|
||||||
|
|
||||||
def include(*what: Union[type, str, Attribute[Any]]) -> _FilterType[Any]: ...
|
def include(*what: type | str | Attribute[Any]) -> _FilterType[Any]: ...
|
||||||
def exclude(*what: Union[type, str, Attribute[Any]]) -> _FilterType[Any]: ...
|
def exclude(*what: type | str | Attribute[Any]) -> _FilterType[Any]: ...
|
||||||
|
|
|
@ -69,5 +69,6 @@ def convert(instance, attrib, new_value):
|
||||||
|
|
||||||
|
|
||||||
# Sentinel for disabling class-wide *on_setattr* hooks for certain attributes.
|
# Sentinel for disabling class-wide *on_setattr* hooks for certain attributes.
|
||||||
# autodata stopped working, so the docstring is inlined in the API docs.
|
# Sphinx's autodata stopped working, so the docstring is inlined in the API
|
||||||
|
# docs.
|
||||||
NO_OP = object()
|
NO_OP = object()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from typing import Any, NewType, NoReturn, TypeVar
|
from typing import Any, NewType, NoReturn, TypeVar
|
||||||
|
|
||||||
from . import Attribute, _OnSetAttrType
|
from . import Attribute
|
||||||
|
from attrs import _OnSetAttrType
|
||||||
|
|
||||||
_T = TypeVar("_T")
|
_T = TypeVar("_T")
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@ __all__ = [
|
||||||
"min_len",
|
"min_len",
|
||||||
"not_",
|
"not_",
|
||||||
"optional",
|
"optional",
|
||||||
"provides",
|
|
||||||
"set_disabled",
|
"set_disabled",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -46,7 +45,7 @@ def set_disabled(disabled):
|
||||||
|
|
||||||
By default, they are run.
|
By default, they are run.
|
||||||
|
|
||||||
:param disabled: If ``True``, disable running all validators.
|
:param disabled: If `True`, disable running all validators.
|
||||||
:type disabled: bool
|
:type disabled: bool
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
@ -62,7 +61,7 @@ def get_disabled():
|
||||||
"""
|
"""
|
||||||
Return a bool indicating whether validators are currently disabled or not.
|
Return a bool indicating whether validators are currently disabled or not.
|
||||||
|
|
||||||
:return: ``True`` if validators are currently disabled.
|
:return: `True` if validators are currently disabled.
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
|
|
||||||
.. versionadded:: 21.3.0
|
.. versionadded:: 21.3.0
|
||||||
|
@ -97,12 +96,7 @@ class _InstanceOfValidator:
|
||||||
We use a callable class to be able to change the ``__repr__``.
|
We use a callable class to be able to change the ``__repr__``.
|
||||||
"""
|
"""
|
||||||
if not isinstance(value, self.type):
|
if not isinstance(value, self.type):
|
||||||
msg = "'{name}' must be {type!r} (got {value!r} that is a {actual!r}).".format(
|
msg = f"'{attr.name}' must be {self.type!r} (got {value!r} that is a {value.__class__!r})."
|
||||||
name=attr.name,
|
|
||||||
type=self.type,
|
|
||||||
actual=value.__class__,
|
|
||||||
value=value,
|
|
||||||
)
|
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
msg,
|
msg,
|
||||||
attr,
|
attr,
|
||||||
|
@ -116,16 +110,14 @@ class _InstanceOfValidator:
|
||||||
|
|
||||||
def instance_of(type):
|
def instance_of(type):
|
||||||
"""
|
"""
|
||||||
A validator that raises a `TypeError` if the initializer is called
|
A validator that raises a `TypeError` if the initializer is called with a
|
||||||
with a wrong type for this particular attribute (checks are performed using
|
wrong type for this particular attribute (checks are performed using
|
||||||
`isinstance` therefore it's also valid to pass a tuple of types).
|
`isinstance` therefore it's also valid to pass a tuple of types).
|
||||||
|
|
||||||
:param type: The type to check for.
|
:param type | tuple[type] type: The type to check for.
|
||||||
:type type: type or tuple of type
|
|
||||||
|
|
||||||
:raises TypeError: With a human readable error message, the attribute
|
:raises TypeError: With a human readable error message, the attribute (of
|
||||||
(of type `attrs.Attribute`), the expected type, and the value it
|
type `attrs.Attribute`), the expected type, and the value it got.
|
||||||
got.
|
|
||||||
"""
|
"""
|
||||||
return _InstanceOfValidator(type)
|
return _InstanceOfValidator(type)
|
||||||
|
|
||||||
|
@ -140,9 +132,7 @@ class _MatchesReValidator:
|
||||||
We use a callable class to be able to change the ``__repr__``.
|
We use a callable class to be able to change the ``__repr__``.
|
||||||
"""
|
"""
|
||||||
if not self.match_func(value):
|
if not self.match_func(value):
|
||||||
msg = "'{name}' must match regex {pattern!r} ({value!r} doesn't)".format(
|
msg = f"'{attr.name}' must match regex {self.pattern.pattern!r} ({value!r} doesn't)"
|
||||||
name=attr.name, pattern=self.pattern.pattern, value=value
|
|
||||||
)
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
msg,
|
msg,
|
||||||
attr,
|
attr,
|
||||||
|
@ -156,16 +146,16 @@ class _MatchesReValidator:
|
||||||
|
|
||||||
def matches_re(regex, flags=0, func=None):
|
def matches_re(regex, flags=0, func=None):
|
||||||
r"""
|
r"""
|
||||||
A validator that raises `ValueError` if the initializer is called
|
A validator that raises `ValueError` if the initializer is called with a
|
||||||
with a string that doesn't match *regex*.
|
string that doesn't match *regex*.
|
||||||
|
|
||||||
:param regex: a regex string or precompiled pattern to match against
|
:param regex: a regex string or precompiled pattern to match against
|
||||||
:param int flags: flags that will be passed to the underlying re function
|
:param int flags: flags that will be passed to the underlying re function
|
||||||
(default 0)
|
(default 0)
|
||||||
:param callable func: which underlying `re` function to call. Valid options
|
:param typing.Callable func: which underlying `re` function to call. Valid
|
||||||
are `re.fullmatch`, `re.search`, and `re.match`; the default ``None``
|
options are `re.fullmatch`, `re.search`, and `re.match`; the default
|
||||||
means `re.fullmatch`. For performance reasons, the pattern is always
|
`None` means `re.fullmatch`. For performance reasons, the pattern is
|
||||||
precompiled using `re.compile`.
|
always precompiled using `re.compile`.
|
||||||
|
|
||||||
.. versionadded:: 19.2.0
|
.. versionadded:: 19.2.0
|
||||||
.. versionchanged:: 21.3.0 *regex* can be a pre-compiled pattern.
|
.. versionchanged:: 21.3.0 *regex* can be a pre-compiled pattern.
|
||||||
|
@ -197,56 +187,6 @@ def matches_re(regex, flags=0, func=None):
|
||||||
return _MatchesReValidator(pattern, match_func)
|
return _MatchesReValidator(pattern, match_func)
|
||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, slots=True, hash=True)
|
|
||||||
class _ProvidesValidator:
|
|
||||||
interface = attrib()
|
|
||||||
|
|
||||||
def __call__(self, inst, attr, value):
|
|
||||||
"""
|
|
||||||
We use a callable class to be able to change the ``__repr__``.
|
|
||||||
"""
|
|
||||||
if not self.interface.providedBy(value):
|
|
||||||
msg = "'{name}' must provide {interface!r} which {value!r} doesn't.".format(
|
|
||||||
name=attr.name, interface=self.interface, value=value
|
|
||||||
)
|
|
||||||
raise TypeError(
|
|
||||||
msg,
|
|
||||||
attr,
|
|
||||||
self.interface,
|
|
||||||
value,
|
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f"<provides validator for interface {self.interface!r}>"
|
|
||||||
|
|
||||||
|
|
||||||
def provides(interface):
|
|
||||||
"""
|
|
||||||
A validator that raises a `TypeError` if the initializer is called
|
|
||||||
with an object that does not provide the requested *interface* (checks are
|
|
||||||
performed using ``interface.providedBy(value)`` (see `zope.interface
|
|
||||||
<https://zopeinterface.readthedocs.io/en/latest/>`_).
|
|
||||||
|
|
||||||
:param interface: The interface to check for.
|
|
||||||
:type interface: ``zope.interface.Interface``
|
|
||||||
|
|
||||||
:raises TypeError: With a human readable error message, the attribute
|
|
||||||
(of type `attrs.Attribute`), the expected interface, and the
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
@attrs(repr=False, slots=True, hash=True)
|
@attrs(repr=False, slots=True, hash=True)
|
||||||
class _OptionalValidator:
|
class _OptionalValidator:
|
||||||
validator = attrib()
|
validator = attrib()
|
||||||
|
@ -264,11 +204,13 @@ class _OptionalValidator:
|
||||||
def optional(validator):
|
def optional(validator):
|
||||||
"""
|
"""
|
||||||
A validator that makes an attribute optional. An optional attribute is one
|
A validator that makes an attribute optional. An optional attribute is one
|
||||||
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 Callable | tuple[Callable] | list[Callable] validator: A validator
|
:param validator: A validator (or validators) that is used for non-`None`
|
||||||
(or validators) that is used for non-``None`` values.
|
values.
|
||||||
|
:type validator: typing.Callable | tuple[typing.Callable] |
|
||||||
|
list[typing.Callable]
|
||||||
|
|
||||||
.. 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.
|
||||||
|
@ -426,9 +368,7 @@ class _DeepMapping:
|
||||||
self.value_validator(inst, attr, value[key])
|
self.value_validator(inst, attr, value[key])
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return (
|
return f"<deep_mapping validator for objects mapping {self.key_validator!r} to {self.value_validator!r}>"
|
||||||
"<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):
|
def deep_mapping(key_validator, value_validator, mapping_validator=None):
|
||||||
|
@ -550,7 +490,7 @@ class _MinLengthValidator:
|
||||||
We use a callable class to be able to change the ``__repr__``.
|
We use a callable class to be able to change the ``__repr__``.
|
||||||
"""
|
"""
|
||||||
if len(value) < self.min_length:
|
if len(value) < self.min_length:
|
||||||
msg = f"Length of '{attr.name}' must be => {self.min_length}: {len(value)}"
|
msg = f"Length of '{attr.name}' must be >= {self.min_length}: {len(value)}"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -640,12 +580,7 @@ class _NotValidator:
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return (
|
return f"<not_ validator wrapping {self.validator!r}, capturing {self.exc_types!r}>"
|
||||||
"<not_ validator wrapping {what!r}, capturing {exc_types!r}>"
|
|
||||||
).format(
|
|
||||||
what=self.validator,
|
|
||||||
exc_types=self.exc_types,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def not_(validator, *, msg=None, exc_types=(ValueError, TypeError)):
|
def not_(validator, *, msg=None, exc_types=(ValueError, TypeError)):
|
||||||
|
|
|
@ -5,20 +5,15 @@ from typing import (
|
||||||
Container,
|
Container,
|
||||||
ContextManager,
|
ContextManager,
|
||||||
Iterable,
|
Iterable,
|
||||||
List,
|
|
||||||
Mapping,
|
Mapping,
|
||||||
Match,
|
Match,
|
||||||
Optional,
|
|
||||||
Pattern,
|
Pattern,
|
||||||
Tuple,
|
|
||||||
Type,
|
|
||||||
TypeVar,
|
TypeVar,
|
||||||
Union,
|
|
||||||
overload,
|
overload,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import _ValidatorType
|
from attrs import _ValidatorType
|
||||||
from . import _ValidatorArgType
|
from attrs import _ValidatorArgType
|
||||||
|
|
||||||
_T = TypeVar("_T")
|
_T = TypeVar("_T")
|
||||||
_T1 = TypeVar("_T1")
|
_T1 = TypeVar("_T1")
|
||||||
|
@ -36,42 +31,41 @@ def disabled() -> ContextManager[None]: ...
|
||||||
# To be more precise on instance_of use some overloads.
|
# To be more precise on instance_of use some overloads.
|
||||||
# If there are more than 3 items in the tuple then we fall back to Any
|
# If there are more than 3 items in the tuple then we fall back to Any
|
||||||
@overload
|
@overload
|
||||||
def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ...
|
def instance_of(type: type[_T]) -> _ValidatorType[_T]: ...
|
||||||
@overload
|
@overload
|
||||||
def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ...
|
def instance_of(type: tuple[type[_T]]) -> _ValidatorType[_T]: ...
|
||||||
@overload
|
@overload
|
||||||
def instance_of(
|
def instance_of(
|
||||||
type: Tuple[Type[_T1], Type[_T2]]
|
type: tuple[type[_T1], type[_T2]]
|
||||||
) -> _ValidatorType[Union[_T1, _T2]]: ...
|
) -> _ValidatorType[_T1 | _T2]: ...
|
||||||
@overload
|
@overload
|
||||||
def instance_of(
|
def instance_of(
|
||||||
type: Tuple[Type[_T1], Type[_T2], Type[_T3]]
|
type: tuple[type[_T1], type[_T2], type[_T3]]
|
||||||
) -> _ValidatorType[Union[_T1, _T2, _T3]]: ...
|
) -> _ValidatorType[_T1 | _T2 | _T3]: ...
|
||||||
@overload
|
@overload
|
||||||
def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ...
|
def instance_of(type: tuple[type, ...]) -> _ValidatorType[Any]: ...
|
||||||
def provides(interface: Any) -> _ValidatorType[Any]: ...
|
|
||||||
def optional(
|
def optional(
|
||||||
validator: Union[
|
validator: (
|
||||||
_ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_ValidatorType[_T]]
|
_ValidatorType[_T]
|
||||||
]
|
| list[_ValidatorType[_T]]
|
||||||
) -> _ValidatorType[Optional[_T]]: ...
|
| tuple[_ValidatorType[_T]]
|
||||||
|
),
|
||||||
|
) -> _ValidatorType[_T | None]: ...
|
||||||
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]: ...
|
||||||
def matches_re(
|
def matches_re(
|
||||||
regex: Union[Pattern[AnyStr], AnyStr],
|
regex: Pattern[AnyStr] | AnyStr,
|
||||||
flags: int = ...,
|
flags: int = ...,
|
||||||
func: Optional[
|
func: Callable[[AnyStr, AnyStr, int], Match[AnyStr] | None] | None = ...,
|
||||||
Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]]
|
|
||||||
] = ...,
|
|
||||||
) -> _ValidatorType[AnyStr]: ...
|
) -> _ValidatorType[AnyStr]: ...
|
||||||
def deep_iterable(
|
def deep_iterable(
|
||||||
member_validator: _ValidatorArgType[_T],
|
member_validator: _ValidatorArgType[_T],
|
||||||
iterable_validator: Optional[_ValidatorType[_I]] = ...,
|
iterable_validator: _ValidatorType[_I] | None = ...,
|
||||||
) -> _ValidatorType[_I]: ...
|
) -> _ValidatorType[_I]: ...
|
||||||
def deep_mapping(
|
def deep_mapping(
|
||||||
key_validator: _ValidatorType[_K],
|
key_validator: _ValidatorType[_K],
|
||||||
value_validator: _ValidatorType[_V],
|
value_validator: _ValidatorType[_V],
|
||||||
mapping_validator: Optional[_ValidatorType[_M]] = ...,
|
mapping_validator: _ValidatorType[_M] | None = ...,
|
||||||
) -> _ValidatorType[_M]: ...
|
) -> _ValidatorType[_M]: ...
|
||||||
def is_callable() -> _ValidatorType[_T]: ...
|
def is_callable() -> _ValidatorType[_T]: ...
|
||||||
def lt(val: _T) -> _ValidatorType[_T]: ...
|
def lt(val: _T) -> _ValidatorType[_T]: ...
|
||||||
|
@ -83,6 +77,6 @@ def min_len(length: int) -> _ValidatorType[_T]: ...
|
||||||
def not_(
|
def not_(
|
||||||
validator: _ValidatorType[_T],
|
validator: _ValidatorType[_T],
|
||||||
*,
|
*,
|
||||||
msg: Optional[str] = None,
|
msg: str | None = None,
|
||||||
exc_types: Union[Type[Exception], Iterable[Type[Exception]]] = ...,
|
exc_types: type[Exception] | Iterable[type[Exception]] = ...,
|
||||||
) -> _ValidatorType[_T]: ...
|
) -> _ValidatorType[_T]: ...
|
||||||
|
|
Loading…
Reference in a new issue