CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-singleton-decorator

A testable singleton decorator that allows easily creating singleton objects by adding a decorator to class definitions while maintaining testability.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

Singleton Decorator

A testable singleton decorator that allows easily creating singleton objects by adding a decorator to class definitions while maintaining testability. Unlike traditional singleton implementations that make direct class access impossible in unit tests, this decorator uses a wrapper object that stores the original class in a __wrapped__ attribute, allowing developers to access the decorated class directly for isolated testing.

Package Information

  • Package Name: singleton-decorator
  • Language: Python
  • Installation: pip install singleton-decorator

Core Imports

from singleton_decorator import singleton

Version information:

from singleton_decorator import __version__

Basic Usage

from singleton_decorator import singleton

@singleton
class DatabaseConnection:
    def __init__(self, host, port):
        self.host = host
        self.port = port
        print(f"Connecting to {host}:{port}")
    
    def query(self, sql):
        return f"Executing: {sql}"

# First call creates the instance
db1 = DatabaseConnection("localhost", 5432)
# Subsequent calls return the same instance (constructor args ignored)
db2 = DatabaseConnection("ignored", 9999)
db3 = DatabaseConnection("also_ignored", 1111)

# All variables reference the same instance
assert db1 is db2 is db3
print(db1.host)  # "localhost"
print(db2.host)  # "localhost" (not "ignored")

Capabilities

Singleton Decorator

Creates a singleton wrapper for any class, ensuring only one instance exists while maintaining testability through the __wrapped__ attribute.

def singleton(cls):
    """
    A singleton decorator that returns a wrapper object. A call on that object
    returns a single instance object of decorated class. Use the __wrapped__
    attribute to access decorated class directly in unit tests.
    
    Args:
        cls: The class to decorate as a singleton
        
    Returns:
        _SingletonWrapper: Wrapper object that manages singleton instance
    """

Testing Access

Access the original class for isolated unit testing without singleton behavior.

# Access pattern for testing
decorated_class.__wrapped__  # Original class for direct method calls

Usage in Tests:

from unittest import TestCase, mock
from singleton_decorator import singleton

@singleton
class MyService:
    def __init__(self, config):
        self.config = config
    
    def process_data(self, data):
        return f"Processing {data} with {self.config}"

class TestMyService(TestCase):
    def test_process_data(self):
        # Use __wrapped__ to test method in isolation
        mock_self = mock.MagicMock()
        mock_self.config = "test_config"
        
        result = MyService.__wrapped__.process_data(mock_self, "test_data")
        
        assert result == "Processing test_data with test_config"

Types and Implementation Details

class _SingletonWrapper:
    """
    Internal wrapper class created for each decorated class.
    Manages singleton instance lifecycle.
    """
    
    def __init__(self, cls):
        """
        Initialize wrapper with the decorated class.
        
        Args:
            cls: The class to wrap
        """
    
    def __call__(self, *args, **kwargs):
        """
        Returns singleton instance of wrapped class.
        Creates instance on first call, returns existing instance thereafter.
        
        Args:
            *args: Constructor arguments (only used on first call)
            **kwargs: Constructor keyword arguments (only used on first call)
            
        Returns:
            object: Single instance of the wrapped class
        """
    
    __wrapped__: type  # Original decorated class for testing access
    _instance: object  # Singleton instance (None until first call)

__version__: str  # Package version constant ("1.0.0")

Important Notes

Constructor Behavior

  • The __init__ method is called only once with arguments from the first instantiation
  • All subsequent instantiation attempts ignore their arguments and return the existing instance
  • This behavior ensures true singleton semantics but requires careful consideration of constructor arguments

Testing Guidelines

  • Use ClassName.__wrapped__ to access the original class in unit tests
  • Pass mock objects as self to test methods in complete isolation
  • This approach avoids constructor dependencies and maintains test isolation
  • The __wrapped__ attribute provides direct access to all class methods and attributes

Thread Safety

This implementation does not provide thread-safety guarantees. In multi-threaded environments, consider additional synchronization mechanisms if concurrent access to the singleton creation is possible.

docs

index.md

tile.json