ant-ray-nightly 3.0.0.dev20251006__cp312-cp312-macosx_14_0_arm64.whl → 3.0.0.dev20251015__cp312-cp312-macosx_14_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ant-ray-nightly might be problematic. Click here for more details.
- {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/METADATA +105 -105
- {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/RECORD +100 -100
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/_cparser.pxd.hash +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/_find_header.pxd.hash +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/_http_parser.pyx.hash +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/_http_writer.pyx.hash +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/hdrs.py.hash +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/__init__.py +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_cookie_helpers.py +2 -6
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_http_parser.cpython-312-darwin.so +0 -0
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_http_parser.pyx +1 -3
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_http_writer.cpython-312-darwin.so +0 -0
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_http_writer.pyx +9 -7
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/.hash/mask.pxd.hash +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/.hash/mask.pyx.hash +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/.hash/reader_c.pxd.hash +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/mask.cpython-312-darwin.so +0 -0
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/reader_c.cpython-312-darwin.so +0 -0
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/abc.py +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/client_reqrep.py +13 -4
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/compression_utils.py +31 -0
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/formdata.py +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/http_parser.py +18 -3
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/multipart.py +4 -0
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/streams.py +8 -0
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/web_fileresponse.py +4 -4
- ray/_private/runtime_env/agent/thirdparty_files/aiohttp/web_urldispatcher.py +3 -1
- ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/METADATA +24 -12
- ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/RECORD +33 -33
- ray/_private/runtime_env/agent/thirdparty_files/attr/__init__.pyi +4 -4
- ray/_private/runtime_env/agent/thirdparty_files/attr/_compat.py +8 -3
- ray/_private/runtime_env/agent/thirdparty_files/attr/_funcs.py +45 -16
- ray/_private/runtime_env/agent/thirdparty_files/attr/_make.py +334 -95
- ray/_private/runtime_env/agent/thirdparty_files/attr/_next_gen.py +58 -7
- ray/_private/runtime_env/agent/thirdparty_files/attr/_version_info.py +3 -0
- ray/_private/runtime_env/agent/thirdparty_files/attr/validators.py +51 -13
- ray/_private/runtime_env/agent/thirdparty_files/attr/validators.pyi +59 -5
- ray/_private/runtime_env/agent/thirdparty_files/attrs/__init__.py +4 -1
- ray/_private/runtime_env/agent/thirdparty_files/attrs/__init__.pyi +58 -7
- ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/METADATA +63 -60
- ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/RECORD +15 -15
- ray/_private/runtime_env/agent/thirdparty_files/frozenlist/__init__.py +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/frozenlist/_frozenlist.cpython-312-darwin.so +0 -0
- ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/METADATA +47 -1
- ray/_private/runtime_env/agent/thirdparty_files/frozenlist-1.8.0.dist-info/RECORD +12 -0
- ray/_private/runtime_env/agent/thirdparty_files/idna/codec.py +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/idna/core.py +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/idna/idnadata.py +72 -6
- ray/_private/runtime_env/agent/thirdparty_files/idna/package_data.py +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/idna/uts46data.py +891 -731
- ray/_private/runtime_env/agent/thirdparty_files/{idna-3.10.dist-info → idna-3.11.dist-info}/METADATA +37 -78
- ray/_private/runtime_env/agent/thirdparty_files/idna-3.11.dist-info/RECORD +22 -0
- ray/_private/runtime_env/agent/thirdparty_files/{idna-3.10.dist-info → idna-3.11.dist-info}/WHEEL +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/{idna-3.10.dist-info → idna-3.11.dist-info/licenses}/LICENSE.md +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/multidict/__init__.py +9 -8
- ray/_private/runtime_env/agent/thirdparty_files/multidict/_multidict.cpython-312-darwin.so +0 -0
- ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/METADATA +2 -1
- ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/RECORD +8 -8
- ray/_private/runtime_env/agent/thirdparty_files/propcache/__init__.py +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/propcache/_helpers_c.cpython-312-darwin.so +0 -0
- ray/_private/runtime_env/agent/thirdparty_files/propcache/_helpers_c.pyx +4 -5
- ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/METADATA +31 -1
- ray/_private/runtime_env/agent/thirdparty_files/propcache-0.4.1.dist-info/RECORD +18 -0
- ray/_private/runtime_env/agent/thirdparty_files/yarl/__init__.py +1 -1
- ray/_private/runtime_env/agent/thirdparty_files/yarl/_quoting_c.cpython-312-darwin.so +0 -0
- ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/METADATA +20 -1
- ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/RECORD +9 -9
- ray/thirdparty_files/setproctitle-1.2.2.dist-info/RECORD +1 -1
- ray/thirdparty_files/setproctitle.cpython-312-darwin.so +0 -0
- ray/_private/runtime_env/agent/thirdparty_files/frozenlist-1.7.0.dist-info/RECORD +0 -12
- ray/_private/runtime_env/agent/thirdparty_files/idna-3.10.dist-info/RECORD +0 -22
- ray/_private/runtime_env/agent/thirdparty_files/propcache-0.4.0.dist-info/RECORD +0 -18
- {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/WHEEL +0 -0
- {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/entry_points.txt +0 -0
- {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/top_level.txt +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/INSTALLER +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/REQUESTED +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/WHEEL +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/licenses/LICENSE.txt +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/licenses/vendor/llhttp/LICENSE +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/top_level.txt +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/INSTALLER +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/WHEEL +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/licenses/LICENSE +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/INSTALLER +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/WHEEL +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/licenses/LICENSE +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/top_level.txt +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{idna-3.10.dist-info → idna-3.11.dist-info}/INSTALLER +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/INSTALLER +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/WHEEL +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/licenses/LICENSE +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/top_level.txt +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/INSTALLER +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/WHEEL +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/licenses/LICENSE +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/licenses/NOTICE +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/top_level.txt +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/INSTALLER +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/WHEEL +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/licenses/LICENSE +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/licenses/NOTICE +0 -0
- /ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/top_level.txt +0 -0
|
@@ -17,7 +17,7 @@ from ._make import (
|
|
|
17
17
|
attrib,
|
|
18
18
|
attrs,
|
|
19
19
|
)
|
|
20
|
-
from .exceptions import UnannotatedAttributeError
|
|
20
|
+
from .exceptions import NotAnAttrsClassError, UnannotatedAttributeError
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def define(
|
|
@@ -43,6 +43,7 @@ def define(
|
|
|
43
43
|
on_setattr=None,
|
|
44
44
|
field_transformer=None,
|
|
45
45
|
match_args=True,
|
|
46
|
+
force_kw_only=False,
|
|
46
47
|
):
|
|
47
48
|
r"""
|
|
48
49
|
A class decorator that adds :term:`dunder methods` according to
|
|
@@ -76,7 +77,7 @@ def define(
|
|
|
76
77
|
sensible ``__ne__`` by default, so it *should* be enough to only
|
|
77
78
|
implement ``__eq__`` in most cases).
|
|
78
79
|
|
|
79
|
-
Passing True or False` to *init*, *repr*, *eq*, or *hash*
|
|
80
|
+
Passing :data:`True` or :data:`False` to *init*, *repr*, *eq*, or *hash*
|
|
80
81
|
overrides whatever *auto_detect* would determine.
|
|
81
82
|
|
|
82
83
|
auto_exc (bool):
|
|
@@ -214,8 +215,12 @@ def define(
|
|
|
214
215
|
5. Subclasses of a frozen class are frozen too.
|
|
215
216
|
|
|
216
217
|
kw_only (bool):
|
|
217
|
-
Make
|
|
218
|
-
*init* is False, this parameter is ignored).
|
|
218
|
+
Make attributes keyword-only in the generated ``__init__`` (if
|
|
219
|
+
*init* is False, this parameter is ignored). Attributes that
|
|
220
|
+
explicitly set ``kw_only=False`` are not affected; base class
|
|
221
|
+
attributes are also not affected.
|
|
222
|
+
|
|
223
|
+
Also see *force_kw_only*.
|
|
219
224
|
|
|
220
225
|
weakref_slot (bool):
|
|
221
226
|
Make instances weak-referenceable. This has no effect unless
|
|
@@ -244,6 +249,15 @@ def define(
|
|
|
244
249
|
See also `issue #428
|
|
245
250
|
<https://github.com/python-attrs/attrs/issues/428>`_.
|
|
246
251
|
|
|
252
|
+
force_kw_only (bool):
|
|
253
|
+
A back-compat flag for restoring pre-25.4.0 behavior. If True and
|
|
254
|
+
``kw_only=True``, all attributes are made keyword-only, including
|
|
255
|
+
base class attributes, and those set to ``kw_only=False`` at the
|
|
256
|
+
attribute level. Defaults to False.
|
|
257
|
+
|
|
258
|
+
See also `issue #980
|
|
259
|
+
<https://github.com/python-attrs/attrs/issues/980>`_.
|
|
260
|
+
|
|
247
261
|
getstate_setstate (bool | None):
|
|
248
262
|
.. note::
|
|
249
263
|
|
|
@@ -319,6 +333,11 @@ def define(
|
|
|
319
333
|
.. versionadded:: 24.3.0
|
|
320
334
|
Unless already present, a ``__replace__`` method is automatically
|
|
321
335
|
created for `copy.replace` (Python 3.13+ only).
|
|
336
|
+
.. versionchanged:: 25.4.0
|
|
337
|
+
*kw_only* now only applies to attributes defined in the current class,
|
|
338
|
+
and respects attribute-level ``kw_only=False`` settings.
|
|
339
|
+
.. versionadded:: 25.4.0
|
|
340
|
+
Added *force_kw_only* to go back to the previous *kw_only* behavior.
|
|
322
341
|
|
|
323
342
|
.. note::
|
|
324
343
|
|
|
@@ -337,6 +356,7 @@ def define(
|
|
|
337
356
|
- *auto_exc=True*
|
|
338
357
|
- *auto_detect=True*
|
|
339
358
|
- *order=False*
|
|
359
|
+
- *force_kw_only=False*
|
|
340
360
|
- Some options that were only relevant on Python 2 or were kept around
|
|
341
361
|
for backwards-compatibility have been removed.
|
|
342
362
|
|
|
@@ -366,6 +386,7 @@ def define(
|
|
|
366
386
|
on_setattr=on_setattr,
|
|
367
387
|
field_transformer=field_transformer,
|
|
368
388
|
match_args=match_args,
|
|
389
|
+
force_kw_only=force_kw_only,
|
|
369
390
|
)
|
|
370
391
|
|
|
371
392
|
def wrap(cls):
|
|
@@ -424,7 +445,7 @@ def field(
|
|
|
424
445
|
type=None,
|
|
425
446
|
converter=None,
|
|
426
447
|
factory=None,
|
|
427
|
-
kw_only=
|
|
448
|
+
kw_only=None,
|
|
428
449
|
eq=None,
|
|
429
450
|
order=None,
|
|
430
451
|
on_setattr=None,
|
|
@@ -550,9 +571,10 @@ def field(
|
|
|
550
571
|
itself. You can use it as part of your own code or for `static type
|
|
551
572
|
checking <types>`.
|
|
552
573
|
|
|
553
|
-
kw_only (bool):
|
|
574
|
+
kw_only (bool | None):
|
|
554
575
|
Make this attribute keyword-only in the generated ``__init__`` (if
|
|
555
|
-
|
|
576
|
+
*init* is False, this parameter is ignored). If None (default),
|
|
577
|
+
mirror the setting from `attrs.define`.
|
|
556
578
|
|
|
557
579
|
on_setattr (~typing.Callable | list[~typing.Callable] | None | ~typing.Literal[attrs.setters.NO_OP]):
|
|
558
580
|
Allows to overwrite the *on_setattr* setting from `attr.s`. If left
|
|
@@ -572,6 +594,9 @@ def field(
|
|
|
572
594
|
.. versionadded:: 23.1.0
|
|
573
595
|
The *type* parameter has been re-added; mostly for `attrs.make_class`.
|
|
574
596
|
Please note that type checkers ignore this metadata.
|
|
597
|
+
.. versionchanged:: 25.4.0
|
|
598
|
+
*kw_only* can now be None, and its default is also changed from False to
|
|
599
|
+
None.
|
|
575
600
|
|
|
576
601
|
.. seealso::
|
|
577
602
|
|
|
@@ -621,3 +646,29 @@ def astuple(inst, *, recurse=True, filter=None):
|
|
|
621
646
|
return _astuple(
|
|
622
647
|
inst=inst, recurse=recurse, filter=filter, retain_collection_types=True
|
|
623
648
|
)
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
def inspect(cls):
|
|
652
|
+
"""
|
|
653
|
+
Inspect the class and return its effective build parameters.
|
|
654
|
+
|
|
655
|
+
Warning:
|
|
656
|
+
This feature is currently **experimental** and is not covered by our
|
|
657
|
+
strict backwards-compatibility guarantees.
|
|
658
|
+
|
|
659
|
+
Args:
|
|
660
|
+
cls: The *attrs*-decorated class to inspect.
|
|
661
|
+
|
|
662
|
+
Returns:
|
|
663
|
+
The effective build parameters of the class.
|
|
664
|
+
|
|
665
|
+
Raises:
|
|
666
|
+
NotAnAttrsClassError: If the class is not an *attrs*-decorated class.
|
|
667
|
+
|
|
668
|
+
.. versionadded:: 25.4.0
|
|
669
|
+
"""
|
|
670
|
+
try:
|
|
671
|
+
return cls.__dict__["__attrs_props__"]
|
|
672
|
+
except KeyError:
|
|
673
|
+
msg = f"{cls!r} is not an attrs-decorated class."
|
|
674
|
+
raise NotAnAttrsClassError(msg) from None
|
|
@@ -84,3 +84,6 @@ class VersionInfo:
|
|
|
84
84
|
# Since alphabetically "dev0" < "final" < "post1" < "post2", we don't
|
|
85
85
|
# have to do anything special with releaselevel for now.
|
|
86
86
|
return us < them
|
|
87
|
+
|
|
88
|
+
def __hash__(self):
|
|
89
|
+
return hash((self.year, self.minor, self.micro, self.releaselevel))
|
|
@@ -361,26 +361,32 @@ def deep_iterable(member_validator, iterable_validator=None):
|
|
|
361
361
|
A validator that performs deep validation of an iterable.
|
|
362
362
|
|
|
363
363
|
Args:
|
|
364
|
-
member_validator: Validator to apply to iterable members.
|
|
364
|
+
member_validator: Validator(s) to apply to iterable members.
|
|
365
365
|
|
|
366
366
|
iterable_validator:
|
|
367
|
-
Validator to apply to iterable itself (optional).
|
|
367
|
+
Validator(s) to apply to iterable itself (optional).
|
|
368
368
|
|
|
369
369
|
Raises
|
|
370
370
|
TypeError: if any sub-validators fail
|
|
371
371
|
|
|
372
372
|
.. versionadded:: 19.1.0
|
|
373
|
+
|
|
374
|
+
.. versionchanged:: 25.4.0
|
|
375
|
+
*member_validator* and *iterable_validator* can now be a list or tuple
|
|
376
|
+
of validators.
|
|
373
377
|
"""
|
|
374
378
|
if isinstance(member_validator, (list, tuple)):
|
|
375
379
|
member_validator = and_(*member_validator)
|
|
380
|
+
if isinstance(iterable_validator, (list, tuple)):
|
|
381
|
+
iterable_validator = and_(*iterable_validator)
|
|
376
382
|
return _DeepIterable(member_validator, iterable_validator)
|
|
377
383
|
|
|
378
384
|
|
|
379
385
|
@attrs(repr=False, slots=True, unsafe_hash=True)
|
|
380
386
|
class _DeepMapping:
|
|
381
|
-
key_validator = attrib(validator=is_callable())
|
|
382
|
-
value_validator = attrib(validator=is_callable())
|
|
383
|
-
mapping_validator = attrib(
|
|
387
|
+
key_validator = attrib(validator=optional(is_callable()))
|
|
388
|
+
value_validator = attrib(validator=optional(is_callable()))
|
|
389
|
+
mapping_validator = attrib(validator=optional(is_callable()))
|
|
384
390
|
|
|
385
391
|
def __call__(self, inst, attr, value):
|
|
386
392
|
"""
|
|
@@ -390,30 +396,62 @@ class _DeepMapping:
|
|
|
390
396
|
self.mapping_validator(inst, attr, value)
|
|
391
397
|
|
|
392
398
|
for key in value:
|
|
393
|
-
self.key_validator
|
|
394
|
-
|
|
399
|
+
if self.key_validator is not None:
|
|
400
|
+
self.key_validator(inst, attr, key)
|
|
401
|
+
if self.value_validator is not None:
|
|
402
|
+
self.value_validator(inst, attr, value[key])
|
|
395
403
|
|
|
396
404
|
def __repr__(self):
|
|
397
405
|
return f"<deep_mapping validator for objects mapping {self.key_validator!r} to {self.value_validator!r}>"
|
|
398
406
|
|
|
399
407
|
|
|
400
|
-
def deep_mapping(
|
|
408
|
+
def deep_mapping(
|
|
409
|
+
key_validator=None, value_validator=None, mapping_validator=None
|
|
410
|
+
):
|
|
401
411
|
"""
|
|
402
412
|
A validator that performs deep validation of a dictionary.
|
|
403
413
|
|
|
414
|
+
All validators are optional, but at least one of *key_validator* or
|
|
415
|
+
*value_validator* must be provided.
|
|
416
|
+
|
|
404
417
|
Args:
|
|
405
|
-
key_validator: Validator to apply to dictionary keys.
|
|
418
|
+
key_validator: Validator(s) to apply to dictionary keys.
|
|
406
419
|
|
|
407
|
-
value_validator: Validator to apply to dictionary values.
|
|
420
|
+
value_validator: Validator(s) to apply to dictionary values.
|
|
408
421
|
|
|
409
422
|
mapping_validator:
|
|
410
|
-
Validator to apply to top-level mapping attribute
|
|
423
|
+
Validator(s) to apply to top-level mapping attribute.
|
|
411
424
|
|
|
412
425
|
.. versionadded:: 19.1.0
|
|
413
426
|
|
|
427
|
+
.. versionchanged:: 25.4.0
|
|
428
|
+
*key_validator* and *value_validator* are now optional, but at least one
|
|
429
|
+
of them must be provided.
|
|
430
|
+
|
|
431
|
+
.. versionchanged:: 25.4.0
|
|
432
|
+
*key_validator*, *value_validator*, and *mapping_validator* can now be a
|
|
433
|
+
list or tuple of validators.
|
|
434
|
+
|
|
414
435
|
Raises:
|
|
415
|
-
TypeError:
|
|
436
|
+
TypeError: If any sub-validator fails on validation.
|
|
437
|
+
|
|
438
|
+
ValueError:
|
|
439
|
+
If neither *key_validator* nor *value_validator* is provided on
|
|
440
|
+
instantiation.
|
|
416
441
|
"""
|
|
442
|
+
if key_validator is None and value_validator is None:
|
|
443
|
+
msg = (
|
|
444
|
+
"At least one of key_validator or value_validator must be provided"
|
|
445
|
+
)
|
|
446
|
+
raise ValueError(msg)
|
|
447
|
+
|
|
448
|
+
if isinstance(key_validator, (list, tuple)):
|
|
449
|
+
key_validator = and_(*key_validator)
|
|
450
|
+
if isinstance(value_validator, (list, tuple)):
|
|
451
|
+
value_validator = and_(*value_validator)
|
|
452
|
+
if isinstance(mapping_validator, (list, tuple)):
|
|
453
|
+
mapping_validator = and_(*mapping_validator)
|
|
454
|
+
|
|
417
455
|
return _DeepMapping(key_validator, value_validator, mapping_validator)
|
|
418
456
|
|
|
419
457
|
|
|
@@ -485,7 +523,7 @@ def gt(val):
|
|
|
485
523
|
A validator that raises `ValueError` if the initializer is called with a
|
|
486
524
|
number smaller or equal to *val*.
|
|
487
525
|
|
|
488
|
-
The validator uses `operator.
|
|
526
|
+
The validator uses `operator.gt` to compare the values.
|
|
489
527
|
|
|
490
528
|
Args:
|
|
491
529
|
val: Exclusive lower bound for values
|
|
@@ -20,6 +20,9 @@ _T = TypeVar("_T")
|
|
|
20
20
|
_T1 = TypeVar("_T1")
|
|
21
21
|
_T2 = TypeVar("_T2")
|
|
22
22
|
_T3 = TypeVar("_T3")
|
|
23
|
+
_T4 = TypeVar("_T4")
|
|
24
|
+
_T5 = TypeVar("_T5")
|
|
25
|
+
_T6 = TypeVar("_T6")
|
|
23
26
|
_I = TypeVar("_I", bound=Iterable)
|
|
24
27
|
_K = TypeVar("_K")
|
|
25
28
|
_V = TypeVar("_V")
|
|
@@ -63,12 +66,19 @@ def matches_re(
|
|
|
63
66
|
) -> _ValidatorType[AnyStr]: ...
|
|
64
67
|
def deep_iterable(
|
|
65
68
|
member_validator: _ValidatorArgType[_T],
|
|
66
|
-
iterable_validator:
|
|
69
|
+
iterable_validator: _ValidatorArgType[_I] | None = ...,
|
|
67
70
|
) -> _ValidatorType[_I]: ...
|
|
71
|
+
@overload
|
|
72
|
+
def deep_mapping(
|
|
73
|
+
key_validator: _ValidatorArgType[_K],
|
|
74
|
+
value_validator: _ValidatorArgType[_V] | None = ...,
|
|
75
|
+
mapping_validator: _ValidatorArgType[_M] | None = ...,
|
|
76
|
+
) -> _ValidatorType[_M]: ...
|
|
77
|
+
@overload
|
|
68
78
|
def deep_mapping(
|
|
69
|
-
key_validator:
|
|
70
|
-
value_validator:
|
|
71
|
-
mapping_validator:
|
|
79
|
+
key_validator: _ValidatorArgType[_K] | None = ...,
|
|
80
|
+
value_validator: _ValidatorArgType[_V] = ...,
|
|
81
|
+
mapping_validator: _ValidatorArgType[_M] | None = ...,
|
|
72
82
|
) -> _ValidatorType[_M]: ...
|
|
73
83
|
def is_callable() -> _ValidatorType[_T]: ...
|
|
74
84
|
def lt(val: _T) -> _ValidatorType[_T]: ...
|
|
@@ -83,4 +93,48 @@ def not_(
|
|
|
83
93
|
msg: str | None = None,
|
|
84
94
|
exc_types: type[Exception] | Iterable[type[Exception]] = ...,
|
|
85
95
|
) -> _ValidatorType[_T]: ...
|
|
86
|
-
|
|
96
|
+
@overload
|
|
97
|
+
def or_(
|
|
98
|
+
__v1: _ValidatorType[_T1],
|
|
99
|
+
__v2: _ValidatorType[_T2],
|
|
100
|
+
) -> _ValidatorType[_T1 | _T2]: ...
|
|
101
|
+
@overload
|
|
102
|
+
def or_(
|
|
103
|
+
__v1: _ValidatorType[_T1],
|
|
104
|
+
__v2: _ValidatorType[_T2],
|
|
105
|
+
__v3: _ValidatorType[_T3],
|
|
106
|
+
) -> _ValidatorType[_T1 | _T2 | _T3]: ...
|
|
107
|
+
@overload
|
|
108
|
+
def or_(
|
|
109
|
+
__v1: _ValidatorType[_T1],
|
|
110
|
+
__v2: _ValidatorType[_T2],
|
|
111
|
+
__v3: _ValidatorType[_T3],
|
|
112
|
+
__v4: _ValidatorType[_T4],
|
|
113
|
+
) -> _ValidatorType[_T1 | _T2 | _T3 | _T4]: ...
|
|
114
|
+
@overload
|
|
115
|
+
def or_(
|
|
116
|
+
__v1: _ValidatorType[_T1],
|
|
117
|
+
__v2: _ValidatorType[_T2],
|
|
118
|
+
__v3: _ValidatorType[_T3],
|
|
119
|
+
__v4: _ValidatorType[_T4],
|
|
120
|
+
__v5: _ValidatorType[_T5],
|
|
121
|
+
) -> _ValidatorType[_T1 | _T2 | _T3 | _T4 | _T5]: ...
|
|
122
|
+
@overload
|
|
123
|
+
def or_(
|
|
124
|
+
__v1: _ValidatorType[_T1],
|
|
125
|
+
__v2: _ValidatorType[_T2],
|
|
126
|
+
__v3: _ValidatorType[_T3],
|
|
127
|
+
__v4: _ValidatorType[_T4],
|
|
128
|
+
__v5: _ValidatorType[_T5],
|
|
129
|
+
__v6: _ValidatorType[_T6],
|
|
130
|
+
) -> _ValidatorType[_T1 | _T2 | _T3 | _T4 | _T5 | _T6]: ...
|
|
131
|
+
@overload
|
|
132
|
+
def or_(
|
|
133
|
+
__v1: _ValidatorType[Any],
|
|
134
|
+
__v2: _ValidatorType[Any],
|
|
135
|
+
__v3: _ValidatorType[Any],
|
|
136
|
+
__v4: _ValidatorType[Any],
|
|
137
|
+
__v5: _ValidatorType[Any],
|
|
138
|
+
__v6: _ValidatorType[Any],
|
|
139
|
+
*validators: _ValidatorType[Any],
|
|
140
|
+
) -> _ValidatorType[Any]: ...
|
|
@@ -22,7 +22,8 @@ from attr import (
|
|
|
22
22
|
resolve_types,
|
|
23
23
|
validate,
|
|
24
24
|
)
|
|
25
|
-
from attr.
|
|
25
|
+
from attr._make import ClassProps
|
|
26
|
+
from attr._next_gen import asdict, astuple, inspect
|
|
26
27
|
|
|
27
28
|
from . import converters, exceptions, filters, setters, validators
|
|
28
29
|
|
|
@@ -31,6 +32,7 @@ __all__ = [
|
|
|
31
32
|
"NOTHING",
|
|
32
33
|
"Attribute",
|
|
33
34
|
"AttrsInstance",
|
|
35
|
+
"ClassProps",
|
|
34
36
|
"Converter",
|
|
35
37
|
"Factory",
|
|
36
38
|
"NothingType",
|
|
@@ -58,6 +60,7 @@ __all__ = [
|
|
|
58
60
|
"filters",
|
|
59
61
|
"frozen",
|
|
60
62
|
"has",
|
|
63
|
+
"inspect",
|
|
61
64
|
"make_class",
|
|
62
65
|
"mutable",
|
|
63
66
|
"resolve_types",
|
|
@@ -77,7 +77,7 @@ def field(
|
|
|
77
77
|
metadata: Mapping[Any, Any] | None = ...,
|
|
78
78
|
converter: None = ...,
|
|
79
79
|
factory: None = ...,
|
|
80
|
-
kw_only: bool = ...,
|
|
80
|
+
kw_only: bool | None = ...,
|
|
81
81
|
eq: bool | None = ...,
|
|
82
82
|
order: bool | None = ...,
|
|
83
83
|
on_setattr: _OnSetAttrArgType | None = ...,
|
|
@@ -98,10 +98,10 @@ def field(
|
|
|
98
98
|
metadata: Mapping[Any, Any] | None = ...,
|
|
99
99
|
converter: _ConverterType
|
|
100
100
|
| list[_ConverterType]
|
|
101
|
-
| tuple[_ConverterType]
|
|
101
|
+
| tuple[_ConverterType, ...]
|
|
102
102
|
| None = ...,
|
|
103
103
|
factory: Callable[[], _T] | None = ...,
|
|
104
|
-
kw_only: bool = ...,
|
|
104
|
+
kw_only: bool | None = ...,
|
|
105
105
|
eq: _EqOrderType | None = ...,
|
|
106
106
|
order: _EqOrderType | None = ...,
|
|
107
107
|
on_setattr: _OnSetAttrArgType | None = ...,
|
|
@@ -121,10 +121,10 @@ def field(
|
|
|
121
121
|
metadata: Mapping[Any, Any] | None = ...,
|
|
122
122
|
converter: _ConverterType
|
|
123
123
|
| list[_ConverterType]
|
|
124
|
-
| tuple[_ConverterType]
|
|
124
|
+
| tuple[_ConverterType, ...]
|
|
125
125
|
| None = ...,
|
|
126
126
|
factory: Callable[[], _T] | None = ...,
|
|
127
|
-
kw_only: bool = ...,
|
|
127
|
+
kw_only: bool | None = ...,
|
|
128
128
|
eq: _EqOrderType | None = ...,
|
|
129
129
|
order: _EqOrderType | None = ...,
|
|
130
130
|
on_setattr: _OnSetAttrArgType | None = ...,
|
|
@@ -144,10 +144,10 @@ def field(
|
|
|
144
144
|
metadata: Mapping[Any, Any] | None = ...,
|
|
145
145
|
converter: _ConverterType
|
|
146
146
|
| list[_ConverterType]
|
|
147
|
-
| tuple[_ConverterType]
|
|
147
|
+
| tuple[_ConverterType, ...]
|
|
148
148
|
| None = ...,
|
|
149
149
|
factory: Callable[[], _T] | None = ...,
|
|
150
|
-
kw_only: bool = ...,
|
|
150
|
+
kw_only: bool | None = ...,
|
|
151
151
|
eq: _EqOrderType | None = ...,
|
|
152
152
|
order: _EqOrderType | None = ...,
|
|
153
153
|
on_setattr: _OnSetAttrArgType | None = ...,
|
|
@@ -261,3 +261,54 @@ def frozen(
|
|
|
261
261
|
field_transformer: _FieldTransformer | None = ...,
|
|
262
262
|
match_args: bool = ...,
|
|
263
263
|
) -> Callable[[_C], _C]: ...
|
|
264
|
+
|
|
265
|
+
class ClassProps:
|
|
266
|
+
# XXX: somehow when defining/using enums Mypy starts looking at our own
|
|
267
|
+
# (untyped) code and causes tons of errors.
|
|
268
|
+
Hashability: Any
|
|
269
|
+
KeywordOnly: Any
|
|
270
|
+
|
|
271
|
+
is_exception: bool
|
|
272
|
+
is_slotted: bool
|
|
273
|
+
has_weakref_slot: bool
|
|
274
|
+
is_frozen: bool
|
|
275
|
+
# kw_only: ClassProps.KeywordOnly
|
|
276
|
+
kw_only: Any
|
|
277
|
+
collected_fields_by_mro: bool
|
|
278
|
+
added_init: bool
|
|
279
|
+
added_repr: bool
|
|
280
|
+
added_eq: bool
|
|
281
|
+
added_ordering: bool
|
|
282
|
+
# hashability: ClassProps.Hashability
|
|
283
|
+
hashability: Any
|
|
284
|
+
added_match_args: bool
|
|
285
|
+
added_str: bool
|
|
286
|
+
added_pickling: bool
|
|
287
|
+
on_setattr_hook: _OnSetAttrType | None
|
|
288
|
+
field_transformer: Callable[[Attribute[Any]], Attribute[Any]] | None
|
|
289
|
+
|
|
290
|
+
def __init__(
|
|
291
|
+
self,
|
|
292
|
+
is_exception: bool,
|
|
293
|
+
is_slotted: bool,
|
|
294
|
+
has_weakref_slot: bool,
|
|
295
|
+
is_frozen: bool,
|
|
296
|
+
# kw_only: ClassProps.KeywordOnly
|
|
297
|
+
kw_only: Any,
|
|
298
|
+
collected_fields_by_mro: bool,
|
|
299
|
+
added_init: bool,
|
|
300
|
+
added_repr: bool,
|
|
301
|
+
added_eq: bool,
|
|
302
|
+
added_ordering: bool,
|
|
303
|
+
# hashability: ClassProps.Hashability
|
|
304
|
+
hashability: Any,
|
|
305
|
+
added_match_args: bool,
|
|
306
|
+
added_str: bool,
|
|
307
|
+
added_pickling: bool,
|
|
308
|
+
on_setattr_hook: _OnSetAttrType,
|
|
309
|
+
field_transformer: Callable[[Attribute[Any]], Attribute[Any]],
|
|
310
|
+
) -> None: ...
|
|
311
|
+
@property
|
|
312
|
+
def is_hashable(self) -> bool: ...
|
|
313
|
+
|
|
314
|
+
def inspect(cls: type) -> ClassProps: ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: attrs
|
|
3
|
-
Version: 25.
|
|
3
|
+
Version: 25.4.0
|
|
4
4
|
Summary: Classes Without Boilerplate
|
|
5
5
|
Project-URL: Documentation, https://www.attrs.org/
|
|
6
6
|
Project-URL: Changelog, https://www.attrs.org/en/stable/changelog.html
|
|
@@ -12,62 +12,16 @@ License-Expression: MIT
|
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
Keywords: attribute,boilerplate,class
|
|
14
14
|
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
21
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
22
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
23
23
|
Classifier: Typing :: Typed
|
|
24
|
-
Requires-Python: >=3.
|
|
25
|
-
Provides-Extra: benchmark
|
|
26
|
-
Requires-Dist: cloudpickle; (platform_python_implementation == 'CPython') and extra == 'benchmark'
|
|
27
|
-
Requires-Dist: hypothesis; extra == 'benchmark'
|
|
28
|
-
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'benchmark'
|
|
29
|
-
Requires-Dist: pympler; extra == 'benchmark'
|
|
30
|
-
Requires-Dist: pytest-codspeed; extra == 'benchmark'
|
|
31
|
-
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'benchmark'
|
|
32
|
-
Requires-Dist: pytest-xdist[psutil]; extra == 'benchmark'
|
|
33
|
-
Requires-Dist: pytest>=4.3.0; extra == 'benchmark'
|
|
34
|
-
Provides-Extra: cov
|
|
35
|
-
Requires-Dist: cloudpickle; (platform_python_implementation == 'CPython') and extra == 'cov'
|
|
36
|
-
Requires-Dist: coverage[toml]>=5.3; extra == 'cov'
|
|
37
|
-
Requires-Dist: hypothesis; extra == 'cov'
|
|
38
|
-
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'cov'
|
|
39
|
-
Requires-Dist: pympler; extra == 'cov'
|
|
40
|
-
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'cov'
|
|
41
|
-
Requires-Dist: pytest-xdist[psutil]; extra == 'cov'
|
|
42
|
-
Requires-Dist: pytest>=4.3.0; extra == 'cov'
|
|
43
|
-
Provides-Extra: dev
|
|
44
|
-
Requires-Dist: cloudpickle; (platform_python_implementation == 'CPython') and extra == 'dev'
|
|
45
|
-
Requires-Dist: hypothesis; extra == 'dev'
|
|
46
|
-
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'dev'
|
|
47
|
-
Requires-Dist: pre-commit-uv; extra == 'dev'
|
|
48
|
-
Requires-Dist: pympler; extra == 'dev'
|
|
49
|
-
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'dev'
|
|
50
|
-
Requires-Dist: pytest-xdist[psutil]; extra == 'dev'
|
|
51
|
-
Requires-Dist: pytest>=4.3.0; extra == 'dev'
|
|
52
|
-
Provides-Extra: docs
|
|
53
|
-
Requires-Dist: cogapp; extra == 'docs'
|
|
54
|
-
Requires-Dist: furo; extra == 'docs'
|
|
55
|
-
Requires-Dist: myst-parser; extra == 'docs'
|
|
56
|
-
Requires-Dist: sphinx; extra == 'docs'
|
|
57
|
-
Requires-Dist: sphinx-notfound-page; extra == 'docs'
|
|
58
|
-
Requires-Dist: sphinxcontrib-towncrier; extra == 'docs'
|
|
59
|
-
Requires-Dist: towncrier; extra == 'docs'
|
|
60
|
-
Provides-Extra: tests
|
|
61
|
-
Requires-Dist: cloudpickle; (platform_python_implementation == 'CPython') and extra == 'tests'
|
|
62
|
-
Requires-Dist: hypothesis; extra == 'tests'
|
|
63
|
-
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'tests'
|
|
64
|
-
Requires-Dist: pympler; extra == 'tests'
|
|
65
|
-
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'tests'
|
|
66
|
-
Requires-Dist: pytest-xdist[psutil]; extra == 'tests'
|
|
67
|
-
Requires-Dist: pytest>=4.3.0; extra == 'tests'
|
|
68
|
-
Provides-Extra: tests-mypy
|
|
69
|
-
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'tests-mypy'
|
|
70
|
-
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'tests-mypy'
|
|
24
|
+
Requires-Python: >=3.9
|
|
71
25
|
Description-Content-Type: text/markdown
|
|
72
26
|
|
|
73
27
|
<p align="center">
|
|
@@ -78,7 +32,7 @@ Description-Content-Type: text/markdown
|
|
|
78
32
|
|
|
79
33
|
|
|
80
34
|
*attrs* is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka [dunder methods](https://www.attrs.org/en/latest/glossary.html#term-dunder-methods)).
|
|
81
|
-
|
|
35
|
+
Trusted by NASA for [Mars missions since 2020](https://github.com/readme/featured/nasa-ingenuity-helicopter)!
|
|
82
36
|
|
|
83
37
|
Its main goal is to help you to write **concise** and **correct** software without slowing down your code.
|
|
84
38
|
|
|
@@ -96,15 +50,13 @@ Especially those generously supporting us at the *The Organization* tier and hig
|
|
|
96
50
|
import pathlib, tomllib
|
|
97
51
|
|
|
98
52
|
for sponsor in tomllib.loads(pathlib.Path("pyproject.toml").read_text())["tool"]["sponcon"]["sponsors"]:
|
|
99
|
-
print(f'<a href="{sponsor["url"]}"><img title="{sponsor["title"]}" src="https://www.attrs.org/en/25.
|
|
53
|
+
print(f'<a href="{sponsor["url"]}"><img title="{sponsor["title"]}" src="https://www.attrs.org/en/25.4.0/_static/sponsors/{sponsor["img"]}" width="190" /></a>')
|
|
100
54
|
]]] -->
|
|
101
|
-
<a href="https://www.variomedia.de/"><img title="Variomedia AG" src="https://www.attrs.org/en/25.
|
|
102
|
-
<a href="https://tidelift.com/?utm_source=lifter&utm_medium=referral&utm_campaign=hynek"><img title="Tidelift" src="https://www.attrs.org/en/25.
|
|
103
|
-
<a href="https://
|
|
104
|
-
<a href="https://
|
|
105
|
-
<a href="https://
|
|
106
|
-
<a href="https://filepreviews.io/"><img title="FilePreviews" src="https://www.attrs.org/en/25.3.0/_static/sponsors/FilePreviews.svg" width="190" /></a>
|
|
107
|
-
<a href="https://polar.sh/"><img title="Polar" src="https://www.attrs.org/en/25.3.0/_static/sponsors/Polar.svg" width="190" /></a>
|
|
55
|
+
<a href="https://www.variomedia.de/"><img title="Variomedia AG" src="https://www.attrs.org/en/25.4.0/_static/sponsors/Variomedia.svg" width="190" /></a>
|
|
56
|
+
<a href="https://tidelift.com/?utm_source=lifter&utm_medium=referral&utm_campaign=hynek"><img title="Tidelift" src="https://www.attrs.org/en/25.4.0/_static/sponsors/Tidelift.svg" width="190" /></a>
|
|
57
|
+
<a href="https://privacy-solutions.org/"><img title="Privacy Solutions" src="https://www.attrs.org/en/25.4.0/_static/sponsors/Privacy-Solutions.svg" width="190" /></a>
|
|
58
|
+
<a href="https://filepreviews.io/"><img title="FilePreviews" src="https://www.attrs.org/en/25.4.0/_static/sponsors/FilePreviews.svg" width="190" /></a>
|
|
59
|
+
<a href="https://polar.sh/"><img title="Polar" src="https://www.attrs.org/en/25.4.0/_static/sponsors/Polar.svg" width="190" /></a>
|
|
108
60
|
<!-- [[[end]]] -->
|
|
109
61
|
|
|
110
62
|
</p>
|
|
@@ -220,10 +172,61 @@ Save time, reduce risk, and improve code health, while paying the maintainers of
|
|
|
220
172
|
|
|
221
173
|
## Release Information
|
|
222
174
|
|
|
175
|
+
### Backwards-incompatible Changes
|
|
176
|
+
|
|
177
|
+
- Class-level `kw_only=True` behavior is now consistent with `dataclasses`.
|
|
178
|
+
|
|
179
|
+
Previously, a class that sets `kw_only=True` makes all attributes keyword-only, including those from base classes.
|
|
180
|
+
If an attribute sets `kw_only=False`, that setting is ignored, and it is still made keyword-only.
|
|
181
|
+
|
|
182
|
+
Now, only the attributes defined in that class that doesn't explicitly set `kw_only=False` are made keyword-only.
|
|
183
|
+
|
|
184
|
+
This shouldn't be a problem for most users, unless you have a pattern like this:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
@attrs.define(kw_only=True)
|
|
188
|
+
class Base:
|
|
189
|
+
a: int
|
|
190
|
+
b: int = attrs.field(default=1, kw_only=False)
|
|
191
|
+
|
|
192
|
+
@attrs.define
|
|
193
|
+
class Subclass(Base):
|
|
194
|
+
c: int
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Here, we have a `kw_only=True` *attrs* class (`Base`) with an attribute that sets `kw_only=False` and has a default (`Base.b`), and then create a subclass (`Subclass`) with required arguments (`Subclass.c`).
|
|
198
|
+
Previously this would work, since it would make `Base.b` keyword-only, but now this fails since `Base.b` is positional, and we have a required positional argument (`Subclass.c`) following another argument with defaults.
|
|
199
|
+
[#1457](https://github.com/python-attrs/attrs/issues/1457)
|
|
200
|
+
|
|
201
|
+
|
|
223
202
|
### Changes
|
|
224
203
|
|
|
225
|
-
-
|
|
226
|
-
[#
|
|
204
|
+
- Values passed to the `__init__()` method of `attrs` classes are now correctly passed to `__attrs_pre_init__()` instead of their default values (in cases where *kw_only* was not specified).
|
|
205
|
+
[#1427](https://github.com/python-attrs/attrs/issues/1427)
|
|
206
|
+
- Added support for Python 3.14 and [PEP 749](https://peps.python.org/pep-0749/).
|
|
207
|
+
[#1446](https://github.com/python-attrs/attrs/issues/1446),
|
|
208
|
+
[#1451](https://github.com/python-attrs/attrs/issues/1451)
|
|
209
|
+
- `attrs.validators.deep_mapping()` now allows to leave out either *key_validator* xor *value_validator*.
|
|
210
|
+
[#1448](https://github.com/python-attrs/attrs/issues/1448)
|
|
211
|
+
- `attrs.validators.deep_iterator()` and `attrs.validators.deep_mapping()` now accept lists and tuples for all validators and wrap them into a `attrs.validators.and_()`.
|
|
212
|
+
[#1449](https://github.com/python-attrs/attrs/issues/1449)
|
|
213
|
+
- Added a new **experimental** way to inspect classes:
|
|
214
|
+
|
|
215
|
+
`attrs.inspect(cls)` returns the _effective_ class-wide parameters that were used by *attrs* to construct the class.
|
|
216
|
+
|
|
217
|
+
The returned class is the same data structure that *attrs* uses internally to decide how to construct the final class.
|
|
218
|
+
[#1454](https://github.com/python-attrs/attrs/issues/1454)
|
|
219
|
+
- Fixed annotations for `attrs.field(converter=...)`.
|
|
220
|
+
Previously, a `tuple` of converters was only accepted if it had exactly one element.
|
|
221
|
+
[#1461](https://github.com/python-attrs/attrs/issues/1461)
|
|
222
|
+
- The performance of `attrs.asdict()` has been improved by 45–260%.
|
|
223
|
+
[#1463](https://github.com/python-attrs/attrs/issues/1463)
|
|
224
|
+
- The performance of `attrs.astuple()` has been improved by 49–270%.
|
|
225
|
+
[#1469](https://github.com/python-attrs/attrs/issues/1469)
|
|
226
|
+
- The type annotation for `attrs.validators.or_()` now allows for different types of validators.
|
|
227
|
+
|
|
228
|
+
This was only an issue on Pyright.
|
|
229
|
+
[#1474](https://github.com/python-attrs/attrs/issues/1474)
|
|
227
230
|
|
|
228
231
|
|
|
229
232
|
|