osn-selenium 0.0.0__py3-none-any.whl → 1.1.0__py3-none-any.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 (635) hide show
  1. osn_selenium/_base_models.py +41 -0
  2. osn_selenium/_cdp_import.py +253 -0
  3. osn_selenium/_functions.py +84 -0
  4. osn_selenium/_typehints.py +19 -0
  5. osn_selenium/abstract/executors/cdp/__init__.py +435 -0
  6. osn_selenium/abstract/executors/cdp/accessibility.py +62 -0
  7. osn_selenium/abstract/executors/cdp/animation.py +47 -0
  8. osn_selenium/abstract/executors/cdp/audits.py +39 -0
  9. osn_selenium/abstract/executors/cdp/autofill.py +34 -0
  10. osn_selenium/abstract/executors/cdp/background_service.py +22 -0
  11. osn_selenium/abstract/executors/cdp/bluetooth_emulation.py +95 -0
  12. osn_selenium/abstract/executors/cdp/browser.py +122 -0
  13. osn_selenium/abstract/executors/cdp/cache_storage.py +49 -0
  14. osn_selenium/abstract/executors/cdp/cast.py +31 -0
  15. osn_selenium/abstract/executors/cdp/console.py +18 -0
  16. osn_selenium/abstract/executors/cdp/css.py +197 -0
  17. osn_selenium/abstract/executors/cdp/debugger.py +198 -0
  18. osn_selenium/abstract/executors/cdp/device_access.py +22 -0
  19. osn_selenium/abstract/executors/cdp/device_orientation.py +14 -0
  20. osn_selenium/abstract/executors/cdp/dom.py +305 -0
  21. osn_selenium/abstract/executors/cdp/dom_debugger.py +57 -0
  22. osn_selenium/abstract/executors/cdp/dom_snapshot.py +42 -0
  23. osn_selenium/abstract/executors/cdp/dom_storage.py +31 -0
  24. osn_selenium/abstract/executors/cdp/emulation.py +259 -0
  25. osn_selenium/abstract/executors/cdp/event_breakpoints.py +18 -0
  26. osn_selenium/abstract/executors/cdp/extensions.py +31 -0
  27. osn_selenium/abstract/executors/cdp/fed_cm.py +35 -0
  28. osn_selenium/abstract/executors/cdp/fetch.py +76 -0
  29. osn_selenium/abstract/executors/cdp/file_system.py +11 -0
  30. osn_selenium/abstract/executors/cdp/headless_experimental.py +30 -0
  31. osn_selenium/abstract/executors/cdp/heap_profiler.py +73 -0
  32. osn_selenium/abstract/executors/cdp/indexed_db.py +99 -0
  33. osn_selenium/abstract/executors/cdp/input.py +158 -0
  34. osn_selenium/abstract/executors/cdp/inspector.py +14 -0
  35. osn_selenium/abstract/executors/cdp/io.py +24 -0
  36. osn_selenium/abstract/executors/cdp/layer_tree.py +61 -0
  37. osn_selenium/abstract/executors/cdp/log.py +27 -0
  38. osn_selenium/abstract/executors/cdp/media.py +14 -0
  39. osn_selenium/abstract/executors/cdp/memory.py +61 -0
  40. osn_selenium/abstract/executors/cdp/network.py +252 -0
  41. osn_selenium/abstract/executors/cdp/overlay.py +166 -0
  42. osn_selenium/abstract/executors/cdp/page.py +347 -0
  43. osn_selenium/abstract/executors/cdp/performance.py +28 -0
  44. osn_selenium/abstract/executors/cdp/performance_timeline.py +11 -0
  45. osn_selenium/abstract/executors/cdp/preload.py +14 -0
  46. osn_selenium/abstract/executors/cdp/profiler.py +54 -0
  47. osn_selenium/abstract/executors/cdp/pwa.py +46 -0
  48. osn_selenium/abstract/executors/cdp/runtime.py +176 -0
  49. osn_selenium/abstract/executors/cdp/schema.py +11 -0
  50. osn_selenium/abstract/executors/cdp/security.py +26 -0
  51. osn_selenium/abstract/executors/cdp/service_worker.py +54 -0
  52. osn_selenium/abstract/executors/cdp/storage.py +175 -0
  53. osn_selenium/abstract/executors/cdp/system_info.py +24 -0
  54. osn_selenium/abstract/executors/cdp/target.py +125 -0
  55. osn_selenium/abstract/executors/cdp/tethering.py +14 -0
  56. osn_selenium/abstract/executors/cdp/tracing.py +48 -0
  57. osn_selenium/abstract/executors/cdp/web_audio.py +19 -0
  58. osn_selenium/abstract/executors/cdp/web_authn.py +76 -0
  59. osn_selenium/abstract/executors/cdp.py +63 -0
  60. osn_selenium/abstract/executors/javascript.py +203 -0
  61. osn_selenium/abstract/instances/action_chains/__init__.py +12 -0
  62. osn_selenium/abstract/instances/action_chains/base.py +25 -0
  63. osn_selenium/abstract/instances/action_chains/click.py +93 -0
  64. osn_selenium/abstract/instances/action_chains/drag_and_drop.py +46 -0
  65. osn_selenium/abstract/instances/action_chains/hm_keyboard.py +44 -0
  66. osn_selenium/abstract/instances/action_chains/hm_move.py +104 -0
  67. osn_selenium/abstract/instances/action_chains/hm_scroll.py +75 -0
  68. osn_selenium/abstract/instances/action_chains/keyboard.py +79 -0
  69. osn_selenium/abstract/instances/action_chains/move.py +60 -0
  70. osn_selenium/abstract/instances/action_chains/scroll.py +61 -0
  71. osn_selenium/abstract/instances/action_chains/utils.py +44 -0
  72. osn_selenium/abstract/instances/alert.py +67 -0
  73. osn_selenium/abstract/instances/browser.py +76 -0
  74. osn_selenium/abstract/instances/browsing_context.py +310 -0
  75. osn_selenium/abstract/instances/dialog.py +107 -0
  76. osn_selenium/abstract/instances/fedcm.py +133 -0
  77. osn_selenium/abstract/instances/mobile.py +79 -0
  78. osn_selenium/abstract/instances/network.py +100 -0
  79. osn_selenium/abstract/instances/permissions.py +52 -0
  80. osn_selenium/abstract/instances/script.py +109 -0
  81. osn_selenium/abstract/instances/shadow_root.py +81 -0
  82. osn_selenium/abstract/instances/storage.py +98 -0
  83. osn_selenium/abstract/instances/switch_to.py +104 -0
  84. osn_selenium/abstract/instances/web_driver_wait.py +57 -0
  85. osn_selenium/abstract/instances/web_element.py +395 -0
  86. osn_selenium/abstract/instances/web_extension.py +70 -0
  87. osn_selenium/abstract/webdriver/blink/__init__.py +18 -0
  88. osn_selenium/abstract/webdriver/blink/base.py +80 -0
  89. osn_selenium/abstract/webdriver/blink/casting.py +82 -0
  90. osn_selenium/abstract/webdriver/blink/features.py +51 -0
  91. osn_selenium/abstract/webdriver/blink/lifecycle.py +76 -0
  92. osn_selenium/abstract/webdriver/blink/logging.py +40 -0
  93. osn_selenium/abstract/webdriver/blink/network.py +45 -0
  94. osn_selenium/abstract/webdriver/blink/settings.py +68 -0
  95. osn_selenium/abstract/webdriver/chrome/__init__.py +18 -0
  96. osn_selenium/abstract/webdriver/chrome/base.py +36 -0
  97. osn_selenium/abstract/webdriver/chrome/lifecycle.py +92 -0
  98. osn_selenium/abstract/webdriver/chrome/settings.py +110 -0
  99. osn_selenium/abstract/webdriver/core/__init__.py +16 -0
  100. osn_selenium/abstract/webdriver/core/actions.py +58 -0
  101. osn_selenium/abstract/webdriver/core/auth.py +145 -0
  102. osn_selenium/abstract/webdriver/core/base.py +298 -0
  103. osn_selenium/abstract/webdriver/core/capture.py +84 -0
  104. osn_selenium/abstract/webdriver/core/components.py +82 -0
  105. osn_selenium/abstract/webdriver/core/devtools.py +69 -0
  106. osn_selenium/abstract/webdriver/core/element.py +55 -0
  107. osn_selenium/abstract/webdriver/core/file.py +82 -0
  108. osn_selenium/abstract/webdriver/core/lifecycle.py +103 -0
  109. osn_selenium/abstract/webdriver/core/navigation.py +65 -0
  110. osn_selenium/abstract/webdriver/core/script.py +88 -0
  111. osn_selenium/abstract/webdriver/core/settings.py +43 -0
  112. osn_selenium/abstract/webdriver/core/storage.py +81 -0
  113. osn_selenium/abstract/webdriver/core/timeouts.py +101 -0
  114. osn_selenium/abstract/webdriver/core/window.py +237 -0
  115. osn_selenium/abstract/webdriver/edge/__init__.py +18 -0
  116. osn_selenium/abstract/webdriver/edge/base.py +36 -0
  117. osn_selenium/abstract/webdriver/edge/lifecycle.py +92 -0
  118. osn_selenium/abstract/webdriver/edge/settings.py +110 -0
  119. osn_selenium/abstract/webdriver/yandex/__init__.py +18 -0
  120. osn_selenium/abstract/webdriver/yandex/base.py +18 -0
  121. osn_selenium/abstract/webdriver/yandex/lifecycle.py +92 -0
  122. osn_selenium/abstract/webdriver/yandex/settings.py +110 -0
  123. osn_selenium/base_mixin.py +122 -0
  124. osn_selenium/browsers_handler/__init__.py +47 -17
  125. osn_selenium/browsers_handler/_linux.py +226 -0
  126. osn_selenium/browsers_handler/_windows.py +21 -14
  127. osn_selenium/browsers_handler/{types.py → models.py} +5 -2
  128. osn_selenium/dev_tools/_decorators.py +149 -0
  129. osn_selenium/dev_tools/_exception_helpers.py +116 -0
  130. osn_selenium/dev_tools/_functions.py +174 -0
  131. osn_selenium/dev_tools/_system_utils.py +35 -0
  132. osn_selenium/dev_tools/_typehints.py +35 -0
  133. osn_selenium/dev_tools/_validators.py +227 -0
  134. osn_selenium/dev_tools/_wrappers.py +92 -0
  135. osn_selenium/dev_tools/domains/__init__.py +7 -40
  136. osn_selenium/dev_tools/domains/abstract.py +98 -254
  137. osn_selenium/dev_tools/domains/fetch.py +229 -906
  138. osn_selenium/dev_tools/domains_default/fetch.py +40 -28
  139. osn_selenium/dev_tools/filters.py +40 -0
  140. osn_selenium/dev_tools/logger/main.py +214 -0
  141. osn_selenium/dev_tools/logger/models.py +232 -0
  142. osn_selenium/dev_tools/logger/target.py +278 -0
  143. osn_selenium/dev_tools/manager/__init__.py +16 -0
  144. osn_selenium/dev_tools/manager/base.py +124 -0
  145. osn_selenium/dev_tools/manager/lifecycle.py +236 -0
  146. osn_selenium/dev_tools/manager/logging.py +153 -0
  147. osn_selenium/dev_tools/manager/settings.py +89 -0
  148. osn_selenium/dev_tools/manager/targets.py +175 -0
  149. osn_selenium/dev_tools/models.py +49 -0
  150. osn_selenium/dev_tools/settings.py +139 -0
  151. osn_selenium/dev_tools/target/__init__.py +16 -0
  152. osn_selenium/dev_tools/target/base.py +427 -0
  153. osn_selenium/dev_tools/target/detach.py +54 -0
  154. osn_selenium/dev_tools/target/discovery.py +112 -0
  155. osn_selenium/dev_tools/target/events.py +120 -0
  156. osn_selenium/dev_tools/target/fingerprint.py +126 -0
  157. osn_selenium/dev_tools/target/lifecycle.py +184 -0
  158. osn_selenium/dev_tools/target/logging.py +163 -0
  159. osn_selenium/exceptions/__init__.py +1 -0
  160. osn_selenium/exceptions/base.py +9 -0
  161. osn_selenium/exceptions/configuration.py +84 -0
  162. osn_selenium/exceptions/dependencies.py +60 -0
  163. osn_selenium/exceptions/devtools.py +114 -0
  164. osn_selenium/exceptions/flags.py +45 -0
  165. osn_selenium/exceptions/instance.py +92 -0
  166. osn_selenium/exceptions/javascript.py +31 -0
  167. osn_selenium/exceptions/logic.py +31 -0
  168. osn_selenium/exceptions/path.py +77 -0
  169. osn_selenium/exceptions/platform.py +33 -0
  170. osn_selenium/exceptions/protocol.py +86 -0
  171. osn_selenium/exceptions/webdriver.py +44 -0
  172. osn_selenium/exceptions/window.py +63 -0
  173. osn_selenium/executors/__init__.py +1 -0
  174. osn_selenium/executors/sync/__init__.py +1 -0
  175. osn_selenium/executors/sync/cdp/__init__.py +550 -0
  176. osn_selenium/executors/sync/cdp/accessibility.py +74 -0
  177. osn_selenium/executors/sync/cdp/animation.py +50 -0
  178. osn_selenium/executors/sync/cdp/audits.py +48 -0
  179. osn_selenium/executors/sync/cdp/autofill.py +39 -0
  180. osn_selenium/executors/sync/cdp/background_service.py +30 -0
  181. osn_selenium/executors/sync/cdp/bluetooth_emulation.py +101 -0
  182. osn_selenium/executors/sync/cdp/browser.py +131 -0
  183. osn_selenium/executors/sync/cdp/cache_storage.py +66 -0
  184. osn_selenium/executors/sync/cdp/cast.py +38 -0
  185. osn_selenium/executors/sync/cdp/console.py +24 -0
  186. osn_selenium/executors/sync/cdp/css.py +187 -0
  187. osn_selenium/executors/sync/cdp/debugger.py +206 -0
  188. osn_selenium/executors/sync/cdp/device_access.py +27 -0
  189. osn_selenium/executors/sync/cdp/device_orientation.py +24 -0
  190. osn_selenium/executors/sync/cdp/dom.py +310 -0
  191. osn_selenium/executors/sync/cdp/dom_debugger.py +56 -0
  192. osn_selenium/executors/sync/cdp/dom_snapshot.py +58 -0
  193. osn_selenium/executors/sync/cdp/dom_storage.py +38 -0
  194. osn_selenium/executors/sync/cdp/emulation.py +270 -0
  195. osn_selenium/executors/sync/cdp/event_breakpoints.py +27 -0
  196. osn_selenium/executors/sync/cdp/extensions.py +39 -0
  197. osn_selenium/executors/sync/cdp/fed_cm.py +45 -0
  198. osn_selenium/executors/sync/cdp/fetch.py +96 -0
  199. osn_selenium/executors/sync/cdp/file_system.py +18 -0
  200. osn_selenium/executors/sync/cdp/headless_experimental.py +44 -0
  201. osn_selenium/executors/sync/cdp/heap_profiler.py +89 -0
  202. osn_selenium/executors/sync/cdp/indexed_db.py +142 -0
  203. osn_selenium/executors/sync/cdp/input.py +233 -0
  204. osn_selenium/executors/sync/cdp/inspector.py +21 -0
  205. osn_selenium/executors/sync/cdp/io.py +33 -0
  206. osn_selenium/executors/sync/cdp/layer_tree.py +71 -0
  207. osn_selenium/executors/sync/cdp/log.py +35 -0
  208. osn_selenium/executors/sync/cdp/media.py +21 -0
  209. osn_selenium/executors/sync/cdp/memory.py +62 -0
  210. osn_selenium/executors/sync/cdp/network.py +287 -0
  211. osn_selenium/executors/sync/cdp/overlay.py +174 -0
  212. osn_selenium/executors/sync/cdp/page.py +365 -0
  213. osn_selenium/executors/sync/cdp/performance.py +33 -0
  214. osn_selenium/executors/sync/cdp/performance_timeline.py +26 -0
  215. osn_selenium/executors/sync/cdp/preload.py +21 -0
  216. osn_selenium/executors/sync/cdp/profiler.py +58 -0
  217. osn_selenium/executors/sync/cdp/pwa.py +55 -0
  218. osn_selenium/executors/sync/cdp/runtime.py +221 -0
  219. osn_selenium/executors/sync/cdp/schema.py +23 -0
  220. osn_selenium/executors/sync/cdp/security.py +30 -0
  221. osn_selenium/executors/sync/cdp/service_worker.py +56 -0
  222. osn_selenium/executors/sync/cdp/storage.py +151 -0
  223. osn_selenium/executors/sync/cdp/system_info.py +30 -0
  224. osn_selenium/executors/sync/cdp/target.py +147 -0
  225. osn_selenium/executors/sync/cdp/tethering.py +21 -0
  226. osn_selenium/executors/sync/cdp/tracing.py +62 -0
  227. osn_selenium/executors/sync/cdp/web_audio.py +24 -0
  228. osn_selenium/executors/sync/cdp/web_authn.py +82 -0
  229. osn_selenium/executors/sync/cdp.py +100 -0
  230. osn_selenium/executors/sync/javascript.py +79 -0
  231. osn_selenium/executors/trio_threads/__init__.py +1 -0
  232. osn_selenium/executors/trio_threads/cdp/__init__.py +771 -0
  233. osn_selenium/executors/trio_threads/cdp/accessibility.py +87 -0
  234. osn_selenium/executors/trio_threads/cdp/animation.py +63 -0
  235. osn_selenium/executors/trio_threads/cdp/audits.py +57 -0
  236. osn_selenium/executors/trio_threads/cdp/autofill.py +52 -0
  237. osn_selenium/executors/trio_threads/cdp/background_service.py +40 -0
  238. osn_selenium/executors/trio_threads/cdp/bluetooth_emulation.py +111 -0
  239. osn_selenium/executors/trio_threads/cdp/browser.py +140 -0
  240. osn_selenium/executors/trio_threads/cdp/cache_storage.py +79 -0
  241. osn_selenium/executors/trio_threads/cdp/cast.py +47 -0
  242. osn_selenium/executors/trio_threads/cdp/console.py +33 -0
  243. osn_selenium/executors/trio_threads/cdp/css.py +196 -0
  244. osn_selenium/executors/trio_threads/cdp/debugger.py +219 -0
  245. osn_selenium/executors/trio_threads/cdp/device_access.py +40 -0
  246. osn_selenium/executors/trio_threads/cdp/device_orientation.py +34 -0
  247. osn_selenium/executors/trio_threads/cdp/dom.py +319 -0
  248. osn_selenium/executors/trio_threads/cdp/dom_debugger.py +69 -0
  249. osn_selenium/executors/trio_threads/cdp/dom_snapshot.py +71 -0
  250. osn_selenium/executors/trio_threads/cdp/dom_storage.py +51 -0
  251. osn_selenium/executors/trio_threads/cdp/emulation.py +283 -0
  252. osn_selenium/executors/trio_threads/cdp/event_breakpoints.py +37 -0
  253. osn_selenium/executors/trio_threads/cdp/extensions.py +52 -0
  254. osn_selenium/executors/trio_threads/cdp/fed_cm.py +54 -0
  255. osn_selenium/executors/trio_threads/cdp/fetch.py +105 -0
  256. osn_selenium/executors/trio_threads/cdp/file_system.py +31 -0
  257. osn_selenium/executors/trio_threads/cdp/headless_experimental.py +54 -0
  258. osn_selenium/executors/trio_threads/cdp/heap_profiler.py +102 -0
  259. osn_selenium/executors/trio_threads/cdp/indexed_db.py +155 -0
  260. osn_selenium/executors/trio_threads/cdp/input.py +242 -0
  261. osn_selenium/executors/trio_threads/cdp/inspector.py +34 -0
  262. osn_selenium/executors/trio_threads/cdp/io.py +42 -0
  263. osn_selenium/executors/trio_threads/cdp/layer_tree.py +84 -0
  264. osn_selenium/executors/trio_threads/cdp/log.py +44 -0
  265. osn_selenium/executors/trio_threads/cdp/media.py +30 -0
  266. osn_selenium/executors/trio_threads/cdp/memory.py +71 -0
  267. osn_selenium/executors/trio_threads/cdp/network.py +296 -0
  268. osn_selenium/executors/trio_threads/cdp/overlay.py +183 -0
  269. osn_selenium/executors/trio_threads/cdp/page.py +374 -0
  270. osn_selenium/executors/trio_threads/cdp/performance.py +46 -0
  271. osn_selenium/executors/trio_threads/cdp/performance_timeline.py +36 -0
  272. osn_selenium/executors/trio_threads/cdp/preload.py +30 -0
  273. osn_selenium/executors/trio_threads/cdp/profiler.py +71 -0
  274. osn_selenium/executors/trio_threads/cdp/pwa.py +64 -0
  275. osn_selenium/executors/trio_threads/cdp/runtime.py +230 -0
  276. osn_selenium/executors/trio_threads/cdp/schema.py +32 -0
  277. osn_selenium/executors/trio_threads/cdp/security.py +43 -0
  278. osn_selenium/executors/trio_threads/cdp/service_worker.py +69 -0
  279. osn_selenium/executors/trio_threads/cdp/storage.py +162 -0
  280. osn_selenium/executors/trio_threads/cdp/system_info.py +43 -0
  281. osn_selenium/executors/trio_threads/cdp/target.py +156 -0
  282. osn_selenium/executors/trio_threads/cdp/tethering.py +34 -0
  283. osn_selenium/executors/trio_threads/cdp/tracing.py +71 -0
  284. osn_selenium/executors/trio_threads/cdp/web_audio.py +37 -0
  285. osn_selenium/executors/trio_threads/cdp/web_authn.py +95 -0
  286. osn_selenium/executors/trio_threads/cdp.py +104 -0
  287. osn_selenium/executors/trio_threads/javascript.py +90 -0
  288. osn_selenium/executors/unified/__init__.py +1 -0
  289. osn_selenium/executors/unified/cdp/__init__.py +1 -0
  290. osn_selenium/executors/unified/cdp/accessibility.py +81 -0
  291. osn_selenium/executors/unified/cdp/animation.py +50 -0
  292. osn_selenium/executors/unified/cdp/audits.py +45 -0
  293. osn_selenium/executors/unified/cdp/autofill.py +41 -0
  294. osn_selenium/executors/unified/cdp/background_service.py +24 -0
  295. osn_selenium/executors/unified/cdp/bluetooth_emulation.py +132 -0
  296. osn_selenium/executors/unified/cdp/browser.py +143 -0
  297. osn_selenium/executors/unified/cdp/cache_storage.py +69 -0
  298. osn_selenium/executors/unified/cdp/cast.py +32 -0
  299. osn_selenium/executors/unified/cdp/console.py +18 -0
  300. osn_selenium/executors/unified/cdp/css.py +237 -0
  301. osn_selenium/executors/unified/cdp/debugger.py +243 -0
  302. osn_selenium/executors/unified/cdp/device_access.py +21 -0
  303. osn_selenium/executors/unified/cdp/device_orientation.py +18 -0
  304. osn_selenium/executors/unified/cdp/dom.py +380 -0
  305. osn_selenium/executors/unified/cdp/dom_debugger.py +65 -0
  306. osn_selenium/executors/unified/cdp/dom_snapshot.py +58 -0
  307. osn_selenium/executors/unified/cdp/dom_storage.py +38 -0
  308. osn_selenium/executors/unified/cdp/emulation.py +312 -0
  309. osn_selenium/executors/unified/cdp/event_breakpoints.py +24 -0
  310. osn_selenium/executors/unified/cdp/extensions.py +45 -0
  311. osn_selenium/executors/unified/cdp/fed_cm.py +51 -0
  312. osn_selenium/executors/unified/cdp/fetch.py +111 -0
  313. osn_selenium/executors/unified/cdp/file_system.py +15 -0
  314. osn_selenium/executors/unified/cdp/headless_experimental.py +38 -0
  315. osn_selenium/executors/unified/cdp/heap_profiler.py +101 -0
  316. osn_selenium/executors/unified/cdp/indexed_db.py +157 -0
  317. osn_selenium/executors/unified/cdp/input.py +254 -0
  318. osn_selenium/executors/unified/cdp/inspector.py +15 -0
  319. osn_selenium/executors/unified/cdp/io.py +29 -0
  320. osn_selenium/executors/unified/cdp/layer_tree.py +71 -0
  321. osn_selenium/executors/unified/cdp/log.py +29 -0
  322. osn_selenium/executors/unified/cdp/media.py +15 -0
  323. osn_selenium/executors/unified/cdp/memory.py +59 -0
  324. osn_selenium/executors/unified/cdp/network.py +323 -0
  325. osn_selenium/executors/unified/cdp/overlay.py +209 -0
  326. osn_selenium/executors/unified/cdp/page.py +410 -0
  327. osn_selenium/executors/unified/cdp/performance.py +27 -0
  328. osn_selenium/executors/unified/cdp/performance_timeline.py +17 -0
  329. osn_selenium/executors/unified/cdp/preload.py +15 -0
  330. osn_selenium/executors/unified/cdp/profiler.py +55 -0
  331. osn_selenium/executors/unified/cdp/pwa.py +55 -0
  332. osn_selenium/executors/unified/cdp/runtime.py +245 -0
  333. osn_selenium/executors/unified/cdp/schema.py +17 -0
  334. osn_selenium/executors/unified/cdp/security.py +27 -0
  335. osn_selenium/executors/unified/cdp/service_worker.py +62 -0
  336. osn_selenium/executors/unified/cdp/storage.py +178 -0
  337. osn_selenium/executors/unified/cdp/system_info.py +24 -0
  338. osn_selenium/executors/unified/cdp/target.py +165 -0
  339. osn_selenium/executors/unified/cdp/tethering.py +15 -0
  340. osn_selenium/executors/unified/cdp/tracing.py +62 -0
  341. osn_selenium/executors/unified/cdp/web_audio.py +18 -0
  342. osn_selenium/executors/unified/cdp/web_authn.py +103 -0
  343. osn_selenium/executors/unified/javascript.py +104 -0
  344. osn_selenium/flags/__init__.py +1 -0
  345. osn_selenium/flags/_functions.py +45 -0
  346. osn_selenium/flags/_typehints.py +34 -0
  347. osn_selenium/flags/_validators.py +101 -0
  348. osn_selenium/{webdrivers/BaseDriver/flags.py → flags/base.py} +159 -245
  349. osn_selenium/{webdrivers/Blink/flags.py → flags/blink.py} +130 -374
  350. osn_selenium/flags/chrome.py +259 -0
  351. osn_selenium/flags/edge.py +259 -0
  352. osn_selenium/flags/models/__init__.py +1 -0
  353. osn_selenium/flags/models/base.py +130 -0
  354. osn_selenium/flags/models/blink.py +263 -0
  355. osn_selenium/{webdrivers/Chrome/flags.py → flags/models/chrome.py} +25 -75
  356. osn_selenium/{webdrivers/Edge/flags.py → flags/models/edge.py} +25 -75
  357. osn_selenium/flags/models/values.py +44 -0
  358. osn_selenium/{webdrivers/Yandex/flags.py → flags/models/yandex.py} +26 -76
  359. osn_selenium/flags/yandex.py +259 -0
  360. osn_selenium/instances/__init__.py +1 -0
  361. osn_selenium/instances/_functions.py +242 -0
  362. osn_selenium/instances/_typehints.py +148 -0
  363. osn_selenium/instances/_utils.py +143 -0
  364. osn_selenium/instances/convert.py +287 -0
  365. osn_selenium/instances/protocols.py +105 -0
  366. osn_selenium/instances/sync/__init__.py +1 -0
  367. osn_selenium/instances/sync/action_chains/__init__.py +32 -0
  368. osn_selenium/instances/sync/action_chains/base.py +74 -0
  369. osn_selenium/instances/sync/action_chains/click.py +61 -0
  370. osn_selenium/instances/sync/action_chains/drag_and_drop.py +45 -0
  371. osn_selenium/instances/sync/action_chains/hm_keyboard.py +37 -0
  372. osn_selenium/instances/sync/action_chains/hm_move.py +81 -0
  373. osn_selenium/instances/sync/action_chains/hm_scroll.py +60 -0
  374. osn_selenium/instances/sync/action_chains/keyboard.py +55 -0
  375. osn_selenium/instances/sync/action_chains/move.py +46 -0
  376. osn_selenium/instances/sync/action_chains/scroll.py +43 -0
  377. osn_selenium/instances/sync/action_chains/utils.py +30 -0
  378. osn_selenium/instances/sync/alert.py +69 -0
  379. osn_selenium/instances/sync/browser.py +72 -0
  380. osn_selenium/instances/sync/browsing_context.py +193 -0
  381. osn_selenium/instances/sync/dialog.py +81 -0
  382. osn_selenium/instances/sync/fedcm.py +92 -0
  383. osn_selenium/instances/sync/mobile.py +75 -0
  384. osn_selenium/instances/sync/network.py +90 -0
  385. osn_selenium/instances/sync/permissions.py +80 -0
  386. osn_selenium/instances/sync/script.py +77 -0
  387. osn_selenium/instances/sync/shadow_root.py +113 -0
  388. osn_selenium/instances/sync/storage.py +91 -0
  389. osn_selenium/instances/sync/switch_to.py +92 -0
  390. osn_selenium/instances/sync/web_driver_wait.py +83 -0
  391. osn_selenium/instances/sync/web_element.py +179 -0
  392. osn_selenium/instances/sync/web_extension.py +77 -0
  393. osn_selenium/instances/trio_threads/__init__.py +1 -0
  394. osn_selenium/instances/trio_threads/action_chains/__init__.py +32 -0
  395. osn_selenium/instances/trio_threads/action_chains/base.py +88 -0
  396. osn_selenium/instances/trio_threads/action_chains/click.py +71 -0
  397. osn_selenium/instances/trio_threads/action_chains/drag_and_drop.py +49 -0
  398. osn_selenium/instances/trio_threads/action_chains/hm_keyboard.py +41 -0
  399. osn_selenium/instances/trio_threads/action_chains/hm_move.py +91 -0
  400. osn_selenium/instances/trio_threads/action_chains/hm_scroll.py +66 -0
  401. osn_selenium/instances/trio_threads/action_chains/keyboard.py +63 -0
  402. osn_selenium/instances/trio_threads/action_chains/move.py +52 -0
  403. osn_selenium/instances/trio_threads/action_chains/scroll.py +49 -0
  404. osn_selenium/instances/trio_threads/action_chains/utils.py +32 -0
  405. osn_selenium/instances/trio_threads/alert.py +87 -0
  406. osn_selenium/instances/trio_threads/browser.py +90 -0
  407. osn_selenium/instances/trio_threads/browsing_context.py +216 -0
  408. osn_selenium/instances/trio_threads/dialog.py +99 -0
  409. osn_selenium/instances/trio_threads/fedcm.py +110 -0
  410. osn_selenium/instances/trio_threads/mobile.py +93 -0
  411. osn_selenium/instances/trio_threads/network.py +108 -0
  412. osn_selenium/instances/trio_threads/permissions.py +102 -0
  413. osn_selenium/instances/trio_threads/script.py +95 -0
  414. osn_selenium/instances/trio_threads/shadow_root.py +154 -0
  415. osn_selenium/instances/trio_threads/storage.py +109 -0
  416. osn_selenium/instances/trio_threads/switch_to.py +124 -0
  417. osn_selenium/instances/trio_threads/web_driver_wait.py +101 -0
  418. osn_selenium/instances/trio_threads/web_element.py +217 -0
  419. osn_selenium/instances/trio_threads/web_extension.py +99 -0
  420. osn_selenium/instances/unified/__init__.py +1 -0
  421. osn_selenium/instances/unified/action_chains/__init__.py +22 -0
  422. osn_selenium/instances/unified/action_chains/base.py +31 -0
  423. osn_selenium/instances/unified/action_chains/click.py +27 -0
  424. osn_selenium/instances/unified/action_chains/drag_and_drop.py +24 -0
  425. osn_selenium/instances/unified/action_chains/hm_keyboard.py +30 -0
  426. osn_selenium/instances/unified/action_chains/hm_move.py +66 -0
  427. osn_selenium/instances/unified/action_chains/hm_scroll.py +79 -0
  428. osn_selenium/instances/unified/action_chains/keyboard.py +24 -0
  429. osn_selenium/instances/unified/action_chains/move.py +24 -0
  430. osn_selenium/instances/unified/action_chains/scroll.py +21 -0
  431. osn_selenium/instances/unified/action_chains/utils.py +19 -0
  432. osn_selenium/instances/unified/alert.py +29 -0
  433. osn_selenium/instances/unified/browser.py +33 -0
  434. osn_selenium/instances/unified/browsing_context.py +151 -0
  435. osn_selenium/instances/unified/dialog.py +42 -0
  436. osn_selenium/instances/unified/fedcm.py +48 -0
  437. osn_selenium/instances/unified/mobile.py +36 -0
  438. osn_selenium/instances/unified/network.py +50 -0
  439. osn_selenium/instances/unified/permissions.py +43 -0
  440. osn_selenium/instances/unified/script.py +38 -0
  441. osn_selenium/instances/unified/shadow_root.py +46 -0
  442. osn_selenium/instances/unified/storage.py +48 -0
  443. osn_selenium/instances/unified/switch_to.py +49 -0
  444. osn_selenium/instances/unified/web_driver_wait.py +45 -0
  445. osn_selenium/instances/unified/web_element.py +145 -0
  446. osn_selenium/instances/unified/web_extension.py +38 -0
  447. osn_selenium/javascript/__init__.py +1 -0
  448. osn_selenium/javascript/_functions.py +63 -0
  449. osn_selenium/javascript/fingerprint/__init__.py +120 -0
  450. osn_selenium/javascript/fingerprint/_decorators.py +41 -0
  451. osn_selenium/javascript/fingerprint/_detect/__init__.py +1 -0
  452. osn_selenium/javascript/fingerprint/_detect/functions.py +253 -0
  453. osn_selenium/javascript/fingerprint/_detect/templates.py +128 -0
  454. osn_selenium/javascript/fingerprint/_functions.py +35 -0
  455. osn_selenium/javascript/fingerprint/_typehints.py +27 -0
  456. osn_selenium/javascript/fingerprint/registry/__init__.py +7 -0
  457. osn_selenium/javascript/fingerprint/registry/_core_functions.py +236 -0
  458. osn_selenium/javascript/fingerprint/registry/_functions.py +923 -0
  459. osn_selenium/javascript/fingerprint/registry/_typehints.py +6 -0
  460. osn_selenium/javascript/fingerprint/registry/_utils.py +6 -0
  461. osn_selenium/javascript/fingerprint/registry/models.py +41 -0
  462. osn_selenium/javascript/fingerprint/spoof/__init__.py +1 -0
  463. osn_selenium/javascript/fingerprint/spoof/_functions.py +172 -0
  464. osn_selenium/javascript/fingerprint/spoof/_templates.py +134 -0
  465. osn_selenium/javascript/fingerprint/spoof/_typehints.py +22 -0
  466. osn_selenium/javascript/fingerprint/spoof/core_rules.py +141 -0
  467. osn_selenium/javascript/fingerprint/spoof/noise.py +51 -0
  468. osn_selenium/javascript/fingerprint/spoof/rules.py +313 -0
  469. osn_selenium/javascript/functions.py +44 -0
  470. osn_selenium/javascript/models.py +35 -0
  471. osn_selenium/javascript/scripts/start_fingerprint_detection.js +56 -0
  472. osn_selenium/models.py +94 -0
  473. osn_selenium/trio_threads_mixin.py +159 -0
  474. osn_selenium/webdrivers/_args_helpers.py +181 -0
  475. osn_selenium/webdrivers/_bridges.py +57 -0
  476. osn_selenium/webdrivers/_decorators.py +83 -0
  477. osn_selenium/webdrivers/_executable_tables/__init__.py +1 -0
  478. osn_selenium/webdrivers/_executable_tables/functions.py +113 -0
  479. osn_selenium/webdrivers/_executable_tables/models.py +19 -0
  480. osn_selenium/webdrivers/_typehints.py +10 -0
  481. osn_selenium/webdrivers/protocols.py +50 -0
  482. osn_selenium/webdrivers/sync/__init__.py +1 -0
  483. osn_selenium/webdrivers/sync/blink/__init__.py +124 -0
  484. osn_selenium/webdrivers/sync/blink/base.py +140 -0
  485. osn_selenium/webdrivers/sync/blink/casting.py +34 -0
  486. osn_selenium/webdrivers/sync/blink/features.py +28 -0
  487. osn_selenium/webdrivers/sync/blink/lifecycle.py +66 -0
  488. osn_selenium/webdrivers/sync/blink/logging.py +25 -0
  489. osn_selenium/webdrivers/sync/blink/network.py +28 -0
  490. osn_selenium/webdrivers/sync/blink/settings.py +63 -0
  491. osn_selenium/webdrivers/sync/chrome/__init__.py +102 -0
  492. osn_selenium/webdrivers/sync/chrome/base.py +118 -0
  493. osn_selenium/webdrivers/sync/chrome/lifecycle.py +63 -0
  494. osn_selenium/webdrivers/sync/chrome/settings.py +58 -0
  495. osn_selenium/webdrivers/sync/core/__init__.py +100 -0
  496. osn_selenium/webdrivers/sync/core/actions.py +59 -0
  497. osn_selenium/webdrivers/sync/core/auth.py +77 -0
  498. osn_selenium/webdrivers/sync/core/base.py +175 -0
  499. osn_selenium/webdrivers/sync/core/capture.py +37 -0
  500. osn_selenium/webdrivers/sync/core/comonents.py +57 -0
  501. osn_selenium/webdrivers/sync/core/devtools.py +47 -0
  502. osn_selenium/webdrivers/sync/core/element.py +42 -0
  503. osn_selenium/webdrivers/sync/core/file.py +40 -0
  504. osn_selenium/webdrivers/sync/core/lifecycle.py +59 -0
  505. osn_selenium/webdrivers/sync/core/navigation.py +36 -0
  506. osn_selenium/webdrivers/sync/core/script.py +53 -0
  507. osn_selenium/webdrivers/sync/core/settings.py +35 -0
  508. osn_selenium/webdrivers/sync/core/storage.py +48 -0
  509. osn_selenium/webdrivers/sync/core/timeouts.py +59 -0
  510. osn_selenium/webdrivers/sync/core/window.py +99 -0
  511. osn_selenium/webdrivers/sync/edge/__init__.py +102 -0
  512. osn_selenium/webdrivers/sync/edge/base.py +114 -0
  513. osn_selenium/webdrivers/sync/edge/lifecycle.py +63 -0
  514. osn_selenium/webdrivers/sync/edge/settings.py +58 -0
  515. osn_selenium/webdrivers/sync/yandex/__init__.py +102 -0
  516. osn_selenium/webdrivers/sync/yandex/base.py +111 -0
  517. osn_selenium/webdrivers/sync/yandex/lifecycle.py +63 -0
  518. osn_selenium/webdrivers/sync/yandex/settings.py +58 -0
  519. osn_selenium/webdrivers/trio_threads/__init__.py +1 -0
  520. osn_selenium/webdrivers/trio_threads/blink/__init__.py +134 -0
  521. osn_selenium/webdrivers/trio_threads/blink/base.py +143 -0
  522. osn_selenium/webdrivers/trio_threads/blink/casting.py +35 -0
  523. osn_selenium/webdrivers/trio_threads/blink/features.py +29 -0
  524. osn_selenium/webdrivers/trio_threads/blink/lifecycle.py +66 -0
  525. osn_selenium/webdrivers/trio_threads/blink/logging.py +26 -0
  526. osn_selenium/webdrivers/trio_threads/blink/network.py +29 -0
  527. osn_selenium/webdrivers/trio_threads/blink/settings.py +63 -0
  528. osn_selenium/webdrivers/trio_threads/chrome/__init__.py +114 -0
  529. osn_selenium/webdrivers/trio_threads/chrome/base.py +119 -0
  530. osn_selenium/webdrivers/trio_threads/chrome/lifecycle.py +63 -0
  531. osn_selenium/webdrivers/trio_threads/chrome/settings.py +63 -0
  532. osn_selenium/webdrivers/trio_threads/core/__init__.py +115 -0
  533. osn_selenium/webdrivers/trio_threads/core/actions.py +72 -0
  534. osn_selenium/webdrivers/trio_threads/core/auth.py +88 -0
  535. osn_selenium/webdrivers/trio_threads/core/base.py +199 -0
  536. osn_selenium/webdrivers/trio_threads/core/capture.py +38 -0
  537. osn_selenium/webdrivers/trio_threads/core/comonents.py +92 -0
  538. osn_selenium/webdrivers/trio_threads/core/devtools.py +53 -0
  539. osn_selenium/webdrivers/trio_threads/core/element.py +58 -0
  540. osn_selenium/webdrivers/trio_threads/core/file.py +45 -0
  541. osn_selenium/webdrivers/trio_threads/core/lifecycle.py +60 -0
  542. osn_selenium/webdrivers/trio_threads/core/navigation.py +41 -0
  543. osn_selenium/webdrivers/trio_threads/core/script.py +59 -0
  544. osn_selenium/webdrivers/trio_threads/core/settings.py +36 -0
  545. osn_selenium/webdrivers/trio_threads/core/storage.py +54 -0
  546. osn_selenium/webdrivers/trio_threads/core/timeouts.py +60 -0
  547. osn_selenium/webdrivers/trio_threads/core/window.py +105 -0
  548. osn_selenium/webdrivers/trio_threads/edge/__init__.py +114 -0
  549. osn_selenium/webdrivers/trio_threads/edge/base.py +115 -0
  550. osn_selenium/webdrivers/trio_threads/edge/lifecycle.py +63 -0
  551. osn_selenium/webdrivers/trio_threads/edge/settings.py +63 -0
  552. osn_selenium/webdrivers/trio_threads/yandex/__init__.py +114 -0
  553. osn_selenium/webdrivers/trio_threads/yandex/base.py +112 -0
  554. osn_selenium/webdrivers/trio_threads/yandex/lifecycle.py +63 -0
  555. osn_selenium/webdrivers/trio_threads/yandex/settings.py +63 -0
  556. osn_selenium/webdrivers/unified/__init__.py +1 -0
  557. osn_selenium/webdrivers/unified/blink/__init__.py +1 -0
  558. osn_selenium/webdrivers/unified/blink/base.py +135 -0
  559. osn_selenium/webdrivers/unified/blink/casting.py +30 -0
  560. osn_selenium/webdrivers/unified/blink/features.py +22 -0
  561. osn_selenium/webdrivers/unified/blink/lifecycle.py +114 -0
  562. osn_selenium/webdrivers/unified/blink/logging.py +18 -0
  563. osn_selenium/webdrivers/unified/blink/network.py +22 -0
  564. osn_selenium/webdrivers/unified/blink/settings.py +86 -0
  565. osn_selenium/webdrivers/unified/chrome/__init__.py +1 -0
  566. osn_selenium/webdrivers/unified/chrome/base.py +58 -0
  567. osn_selenium/webdrivers/unified/chrome/lifecycle.py +88 -0
  568. osn_selenium/webdrivers/unified/chrome/settings.py +48 -0
  569. osn_selenium/webdrivers/unified/core/__init__.py +1 -0
  570. osn_selenium/webdrivers/unified/core/actions.py +43 -0
  571. osn_selenium/webdrivers/unified/core/auth.py +70 -0
  572. osn_selenium/webdrivers/unified/core/base.py +139 -0
  573. osn_selenium/webdrivers/unified/core/capture.py +32 -0
  574. osn_selenium/webdrivers/unified/core/components.py +32 -0
  575. osn_selenium/webdrivers/unified/core/devtools.py +35 -0
  576. osn_selenium/webdrivers/unified/core/element.py +24 -0
  577. osn_selenium/webdrivers/unified/core/file.py +35 -0
  578. osn_selenium/webdrivers/unified/core/lifecycle.py +84 -0
  579. osn_selenium/webdrivers/unified/core/navigation.py +31 -0
  580. osn_selenium/webdrivers/unified/core/script.py +32 -0
  581. osn_selenium/webdrivers/unified/core/settings.py +44 -0
  582. osn_selenium/webdrivers/unified/core/storage.py +37 -0
  583. osn_selenium/webdrivers/unified/core/timeouts.py +56 -0
  584. osn_selenium/webdrivers/unified/core/window.py +135 -0
  585. osn_selenium/webdrivers/unified/edge/__init__.py +1 -0
  586. osn_selenium/webdrivers/unified/edge/base.py +56 -0
  587. osn_selenium/webdrivers/unified/edge/lifecycle.py +88 -0
  588. osn_selenium/webdrivers/unified/edge/settings.py +48 -0
  589. osn_selenium/webdrivers/unified/yandex/__init__.py +1 -0
  590. osn_selenium/webdrivers/unified/yandex/base.py +58 -0
  591. osn_selenium/webdrivers/unified/yandex/lifecycle.py +58 -0
  592. osn_selenium/webdrivers/unified/yandex/settings.py +48 -0
  593. osn_selenium-1.1.0.dist-info/METADATA +252 -0
  594. osn_selenium-1.1.0.dist-info/RECORD +615 -0
  595. {osn_selenium-0.0.0.dist-info → osn_selenium-1.1.0.dist-info}/WHEEL +1 -1
  596. osn_selenium/captcha_workers/__init__.py +0 -26
  597. osn_selenium/dev_tools/_types.py +0 -22
  598. osn_selenium/dev_tools/errors.py +0 -89
  599. osn_selenium/dev_tools/logger.py +0 -558
  600. osn_selenium/dev_tools/manager.py +0 -1551
  601. osn_selenium/dev_tools/utils.py +0 -509
  602. osn_selenium/errors.py +0 -16
  603. osn_selenium/types.py +0 -118
  604. osn_selenium/webdrivers/BaseDriver/_utils.py +0 -37
  605. osn_selenium/webdrivers/BaseDriver/protocols.py +0 -2135
  606. osn_selenium/webdrivers/BaseDriver/trio_wrapper.py +0 -71
  607. osn_selenium/webdrivers/BaseDriver/webdriver.py +0 -2626
  608. osn_selenium/webdrivers/Blink/protocols.py +0 -330
  609. osn_selenium/webdrivers/Blink/webdriver.py +0 -637
  610. osn_selenium/webdrivers/Chrome/protocols.py +0 -228
  611. osn_selenium/webdrivers/Chrome/webdriver.py +0 -394
  612. osn_selenium/webdrivers/Edge/protocols.py +0 -228
  613. osn_selenium/webdrivers/Edge/webdriver.py +0 -394
  614. osn_selenium/webdrivers/Yandex/protocols.py +0 -211
  615. osn_selenium/webdrivers/Yandex/webdriver.py +0 -350
  616. osn_selenium/webdrivers/_functions.py +0 -504
  617. osn_selenium/webdrivers/types.py +0 -390
  618. osn_selenium-0.0.0.dist-info/METADATA +0 -710
  619. osn_selenium-0.0.0.dist-info/RECORD +0 -57
  620. /osn_selenium/{webdrivers/BaseDriver → abstract}/__init__.py +0 -0
  621. /osn_selenium/{webdrivers/Blink → abstract/executors}/__init__.py +0 -0
  622. /osn_selenium/{webdrivers/Chrome → abstract/instances}/__init__.py +0 -0
  623. /osn_selenium/{webdrivers/Edge → abstract/webdriver}/__init__.py +0 -0
  624. /osn_selenium/{webdrivers/Yandex → dev_tools/logger}/__init__.py +0 -0
  625. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/check_element_in_viewport.js +0 -0
  626. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_document_scroll_size.js +0 -0
  627. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_element_css.js +0 -0
  628. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_element_rect_in_viewport.js +0 -0
  629. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_random_element_point_in_viewport.js +0 -0
  630. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_viewport_position.js +0 -0
  631. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_viewport_rect.js +0 -0
  632. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/get_viewport_size.js +0 -0
  633. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/open_new_tab.js +0 -0
  634. /osn_selenium/{webdrivers/js_scripts → javascript/scripts}/stop_window_loading.js +0 -0
  635. {osn_selenium-0.0.0.dist-info → osn_selenium-1.1.0.dist-info}/top_level.txt +0 -0
@@ -1,1551 +0,0 @@
1
- import trio
2
- import inspect
3
- import warnings
4
- from datetime import datetime
5
- from types import TracebackType
6
- from dataclasses import dataclass
7
- from collections.abc import Sequence
8
- from contextlib import (
9
- AbstractAsyncContextManager
10
- )
11
- from selenium.webdriver.remote.bidi_connection import BidiConnection
12
- from typing import (
13
- Any,
14
- Awaitable,
15
- Callable,
16
- Optional,
17
- TYPE_CHECKING,
18
- Union
19
- )
20
- from osn_selenium.dev_tools.domains.abstract import (
21
- AbstractDomain,
22
- AbstractEvent
23
- )
24
- from selenium.webdriver.common.bidi.cdp import (
25
- BrowserError,
26
- CdpSession,
27
- open_cdp
28
- )
29
- from osn_selenium.dev_tools._types import (
30
- LogLevelsType,
31
- devtools_background_func_type
32
- )
33
- from osn_selenium.dev_tools.domains import (
34
- Domains,
35
- DomainsSettings,
36
- domains_classes_type,
37
- domains_type
38
- )
39
- from osn_selenium.dev_tools.errors import (
40
- BidiConnectionNotEstablishedError,
41
- CantEnterDevToolsContextError,
42
- cdp_end_exceptions
43
- )
44
- from osn_selenium.dev_tools.logger import (
45
- LogEntry,
46
- LogLevelStats,
47
- LoggerChannelStats,
48
- LoggerSettings,
49
- MainLogEntry,
50
- MainLogger,
51
- TargetLogger,
52
- TargetTypeStats,
53
- build_main_logger,
54
- build_target_logger
55
- )
56
- from osn_selenium.dev_tools.utils import (
57
- TargetData,
58
- TargetFilter,
59
- _background_task_decorator,
60
- _prepare_log_dir,
61
- _validate_type_filter,
62
- execute_cdp_command,
63
- extract_exception_trace,
64
- log_exception,
65
- log_on_error,
66
- wait_one,
67
- warn_if_active
68
- )
69
-
70
-
71
- if TYPE_CHECKING:
72
- from osn_selenium.webdrivers.BaseDriver.webdriver import BrowserWebDriver
73
-
74
-
75
- @dataclass
76
- class DevToolsSettings:
77
- """
78
- Settings for configuring the DevTools manager.
79
-
80
- Attributes:
81
- new_targets_filter (Optional[Sequence[TargetFilter]]): A sequence of `TargetFilter` objects
82
- to control which new browser targets (e.g., tabs, iframes) DevTools should discover and attach to.
83
- Defaults to None, meaning all targets are considered.
84
- new_targets_buffer_size (int): The buffer size for the Trio memory channel
85
- used to receive new target events. A larger buffer can prevent `trio.WouldBlock`
86
- errors under high event load. Defaults to 100.
87
- target_background_task (Optional[devtools_background_func_type]): An optional asynchronous function
88
- that will be run as a background task for each attached DevTools target. This can be used
89
- for custom per-target logic. Defaults to None.
90
- logger_settings (Optional[LoggerSettings]): Configuration settings for the internal logging system.
91
- If None, default logging settings will be used (no file logging by default).
92
- Defaults to None.
93
- """
94
-
95
- new_targets_filter: Optional[Sequence[TargetFilter]] = None
96
- new_targets_buffer_size: int = 100
97
- target_background_task: devtools_background_func_type = None
98
- logger_settings: Optional[LoggerSettings] = None
99
-
100
-
101
- class DevToolsTarget:
102
- """
103
- Manages the DevTools Protocol session and event handling for a specific browser target.
104
-
105
- Each `DevToolsTarget` instance represents a single CDP target (e.g., a browser tab,
106
- an iframe, or a service worker) and handles its dedicated CDP session, event listeners,
107
- and associated logging.
108
-
109
- Attributes:
110
- target_data (TargetData): Data describing the browser target.
111
- _logger_settings (LoggerSettings): Logging configuration for this target.
112
- devtools_package (Any): The DevTools protocol package (e.g., `selenium.webdriver.common.bidi.cdp.devtools`).
113
- websocket_url (Optional[str]): The WebSocket URL for establishing the CDP connection.
114
- _new_targets_filter (Optional[list[dict[str, Any]]]): Filter settings for discovering new targets.
115
- _new_targets_buffer_size (int): Buffer size for new target events.
116
- _domains (Domains): Configuration for DevTools domains and their event handlers.
117
- _nursery_object (trio.Nursery): The Trio nursery for spawning concurrent tasks.
118
- exit_event (trio.Event): An event signaling that the main DevTools context is exiting.
119
- _target_type_log_accepted (bool): Indicates if this target's type is accepted by the logger filter.
120
- _target_background_task (Optional[devtools_background_func_type]): An optional background task to run for this target.
121
- _add_target_func (Callable[[Any], Awaitable[bool]]): Callback function to add new targets to the manager.
122
- _remove_target_func (Callable[["DevToolsTarget"], Awaitable[bool]]): Callback function to remove targets from the manager.
123
- _add_log_func (Callable[[LogEntry], Awaitable[None]]): Callback function to add log entries to the main logger.
124
- started_event (trio.Event): An event set when the target's `run` method has started.
125
- about_to_stop_event (trio.Event): An event set when the target is signaled to stop.
126
- background_task_ended (Optional[trio.Event]): An event set when the target's background task completes.
127
- stopped_event (trio.Event): An event set when the target's `run` method has fully stopped.
128
- _log_stats (LoggerChannelStats): Statistics specific to this target's logging.
129
- _logger_send_channel (Optional[trio.MemorySendChannel[LogEntry]]): Send channel for this target's logger.
130
- _logger (Optional[TargetLogger]): The logger instance for this specific target.
131
- _cdp_session (Optional[CdpSession]): The active CDP session for this target.
132
- _new_target_receive_channel (Optional[tuple[trio.MemoryReceiveChannel[Any], trio.Event]]): Channel and event for new target events.
133
- _events_receive_channels (dict[str, tuple[trio.MemoryReceiveChannel[Any], trio.Event]]): Channels and events for domain-specific events.
134
- """
135
-
136
- def __init__(
137
- self,
138
- target_data: TargetData,
139
- logger_settings: LoggerSettings,
140
- devtools_package: Any,
141
- websocket_url: Optional[str],
142
- new_targets_filter: list[dict[str, Any]],
143
- new_targets_buffer_size: int,
144
- domains: Domains,
145
- nursery: trio.Nursery,
146
- exit_event: trio.Event,
147
- target_background_task: Optional[devtools_background_func_type],
148
- add_target_func: Callable[[Any], Awaitable[bool]],
149
- remove_target_func: Callable[["DevToolsTarget"], Awaitable[bool]],
150
- add_log_func: Callable[[LogEntry], Awaitable[None]],
151
- ):
152
- """
153
- Initializes a DevToolsTarget instance.
154
-
155
- Args:
156
- target_data (TargetData): Initial data for this target.
157
- logger_settings (LoggerSettings): Logging configuration.
158
- devtools_package (Any): The DevTools protocol package.
159
- websocket_url (Optional[str]): WebSocket URL for CDP connection.
160
- new_targets_filter (Optional[list[dict[str, Any]]]): Filters for new targets.
161
- new_targets_buffer_size (int): Buffer size for new target events.
162
- domains (Domains): Configured DevTools domains.
163
- nursery (trio.Nursery): The Trio nursery for tasks.
164
- exit_event (trio.Event): Event to signal global exit.
165
- target_background_task (Optional[devtools_background_func_type]): Optional background task.
166
- add_target_func (Callable[[Any], Awaitable[Optional[bool]]]): Function to add new targets.
167
- remove_target_func (Callable[["DevToolsTarget"], Awaitable[Optional[bool]]]): Function to remove targets.
168
- add_log_func (Callable[[LogEntry], Awaitable[None]]): Function to add logs to main logger.
169
- """
170
-
171
- self.target_data = target_data
172
- self._logger_settings = logger_settings
173
- self.devtools_package = devtools_package
174
- self.websocket_url = websocket_url
175
- self._new_targets_filter = new_targets_filter
176
- self._new_targets_buffer_size = new_targets_buffer_size
177
- self._domains = domains
178
- self._nursery_object = nursery
179
- self.exit_event = exit_event
180
-
181
- self._target_type_log_accepted = _validate_type_filter(
182
- self.type_,
183
- self._logger_settings.target_type_filter_mode,
184
- self._logger_settings.target_type_filter
185
- )
186
-
187
- self._target_background_task = target_background_task
188
- self._add_target_func = add_target_func
189
- self._remove_target_func = remove_target_func
190
- self._add_log_func = add_log_func
191
- self.started_event = trio.Event()
192
- self.about_to_stop_event = trio.Event()
193
- self.background_task_ended: Optional[trio.Event] = None
194
- self.stopped_event = trio.Event()
195
-
196
- self._log_stats = LoggerChannelStats(
197
- target_id=target_data.target_id,
198
- title=target_data.title,
199
- url=target_data.url,
200
- num_logs=0,
201
- last_log_time=datetime.now(),
202
- log_level_stats={}
203
- )
204
-
205
- self._logger_send_channel: Optional[trio.MemorySendChannel] = None
206
- self._logger: Optional[TargetLogger] = None
207
- self._cdp_session: Optional[CdpSession] = None
208
- self._new_target_receive_channel: Optional[tuple[trio.MemoryReceiveChannel, trio.Event]] = None
209
- self._events_receive_channels: dict[str, tuple[trio.MemoryReceiveChannel, trio.Event]] = {}
210
-
211
- @property
212
- def type_(self) -> Optional[str]:
213
- """
214
- Gets the type of the target (e.g., "page", "iframe", "service_worker").
215
-
216
- Returns:
217
- Optional[str]: The type of the target, or None if not set.
218
- """
219
-
220
- return self.target_data.type_
221
-
222
- @type_.setter
223
- def type_(self, value: Optional[str]) -> None:
224
- """
225
- Sets the type of the target and updates the logging acceptance flag.
226
-
227
- When the type is updated, this setter also re-evaluates whether
228
- this target's type should be accepted by the logging system's filters.
229
-
230
- Args:
231
- value (Optional[str]): The new type string for the target, or None to clear it.
232
- """
233
-
234
- self._target_type_log_accepted = _validate_type_filter(
235
- value,
236
- self._logger_settings.target_type_filter_mode,
237
- self._logger_settings.target_type_filter
238
- )
239
- self.target_data.type_ = value
240
-
241
- @property
242
- def attached(self) -> Optional[bool]:
243
- """
244
- Gets whether the DevTools session is currently attached to this target.
245
-
246
- Returns:
247
- Optional[bool]: True if attached, False if not, or None if status is unknown.
248
- """
249
-
250
- return self.target_data.attached
251
-
252
- @attached.setter
253
- def attached(self, value: Optional[bool]) -> None:
254
- """
255
- Sets whether the DevTools session is currently attached to this target.
256
-
257
- Args:
258
- value (Optional[bool]): The new attached status (True, False, or None).
259
- """
260
-
261
- self.target_data.attached = value
262
-
263
- @property
264
- def browser_context_id(self) -> Optional[str]:
265
- """
266
- Gets the ID of the browser context this target belongs to.
267
-
268
- Browser contexts are isolated environments, often used for incognito mode
269
- or separate user profiles.
270
-
271
- Returns:
272
- Optional[str]: The ID of the browser context, or None if not associated
273
- with a specific context.
274
- """
275
-
276
- return self.target_data.browser_context_id
277
-
278
- @browser_context_id.setter
279
- def browser_context_id(self, value: Optional[str]) -> None:
280
- """
281
- Sets the ID of the browser context this target belongs to.
282
-
283
- Args:
284
- value (Optional[str]): The new browser context ID string, or None to clear it.
285
- """
286
-
287
- self.target_data.browser_context_id = value
288
-
289
- @property
290
- def can_access_opener(self) -> Optional[bool]:
291
- """
292
- Gets whether the target can access its opener.
293
-
294
- This property indicates if the target has permission to interact with
295
- the target that opened it.
296
-
297
- Returns:
298
- Optional[bool]: True if it can access the opener, False if not,
299
- or None if the status is unknown.
300
- """
301
-
302
- return self.target_data.can_access_opener
303
-
304
- @can_access_opener.setter
305
- def can_access_opener(self, value: Optional[bool]) -> None:
306
- """
307
- Sets whether the target can access its opener.
308
-
309
- Args:
310
- value (Optional[bool]): The new status for opener access (True, False, or None).
311
- """
312
-
313
- self.target_data.can_access_opener = value
314
-
315
- @property
316
- def cdp_session(self) -> CdpSession:
317
- """
318
- Gets the active Chrome DevTools Protocol (CDP) session for this target.
319
-
320
- This session object is the primary interface for sending CDP commands
321
- and receiving events specific to this target.
322
-
323
- Returns:
324
- CdpSession: The CDP session object associated with this target.
325
- """
326
-
327
- return self._cdp_session
328
-
329
- @property
330
- def log_stats(self) -> LoggerChannelStats:
331
- """
332
- Gets the logging statistics for this specific target channel.
333
-
334
- This provides aggregated data such as total log count, last log time,
335
- and per-level log counts for this target.
336
-
337
- Returns:
338
- LoggerChannelStats: An object containing the logging statistics for this target.
339
- """
340
-
341
- return self._log_stats
342
-
343
- @property
344
- def opener_frame_id(self) -> Optional[str]:
345
- """
346
- Gets the frame ID of the target that opened this one.
347
-
348
- Returns:
349
- Optional[str]: The frame ID of the opener, or None if not applicable or known.
350
- """
351
-
352
- return self.target_data.opener_frame_id
353
-
354
- @opener_frame_id.setter
355
- def opener_frame_id(self, value: Optional[str]) -> None:
356
- """
357
- Sets the frame ID of the target that opened this one.
358
-
359
- Args:
360
- value (Optional[str]): The new opener frame ID string, or None to clear it.
361
- """
362
-
363
- self.target_data.opener_frame_id = value
364
-
365
- @property
366
- def opener_id(self) -> Optional[str]:
367
- """
368
- Gets the ID of the target that opened this one.
369
-
370
- Returns:
371
- Optional[str]: The ID of the opener target, or None if not applicable or known.
372
- """
373
-
374
- return self.target_data.opener_id
375
-
376
- @opener_id.setter
377
- def opener_id(self, value: Optional[str]) -> None:
378
- """
379
- Sets the ID of the target that opened this one.
380
-
381
- Args:
382
- value (Optional[str]): The new opener target ID string, or None to clear it.
383
- """
384
-
385
- self.target_data.opener_id = value
386
-
387
- async def stop(self):
388
- """
389
- Signals the target to begin its shutdown process.
390
-
391
- This sets the `about_to_stop_event`, which is used to gracefully
392
- terminate ongoing tasks within the target's `run` method.
393
- """
394
-
395
- self.about_to_stop_event.set()
396
-
397
- async def _close_instances(self):
398
- """
399
- Closes all associated instances and channels for this target.
400
-
401
- This includes the new target receive channel, the logger send channel,
402
- the target logger itself, and all event receive channels. It also waits
403
- for the background task to end if one was started.
404
- """
405
-
406
- if self._new_target_receive_channel is not None:
407
- await self._new_target_receive_channel[0].aclose()
408
- await self._new_target_receive_channel[1].wait()
409
-
410
- self._new_target_receive_channel = None
411
-
412
- if self._logger_send_channel is not None:
413
- await self._logger_send_channel.aclose()
414
- self._logger_send_channel = None
415
-
416
- if self._logger is not None:
417
- await self._logger.close()
418
- self._logger = None
419
-
420
- for channel in self._events_receive_channels.values():
421
- await channel[0].aclose()
422
- await channel[1].wait()
423
-
424
- self._events_receive_channels = {}
425
-
426
- if self.background_task_ended is not None:
427
- await self.background_task_ended.wait()
428
- self.background_task_ended = None
429
-
430
- async def log_error(self, error: BaseException, extra_data: Optional[dict[str, Any]] = None):
431
- """
432
- Logs an error message, including its traceback, to the relevant target's log file
433
- and also logs it globally via the standard logging module.
434
-
435
- This method formats the exception's traceback using `extract_exception_trace`
436
- and sends it as an "ERROR" level log entry. It also calls `log_exception`
437
- to ensure the error is processed by the default Python logging system.
438
-
439
- Args:
440
- error (BaseException): The exception object to be logged.
441
- extra_data (Optional[dict[str, Any]]): Optional additional data to include
442
- with the error log entry.
443
- """
444
-
445
- await self.log(
446
- level="ERROR",
447
- message=extract_exception_trace(error),
448
- source_function=" <- ".join(stack.function for stack in inspect.stack()[1:]),
449
- extra_data=extra_data
450
- )
451
- log_exception(error)
452
-
453
- async def get_devtools_object(self, path: str) -> Any:
454
- """
455
- Navigates and retrieves a specific object within the DevTools API structure.
456
-
457
- Using a dot-separated path, this method traverses the nested DevTools API objects to retrieve a target object.
458
- For example, a path like "fetch.enable" would access `self.devtools_module.fetch.enable`.
459
- Results are cached for faster access.
460
-
461
- Args:
462
- path (str): A dot-separated string representing the path to the desired DevTools API object.
463
-
464
- Returns:
465
- Any: The DevTools API object located at the specified path.
466
-
467
- Raises:
468
- cdp_end_exceptions: If a CDP-related connection error occurs.
469
- BaseException: If the object cannot be found or another error occurs during retrieval.
470
- """
471
-
472
- try:
473
- package = self.devtools_package
474
-
475
- for part in path.split("."):
476
- package = getattr(package, part)
477
-
478
- return package
479
- except cdp_end_exceptions as error:
480
- raise error
481
- except BaseException as error:
482
- await self.log_error(error=error)
483
- raise error
484
-
485
- async def _run_event_handler(
486
- self,
487
- domain_handler_ready_event: trio.Event,
488
- event_config: AbstractEvent
489
- ):
490
- """
491
- Runs a single DevTools event handler for a specific target.
492
-
493
- This method sets up a listener for the specified CDP event and continuously
494
- receives and dispatches events to the configured `handle_function`.
495
-
496
- Args:
497
- domain_handler_ready_event (trio.Event): An event that will be set once the handler is started.
498
- event_config (AbstractEvent): The configuration for the specific CDP event handler.
499
-
500
- Raises:
501
- cdp_end_exceptions: If a CDP-related connection error occurs during listener setup or event processing.
502
- BaseException: If another unexpected error occurs during listener setup or event processing.
503
- """
504
-
505
- await self.log_step(
506
- message=f"Event handler '{event_config['class_to_use_path']}' starting."
507
- )
508
-
509
- try:
510
- receiver_channel: trio.MemoryReceiveChannel = self.cdp_session.listen(
511
- await self.get_devtools_object(event_config["class_to_use_path"]),
512
- buffer_size=event_config["listen_buffer_size"]
513
- )
514
- channel_stopped_event = trio.Event()
515
-
516
- self._events_receive_channels[event_config["class_to_use_path"]] = (receiver_channel, channel_stopped_event)
517
-
518
- domain_handler_ready_event.set()
519
- handler = event_config["handle_function"]
520
- except cdp_end_exceptions as error:
521
- raise error
522
- except BaseException as error:
523
- await self.log_error(error=error)
524
- raise error
525
-
526
- await self.log_step(
527
- message=f"Event handler '{event_config['class_to_use_path']}' started."
528
- )
529
-
530
- keep_alive = True
531
- while keep_alive:
532
- try:
533
- event = await receiver_channel.receive()
534
- self._nursery_object.start_soon(handler, self, event_config, event)
535
- except* cdp_end_exceptions:
536
- keep_alive = False
537
- except* BaseException as error:
538
- await self.log_error(error=error)
539
- keep_alive = False
540
-
541
- channel_stopped_event.set()
542
-
543
- async def _run_events_handlers(self, events_ready_event: trio.Event, domain_config: AbstractDomain):
544
- """
545
- Runs all configured event handlers for a specific DevTools domain within a target.
546
-
547
- This method iterates through the event configurations for a given domain and
548
- starts a separate task for each event handler.
549
-
550
- Args:
551
- events_ready_event (trio.Event): An event that will be set once all domain handlers are started.
552
- domain_config (AbstractDomain): The configuration for the DevTools domain.
553
-
554
- Raises:
555
- cdp_end_exceptions: If a CDP-related connection error occurs during handler setup.
556
- BaseException: If another unexpected error occurs during the setup of any event handler.
557
- """
558
-
559
- await self.log_step(
560
- message=f"Domain '{domain_config['name']}' events handlers setup started."
561
- )
562
-
563
- try:
564
- events_handlers_ready_events: list[trio.Event] = []
565
-
566
- for event_name, event_config in domain_config.get("handlers", {}).items():
567
- if event_config is not None:
568
- event_handler_ready_event = trio.Event()
569
- events_handlers_ready_events.append(event_handler_ready_event)
570
-
571
- self._nursery_object.start_soon(self._run_event_handler, event_handler_ready_event, event_config)
572
-
573
- for event_handler_ready_event in events_handlers_ready_events:
574
- await event_handler_ready_event.wait()
575
-
576
- events_ready_event.set()
577
-
578
- await self.log_step(
579
- message=f"Domain '{domain_config['name']}' events handlers setup complete."
580
- )
581
- except* cdp_end_exceptions as error:
582
- raise error
583
- except* BaseException as error:
584
- await self.log_error(error=error)
585
- raise error
586
-
587
- async def _run_new_targets_listener(self, new_targets_listener_ready_event: trio.Event):
588
- """
589
- Runs a listener for new browser targets (e.g., new tabs, iframes).
590
-
591
- This method continuously listens for `TargetCreated`, `AttachedToTarget`, and
592
- `TargetInfoChanged` events, and spawns a new task to handle each new target.
593
-
594
- Args:
595
- new_targets_listener_ready_event (trio.Event): An event that will be set once the listener is started.
596
-
597
- Raises:
598
- cdp_end_exceptions: If a CDP-related connection error occurs during listener setup or event processing.
599
- BaseException: If another unexpected error occurs during listener setup or event processing.
600
- """
601
-
602
- await self.log_step(message="New Targets listener starting.")
603
-
604
- try:
605
- self._new_target_receive_channel: tuple[trio.MemoryReceiveChannel, trio.Event] = (
606
- self.cdp_session.listen(
607
- await self.get_devtools_object("target.TargetCreated"),
608
- await self.get_devtools_object("target.AttachedToTarget"),
609
- await self.get_devtools_object("target.TargetInfoChanged"),
610
- buffer_size=self._new_targets_buffer_size
611
- ),
612
- trio.Event()
613
- )
614
- new_targets_listener_ready_event.set()
615
- except cdp_end_exceptions as error:
616
- raise error
617
- except BaseException as error:
618
- await self.log_error(error=error)
619
- raise error
620
-
621
- await self.log_step(message="New Targets listener started.")
622
-
623
- keep_alive = True
624
- while keep_alive:
625
- try:
626
- event = await self._new_target_receive_channel[0].receive()
627
- self._nursery_object.start_soon(self._add_target_func, event)
628
- except* cdp_end_exceptions:
629
- keep_alive = False
630
- except* BaseException as error:
631
- await self.log_error(error=error)
632
- keep_alive = False
633
-
634
- self._new_target_receive_channel[1].set()
635
-
636
- async def _setup_new_targets_attaching(self):
637
- """
638
- Configures the DevTools protocol to discover and auto-attach to new targets.
639
-
640
- This method uses `target.setDiscoverTargets` and `target.setAutoAttach`
641
- to ensure that new browser contexts (like new tabs or iframes) are
642
- automatically detected and attached to, allowing DevTools to manage them.
643
-
644
- Raises:
645
- cdp_end_exceptions: If a CDP-related connection error occurs during setup.
646
- BaseException: If another unexpected error occurs while setting up target discovery or auto-attachment.
647
- """
648
-
649
- try:
650
- target_filter = (await self.get_devtools_object("target.TargetFilter"))(self._new_targets_filter) if self._new_targets_filter is not None else None
651
-
652
- await execute_cdp_command(
653
- self,
654
- "log",
655
- await self.get_devtools_object("target.set_discover_targets"),
656
- discover=True,
657
- filter_=target_filter,
658
- )
659
- await execute_cdp_command(
660
- self,
661
- "log",
662
- await self.get_devtools_object("target.set_auto_attach"),
663
- auto_attach=True,
664
- wait_for_debugger_on_start=True,
665
- flatten=True,
666
- filter_=target_filter,
667
- )
668
- except cdp_end_exceptions as error:
669
- raise error
670
- except BaseException as error:
671
- await self.log_error(error=error)
672
- raise error
673
-
674
- async def _setup_target(self):
675
- """
676
- Sets up a new browser target for DevTools interaction.
677
-
678
- This involves enabling target discovery and auto-attachment, and
679
- starting event handlers for configured DevTools domains within the target's session.
680
-
681
- Raises:
682
- cdp_end_exceptions: If a CDP-related connection error occurs during setup.
683
- BaseException: If any other unexpected error occurs during the target setup process.
684
- """
685
-
686
- try:
687
- await self.log_step(message="Target setup started.")
688
-
689
- await self._setup_new_targets_attaching()
690
-
691
- target_ready_events: list[trio.Event] = []
692
-
693
- new_targets_listener_ready_event = trio.Event()
694
- target_ready_events.append(new_targets_listener_ready_event)
695
-
696
- self._nursery_object.start_soon(self._run_new_targets_listener, new_targets_listener_ready_event)
697
-
698
- for domain_name, domain_config in self._domains.items():
699
- if domain_config.get("enable_func_path", None) is not None:
700
- enable_func_kwargs = domain_config.get("enable_func_kwargs", {})
701
- await execute_cdp_command(
702
- self,
703
- "raise",
704
- await self.get_devtools_object(domain_config["enable_func_path"]),
705
- **enable_func_kwargs
706
- )
707
-
708
- domain_handlers_ready_event = trio.Event()
709
- target_ready_events.append(domain_handlers_ready_event)
710
- self._nursery_object.start_soon(self._run_events_handlers, domain_handlers_ready_event, domain_config)
711
-
712
- for domain_handlers_ready_event in target_ready_events:
713
- await domain_handlers_ready_event.wait()
714
-
715
- await execute_cdp_command(
716
- self,
717
- "log",
718
- await self.get_devtools_object("runtime.run_if_waiting_for_debugger")
719
- )
720
-
721
- await self.log_step(message="Target setup complete.")
722
- except* cdp_end_exceptions as error:
723
- raise error
724
- except* BaseException as error:
725
- await self.log_error(error=error)
726
- raise error
727
-
728
- @property
729
- def target_id(self) -> Optional[str]:
730
- """
731
- Gets the unique identifier for the target.
732
-
733
- Returns:
734
- Optional[str]: The unique ID of the target, or None if not set.
735
- """
736
-
737
- return self.target_data.target_id
738
-
739
- @target_id.setter
740
- def target_id(self, value: Optional[str]) -> None:
741
- """
742
- Sets the unique identifier for the target and updates associated log statistics.
743
-
744
- When the target ID is updated, this setter ensures that the `target_data`
745
- object reflects the new ID and that the `_log_stats` object
746
- (which tracks per-channel statistics) is also updated.
747
-
748
- Args:
749
- value (Optional[str]): The new unique ID string to set, or None to clear it.
750
- """
751
-
752
- self._log_stats.target_id = value
753
- self.target_data.target_id = value
754
-
755
- async def run(self):
756
- """
757
- Runs the DevTools session for this target, handling its lifecycle.
758
-
759
- This method establishes the CDP session, sets up event listeners,
760
- runs the optional background task, and waits for a stop signal.
761
- It handles various exceptions during its lifecycle, logging them
762
- and ensuring graceful shutdown.
763
- """
764
-
765
- try:
766
- self._logger_send_channel, self._logger = build_target_logger(self.target_data, self._nursery_object, self._logger_settings)
767
-
768
- if self._target_type_log_accepted:
769
- await self._logger.run()
770
-
771
- await self.log_step(message=f"Target '{self.target_id}' added.")
772
-
773
- async with open_cdp(self.websocket_url) as new_connection:
774
- async with new_connection.open_session(self.target_id) as new_session:
775
- self._cdp_session = new_session
776
-
777
- await self._setup_target()
778
-
779
- if self._target_background_task is not None:
780
- self._nursery_object.start_soon(_background_task_decorator(self._target_background_task), self)
781
-
782
- await wait_one(self.exit_event, self.about_to_stop_event)
783
- except* (BrowserError, RuntimeError):
784
- self.about_to_stop_event.set()
785
- except* cdp_end_exceptions:
786
- self.about_to_stop_event.set()
787
- except* BaseException as error:
788
- self.about_to_stop_event.set()
789
- await self.log_error(error=error)
790
- finally:
791
- await self._close_instances()
792
- await self._remove_target_func(self)
793
- self.stopped_event.set()
794
-
795
- @property
796
- def subtype(self) -> Optional[str]:
797
- """
798
- Gets the subtype of the target, if applicable.
799
-
800
- Returns:
801
- Optional[str]: The subtype of the target, or None if not set.
802
- """
803
-
804
- return self.target_data.subtype
805
-
806
- @subtype.setter
807
- def subtype(self, value: Optional[str]) -> None:
808
- """
809
- Sets the subtype of the target.
810
-
811
- Args:
812
- value (Optional[str]): The new subtype string to set, or None to clear it.
813
- """
814
-
815
- self.target_data.subtype = value
816
-
817
- @property
818
- def target_type_log_accepted(self) -> bool:
819
- """
820
- Checks if this target's type is accepted by the logger's filter.
821
-
822
- This property reflects whether log entries originating from this target's
823
- type are configured to be processed by the logging system.
824
-
825
- Returns:
826
- bool: True if the target's type is accepted for logging, False otherwise.
827
- """
828
-
829
- return self._target_type_log_accepted
830
-
831
- @property
832
- def title(self) -> Optional[str]:
833
- """
834
- Gets the title of the target (e.g., the page title).
835
-
836
- Returns:
837
- Optional[str]: The current title of the target, or None if not available.
838
- """
839
-
840
- return self.target_data.title
841
-
842
- @title.setter
843
- def title(self, value: Optional[str]) -> None:
844
- """
845
- Sets the title of the target and updates associated log statistics.
846
-
847
- When the title is updated, this setter ensures that the `target_data`
848
- object reflects the new title and that the `_log_stats` object
849
- (which tracks per-channel statistics) is also updated.
850
-
851
- Args:
852
- value (Optional[str]): The new title string to set, or None to clear it.
853
- """
854
-
855
- self._log_stats.title = value
856
- self.target_data.title = value
857
-
858
- @property
859
- def url(self) -> Optional[str]:
860
- """
861
- Gets the URL of the target.
862
-
863
- Returns:
864
- Optional[str]: The current URL of the target, or None if not available.
865
- """
866
-
867
- return self.target_data.url
868
-
869
- @url.setter
870
- def url(self, value: Optional[str]) -> None:
871
- """
872
- Sets the URL of the target and updates associated log statistics.
873
-
874
- When the URL is updated, this setter ensures that the `target_data`
875
- object reflects the new URL and that the `_log_stats` object
876
- (which tracks per-channel statistics) is also updated.
877
-
878
- Args:
879
- value (Optional[str]): The new URL string to set, or None to clear it.
880
- """
881
-
882
- self._log_stats.url = value
883
- self.target_data.url = value
884
-
885
- async def log(
886
- self,
887
- level: LogLevelsType,
888
- message: str,
889
- source_function: Optional[str] = None,
890
- extra_data: Optional[dict[str, Any]] = None
891
- ):
892
- """
893
- Logs a message to the internal logger manager, automatically determining the source function.
894
-
895
- This method acts as a convenient wrapper around the underlying `_logger.log` method.
896
- If `source_function` is not explicitly provided, it automatically determines the
897
- calling function's name from the call stack to enrich the log entry.
898
-
899
- Args:
900
- level (LogLevelsType): The severity level of the log (e.g., "INFO", "ERROR").
901
- message (str): The main log message.
902
- source_function (Optional[str]): The name of the function that generated the log.
903
- If None, the function will attempt to determine it from the call stack.
904
- extra_data (Optional[dict[str, Any]]): Optional additional data to associate
905
- with the log entry.
906
- """
907
-
908
- log_entry = LogEntry(
909
- target_data=self.target_data,
910
- message=message,
911
- level=level,
912
- timestamp=datetime.now(),
913
- source_function=" <- ".join(stack.function for stack in inspect.stack()[1:])
914
- if source_function is None
915
- else source_function,
916
- extra_data=extra_data
917
- )
918
- await self._add_log_func(log_entry)
919
-
920
- if self._target_type_log_accepted and self._logger is not None and self._logger_send_channel is not None:
921
- await self._log_stats.add_log(log_entry)
922
- await self._logger.run()
923
-
924
- try:
925
- self._logger_send_channel.send_nowait(log_entry)
926
- except trio.WouldBlock:
927
- warnings.warn(
928
- f"WARNING: Log channel for session {self.target_id} is full. Log dropped:\n{log_entry.to_string()}"
929
- )
930
- except trio.BrokenResourceError:
931
- warnings.warn(
932
- f"WARNING: Log channel for session {self.target_id} is broken. Log dropped:\n{log_entry.to_string()}"
933
- )
934
-
935
- async def log_step(self, message: str):
936
- """
937
- Logs an informational step message using the internal logger manager.
938
-
939
- This is a convenience method for logging "INFO" level messages,
940
- automatically determining the source function from the call stack.
941
-
942
- Args:
943
- message (str): The step message to log.
944
- """
945
-
946
- await self.log(
947
- level="INFO",
948
- message=message,
949
- source_function=" <- ".join(stack.function for stack in inspect.stack()[1:])
950
- )
951
-
952
-
953
- class DevTools:
954
- """
955
- Base class for handling DevTools functionalities in Selenium WebDriver.
956
-
957
- Provides an interface to interact with Chrome DevTools Protocol (CDP)
958
- for advanced browser control and monitoring. This class supports event handling
959
- and allows for dynamic modifications of browser behavior, such as network request interception,
960
- by using an asynchronous context manager.
961
-
962
- Attributes:
963
- _webdriver ("BrowserWebDriver"): The parent WebDriver instance associated with this DevTools instance.
964
- _new_targets_filter (Optional[list[dict[str, Any]]]): Processed filters for new targets.
965
- _new_targets_buffer_size (int): Buffer size for new target events.
966
- _target_background_task (Optional[devtools_background_func_type]): Optional background task for targets.
967
- _logger_settings (LoggerSettings): Logging configuration for the entire DevTools manager.
968
- _bidi_connection (Optional[AbstractAsyncContextManager[BidiConnection, Any]]): Asynchronous context manager for the BiDi connection.
969
- _bidi_connection_object (Optional[BidiConnection]): The BiDi connection object when active.
970
- _nursery (Optional[AbstractAsyncContextManager[trio.Nursery, object]]): Asynchronous context manager for the Trio nursery.
971
- _nursery_object (Optional[trio.Nursery]): The Trio nursery object when active, managing concurrent tasks.
972
- _domains_settings (Domains): Settings for configuring DevTools domain handlers.
973
- _handling_targets (dict[str, DevToolsTarget]): Dictionary of target IDs currently being handled by event listeners.
974
- targets_lock (trio.Lock): A lock used for synchronizing access to shared resources, like the list of handled targets.
975
- exit_event (Optional[trio.Event]): Trio Event to signal exiting of DevTools event handling.
976
- _is_active (bool): Flag indicating if the DevTools event handler is currently active.
977
- _is_closing (bool): Flag indicating if the DevTools manager is in the process of closing.
978
- _num_logs (int): Total count of all log entries across all targets.
979
- _targets_types_stats (dict[str, TargetTypeStats]): Statistics for each target type.
980
- _log_level_stats (dict[str, LogLevelStats]): Overall statistics for each log level.
981
- _main_logger (Optional[MainLogger]): The main logger instance.
982
- _main_logger_send_channel (Optional[trio.MemorySendChannel[MainLogEntry]]): Send channel for the main logger.
983
-
984
- EXAMPLES
985
- ________
986
- >>> from osn_selenium.webdrivers.Chrome.webdriver import ChromeWebDriver
987
- ... from osn_selenium.dev_tools.domains import DomainsSettings
988
- ...
989
- ... async def main():
990
- ... driver = ChromeWebDriver("path/to/chromedriver")
991
- ... driver.dev_tools.set_domains_handlers(DomainsSettings(...))
992
- ...
993
- ... driver_wrapper = driver.to_wrapper()
994
- ...
995
- ... # Configure domain handlers here.
996
- ... async with driver.dev_tools:
997
- ... # DevTools event handling is active within this block.
998
- ... await driver_wrapper.search_url("https://example.com")
999
- ... # DevTools event handling is deactivated after exiting the block.
1000
- """
1001
-
1002
- def __init__(
1003
- self,
1004
- parent_webdriver: "BrowserWebDriver",
1005
- devtools_settings: Optional[DevToolsSettings] = None
1006
- ):
1007
- """
1008
- Initializes the DevTools manager.
1009
-
1010
- Args:
1011
- parent_webdriver ("BrowserWebDriver"): The WebDriver instance to which this DevTools manager is attached.
1012
- devtools_settings (Optional[DevToolsSettings]): Configuration settings for DevTools.
1013
- If None, default settings will be used.
1014
- """
1015
-
1016
- if devtools_settings is None:
1017
- devtools_settings = DevToolsSettings()
1018
-
1019
- self._webdriver = parent_webdriver
1020
-
1021
- self._new_targets_filter = [filter_.to_dict() for filter_ in devtools_settings.new_targets_filter] if devtools_settings.new_targets_filter is not None else None
1022
-
1023
- self._new_targets_buffer_size = devtools_settings.new_targets_buffer_size
1024
- self._target_background_task = devtools_settings.target_background_task
1025
- self._logger_settings = devtools_settings.logger_settings
1026
- self._bidi_connection: Optional[AbstractAsyncContextManager[BidiConnection, Any]] = None
1027
- self._bidi_connection_object: Optional[BidiConnection] = None
1028
- self._nursery: Optional[AbstractAsyncContextManager[trio.Nursery, Optional[bool]]] = None
1029
- self._nursery_object: Optional[trio.Nursery] = None
1030
- self._domains_settings: Domains = {}
1031
- self._handling_targets: dict[str, DevToolsTarget] = {}
1032
- self.targets_lock = trio.Lock()
1033
- self._websocket_url: Optional[str] = None
1034
- self.exit_event: Optional[trio.Event] = None
1035
- self._is_active = False
1036
- self._is_closing = False
1037
- self._num_logs = 0
1038
- self._targets_types_stats: dict[str, TargetTypeStats] = {}
1039
- self._log_level_stats: dict[str, LogLevelStats] = {}
1040
- self._main_logger: Optional[MainLogger] = None
1041
- self._main_logger_send_channel: Optional[trio.MemorySendChannel[MainLogEntry]] = None
1042
-
1043
- _prepare_log_dir(devtools_settings.logger_settings)
1044
-
1045
- async def _main_log(self):
1046
- """
1047
- Sends updated overall logging statistics to the main logger.
1048
-
1049
- This method constructs a `MainLogEntry` with current statistics and
1050
- sends it to the `_main_logger_send_channel`. If the channel buffer is full,
1051
- the log is dropped silently.
1052
- """
1053
-
1054
- try:
1055
- if self._main_logger_send_channel is not None and self._main_logger is not None:
1056
- log_entry = MainLogEntry(
1057
- num_channels=len(self._handling_targets),
1058
- targets_types_stats=self._targets_types_stats,
1059
- num_logs=self._num_logs,
1060
- log_level_stats=self._log_level_stats,
1061
- channels_stats=list(
1062
- map(
1063
- lambda target: target.log_stats,
1064
- filter(
1065
- lambda target: target.target_type_log_accepted,
1066
- self._handling_targets.values()
1067
- )
1068
- )
1069
- ),
1070
- )
1071
- self._main_logger_send_channel.send_nowait(log_entry)
1072
- except (trio.WouldBlock, trio.BrokenResourceError):
1073
- pass
1074
- except cdp_end_exceptions as error:
1075
- raise error
1076
- except BaseException as error:
1077
- log_exception(error)
1078
- raise error
1079
-
1080
- async def _add_log(self, log_entry: LogEntry):
1081
- """
1082
- Updates internal logging statistics based on a new log entry.
1083
-
1084
- This method increments total log counts and updates per-channel and per-level statistics.
1085
- It also triggers an update to the main logger.
1086
-
1087
- Args:
1088
- log_entry (LogEntry): The log entry to use for updating statistics.
1089
-
1090
- Raises:
1091
- BaseException: Catches and logs any unexpected errors during the log aggregation process.
1092
- """
1093
-
1094
- try:
1095
- self._num_logs += 1
1096
-
1097
- if log_entry.level not in self._log_level_stats:
1098
- self._log_level_stats[log_entry.level] = LogLevelStats(num_logs=1, last_log_time=log_entry.timestamp)
1099
- else:
1100
- self._log_level_stats[log_entry.level].num_logs += 1
1101
- self._log_level_stats[log_entry.level].last_log_time = log_entry.timestamp
1102
-
1103
- await self._main_log()
1104
- except cdp_end_exceptions:
1105
- pass
1106
- except BaseException as error:
1107
- log_exception(error)
1108
- raise error
1109
-
1110
- async def _remove_target(self, target: DevToolsTarget) -> Optional[bool]:
1111
- """
1112
- Removes a target ID from the list of currently handled targets.
1113
-
1114
- This method also triggers the removal of the target's specific logger channel
1115
- and updates overall logging statistics.
1116
-
1117
- Args:
1118
- target (DevToolsTarget): The target instance to remove.
1119
-
1120
- Returns:
1121
- Optional[bool]: True if the target ID was successfully removed, False if it was not found.
1122
- Returns None if an exception occurs.
1123
- """
1124
-
1125
- try:
1126
- async with self.targets_lock:
1127
- if target.target_id in self._handling_targets:
1128
- self._targets_types_stats[target.type_].num_targets -= 1
1129
-
1130
- target = self._handling_targets.pop(target.target_id)
1131
- await target.log_step(message=f"Target '{target.target_id}' removed.")
1132
- await target.stop()
1133
-
1134
- await self._main_log()
1135
-
1136
- return True
1137
- else:
1138
- return False
1139
- except cdp_end_exceptions:
1140
- pass
1141
- except BaseException as error:
1142
- log_exception(error)
1143
-
1144
- @property
1145
- def _devtools_package(self) -> Any:
1146
- """
1147
- Retrieves the DevTools protocol package from the active BiDi connection.
1148
-
1149
- Returns:
1150
- Any: The DevTools protocol package object, providing access to CDP domains and commands.
1151
-
1152
- Raises:
1153
- BidiConnectionNotEstablishedError: If the BiDi connection is not active.
1154
- """
1155
-
1156
- try:
1157
- if self._bidi_connection_object is not None:
1158
- return self._bidi_connection_object.devtools
1159
- else:
1160
- raise BidiConnectionNotEstablishedError()
1161
- except cdp_end_exceptions as error:
1162
- raise error
1163
- except BaseException as error:
1164
- log_exception(error)
1165
- raise error
1166
-
1167
- async def _add_target(self, target_event: Any) -> Optional[bool]:
1168
- """
1169
- Adds a new browser target to the manager based on a target event.
1170
-
1171
- This method processes events like `TargetCreated` or `AttachedToTarget`
1172
- to initialize and manage new `DevToolsTarget` instances. It ensures
1173
- that targets are not added if the manager is closing or if they already exist.
1174
-
1175
- Args:
1176
- target_event (Any): The event object containing target information.
1177
- Expected to have a `target_info` attribute or be the target info itself.
1178
-
1179
- Returns:
1180
- Optional[bool]: True if a new target was successfully added and started,
1181
- False if the target already existed or was filtered,
1182
- or None if an error occurred.
1183
-
1184
- Raises:
1185
- BaseException: Catches and logs any unexpected errors during target addition.
1186
- """
1187
-
1188
- try:
1189
- if hasattr(target_event, "target_info"):
1190
- target_info = target_event.target_info
1191
- else:
1192
- target_info = target_event
1193
-
1194
- async with self.targets_lock:
1195
- target_id = target_info.target_id
1196
-
1197
- if self._is_closing:
1198
- return False
1199
-
1200
- if target_id not in self._handling_targets:
1201
- self._handling_targets[target_id] = DevToolsTarget(
1202
- target_data=TargetData(
1203
- target_id=target_id,
1204
- type_=target_info.type_,
1205
- title=target_info.title,
1206
- url=target_info.url,
1207
- attached=target_info.attached,
1208
- can_access_opener=target_info.can_access_opener,
1209
- opener_id=target_info.opener_id,
1210
- opener_frame_id=target_info.opener_frame_id,
1211
- browser_context_id=target_info.browser_context_id,
1212
- subtype=target_info.subtype,
1213
- ),
1214
- logger_settings=self._logger_settings,
1215
- devtools_package=self._devtools_package,
1216
- websocket_url=self._websocket_url,
1217
- new_targets_filter=self._new_targets_filter,
1218
- new_targets_buffer_size=self._new_targets_buffer_size,
1219
- domains=self._domains_settings,
1220
- nursery=self._nursery_object,
1221
- exit_event=self.exit_event,
1222
- target_background_task=self._target_background_task,
1223
- add_target_func=self._add_target,
1224
- remove_target_func=self._remove_target,
1225
- add_log_func=self._add_log,
1226
- )
1227
-
1228
- if target_info.type_ not in self._targets_types_stats:
1229
- self._targets_types_stats[target_info.type_] = TargetTypeStats(num_targets=1)
1230
- else:
1231
- self._targets_types_stats[target_info.type_].num_targets += 1
1232
-
1233
- await self._main_log()
1234
-
1235
- self._nursery_object.start_soon(self._handling_targets[target_id].run,)
1236
-
1237
- return True
1238
- else:
1239
- self._handling_targets[target_id].type_ = target_info.type_
1240
- self._handling_targets[target_id].title = target_info.title
1241
- self._handling_targets[target_id].url = target_info.url
1242
- self._handling_targets[target_id].attached = target_info.attached
1243
- self._handling_targets[target_id].can_access_opener = target_info.can_access_opener
1244
- self._handling_targets[target_id].opener_id = target_info.opener_id
1245
- self._handling_targets[target_id].opener_frame_id = target_info.opener_frame_id
1246
- self._handling_targets[target_id].browser_context_id = target_info.browser_context_id
1247
- self._handling_targets[target_id].subtype = target_info.subtype
1248
-
1249
- return False
1250
- except* cdp_end_exceptions:
1251
- pass
1252
- except* BaseException as error:
1253
- log_exception(error)
1254
- raise error
1255
-
1256
- async def _get_devtools_object(self, path: str) -> Any:
1257
- """
1258
- Navigates and retrieves a specific object within the DevTools API structure.
1259
-
1260
- Using a dot-separated path, this method traverses the nested DevTools API objects to retrieve a target object.
1261
- For example, a path like "fetch.enable" would access `self.devtools_module.fetch.enable`.
1262
- Results are cached for faster access.
1263
-
1264
- Args:
1265
- path (str): A dot-separated string representing the path to the desired DevTools API object.
1266
-
1267
- Returns:
1268
- Any: The DevTools API object located at the specified path.
1269
-
1270
- Raises:
1271
- cdp_end_exceptions: If a CDP-related connection error occurs.
1272
- BaseException: If the object cannot be found or another error occurs during retrieval.
1273
- """
1274
-
1275
- try:
1276
- package = self._devtools_package
1277
-
1278
- for part in path.split("."):
1279
- package = getattr(package, part)
1280
-
1281
- return package
1282
- except cdp_end_exceptions as error:
1283
- raise error
1284
- except BaseException as error:
1285
- log_exception(error)
1286
- raise error
1287
-
1288
- async def _get_all_targets(self) -> list[Any]:
1289
- """
1290
- Retrieves a list of all currently active browser targets.
1291
-
1292
- Returns:
1293
- list[Any]: A list of target objects, each containing information like target ID, type, and URL.
1294
-
1295
- Raises:
1296
- BidiConnectionNotEstablishedError: If the BiDi connection is not active.
1297
- """
1298
-
1299
- try:
1300
- if self._bidi_connection_object is not None:
1301
- targets_filter = (await self._get_devtools_object("target.TargetFilter"))(
1302
- [
1303
- {"exclude": False, "type": "page"},
1304
- {"exclude": False, "type": "tab"},
1305
- {"exclude": True}
1306
- ]
1307
- )
1308
-
1309
- return await self._bidi_connection_object.session.execute(self._devtools_package.target.get_targets(targets_filter))
1310
- else:
1311
- raise BidiConnectionNotEstablishedError()
1312
- except cdp_end_exceptions as error:
1313
- raise error
1314
- except BaseException as error:
1315
- log_exception(error)
1316
- raise error
1317
-
1318
- def _get_websocket_url(self) -> Optional[str]:
1319
- """
1320
- Retrieves the WebSocket URL for DevTools from the WebDriver.
1321
-
1322
- This method attempts to get the WebSocket URL from the WebDriver capabilities or by directly querying the CDP details.
1323
- The WebSocket URL is necessary to establish a connection to the browser's DevTools.
1324
-
1325
- Returns:
1326
- Optional[str]: The WebSocket URL for DevTools, or None if it cannot be retrieved.
1327
-
1328
- Raises:
1329
- cdp_end_exceptions: If a CDP-related connection error occurs.
1330
- BaseException: If another unexpected error occurs during URL retrieval.
1331
- """
1332
-
1333
- try:
1334
- driver = self._webdriver.driver
1335
-
1336
- if driver is None:
1337
- self._websocket_url = None
1338
-
1339
- if driver.caps.get("se:cdp"):
1340
- self._websocket_url = driver.caps.get("se:cdp")
1341
-
1342
- self._websocket_url = driver._get_cdp_details()[1]
1343
- except cdp_end_exceptions as error:
1344
- raise error
1345
- except BaseException as error:
1346
- log_exception(error)
1347
- raise error
1348
-
1349
- async def __aenter__(self):
1350
- """
1351
- Enters the asynchronous context for DevTools event handling.
1352
-
1353
- This method establishes the BiDi connection, initializes the Trio nursery,
1354
- sets up the main target, and starts listening for DevTools events.
1355
-
1356
- Raises:
1357
- CantEnterDevToolsContextError: If the WebDriver is not initialized.
1358
- BaseException: If any other unexpected error occurs during context entry.
1359
- """
1360
-
1361
- if self._webdriver.driver is None:
1362
- raise CantEnterDevToolsContextError("Driver is not initialized")
1363
-
1364
- self._bidi_connection: AbstractAsyncContextManager[BidiConnection, Any] = self._webdriver.driver.bidi_connection()
1365
- self._bidi_connection_object = await self._bidi_connection.__aenter__()
1366
-
1367
- self._nursery = trio.open_nursery()
1368
- self._nursery_object = await self._nursery.__aenter__()
1369
-
1370
- self._get_websocket_url()
1371
-
1372
- self._main_logger_send_channel, self._main_logger = build_main_logger(self._nursery_object, self._logger_settings)
1373
- await self._main_logger.run()
1374
-
1375
- self.exit_event = trio.Event()
1376
-
1377
- main_target = (await self._get_all_targets())[0]
1378
- await self._add_target(main_target)
1379
-
1380
- self._is_active = True
1381
-
1382
- async def __aexit__(
1383
- self,
1384
- exc_type: Optional[type],
1385
- exc_val: Optional[BaseException],
1386
- exc_tb: Optional[TracebackType]
1387
- ):
1388
- """
1389
- Asynchronously exits the DevTools event handling context.
1390
-
1391
- This method is called when exiting an `async with` block with a DevTools instance.
1392
- It ensures that all event listeners are cancelled, the Trio nursery is closed,
1393
- and the BiDi connection is properly shut down. Cleanup attempts are made even if
1394
- an exception occurred within the `async with` block.
1395
-
1396
- Args:
1397
- exc_type (Optional[type[BaseException]]): The exception type, if any, that caused the context to be exited.
1398
- exc_val (Optional[BaseException]): The exception value, if any.
1399
- exc_tb (Optional[TracebackType]): The exception traceback, if any.
1400
- """
1401
-
1402
- @log_on_error
1403
- async def _stop_main_logger():
1404
- """Stops the main logger and closes its channels."""
1405
-
1406
- if self._main_logger_send_channel is not None:
1407
- await self._main_logger_send_channel.aclose()
1408
- self._main_logger_send_channel = None
1409
-
1410
- if self._main_logger is not None:
1411
- await self._main_logger.close()
1412
- self._main_logger = None
1413
-
1414
- @log_on_error
1415
- async def _stop_all_targets():
1416
- """Signals all active targets to stop and waits for their completion."""
1417
-
1418
- for target in self._handling_targets.copy().values():
1419
- await target.stop()
1420
- await target.stopped_event.wait()
1421
-
1422
- self._handling_targets = {}
1423
-
1424
- @log_on_error
1425
- async def _close_nursery():
1426
- """Asynchronously exits the Trio nursery context manager."""
1427
-
1428
- if self._nursery_object is not None:
1429
- self._nursery_object.cancel_scope.cancel()
1430
- self._nursery_object = None
1431
-
1432
- if self._nursery is not None:
1433
- await self._nursery.__aexit__(exc_type, exc_val, exc_tb)
1434
- self._nursery = None
1435
-
1436
- @log_on_error
1437
- async def _close_bidi_connection():
1438
- """Asynchronously exits the BiDi connection context manager."""
1439
-
1440
- if self._bidi_connection is not None:
1441
- await self._bidi_connection.__aexit__(exc_type, exc_val, exc_tb)
1442
- self._bidi_connection = None
1443
- self._bidi_connection_object = None
1444
-
1445
- if self._is_active:
1446
- self._is_closing = True
1447
- self.exit_event.set()
1448
-
1449
- await _stop_main_logger()
1450
- await _stop_all_targets()
1451
- await _close_nursery()
1452
- await _close_bidi_connection()
1453
-
1454
- self.exit_event = None
1455
- self._websocket_url = None
1456
- self._num_logs = 0
1457
- self._targets_types_stats = {}
1458
- self._log_level_stats = {}
1459
- self._is_active = False
1460
- self._is_closing = False
1461
-
1462
- @property
1463
- def is_active(self) -> bool:
1464
- """
1465
- Checks if DevTools is currently active.
1466
-
1467
- Returns:
1468
- bool: True if DevTools event handler context manager is active, False otherwise.
1469
- """
1470
-
1471
- return self._is_active
1472
-
1473
- @warn_if_active
1474
- def _remove_handler_settings(self, domain: domains_type):
1475
- """
1476
- Removes the settings for a specific domain.
1477
-
1478
- This is an internal method intended to be used only when the DevTools context is not active.
1479
- It uses the `@warn_if_active` decorator to log a warning if called incorrectly.
1480
-
1481
- Args:
1482
- domain (domains_type): The name of the domain to remove settings for.
1483
- """
1484
-
1485
- self._domains_settings.pop(domain, None)
1486
-
1487
- def remove_domains_handlers(self, domains: Union[domains_type, Sequence[domains_type]]):
1488
- """
1489
- Removes handler settings for one or more DevTools domains.
1490
-
1491
- This method can be called with a single domain name or a sequence of domain names.
1492
- It should only be called when the DevTools context is not active.
1493
-
1494
- Args:
1495
- domains (Union[domains_type, Sequence[domains_type]]): A single domain name as a string,
1496
- or a sequence of domain names to be removed.
1497
-
1498
- Raises:
1499
- TypeError: If the `domains` argument is not a string or a sequence of strings.
1500
- """
1501
-
1502
- if isinstance(domains, Sequence) and all(isinstance(domain, str) for domain in domains):
1503
- for domain in domains:
1504
- self._remove_handler_settings(domain)
1505
- elif isinstance(domains, str):
1506
- self._remove_handler_settings(domains)
1507
- else:
1508
- raise TypeError(f"domains must be a str or a sequence of str, got {type(domains)}.")
1509
-
1510
- @warn_if_active
1511
- def _set_handler_settings(self, domain: domains_type, settings: domains_classes_type):
1512
- """
1513
- Sets the handler settings for a specific domain.
1514
-
1515
- This is an internal method intended to be used only when the DevTools context is not active.
1516
- It uses the `@warn_if_active` decorator to log a warning if called incorrectly.
1517
-
1518
- Args:
1519
- domain (domains_type): The name of the domain to configure.
1520
- settings (domains_classes_type): The configuration settings for the domain.
1521
- """
1522
-
1523
- self._domains_settings[domain] = settings
1524
-
1525
- def set_domains_handlers(self, settings: DomainsSettings):
1526
- """
1527
- Sets handler settings for multiple domains from a DomainsSettings object.
1528
-
1529
- This method iterates through the provided settings and applies them to the corresponding domains.
1530
- It should only be called when the DevTools context is not active.
1531
-
1532
- Args:
1533
- settings (DomainsSettings): An object containing the configuration for one or more domains.
1534
- """
1535
-
1536
- for domain_name, domain_settings in settings.to_dict().items():
1537
- self._set_handler_settings(domain_name, domain_settings)
1538
-
1539
- @property
1540
- def websocket_url(self) -> Optional[str]:
1541
- """
1542
- Gets the WebSocket URL for the DevTools session.
1543
-
1544
- This URL is used to establish a direct Chrome DevTools Protocol (CDP) connection
1545
- to the browser, enabling low-level control and event listening.
1546
-
1547
- Returns:
1548
- Optional[str]: The WebSocket URL, or None if it has not been retrieved yet.
1549
- """
1550
-
1551
- return self._websocket_url