dissolve-python 0.3.0

A tool to dissolve deprecated calls in Python codebases
Documentation
"""
Class and method deprecation examples.
"""

try:
    from dissolve import replace_me
except ModuleNotFoundError:
    # Fallback implementation for when dissolve is not available
    import warnings

    def replace_me(since=None, remove_in=None, message=None):
        def decorator(func):
            def wrapper(*args, **kwargs):
                msg = f"{func.__name__} has been deprecated"
                if since:
                    msg += f" since {since}"
                if remove_in:
                    msg += f" and will be removed in {remove_in}"
                if message:
                    msg += f". {message}"
                else:
                    msg += ". Consider running 'dissolve migrate' to automatically update your code."
                warnings.warn(msg, DeprecationWarning, stacklevel=2)
                return func(*args, **kwargs)
            return wrapper
        return decorator


class DataProcessor:
    """
    Modern data processing class (new API).
    """
    
    def __init__(self, data_source, batch_size=100, enable_caching=True):
        self.data_source = data_source
        self.batch_size = batch_size
        self.enable_caching = enable_caching
        self._cache = {} if enable_caching else None
    
    def process(self, data):
        """Process data with modern algorithms."""
        if self._cache is not None and data in self._cache:
            return self._cache[data]
        
        # Simulate processing
        result = f"Processed: {data} (batch_size={self.batch_size})"
        
        if self._cache is not None:
            self._cache[data] = result
        
        return result
    
    def batch_process(self, data_list):
        """Process multiple data items efficiently."""
        return [self.process(item) for item in data_list]
    
    def get_stats(self):
        """Get processing statistics."""
        cache_size = len(self._cache) if self._cache else 0
        return {
            "data_source": self.data_source,
            "batch_size": self.batch_size,
            "caching_enabled": self.enable_caching,
            "cache_size": cache_size
        }


class User:
    """
    User model with modern API design.
    """
    
    def __init__(self, username, email, full_name=None, is_active=True):
        self.username = username
        self.email = email
        self.full_name = full_name or username
        self.is_active = is_active
        self._profile = {}
    
    def get_display_name(self):
        """Get the user's display name."""
        return self.full_name or self.username
    
    def update_profile(self, **kwargs):
        """Update user profile information."""
        self._profile.update(kwargs)
        return self._profile
    
    def get_profile(self):
        """Get user profile information."""
        return self._profile.copy()
    
    @property
    def status(self):
        """Get user status."""
        return "active" if self.is_active else "inactive"


# === DEPRECATED CLASSES AND METHODS ===

@replace_me(since="2.0.0", remove_in="3.0.0")
class OldDataProcessor:
    """
    Legacy data processing class.
    
    .. deprecated:: 2.0.0
        Use :class:`DataProcessor` instead.
    """
    
    def __init__(self, data_source, cache_size=50):
        """Initialize with legacy parameter names."""
        # Convert old parameters to new format
        self._processor = DataProcessor(
            data_source=data_source, 
            batch_size=cache_size * 2,  # Old cache_size maps to batch_size * 2
            enable_caching=True
        )
    
    def process(self, data):
        """Process data using the legacy interface."""
        return self._processor.process(data)
    
    def get_info(self):
        """Get processor info (legacy method)."""
        return self._processor.get_stats()


class LegacyUser:
    """
    User model with legacy method names.
    """
    
    def __init__(self, name, email_address, active=True):
        self._user = User(username=name, email=email_address, is_active=active)
    
    @replace_me(since="1.5.0", remove_in="2.5.0")
    def get_name(self):
        """
        Get user name (legacy method).
        
        .. deprecated:: 1.5.0
            Use :meth:`get_display_name` instead.
        """
        return self._user.get_display_name()
    
    @replace_me(since="1.8.0")
    def set_profile_data(self, data):
        """
        Set profile data (legacy method).
        
        .. deprecated:: 1.8.0
            Use :meth:`update_profile` instead.
        """
        return self._user.update_profile(**data)
    
    def get_display_name(self):
        """Get the user's display name (new method)."""
        return self._user.get_display_name()
    
    def update_profile(self, **kwargs):
        """Update profile (new method)."""
        return self._user.update_profile(**kwargs)
    
    # Property deprecation example
    @property
    @replace_me(since="1.0.0")
    def is_enabled(self):
        """
        Check if user is enabled (legacy property).
        
        .. deprecated:: 2.0.0
            Use :attr:`status` instead.
        """
        return self._user.status == "active"
    
    @property
    def status(self):
        """Get user status (new property)."""
        return self._user.status


# Wrapper class demonstrating complex deprecation
@replace_me(since="1.0.0")
class SimpleProcessor:
    """
    Simplified processor without caching (deprecated).
    
    .. deprecated:: 2.2.0
        Use :class:`DataProcessor` instead.
    """
    
    def __init__(self, source):
        self._processor = DataProcessor(source, batch_size=1, enable_caching=False)
    
    def process_item(self, item):
        """Process a single item."""
        return self._processor.process(item)