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