CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-jsonargparse

Implement minimal boilerplate CLIs derived from type hints and parse from command line, config files and environment variables.

Pending
Overview
Eval results
Files

utilities.mddocs/

Utilities

Utility functions and classes for path handling, lazy instantiation, parser introspection, and advanced type support. These utilities provide foundational functionality used throughout jsonargparse and offer helpful tools for building sophisticated CLI applications.

Capabilities

Path Handling

Enhanced path class for robust file system path validation, resolution, and access control.

class Path:
    def __init__(self, path: Union[str, os.PathLike], mode: str = "fr"):
        """
        Create a Path object with validation and access control.
        
        Args:
            path: File system path (relative or absolute)
            mode: Access mode string (combinations of 'f'=file, 'd'=dir, 'r'=read, 'w'=write, 'x'=executable)
            
        Raises:
            TypeError: If path validation fails
        """
    
    def __str__(self) -> str:
        """
        Get string representation of the path.
        
        Returns:
            str: String path
        """
    
    @property
    def absolute(self) -> pathlib.Path:
        """
        Get absolute path as pathlib.Path object.
        
        Returns:
            pathlib.Path: Absolute path
        """
    
    def exists(self) -> bool:
        """
        Check if path exists.
        
        Returns:
            bool: True if path exists
        """
    
    def is_file(self) -> bool:
        """
        Check if path is a file.
        
        Returns:
            bool: True if path is a file
        """
    
    def is_dir(self) -> bool:
        """
        Check if path is a directory.
        
        Returns:
            bool: True if path is a directory
        """

Lazy Instantiation

Utility for creating lazy instances where class instantiation is delayed until first method call.

def lazy_instance(init_fn: Callable[[], Any]) -> Any:
    """
    Create a lazy instance that delays instantiation until first use.
    
    Args:
        init_fn: Function that returns the instance when called
        
    Returns:
        Any: Lazy proxy object that behaves like the target instance
    """

Parser Introspection

Utilities for capturing and introspecting ArgumentParser instances during execution.

def capture_parser() -> ArgumentParser:
    """
    Capture the ArgumentParser being used in the current execution context.
    
    Returns:
        ArgumentParser: The parser instance currently being used
        
    Raises:
        RuntimeError: If no parser is active in current context
    """

Dynamic Class Generation

Utilities for creating classes dynamically from functions and managing class introspection.

def class_from_function(function: Callable, *args, **kwargs) -> Type:
    """
    Create a dynamic class equivalent to calling a function.
    
    Args:
        function: Function to wrap as a class
        *args: Positional arguments for function
        **kwargs: Keyword arguments for function
        
    Returns:
        Type: Dynamic class that instantiates by calling the function
    """

def register_unresolvable_import_paths(*import_paths: str) -> None:
    """
    Register import paths for objects whose import path cannot be automatically resolved.
    
    Args:
        *import_paths: Import path strings to register
    """

Usage Examples

Path Validation and Access Control

from jsonargparse import ArgumentParser, Path

parser = ArgumentParser()

# Add path arguments with validation
parser.add_argument(
    "--input-file",
    type=Path(mode="fr"),  # Must exist, be a file, and be readable
    help="Input file path"
)

parser.add_argument(
    "--output-dir",
    type=Path(mode="dw"),  # Must be a directory and writable
    help="Output directory path"
)

parser.add_argument(
    "--script",
    type=Path(mode="fx"),  # Must be a file and executable
    help="Script to execute"
)

config = parser.parse_args()

# Paths are validated automatically
print(f"Input file: {config.input_file}")
print(f"Absolute path: {config.input_file.absolute}")
print(f"Exists: {config.input_file.exists()}")
print(f"Is file: {config.input_file.is_file()}")

# Use the paths
with open(config.input_file, 'r') as f:
    data = f.read()

Lazy Instance Creation

from jsonargparse import lazy_instance
import expensive_module

# Create lazy instance that delays expensive initialization
def create_model():
    print("Creating expensive model...")
    return expensive_module.LargeModel()

# Model is not created yet
lazy_model = lazy_instance(create_model)

print("Lazy model created")

# Model is created only when first accessed
result = lazy_model.predict(data)  # "Creating expensive model..." printed here
print(f"Prediction: {result}")

# Subsequent calls use the same instance
result2 = lazy_model.predict(more_data)  # No "Creating..." message

Parser Capture and Introspection

from jsonargparse import ArgumentParser, capture_parser

def setup_logging_args(enable_capture: bool = True):
    """Function that adds logging arguments to current parser."""
    if enable_capture:
        # Capture the current parser being used
        parser = capture_parser()
        
        # Add logging arguments to captured parser
        parser.add_argument("--log-level", 
                          choices=["DEBUG", "INFO", "WARNING", "ERROR"],
                          default="INFO")
        parser.add_argument("--log-file", type=str, help="Log file path")
        parser.add_argument("--quiet", action="store_true", help="Suppress output")
        
        print("Added logging arguments to parser")

# Create parser
parser = ArgumentParser()
parser.add_argument("--name", type=str, required=True)

# Add function arguments - this will capture the current parser
parser.add_function_arguments(setup_logging_args)

config = parser.parse_args()

print(f"Name: {config.name}")
print(f"Log level: {config.log_level}")
if config.log_file:
    print(f"Log file: {config.log_file}")

Dynamic Class Creation

from jsonargparse import class_from_function, ArgumentParser

def train_model(data_path: str, epochs: int = 100, learning_rate: float = 0.001):
    """Train a machine learning model."""
    print(f"Training model with data from {data_path}")
    print(f"Epochs: {epochs}, Learning rate: {learning_rate}")
    return {"status": "trained", "epochs": epochs}

# Create a class from the function
TrainingClass = class_from_function(train_model)

# Use the dynamic class with jsonargparse
parser = ArgumentParser()
parser.add_class_arguments(TrainingClass, "training")

config = parser.parse_args()

# Instantiate the dynamic class (calls the original function)
trainer = TrainingClass(**config.training.as_dict())
print(f"Training result: {trainer}")

Import Path Registration

from jsonargparse import register_unresolvable_import_paths
from some_complex_module import HardToResolveClass

# Register import paths for classes that can't be automatically resolved
register_unresolvable_import_paths(
    "some_complex_module.HardToResolveClass",
    "another_module.DynamicClass"
)

# Now these classes can be properly serialized and deserialized
# in configuration files and command line arguments

Advanced Path Usage

from jsonargparse import ArgumentParser, Path

parser = ArgumentParser()

# Different path modes for different use cases
parser.add_argument("--config", type=Path(mode="fr"))    # File, readable
parser.add_argument("--output", type=Path(mode="fw"))    # File, writable (may not exist)
parser.add_argument("--data-dir", type=Path(mode="dr"))  # Directory, readable
parser.add_argument("--temp-dir", type=Path(mode="dw"))  # Directory, writable
parser.add_argument("--script", type=Path(mode="frx"))   # File, readable, executable

try:
    config = parser.parse_args()
    
    # All paths are validated according to their modes
    print(f"Config file: {config.config}")
    print(f"Output will be written to: {config.output}")
    print(f"Data directory: {config.data_dir}")
    print(f"Script to run: {config.script}")
    
except Exception as e:
    print(f"Path validation failed: {e}")

Combining Utilities

from jsonargparse import ArgumentParser, Path, lazy_instance, capture_parser
import logging

def create_logger():
    """Create logger instance only when needed."""
    logger = logging.getLogger("myapp")
    logger.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    return logger

def setup_app_args():
    """Setup application-specific arguments."""
    parser = capture_parser()
    parser.add_argument("--debug", action="store_true")
    parser.add_argument("--workers", type=int, default=1)

class AppConfig:
    def __init__(self, 
                 input_file: Path(mode="fr"),
                 output_dir: Path(mode="dw"),
                 log_file: Path(mode="fw") = None):
        self.input_file = input_file
        self.output_dir = output_dir
        self.log_file = log_file
        
        # Create lazy logger
        self.logger = lazy_instance(create_logger)
    
    def process(self):
        self.logger.info(f"Processing {self.input_file}")
        self.logger.info(f"Output will go to {self.output_dir}")
        
        # Process files here
        print(f"Processing {self.input_file} -> {self.output_dir}")

parser = ArgumentParser()
parser.add_class_arguments(AppConfig, "config")
parser.add_function_arguments(setup_app_args)

args = parser.parse_args()

app = AppConfig(**args.config.as_dict())
app.process()

if args.debug:
    print("Debug mode enabled")
print(f"Using {args.workers} workers")

Path Mode Reference

Path validation modes:

  • "f" - Must be a file
  • "d" - Must be a directory
  • "r" - Must be readable
  • "w" - Must be writable
  • "x" - Must be executable
  • "c" - File can be created (parent directory must exist and be writable)
  • "u" - Path can be a URL

Common combinations:

  • "fr" - Existing readable file
  • "fw" - Writable file (may not exist yet)
  • "dr" - Existing readable directory
  • "dw" - Writable directory
  • "frx" - Executable file
  • "fc" - File that can be created

Install with Tessl CLI

npx tessl i tessl/pypi-jsonargparse

docs

advanced-actions.md

cli-creation.md

core-parser.md

index.md

namespace-management.md

settings.md

signature-arguments.md

types-validation.md

utilities.md

tile.json