pydoll-python 2.12.3__tar.gz → 2.13.0__tar.gz

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 (94) hide show
  1. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/PKG-INFO +51 -1
  2. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/README.md +50 -0
  3. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/constants.py +79 -0
  4. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/elements/mixins/find_elements_mixin.py +33 -2
  5. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/elements/web_element.py +122 -571
  6. pydoll_python-2.13.0/pydoll/interactions/__init__.py +25 -0
  7. pydoll_python-2.13.0/pydoll/interactions/iframe.py +359 -0
  8. pydoll_python-2.13.0/pydoll/interactions/keyboard.py +463 -0
  9. pydoll_python-2.13.0/pydoll/interactions/scroll.py +437 -0
  10. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pyproject.toml +1 -1
  11. pydoll_python-2.12.3/pydoll/interactions/__init__.py +0 -4
  12. pydoll_python-2.12.3/pydoll/interactions/keyboard.py +0 -178
  13. pydoll_python-2.12.3/pydoll/interactions/scroll.py +0 -121
  14. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/LICENSE +0 -0
  15. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/__init__.py +0 -0
  16. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/__init__.py +0 -0
  17. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/chromium/__init__.py +0 -0
  18. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/chromium/base.py +0 -0
  19. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/chromium/chrome.py +0 -0
  20. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/chromium/edge.py +0 -0
  21. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/interfaces.py +0 -0
  22. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/managers/__init__.py +0 -0
  23. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/managers/browser_options_manager.py +0 -0
  24. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/managers/browser_process_manager.py +0 -0
  25. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/managers/proxy_manager.py +0 -0
  26. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/managers/temp_dir_manager.py +0 -0
  27. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/options.py +0 -0
  28. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/requests/__init__.py +0 -0
  29. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/requests/request.py +0 -0
  30. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/requests/response.py +0 -0
  31. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/browser/tab.py +0 -0
  32. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/__init__.py +0 -0
  33. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/browser_commands.py +0 -0
  34. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/dom_commands.py +0 -0
  35. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/fetch_commands.py +0 -0
  36. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/input_commands.py +0 -0
  37. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/network_commands.py +0 -0
  38. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/page_commands.py +0 -0
  39. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/runtime_commands.py +0 -0
  40. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/storage_commands.py +0 -0
  41. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/commands/target_commands.py +0 -0
  42. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/connection/__init__.py +0 -0
  43. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/connection/connection_handler.py +0 -0
  44. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/connection/managers/__init__.py +0 -0
  45. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/connection/managers/commands_manager.py +0 -0
  46. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/connection/managers/events_manager.py +0 -0
  47. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/decorators.py +0 -0
  48. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/elements/__init__.py +0 -0
  49. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/elements/mixins/__init__.py +0 -0
  50. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/exceptions.py +0 -0
  51. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/__init__.py +0 -0
  52. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/base.py +0 -0
  53. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/browser/__init__.py +0 -0
  54. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/browser/events.py +0 -0
  55. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/browser/methods.py +0 -0
  56. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/browser/types.py +0 -0
  57. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/debugger/types.py +0 -0
  58. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/dom/__init__.py +0 -0
  59. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/dom/events.py +0 -0
  60. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/dom/methods.py +0 -0
  61. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/dom/types.py +0 -0
  62. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/emulation/types.py +0 -0
  63. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/fetch/__init__.py +0 -0
  64. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/fetch/events.py +0 -0
  65. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/fetch/methods.py +0 -0
  66. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/fetch/types.py +0 -0
  67. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/input/__init__.py +0 -0
  68. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/input/events.py +0 -0
  69. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/input/methods.py +0 -0
  70. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/input/types.py +0 -0
  71. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/io/types.py +0 -0
  72. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/network/__init__.py +0 -0
  73. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/network/events.py +0 -0
  74. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/network/methods.py +0 -0
  75. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/network/types.py +0 -0
  76. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/page/__init__.py +0 -0
  77. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/page/events.py +0 -0
  78. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/page/methods.py +0 -0
  79. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/page/types.py +0 -0
  80. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/runtime/__init__.py +0 -0
  81. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/runtime/events.py +0 -0
  82. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/runtime/methods.py +0 -0
  83. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/runtime/types.py +0 -0
  84. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/security/types.py +0 -0
  85. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/storage/__init__.py +0 -0
  86. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/storage/events.py +0 -0
  87. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/storage/methods.py +0 -0
  88. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/storage/types.py +0 -0
  89. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/target/__init__.py +0 -0
  90. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/target/events.py +0 -0
  91. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/target/methods.py +0 -0
  92. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/protocol/target/types.py +0 -0
  93. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/py.typed +0 -0
  94. {pydoll_python-2.12.3 → pydoll_python-2.13.0}/pydoll/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydoll-python
3
- Version: 2.12.3
3
+ Version: 2.13.0
4
4
  Summary: Pydoll is a library for automating chromium-based browsers without a WebDriver, offering realistic interactions.
5
5
  License-File: LICENSE
6
6
  Author: Thalison Fernandes
@@ -59,6 +59,56 @@ pip install pydoll-python
59
59
  ```
60
60
  That's it. No `webdrivers`. No external dependencies.
61
61
 
62
+ <details>
63
+ <summary><b>🆕 What's New</b></summary>
64
+ <br>
65
+
66
+ ### Humanized Keyboard Input (`humanize=True`)
67
+
68
+ Pydoll now includes a **humanized typing engine** that simulates realistic human typing behavior:
69
+
70
+ - **Variable keystroke timing**: 30-120ms between keys (not fixed intervals)
71
+ - **Realistic typos**: ~2% error rate with automatic correction behavior
72
+ - **No more `interval` parameter**: Just use `humanize=True` for anti-bot evasion
73
+
74
+ ```python
75
+ # Old way (detectable)
76
+ await element.type_text("hello", interval=0.1)
77
+
78
+ # New way (human-like, anti-bot)
79
+ await element.type_text("hello", humanize=True)
80
+ ```
81
+
82
+ ---
83
+
84
+ ### Humanized Scroll with Physics Engine (`humanize=True`)
85
+
86
+ The scroll API now features a **Cubic Bezier curve physics engine** for realistic scrolling:
87
+
88
+ - **Momentum & friction**: Natural acceleration and deceleration
89
+ - **Micro-pauses**: Brief stops during long scrolls (simulates reading)
90
+ - **Jitter injection**: Small random variations in scroll path
91
+ - **Overshoot correction**: Occasionally scrolls past target and corrects back
92
+
93
+ ```python
94
+ # Smooth scroll (CSS animation, predictable timing)
95
+ await tab.scroll.by(ScrollPosition.DOWN, 500, smooth=True)
96
+
97
+ # Humanized scroll (physics engine, anti-bot)
98
+ await tab.scroll.by(ScrollPosition.DOWN, 500, humanize=True)
99
+ await tab.scroll.to_bottom(humanize=True)
100
+ ```
101
+
102
+ | Mode | Parameter | Use Case |
103
+ |------|-----------|----------|
104
+ | **Instant** | `smooth=False` | Speed-critical operations |
105
+ | **Smooth** | `smooth=True` | General browsing simulation |
106
+ | **Humanized** | `humanize=True` | **Anti-bot evasion** |
107
+
108
+ [**📖 Human-Like Interactions Docs**](https://pydoll.tech/docs/features/automation/human-interactions/)
109
+
110
+ </details>
111
+
62
112
  ## 🚀 Getting Started in 60 Seconds
63
113
 
64
114
  Thanks to its `async` architecture and context managers, Pydoll is clean and efficient.
@@ -39,6 +39,56 @@ pip install pydoll-python
39
39
  ```
40
40
  That's it. No `webdrivers`. No external dependencies.
41
41
 
42
+ <details>
43
+ <summary><b>🆕 What's New</b></summary>
44
+ <br>
45
+
46
+ ### Humanized Keyboard Input (`humanize=True`)
47
+
48
+ Pydoll now includes a **humanized typing engine** that simulates realistic human typing behavior:
49
+
50
+ - **Variable keystroke timing**: 30-120ms between keys (not fixed intervals)
51
+ - **Realistic typos**: ~2% error rate with automatic correction behavior
52
+ - **No more `interval` parameter**: Just use `humanize=True` for anti-bot evasion
53
+
54
+ ```python
55
+ # Old way (detectable)
56
+ await element.type_text("hello", interval=0.1)
57
+
58
+ # New way (human-like, anti-bot)
59
+ await element.type_text("hello", humanize=True)
60
+ ```
61
+
62
+ ---
63
+
64
+ ### Humanized Scroll with Physics Engine (`humanize=True`)
65
+
66
+ The scroll API now features a **Cubic Bezier curve physics engine** for realistic scrolling:
67
+
68
+ - **Momentum & friction**: Natural acceleration and deceleration
69
+ - **Micro-pauses**: Brief stops during long scrolls (simulates reading)
70
+ - **Jitter injection**: Small random variations in scroll path
71
+ - **Overshoot correction**: Occasionally scrolls past target and corrects back
72
+
73
+ ```python
74
+ # Smooth scroll (CSS animation, predictable timing)
75
+ await tab.scroll.by(ScrollPosition.DOWN, 500, smooth=True)
76
+
77
+ # Humanized scroll (physics engine, anti-bot)
78
+ await tab.scroll.by(ScrollPosition.DOWN, 500, humanize=True)
79
+ await tab.scroll.to_bottom(humanize=True)
80
+ ```
81
+
82
+ | Mode | Parameter | Use Case |
83
+ |------|-----------|----------|
84
+ | **Instant** | `smooth=False` | Speed-critical operations |
85
+ | **Smooth** | `smooth=True` | General browsing simulation |
86
+ | **Humanized** | `humanize=True` | **Anti-bot evasion** |
87
+
88
+ [**📖 Human-Like Interactions Docs**](https://pydoll.tech/docs/features/automation/human-interactions/)
89
+
90
+ </details>
91
+
42
92
  ## 🚀 Getting Started in 60 Seconds
43
93
 
44
94
  Thanks to its `async` architecture and context managers, Pydoll is clean and efficient.
@@ -382,6 +382,22 @@ new Promise((resolve) => {{
382
382
  }});
383
383
  """
384
384
 
385
+ GET_SCROLL_Y = 'window.scrollY || window.pageYOffset || 0'
386
+
387
+ GET_REMAINING_SCROLL_TO_BOTTOM = """
388
+ (function() {
389
+ const scrollHeight = Math.max(
390
+ document.body.scrollHeight,
391
+ document.documentElement.scrollHeight
392
+ );
393
+ const clientHeight = window.innerHeight;
394
+ const scrollTop = window.scrollY || window.pageYOffset || 0;
395
+ return Math.max(0, scrollHeight - clientHeight - scrollTop);
396
+ })()
397
+ """
398
+
399
+ GET_VIEWPORT_CENTER = 'JSON.stringify([window.innerWidth / 2, window.innerHeight / 2])'
400
+
385
401
  INSERT_TEXT = """
386
402
  function() {
387
403
  const el = this;
@@ -562,3 +578,66 @@ class Key(tuple[str, int], Enum):
562
578
  class BrowserType(Enum):
563
579
  CHROME = auto()
564
580
  EDGE = auto()
581
+
582
+
583
+ class TypoType(str, Enum):
584
+ """Types of realistic typing errors."""
585
+
586
+ ADJACENT = 'adjacent'
587
+ TRANSPOSE = 'transpose'
588
+ DOUBLE = 'double'
589
+ SKIP = 'skip'
590
+ MISSED_SPACE = 'missed_space'
591
+
592
+
593
+ DEFAULT_TYPO_PROBABILITY = 0.02
594
+
595
+
596
+ QWERTY_NEIGHBORS: dict[str, list[str]] = {
597
+ '1': ['2', 'q'],
598
+ '2': ['1', '3', 'q', 'w'],
599
+ '3': ['2', '4', 'w', 'e'],
600
+ '4': ['3', '5', 'e', 'r'],
601
+ '5': ['4', '6', 'r', 't'],
602
+ '6': ['5', '7', 't', 'y'],
603
+ '7': ['6', '8', 'y', 'u'],
604
+ '8': ['7', '9', 'u', 'i'],
605
+ '9': ['8', '0', 'i', 'o'],
606
+ '0': ['9', '-', 'o', 'p'],
607
+ '-': ['0', '=', 'p', '['],
608
+ '=': ['-', '[', ']'],
609
+ 'q': ['1', '2', 'w', 'a', 's'],
610
+ 'w': ['q', '2', '3', 'e', 'a', 's', 'd'],
611
+ 'e': ['w', '3', '4', 'r', 's', 'd', 'f'],
612
+ 'r': ['e', '4', '5', 't', 'd', 'f', 'g'],
613
+ 't': ['r', '5', '6', 'y', 'f', 'g', 'h'],
614
+ 'y': ['t', '6', '7', 'u', 'g', 'h', 'j'],
615
+ 'u': ['y', '7', '8', 'i', 'h', 'j', 'k'],
616
+ 'i': ['u', '8', '9', 'o', 'j', 'k', 'l'],
617
+ 'o': ['i', '9', '0', 'p', 'k', 'l', ';'],
618
+ 'p': ['o', '0', '-', '[', 'l', ';', "'"],
619
+ '[': ['p', '-', '=', ']', ';', "'"],
620
+ ']': ['[', '=', "'"],
621
+ 'a': ['q', 'w', 's', 'z', 'x'],
622
+ 's': ['q', 'w', 'e', 'a', 'd', 'z', 'x', 'c'],
623
+ 'd': ['w', 'e', 'r', 's', 'f', 'x', 'c', 'v'],
624
+ 'f': ['e', 'r', 't', 'd', 'g', 'c', 'v', 'b'],
625
+ 'g': ['r', 't', 'y', 'f', 'h', 'v', 'b', 'n'],
626
+ 'h': ['t', 'y', 'u', 'g', 'j', 'b', 'n', 'm'],
627
+ 'j': ['y', 'u', 'i', 'h', 'k', 'n', 'm', ','],
628
+ 'k': ['u', 'i', 'o', 'j', 'l', 'm', ',', '.'],
629
+ 'l': ['i', 'o', 'p', 'k', ';', ',', '.', '/'],
630
+ ';': ['o', 'p', '[', 'l', "'", '.', '/'],
631
+ "'": ['p', '[', ']', ';', '/'],
632
+ 'z': ['a', 's', 'x'],
633
+ 'x': ['z', 'a', 's', 'd', 'c'],
634
+ 'c': ['x', 's', 'd', 'f', 'v'],
635
+ 'v': ['c', 'd', 'f', 'g', 'b'],
636
+ 'b': ['v', 'f', 'g', 'h', 'n'],
637
+ 'n': ['b', 'g', 'h', 'j', 'm'],
638
+ 'm': ['n', 'h', 'j', 'k', ','],
639
+ ',': ['m', 'j', 'k', 'l', '.'],
640
+ '.': [',', 'k', 'l', ';', '/'],
641
+ '/': ['.', 'l', ';', "'"],
642
+ ' ': ['c', 'v', 'b', 'n', 'm'],
643
+ }
@@ -11,11 +11,13 @@ from pydoll.commands import (
11
11
  from pydoll.connection.connection_handler import ConnectionHandler
12
12
  from pydoll.constants import By, Scripts
13
13
  from pydoll.exceptions import ElementNotFound, WaitElementTimeout
14
+ from pydoll.utils import normalize_synthetic_xpath
14
15
 
15
16
  if TYPE_CHECKING:
16
17
  from typing import Literal, Optional, Union
17
18
 
18
- from pydoll.elements.web_element import WebElement, _IFrameContext
19
+ from pydoll.elements.web_element import WebElement
20
+ from pydoll.interactions.iframe import IFrameContext
19
21
  from pydoll.protocol.base import Command, T_CommandParams, T_CommandResponse
20
22
  from pydoll.protocol.dom.methods import DescribeNodeResponse
21
23
  from pydoll.protocol.dom.types import Node
@@ -56,6 +58,35 @@ class FindElementsMixin:
56
58
  if TYPE_CHECKING:
57
59
  _connection_handler: ConnectionHandler
58
60
 
61
+ @staticmethod
62
+ def _build_text_expression(selector: str, method: str) -> Optional[str]:
63
+ """
64
+ Build JS expression using Scripts to extract textContent based on selector type.
65
+ """
66
+ raw = str(selector)
67
+ method_lc = (method or '').lower()
68
+
69
+ if 'xpath' in method_lc:
70
+ normalized_xpath = normalize_synthetic_xpath(raw)
71
+ escaped_xpath = normalized_xpath.replace('"', '\\"')
72
+ return Scripts.GET_TEXT_BY_XPATH.replace('{escaped_value}', escaped_xpath)
73
+
74
+ if method_lc == 'name':
75
+ escaped_name = raw.replace('"', '\\"')
76
+ xpath = f'//*[@name="{escaped_name}"]'
77
+ return Scripts.GET_TEXT_BY_XPATH.replace('{escaped_value}', xpath)
78
+
79
+ escaped = raw.replace('\\', '\\\\').replace('"', '\\"')
80
+ if method_lc == 'id':
81
+ css = f'#{escaped}'
82
+ elif method_lc == 'class_name':
83
+ css = f'.{escaped}'
84
+ elif method_lc == 'tag_name':
85
+ css = escaped
86
+ else:
87
+ css = escaped
88
+ return Scripts.GET_TEXT_BY_CSS.replace('{selector}', css)
89
+
59
90
  @overload
60
91
  async def find(
61
92
  self,
@@ -583,7 +614,7 @@ class FindElementsMixin:
583
614
  return response.get('result', {}).get('node', {})
584
615
 
585
616
  def _apply_iframe_context_to_element(
586
- self, element: WebElement, iframe_context: _IFrameContext | None
617
+ self, element: WebElement, iframe_context: IFrameContext | None
587
618
  ) -> None:
588
619
  """
589
620
  Propagate iframe context to the newly created element.