Module slack_bolt.kwargs_injection

For middleware/listener arguments, Bolt does flexible data injection in accordance with their names.

To learn the available arguments, check slack_bolt.kwargs_injection.args's API document. For Workflow steps, checking slack_bolt.workflows.step.utilities as well should be helpful.

Expand source code
"""For middleware/listener arguments, Bolt does flexible data injection in accordance with their names.

To learn the available arguments, check `slack_bolt.kwargs_injection.args`'s API document.
For Workflow steps, checking `slack_bolt.workflows.step.utilities` as well should be helpful.
"""

# Don't add async module imports here
from .args import Args
from .utils import build_required_kwargs

__all__ = [
    "Args",
    "build_required_kwargs",
]

Sub-modules

slack_bolt.kwargs_injection.args
slack_bolt.kwargs_injection.async_args
slack_bolt.kwargs_injection.async_utils
slack_bolt.kwargs_injection.utils

Functions

def build_required_kwargs(*, logger: logging.Logger, required_arg_names: Sequence[str], request: BoltRequest, response: Optional[BoltResponse], next_func: Callable[[], None] = None, this_func: Optional[Callable] = None, error: Optional[Exception] = None, next_keys_required: bool = True) ‑> Dict[str, Any]
Expand source code
def build_required_kwargs(
    *,
    logger: logging.Logger,
    required_arg_names: Sequence[str],
    request: BoltRequest,
    response: Optional[BoltResponse],
    next_func: Callable[[], None] = None,
    this_func: Optional[Callable] = None,
    error: Optional[Exception] = None,  # for error handlers
    next_keys_required: bool = True,  # False for listeners / middleware / error handlers
) -> Dict[str, Any]:
    all_available_args = {
        "logger": logger,
        "client": request.context.client,
        "req": request,
        "request": request,
        "resp": response,
        "response": response,
        "context": request.context,
        # payload
        "body": request.body,
        "options": to_options(request.body),
        "shortcut": to_shortcut(request.body),
        "action": to_action(request.body),
        "view": to_view(request.body),
        "command": to_command(request.body),
        "event": to_event(request.body),
        "message": to_message(request.body),
        "step": to_step(request.body),
        # utilities
        "ack": request.context.ack,
        "say": request.context.say,
        "respond": request.context.respond,
        # middleware
        "next": next_func,
        "next_": next_func,  # for the middleware using Python's built-in `next()` function
        # error handler
        "error": error,  # Exception
    }
    if not next_keys_required:
        all_available_args.pop("next")
        all_available_args.pop("next_")

    all_available_args["payload"] = (
        all_available_args["options"]
        or all_available_args["shortcut"]
        or all_available_args["action"]
        or all_available_args["view"]
        or all_available_args["command"]
        or all_available_args["event"]
        or all_available_args["message"]
        or all_available_args["step"]
        or request.body
    )
    for k, v in request.context.items():
        if k not in all_available_args:
            all_available_args[k] = v

    if len(required_arg_names) > 0:
        # To support instance/class methods in a class for listeners/middleware,
        # check if the first argument is either self or cls
        first_arg_name = required_arg_names[0]
        if first_arg_name in {"self", "cls"}:
            required_arg_names.pop(0)
        elif first_arg_name not in all_available_args.keys() and first_arg_name != "args":
            if this_func is None:
                logger.warning(warning_skip_uncommon_arg_name(first_arg_name))
                required_arg_names.pop(0)
            elif inspect.ismethod(this_func):
                # We are sure that we should skip manipulating this arg
                required_arg_names.pop(0)

    kwargs: Dict[str, Any] = {k: v for k, v in all_available_args.items() if k in required_arg_names}
    found_arg_names = kwargs.keys()
    for name in required_arg_names:
        if name == "args":
            if isinstance(request, BoltRequest):
                kwargs[name] = Args(**all_available_args)
            else:
                logger.warning(f"Unknown Request object type detected ({type(request)})")

        elif name not in found_arg_names:
            logger.warning(f"{name} is not a valid argument")
            kwargs[name] = None
    return kwargs

Classes

class Args (*, logger: logging.Logger, client: slack_sdk.web.client.WebClient, req: BoltRequest, resp: BoltResponse, context: BoltContext, body: Dict[str, Any], payload: Dict[str, Any], options: Optional[Dict[str, Any]] = None, shortcut: Optional[Dict[str, Any]] = None, action: Optional[Dict[str, Any]] = None, view: Optional[Dict[str, Any]] = None, command: Optional[Dict[str, Any]] = None, event: Optional[Dict[str, Any]] = None, message: Optional[Dict[str, Any]] = None, ack: Ack, say: Say, respond: Respond, next: Callable[[], None], **kwargs)

All the arguments in this class are available in any middleware / listeners. You can inject the named variables in the argument list in arbitrary order.

@app.action("link_button")
def handle_buttons(ack, respond, logger, context, body, client):
    logger.info(f"request body: {body}")
    ack()
    if context.channel_id is not None:
        respond("Hi!")
    client.views_open(
        trigger_id=body["trigger_id"],
        view={ ... }
    )

Alternatively, you can include a parameter named slack_bolt.kwargs_injection.args and it will be injected with an instance of this class.

@app.action("link_button")
def handle_buttons(args):
    args.logger.info(f"request body: {args.body}")
    args.ack()
    if args.context.channel_id is not None:
        args.respond("Hi!")
    args.client.views_open(
        trigger_id=args.body["trigger_id"],
        view={ ... }
    )
Expand source code
class Args:
    """All the arguments in this class are available in any middleware / listeners.
    You can inject the named variables in the argument list in arbitrary order.

        @app.action("link_button")
        def handle_buttons(ack, respond, logger, context, body, client):
            logger.info(f"request body: {body}")
            ack()
            if context.channel_id is not None:
                respond("Hi!")
            client.views_open(
                trigger_id=body["trigger_id"],
                view={ ... }
            )

    Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class.

        @app.action("link_button")
        def handle_buttons(args):
            args.logger.info(f"request body: {args.body}")
            args.ack()
            if args.context.channel_id is not None:
                args.respond("Hi!")
            args.client.views_open(
                trigger_id=args.body["trigger_id"],
                view={ ... }
            )

    """

    client: WebClient
    """`slack_sdk.web.WebClient` instance with a valid token"""
    logger: Logger
    """Logger instance"""
    req: BoltRequest
    """Incoming request from Slack"""
    resp: BoltResponse
    """Response representation"""
    request: BoltRequest
    """Incoming request from Slack"""
    response: BoltResponse
    """Response representation"""
    context: BoltContext
    """Context data associated with the incoming request"""
    body: Dict[str, Any]
    """Parsed request body data"""
    # payload
    payload: Dict[str, Any]
    """The unwrapped core data in the request body"""
    options: Optional[Dict[str, Any]]  # payload alias
    """An alias for payload in an `@app.options` listener"""
    shortcut: Optional[Dict[str, Any]]  # payload alias
    """An alias for payload in an `@app.shortcut` listener"""
    action: Optional[Dict[str, Any]]  # payload alias
    """An alias for payload in an `@app.action` listener"""
    view: Optional[Dict[str, Any]]  # payload alias
    """An alias for payload in an `@app.view` listener"""
    command: Optional[Dict[str, Any]]  # payload alias
    """An alias for payload in an `@app.command` listener"""
    event: Optional[Dict[str, Any]]  # payload alias
    """An alias for payload in an `@app.event` listener"""
    message: Optional[Dict[str, Any]]  # payload alias
    """An alias for payload in an `@app.message` listener"""
    # utilities
    ack: Ack
    """`ack()` utility function, which returns acknowledgement to the Slack servers"""
    say: Say
    """`say()` utility function, which calls `chat.postMessage` API with the associated channel ID"""
    respond: Respond
    """`respond()` utility function, which utilizes the associated `response_url`"""
    # middleware
    next: Callable[[], None]
    """`next()` utility function, which tells the middleware chain that it can continue with the next one"""
    next_: Callable[[], None]
    """An alias of `next()` for avoiding the Python built-in method overrides in middleware functions"""

    def __init__(
        self,
        *,
        logger: logging.Logger,
        client: WebClient,
        req: BoltRequest,
        resp: BoltResponse,
        context: BoltContext,
        body: Dict[str, Any],
        payload: Dict[str, Any],
        options: Optional[Dict[str, Any]] = None,
        shortcut: Optional[Dict[str, Any]] = None,
        action: Optional[Dict[str, Any]] = None,
        view: Optional[Dict[str, Any]] = None,
        command: Optional[Dict[str, Any]] = None,
        event: Optional[Dict[str, Any]] = None,
        message: Optional[Dict[str, Any]] = None,
        ack: Ack,
        say: Say,
        respond: Respond,
        # As this method is not supposed to be invoked by bolt-python users,
        # the naming conflict with the built-in one affects
        # only the internals of this method
        next: Callable[[], None],
        **kwargs  # noqa
    ):
        self.logger: logging.Logger = logger
        self.client: WebClient = client
        self.request = self.req = req
        self.response = self.resp = resp
        self.context: BoltContext = context

        self.body: Dict[str, Any] = body
        self.payload: Dict[str, Any] = payload
        self.options: Optional[Dict[str, Any]] = options
        self.shortcut: Optional[Dict[str, Any]] = shortcut
        self.action: Optional[Dict[str, Any]] = action
        self.view: Optional[Dict[str, Any]] = view
        self.command: Optional[Dict[str, Any]] = command
        self.event: Optional[Dict[str, Any]] = event
        self.message: Optional[Dict[str, Any]] = message

        self.ack: Ack = ack
        self.say: Say = say
        self.respond: Respond = respond
        self.next: Callable[[], None] = next
        self.next_: Callable[[], None] = next

Class variables

var ackAck

ack() utility function, which returns acknowledgement to the Slack servers

var action : Optional[Dict[str, Any]]

An alias for payload in an @app.action listener

var body : Dict[str, Any]

Parsed request body data

var client : slack_sdk.web.client.WebClient

slack_sdk.web.WebClient instance with a valid token

var command : Optional[Dict[str, Any]]

An alias for payload in an @app.command listener

var contextBoltContext

Context data associated with the incoming request

var event : Optional[Dict[str, Any]]

An alias for payload in an @app.event listener

var logger : logging.Logger

Logger instance

var message : Optional[Dict[str, Any]]

An alias for payload in an @app.message listener

var next : Callable[[], None]

next() utility function, which tells the middleware chain that it can continue with the next one

var next_ : Callable[[], None]

An alias of next() for avoiding the Python built-in method overrides in middleware functions

var options : Optional[Dict[str, Any]]

An alias for payload in an @app.options listener

var payload : Dict[str, Any]

The unwrapped core data in the request body

var reqBoltRequest

Incoming request from Slack

var requestBoltRequest

Incoming request from Slack

var respBoltResponse

Response representation

var respondRespond

respond() utility function, which utilizes the associated response_url

var responseBoltResponse

Response representation

var saySay

say() utility function, which calls chat.postMessage API with the associated channel ID

var shortcut : Optional[Dict[str, Any]]

An alias for payload in an @app.shortcut listener

var view : Optional[Dict[str, Any]]

An alias for payload in an @app.view listener