Tool for pinpointing circular imports in Python. Find cyclic imports in any project

Overview

Pycycle: Find and fix circular imports in python projects

https://api.travis-ci.org/bndr/pycycle.svg?branch=master

Pycycle is an experimental project that aims to help python developers fix their circular dependencies problems.

ImportError: Cannot import name X is a python exception that is related to the circular imports, but the exception tells nothing about where or what.

This tool automatically analyzes the imports of your projects, and looks for imports that may cause a circular dependency problem.

https://i.imgur.com/8JeLQxu.gif

Features

  • Shows you the whole chain of the circular imports.
  • Gives you lines of code where each import is, for you to easily find and fix the problem.
  • Visualizes your imports in a graph (Not Yet Implemented)

Usage

$ pycycle
Usage: pycycle [OPTIONS] COMMAND [ARGS]...


Examples:
    Get the circular imports in current project:
    $ pycycle --here
    Look for circular imports in another project
    $ pycycle --source /home/user/workspace/awesome_project
    Ignore specific directories when looking for circular import
    $ pycycle --source /home/user/workspace/awesome_project --ignore some_dir,some_dir2
    Get verbose output
    $ pycycle --source /home/user/workspace/awesome_project --verbose

Options:
  --verbose        Verbose output.
  --here           Try to find cycles in the current project.
  --source TEXT    Try to find cycles in the path provided.
  --ignore TEXT    Comma separated directories that will be ignored during
                   analysis.
  --encoding TEXT  Change enconding with which the project is read.
  --help           Show this message then exit.
  --version        Show the version and exit.
$ pycycle --here
Project successfully transformed to AST, checking imports for cycles..
Cycle Found :(
a_module.a_file: Line 1 -> a_module.b_module.b_file: Line 1 -> c_module.c_file: Line 1 -> d_module.d_file: Line 1 =>> a_module.a_file
Finished.
$ pycycle --source /Users/vkravcenko/workspace/awesome_project
Target source provided:/Users/vkravcenko/workspace/awesome_project
Project successfully transformed to AST, checking imports for cycles..
No worries, no cycles here!
If you think some cycle was missed, please open an Issue on Github.
Finished.

Installation

$ pip install pycycle
Comments
  • Weird false positive

    Weird false positive

    Hello, here is a very weird false positive I found.

    Minimal reproductible code: https://gist.github.com/bfontaine/551dc93cae6c70df649db43aa859dd4a

    Reproduce it:

    git clone https://gist.github.com/bfontaine/551dc93cae6c70df649db43aa859dd4a.git
    cd 551dc93cae6c70df649db43aa859dd4a
    pycycle --here --verbose
    

    Output:

    Trying to parse file: /tmp/551dc93cae6c70df649db43aa859dd4a/toto_tutu.py
    Trying to parse file: /tmp/551dc93cae6c70df649db43aa859dd4a/tutu.py
    Trying to parse file: /tmp/551dc93cae6c70df649db43aa859dd4a/lala.py
    Project successfully transformed to AST, checking imports for cycles..
    Cycle Found :(
    tutu -> lala: Line 2 =>> tutu
    Finished.
    

    My environment:

    $ pycycle --version
    pycycle, version 0.0.8
    $ python --version
    Python 3.9.6
    

    The first weird thing is that it finds a circular import tutu -> lala -> tutu but lala doesn’t import tutu.

    There are other unrelated imports in these files, but if I change or remove a single one of them, the output changes. For example, if I remove import argparse from lala.py, the cycle disappears. If instead I remove import typing from that same file, there’s style a "Cycle Found" but it’s not printed.

    opened by bfontaine 1
  • apply python module import logic

    apply python module import logic

    It seems that in this moment, the program only takes into account the importation statement in each file, not integrated the python modules loading logic with context, for example, for the tests/_projects/large_circle case, if I change the tests/_projects/large_circle/a_module/a_file.py just by moving the function before import statement like this:

    def a_func():
        return "a func"
    
    from a_module.b_module.b_file import b_func
    

    Then this test case should be fine and we can run it successfully, but the program still give us circular import error.

    bug 
    opened by PnPie 1
  • Update cli.py

    Update cli.py

    Set default to a string, instead of "False", which causes the type to be "BOOLEAN".

    #21

    Error: Invalid value for '--source': 'path_to_project/' is not a valid boolean.
    
    Options:
      --source BOOLEAN  Try to find cycles in the path provided.
      --ignore TEXT     Comma separated directories that will be ignored during
                        analysis.
    
    opened by MichaelQuaMan 0
  • cycle not detected

    cycle not detected

    A rather primitive module cycle is not detected. Minimal working example:

    reproduction
    ├── __init__.py
    ├── moduleA
    │   ├── __init__.py
    │   └── a_class.py
    └── moduleB
        ├── __init__.py
        └── b_class.py
    

    reproduction > moduleA > __init__.py:

    from .a_class import ClassA
    

    reproduction > moduleA > a_class.py:

    import reproduction.moduleB
    
    
    class ClassA:
        pass
    

    reproduction > moduleB > __init__.py:

    from .b_class import ClassB
    

    reproduction > moduleB > b_class.py:

    from ..moduleA import ClassA
    
    
    class ClassB:
        pass
    

    When running pycycle:

    > pycycle --here --verbose
    Trying to parse file: /private/tmp/reproduction/reproduction/__init__.py
    Trying to parse file: /private/tmp/reproduction/reproduction/moduleB/__init__.py
    Trying to parse file: /private/tmp/reproduction/reproduction/moduleB/b_class.py
    Trying to parse file: /private/tmp/reproduction/reproduction/moduleA/a_class.py
    Trying to parse file: /private/tmp/reproduction/reproduction/moduleA/__init__.py
    Project successfully transformed to AST, checking imports for cycles..
    No worries, no cycles here!
    If you think some cycle was missed, please open an Issue on Github.
    Finished.
    

    when trying to import moduleA:

    > python3 -c 'import reproduction.moduleA'   
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/tmp/reproduction/reproduction/moduleA/__init__.py", line 1, in <module>
        from .a_class import ClassA
      File "/private/tmp/reproduction/reproduction/moduleA/a_class.py", line 1, in <module>
        import reproduction.moduleB
      File "/private/tmp/reproduction/reproduction/moduleB/__init__.py", line 1, in <module>
        from .b_class import ClassB
      File "/private/tmp/reproduction/reproduction/moduleB/b_class.py", line 1, in <module>
        from ..moduleA import ClassA
    ImportError: cannot import name 'ClassA' from partially initialized module 'reproduction.moduleA' (most likely due to a circular import) (/private/tmp/reproduction/reproduction/moduleA/__init__.py)
    
    opened by Jofkos 0
  • Error: Invalid value for '--source': '.' is not a valid boolean.

    Error: Invalid value for '--source': '.' is not a valid boolean.

    Version: pycycle 0.0.8

    Tried to use but --source requires a BOOLEAN and not a string:

    Error: Invalid value for '--source': 'path_to_code' is not a valid boolean.
    
    pycycle.exe
    Usage: pycycle [OPTIONS] COMMAND [ARGS]...
    
    Options:
      --source BOOLEAN  Try to find cycles in the path provided.
      --ignore TEXT     Comma separated directories that will be ignored during
                        analysis.
    
    opened by MichaelQuaMan 2
  • No Cycles detected

    No Cycles detected

    My code have structure like this. I have multiple modules and

    A modules import B modules to work, B import C and C needs B to work. There are other dependancies are involved as well. But , this is general idea. I get 'No Cycles detected'.

    opened by Godcreatebugs 4
  • Bug: Subpackage circular imports not detected

    Bug: Subpackage circular imports not detected

    Summary

    My example is the following package structure where package.subpackage.module imports from package.module and visa-versa.

    .
    ├── package
    │   ├── __init__.py
    │   ├── module.py
    │   └── subpackage
    │       ├── __init__.py
    │       └── module.py
    └── run.py
    

    run.py

    from package.module import Anything
    

    package/subpackage/module.py

    from package.module import Anything
    
    
    class Thing:
        pass
    

    package/module.py

    from package.subpackage.module import Thing
    
    
    class Anything:
        pass
    

    Expected behaviour

    I consider this a circular import but pycycle detects no errors.

    Executing run.py results in a circular import error:

    Traceback (most recent call last):
      File "run.py", line 1, in <module>
        from package.module import Anything
      File "/home/dom/Code/package/package/module.py", line 1, in <module>
        from package.subpackage.module import Thing
      File "/home/dom/Code/package/package/subpackage/module.py", line 1, in <module>
        from package.module import Anything
    ImportError: cannot import name 'Anything' from 'package.module' (/home/dom/Code/package/package/module.py)
    

    An archive containing the package structure and code. package.tar.gz

    opened by DomHudson 0
Owner
Vadim Kravcenko
CTO @ Mindnow AG
Vadim Kravcenko
Tools for improving Python imports

imptools Tools for improving Python imports. Installation pip3 install imptools Overview Detailed docs import_path Import a module from any path on th

Danijar Hafner 7 Aug 7, 2022
Utilities for refactoring imports in python-like syntax.

aspy.refactor_imports Utilities for refactoring imports in python-like syntax. Installation pip install aspy.refactor_imports Examples aspy.refactor_i

Anthony Sottile 20 Nov 1, 2022
Convert relative imports to absolute

absolufy-imports A tool and pre-commit hook to automatically convert relative imports to absolute. Installation $ pip install absolufy-imports Usage a

Marco Gorelli 130 Dec 30, 2022
Flake8 plugin to find commented out or dead code

flake8-eradicate flake8 plugin to find commented out (or so called "dead") code. This is quite important for the project in a long run. Based on eradi

wemake.services 277 Dec 27, 2022
Pymxs, the 3DsMax bindings of Maxscript to Python doesn't come with any stubs

PyMXS Stubs generator What Pymxs, the 3DsMax bindings of Maxscript to Python doe

Frieder Erdmann 19 Dec 27, 2022
Tool to check the completeness of MANIFEST.in for Python packages

check-manifest Are you a Python developer? Have you uploaded packages to the Python Package Index? Have you accidentally uploaded broken packages with

Marius Gedminas 270 Dec 26, 2022
Code audit tool for python.

Pylama Code audit tool for Python and JavaScript. Pylama wraps these tools: pycodestyle (formerly pep8) © 2012-2013, Florent Xicluna; pydocstyle (form

Kirill Klenov 967 Jan 7, 2023
Tool to automatically fix some issues reported by flake8 (forked from autoflake).

autoflake8 Introduction autoflake8 removes unused imports and unused variables from Python code. It makes use of pyflakes to do this. autoflake8 also

francisco souza 27 Sep 8, 2022
Simple Python style checker in one Python file

pycodestyle (formerly called pep8) - Python style guide checker pycodestyle is a tool to check your Python code against some of the style conventions

Python Code Quality Authority 4.7k Jan 1, 2023
Optional static typing for Python 3 and 2 (PEP 484)

Mypy: Optional Static Typing for Python Got a question? Join us on Gitter! We don't have a mailing list; but we are always happy to answer questions o

Python 14.4k Jan 8, 2023
A Python Parser

parso - A Python Parser Parso is a Python parser that supports error recovery and round-trip parsing for different Python versions (in multiple Python

Dave Halter 520 Dec 26, 2022
A simple program which checks Python source files for errors

Pyflakes A simple program which checks Python source files for errors. Pyflakes analyzes programs and detects various errors. It works by parsing the

Python Code Quality Authority 1.2k Dec 30, 2022
Performant type-checking for python.

Pyre is a performant type checker for Python compliant with PEP 484. Pyre can analyze codebases with millions of lines of code incrementally – providi

Facebook 6.2k Jan 4, 2023
A static type analyzer for Python code

pytype - ?? ✔ Pytype checks and infers types for your Python code - without requiring type annotations. Pytype can: Lint plain Python code, flagging c

Google 4k Dec 31, 2022
The strictest and most opinionated python linter ever!

wemake-python-styleguide Welcome to the strictest and most opinionated python linter ever. wemake-python-styleguide is actually a flake8 plugin with s

wemake.services 2.1k Jan 1, 2023
Static type checker for Python

Static type checker for Python Speed Pyright is a fast type checker meant for large Python source bases. It can run in a “watch” mode and performs fas

Microsoft 9.2k Jan 3, 2023
A python documentation linter which checks that the docstring description matches the definition.

Darglint A functional docstring linter which checks whether a docstring's description matches the actual function/method implementation. Darglint expe

Terrence Reilly 463 Dec 31, 2022
Flake8 plugin that checks import order against various Python Style Guides

flake8-import-order A flake8 and Pylama plugin that checks the ordering of your imports. It does not check anything else about the imports. Merely tha

Python Code Quality Authority 270 Nov 24, 2022
Flake8 extension for checking quotes in python

Flake8 Extension to lint for quotes. Major update in 2.0.0 We automatically encourage avoiding escaping quotes as per PEP 8. To disable this, use --no

Zachary Heller 157 Dec 13, 2022