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 todataclass()
📤 Output:
- Enhanced dataclass with additional utilities
🔧 Functionality:
Wraps Python's dataclass
to address key limitations:
- Automatic Type Annotation: Adds type annotations for members without explicit types
- Mutable Default Handling: Automatically handles mutable defaults using
field(default_factory=...)
- 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
✅ Recommended Usage
@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
fromdataclasses
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
- Type Annotation Addition:
_add_annotation_types()
processes inheritance and adds missing type hints - Mutable Field Processing:
_process_mutable_types()
converts mutable defaults to field factories - Post-Init Enhancement: Combines user-defined
__post_init__
with deep copy functionality - Method Injection: Adds utility methods (
to_dict
,from_dict
, etc.) - 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.