def _get_test_candidate(version: str, locale: str) -> str or None: """Download and extract a build candidate. Build may either refer to a Firefox release identifier, package, or build directory. :param: build: str with firefox build :return: Installation path for the Firefox App """ logger.debug('Getting build, version %s, locale %s' % (version, locale)) if version == 'local': candidate = PathManager.get_local_firefox_path() if candidate is None: logger.critical('Firefox not found. Please download if from https://www.mozilla.org/en-US/firefox/new/') else: try: s_t, s_d = _get_scraper_details(version, CHANNELS, os.path.join(PathManager.get_working_dir(), 'cache'), locale) scraper = FactoryScraper(s_t, **s_d) firefox_dmg = scraper.download() install_dir = install(src=firefox_dmg, dest=os.path.join(PathManager.get_temp_dir(), 'firefox{}{}'.format(normalize_str(version), normalize_str(locale)))) return get_binary(install_dir, 'Firefox') except errors.NotFoundError: logger.critical('Specified build {} has not been found. Closing Iris ...'.format(version)) return None
def get_app_test_directory(): """Collects tests based on include/exclude criteria and selected application.""" app = core_args.application test_list = [] if load_app(app): include = core_args.test exclude = core_args.exclude tests_dir = os.path.join(PathManager.get_tests_dir(), app) logger.debug('Path %s found. Checking content ...', tests_dir) for dir_path, sub_dirs, all_files in PathManager.sorted_walk( tests_dir): for current_file in all_files: current_full_path = os.path.join(dir_path, current_file) if current_file.endswith( '.py') and not current_file.startswith( '__') and include in current_full_path: if exclude == '' or exclude not in current_full_path: test_list.append(current_full_path) if len(test_list) == 0: logger.error( '\'%s\' does not contain tests based on your search criteria. Exiting program.' % tests_dir) else: logger.info('List of all tests found: [%s]' % ', '.join(map(str, test_list))) return test_list
def get_test_params(): tests_to_execute = collect_tests() pytest_args = [] if get_core_args().rerun: failed_tests_file = os.path.join(PathManager.get_working_dir(), 'lastfail.txt') tests_dir = os.path.join(PathManager.get_tests_dir(), get_core_args().target) failed_tests = [] with open(failed_tests_file, 'r') as f: for line in f: failed_tests.append(line.rstrip('\n')) f.close() # Read first line to see if these tests apply to current target. if tests_dir in failed_tests[0]: pytest_args = failed_tests else: logging.error( 'The -a flag cannot be used now because the last failed tests don\'t match current target.' ) else: if len(tests_to_execute) > 0: for running in tests_to_execute: pytest_args.append(running) else: exit_iris('No tests to execute.', status=1) return pytest_args
def make_profile(profile_type: Profiles = None, preferences: dict = None): """Internal-only method used to create profiles on disk. :param profile_type: Profiles.BRAND_NEW, Profiles.LIKE_NEW, Profiles.TEN_BOOKMARKS, Profiles.DEFAULT :param preferences: A dictionary containing profile preferences """ if profile_type is None: profile_type = Profiles.DEFAULT if preferences is None: if profile_type is Profiles.BRAND_NEW: preferences = Settings.default_fx_prefs else: preferences = {} test_root = PathManager.get_current_tests_directory() current_test = os.environ.get('CURRENT_TEST') test_path = current_test.split(test_root)[1].split('.py')[0][1:] profile_path = os.path.join(PathManager.get_current_run_dir(), test_path, 'profile') if not os.path.exists(profile_path): os.makedirs(profile_path) if profile_type is Profiles.BRAND_NEW: logger.debug('Creating brand new profile: %s' % profile_path) elif profile_type in (Profiles.LIKE_NEW, Profiles.TEN_BOOKMARKS): logger.debug('Creating new profile from %s staged profile.' % profile_type.value.upper()) profile_path = FirefoxProfile._get_staged_profile( profile_type, profile_path) else: raise ValueError('No profile found: %s' % profile_type.value) return MozProfile(profile=profile_path, preferences=preferences)
def convert_test_list(test_list, only_failures=False): """Takes a flat list of test objects and paths and converts to an object that can be serialized as JSON. :param test_list: List of completed tests :param only_failures: If True, only return failed tests :return: """ test_root = os.path.join(PathManager.get_module_dir(), 'tests') tests = [] for test in test_list: test_failed = True if 'FAILED' in test.outcome or 'ERROR' in test.outcome else False original_path = str(test.item.__dict__.get('fspath')) target_root = original_path.split(test_root)[1] target = target_root.split(os.sep)[1] test_path = target_root.split('%s%s%s' % (os.sep, target, os.sep))[1] parent = tests details = get_test_markers(test.item) for module in test_path.split(os.sep): test_obj = {'name': module.split('.py')[0]} if 'py' not in module: module_exists = False for objects in parent: if objects['name'] == module: parent = objects['children'] module_exists = True break if not module_exists: new_parent = test_obj['children'] = [] if only_failures and test_failed: parent.append(test_obj) elif not only_failures: parent.append(test_obj) parent = new_parent else: if test_failed: test_assert = { 'error': test.error.lstrip(), 'message': test.message.lstrip(), 'call_stack': test.traceback + '\n\n ', 'code': get_failing_code(test.node_name, int(test.line)) } test_obj['assert'] = test_assert test_obj['result'] = test.outcome test_obj['time'] = test.test_duration debug_image_directory = os.path.join(PathManager.get_current_run_dir(), test_path.split('.py')[0], 'debug_images') test_obj['debug_image_directory'] = debug_image_directory test_obj['debug_images'] = get_image_names(debug_image_directory) test_obj['description'] = details.get('description') values = {} for i in details: if i != 'description': values[i] = details.get(i) test_obj['values'] = values if only_failures and test_failed: parent.append(test_obj) elif not only_failures: parent.append(test_obj) parent = tests return tests
def scan_all_tests(): tests_directory = PathManager.get_tests_dir() logger.debug('Path %s found. Checking content ...', tests_directory) test_list = {} rootdir = tests_directory.rstrip(os.sep) start = rootdir.rfind(os.sep) + 1 exclude_dirs = {'images', '.pytest_cache', '__pycache__'} exclude_files = {'__init__.py', 'pytest.ini', '.DS_Store'} for path, dirs, files in PathManager.sorted_walk(rootdir): [dirs.remove(d) for d in list(dirs) if d in exclude_dirs] [files.remove(d) for d in list(files) if d in exclude_files] folders = path[start:].split(os.sep) subdir = dict.fromkeys(files) parent = reduce(dict.get, folders[:-1], test_list) parent[folders[-1]] = subdir if len(files) > 0: if os.path.isdir(path): my_plugin = TestCollector() pytest.main(['--collect-only', '-p', 'no:terminal', path], plugins=[my_plugin]) for module in my_plugin.get_collected_items(): try: module_path = str(module.fspath) module_name = os.path.basename(module_path) temp = module_path.split( '%stests%s' % (os.sep, os.sep))[1].split(module_name)[0] package = os.path.join('tests', temp) current_test = module.own_markers[0].kwargs test_object = { 'name': module_name, 'module': module_path, 'description': current_test.get('description'), 'package': package } if not current_test.get('values'): pass else: for value in current_test.get('values').kwargs: test_object[value] = current_test.get( 'values').kwargs[value] subdir[module_name] = test_object except TypeError as e: logger.warning('Error in test - %s: %s' % (module, e.message)) except AttributeError: logger.warning('[%s] is not a test file. Skipping...', module) return test_list
def main(): args = get_core_args() initialize_logger() validate_config_ini(args) if verify_config(args): pytest_args = None settings = None if show_control_center(): init_control_center() user_result = launch_control_center() logger.debug(user_result) if user_result is not 'cancel': # Extract list of tests if not 'tests' in user_result: logger.info('No tests chosen, closing Iris.') delete(PathManager.get_run_id(), update_run_file=False) ShutdownTasks.at_exit() exit(0) pytest_args = user_result['tests'] # Extract target from response and update core arg for application/target set_core_arg('application', user_result['target']) # Extract settings from response args = get_core_args() settings = user_result['args'] else: # User cancelled or otherwise failed to select tests, # so we will shut down Iris. delete(PathManager.get_run_id(), update_run_file=False) ShutdownTasks.at_exit() exit(0) try: target_plugin = get_target(args.application) if settings is not None: logger.debug('Passing settings to target: %s' % settings) target_plugin.update_settings(settings) if pytest_args is None: pytest_args = get_test_params() pytest_args.append('-vs') pytest_args.append('-r ') pytest_args.append('-s') initialize_platform(args) pytest.main(pytest_args, plugins=[target_plugin]) except ImportError: logger.error('Could not load plugin for {} application'.format( args.application)) exit(1) else: logger.error('Failed platform verification.') exit(1)
def _load_all_patterns(application: str) -> list: """Function returns a list with all the project's Patterns.""" if get_core_args().resize: _convert_hi_res_images() result_list = [] for root, dirs, files in os.walk(PathManager.get_module_dir()): for file_name in files: if file_name.endswith('.png'): if application in root and (PathManager.get_images_path() in root or 'common' in root): pattern_name, pattern_scale = _parse_name(file_name) pattern_path = os.path.join(root, file_name) pattern = {'name': pattern_name, 'path': pattern_path, 'scale': pattern_scale} result_list.append(pattern) return result_list
def collect_tests(): """Collects tests based on include/exclude criteria and selected target.""" target = core_args.target test_list = [] if load_target(target): include = core_args.test exclude = core_args.exclude if os.path.isfile(include): with open(include, 'r') as f: for line in f: test_list.append(line.rstrip('\n')) f.close() else: tests_dir = os.path.join(PathManager.get_tests_dir(), target) logger.debug('Path %s found. Checking content ...', tests_dir) for dir_path, sub_dirs, all_files in PathManager.sorted_walk(tests_dir): for current_file in all_files: directory = '%s%s%s' % (os.sep, core_args.directory, os.sep) include_params = [include] exclude_params = [exclude] if ',' in include: include_params = include.split(',') if ',' in exclude: exclude_params = exclude.split(',') current_full_path = os.path.join(dir_path, current_file) if current_file.endswith('.py') and not current_file.startswith('__'): if include is '' and exclude is '' and directory is '': if not current_full_path in test_list: test_list.append(current_full_path) else: if core_args.directory is '' or directory in current_full_path: for include_param in include_params: if include_param is '' or include_param in current_full_path: for exclude_param in exclude_params: if exclude_param is '': if not current_full_path in test_list: test_list.append(current_full_path) else: if exclude_param not in current_full_path: if not current_full_path in test_list: test_list.append(current_full_path) if len(test_list) == 0: logger.error('\'%s\' does not contain tests based on your search criteria. Exiting program.' % tests_dir) else: logger.debug('List of all tests found: [%s]' % ', '.join(map(str, test_list))) return test_list
def save_failed_tests(test_list): failed_tests_file = os.path.join(PathManager.get_working_dir(), 'lastfail.txt') with open(failed_tests_file, 'w') as f: for test in test_list: f.write(test + '\n') f.close()
def _convert_hi_res_images(): """Function resizes all the project's hi-resolution images.""" for root, dirs, files in os.walk(PathManager.get_module_dir()): for file_name in files: if file_name.endswith('.png'): if 'images' in root or 'local_web' in root: if '@' in file_name: logger.debug('Found hi-resolution image at: %s' % os.path.join(root, file_name)) temp = file_name.split('@') name = temp[0] scale = int(temp[1].split('x')[0]) new_name = '%s.png' % name img = Image.open(os.path.join(root, file_name)) logger.debug('Resizing image from %sx scale' % scale) new_img = img.resize( (img.width / scale, img.height / scale), Image.ANTIALIAS) logger.debug( 'Creating newly converted image file at: %s' % os.path.join(root, new_name)) new_img.save(os.path.join(root, new_name)) logger.debug('Removing unused image at: %s' % os.path.join(root, file_name)) os.remove(os.path.join(root, file_name))
def initialize_logger(): logging.basicConfig(filename=PathManager.get_log_file_path(), format=set_log_format()) initialize_logger_level(core_args.level) # Control pytest terminal output via environment variable instead of parameter. if core_args.level > 10: os.environ['PYTEST_ADDOPTS'] = '-p no:terminal'
def create_target_json(): if not use_cached_target_file(): logging.info('Preparing data for the Control Center.') logging.info('This may take a minute.') master_target_dir = os.path.join(PathManager.get_module_dir(), 'targets') target_list = [ f for f in os.listdir(master_target_dir) if not f.startswith('__') and not f.startswith('.') ] targets = [] for item in target_list: try: app_tests = scan_all_tests(item) target_module = importlib.import_module('targets.%s.app' % item) try: target = target_module.Target() targets.append({ 'name': target.target_name, 'tests': app_tests, 'icon': '%s.png' % item, 'settings': target.cc_settings }) except NameError: logger.error('Can\'t find default Target class.') except ImportError as e: logger.error('Problems importing module \'%s\':\n%s' % (item, e)) target_json = {'targets': targets} target_json_file = os.path.join(args.workdir, 'data', 'targets.json') with open(target_json_file, 'w') as f: json.dump(target_json, f, sort_keys=True, indent=True)
def launch_control_center(): profile_path = os.path.join(get_core_args().workdir, 'cc_profile') fx_path = PathManager.get_local_firefox_path() if fx_path is None: logger.error( 'Can\'t find local Firefox installation, aborting Iris run.') return False, None args = ['http://127.0.0.1:%s' % get_core_args().port] process_args = {'stream': None} profile = MozProfile(profile=profile_path, preferences=Settings.default_fx_prefs) fx_runner = FirefoxRunner(binary=fx_path, profile=profile, cmdargs=args, process_args=process_args) fx_runner.start() server = LocalWebServer(get_core_args().workdir, get_core_args().port) server.stop() time.sleep(Settings.DEFAULT_UI_DELAY) if OSHelper.is_mac(): type(text='q', modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text='w', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text='q', modifier=KeyModifier.CTRL) try: fx_runner.stop() except Exception as e: logger.debug('Error stopping fx_runner') logger.debug(e) return server.result
def update_run_index(app, finished=False): if finished: failed = 0 total_duration = 0 for test in app.completed_tests: if test.outcome == 'FAILED' or test.outcome == 'ERROR': failed = failed + 1 total_duration = total_duration + test.test_duration current_run = { 'duration': total_duration, 'failed': failed, 'id': PathManager.get_run_id(), 'locale': args.locale, 'target': args.target, 'total': len(app.completed_tests) } else: current_run = { 'duration': '-1', 'failed': '-1', 'id': PathManager.get_run_id(), 'locale': args.locale, 'target': args.target, 'total': '-1' } run_file = os.path.join(args.workdir, 'data', 'runs.json') if os.path.exists(run_file): logger.debug('Updating run file: %s' % run_file) with open(run_file, 'r') as f: run_file_data = json.load(f) for run in run_file_data['runs']: if run['id'] == PathManager.get_run_id(): run_file_data['runs'].remove(run) run_file_data['runs'].append(current_run) else: logger.debug('Creating run file: %s' % run_file) run_file_data = {'runs': []} run_file_data['runs'].append(current_run) with open(run_file, 'w') as f: json.dump(run_file_data, f, sort_keys=True, indent=True) f.close()
def submit_email_report(target, result): """ PLACEHOLDER FOR EMAIL REPORT :param test_results: TEST RESULT SESSION need to update with appliications and git object """ logger.info(' --------------------------------------------------------- '+Color.BLUE+'Starting Email report:'+Color.END+' ----------------------------------------------------------\n') email_report = EmailClient() email_report.send_email_report(target, str(result), PathManager.get_git_details())
def exit_iris(message, status=0): if status == 0: logger.info(message) elif status == 1: logger.error(message) else: logger.debug(message) delete(PathManager.get_run_id(), update_run_file=False) ShutdownTasks.at_exit() exit(status)
def launch_control_center(): profile_path = os.path.join(get_core_args().workdir, 'cc_profile') fx_path = PathManager.get_local_firefox_path() if fx_path is None: logger.error( 'Can\'t find local Firefox installation, aborting Iris run.') return False, None args = ['http://127.0.0.1:%s' % get_core_args().port] process_args = {'stream': None} profile = MozProfile(profile=profile_path, preferences=Settings.default_fx_prefs) if OSHelper.is_windows(): process = subprocess.Popen([ fx_path, '-no-remote', '-new-tab', args, '--wait-for-browser', '-foreground', '-profile', profile.profile ], shell=False) else: fx_runner = FirefoxRunner(binary=fx_path, profile=profile, cmdargs=args, process_args=process_args) fx_runner.start() server = LocalWebServer(get_core_args().workdir, get_core_args().port) server.stop() time.sleep(Settings.DEFAULT_UI_DELAY) if OSHelper.is_mac(): type(text='q', modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text='w', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text='q', modifier=KeyModifier.CTRL) if OSHelper.is_windows(): if process.pid is not None: try: logger.debug('Closing Firefox process ID: %s' % process.pid) process = psutil.Process(process.pid) for proc in process.children(recursive=True): proc.kill() process.kill() except psutil.NoSuchProcess: pass else: try: fx_runner.stop() except Exception as e: logger.debug('Error stopping fx_runner') logger.debug(e) return server.result
def get_file_attachment(): test_report_file = os.path.join(PathManager.get_current_run_dir(), 'iris_log.log') if os.path.exists(test_report_file): file_log = open(test_report_file) attachment = MIMEText(file_log.read(), 1) file_log.close() attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(test_report_file)) return attachment else: raise Exception('File %s is not present in path' % test_report_file)
def init_control_center(): copy_tree( os.path.join(PathManager.get_module_dir(), 'src', 'control_center', 'assets'), get_core_args().workdir) targets_dir = os.path.join(PathManager.get_module_dir(), 'targets') exclude_dirs = {'__pycache__'} for path, dirs, files in PathManager.sorted_walk(targets_dir): [dirs.remove(d) for d in list(dirs) if d in exclude_dirs] for target in dirs: src = os.path.join(targets_dir, target, 'icon.png') dest = os.path.join(get_core_args().workdir, 'images', '%s.png' % target) try: shutil.copyfile(src, dest) except FileNotFoundError: logger.warning('Could not find icon file for target: %s' % target) break create_target_json()
def load_target(target: str = None): """Checks if provided target exists.""" if target is None: logger.warning('No target provided. Launching Firefox target by default') target = core_args.target target_dir = os.path.join(PathManager.get_module_dir(), 'targets', target) if os.path.exists(target_dir): logger.debug('%s target module found!' % target) return True logger.critical('Iris doesn\'t contain %s target module' % target) return False
def delete_all(): """ Delete each run in the runs.json file, one at a time. """ logger.debug('Delete All command received.') run_file = os.path.join(PathManager.get_working_dir(), 'data', 'runs.json') with open(run_file, 'r') as data: run_file_data = json.load(data) data.close() for run in run_file_data['runs']: delete(run['id'])
def delete(args, update_run_file=True): """ Delete a past run. :param args: The run ID to delete :param update_run_file: Remove entry from runs.json file """ logger.debug('Received delete command with arguments: %s ' % args) if update_run_file: # Load run log JSON, find entry that matches the argument and delete it. # Then, write new run log file. run_file = os.path.join(PathManager.get_working_dir(), 'data', 'runs.json') if os.path.exists(run_file): logger.debug('Deleting entry %s from run file: %s' % (args, run_file)) with open(run_file, 'r') as data: run_file_data = json.load(data) found = False for run in run_file_data['runs']: if run['id'] == args: run_file_data['runs'].remove(run) found = True if found: with open(run_file, 'w') as data: json.dump(run_file_data, data, sort_keys=True, indent=True) else: logger.error('Entry for run %s not found in run log file.' % args) else: logger.error('Run file not found.') # Remove run directory on disk. target_run = os.path.join(PathManager.get_working_dir(), 'runs', args) if os.path.exists(target_run): shutil.rmtree(target_run, ignore_errors=True) else: logger.error('Run directory does not exist: %s' % target_run)
def _get_staged_profile(profile_name, path): """ Internal-only method used to extract a given profile. :param profile_name: :param path: :return: """ staged_profiles = os.path.join(PathManager.get_module_dir(), 'targets', 'firefox', 'firefox_app', 'profiles') sz_bin = find_executable('7z') logger.debug('Using 7zip executable at "%s"' % sz_bin) zipped_profile = os.path.join(staged_profiles, '%s.zip' % profile_name.value) cmd = [ sz_bin, 'x', '-y', '-bd', '-o%s' % staged_profiles, zipped_profile ] logger.debug('Unzipping profile with command "%s"' % ' '.join(cmd)) try: output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: logger.error('7zip failed: %s' % repr(e.output)) raise Exception('Unable to unzip profile.') logger.debug('7zip succeeded: %s' % repr(output)) from_directory = os.path.join(staged_profiles, profile_name.value) to_directory = path logger.debug('Creating new profile: %s' % to_directory) dir_util.copy_tree(from_directory, to_directory) try: shutil.rmtree(from_directory) except WindowsError: logger.debug( 'Error, can\'t remove orphaned directory, leaving in place.') resource_fork_folder = os.path.join(staged_profiles, '__MACOSX') if os.path.exists(resource_fork_folder): try: shutil.rmtree(resource_fork_folder) except WindowsError: logger.debug( 'Error, can\'t remove orphaned directory, leaving in place.' ) return to_directory
def scan_all_tests(target): logging.info('Gathering test info for \'%s\'...' % target) master_test_root = os.path.join(PathManager.get_module_dir(), 'tests') test_root = os.path.join(master_test_root, target) base_props = ['description'] tests = [] my_plugin = TestCollector() pytest.main(['--collect-only', '-s', '-p', 'no:terminal', test_root], plugins=[my_plugin]) for test in my_plugin.get_collected_items(): original_path = str(test.__dict__.get('fspath')) target_root = original_path.split(master_test_root)[1] test_path = target_root.split('%s%s%s' % (os.sep, target, os.sep))[1] parent = tests details = get_test_markers(test) for module in test_path.split(os.sep): test_obj = {'name': module.split('.py')[0]} if 'py' not in module: module_exists = False for objects in parent: if objects['name'] == module: parent = objects['children'] module_exists = True break if not module_exists: new_parent = test_obj['children'] = [] parent.append(test_obj) parent = new_parent else: for prop in base_props: if details.get(prop) is not None: test_obj[prop] = details.get(prop) else: test_obj[prop] = '' test_obj['file'] = original_path values = {} for i in details: if i not in base_props: values[i] = details.get(i) if details.get('platform') is None: values['platform'] = 'all' if details.get('locale') is None: values['locale'] = 'all' test_obj['values'] = values parent.append(test_obj) parent = tests return tests
def load_app(app: str = None): """Checks if provided application exists.""" if app is None: logger.warning( 'No application provided. Launching Firefox application by default' ) app = core_args.application app_dir = os.path.join(PathManager.get_module_dir(), 'targets', app) if os.path.exists(app_dir): logger.debug('%s application module found!' % app) return True logger.critical('Iris doesn\'t contain %s application module' % app) return False
def __init__(self): BaseTarget.__init__(self) global target_args target_args = self.get_target_args() self.target_name = 'Firefox' self.process_list = [] self.cc_settings = [{ 'name': 'firefox', 'type': 'list', 'label': 'Firefox', 'value': ['local', 'latest', 'latest-esr', 'latest-beta', 'nightly'], 'default': 'beta' }, { 'name': 'locale', 'type': 'list', 'label': 'Locale', 'value': OSHelper.LOCALES, 'default': 'en-US' }, { 'name': 'mouse', 'type': 'list', 'label': 'Mouse speed', 'value': ['0.0', '0.5', '1.0', '2.0'], 'default': '0.5' }, { 'name': 'highlight', 'type': 'checkbox', 'label': 'Debug using highlighting' }, { 'name': 'override', 'type': 'checkbox', 'label': 'Run disabled tests' }, { 'name': 'email', 'type': 'checkbox', 'label': 'Email results' }, { 'name': 'report', 'type': 'checkbox', 'label': 'Create TestRail report' }] self.local_web_root = os.path.join(PathManager.get_module_dir(), 'targets', 'firefox', 'local_web')
def save_debug_image(needle, haystack, locations): """Saves input Image for debug. :param Image || None needle: Input needle image that needs to be highlighted. :param haystack: Input Region as Image. :param List[Location] || Location locations: Location or list of Location as coordinates. :return: None. """ w, h = needle.get_size() path = PathManager.get_debug_image_directory() timestamp_str = re.sub('[ :.-]', '_', str(datetime.datetime.now())) resolution_str = '_not_found' if len(locations) == 0 else '_found' temp_f = timestamp_str + resolution_str file_name = '%s.jpg' % os.path.join(path, temp_f) if not os.path.exists(path): os.makedirs(path) not_found_txt = ' <<< Pattern not found!' if len(locations) > 0: for loc in locations: cv2.rectangle(haystack.get_gray_array(), (loc.x, loc.y), (loc.x + w, loc.y + h), (0, 0, 255), 2) cv2.imwrite(file_name, haystack.get_gray_array(), [int(cv2.IMWRITE_JPEG_QUALITY), 50]) else: gray_img = haystack.get_gray_image() search_for_image = needle.get_color_image() v_align_pos = int(gray_img.size[1] / 2 - h / 2) d_image = Image.new("RGB", (gray_img.size[0], gray_img.size[1])) d_image.paste(gray_img) d_image.paste(search_for_image, (0, v_align_pos)) d_array = np.array(d_image) cv2.rectangle(d_array, (w, v_align_pos), (haystack.width, v_align_pos + h), (255, 255, 255), cv2.FILLED) cv2.putText(d_array, not_found_txt, (w, v_align_pos + h - 5), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (0, 0, 0), 1, 16) cv2.imwrite(file_name, d_array, [int(cv2.IMWRITE_JPEG_QUALITY), 50])
def save_debug_ocr_image(text, haystack, text_occurrences): """Saves input Image for debug. :param text: Input text that needs to be highlighted. :param haystack: Input Region as Image. :param List[Location] || Location text_occurrences: Location or list of Location as coordinates. :return: None. """ path = PathManager.get_debug_image_directory() timestamp_str = re.sub('[ :.-]', '_', str(datetime.datetime.now())) resolution_str = '_not_found' if len(text_occurrences) == 0 else '_found' temp_f = timestamp_str + resolution_str file_name = '%s.jpg' % os.path.join(path, temp_f) if not os.path.exists(path): os.makedirs(path) not_found_txt = ' \'{}\' not found!'.format(text) if text_occurrences and len(text_occurrences) > 0: for occurrence in text_occurrences: cv2.rectangle(haystack.get_gray_array(), (occurrence.x, occurrence.y), (occurrence.x + occurrence.width, occurrence.y + occurrence.height), (0, 0, 255), 2) cv2.imwrite(file_name, haystack.get_gray_array(), [int(cv2.IMWRITE_JPEG_QUALITY), 50]) else: gray_img = haystack.get_gray_image() v_align_pos = int(gray_img.size[1] / 2 - 20 / 2) d_image = Image.new("RGB", (gray_img.size[0], gray_img.size[1])) d_image.paste(gray_img) d_array = np.array(d_image) cv2.rectangle(d_array, (0, v_align_pos), (haystack.width, v_align_pos + 20), (255, 255, 255), cv2.FILLED) cv2.putText(d_array, not_found_txt, (0, v_align_pos + 20 - 5), cv2.FONT_HERSHEY_TRIPLEX, 0.4, (0, 0, 0), 1, 16) cv2.imwrite(file_name, d_array, [int(cv2.IMWRITE_JPEG_QUALITY), 50])
# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. import logging import os.path from configparser import ConfigParser from src.core.util.path_manager import PathManager logger = logging.getLogger(__name__) config_file = os.path.join(PathManager.get_module_dir(), 'config.ini') config = ConfigParser() def get_config_section(section): """Returns all properties of a section as a dict or None if section does not exist.""" if os.path.isfile(config_file): try: config.read(config_file) if config.has_section(section): result = dict(config.items(section)) return result except EOFError: logger.warning('Config file error.') return None logger.warning('Config file not found.') return None