Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/rgryta/cyclic-classes

Enable relations between different classes across modules, skipping issues with cyclic imports
https://github.com/rgryta/cyclic-classes

caching classes-and-inheritance classes-python cyclic import python

Last synced: about 2 months ago
JSON representation

Enable relations between different classes across modules, skipping issues with cyclic imports

Awesome Lists containing this project

README

        


Cyclic Classes



Python package
PyPI
Code style: black
pylint
NoPrint

## About

Ever had a situation when you wanted to create a cyclic reference between two objects, but don't want to maintain a large singular file?
You're tired of seeing "cyclic-import" errors? This package is for you!
Simply "register" a class you want to share between different modules and you're pretty much good to go!

See the [documentation](https://github.com/rgryta/Cyclic-Classes/#Usage) for more information.

## Requirements

There's ***NONE!***

## Installation

Pull straight from this repo to install manually or just use pip: `pip install cyclic-classes` will do the trick.

## Usage

Consider a package `myk8s` with two modules, maybe one is to reference a k8s deployment and the other one is for pods within that deployment.

`deployment.py`
```python
from .pod import Pod

class Deployment:
def __init__(self, name: str):
self.name = name

@property
def pods(self):
return [Pod(f"{self.name}-pod-{i}") for i in range(3)]
```

Now, if you want to create a back-reference for Deployment within Pod, like this:
`pod.py`
```python
from .deployment import Deployment

class Pod:
def __init__(self, name: str):
self.name = name

@property
def deployment(self):
return Deployment(self.name.split("-")[0])
```

In the above example, you would get a cyclic-import error. To avoid this, you can use `cyclic_classes` to register the classes you want to share between modules.
Do so like this:

`deployment.py`
```python
from cyclic_classes import register, cyclic_import

with cyclic_import(): # This is required to avoid cyclic-import errors - you're actually importing a registered class underneath, but IDE will think it's your actual class
from .pod import Pod

@register # You have to register the class you want to access so that Pod will also be able to use it in the pod.py file
class Deployment:
def __init__(self, name: str):
self.name = name

@property
def pods(self):
return [Pod(f"{self.name}-pod-{i}") for i in range(3)]
```

Now, if you want to create a back-reference for Deployment within Pod, like this:
`pod.py`
```python
from cyclic_classes import register, cyclic_import

with cyclic_import():
from .deployment import Deployment

@register # Making Pod available to cyclic_import
class Pod:
def __init__(self, name: str):
self.name = name

@property
def deployment(self):
return Deployment(self.name.split("-")[0])
```

And that's it! You can now use the classes in your code without any issues.

### Note

Cyclic import supports multiple ways of imports, including relative imports, absolute imports, and even module imports.
As such, in the `cyclic_import` context you can use either of the following:

```python
import myk8s.deployment as depl # And later use depl.Deployment
from .deployment import Deployment
from myk8s.deployment import Deployment

# Not recommended, but also possible
# Reason: Such imports wouldn't work even if there was no cyclic import issue, but it works with cyclic import (you'll get a warning though) and some IDEs think it's correct
from deployment import Deployment
import deployment
```

This also works with aliases! So feel free to use `import ... as ...` or `from ... import ... as ...` as you wish.

## Development

### Installation

Install virtual environment and cyclic_classes package in editable mode with dev dependencies.

```bash
python -m venv venv
source venv/bin/activate
pip install -e .[dev]
```

### How to?

Automate as much as we can, see configuration in `pyproject.toml` file to see what are the flags used.

```bash
staging format # Reformat the code
staging lint # Check for linting issues
staging test # Run unit tests and coverage report
```