No project description provided
Project description
pyxplod
pyxplod is a Python refactoring tool that "explodes" Python files by extracting each class and function definition into separate files, automatically replacing them with imports. This helps break down large Python modules into smaller, more manageable pieces while maintaining functionality.
Features
- 🔍 Intelligent code extraction: Uses Python's AST to accurately identify and extract classes and functions
- 📁 Structure preservation: Maintains your project's directory structure in the output
- 🔗 Automatic imports: Replaces extracted code with proper relative imports
- ⚡ Smart import optimization: Only includes imports actually used in each extracted file (v0.3.0+)
- 🛡️ Safe operation: Non-destructive - creates new files without modifying originals
- 📊 Progress tracking: Visual progress bars and detailed logging with
richandloguru - 🎯 Smart naming: Converts class/function names to snake_case for consistent file naming
- 🗂️ Dual methods: Choose between flat file structure or package-based organization
- ⚡ Fast processing: Efficiently handles large codebases with error recovery
Installation
From PyPI (when published)
pip install pyxplod
Or using uv:
uv pip install pyxplod
From Source (Current)
# Clone the repository
git clone https://github.com/twardoch/pyxplod.git
cd pyxplod
# Install in development mode
uv pip install -e .
Usage
Basic Usage (Files Method)
pyxplod --input /path/to/source --output /path/to/output
Using Dirs Method
pyxplod --input /path/to/source --output /path/to/output --method dirs
With Verbose Logging
pyxplod --input /path/to/source --output /path/to/output --verbose
Methods
pyxplod supports two different explosion methods:
Files Method (Default)
The files method creates separate files in the same directory structure, with each extracted class/function having a filename prefix based on the original file.
Dirs Method
The dirs method creates a directory (package) for each Python file, with extracted classes and functions as separate modules within that package. An __init__.py file contains imports and any remaining module-level code.
How It Works
Given a Python file like this:
# src/utils.py
import os
from typing import List
class FileHandler:
def __init__(self):
self.files = []
def add_file(self, path: str):
self.files.append(path)
def process_data(data: List[str]) -> str:
return "\n".join(data)
CONSTANT = "some_value"
pyxplod will create different structures based on the method used:
Files Method Output (Default)
output/
└── src/
├── utils.py # Modified main file
├── utils_file_handler.py # Extracted class
└── utils_process_data.py # Extracted function
Dirs Method Output
output/
└── src/
└── utils/
├── __init__.py # Module interface with imports
├── file_handler.py # Extracted class
└── process_data.py # Extracted function
Example Contents
Files Method Output
output/src/utils.py:
from typing import List
from .utils_file_handler import FileHandler
from .utils_process_data import process_data
CONSTANT = "some_value"
output/src/utils_file_handler.py:
class FileHandler:
def __init__(self):
self.files = []
def add_file(self, path: str):
self.files.append(path)
output/src/utils_process_data.py:
from typing import List
def process_data(data: List[str]) -> str:
return "\n".join(data)
Dirs Method Output
output/src/utils/init.py:
from typing import List
from .file_handler import FileHandler
from .process_data import process_data
CONSTANT = "some_value"
output/src/utils/file_handler.py:
class FileHandler:
def __init__(self):
self.files = []
def add_file(self, path: str):
self.files.append(path)
output/src/utils/process_data.py:
from typing import List
def process_data(data: List[str]) -> str:
return "\n".join(data)
Note: pyxplod v0.3.0+ automatically optimizes imports - only the imports actually used in each file are included, reducing file sizes by 30-50%.
Advanced Options
Command Line Arguments
pyxplod --help
| Argument | Description | Default | Example |
|---|---|---|---|
--input |
Source directory to process | Required | --input ./src |
--output |
Output directory for exploded files | Required | --output ./output |
--method |
Processing method: files or dirs |
files |
--method dirs |
--verbose |
Enable detailed logging | False |
--verbose |
Processing Methods Comparison
| Aspect | Files Method | Dirs Method |
|---|---|---|
| Structure | Flat files with prefixes | Package directories |
| File naming | utils_my_class.py |
my_class.py |
| Organization | Same directory | Subdirectories with __init__.py |
| Best for | Simple modules, quick extraction | Complex modules, clean organization |
| Import style | from .utils_my_class import MyClass |
from .utils.my_class import MyClass |
Use Cases
- Refactoring large modules: Break down monolithic Python files (500+ lines) into smaller, focused modules
- Code organization: Improve project structure by separating concerns and creating logical boundaries
- Testing: Make it easier to test individual components in isolation with focused test files
- Code review: Simplify code reviews by creating smaller, single-purpose files that are easier to understand
- Legacy code: Gradually modernize legacy codebases by extracting reusable components
- Microservices preparation: Extract functionality before splitting monoliths into microservices
- Educational purposes: Help understand code structure by separating concerns visually
Features in Detail
Smart Import Handling
- Preserves all module-level imports in extracted files
- Generates relative imports for the extracted components
- Maintains import order and structure
Error Handling
- Gracefully handles syntax errors in source files
- Skips files that cannot be parsed
- Provides detailed error messages for troubleshooting
File Naming
- Converts CamelCase to snake_case automatically
- Handles naming conflicts with automatic deduplication
- Preserves meaningful names while ensuring filesystem compatibility
Development
Setup Development Environment
# Clone the repository
git clone https://github.com/twardoch/pyxplod.git
cd pyxplod
# Install in development mode
pip install -e .
# Install development dependencies
pip install -e ".[dev,test]"
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=pyxplod
# Run specific test
pytest tests/test_pyxplod.py::TestProcessing::test_process_simple_file
Code Quality
# Auto-format, lint and test (recommended)
fd -e py -x autoflake {}; fd -e py -x pyupgrade --py311-plus {}; fd -e py -x ruff check --output-format=github --fix --unsafe-fixes {}; fd -e py -x ruff format --respect-gitignore --target-version py311 {}; python -m pytest;
# Individual commands
ruff check src/ tests/ # Linting
ruff format src/ tests/ # Formatting
mypy src/ # Type checking
Requirements
- Python 3.10 or higher
- Dependencies:
fire- CLI interfaceloguru- Enhanced loggingrich- Progress bars and formatting- Standard library:
ast,pathlib,os
License
MIT License - see LICENSE file for details.
Limitations & Known Issues
- Comments: Comments between class/function definitions may be lost during processing
- Formatting: Code formatting may change due to AST parsing and regeneration
- Nested definitions: Only top-level classes and functions are extracted (nested classes/functions remain in original files)
- Decorators: Some complex decorator chains may need manual review after extraction
- Large files: Very large files (>1000 lines) may require more memory and processing time
See TODO.md for a complete list of planned improvements.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development Setup
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Set up development environment:
uv pip install -e ".[dev,test]"
- Make your changes and add tests
- Run the test suite:
python -m pytest --cov=pyxplod
- Ensure code quality:
fd -e py -x ruff check --fix {}; fd -e py -x ruff format {}
- Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Code Guidelines
- Follow PEP 8 style guidelines
- Add type hints using simple syntax (
list,dict,str | None) - Write clear docstrings for all functions and classes
- Add tests for new features and bug fixes
- Keep functions focused and single-purpose
Changelog
See CHANGELOG.md for a detailed history of changes.
Author
Created by Adam Twardoch
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyxplod-1.0.0.tar.gz.
File metadata
- Download URL: pyxplod-1.0.0.tar.gz
- Upload date:
- Size: 9.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a842f6d811421905a450171e6cb5c8202ac4203919a15b3a75d173ada9d0742
|
|
| MD5 |
cfcafc940e8809c235ff32f45802943b
|
|
| BLAKE2b-256 |
ba0c8f4da13fcf35642c8aa5ff749225275a63f4f75e4b7086ba2dc608a1a8ca
|
File details
Details for the file pyxplod-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pyxplod-1.0.0-py3-none-any.whl
- Upload date:
- Size: 6.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e93d1d7e03b85a2facefac9a4f455e26aa2d046ea9c310d86c86fe210594bd31
|
|
| MD5 |
ff71a5bbe459f8faf6688e2676b03bae
|
|
| BLAKE2b-256 |
b8307bbe47320fb4558d294356ec1fc633e419465541f6d55cf221c15fc4655a
|