Similar to Python's built in `getattr(instance, attr)`, but takes a list of nested attributes, instead of a single attribute. Also accepts either attribute lookup on objects or dictionary lookups.
(instance, attrs)
| 90 | |
| 91 | |
| 92 | def get_attribute(instance, attrs): |
| 93 | """ |
| 94 | Similar to Python's built in `getattr(instance, attr)`, |
| 95 | but takes a list of nested attributes, instead of a single attribute. |
| 96 | |
| 97 | Also accepts either attribute lookup on objects or dictionary lookups. |
| 98 | """ |
| 99 | for attr in attrs: |
| 100 | try: |
| 101 | if isinstance(instance, Mapping): |
| 102 | instance = instance[attr] |
| 103 | else: |
| 104 | instance = getattr(instance, attr) |
| 105 | except ObjectDoesNotExist: |
| 106 | return None |
| 107 | if is_simple_callable(instance): |
| 108 | try: |
| 109 | instance = instance() |
| 110 | except (AttributeError, KeyError) as exc: |
| 111 | # If we raised an Attribute or KeyError here it'd get treated |
| 112 | # as an omitted field in `Field.get_attribute()`. Instead we |
| 113 | # raise a ValueError to ensure the exception is not masked. |
| 114 | raise ValueError(f'Exception raised in callable attribute "{attr}"; original exception was: {exc}') |
| 115 | |
| 116 | return instance |
| 117 | |
| 118 | |
| 119 | def to_choices_dict(choices): |
no test coverage detected