ant-ray-nightly 3.0.0.dev20251006__cp311-cp311-macosx_14_0_arm64.whl → 3.0.0.dev20251015__cp311-cp311-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.

Files changed (104) hide show
  1. {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/METADATA +82 -82
  2. {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/RECORD +101 -101
  3. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/_cparser.pxd.hash +1 -1
  4. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/_find_header.pxd.hash +1 -1
  5. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/_http_parser.pyx.hash +1 -1
  6. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/_http_writer.pyx.hash +1 -1
  7. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/.hash/hdrs.py.hash +1 -1
  8. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/__init__.py +1 -1
  9. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_cookie_helpers.py +2 -6
  10. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_http_parser.cpython-311-darwin.so +0 -0
  11. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_http_parser.pyx +1 -3
  12. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_http_writer.cpython-311-darwin.so +0 -0
  13. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_http_writer.pyx +9 -7
  14. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/.hash/mask.pxd.hash +1 -1
  15. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/.hash/mask.pyx.hash +1 -1
  16. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/.hash/reader_c.pxd.hash +1 -1
  17. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/mask.cpython-311-darwin.so +0 -0
  18. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/_websocket/reader_c.cpython-311-darwin.so +0 -0
  19. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/abc.py +1 -1
  20. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/client_reqrep.py +13 -4
  21. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/compression_utils.py +31 -0
  22. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/formdata.py +1 -1
  23. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/http_parser.py +18 -3
  24. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/multipart.py +4 -0
  25. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/streams.py +8 -0
  26. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/web_fileresponse.py +4 -4
  27. ray/_private/runtime_env/agent/thirdparty_files/aiohttp/web_urldispatcher.py +3 -1
  28. ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/METADATA +24 -12
  29. ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/RECORD +33 -33
  30. ray/_private/runtime_env/agent/thirdparty_files/attr/__init__.pyi +4 -4
  31. ray/_private/runtime_env/agent/thirdparty_files/attr/_compat.py +8 -3
  32. ray/_private/runtime_env/agent/thirdparty_files/attr/_funcs.py +45 -16
  33. ray/_private/runtime_env/agent/thirdparty_files/attr/_make.py +334 -95
  34. ray/_private/runtime_env/agent/thirdparty_files/attr/_next_gen.py +58 -7
  35. ray/_private/runtime_env/agent/thirdparty_files/attr/_version_info.py +3 -0
  36. ray/_private/runtime_env/agent/thirdparty_files/attr/validators.py +51 -13
  37. ray/_private/runtime_env/agent/thirdparty_files/attr/validators.pyi +59 -5
  38. ray/_private/runtime_env/agent/thirdparty_files/attrs/__init__.py +4 -1
  39. ray/_private/runtime_env/agent/thirdparty_files/attrs/__init__.pyi +58 -7
  40. ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/METADATA +63 -60
  41. ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/RECORD +15 -15
  42. ray/_private/runtime_env/agent/thirdparty_files/frozenlist/__init__.py +1 -1
  43. ray/_private/runtime_env/agent/thirdparty_files/frozenlist/_frozenlist.cpython-311-darwin.so +0 -0
  44. ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/METADATA +47 -1
  45. ray/_private/runtime_env/agent/thirdparty_files/frozenlist-1.8.0.dist-info/RECORD +12 -0
  46. ray/_private/runtime_env/agent/thirdparty_files/idna/codec.py +1 -1
  47. ray/_private/runtime_env/agent/thirdparty_files/idna/core.py +1 -1
  48. ray/_private/runtime_env/agent/thirdparty_files/idna/idnadata.py +72 -6
  49. ray/_private/runtime_env/agent/thirdparty_files/idna/package_data.py +1 -1
  50. ray/_private/runtime_env/agent/thirdparty_files/idna/uts46data.py +891 -731
  51. ray/_private/runtime_env/agent/thirdparty_files/{idna-3.10.dist-info → idna-3.11.dist-info}/METADATA +37 -78
  52. ray/_private/runtime_env/agent/thirdparty_files/idna-3.11.dist-info/RECORD +22 -0
  53. ray/_private/runtime_env/agent/thirdparty_files/{idna-3.10.dist-info → idna-3.11.dist-info}/WHEEL +1 -1
  54. ray/_private/runtime_env/agent/thirdparty_files/{idna-3.10.dist-info → idna-3.11.dist-info/licenses}/LICENSE.md +1 -1
  55. ray/_private/runtime_env/agent/thirdparty_files/multidict/__init__.py +9 -8
  56. ray/_private/runtime_env/agent/thirdparty_files/multidict/_multidict.cpython-311-darwin.so +0 -0
  57. ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/METADATA +2 -1
  58. ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/RECORD +8 -8
  59. ray/_private/runtime_env/agent/thirdparty_files/propcache/__init__.py +1 -1
  60. ray/_private/runtime_env/agent/thirdparty_files/propcache/_helpers_c.cpython-311-darwin.so +0 -0
  61. ray/_private/runtime_env/agent/thirdparty_files/propcache/_helpers_c.pyx +4 -5
  62. ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/METADATA +31 -1
  63. ray/_private/runtime_env/agent/thirdparty_files/propcache-0.4.1.dist-info/RECORD +18 -0
  64. ray/_private/runtime_env/agent/thirdparty_files/yarl/__init__.py +1 -1
  65. ray/_private/runtime_env/agent/thirdparty_files/yarl/_quoting_c.cpython-311-darwin.so +0 -0
  66. ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/METADATA +20 -1
  67. ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/RECORD +9 -9
  68. ray/core/src/ray/gcs/gcs_server +0 -0
  69. ray/thirdparty_files/setproctitle-1.2.2.dist-info/RECORD +1 -1
  70. ray/thirdparty_files/setproctitle.cpython-311-darwin.so +0 -0
  71. ray/_private/runtime_env/agent/thirdparty_files/frozenlist-1.7.0.dist-info/RECORD +0 -12
  72. ray/_private/runtime_env/agent/thirdparty_files/idna-3.10.dist-info/RECORD +0 -22
  73. ray/_private/runtime_env/agent/thirdparty_files/propcache-0.4.0.dist-info/RECORD +0 -18
  74. {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/WHEEL +0 -0
  75. {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/entry_points.txt +0 -0
  76. {ant_ray_nightly-3.0.0.dev20251006.dist-info → ant_ray_nightly-3.0.0.dev20251015.dist-info}/top_level.txt +0 -0
  77. /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/INSTALLER +0 -0
  78. /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/REQUESTED +0 -0
  79. /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/WHEEL +0 -0
  80. /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/licenses/LICENSE.txt +0 -0
  81. /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
  82. /ray/_private/runtime_env/agent/thirdparty_files/{aiohttp-3.12.15.dist-info → aiohttp-3.13.0.dist-info}/top_level.txt +0 -0
  83. /ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/INSTALLER +0 -0
  84. /ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/WHEEL +0 -0
  85. /ray/_private/runtime_env/agent/thirdparty_files/{attrs-25.3.0.dist-info → attrs-25.4.0.dist-info}/licenses/LICENSE +0 -0
  86. /ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/INSTALLER +0 -0
  87. /ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/WHEEL +0 -0
  88. /ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/licenses/LICENSE +0 -0
  89. /ray/_private/runtime_env/agent/thirdparty_files/{frozenlist-1.7.0.dist-info → frozenlist-1.8.0.dist-info}/top_level.txt +0 -0
  90. /ray/_private/runtime_env/agent/thirdparty_files/{idna-3.10.dist-info → idna-3.11.dist-info}/INSTALLER +0 -0
  91. /ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/INSTALLER +0 -0
  92. /ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/WHEEL +0 -0
  93. /ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/licenses/LICENSE +0 -0
  94. /ray/_private/runtime_env/agent/thirdparty_files/{multidict-6.6.4.dist-info → multidict-6.7.0.dist-info}/top_level.txt +0 -0
  95. /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/INSTALLER +0 -0
  96. /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/WHEEL +0 -0
  97. /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/licenses/LICENSE +0 -0
  98. /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/licenses/NOTICE +0 -0
  99. /ray/_private/runtime_env/agent/thirdparty_files/{propcache-0.4.0.dist-info → propcache-0.4.1.dist-info}/top_level.txt +0 -0
  100. /ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/INSTALLER +0 -0
  101. /ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/WHEEL +0 -0
  102. /ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/licenses/LICENSE +0 -0
  103. /ray/_private/runtime_env/agent/thirdparty_files/{yarl-1.21.0.dist-info → yarl-1.22.0.dist-info}/licenses/NOTICE +0 -0
  104. /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 all attributes keyword-only in the generated ``__init__`` (if
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=False,
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
- ``init`` is False, this parameter is ignored).
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(default=None, validator=optional(is_callable()))
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(inst, attr, key)
394
- self.value_validator(inst, attr, value[key])
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(key_validator, value_validator, mapping_validator=None):
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 (optional).
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: if any sub-validators fail
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.ge` to compare the values.
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: _ValidatorType[_I] | None = ...,
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: _ValidatorType[_K],
70
- value_validator: _ValidatorType[_V],
71
- mapping_validator: _ValidatorType[_M] | None = ...,
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
- def or_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ...
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._next_gen import asdict, astuple
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.0
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.8
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
- [Trusted by NASA](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/personalizing-your-profile#list-of-qualifying-repositories-for-mars-2020-helicopter-contributor-achievement) for Mars missions since 2020!
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.3.0/_static/sponsors/{sponsor["img"]}" width="190" /></a>')
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.3.0/_static/sponsors/Variomedia.svg" width="190" /></a>
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.3.0/_static/sponsors/Tidelift.svg" width="190" /></a>
103
- <a href="https://klaviyo.com/"><img title="Klaviyo" src="https://www.attrs.org/en/25.3.0/_static/sponsors/Klaviyo.svg" width="190" /></a>
104
- <a href="https://privacy-solutions.org/"><img title="Privacy Solutions" src="https://www.attrs.org/en/25.3.0/_static/sponsors/Privacy-Solutions.svg" width="190" /></a>
105
- <a href="https://www.emsys-renewables.com/"><img title="emsys renewables" src="https://www.attrs.org/en/25.3.0/_static/sponsors/emsys-renewables.svg" width="190" /></a>
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
- - Restore support for generator-based `field_transformer`s.
226
- [#1417](https://github.com/python-attrs/attrs/issues/1417)
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