Pyan3 - Offline call graph generator for Python 3

Overview

Pyan3

Offline call graph generator for Python 3

Build Status FOSSA Status Codacy Badge PyPI - Python Version

Pyan takes one or more Python source files, performs a (rather superficial) static analysis, and constructs a directed graph of the objects in the combined source, and how they define or use each other. The graph can be output for rendering by GraphViz or yEd.

This project has 2 official repositories:

The PyPI package pyan3 is built from development

About

Example output

Defines relations are drawn with dotted gray arrows.

Uses relations are drawn with black solid arrows. Recursion is indicated by an arrow from a node to itself. Mutual recursion between nodes X and Y is indicated by a pair of arrows, one pointing from X to Y, and the other from Y to X.

Nodes are always filled, and made translucent to clearly show any arrows passing underneath them. This is especially useful for large graphs with GraphViz's fdp filter. If colored output is not enabled, the fill is white.

In node coloring, the HSL color model is used. The hue is determined by the filename the node comes from. The lightness is determined by depth of namespace nesting, with darker meaning more deeply nested. Saturation is constant. The spacing between different hues depends on the number of files analyzed; better results are obtained for fewer files.

Groups are filled with translucent gray to avoid clashes with any node color.

The nodes can be annotated by filename and source line number information.

Note

The static analysis approach Pyan takes is different from running the code and seeing which functions are called and how often. There are various tools that will generate a call graph that way, usually using a debugger or profiling trace hooks, such as Python Call Graph.

In Pyan3, the analyzer was ported from compiler (good riddance) to a combination of ast and symtable, and slightly extended.

Install

pip install pyan3

Usage

See pyan3 --help.

Example:

pyan *.py --uses --no-defines --colored --grouped --annotated --dot >myuses.dot

Then render using your favorite GraphViz filter, mainly dot or fdp:

dot -Tsvg myuses.dot >myuses.svg

Or use directly

pyan *.py --uses --no-defines --colored --grouped --annotated --svg >myuses.svg

You can also export as an interactive HTML

pyan *.py --uses --no-defines --colored --grouped --annotated --html > myuses.html

Alternatively, you can call pyan from a script

import pyan
from IPython.display import HTML
HTML(pyan.create_callgraph(filenames="**/*.py", format="html"))

Sphinx integration

You can integrate callgraphs into Sphinx. Install graphviz (e.g. via sudo apt-get install graphviz) and modify source/conf.py so that

# modify extensions
extensions = [
  ...
  "sphinx.ext.graphviz"
  "pyan.sphinx",
]

# add graphviz options
graphviz_output_format = "svg"

Now, there is a callgraph directive which has all the options of the graphviz directive and in addition:

  • :no-groups: (boolean flag): do not group
  • :no-defines: (boolean flag): if to not draw edges that show which functions, methods and classes are defined by a class or module
  • :no-uses: (boolean flag): if to not draw edges that show how a function uses other functions
  • :no-colors: (boolean flag): if to not color in callgraph (default is coloring)
  • :nested-grops: (boolean flag): if to group by modules and submodules
  • :annotated: (boolean flag): annotate callgraph with file names
  • :direction: (string): "horizontal" or "vertical" callgraph
  • :toctree: (string): path to toctree (as used with autosummary) to link elements of callgraph to documentation (makes all nodes clickable)
  • :zoomable: (boolean flag): enables users to zoom and pan callgraph

Example to create a callgraph for the function pyan.create_callgraph that is zoomable, is defined from left to right and links each node to the API documentation that was created at the toctree path api.

.. callgraph:: pyan.create_callgraph
   :toctree: api
   :zoomable:
   :direction: horizontal

Troubleshooting

If GraphViz says trouble in init_rank, try adding -Gnewrank=true, as in:

dot -Gnewrank=true -Tsvg myuses.dot >myuses.svg

Usually either old or new rank (but often not both) works; this is a long-standing GraphViz issue with complex graphs.

Too much detail?

If the graph is visually unreadable due to too much detail, consider visualizing only a subset of the files in your project. Any references to files outside the analyzed set will be considered as undefined, and will not be drawn.

Currently Pyan always operates at the level of individual functions and methods; an option to visualize only relations between namespaces may (or may not) be added in a future version.

Features

Items tagged with ☆ are new in Pyan3.

Graph creation:

  • Nodes for functions and classes
  • Edges for defines
  • Edges for uses
    • This includes recursive calls ☆
  • Grouping to represent defines, with or without nesting
  • Coloring of nodes by filename
    • Unlimited number of hues ☆

Analysis:

  • Name lookup across the given set of files
  • Nested function definitions
  • Nested class definitions ☆
  • Nested attribute accesses like self.a.b
  • Inherited attributes ☆
    • Pyan3 looks up also in base classes when resolving attributes. In the old Pyan, calls to inherited methods used to be picked up by contract_nonexistents() followed by expand_unknowns(), but that often generated spurious uses edges (because the wildcard to *.name expands to X.name for all X that have an attribute called name.).
  • Resolution of super() based on the static type at the call site ☆
  • MRO is (statically) respected in looking up inherited attributes and super()
  • Assignment tracking with lexical scoping
    • E.g. if self.a = MyFancyClass(), the analyzer knows that any references to self.a point to MyFancyClass
    • All binding forms are supported (assign, augassign, for, comprehensions, generator expressions, with) ☆
      • Name clashes between for loop counter variables and functions or classes defined elsewhere no longer confuse Pyan.
  • self is defined by capturing the name of the first argument of a method definition, like Python does. ☆
  • Simple item-by-item tuple assignments like x,y,z = a,b,c
  • Chained assignments a = b = c
  • Local scope for lambda, listcomp, setcomp, dictcomp, genexpr ☆
    • Keep in mind that list comprehensions gained a local scope (being treated like a function) only in Python 3. Thus, Pyan3, when applied to legacy Python 2 code, will give subtly wrong results if the code uses list comprehensions.
  • Source filename and line number annotation ☆
    • The annotation is appended to the node label. If grouping is off, namespace is included in the annotation. If grouping is on, only source filename and line number information is included, because the group title already shows the namespace.

TODO

  • Determine confidence of detected edges (probability that the edge is correct). Start with a binary system, with only values 1.0 and 0.0.
    • A fully resolved reference to a name, based on lexical scoping, has confidence 1.0.
    • A reference to an unknown name has confidence 0.0.
    • Attributes:
      • A fully resolved reference to a known attribute of a known object has confidence 1.0.
      • A reference to an unknown attribute of a known object has confidence 1.0. These are mainly generated by imports, when the imported file is not in the analyzed set. (Does this need a third value, such as 0.5?)
      • A reference to an attribute of an unknown object has confidence 0.0.
    • A wildcard and its expansions have confidence 0.0.
    • Effects of binding analysis? The system should not claim full confidence in a bound value, unless it fully understands both the binding syntax and the value. (Note that this is very restrictive. A function call or a list in the expression for the value will currently spoil the full analysis.)
    • Confidence values may need updating in pass 2.
  • Make the analyzer understand del name (probably seen as isinstance(node.ctx, ast.Del) in visit_Name(), visit_Attribute())
  • Prefix methods by class name in the graph; create a legend for annotations. See the discussion here.
  • Improve the wildcard resolution mechanism, see discussion here.
    • Could record the namespace of the use site upon creating the wildcard, and check any possible resolutions against that (requiring that the resolved name is in scope at the use site)?
  • Add an option to visualize relations only between namespaces, useful for large projects.
    • Scan the nodes and edges, basically generate a new graph and visualize that.
  • Publish test cases.
  • Get rid of self.last_value?
    • Consider each specific kind of expression or statement being handled; get the relevant info directly (or by a more controlled kind of recursion) instead of self.visit().
    • At some point, may need a second visitor class that is just a catch-all that extracts names, which is then applied to only relevant branches of the AST.
    • On the other hand, maybe self.last_value is the simplest implementation that extracts a value from an expression, and it only needs to be used in a controlled manner (as analyze_binding() currently does); i.e. reset before visiting, and reset immediately when done.

The analyzer does not currently support:

  • Tuples/lists as first-class values (currently ignores any assignment of a tuple/list to a single name).
    • Support empty lists, too (for resolving method calls to .append() and similar).
  • Starred assignment a,*b,c = d,e,f,g,h
  • Slicing and indexing in assignment (ast.Subscript)
  • Additional unpacking generalizations (PEP 448, Python 3.5+).
    • Any uses on the RHS at the binding site in all of the above are already detected by the name and attribute analyzers, but the binding information from assignments of these forms will not be recorded (at least not correctly).
  • Enums; need to mark the use of any of their attributes as use of the Enum. Need to detect Enum in bases during analysis of ClassDef; then tag the class as an enum and handle differently.
  • Resolving results of function calls, except for a very limited special case for super().
    • Any binding of a name to a result of a function (or method) call - provided that the binding itself is understood by Pyan - will instead show in the output as binding the name to that function (or method). (This may generate some unintuitive uses edges in the graph.)
  • Distinguishing between different Lambdas in the same namespace (to report uses of a particular lambda that has been stored in self.something).
  • Type hints (PEP 484, Python 3.5+).
  • Type inference for function arguments
    • Either of these two could be used to bind function argument names to the appropriate object types, avoiding the need for wildcard references (especially for attribute accesses on objects passed in as function arguments).
    • Type inference could run as pass 3, using additional information from the state of the graph after pass 2 to connect call sites to function definitions. Alternatively, no additional pass; store the AST nodes in the earlier pass. Type inference would allow resolving some wildcards by finding the method of the actual object instance passed in.
    • Must understand, at the call site, whether the first positional argument in the function def is handled implicitly or not. This is found by looking at the flavor of the Node representing the call target.
  • Async definitions are detected, but passed through to the corresponding non-async analyzers; could be annotated.
  • Cython; could strip or comment out Cython-specific code as a preprocess step, then treat as Python (will need to be careful to get line numbers right).

How it works

From the viewpoint of graphing the defines and uses relations, the interesting parts of the AST are bindings (defining new names, or assigning new values to existing names), and any name that appears in an ast.Load context (i.e. a use). The latter includes function calls; the function's name then appears in a load context inside the ast.Call node that represents the call site.

Bindings are tracked, with lexical scoping, to determine which type of object, or which function, each name points to at any given point in the source code being analyzed. This allows tracking things like:

def some_func():
    pass

class MyClass:
    def __init__(self):
        self.f = some_func

    def dostuff(self)
        self.f()

By tracking the name self.f, the analyzer will see that MyClass.dostuff() uses some_func().

The analyzer also needs to keep track of what type of object self currently points to. In a method definition, the literal name representing self is captured from the argument list, as Python does; then in the lexical scope of that method, that name points to the current class (since Pyan cares only about object types, not instances).

Of course, this simple approach cannot correctly track cases where the current binding of self.f depends on the order in which the methods of the class are executed. To keep things simple, Pyan decides to ignore this complication, just reads through the code in a linear fashion (twice so that any forward-references are picked up), and uses the most recent binding that is currently in scope.

When a binding statement is encountered, the current namespace determines in which scope to store the new value for the name. Similarly, when encountering a use, the current namespace determines which object type or function to tag as the user.

Authors

See AUTHORS.md.

License

GPL v2, as per comments here.

Comments
  • pyan3 is crashing all the time

    pyan3 is crashing all the time

    Every time i try pyan3 on different projects it crash with the following results

    $ pyan3 sun.py
    Traceback (most recent call last):
      File "c:\users\anders\anaconda3\envs\py36\lib\runpy.py", line 193, in _run_module_as_main
        "__main__", mod_spec)
      File "c:\users\anders\anaconda3\envs\py36\lib\runpy.py", line 85, in _run_code
        exec(code, run_globals)
      File "C:\Users\anders\anaconda3\envs\py36\Scripts\pyan3.exe\__main__.py", line 7, in <module>
      File "c:\users\anders\anaconda3\envs\py36\lib\site-packages\pyan\main.py", line 206, in main
        v = CallGraphVisitor(filenames, logger, root=root)
    TypeError: __init__() got multiple values for argument 'root'
    
    

    Any ideas how to fix this?

    I tried it on both Python 3.6 and 3.8 with the same results.

    bug 
    opened by simbalsyd 12
  • Resolve `from` imports

    Resolve `from` imports

    This PR addresses import such as from mod_x import func_y as func_z and from mod_x import mod_y. Relative imports such as from ..mod_x import mod_y are not supported. However, relative imports are considered bad style and discouraged. It's probably not too much work to add this functionality.

    As the package structure has to be known to resolve imports, this is done as a post-processing step relinking the modules.

    opened by jdb78 9
  • RuntimeError: dictionary changed size during iteration

    RuntimeError: dictionary changed size during iteration

    Getting this on a specific directory (not seeing it elsewhere) What do you need to dig into this?

    Traceback (most recent call last): File "/Users/nevep/.pyenv/bin/versions/3.7.4/envs/egs-api/bin/pyan3", line 7, in exec(compile(f.read(), file, 'exec')) File "/Users/nevep/bepress/pyan/pyan3", line 11, in sys.exit(main()) File "/Users/nevep/bepress/pyan/pyan/main.py", line 109, in main v = CallGraphVisitor(filenames, logger) File "/Users/nevep/bepress/pyan/pyan/analyzer.py", line 77, in init self.process() File "/Users/nevep/bepress/pyan/pyan/analyzer.py", line 87, in process self.postprocess() File "/Users/nevep/bepress/pyan/pyan/analyzer.py", line 154, in postprocess self.collapse_inner() File "/Users/nevep/bepress/pyan/pyan/analyzer.py", line 1562, in collapse_inner for name in self.nodes: RuntimeError: dictionary changed size during iteration

    bug 
    opened by pmneve 8
  • Installing pyan3

    Installing pyan3

    Hello, and sorry if my errors are obvious, I'm relativly new. So after installing pyan3 using pip install pyan3 I don't find a way to put it into the PATH of windows 10 so I can use the projet with powershell like in the guidelines pyan *.py --uses --no-defines --colored --grouped --annotated --dot >myuses.dot I tried to put the directory into the PATH "C:\ProgramData\Anaconda3\Lib\site-packages\pyan" or "C:\ProgramData\Anaconda3\Lib\site-packages" and it didn't work

    Thanks in advance for anyone who will read and put they minds into it, and sorry if it's a stupid error and my part, anyway, have a good day

    question 
    opened by Djaningo 7
  • Requirements on python files? -- failing to graph

    Requirements on python files? -- failing to graph

    Hello, I'm having issues with pyan. Specifically, when I try to graph my python files, I get blank graph. I tested pyan with a simple test.py file and it works fine, but my large program shows nothing. Is there specific programming style it expects? I'm not sure if this is a style issue, or an issue with I have an associated library it calls ? or something else. The only thing I can think of is I have a weird mix of global variables and calls to classes in my library file.

    When I put both the library and my main file on the command line calling pyan , it graphs only the library file. Does that seem right?

    I can't post the code it is private.

    I have python 3.8 on windows 64 bit.

    question 
    opened by sk3499 6
  • IndexError in visit_AnnAssign

    IndexError in visit_AnnAssign

    Hi.

    trying to run pyan against my code, it crashes with this error:

    pyan3 *.py --uses --no-defines --colored --grouped --annotated --svg >myuses.svg
    Traceback (most recent call last):
      File "/home/<user>/.local/bin/pyan3", line 11, in <module>
        sys.exit(main())
      File "/home/<user>/.local/lib/python3.6/site-packages/pyan/main.py", line 235, in main
        v = CallGraphVisitor(filenames, logger)
      File "/home/<user>/.local/lib/python3.6/site-packages/pyan/analyzer.py", line 75, in __init__
        self.process()
      File "/home/<user>/.local/lib/python3.6/site-packages/pyan/analyzer.py", line 82, in process
        self.process_one(filename)
      File "/home/<user>/.local/lib/python3.6/site-packages/pyan/analyzer.py", line 96, in process_one
        self.visit(ast.parse(content, filename))
      File "/usr/lib64/python3.6/ast.py", line 253, in visit
        return visitor(node)
      File "/home/<user>/.local/lib/python3.6/site-packages/pyan/analyzer.py", line 340, in visit_Module
        self.generic_visit(node)  # visit the **children** of node
      File "/usr/lib64/python3.6/ast.py", line 261, in generic_visit
        self.visit(item)
      File "/usr/lib64/python3.6/ast.py", line 253, in visit
        return visitor(node)
      File "/home/<user>/.local/lib/python3.6/site-packages/pyan/analyzer.py", line 386, in visit_ClassDef
        self.visit(stmt)
      File "/usr/lib64/python3.6/ast.py", line 253, in visit
        return visitor(node)
      File "/home/<user>/.local/lib/python3.6/site-packages/pyan/analyzer.py", line 463, in visit_AsyncFunctionDef
        self.visit_FunctionDef(node)  # TODO: alias for now; tag async functions in output in a future version?
      File "/home/<user>/.local/lib/python3.6/site-packages/pyan/analyzer.py", line 454, in visit_FunctionDef
        self.visit(stmt)
      File "/usr/lib64/python3.6/ast.py", line 253, in visit
        return visitor(node)
      File "/home/<user>/.local/lib/python3.6/site-packages/pyan/analyzer.py", line 752, in visit_AnnAssign
        get_ast_node_name(value[0]),
    IndexError: list index out of range
    
    

    Cannot share my code, but if I could do something else to help you in debugging, just let me know

    bug 
    opened by njordr 5
  • Syntax error give by pyan

    Syntax error give by pyan

    @Technologicat hi thanks for working on pyan , currently i face issues for higher version of python3.6 which has different syntax as shown below

    print(f"Kitti info train file is saved to {filename}") SyntaxError: invalid syntax

    How to solve this ??

    question 
    opened by abhigoku10 5
  • Relative imports crash pyan

    Relative imports crash pyan

    Pyan does not currently support from . import foo, and crashes when it sees one.

    For relative imports, the module attribute of the ImportFrom node is None.

    We need to detect this case, and then also handle the level attribute, and actually figure out the correct absolute module path (at least as far as Pyan can reasonably detect) based on the relative one.

    See GTS on imports.

    bug 
    opened by Technologicat 5
  • __init__() got multiple values for argument 'root'

    __init__() got multiple values for argument 'root'

    Issue Calling pyan3 from command line exits with a TypeError

    Traceback (most recent call last):
      File "/usr/lib/python3.7/runpy.py", line 193, in _run_module_as_main
        "__main__", mod_spec)
      File "/usr/lib/python3.7/runpy.py", line 85, in _run_code
        exec(code, run_globals)
      File "/usr/local/lib/python3.7/dist-packages/pyan/main.py", line 244, in <module>
        main()
      File "/usr/local/lib/python3.7/dist-packages/pyan/main.py", line 206, in main
        v = CallGraphVisitor(filenames, logger, root=root)
    TypeError: __init__() got multiple values for argument 'root'
    

    To reproduce Install using pip and git master: pip3 install git+https://github.com/Technologicat/pyan.git Run pyan3 with parameters: pyan3 application.py --dot > test.dot

    Environment Python 3.7.10 VIrtualEnv on Ubuntu 21.04

    opened by ALeyshon 4
  • Asserts can be removed during bytecode optimization

    Asserts can be removed during bytecode optimization

    From Codacy issues

    assert is removed with compiling to optimised byte code (python -o producing *.pyo files). This caused various protections to be removed. The use of assert is also considered as general bad practice in OpenStack codebases.

    Link to list all occurrences: https://app.codacy.com/manual/edumco/pyan/issues/index?bid=15369107

    opened by edumco 4
  • pip install from pypi is broken for venvs

    pip install from pypi is broken for venvs

    Here is what I got when installed in fresh temporary python venv:

    ➜  ~ mktmpenv --python=/usr/bin/python3
    Already using interpreter /usr/bin/python3
    Using base prefix '/usr'
    New python executable in /home/ttylec/.virtualenvs/tmp-195183325368ab1e/bin/python3
    Also creating executable in /home/ttylec/.virtualenvs/tmp-195183325368ab1e/bin/python
    Installing setuptools, pkg_resources, pip, wheel...done.
    This is a temporary environment. It will be deleted when you run 'deactivate'.
    (tmp-195183325368ab1e) ➜  tmp-195183325368ab1e python --version
    Python 3.6.8
    (tmp-195183325368ab1e) ➜  tmp-195183325368ab1e pip install pyan3
    Collecting pyan3
      Using cached https://files.pythonhosted.org/packages/1a/82/d1b47fbcde2472d5954b4ed70cc3acf67d27bb0e83cf9b5cd5785684c629/pyan3-1.0.4-py3-none-any.whl
    Installing collected packages: pyan3
    Successfully installed pyan3-1.0.4
    (tmp-195183325368ab1e) ➜  tmp-195183325368ab1e pyan3
    Traceback (most recent call last):
      File "/home/ttylec/.virtualenvs/tmp-195183325368ab1e/bin/pyan3", line 7, in <module>
        from pyan import main
    ModuleNotFoundError: No module named 'pyan'
    

    Installing from within cloned repo works.

    bug 
    opened by ttylec 4
  • What is

    What is "dot"?

    New to Python and Graphviz, sorry!

    I stumbled on the answer by typing

    dot --help
    

    The docs should mention the prerequisite:

    sudo apt install graphviz
    
    opened by martinhbramwell 0
  • Would like to generate call graph for a very basic file

    Would like to generate call graph for a very basic file

    I'd like to generate a call graph for the following minimum working example:

    def g(x):
        return x+2
    
    def h(x):
        return x*7
    
    def f(x):
        r = g(x)
        s = h(r)
        return s
    
    if __name__=="__main__":
        print(f(3))
    

    I tried the following command:

    pyan3 test.py --dot

    But I got an error:

    TypeError: init() got multiple values for argument 'root'

    What am I doing wrong here?

    opened by amine-aboufirass 1
  • Is the project still maintained?

    Is the project still maintained?

    Thanks @Technologicat for this project, it's so useful and lightweight ! The latest commit happened a while ago, and 3 PRs have been waiting for a while. Is it still maintained? Or are you looking for a new maintainer?

    discussion 
    opened by aurelg 4
  • FileNotFoundError: [Errno 2] No such file or directory: ''

    FileNotFoundError: [Errno 2] No such file or directory: ''

    Hi,

    Recently I installed pyan and try to use it to generate a graph of my python script. Unfortunately I encountered an error. Here is my installation command and my python is 3.8.0:

    pip install git+https://github.com/Technologicat/pyan.git
    

    While I run the command for my own script:

    pyan3 tre_graph.py --uses --no-defines --colored --grouped --annotated --dot > tre.dot
    

    It didn't work as expected but give an error as below:

    Traceback (most recent call last):
      File "/home/wangjie/miniconda3/envs/straglr/bin/pyan3", line 8, in <module>
        sys.exit(main())
      File "/home/wangjie/miniconda3/envs/straglr/lib/python3.8/site-packages/pyan/main.py", line 208, in main
        v = CallGraphVisitor(filenames, logger=logger, root=root)
      File "/home/wangjie/miniconda3/envs/straglr/lib/python3.8/site-packages/pyan/analyzer.py", line 60, in __init__
        mod_name = get_module_name(filename)
      File "/home/wangjie/miniconda3/envs/straglr/lib/python3.8/site-packages/pyan/anutils.py", line 41, in get_module_name
        print(os.listdir(potential_root))
    FileNotFoundError: [Errno 2] No such file or directory: ''
    

    After some simple inspections of these codes that raising errors, I guess it is the problem of --root parameter. But it is inferred by default so I don't know how to fix it. Could you give some suggestions?

    Thanks!

    JieWang

    opened by Jesson-mark 2
  • Fixed anutils.get_module_name

    Fixed anutils.get_module_name

    Before this commit, I would get the following error:

    Traceback (most recent call last):
      File "/home/sam/.local/share/virtualenvs/.repos-OcsR-W1w/bin/pyan3", line 33, in <module>
        sys.exit(load_entry_point('pyan3', 'console_scripts', 'pyan3')())
      File "/home/sam/box/charmonium.cache/benchmark/.repos/pyan/pyan/main.py", line 206, in main
        v = CallGraphVisitor(filenames, logger=logger, root=root)
      File "/home/sam/box/charmonium.cache/benchmark/.repos/pyan/pyan/analyzer.py", line 60, in __init__
        mod_name = get_module_name(filename)
      File "/home/sam/box/charmonium.cache/benchmark/.repos/pyan/pyan/anutils.py", line 43, in get_module_name
        is_root = any([f == "__init__.py" for f in os.listdir(potential_root)])
    FileNotFoundError: [Errno 2] No such file or directory: ''
    

    because directories[0][0] was:

    ./pudl/src/pudl/cli.py None
    ./pudl/src/pudl
    ./pudl/src
    ./pudl
    .
    

    After this commit, the code works as expected, because the loop stops when it finds the root.

    opened by charmoniumQ 0
Releases(v1.2.0)
  • v1.2.0(Feb 11, 2021)

    Starting with this release, Pyan is now jointly maintained by @Technologicat, @jdb78, and @johnyf.

    New:

    • Sphinx extension.

    Changed:

    • Improve package root resolution.

    Fixed:

    • #62: visit_AnnAssign crash on an empty list.
    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Dec 10, 2020)

    This version adds HTML and SVG export by @jdb78, several small fixes by @johnyf, some individual fixes by other community members, and most importantly, brings the long-outdated PyPI package back into sync with this development repo.

    Thanks to everyone who contributed to this release!

    Source code(tar.gz)
    Source code(zip)
  • v1.0.4(Jun 25, 2019)

  • v1.0.3(Jun 25, 2019)

  • v1.0.2(Jan 3, 2018)

    Bugfix:

    • fix regression: keep wildcard if the 'resolved' target is actually an unresolved function argument

    Enhancements:

    • add --grouped-alt (-G) to make invisible defines edges to suggest grouping for GraphViz, without actually placing the nodes into GraphViz clusters. Overrides --no-defines. Overridden by --defines.
    • analyze str() and repr() if the argument is a Name or Attribute mapping to a known Node.
    • add uses edge to result from a resolved call to built-ins, important for str() and repr()
    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Nov 21, 2017)

    Bugfixes:

    • crash in analyzer when resolving super() call with no known bases
    • crash in collapse_inner() during postprocessing
    • use /usr/bin/env python3 instead of hard-coded /usr/bin/python3 in hashbang in pyan.py to support virtualenvs correctly

    Enhancements:

    • analyze the with statement: add uses edges from the node containing the with block to __enter__ and __exit__ methods of the with'd object; also track binding from with ... as foo (single target only for now, and __enter__ is assumed to return self)
    • analyze instantiation: add a uses edge to MyClass.__init__ for a call to MyClass()
    • node flavoring both in analysis and in output (class, function, method, staticmethod, classmethod)
    • figure out which names correspond to arguments in FunctionDef; prevent leakage of matching names from the enclosing scope. This fixes some spurious edges.
    • avoid adding a uses wildcard when resolving super() fails. This fixes spurious, possibly seemingly recursive, uses edges in the case that part of the class hierarchy is not available for analysis. (The most common reasons for super() resolution to fail are that either the analyzer is still running pass 1 [MRO is computed between passes], or some relevant source file is not in the analyzed set.)

    Technical improvements:

    • refactor analyzer: split into the main class and anutils
    • reorder methods in the analyzer main class to make the source code more logical to read for humans
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Nov 21, 2017)

    Python 3 compatibility.

    Changes w.r.t. the long-standing version of Pyan for Python 2, https://github.com/davidfraser/pyan/commit/26faced4edcd2bbe3f0672d6b96d7fbb2099624e :

    • rewrite analyzer in Python 3, using ast and symtable
    • unlimited number of hues for output graph nodes
    • graph node hue is now based on filename, not top-level namespace
    • detailed (debug) logging with --very-verbose, can be abbreviated to -V
    • treat __init__ like any method (now shows up in the output graph)
    • add uses edges for recursive calls
    • analyze nested class definitions
    • define "self" by capturing the name of the first argument of methods and class methods, like Python does
    • analyze nested attribute accesses (e.g. self.a.b)
    • look up inherited attributes (using MRO with C3 linearization, based on static type at use site)
    • analyze super() calls
    • recognize for as a binding form to avoid name clashes between loop counters and functions defined elsewhere (however, can fail if the expression to be assigned is complex enough)
    • analyze simple item-by-item tuple assignments x,y,z = a,b,c and pythonic swap a,b = b,a
    • analyze chained assignments a = b = c
    • in analysis, use local scope for lambda, listcomp, setcomp, dictcomp, genexpr to follow Python 3 scoping rules correctly; for visualization, contract these into the parent node in postprocessing
    • yEd GraphML output support, framework for easily adding new output formats (merge PR #1 from davidfraser/pyan)
    • bugfix for unsafe graph node identifiers, fix inspired by https://github.com/davidfraser/pyan/commit/ddb62d2eef872329c5efe9ed780120eb11e11419
    • refactor code into modules for easier maintenance
    Source code(tar.gz)
    Source code(zip)
Owner
Juha Jeronen
Computational scientist with an interest in open-source development, Python, Lisp and metaprogramming.
Juha Jeronen
This project is created to visualize the system statistics such as memory usage, CPU usage, memory accessible by process and much more using Kibana Dashboard with Elasticsearch.

System Stats Visualizer This project is created to visualize the system statistics such as memory usage, CPU usage, memory accessible by process and m

Vishal Teotia 5 Feb 06, 2022
Learn Data Science with focus on adding value with the most efficient tech stack.

DataScienceWithPython Get started with Data Science with Python An engaging journey to become a Data Scientist with Python TL;DR Download all Jupyter

Learn Python with Rune 110 Dec 22, 2022
nptsne is a numpy compatible python binary package that offers a number of APIs for fast tSNE calculation.

nptsne nptsne is a numpy compatible python binary package that offers a number of APIs for fast tSNE calculation and HSNE modelling. For more detail s

Biomedical Visual Analytics Unit LUMC - TU Delft 29 Jul 05, 2022
Moscow DEG 2021 elections plots

Построение графиков на основе публичных данных о ДЭГ в Москве в 2021г. Описание Скрипты в данном репозитории позволяют собственноручно построить графи

9 Jul 15, 2022
The official colors of the FAU as matplotlib/seaborn colormaps

FAU - Colors The official colors of Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU) as matplotlib / seaborn colormaps. We support the old colo

Machine Learning and Data Analytics Lab FAU 9 Sep 05, 2022
Dipto Chakrabarty 7 Sep 06, 2022
Some method of processing point cloud

Point-Cloud Some method of processing point cloud inversion the completion pointcloud to incomplete point cloud Some model of encoding point cloud to

Tan 1 Nov 19, 2021
Lime: Explaining the predictions of any machine learning classifier

lime This project is about explaining what machine learning classifiers (or models) are doing. At the moment, we support explaining individual predict

Marco Tulio Correia Ribeiro 10.3k Dec 29, 2022
Collection of scripts for making high quality beautiful math-related posters.

Poster Collection of scripts for making high quality beautiful math-related posters. The poster can have as large printing size as 3x2 square feet wit

Nattawut Phetmak 3 Jun 09, 2022
Data-FX is an addon for Blender (2.9) that allows for the visualization of data with different charts

Data-FX Data-FX is an addon for Blender (2.9) that allows for the visualization of data with different charts Currently, there are only 2 chart option

Landon Ferguson 20 Nov 21, 2022
A tool for creating Toontown-style nametags in Panda3D

Toontown-Nametag Toontown-Nametag is a tool for creating Toontown Online/Toontown Rewritten-style nametags in Panda3D. It contains a function, createN

BoggoTV 2 Dec 23, 2021
Sprint planner considering JIRA issues and google calendar meetings schedule.

Sprint planner Sprint planner is a Python script for planning your Jira tasks based on your calendar availability. Installation Use the package manage

Apptension 2 Dec 05, 2021
Application for viewing pokemon regional variants.

Pokemon Regional Variants Application Application for viewing pokemon regional variants. Run The Source Code Download Python https://www.python.org/do

Michael J Bailey 4 Oct 08, 2021
Draw interactive NetworkX graphs with Altair

nx_altair Draw NetworkX graphs with Altair nx_altair offers a similar draw API to NetworkX but returns Altair Charts instead. If you'd like to contrib

Zachary Sailer 206 Dec 12, 2022
A D3.js plugin that produces flame graphs from hierarchical data.

d3-flame-graph A D3.js plugin that produces flame graphs from hierarchical data. If you don't know what flame graphs are, check Brendan Gregg's post.

Martin Spier 740 Dec 29, 2022
Sci palettes for matplotlib/seaborn

sci palettes for matplotlib/seaborn Installation python3 -m pip install sci-palettes Usage import seaborn as sns import matplotlib.pyplot as plt impor

Qingdong Su 2 Jun 07, 2022
A Python wrapper of Neighbor Retrieval Visualizer (NeRV)

PyNeRV A Python wrapper of the dimensionality reduction algorithm Neighbor Retrieval Visualizer (NeRV) Compile Set up the paths in Makefile then make.

2 Aug 29, 2021
Python toolkit for defining+simulating+visualizing+analyzing attractors, dynamical systems, iterated function systems, roulette curves, and more

Attractors A small module that provides functions and classes for very efficient simulation and rendering of iterated function systems; dynamical syst

1 Aug 04, 2021
HW_02 Data visualisation task

HW_02 Data visualisation and Matplotlib practice Instructions for HW_02 Idea for data analysis As I was brainstorming ideas and running through databa

9 Dec 13, 2022