CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-tutor

The Docker-based Open edX distribution designed for peace of mind

Overview
Eval results
Files

environment.mddocs/

Environment Management

Template rendering system using Jinja2 for generating Docker Compose configurations, Kubernetes manifests, and application settings. The environment system handles template processing, file generation, and configuration deployment across different execution contexts.

Capabilities

Template Rendering

Process Jinja2 templates with configuration data and custom filters to generate deployment files.

def render_file(config: Config, *path: str) -> Union[str, bytes]:
    """
    Render a template file with configuration data.
    
    Args:
        config (Config): Configuration dictionary for template variables
        *path (str): Path components to the template file
        
    Returns:
        Union[str, bytes]: Rendered template content (bytes for binary files)
    """

def render_str(config: Config, text: str) -> str:
    """
    Render a template string with configuration data.
    
    Args:
        config (Config): Configuration dictionary for template variables  
        text (str): Template string to render
        
    Returns:
        str: Rendered string content
    """

def render_unknown(config: Config, value: Any) -> Any:
    """
    Render unknown value type, handling strings as templates and passing through other types.
    
    Args:
        config (Config): Configuration dictionary for template variables
        value (Any): Value to potentially render
        
    Returns:
        Any: Rendered value or original value if not a string
    """

File Operations

Manage environment directories and file operations. File saving is handled internally by the environment rendering system.

def copy_file(root: str, filename: str) -> None:
    """
    Copy a file from templates to environment directory.
    
    Args:
        root (str): Project root directory
        filename (str): Filename to copy
    """

def delete_file(root: str, filename: str) -> None:
    """
    Delete a file from the environment directory.
    
    Args:
        root (str): Project root directory
        filename (str): Filename to delete
    """

Environment Directory Management

Manage the environment directory structure and lifecycle.

def create_env_dir(root: str) -> str:
    """
    Create and return the environment directory path.
    
    Args:
        root (str): Project root directory
        
    Returns:
        str: Path to the environment directory
    """

def clean_env_dir(root: str) -> None:
    """
    Clean the environment directory, removing all generated files.
    
    Args:
        root (str): Project root directory
    """

def get_env_path(root: str, *path: str) -> str:
    """
    Get the full path to a file in the environment directory.
    
    Args:
        root (str): Project root directory
        *path (str): Path components within environment directory
        
    Returns:
        str: Full path to the file
    """

Template System Configuration

Configure the Jinja2 template environment with custom filters and settings.

def create_template_environment(config: Config) -> jinja2.Environment:
    """
    Create a Jinja2 environment with Tutor-specific settings and filters.
    
    Args:
        config (Config): Configuration dictionary for template context
        
    Returns:  
        jinja2.Environment: Configured Jinja2 environment
    """

def get_template_filters() -> Dict[str, Callable]:
    """
    Get dictionary of custom Jinja2 filters available in templates.
    
    Returns:
        Dict[str, Callable]: Dictionary mapping filter names to functions
    """

Patch System

Apply template patches to customize generated configurations.

def apply_patches(config: Config, content: str, patches: List[str]) -> str:
    """
    Apply a list of patches to template content.
    
    Args:
        config (Config): Configuration dictionary for patch rendering
        content (str): Original content to patch
        patches (List[str]): List of patch identifiers
        
    Returns:
        str: Content with patches applied
    """

def get_patch_content(config: Config, patch_name: str) -> str:
    """
    Get rendered content for a specific patch.
    
    Args:
        config (Config): Configuration dictionary for patch rendering
        patch_name (str): Name of the patch to retrieve
        
    Returns:
        str: Rendered patch content
    """

Template Variables

Built-in Template Variables

Variables automatically available in all templates.

# Configuration access
config: Config  # Complete configuration dictionary
get_config: Callable[[str, Any], Any]  # Get config value with default

# Environment information  
TUTOR_VERSION: str  # Current Tutor version
TUTOR_APP: str  # Application name (usually "tutor")

# Docker and deployment
DOCKER_REGISTRY: str  # Docker registry for images
DOCKER_IMAGE_TAG: str  # Tag for Docker images

# Networking
HTTP_PORT: int  # HTTP port number
HTTPS_PORT: int  # HTTPS port number

# Paths
TUTOR_ROOT: str  # Project root directory
ENV_ROOT: str  # Environment directory path

Custom Template Filters

Custom Jinja2 filters available in templates.

# String processing filters
def common_domain(d1: str, d2: str) -> str:
    """Find common domain between two domain names."""

def reverse_host(domain: str) -> str:
    """Reverse domain name Java-style (com.example.subdomain)."""

def random_string(length: int) -> str:
    """Generate random string of specified length."""

# Configuration filters  
def list_if(services: List[Tuple[str, bool]]) -> str:
    """Generate JSON list of enabled services."""

def walk_templates(obj: Any) -> Any:
    """Recursively render templates in nested data structures."""

# Docker filters
def docker_image(service: str) -> str:
    """Get Docker image name for a service."""

def docker_registry_image(image: str) -> str:
    """Add registry prefix to image name if configured."""

Template Organization

Template Directory Structure

# Template root directories (configurable via ENV_TEMPLATE_ROOTS filter)
TEMPLATES_ROOT: str  # Main templates directory
PLUGIN_TEMPLATES: List[str]  # Plugin template directories

# Standard template files
"docker-compose.yml"  # Docker Compose configuration
"docker-compose.prod.yml"  # Production Docker Compose overrides  
"docker-compose.dev.yml"  # Development Docker Compose overrides
"k8s/"  # Kubernetes manifests directory
"local/"  # Local deployment files
"dev/"  # Development configuration files

Template Targets

Files generated in the environment directory.

# Standard targets (configurable via ENV_TEMPLATE_TARGETS filter)
("docker-compose.yml", "docker-compose.yml")  # Main compose file
("docker-compose.prod.yml", "docker-compose.prod.yml")  # Production overrides
("docker-compose.dev.yml", "docker-compose.dev.yml")  # Development overrides  
("k8s/", "k8s/")  # Kubernetes manifests
("local/", "local/")  # Local deployment files
("dev/", "dev/")  # Development files

Usage Examples

Basic Template Rendering

from tutor import env, config

# Load configuration
config_data = config.load("/path/to/tutor/root")

# Render a template file
content = env.render_file(config_data, "docker-compose.yml")

# Content is rendered for use by the deployment system
print(f"Rendered content length: {len(content)} chars")

Custom Template Processing

from tutor import env, config

config_data = config.load("/path/to/tutor/root")

# Render template string
template_str = "My platform: {{ PLATFORM_NAME }}"
result = env.render_str(config_data, template_str)

# Process nested templates
data = {
    "name": "{{ PLATFORM_NAME }}",
    "host": "{{ LMS_HOST }}",
    "nested": {
        "port": "{{ HTTP_PORT }}"
    }
}
processed = env.render_unknown(config_data, data)

Environment Directory Management

from tutor import env

root = "/path/to/tutor/root"

# Create environment directory
env_dir = env.create_env_dir(root)

# Get path to environment file
compose_path = env.get_env_path(root, "docker-compose.yml")

# Clean environment
env.clean_env_dir(root)

Working with Patches

from tutor import env, config, hooks

config_data = config.load("/path/to/tutor/root")

# Add custom patches via hooks
hooks.Filters.ENV_PATCHES.add_items([
    ("docker-compose.yml", "my-custom-patch"),
    ("k8s/ingress.yml", "ingress-customization"),
])

# Render template with patches applied
content = env.render_file(config_data, "docker-compose.yml")
# Patches are automatically applied during rendering

Custom Template Filters

from tutor import hooks

# Add custom Jinja2 filter
@hooks.Filters.ENV_TEMPLATE_FILTERS.add()
def add_custom_filters():
    def uppercase_filter(text):
        return text.upper()
    
    def format_url(host, protocol="https"):
        return f"{protocol}://{host}"
    
    return [
        ("uppercase", uppercase_filter),
        ("format_url", format_url),
    ]

# Use in templates:
# {{ PLATFORM_NAME | uppercase }}
# {{ LMS_HOST | format_url("http") }}

Install with Tessl CLI

npx tessl i tessl/pypi-tutor

docs

cli-commands.md

configuration.md

environment.md

hooks-plugins.md

index.md

task-execution.md

utilities.md

tile.json