CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-invoke

Pythonic task execution library for managing shell-oriented subprocesses and organizing executable Python code into CLI-invokable tasks

Overall
score

96%

Overview
Eval results
Files

configuration.mddocs/

Configuration Management

Invoke provides a sophisticated multi-source configuration system that supports files, environment variables, command-line arguments, and Python dictionaries with hierarchical merging and attribute-style access.

Capabilities

Config Class

Main configuration management system with multi-source loading and hierarchical merging.

class Config:
    """
    Configuration management with multi-source loading and merging.
    
    Supports loading from:
    - Default values
    - System configuration files  
    - User configuration files
    - Project configuration files
    - Environment variables
    - Runtime overrides
    - Collection-specific configuration
    
    Attributes:
    - _defaults (dict): Default configuration values
    - _overrides (dict): Runtime override values  
    - _system (dict): System-level configuration
    - _user (dict): User-level configuration
    - _project (dict): Project-level configuration
    - _runtime (dict): Runtime configuration
    - _collection (dict): Collection-specific configuration
    - _env (dict): Environment variable configuration
    """
    
    def __init__(self, defaults=None, overrides=None, lazy=False, runtime_path=None, system_prefix=None, user_prefix=None, project_location=None, env_prefix=None, file_prefix=None):
        """
        Initialize Config object.
        
        Parameters:
        - defaults (dict, optional): Default configuration values
        - overrides (dict, optional): Runtime override values
        - lazy (bool): Whether to defer configuration loading
        - runtime_path (str, optional): Runtime configuration file path
        - system_prefix (str, optional): System config file prefix
        - user_prefix (str, optional): User config file prefix  
        - project_location (str, optional): Project root directory
        - env_prefix (str, optional): Environment variable prefix
        - file_prefix (str, optional): Configuration file prefix
        """
    
    @classmethod
    def global_defaults(cls):
        """
        Get global default configuration values.
        
        Returns:
        dict: Global default configuration
        """
    
    def load_defaults(self, merge=True):
        """
        Load default configuration values.
        
        Parameters:
        - merge (bool): Whether to merge with existing configuration
        
        Returns:
        Config: Self for method chaining
        """
    
    def load_overrides(self, merge=True):
        """
        Load runtime override configuration.
        
        Parameters:
        - merge (bool): Whether to merge with existing configuration
        
        Returns:
        Config: Self for method chaining
        """
    
    def load_system(self, merge=True):
        """
        Load system-level configuration files.
        
        Parameters:
        - merge (bool): Whether to merge with existing configuration
        
        Returns:
        Config: Self for method chaining
        """
    
    def load_user(self, merge=True):
        """
        Load user-level configuration files.
        
        Parameters:
        - merge (bool): Whether to merge with existing configuration
        
        Returns:
        Config: Self for method chaining
        """
    
    def load_project(self, merge=True):
        """
        Load project-level configuration files.
        
        Parameters:
        - merge (bool): Whether to merge with existing configuration
        
        Returns:
        Config: Self for method chaining
        """
    
    def load_runtime(self, merge=True):
        """
        Load runtime configuration file.
        
        Parameters:
        - merge (bool): Whether to merge with existing configuration
        
        Returns:
        Config: Self for method chaining
        """
    
    def load_shell_env(self, merge=True):
        """
        Load configuration from environment variables.
        
        Parameters:
        - merge (bool): Whether to merge with existing configuration
        
        Returns:
        Config: Self for method chaining
        """
    
    def load_collection(self, collection, merge=True):
        """
        Load collection-specific configuration.
        
        Parameters:
        - collection (Collection): Task collection
        - merge (bool): Whether to merge with existing configuration
        
        Returns:
        Config: Self for method chaining
        """
    
    def set_project_location(self, path):
        """
        Set project root directory for configuration files.
        
        Parameters:
        - path (str): Project root directory path
        """
    
    def set_runtime_path(self, path):
        """
        Set runtime configuration file path.
        
        Parameters:
        - path (str): Runtime configuration file path
        """
    
    def merge(self, *dicts):
        """
        Merge configuration dictionaries hierarchically.
        
        Parameters:
        - *dicts: Configuration dictionaries to merge
        
        Returns:
        Config: New merged configuration
        """
    
    def clone(self, into=None):
        """
        Create a copy of this configuration.
        
        Parameters:
        - into (type, optional): Class to clone into
        
        Returns:
        Config: Cloned configuration object
        """

DataProxy Class

Base class providing nested dictionary access with attribute-style syntax.

class DataProxy:
    """
    Nested dictionary with attribute-style access.
    
    Provides both dict-style (obj['key']) and attribute-style (obj.key) 
    access to nested configuration data.
    """
    
    @classmethod
    def from_data(cls, data):
        """
        Create DataProxy from dictionary data.
        
        Parameters:
        - data (dict): Dictionary data to wrap
        
        Returns:
        DataProxy: Proxy object for the data
        """
    
    def __getitem__(self, key):
        """Get item using dict-style access."""
    
    def __setitem__(self, key, value):
        """Set item using dict-style access."""
    
    def __delitem__(self, key):
        """Delete item using dict-style access."""
    
    def __contains__(self, key):
        """Test membership using 'in' operator."""
    
    def __iter__(self):
        """Iterate over keys."""
    
    def __len__(self):
        """Get number of top-level keys."""
    
    def __getattr__(self, key):
        """Get item using attribute-style access."""
    
    def __setattr__(self, key, value):
        """Set item using attribute-style access."""
    
    def get(self, key, default=None):
        """Get item with default value."""
    
    def pop(self, key, *args):
        """Remove and return item."""
    
    def popitem(self):
        """Remove and return arbitrary item."""
    
    def clear(self):
        """Remove all items."""
    
    def update(self, other):
        """Update with items from another mapping."""
    
    def keys(self):
        """Get view of keys."""
    
    def values(self):
        """Get view of values."""
    
    def items(self):
        """Get view of key-value pairs."""

Configuration Utility Functions

Helper functions for configuration manipulation.

def merge_dicts(base, updates):
    """
    Recursively merge configuration dictionaries.
    
    Parameters:
    - base (dict): Base configuration dictionary
    - updates (dict): Updates to apply
    
    Returns:
    dict: Merged configuration dictionary
    """

def copy_dict(source):
    """
    Deep copy a configuration dictionary.
    
    Parameters:
    - source (dict): Dictionary to copy
    
    Returns:
    dict: Deep copy of source dictionary
    """

def excise(dict_, keypath):
    """
    Remove nested key from dictionary.
    
    Parameters:
    - dict_ (dict): Dictionary to modify
    - keypath (str): Dot-separated key path (e.g., 'section.subsection.key')
    
    Returns:
    any: Removed value
    """

def obliterate(base, deletions):
    """
    Remove multiple nested keys from dictionary.
    
    Parameters:
    - base (dict): Dictionary to modify
    - deletions (list): List of dot-separated key paths to remove
    
    Returns:
    dict: Modified dictionary
    """

Usage Examples

Basic Configuration Usage

from invoke import Config

# Create configuration with defaults
config = Config({
    'run': {
        'echo': True,
        'pty': False
    },
    'sudo': {
        'password': None
    }
})

# Access configuration values
print(config.run.echo)  # True
print(config['run']['pty'])  # False

# Modify configuration
config.run.timeout = 30
config['sudo']['password'] = 'secret'

Multi-source Configuration Loading

from invoke import Config

# Load from all default sources
config = Config()
config.load_defaults()
config.load_system()       # /etc/invoke.yaml
config.load_user()         # ~/.invoke.yaml  
config.load_project()      # ./invoke.yaml
config.load_shell_env()    # Environment variables

# Check final configuration
print(f"Echo enabled: {config.run.echo}")

Configuration Files

Create configuration files in YAML or JSON format:

invoke.yaml:

run:
  echo: true
  pty: false
  warn: false
  
sudo:
  password: null
  prompt_for_password: true
  
tasks:
  auto_dash_names: true
  collection_name: 'tasks'

invoke.json:

{
  "run": {
    "echo": true,
    "pty": false,
    "shell": "/bin/bash"
  },
  "sudo": {
    "password": null
  }
}

Environment Variable Configuration

import os
from invoke import Config

# Set environment variables (prefix with INVOKE_)
os.environ['INVOKE_RUN_ECHO'] = 'false'
os.environ['INVOKE_RUN_PTY'] = 'true'
os.environ['INVOKE_SUDO_PASSWORD'] = 'mypassword'

# Load configuration including environment
config = Config()
config.load_defaults()
config.load_shell_env()

print(config.run.echo)  # False (from env var)
print(config.run.pty)   # True (from env var)

Configuration Merging and Cloning

from invoke import Config, merge_dicts

# Base configuration
base_config = Config({
    'run': {'echo': True, 'pty': False},
    'sudo': {'password': None}
})

# Override configuration
overrides = {
    'run': {'pty': True, 'timeout': 30},
    'new_section': {'enabled': True}
}

# Merge configurations
merged = base_config.merge(overrides)
print(merged.run.echo)     # True (from base)
print(merged.run.pty)      # True (from override)
print(merged.run.timeout)  # 30 (from override)

# Clone configuration
cloned = base_config.clone()
cloned.run.echo = False
print(base_config.run.echo)  # True (original unchanged)
print(cloned.run.echo)       # False (clone modified)

Context Integration

from invoke import Context, Config

# Create custom configuration
config = Config({
    'run': {
        'echo': True,
        'pty': True,
        'shell': '/bin/zsh'
    }
})

# Use with context
ctx = Context(config=config)
result = ctx.run("echo 'Hello World'")  # Uses custom config

Task-specific Configuration

from invoke import task, Context

@task
def deploy(ctx, env='staging'):
    """Deploy with environment-specific configuration."""
    
    # Access configuration for current environment
    db_host = ctx.config.environments[env].database.host
    api_key = ctx.config.environments[env].api_key
    
    ctx.run(f"deploy.sh --host {db_host} --key {api_key}")

# Configuration file (invoke.yaml):
# environments:
#   staging:
#     database:
#       host: staging-db.example.com  
#     api_key: staging-key
#   production:
#     database:
#       host: prod-db.example.com
#     api_key: prod-key

Configuration Validation

from invoke import Config
from invoke.exceptions import UncastableEnvVar, AmbiguousEnvVar

try:
    config = Config()
    config.load_shell_env()
except UncastableEnvVar as e:
    print(f"Invalid environment variable: {e}")
except AmbiguousEnvVar as e:
    print(f"Ambiguous environment variable: {e}")

Install with Tessl CLI

npx tessl i tessl/pypi-invoke

docs

cli-parsing.md

collections.md

configuration.md

index.md

subprocess-runners.md

task-execution.md

watchers.md

tile.json