Merge pull request #2608 from ezheidtmann/dont-swallow-errors-in-callable-sources

Dont swallow errors in callable sources
This commit is contained in:
Tom Christie 2015-02-27 09:13:01 +00:00
commit cda74b5997
2 changed files with 33 additions and 1 deletions

View File

@ -71,7 +71,14 @@ def get_attribute(instance, attrs):
except ObjectDoesNotExist: except ObjectDoesNotExist:
return None return None
if is_simple_callable(instance): if is_simple_callable(instance):
instance = instance() try:
instance = instance()
except (AttributeError, KeyError) as exc:
# If we raised an Attribute or KeyError here it'd get treated
# as an omitted field in `Field.get_attribute()`. Instead we
# raise a ValueError to ensure the exception is not masked.
raise ValueError('Exception raised in callable attribute "{0}"; original exception was: {1}'.format(attr, exc))
return instance return instance

View File

@ -93,6 +93,31 @@ class TestSource:
"same as the field name. Remove the `source` keyword argument." "same as the field name. Remove the `source` keyword argument."
) )
def test_callable_source(self):
class ExampleSerializer(serializers.Serializer):
example_field = serializers.CharField(source='example_callable')
class ExampleInstance(object):
def example_callable(self):
return 'example callable value'
serializer = ExampleSerializer(ExampleInstance())
assert serializer.data['example_field'] == 'example callable value'
def test_callable_source_raises(self):
class ExampleSerializer(serializers.Serializer):
example_field = serializers.CharField(source='example_callable', read_only=True)
class ExampleInstance(object):
def example_callable(self):
raise AttributeError('method call failed')
with pytest.raises(ValueError) as exc_info:
serializer = ExampleSerializer(ExampleInstance())
serializer.data.items()
assert 'method call failed' in str(exc_info.value)
class TestReadOnly: class TestReadOnly:
def setup(self): def setup(self):