Skip to content
Permalink
Browse files

making more informative error message for setting values of 1:1 attri…

…butes
  • Loading branch information
jonrkarr committed Oct 29, 2019
1 parent 6350f24 commit 839df5933735b961a5900835be9e619ea1710508
Showing with 29 additions and 4 deletions.
  1. +23 −2 obj_tables/core.py
  2. +6 −2 tests/test_core.py
@@ -6083,7 +6083,12 @@ def set_value(self, obj, new_value):
old_related = getattr(new_value, self.related_name)
old_related_cls = old_related.__class__
new_cls = new_value.__class__
raise ValueError("Attribute '{}:{}' of '{}:{}' must be `None`".format(
raise ValueError(("Attribute '{}:{}' of '{}:{}' cannot be set because it is not `None`. "
"The values of one-to-one attributes cannot be directly changed to other non-`None` values because "
"this would opaquely change the reverse relationship of the related object. "
"To change the value of this attribute to another non-`None` value, first set the value of the attribute "
"to `None`."
).format(
old_related_cls.__name__, old_related.serialize(),
new_cls.__name__, new_value.serialize()))

@@ -6115,9 +6120,25 @@ def set_related_value(self, obj, new_value):
cur_value = getattr(obj, self.related_name)
if cur_value is new_value:
return new_value
if cur_value and new_value is not None:
raise ValueError(("Attribute '{}:{}' of '{}:{}' cannot be set because it is not `None`. "
"The values of one-to-one attributes cannot be directly changed to other non-`None` values because "
"this would opaquely change the reverse relationship of the related object. "
"To change the value of this attribute to another non-`None` value, first set the value of the attribute "
"to `None`."
).format(
self.related_name, cur_value.serialize(),
obj.__class__.__name__, obj.serialize()))

if new_value and getattr(new_value, self.name):
raise ValueError('Attribute of `new_value` must be `None`')
raise ValueError(("Attribute '{}:{}' of '{}:{}' cannot be set because it is not `None`. "
"The values of one-to-one attributes cannot be directly changed to other non-`None` values because "
"this would opaquely change the reverse relationship of the related object. "
"To change the value of this attribute to another non-`None` value, first set the value of the attribute "
"to `None`."
).format(
self.name, getattr(new_value, self.name).serialize(),
new_value.__class__.__name__, new_value.serialize()))

if cur_value:
cur_value.__setattr__(self.name, None, propagate=False)
@@ -2298,7 +2298,7 @@ class TestChild(core.Model):
parent_2 = TestParent(id='parent_2')
child_0 = TestChild(id='child_0', parent=parent_0)
child_1 = TestChild(id='child_1', parent=parent_1)
with self.assertRaisesRegex(ValueError, "'{}:{}' of '{}:{}' must be `None`".format(
with self.assertRaisesRegex(ValueError, "'{}:{}' of '{}:{}' cannot be set".format(
'TestChild', 'child_1', 'TestParent', 'parent_1')):
child_0.parent = parent_1
self.assertEqual(child_0.parent, parent_0)
@@ -2325,12 +2325,16 @@ class TestChild(core.Model):

parent_0 = TestParent()
parent_1 = TestParent()
parent_2 = TestParent()
child_0 = TestChild(parent=parent_0)
child_1 = TestChild(parent=parent_1)
child_2 = TestChild()
with self.assertRaisesRegex(ValueError, 'Attribute of `new_value` must be `None`'):
with self.assertRaisesRegex(ValueError, 'cannot be set'):
parent_0.child = child_1
self.assertEqual(parent_0.child, child_0)
with self.assertRaisesRegex(ValueError, 'cannot be set'):
parent_2.child = child_1
parent_0.child = None
parent_0.child = child_2
self.assertEqual(parent_0.child, child_2)

0 comments on commit 839df59

Please sign in to comment.
You can’t perform that action at this time.