Skip to content

Commit

Permalink
[flows] allowing body in FlowResponseError subclasses
Browse files Browse the repository at this point in the history
  • Loading branch information
david-lev committed Jul 12, 2024
1 parent f4c309a commit d727681
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 29 deletions.
5 changes: 5 additions & 0 deletions docs/source/content/flows/flow_types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ Flow Types

.. autoclass:: FlowAsset()

.. autoclass:: FlowResponseError()
:show-inheritance:

.. autoclass:: FlowTokenNoLongerValid()
:show-inheritance:

.. autoclass:: FlowRequestSignatureAuthenticationFailed()
:show-inheritance:

.. currentmodule:: pywa.utils

Expand Down
46 changes: 18 additions & 28 deletions pywa/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
"TemplateStatusHandler",
"FlowCompletionHandler",
"FlowRequestHandler",
"FlowRequestCallbackWrapper",
"ChatOpenedHandler",
]

Expand Down Expand Up @@ -677,7 +676,6 @@ def on_raw_update(
instance and the incoming update as :class:`dict` and return a :class:`bool` if the update should be handled).
"""

@functools.wraps(self.on_raw_update)
def decorator(
callback: Callable[[WhatsApp, dict], Any | Awaitable[Any]],
) -> Callable[[WhatsApp, dict], Any | Awaitable[Any]]:
Expand Down Expand Up @@ -712,7 +710,6 @@ def on_message(
instance and the incoming :class:`pywa.types.Message` and return a boolean).
"""

@functools.wraps(self.on_message)
def decorator(
callback: Callable[[WhatsApp, Message], Any | Awaitable[Any]],
) -> Callable[[WhatsApp, Message], Any | Awaitable[Any]]:
Expand Down Expand Up @@ -753,7 +750,6 @@ def on_callback_button(
filters will get the callback data after the factory is applied).
"""

@functools.wraps(self.on_callback_button)
def decorator(
callback: Callable[[WhatsApp, CallbackButton], Any | Awaitable[Any]],
) -> Callable[[WhatsApp, CallbackButton], Any | Awaitable[Any]]:
Expand Down Expand Up @@ -801,7 +797,6 @@ def on_callback_selection(
filters will get the callback data after the factory is applied).
"""

@functools.wraps(self.on_callback_selection)
def decorator(
callback: Callable[[WhatsApp, CallbackSelection], Any | Awaitable[Any]],
) -> Callable[[WhatsApp, CallbackSelection], Any | Awaitable[Any]]:
Expand Down Expand Up @@ -853,7 +848,6 @@ def on_message_status(
filters will get the tracker data after the factory is applied).
"""

@functools.wraps(self.on_message_status)
def decorator(
callback: Callable[[WhatsApp, MessageStatus], Any | Awaitable[Any]],
) -> Callable[[WhatsApp, MessageStatus], Any | Awaitable[Any]]:
Expand Down Expand Up @@ -895,7 +889,6 @@ def on_chat_opened(
:class:`pywa.WhatsApp` instance and the incoming :class:`pywa.types.ChatOpened` and return :class:`bool`).
"""

@functools.wraps(self.on_chat_opened)
def decorator(
callback: Callable[[WhatsApp, ChatOpened], Any | Awaitable[Any]],
) -> Callable[[WhatsApp, ChatOpened], Any | Awaitable[Any]]:
Expand Down Expand Up @@ -931,7 +924,6 @@ def on_template_status(
:class:`pywa.WhatsApp` instance and the incoming :class:`pywa.types.TemplateStatus` and return :class:`bool`).
"""

@functools.wraps(self.on_template_status)
def decorator(
callback: Callable[[WhatsApp, TemplateStatus], Any | Awaitable[Any]],
) -> Callable[[WhatsApp, TemplateStatus], Any | Awaitable[Any]]:
Expand Down Expand Up @@ -966,7 +958,6 @@ def on_flow_completion(
:class:`pywa.WhatsApp` instance and the incoming :class:`pywa.types.FlowCompletion` and return :class:`bool`).
"""

@functools.wraps(self.on_flow_completion)
def decorator(
callback: Callable[[WhatsApp, FlowCompletion], Any | Awaitable[Any]],
) -> Callable[[WhatsApp, FlowCompletion], Any | Awaitable[Any]]:
Expand Down Expand Up @@ -1018,7 +1009,6 @@ def on_flow_request(
response_encryptor: The function to use to encrypt the responses (Override the global ``flows_response_encryptor``)
"""

@functools.wraps(self.on_flow_request)
def decorator(
callback: _FlowRequestHandlerT,
) -> FlowRequestCallbackWrapper:
Expand Down Expand Up @@ -1119,16 +1109,16 @@ def on(
>>> wa = WhatsApp(...)
>>> @wa.on_flow_request("/feedback_flow")
>>> def feedback_flow_handler(_: WhatsApp, flow: FlowRequest):
... if flow.has_error: print(flow.data)
>>> def feedback_flow_handler(_: WhatsApp, req: FlowRequest):
... if req.has_error: print(req.data)
>>> @feedback_flow_handler.on(action=FlowRequestActionType.INIT)
>>> def on_init(_: WhatsApp, flow: FlowRequest):
>>> def on_init(_: WhatsApp, req: FlowRequest):
... ...
>>> @feedback_flow_handler.on(action=FlowRequestActionType.DATA_EXCHANGE, screen="SURVEY")
>>> def on_survey_data_exchange(_: WhatsApp, flow: FlowRequest):
>>> def on_survey_data_exchange(_: WhatsApp, req: FlowRequest):
... ...
>>> @feedback_flow_handler.on(..., data_filter=lambda _, data: data.get("rating") == 5)
>>> def on_rating_5(_: WhatsApp, flow: FlowRequest):
>>> def on_rating_5(_: WhatsApp, req: FlowRequest):
... ...
Args:
Expand Down Expand Up @@ -1158,11 +1148,11 @@ def on_errors(self) -> Callable[[_FlowRequestHandlerT], _FlowRequestHandlerT]:
>>> wa = WhatsApp(...)
>>> @wa.on_flow_request("/feedback_flow")
>>> def feedback_flow_handler(_: WhatsApp, flow: FlowRequest):
>>> def feedback_flow_handler(_: WhatsApp, req: FlowRequest):
... ...
>>> @feedback_flow_handler.on_errors()
>>> def on_error(_: WhatsApp, flow: FlowRequest):
... logging.error("An error occurred: %s", flow.data)
>>> def on_error(_: WhatsApp, req: FlowRequest):
... logging.error("An error occurred: %s", req.data)
Returns:
The function itself.
Expand Down Expand Up @@ -1190,10 +1180,10 @@ def add_handler(
Example:
>>> wa = WhatsApp(...)
>>> def feedback_flow_handler(_: WhatsApp, flow: FlowRequest):
>>> def feedback_flow_handler(_: WhatsApp, req: FlowRequest):
... ...
>>> on_init = lambda _, flow: ...
>>> on_survey_data_exchange = lambda _, flow: ...
>>> on_init = lambda _, req: ...
>>> on_survey_data_exchange = lambda _, req: ...
>>> wa.add_flow_request_handler(
... FlowRequestHandler(callback=feedback_flow_handler, endpoint="/feedback_flow")
... ).add_handler(callback=on_init, action=FlowRequestActionType.INIT)
Expand Down Expand Up @@ -1221,11 +1211,13 @@ def set_errors_handler(
Example:
>>> wa = WhatsApp(...)
>>> def feedback_flow_handler(_: WhatsApp, flow: FlowRequest):
>>> def feedback_flow_handler(_: WhatsApp, req: FlowRequest):
... ...
>>> def on_error(_: WhatsApp, flow: FlowRequest):
... logging.error("An error occurred: %s", flow.data)
>>> def on_error(_: WhatsApp, req: FlowRequest):
... logging.error("An error occurred: %s", req.data)
>>> wa.add_flow_request_handler(
... FlowRequestHandler(callback=feedback_flow_handler, endpoint="/feedback_flow")
... ).set_errors_handler(callback=on_error)
...
Args:
Expand Down Expand Up @@ -1305,17 +1297,15 @@ async def __call__(self, payload: dict) -> tuple[str, int]:
response = callback(self._wa, request)
if isinstance(response, FlowResponseError):
raise response
except FlowTokenNoLongerValid as e:
except FlowResponseError as e:
return (
self._response_encryptor(
{"error_msg": e.error_message},
e.body or {"error": e.__class__.__name__},
aes_key,
iv,
),
e.status_code,
)
except FlowResponseError as e:
return e.__class__.__name__, e.status_code
except Exception:
_logger.exception(
"Flow Endpoint ('%s'): An error occurred while %s was handling a flow request",
Expand Down
4 changes: 3 additions & 1 deletion pywa/types/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,9 +372,11 @@ class FlowResponseError(Exception):
- Subclass this exception to return or raise from the flow endpoint callback (@wa.on_flow_request).
- Override the ``status_code`` attribute to set the status code of the response.
- Override the ``body`` attribute to set the body of the response (optional).
"""

status_code: int
body: dict | None = None


class FlowRequestCannotBeDecrypted(FlowResponseError):
Expand Down Expand Up @@ -420,7 +422,7 @@ class FlowTokenNoLongerValid(FlowResponseError):
status_code = 427

def __init__(self, error_message: str):
self.error_message = error_message
self.body = {"error_msg": error_message}


class FlowStatus(utils.StrEnum):
Expand Down

0 comments on commit d727681

Please sign in to comment.