CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-molecule

Molecule aids in the development and testing of Ansible roles

Pending
Overview
Eval results
Files

exceptions.mddocs/

Exception Handling

Molecule provides a comprehensive exception system for handling errors during testing workflows, with specific exception types for different failure scenarios and detailed error reporting capabilities.

Capabilities

Core Exception Classes

Base exception classes for handling Molecule-specific errors and failures.

class MoleculeError(Exception):
    """
    Generic Molecule error.
    
    Custom exception to handle scenario run failures with support
    for exit codes, detailed messages, and warning aggregation.
    
    Args:
        message (str): The message to display about the problem
        code (int): Exit code to use when exiting (default: 1)
        warns (Sequence[WarningMessage]): Warnings about the problem to issue
        
    Attributes:
        code (int): Exit code for process termination
    """
    
    def __init__(self, message="", code=1, warns=()):
        """Initialize MoleculeError with message, code, and warnings."""

class ScenarioFailureError(MoleculeError):
    """
    Details about a scenario that failed.
    
    Specialized exception for scenario execution failures,
    inheriting all capabilities from MoleculeError.
    """

Runtime Warning Classes

Warning classes for handling runtime issues and compatibility problems.

class MoleculeRuntimeWarning(RuntimeWarning):
    """
    A runtime warning used by Molecule and its plugins.
    
    Base warning class for Molecule-specific runtime issues
    that don't prevent execution but should be reported.
    """

class IncompatibleMoleculeRuntimeWarning(MoleculeRuntimeWarning):
    """
    A warning noting an unsupported runtime environment.
    
    Issued when Molecule detects compatibility issues with
    the current runtime environment or dependencies.
    """

Usage Examples

Basic Exception Handling

from molecule.exceptions import MoleculeError, ScenarioFailureError

try:
    # Molecule operation that might fail
    config = Config()
    result = config.driver.status()
except MoleculeError as e:
    print(f"Molecule error occurred: {e}")
    print(f"Exit code: {e.code}")
    # Handle the error appropriately
    exit(e.code)
except ScenarioFailureError as e:
    print(f"Scenario failed: {e}")
    # Specific handling for scenario failures
    exit(e.code)

Raising Custom Molecule Errors

from molecule.exceptions import MoleculeError
import warnings

def validate_configuration():
    """Validate Molecule configuration and raise errors if invalid."""
    
    # Check for missing required files
    if not os.path.exists("molecule.yml"):
        raise MoleculeError(
            message="molecule.yml configuration file not found",
            code=4  # RC_SETUP_ERROR
        )
    
    # Check for compatibility issues
    warning_msgs = []
    if incompatible_version_detected():
        warning = warnings.WarningMessage(
            message="Incompatible version detected",
            category=UserWarning,
            filename=__file__,
            lineno=0
        )
        warning_msgs.append(warning)
    
    if warning_msgs:
        raise MoleculeError(
            message="Configuration validation failed",
            code=1,
            warns=warning_msgs
        )

Exception Handling in Custom Drivers

from molecule.driver.base import Driver
from molecule.exceptions import MoleculeError

class CustomDriver(Driver):
    def sanity_checks(self):
        """Validate driver prerequisites."""
        
        # Check for required external tools
        if not self._tool_available("custom-tool"):
            raise MoleculeError(
                message="custom-tool is required but not found in PATH",
                code=4  # RC_SETUP_ERROR
            )
        
        # Check for valid configuration
        if not self.options.get("api_key"):
            raise MoleculeError(
                message="API key is required for custom driver",
                code=4
            )
    
    def _tool_available(self, tool_name):
        """Check if external tool is available."""
        import subprocess
        try:
            subprocess.run([tool_name, "--version"], 
                         capture_output=True, check=True)
            return True
        except (subprocess.CalledProcessError, FileNotFoundError):
            return False

Exception Handling in Custom Verifiers

from molecule.verifier.base import Verifier
from molecule.exceptions import MoleculeError

class CustomVerifier(Verifier):
    def execute(self, action_args):
        """Execute verification tests with error handling."""
        
        try:
            result = self._run_tests(action_args)
            
            if result.returncode != 0:
                raise ScenarioFailureError(
                    message=f"Verification tests failed: {result.stderr}",
                    code=result.returncode
                )
                
            return result
            
        except FileNotFoundError as e:
            raise MoleculeError(
                message=f"Test runner not found: {e}",
                code=4  # RC_SETUP_ERROR
            )
        except TimeoutError:
            raise MoleculeError(
                message="Verification tests timed out",
                code=3  # RC_TIMEOUT
            )

Warning Handling

import warnings
from molecule.api import MoleculeRuntimeWarning, IncompatibleMoleculeRuntimeWarning

def check_runtime_compatibility():
    """Check runtime environment and issue warnings."""
    
    # Check Python version compatibility
    import sys
    if sys.version_info < (3, 10):
        warnings.warn(
            "Python version < 3.10 is not officially supported",
            IncompatibleMoleculeRuntimeWarning,
            stacklevel=2
        )
    
    # Check for deprecated features
    if using_deprecated_feature():
        warnings.warn(
            "This feature is deprecated and will be removed in a future version",
            MoleculeRuntimeWarning,
            stacklevel=2
        )

# Configure warning filters
warnings.filterwarnings("always", category=MoleculeRuntimeWarning)
warnings.filterwarnings("error", category=IncompatibleMoleculeRuntimeWarning)

Error Code Constants

from molecule.constants import (
    RC_SUCCESS,        # 0
    RC_TIMEOUT,        # 3
    RC_SETUP_ERROR,    # 4
    RC_UNKNOWN_ERROR   # 5
)

def handle_molecule_operation():
    """Handle Molecule operation with proper exit codes."""
    
    try:
        # Perform Molecule operation
        result = run_molecule_test()
        return RC_SUCCESS
        
    except TimeoutError:
        return RC_TIMEOUT
        
    except MoleculeError as e:
        if "setup" in str(e).lower():
            return RC_SETUP_ERROR
        return e.code
        
    except Exception:
        return RC_UNKNOWN_ERROR

Integration Notes

  • All Molecule exceptions inherit from MoleculeError for consistent error handling
  • Exit codes follow standard conventions (0=success, >0=error)
  • Warning messages are logged through the Molecule logging system
  • Exception messages support rich formatting and highlighting
  • Custom plugins should use appropriate exception types for consistency
  • Error reporting includes context information for debugging
  • Exception handling integrates with Click framework for CLI error display

Install with Tessl CLI

npx tessl i tessl/pypi-molecule

docs

cli-commands.md

configuration.md

core-api.md

driver-system.md

exceptions.md

index.md

verifier-system.md

tile.json