Skip to content

Commit f347dd4

Browse files
authored
feat(api): schedule tasks for async route handlers (microsoft#380)
1 parent 9558892 commit f347dd4

11 files changed

+160
-148
lines changed

playwright/_browser_context.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
# limitations under the License.
1414

1515
import asyncio
16+
import inspect
1617
import json
1718
from pathlib import Path
1819
from types import SimpleNamespace
19-
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union
20+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union, cast
2021

2122
from playwright._api_structures import Cookie, StorageState
2223
from playwright._api_types import Error, Geolocation
@@ -84,7 +85,9 @@ def _on_page(self, page: Page) -> None:
8485
def _on_route(self, route: Route, request: Request) -> None:
8586
for handler_entry in self._routes:
8687
if handler_entry.matcher.matches(request.url):
87-
handler_entry.handler(route, request)
88+
result = cast(Any, handler_entry.handler)(route, request)
89+
if inspect.iscoroutine(result):
90+
asyncio.create_task(result)
8891
return
8992
asyncio.create_task(route.continue_())
9093

playwright/_helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
from playwright._network import Request, Route
4545

4646
URLMatch = Union[str, Pattern, Callable[[str], bool]]
47-
RouteHandler = Callable[["Route", "Request"], Any]
47+
RouteHandler = Union[Callable[["Route"], Any], Callable[["Route", "Request"], Any]]
4848

4949
ColorScheme = Literal["dark", "light", "no-preference"]
5050
DocumentLoadState = Literal["domcontentloaded", "load", "networkidle"]

playwright/_network.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ async def response(self) -> Optional["Response"]:
105105
def frame(self) -> "Frame":
106106
return from_channel(self._initializer["frame"])
107107

108+
@property
108109
def isNavigationRequest(self) -> bool:
109110
return self._initializer["isNavigationRequest"]
110111

playwright/_page.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import asyncio
1616
import base64
17+
import inspect
1718
import sys
1819
from pathlib import Path
1920
from types import SimpleNamespace
@@ -267,7 +268,9 @@ def _on_frame_detached(self, frame: Frame) -> None:
267268
def _on_route(self, route: Route, request: Request) -> None:
268269
for handler_entry in self._routes:
269270
if handler_entry.matcher.matches(request.url):
270-
handler_entry.handler(route, request)
271+
result = cast(Any, handler_entry.handler)(route, request)
272+
if inspect.iscoroutine(result):
273+
asyncio.create_task(result)
271274
return
272275
self._browser_context._on_route(route, request)
273276

playwright/async_api.py

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,18 @@ def frame(self) -> "Frame":
174174
"""
175175
return mapping.from_impl(self._impl_obj.frame)
176176

177+
@property
178+
def is_navigation_request(self) -> bool:
179+
"""Request.is_navigation_request
180+
181+
Whether this request is driving frame's navigation.
182+
183+
Returns
184+
-------
185+
bool
186+
"""
187+
return mapping.from_maybe_impl(self._impl_obj.isNavigationRequest)
188+
177189
@property
178190
def redirected_from(self) -> typing.Union["Request", NoneType]:
179191
"""Request.redirected_from
@@ -242,17 +254,6 @@ async def response(self) -> typing.Union["Response", NoneType]:
242254
"""
243255
return mapping.from_impl_nullable(await self._impl_obj.response())
244256

245-
def is_navigation_request(self) -> bool:
246-
"""Request.is_navigation_request
247-
248-
Whether this request is driving frame's navigation.
249-
250-
Returns
251-
-------
252-
bool
253-
"""
254-
return mapping.from_maybe_impl(self._impl_obj.isNavigationRequest())
255-
256257

257258
mapping.register(RequestImpl, Request)
258259

@@ -4606,7 +4607,10 @@ async def add_init_script(
46064607
async def route(
46074608
self,
46084609
url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
4609-
handler: typing.Callable[["Route", "Request"], typing.Any],
4610+
handler: typing.Union[
4611+
typing.Callable[["Route"], typing.Any],
4612+
typing.Callable[["Route", "Request"], typing.Any],
4613+
],
46104614
) -> NoneType:
46114615
"""Page.route
46124616
@@ -4626,7 +4630,7 @@ async def route(
46264630
----------
46274631
url : Union[str, Pattern, Callable[[str], bool]]
46284632
A glob pattern, regex pattern or predicate receiving URL to match while routing.
4629-
handler : Callable[[Route, Request], Any]
4633+
handler : Union[Callable[[Route], Any], Callable[[Route, Request], Any]]
46304634
handler function to route the request.
46314635
"""
46324636
return mapping.from_maybe_impl(
@@ -4638,7 +4642,10 @@ async def route(
46384642
async def unroute(
46394643
self,
46404644
url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
4641-
handler: typing.Union[typing.Callable[["Route", "Request"], typing.Any]] = None,
4645+
handler: typing.Union[
4646+
typing.Callable[["Route"], typing.Any],
4647+
typing.Callable[["Route", "Request"], typing.Any],
4648+
] = None,
46424649
) -> NoneType:
46434650
"""Page.unroute
46444651
@@ -4648,7 +4655,7 @@ async def unroute(
46484655
----------
46494656
url : Union[str, Pattern, Callable[[str], bool]]
46504657
A glob pattern, regex pattern or predicate receiving URL to match while routing.
4651-
handler : Optional[Callable[[Route, Request], Any]]
4658+
handler : Union[Callable[[Route], Any], Callable[[Route, Request], Any], NoneType]
46524659
Optional handler function to route the request.
46534660
"""
46544661
return mapping.from_maybe_impl(
@@ -6150,7 +6157,10 @@ async def expose_function(self, name: str, binding: typing.Callable) -> NoneType
61506157
async def route(
61516158
self,
61526159
url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
6153-
handler: typing.Callable[["Route", "Request"], typing.Any],
6160+
handler: typing.Union[
6161+
typing.Callable[["Route"], typing.Any],
6162+
typing.Callable[["Route", "Request"], typing.Any],
6163+
],
61546164
) -> NoneType:
61556165
"""BrowserContext.route
61566166
@@ -6167,7 +6177,7 @@ async def route(
61676177
----------
61686178
url : Union[str, Pattern, Callable[[str], bool]]
61696179
A glob pattern, regex pattern or predicate receiving URL to match while routing.
6170-
handler : Callable[[Route, Request], Any]
6180+
handler : Union[Callable[[Route], Any], Callable[[Route, Request], Any]]
61716181
handler function to route the request.
61726182
"""
61736183
return mapping.from_maybe_impl(
@@ -6179,7 +6189,10 @@ async def route(
61796189
async def unroute(
61806190
self,
61816191
url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
6182-
handler: typing.Union[typing.Callable[["Route", "Request"], typing.Any]] = None,
6192+
handler: typing.Union[
6193+
typing.Callable[["Route"], typing.Any],
6194+
typing.Callable[["Route", "Request"], typing.Any],
6195+
] = None,
61836196
) -> NoneType:
61846197
"""BrowserContext.unroute
61856198
@@ -6190,7 +6203,7 @@ async def unroute(
61906203
----------
61916204
url : Union[str, Pattern, Callable[[str], bool]]
61926205
A glob pattern, regex pattern or predicate receiving URL used to register a routing with browser_context.route(url, handler).
6193-
handler : Optional[Callable[[Route, Request], Any]]
6206+
handler : Union[Callable[[Route], Any], Callable[[Route, Request], Any], NoneType]
61946207
Optional handler function used to register a routing with browser_context.route(url, handler).
61956208
"""
61966209
return mapping.from_maybe_impl(

playwright/sync_api.py

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,18 @@ def frame(self) -> "Frame":
174174
"""
175175
return mapping.from_impl(self._impl_obj.frame)
176176

177+
@property
178+
def is_navigation_request(self) -> bool:
179+
"""Request.is_navigation_request
180+
181+
Whether this request is driving frame's navigation.
182+
183+
Returns
184+
-------
185+
bool
186+
"""
187+
return mapping.from_maybe_impl(self._impl_obj.isNavigationRequest)
188+
177189
@property
178190
def redirected_from(self) -> typing.Union["Request", NoneType]:
179191
"""Request.redirected_from
@@ -242,17 +254,6 @@ def response(self) -> typing.Union["Response", NoneType]:
242254
"""
243255
return mapping.from_impl_nullable(self._sync(self._impl_obj.response()))
244256

245-
def is_navigation_request(self) -> bool:
246-
"""Request.is_navigation_request
247-
248-
Whether this request is driving frame's navigation.
249-
250-
Returns
251-
-------
252-
bool
253-
"""
254-
return mapping.from_maybe_impl(self._impl_obj.isNavigationRequest())
255-
256257

257258
mapping.register(RequestImpl, Request)
258259

@@ -4764,7 +4765,10 @@ def add_init_script(
47644765
def route(
47654766
self,
47664767
url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
4767-
handler: typing.Callable[["Route", "Request"], typing.Any],
4768+
handler: typing.Union[
4769+
typing.Callable[["Route"], typing.Any],
4770+
typing.Callable[["Route", "Request"], typing.Any],
4771+
],
47684772
) -> NoneType:
47694773
"""Page.route
47704774
@@ -4784,7 +4788,7 @@ def route(
47844788
----------
47854789
url : Union[str, Pattern, Callable[[str], bool]]
47864790
A glob pattern, regex pattern or predicate receiving URL to match while routing.
4787-
handler : Callable[[Route, Request], Any]
4791+
handler : Union[Callable[[Route], Any], Callable[[Route, Request], Any]]
47884792
handler function to route the request.
47894793
"""
47904794
return mapping.from_maybe_impl(
@@ -4798,7 +4802,10 @@ def route(
47984802
def unroute(
47994803
self,
48004804
url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
4801-
handler: typing.Union[typing.Callable[["Route", "Request"], typing.Any]] = None,
4805+
handler: typing.Union[
4806+
typing.Callable[["Route"], typing.Any],
4807+
typing.Callable[["Route", "Request"], typing.Any],
4808+
] = None,
48024809
) -> NoneType:
48034810
"""Page.unroute
48044811
@@ -4808,7 +4815,7 @@ def unroute(
48084815
----------
48094816
url : Union[str, Pattern, Callable[[str], bool]]
48104817
A glob pattern, regex pattern or predicate receiving URL to match while routing.
4811-
handler : Optional[Callable[[Route, Request], Any]]
4818+
handler : Union[Callable[[Route], Any], Callable[[Route, Request], Any], NoneType]
48124819
Optional handler function to route the request.
48134820
"""
48144821
return mapping.from_maybe_impl(
@@ -6325,7 +6332,10 @@ def expose_function(self, name: str, binding: typing.Callable) -> NoneType:
63256332
def route(
63266333
self,
63276334
url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
6328-
handler: typing.Callable[["Route", "Request"], typing.Any],
6335+
handler: typing.Union[
6336+
typing.Callable[["Route"], typing.Any],
6337+
typing.Callable[["Route", "Request"], typing.Any],
6338+
],
63296339
) -> NoneType:
63306340
"""BrowserContext.route
63316341
@@ -6342,7 +6352,7 @@ def route(
63426352
----------
63436353
url : Union[str, Pattern, Callable[[str], bool]]
63446354
A glob pattern, regex pattern or predicate receiving URL to match while routing.
6345-
handler : Callable[[Route, Request], Any]
6355+
handler : Union[Callable[[Route], Any], Callable[[Route, Request], Any]]
63466356
handler function to route the request.
63476357
"""
63486358
return mapping.from_maybe_impl(
@@ -6356,7 +6366,10 @@ def route(
63566366
def unroute(
63576367
self,
63586368
url: typing.Union[str, typing.Pattern, typing.Callable[[str], bool]],
6359-
handler: typing.Union[typing.Callable[["Route", "Request"], typing.Any]] = None,
6369+
handler: typing.Union[
6370+
typing.Callable[["Route"], typing.Any],
6371+
typing.Callable[["Route", "Request"], typing.Any],
6372+
] = None,
63606373
) -> NoneType:
63616374
"""BrowserContext.unroute
63626375
@@ -6367,7 +6380,7 @@ def unroute(
63676380
----------
63686381
url : Union[str, Pattern, Callable[[str], bool]]
63696382
A glob pattern, regex pattern or predicate receiving URL used to register a routing with browser_context.route(url, handler).
6370-
handler : Optional[Callable[[Route, Request], Any]]
6383+
handler : Union[Callable[[Route], Any], Callable[[Route, Request], Any], NoneType]
63716384
Optional handler function used to register a routing with browser_context.route(url, handler).
63726385
"""
63736386
return mapping.from_maybe_impl(

scripts/expected_api_mismatch.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ Parameter type mismatch in Frame.dispatchEvent(eventInit=): documented as Option
9595
Parameter type mismatch in Page.dispatchEvent(eventInit=): documented as Optional[EvaluationArgument], code has Optional[Dict]
9696

9797
# Route
98-
Parameter type mismatch in Page.route(handler=): documented as function(Route, Request), code has Callable[[Route, Request], Any]
99-
Parameter type mismatch in Page.unroute(handler=): documented as Optional[function(Route, Request)], code has Optional[Callable[[Route, Request], Any]]
100-
Parameter type mismatch in BrowserContext.route(handler=): documented as function(Route, Request), code has Callable[[Route, Request], Any]
101-
Parameter type mismatch in BrowserContext.unroute(handler=): documented as Optional[function(Route, Request)], code has Optional[Callable[[Route, Request], Any]]
98+
Parameter type mismatch in Page.unroute(handler=): documented as Optional[function(Route, Request)], code has Union[Callable[[Route], Any], Callable[[Route, Request], Any], NoneType]
99+
Parameter type mismatch in Page.route(handler=): documented as function(Route, Request), code has Union[Callable[[Route], Any], Callable[[Route, Request], Any]]
100+
Parameter type mismatch in BrowserContext.unroute(handler=): documented as Optional[function(Route, Request)], code has Union[Callable[[Route], Any], Callable[[Route, Request], Any], NoneType]
101+
Parameter type mismatch in BrowserContext.route(handler=): documented as function(Route, Request), code has Union[Callable[[Route], Any], Callable[[Route, Request], Any]]
102102

103103
# Selectors
104104
Parameter type mismatch in Selectors.register(script=): documented as Union[Callable, str, Dict], code has Optional[str]

tests/async/test_browsercontext.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ def handle(route, request):
440440
assert request.headers["user-agent"]
441441
assert request.method == "GET"
442442
assert request.post_data is None
443-
assert request.is_navigation_request()
443+
assert request.is_navigation_request
444444
assert request.resource_type == "document"
445445
assert request.frame == page.main_frame
446446
assert request.frame.url == "about:blank"

0 commit comments

Comments
 (0)