_next_gen.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. """
  2. These are Python 3.6+-only and keyword-only APIs that call `attr.s` and
  3. `attr.ib` with different default values.
  4. """
  5. from functools import partial
  6. from attr.exceptions import UnannotatedAttributeError
  7. from . import setters
  8. from ._make import NOTHING, _frozen_setattrs, attrib, attrs
  9. def define(
  10. maybe_cls=None,
  11. *,
  12. these=None,
  13. repr=None,
  14. hash=None,
  15. init=None,
  16. slots=True,
  17. frozen=False,
  18. weakref_slot=True,
  19. str=False,
  20. auto_attribs=None,
  21. kw_only=False,
  22. cache_hash=False,
  23. auto_exc=True,
  24. eq=None,
  25. order=False,
  26. auto_detect=True,
  27. getstate_setstate=None,
  28. on_setattr=None,
  29. field_transformer=None,
  30. ):
  31. r"""
  32. The only behavioral differences are the handling of the *auto_attribs*
  33. option:
  34. :param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves
  35. exactly like `attr.s`. If left `None`, `attr.s` will try to guess:
  36. 1. If any attributes are annotated and no unannotated `attr.ib`\ s
  37. are found, it assumes *auto_attribs=True*.
  38. 2. Otherwise it assumes *auto_attribs=False* and tries to collect
  39. `attr.ib`\ s.
  40. and that mutable classes (``frozen=False``) validate on ``__setattr__``.
  41. .. versionadded:: 20.1.0
  42. """
  43. def do_it(cls, auto_attribs):
  44. return attrs(
  45. maybe_cls=cls,
  46. these=these,
  47. repr=repr,
  48. hash=hash,
  49. init=init,
  50. slots=slots,
  51. frozen=frozen,
  52. weakref_slot=weakref_slot,
  53. str=str,
  54. auto_attribs=auto_attribs,
  55. kw_only=kw_only,
  56. cache_hash=cache_hash,
  57. auto_exc=auto_exc,
  58. eq=eq,
  59. order=order,
  60. auto_detect=auto_detect,
  61. collect_by_mro=True,
  62. getstate_setstate=getstate_setstate,
  63. on_setattr=on_setattr,
  64. field_transformer=field_transformer,
  65. )
  66. def wrap(cls):
  67. """
  68. Making this a wrapper ensures this code runs during class creation.
  69. We also ensure that frozen-ness of classes is inherited.
  70. """
  71. nonlocal frozen, on_setattr
  72. had_on_setattr = on_setattr not in (None, setters.NO_OP)
  73. # By default, mutable classes validate on setattr.
  74. if frozen is False and on_setattr is None:
  75. on_setattr = setters.validate
  76. # However, if we subclass a frozen class, we inherit the immutability
  77. # and disable on_setattr.
  78. for base_cls in cls.__bases__:
  79. if base_cls.__setattr__ is _frozen_setattrs:
  80. if had_on_setattr:
  81. raise ValueError(
  82. "Frozen classes can't use on_setattr "
  83. "(frozen-ness was inherited)."
  84. )
  85. on_setattr = setters.NO_OP
  86. break
  87. if auto_attribs is not None:
  88. return do_it(cls, auto_attribs)
  89. try:
  90. return do_it(cls, True)
  91. except UnannotatedAttributeError:
  92. return do_it(cls, False)
  93. # maybe_cls's type depends on the usage of the decorator. It's a class
  94. # if it's used as `@attrs` but ``None`` if used as `@attrs()`.
  95. if maybe_cls is None:
  96. return wrap
  97. else:
  98. return wrap(maybe_cls)
  99. mutable = define
  100. frozen = partial(define, frozen=True, on_setattr=None)
  101. def field(
  102. *,
  103. default=NOTHING,
  104. validator=None,
  105. repr=True,
  106. hash=None,
  107. init=True,
  108. metadata=None,
  109. converter=None,
  110. factory=None,
  111. kw_only=False,
  112. eq=None,
  113. order=None,
  114. on_setattr=None,
  115. ):
  116. """
  117. Identical to `attr.ib`, except keyword-only and with some arguments
  118. removed.
  119. .. versionadded:: 20.1.0
  120. """
  121. return attrib(
  122. default=default,
  123. validator=validator,
  124. repr=repr,
  125. hash=hash,
  126. init=init,
  127. metadata=metadata,
  128. converter=converter,
  129. factory=factory,
  130. kw_only=kw_only,
  131. eq=eq,
  132. order=order,
  133. on_setattr=on_setattr,
  134. )