示例#1
0
    def find_row(self, row_name, force_expand=False):
        ''' Если row_name:
            a) str или unicode, то это просто имя строки таблицы
            б) если список, то в нем перечислены вложения строк таблицы. Последняя в списке -- искомая строка.

            force_expand -- разворачивать ли свернутые строки, если они обнаружены при поиске строки и являются для нее группирующими.
        '''
        def _find_row_precisely(obj, nested_name, exact_level):
            rows = [DataItem(e) for e in obj.find_all(Name=nested_name, exact_level=exact_level) if e.CONTROL_TYPE in ["DataItem"]]
            if len(rows) > 1:
                Exception('ANPropGrid_Table.find_row._find_row_precisely(...): len(rows) != 0\n\tlen(rows) = %i\n\trows = %s' % (len(rows), str(rows)))
            elif len(rows) == 0:
                raise FindFailed('pikuli.ANPropGrid_Table: row \'%s\' not found.\nSearch arguments:\n\trow_name = %s\n\tforce_expand = %s' % (str(nested_name), str(row_name), str(force_expand)))
            return rows[0]

        logger.debug('pikuli.ANPropGrid_Table.find_row: searching by criteria item_name = \'%s\'' % str(row_name))
        if isinstance(row_name, list):
            row = _find_row_precisely(self, row_name[0], 1)
            for nested_name in row_name[1:]:
                if not row.is_expanded() and not force_expand:
                    raise FindFailed('pikuli.ANPropGrid_Table: row \'%s\' was found, but it is collapsed. Try to set force_expand = True.\nSearch arguments:\n\trow_name = %s\n\tforce_expand = %s' % (str(nested_name), str(row_name), str(force_expand)))
                row.expand()
                row = _find_row_precisely(self, row_name[0], 1)
                row = _find_row_precisely(row, nested_name, 0)  # Раньше: Так функция сперва изет Next, а потом -- Previous. Т.о., максимальная скорость (если строки не найдется, то фейл теста -- можно и потратить время на previous-поиск)
            found_elem = row
        else:
            found_elem = _find_row_precisely(self, row_name, 1)
        return found_elem
示例#2
0
 def init(cls, adapter):
     """
     This method is aimed to avoid Python circular dependencies.
     """
     for name, plain_desc in patterns_plain_description.items():
         desc = _PattDesc(adapter, name, plain_desc)
         if desc.is_valid:
             cls._pattern_descriptions[desc.pattern_name] = desc
         else:
             logger.debug(
                 "Control pattern {} not exist in current UIA namespace".
                 format(desc.pattern_name))
示例#3
0
    def make_class_method(cls, target_cls, method_name, reason):
        formated_reason = cls.format_reason(reason)
        err_msg = (
            'Method {!r} of the {!r} is unavailable by the following reason:'
            '{}{!s}'.format(method_name,
                            type(target_cls).__name__, os.linesep,
                            formated_reason))
        logger.debug('NOTE: ' + err_msg)

        def not_implemeted_dummy(*args, **kwargs):
            raise NotImplementedError(err_msg)

        return staticmethod(not_implemeted_dummy)
示例#4
0
 def _build_map(cls, get_attr_from, name_format, err_msg_preamble, names):
     """
     Is used in derived classes :class:`dotnet.Adapter` and :class:`win_native.Adapter`.
     """
     name2id = {}
     for name in names:
         api_name = name_format.format(name=name)
         id_ = getattr(get_attr_from, api_name, None)
         if id_ is None:
             logger.debug(
                 "{preamble} {name} ({api_name}) not exist in current UIA namespace"
                 .format(preamble=err_msg_preamble,
                         name=name,
                         api_name=api_name))
             continue
         name2id[name] = id_
     return name2id
示例#5
0
    def find_item(self,
                  item_name,
                  force_expand=False,
                  timeout=None,
                  exception_on_find_fail=True):
        '''
            item_name -- Cписок строк-названий эелементов дерева, пречисленных по их вложенности один в другой. Последняя строка в списке -- искомый элемент.
            force_expand -- разворачивать ли свернутые элементы на пути поиска искового.
        '''
        # logger.debug(CONSOLE_ERASE_LINE_SEQUENCE)
        logger.debug(
            'pikuli.TreeItem.find_item: searching by criteria item_name = \'%s\', timeout = %s'
            % (str(item_name), str(timeout)))

        if not isinstance(item_name, (list, tuple)):
            item_name = [item_name]
        if len(item_name) == 0:
            raise Exception('pikuli.ui_element.TreeItem: len(item_name) == 0')
        if not self.is_expanded() and not force_expand:
            raise FindFailed(
                'pikuli.ui_element.TreeItem: item \'%s\' was found, but it is not fully expanded. Try to set force_expand = True.\nSearch arguments:\n\titem_name = %s\n\tforce_expand = %s'
                % (self.Name, str(item_name), str(force_expand)))

        self.expand()

        elem = self.find(Name=item_name[0],
                         ControlType='TreeItem',
                         exact_level=1,
                         timeout=timeout,
                         exception_on_find_fail=exception_on_find_fail)
        if elem is None:
            logger.debug(
                'pikuli.ui_element.TreeItem.find_item: %s has not been found. No exception -- returning None'
                % str(item_name))
            return None
        if len(item_name) == 1:
            found_elem = elem
        else:
            found_elem = elem.find_item(
                item_name[1:],
                force_expand,
                timeout=timeout,
                exception_on_find_fail=exception_on_find_fail)
        """
        TODO: не работает пауза: сразу содает несолкьо анализов ситацайии, не дожидаясь появления первого
        elem = self.find_all(Name=item_name[0], exact_level=1, timeout=timeout, exception_on_find_fail=exception_on_find_fail)
        if (elem is None) or (len(elem) == 0):
            if exception_on_find_fail:
                logger.error('pikuli.ui_element.TreeItem.find_item: \'%s\' has not been found. Raising exception...' % str(item_name))
                raise Exception('pikuli.ui_element.TreeItem.find_item: \'%s\' has not been found.' % str(item_name))
            else:
                logger.error('pikuli.ui_element.TreeItem.find_item: \'%s\' has not been found. No exception -- returning None' % str(item_name))
                return None
        if len(elem) != 1:
            if exception_on_find_fail:
                logger.error('pikuli.ui_element.TreeItem.find_item: more than one elemnt \'%s\' has been found. Raising exception...' % str(item_name))
                raise Exception('pikuli.ui_element.TreeItem: more than one elemnt \'%s\' has been found.' % str(item_name))
            else:
                logger.error('pikuli.ui_element.TreeItem.find_item: more than one elemnt \'%s\' has been found. No exception -- returning None' % str(item_name))
                return None

        if len(item_name) == 1:
            found_elem = elem[0]
        else:
            found_elem = elem[0].find_item(item_name[1:], force_expand, timeout=timeout)
        """

        return found_elem
示例#6
0
 def make_class(cls, target_cls, msg=None, reason=None, **kwargs):
     err_msg = cls._make_class_err_msg(msg, 'class', reason, target_cls,
                                       **kwargs)
     logger.debug('NOTE: ' + err_msg)
     return cls._make_class(err_msg)
示例#7
0
    def find(self, **kwargs):
        '''
        Поиск дочернего окна-объекта любого уровня вложенности. Под окном пнимается любой WinForms-элемент любого класса.

        В **kwargs можно передавать следующие поля, использующиеся для сравнения с одноименноыми UIA-свойствами элементов интерфейса:
            AutomationId          --  Неки текстовый ID, который, видимо, может назанчаться при создании тестируемой программы.
            ClassName             --  Имя класса. К примеру, "WindowsForms10.Window.8.app.0.1e929c1_r9_ad1".
            Name                  --  Имя (title) искомого элемента UI.
            ControlType           --  Тип контрола. Строковое название из структуры UIA_automation_control_type_identifiers_mapping / списка UIA_automation_control_type_identifiers.
                                      (см. также "Control Type Identifiers", https://msdn.microsoft.com/en-us/library/windows/desktop/ee671198(v=vs.85).aspx)
            LocalizedControlType  --  Локализованное название контрола.
            ProcessId             --  Для UAI это число (PID). Дополним возможность указания строки -- имени исполняемого файла, по которому предварительно будем определять PID.

            AutomationId, ClassName, Name --  Строка или "скомпилированное" регулярное выржение (объект от re.compile()).

        Наличие нескольких критериев подразумевает логические AND между ними.

        При поиске [AutomationId, Name, ClassName] парметр может быть:
            1. Строкой. Элемент UI будет добавлять к списку найденных, если эта строка точно соответствует его атрибуту (с учетом регистра).
            2. Списком строк. Каждая из этих строка должна быть подстрокой в атрибуте искомого элемента UI (с учетом регистра).
            3. re.compile

        Также в **kwargs возможны следующие управляющие инструкции:
            find_first_only    --  Если False, то возвращается список _всех_ найденных окон (пустой, если ничего не найдено).
                                   Если True, то возвращается только одно значение первого найденного элемента (после первого обнаружения поиск останавливается!). Если ничего
                                   не найденно, то возвращает None или создает исключение (см. exception_on_find_fail).
            max_descend_level  --  Максимальная глубина вложенности дочерних объектов. Нумерация от 1. None -- бесконечность. Взаимоисключающий с exact_level параметр.
                                   Здесь рассматривается дерево из UI объектов всех возможных типов (TreeWalker, например, создает свое дерево, соответствующее condition'у поиска)
            exact_level        --  Искать элементы строго такой глубины. Взаимоисключающий с max_descend_level параметр.
                                    = 0 -- поиск среди соседних
                                    > 0 -- поиск среди дочерних выбранной глубины
                                    < 0 -- возвращает предка выбранной дальности
            exception_on_find_fail  --  По умолчанию None. Это означает, что переприсовится True при find_first_only = True, False при find_first_only = False.
            timeout            --  Если ищем только один эелемент (find_first_only=True) и ничего не нашлось, то будем повторять попытки в течение этого времени.
                                   Не оказывает влияния на поиск всех элементов (find_first_only=False). Возможные значения:
                                        timeout = 0     --  однократная проверка
                                        timeout = None  --  использование дефолтного значения (по умолчанию)
                                        timeout = <число секунд>

            _find_all  --  служебный (если True, то find() знает, что ее вызвали из find_all())

        Возвращает:
            объект типа Region.
        '''
        self._test4readiness()

        # Обработка воходных аргументов:
        find_first_only = kwargs.pop('find_first_only', True)
        max_descend_level = kwargs.pop('max_descend_level', None)
        exact_level = kwargs.pop('exact_level', None)
        exception_on_find_fail = kwargs.pop('exception_on_find_fail', None)
        timeout = _timeout = verify_timeout_argument(
            kwargs.pop('timeout', None),
            allow_None=True,
            err_msg='pikuli.UIAElement.__init__()')
        next_serach_iter_delya = kwargs.pop('next_serach_iter_delya',
                                            NEXT_SEARCH_ITER_DELAY)
        _find_all = kwargs.pop('_find_all', False)

        # logger.debug('find: timeout = %s; self._find_timeout = %s' % (str(timeout), str(self._find_timeout)))
        if timeout is None:
            if DYNAMIC_FIND_TIMEOUT is not None:
                timeout = DYNAMIC_FIND_TIMEOUT
            else:
                timeout = self._find_timeout
        if exception_on_find_fail is None:
            exception_on_find_fail = find_first_only
        if _find_all:
            _func_name = 'pikuli.UIAElement.find_all'
        else:
            _func_name = 'pikuli.UIAElement.find'

        if max_descend_level is not None and exact_level is not None:
            raise Exception(
                '%s: max_descend_level is not None and exact_level is not None'
                % _func_name)
        if max_descend_level is not None and max_descend_level < 1:
            raise Exception(
                '%s: max_descend_level is not None and max_descend_level < 1' %
                _func_name)

        criteria = {}
        not_none_criteria = {}
        for key in [
                'AutomationId', 'ClassName', 'Name', 'LocalizedControlType'
        ]:
            val = kwargs.pop(key, None)
            if val is not None:
                not_none_criteria[key] = val
                if isinstance(val, re.Pattern) or hasattr(val, 'match'):
                    pass
                elif isinstance(val, (list, tuple)):
                    val = list(map(str, val))
                else:
                    val = str(val)
            criteria[key] = val

        val = kwargs.pop('ControlType', None)
        if val is not None:
            not_none_criteria['ControlType'] = val
            val = Adapter.get_control_type_id(val)
        criteria['ControlType'] = val

        val = kwargs.pop('ProcessId', None)
        if val is not None:
            if isinstance(val, str):
                not_none_criteria['ProcessId'] = val
                for proc in psutil.process_iter():
                    try:
                        if val == proc.name():
                            val = proc.pid
                            break
                    except psutil.NoSuchProcess:
                        pass
            if isinstance(val, str):
                logger.error('Pikuli Cannot find process by name')
                raise Exception(
                    '%s(): can not find process by its name: "%s"' %
                    (_func_name, str(val)))
        criteria['ProcessId'] = val

        # Сделаем not_none_criteria и criteria, которые выводится на экран, крсивее:
        #   -- информативный вывод регулярных выражений
        def _criteria_pretty_print(cri):
            _cri = {}
            for (k, v) in cri.items():
                if hasattr(v, 'pattern'):
                    _cri[k] = v.pattern
                else:
                    _cri[k] = v
            return str(_cri)

        str__not_none_criteria = _criteria_pretty_print(not_none_criteria)
        str__criteria = _criteria_pretty_print(criteria)

        if len(kwargs) != 0:
            raise Exception('%s: kwargs has unknown fields %s\n\tkwargs = %s' %
                            (_func_name, kwargs.keys(), str(kwargs)))

        #  Начинаем поиск по очереди по всем критериям. Поиск элементов с помощью рекурсивного
        # вызова нашей функции. Будем искать через TreeWalker с условием CreateTrueCondition(), так
        # как простая функция поиска не позволяет (судя по документации) искать родителя:
        class FirstFoundEx(Exception):
            def __init__(self, automation_element):
                self.automation_element = automation_element
                super(Exception, self).__init__()

        def _is_automation_element_suitable(automation_element):
            if criteria['ProcessId'] is not None and criteria[
                    'ProcessId'] != automation_element.CurrentProcessId:
                return False

            if (criteria['ControlType'] is not None and criteria['ControlType']
                    != automation_element.GetCurrentPropertyValue(
                        Adapter.try_get_property_id('ControlType'))):
                return False

            for key in [
                    'AutomationId', 'ClassName', 'Name', 'LocalizedControlType'
            ]:
                if criteria[key] is None:
                    continue

                try:
                    prop_id = Adapter.try_get_property_id(key)
                    uielem_val = automation_element.GetCurrentPropertyValue(
                        prop_id)
                    if uielem_val is None:
                        return False
                except Exception as ex:
                    raise ex

                if isinstance(criteria[key], list):
                    for substr in criteria[key]:
                        if uielem_val is None or not (substr in uielem_val):
                            return False
                elif isinstance(criteria[key], str):
                    if not (uielem_val == criteria[key]):
                        return False
                elif isinstance(criteria[key], re.Pattern) or hasattr(
                        criteria[key], 'match'):  # re.complile
                    if not (criteria[key].match(uielem_val) is not None):
                        return False
                else:
                    raise Exception(
                        '%s: unsupported value \"%s\" of key \'%s\'' %
                        (_func_name, str(criteria[key]), str(key)))

            return True

        def _search_with_method(start_automation_element, method_f):
            found_automation_element_arr_local = []
            next_automation_element = method_f(start_automation_element)
            while next_automation_element:
                if _is_automation_element_suitable(next_automation_element):
                    if find_first_only:
                        raise FirstFoundEx(next_automation_element)
                    found_automation_element_arr_local.append(
                        next_automation_element)
                next_automation_element = method_f(next_automation_element)
            return found_automation_element_arr_local

        '''
        # Поиск по веткам элементов:
        def _descendants_range_level(walker, automation_element, level=0):
            found_automation_element_arr = []

            if max_descend_level is None or level < max_descend_level:  # max_descend_level > 0; level от вызова к вызову +1 (растет от 0).
                child_automation_element = walker.GetFirstChild(automation_element)
                while child_automation_element:
                    if _is_automation_element_suitable(child_automation_element):
                        if find_first_only:
                            raise FirstFoundEx(child_automation_element)
                        found_automation_element_arr += [child_automation_element]

                    if max_descend_level is None or level < max_descend_level - 1:
                        found_automation_element_arr += _descendants_range_level(walker, child_automation_element, level+1)

                    child_automation_element = walker.GetNextSibling(child_automation_element)

            return found_automation_element_arr'''

        # Поиск по слоям вложенности:
        def _descendants_range_level(walker, automation_element):
            found_automation_element_arr = []
            current_level_todo_arr = []
            next_level_todo_arr = []
            level = 0

            def _add_to_next_level_todo(root_elem):
                if max_descend_level is None or level < max_descend_level:
                    try:
                        elem = walker.GetFirstChild(root_elem)
                    except Exception as ex:
                        raise FindFailed(ex)
                    while elem:
                        next_level_todo_arr.append(elem)
                        elem = walker.GetNextSibling(elem)

            def _goto_next_level():
                return (next_level_todo_arr, [], level + 1)

            _add_to_next_level_todo(automation_element)
            (current_level_todo_arr, next_level_todo_arr,
             level) = _goto_next_level()

            while len(current_level_todo_arr) != 0:

                while len(current_level_todo_arr) != 0:
                    elem = current_level_todo_arr.pop(0)
                    if _is_automation_element_suitable(elem):
                        if find_first_only:
                            raise FirstFoundEx(elem)
                        found_automation_element_arr.append(elem)
                    _add_to_next_level_todo(elem)

                (current_level_todo_arr, next_level_todo_arr,
                 level) = _goto_next_level()

            return found_automation_element_arr

        def _descendants_exact_level(walker, automation_element, level=0):
            if level < exact_level:  # exact_level > 0; level от вызова к вызову +1 (растет от 0).
                found_automation_element_arr = []
                child_automation_element = walker.GetFirstChild(
                    automation_element)
                while child_automation_element:
                    found_automation_element_arr += _descendants_exact_level(
                        walker, child_automation_element, level + 1)
                    child_automation_element = walker.GetNextSibling(
                        child_automation_element)
                return found_automation_element_arr

            elif level == exact_level:
                if _is_automation_element_suitable(automation_element):
                    if find_first_only:
                        raise FirstFoundEx(automation_element)
                    return [automation_element]
                return []

            else:  # exact_level > 0 && level > exact_level
                raise Exception(
                    '%s: exact_level > 0 && level > exact_level\n\texact_level = %s\n\tlevel = %s'
                    % tuple(map(str, [_func_name, exact_level, level])))

        # - subroutines: end -
        txt_search_timeout = 'searching with timeout = %s (call/class/module: %s/%s/%s) ...' % (
            str(timeout), str(_timeout), str(
                self._find_timeout), str(DEFAULT_FIND_TIMEOUT))
        txt_pikuli_search_pattern = '%s: by criteria %s %%s' % (
            _func_name, str__not_none_criteria)
        logger.debug(txt_pikuli_search_pattern % txt_search_timeout)

        walker = TreeWalker(Condition.TrueCondition)
        t0 = datetime.datetime.today()
        while True:
            try:
                # Исключение FirstFoundEx используется как goto.
                if exact_level is not None:
                    # Обработаем варианты поиска предков:
                    if exact_level < 0:
                        automation_element = self._automation_element
                        for level in range(-exact_level):
                            automation_element = walker.GetParent(
                                automation_element)
                        if find_first_only:
                            # TODO: можом получить структуру automation_element, указывающую на ptr=0, если нет родителя заданного уровня. Надо обработать, но не знаю пока как.
                            raise FirstFoundEx(automation_element)
                        found_automation_element_arr = [automation_element]

                    # Обработаем варианты поиска братьев-сестер:
                    elif exact_level == 0:
                        found_automation_element_arr = _search_with_method(
                            self._automation_element, walker.GetNextSibling)
                        if find_first_only and len(
                                found_automation_element_arr) != 0:
                            raise FirstFoundEx(found_automation_element_arr[0])
                        found_automation_element_arr += _search_with_method(
                            self._automation_element,
                            walker.GetPreviousSibling)
                        if find_first_only:
                            if len(found_automation_element_arr) == 0:
                                raise FirstFoundEx(None)
                            raise FirstFoundEx(found_automation_element_arr[0])

                    # Обработаем вариант поиска потомков (descendants).
                    else:
                        # Поиск по веткам элементов:
                        found_automation_element_arr = _descendants_exact_level(
                            walker, self._automation_element)
                        if find_first_only:
                            if len(found_automation_element_arr) == 0:
                                raise FirstFoundEx(None)
                            raise FirstFoundEx(found_automation_element_arr[0])

                else:
                    # Теперь обработаем вариант поиска потомков в диапазоне возможных вложенностей.
                    # Будем искать по слоям вложенности элементов, а не по веткам. Это немного сложнее сделать, но должно быть эффективнее.
                    found_automation_element_arr = _descendants_range_level(
                        walker, self._automation_element)

                if find_first_only and len(found_automation_element_arr) == 0:
                    raise FirstFoundEx(None)

            except FirstFoundEx as ex:
                if ex.automation_element is None:
                    if (datetime.datetime.today() -
                            t0).total_seconds() >= timeout:
                        if exception_on_find_fail:
                            raise FindFailed(
                                '%s: no one elements was found\n\tself     = %s\n\tkwargs   = %s\n\tcriteria = %s\n\ttimeout  = %s'
                                % (_func_name, repr(self), str(kwargs),
                                   str__criteria, str(timeout)))
                        # logger.debug(CONSOLE_ERASE_LINE_SEQUENCE)
                        logger.debug(txt_pikuli_search_pattern %
                                     'has been found: None (%s)' %
                                     str(timeout))
                        return None
                    # t0 = datetime.datetime.today()
                    time.sleep(next_serach_iter_delya)
                else:
                    found_elem = UIAElement._make_suitable_uiaelement(
                        ex.automation_element, find_timeout=self._find_timeout)
                    # logger.debug(CONSOLE_ERASE_LINE_SEQUENCE)
                    logger.debug(txt_pikuli_search_pattern %
                                 ('has been found: %s (%s)' %
                                  (repr(found_elem), str(timeout))))
                    return found_elem

            except COMError as ex:
                if ex.args[0] == COR_E_TIMEOUT or ex.args[
                        0] == COR_E_SUBSCRIBERS_FAILED:
                    logger.debug(
                        'Cath %s exception: \"%s\". Checking timeout...' %
                        (NAMES_of_COR_E[ex.args[0]], str(ex)))
                    logger.debug(txt_pikuli_search_pattern %
                                 txt_search_timeout)
                    if (datetime.datetime.today() -
                            t0).total_seconds() >= timeout:
                        raise FindFailed(
                            '%s: Timeout while looking for UIA element:\n\tself = %s\n\tkwargs = %s'
                            % (_func_name, repr(self), str(kwargs)))
                    # t0 = datetime.datetime.today()
                    time.sleep(next_serach_iter_delya)
                else:
                    tb_text = ''.join(
                        traceback.format_list(
                            traceback.extract_tb(sys.exc_info()[2])[1:]))
                    full_text = 'Traceback for error point:\n' + tb_text.rstrip(
                    ) + '\nError message:\n  ' + type(
                        ex).__name__ + ': ' + str(ex)
                    logger.error(full_text)
                    raise ex
            else:
                # Тут, если ищем один элемент и все никак его не найдем или ищем много элементов:
                if not find_first_only or (find_first_only and
                                           (datetime.datetime.today() -
                                            t0).total_seconds() >= timeout):
                    break
                # t0 = datetime.datetime.today()
                time.sleep(next_serach_iter_delya)

        # В норме мы тут если ищем все совпадения (если ищем только первое, то должно было произойти и перехватиться исключение FirstFoundEx).
        if find_first_only:
            raise ('%s [INTERNAL]: Strange! We should not be here: ' %
                   _func_name + str(getframeinfo(currentframe())))
        if len(found_automation_element_arr) == 0:
            if exception_on_find_fail:
                raise FindFailed(
                    '%s: no one elements was found\n\tself = %s\n\tkwargs = %s\n\tcriteria = %s'
                    % (_func_name, repr(self), str(kwargs), str__criteria))
            found_elem = []
            # logger.debug(CONSOLE_ERASE_LINE_SEQUENCE)
            logger.debug(txt_pikuli_search_pattern %
                         ('there has been found no one UI-elem (%s)' %
                          (str(timeout))))
        else:
            found_elem = [
                UIAElement._make_suitable_uiaelement(
                    ae, find_timeout=self._find_timeout)
                for ae in found_automation_element_arr
            ]

            # Сормируем строку для вывода на экран из найденных элементов. Длина строки не более 70 символов.
            if len(found_elem) <= 2:
                s = repr(found_elem)
            else:
                s = repr(found_elem[:2])
                for i in range(3, len(found_elem)):
                    ss = repr(found_elem[:i])
                    if len(ss) > 70:
                        break
                    s = ss
                if 'ss' in locals() and len(s) != len(ss):
                    s = s[:-1] + ', ...]'
            # logger.debug(CONSOLE_ERASE_LINE_SEQUENCE)
            logger.debug(txt_pikuli_search_pattern %
                         ('there has been found %i UI-elems: %s (%s)' %
                          (len(found_elem), s, str(timeout))))
        return found_elem
示例#8
0
 def set_text_to_clipboard(cls, data):
     logger.debug(
         'set_text_to_clipboard: data = {d!r} ({d!s})'.format(d=data))
     cls._clipboard.set_text(str(data), -1)
     cls._clipboard.store()