Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] validate_on_save doesn't work with Document.save() #664

Closed
YOricH opened this issue Aug 19, 2023 · 5 comments
Closed

[BUG] validate_on_save doesn't work with Document.save() #664

YOricH opened this issue Aug 19, 2023 · 5 comments
Labels

Comments

@YOricH
Copy link

YOricH commented Aug 19, 2023

Describe the bug
The documentation says that validate_on_save is triggered before any type of document saving (insert, replace, save, save_changes). However, it does not work when using save().

To Reproduce
Dependencies:

annotated-types==0.5.0
beanie==1.21.0
click==8.1.7
dnspython==2.4.2
lazy-model==0.1.0b0
motor==3.2.0
pydantic==2.2.1
pydantic_core==2.6.1
pymongo==4.4.1
toml==0.10.2
typing_extensions==4.7.1

Code for tests:

from beanie import Document, init_beanie
from motor.motor_asyncio import AsyncIOMotorClient
import asyncio


class Tag(Document):
    number: int

    async def validate_self(self, *args, **kwargs):
        print("Calling validate_self()")
        await super().validate_self(*args, **kwargs)

    class Settings:
        validate_on_save = True


async def init():
    client = AsyncIOMotorClient(
        "mongodb://localhost:27017"
    )

    await init_beanie(database=client["test_beanie"], document_models=[Tag])


async def start_test():
    await init()
    tag_new = Tag(number=1)
    await tag_new.create()
    print(tag_new)

    tag_new.number = 3
    await tag_new.save()
    print(tag_new)


async def main():
    await start_test()


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Output:

Calling validate_self()
id=ObjectId('64e0a5dc9fb95d0ea5b21fb7') revision_id=None number=1
id=ObjectId('64e0a5dc9fb95d0ea5b21fb7') revision_id=None number=3

Expected behavior
Output:

Calling validate_self()
id=ObjectId('64e0a5dc9fb95d0ea5b21fb7') revision_id=None number=1
Calling validate_self()
id=ObjectId('64e0a5dc9fb95d0ea5b21fb7') revision_id=None number=3

Additional context
Same problem on an older version (beanie==1.19.2).

@jakeecolution
Copy link

Try adding @after_event(ValidateOnSave) to your validate_self

@after_event(ValidateOnSave)
async def validate_self(self, *args, **kwargs):

Make sure you import from beanie import ValidateOnSave and from beanie.odm.actions import after_event.

I looked on this test file and you'll need to implement this because the base Document class doesn't have the action run for saving and only for creation. Let me know if it works.

@YOricH
Copy link
Author

YOricH commented Aug 25, 2023

@jakeecolution No, it doesn't work. If we add this decorator to a validate_self() that has a parent method call:

@after_event(ValidateOnSave)
    async def validate_self(self, *args, **kwargs):
        print("Calling validate_self()")
        await super().validate_self(*args, **kwargs)

we get infinite recursion:

...
Calling validate_self()
Calling validate_self()
Calling validate_self()
Calling validate_self()
Calling validate_self()
Calling validate_self()
Calling validate_self()
Calling validate_self()
Calling validate_self()
Calling validate_self()
...

If we remove the parent method call:

    @after_event(ValidateOnSave)
    async def validate_self(self, *args, **kwargs):
        print("Calling validate_self()")
        # await super().validate_self(*args, **kwargs)

it will only work on creation, just like before:

Calling validate_self()
id=ObjectId('64e89019a5cae72efae09925') revision_id=None number=1
id=ObjectId('64e89019a5cae72efae09925') revision_id=None number=3

It turns out that ValidateOnSave does not work with save().
And this is not what is written in the documentation.

@roman-right
Copy link
Member

Thank you for the catch. Fixed in the PR: #669

@github-actions
Copy link

This issue is stale because it has been open 30 days with no activity.

@github-actions github-actions bot added the Stale label Oct 10, 2023
@github-actions
Copy link

This issue was closed because it has been stalled for 14 days with no activity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants