Skip to content

motorhead.delete_rule

DeleteConfig = Literal['deny', 'pre', 'post'] module-attribute

Delete rule configuration that specifies when a given delete rule must be executed.

DeleteRule

Bases: BoundMethodWrapper[TOwner, [AgnosticClientSession, Sequence[TPrimaryKey]], DeleteConfig]

Delete rule wrapper.

Delete rules receive an AgnosticClientSession instance and a list of document IDs, and implement any deny, pre- or post-delete behavior.

Delete rule execution sequence:

  • "deny" rules are executed first - delete rules whose role is to prevent a delete operation should have this config.
  • "pre" rules are executed next.
  • Then the requested delete operation takes place.
  • Finally the "post" delete rules are executed.

Delete rules are always called in a transaction. Well-behaved delete rules must:

  • always use the received session instance to interact with the database, i.e. forward the received session to every database driver call;
  • not commit the session;
  • not start a new transaction (see session.in_transaction);
  • raise an exception if the operation can or must not complete.

Example:

class SVC(Service):
    @delete_rule("pre")
    async def delete_cascade(self, session: AgnosticClientSession, ids: Sequence[ObjectId]) -> None:
        from x.y.z import OtherService

        other_service = OtherService(self._database)
        await other_service.delete_many({"foo_ref": {"$in": ids}}, options={"session": session})
Source code in motorhead/delete_rule.py
class DeleteRule(BoundMethodWrapper[TOwner, [AgnosticClientSession, Sequence[TPrimaryKey]], DeleteConfig]):
    """
    Delete rule wrapper.

    Delete rules receive an `AgnosticClientSession` instance and a list of document IDs,
    and implement any deny, pre- or post-delete behavior.

    Delete rule execution sequence:

    - "deny" rules are executed first - delete rules whose role is to prevent
      a delete operation should have this config.
    - "pre" rules are executed next.
    - Then the requested delete operation takes place.
    - Finally the "post" delete rules are executed.

    Delete rules are always called in a transaction. Well-behaved delete rules must:

    - always use the received session instance to interact with the database,
      i.e. forward the received session to every database driver call;
    - *not* commit the session;
    - *not* start a new transaction (see `session.in_transaction`);
    - raise an exception if the operation can or must not complete.

    Example:

    ```python
    class SVC(Service):
        @delete_rule("pre")
        async def delete_cascade(self, session: AgnosticClientSession, ids: Sequence[ObjectId]) -> None:
            from x.y.z import OtherService

            other_service = OtherService(self._database)
            await other_service.delete_many({"foo_ref": {"$in": ids}}, options={"session": session})
    ```
    """

    __slots__ = ()

    exception = DeleteError

delete_rule(config='pre')

Decorator that converts a Service method into a DeleteRule that is then automatically applied by the service during delete operations.

Parameters:

Name Type Description Default
config DeleteConfig

Delete rule configuration.

'pre'
Source code in motorhead/delete_rule.py
def delete_rule(
    config: DeleteConfig = "pre",
) -> Callable[
    [Callable[[TOwner, AgnosticClientSession, Sequence[TPrimaryKey]], Coroutine[None, None, None]]],
    "DeleteRule[TOwner, TPrimaryKey]",
]:
    """
    Decorator that converts a `Service` method into a `DeleteRule` that is then
    automatically applied by the service during delete operations.

    Arguments:
        config: Delete rule configuration.
    """

    def decorator(
        func: Callable[[TOwner, AgnosticClientSession, Sequence[TPrimaryKey]], Coroutine[None, None, None]],
        /,
    ) -> "DeleteRule[TOwner, TPrimaryKey]":
        return DeleteRule(wrapped=func, config=config)

    return decorator