mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 16:40:03 +03:00
Better handle conflicting keys in set_values
This commit adds logic to set_values to move values on keys to be added upon to a blank key inside the value's previous key. This would allow constructions like: ``` fk_object = HyperlinkedRelatedField(source='fk') fk_name = CharField('fk.field') ``` Tests are also added specifically for set_values with the examples given in the function description as well as for this change.
This commit is contained in:
parent
8351747d98
commit
9b33778667
|
@ -125,8 +125,13 @@ def set_value(dictionary, keys, value):
|
|||
for key in keys[:-1]:
|
||||
if key not in dictionary:
|
||||
dictionary[key] = {}
|
||||
elif type(dictionary[key]) is not dict:
|
||||
dictionary[key] = {'': dictionary[key]}
|
||||
dictionary = dictionary[key]
|
||||
|
||||
if keys[-1] in dictionary and type(dictionary[keys[-1]]) is dict:
|
||||
dictionary[keys[-1]][''] = value
|
||||
else:
|
||||
dictionary[keys[-1]] = value
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ from django.utils.timezone import activate, deactivate, override, utc
|
|||
import rest_framework
|
||||
from rest_framework import exceptions, serializers
|
||||
from rest_framework.fields import (
|
||||
BuiltinSignatureError, DjangoImageField, is_simple_callable
|
||||
BuiltinSignatureError, DjangoImageField, is_simple_callable, set_value
|
||||
)
|
||||
|
||||
# Tests for helper functions.
|
||||
|
@ -2380,3 +2380,65 @@ class TestValidationErrorCode:
|
|||
),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
# Tests for set_value function
|
||||
# ----------------------------
|
||||
|
||||
class TestSetValue:
|
||||
|
||||
def test_no_keys(self):
|
||||
"""
|
||||
If no keys are provided, but a dict as value, add the dicts
|
||||
"""
|
||||
d = {'a': 1}
|
||||
set_value(d, [], {'b': 2})
|
||||
assert d == {'a': 1, 'b': 2}
|
||||
|
||||
def test_one_key(self):
|
||||
"""
|
||||
If a key + value provided, add the value to the dict with key
|
||||
"""
|
||||
d = {'a': 1}
|
||||
set_value(d, ['x'], 2)
|
||||
assert d == {'a': 1, 'x': 2}
|
||||
|
||||
def test_many_keys(self):
|
||||
"""
|
||||
With many keys, add the item to the in-most dict
|
||||
"""
|
||||
d = {'a': 1}
|
||||
set_value(d, ['x', 'y'], 2)
|
||||
assert d == {'a': 1, 'x': {'y': 2}}
|
||||
|
||||
def test_many_keys_existing(self):
|
||||
"""
|
||||
With many keys with existing in-built dict
|
||||
"""
|
||||
d = {'a': 1, 'x': {'a': 2}}
|
||||
set_value(d, ['x', 'y'], 3)
|
||||
assert d == {'a': 1, 'x': {'a': 2, 'y': 3}}
|
||||
|
||||
def test_conflicting_keys(self):
|
||||
"""
|
||||
If a value exists where a key will be added, use a blank key for old value
|
||||
"""
|
||||
d = {'a': 1, 'x': 2}
|
||||
set_value(d, ['x', 'y'], 3)
|
||||
assert d == {'a': 1, 'x': {'': 2, 'y': 3}}
|
||||
|
||||
def test_reverse_conflict(self):
|
||||
"""
|
||||
If a dict exists and a value is to be added, add it as blank key
|
||||
"""
|
||||
d = {'a': 1, 'x': {'y': 2}}
|
||||
set_value(d, ['x'], 3)
|
||||
assert d == {'a': 1, 'x': {'y': 2, '': 3}}
|
||||
|
||||
def test_overwrite_conflict(self):
|
||||
"""
|
||||
If a newer final value comes, replace with the older
|
||||
"""
|
||||
d = {'a': 1, 'x': 2}
|
||||
set_value(d, ['x'], 3)
|
||||
assert d == {'a': 1, 'x': 3}
|
||||
|
|
Loading…
Reference in New Issue
Block a user