CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-copier

A library for rendering project templates from Git repositories with Jinja2 templating and interactive questionnaires.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Comprehensive exception hierarchy for handling template processing errors, configuration issues, user interaction problems, and system-level failures in copier operations.

Capabilities

Base Exceptions

Foundation exception classes for all copier errors and warnings.

class CopierError(Exception):
    """Base class for all Copier errors."""

class CopierWarning(UserWarning):
    """Base class for all Copier warnings."""

User-Facing Exceptions

Exceptions that indicate user-level issues requiring user action or input.

class UserMessageError(CopierError):
    """Exit program with user message."""

class UnsupportedVersionError(CopierError):
    """Copier version doesn't support this template."""

class InteractiveSessionError(CopierError):
    """Interactive session required but not available."""

Usage examples:

from copier import run_copy
from copier.errors import UserMessageError, UnsupportedVersionError

try:
    worker = run_copy("template/", "project/")
except UserMessageError as e:
    print(f"User error: {e}")
    # Handle user-facing error gracefully
except UnsupportedVersionError as e:
    print(f"Version compatibility issue: {e}")
    # Suggest upgrading copier or using different template version

Configuration Exceptions

Exceptions related to template configuration files and settings.

class ConfigFileError(CopierError):
    """Base class for config file problems."""

class InvalidConfigFileError(ConfigFileError):
    """Invalid config file format or content."""

class MultipleConfigFilesError(ConfigFileError):
    """Multiple config files found in template."""

Usage examples:

from copier import run_copy
from copier.errors import ConfigFileError, InvalidConfigFileError

try:
    worker = run_copy("template/", "project/")
except InvalidConfigFileError as e:
    print(f"Template configuration error: {e}")
    # Check copier.yml or copier.yaml in template
except MultipleConfigFilesError as e:
    print(f"Conflicting config files: {e}")
    # Remove duplicate configuration files

Path-Related Exceptions

Exceptions for file system path validation and access issues.

class PathError(CopierError):
    """Base class for path-related errors."""

class PathNotAbsoluteError(PathError):
    """Path should be absolute but is relative."""

class PathNotRelativeError(PathError):
    """Path should be relative but is absolute."""

class ForbiddenPathError(PathError):
    """Path is forbidden for security reasons."""

Usage examples:

from copier import Worker
from copier.errors import PathError, ForbiddenPathError

try:
    worker = Worker(
        src_path="template/",
        dst_path="../../../etc/passwd"  # Dangerous path
    )
    worker.run_copy()
except ForbiddenPathError as e:
    print(f"Security violation: {e}")
    # Use safe destination path
except PathError as e:
    print(f"Path issue: {e}")
    # Validate and correct path

Template Processing Exceptions

Exceptions that occur during template processing and rendering.

class InvalidTypeError(CopierError):
    """Unsupported question type in template."""

class ExtensionNotFoundError(CopierError):
    """Template extensions couldn't be loaded."""

class UnsafeTemplateError(CopierError):
    """Template contains unsafe features without user consent."""

class YieldTagInFileError(CopierError):
    """Yield tag found in file content (not allowed)."""

class MultipleYieldTagsError(CopierError):
    """Multiple yield tags found in path name."""

class TaskError(CopierError):
    """Task execution failed during template processing."""
    
    @classmethod
    def from_process(cls, process: subprocess.CompletedProcess) -> TaskError:
        """Create TaskError from a failed subprocess."""

Usage examples:

from copier import run_copy
from copier.errors import UnsafeTemplateError, TaskError

try:
    worker = run_copy(
        "suspicious-template/",
        "project/",
        unsafe=False  # Reject unsafe templates
    )
except UnsafeTemplateError as e:
    print(f"Template safety issue: {e}")
    # Review template or use unsafe=True if trusted
except TaskError as e:
    print(f"Template task failed: {e}")
    # Check template tasks configuration

User Interaction Exceptions

Exceptions related to user input and interactive sessions.

class CopierAnswersInterrupt(CopierError):
    """Keyboard interrupt during questionnaire."""

Usage examples:

from copier import run_copy
from copier.errors import CopierAnswersInterrupt

try:
    worker = run_copy("template/", "project/")
except CopierAnswersInterrupt:
    print("Operation cancelled by user")
    # Clean up partial work if needed
except KeyboardInterrupt:
    print("Process interrupted")
    # Handle general interruption

Warning Classes

Warning classes for non-fatal issues that don't stop processing.

class UnknownCopierVersionWarning(CopierWarning):
    """Cannot determine which Copier version was used."""

class OldTemplateWarning(CopierWarning):
    """Template was designed for an older Copier version."""

class DirtyLocalWarning(CopierWarning):
    """Uncommitted changes in local template directory."""

class ShallowCloneWarning(CopierWarning):
    """Template repository is a shallow clone."""

class MissingSettingsWarning(CopierWarning):
    """Settings file not found at expected location."""

class MissingFileWarning(CopierWarning):
    """Referenced file not found in template."""

Usage examples:

import warnings
from copier import run_copy
from copier.errors import OldTemplateWarning, DirtyLocalWarning

# Configure warning handling
warnings.filterwarnings("always", category=OldTemplateWarning)

try:
    with warnings.catch_warnings(record=True) as w:
        worker = run_copy("old-template/", "project/")
        
        for warning in w:
            if issubclass(warning.category, DirtyLocalWarning):
                print(f"Template has uncommitted changes: {warning.message}")
            elif issubclass(warning.category, OldTemplateWarning):
                print(f"Template compatibility: {warning.message}")
                
except Exception as e:
    print(f"Processing failed: {e}")

Exception Hierarchy Summary

CopierError
├── UserMessageError
├── UnsupportedVersionError
├── ConfigFileError
│   ├── InvalidConfigFileError
│   └── MultipleConfigFilesError
├── PathError
│   ├── PathNotAbsoluteError
│   ├── PathNotRelativeError
│   └── ForbiddenPathError
├── InvalidTypeError
├── ExtensionNotFoundError
├── CopierAnswersInterrupt
├── UnsafeTemplateError
├── YieldTagInFileError
├── MultipleYieldTagsError
└── TaskError

CopierWarning
├── UnknownCopierVersionWarning
├── OldTemplateWarning  
├── DirtyLocalWarning
├── ShallowCloneWarning
├── MissingSettingsWarning
├── MissingFileWarning
└── InteractiveSessionError

Best Practices

from copier import run_copy
from copier.errors import CopierError, ConfigFileError, PathError

def safe_template_processing(template_path: str, output_path: str) -> bool:
    """Safely process template with comprehensive error handling."""
    try:
        worker = run_copy(template_path, output_path)
        return True
        
    except ConfigFileError as e:
        print(f"Template configuration issue: {e}")
        # Log for template author to fix
        return False
        
    except PathError as e:
        print(f"Path validation failed: {e}")
        # Sanitize and retry with safe paths
        return False
        
    except CopierError as e:
        print(f"Copier processing error: {e}")
        # General copier error handling
        return False
        
    except Exception as e:
        print(f"Unexpected error: {e}")
        # Handle unexpected system errors
        return False

Install with Tessl CLI

npx tessl i tessl/pypi-copier

docs

advanced-usage.md

core-operations.md

error-handling.md

index.md

types-enums.md

tile.json