Esempio n. 1
0
 def __init__(self, root, locator):
     '''constructor
     
     :param root: parent control or window
     :param locator: control locator
     '''
     self._root = root
     self._locator = locator
     self._driver = root.get_driver()
     self._proxy = LazyInit(self, "_proxy", self._init_proxy)
Esempio n. 2
0
    def __init__(self, root=None, locator=None):
        '''构造函数        
        :type root: UIA.Control or None
        :param root: 开始查找的UIA控件或包含UIA的win32control.Window;
        :type locator: str or qt4c.qpath.QPath(后面支持)
        :param locator: UIA控件的name属性  or qpath(后面支持)
        :attention: 参数root和locator不能同时为None
        '''
        control.Control.__init__(self)

        if locator is None and root is None:
            raise RuntimeError("传入参数locator和root不能同时为None!")
        self._root = root
        self._locator = locator
        self._uiaobj = LazyInit(self, '_uiaobj', self._init_uiaobj)
Esempio n. 3
0
 def __init__(self, root, locator, **ext):
     '''构造函数
     
     :param root: 父对象(多态:最顶层是App实例对象)
     :type root: App | Element
     :param locator: 定位描述(多态:可以直接是element的id),如果为None则指向_root对象
     :type locator: QPath | str(QPath) | int已定位到的element的ID
     '''
     ControlContainer.__init__(self)
     if ext:
         self.user_name = ext['id']
     self._app = None
     self._root = root
     self._locator = locator
     # -*- -*- -*-
     if not isinstance(self._root, (App, Element)):
         raise Exception('element.root is invalid')
     if self._locator is not None and not isinstance(
             self._locator, (QPath, basestring, int)):
         raise Exception('element.locator is invalid')
     # -*- -*- -*-
     root = self._root
     while True:
         if isinstance(root, App):
             self._app = root
             break
         root = root._root
     if not isinstance(self._app, App):
         raise Exception('element.app is invalid')
     # -*- -*- -*-
     self._check_locator(self._locator)
     # -*- -*- -*-
     self._element = LazyInit(self, '_element', self._init_element)
Esempio n. 4
0
 def __init__(self, app):
     self._app = app
     self._driver = app.get_driver()
     self._locators = {}
     self._proxy = LazyInit(self, "_proxy", self._init_proxy)
Esempio n. 5
0
class Window(object):
    '''Window
    '''
    timeout = 4
    interval = 0.5

    NAME = None

    def __init__(self, app):
        self._app = app
        self._driver = app.get_driver()
        self._locators = {}
        self._proxy = LazyInit(self, "_proxy", self._init_proxy)

    def _init_proxy(self):
        t0 = time.time()
        while time.time() - t0 < self.timeout:
            if self.NAME is None:
                raise ValueError("NAME of class \"%s\" is not set" %
                                 type(self))
            control_id = self._driver.get_window_by_name(self.NAME)
            if control_id:
                return ControlProxy(self._driver, control_id)
            time.sleep(self.interval)
        raise ControlNotFoundError("window with name \"%s\" not found" %
                                   self.NAME)

    def __getitem__(self, key):
        if not self._locators.has_key(key):
            raise RuntimeError("child control of name \"%s\" is not defined" %
                               key)
        params = self._locators.get(key)

        if isinstance(params, basestring):
            params = {"root": self, "type": Control, "locator": params}
        else:
            params["root"] = params.get("root", self)
            params["type"] = params.get("type", Control)

        root = params["root"]
        if isinstance(root, basestring) and re.match('^@', root):
            root_key = re.sub('^@', '', root)
            params["root"] = self.controls[root_key]
        ctrl_class = params.pop("type")
        return ctrl_class(**params)

    @property
    def id(self):
        '''control id
        '''
        return self._proxy.id

    @property
    def app(self):
        '''belonging app
        '''
        return self._app

    @property
    def title(self):
        '''window title
        '''
        return self._proxy.get_attr("title")

    @property
    def controls(self):
        '''children control retriever
        '''
        return self

    def get_driver(self):
        '''get test driver
        '''
        return self._driver

    def update_locator(self, locators):
        '''update UI locator(UI map)
        '''
        self._locators.update(locators)

    def exist(self):
        '''window existence
        '''
        if self.NAME is None:
            raise ValueError("NAME of class \"%s\" is not set" % type(self))
        control_id = self._driver.get_window_by_name(self.NAME)
        if control_id:
            return True
        else:
            return False

    def wait_for_exist(self, timeout, interval):
        '''wait for control existence
        '''
        Timeout(timeout, interval).retry(self.exist, (), None,
                                         lambda x: x == True)

    def wait_for_value(self, timeout, interval, attrname, attrval):
        '''wait for control attribute value
        '''
        Timeout(timeout, interval).retry(lambda: getattr(self, attrname), (),
                                         None, lambda x: x == attrval)
Esempio n. 6
0
class Control(object):
    '''Control
    '''
    def __init__(self, root, locator):
        '''constructor
        
        :param root: parent control or window
        :param locator: control locator
        '''
        self._root = root
        self._locator = locator
        self._driver = root.get_driver()
        self._proxy = LazyInit(self, "_proxy", self._init_proxy)

    def _init_proxy(self):
        if isinstance(self._locator, basestring):
            control_ids = self._driver.find_controls_by_name(
                self._root.id, self._locator)
        elif isinstance(self._locator, int):
            control_ids = [self._locator]
        elif isinstance(self._locator, QPath):
            control_ids = self._driver.find_controls(self._root.id,
                                                     self._locator.dumps()[0])
        else:
            raise TypeError()
        if control_ids:
            if len(control_ids) == 1:
                return ControlProxy(self._driver, control_ids[0])
            else:
                raise ControlAmbiguousError()
        else:
            raise ControlNotFoundError()

    @property
    def id(self):
        '''control id
        '''
        return self._proxy.id

    @property
    def name(self):
        return self._proxy.get_attr("name")

    def get_driver(self):
        '''get test driver
        '''
        return self._driver

    def exist(self):
        '''control existence
        '''
        if not self._root.exist():
            return False
        if isinstance(self._locator, basestring):
            control_ids = self._driver.find_controls_by_name(
                self._root.id, self._locator)
        elif isinstance(self._locator, QPath):
            control_ids = self._driver.find_controls(self._root.id,
                                                     self._locator.dumps())
        else:
            raise TypeError()
        if control_ids:
            return True
        else:
            return False

    def wait_for_exist(self, timeout, interval):
        '''wait for control existence
        '''
        Timeout(timeout, interval).retry(self.exist, (), None,
                                         lambda x: x == True)

    def wait_for_value(self, timeout, interval, attrname, attrval):
        '''wait for control attribute value
        '''
        Timeout(timeout, interval).retry(lambda: getattr(self, attrname), (),
                                         None, lambda x: x == attrval)
Esempio n. 7
0
class Control(control.Control):
    '''
    UIA方式访问控件基类
    '''
    def __init__(self, root=None, locator=None):
        '''构造函数        
        :type root: UIA.Control or None
        :param root: 开始查找的UIA控件或包含UIA的win32control.Window;
        :type locator: str or qt4c.qpath.QPath(后面支持)
        :param locator: UIA控件的name属性  or qpath(后面支持)
        :attention: 参数root和locator不能同时为None
        '''
        control.Control.__init__(self)

        if locator is None and root is None:
            raise RuntimeError("传入参数locator和root不能同时为None!")
        self._root = root
        self._locator = locator
        self._uiaobj = LazyInit(self, '_uiaobj', self._init_uiaobj)

    def _init_uiaobj(self):
        '''初始化uia对象
        '''
        if self._root is None:
            self._root = Control(root=UIAutomationClient.GetRootElement())
            self._root.empty_invoke()

        if isinstance(self._root, wincontrols.Control):
            pid = self._root.ProcessId
            if not pid or not self._root.Valid:
                raise ControlExpiredError("父控件/父窗口已经失效,查找中止!")
            if self._locator is None:
                cnd = UIAutomationClient.CreatePropertyCondition(
                    IUIAutomation.UIA_NativeWindowHandlePropertyId,
                    self._root.HWnd)
                self._root = find_UIAElm(cnd)

        if self._locator is None:
            if isinstance(self._root, Control):
                self._root.empty_invoke()
                elm = self._root._uiaobj
            elif isinstance(self._root, IUIAutomation.IUIAutomationElement):
                elm = self._root
            else:
                raise TypeError(
                    "root应为uiacontrols.Control类型或者UIA element,实际类型为:%s" %
                    type(self._root))
        else:
            if isinstance(self._locator, six.string_types):
                if isinstance(self._root, Control):
                    args = (self._root, self._locator)
                    try:
                        from qt4c.qpath import _find_by_name
                        foundctrl = self._timeout.retry(
                            _find_by_name, args, (ControlNotFoundError))
                        foundctrl.empty_invoke()
                        elm = foundctrl._uiaobj
                    except TimeoutError:
                        raise ControlNotFoundError("找不到name为 (%s)的UIA子控件!" %
                                                   self._locator)
                else:
                    raise TypeError("root应为uiacontrols.Control类型,实际类型为:%s" %
                                    type(self._root))
            else:
                try:
                    kwargs = {'root': self._root}
                    foundctrls = self._timeout.retry(self._locator.search,
                                                     kwargs, (),
                                                     lambda x: len(x) > 0)
                except TimeoutError as erro:
                    raise ControlNotFoundError(
                        "<%s>中的%s查找超时:%s" %
                        (self._root, self._locator.getErrorPath(), erro))
                nctrl = len(foundctrls)
                if (nctrl > 1):
                    raise ControlAmbiguousError("<%s>找到%d个控件" %
                                                (self._locator, nctrl))
                foundctrls[0].empty_invoke()
                elm = foundctrls[0]._uiaobj
        return elm

    def empty_invoke(self):
        '''无意义调用,用于主动初始化对象
        '''
        self._uiaobj.CurrentName

    def SetFocus(self):
        self._uiaobj.SetFocus()  #这个接口没有作用

    @property
    def Valid(self):
        """是否是有效控件
        """
        return self.Enabled

    @property
    def Width(self):
        """控件宽度
        """
        rect = self._getrect()
        return rect['Width']

    @property
    def Height(self):
        """控件高度
        """
        rect = self._getrect()
        return rect['Height']

    @property
    def BoundingRect(self):
        """返回控件
        """
        rect = self._getrect()
        return Rectangle((int(rect['Left']), int(rect['Top']),
                          int(rect['Left'] + rect['Width']),
                          int(rect['Top'] + rect['Height'])))

    def _getrect(self):
        rect = {'Left': 0, 'Top': 0, 'Width': 0, 'Height': 0}
        (rect['Left'], rect['Top'], rect['Width'],
         rect['Height']) = self._uiaobj.GetCurrentPropertyValue(
             IUIAutomation.UIA_BoundingRectanglePropertyId)
        return rect

    def click(self,
              mouseFlag=MouseFlag.LeftButton,
              clickType=MouseClickType.SingleClick,
              xOffset=None,
              yOffset=None):
        """点击控件
        :type mouseFlag:qt4c.mouse.MouseFlag
        :param mouseFlag: 鼠标按钮类型
        :type clickType:qt4c.mouse.MouseClickType
        :param clickType:点击动作类型
        :type xOffset:int
        :param 横向偏移量
        :type yOffset:int
        :param 纵向偏移量
        """
        Timeout(5, 0.5).waitObjectProperty(self, 'Enabled', True)
        x, y = self._getClickXY(xOffset, yOffset)
        Mouse.click(int(x), int(y), mouseFlag, clickType)

    @property
    def ProcessId(self):
        pid = self._uiaobj.GetCurrentPropertyValue(
            IUIAutomation.UIA_ProcessIdPropertyId)
        return pid

    @property
    def ControlType(self):
        """返回UIA控件的类型
        """
        typeint = self._uiaobj.GetCurrentPropertyValue(
            IUIAutomation.UIA_ControlTypePropertyId)
        return UIAControlType[typeint]

    @property
    def Enabled(self):
        """此控件是否可用
        """
        return self._uiaobj.GetCurrentPropertyValue(
            IUIAutomation.UIA_IsEnabledPropertyId)

    @property
    def Children(self):
        """返回子控件列表
        :rtype ListType
        """
        self.empty_invoke()
        children = []
        child = RawWalker.GetFirstChildElement(self._uiaobj)
        while (child != None):
            try:
                child.CurrentName  #测试uiaelm对象是否有效
                children.append(Control(root=child))
                child = RawWalker.GetNextSiblingElement(child)
            except ValueError:
                child = None
        return children

    @property
    def Parent(self):
        self.empty_invoke()
        parent = RawWalker.GetParentElement(self._uiaobj)
        try:
            parent.CurrentName  #测试uia elm对象是否有效
        except ValueError:
            parent = None
        else:
            return Control(root=parent)

    @property
    def Name(self):
        """返回control的name属性
        """
        return self._uiaobj.CurrentName

    @property
    def Type(self):
        """返回控件类型
        """
        return self._uiaobj.CurrentLocalizedControlType

    @property
    def Value(self):
        """返回控件value属性(通常是文本信息)
        """
        return self._uiaobj.GetCurrentPropertyValue(
            IUIAutomation.UIA_LegacyIAccessibleValuePropertyId)

    def equal(self, other):
        if not isinstance(other, Control):
            return False
        if self.ProcessId != other.ProcessId:
            return False
        return self._uiaobj == other._uiaobj

    def exist(self):
        """判断控件是否存在
        """
        try:
            self._init_uiaobj()
        except Exception as e:
            print("判断UIA控件存在失败,UIA elm实例化异常:%s" % e)
            return False
        return True

    def wait_for_exist(self, timeout, interval):
        """等待控件存在
        """
        Timeout(timeout, interval).retry(self.exist, (), (),
                                         lambda x: x == True)

    @property
    def Hwnd(self):
        """返回控件句柄
        """
        return self.hwnd

    @property
    def HWnd(self):
        """兼容其他类型控件
        """
        return self.hwnd

    @property
    def hwnd(self):
        return self._uiaobj.CurrentNativeWindowHandle

    @property
    def HasKeyboardFocus(self):
        """返回是否被选为键盘输入
        """
        return self._uiaobj.CurrentHasKeyboardFocus

    @property
    def ClassName(self):
        """返回ClassName
        """
        return self._uiaobj.CurrentClassName