Metadata-Version: 2.4
Name: e501-fixer
Version: 0.1.0
Summary: Automatic string literal wrapping for PEP 8 E501 compliance
Author-email: Cameron Rout <cameronrout@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/muunkky/e501-fixer
Project-URL: Documentation, https://github.com/muunkky/e501-fixer
Project-URL: Repository, https://github.com/muunkky/e501-fixer.git
Project-URL: Issues, https://github.com/muunkky/e501-fixer/issues
Keywords: pep8,e501,string-wrapping,code-formatter,linter
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=8.2.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
Requires-Dist: mypy>=1.11.0; extra == "dev"
Requires-Dist: ruff>=0.6.8; extra == "dev"
Provides-Extra: cli
Requires-Dist: click>=8.3.0; extra == "cli"
Dynamic: license-file

# e501-fixer

[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Automatic string literal wrapping for PEP 8 E501 compliance.

## Problem

PEP 8 recommends a maximum line length of 88 characters. When strings exceed this limit, Python developers must manually wrap them—a tedious, error-prone process. While tools like Black and ruff exist, none provide comprehensive automatic wrapping of string literals.

**e501-fixer** fills this gap with a safe, well-tested solution that automatically wraps long strings using Python's implicit string concatenation.

## Features

- ✅ **Automatic string wrapping** using implicit concatenation
- ✅ **Preserves quote style** (single vs. double quotes)
- ✅ **Handles all string types** (regular, raw, byte strings)
- ✅ **Safe by default** (skips f-strings and triple-quoted strings)
- ✅ **CLI interface** for easy integration into workflows
- ✅ **Pre-commit hook** support for automated checks
- ✅ **100% test coverage** with comprehensive test suite
- ✅ **Type-safe** with full mypy strict mode compliance

## Installation

### Via pip (when published to PyPI)

```bash
pip install e501-fixer
```

### From source (development)

Clone the standalone e501-fixer repository:

```bash
git clone https://github.com/muunkky/e501-fixer.git
cd e501-fixer
pip install -e .
```

### With CLI support

```bash
pip install -e ".[cli]"
```

## Quick Start

### CLI Usage

```bash
# Fix E501 violations in a file
e501-fixer fix myfile.py

# Fix violations in a directory
e501-fixer fix src/

# Check for violations without fixing
e501-fixer check myfile.py

# Check with custom line length
e501-fixer fix --max-line-length 100 myfile.py
```

### Python API

```python
from e501_fixer import FileProcessor
from pathlib import Path

# Create processor with custom line length
processor = FileProcessor(max_line_length=100)

# Process single file
result = processor.process_file(Path("example.py"))
print(f"Fixed {result.fixes_applied} violations")

# Process directory
result = processor.process_directory(Path("src/"))
print(f"Fixed {result.total_fixes} violations in {result.files_processed} files")
```

## How It Works

### Before

```python
def greet(name: str) -> None:
    message = "Hello, this is a very long string that exceeds the PEP 8 line length limit and needs to be wrapped"
    print(message)
```

### After

```python
def greet(name: str) -> None:
    message = (
        "Hello, this is a very long string that exceeds the "
        "PEP 8 line length limit and needs to be wrapped"
    )
    print(message)
```

## Examples

### Preserving Quote Style

```python
# Input: single quotes
description = 'This is a long single-quoted string that needs wrapping and is quite verbose'

# Output: single quotes preserved
description = (
    'This is a long single-quoted string that needs wrapping '
    'and is quite verbose'
)
```

### Respecting Indentation

```python
# Input: nested string
def setup():
    if True:
        config = "This is a very long configuration string that exceeds the maximum line length and must be wrapped properly"

# Output: indentation respected
def setup():
    if True:
        config = (
            "This is a very long configuration string that exceeds "
            "the maximum line length and must be wrapped properly"
        )
```

### Raw Strings

```python
# Input: raw string
pattern = r'This is a very long regex pattern that exceeds the line length and needs to be wrapped for readability'

# Output: raw string type preserved
pattern = (
    r'This is a very long regex pattern that exceeds the line '
    r'length and needs to be wrapped for readability'
)
```

## Pre-commit Integration

Add to `.pre-commit-config.yaml`:

```yaml
- repo: local
  hooks:
    - id: e501-fixer
      name: e501-fixer
      entry: e501-fixer fix
      language: system
      types: [python]
      stages: [commit]
```

Or using the pre-commit hooks defined in this package (when published):

```yaml
- repo: https://github.com/muunkky/e501-fixer
  rev: v0.1.0
  hooks:
    - id: e501-fix      # Auto-fix violations
    - id: e501-check    # Check without modifying (for CI)
```

The package provides two hooks:
- `e501-fix`: Automatically fixes E501 violations (use before commit)
- `e501-check`: Reports violations without modifying (use in CI/CD)

## Safety Guarantees

- **No Code Corruption**: Conservative approach—skips uncertain cases
- **Preserves Semantics**: Implicit concatenation produces identical behavior
- **Type Safe**: Full mypy strict mode compliance
- **Well Tested**: 90+ tests covering all string types and edge cases
- **Documented**: Comprehensive architecture documentation (ADR-018)

## Architecture

The tool is built on a modular, TDD-driven architecture:

- **StringLiteralParser**: Identifies and extracts string literals using regex
- **BreakPointFinder**: Calculates optimal positions to split strings
- **StringWrapper**: Applies wrapping transformations
- **FileProcessor**: Orchestrates parsing, wrapping, and file I/O

For detailed architecture, see [ARCHITECTURE.md](ARCHITECTURE.md).

## Performance

- Per-file: ~1-2ms for average files (100-200 lines)
- Large files: <100ms for 1000+ line files
- Directory processing: Efficient batch handling

## Configuration

### Line Length

```bash
e501-fixer fix --max-line-length 100 myfile.py
```

Python API:

```python
processor = FileProcessor(max_line_length=100)
```

### Indentation

```python
processor = FileProcessor(default_indentation="  ")  # 2 spaces
```

## Limitations

- **F-strings**: Not wrapped (interpolations make splitting risky)
- **Triple-quoted strings**: Not wrapped (complex semantics)
- **Unbreakable strings**: Strings without spaces cannot be wrapped

These are conservative choices that prioritize safety over coverage.

## Troubleshooting

### No violations found

- Verify the file has strings exceeding the max line length
- Check `--max-line-length` setting (default: 88)
- Some strings may be intentionally unbreakable (no spaces)

### Pre-commit hook not executing

- Ensure `e501-fixer` is installed in the pre-commit environment
- Check `.pre-commit-config.yaml` syntax
- Run `pre-commit install` to activate hooks

### Import errors

- Install CLI dependencies: `pip install e501-fixer[cli]`
- Verify Python 3.10+ is installed

## Development

### Setup

```bash
pip install -e ".[dev]"
```

### Testing

```bash
pytest tests/
pytest --cov=e501_fixer
```

### Type Checking

```bash
mypy e501_fixer/
```

### Linting

```bash
ruff check e501_fixer/
```

## License

MIT - see LICENSE file

## Contributing

Contributions are welcome! Please ensure:

- All tests pass (`pytest`)
- Code passes type checking (`mypy`)
- Code passes linting (`ruff check`)
- New features include tests and documentation

## References

- [PEP 8 - Style Guide for Python Code](https://pep8.org/)
- [E501 - Line too long](https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes)
- [ADR-018 - E501 String Literal Fixer Architecture](ARCHITECTURE.md)
- [Black Code Formatter](https://black.readthedocs.io/)
