diff --git a/tests/integration/model_integration_test.py b/tests/integration/model_integration_test.py index 9a54cccc..f4e962f2 100644 --- a/tests/integration/model_integration_test.py +++ b/tests/integration/model_integration_test.py @@ -142,3 +142,61 @@ class Meta: version_invalid = VersionAttribute() assert str(e.value) == 'The model has more than one Version attribute: version, version_invalid' + + +@pytest.mark.ddblocal +def test_update_model_with_version_attribute_without_get(ddb_url): + class TestModel(Model): + """ + A model for testing + """ + class Meta: + region = 'us-east-1' + table_name = 'pynamodb-ci' + host = ddb_url + forum = UnicodeAttribute(hash_key=True) + score = NumberAttribute(null=True) + version = VersionAttribute() + + if TestModel.exists(): + TestModel.delete_table() + TestModel.create_table(read_capacity_units=1, write_capacity_units=1, wait=True) + + obj = TestModel('1') + obj.save() + assert TestModel.get('1').version == 1 + obj.score = 1 + obj.save() + assert TestModel.get('1').version == 2 + + obj_by_key = TestModel('1') # try to update item without getting it first + obj_by_key.update( + actions=[ + TestModel.score.set(2), # no version increment + ], + add_version_condition=False + ) + updated_obj = TestModel.get('1') + assert updated_obj.score == 2 + assert updated_obj.version == 2 + + obj_2 = TestModel('2') + obj_2.save() + assert TestModel.get('2').version == 1 + obj_2.score = 1 + obj_2.save() + assert TestModel.get('2').version == 2 + + obj_2_by_key = TestModel('2') # try to update item without getting it first + obj_2_by_key.update( + actions=[ + TestModel.score.set(2), + TestModel.version.set(TestModel.version + 1) # increment version manually + ], + add_version_condition=False + ) + updated_obj_2 = TestModel.get('2') + assert updated_obj_2.score == 2 + assert updated_obj_2.version == 3 + + TestModel.delete_table() diff --git a/tests/integration/test_transaction_integration.py b/tests/integration/test_transaction_integration.py index e247fd85..1ab31301 100644 --- a/tests/integration/test_transaction_integration.py +++ b/tests/integration/test_transaction_integration.py @@ -428,3 +428,51 @@ def test_transaction_write_with_version_attribute_condition_failure(connection): assert len(exc_info.value.cancellation_reasons) == 1 assert exc_info.value.cancellation_reasons[0].code == 'ConditionalCheckFailed' assert Foo.Meta.table_name in exc_info.value.cause.MSG_TEMPLATE + + +@pytest.mark.ddblocal +def test_transaction_write_without_version_attribute_condition(connection): + foo = Foo(22) + foo.save() + assert Foo.get(22).version == 1 + foo.star = 'initial_update' + foo.save() + assert Foo.get(22).version == 2 + + foo2 = Foo(22) # try to update a field without getting the item first + + with TransactWrite(connection=connection) as transaction: + transaction.update( + foo2, + actions=[ + Foo.star.set('birdistheword'), + ], + add_version_condition=False, + ) + + foo_updated = Foo.get(22) + assert foo_updated.version == 2 # should not modify the version + assert foo_updated.star == 'birdistheword' + + +@pytest.mark.ddblocal +def test_transaction_write_increment_version_without_version_attribute_condition(connection): + foo = Foo(23) + foo.save() + assert Foo.get(23).version == 1 + + foo2 = Foo(23) + + with TransactWrite(connection=connection) as transaction: + transaction.update( + foo2, + actions=[ + Foo.star.set('birdistheword'), + Foo.version.set(Foo.version + 1), + ], + add_version_condition=False, + ) + + foo_updated = Foo.get(23) + assert foo_updated.star == 'birdistheword' + assert foo_updated.version == 3