Skip to content

Commit 90f00fe

Browse files
committed
Enhance TDLogger and Test Infrastructure
- Consolidated TDLogger functionality with new helper functions: - Added `contains_important_message()` to identify critical log messages - Implemented `is_setup_or_init()` for better message filtering - Created centralized message filtering and formatting utilities - Improved test framework with standardized logging and capture: - Created `common/` directory for shared test utilities - Implemented `PrefixedTestCase` for consistent test logging - Added `log_diff.py` for log capture and verification - Enhanced test organization and discoverability - Refactored test modules to use new infrastructure: - Updated test files to use `common/test_utils.py` and `common/log_diff.py` - Simplified log capture and comparison logic - Improved error handling and test output formatting - Removed deprecated and unused test files - Cleaned up redundant test utilities - Standardized test module structure - Version bump to 0.0.4 to reflect significant improvements in logging and testing
1 parent d561201 commit 90f00fe

36 files changed

+1341
-1117
lines changed

CHANGELOG.md

+36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,41 @@
11
# CHANGELOG
22

3+
## 2025-03-10 - 0.0.4
4+
5+
### TDLogger Improvements
6+
- **Consolidated Duplicate Code**
7+
- Added new helper functions to centralize common operations:
8+
- `contains_important_message()` - Checks if a message contains important patterns that should always be logged
9+
- `is_setup_or_init()` - Identifies setup and initialization functions for better filtering
10+
- `format_message()` - Centralizes message formatting for consistency
11+
- Reorganized code structure for better clarity and maintainability
12+
13+
- **Optimized Message Filtering Logic**
14+
- Improved the `should_skip_message()` function with clearer, more declarative logic
15+
- Created constant `IMPORTANT_MESSAGE_PATTERNS` to centralize patterns that should always be logged
16+
- Enhanced filtering to ensure critical messages are never skipped
17+
- Simplified complex conditional logic for better readability and maintainability
18+
19+
- **Improved Error Handling**
20+
- Added robust try/except blocks in `log_message()` to catch and handle exceptions
21+
- Added error reporting that directs error messages to stderr for easy debugging
22+
- Ensured exceptions in the logger won't propagate to the main application
23+
- Fixed edge cases that could cause unexpected behavior during logging
24+
25+
- **Test Framework Enhancements**
26+
- Improved `PrefixedTestCase` class with clear separation between test messages and TDLogger output
27+
- Fixed formatting inconsistencies in the test output for better readability
28+
- Updated expected output files to reflect new logger behavior
29+
- Enhanced error handling in test utilities
30+
31+
### Test Infrastructure Improvements
32+
- **Created Common Test Utilities Directory**
33+
- Added `tests/common/` directory to house shared test infrastructure
34+
- Implemented `test_utils.py` with the `PrefixedTestCase` class providing standardized logging capabilities
35+
- Moved `log_diff.py` to common location for reuse across all test modules
36+
- Standardized test setup and teardown procedures across all tests
37+
- Improved test discoverability and organization
38+
339
## 2025-03-08 - 0.0.3
440

541
### Logger Improvements

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ TorchDevice is a Python library that enables transparent code portability betwee
2020
- [Limitations](#limitations)
2121
- [Recent Updates](#recent-updates)
2222
- [March 2025 Updates](#march-2025-updates)
23+
- [Improved Logging System](#improved-logging-system)
2324
- [Stream and Event Handling](#stream-and-event-handling)
2425
- [PyTorch Compatibility](#pytorch-compatibility)
2526
- [Code Quality](#code-quality)
@@ -194,6 +195,22 @@ Ensure these scripts are updated with any changes you made to `TorchDevice.py`.
194195

195196
The TorchDevice library has undergone significant improvements to ensure seamless compatibility between CUDA and MPS devices:
196197

198+
#### Improved Logging System
199+
200+
- **TDLogger Module Enhancements**:
201+
- Consolidated duplicate code with dedicated helper functions for message filtering and formatting
202+
- Optimized message filtering logic with declarative pattern matching
203+
- Improved error handling with robust exception capture
204+
- Enhanced memory management using fixed-size collections for logging history
205+
- Centralized important message patterns for consistent filtering
206+
207+
- **Test Framework Improvements**:
208+
- Created standardized test infrastructure in the `common` directory
209+
- Implemented `PrefixedTestCase` class for consistent test behavior and logging
210+
- Added dedicated utilities for log capture and verification
211+
- Improved log message formatting and separation between test output and redirected messages
212+
- Enhanced test organization and discoverability
213+
197214
#### Stream and Event Handling
198215

199216
- **Enhanced Stream Support**: Implemented comprehensive CUDA stream functionality on MPS devices, including:

TODO.md

+82-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,41 @@
11
# TorchDevice Project TODO List
22

3+
## TorchDevice.py Refactoring
4+
5+
- **Modularize TorchDevice Core Functions**
6+
- Split the large single-file implementation into logical modules:
7+
- Core device detection and management
8+
- CUDA function mocking
9+
- Stream and Event handling
10+
- Tensor operations interception
11+
- PyTorch integration utilities
12+
- Create proper module structure with appropriate imports
13+
- Ensure backward compatibility during transition
14+
15+
- **Fix Type Annotations and Linter Errors**
16+
- Address all the linter errors in TorchDevice.py
17+
- Add proper type annotations throughout the codebase
18+
- Fix compatibility with static type checkers
19+
- Maintain dynamic behavior while improving static analysis
20+
21+
- **Implement CPU Override Functionality**
22+
- Add mechanism to respect explicit CPU device requests
23+
- Create policy for when to override vs. when to respect explicit device choices
24+
- Add configuration option to control redirection behavior
25+
- Update documenation to explain the new behavior
26+
27+
- **Improve Class Structure**
28+
- Review inheritance patterns for Stream and Event classes
29+
- Ensure proper inheritance from PyTorch base classes
30+
- Consolidate duplicate code in device handling
31+
- Improve encapsulation of internal state
32+
33+
- **Enhance Error Handling**
34+
- Add more robust error handling for device operations
35+
- Provide clearer error messages for device compatibility issues
36+
- Add fallback mechanisms for unsupported operations
37+
- Improve debugging information during redirection failures
38+
339
## Logger Improvements
440

541
- **Simplify the Frame Inspection Logic**
@@ -15,4 +51,49 @@
1551
- **Use Context Managers for Temporary State**
1652
- Identify operations that temporarily modify state
1753
- Implement context managers for these operations
18-
- Ensure proper cleanup even in case of exceptions
54+
- Ensure proper cleanup even in case of exceptions
55+
56+
- **Implement Lazy Formatting for Log Messages**
57+
- Identify places where f-strings are used for messages that might be filtered out
58+
- Replace these with format strings that are only evaluated if the message will be logged
59+
- Verify that the changes don't affect the log output
60+
- Measure the performance impact of the change
61+
62+
- **Remove Unused Features and Code**
63+
- Identify unused code or overly complex sections
64+
- Simplify or remove these sections
65+
- Verify that the changes don't affect the functionality
66+
67+
## Device Handling Improvements
68+
69+
- **Respect Explicit CPU Device Specifications**
70+
- Modify TorchDevice to respect explicit CPU device requests
71+
- Fix failing tests in test_cpu_mps_operations.py due to device redirection
72+
- Ensure proper handling of operations involving both CPU and accelerated devices
73+
- Add test cases for explicit CPU operations
74+
75+
## Test Framework Improvements
76+
77+
- **Refine Test Utilities into Proper Modules**
78+
- Resolve import issues with common.log_diff and common.test_utils
79+
- Restructure as proper Python modules with __init__.py files
80+
- Update import paths in all test files
81+
- Add proper documentation for all test utility functions
82+
83+
- **Enhance Test Discoverability**
84+
- Improve test organization for better discoverability
85+
- Add test categorization (e.g., unit tests, integration tests)
86+
- Create a more flexible test runner with better filtering options
87+
88+
## Documentation
89+
90+
- **Create Developer Documentation**
91+
- Document the architecture and design decisions
92+
- Add detailed explanations of key components
93+
- Provide examples for common development tasks
94+
- Include troubleshooting guides for common issues
95+
96+
- **Improve API Documentation**
97+
- Document all public interfaces
98+
- Add examples for all major features
99+
- Include type annotations for better IDE support

TorchDevice/TorchDevice.py

+14-11
Original file line numberDiff line numberDiff line change
@@ -67,31 +67,32 @@ def tensor_to_replacement(self, *args, **kwargs):
6767
(hasattr(candidate, '__module__') and candidate.__module__ != 'torch')
6868
):
6969
device_arg = candidate
70+
# Replace args with default device if requested device not available
71+
if isinstance(candidate, str) and candidate != default_device:
72+
args = (default_device,) + args[1:]
73+
elif isinstance(candidate, _ORIGINAL_TORCH_DEVICE_TYPE) and candidate.type != default_device:
74+
args = (default_device,) + args[1:]
7075
elif 'device' in kwargs:
7176
device_arg = kwargs['device']
7277

7378
# Handle device redirection in kwargs
7479
if isinstance(device_arg, str):
7580
device_type = device_arg.split(':')[0] if ':' in device_arg else device_arg
76-
redirected_type = TorchDevice._redirect_device_type(device_type)
77-
78-
if redirected_type != device_type:
81+
if device_type != default_device:
7982
if ':' in device_arg:
8083
index = device_arg.split(':')[1]
81-
kwargs['device'] = f"{redirected_type}:{index}"
84+
kwargs['device'] = f"{default_device}:{index}"
8285
else:
83-
kwargs['device'] = redirected_type
84-
log_message(f"Redirecting tensor.to() from '{device_type}' to '{redirected_type}'.", "tensor.to")
86+
kwargs['device'] = default_device
87+
log_message(f"Redirecting tensor.to() from '{device_type}' to '{default_device}'.", "tensor.to")
8588
elif hasattr(device_arg, 'type'):
8689
device_type = device_arg.type
87-
redirected_type = TorchDevice._redirect_device_type(device_type)
88-
89-
if redirected_type != device_type:
90+
if device_type != default_device:
9091
index = getattr(device_arg, 'index', 0)
9192
if index is None:
9293
index = 0
93-
kwargs['device'] = TorchDevice.torch_device_replacement(f"{redirected_type}:{index}")
94-
log_message(f"Redirecting tensor.to() from '{device_type}' to '{redirected_type}'.", "tensor.to")
94+
kwargs['device'] = TorchDevice.torch_device_replacement(f"{default_device}:{index}")
95+
log_message(f"Redirecting tensor.to() from '{device_type}' to '{default_device}'.", "tensor.to")
9596

9697
# Log warning if target device doesn't match default
9798
if device_arg is not None:
@@ -103,6 +104,8 @@ def tensor_to_replacement(self, *args, **kwargs):
103104
target_device = str(device_arg)
104105
if target_device != default_device:
105106
log_message(f"tensor.to() called with device {device_arg} which does not match the default device {default_device}.", "tensor.to")
107+
108+
# Call the original to() with the redirected device
106109
return _original_tensor_to(self, *args, **kwargs)
107110

108111
def module_to_replacement(self, *args, **kwargs):

0 commit comments

Comments
 (0)