A converter that allows an attribute to be optional. An optional attribute is one which can be set to `None`. Type annotations will be inferred from the wrapped converter's, if it has any. Args: converter (typing.Callable): the converter that is used for no
(converter)
| 19 | |
| 20 | |
| 21 | def optional(converter): |
| 22 | """ |
| 23 | A converter that allows an attribute to be optional. An optional attribute |
| 24 | is one which can be set to `None`. |
| 25 | |
| 26 | Type annotations will be inferred from the wrapped converter's, if it has |
| 27 | any. |
| 28 | |
| 29 | Args: |
| 30 | converter (typing.Callable): |
| 31 | the converter that is used for non-`None` values. |
| 32 | |
| 33 | .. versionadded:: 17.1.0 |
| 34 | """ |
| 35 | |
| 36 | if isinstance(converter, Converter): |
| 37 | |
| 38 | def optional_converter(val, inst, field): |
| 39 | if val is None: |
| 40 | return None |
| 41 | return converter(val, inst, field) |
| 42 | |
| 43 | else: |
| 44 | |
| 45 | def optional_converter(val): |
| 46 | if val is None: |
| 47 | return None |
| 48 | return converter(val) |
| 49 | |
| 50 | xtr = _AnnotationExtractor(converter) |
| 51 | |
| 52 | t = xtr.get_first_param_type() |
| 53 | if t: |
| 54 | optional_converter.__annotations__["val"] = typing.Optional[t] |
| 55 | |
| 56 | rt = xtr.get_return_type() |
| 57 | if rt: |
| 58 | optional_converter.__annotations__["return"] = typing.Optional[rt] |
| 59 | |
| 60 | if isinstance(converter, Converter): |
| 61 | return Converter(optional_converter, takes_self=True, takes_field=True) |
| 62 | |
| 63 | return optional_converter |
| 64 | |
| 65 | |
| 66 | def default_if_none(default=NOTHING, factory=None): |