15
15
import asyncio
16
16
import fnmatch
17
17
import re
18
+ import traceback
18
19
19
20
from typing import (
20
21
Any ,
40
41
from playwright .network import Route , Request
41
42
42
43
Cookie = List [Dict [str , Union [str , int , bool ]]]
43
- URLMatch = Union [str , Callable [[str ], bool ]]
44
+ URLMatch = Union [str , Pattern , Callable [[str ], bool ]]
44
45
RouteHandler = Callable [["Route" , "Request" ], None ]
45
46
FunctionWithSource = Callable [[Dict ], Any ]
46
47
@@ -101,8 +102,10 @@ def __init__(self, match: URLMatch):
101
102
self ._callback : Optional [Callable [[str ], bool ]] = None
102
103
self ._regex_obj : Optional [Pattern ] = None
103
104
if isinstance (match , str ):
104
- regex = "(?:http://|https://)" + fnmatch .translate (match )
105
+ regex = fnmatch .translate (match )
105
106
self ._regex_obj = re .compile (regex )
107
+ elif isinstance (match , Pattern ):
108
+ self ._regex_obj = match
106
109
else :
107
110
self ._callback = match
108
111
self .match = match
@@ -111,16 +114,35 @@ def matches(self, url: str) -> bool:
111
114
if self ._callback :
112
115
return self ._callback (url )
113
116
if self ._regex_obj :
114
- return cast (bool , self ._regex_obj .match (url ))
117
+ return cast (bool , self ._regex_obj .search (url ))
115
118
return False
116
119
117
120
118
121
class TimeoutSettings :
119
122
def __init__ (self , parent : Optional ["TimeoutSettings" ]) -> None :
120
123
self ._parent = parent
124
+ self ._timeout = 30000
125
+ self ._navigation_timeout = 30000
121
126
122
- def set_default_timeout (self , timeout ):
123
- self .timeout = timeout
127
+ def set_timeout (self , timeout : int ):
128
+ self ._timeout = timeout
129
+
130
+ def timeout (self ) -> int :
131
+ if self ._timeout is not None :
132
+ return self ._timeout
133
+ if self ._parent :
134
+ return self ._parent .timeout ()
135
+ return 30000
136
+
137
+ def set_navigation_timeout (self , navigation_timeout : int ):
138
+ self ._navigation_timeout = navigation_timeout
139
+
140
+ def navigation_timeout (self ) -> int :
141
+ if self ._navigation_timeout is not None :
142
+ return self ._navigation_timeout
143
+ if self ._parent :
144
+ return self ._parent .navigation_timeout ()
145
+ return 30000
124
146
125
147
126
148
class Error (Exception ):
@@ -133,11 +155,11 @@ class TimeoutError(Error):
133
155
pass
134
156
135
157
136
- def serialize_error (ex : Exception ) -> ErrorPayload :
137
- return dict (message = str (ex ))
158
+ def serialize_error (ex : Exception , tb ) -> ErrorPayload :
159
+ return dict (message = str (ex ), stack = "" . join ( traceback . format_tb ( tb )) )
138
160
139
161
140
- def parse_error (error : ErrorPayload ):
162
+ def parse_error (error : ErrorPayload ) -> Error :
141
163
base_error_class = Error
142
164
if error .get ("name" ) == "TimeoutError" :
143
165
base_error_class = TimeoutError
@@ -164,9 +186,22 @@ def locals_to_params(args: Dict) -> Dict:
164
186
165
187
166
188
class PendingWaitEvent :
167
- def __init__ (self , event : str , future : asyncio .Future ):
189
+ def __init__ (
190
+ self , event : str , future : asyncio .Future , timeout_future : asyncio .Future
191
+ ):
168
192
self .event = event
169
193
self .future = future
194
+ self .timeout_future = timeout_future
195
+
196
+ def reject (self , is_crash : bool , target : str ):
197
+ self .timeout_future .cancel ()
198
+ if self .event == "close" and not is_crash :
199
+ return
200
+ if self .event == "crash" and is_crash :
201
+ return
202
+ self .future .set_exception (
203
+ Error (f"{ target } crashed" if is_crash else f"{ target } closed" )
204
+ )
170
205
171
206
172
207
class RouteHandlerEntry :
0 commit comments