playwright-browserstack 1.62.0__py3-none-win32.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,158 @@
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 inspect
16
+ from typing import Any, Callable, Dict, List, Optional, Sequence, Union
17
+
18
+ from playwright._impl._errors import Error
19
+ from playwright._impl._map import Map
20
+
21
+ API_ATTR = "_pw_api_instance_"
22
+ IMPL_ATTR = "_pw_impl_instance_"
23
+
24
+
25
+ class ImplWrapper:
26
+ def __init__(self, impl_obj: Any) -> None:
27
+ self._impl_obj = impl_obj
28
+
29
+ def __repr__(self) -> str:
30
+ return self._impl_obj.__repr__()
31
+
32
+
33
+ class ImplToApiMapping:
34
+ def __init__(self) -> None:
35
+ self._mapping: Dict[type, type] = {}
36
+
37
+ def register(self, impl_class: type, api_class: type) -> None:
38
+ self._mapping[impl_class] = api_class
39
+
40
+ def from_maybe_impl(
41
+ self, obj: Any, visited: Optional[Map[Any, Union[List, Dict]]] = None
42
+ ) -> Any:
43
+ # Python does share default arguments between calls, so we need to
44
+ # create a new map if it is not provided.
45
+ if not visited:
46
+ visited = Map()
47
+ if not obj:
48
+ return obj
49
+ if isinstance(obj, dict):
50
+ if obj in visited:
51
+ return visited[obj]
52
+ o: Dict = {}
53
+ visited[obj] = o
54
+ for name, value in obj.items():
55
+ o[name] = self.from_maybe_impl(value, visited)
56
+ return o
57
+ if isinstance(obj, list):
58
+ if obj in visited:
59
+ return visited[obj]
60
+ a: List = []
61
+ visited[obj] = a
62
+ for item in obj:
63
+ a.append(self.from_maybe_impl(item, visited))
64
+ return a
65
+ api_class = self._mapping.get(type(obj))
66
+ if api_class:
67
+ api_instance = getattr(obj, API_ATTR, None)
68
+ if not api_instance:
69
+ api_instance = api_class(obj)
70
+ setattr(obj, API_ATTR, api_instance)
71
+ return api_instance
72
+ else:
73
+ return obj
74
+
75
+ def from_impl(self, obj: Any) -> Any:
76
+ assert obj
77
+ result = self.from_maybe_impl(obj)
78
+ assert result
79
+ return result
80
+
81
+ def from_impl_nullable(self, obj: Any = None) -> Optional[Any]:
82
+ return self.from_impl(obj) if obj else None
83
+
84
+ def from_impl_list(self, items: Sequence[Any]) -> List[Any]:
85
+ return list(map(lambda a: self.from_impl(a), items))
86
+
87
+ def from_impl_dict(self, map: Dict[str, Any]) -> Dict[str, Any]:
88
+ return {name: self.from_impl(value) for name, value in map.items()}
89
+
90
+ def to_impl(
91
+ self, obj: Any, visited: Optional[Map[Any, Union[List, Dict]]] = None
92
+ ) -> Any:
93
+ if visited is None:
94
+ visited = Map()
95
+ try:
96
+ if not obj:
97
+ return obj
98
+ if isinstance(obj, dict):
99
+ if obj in visited:
100
+ return visited[obj]
101
+ o: Dict = {}
102
+ visited[obj] = o
103
+ for name, value in obj.items():
104
+ o[name] = self.to_impl(value, visited)
105
+ return o
106
+ if isinstance(obj, list):
107
+ if obj in visited:
108
+ return visited[obj]
109
+ a: List = []
110
+ visited[obj] = a
111
+ for item in obj:
112
+ a.append(self.to_impl(item, visited))
113
+ return a
114
+ if isinstance(obj, ImplWrapper):
115
+ return obj._impl_obj
116
+ return obj
117
+ except RecursionError:
118
+ raise Error("Maximum argument depth exceeded")
119
+
120
+ def wrap_handler(self, handler: Callable[..., Any]) -> Callable[..., None]:
121
+ def wrapper_func(*args: Any) -> Any:
122
+ parameters = inspect.signature(handler).parameters
123
+ has_varargs = any(
124
+ parameter.kind == inspect.Parameter.VAR_POSITIONAL
125
+ for parameter in parameters.values()
126
+ )
127
+ arg_count = (
128
+ len(args)
129
+ if has_varargs
130
+ else sum(
131
+ parameter.kind
132
+ in (
133
+ inspect.Parameter.POSITIONAL_ONLY,
134
+ inspect.Parameter.POSITIONAL_OR_KEYWORD,
135
+ )
136
+ for parameter in parameters.values()
137
+ )
138
+ )
139
+ return handler(
140
+ *list(map(lambda a: self.from_maybe_impl(a), args))[:arg_count]
141
+ )
142
+
143
+ if inspect.ismethod(handler):
144
+ wrapper = getattr(handler.__self__, IMPL_ATTR + handler.__name__, None)
145
+ if not wrapper:
146
+ wrapper = wrapper_func
147
+ setattr(
148
+ handler.__self__,
149
+ IMPL_ATTR + handler.__name__,
150
+ wrapper,
151
+ )
152
+ return wrapper
153
+
154
+ wrapper = getattr(handler, IMPL_ATTR, None)
155
+ if not wrapper:
156
+ wrapper = wrapper_func
157
+ setattr(handler, IMPL_ATTR, wrapper)
158
+ return wrapper
@@ -0,0 +1,111 @@
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
+ from playwright._impl._connection import Channel
16
+ from playwright._impl._helper import MouseButton, locals_to_params
17
+
18
+
19
+ class Keyboard:
20
+ def __init__(self, channel: Channel) -> None:
21
+ self._channel = channel
22
+ self._loop = channel._connection._loop
23
+ self._dispatcher_fiber = channel._connection._dispatcher_fiber
24
+
25
+ async def down(self, key: str) -> None:
26
+ await self._channel.send("keyboardDown", None, locals_to_params(locals()))
27
+
28
+ async def up(self, key: str) -> None:
29
+ await self._channel.send("keyboardUp", None, locals_to_params(locals()))
30
+
31
+ async def insert_text(self, text: str) -> None:
32
+ await self._channel.send("keyboardInsertText", None, locals_to_params(locals()))
33
+
34
+ async def type(self, text: str, delay: float = None) -> None:
35
+ await self._channel.send("keyboardType", None, locals_to_params(locals()))
36
+
37
+ async def press(self, key: str, delay: float = None) -> None:
38
+ await self._channel.send("keyboardPress", None, locals_to_params(locals()))
39
+
40
+
41
+ class Mouse:
42
+ def __init__(self, channel: Channel) -> None:
43
+ self._channel = channel
44
+ self._loop = channel._connection._loop
45
+ self._dispatcher_fiber = channel._connection._dispatcher_fiber
46
+
47
+ async def move(self, x: float, y: float, steps: int = None) -> None:
48
+ await self._channel.send("mouseMove", None, locals_to_params(locals()))
49
+
50
+ async def down(
51
+ self,
52
+ button: MouseButton = None,
53
+ clickCount: int = None,
54
+ ) -> None:
55
+ await self._channel.send("mouseDown", None, locals_to_params(locals()))
56
+
57
+ async def up(
58
+ self,
59
+ button: MouseButton = None,
60
+ clickCount: int = None,
61
+ ) -> None:
62
+ await self._channel.send("mouseUp", None, locals_to_params(locals()))
63
+
64
+ async def _click(
65
+ self,
66
+ x: float,
67
+ y: float,
68
+ delay: float = None,
69
+ button: MouseButton = None,
70
+ clickCount: int = None,
71
+ title: str = None,
72
+ ) -> None:
73
+ await self._channel.send(
74
+ "mouseClick", None, locals_to_params(locals()), title=title
75
+ )
76
+
77
+ async def click(
78
+ self,
79
+ x: float,
80
+ y: float,
81
+ delay: float = None,
82
+ button: MouseButton = None,
83
+ clickCount: int = None,
84
+ ) -> None:
85
+ params = locals()
86
+ del params["self"]
87
+ await self._click(**params)
88
+
89
+ async def dblclick(
90
+ self,
91
+ x: float,
92
+ y: float,
93
+ delay: float = None,
94
+ button: MouseButton = None,
95
+ ) -> None:
96
+ await self._click(
97
+ x, y, delay=delay, button=button, clickCount=2, title="Double click"
98
+ )
99
+
100
+ async def wheel(self, deltaX: float, deltaY: float) -> None:
101
+ await self._channel.send("mouseWheel", None, locals_to_params(locals()))
102
+
103
+
104
+ class Touchscreen:
105
+ def __init__(self, channel: Channel) -> None:
106
+ self._channel = channel
107
+ self._loop = channel._connection._loop
108
+ self._dispatcher_fiber = channel._connection._dispatcher_fiber
109
+
110
+ async def tap(self, x: float, y: float) -> None:
111
+ await self._channel.send("touchscreenTap", None, locals_to_params(locals()))
@@ -0,0 +1,336 @@
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 base64
16
+ import collections.abc
17
+ import datetime
18
+ import math
19
+ import struct
20
+ import traceback
21
+ from pathlib import Path
22
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
23
+ from urllib.parse import ParseResult, urlparse, urlunparse
24
+
25
+ from playwright._impl._connection import Channel, ChannelOwner, from_channel
26
+ from playwright._impl._errors import Error, is_target_closed_error
27
+ from playwright._impl._map import Map
28
+
29
+ if TYPE_CHECKING: # pragma: no cover
30
+ from playwright._impl._element_handle import ElementHandle
31
+
32
+
33
+ Serializable = Any
34
+
35
+
36
+ class VisitorInfo:
37
+ visited: Map[Any, int]
38
+ last_id: int
39
+
40
+ def __init__(self) -> None:
41
+ self.visited = Map()
42
+ self.last_id = 0
43
+
44
+ def visit(self, obj: Any) -> int:
45
+ assert obj not in self.visited
46
+ self.last_id += 1
47
+ self.visited[obj] = self.last_id
48
+ return self.last_id
49
+
50
+
51
+ class JSHandle(ChannelOwner):
52
+ def __init__(
53
+ self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
54
+ ) -> None:
55
+ super().__init__(parent, type, guid, initializer)
56
+ self._preview = self._initializer["preview"]
57
+ self._channel.on(
58
+ "previewUpdated", lambda params: self._on_preview_updated(params["preview"])
59
+ )
60
+
61
+ def __repr__(self) -> str:
62
+ return f"<JSHandle preview={self._preview}>"
63
+
64
+ def __str__(self) -> str:
65
+ return self._preview
66
+
67
+ def _on_preview_updated(self, preview: str) -> None:
68
+ self._preview = preview
69
+
70
+ async def evaluate(self, expression: str, arg: Serializable = None) -> Any:
71
+ return parse_result(
72
+ await self._channel.send(
73
+ "evaluateExpression",
74
+ None,
75
+ dict(
76
+ expression=expression,
77
+ arg=serialize_argument(arg),
78
+ ),
79
+ )
80
+ )
81
+
82
+ async def evaluate_handle(
83
+ self, expression: str, arg: Serializable = None
84
+ ) -> "JSHandle":
85
+ return from_channel(
86
+ await self._channel.send(
87
+ "evaluateExpressionHandle",
88
+ None,
89
+ dict(
90
+ expression=expression,
91
+ arg=serialize_argument(arg),
92
+ ),
93
+ )
94
+ )
95
+
96
+ async def get_property(self, propertyName: str) -> "JSHandle":
97
+ return from_channel(
98
+ await self._channel.send("getProperty", None, dict(name=propertyName))
99
+ )
100
+
101
+ async def get_properties(self) -> Dict[str, "JSHandle"]:
102
+ return {
103
+ prop["name"]: from_channel(prop["value"])
104
+ for prop in await self._channel.send(
105
+ "getPropertyList",
106
+ None,
107
+ )
108
+ }
109
+
110
+ def as_element(self) -> Optional["ElementHandle"]:
111
+ return None
112
+
113
+ async def dispose(self) -> None:
114
+ try:
115
+ await self._channel.send(
116
+ "dispose",
117
+ None,
118
+ )
119
+ except Exception as e:
120
+ if not is_target_closed_error(e):
121
+ raise e
122
+
123
+ async def json_value(self) -> Any:
124
+ return parse_result(
125
+ await self._channel.send(
126
+ "jsonValue",
127
+ None,
128
+ )
129
+ )
130
+
131
+
132
+ def serialize_value(
133
+ value: Any, handles: List[Channel], visitor_info: Optional[VisitorInfo] = None
134
+ ) -> Any:
135
+ if visitor_info is None:
136
+ visitor_info = VisitorInfo()
137
+ if isinstance(value, JSHandle):
138
+ h = len(handles)
139
+ handles.append(value._channel)
140
+ return dict(h=h)
141
+ if value is None:
142
+ return dict(v="null")
143
+ if isinstance(value, float):
144
+ if value == float("inf"):
145
+ return dict(v="Infinity")
146
+ if value == float("-inf"):
147
+ return dict(v="-Infinity")
148
+ if value == float("-0"):
149
+ return dict(v="-0")
150
+ if math.isnan(value):
151
+ return dict(v="NaN")
152
+ if isinstance(value, datetime.datetime):
153
+ # Node.js Date objects are always in UTC.
154
+ return {
155
+ "d": datetime.datetime.strftime(
156
+ value.astimezone(datetime.timezone.utc), "%Y-%m-%dT%H:%M:%S.%fZ"
157
+ )
158
+ }
159
+ if isinstance(value, Exception):
160
+ return {
161
+ "e": {
162
+ "m": str(value),
163
+ "n": (
164
+ (value.name or "")
165
+ if isinstance(value, Error)
166
+ else value.__class__.__name__
167
+ ),
168
+ "s": (
169
+ (value.stack or "")
170
+ if isinstance(value, Error)
171
+ else "".join(
172
+ traceback.format_exception(type(value), value=value, tb=None)
173
+ )
174
+ ),
175
+ }
176
+ }
177
+ if isinstance(value, bool):
178
+ return {"b": value}
179
+ if isinstance(value, (int, float)):
180
+ return {"n": value}
181
+ if isinstance(value, str):
182
+ return {"s": value}
183
+ if isinstance(value, ParseResult):
184
+ return {"u": urlunparse(value)}
185
+
186
+ if value in visitor_info.visited:
187
+ return dict(ref=visitor_info.visited[value])
188
+
189
+ if isinstance(value, collections.abc.Sequence) and not isinstance(value, str):
190
+ id = visitor_info.visit(value)
191
+ a = []
192
+ for e in value:
193
+ a.append(serialize_value(e, handles, visitor_info))
194
+ return dict(a=a, id=id)
195
+
196
+ if isinstance(value, dict):
197
+ id = visitor_info.visit(value)
198
+ o = []
199
+ for name in value:
200
+ o.append(
201
+ {"k": name, "v": serialize_value(value[name], handles, visitor_info)}
202
+ )
203
+ return dict(o=o, id=id)
204
+ return dict(v="undefined")
205
+
206
+
207
+ def serialize_argument(arg: Serializable = None) -> Any:
208
+ handles: List[Channel] = []
209
+ value = serialize_value(arg, handles)
210
+ return dict(value=value, handles=handles)
211
+
212
+
213
+ def parse_value(value: Any, refs: Optional[Dict[int, Any]] = None) -> Any:
214
+ if refs is None:
215
+ refs = {}
216
+ if value is None:
217
+ return None
218
+ if isinstance(value, dict):
219
+ if "ref" in value:
220
+ return refs[value["ref"]]
221
+
222
+ if "v" in value:
223
+ v = value["v"]
224
+ if v == "Infinity":
225
+ return float("inf")
226
+ if v == "-Infinity":
227
+ return float("-inf")
228
+ if v == "-0":
229
+ return float("-0")
230
+ if v == "NaN":
231
+ return float("nan")
232
+ if v == "undefined":
233
+ return None
234
+ if v == "null":
235
+ return None
236
+ return v
237
+
238
+ if "u" in value:
239
+ return urlparse(value["u"])
240
+
241
+ if "bi" in value:
242
+ return int(value["bi"])
243
+
244
+ if "e" in value:
245
+ error = Error(value["e"]["m"])
246
+ error._name = value["e"]["n"]
247
+ error._stack = value["e"]["s"]
248
+ return error
249
+
250
+ if "a" in value:
251
+ a: List = []
252
+ refs[value["id"]] = a
253
+ for e in value["a"]:
254
+ a.append(parse_value(e, refs))
255
+ return a
256
+
257
+ if "d" in value:
258
+ # Node.js Date objects are always in UTC.
259
+ return datetime.datetime.strptime(
260
+ value["d"], "%Y-%m-%dT%H:%M:%S.%fZ"
261
+ ).replace(tzinfo=datetime.timezone.utc)
262
+
263
+ if "o" in value:
264
+ o: Dict = {}
265
+ refs[value["id"]] = o
266
+ for e in value["o"]:
267
+ o[e["k"]] = parse_value(e["v"], refs)
268
+ return o
269
+
270
+ if "n" in value:
271
+ return value["n"]
272
+
273
+ if "s" in value:
274
+ return value["s"]
275
+
276
+ if "b" in value:
277
+ return value["b"]
278
+
279
+ if "ta" in value:
280
+ encoded_bytes = value["ta"]["b"]
281
+ decoded_bytes = base64.b64decode(encoded_bytes)
282
+ array_type = value["ta"]["k"]
283
+ if array_type == "i8":
284
+ word_size = 1
285
+ fmt = "b"
286
+ elif array_type == "ui8" or array_type == "ui8c":
287
+ word_size = 1
288
+ fmt = "B"
289
+ elif array_type == "i16":
290
+ word_size = 2
291
+ fmt = "h"
292
+ elif array_type == "ui16":
293
+ word_size = 2
294
+ fmt = "H"
295
+ elif array_type == "i32":
296
+ word_size = 4
297
+ fmt = "i"
298
+ elif array_type == "ui32":
299
+ word_size = 4
300
+ fmt = "I"
301
+ elif array_type == "f32":
302
+ word_size = 4
303
+ fmt = "f"
304
+ elif array_type == "f64":
305
+ word_size = 8
306
+ fmt = "d"
307
+ elif array_type == "bi64":
308
+ word_size = 8
309
+ fmt = "q"
310
+ elif array_type == "bui64":
311
+ word_size = 8
312
+ fmt = "Q"
313
+ else:
314
+ raise ValueError(f"Unsupported array type: {array_type}")
315
+
316
+ byte_len = len(decoded_bytes)
317
+ if byte_len % word_size != 0:
318
+ raise ValueError(
319
+ f"Decoded bytes length {byte_len} is not a multiple of word size {word_size}"
320
+ )
321
+
322
+ if byte_len == 0:
323
+ return []
324
+ array_len = byte_len // word_size
325
+ # "<" denotes little-endian
326
+ format_string = f"<{array_len}{fmt}"
327
+ return list(struct.unpack(format_string, decoded_bytes))
328
+ return value
329
+
330
+
331
+ def parse_result(result: Any) -> Any:
332
+ return parse_value(result)
333
+
334
+
335
+ def add_source_url_to_script(source: str, path: Union[str, Path]) -> str:
336
+ return source + "\n//# sourceURL=" + str(path).replace("\n", "")
@@ -0,0 +1,97 @@
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 logging
17
+ from typing import Dict, Optional, cast
18
+
19
+ from pyee.asyncio import AsyncIOEventEmitter
20
+
21
+ from playwright._impl._connection import Channel
22
+ from playwright._impl._errors import TargetClosedError
23
+ from playwright._impl._helper import Error, ParsedMessagePayload
24
+ from playwright._impl._transport import Transport
25
+
26
+ _logger = logging.getLogger(__name__)
27
+
28
+
29
+ class JsonPipeTransport(AsyncIOEventEmitter, Transport):
30
+ def __init__(
31
+ self,
32
+ loop: asyncio.AbstractEventLoop,
33
+ pipe_channel: Channel,
34
+ ) -> None:
35
+ super().__init__(loop)
36
+ Transport.__init__(self, loop)
37
+ self._stop_requested = False
38
+ self._pipe_channel = pipe_channel
39
+
40
+ def request_stop(self) -> None:
41
+ self._stop_requested = True
42
+ self._pipe_channel.send_no_reply("close", None, {})
43
+
44
+ def dispose(self) -> None:
45
+ self.on_error_future.cancel()
46
+ self._stopped_future.cancel()
47
+
48
+ async def wait_until_stopped(self) -> None:
49
+ await self._stopped_future
50
+
51
+ async def connect(self) -> None:
52
+ self._stopped_future: asyncio.Future = asyncio.Future()
53
+
54
+ def handle_message(message: Dict) -> None:
55
+ if self._stop_requested:
56
+ return
57
+ self.on_message(cast(ParsedMessagePayload, message))
58
+
59
+ def handle_closed(reason: Optional[str]) -> None:
60
+ # Set the close error before notifying listeners, so a listener
61
+ # that raises cannot stop callers from observing the reason.
62
+ if reason and not self.on_error_future.done():
63
+ self.on_error_future.set_exception(TargetClosedError(reason))
64
+ try:
65
+ self.emit("close", reason)
66
+ except Exception:
67
+ # Never propagate a listener's exception into _stopped_future:
68
+ # run() and wait_until_stopped() await it, and
69
+ # Connection.stop_async() awaits it *before* cleanup(), so
70
+ # resolving it with an exception would skip cleanup entirely
71
+ # and surface as an unretrieved exception from the bare
72
+ # create_task(connection.run()).
73
+ _logger.exception("Error in JsonPipeTransport close listener")
74
+ finally:
75
+ # Guarded because "closed" can arrive more than once (e.g. a
76
+ # server-initiated close racing request_stop()); an
77
+ # unguarded set_result raised InvalidStateError, leaving
78
+ # run() awaiting a future nothing would ever resolve.
79
+ if not self._stopped_future.done():
80
+ self._stopped_future.set_result(None)
81
+
82
+ self._pipe_channel.on(
83
+ "message",
84
+ lambda params: handle_message(params["message"]),
85
+ )
86
+ self._pipe_channel.on(
87
+ "closed",
88
+ lambda params: handle_closed(params.get("reason")),
89
+ )
90
+
91
+ async def run(self) -> None:
92
+ await self._stopped_future
93
+
94
+ def send(self, message: Dict) -> None:
95
+ if self._stop_requested:
96
+ raise Error("Playwright connection closed")
97
+ self._pipe_channel.send_no_reply("send", None, {"message": message})