mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
wait.ele_display()和wait.ele_hidden()会等待元素加载;
修复Page获取元素有时会返回str问题
This commit is contained in:
parent
4adb8247fd
commit
71dfe3037c
@ -13,4 +13,4 @@ from ._configs.chromium_options import ChromiumOptions
|
||||
from ._configs.session_options import SessionOptions
|
||||
|
||||
__all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__']
|
||||
__version__ = '4.0.0b24'
|
||||
__version__ = '4.0.0b25'
|
||||
|
@ -447,14 +447,13 @@ class BasePage(BaseParser):
|
||||
|
||||
r = self._find_elements(loc_or_ele, timeout=timeout, single=single, raise_err=raise_err)
|
||||
|
||||
if not single:
|
||||
if r or isinstance(r, list):
|
||||
return r
|
||||
if isinstance(r, NoneElement):
|
||||
if Settings.raise_when_ele_not_found or raise_err is True:
|
||||
raise ElementNotFoundError(None, method, {'loc_or_str': loc_or_ele})
|
||||
else:
|
||||
r.method = method
|
||||
r.args = {'loc_or_str': loc_or_ele}
|
||||
if Settings.raise_when_ele_not_found or raise_err is True:
|
||||
raise ElementNotFoundError(None, method, {'loc_or_str': loc_or_ele})
|
||||
|
||||
r.method = method
|
||||
r.args = {'loc_or_str': loc_or_ele}
|
||||
return r
|
||||
|
||||
@abstractmethod
|
||||
|
@ -1040,7 +1040,7 @@ class ShadowRoot(BaseElement):
|
||||
|
||||
else:
|
||||
nod_ids = self.page.run_cdp('DOM.querySelectorAll', nodeId=self._node_id, selector=loc[1])['nodeId']
|
||||
result = [make_chromium_ele(self.page, node_id=n) for n in nod_ids]
|
||||
result = make_chromium_eles(self.page, node_ids=nod_ids, single=False)
|
||||
|
||||
else:
|
||||
eles = make_session_ele(self.html).eles(loc)
|
||||
@ -1205,6 +1205,7 @@ def make_chromium_ele(page, node_id=None, obj_id=None):
|
||||
if node_id:
|
||||
node = page.run_cdp('DOM.describeNode', nodeId=node_id)
|
||||
if node['node']['nodeName'] in ('#text', '#comment'):
|
||||
# todo: Node()
|
||||
return node['node']['nodeValue']
|
||||
backend_id = node['node']['backendNodeId']
|
||||
obj_id = page.run_cdp('DOM.resolveNode', nodeId=node_id)['object']['objectId']
|
||||
@ -1212,6 +1213,7 @@ def make_chromium_ele(page, node_id=None, obj_id=None):
|
||||
elif obj_id:
|
||||
node = page.run_cdp('DOM.describeNode', objectId=obj_id)
|
||||
if node['node']['nodeName'] in ('#text', '#comment'):
|
||||
# todo: Node()
|
||||
return node['node']['nodeValue']
|
||||
backend_id = node['node']['backendNodeId']
|
||||
node_id = node['node']['nodeId']
|
||||
@ -1227,6 +1229,61 @@ def make_chromium_ele(page, node_id=None, obj_id=None):
|
||||
return ele
|
||||
|
||||
|
||||
def make_chromium_eles(page, node_ids=None, obj_ids=None, single=True, ele_only=True):
|
||||
"""根据node id或object id生成相应元素对象
|
||||
:param page: ChromiumPage对象
|
||||
:param node_ids: 元素的node id
|
||||
:param obj_ids: 元素的object id
|
||||
:param single: 是否获取但个元素
|
||||
:param ele_only: 是否只要ele
|
||||
:return: ChromiumElement对象或ChromiumFrame对象
|
||||
"""
|
||||
nodes = []
|
||||
if node_ids:
|
||||
for node_id in node_ids:
|
||||
if not node_id:
|
||||
return False
|
||||
node = page.run_cdp('DOM.describeNode', nodeId=node_id)
|
||||
if node['node']['nodeName'] in ('#text', '#comment'):
|
||||
if ele_only:
|
||||
continue
|
||||
else:
|
||||
# todo: Node()
|
||||
pass
|
||||
|
||||
obj_id = page.run_cdp('DOM.resolveNode', nodeId=node_id)['object']['objectId']
|
||||
ele = ChromiumElement(page, obj_id=obj_id, node_id=node_id, backend_id=node['node']['backendNodeId'])
|
||||
if ele.tag in __FRAME_ELEMENT__:
|
||||
from .._pages.chromium_frame import ChromiumFrame
|
||||
ele = ChromiumFrame(page, ele)
|
||||
if single:
|
||||
return ele
|
||||
nodes.append(ele)
|
||||
|
||||
if obj_ids:
|
||||
for obj_id in obj_ids:
|
||||
if not obj_id:
|
||||
return False
|
||||
node = page.run_cdp('DOM.describeNode', objectId=obj_id)
|
||||
if node['node']['nodeName'] in ('#text', '#comment'):
|
||||
if ele_only:
|
||||
continue
|
||||
else:
|
||||
# todo: Node
|
||||
pass
|
||||
|
||||
ele = ChromiumElement(page, obj_id=obj_id, node_id=node['node']['nodeId'],
|
||||
backend_id=node['node']['backendNodeId'])
|
||||
if ele.tag in __FRAME_ELEMENT__:
|
||||
from .._pages.chromium_frame import ChromiumFrame
|
||||
ele = ChromiumFrame(page, ele)
|
||||
if single:
|
||||
return ele
|
||||
nodes.append(ele)
|
||||
|
||||
return NoneElement(page) if single and not nodes else nodes
|
||||
|
||||
|
||||
def make_js_for_find_ele_by_xpath(xpath, type_txt, node_txt):
|
||||
"""生成用xpath在元素中查找元素的js文本
|
||||
:param xpath: xpath文本
|
||||
@ -1347,7 +1404,7 @@ def parse_js_result(page, ele, result):
|
||||
elif class_name == 'HTMLDocument':
|
||||
return result
|
||||
else:
|
||||
return make_chromium_ele(page, obj_id=result['objectId'])
|
||||
return make_chromium_eles(page, obj_ids=(result['objectId'],))
|
||||
|
||||
elif sub_type == 'array':
|
||||
r = page.run_cdp('Runtime.getProperties', objectId=result['objectId'],
|
||||
|
@ -26,10 +26,10 @@ PIC_TYPE = Literal['jpg', 'jpeg', 'png', 'webp', True]
|
||||
|
||||
class ChromiumElement(DrissionElement):
|
||||
|
||||
def __init__(self, page: ChromiumBase, node_id: str = None, obj_id: str = None, backend_id: int = None):
|
||||
def __init__(self, page: ChromiumBase, node_id: int = None, obj_id: str = None, backend_id: int = None):
|
||||
self._tag: str = ...
|
||||
self.page: Union[ChromiumPage, WebPage] = ...
|
||||
self._node_id: str = ...
|
||||
self._node_id: int = ...
|
||||
self._obj_id: str = ...
|
||||
self._backend_id: int = ...
|
||||
self._doc_id: str = ...
|
||||
@ -217,11 +217,11 @@ class ChromiumElement(DrissionElement):
|
||||
|
||||
def drag_to(self, ele_or_loc: Union[tuple, ChromiumElement], duration: float = 0.5) -> None: ...
|
||||
|
||||
def _get_obj_id(self, node_id: str = None, backend_id: int = None) -> str: ...
|
||||
def _get_obj_id(self, node_id: int = None, backend_id: int = None) -> str: ...
|
||||
|
||||
def _get_node_id(self, obj_id: str = None, backend_id: int = None) -> str: ...
|
||||
def _get_node_id(self, obj_id: str = None, backend_id: int = None) -> int: ...
|
||||
|
||||
def _get_backend_id(self, node_id: str) -> str: ...
|
||||
def _get_backend_id(self, node_id: int) -> int: ...
|
||||
|
||||
def _get_ele_path(self, mode: str) -> str: ...
|
||||
|
||||
@ -230,7 +230,7 @@ class ShadowRoot(BaseElement):
|
||||
|
||||
def __init__(self, parent_ele: ChromiumElement, obj_id: str = None, backend_id: int = None):
|
||||
self._obj_id: str = ...
|
||||
self._node_id: str = ...
|
||||
self._node_id: int = ...
|
||||
self._backend_id: int = ...
|
||||
self.page: ChromiumPage = ...
|
||||
self.parent_ele: ChromiumElement = ...
|
||||
@ -294,11 +294,11 @@ class ShadowRoot(BaseElement):
|
||||
-> Union[ChromiumElement, ChromiumFrame, NoneElement, str, List[Union[ChromiumElement,
|
||||
ChromiumFrame, str]]]: ...
|
||||
|
||||
def _get_node_id(self, obj_id: str) -> str: ...
|
||||
def _get_node_id(self, obj_id: str) -> int: ...
|
||||
|
||||
def _get_obj_id(self, back_id: str) -> str: ...
|
||||
def _get_obj_id(self, back_id: int) -> str: ...
|
||||
|
||||
def _get_backend_id(self, node_id: str) -> int: ...
|
||||
def _get_backend_id(self, node_id: int) -> int: ...
|
||||
|
||||
|
||||
def find_in_chromium_ele(ele: ChromiumElement, loc: Union[str, Tuple[str, str]],
|
||||
@ -314,10 +314,18 @@ def find_by_css(ele: ChromiumElement, selector: str, single: bool,
|
||||
timeout: float) -> Union[ChromiumElement, List[ChromiumElement], NoneElement]: ...
|
||||
|
||||
|
||||
def make_chromium_ele(page: ChromiumBase, node_id: str = ..., obj_id: str = ...) \
|
||||
def make_chromium_ele(page: ChromiumBase, node_id: int = ..., obj_id: str = ...) \
|
||||
-> Union[ChromiumElement, ChromiumFrame, str]: ...
|
||||
|
||||
|
||||
def make_chromium_eles(page: ChromiumBase,
|
||||
node_ids: Union[tuple, list] = None,
|
||||
obj_ids: Union[tuple, list] = None,
|
||||
single: bool = True,
|
||||
ele_only: bool = True) -> Union[ChromiumElement, ChromiumFrame, NoneElement,
|
||||
List[Union[ChromiumElement, ChromiumFrame]]]: ...
|
||||
|
||||
|
||||
def make_js_for_find_ele_by_xpath(xpath: str, type_txt: str, node_txt: str) -> str: ...
|
||||
|
||||
|
||||
|
@ -11,13 +11,13 @@ from time import perf_counter, sleep
|
||||
from urllib.parse import quote
|
||||
|
||||
from .._base.base import BasePage
|
||||
from .._elements.chromium_element import ChromiumElement, run_js, make_chromium_eles
|
||||
from .._elements.none_element import NoneElement
|
||||
from .._elements.session_element import make_session_ele
|
||||
from .._functions.locator import get_loc, is_loc
|
||||
from .._functions.settings import Settings
|
||||
from .._functions.tools import get_usable_path, raise_error
|
||||
from .._functions.web import location_in_viewport
|
||||
from .._elements.chromium_element import ChromiumElement, run_js, make_chromium_ele
|
||||
from .._elements.none_element import NoneElement
|
||||
from .._elements.session_element import make_session_ele
|
||||
from .._units.actions import Actions
|
||||
from .._units.listener import Listener
|
||||
from .._units.rect import TabRect
|
||||
@ -26,7 +26,7 @@ from .._units.scroller import PageScroller
|
||||
from .._units.setter import ChromiumBaseSetter
|
||||
from .._units.states import PageStates
|
||||
from .._units.waiter import BaseWaiter
|
||||
from ..errors import ContextLostError, ElementLostError, CDPError, PageClosedError, ElementNotFoundError
|
||||
from ..errors import ContextLostError, CDPError, PageClosedError, ElementNotFoundError
|
||||
|
||||
__ERROR__ = 'error'
|
||||
|
||||
@ -586,9 +586,11 @@ class ChromiumBase(BasePage):
|
||||
timeout = timeout if timeout is not None else self.timeout
|
||||
end_time = perf_counter() + timeout
|
||||
|
||||
search_ids = []
|
||||
try:
|
||||
search_result = self.run_cdp_loaded('DOM.performSearch', query=loc, includeUserAgentShadowDOM=True)
|
||||
count = search_result['resultCount']
|
||||
search_ids.append(search_result['searchId'])
|
||||
except ContextLostError:
|
||||
search_result = None
|
||||
count = 0
|
||||
@ -606,33 +608,27 @@ class ChromiumBase(BasePage):
|
||||
pass
|
||||
|
||||
if ok:
|
||||
try:
|
||||
if single:
|
||||
r = make_chromium_ele(self, node_id=nodeIds['nodeIds'][0])
|
||||
break
|
||||
|
||||
else:
|
||||
r = [make_chromium_ele(self, node_id=i) for i in nodeIds['nodeIds']]
|
||||
break
|
||||
|
||||
except ElementLostError:
|
||||
r = make_chromium_eles(self, node_ids=nodeIds['nodeIds'], single=single)
|
||||
if r is not False:
|
||||
break
|
||||
else:
|
||||
ok = False
|
||||
|
||||
try:
|
||||
search_result = self.run_cdp_loaded('DOM.performSearch', query=loc, includeUserAgentShadowDOM=True)
|
||||
count = search_result['resultCount']
|
||||
search_ids.append(search_result['searchId'])
|
||||
except ContextLostError:
|
||||
pass
|
||||
|
||||
if perf_counter() >= end_time:
|
||||
return NoneElement(self) if single else []
|
||||
return None if single else []
|
||||
|
||||
sleep(.1)
|
||||
|
||||
try:
|
||||
self.run_cdp('DOM.discardSearchResults', searchId=search_result['searchId'])
|
||||
except:
|
||||
pass
|
||||
for _id in search_ids:
|
||||
self._driver.run('DOM.discardSearchResults', searchId=_id)
|
||||
|
||||
return r
|
||||
|
||||
def refresh(self, ignore_cache=False):
|
||||
|
@ -586,9 +586,7 @@ class ChromiumFrame(ChromiumBase):
|
||||
"""
|
||||
if isinstance(loc_or_ele, ChromiumElement):
|
||||
return loc_or_ele
|
||||
|
||||
self.wait.load_complete()
|
||||
|
||||
return self.doc_ele._ele(loc_or_ele, timeout,
|
||||
raise_err=raise_err) if single else self.doc_ele.eles(loc_or_ele, timeout)
|
||||
|
||||
|
@ -96,7 +96,7 @@ class ChromiumFrame(ChromiumBase):
|
||||
def _obj_id(self) -> str: ...
|
||||
|
||||
@property
|
||||
def _node_id(self) -> str: ...
|
||||
def _node_id(self) -> int: ...
|
||||
|
||||
@property
|
||||
def active_ele(self) -> ChromiumElement: ...
|
||||
|
@ -36,7 +36,16 @@ class BaseWaiter(object):
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
ele = self._driver._ele(loc_or_ele, raise_err=False, timeout=0)
|
||||
if timeout is None:
|
||||
timeout = self._driver.timeout
|
||||
end_time = perf_counter() + timeout
|
||||
ele = self._driver._ele(loc_or_ele, raise_err=False, timeout=timeout)
|
||||
timeout = end_time - perf_counter()
|
||||
if timeout <= 0:
|
||||
if raise_err is True or Settings.raise_when_wait_failed is True:
|
||||
raise WaitTimeoutError('等待元素显示失败。')
|
||||
else:
|
||||
return False
|
||||
return ele.wait.display(timeout, raise_err=raise_err)
|
||||
|
||||
def ele_hidden(self, loc_or_ele, timeout=None, raise_err=None):
|
||||
@ -46,7 +55,16 @@ class BaseWaiter(object):
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
ele = self._driver._ele(loc_or_ele, raise_err=False, timeout=0)
|
||||
if timeout is None:
|
||||
timeout = self._driver.timeout
|
||||
end_time = perf_counter() + timeout
|
||||
ele = self._driver._ele(loc_or_ele, raise_err=False, timeout=timeout)
|
||||
timeout = end_time - perf_counter()
|
||||
if timeout <= 0:
|
||||
if raise_err is True or Settings.raise_when_wait_failed is True:
|
||||
raise WaitTimeoutError('等待元素显示失败。')
|
||||
else:
|
||||
return False
|
||||
return ele.wait.hidden(timeout, raise_err=raise_err)
|
||||
|
||||
def ele_loaded(self, loc, timeout=None, raise_err=None):
|
||||
@ -296,7 +314,7 @@ class ElementWaiter(object):
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._wait_state('is_alive', False, timeout, raise_err)
|
||||
return self._wait_state('is_alive', False, timeout, raise_err, err_text='等待元素被删除失败。')
|
||||
|
||||
def display(self, timeout=None, raise_err=None):
|
||||
"""等待元素从dom显示
|
||||
@ -304,7 +322,7 @@ class ElementWaiter(object):
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._wait_state('is_displayed', True, timeout, raise_err)
|
||||
return self._wait_state('is_displayed', True, timeout, raise_err, err_text='等待元素显示失败。')
|
||||
|
||||
def hidden(self, timeout=None, raise_err=None):
|
||||
"""等待元素从dom隐藏
|
||||
@ -312,7 +330,7 @@ class ElementWaiter(object):
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._wait_state('is_displayed', False, timeout, raise_err)
|
||||
return self._wait_state('is_displayed', False, timeout, raise_err, err_text='等待元素隐藏失败。')
|
||||
|
||||
def covered(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素被遮盖
|
||||
@ -320,15 +338,15 @@ class ElementWaiter(object):
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._wait_state('is_covered', True, timeout, raise_err)
|
||||
return self._wait_state('is_covered', True, timeout, raise_err, err_text='等待元素被覆盖失败。')
|
||||
|
||||
def not_covered(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素被遮盖
|
||||
"""等待当前元素不被遮盖
|
||||
:param timeout: 超时时间,为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._wait_state('is_covered', False, timeout, raise_err)
|
||||
return self._wait_state('is_covered', False, timeout, raise_err, err_text='等待元素不被覆盖失败。')
|
||||
|
||||
def enabled(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素变成可用
|
||||
@ -336,15 +354,15 @@ class ElementWaiter(object):
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._wait_state('is_enabled', True, timeout, raise_err)
|
||||
return self._wait_state('is_enabled', True, timeout, raise_err, err_text='等待元素变成可用失败。')
|
||||
|
||||
def disabled(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素变成可用
|
||||
"""等待当前元素变成不可用
|
||||
:param timeout: 超时时间,为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._wait_state('is_enabled', False, timeout, raise_err)
|
||||
return self._wait_state('is_enabled', False, timeout, raise_err, err_text='等待元素变成不可用失败。')
|
||||
|
||||
def disabled_or_deleted(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素变成不可用或从DOM移除
|
||||
@ -361,7 +379,7 @@ class ElementWaiter(object):
|
||||
sleep(.05)
|
||||
|
||||
if raise_err is True or Settings.raise_when_wait_failed is True:
|
||||
raise WaitTimeoutError('等待元素隐藏或删除失败。')
|
||||
raise WaitTimeoutError('等待元素隐藏或被删除失败。')
|
||||
else:
|
||||
return False
|
||||
|
||||
@ -397,14 +415,16 @@ class ElementWaiter(object):
|
||||
else:
|
||||
return False
|
||||
|
||||
def _wait_state(self, attr, mode=False, timeout=None, raise_err=None):
|
||||
"""等待元素某个bool状态到达指定状态
|
||||
def _wait_state(self, attr, mode=False, timeout=None, raise_err=None, err_text=None):
|
||||
"""等待元素某个元素状态到达指定状态
|
||||
:param attr: 状态名称
|
||||
:param mode: True或False
|
||||
:param timeout: 超时时间,为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:param err_text: 抛出错误时显示的信息
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
err_text = err_text or '等待元素状态改变失败。'
|
||||
if timeout is None:
|
||||
timeout = self._page.timeout
|
||||
end_time = perf_counter() + timeout
|
||||
@ -414,7 +434,7 @@ class ElementWaiter(object):
|
||||
sleep(.05)
|
||||
|
||||
if raise_err is True or Settings.raise_when_wait_failed is True:
|
||||
raise WaitTimeoutError('等待元素状态改变失败。')
|
||||
raise WaitTimeoutError(err_text)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
@ -18,17 +18,23 @@ class BaseWaiter(object):
|
||||
|
||||
def __call__(self, second: float) -> None: ...
|
||||
|
||||
def ele_deleted(self, loc_or_ele: Union[str, tuple, ChromiumElement], timeout: float = None,
|
||||
raise_err: bool = None) -> bool: ...
|
||||
def ele_deleted(self,
|
||||
loc_or_ele: Union[str, tuple, ChromiumElement],
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> bool: ...
|
||||
|
||||
def ele_display(self, loc_or_ele: Union[str, tuple, ChromiumElement], timeout: float = None,
|
||||
def ele_display(self,
|
||||
loc_or_ele: Union[str, tuple, ChromiumElement],
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> bool: ...
|
||||
|
||||
def ele_hidden(self, loc_or_ele: Union[str, tuple, ChromiumElement], timeout: float = None,
|
||||
raise_err: bool = None) -> bool: ...
|
||||
|
||||
def ele_loaded(self, loc: Union[str, tuple], timeout: float = None,
|
||||
raise_err: bool = None) -> Union[bool, ChromiumElement]: ...
|
||||
def ele_loaded(self,
|
||||
loc: Union[str, tuple],
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> Union[bool, ChromiumElement]: ...
|
||||
|
||||
def _loading(self, timeout: float = None, start: bool = True, gap: float = .01, raise_err: bool = None) -> bool: ...
|
||||
|
||||
@ -64,9 +70,7 @@ class PageWaiter(TabWaiter):
|
||||
|
||||
|
||||
class ElementWaiter(object):
|
||||
def __init__(self,
|
||||
page: ChromiumBase,
|
||||
ele: ChromiumElement):
|
||||
def __init__(self, page: ChromiumBase, ele: ChromiumElement):
|
||||
self._ele: ChromiumElement = ...
|
||||
self._page: ChromiumBase = ...
|
||||
|
||||
@ -90,7 +94,12 @@ class ElementWaiter(object):
|
||||
|
||||
def stop_moving(self, gap: float = .1, timeout: float = None, raise_err: bool = None) -> bool: ...
|
||||
|
||||
def _wait_state(self, attr: str, mode: bool = False, timeout: float = None, raise_err: bool = None) -> bool: ...
|
||||
def _wait_state(self,
|
||||
attr: str,
|
||||
mode: bool = False,
|
||||
timeout: float = None,
|
||||
raise_err: bool = None,
|
||||
err_text: str = None) -> bool: ...
|
||||
|
||||
|
||||
class FrameWaiter(BaseWaiter, ElementWaiter):
|
||||
|
Loading…
x
Reference in New Issue
Block a user