beanie icon indicating copy to clipboard operation
beanie copied to clipboard

[BUG] Documents with multiple inheritance on top level are not properly initialised

Open ADR-007 opened this issue 5 months ago • 1 comments

Describe the bug

Models that have more than 1 base class on top level are skipped during the initialization, so they cannot be used for any query.

To Reproduce

class CustomBaseDocument(Document):
    my_custom_base_field: int

class Account(
    # any two classes inherited from Document:
    CustomBaseDocument,
    DocumentWithSoftDelete,
):
    name: str


account = Account(name="test", my_custom_base_field=42)
await account.save()

Error
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.venv/lib/python3.12/site-packages/beanie/odm/actions.py:239: in wrapper
    result = await f(
.venv/lib/python3.12/site-packages/beanie/odm/utils/state.py:85: in wrapper
    result = await f(self, *args, **kwargs)
.venv/lib/python3.12/site-packages/beanie/odm/utils/self_validation.py:19: in wrapper
    return await f(self, *args, **kwargs)
.venv/lib/python3.12/site-packages/beanie/odm/documents.py:611: in save
    return await self.update(
.venv/lib/python3.12/site-packages/beanie/odm/actions.py:239: in wrapper
    result = await f(
.venv/lib/python3.12/site-packages/beanie/odm/utils/state.py:85: in wrapper
    result = await f(self, *args, **kwargs)
.venv/lib/python3.12/site-packages/beanie/odm/documents.py:728: in update
    result = await self.find_one(find_query).update(
.venv/lib/python3.12/site-packages/beanie/odm/queries/update.py:351: in __await__
    update_result = yield from self._update().__await__()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <beanie.odm.queries.update.UpdateOne object at 0x1311c6990>

    async def _update(self):
        if not self.bulk_writer:
            if self.response_type == UpdateResponse.UPDATE_RESULT:
                return await self.document_model.get_motor_collection().update_one(
                    self.find_query,
                    self.update_query,
                    session=self.session,
                    **self.pymongo_kwargs,
                )
            else:
>               result = await self.document_model.get_motor_collection().find_one_and_update(
                    self.find_query,
                    self.update_query,
                    session=self.session,
                    return_document=ReturnDocument.BEFORE
                    if self.response_type == UpdateResponse.OLD_DOCUMENT
                    else ReturnDocument.AFTER,
                    **self.pymongo_kwargs,
                )
E               AttributeError: 'NoneType' object has no attribute 'find_one_and_update'

.venv/lib/python3.12/site-packages/beanie/odm/queries/update.py:319: AttributeError

Expected behavior Document is saved as it happens when there is just a single base class

Additional context

Source of the problem: beanie/odm/utils/init.py:

    class Initializer:
        ...
        async def init_document(self, cls: Type[Document]) -> Optional[Output]:
            ...
            bases = [b for b in cls.__bases__ if issubclass(b, Document)]
            if len(bases) > 1:
                return None
            ...

ADR-007 avatar Sep 23 '24 16:09 ADR-007