converters.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. """
  2. Commonly useful converters.
  3. """
  4. from __future__ import absolute_import, division, print_function
  5. from ._compat import PY2
  6. from ._make import NOTHING, Factory, pipe
  7. if not PY2:
  8. import inspect
  9. import typing
  10. __all__ = [
  11. "pipe",
  12. "optional",
  13. "default_if_none",
  14. ]
  15. def optional(converter):
  16. """
  17. A converter that allows an attribute to be optional. An optional attribute
  18. is one which can be set to ``None``.
  19. Type annotations will be inferred from the wrapped converter's, if it
  20. has any.
  21. :param callable converter: the converter that is used for non-``None``
  22. values.
  23. .. versionadded:: 17.1.0
  24. """
  25. def optional_converter(val):
  26. if val is None:
  27. return None
  28. return converter(val)
  29. if not PY2:
  30. sig = None
  31. try:
  32. sig = inspect.signature(converter)
  33. except (ValueError, TypeError): # inspect failed
  34. pass
  35. if sig:
  36. params = list(sig.parameters.values())
  37. if params and params[0].annotation is not inspect.Parameter.empty:
  38. optional_converter.__annotations__["val"] = typing.Optional[
  39. params[0].annotation
  40. ]
  41. if sig.return_annotation is not inspect.Signature.empty:
  42. optional_converter.__annotations__["return"] = typing.Optional[
  43. sig.return_annotation
  44. ]
  45. return optional_converter
  46. def default_if_none(default=NOTHING, factory=None):
  47. """
  48. A converter that allows to replace ``None`` values by *default* or the
  49. result of *factory*.
  50. :param default: Value to be used if ``None`` is passed. Passing an instance
  51. of `attr.Factory` is supported, however the ``takes_self`` option
  52. is *not*.
  53. :param callable factory: A callable that takes no parameters whose result
  54. is used if ``None`` is passed.
  55. :raises TypeError: If **neither** *default* or *factory* is passed.
  56. :raises TypeError: If **both** *default* and *factory* are passed.
  57. :raises ValueError: If an instance of `attr.Factory` is passed with
  58. ``takes_self=True``.
  59. .. versionadded:: 18.2.0
  60. """
  61. if default is NOTHING and factory is None:
  62. raise TypeError("Must pass either `default` or `factory`.")
  63. if default is not NOTHING and factory is not None:
  64. raise TypeError(
  65. "Must pass either `default` or `factory` but not both."
  66. )
  67. if factory is not None:
  68. default = Factory(factory)
  69. if isinstance(default, Factory):
  70. if default.takes_self:
  71. raise ValueError(
  72. "`takes_self` is not supported by default_if_none."
  73. )
  74. def default_if_none_converter(val):
  75. if val is not None:
  76. return val
  77. return default.factory()
  78. else:
  79. def default_if_none_converter(val):
  80. if val is not None:
  81. return val
  82. return default
  83. return default_if_none_converter