Skip to content

Logical Composability

Use logical constraints to handle complex inputs and group error messages.

  • AnyOf (OR): Passes if at least one constraint succeeds. Perfect for fields that accept multiple formats.
  • AllOf (AND): Enforces that all constraints pass. Used to group multiple rules under a single custom error message or code.
  • Not (NOT): Inverts a constraint. Succeeds only if the inner rule fails.

Nested Composability

Because these operators are standard constraints, you can deeply nest them to represent complex real-world business logic.

from typing import Annotated
from monk import monk
from monk.constraints import AnyOf, AllOf, Not, Email, StartsWith, LowerCase, Len, EndsWith

@monk
class ComplexRules:
    # 1. AnyOf (OR): Email OR Phone
    identifier: Annotated[
        str, 
        AnyOf(Email, StartsWith("+"), message="Must be an email or phone number.")
    ]

    # 2. AllOf (AND): Groups rules under one unified message
    username: Annotated[
        str, 
        AllOf(LowerCase, Len(min_len=5), message="Usernames must be lowercase and 5+ chars.")
    ]

    # 3. Not (NOT): Fails if the password IS entirely lowercase
    password: Annotated[
        str, 
        Not(LowerCase, message="Password cannot be entirely lowercase.")
    ]

    # 4. Nested: Matches Email OR (Phone AND length <= 15 AND NOT ending in "000")
    contact: Annotated[
        str,
        AnyOf(
            Email,
            AllOf(StartsWith("+"), Len(max_len=15), Not(EndsWith("000")))
        )
    ]