| 64 | |
| 65 | |
| 66 | class Locator: |
| 67 | def __init__( |
| 68 | self, |
| 69 | frame: "Frame", |
| 70 | selector: str, |
| 71 | has_text: Union[str, Pattern[str]] = None, |
| 72 | has_not_text: Union[str, Pattern[str]] = None, |
| 73 | has: "Locator" = None, |
| 74 | has_not: "Locator" = None, |
| 75 | visible: bool = None, |
| 76 | ) -> None: |
| 77 | self._frame = frame |
| 78 | self._selector = selector |
| 79 | self._loop = frame._loop |
| 80 | self._dispatcher_fiber = frame._connection._dispatcher_fiber |
| 81 | |
| 82 | if has_text: |
| 83 | self._selector += f" >> internal:has-text={escape_for_text_selector(has_text, exact=False)}" |
| 84 | |
| 85 | if has: |
| 86 | if has._frame != frame: |
| 87 | raise Error('Inner "has" locator must belong to the same frame.') |
| 88 | self._selector += " >> internal:has=" + json.dumps( |
| 89 | has._selector, ensure_ascii=False |
| 90 | ) |
| 91 | |
| 92 | if has_not_text: |
| 93 | self._selector += f" >> internal:has-not-text={escape_for_text_selector(has_not_text, exact=False)}" |
| 94 | |
| 95 | if has_not: |
| 96 | locator = has_not |
| 97 | if locator._frame != frame: |
| 98 | raise Error('Inner "has_not" locator must belong to the same frame.') |
| 99 | self._selector += " >> internal:has-not=" + json.dumps(locator._selector) |
| 100 | |
| 101 | if visible is not None: |
| 102 | self._selector += f" >> visible={bool_to_js_bool(visible)}" |
| 103 | |
| 104 | def __repr__(self) -> str: |
| 105 | return f"<Locator frame={self._frame!r} selector={self._selector!r}>" |
| 106 | |
| 107 | async def _with_element( |
| 108 | self, |
| 109 | task: Callable[[ElementHandle, float], Awaitable[T]], |
| 110 | timeout: float = None, |
| 111 | ) -> T: |
| 112 | timeout = self._frame._timeout(timeout) |
| 113 | deadline = (monotonic_time() + timeout) if timeout else 0 |
| 114 | handle = await self.element_handle(timeout=timeout) |
| 115 | if not handle: |
| 116 | raise Error(f"Could not resolve {self._selector} to DOM Element") |
| 117 | try: |
| 118 | return await task( |
| 119 | handle, |
| 120 | (deadline - monotonic_time()) if deadline else 0, |
| 121 | ) |
| 122 | finally: |
| 123 | await handle.dispose() |