Skip to main content

byecycle 🚲

python pyPI docs pdm-managed license chat

Find and expose cyclic imports in python projects.

Installation

byecycle uses the built-in ast module to parse code files. As a consequence, it can only handle python code within the same major version (read: no support for python 1 and 2), and the same or lower minor version of the python interpreter it was installed with. If byecycle raises SyntaxErrors in code that you know to be working, try using a byecycle that is installed with the same python version that can run the code in question.

From PyPI

Requirements:

  • python 3.11 or higher
  • pipx
pipx install byecycle

Development Setup

Requirements:

  • python 3.11 or higher
  • pdm
  • git
git clone https://github.com/a-recknagel/byecycle.git
cd byecycle
pdm install -G:all

Usage

As a Command Line Tool

# with a path
byecycle /home/me/dev/byecycle/src/byecycle/
# or the name of an installed package
byecycle byecycle

The result will be a json string:

{
  "byecycle.misc": {},
  "byecycle.graph": {
    "byecycle": {
      "tags": [
        "vanilla",
        "parent"
      ],
      "cycle": "complicated"
    },
    "byecycle.misc": {
      "tags": [
        "vanilla"
      ],
      "cycle": null
    }
  },
  [...]
  "byecycle": {
    "byecycle.graph": {
      "tags": [
        "vanilla",
        "parent"
      ],
      "cycle": "complicated"
    }
  }
}

By default, the result is printed with some rich formatting to highlight types and such. If you need the output to be plain ascii, pass the --no-rich flag.


For bigger projects, you might get much more complex output. The intent of returning json is to have something that can be easily piped into e.g. jq for further processing:

# filter out imports that don't have a cycle
byecycle byecycle | jq '.[] |= (.[] |= select(.cycle != null) | select(. != {}))'
{
  "byecycle.graph": {
    "byecycle": {
      "tags": [
        "parent",
        "vanilla"
      ],
      "cycle": "complicated"
    }
  },
  "byecycle.cli": {
    "byecycle": {
      "tags": [
        "parent",
        "vanilla"
      ],
      "cycle": "complicated"
    }
  },
  "byecycle": {
    "byecycle.graph": {
      "tags": [
        "parent",
        "vanilla"
      ],
      "cycle": "complicated"
    },
    "byecycle.cli": {
      "tags": [
        "parent",
        "vanilla"
      ],
      "cycle": "complicated"
    }
  }
}

Alternatively, you can also call the main entrypoint's core functionality as a regular python function. Among other things, it returns a dictionary equivalent to the CLI's json that you can work with:

from byecycle import run
cycles, *_ = run("byecycle")
# filter out imports that don't have a cycle
for outer_k, outer_v in cycles.items():
    for inner_k, inner_v in outer_v.items():
        if inner_v["cycle"]:
            print(f"{outer_k} -> {inner_k}: {inner_v['cycle']}")
byecycle.graph -> byecycle -> complicated
byecycle.cli -> byecycle -> complicated
byecycle -> byecycle.graph -> complicated
byecycle -> byecycle.cli -> complicated

See the help text of byecycle for an explanation of tags/ImportKinds and cycle/EdgeKinds.

In short, if there is a cycle, the tags of all involved imports inform the cycle-severity, with the highest severity winning out if multiple apply. The defaults can be overriden in order to isolate, filter, or highlight cycles with specific severities.

To Visualize the Import Graph

If you pass the --draw flag1 on your command-line-call, byecycle will create an image of the import graph instead:

byecycle byecycle --draw
Plot of imports in the byecycle project Legend for nodes in the plot

[1] Requires installation of the draw-extra, i.e. pipx install "byecycle[draw]".

Release files for byecycle 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for byecycle 0.1.5
File Size Uploaded
byecycle-0.1.5.tar.gz 18.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for byecycle 0.1.5
File Interpreter ABI Platform
byecycle-0.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 33.9 kB

Release files / byecycle-0.1.5.tar.gz

Download URL byecycle-0.1.5.tar.gz
Size 18.1 kB
Tags Source
SHA-256 checksum
How to use checksums
be2c907b090d27f9699daa7a8dec419d573b59b1ef9413302f013c822e0bdacb
BLAKE2b-256 checksum
How to use checksums
44b7053810b8f83772d72c8814168b1a010184a7b8146eb0368a33cbd768b63d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.15.4 CPython/3.10.12 Linux/6.5.0-1021-azure

Release files / byecycle-0.1.5-py3-none-any.whl

Download URL byecycle-0.1.5-py3-none-any.whl
Size 15.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a75cf216b0e0ba6f061beb5c94ed1a9a9e080ea6ed93993c71790276da075a89
BLAKE2b-256 checksum
How to use checksums
1aa178de79b757bccae010a1eb90bab3998d099c4090f71849ccfccf00c5a71d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via pdm/2.15.4 CPython/3.10.12 Linux/6.5.0-1021-azure

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page