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