playwright-browserstack 1.62.0__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. playwright/__init__.py +19 -0
  2. playwright/__main__.py +33 -0
  3. playwright/_impl/__init__.py +0 -0
  4. playwright/_impl/__pyinstaller/__init__.py +20 -0
  5. playwright/_impl/__pyinstaller/hook-playwright.async_api.py +17 -0
  6. playwright/_impl/__pyinstaller/hook-playwright.sync_api.py +17 -0
  7. playwright/_impl/_android.py +704 -0
  8. playwright/_impl/_api_structures.py +365 -0
  9. playwright/_impl/_artifact.py +87 -0
  10. playwright/_impl/_assertions.py +1124 -0
  11. playwright/_impl/_async_base.py +105 -0
  12. playwright/_impl/_browser.py +293 -0
  13. playwright/_impl/_browser_context.py +754 -0
  14. playwright/_impl/_browser_type.py +368 -0
  15. playwright/_impl/_cdp_session.py +46 -0
  16. playwright/_impl/_clock.py +104 -0
  17. playwright/_impl/_connection.py +764 -0
  18. playwright/_impl/_console_message.py +98 -0
  19. playwright/_impl/_credentials.py +57 -0
  20. playwright/_impl/_debugger.py +54 -0
  21. playwright/_impl/_dialog.py +63 -0
  22. playwright/_impl/_disposable.py +96 -0
  23. playwright/_impl/_download.py +64 -0
  24. playwright/_impl/_driver.py +41 -0
  25. playwright/_impl/_element_handle.py +480 -0
  26. playwright/_impl/_errors.py +64 -0
  27. playwright/_impl/_event_context_manager.py +33 -0
  28. playwright/_impl/_fetch.py +626 -0
  29. playwright/_impl/_file_chooser.py +57 -0
  30. playwright/_impl/_form_data.py +34 -0
  31. playwright/_impl/_frame.py +985 -0
  32. playwright/_impl/_glob.py +65 -0
  33. playwright/_impl/_greenlets.py +49 -0
  34. playwright/_impl/_har_router.py +122 -0
  35. playwright/_impl/_helper.py +601 -0
  36. playwright/_impl/_impl_to_api_mapping.py +158 -0
  37. playwright/_impl/_input.py +111 -0
  38. playwright/_impl/_js_handle.py +336 -0
  39. playwright/_impl/_json_pipe.py +97 -0
  40. playwright/_impl/_local_utils.py +95 -0
  41. playwright/_impl/_locator.py +1024 -0
  42. playwright/_impl/_map.py +31 -0
  43. playwright/_impl/_network.py +1017 -0
  44. playwright/_impl/_object_factory.py +116 -0
  45. playwright/_impl/_page.py +1637 -0
  46. playwright/_impl/_path_utils.py +27 -0
  47. playwright/_impl/_playwright.py +68 -0
  48. playwright/_impl/_screencast.py +177 -0
  49. playwright/_impl/_selectors.py +67 -0
  50. playwright/_impl/_set_input_files_helpers.py +158 -0
  51. playwright/_impl/_str_utils.py +76 -0
  52. playwright/_impl/_stream.py +46 -0
  53. playwright/_impl/_sync_base.py +151 -0
  54. playwright/_impl/_tracing.py +281 -0
  55. playwright/_impl/_transport.py +184 -0
  56. playwright/_impl/_video.py +56 -0
  57. playwright/_impl/_waiter.py +197 -0
  58. playwright/_impl/_web_error.py +48 -0
  59. playwright/_impl/_web_storage.py +58 -0
  60. playwright/_impl/_writable_stream.py +42 -0
  61. playwright/_repo_version.py +24 -0
  62. playwright/async_api/__init__.py +275 -0
  63. playwright/async_api/_android_generated.py +462 -0
  64. playwright/async_api/_context_manager.py +57 -0
  65. playwright/async_api/_generated.py +23875 -0
  66. playwright/driver/LICENSE +2946 -0
  67. playwright/driver/README.md +1 -0
  68. playwright/driver/node.exe +0 -0
  69. playwright/driver/package/LICENSE +202 -0
  70. playwright/driver/package/NOTICE +5 -0
  71. playwright/driver/package/README.md +3 -0
  72. playwright/driver/package/ThirdPartyNotices.txt +13 -0
  73. playwright/driver/package/bin/install_media_pack.ps1 +5 -0
  74. playwright/driver/package/bin/install_webkit_wsl.ps1 +33 -0
  75. playwright/driver/package/bin/reinstall_chrome_beta_linux.sh +42 -0
  76. playwright/driver/package/bin/reinstall_chrome_beta_mac.sh +13 -0
  77. playwright/driver/package/bin/reinstall_chrome_beta_win.ps1 +24 -0
  78. playwright/driver/package/bin/reinstall_chrome_stable_linux.sh +42 -0
  79. playwright/driver/package/bin/reinstall_chrome_stable_mac.sh +12 -0
  80. playwright/driver/package/bin/reinstall_chrome_stable_win.ps1 +24 -0
  81. playwright/driver/package/bin/reinstall_msedge_beta_linux.sh +48 -0
  82. playwright/driver/package/bin/reinstall_msedge_beta_mac.sh +11 -0
  83. playwright/driver/package/bin/reinstall_msedge_beta_win.ps1 +23 -0
  84. playwright/driver/package/bin/reinstall_msedge_dev_linux.sh +48 -0
  85. playwright/driver/package/bin/reinstall_msedge_dev_mac.sh +11 -0
  86. playwright/driver/package/bin/reinstall_msedge_dev_win.ps1 +23 -0
  87. playwright/driver/package/bin/reinstall_msedge_stable_linux.sh +48 -0
  88. playwright/driver/package/bin/reinstall_msedge_stable_mac.sh +11 -0
  89. playwright/driver/package/bin/reinstall_msedge_stable_win.ps1 +24 -0
  90. playwright/driver/package/browsers.json +75 -0
  91. playwright/driver/package/cli.js +21 -0
  92. playwright/driver/package/index.d.ts +17 -0
  93. playwright/driver/package/index.js +17 -0
  94. playwright/driver/package/index.mjs +28 -0
  95. playwright/driver/package/lib/bootstrap.js +88 -0
  96. playwright/driver/package/lib/coreBundle.js +74830 -0
  97. playwright/driver/package/lib/entry/cliDaemon.js +5 -0
  98. playwright/driver/package/lib/entry/dashboardApp.js +3 -0
  99. playwright/driver/package/lib/entry/mcp.js +10 -0
  100. playwright/driver/package/lib/entry/oopBrowserDownload.js +3 -0
  101. playwright/driver/package/lib/package.js +50 -0
  102. playwright/driver/package/lib/server/chromium/appIcon.png +0 -0
  103. playwright/driver/package/lib/server/electron/loader.js +118 -0
  104. playwright/driver/package/lib/serverRegistry.js +7347 -0
  105. playwright/driver/package/lib/serverRegistry.js.LICENSE +354 -0
  106. playwright/driver/package/lib/tools/cli-client/channelSessions.js +141 -0
  107. playwright/driver/package/lib/tools/cli-client/cli.js +6 -0
  108. playwright/driver/package/lib/tools/cli-client/help.json +708 -0
  109. playwright/driver/package/lib/tools/cli-client/minimist.js +128 -0
  110. playwright/driver/package/lib/tools/cli-client/output.js +343 -0
  111. playwright/driver/package/lib/tools/cli-client/program.js +404 -0
  112. playwright/driver/package/lib/tools/cli-client/registry.js +176 -0
  113. playwright/driver/package/lib/tools/cli-client/session.js +258 -0
  114. playwright/driver/package/lib/tools/dashboard/appIcon.png +0 -0
  115. playwright/driver/package/lib/tools/skills/playwright-cli/SKILL.md +420 -0
  116. playwright/driver/package/lib/tools/skills/playwright-cli/references/element-attributes.md +23 -0
  117. playwright/driver/package/lib/tools/skills/playwright-cli/references/playwright-tests.md +39 -0
  118. playwright/driver/package/lib/tools/skills/playwright-cli/references/request-mocking.md +87 -0
  119. playwright/driver/package/lib/tools/skills/playwright-cli/references/running-code.md +241 -0
  120. playwright/driver/package/lib/tools/skills/playwright-cli/references/session-management.md +225 -0
  121. playwright/driver/package/lib/tools/skills/playwright-cli/references/storage-state.md +275 -0
  122. playwright/driver/package/lib/tools/skills/playwright-cli/references/test-generation.md +433 -0
  123. playwright/driver/package/lib/tools/skills/playwright-cli/references/tracing.md +139 -0
  124. playwright/driver/package/lib/tools/skills/playwright-cli/references/video-recording.md +143 -0
  125. playwright/driver/package/lib/tools/skills/playwright-component-testing/SKILL.md +143 -0
  126. playwright/driver/package/lib/tools/skills/playwright-component-testing/references/gallery-spec.md +144 -0
  127. playwright/driver/package/lib/tools/skills/playwright-component-testing/references/migration.md +85 -0
  128. playwright/driver/package/lib/tools/skills/playwright-component-testing/references/react.md +67 -0
  129. playwright/driver/package/lib/tools/skills/playwright-component-testing/references/vue.md +75 -0
  130. playwright/driver/package/lib/tools/skills/playwright-trace/SKILL.md +171 -0
  131. playwright/driver/package/lib/tools/utils/extension.js +101 -0
  132. playwright/driver/package/lib/tools/utils/socketConnection.js +108 -0
  133. playwright/driver/package/lib/utilsBundle.js +90764 -0
  134. playwright/driver/package/lib/utilsBundle.js.LICENSE +2179 -0
  135. playwright/driver/package/lib/vite/dashboard/assets/codicon-DCmgc-ay.ttf +0 -0
  136. playwright/driver/package/lib/vite/dashboard/assets/firefox-1bWoP6pv.svg +1 -0
  137. playwright/driver/package/lib/vite/dashboard/assets/firefox-beta-k3eOH_eK.svg +1 -0
  138. playwright/driver/package/lib/vite/dashboard/assets/firefox-nightly-Cp5nfeDT.svg +1 -0
  139. playwright/driver/package/lib/vite/dashboard/assets/index-CyWAfh-p.js +11 -0
  140. playwright/driver/package/lib/vite/dashboard/assets/index-DhC616m4.css +1 -0
  141. playwright/driver/package/lib/vite/dashboard/assets/safari-na3_-uQk.svg +1 -0
  142. playwright/driver/package/lib/vite/dashboard/index.html +29 -0
  143. playwright/driver/package/lib/vite/dashboard/playwright-logo.svg +24 -0
  144. playwright/driver/package/lib/vite/htmlReport/index.html +16 -0
  145. playwright/driver/package/lib/vite/htmlReport/report.css +2 -0
  146. playwright/driver/package/lib/vite/htmlReport/report.js +32 -0
  147. playwright/driver/package/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +1 -0
  148. playwright/driver/package/lib/vite/recorder/assets/codeMirrorModule-CwYYHbcZ.js +32 -0
  149. playwright/driver/package/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
  150. playwright/driver/package/lib/vite/recorder/assets/index-DYjdXIbE.js +129 -0
  151. playwright/driver/package/lib/vite/recorder/assets/index-l_lX622x.css +1 -0
  152. playwright/driver/package/lib/vite/recorder/index.html +29 -0
  153. playwright/driver/package/lib/vite/recorder/playwright-logo.svg +9 -0
  154. playwright/driver/package/lib/vite/traceViewer/assets/codeMirrorModule-By56iMx7.js +32 -0
  155. playwright/driver/package/lib/vite/traceViewer/assets/defaultSettingsView-B34OrIms.js +181 -0
  156. playwright/driver/package/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +1 -0
  157. playwright/driver/package/lib/vite/traceViewer/assets/xtermModule-COQkjINf.js +7 -0
  158. playwright/driver/package/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +1 -0
  159. playwright/driver/package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  160. playwright/driver/package/lib/vite/traceViewer/defaultSettingsView.BLFoOugd.css +1 -0
  161. playwright/driver/package/lib/vite/traceViewer/index.B_TqY17P.css +1 -0
  162. playwright/driver/package/lib/vite/traceViewer/index.Dl36UVQT.js +1 -0
  163. playwright/driver/package/lib/vite/traceViewer/index.html +44 -0
  164. playwright/driver/package/lib/vite/traceViewer/manifest.webmanifest +16 -0
  165. playwright/driver/package/lib/vite/traceViewer/playwright-logo.svg +9 -0
  166. playwright/driver/package/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +1 -0
  167. playwright/driver/package/lib/vite/traceViewer/snapshot.html +10 -0
  168. playwright/driver/package/lib/vite/traceViewer/sw.bundle.js +4 -0
  169. playwright/driver/package/lib/vite/traceViewer/uiMode.C7UW1sC9.css +1 -0
  170. playwright/driver/package/lib/vite/traceViewer/uiMode.D962mr9b.js +5 -0
  171. playwright/driver/package/lib/vite/traceViewer/uiMode.html +18 -0
  172. playwright/driver/package/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +1 -0
  173. playwright/driver/package/lib/webp_codec.LICENSE +173 -0
  174. playwright/driver/package/lib/webp_codec.wasm +0 -0
  175. playwright/driver/package/lib/xdg-open +1267 -0
  176. playwright/driver/package/package.json +34 -0
  177. playwright/driver/package/types/protocol.d.ts +24842 -0
  178. playwright/driver/package/types/structs.d.ts +47 -0
  179. playwright/driver/package/types/types.d.ts +26188 -0
  180. playwright/py.typed +0 -0
  181. playwright/sync_api/__init__.py +275 -0
  182. playwright/sync_api/_android_generated.py +494 -0
  183. playwright/sync_api/_context_manager.py +98 -0
  184. playwright/sync_api/_generated.py +24045 -0
  185. playwright_browserstack-1.62.0.dist-info/METADATA +82 -0
  186. playwright_browserstack-1.62.0.dist-info/RECORD +192 -0
  187. playwright_browserstack-1.62.0.dist-info/WHEEL +5 -0
  188. playwright_browserstack-1.62.0.dist-info/entry_points.txt +5 -0
  189. playwright_browserstack-1.62.0.dist-info/licenses/LICENSE +202 -0
  190. playwright_browserstack-1.62.0.dist-info/licenses/LICENSE.txt +51 -0
  191. playwright_browserstack-1.62.0.dist-info/licenses/NOTICE +18 -0
  192. playwright_browserstack-1.62.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,754 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import asyncio
16
+ import json
17
+ from pathlib import Path
18
+ from types import SimpleNamespace
19
+ from typing import (
20
+ TYPE_CHECKING,
21
+ Any,
22
+ Callable,
23
+ Dict,
24
+ List,
25
+ Literal,
26
+ Optional,
27
+ Pattern,
28
+ Sequence,
29
+ Set,
30
+ Union,
31
+ cast,
32
+ )
33
+
34
+ from playwright._impl._api_structures import (
35
+ Cookie,
36
+ Geolocation,
37
+ SetCookieParam,
38
+ StorageState,
39
+ WebErrorLocation,
40
+ )
41
+ from playwright._impl._cdp_session import CDPSession
42
+ from playwright._impl._clock import Clock
43
+ from playwright._impl._connection import (
44
+ ChannelOwner,
45
+ from_channel,
46
+ from_nullable_channel,
47
+ )
48
+ from playwright._impl._console_message import ConsoleMessage
49
+ from playwright._impl._credentials import Credentials
50
+ from playwright._impl._debugger import Debugger
51
+ from playwright._impl._dialog import Dialog
52
+ from playwright._impl._disposable import Disposable, DisposableStub
53
+ from playwright._impl._errors import Error, TargetClosedError
54
+ from playwright._impl._event_context_manager import EventContextManagerImpl
55
+ from playwright._impl._fetch import APIRequestContext
56
+ from playwright._impl._frame import Frame
57
+ from playwright._impl._har_router import HarRouter
58
+ from playwright._impl._helper import (
59
+ HarContentPolicy,
60
+ HarMode,
61
+ RouteFromHarNotFoundPolicy,
62
+ RouteHandler,
63
+ RouteHandlerCallback,
64
+ TimeoutSettings,
65
+ URLMatch,
66
+ WebSocketRouteHandlerCallback,
67
+ async_readfile,
68
+ async_writefile,
69
+ create_task_and_ignore_exception,
70
+ locals_to_params,
71
+ parse_error,
72
+ to_impl,
73
+ )
74
+ from playwright._impl._network import (
75
+ Request,
76
+ Response,
77
+ Route,
78
+ WebSocketRoute,
79
+ WebSocketRouteHandler,
80
+ serialize_headers,
81
+ )
82
+ from playwright._impl._page import BindingCall, Page, Worker
83
+ from playwright._impl._str_utils import escape_regex_flags
84
+ from playwright._impl._tracing import Tracing
85
+ from playwright._impl._waiter import Waiter
86
+ from playwright._impl._web_error import WebError
87
+
88
+ if TYPE_CHECKING: # pragma: no cover
89
+ from playwright._impl._browser import Browser
90
+
91
+
92
+ class BrowserContext(ChannelOwner):
93
+ Events = SimpleNamespace(
94
+ # Deprecated in v1.56, never emitted anymore.
95
+ BackgroundPage="backgroundpage",
96
+ Close="close",
97
+ Console="console",
98
+ Dialog="dialog",
99
+ Download="download",
100
+ FrameAttached="frameattached",
101
+ FrameDetached="framedetached",
102
+ FrameNavigated="framenavigated",
103
+ Page="page",
104
+ PageClose="pageclose",
105
+ PageLoad="pageload",
106
+ WebError="weberror",
107
+ ServiceWorker="serviceworker",
108
+ Request="request",
109
+ Response="response",
110
+ RequestFailed="requestfailed",
111
+ RequestFinished="requestfinished",
112
+ )
113
+
114
+ def __init__(
115
+ self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
116
+ ) -> None:
117
+ super().__init__(parent, type, guid, initializer)
118
+ # Browser is null for browser contexts created outside of normal browser, e.g. android or electron.
119
+ # circular import workaround:
120
+ self._browser: Optional["Browser"] = None
121
+ if parent.__class__.__name__ == "Browser":
122
+ self._browser = cast("Browser", parent)
123
+ self._pages: List[Page] = []
124
+ self._routes: List[RouteHandler] = []
125
+ self._web_socket_routes: List[WebSocketRouteHandler] = []
126
+ self._bindings: Dict[str, Any] = {}
127
+ self._timeout_settings = TimeoutSettings(None)
128
+ self._owner_page: Optional[Page] = None
129
+ self._options: Dict[str, Any] = initializer["options"]
130
+ self._service_workers: Set[Worker] = set()
131
+ self._base_url: Optional[str] = self._options.get("baseURL")
132
+ self._videos_dir: Optional[str] = self._options.get("recordVideo")
133
+ self._tracing = cast(Tracing, from_channel(initializer["tracing"]))
134
+ self._debugger: Debugger = cast(Debugger, from_channel(initializer["debugger"]))
135
+ self._request: APIRequestContext = from_channel(initializer["requestContext"])
136
+ self._request._timeout_settings = self._timeout_settings
137
+ self._clock = Clock(self)
138
+ self._credentials = Credentials(self)
139
+ self._channel.on(
140
+ "bindingCall",
141
+ lambda params: self._on_binding(from_channel(params["binding"])),
142
+ )
143
+ self._channel.on("close", lambda _: self._on_close())
144
+ self._channel.on(
145
+ "page", lambda params: self._on_page(from_channel(params["page"]))
146
+ )
147
+ self._channel.on(
148
+ "route",
149
+ lambda params: self._loop.create_task(
150
+ self._on_route(
151
+ from_channel(params.get("route")),
152
+ )
153
+ ),
154
+ )
155
+ self._channel.on(
156
+ "webSocketRoute",
157
+ lambda params: self._loop.create_task(
158
+ self._on_web_socket_route(
159
+ from_channel(params["webSocketRoute"]),
160
+ )
161
+ ),
162
+ )
163
+
164
+ self._channel.on(
165
+ "serviceWorker",
166
+ lambda params: self._on_service_worker(from_channel(params["worker"])),
167
+ )
168
+ self._channel.on(
169
+ "console",
170
+ lambda event: self._on_console_message(event),
171
+ )
172
+
173
+ self._channel.on(
174
+ "dialog", lambda params: self._on_dialog(from_channel(params["dialog"]))
175
+ )
176
+ self._channel.on(
177
+ "pageError",
178
+ lambda params: self._on_page_error(
179
+ parse_error(params["error"]["error"]),
180
+ from_nullable_channel(params["page"]),
181
+ cast(
182
+ WebErrorLocation,
183
+ params.get("location") or {"url": "", "line": 0, "column": 0},
184
+ ),
185
+ ),
186
+ )
187
+ self._channel.on(
188
+ "request",
189
+ lambda params: self._on_request(
190
+ from_channel(params["request"]),
191
+ from_nullable_channel(params.get("page")),
192
+ ),
193
+ )
194
+ self._channel.on(
195
+ "response",
196
+ lambda params: self._on_response(
197
+ from_channel(params["response"]),
198
+ from_nullable_channel(params.get("page")),
199
+ ),
200
+ )
201
+ self._channel.on(
202
+ "requestFailed",
203
+ lambda params: self._on_request_failed(
204
+ from_channel(params["request"]),
205
+ params["responseEndTiming"],
206
+ params.get("failureText"),
207
+ from_nullable_channel(params.get("page")),
208
+ ),
209
+ )
210
+ self._channel.on(
211
+ "requestFinished",
212
+ lambda params: self._on_request_finished(
213
+ from_channel(params["request"]),
214
+ from_nullable_channel(params.get("response")),
215
+ params["responseEndTiming"],
216
+ from_nullable_channel(params.get("page")),
217
+ ),
218
+ )
219
+ self._closed_future: asyncio.Future = asyncio.Future()
220
+ self.once(
221
+ self.Events.Close, lambda context: self._closed_future.set_result(True)
222
+ )
223
+ self._close_reason: Optional[str] = None
224
+ self._har_routers: List[HarRouter] = []
225
+ self._set_event_to_subscription_mapping(
226
+ {
227
+ BrowserContext.Events.Console: "console",
228
+ BrowserContext.Events.Dialog: "dialog",
229
+ BrowserContext.Events.Request: "request",
230
+ BrowserContext.Events.Response: "response",
231
+ BrowserContext.Events.RequestFinished: "requestFinished",
232
+ BrowserContext.Events.RequestFailed: "requestFailed",
233
+ }
234
+ )
235
+ self._closing_or_closed = False
236
+
237
+ def __repr__(self) -> str:
238
+ return f"<BrowserContext browser={self.browser}>"
239
+
240
+ def _on_page(self, page: Page) -> None:
241
+ self._pages.append(page)
242
+ self.emit(BrowserContext.Events.Page, page)
243
+ if page._opener and not page._opener.is_closed():
244
+ page._opener.emit(Page.Events.Popup, page)
245
+
246
+ async def _on_route(self, route: Route) -> None:
247
+ route._context = self
248
+ page = route.request._safe_page()
249
+ route_handlers = self._routes.copy()
250
+ for route_handler in route_handlers:
251
+ # If the page or the context was closed we stall all requests right away.
252
+ if (page and page._close_was_called) or self._closing_or_closed:
253
+ return
254
+ if not route_handler.matches(route.request.url):
255
+ continue
256
+ if route_handler not in self._routes:
257
+ continue
258
+ if route_handler.will_expire:
259
+ self._routes.remove(route_handler)
260
+ try:
261
+ handled = await route_handler.handle(route)
262
+ finally:
263
+ if len(self._routes) == 0:
264
+ create_task_and_ignore_exception(
265
+ self._loop,
266
+ self._connection.wrap_api_call(
267
+ lambda: self._update_interception_patterns(), True
268
+ ),
269
+ )
270
+ if handled:
271
+ return
272
+ try:
273
+ # If the page is closed or unrouteAll() was called without waiting and interception disabled,
274
+ # the method will throw an error - silence it.
275
+ await route._inner_continue(True)
276
+ except Exception:
277
+ pass
278
+
279
+ async def _on_web_socket_route(self, web_socket_route: WebSocketRoute) -> None:
280
+ route_handler = next(
281
+ (
282
+ route_handler
283
+ for route_handler in self._web_socket_routes
284
+ if route_handler.matches(web_socket_route.url)
285
+ ),
286
+ None,
287
+ )
288
+ if route_handler:
289
+ await route_handler.handle(web_socket_route)
290
+ else:
291
+ web_socket_route.connect_to_server()
292
+
293
+ def _on_binding(self, binding_call: BindingCall) -> None:
294
+ func = self._bindings.get(binding_call._initializer["name"])
295
+ if func is None:
296
+ return
297
+ asyncio.create_task(binding_call.call(func))
298
+
299
+ def set_default_navigation_timeout(self, timeout: float) -> None:
300
+ return self._set_default_navigation_timeout_impl(timeout)
301
+
302
+ def _set_default_navigation_timeout_impl(self, timeout: Optional[float]) -> None:
303
+ self._timeout_settings.set_default_navigation_timeout(timeout)
304
+
305
+ def set_default_timeout(self, timeout: float) -> None:
306
+ return self._set_default_timeout_impl(timeout)
307
+
308
+ def _set_default_timeout_impl(self, timeout: Optional[float]) -> None:
309
+ self._timeout_settings.set_default_timeout(timeout)
310
+
311
+ @property
312
+ def pages(self) -> List[Page]:
313
+ return self._pages.copy()
314
+
315
+ @property
316
+ def browser(self) -> Optional["Browser"]:
317
+ return self._browser
318
+
319
+ async def _initialize_har_from_options(
320
+ self,
321
+ record_har_path: Optional[Union[Path, str]],
322
+ record_har_content: Optional[HarContentPolicy],
323
+ record_har_omit_content: Optional[bool],
324
+ record_har_url_filter: Optional[Union[Pattern[str], str]],
325
+ record_har_mode: Optional[HarMode],
326
+ ) -> None:
327
+ if not record_har_path:
328
+ return
329
+ record_har_path = str(record_har_path)
330
+ default_policy: HarContentPolicy = (
331
+ "attach" if record_har_path.endswith(".zip") else "embed"
332
+ )
333
+ content_policy: HarContentPolicy = record_har_content or (
334
+ "omit" if record_har_omit_content is True else default_policy
335
+ )
336
+ await self._tracing._record_into_har(
337
+ har=record_har_path,
338
+ page=None,
339
+ url=record_har_url_filter,
340
+ update_content=content_policy,
341
+ update_mode=(record_har_mode or "full"),
342
+ )
343
+
344
+ async def new_page(self) -> Page:
345
+ if self._owner_page:
346
+ raise Error("Please use browser.new_context()")
347
+ return from_channel(await self._channel.send("newPage", None))
348
+
349
+ async def cookies(self, urls: Union[str, Sequence[str]] = None) -> List[Cookie]:
350
+ if urls is None:
351
+ urls = []
352
+ if isinstance(urls, str):
353
+ urls = [urls]
354
+ return await self._channel.send("cookies", None, dict(urls=urls))
355
+
356
+ async def add_cookies(self, cookies: Sequence[SetCookieParam]) -> None:
357
+ await self._channel.send("addCookies", None, dict(cookies=cookies))
358
+
359
+ async def clear_cookies(
360
+ self,
361
+ name: Union[str, Pattern[str]] = None,
362
+ domain: Union[str, Pattern[str]] = None,
363
+ path: Union[str, Pattern[str]] = None,
364
+ ) -> None:
365
+ await self._channel.send(
366
+ "clearCookies",
367
+ None,
368
+ {
369
+ "name": name if isinstance(name, str) else None,
370
+ "nameRegexSource": name.pattern if isinstance(name, Pattern) else None,
371
+ "nameRegexFlags": (
372
+ escape_regex_flags(name) if isinstance(name, Pattern) else None
373
+ ),
374
+ "domain": domain if isinstance(domain, str) else None,
375
+ "domainRegexSource": (
376
+ domain.pattern if isinstance(domain, Pattern) else None
377
+ ),
378
+ "domainRegexFlags": (
379
+ escape_regex_flags(domain) if isinstance(domain, Pattern) else None
380
+ ),
381
+ "path": path if isinstance(path, str) else None,
382
+ "pathRegexSource": path.pattern if isinstance(path, Pattern) else None,
383
+ "pathRegexFlags": (
384
+ escape_regex_flags(path) if isinstance(path, Pattern) else None
385
+ ),
386
+ },
387
+ )
388
+
389
+ async def grant_permissions(
390
+ self, permissions: Sequence[str], origin: str = None
391
+ ) -> None:
392
+ await self._channel.send("grantPermissions", None, locals_to_params(locals()))
393
+
394
+ async def clear_permissions(self) -> None:
395
+ await self._channel.send("clearPermissions", None)
396
+
397
+ async def set_geolocation(self, geolocation: Geolocation = None) -> None:
398
+ await self._channel.send("setGeolocation", None, locals_to_params(locals()))
399
+
400
+ async def set_extra_http_headers(self, headers: Dict[str, str]) -> None:
401
+ await self._channel.send(
402
+ "setExtraHTTPHeaders", None, dict(headers=serialize_headers(headers))
403
+ )
404
+
405
+ async def set_offline(self, offline: bool) -> None:
406
+ await self._channel.send("setOffline", None, dict(offline=offline))
407
+
408
+ async def add_init_script(
409
+ self, script: str = None, path: Union[str, Path] = None
410
+ ) -> Disposable:
411
+ if path:
412
+ script = (await async_readfile(path)).decode()
413
+ if not isinstance(script, str):
414
+ raise Error("Either path or script parameter must be specified")
415
+ return from_channel(
416
+ await self._channel.send("addInitScript", None, dict(source=script))
417
+ )
418
+
419
+ async def expose_binding(self, name: str, callback: Callable) -> Disposable:
420
+ for page in self._pages:
421
+ if name in page._bindings:
422
+ raise Error(
423
+ f'Function "{name}" has been already registered in one of the pages'
424
+ )
425
+ if name in self._bindings:
426
+ raise Error(f'Function "{name}" has been already registered')
427
+ self._bindings[name] = callback
428
+ return from_channel(
429
+ await self._channel.send("exposeBinding", None, dict(name=name))
430
+ )
431
+
432
+ async def expose_function(self, name: str, callback: Callable) -> Disposable:
433
+ return await self.expose_binding(name, lambda source, *args: callback(*args))
434
+
435
+ async def route(
436
+ self, url: URLMatch, handler: RouteHandlerCallback, times: int = None
437
+ ) -> DisposableStub:
438
+ self._routes.insert(
439
+ 0,
440
+ RouteHandler(
441
+ self._base_url,
442
+ url,
443
+ handler,
444
+ True if self._dispatcher_fiber else False,
445
+ times,
446
+ ),
447
+ )
448
+ await self._update_interception_patterns()
449
+ return DisposableStub(lambda: self.unroute(url, handler), self)
450
+
451
+ async def unroute(
452
+ self, url: URLMatch, handler: Optional[RouteHandlerCallback] = None
453
+ ) -> None:
454
+ removed = []
455
+ remaining = []
456
+ for route in self._routes:
457
+ if route.url != url or (handler and route.handler != handler):
458
+ remaining.append(route)
459
+ else:
460
+ removed.append(route)
461
+ await self._unroute_internal(removed, remaining, "default")
462
+
463
+ async def _unroute_internal(
464
+ self,
465
+ removed: List[RouteHandler],
466
+ remaining: List[RouteHandler],
467
+ behavior: Literal["default", "ignoreErrors", "wait"] = None,
468
+ ) -> None:
469
+ self._routes = remaining
470
+ if behavior is not None and behavior != "default":
471
+ await asyncio.gather(*map(lambda router: router.stop(behavior), removed)) # type: ignore
472
+ await self._update_interception_patterns()
473
+
474
+ async def route_web_socket(
475
+ self, url: URLMatch, handler: WebSocketRouteHandlerCallback
476
+ ) -> None:
477
+ self._web_socket_routes.insert(
478
+ 0,
479
+ WebSocketRouteHandler(self._base_url, url, handler),
480
+ )
481
+ await self._update_web_socket_interception_patterns()
482
+
483
+ def _dispose_har_routers(self) -> None:
484
+ for router in self._har_routers:
485
+ router.dispose()
486
+ self._har_routers = []
487
+
488
+ async def unroute_all(
489
+ self, behavior: Literal["default", "ignoreErrors", "wait"] = None
490
+ ) -> None:
491
+ await self._unroute_internal(self._routes, [], behavior)
492
+ self._dispose_har_routers()
493
+
494
+ async def route_from_har(
495
+ self,
496
+ har: Union[Path, str],
497
+ url: Union[Pattern[str], str] = None,
498
+ notFound: RouteFromHarNotFoundPolicy = None,
499
+ update: bool = None,
500
+ updateContent: Literal["attach", "embed"] = None,
501
+ updateMode: HarMode = None,
502
+ ) -> None:
503
+ if update:
504
+ await self._tracing._record_into_har(
505
+ har=har,
506
+ page=None,
507
+ url=url,
508
+ update_content=updateContent,
509
+ update_mode=updateMode,
510
+ )
511
+ return
512
+ router = await HarRouter.create(
513
+ local_utils=self._connection.local_utils,
514
+ file=str(har),
515
+ not_found_action=notFound or "abort",
516
+ url_matcher=url,
517
+ )
518
+ self._har_routers.append(router)
519
+ await router.add_context_route(self)
520
+
521
+ async def _update_interception_patterns(self) -> None:
522
+ patterns = RouteHandler.prepare_interception_patterns(self._routes)
523
+ await self._channel.send(
524
+ "setNetworkInterceptionPatterns", None, {"patterns": patterns}
525
+ )
526
+
527
+ async def _update_web_socket_interception_patterns(self) -> None:
528
+ patterns = WebSocketRouteHandler.prepare_interception_patterns(
529
+ self._web_socket_routes
530
+ )
531
+ await self._channel.send(
532
+ "setWebSocketInterceptionPatterns", None, {"patterns": patterns}
533
+ )
534
+
535
+ def expect_event(
536
+ self,
537
+ event: str,
538
+ predicate: Callable = None,
539
+ timeout: float = None,
540
+ ) -> EventContextManagerImpl:
541
+ if timeout is None:
542
+ timeout = self._timeout_settings.timeout()
543
+ waiter = Waiter(self, f"browser_context.expect_event({event})")
544
+ waiter.reject_on_timeout(
545
+ timeout, f'Timeout {timeout}ms exceeded while waiting for event "{event}"'
546
+ )
547
+ if event != BrowserContext.Events.Close:
548
+ waiter.reject_on_event(
549
+ self, BrowserContext.Events.Close, lambda: TargetClosedError()
550
+ )
551
+ waiter.wait_for_event(self, event, predicate)
552
+ return EventContextManagerImpl(waiter.result())
553
+
554
+ def _on_close(self) -> None:
555
+ self._closing_or_closed = True
556
+ if self._browser:
557
+ if self in self._browser._contexts:
558
+ self._browser._contexts.remove(self)
559
+ assert self._browser._browser_type is not None
560
+ if (
561
+ self
562
+ in self._browser._browser_type._playwright.selectors._contexts_for_selectors
563
+ ):
564
+ self._browser._browser_type._playwright.selectors._contexts_for_selectors.remove(
565
+ self
566
+ )
567
+
568
+ self._dispose_har_routers()
569
+ self._tracing._reset_stack_counter()
570
+ self.emit(BrowserContext.Events.Close, self)
571
+
572
+ def is_closed(self) -> bool:
573
+ return self._closing_or_closed
574
+
575
+ async def close(self, reason: str = None) -> None:
576
+ if self._closing_or_closed:
577
+ return
578
+ self._close_reason = reason
579
+ self._closing_or_closed = True
580
+
581
+ await self.request.dispose(reason=reason)
582
+
583
+ async def _inner_close() -> None:
584
+ await self._tracing._export_all_hars()
585
+
586
+ await self._channel._connection.wrap_api_call(_inner_close, True)
587
+ await self._channel.send("close", None, {"reason": reason})
588
+ await self._closed_future
589
+
590
+ async def storage_state(
591
+ self,
592
+ path: Union[str, Path] = None,
593
+ indexedDB: bool = None,
594
+ credentials: bool = None,
595
+ ) -> StorageState:
596
+ result = await self._channel.send_return_as_dict(
597
+ "storageState", None, {"indexedDB": indexedDB, "credentials": credentials}
598
+ )
599
+ if path:
600
+ await async_writefile(path, json.dumps(result))
601
+ return result
602
+
603
+ async def set_storage_state(
604
+ self, storageState: Union[StorageState, str, Path]
605
+ ) -> None:
606
+ if isinstance(storageState, (str, Path)):
607
+ state = json.loads(await async_readfile(storageState))
608
+ else:
609
+ state = storageState
610
+ await self._channel.send("setStorageState", None, {"storageState": state})
611
+
612
+ def _effective_close_reason(self) -> Optional[str]:
613
+ if self._close_reason:
614
+ return self._close_reason
615
+ if self._browser:
616
+ return self._browser._close_reason
617
+ return None
618
+
619
+ async def wait_for_event(
620
+ self, event: str, predicate: Callable = None, timeout: float = None
621
+ ) -> Any:
622
+ async with self.expect_event(event, predicate, timeout) as event_info:
623
+ pass
624
+ return await event_info
625
+
626
+ def expect_console_message(
627
+ self,
628
+ predicate: Callable[[ConsoleMessage], bool] = None,
629
+ timeout: float = None,
630
+ ) -> EventContextManagerImpl[ConsoleMessage]:
631
+ return self.expect_event(Page.Events.Console, predicate, timeout)
632
+
633
+ def expect_page(
634
+ self,
635
+ predicate: Callable[[Page], bool] = None,
636
+ timeout: float = None,
637
+ ) -> EventContextManagerImpl[Page]:
638
+ return self.expect_event(BrowserContext.Events.Page, predicate, timeout)
639
+
640
+ def _on_service_worker(self, worker: Worker) -> None:
641
+ worker._context = self
642
+ self._service_workers.add(worker)
643
+ self.emit(BrowserContext.Events.ServiceWorker, worker)
644
+
645
+ def _on_request_failed(
646
+ self,
647
+ request: Request,
648
+ response_end_timing: float,
649
+ failure_text: Optional[str],
650
+ page: Optional[Page],
651
+ ) -> None:
652
+ request._failure_text = failure_text
653
+ request._set_response_end_timing(response_end_timing)
654
+ self.emit(BrowserContext.Events.RequestFailed, request)
655
+ if page:
656
+ page.emit(Page.Events.RequestFailed, request)
657
+
658
+ def _on_request_finished(
659
+ self,
660
+ request: Request,
661
+ response: Optional[Response],
662
+ response_end_timing: float,
663
+ page: Optional[Page],
664
+ ) -> None:
665
+ request._set_response_end_timing(response_end_timing)
666
+ self.emit(BrowserContext.Events.RequestFinished, request)
667
+ if page:
668
+ page.emit(Page.Events.RequestFinished, request)
669
+ if response:
670
+ response._finished_future.set_result(True)
671
+
672
+ def _on_console_message(self, event: Dict) -> None:
673
+ message = ConsoleMessage(event, self._loop, self._dispatcher_fiber)
674
+ worker = message.worker
675
+ if worker:
676
+ worker.emit(Worker.Events.Console, message)
677
+ page = message.page
678
+ if page:
679
+ page.emit(Page.Events.Console, message)
680
+ self.emit(BrowserContext.Events.Console, message)
681
+
682
+ def _on_dialog(self, dialog: Dialog) -> None:
683
+ has_listeners = self.emit(BrowserContext.Events.Dialog, dialog)
684
+ page = dialog.page
685
+ if page:
686
+ has_listeners = page.emit(Page.Events.Dialog, dialog) or has_listeners
687
+ if not has_listeners:
688
+ # Although we do similar handling on the server side, we still need this logic
689
+ # on the client side due to a possible race condition between two async calls:
690
+ # a) removing "dialog" listener subscription (client->server)
691
+ # b) actual "dialog" event (server->client)
692
+ if dialog.type == "beforeunload":
693
+ create_task_and_ignore_exception(self._loop, dialog.accept())
694
+ else:
695
+ create_task_and_ignore_exception(self._loop, dialog.dismiss())
696
+
697
+ def _on_page_error(
698
+ self, error: Error, page: Optional[Page], location: WebErrorLocation
699
+ ) -> None:
700
+ self.emit(
701
+ BrowserContext.Events.WebError,
702
+ WebError(self._loop, self._dispatcher_fiber, page, error, location),
703
+ )
704
+ if page:
705
+ page.emit(Page.Events.PageError, error)
706
+
707
+ def _on_request(self, request: Request, page: Optional[Page]) -> None:
708
+ self.emit(BrowserContext.Events.Request, request)
709
+ if page:
710
+ page.emit(Page.Events.Request, request)
711
+
712
+ def _on_response(self, response: Response, page: Optional[Page]) -> None:
713
+ self.emit(BrowserContext.Events.Response, response)
714
+ if page:
715
+ page.emit(Page.Events.Response, response)
716
+
717
+ @property
718
+ def background_pages(self) -> List[Page]:
719
+ return []
720
+
721
+ @property
722
+ def service_workers(self) -> List[Worker]:
723
+ return list(self._service_workers)
724
+
725
+ async def new_cdp_session(self, page: Union[Page, Frame]) -> CDPSession:
726
+ page = to_impl(page)
727
+ params = {}
728
+ if isinstance(page, Page):
729
+ params["page"] = page._channel
730
+ elif isinstance(page, Frame):
731
+ params["frame"] = page._channel
732
+ else:
733
+ raise Error("page: expected Page or Frame")
734
+ return from_channel(await self._channel.send("newCDPSession", None, params))
735
+
736
+ @property
737
+ def tracing(self) -> Tracing:
738
+ return self._tracing
739
+
740
+ @property
741
+ def debugger(self) -> Debugger:
742
+ return self._debugger
743
+
744
+ @property
745
+ def request(self) -> "APIRequestContext":
746
+ return self._request
747
+
748
+ @property
749
+ def clock(self) -> Clock:
750
+ return self._clock
751
+
752
+ @property
753
+ def credentials(self) -> Credentials:
754
+ return self._credentials