def wait(ps, timeout=None, region=None) -> bool or FindError: """Verify that a Pattern or str appears. :param ps: String or Pattern. :param timeout: Number as maximum waiting time in seconds. :param region: Rectangle object in order to minimize the area. :return: True if found, otherwise raise FindError. """ if isinstance(ps, Pattern): if timeout is None: timeout = Settings.auto_wait_timeout image_found = image_find(ps, timeout, region) if image_found is not None: if get_core_args().highlight: highlight(region=region, ps=ps, location=[image_found]) return True else: raise FindError('Unable to find image %s' % ps.get_filename()) elif isinstance(ps, str): text_found = text_find(ps, region) if len(text_found) > 0: if get_core_args().highlight: highlight(region=region, ps=ps, text_location=text_found) return Location(text_found[0].x, text_found[0].y) else: raise FindError('Unable to find text %s' % ps) else: raise ValueError('Invalid input')
def find_all(ps: Pattern or str, region: Rectangle = None): """Look for all matches of a Pattern or image. :param ps: Pattern or String. :param region: Rectangle object in order to minimize the area. :return: Location object or FindError. """ if isinstance(ps, Pattern): images_found = match_template(ps, region, MatchTemplateType.MULTIPLE) if len(images_found) > 0: if get_core_args().highlight: highlight(region=region, ps=ps, location=images_found) return images_found else: raise FindError('Unable to find image %s' % ps.get_filename()) elif isinstance(ps, str): locations = [] text_found = text_find_all(ps, region) if len(text_found) > 0: if get_core_args().highlight: highlight(region=region, ps=ps, text_location=text_found) for text in text_found: locations.append(Location(text.x, text.y)) return locations else: raise FindError('Unable to find text %s' % ps)
def paste(text: str): """ :param text: Text to be pasted. :return: None. """ pyperclip.copy(text) text_copied = False wait_scan_rate = float(Settings.wait_scan_rate) interval = 1 / wait_scan_rate max_attempts = int(Settings.auto_wait_timeout * wait_scan_rate) attempt = 0 while not text_copied and attempt < max_attempts: if pyperclip.paste() == text: text_copied = True else: time.sleep(interval) attempt += 1 if not text_copied: raise FindError('Paste method failed.') if OSHelper.is_mac(): type(text='v', modifier=KeyModifier.CMD) else: type(text='v', modifier=KeyModifier.CTRL) pyperclip.copy('')
def _get_string_click_location(ps: str, region: Rectangle = None, align: Alignment = None): if align is None: align = Alignment.CENTER find_location = text_find(ps, region) if len(find_location) == 0: raise FindError('Unable to click on: %s' % ps) return find_location[0].apply_alignment(align)
def _get_string_click_location(ps: str, region: Rectangle = None, align: Alignment = None): if align is None: align = Alignment.CENTER find_location = text_find(ps, region) if len(find_location) == 0: raise FindError('Unable to find pattern {}'.format(ps.get_filename())) return find_location[0].apply_alignment(align)
def find(ps: Pattern or str, region: Rectangle = None) -> Location or FindError: """Look for a single match of a Pattern or image. :param ps: Pattern or String. :param region: Rectangle object in order to minimize the area. :return: Location object. """ if isinstance(ps, Pattern): image_found = match_template(ps, region, MatchTemplateType.SINGLE) if len(image_found) > 0: if get_core_args().highlight: highlight(region=region, ps=ps, location=image_found) return image_found[0] else: raise FindError('Unable to find image %s' % ps.get_filename()) elif isinstance(ps, str): text_found = text_find(ps, region) if len(text_found) > 0: if get_core_args().highlight: highlight(region=region, ps=ps, text_location=text_found) return Location(text_found[0].x, text_found[0].y) else: raise FindError('Unable to find text %s' % ps)
def _get_pattern_click_location(ps: Pattern, region: Rectangle = None, align: Alignment = None): """Returns the click location based on the pattern/string found location and alignment.""" if align is None: align = Alignment.CENTER width, height = ps.get_size() find_location = image_find(ps, region=region) if find_location is None: raise FindError('Unable to click on: %s' % ps.get_file_path()) if ps.get_target_offset(): target_offset = ps.get_target_offset() find_location.x += target_offset.x find_location.y += target_offset.y rect = Rectangle(find_location.x, find_location.y, width, height) return rect.apply_alignment(align)
def wait_vanish(pattern: Pattern, timeout: float = None, region: Rectangle = None) -> bool or FindError: """Wait until a Pattern disappears. :param pattern: Pattern. :param timeout: Number as maximum waiting time in seconds. :param region: Rectangle object in order to minimize the area. :return: True if vanished. """ if timeout is None: timeout = Settings.auto_wait_timeout image_found = image_vanish(pattern, timeout, region) if image_found is not None: return True else: raise FindError('%s did not vanish' % pattern.get_filename())
def generate_region_by_markers(top_left_marker_img=None, bottom_right_marker_img=None): """Generate a region starting from 2 markers. :param top_left_marker_img: Top left pattern used to generate the region. :param bottom_right_marker_img: Bottom right pattern used to generate the region. :return: Screen region generated. """ try: wait(top_left_marker_img, 10) exists(bottom_right_marker_img, 10) except FindError: raise FindError('Unable to find page markers.') top_left_pos = find(top_left_marker_img) bottom_right_pos = find(bottom_right_marker_img) marker_width, marker_height = bottom_right_marker_img.get_size() return Region(top_left_pos.x, top_left_pos.y, (bottom_right_pos.x + marker_width), bottom_right_pos.y - top_left_pos.y + marker_height)
def cancel_in_progress_downloads_from_the_library(private_window=False): # Open the 'Show Downloads' window and cancel all 'in progress' downloads. global cancel_downloads if private_window: steps = show_all_downloads_from_library_menu_private_window() logger.debug('Creating a region for Private Library window.') try: find_back_button = find(NavBar.BACK_BUTTON) except FindError: raise FindError('Could not get the coordinates of the nav bar back button.') try: find_hamburger_menu = find(NavBar.HAMBURGER_MENU) except FindError: raise FindError('Could not get the coordinates of the hamburger menu.') region = Region(find_back_button.x - 10, find_back_button.y, Screen.SCREEN_WIDTH, Screen.SCREEN_HEIGHT) else: steps = open_show_all_downloads_window_from_library_menu() logger.debug('Creating a region for Non-private Library window.') expected = exists(Library.TITLE, 10) assert expected is True, 'Library successfully opened.' try: find_library = find(Library.TITLE) except FindError: raise FindError('Could not get the x-coordinate of the library window title.') try: find_clear_downloads = find(Library.CLEAR_DOWNLOADS) except FindError: raise FindError('Could not get the x-coordinate of the clear_downloads button.') clear_downloads_width, clear_downloads_height = Library.CLEAR_DOWNLOADS.get_size() region = Region(find_library.x - 10, find_library.y, (find_clear_downloads.x + clear_downloads_width + 20) - find_library.x, 500) # Cancel all 'in progress' downloads. expected = region.exists(DownloadManager.DownloadsPanel.DOWNLOAD_CANCEL, 5) expected_highlighted = region.exists(DownloadManager.DownloadsPanel.DOWNLOAD_CANCEL_HIGHLIGHTED) if expected or expected_highlighted: steps.append(Step(expected, 'The Cancel Download button is displayed properly.')) cancel_downloads = True expected_cancel = True else: steps.append(Step(True, 'There are no downloads to be cancelled.')) cancel_downloads = False cancel_pattern = DownloadManager.DownloadsPanel.DOWNLOAD_CANCEL if expected \ else DownloadManager.DownloadsPanel.DOWNLOAD_CANCEL_HIGHLIGHTED if cancel_downloads: while expected_cancel: expected_cancel = region.exists(cancel_pattern, 10) if expected_cancel: click(cancel_pattern) if not private_window: hover(Library.TITLE) steps.append(Step(True, 'All downloads were cancelled.')) if private_window: close_tab() else: click_window_control('close') return steps
def _get_image_path(caller, image: str, target: str) -> str: """Enforce proper location for all Pattern creation. :param caller: Path of calling Python module. :param image: String filename of image. :return: Full path to image on disk. We will look at all possible paths relative to the calling file, with this priority: - current platform locale folder - common locale folder - current platform root - common root Each directory is scanned for four possible file names, depending on resolution. If the above fails, we will look up the file name in the list of project-wide images, and return whatever we find, with a warning message. If we find nothing, we will raise an exception. """ module = os.path.split(caller)[1] module_directory = os.path.split(caller)[0] parent_directory = os.path.basename(module_directory) file_name = image.split('.')[0] names = [image, '*****@*****.**' % file_name] if OSHelper.get_os_version() == 'win7': os_version = 'win7' else: os_version = OSHelper.get_os().value paths = [] current_locale = '' try: current_locale = get_core_args().locale except AttributeError: pass platform_directory = os.path.join(module_directory, 'images', os_version) platform_locale_directory = os.path.join(platform_directory, current_locale) for name in names: paths.append(os.path.join(platform_locale_directory, name)) common_directory = os.path.join(module_directory, 'images', 'common') common_locale_directory = os.path.join(common_directory, current_locale) for name in names: paths.append(os.path.join(common_locale_directory, name)) for name in names: paths.append(os.path.join(platform_directory, name)) for name in names: paths.append(os.path.join(common_directory, name)) found = False image_path = None for path in paths: if os.path.exists(path): found = True image_path = path break if found: logger.debug('Module %s requests image %s' % (module, image)) logger.debug('Found %s' % image_path) return image_path else: result_list = [ x for x in _load_all_patterns(target) if x['name'] == image ] if len(result_list) > 0: res = result_list[0] logger.warning( 'Failed to find image %s in default locations for module %s.' % (image, module)) logger.warning('Using this one instead: %s' % res['path']) logger.warning( 'Please move image to correct location relative to caller.') location_1 = os.path.join(parent_directory, 'images', 'common') location_2 = os.path.join(parent_directory, PathManager.get_images_path()) logger.warning('Suggested locations: %s, %s' % (location_1, location_2)) return res['path'] else: logger.error('Pattern creation for %s failed for caller %s.' % (image, caller)) logger.error( 'Image not found. Either it is in the wrong platform folder, or it does not exist.' ) logger.debug('Paths searched:') logger.debug('\n'.join(paths)) raise FindError('Pattern not found.')
def create_region_from_patterns(top=None, bottom=None, left=None, right=None, padding_top=None, padding_bottom=None, padding_left=None, padding_right=None): """Returns a region created from combined area of one or more patterns. Argument names are just for convenience and don't influence outcome. :param top: Top pattern used to generate the region. :param bottom: Bottom pattern used to generate the region. :param left: Left pattern used to generate the region. :param right: Right pattern used to generate the region. :param padding_top: Padding to be added to the pattern's top. :param padding_bottom: Padding to be added to the pattern's bottom. :param padding_left: Padding to be added to the pattern's left. :param padding_right: Padding to be added to the pattern's right. :return: region created from combined area of one or more patterns. """ patterns = [] if top: patterns.append(top) if bottom: patterns.append(bottom) if left: patterns.append(left) if right: patterns.append(right) if len(patterns) == 0: raise ValueError('One or more patterns required.') logger.debug('Creating region from %s pattern(s).' % len(patterns)) a, b = (Screen().width, Screen().height) p1 = Location(a, b) p2 = Location(0, 0) for pattern in patterns: if exists(pattern, 5): current_pattern = find(pattern) if current_pattern.x < p1.x: p1.x = current_pattern.x if current_pattern.y < p1.y: p1.y = current_pattern.y w, h = pattern.get_size() if current_pattern.x + w > p2.x: p2.x = current_pattern.x + w if current_pattern.y + h > p2.y: p2.y = current_pattern.y + h else: raise FindError('Pattern not found: %s ' % pattern) found_region = Region(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y) if padding_top or padding_bottom or padding_left or padding_right: logger.debug('Adding padding to region.') if padding_top: found_region.y -= padding_top found_region.height += padding_top if padding_bottom: found_region.height += padding_bottom if padding_left: found_region.x -= padding_left found_region.width += padding_left if padding_right: found_region.width += padding_right return found_region