Esempio n. 1
0
    def set_rect(self, *args, **kwargs):
        try:
            if len(args) == 4 and \
                    isinstance(args[0], int) and \
                    isinstance(args[1], int) and \
                    isinstance(args[2], int) and \
                    isinstance(args[3], int) and \
                    args[2] > 0 and args[3] > 0:
                relation = kwargs.get('relation', 'top-left') or 'top-left'

                self.w = args[2]
                self.h = args[3]
                if relation == 'top-left':
                    self.x = args[0]
                    self.y = args[1]
                elif relation == 'center':
                    self.x = args[0] - int(self.w / 2)
                    self.y = args[1] - int(self.h / 2)
            elif len(args) == 1:
                self._set_from_region(args[0])
            else:
                raise FailExit()

        except FailExit as e:
            raise FailExit(
                'Incorrect Region.set_rect() method call:'
                '\n\targs = {args}\n\tkwargs = {kwargs}\n\terror message: {msg}'
                .format(args=str(args), kwargs=str(kwargs), msg=str(e)))
Esempio n. 2
0
 def left(self, length=None):
     """
     Return left area relates to self, do not including self.
     Height of new area is equal to height of self.
     Width of new area is equal to 'length' or till the end of the screen
     if 'length' is not set
     """
     left_title = 'Region left of {}'.format(self.title)
     try:
         if length is None:
             scr = Region(*Screen(self.screen_number).area)
             reg = Region(scr.x,
                          self.y, (self.x - 1) - scr.x + 1,
                          self.h,
                          find_timeout=self._find_timeout,
                          title=left_title)
         elif isinstance(length, int) and length > 0:
             reg = Region(self.x - length,
                          self.y,
                          length,
                          self.h,
                          find_timeout=self._find_timeout,
                          title=left_title)
         else:
             raise FailExit(
                 'Incorrect length: type is {type}; value is {length}'.
                 format(typr=str(type(length)), length=str(length)))
     except FailExit:
         raise FailExit(
             'Incorrect left() method call:\n\tlength = {length}'.format(
                 length=length))
     return reg
Esempio n. 3
0
    def __init__(self, img_path, similarity=None):
        (self.__similarity, self.__img_path) = (None, None)
        img_path = str(img_path)

        try:
            _path = os.path.abspath(img_path)
            if os.path.exists(_path) and os.path.isfile(_path):
                self.__img_path = _path
            else:
                for _path in settings.list_image_path():
                    _path = os.path.join(_path, img_path)
                    if os.path.exists(_path) and os.path.isfile(_path):
                        self.__img_path = _path
                        break
            if not self.__img_path:
                raise FailExit('image file "{}" not found'.format(_path))

            if not similarity:
                self.__similarity = settings.min_similarity
            elif isinstance(similarity, float) and 0.0 < similarity <= 1.0:
                self.__similarity = similarity
            else:
                raise FailExit('error around "similarity" parameter')

        except FailExit as e:
            raise FailExit(
                'Incorect Pattern class constructor call:\n    img_path = %s'
                '\n    abspath(img_path) = %s\n    similarity = %s\n    message: %s'
                %
                (str(img_path), str(self.__img_path), str(similarity), str(e)))

        self.cv2_pattern = cv2.imread(self.__img_path)
        self.w = int(self.cv2_pattern.shape[1])
        self.h = int(self.cv2_pattern.shape[0])
Esempio n. 4
0
    def drag_to(self, *dest_location):

        delay = DRAGnDROP_MOVE_DELAY
        if len(dest_location) == 1 and isinstance(dest_location[0], Location):
            (dest_x, dest_y) = (dest_location[0].x, dest_location[0].y)
        elif len(dest_location) == 2:
            try:
                (dest_x, dest_y) = (int(dest_location[0]),
                                    int(dest_location[1]))
            except ValueError:
                raise FailExit('Location.drag_to: incorrect parameters')
        elif len(dest_location) == 3:
            try:
                (dest_x, dest_y) = (int(dest_location[0]),
                                    int(dest_location[1]))
            except ValueError:
                raise FailExit('Location.drag_to: incorrect parameters')
            delay = float(dest_location[2])

        else:
            raise FailExit('')

        self.mouse.drag_to(self.x, self.y, dest_x, dest_y, delay)
        logger.debug('Mouse drag from (%i, %i) to (%i, %i)' %
                     (self.x, self.y, dest_x, dest_y))
        return self
Esempio n. 5
0
    def offset(self, *args, **kwargs):
        """
        Return area moved relates to self.
        Option 1 (Sikuli-like):
            loc_offs := args[0] - Location type; where to move; (w,h) don't change
        Option 2:
            x_offs := args[0] - int; where to move by x
            y_offs := args[1] - int; where to move by y
            (w,h) don't change
        """
        if len(kwargs) != 0:
            raise FailExit('Unknown keys in kwargs = %s' % str(kwargs))

        offset_title = 'Offset of {}'.format(self.title)
        if len(args) == 2 and \
                (isinstance(args[0], int) or isinstance(args[0], float)) and \
                (isinstance(args[1], int) or isinstance(args[1], float)):
            return Region(self.x + int(args[0]),
                          self.y + int(args[1]),
                          self.w,
                          self.h,
                          find_timeout=self._find_timeout,
                          title=offset_title)
        elif len(args) == 1 and isinstance(args[0], Location):
            return Region(self.x + args[0].x,
                          self.y + args[0].y,
                          self.w,
                          self.h,
                          find_timeout=self._find_timeout,
                          title=offset_title)
        else:
            raise FailExit(
                'Incorrect offset() method call:\n\targs = {}'.format(args))
Esempio n. 6
0
    def wait_vanish(self,
                    image_path,
                    timeout=None,
                    similarity=settings.min_similarity):
        """
        Waits for pattern vanish during timeout (in seconds).
        If pattern already vanished before method call it return True

        if timeout = 0 - one search iteration will perform
        if timeout = None - default value will use
        """
        logger.info(
            'Check if "{file}" vanish during {t} with similarity {s}'.format(
                file=str(image_path).split(os.path.sep)[-1],
                t=timeout if timeout else str(self._find_timeout),
                s=similarity))
        try:
            self._wait_for_appear_or_vanish(Pattern(image_path, similarity),
                                            timeout, 'vanish')
        except FailExit:
            raise FailExit(
                'Incorrect wait_vanish() method call:'
                '\n\tregion = {region}\n\timage_path = {path}\n\ttimeout = {t}'
                .format(region=str(self), path=image_path, t=timeout))
        except FindFailed:
            logger.info('"{}" not vanished'.format(
                str(image_path).split(os.path.sep)[-1]))
            return False
        else:
            logger.info('"{}" vanished'.format(
                str(image_path).split(os.path.sep)[-1]))
            return True
        finally:
            self._last_match = None
Esempio n. 7
0
    def _take_screenshot_with_native_api(self, x, y, w, h, hwnd):
        if hwnd is None:
            scr_hdc = win32gui.CreateDC('DISPLAY', None, None)
        else:
            scr_hdc = win32gui.GetDC(hwnd)
        mem_hdc = win32gui.CreateCompatibleDC(scr_hdc)
        new_bitmap_h = win32gui.CreateCompatibleBitmap(scr_hdc, w, h)
        win32gui.SelectObject(
            mem_hdc, new_bitmap_h
        )  # Returns 'old_bitmap_h'. It will be deleted automatically.

        win32gui.BitBlt(mem_hdc, 0, 0, w, h, scr_hdc, x, y, win32con.SRCCOPY)

        bmp = win32ui.CreateBitmapFromHandle(new_bitmap_h)
        bmp_info = bmp.GetInfo()
        if bmp_info['bmHeight'] != h or bmp_info['bmWidth'] != w:
            raise FailExit('bmp_info = {bmp}, but (w, h) = ({w}, {h})'.format(
                bmp=bmp_info, width=w, height=h))
        if bmp_info['bmType'] != 0 or bmp_info['bmPlanes'] != 1:
            raise FailExit(
                'bmp_info = {bmp}: bmType !=0 or bmPlanes != 1'.format(
                    bmp=str(bmp_info)))
        if bmp_info['bmBitsPixel'] % 8 != 0:
            raise FailExit(
                'bmp_info = {bmp}: bmBitsPixel mod. 8 is not zero'.format(
                    bmp=str(bmp_info)))

        bmp_arr = list(bmp.GetBitmapBits())

        if len(bmp_arr) == w * h * 4:
            del bmp_arr[3::
                        4]  # Delete alpha channel. TODO: Is it fast enough???
        elif len(bmp_arr) != w * h * 3:
            raise FailExit('An error occurred while read bitmap bits')

        result = np.array(bmp_arr, dtype=np.uint8).reshape((h, w, 3))

        win32gui.DeleteDC(mem_hdc)
        win32gui.DeleteObject(new_bitmap_h)

        if not hwnd:
            win32gui.DeleteDC(scr_hdc)
        else:
            win32gui.ReleaseDC(hwnd, scr_hdc)

        return result
Esempio n. 8
0
 def set_h(self, h, relation='top-left'):
     if isinstance(h, int) and h > 0 and relation in self.relations:
         if relation == 'center':
             self.y += int((self.h - h) / 2)
         self.h = h
     else:
         raise FailExit(
             'Incorrect Region.set_h() method call:\n\th = {h}, {type_h}\n\trelation = {r}'
             .format(h=h, type_h=type(h), r=relation))
Esempio n. 9
0
 def set_w(self, w, relation='top-left'):
     if isinstance(w, int) and w > 0 and relation in self.relations:
         if relation == 'center':
             self.x += int((self.w - w) / 2)
         self.w = w
     else:
         raise FailExit(
             'Incorrect Region.set_w() method call:\n\tw = {w}, {type_w}\n\trelation = {r}'
             .format(w=w, type_w=type(w), r=relation))
Esempio n. 10
0
 def _set_from_region(self, reg):
     try:
         self.x = reg.x
         self.y = reg.y
         self.w = reg.w
         self.h = reg.h
         self._find_timeout = reg.get_find_timeout()
     except Exception as ex:
         raise FailExit(str(ex))
Esempio n. 11
0
    def __init__(self, n):
        if isinstance(n, int) and n >= 0:
            # Returns a sequence of tuples. For each monitor found, returns a handle to the monitor,
            # device context handle, and intersection rectangle: (hMonitor, hdcMonitor, PyRECT)
            (mon_hndl, _, mon_rect, _) = Display().get_monitor_info(n)

            self.area = (mon_rect[0], mon_rect[1], mon_rect[2] - mon_rect[0],
                         mon_rect[3] - mon_rect[1])
            self.number = n

        else:
            raise FailExit()
Esempio n. 12
0
    def __init__(self, *args, **kwargs):
        """
        Option 1:
            args[0]:
                Region object
                or Screen - whole screen

        Option 2:
            args[0:4] == [x, y, w, h]:
                integers - x,y coordinates, width w, height h;
                           A new rectangle area will build.
                           Area borders belongs to area

        kwargs can contain:
            title        - human-readable id (string)
            id           - id for use in code
            find_timeout - default value used for find() method
                           if don't pass to constructor a DEFAULT_FIND_TIMEOUT will use.
        """

        self.display = Display()
        self.scaling_factor = self.display.get_monitor_info(1)[-1]
        self.drag_location = None
        self.relations = ['top-left', 'center']
        (self.x, self.y, self.w, self.h) = (None, None, None, None)
        self.screen_number = 1
        self._last_match = None

        # human-readable id
        self.title = str(kwargs.get('title', 'New Region'))

        # internal id
        self._id = kwargs.get('id', 0)

        try:
            self.set_rect(*args, **kwargs)
        except FailExit:
            raise FailExit(
                'Incorrect Region class constructor call:\n\targs = {args}\n\tkwargs = {kwargs}'
                .format(args=args, kwargs=kwargs))

        self._find_timeout = self._verify_timeout(
            kwargs.get('find_timeout', DEFAULT_FIND_TIMEOUT),
            err_msg='pikuli.{}'.format(type(self).__name__))
        logger.debug(
            'New Region with name "{name}" created (x:{x} y:{y} w:{w} h:{h} timeout:{t})'
            .format(name=self.title,
                    x=self.x,
                    y=self.y,
                    w=self.w,
                    h=self.h,
                    t=self._find_timeout))
Esempio n. 13
0
 def set_x(self, x, relation='top-left'):
     """ 'top-left' -- x - top-left corner coordinate;
         'center'   -- x - center coordinate
     """
     if isinstance(x, int) and relation in self.relations:
         if relation is None or relation == 'top-left':
             self.x = x
         elif relation == 'center':
             self.x = x - int(self.w / 2)
     else:
         raise FailExit(
             'Incorrect Region.set_x() method call:\n\tx = {x}, {type_x}\n\trelation = {r}'
             .format(x=x, type_x=type(x), r=relation))
Esempio n. 14
0
 def _verify_timeout(timeout,
                     allow_none=False,
                     err_msg='pikuli.verify_timeout_argument()'):
     if not timeout and allow_none:
         return None
     try:
         timeout = float(timeout)
         if timeout < 0:
             raise ValueError
     except (ValueError, TypeError) as ex:
         raise FailExit('{msg}: wrong timeout = "{t}" ({ex})'.format(
             msg=err_msg, t=timeout, ex=str(ex)))
     return timeout
Esempio n. 15
0
 def set_y(self, y, relation='top-left'):
     """ 'top-left' -- y - top-left corner coordinate;
         'center'   -- y - center coordinate
     """
     if isinstance(y, int) and relation in self.relations:
         if relation is None or relation == 'top-left':
             self.y = y
         elif relation == 'center':
             self.y = y - int(self.h / 2)
     else:
         raise FailExit(
             'Incorrect Region.set_y() method call:\n\ty = {y}, {type_y}\n\trelation = {r}'
             .format(y=y, type_y=type(y), r=relation))
Esempio n. 16
0
 def __init__(self, x, y, w, h, score, pattern):
     try:
         super(Match,
               self).__init__(x,
                              y,
                              w,
                              h,
                              title=pattern.get_filename(full_path=False))
         if not isinstance(score, float) or score <= 0.0 or score > 1.0:
             raise FailExit(
                 'not isinstance(score, float) or score <= 0.0 or score > 1.0:'
             )
         self._score = score
         self._pattern = pattern
     except FailExit:
         raise FailExit(
             'Incorrect Match constructor call:\n\tx = {x}\n\ty = {y}\n\tw = {w}\n\th = {h}\n\tscore = {score}'
             .format(file=self._pattern.get_filename(),
                     x=self.x,
                     y=self.y,
                     w=self.w,
                     h=self.h,
                     score=self._score))
Esempio n. 17
0
 def exists(self, image_path):
     self._last_match = None
     try:
         self._last_match = self._wait_for_appear_or_vanish(
             image_path, 0, 'appear')
     except FailExit:
         raise FailExit(
             'Incorrect exists() method call:'
             '\n\tregion = {region}\n\timage_path = {path}'.format(
                 region=str(self), path=image_path))
     except FindFailed:
         return False
     else:
         return True
Esempio n. 18
0
    def find_all(self, pattern, delay_before=0):
        err_msg = 'Incorrect find_all() method call:' \
                  '\n\tpattern = {pattern}\n\tdelay_before = {delay}'.format(
                      pattern=str(pattern).split(os.pathsep)[-1], delay=delay_before)
        try:
            delay_before = float(delay_before)
        except ValueError:
            raise FailExit(err_msg)

        if isinstance(pattern, str):
            pattern = Pattern(pattern)
        if not isinstance(pattern, Pattern):
            raise FailExit(err_msg)

        time.sleep(delay_before)
        results = self._find(pattern, self.search_area)
        self._last_match = map(
            lambda pt: Match(pt[0], pt[1], pattern.get_w, pattern.get_h, pt[2],
                             pattern), results)
        logger.info('total found {count} matches of "{file}"'.format(
            count=len(self._last_match),
            file=pattern.get_filename(full_path=False)))
        return self._last_match
Esempio n. 19
0
 def _monitor_hndl_to_screen_n(self, m_hndl):
     """
     Converts monitor handle to number (from 1)
     0 - virtual monitor
     """
     minfo = win32api.GetMonitorInfo(
         m_hndl)  # For example for primary monitor:
     # {'Device': '\\\\.\\DISPLAY1', 'Work': (0, 0, 1920, 1040), 'Flags': 1, 'Monitor': (0, 0, 1920, 1080)}
     screen_n = int(minfo['Device'][len(r'\\.\DISPLAY'):])
     if screen_n <= 0:
         raise FailExit(
             'can not obtain Screen number from win32api.GetMonitorInfo() = {}'
             .format(minfo))
     return screen_n
Esempio n. 20
0
 def __init__(self, x, y, title="New Location"):
     self.title = title
     self.mouse = Mouse()
     self.keyboard = Keyboard()
     try:
         self.x = int(x)
         self.y = int(y)
         self._is_mouse_down = False
         logger.debug(
             'New Location with name "{name}" created ({x}, {y})'.format(
                 name=self.title, x=self.x, y=self.y))
     except:
         raise FailExit('Incorect Location class constructor call:'
                        '\n\tx = {x}\n\ty = {y}\n\ttitle= %{title}'.format(
                            x=x, y=y, title=title))
Esempio n. 21
0
 def nearby(self, length=0):
     """
     Return area around self, including self.
     """
     try:
         if isinstance(length, int) and ((length >= 0) or
                                         (length < 0 and
                                          (-2 * length) < self.w and
                                          (-2 * length) < self.h)):
             reg = Region(self.x - length,
                          self.y - length,
                          self.w + 2 * length,
                          self.h + 2 * length,
                          find_timeout=self._find_timeout,
                          title='Nearby region of {}'.format(self.title))
         else:
             raise FailExit(
                 'Incorrect length: type is {type}; value is {length}'.
                 format(typr=str(type(length)), length=str(length)))
     except FailExit:
         raise FailExit(
             'Incorrect nearby() method call:\n\tlength = {length}'.format(
                 length=length))
     return reg
Esempio n. 22
0
 def get_monitor_info(self, n):
     monitors = AppKit.NSScreen.screens()
     if n == 0:
         raise NotImplementedError
     elif n <= len(monitors):
         monitor = monitors[n - 1]
         sf = monitor.backingScaleFactor()
         return (monitor.deviceDescription()['NSScreenNumber'], None,
                 (int(monitor.frame().origin.x),
                  int(monitor.frame().origin.y),
                  int(monitor.frame().size.width * sf +
                      monitor.frame().origin.x),
                  int(monitor.frame().size.height * sf +
                      monitor.frame().origin.y)), sf)
     else:
         raise FailExit(
             'Pikuli.helpers.MacDisplay.get_monitor_info(): wrong monitor number specified: {}'
             .format(n))
Esempio n. 23
0
 def get_monitor_info(self, n):
     """
     Returns a sequence of tuples. For each monitor found, returns a handle to the monitor,
     device context handle, and intersection rectangle:
     (hMonitor, hdcMonitor, PyRECT)
     """
     monitors = win32api.EnumDisplayMonitors(None, None)
     if n >= 1:
         for m in monitors:
             if self._monitor_hndl_to_screen_n(m[0]) == n:
                 break
     elif n == 0:
         # (x1, y1, x2, y2) = (m[2][0], m[2][1], m[2][2], m[2][3])
         x_max = max(map(lambda m: m[2][2], monitors))
         y_max = max(map(lambda m: m[2][3], monitors))
         m = (None, None, (0, 0, x_max, y_max))
     else:
         raise FailExit('wrong screen number "{}"'.format(n))
     return m + (1, )
Esempio n. 24
0
 def wait(self, image_path=None, timeout=None):
     """
     For compatibility with Sikuli.
     Wait for pattern appear or just wait
     """
     if image_path is None:
         if timeout:
             time.sleep(timeout)
     else:
         try:
             self._last_match = self._wait_for_appear_or_vanish(
                 image_path, timeout, 'appear')
         except FailExit:
             self._last_match = None
             raise FailExit(
                 'Incorrect wait() method call:'
                 '\n\tregion = {region}\n\timage_path = {path}\n\ttimeout = {t}'
                 .format(region=str(self), path=image_path, t=timeout))
         else:
             return self._last_match
Esempio n. 25
0
 def right(self, dx):
     if isinstance(dx, int) and dx >= 0:
         return Location(self.x + dx, self.y)
     else:
         raise FailExit('Location.right: incorrect value')
Esempio n. 26
0
 def below(self, dy):
     if isinstance(dy, int) and dy >= 0:
         return Location(self.x, self.y + dy)
     else:
         raise FailExit('Location.below: incorrect value')
Esempio n. 27
0
 def above(self, dy):
     if isinstance(dy, int) and dy >= 0:
         return Location(self.x, self.y - dy)
     else:
         raise FailExit('Location.above: incorrect value')
Esempio n. 28
0
 def offset(self, dx, dy):
     if isinstance(dx, int) and isinstance(dy, int):
         return Location(self.x + dx, self.y + dy)
     else:
         raise FailExit('Location.offset: incorrect offset values')
Esempio n. 29
0
    def _wait_for_appear_or_vanish(self, pattern, timeout, condition):
        """
            pattern - could be String or List.
                      If isinstance(pattern, list), the first element will return.
                      It can be used when it's necessary to find one of the several images
        """
        fail_exit_text = 'bad "pattern" argument; it should be a string (path to image file) or Pattern object: {}'

        if not isinstance(pattern, list):
            pattern = [pattern]

        for (_i, p) in enumerate(pattern):
            if isinstance(p, str):
                pattern[_i] = Pattern(p)
            elif not isinstance(p, Pattern):
                raise FailExit(fail_exit_text.format(p))

        if timeout is None:
            timeout = self._find_timeout
        else:
            try:
                timeout = float(timeout)
                if timeout < 0:
                    raise ValueError
            except ValueError:
                raise FailExit(
                    'Incorrect argument: timeout = {}'.format(timeout))

        prev_field = None
        elaps_time = 0
        while True:
            if prev_field is None or (prev_field != self.search_area).all():
                for ptn in pattern:
                    results = self._find(ptn, self.search_area)
                    if condition == 'appear':
                        if len(results) != 0:
                            # Found something. Choose one result with best 'score'.
                            # If several results has the same 'score' a first found result will choose
                            res = max(results, key=lambda x: x[2])
                            logger.info(' "%s" has been found in(%i, %i)' %
                                        (ptn.get_filename(full_path=False),
                                         res[0], res[1]))
                            return Match(int(res[0] / self.scaling_factor),
                                         int(res[1] / self.scaling_factor),
                                         int(ptn.get_w / self.scaling_factor),
                                         int(ptn.get_h / self.scaling_factor),
                                         res[2], ptn)
                    elif condition == 'vanish':
                        if len(results) == 0:
                            logger.info('"{}" has vanished'.format(
                                ptn.get_filename(full_path=False)))
                            return
                    else:
                        raise FailExit(
                            'unknown condition: "{}"'.format(condition))

            time.sleep(DELAY_BETWEEN_CV_ATTEMPT)
            elaps_time += DELAY_BETWEEN_CV_ATTEMPT
            if elaps_time >= timeout:
                logger.warning('{} hasn`t been found'.format(
                    ptn.get_filename(full_path=False)))
                failed_images = ', '.join(
                    map(lambda _p: _p.get_filename(full_path=False), pattern))
                raise FindFailed('Unable to find "{file}" in {region}'.format(
                    file=failed_images, region=str(self)))