Skip to content

Commit ddc8d7e

Browse files
author
Chris Rossi
authored
Implement _prepare_for_put for StructuredProperty and LocalStructuredProperty. (#221)
This was in the original code, but was overlooked when porting. Fixes #216.
1 parent 45fa423 commit ddc8d7e

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

packages/google-cloud-ndb/google/cloud/ndb/model.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4035,6 +4035,14 @@ def _to_datastore(self, entity, data, prefix="", repeated=False):
40354035

40364036
return set(keys)
40374037

4038+
def _prepare_for_put(self, entity):
4039+
values = self._get_user_value(entity)
4040+
if not self._repeated:
4041+
values = [values]
4042+
for value in values:
4043+
if value is not None:
4044+
value._prepare_for_put()
4045+
40384046

40394047
class LocalStructuredProperty(BlobProperty):
40404048
"""A property that contains ndb.Model value.
@@ -4130,6 +4138,14 @@ def _from_base_type(self, value):
41304138
value.key = None
41314139
return _entity_from_ds_entity(value, model_class=self._model_class)
41324140

4141+
def _prepare_for_put(self, entity):
4142+
values = self._get_user_value(entity)
4143+
if not self._repeated:
4144+
values = [values]
4145+
for value in values:
4146+
if value is not None:
4147+
value._prepare_for_put()
4148+
41334149

41344150
class GenericProperty(Property):
41354151
"""A Property whose value can be (almost) any basic type.

packages/google-cloud-ndb/tests/system/test_crud.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,26 @@ class SomeKind(ndb.Model):
912912
dispose_of(key._key)
913913

914914

915+
@pytest.mark.usefixtures("client_context")
916+
def test_insert_nested_autonow_property(dispose_of):
917+
class OtherKind(ndb.Model):
918+
created_at = ndb.DateTimeProperty(indexed=True, auto_now_add=True)
919+
updated_at = ndb.DateTimeProperty(indexed=True, auto_now=True)
920+
921+
class SomeKind(ndb.Model):
922+
other = ndb.StructuredProperty(OtherKind)
923+
924+
entity = SomeKind(other=OtherKind())
925+
key = entity.put()
926+
927+
retrieved = key.get()
928+
929+
assert isinstance(retrieved.other.created_at, datetime.datetime)
930+
assert isinstance(retrieved.other.updated_at, datetime.datetime)
931+
932+
dispose_of(key._key)
933+
934+
915935
@pytest.mark.usefixtures("client_context")
916936
def test_uninitialized_property(dispose_of):
917937
class SomeKind(ndb.Model):

packages/google-cloud-ndb/tests/unit/test_model.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,6 +3295,45 @@ class SomeKind(model.Model):
32953295
assert SomeKind.foo._to_datastore(entity, data) == {"foo.bar"}
32963296
assert data == {"foo.bar": ["baz", "boz"]}
32973297

3298+
@staticmethod
3299+
def test__prepare_for_put():
3300+
class SubKind(model.Model):
3301+
bar = model.Property()
3302+
3303+
class SomeKind(model.Model):
3304+
foo = model.StructuredProperty(SubKind)
3305+
3306+
entity = SomeKind(foo=SubKind())
3307+
entity.foo._prepare_for_put = unittest.mock.Mock()
3308+
SomeKind.foo._prepare_for_put(entity)
3309+
entity.foo._prepare_for_put.assert_called_once_with()
3310+
3311+
@staticmethod
3312+
def test__prepare_for_put_repeated():
3313+
class SubKind(model.Model):
3314+
bar = model.Property()
3315+
3316+
class SomeKind(model.Model):
3317+
foo = model.StructuredProperty(SubKind, repeated=True)
3318+
3319+
entity = SomeKind(foo=[SubKind(), SubKind()])
3320+
entity.foo[0]._prepare_for_put = unittest.mock.Mock()
3321+
entity.foo[1]._prepare_for_put = unittest.mock.Mock()
3322+
SomeKind.foo._prepare_for_put(entity)
3323+
entity.foo[0]._prepare_for_put.assert_called_once_with()
3324+
entity.foo[1]._prepare_for_put.assert_called_once_with()
3325+
3326+
@staticmethod
3327+
def test__prepare_for_put_repeated_None():
3328+
class SubKind(model.Model):
3329+
bar = model.Property()
3330+
3331+
class SomeKind(model.Model):
3332+
foo = model.StructuredProperty(SubKind)
3333+
3334+
entity = SomeKind()
3335+
SomeKind.foo._prepare_for_put(entity) # noop
3336+
32983337

32993338
class TestLocalStructuredProperty:
33003339
@staticmethod
@@ -3397,6 +3436,45 @@ class Simple(model.Model):
33973436
expected = Simple()
33983437
assert prop._from_base_type(entity) == expected
33993438

3439+
@staticmethod
3440+
def test__prepare_for_put():
3441+
class SubKind(model.Model):
3442+
bar = model.Property()
3443+
3444+
class SomeKind(model.Model):
3445+
foo = model.LocalStructuredProperty(SubKind)
3446+
3447+
entity = SomeKind(foo=SubKind())
3448+
entity.foo._prepare_for_put = unittest.mock.Mock()
3449+
SomeKind.foo._prepare_for_put(entity)
3450+
entity.foo._prepare_for_put.assert_called_once_with()
3451+
3452+
@staticmethod
3453+
def test__prepare_for_put_repeated():
3454+
class SubKind(model.Model):
3455+
bar = model.Property()
3456+
3457+
class SomeKind(model.Model):
3458+
foo = model.LocalStructuredProperty(SubKind, repeated=True)
3459+
3460+
entity = SomeKind(foo=[SubKind(), SubKind()])
3461+
entity.foo[0]._prepare_for_put = unittest.mock.Mock()
3462+
entity.foo[1]._prepare_for_put = unittest.mock.Mock()
3463+
SomeKind.foo._prepare_for_put(entity)
3464+
entity.foo[0]._prepare_for_put.assert_called_once_with()
3465+
entity.foo[1]._prepare_for_put.assert_called_once_with()
3466+
3467+
@staticmethod
3468+
def test__prepare_for_put_repeated_None():
3469+
class SubKind(model.Model):
3470+
bar = model.Property()
3471+
3472+
class SomeKind(model.Model):
3473+
foo = model.LocalStructuredProperty(SubKind)
3474+
3475+
entity = SomeKind()
3476+
SomeKind.foo._prepare_for_put(entity) # noop
3477+
34003478

34013479
class TestGenericProperty:
34023480
@staticmethod

0 commit comments

Comments
 (0)