跳到主要内容

config_class

This module provides an enhanced wrapper around Python's dataclasses functionality, originally developed by the Isaac Lab Project. It addresses common limitations of standard dataclasses for configuration management in robotics applications.

📚 Dependencies

This module requires the following Python packages:

  • dataclasses (standard library)
  • inspect (standard library)
  • types (standard library)
  • copy (standard library)
  • typing (standard library)
  • re (standard library)
  • importlib (standard library)
  • ast (standard library)

🏗️ Core Functionality

🎯 Source Attribution

Original Source: Isaac Lab Project
License: BSD-3-Clause
Copyright: 2022-2024, The Isaac Lab Project Developers

This implementation is adapted from Isaac Lab's configuration system to provide robust dataclass functionality for the GBC framework.


🔧 Main Decorator

📝 configclass

Module Name: GBC.utils.base.config_class.configclass

Definition:

@__dataclass_transform__()
def configclass(cls, **kwargs)

📥 Input:

  • cls: The class to wrap around
  • **kwargs: Additional arguments passed to dataclass()

📤 Output:

  • Enhanced dataclass with additional utilities

🔧 Functionality: Wraps Python's dataclass to address key limitations:

  1. Automatic Type Annotation: Adds type annotations for members without explicit types
  2. Mutable Default Handling: Automatically handles mutable defaults using field(default_factory=...)
  3. Enhanced Utilities: Adds helper methods for dictionary conversion, copying, and validation

💡 Example Usage:

from dataclasses import MISSING
from GBC.utils.base.config_class import configclass

@configclass
class ViewerCfg:
eye: list = [7.5, 7.5, 7.5] # No explicit type needed
lookat: list = [0.0, 0.0, 0.0] # Mutable defaults handled automatically

@configclass
class EnvCfg:
num_envs: int = MISSING # Required field
episode_length: int = 2000
viewer: ViewerCfg = ViewerCfg()

# Usage
env_cfg = EnvCfg(num_envs=24)
print(env_cfg.to_dict()) # Convert to dictionary
env_cfg_copy = env_cfg.copy() # Create deep copy
env_cfg_new = env_cfg.replace(num_envs=32) # Replace fields

🛠️ Enhanced Methods

The configclass decorator automatically adds the following methods to decorated classes:

📋 to_dict()

Converts the configuration object to a nested dictionary recursively

📥 from_dict()

Updates the configuration object from a dictionary with type validation

🔄 replace()

Creates a new instance with specified fields replaced (useful for frozen classes)

📄 copy()

Creates a deep copy of the configuration object

✅ validate()

Validates the configuration object for missing required fields


🔧 Utility Functions

🔗 callable_to_string / string_to_callable

Functionality: Converts callable objects (functions, lambdas) to/from string representations for serialization support.

🔍 is_lambda_expression

Functionality: Detects if a string represents a lambda expression using AST parsing.


🎯 Key Features

✨ Automatic Type Inference

  • Deduces types from default values when type annotations are missing
  • Handles inheritance properly across configuration hierarchies

🔒 Mutable Default Safety

  • Automatically wraps mutable defaults with field(default_factory=...)
  • Prevents shared reference issues between class instances

📊 Dictionary Integration

  • Seamless conversion between configuration objects and dictionaries
  • Type-safe updates from dictionary data with validation

🛡️ Validation System

  • Detects missing required fields (marked with MISSING)
  • Provides clear error messages for configuration issues

🧬 Deep Copy Support

  • Automatic deep copying of mutable members to prevent reference sharing
  • Custom __post_init__ integration

💡 Best Practices

@configclass
class RobotCfg:
# Required fields - use MISSING
robot_name: str = MISSING

# Optional fields with defaults
max_speed: float = 1.0
joint_limits: list = [-3.14, 3.14] # Automatically handled as mutable

# Nested configurations
control: ControlCfg = ControlCfg()

# Validation
try:
config = RobotCfg() # Will raise error for missing robot_name
config.validate()
except TypeError as e:
print("Missing required fields:", e)

# Safe updates from dictionary
config_dict = {"robot_name": "h1", "max_speed": 2.0}
config.from_dict(config_dict)

⚠️ Important Notes

  • Use MISSING from dataclasses for required fields without defaults
  • The decorator handles mutable defaults automatically - no need for manual field() usage
  • All enhanced methods are added at runtime and available on decorated classes
  • Supports complex nested configurations with proper type validation

🔍 Implementation Details

🏗️ Processing Pipeline

  1. Type Annotation Addition: _add_annotation_types() processes inheritance and adds missing type hints
  2. Mutable Field Processing: _process_mutable_types() converts mutable defaults to field factories
  3. Post-Init Enhancement: Combines user-defined __post_init__ with deep copy functionality
  4. Method Injection: Adds utility methods (to_dict, from_dict, etc.)
  5. Dataclass Wrapping: Applies standard @dataclass decorator with enhancements

🧠 Smart Features

  • Inheritance Aware: Properly handles configuration class inheritance
  • Callable Serialization: Supports function/lambda serialization for complete configurability
  • Cross-Platform: Handles path separators and module imports across platforms
  • Performance Optimized: Minimal runtime overhead with efficient deep copying

🚨 Error Handling

The module provides comprehensive error handling for common configuration issues:

  • Missing Type Annotations: Clear errors when types cannot be inferred
  • Dictionary Validation: Type checking during from_dict() operations
  • Missing Required Fields: Validation errors with field paths
  • Callable Resolution: Detailed errors for invalid function string formats

This enhanced configuration system provides a robust foundation for managing complex robotics configurations while maintaining the simplicity and performance of Python dataclasses.