Metadata-Version: 2.1
Name: singleton-class-decorator
Version: 1.0.1
Summary: Singleton Class Decorator
Author-email: Jeremy Ribeiro <jeremy.d.ribeiro@gmail.com>
License: MIT License
        
        Copyright (c) 2022 Jeremy Ribeiro
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/Jrmy-rbr/singleton-class-decorator
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE

![coverage_badge](https://img.shields.io/badge/coverage-100%25-brightgreen)

# Installation
## Through GitHub
1. Go to a folder where you want to store the repo: `cd <path_to_folder>`
2. Clone the repo using the following: `git clone git@github.com:Jrmy-rbr/singleton-class-decorator.git`
3. Install using pip: `pip install ./singleton-class-decorator`

## Through PyPI
Run `python -m pip install singleton-class-decorator`
# Singleton Class Decorator

This repo implements a decorator that creates singleton classes. As opposed to some other singleton decorators,
the singleton classes created through this decorator are true classes. As a consequence,
every operation supported by classes is supported by the singleton classes, like the use of instance, or inheritance for example.

The main purpose of this repo was for me to learn more about Python, and some of its more advanced features. But this decorator comes with its advantages. It is not more powerful than for example [this](https://github.com/Kemaweyan/singleton_decorator) commonly used decorator by [Kemaweyan](https://github.com/Kemaweyan). However, it allows using singleton classes as actual classes, and therefore it might be more intuitive to use in situations where Kemayan's singleton object needs to use some extra attribute. Here is a quick illustration of situations in which our decorator behaves differently.

## Quick comparison with Kemayan's decorator
### Kemayan's decorator
```python
@singleton
class MyClass:
    @static
    def add(x, y):
        return x+y

# This will raise an AttributeError
MyClass.add(1, 2)

# You need to do this instead. It'll return 3
MyClass.__wrapped__.add(1, 2)
```

```python
@singleton
class MyClass:
    ...

obj = MyClass()

# this will raise an error
isinstance(obj, MyClass)

# you need to do this instead
isinstance(obj, MyClass.__wrapped__)
```

### This decorator

```python
@singleton
class MyClass:
    @static
    def add(x, y):
        return x+y

# This works fine
MyClass.add(1, 2)
```

```python
@singleton
class MyClass:
    ...

obj = MyClass()

# this works fine
isinstance(obj, MyClass)
```

# Usage


You can import the singleton class decorator as follows:

```python
from singleton_class_decorator import singleton
```

## Simplest use case
Here are some usage examples. To make a singleton class you simply need to use the singleton decorator
on your class as follows:

```python
@singleton
class MyClass:
    ...

# MyClass is now a singleton, which we can check
assert MyClass() is MyClass()

```

As mentioned earlier, you can check the type of an object as with a regular class:

```python
obj = MyClass()

type(obj)
# returns `<class 'singleton_class_decorator.MetaClasses.MyClass'>`

type(obj) == MyClass
# This evaluates to True

isinstance(obj, MyClass)
# This evaluates to True

```

## Enabling Inheritance

The above should work for any class. However, if you try to create a child class from `MyClass` an error will be raised. This is because by default the singleton disables inheritance. 
```python
from singleton_class_decorator import singleton

@singleton
class MyClass:
    ...

# is equivalent to the following

@singleton(is_final=True)
class MyClass:
    ...
```
As you see, the default value of the keyword argument `is_final` is `True`, which disables inheritance. But you can easily change it.

```python
# enable inheritance by setting the ketword argument `is_final` for `False`
@singleton(is_final=False)
class MyClass:
    ...

# This will now work
class ChildClass(MyClass):
    ...

# However the ClidClass is not automatically a singleton
assert ChildClass() is not ChildClass()

# If you want a child class to be a singleton, you need to use the singleton decorator
# Again you may set the `is_final` to `True` or `False` as you whish.
@singleton
class OtherChildClass(MyClass):
    ...

# OtherChildClass is a singleton
assert OtherChildClass() is OtherChildClass()

```

# How Does it work?

Go check my blog post about this decorator [here](https://jrmy-rbr.github.io/2023/02/19/singleton_decorator.html) 
