def main(): opt_parser = rose.opt_parse.RoseOptionParser() opt_parser.add_my_options("conf_dir", "property") opts, args = opt_parser.parse_args() reporter = rose.reporter.Reporter(opts.verbosity - opts.quietness) if opts.conf_dir is None: opts.conf_dir = os.getcwd() opts.conf_dir = os.path.abspath(opts.conf_dir) meta_conf_file_path = os.path.join(opts.conf_dir, rose.META_CONFIG_NAME) if not os.path.isfile(meta_conf_file_path): sys.exit(ERROR_LOAD_META_CONFIG_DIR.format(opts.conf_dir)) meta_config = rose.config.load(meta_conf_file_path) sections = None if args: sections = args properties = None if opts.property: properties = opts.property reports = metadata_check(meta_config, meta_dir=opts.conf_dir, only_these_sections=sections, only_these_properties=properties) macro_id = rose.macro.MACRO_OUTPUT_ID.format( rose.macro.VALIDATE_METHOD.upper()[0], "rose.metadata_check.MetadataChecker") text = rose.macro.get_reports_as_text( reports, macro_id) if reports: reporter(text, kind=reporter.KIND_ERR, level=reporter.FAIL, prefix="") sys.exit(1) reporter(rose.macro.MacroFinishNothingEvent(), level=reporter.V)
def handle_transform(config_map, new_config_map, change_map, macro_id, opt_conf_dir, opt_output_dir, opt_non_interactive, reporter): """Prompt the user to go ahead with macro changes and dump the output.""" user_allowed_changes = False has_changes = False for change_list in change_map.values(): for report in change_list: if not report.is_warning: has_changes = True break if has_changes: break reporter(get_reports_as_text(change_map, macro_id, is_from_transform=True), level=reporter.V, prefix="") if has_changes and (opt_non_interactive or _get_user_accept()): for conf_key, config in sorted(new_config_map.items()): dump_config(config, opt_conf_dir, opt_output_dir, conf_key=conf_key) if reporter is not None: reporter(MacroTransformDumpEvent(opt_conf_dir, opt_output_dir), level=reporter.VV) return True return False
def check_fields(self, info_config, interactive_mode, from_id=None, optional_file=None, prefix=None, error_reported=False): """Check the fields in the info config""" for key in ["owner", "project", "title"]: if not info_config.get([key], no_ignore=True): if optional_file is not None: raise SuiteInfoFieldError(key) info_config_new = info_config error_reported = True if interactive_mode: question = ("rose-suite.info: \n compulsory field \"%s\"" + " not defined,\n try again?") % key try: response = raw_input(question + " y/n (default n) ") except EOFError: sys.exit(1) if response != 'y': sys.exit(1) return info_config_new, error_reported else: raise SuiteInfoFieldError(key) meta_config = load_meta_config(info_config, directory=None, config_type=rose.INFO_CONFIG_NAME, error_handler=None, ignore_meta_error=False) reports = DefaultValidators().validate(info_config, meta_config) if reports != []: reports_map = {None: reports} text = (rose.macro.get_reports_as_text (reports_map, "rose.macro.DefaultValidators")) if interactive_mode: reporter = rose.reporter.Reporter() reporter(text, kind=reporter.KIND_ERR, level=reporter.FAIL, prefix="") info_config_new = info_config error_reported = True question = "Metadata issue, do you want to try again?" try: response = raw_input(question + " y/n (default n) ") except EOFError: sys.exit(1) if response != 'y': sys.exit(1) return info_config_new, error_reported else: raise SuiteInfoError(text) elif error_reported: return None, error_reported elif error_reported is False: return info_config, error_reported if from_id is not None: return self._copy(info_config, from_id) return info_config, error_reported
def handle_transform(app_config, new_config, change_list, macro_id, opt_conf_dir, opt_output_dir, opt_non_interactive, reporter): """Prompt the user to go ahead with macro changes and dump the output.""" user_allowed_changes = False has_changes = any([not i.is_warning for i in change_list]) reporter(get_reports_as_text(change_list, macro_id, is_from_transform=True), level=reporter.V, prefix="") if has_changes and (opt_non_interactive or _get_user_accept()): app_config = new_config dump_config(app_config, opt_conf_dir, opt_output_dir) if reporter is not None: reporter(MacroTransformDumpEvent(opt_conf_dir, opt_output_dir), level=reporter.VV) return True return False
def print_graph(suite_data, filter_id, properties=None, max_distance=None): """Dump out list of graph entries relating to a suite""" PREFIX_CHILD_GEN_TMPL = "[child%s]" PREFIX_PARENT = "[parent]" if properties is None: properties = [] reporter = rose.reporter.Reporter() ancestry = {} # Process suite_data to get ancestry tree for dict_row in sorted(suite_data, key=lambda _: _["revision"]): idx = dict_row["idx"] from_idx = dict_row.get("from_idx") if idx not in ancestry: ancestry[idx] = {'parent': None, 'children': []} if from_idx: ancestry[idx]['parent'] = from_idx for property in properties: ancestry[idx][property] = dict_row.get(property) if from_idx in ancestry: ancestry[from_idx]['children'].append(idx) else: ancestry[from_idx] = {'parent': None, 'children': [idx]} # Print out info parent_id = ancestry[filter_id]['parent'] if parent_id: reporter(PrintSuiteDetails( parent_id, [ancestry[parent_id][p] for p in properties]), prefix=PREFIX_PARENT) else: reporter(PrintSuiteDetails(None), prefix=PREFIX_PARENT) children = ancestry[filter_id]['children'] generation = 1 # Print out each generation of child suites while children: next_children = [] for c in children: output = [c] reporter(PrintSuiteDetails(c, [ancestry[c][p] for p in properties]), prefix=PREFIX_CHILD_GEN_TMPL % generation) # If a child has children add to list of next generation children if ancestry[c]['children']: next_children += ancestry[c]['children'] if max_distance and generation >= max_distance: break generation += 1 children = next_children
def main(): opt_parser = rose.opt_parse.RoseOptionParser() opt_parser.add_my_options("conf_dir", "property") rose.macro.add_site_meta_paths() rose.macro.add_env_meta_paths() opts, args = opt_parser.parse_args() reporter = rose.reporter.Reporter(opts.verbosity - opts.quietness) if opts.conf_dir is None: opts.conf_dir = os.getcwd() opts.conf_dir = os.path.abspath(opts.conf_dir) try: meta_config = rose.config_tree.ConfigTreeLoader().load( opts.conf_dir, rose.META_CONFIG_NAME, list(sys.path) ).node except IOError: sys.exit(ERROR_LOAD_META_CONFIG_DIR.format(opts.conf_dir)) sections = None if args: sections = args properties = None if opts.property: properties = opts.property reports = metadata_check(meta_config, meta_dir=opts.conf_dir, only_these_sections=sections, only_these_properties=properties) macro_id = rose.macro.MACRO_OUTPUT_ID.format( rose.macro.VALIDATE_METHOD.upper()[0], "rose.metadata_check.MetadataChecker") reports_map = {None: reports} text = rose.macro.get_reports_as_text(reports_map, macro_id) if reports: reporter(text, kind=reporter.KIND_ERR, level=reporter.FAIL, prefix="") sys.exit(1) reporter(rose.macro.MacroFinishNothingEvent(), level=reporter.V)
def calculate_edges(graph, suite_data, filter_id=None, properties=None, max_distance=None): """Get all connected suites for a prefix, optionally filtered.""" if properties is None: properties = [] node_rosie_properties = {} edges = [] forward_edges = {} back_edges = {} for dict_row in sorted(suite_data, key=lambda _: _["revision"]): idx = dict_row["idx"] node_rosie_properties[idx] = [] for prop in properties: node_rosie_properties[idx].append(dict_row.get(prop)) from_idx = dict_row.get("from_idx") if from_idx is None: continue edges.append((from_idx, idx)) forward_edges.setdefault(from_idx, []) forward_edges[from_idx].append(idx) back_edges.setdefault(idx, []) back_edges[idx].append(from_idx) if filter_id is None: # Plot all the edges we've found. for edge in sorted(edges): node0, node1 = edge add_node(graph, node0, node_rosie_properties.get(node0)) add_node(graph, node1, node_rosie_properties.get(node1)) graph.add_edge(edge[0], edge[1]) else: reporter = rose.reporter.Reporter() # Only plot the connections involving filter_id. node_stack = [] node_stack = [(filter_id, 0)] add_node(graph, filter_id, node_rosie_properties.get(filter_id), fillcolor="lightgrey", style="filled") ok_nodes = set([]) while node_stack: node, distance = node_stack.pop() if max_distance is not None and distance > max_distance: continue ok_nodes.add(node) for neighbour_node in (forward_edges.get(node, []) + back_edges.get(node, [])): if neighbour_node not in ok_nodes: node_stack.append((neighbour_node, distance + 1)) if len(ok_nodes) == 1: # There are no related suites. reporter(NoConnectionsEvent(filter_id)) for edge in sorted(edges): node0, node1 = edge if node0 in ok_nodes and node1 in ok_nodes: add_node(graph, node0, node_rosie_properties.get(node0)) add_node(graph, node1, node_rosie_properties.get(node1)) graph.add_edge(node0, node1)
def run_macros(app_config, meta_config, config_name, macro_names, opt_conf_dir=None, opt_fix=False, opt_non_interactive=False, opt_output_dir=None, opt_validate_all=False, verbosity=None): """Run standard or custom macros for a configuration.""" reporter = rose.reporter.Reporter(verbosity) macro_tuples, modules = get_macros_for_config( app_config, opt_conf_dir, return_modules=True, include_system=True) # Add all validator macros to the run list if specified. if opt_validate_all: for module_name, class_name, method, help in macro_tuples: if method == VALIDATE_METHOD: macro_name = ".".join([module_name, class_name]) macro_names.insert(0, macro_name) if not macro_names: sys.exit(0) elif opt_fix: for module_name, class_name, method, help in macro_tuples: if module_name != rose.macros.__name__: continue if method == TRANSFORM_METHOD: macro_name = ".".join([module_name, class_name]) macro_names.insert(0, macro_name) if not macro_names: sys.exit(0) # List all macros if none are given. if not macro_names: for module_name, class_name, method, help in macro_tuples: macro_name = ".".join([module_name, class_name]) macro_id = MACRO_OUTPUT_ID.format(method.upper()[0], macro_name) reporter(macro_id + "\n", prefix="") for help_line in help.split("\n"): reporter(MACRO_OUTPUT_HELP.format(help_line), level=reporter.V, prefix="") sys.exit(0) # Categorise macros given as arguments. macros_by_type = {} macros_not_found = [m for m in macro_names] for module_name, class_name, method, help in macro_tuples: this_macro_name = ".".join([module_name, class_name]) this_macro_method_name = ".".join([this_macro_name, method]) if this_macro_name in macro_names: macros_by_type.setdefault(method, []) macros_by_type[method].append(this_macro_name) if this_macro_name in macros_not_found: macros_not_found.remove(this_macro_name) elif this_macro_method_name in macro_names: macros_by_type.setdefault(method, []) macros_by_type[method].append(this_macro_name) if this_macro_method_name in macros_not_found: macros_not_found.remove(this_macro_method_name) for macro_name in macros_not_found: reporter(MacroNotFoundError(macro_name)) if macros_not_found: sys.exit(1) rc = 0 # Run any validator macros. if VALIDATE_METHOD in macros_by_type: config_problem_dict = validate_config(app_config, meta_config, macros_by_type[VALIDATE_METHOD], modules, macro_tuples, opt_non_interactive) if config_problem_dict: rc = 1 problem_macros = config_problem_dict.keys() problem_macros.sort() for macro_name in problem_macros: problem_list = config_problem_dict[macro_name] sort = rose.config.sort_settings problem_list.sort(report_sort) method_id = VALIDATE_METHOD.upper()[0] macro_id = MACRO_OUTPUT_ID.format(method_id, macro_name) reporter( get_reports_as_text( problem_list, macro_id, is_from_transform=False), level=reporter.V, kind=reporter.KIND_ERR, prefix="" ) no_changes = True # Run any transform macros. if TRANSFORM_METHOD in macros_by_type: no_changes = _run_transform_macros( macros_by_type[TRANSFORM_METHOD], config_name, app_config, meta_config, modules, macro_tuples, opt_non_interactive=opt_non_interactive, opt_conf_dir=opt_conf_dir, opt_output_dir=opt_output_dir, reporter=reporter) if not rc and no_changes: reporter(MacroFinishNothingEvent()) sys.exit(rc)
def main(): """Run rose upgrade.""" return_objects = parse_upgrade_args() if return_objects is None: sys.exit(1) app_config, config_map, meta_config, config_name, args, opts = ( return_objects) if opts.conf_dir is not None: os.chdir(opts.conf_dir) verbosity = 1 + opts.verbosity - opts.quietness reporter = rose.reporter.Reporter(verbosity) meta_opt_node = app_config.get([rose.CONFIG_SECT_TOP, rose.CONFIG_OPT_META_TYPE], no_ignore=True) if meta_opt_node is None or len(meta_opt_node.value.split("/")) < 2: reporter(rose.macro.MetaConfigFlagMissingError()) sys.exit(1) try: upgrade_manager = MacroUpgradeManager(app_config, opts.downgrade) except OSError as e: reporter(e) sys.exit(1) need_all_versions = opts.all_versions or args ok_versions = upgrade_manager.get_tags(only_named=not need_all_versions) if args: user_choice = args[0] else: best_mark = BEST_VERSION_MARKER curr_mark = CURRENT_VERSION_MARKER all_versions = [" " * len(curr_mark) + v for v in ok_versions] if opts.downgrade: all_versions.reverse() if all_versions: all_versions[0] = best_mark + all_versions[0].lstrip() all_versions.append(curr_mark + upgrade_manager.tag) else: if all_versions: all_versions[-1] = best_mark + all_versions[-1].lstrip() all_versions.insert(0, curr_mark + upgrade_manager.tag) reporter("\n".join(all_versions) + "\n", prefix="") sys.exit() if user_choice == upgrade_manager.tag: reporter(UpgradeVersionSame(user_choice)) sys.exit(1) elif user_choice not in ok_versions: reporter(UpgradeVersionError(user_choice)) sys.exit(1) upgrade_manager.set_new_tag(user_choice) macro_config = copy.deepcopy(app_config) combined_config_map = rose.macro.combine_opt_config_map(config_map) macro_function = ( lambda conf, meta, conf_key: upgrade_manager.transform( conf, meta, opts.non_interactive) ) method_id = UPGRADE_METHOD.upper()[0] if opts.downgrade: method_id = DOWNGRADE_METHOD.upper()[0] macro_id = rose.macro.MACRO_OUTPUT_ID.format(method_id, upgrade_manager.get_name()) new_config_map, changes_map = rose.macro.apply_macro_to_config_map( combined_config_map, meta_config, macro_function, macro_name=macro_id) has_changes = rose.macro.handle_transform(config_map, new_config_map, changes_map, macro_id, opts.conf_dir, opts.output_dir, opts.non_interactive, reporter) if not has_changes: return new_meta_config = rose.macro.load_meta_config( new_config_map[None], directory=opts.conf_dir, config_type=rose.SUB_CONFIG_NAME, ignore_meta_error=True ) config_map = new_config_map combined_config_map = rose.macro.combine_opt_config_map(config_map) macro_function = ( lambda conf, meta, conf_key: rose.macros.trigger.TriggerMacro().transform(conf, meta) ) new_config_map, changes_map = rose.macro.apply_macro_to_config_map( combined_config_map, new_meta_config, macro_function, macro_name=macro_id) trig_macro_id = rose.macro.MACRO_OUTPUT_ID.format( rose.macro.TRANSFORM_METHOD.upper()[0], MACRO_UPGRADE_TRIGGER_NAME ) if any(changes_map.values()): rose.macro.handle_transform(config_map, new_config_map, changes_map, trig_macro_id, opts.conf_dir, opts.output_dir, opts.non_interactive, reporter)
def calculate_edges(graph, prefix, filter_id=None, properties=None, max_distance=None): """Get all connected suites for a prefix, optionally filtered.""" if properties is None: properties = [] ws_client = rosie.ws_client.RosieWSClient( prefixes=[prefix], event_handler=rose.reporter.Reporter()) node_rosie_properties = {} edges = [] forward_edges = {} back_edges = {} dict_rows = ws_client.search(prefix, all_revs=1)[0][0] for dict_row in sorted(dict_rows, key=lambda _: _["revision"]): suite_id = rosie.suite_id.SuiteId.from_idx_branch_revision( dict_row["idx"], dict_row["branch"], dict_row["revision"]) dict_row["suite"] = suite_id.to_string_with_version() if "local" in properties: dict_row["local"] = suite_id.get_status() if "date" in properties: dict_row["date"] = time.strftime( rosie.ws_client_cli.DATE_TIME_FORMAT, time.gmtime(dict_row.get("date"))) idx = dict_row["idx"] node_rosie_properties[idx] = [] for property in properties: node_rosie_properties[idx].append(dict_row.get(property)) from_idx = dict_row.get("from_idx") if from_idx is None: continue edges.append((from_idx, idx)) forward_edges.setdefault(from_idx, []) forward_edges[from_idx].append(idx) back_edges.setdefault(idx, []) back_edges[idx].append(from_idx) if filter_id is None: # Plot all the edges we've found. for edge in sorted(edges): node0, node1 = edge add_node(graph, node0, node_rosie_properties.get(node0)) add_node(graph, node1, node_rosie_properties.get(node1)) graph.add_edge(edge[0], edge[1]) else: # Only plot the connections involving filter_id. nodes = [n for edge in edges for n in edge] node_stack = [] node_stack = [(filter_id, 0)] add_node(graph, filter_id, node_rosie_properties.get(filter_id), fillcolor="lightgrey", style="filled") ok_nodes = set([]) while node_stack: node, distance = node_stack.pop() if max_distance is not None and distance > max_distance: continue ok_nodes.add(node) for neighbour_node in (forward_edges.get(node, []) + back_edges.get(node, [])): if neighbour_node not in ok_nodes: node_stack.append((neighbour_node, distance + 1)) if len(ok_nodes) == 1: # There are no related suites. reporter = rose.reporter.Reporter() reporter(NoConnectionsEvent(filter_id)) for edge in sorted(edges): node0, node1 = edge if node0 in ok_nodes and node1 in ok_nodes: add_node(graph, node0, node_rosie_properties.get(node0)) add_node(graph, node1, node_rosie_properties.get(node1)) graph.add_edge(node0, node1)
def calculate_edges(graph, prefix, filter_id=None, properties=None, max_distance=None): """Get all connected suites for a prefix, optionally filtered.""" if properties is None: properties = [] ws_client = rosie.ws_client.RosieWSClient(prefixes=[prefix], event_handler=rose.reporter.Reporter()) node_rosie_properties = {} edges = [] forward_edges = {} back_edges = {} dict_rows = ws_client.search(prefix, all_revs=1)[0][0] for dict_row in sorted(dict_rows, key=lambda _: _["revision"]): suite_id = rosie.suite_id.SuiteId.from_idx_branch_revision( dict_row["idx"], dict_row["branch"], dict_row["revision"] ) dict_row["suite"] = suite_id.to_string_with_version() if "local" in properties: dict_row["local"] = suite_id.get_status() if "date" in properties: dict_row["date"] = time.strftime(rosie.ws_client_cli.DATE_TIME_FORMAT, time.gmtime(dict_row.get("date"))) idx = dict_row["idx"] node_rosie_properties[idx] = [] for property in properties: node_rosie_properties[idx].append(dict_row.get(property)) from_idx = dict_row.get("from_idx") if from_idx is None: continue edges.append((from_idx, idx)) forward_edges.setdefault(from_idx, []) forward_edges[from_idx].append(idx) back_edges.setdefault(idx, []) back_edges[idx].append(from_idx) if filter_id is None: # Plot all the edges we've found. for edge in sorted(edges): node0, node1 = edge add_node(graph, node0, node_rosie_properties.get(node0)) add_node(graph, node1, node_rosie_properties.get(node1)) graph.add_edge(edge[0], edge[1]) else: # Only plot the connections involving filter_id. nodes = [n for edge in edges for n in edge] node_stack = [] node_stack = [(filter_id, 0)] add_node(graph, filter_id, node_rosie_properties.get(filter_id), fillcolor="lightgrey", style="filled") ok_nodes = set([]) while node_stack: node, distance = node_stack.pop() if max_distance is not None and distance > max_distance: continue ok_nodes.add(node) for neighbour_node in forward_edges.get(node, []) + back_edges.get(node, []): if neighbour_node not in ok_nodes: node_stack.append((neighbour_node, distance + 1)) if len(ok_nodes) == 1: # There are no related suites. reporter = rose.reporter.Reporter() reporter(NoConnectionsEvent(filter_id)) for edge in sorted(edges): node0, node1 = edge if node0 in ok_nodes and node1 in ok_nodes: add_node(graph, node0, node_rosie_properties.get(node0)) add_node(graph, node1, node_rosie_properties.get(node1)) graph.add_edge(node0, node1)