Пример #1
0
def create_pyan_graph(path, keep_undefined=False, content="default"):
    converter = _converter(content)

    from pyan.analyzer import CallGraphVisitor
    from pyan.analyzer import Flavor
    visitor = CallGraphVisitor(_path2files(path))
    visited_nodes = [
        node for name in visitor.nodes for node in visitor.nodes[name]
        if node.defined or keep_undefined
    ]
    #visited_nodes.sort(key=lambda x: (x.namespace, x.name))
    logger.log("Found", len(visited_nodes), "entities")
    G = nx.DiGraph()
    modules = {}
    for node in visited_nodes:
        if (node.flavor == Flavor.MODULE or node.flavor
                == Flavor.CLASS) and node in visitor.defines_edges:
            modules[node] = [
                cdefined for defined in visitor.defines_edges[node]
                if defined.defined or keep_undefined
                for cdefined in converter(defined)
            ] + [cnode for cnode in converter(node)]
        if node in visitor.uses_edges:
            for cnode in converter(node):
                G.add_node(cnode)
            for called in visitor.uses_edges[node]:
                if (called.defined or keep_undefined) and (
                        called.flavor == Flavor.FUNCTION
                        or called.flavor == Flavor.CLASSMETHOD
                        or called.flavor == Flavor.METHOD):
                    for cnode in converter(node):
                        for ccalled in converter(called):
                            G.add_edge(cnode, ccalled)
                            G.add_edge(ccalled, cnode)
    return G, modules
Пример #2
0
def test_resolve_package_with_known_root():
    dirname = os.path.dirname(__file__)
    filenames = glob(os.path.join(dirname, "test_code/**/*.py"), recursive=True)
    callgraph = CallGraphVisitor(filenames, logger=logging.getLogger(), root=dirname)
    dirname_base = os.path.basename(dirname)
    defines = get_in_dict(callgraph.defines_edges, f"{dirname_base}.test_code.subpackage2.submodule_hidden1")
    get_node(defines, f"{dirname_base}.test_code.subpackage2.submodule_hidden1.test_func1")
Пример #3
0
def main():
    repo_paths = ['ecosystem\\**\\*.py']
    filenames = [
        fn for repo_path in repo_paths
        for fn in glob(repo_path, recursive=True)
    ]
    filenames = list(
        filter(
            lambda filename:
            (os.path.sep + 'tests' + os.path.sep) not in filename and
            (os.path.sep + 'testing' + os.path.sep) not in filename,
            filenames))
    v = CallGraphVisitor(filenames)
    graph = VisualGraph.dump_callgraph(v)
Пример #4
0
def main():

    start = time.clock()
    repo_paths = [
        'C:\\Users\\njdx\\Desktop\\CG_Python\\pro\\matplotlib\\**\\*.py'
    ]
    filenames = [
        fn for repo_path in repo_paths
        for fn in glob(repo_path, recursive=True)
    ]
    all_graph = defaultdict(list)

    v = CallGraphVisitor(filenames, logger=[])
    all_graph = VisualGraph.dump_callgraph(v)

    json_str = json.dumps(all_graph, indent=4)
    end = time.clock()
Пример #5
0
def main():
    usage = """usage: %prog FILENAME... [--dot|--tgf|--yed]"""
    desc = ('Analyse one or more Python source files and generate an'
            'approximate call graph of the modules, classes and functions'
            ' within them.')
    parser = OptionParser(usage=usage, description=desc)
    parser.add_option("--dot",
                      action="store_true",
                      default=False,
                      help="output in GraphViz dot format")
    parser.add_option("--tgf",
                      action="store_true",
                      default=False,
                      help="output in Trivial Graph Format")
    parser.add_option("--yed",
                      action="store_true",
                      default=False,
                      help="output in yEd GraphML Format")
    parser.add_option("-f",
                      "--file",
                      dest="filename",
                      help="write graph to FILE",
                      metavar="FILE",
                      default=None)
    parser.add_option("-l",
                      "--log",
                      dest="logname",
                      help="write log to LOG",
                      metavar="LOG")
    parser.add_option("-v",
                      "--verbose",
                      action="store_true",
                      default=False,
                      dest="verbose",
                      help="verbose output")
    parser.add_option("-V",
                      "--very-verbose",
                      action="store_true",
                      default=False,
                      dest="very_verbose",
                      help="even more verbose output (mainly for debug)")
    parser.add_option("-d",
                      "--defines",
                      action="store_true",
                      default=True,
                      dest="draw_defines",
                      help="add edges for 'defines' relationships [default]")
    parser.add_option("-n",
                      "--no-defines",
                      action="store_false",
                      default=True,
                      dest="draw_defines",
                      help="do not add edges for 'defines' relationships")
    parser.add_option("-u",
                      "--uses",
                      action="store_true",
                      default=True,
                      dest="draw_uses",
                      help="add edges for 'uses' relationships [default]")
    parser.add_option("-N",
                      "--no-uses",
                      action="store_false",
                      default=True,
                      dest="draw_uses",
                      help="do not add edges for 'uses' relationships")
    parser.add_option("-c",
                      "--colored",
                      action="store_true",
                      default=False,
                      dest="colored",
                      help="color nodes according to namespace [dot only]")
    parser.add_option(
        "-G",
        "--grouped-alt",
        action="store_true",
        default=False,
        dest="grouped_alt",
        help=
        "suggest grouping by adding invisible defines edges [only useful with --no-defines]"
    )
    parser.add_option(
        "-g",
        "--grouped",
        action="store_true",
        default=False,
        dest="grouped",
        help="group nodes (create subgraphs) according to namespace [dot only]"
    )
    parser.add_option(
        "-e",
        "--nested-groups",
        action="store_true",
        default=False,
        dest="nested_groups",
        help=
        "create nested groups (subgraphs) for nested namespaces (implies -g) [dot only]"
    )
    parser.add_option("--dot-rankdir",
                      default="TB",
                      dest="rankdir",
                      help=("specifies the dot graph 'rankdir' property for "
                            "controlling the direction of the graph. "
                            "Allowed values: ['TB', 'LR', 'BT', 'RL']. "
                            "[dot only]"))
    parser.add_option("-a",
                      "--annotated",
                      action="store_true",
                      default=False,
                      dest="annotated",
                      help="annotate with module and source line number")
    parser.add_option("--make-svg",
                      action="store_true",
                      default=False,
                      dest="make_svg",
                      help="try to run dot to make svg automatically")

    options, args = parser.parse_args()
    filenames = [fn2 for fn in args for fn2 in glob(fn)]
    if len(args) == 0:
        parser.error('Need one or more filenames to process')

    if options.nested_groups:
        options.grouped = True

    graph_options = {
        'draw_defines': options.draw_defines,
        'draw_uses': options.draw_uses,
        'colored': options.colored,
        'grouped_alt': options.grouped_alt,
        'grouped': options.grouped,
        'nested_groups': options.nested_groups,
        'annotated': options.annotated
    }

    # TODO: use an int argument for verbosity
    logger = logging.getLogger(__name__)
    if options.very_verbose:
        logger.setLevel(logging.DEBUG)
    elif options.verbose:
        logger.setLevel(logging.INFO)
    else:
        logger.setLevel(logging.WARN)
    logger.addHandler(logging.StreamHandler())
    if options.logname:
        handler = logging.FileHandler(options.logname)
        logger.addHandler(handler)

    v = CallGraphVisitor(filenames, logger)
    graph = VisualGraph.from_visitor(v, options=graph_options, logger=logger)

    if options.dot:
        writer = DotWriter(graph,
                           options=['rankdir=' + options.rankdir],
                           output=options.filename,
                           logger=logger)
        writer.run()
        if options.make_svg:
            base, _ = os.path.splitext(options.filename)
            svg = base + ".svg"
            subprocess.run("dot -Tsvg {dot} > {svg}".format(
                dot=options.filename, svg=svg),
                           shell=True)

    if options.tgf:
        writer = TgfWriter(graph, output=options.filename, logger=logger)
        writer.run()

    if options.yed:
        writer = YedWriter(graph, output=options.filename, logger=logger)
        writer.run()
Пример #6
0
def callgraph():
    filenames = glob(os.path.join(os.path.dirname(__file__),
                                  "test_code/**/*.py"),
                     recursive=True)
    v = CallGraphVisitor(filenames, logger=logging.getLogger())
    return v
Пример #7
0
def main():
    args = process_command_line(sys.argv)

    filenames = [y for x in args.filename for y in glob(x)]

    if args.nested_groups:
        args.grouped = True

    graph_options = {
        "draw_defines": args.draw_defines,
        "draw_uses": args.draw_uses,
        "colored": args.colored,
        "grouped_alt": args.grouped_alt,
        "grouped": args.grouped,
        "nested_groups": args.nested_groups,
        "annotated": args.annotated,
    }

    out_format = args.format
    if args.outfilename and not args.format:
        out_format = os.path.splitext(args.outfilename)[1][1:]
    if not out_format:
        out_format = "dot"

    logger = logging.getLogger(__name__)
    if args.verbose >= 2:
        logger.setLevel(logging.DEBUG)
    elif args.verbose == 1:
        logger.setLevel(logging.INFO)
    else:
        logger.setLevel(logging.WARN)
    logger.addHandler(logging.StreamHandler())
    if args.logname:
        handler = logging.FileHandler(args.logname)
        logger.addHandler(handler)

    v = CallGraphVisitor(filenames, logger)
    graph = VisualGraph.from_visitor(v, options=graph_options, logger=logger)

    if out_format == "dot":
        writer = DotWriter(
            graph,
            options=["rankdir=" + args.rankdir],
            output=args.outfilename,
            logger=logger,
        )
    elif out_format == "tgf":
        writer = TgfWriter(graph, output=args.outfilename, logger=logger)
    elif out_format == "yed":
        writer = YedWriter(graph, output=args.outfilename, logger=logger)
    elif out_format in ["svg", "png", "eps", "pdf", "ps", "webp"]:
        try:
            writer = DotRenderer(
                graph,
                options=["rankdir=" + args.rankdir],
                output=args.outfilename,
                output_format=out_format,
                logger=logger,
            )
        except NoDotError:
            print(
                "No executable 'dot' found in PATH.  Stopping without creating"
                " any output."
            )
            print(
                "To enable this functionality, install Graphviz's dot utility"
                " to your path."
            )
            return
    else:
        print("Cannot determine output format.  Stopping without creating any output.")
        return
    # actually write file output
    writer.run()