CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-hatch

Modern, extensible Python project management tool with comprehensive environment and build system support

Pending
Overview
Eval results
Files

environment-management.mddocs/

Environment Management

Environment plugin system for creating, managing, and executing commands in isolated Python environments. Supports virtual environments, Docker containers, and custom environment types through plugins.

Capabilities

Environment Interface

Base interface for all environment plugins providing standardized operations for environment lifecycle management.

class EnvironmentInterface:
    """
    Base interface for environment plugins.
    
    All environment plugins must inherit from this class and implement
    the abstract methods to provide environment management capabilities.
    """
    
    PLUGIN_NAME: str = ''  # Must be set by plugin implementations
    
    def __init__(self, root, metadata, name, config, matrix_variables, data_directory, platform, verbosity, app):
        """
        Initialize environment interface.
        
        Args:
            root: Project root directory
            metadata: Project metadata
            name (str): Environment name
            config (dict): Environment configuration
            matrix_variables (dict): Matrix variables for environment
            data_directory: Directory for environment data
            platform: Platform utilities
            verbosity (int): Verbosity level
            app: Application instance
        """
    
    @property
    def root(self):
        """Project root directory."""
    
    @property
    def metadata(self):
        """Project metadata."""
    
    @property
    def name(self) -> str:
        """Environment name."""
    
    @property
    def config(self) -> dict:
        """Environment configuration."""
    
    @property
    def matrix_variables(self) -> dict:
        """Matrix variables for this environment."""
    
    @property
    def data_directory(self):
        """Directory for environment data storage."""
    
    @property
    def platform(self):
        """Platform utilities for command execution."""
    
    @property
    def app(self):
        """Application instance."""
    
    @property
    def env_vars(self) -> dict:
        """
        Environment variables for this environment.
        
        Returns:
            Dict of environment variables to set during execution
        """
    
    @property
    def dependencies(self) -> list:
        """
        List of dependencies for this environment.
        
        Returns:
            List of dependency specifications
        """
    
    @property
    def features(self) -> list[str]:
        """
        List of features enabled for this environment.
        
        Returns:
            List of feature names
        """
    
    @property
    def scripts(self) -> dict[str, str]:
        """
        Scripts defined for this environment.
        
        Returns:
            Dict mapping script names to commands
        """
    
    def exists(self) -> bool:
        """
        Check if environment exists.
        
        Returns:
            True if environment exists and is ready for use
        """
    
    def create(self) -> None:
        """
        Create the environment.
        
        This should create all necessary resources for the environment
        including installing base dependencies.
        """
    
    def remove(self) -> None:
        """
        Remove the environment.
        
        This should clean up all resources associated with the environment.
        """
    
    def install_project(self) -> None:
        """
        Install the project in the environment.
        
        This should install the project package in the environment
        without development mode.
        """
    
    def install_project_dev_mode(self) -> None:
        """
        Install the project in development mode.
        
        This should install the project package in editable/development mode
        so changes to source code are immediately reflected.
        """
    
    def dependencies_in_sync(self) -> bool:
        """
        Check if dependencies are synchronized with configuration.
        
        Returns:
            True if installed dependencies match configuration
        """
    
    def sync_dependencies(self) -> None:
        """
        Synchronize dependencies with configuration.
        
        This should install, upgrade, or remove dependencies to match
        the current environment configuration.
        """
    
    def run_command(
        self,
        command: list[str],
        *,
        shell: bool = False,
        env_vars: dict | None = None,
        capture_output: bool = False
    ):
        """
        Run command in the environment.
        
        Args:
            command (list[str]): Command and arguments to execute
            shell (bool): Whether to use shell execution
            env_vars (dict, optional): Additional environment variables
            capture_output (bool): Whether to capture command output
            
        Returns:
            Command execution result
        """
    
    def enter_shell(self, name: str, path: str, args: list[str]):
        """
        Enter interactive shell in the environment.
        
        Args:
            name (str): Shell name
            path (str): Shell executable path
            args (list[str]): Shell arguments
        """
    
    def build_environment(self, targets: list[str], env_vars: dict):
        """
        Build artifacts in the environment.
        
        Args:
            targets (list[str]): Build targets
            env_vars (dict): Environment variables for build
        """
    
    def get_build_process(self, build_environment, **kwargs):
        """
        Get build process for this environment.
        
        Args:
            build_environment: Build environment configuration
            **kwargs: Additional build arguments
            
        Returns:
            Build process instance
        """

Virtual Environment Plugin

Built-in virtual environment plugin providing standard Python virtual environment support.

class VirtualEnvironment(EnvironmentInterface):
    """
    Virtual environment plugin using Python's venv module.
    
    Provides isolated Python environments with dependency management
    and project installation support.
    """
    
    PLUGIN_NAME = 'virtual'
    
    @property
    def python_info(self) -> dict:
        """Information about Python installation in environment."""
    
    @property
    def python_path(self) -> str:
        """Path to Python executable in environment."""
    
    @property
    def site_packages_path(self) -> str:
        """Path to site-packages directory in environment."""
    
    @property
    def scripts_path(self) -> str:
        """Path to scripts/bin directory in environment."""
    
    def activate_environment(self) -> dict[str, str]:
        """
        Get environment variables for activating virtual environment.
        
        Returns:
            Dict of environment variables to set for activation
        """
    
    def deactivate_environment(self) -> dict[str, str]:
        """
        Get environment variables for deactivating virtual environment.
        
        Returns:
            Dict of environment variables to unset for deactivation
        """
    
    def install_packages(self, packages: list[str], *, dev: bool = False) -> None:
        """
        Install packages in the virtual environment.
        
        Args:
            packages (list[str]): Package specifications to install
            dev (bool): Whether to install development dependencies
        """
    
    def uninstall_packages(self, packages: list[str]) -> None:
        """
        Uninstall packages from the virtual environment.
        
        Args:
            packages (list[str]): Package names to uninstall
        """
    
    def list_packages(self) -> list[str]:
        """
        List installed packages in the environment.
        
        Returns:
            List of installed package specifications
        """

Environment Configuration

Configuration system for defining environments including dependencies, scripts, environment variables, and plugin settings.

class EnvironmentConfig:
    """Configuration for a single environment."""
    
    @property
    def type(self) -> str:
        """Environment type/plugin name."""
    
    @property
    def dependencies(self) -> list[str]:
        """List of dependencies for this environment."""
    
    @property
    def extra_dependencies(self) -> list[str]:
        """Extra dependencies beyond project dependencies."""
    
    @property
    def features(self) -> list[str]:
        """Project features to install."""
    
    @property
    def dev_mode(self) -> bool:
        """Whether to install project in development mode."""
    
    @property
    def skip_install(self) -> bool:
        """Whether to skip project installation."""
    
    @property
    def python(self) -> str:
        """Python version or path for this environment."""
    
    @property
    def matrix(self) -> dict:
        """Matrix variables for environment variants."""
    
    @property
    def env_vars(self) -> dict[str, str]:
        """Environment variables to set."""
    
    @property
    def env_include(self) -> list[str]:
        """Environment variables to include from host."""
    
    @property
    def env_exclude(self) -> list[str]:
        """Environment variables to exclude."""
    
    @property
    def scripts(self) -> dict[str, str]:
        """Scripts defined for this environment."""
    
    @property
    def pre_install_commands(self) -> list[str]:
        """Commands to run before installing dependencies."""
    
    @property
    def post_install_commands(self) -> list[str]:
        """Commands to run after installing dependencies."""
    
    @property
    def template(self) -> str:
        """Template environment to inherit from."""

Environment Discovery

Utilities for discovering, validating, and collecting environment configurations from various sources.

def discover_environments(project) -> dict[str, EnvironmentConfig]:
    """
    Discover environment configurations from project.
    
    Args:
        project: Project instance
        
    Returns:
        Dict mapping environment names to configurations
    """

def validate_environment_config(config: dict) -> list[str]:
    """
    Validate environment configuration.
    
    Args:
        config (dict): Environment configuration to validate
        
    Returns:
        List of validation errors (empty if valid)
    """

def resolve_environment_dependencies(
    base_dependencies: list[str],
    env_config: EnvironmentConfig,
    features: list[str]
) -> list[str]:
    """
    Resolve final dependency list for environment.
    
    Args:
        base_dependencies (list[str]): Project base dependencies
        env_config (EnvironmentConfig): Environment configuration
        features (list[str]): Enabled features
        
    Returns:
        Final list of dependencies to install
    """

def expand_environment_matrix(
    env_config: EnvironmentConfig
) -> list[tuple[str, dict]]:
    """
    Expand environment matrix into individual configurations.
    
    Args:
        env_config (EnvironmentConfig): Environment with matrix
        
    Returns:
        List of (environment_name, matrix_variables) tuples
    """

Environment Operations

High-level operations for managing environments including creation, synchronization, cleanup, and status reporting.

def create_environment(app, env_name: str) -> None:
    """
    Create named environment.
    
    Args:
        app: Application instance
        env_name (str): Environment name to create
    """

def remove_environment(app, env_name: str) -> None:
    """
    Remove named environment.
    
    Args:
        app: Application instance
        env_name (str): Environment name to remove
    """

def sync_environment(app, env_name: str) -> None:
    """
    Synchronize environment dependencies.
    
    Args:
        app: Application instance
        env_name (str): Environment name to synchronize
    """

def prune_environments(app) -> list[str]:
    """
    Remove unused environments.
    
    Args:
        app: Application instance
        
    Returns:
        List of removed environment names
    """

def show_environment_info(app, env_name: str) -> dict:
    """
    Get environment information.
    
    Args:
        app: Application instance
        env_name (str): Environment name
        
    Returns:
        Dict with environment information
    """

def find_environment_path(app, env_name: str) -> str | None:
    """
    Find path to environment directory.
    
    Args:
        app: Application instance
        env_name (str): Environment name
        
    Returns:
        Path to environment or None if not found
    """

Usage Examples

Creating and Using Environments

from hatch.cli.application import Application
from hatch.env.plugin.interface import EnvironmentInterface

app = Application(lambda code: exit(code))

# Get environment interface
env = app.get_environment("test")

# Create environment if it doesn't exist
if not env.exists():
    print("Creating test environment...")
    env.create()

# Install project in development mode
env.install_project_dev_mode()

# Synchronize dependencies
if not env.dependencies_in_sync():
    print("Synchronizing dependencies...")
    env.sync_dependencies()

# Run command in environment
result = env.run_command(
    ["python", "-m", "pytest", "tests/"],
    capture_output=True
)
print(f"Test result: {result.returncode}")

Environment Configuration

from hatch.env import discover_environments

# Discover environments from project
project = app.project
environments = discover_environments(project)

# Access environment configuration
test_env_config = environments.get("test")
if test_env_config:
    print(f"Test dependencies: {test_env_config.dependencies}")
    print(f"Test scripts: {test_env_config.scripts}")
    print(f"Python version: {test_env_config.python}")

# Validate configuration
errors = validate_environment_config(test_env_config.__dict__)
if errors:
    print(f"Configuration errors: {errors}")

Custom Environment Plugin

from hatch.env.plugin.interface import EnvironmentInterface

class DockerEnvironment(EnvironmentInterface):
    """Custom Docker-based environment plugin."""
    
    PLUGIN_NAME = 'docker'
    
    def exists(self) -> bool:
        # Check if Docker container exists
        result = self.platform.run_command([
            'docker', 'inspect', self.container_name
        ], capture_output=True)
        return result.returncode == 0
    
    def create(self) -> None:
        # Create Docker container
        self.platform.run_command([
            'docker', 'create',
            '--name', self.container_name,
            '--volume', f'{self.root}:/workspace',
            self.config.get('image', 'python:3.11'),
            'sleep', 'infinity'
        ])
        
        # Start container
        self.platform.run_command([
            'docker', 'start', self.container_name
        ])
    
    def remove(self) -> None:
        # Remove Docker container
        self.platform.run_command([
            'docker', 'rm', '-f', self.container_name
        ])
    
    @property
    def container_name(self) -> str:
        return f'hatch-{self.name}-{self.root.name}'
    
    def run_command(self, command: list[str], **kwargs):
        # Execute command in Docker container
        docker_cmd = [
            'docker', 'exec',
            '-w', '/workspace',
            self.container_name
        ] + command
        
        return self.platform.run_command(docker_cmd, **kwargs)

Environment Matrix

from hatch.env import expand_environment_matrix

# Environment configuration with matrix
config = EnvironmentConfig({
    'matrix': {
        'python': ['3.9', '3.10', '3.11'],
        'django': ['3.2', '4.0', '4.1']
    },
    'dependencies': [
        'django=={matrix:django}'
    ]
})

# Expand matrix into individual environments
environments = expand_environment_matrix(config)

for env_name, matrix_vars in environments:
    print(f"Environment: {env_name}")
    print(f"Variables: {matrix_vars}")
    # Result: test-py3.9-django3.2, test-py3.10-django4.0, etc.

Install with Tessl CLI

npx tessl i tessl/pypi-hatch

docs

application.md

cli-commands.md

configuration.md

environment-management.md

index.md

plugin-system.md

project-management.md

python-management.md

tile.json