Skip to content

google-cloud-ndb: Expando dynamic property updates are not persisted by put() #18204

Description

@samuel100u

google-cloud-ndb==2.3.0, Python 3.11.

If I assign a dynamic property on an Expando and put(), the first write sticks. Changing that same property later and put() again looks fine (no error; in-process it even reads as the new value) but a refetch from datastore still has the old number.

Declared properties on the class (e.g. FloatProperty) update correctly. This also worked on the old App Engine ndb.

from google.cloud import ndb

class Item(ndb.Expando):
    name = ndb.StringProperty()

# ndb client context already active
ent = Item(name="x")
ent.extra = 2.00
key = ent.put()

ent = key.get()
ent.extra = 9.99
ent.put()

ent = key.get()
print(ent.extra)  # 2.00, expected 9.99

Expando.__setattr__ looks like the cause. If the name is already in _properties it calls super().__setattr__. For a class-level Property that hits the descriptor and updates _values. For a dynamic name there is no descriptor on the class, so it lands in __dict__ and put() serializes the stale _values.

Is this expected? I couldn't find it documented. The old runtime always went through _set_value for non-class names.

Opened here because https://github.com/googleapis/python-ndb is archived.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions