# PathLib Best Practices and Common Pitfalls

## Important Learnings from Storm Logger Development

### 1. Empty String Path Behavior

When you pass an empty string to `Path()`, it doesn't remain empty - it becomes the current directory:

```python
from pathlib import Path

# Common mistake - expecting empty string to remain empty
path = Path('')
print(path)  # Output: .
print(str(path))  # Output: .
print(repr(path))  # Output: PosixPath('.')

# The path is NOT falsy even though created from empty string
if path:
    print("This will execute!")  # This runs because Path('.') is truthy
```

### 2. Falsy Check Pitfall

When normalizing paths in configuration, be careful with falsy checks:

```python
# WRONG - will skip empty string paths
if self.archive_directory and isinstance(self.archive_directory, str):
    self.archive_directory = Path(self.archive_directory)
    
# Result: archive_directory = '' remains as empty string

# CORRECT - check type first
if isinstance(self.archive_directory, str):
    if self.archive_directory:  # Only convert non-empty strings
        self.archive_directory = Path(self.archive_directory)
    # else: handle empty string case explicitly
```

### 3. Path Normalization Best Practices

```python
def normalize_path(path_value):
    """Safely normalize path values."""
    if path_value is None:
        return None
    
    if isinstance(path_value, Path):
        return path_value
    
    if isinstance(path_value, str):
        if not path_value:  # Empty string
            # Decide: return None, Path('.'), or raise error
            return None  # or Path('.') depending on use case
        return Path(path_value)
    
    raise TypeError(f"Expected str or Path, got {type(path_value)}")
```

### 4. Testing Path Behavior

When testing path normalization:

```python
import pytest
from pathlib import Path

def test_path_normalization():
    # Test empty string
    assert Path('') == Path('.')
    assert str(Path('')) == '.'
    
    # Test None - Path(None) raises TypeError
    with pytest.raises(TypeError):
        Path(None)
    
    # Test absolute vs relative
    assert Path('/tmp').is_absolute()
    assert not Path('tmp').is_absolute()
    
    # Test path joining
    assert Path('logs') / 'app.log' == Path('logs/app.log')
```

### 5. Common PathLib Methods to Remember

```python
from pathlib import Path

path = Path('/tmp/logs/app.log')

# Existence checks
path.exists()
path.is_file()
path.is_dir()

# Path components
path.name          # 'app.log'
path.stem          # 'app'
path.suffix        # '.log'
path.parent        # Path('/tmp/logs')
path.parents       # [Path('/tmp/logs'), Path('/tmp'), Path('/')]

# Path manipulation
path.with_suffix('.txt')    # Path('/tmp/logs/app.txt')
path.with_name('error.log') # Path('/tmp/logs/error.log')

# File operations
path.touch()               # Create empty file
path.mkdir(parents=True)   # Create directory and parents
path.unlink()              # Delete file
path.rmdir()               # Delete empty directory
```

### 6. Cross-Platform Considerations

```python
from pathlib import Path, PurePosixPath, PureWindowsPath

# Always use forward slashes in code
config_path = Path('logs/app/error.log')  # Works on all platforms

# Don't hardcode separators
# WRONG: 'logs\\app\\error.log'  # Windows only
# WRONG: 'logs/app/error.log'.split('/')  # Assumes POSIX

# For path manipulation without filesystem access
pure_path = PurePosixPath('logs/app/error.log')
```

### 7. Integration with Storm Logger Config

When working with Storm Logger's configuration:

1. Always normalize paths in `__post_init__` or dedicated methods
2. Be explicit about empty string handling
3. Consider using Optional[Path] for optional paths
4. Validate paths exist/are writable in separate validation step
5. Use dependency injection for filesystem operations (testability)

## Summary

The key lesson learned: `Path('')` becomes `Path('.')`, not an empty path. This affects:
- Falsy checks (empty string is falsy, but Path('.') is truthy)
- String representation (str(Path('')) == '.')
- Path comparisons and validations

Always handle empty strings explicitly when converting to Path objects, and be clear about the intended behavior in your application.