Exemple #1
0
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)
Exemple #2
0
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
Exemple #3
0
 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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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)
Exemple #9
0
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)
Exemple #10
0
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)
Exemple #11
0
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)
Exemple #12
0
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)
Exemple #13
0
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)
Exemple #14
0
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)