Skip to content

Commit

Permalink
Fix #370 by adding an alias of next arg (next_) in middleware arg…
Browse files Browse the repository at this point in the history
…uments (#394)
  • Loading branch information
seratch authored Jul 9, 2021
1 parent c61206d commit dce45c5
Show file tree
Hide file tree
Showing 23 changed files with 198 additions and 3 deletions.
6 changes: 6 additions & 0 deletions slack_bolt/kwargs_injection/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ def handle_buttons(ack, respond, logger, context, body, client):
# 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,
Expand All @@ -93,6 +95,9 @@ def __init__(
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
):
Expand All @@ -116,3 +121,4 @@ def __init__(
self.say: Say = say
self.respond: Respond = respond
self.next: Callable[[], None] = next
self.next_: Callable[[], None] = next
3 changes: 3 additions & 0 deletions slack_bolt/kwargs_injection/async_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ async def handle_buttons(ack, respond, logger, context, body, client):
# middleware
next: Callable[[], Awaitable[None]]
"""`next()` utility function, which tells the middleware chain that it can continue with the next one"""
next_: Callable[[], Awaitable[None]]
"""An alias of `next()` for avoiding the Python built-in method overrides in middleware functions"""

def __init__(
self,
Expand Down Expand Up @@ -115,3 +117,4 @@ def __init__(
self.say: AsyncSay = say
self.respond: AsyncRespond = respond
self.next: Callable[[], Awaitable[None]] = next
self.next_: Callable[[], Awaitable[None]] = next
1 change: 1 addition & 0 deletions slack_bolt/kwargs_injection/async_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def build_async_required_kwargs(
"respond": request.context.respond,
# middleware
"next": next_func,
"next_": next_func, # for the middleware using Python's built-in `next()` function
}
all_available_args["payload"] = (
all_available_args["options"]
Expand Down
1 change: 1 addition & 0 deletions slack_bolt/kwargs_injection/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def build_required_kwargs(
"respond": request.context.respond,
# middleware
"next": next_func,
"next_": next_func, # for the middleware using Python's built-in `next()` function
}
all_available_args["payload"] = (
all_available_args["options"]
Expand Down
4 changes: 2 additions & 2 deletions slack_bolt/listener/listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ def run_middleware(
for m in self.middleware:
middleware_state = {"next_called": False}

def next():
def next_():
middleware_state["next_called"] = True

resp = m.process(req=req, resp=resp, next=next)
resp = m.process(req=req, resp=resp, next=next_)
if not middleware_state["next_called"]:
# next() was not called in this middleware
return (resp, True)
Expand Down
2 changes: 1 addition & 1 deletion slack_bolt/logger/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def warning_unhandled_by_global_middleware( # type: ignore
name: str, req: Union[BoltRequest, "AsyncBoltRequest"] # type: ignore
) -> str: # type: ignore
return (
f"A global middleware ({name}) skipped calling `next()` "
f"A global middleware ({name}) skipped calling either `next()` or `next_()` "
f"without providing a response for the request ({req.body})"
)

Expand Down
3 changes: 3 additions & 0 deletions slack_bolt/middleware/async_custom_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ async def async_process(
*,
req: AsyncBoltRequest,
resp: BoltResponse,
# 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[[], Awaitable[BoltResponse]],
) -> BoltResponse:
return await self.func(
Expand Down
11 changes: 11 additions & 0 deletions slack_bolt/middleware/async_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ async def async_process(
*,
req: AsyncBoltRequest,
resp: BoltResponse,
# 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[[], Awaitable[BoltResponse]],
) -> Optional[BoltResponse]:
"""Processes a request data before other middleware and listeners.
Expand All @@ -24,6 +27,14 @@ async def simple_middleware(req, resp, next):
# do something here
await next()
This `async_process(req, resp, next)` method is supposed to be invoked only inside bolt-python.
If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead.
@app.middleware
async def simple_middleware(req, resp, next_):
# do something here
await next_()
Args:
req: The incoming request
resp: The response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ async def async_process(
*,
req: AsyncBoltRequest,
resp: BoltResponse,
# 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[[], Awaitable[BoltResponse]],
) -> BoltResponse:
if _is_no_auth_required(req):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ async def async_process(
*,
req: AsyncBoltRequest,
resp: BoltResponse,
# 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[[], Awaitable[BoltResponse]],
) -> BoltResponse:
if _is_no_auth_required(req):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ def process(
*,
req: BoltRequest,
resp: BoltResponse,
# 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[[], BoltResponse],
) -> BoltResponse:
if _is_no_auth_required(req):
Expand Down
3 changes: 3 additions & 0 deletions slack_bolt/middleware/custom_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ def process(
*,
req: BoltRequest,
resp: BoltResponse,
# 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[[], BoltResponse],
) -> BoltResponse:
return self.func(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ async def async_process(
*,
req: AsyncBoltRequest,
resp: BoltResponse,
# 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[[], Awaitable[BoltResponse]],
) -> BoltResponse:
text = req.body.get("event", {}).get("text", "")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ def process(
*,
req: BoltRequest,
resp: BoltResponse,
# 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[[], BoltResponse],
) -> BoltResponse:
text = req.body.get("event", {}).get("text", "")
Expand Down
11 changes: 11 additions & 0 deletions slack_bolt/middleware/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def process(
*,
req: BoltRequest,
resp: BoltResponse,
# 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[[], BoltResponse],
) -> Optional[BoltResponse]:
"""Processes a request data before other middleware and listeners.
Expand All @@ -24,6 +27,14 @@ def simple_middleware(req, resp, next):
# do something here
next()
This `process(req, resp, next)` method is supposed to be invoked only inside bolt-python.
If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead.
@app.middleware
def simple_middleware(req, resp, next_):
# do something here
next_()
Args:
req: The incoming request
resp: The response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ async def async_process(
*,
req: AsyncBoltRequest,
resp: BoltResponse,
# 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[[], Awaitable[BoltResponse]],
) -> BoltResponse:
if self._can_skip(req.mode, req.body):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ def process(
*,
req: BoltRequest,
resp: BoltResponse,
# 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[[], BoltResponse],
) -> BoltResponse:
if self._can_skip(req.mode, req.body):
Expand Down
3 changes: 3 additions & 0 deletions slack_bolt/middleware/ssl_check/async_ssl_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ async def async_process(
*,
req: AsyncBoltRequest,
resp: BoltResponse,
# 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[[], Awaitable[BoltResponse]],
) -> BoltResponse:
if self._is_ssl_check_request(req.body):
Expand Down
3 changes: 3 additions & 0 deletions slack_bolt/middleware/ssl_check/ssl_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ def process(
*,
req: BoltRequest,
resp: BoltResponse,
# 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[[], BoltResponse],
) -> BoltResponse:
if self._is_ssl_check_request(req.body):
Expand Down
3 changes: 3 additions & 0 deletions slack_bolt/middleware/url_verification/url_verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ def process(
*,
req: BoltRequest,
resp: BoltResponse,
# 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[[], BoltResponse],
) -> BoltResponse:
if self._is_url_verification_request(req.body):
Expand Down
3 changes: 3 additions & 0 deletions slack_bolt/workflows/step/step_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ def process(
*,
req: BoltRequest,
resp: BoltResponse,
# 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[[], BoltResponse],
) -> Optional[BoltResponse]:

Expand Down
68 changes: 68 additions & 0 deletions tests/scenario_tests/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,53 @@ def test_next_call(self):
assert response.body == "acknowledged!"
assert_auth_test_count(self, 1)

def test_decorator_next_call(self):
app = App(
client=self.web_client,
signing_secret=self.signing_secret,
)

@app.middleware
def just_next(next):
next()

app.shortcut("test-shortcut")(just_ack)

response = app.dispatch(self.build_request())
assert response.status == 200
assert response.body == "acknowledged!"
assert_auth_test_count(self, 1)

def test_next_call_(self):
app = App(
client=self.web_client,
signing_secret=self.signing_secret,
)
app.use(just_next_)
app.shortcut("test-shortcut")(just_ack)

response = app.dispatch(self.build_request())
assert response.status == 200
assert response.body == "acknowledged!"
assert_auth_test_count(self, 1)

def test_decorator_next_call_(self):
app = App(
client=self.web_client,
signing_secret=self.signing_secret,
)

@app.middleware
def just_next_(next_):
next_()

app.shortcut("test-shortcut")(just_ack)

response = app.dispatch(self.build_request())
assert response.status == 200
assert response.body == "acknowledged!"
assert_auth_test_count(self, 1)

def test_class_call(self):
class NextClass:
def __call__(self, next):
Expand All @@ -104,6 +151,23 @@ def __call__(self, next):
assert response.body == "acknowledged!"
assert_auth_test_count(self, 1)

def test_class_call_(self):
class NextUnderscoreClass:
def __call__(self, next_):
next_()

app = App(
client=self.web_client,
signing_secret=self.signing_secret,
)
app.use(NextUnderscoreClass())
app.shortcut("test-shortcut")(just_ack)

response = app.dispatch(self.build_request())
assert response.status == 200
assert response.body == "acknowledged!"
assert_auth_test_count(self, 1)


def just_ack(ack):
ack("acknowledged!")
Expand All @@ -115,3 +179,7 @@ def no_next():

def just_next(next):
next()


def just_next_(next_):
next_()
Loading

0 comments on commit dce45c5

Please sign in to comment.