Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant way to avoid .put() on unchanged entities

A reoccurring pattern in my Python programming on GAE is getting some entity from the data store, then possibly changing that entity based on various conditions. In the end I need to .put() the entity back to the data store to ensure that any changes that might have been made to it get saved.

However often there were no changes actually made and the final .put() is just a waste of money. How to easily make sure that I only put an entity if it has really changed?

The code might look something like

def handle_get_request():
    entity = Entity.get_by_key_name("foobar")

    if phase_of_moon() == "full":
       entity.werewolf = True
    if random.choice([True, False]):
       entity.lucky = True
    if some_complicated_condition:
       entity.answer = 42

    entity.put()

I could maintain a "changed" flag which I set if any condition changed the entity, but that seems very brittle. If I forget to set it somewhere, then changes would be lost.

What I ended up using

def handle_get_request():
    entity = Entity.get_by_key_name("foobar")
    original_xml = entity.to_xml()

    if phase_of_moon() == "full":
       entity.werewolf = True
    if random.choice([True, False]):
       entity.lucky = True
    if some_complicated_condition:
       entity.answer = 42

    if entity.to_xml() != original_xml: entity.put()

I would not call this "elegant". Elegant would be if the object just saved itself automatically in the end, but I felt this was simple and readable enough to do for now.

like image 421
Bemmu Avatar asked Sep 07 '11 08:09

Bemmu


1 Answers

Why not check if the result equals (==) the original and so decide whether to save it. This depends on a correctly implemented __eq__, but by default a field-by-field comparison based on the __dict__ should do it.

  def __eq__(self, other) : 
        return self.__dict__ == other.__dict__

(Be sure that the other rich comparison and hash operators work correctly if you do this. See here.)

like image 110
Joshua Fox Avatar answered Oct 19 '22 05:10

Joshua Fox