mirror of
https://github.com/SickGear/SickGear.git
synced 2024-11-28 15:43:37 +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)
|
||||
|
||||
* Update attr 23.1.0 (67e4ff2) to 23.2.0 (b393d79)
|
||||
* Update Beautiful Soup 4.12.2 (30c58a1) to 4.12.3 (7fb5175)
|
||||
* Update CacheControl 0.13.1 (783a338) to 0.14.0 (e2be0c2)
|
||||
* 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:
|
||||
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:
|
||||
if name not in ("__version__", "__version_info__"):
|
||||
msg = f"module {mod_name} has no attribute {name}"
|
||||
raise AttributeError(msg)
|
||||
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
from importlib_metadata import metadata
|
||||
else:
|
||||
try:
|
||||
from importlib.metadata import metadata
|
||||
|
||||
if name not in ("__version__", "__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,
|
||||
)
|
||||
except ImportError:
|
||||
from importlib_metadata import metadata
|
||||
|
||||
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__":
|
||||
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__
|
||||
|
||||
|
|
|
@ -4,17 +4,11 @@ import sys
|
|||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Generic,
|
||||
List,
|
||||
Mapping,
|
||||
Optional,
|
||||
Protocol,
|
||||
Sequence,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
|
||||
|
@ -27,6 +21,20 @@ from . import validators as validators
|
|||
from ._cmp import cmp_using as cmp_using
|
||||
from ._typing_compat import AttrsInstance_
|
||||
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):
|
||||
from typing import TypeGuard
|
||||
|
@ -52,23 +60,7 @@ __copyright__: str
|
|||
_T = TypeVar("_T")
|
||||
_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]
|
||||
_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.
|
||||
class AttrsInstance(AttrsInstance_, Protocol):
|
||||
|
@ -110,20 +102,20 @@ else:
|
|||
|
||||
class Attribute(Generic[_T]):
|
||||
name: str
|
||||
default: Optional[_T]
|
||||
validator: Optional[_ValidatorType[_T]]
|
||||
default: _T | None
|
||||
validator: _ValidatorType[_T] | None
|
||||
repr: _ReprArgType
|
||||
cmp: _EqOrderType
|
||||
eq: _EqOrderType
|
||||
order: _EqOrderType
|
||||
hash: Optional[bool]
|
||||
hash: bool | None
|
||||
init: bool
|
||||
converter: Optional[_ConverterType]
|
||||
metadata: Dict[Any, Any]
|
||||
type: Optional[Type[_T]]
|
||||
converter: _ConverterType | None
|
||||
metadata: dict[Any, Any]
|
||||
type: type[_T] | None
|
||||
kw_only: bool
|
||||
on_setattr: _OnSetAttrType
|
||||
alias: Optional[str]
|
||||
alias: str | None
|
||||
|
||||
def evolve(self, **changes: Any) -> "Attribute[Any]": ...
|
||||
|
||||
|
@ -156,18 +148,18 @@ def attrib(
|
|||
default: None = ...,
|
||||
validator: None = ...,
|
||||
repr: _ReprArgType = ...,
|
||||
cmp: Optional[_EqOrderType] = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
cmp: _EqOrderType | None = ...,
|
||||
hash: bool | None = ...,
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
metadata: Mapping[Any, Any] | None = ...,
|
||||
type: None = ...,
|
||||
converter: None = ...,
|
||||
factory: None = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[_EqOrderType] = ...,
|
||||
order: Optional[_EqOrderType] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
alias: Optional[str] = ...,
|
||||
eq: _EqOrderType | None = ...,
|
||||
order: _EqOrderType | None = ...,
|
||||
on_setattr: _OnSetAttrArgType | None = ...,
|
||||
alias: str | None = ...,
|
||||
) -> Any: ...
|
||||
|
||||
# This form catches an explicit None or no default and infers the type from the
|
||||
|
@ -175,149 +167,70 @@ def attrib(
|
|||
@overload
|
||||
def attrib(
|
||||
default: None = ...,
|
||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||
validator: _ValidatorArgType[_T] | None = ...,
|
||||
repr: _ReprArgType = ...,
|
||||
cmp: Optional[_EqOrderType] = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
cmp: _EqOrderType | None = ...,
|
||||
hash: bool | None = ...,
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
type: Optional[Type[_T]] = ...,
|
||||
converter: Optional[_ConverterType] = ...,
|
||||
factory: Optional[Callable[[], _T]] = ...,
|
||||
metadata: Mapping[Any, Any] | None = ...,
|
||||
type: type[_T] | None = ...,
|
||||
converter: _ConverterType | None = ...,
|
||||
factory: Callable[[], _T] | None = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[_EqOrderType] = ...,
|
||||
order: Optional[_EqOrderType] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
alias: Optional[str] = ...,
|
||||
eq: _EqOrderType | None = ...,
|
||||
order: _EqOrderType | None = ...,
|
||||
on_setattr: _OnSetAttrArgType | None = ...,
|
||||
alias: str | None = ...,
|
||||
) -> _T: ...
|
||||
|
||||
# This form catches an explicit default argument.
|
||||
@overload
|
||||
def attrib(
|
||||
default: _T,
|
||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||
validator: _ValidatorArgType[_T] | None = ...,
|
||||
repr: _ReprArgType = ...,
|
||||
cmp: Optional[_EqOrderType] = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
cmp: _EqOrderType | None = ...,
|
||||
hash: bool | None = ...,
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
type: Optional[Type[_T]] = ...,
|
||||
converter: Optional[_ConverterType] = ...,
|
||||
factory: Optional[Callable[[], _T]] = ...,
|
||||
metadata: Mapping[Any, Any] | None = ...,
|
||||
type: type[_T] | None = ...,
|
||||
converter: _ConverterType | None = ...,
|
||||
factory: Callable[[], _T] | None = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[_EqOrderType] = ...,
|
||||
order: Optional[_EqOrderType] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
alias: Optional[str] = ...,
|
||||
eq: _EqOrderType | None = ...,
|
||||
order: _EqOrderType | None = ...,
|
||||
on_setattr: _OnSetAttrArgType | None = ...,
|
||||
alias: str | None = ...,
|
||||
) -> _T: ...
|
||||
|
||||
# This form covers type=non-Type: e.g. forward references (str), Any
|
||||
@overload
|
||||
def attrib(
|
||||
default: Optional[_T] = ...,
|
||||
validator: Optional[_ValidatorArgType[_T]] = ...,
|
||||
default: _T | None = ...,
|
||||
validator: _ValidatorArgType[_T] | None = ...,
|
||||
repr: _ReprArgType = ...,
|
||||
cmp: Optional[_EqOrderType] = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
cmp: _EqOrderType | None = ...,
|
||||
hash: bool | None = ...,
|
||||
init: bool = ...,
|
||||
metadata: Optional[Mapping[Any, Any]] = ...,
|
||||
metadata: Mapping[Any, Any] | None = ...,
|
||||
type: object = ...,
|
||||
converter: Optional[_ConverterType] = ...,
|
||||
factory: Optional[Callable[[], _T]] = ...,
|
||||
converter: _ConverterType | None = ...,
|
||||
factory: Callable[[], _T] | None = ...,
|
||||
kw_only: bool = ...,
|
||||
eq: Optional[_EqOrderType] = ...,
|
||||
order: Optional[_EqOrderType] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
alias: Optional[str] = ...,
|
||||
) -> 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] = ...,
|
||||
eq: _EqOrderType | None = ...,
|
||||
order: _EqOrderType | None = ...,
|
||||
on_setattr: _OnSetAttrArgType | None = ...,
|
||||
alias: str | None = ...,
|
||||
) -> Any: ...
|
||||
@overload
|
||||
@dataclass_transform(order_default=True, field_specifiers=(attrib, field))
|
||||
def attrs(
|
||||
maybe_cls: _C,
|
||||
these: Optional[Dict[str, Any]] = ...,
|
||||
repr_ns: Optional[str] = ...,
|
||||
these: dict[str, Any] | None = ...,
|
||||
repr_ns: str | None = ...,
|
||||
repr: bool = ...,
|
||||
cmp: Optional[_EqOrderType] = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
cmp: _EqOrderType | None = ...,
|
||||
hash: bool | None = ...,
|
||||
init: bool = ...,
|
||||
slots: bool = ...,
|
||||
frozen: bool = ...,
|
||||
|
@ -327,25 +240,25 @@ def attrs(
|
|||
kw_only: bool = ...,
|
||||
cache_hash: bool = ...,
|
||||
auto_exc: bool = ...,
|
||||
eq: Optional[_EqOrderType] = ...,
|
||||
order: Optional[_EqOrderType] = ...,
|
||||
eq: _EqOrderType | None = ...,
|
||||
order: _EqOrderType | None = ...,
|
||||
auto_detect: bool = ...,
|
||||
collect_by_mro: bool = ...,
|
||||
getstate_setstate: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
field_transformer: Optional[_FieldTransformer] = ...,
|
||||
getstate_setstate: bool | None = ...,
|
||||
on_setattr: _OnSetAttrArgType | None = ...,
|
||||
field_transformer: _FieldTransformer | None = ...,
|
||||
match_args: bool = ...,
|
||||
unsafe_hash: Optional[bool] = ...,
|
||||
unsafe_hash: bool | None = ...,
|
||||
) -> _C: ...
|
||||
@overload
|
||||
@dataclass_transform(order_default=True, field_specifiers=(attrib, field))
|
||||
def attrs(
|
||||
maybe_cls: None = ...,
|
||||
these: Optional[Dict[str, Any]] = ...,
|
||||
repr_ns: Optional[str] = ...,
|
||||
these: dict[str, Any] | None = ...,
|
||||
repr_ns: str | None = ...,
|
||||
repr: bool = ...,
|
||||
cmp: Optional[_EqOrderType] = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
cmp: _EqOrderType | None = ...,
|
||||
hash: bool | None = ...,
|
||||
init: bool = ...,
|
||||
slots: bool = ...,
|
||||
frozen: bool = ...,
|
||||
|
@ -355,131 +268,24 @@ def attrs(
|
|||
kw_only: bool = ...,
|
||||
cache_hash: bool = ...,
|
||||
auto_exc: bool = ...,
|
||||
eq: Optional[_EqOrderType] = ...,
|
||||
order: Optional[_EqOrderType] = ...,
|
||||
eq: _EqOrderType | None = ...,
|
||||
order: _EqOrderType | None = ...,
|
||||
auto_detect: bool = ...,
|
||||
collect_by_mro: bool = ...,
|
||||
getstate_setstate: Optional[bool] = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
field_transformer: Optional[_FieldTransformer] = ...,
|
||||
getstate_setstate: bool | None = ...,
|
||||
on_setattr: _OnSetAttrArgType | None = ...,
|
||||
field_transformer: _FieldTransformer | None = ...,
|
||||
match_args: bool = ...,
|
||||
unsafe_hash: Optional[bool] = ...,
|
||||
unsafe_hash: bool | None = ...,
|
||||
) -> Callable[[_C], _C]: ...
|
||||
@overload
|
||||
@dataclass_transform(field_specifiers=(attrib, field))
|
||||
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 fields(cls: type[AttrsInstance]) -> Any: ...
|
||||
def fields_dict(cls: type[AttrsInstance]) -> dict[str, Attribute[Any]]: ...
|
||||
def validate(inst: AttrsInstance) -> None: ...
|
||||
def resolve_types(
|
||||
cls: _A,
|
||||
globalns: Optional[Dict[str, Any]] = ...,
|
||||
localns: Optional[Dict[str, Any]] = ...,
|
||||
attribs: Optional[List[Attribute[Any]]] = ...,
|
||||
globalns: dict[str, Any] | None = ...,
|
||||
localns: dict[str, Any] | None = ...,
|
||||
attribs: list[Attribute[Any]] | None = ...,
|
||||
include_extras: bool = ...,
|
||||
) -> _A: ...
|
||||
|
||||
|
@ -488,12 +294,13 @@ def resolve_types(
|
|||
# [attr.ib()])` is valid
|
||||
def make_class(
|
||||
name: str,
|
||||
attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]],
|
||||
bases: Tuple[type, ...] = ...,
|
||||
repr_ns: Optional[str] = ...,
|
||||
attrs: list[str] | tuple[str, ...] | dict[str, Any],
|
||||
bases: tuple[type, ...] = ...,
|
||||
class_body: dict[str, Any] | None = ...,
|
||||
repr_ns: str | None = ...,
|
||||
repr: bool = ...,
|
||||
cmp: Optional[_EqOrderType] = ...,
|
||||
hash: Optional[bool] = ...,
|
||||
cmp: _EqOrderType | None = ...,
|
||||
hash: bool | None = ...,
|
||||
init: bool = ...,
|
||||
slots: bool = ...,
|
||||
frozen: bool = ...,
|
||||
|
@ -503,11 +310,11 @@ def make_class(
|
|||
kw_only: bool = ...,
|
||||
cache_hash: bool = ...,
|
||||
auto_exc: bool = ...,
|
||||
eq: Optional[_EqOrderType] = ...,
|
||||
order: Optional[_EqOrderType] = ...,
|
||||
eq: _EqOrderType | None = ...,
|
||||
order: _EqOrderType | None = ...,
|
||||
collect_by_mro: bool = ...,
|
||||
on_setattr: Optional[_OnSetAttrArgType] = ...,
|
||||
field_transformer: Optional[_FieldTransformer] = ...,
|
||||
on_setattr: _OnSetAttrArgType | None = ...,
|
||||
field_transformer: _FieldTransformer | None = ...,
|
||||
) -> type: ...
|
||||
|
||||
# _funcs --
|
||||
|
@ -521,24 +328,22 @@ def make_class(
|
|||
def asdict(
|
||||
inst: AttrsInstance,
|
||||
recurse: bool = ...,
|
||||
filter: Optional[_FilterType[Any]] = ...,
|
||||
dict_factory: Type[Mapping[Any, Any]] = ...,
|
||||
filter: _FilterType[Any] | None = ...,
|
||||
dict_factory: type[Mapping[Any, Any]] = ...,
|
||||
retain_collection_types: bool = ...,
|
||||
value_serializer: Optional[
|
||||
Callable[[type, Attribute[Any], Any], Any]
|
||||
] = ...,
|
||||
tuple_keys: Optional[bool] = ...,
|
||||
) -> Dict[str, Any]: ...
|
||||
value_serializer: Callable[[type, Attribute[Any], Any], Any] | None = ...,
|
||||
tuple_keys: bool | None = ...,
|
||||
) -> dict[str, Any]: ...
|
||||
|
||||
# TODO: add support for returning NamedTuple from the mypy plugin
|
||||
def astuple(
|
||||
inst: AttrsInstance,
|
||||
recurse: bool = ...,
|
||||
filter: Optional[_FilterType[Any]] = ...,
|
||||
tuple_factory: Type[Sequence[Any]] = ...,
|
||||
filter: _FilterType[Any] | None = ...,
|
||||
tuple_factory: type[Sequence[Any]] = ...,
|
||||
retain_collection_types: bool = ...,
|
||||
) -> Tuple[Any, ...]: ...
|
||||
def has(cls: type) -> TypeGuard[Type[AttrsInstance]]: ...
|
||||
) -> tuple[Any, ...]: ...
|
||||
def has(cls: type) -> TypeGuard[type[AttrsInstance]]: ...
|
||||
def assoc(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
|
||||
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.
|
||||
: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.
|
||||
: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.
|
||||
: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.
|
||||
: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.
|
||||
|
||||
:param bool require_same_type: When `True`, equality and ordering methods
|
||||
will return `NotImplemented` if objects are not of the same type.
|
||||
|
||||
:param Optional[str] class_name: Name of class. Defaults to 'Comparable'.
|
||||
:param str | None class_name: Name of class. Defaults to "Comparable".
|
||||
|
||||
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]
|
||||
|
||||
def cmp_using(
|
||||
eq: Optional[_CompareWithType] = ...,
|
||||
lt: Optional[_CompareWithType] = ...,
|
||||
le: Optional[_CompareWithType] = ...,
|
||||
gt: Optional[_CompareWithType] = ...,
|
||||
ge: Optional[_CompareWithType] = ...,
|
||||
eq: _CompareWithType | None = ...,
|
||||
lt: _CompareWithType | None = ...,
|
||||
le: _CompareWithType | None = ...,
|
||||
gt: _CompareWithType | None = ...,
|
||||
ge: _CompareWithType | None = ...,
|
||||
require_same_type: bool = ...,
|
||||
class_name: str = ...,
|
||||
) -> Type: ...
|
||||
) -> type: ...
|
||||
|
|
|
@ -4,17 +4,17 @@ import inspect
|
|||
import platform
|
||||
import sys
|
||||
import threading
|
||||
import types
|
||||
import warnings
|
||||
|
||||
from collections.abc import Mapping, Sequence # noqa: F401
|
||||
from typing import _GenericAlias
|
||||
|
||||
|
||||
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)
|
||||
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_13_PLUS = sys.version_info[:2] >= (3, 13)
|
||||
|
||||
|
||||
if sys.version_info < (3, 8):
|
||||
|
@ -26,16 +26,6 @@ else:
|
|||
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:
|
||||
"""
|
||||
Extract type annotations from a callable, returning None whenever there
|
||||
|
@ -76,101 +66,6 @@ class _AnnotationExtractor:
|
|||
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.
|
||||
# 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
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import copy
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -22,22 +22,21 @@ def asdict(
|
|||
Optionally recurse into other *attrs*-decorated classes.
|
||||
|
||||
:param inst: Instance of an *attrs*-decorated class.
|
||||
:param bool recurse: Recurse into classes that are also
|
||||
*attrs*-decorated.
|
||||
:param callable filter: A callable whose return code determines whether an
|
||||
attribute or element is included (``True``) or dropped (``False``). Is
|
||||
called with the `attrs.Attribute` as the first argument and the
|
||||
value as the second argument.
|
||||
:param callable dict_factory: A callable to produce dictionaries from. For
|
||||
example, to produce ordered dictionaries instead of normal Python
|
||||
dictionaries, pass in ``collections.OrderedDict``.
|
||||
:param bool retain_collection_types: Do not convert to ``list`` when
|
||||
encountering an attribute whose type is ``tuple`` or ``set``. Only
|
||||
meaningful if ``recurse`` is ``True``.
|
||||
:param Optional[callable] value_serializer: A hook that is called for every
|
||||
attribute or dict key/value. It receives the current instance, field
|
||||
and value and must return the (updated) value. The hook is run *after*
|
||||
the optional *filter* has been applied.
|
||||
:param bool recurse: Recurse into classes that are also *attrs*-decorated.
|
||||
:param ~typing.Callable filter: A callable whose return code determines
|
||||
whether an attribute or element is included (`True`) or dropped
|
||||
(`False`). Is called with the `attrs.Attribute` as the first argument
|
||||
and the value as the second argument.
|
||||
:param ~typing.Callable dict_factory: A callable to produce dictionaries
|
||||
from. For example, to produce ordered dictionaries instead of normal
|
||||
Python dictionaries, pass in ``collections.OrderedDict``.
|
||||
:param bool retain_collection_types: Do not convert to `list` when
|
||||
encountering an attribute whose type is `tuple` or `set`. Only
|
||||
meaningful if *recurse* is `True`.
|
||||
:param typing.Callable | None value_serializer: A hook that is called for
|
||||
every attribute or dict key/value. It receives the current instance,
|
||||
field and value and must return the (updated) value. The hook is run
|
||||
*after* the optional *filter* has been applied.
|
||||
|
||||
:rtype: return type of *dict_factory*
|
||||
|
||||
|
@ -207,18 +206,16 @@ def astuple(
|
|||
Optionally recurse into other *attrs*-decorated classes.
|
||||
|
||||
:param inst: Instance of an *attrs*-decorated class.
|
||||
:param bool recurse: Recurse into classes that are also
|
||||
*attrs*-decorated.
|
||||
:param callable filter: A callable whose return code determines whether an
|
||||
attribute or element is included (``True``) or dropped (``False``). Is
|
||||
called with the `attrs.Attribute` as the first argument and the
|
||||
value as the second argument.
|
||||
:param callable tuple_factory: A callable to produce tuples from. For
|
||||
example, to produce lists instead of tuples.
|
||||
:param bool retain_collection_types: Do not convert to ``list``
|
||||
or ``dict`` when encountering an attribute which type is
|
||||
``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is
|
||||
``True``.
|
||||
:param bool recurse: Recurse into classes that are also *attrs*-decorated.
|
||||
:param ~typing.Callable filter: A callable whose return code determines
|
||||
whether an attribute or element is included (`True`) or dropped
|
||||
(`False`). Is called with the `attrs.Attribute` as the first argument
|
||||
and the value as the second argument.
|
||||
:param ~typing.Callable tuple_factory: A callable to produce tuples from.
|
||||
For example, to produce lists instead of tuples.
|
||||
:param bool retain_collection_types: Do not convert to `list` or `dict`
|
||||
when encountering an attribute which type is `tuple`, `dict` or `set`.
|
||||
Only meaningful if *recurse* is `True`.
|
||||
|
||||
:rtype: return type of *tuple_factory*
|
||||
|
||||
|
@ -248,15 +245,17 @@ def astuple(
|
|||
elif isinstance(v, (tuple, list, set, frozenset)):
|
||||
cf = v.__class__ if retain is True else list
|
||||
items = [
|
||||
astuple(
|
||||
j,
|
||||
recurse=True,
|
||||
filter=filter,
|
||||
tuple_factory=tuple_factory,
|
||||
retain_collection_types=retain,
|
||||
(
|
||||
astuple(
|
||||
j,
|
||||
recurse=True,
|
||||
filter=filter,
|
||||
tuple_factory=tuple_factory,
|
||||
retain_collection_types=retain,
|
||||
)
|
||||
if has(j.__class__)
|
||||
else j
|
||||
)
|
||||
if has(j.__class__)
|
||||
else j
|
||||
for j in v
|
||||
]
|
||||
try:
|
||||
|
@ -272,20 +271,24 @@ def astuple(
|
|||
rv.append(
|
||||
df(
|
||||
(
|
||||
astuple(
|
||||
kk,
|
||||
tuple_factory=tuple_factory,
|
||||
retain_collection_types=retain,
|
||||
)
|
||||
if has(kk.__class__)
|
||||
else kk,
|
||||
astuple(
|
||||
vv,
|
||||
tuple_factory=tuple_factory,
|
||||
retain_collection_types=retain,
|
||||
)
|
||||
if has(vv.__class__)
|
||||
else vv,
|
||||
(
|
||||
astuple(
|
||||
kk,
|
||||
tuple_factory=tuple_factory,
|
||||
retain_collection_types=retain,
|
||||
)
|
||||
if has(kk.__class__)
|
||||
else kk
|
||||
),
|
||||
(
|
||||
astuple(
|
||||
vv,
|
||||
tuple_factory=tuple_factory,
|
||||
retain_collection_types=retain,
|
||||
)
|
||||
if has(vv.__class__)
|
||||
else vv
|
||||
),
|
||||
)
|
||||
for kk, vv in v.items()
|
||||
)
|
||||
|
@ -356,7 +359,7 @@ def assoc(inst, **changes):
|
|||
if a is NOTHING:
|
||||
msg = f"{k} is not an attrs attribute on {new.__class__}."
|
||||
raise AttrsAttributeNotFoundError(msg)
|
||||
_obj_setattr(new, k, v)
|
||||
_OBJ_SETATTR(new, k, v)
|
||||
return new
|
||||
|
||||
|
||||
|
@ -365,7 +368,8 @@ def evolve(*args, **changes):
|
|||
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. *inst* must be
|
||||
passed as a positional argument.
|
||||
:param changes: Keyword changes in the new copy.
|
||||
|
||||
: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
|
||||
it will become an error. Always pass the instance as a positional
|
||||
argument.
|
||||
.. versionchanged:: 24.1.0
|
||||
*inst* can't be passed as a keyword argument anymore.
|
||||
"""
|
||||
# Try to get instance by positional argument first.
|
||||
# Use changes otherwise and warn it'll break.
|
||||
if args:
|
||||
try:
|
||||
(inst,) = args
|
||||
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,
|
||||
try:
|
||||
(inst,) = args
|
||||
except ValueError:
|
||||
msg = (
|
||||
f"evolve() takes 1 positional argument, but {len(args)} were given"
|
||||
)
|
||||
raise TypeError(msg) from None
|
||||
|
||||
cls = inst.__class__
|
||||
attrs = fields(cls)
|
||||
|
@ -426,25 +416,25 @@ def resolve_types(
|
|||
Resolve any strings and forward annotations in type annotations.
|
||||
|
||||
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
|
||||
use them for static type checking.
|
||||
field. In other words, you don't need to resolve your types if you only use
|
||||
them for static type checking.
|
||||
|
||||
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
|
||||
inside a method, you may pass *globalns* or *localns* to specify other
|
||||
dictionaries in which to look up these names. See the docs of
|
||||
was created. If this is not what you want, for example, if the name only
|
||||
exists inside a method, you may pass *globalns* or *localns* to specify
|
||||
other dictionaries in which to look up these names. See the docs of
|
||||
`typing.get_type_hints` for more details.
|
||||
|
||||
:param type cls: Class to resolve.
|
||||
:param Optional[dict] globalns: Dictionary containing global variables.
|
||||
:param Optional[dict] localns: Dictionary containing local variables.
|
||||
:param Optional[list] attribs: List of attribs for the given class.
|
||||
This is necessary when calling from inside a ``field_transformer``
|
||||
since *cls* is not an *attrs* class yet.
|
||||
:param 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.
|
||||
:param dict | None globalns: Dictionary containing global variables.
|
||||
:param dict | None localns: Dictionary containing local variables.
|
||||
:param list | None attribs: List of attribs for the given class. This is
|
||||
necessary when calling from inside a ``field_transformer`` since *cls*
|
||||
is not an *attrs* class yet.
|
||||
:param 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 attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs*
|
||||
|
@ -458,7 +448,6 @@ def resolve_types(
|
|||
.. versionadded:: 20.1.0
|
||||
.. versionadded:: 21.1.0 *attribs*
|
||||
.. versionadded:: 23.1.0 *include_extras*
|
||||
|
||||
"""
|
||||
# Since calling get_type_hints is expensive we cache whether we've
|
||||
# done it already.
|
||||
|
@ -474,7 +463,7 @@ def resolve_types(
|
|||
for field in fields(cls) if attribs is None else attribs:
|
||||
if field.name in hints:
|
||||
# Since fields have been frozen we must work around it.
|
||||
_obj_setattr(field, "type", hints[field.name])
|
||||
_OBJ_SETATTR(field, "type", hints[field.name])
|
||||
# We store the class we resolved so that subclasses know they haven't
|
||||
# been resolved.
|
||||
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 astuple as _astuple
|
||||
from ._make import (
|
||||
_DEFAULT_ON_SETATTR,
|
||||
NOTHING,
|
||||
_frozen_setattrs,
|
||||
_ng_default_on_setattr,
|
||||
attrib,
|
||||
attrs,
|
||||
)
|
||||
|
@ -52,8 +52,8 @@ def define(
|
|||
|
||||
- Automatically detect whether or not *auto_attribs* should be `True` (c.f.
|
||||
*auto_attribs* parameter).
|
||||
- If *frozen* is `False`, run converters and validators when setting an
|
||||
attribute by default.
|
||||
- Converters and validators run when attributes are set by default -- if
|
||||
*frozen* is `False`.
|
||||
- *slots=True*
|
||||
|
||||
.. caution::
|
||||
|
@ -70,7 +70,7 @@ def define(
|
|||
Please note that these are all defaults and you can change them as you
|
||||
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:
|
||||
|
||||
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.
|
||||
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
|
||||
# and disable on_setattr.
|
||||
|
@ -146,7 +146,7 @@ def define(
|
|||
return do_it(cls, False)
|
||||
|
||||
# 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:
|
||||
return wrap
|
||||
|
||||
|
|
|
@ -22,12 +22,12 @@ __all__ = [
|
|||
def optional(converter):
|
||||
"""
|
||||
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
|
||||
has any.
|
||||
Type annotations will be inferred from the wrapped converter's, if it has
|
||||
any.
|
||||
|
||||
:param callable converter: the converter that is used for non-``None``
|
||||
:param typing.Callable converter: the converter that is used for non-`None`
|
||||
values.
|
||||
|
||||
.. versionadded:: 17.1.0
|
||||
|
@ -53,14 +53,14 @@ def optional(converter):
|
|||
|
||||
def default_if_none(default=NOTHING, factory=None):
|
||||
"""
|
||||
A converter that allows to replace ``None`` values by *default* or the
|
||||
result of *factory*.
|
||||
A converter that allows to replace `None` values by *default* or the result
|
||||
of *factory*.
|
||||
|
||||
:param default: Value to be used if ``None`` is passed. Passing an instance
|
||||
of `attrs.Factory` is supported, however the ``takes_self`` option
|
||||
is *not*.
|
||||
:param callable factory: A callable that takes no parameters whose result
|
||||
is used if ``None`` is passed.
|
||||
:param default: Value to be used if `None` is passed. Passing an instance
|
||||
of `attrs.Factory` is supported, however the ``takes_self`` option is
|
||||
*not*.
|
||||
:param typing.Callable factory: A callable that takes no parameters whose
|
||||
result is used if `None` is passed.
|
||||
|
||||
:raises TypeError: If **neither** *default* or *factory* is passed.
|
||||
: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):
|
||||
"""
|
||||
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`
|
||||
- :code:`"true"` / :code:`"t"`
|
||||
- :code:`"yes"` / :code:`"y"`
|
||||
- :code:`"on"`
|
||||
- :code:`"1"`
|
||||
- :code:`1`
|
||||
- ``True``
|
||||
- ``"true"`` / ``"t"``
|
||||
- ``"yes"`` / ``"y"``
|
||||
- ``"on"``
|
||||
- ``"1"``
|
||||
- ``1``
|
||||
|
||||
Values mapping to :code:`False`:
|
||||
Values mapping to `False`:
|
||||
|
||||
- :code:`False`
|
||||
- :code:`"false"` / :code:`"f"`
|
||||
- :code:`"no"` / :code:`"n"`
|
||||
- :code:`"off"`
|
||||
- :code:`"0"`
|
||||
- :code:`0`
|
||||
- ``False``
|
||||
- ``"false"`` / ``"f"``
|
||||
- ``"no"`` / ``"n"``
|
||||
- ``"off"``
|
||||
- ``"0"``
|
||||
- ``0``
|
||||
|
||||
:raises ValueError: for any other value.
|
||||
|
||||
|
@ -130,15 +131,11 @@ def to_bool(val):
|
|||
"""
|
||||
if isinstance(val, str):
|
||||
val = val.lower()
|
||||
truthy = {True, "true", "t", "yes", "y", "on", "1", 1}
|
||||
falsy = {False, "false", "f", "no", "n", "off", "0", 0}
|
||||
try:
|
||||
if val in truthy:
|
||||
return True
|
||||
if val in falsy:
|
||||
return False
|
||||
except TypeError:
|
||||
# Raised when "val" is not hashable (e.g., lists)
|
||||
pass
|
||||
msg = f"Cannot convert value to bool: {val}"
|
||||
|
||||
if val in (True, "true", "t", "yes", "y", "on", "1", 1):
|
||||
return True
|
||||
if val in (False, "false", "f", "no", "n", "off", "0", 0):
|
||||
return False
|
||||
|
||||
msg = f"Cannot convert value to bool: {val!r}"
|
||||
raise ValueError(msg)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Callable, TypeVar, overload
|
||||
|
||||
from . import _ConverterType
|
||||
from attrs import _ConverterType
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from typing import Any, Union
|
||||
from typing import Any
|
||||
|
||||
from . import Attribute, _FilterType
|
||||
|
||||
def include(*what: Union[type, str, Attribute[Any]]) -> _FilterType[Any]: ...
|
||||
def exclude(*what: Union[type, str, Attribute[Any]]) -> _FilterType[Any]: ...
|
||||
def include(*what: 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.
|
||||
# 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()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from typing import Any, NewType, NoReturn, TypeVar
|
||||
|
||||
from . import Attribute, _OnSetAttrType
|
||||
from . import Attribute
|
||||
from attrs import _OnSetAttrType
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ __all__ = [
|
|||
"min_len",
|
||||
"not_",
|
||||
"optional",
|
||||
"provides",
|
||||
"set_disabled",
|
||||
]
|
||||
|
||||
|
@ -46,7 +45,7 @@ def set_disabled(disabled):
|
|||
|
||||
By default, they are run.
|
||||
|
||||
:param disabled: If ``True``, disable running all validators.
|
||||
:param disabled: If `True`, disable running all validators.
|
||||
:type disabled: bool
|
||||
|
||||
.. warning::
|
||||
|
@ -62,7 +61,7 @@ def get_disabled():
|
|||
"""
|
||||
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
|
||||
|
||||
.. versionadded:: 21.3.0
|
||||
|
@ -97,12 +96,7 @@ class _InstanceOfValidator:
|
|||
We use a callable class to be able to change the ``__repr__``.
|
||||
"""
|
||||
if not isinstance(value, self.type):
|
||||
msg = "'{name}' must be {type!r} (got {value!r} that is a {actual!r}).".format(
|
||||
name=attr.name,
|
||||
type=self.type,
|
||||
actual=value.__class__,
|
||||
value=value,
|
||||
)
|
||||
msg = f"'{attr.name}' must be {self.type!r} (got {value!r} that is a {value.__class__!r})."
|
||||
raise TypeError(
|
||||
msg,
|
||||
attr,
|
||||
|
@ -116,16 +110,14 @@ class _InstanceOfValidator:
|
|||
|
||||
def instance_of(type):
|
||||
"""
|
||||
A validator that raises a `TypeError` if the initializer is called
|
||||
with a wrong type for this particular attribute (checks are performed using
|
||||
A validator that raises a `TypeError` if the initializer is called with a
|
||||
wrong type for this particular attribute (checks are performed using
|
||||
`isinstance` therefore it's also valid to pass a tuple of types).
|
||||
|
||||
:param type: The type to check for.
|
||||
:type type: type or tuple of type
|
||||
:param type | tuple[type] type: The type to check for.
|
||||
|
||||
:raises TypeError: With a human readable error message, the attribute
|
||||
(of type `attrs.Attribute`), the expected type, and the value it
|
||||
got.
|
||||
:raises TypeError: With a human readable error message, the attribute (of
|
||||
type `attrs.Attribute`), the expected type, and the value it got.
|
||||
"""
|
||||
return _InstanceOfValidator(type)
|
||||
|
||||
|
@ -140,9 +132,7 @@ class _MatchesReValidator:
|
|||
We use a callable class to be able to change the ``__repr__``.
|
||||
"""
|
||||
if not self.match_func(value):
|
||||
msg = "'{name}' must match regex {pattern!r} ({value!r} doesn't)".format(
|
||||
name=attr.name, pattern=self.pattern.pattern, value=value
|
||||
)
|
||||
msg = f"'{attr.name}' must match regex {self.pattern.pattern!r} ({value!r} doesn't)"
|
||||
raise ValueError(
|
||||
msg,
|
||||
attr,
|
||||
|
@ -156,16 +146,16 @@ class _MatchesReValidator:
|
|||
|
||||
def matches_re(regex, flags=0, func=None):
|
||||
r"""
|
||||
A validator that raises `ValueError` if the initializer is called
|
||||
with a string that doesn't match *regex*.
|
||||
A validator that raises `ValueError` if the initializer is called with a
|
||||
string that doesn't match *regex*.
|
||||
|
||||
:param regex: a regex string or precompiled pattern to match against
|
||||
:param int flags: flags that will be passed to the underlying re function
|
||||
(default 0)
|
||||
:param callable func: which underlying `re` function to call. Valid options
|
||||
are `re.fullmatch`, `re.search`, and `re.match`; the default ``None``
|
||||
means `re.fullmatch`. For performance reasons, the pattern is always
|
||||
precompiled using `re.compile`.
|
||||
:param typing.Callable func: which underlying `re` function to call. Valid
|
||||
options are `re.fullmatch`, `re.search`, and `re.match`; the default
|
||||
`None` means `re.fullmatch`. For performance reasons, the pattern is
|
||||
always precompiled using `re.compile`.
|
||||
|
||||
.. versionadded:: 19.2.0
|
||||
.. 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)
|
||||
|
||||
|
||||
@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)
|
||||
class _OptionalValidator:
|
||||
validator = attrib()
|
||||
|
@ -264,11 +204,13 @@ class _OptionalValidator:
|
|||
def optional(validator):
|
||||
"""
|
||||
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.
|
||||
|
||||
:param Callable | tuple[Callable] | list[Callable] validator: A validator
|
||||
(or validators) that is used for non-``None`` values.
|
||||
:param validator: A validator (or validators) that is used for non-`None`
|
||||
values.
|
||||
:type validator: typing.Callable | tuple[typing.Callable] |
|
||||
list[typing.Callable]
|
||||
|
||||
.. versionadded:: 15.1.0
|
||||
.. versionchanged:: 17.1.0 *validator* can be a list of validators.
|
||||
|
@ -426,9 +368,7 @@ class _DeepMapping:
|
|||
self.value_validator(inst, attr, value[key])
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
"<deep_mapping validator for objects mapping {key!r} to {value!r}>"
|
||||
).format(key=self.key_validator, value=self.value_validator)
|
||||
return f"<deep_mapping validator for objects mapping {self.key_validator!r} to {self.value_validator!r}>"
|
||||
|
||||
|
||||
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__``.
|
||||
"""
|
||||
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)
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -640,12 +580,7 @@ class _NotValidator:
|
|||
)
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
"<not_ validator wrapping {what!r}, capturing {exc_types!r}>"
|
||||
).format(
|
||||
what=self.validator,
|
||||
exc_types=self.exc_types,
|
||||
)
|
||||
return f"<not_ validator wrapping {self.validator!r}, capturing {self.exc_types!r}>"
|
||||
|
||||
|
||||
def not_(validator, *, msg=None, exc_types=(ValueError, TypeError)):
|
||||
|
|
|
@ -5,20 +5,15 @@ from typing import (
|
|||
Container,
|
||||
ContextManager,
|
||||
Iterable,
|
||||
List,
|
||||
Mapping,
|
||||
Match,
|
||||
Optional,
|
||||
Pattern,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
overload,
|
||||
)
|
||||
|
||||
from . import _ValidatorType
|
||||
from . import _ValidatorArgType
|
||||
from attrs import _ValidatorType
|
||||
from attrs import _ValidatorArgType
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_T1 = TypeVar("_T1")
|
||||
|
@ -36,42 +31,41 @@ def disabled() -> ContextManager[None]: ...
|
|||
# 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
|
||||
@overload
|
||||
def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ...
|
||||
def instance_of(type: type[_T]) -> _ValidatorType[_T]: ...
|
||||
@overload
|
||||
def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ...
|
||||
def instance_of(type: tuple[type[_T]]) -> _ValidatorType[_T]: ...
|
||||
@overload
|
||||
def instance_of(
|
||||
type: Tuple[Type[_T1], Type[_T2]]
|
||||
) -> _ValidatorType[Union[_T1, _T2]]: ...
|
||||
type: tuple[type[_T1], type[_T2]]
|
||||
) -> _ValidatorType[_T1 | _T2]: ...
|
||||
@overload
|
||||
def instance_of(
|
||||
type: Tuple[Type[_T1], Type[_T2], Type[_T3]]
|
||||
) -> _ValidatorType[Union[_T1, _T2, _T3]]: ...
|
||||
type: tuple[type[_T1], type[_T2], type[_T3]]
|
||||
) -> _ValidatorType[_T1 | _T2 | _T3]: ...
|
||||
@overload
|
||||
def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ...
|
||||
def provides(interface: Any) -> _ValidatorType[Any]: ...
|
||||
def instance_of(type: tuple[type, ...]) -> _ValidatorType[Any]: ...
|
||||
def optional(
|
||||
validator: Union[
|
||||
_ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_ValidatorType[_T]]
|
||||
]
|
||||
) -> _ValidatorType[Optional[_T]]: ...
|
||||
validator: (
|
||||
_ValidatorType[_T]
|
||||
| list[_ValidatorType[_T]]
|
||||
| tuple[_ValidatorType[_T]]
|
||||
),
|
||||
) -> _ValidatorType[_T | None]: ...
|
||||
def in_(options: Container[_T]) -> _ValidatorType[_T]: ...
|
||||
def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ...
|
||||
def matches_re(
|
||||
regex: Union[Pattern[AnyStr], AnyStr],
|
||||
regex: Pattern[AnyStr] | AnyStr,
|
||||
flags: int = ...,
|
||||
func: Optional[
|
||||
Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]]
|
||||
] = ...,
|
||||
func: Callable[[AnyStr, AnyStr, int], Match[AnyStr] | None] | None = ...,
|
||||
) -> _ValidatorType[AnyStr]: ...
|
||||
def deep_iterable(
|
||||
member_validator: _ValidatorArgType[_T],
|
||||
iterable_validator: Optional[_ValidatorType[_I]] = ...,
|
||||
iterable_validator: _ValidatorType[_I] | None = ...,
|
||||
) -> _ValidatorType[_I]: ...
|
||||
def deep_mapping(
|
||||
key_validator: _ValidatorType[_K],
|
||||
value_validator: _ValidatorType[_V],
|
||||
mapping_validator: Optional[_ValidatorType[_M]] = ...,
|
||||
mapping_validator: _ValidatorType[_M] | None = ...,
|
||||
) -> _ValidatorType[_M]: ...
|
||||
def is_callable() -> _ValidatorType[_T]: ...
|
||||
def lt(val: _T) -> _ValidatorType[_T]: ...
|
||||
|
@ -83,6 +77,6 @@ def min_len(length: int) -> _ValidatorType[_T]: ...
|
|||
def not_(
|
||||
validator: _ValidatorType[_T],
|
||||
*,
|
||||
msg: Optional[str] = None,
|
||||
exc_types: Union[Type[Exception], Iterable[Type[Exception]]] = ...,
|
||||
msg: str | None = None,
|
||||
exc_types: type[Exception] | Iterable[type[Exception]] = ...,
|
||||
) -> _ValidatorType[_T]: ...
|
||||
|
|
Loading…
Reference in a new issue