__init__.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # SPDX-License-Identifier: MIT
  2. """
  3. Classes Without Boilerplate
  4. """
  5. from functools import partial
  6. from typing import Callable
  7. from . import converters, exceptions, filters, setters, validators
  8. from ._cmp import cmp_using
  9. from ._compat import Protocol
  10. from ._config import get_run_validators, set_run_validators
  11. from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types
  12. from ._make import (
  13. NOTHING,
  14. Attribute,
  15. Factory,
  16. attrib,
  17. attrs,
  18. fields,
  19. fields_dict,
  20. make_class,
  21. validate,
  22. )
  23. from ._next_gen import define, field, frozen, mutable
  24. from ._version_info import VersionInfo
  25. s = attributes = attrs
  26. ib = attr = attrib
  27. dataclass = partial(attrs, auto_attribs=True) # happy Easter ;)
  28. class AttrsInstance(Protocol):
  29. pass
  30. __all__ = [
  31. "Attribute",
  32. "AttrsInstance",
  33. "Factory",
  34. "NOTHING",
  35. "asdict",
  36. "assoc",
  37. "astuple",
  38. "attr",
  39. "attrib",
  40. "attributes",
  41. "attrs",
  42. "cmp_using",
  43. "converters",
  44. "define",
  45. "evolve",
  46. "exceptions",
  47. "field",
  48. "fields",
  49. "fields_dict",
  50. "filters",
  51. "frozen",
  52. "get_run_validators",
  53. "has",
  54. "ib",
  55. "make_class",
  56. "mutable",
  57. "resolve_types",
  58. "s",
  59. "set_run_validators",
  60. "setters",
  61. "validate",
  62. "validators",
  63. ]
  64. def _make_getattr(mod_name: str) -> Callable:
  65. """
  66. Create a metadata proxy for packaging information that uses *mod_name* in
  67. its warnings and errors.
  68. """
  69. def __getattr__(name: str) -> str:
  70. dunder_to_metadata = {
  71. "__title__": "Name",
  72. "__copyright__": "",
  73. "__version__": "version",
  74. "__version_info__": "version",
  75. "__description__": "summary",
  76. "__uri__": "",
  77. "__url__": "",
  78. "__author__": "",
  79. "__email__": "",
  80. "__license__": "license",
  81. }
  82. if name not in dunder_to_metadata:
  83. msg = f"module {mod_name} has no attribute {name}"
  84. raise AttributeError(msg)
  85. import sys
  86. import warnings
  87. if sys.version_info < (3, 8):
  88. from importlib_metadata import metadata
  89. else:
  90. from importlib.metadata import metadata
  91. if name not in ("__version__", "__version_info__"):
  92. warnings.warn(
  93. f"Accessing {mod_name}.{name} is deprecated and will be "
  94. "removed in a future release. Use importlib.metadata directly "
  95. "to query for attrs's packaging metadata.",
  96. DeprecationWarning,
  97. stacklevel=2,
  98. )
  99. meta = metadata("attrs")
  100. if name == "__license__":
  101. return "MIT"
  102. if name == "__copyright__":
  103. return "Copyright (c) 2015 Hynek Schlawack"
  104. if name in ("__uri__", "__url__"):
  105. return meta["Project-URL"].split(" ", 1)[-1]
  106. if name == "__version_info__":
  107. return VersionInfo._from_version_string(meta["version"])
  108. if name == "__author__":
  109. return meta["Author-email"].rsplit(" ", 1)[0]
  110. if name == "__email__":
  111. return meta["Author-email"].rsplit("<", 1)[1][:-1]
  112. return meta[dunder_to_metadata[name]]
  113. return __getattr__
  114. __getattr__ = _make_getattr(__name__)