Skip to content

Commit

Permalink
[fields] Format error message only if params exist (encode#6624)
Browse files Browse the repository at this point in the history
This prevents exceptions when the error message contains `%`, but is
not intended for formatting.  Django itself does the same:
https://github.com/django/django/blob/6866c91b638de5368c18713fa851bfe56253ea55/django/core/exceptions.py#L168-L169

Fixes encode#6622
  • Loading branch information
michael-k authored and Pierre Chiquet committed Mar 24, 2020
1 parent ba4028e commit cbebd93
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
4 changes: 2 additions & 2 deletions rest_framework/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,12 @@ def get_error_detail(exc_info):
error_dict = exc_info.error_dict
except AttributeError:
return [
ErrorDetail(error.message % (error.params or ()),
ErrorDetail((error.message % error.params) if error.params else error.message,
code=error.code if error.code else code)
for error in exc_info.error_list]
return {
k: [
ErrorDetail(error.message % (error.params or ()),
ErrorDetail((error.message % error.params) if error.params else error.message,
code=error.code if error.code else code)
for error in errors
] for k, errors in error_dict.items()
Expand Down
23 changes: 21 additions & 2 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -2255,14 +2255,33 @@ class ExampleSerializer(serializers.Serializer):
password = serializers.CharField()

def validate_password(self, obj):
err = DjangoValidationError('exc_msg', code='exc_code')
err = DjangoValidationError(
'exc_msg %s', code='exc_code', params=('exc_param',),
)
if use_list:
err = DjangoValidationError([err])
raise err

serializer = ExampleSerializer(data={'password': 123})
serializer.is_valid()
assert serializer.errors == {'password': ['exc_msg']}
assert serializer.errors == {'password': ['exc_msg exc_param']}
assert serializer.errors['password'][0].code == 'exc_code'

@pytest.mark.parametrize('use_list', (False, True))
def test_validationerror_code_with_msg_including_percent(self, use_list):

class ExampleSerializer(serializers.Serializer):
password = serializers.CharField()

def validate_password(self, obj):
err = DjangoValidationError('exc_msg with %', code='exc_code')
if use_list:
err = DjangoValidationError([err])
raise err

serializer = ExampleSerializer(data={'password': 123})
serializer.is_valid()
assert serializer.errors == {'password': ['exc_msg with %']}
assert serializer.errors['password'][0].code == 'exc_code'

@pytest.mark.parametrize('code', (None, 'exc_code',))
Expand Down

0 comments on commit cbebd93

Please sign in to comment.