snake-shift


Namesnake-shift JSON
Version 1.0.2 PyPI version JSON
download
home_pageNone
SummarySmart codebase refactor from camelCase to pythonic snake_case
upload_time2025-09-02 00:22:52
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseNone
keywords camelcase code-formatting python refactoring snake-case
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Snake Shift

[![Tests](https://img.shields.io/badge/tests-95%2F95%20passing-brightgreen)](https://github.com/simondoesstuff/snake_shift)
[![Python](https://img.shields.io/badge/python-3.9%2B-blue)](https://python.org)
[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)

A powerful Python refactoring tool that converts camelCase _codebases_ to pythonic naming conventions while intelligently preserving external library calls.

## Features

- **Smart Environment Detection** - Automatically distinguishes between internal and external modules
- **Aggressive Refactoring** - Converts entire codebases while preserving external library APIs
- **File & Directory Renaming** - Renames files and directories to match pythonic conventions
  - Ignores non-code directories.
- **Gitignore Integration** - Respects .gitignore patterns and includes sensible defaults
- **PascalCase Preservation** - Keeps class names and type imports in PascalCase
- **LibCST-Powered** - Uses concrete syntax trees for accurate code transformation
- **Dry Run Support** - Preview changes before applying them

## Quick Start

```bash
# Install the tool
pip install snake-shift

# Preview changes to a single file
snake-shift my_file.py --dry-run

# Refactor code and rename files in a directory
snake-shift src/ --rename-files

# Just refactor code without renaming files
snake-shift project/ --dry-run
```

## Before & After

**Before:**

```python
# myModule.py
import pandas as pd
from myPackage.dataUtils import processData

class myClass:
    def myMethod(self, inputData):
        df = pd.DataFrame(inputData)
        processedData = processData(df.dropna())
        return processedData
```

**After:**

```python
# my_module.py
import pandas as pd
from my_package.data_utils import process_data

class MyClass:
    def my_method(self, input_data):
        df = pd.DataFrame(input_data)  # External library preserved!
        processed_data = process_data(df.dropna())
        return processed_data
```

## How It Works

### 1. Environment-Based Module Detection

Unlike other tools that use hardcoded library lists, snake-shift intelligently detects external modules by:

- Checking if modules are installed in your Python environment
- Identifying standard library modules
- Recognizing common external packages even when not installed
- Treating unknown modules as internal (local code)

### 2. Pythonic Convention Application

- **Classes** ? `PascalCase` (MyClass)
- **Functions & Variables** ? `snake_case` (my_function, my_var)
- **PascalCase Imports** ? Preserved (Dict, Path, MyClass)
- **External Library Calls** ? Untouched (pd.DataFrame, np.zeros)

### 3. File System Organization

With `--rename-files`:

- `myModule.py` ? `my_module.py`
- `dataUtils/` ? `data_utils/`
- `MyClass.py` ? `MyClass.py` (PascalCase preserved)

## Installation

```bash
pip install snake-shift
```

Or install from source:

```bash
git clone https://github.com/simondoesstuff/snake_shift.git
pip install -e .
```

## Usage

### Command Line Interface

```bash
snake-shift [OPTIONS] PATH
```

**Options:**

- `--dry-run, -n` - Show changes without writing to files
- `--rename-files, -r` - Also rename files and directories
- `--stdout` - Print refactored code to stdout (single files only)
- `--verbose, -v` - Show detailed output during processing
- `--help` - Show help message

**Examples:**

```bash
# Preview all changes to a project
snake-shift my_project/ --rename-files --dry-run

# Refactor a single file
snake-shift utils.py

# Refactor directory with file renaming
snake-shift src/ --rename-files --verbose

# Output refactored code to stdout
snake-shift my_script.py --stdout
```

### Python API

```python
from snake_shift import refactor_source, refactor_directory

# Refactor source code string
code = """
def myFunction(inputData):
    return inputData.lower()
"""
refactored = refactor_source(code)
print(refactored)
# Output: def my_function(input_data):\n    return input_data.lower()

# Refactor entire directory
from pathlib import Path
refactor_directory(
    Path("my_project/"),
    rename_files=True,
    dry_run=False
)
```

## What Gets Refactored

### Internal Code (Your Code)

- Variable names: `myVar` $\to$ `my_var`
- Function names: `myFunction` $\to$ `my_function`
- Class names: `myClass` $\to$ `MyClass`
- Module imports: `from myPackage.myModule` $\to$ `from my_package.my_module`
- File names: `myModule.py` $\to$ `my_module.py`
- Directory names: `myPackage/` $\to$ `my_package/`

### External Code (Preserved)

- Library calls: `pd.DataFrame()` stays `pd.DataFrame()`
- Standard library: `os.path.join()` stays `os.path.join()`
- PascalCase imports: `from typing import Dict` stays `Dict`
- External attributes: `model.fit()` stays `model.fit()`

## Contributing

Contributions are welcome!

### Building

```bash
# run tests with,
uv run pytest

# or just set up the environment,
uv sync

# or if you don't have UV,
pip install -r requirements.txt
pytest  # tests
```

## License

MIT Licence

## Acknowledgments

- Built with [LibCST](https://libcst.readthedocs.io/) for accurate Python code transformation
- CLI powered by [Typer](https://typer.tiangolo.com/)
- Inspired by the need for better Python refactoring tools that understand modern codebases

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "snake-shift",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "camelcase, code-formatting, python, refactoring, snake-case",
    "author": null,
    "author_email": "Simon Walker <simon@simonwalker.tech>",
    "download_url": "https://files.pythonhosted.org/packages/d0/16/2be29a5671f626beb19c1a813d6e15341b1afb17750411ecb0ed9bcff349/snake_shift-1.0.2.tar.gz",
    "platform": null,
    "description": "# Snake Shift\n\n[![Tests](https://img.shields.io/badge/tests-95%2F95%20passing-brightgreen)](https://github.com/simondoesstuff/snake_shift)\n[![Python](https://img.shields.io/badge/python-3.9%2B-blue)](https://python.org)\n[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n\nA powerful Python refactoring tool that converts camelCase _codebases_ to pythonic naming conventions while intelligently preserving external library calls.\n\n## Features\n\n- **Smart Environment Detection** - Automatically distinguishes between internal and external modules\n- **Aggressive Refactoring** - Converts entire codebases while preserving external library APIs\n- **File & Directory Renaming** - Renames files and directories to match pythonic conventions\n  - Ignores non-code directories.\n- **Gitignore Integration** - Respects .gitignore patterns and includes sensible defaults\n- **PascalCase Preservation** - Keeps class names and type imports in PascalCase\n- **LibCST-Powered** - Uses concrete syntax trees for accurate code transformation\n- **Dry Run Support** - Preview changes before applying them\n\n## Quick Start\n\n```bash\n# Install the tool\npip install snake-shift\n\n# Preview changes to a single file\nsnake-shift my_file.py --dry-run\n\n# Refactor code and rename files in a directory\nsnake-shift src/ --rename-files\n\n# Just refactor code without renaming files\nsnake-shift project/ --dry-run\n```\n\n## Before & After\n\n**Before:**\n\n```python\n# myModule.py\nimport pandas as pd\nfrom myPackage.dataUtils import processData\n\nclass myClass:\n    def myMethod(self, inputData):\n        df = pd.DataFrame(inputData)\n        processedData = processData(df.dropna())\n        return processedData\n```\n\n**After:**\n\n```python\n# my_module.py\nimport pandas as pd\nfrom my_package.data_utils import process_data\n\nclass MyClass:\n    def my_method(self, input_data):\n        df = pd.DataFrame(input_data)  # External library preserved!\n        processed_data = process_data(df.dropna())\n        return processed_data\n```\n\n## How It Works\n\n### 1. Environment-Based Module Detection\n\nUnlike other tools that use hardcoded library lists, snake-shift intelligently detects external modules by:\n\n- Checking if modules are installed in your Python environment\n- Identifying standard library modules\n- Recognizing common external packages even when not installed\n- Treating unknown modules as internal (local code)\n\n### 2. Pythonic Convention Application\n\n- **Classes** ? `PascalCase` (MyClass)\n- **Functions & Variables** ? `snake_case` (my_function, my_var)\n- **PascalCase Imports** ? Preserved (Dict, Path, MyClass)\n- **External Library Calls** ? Untouched (pd.DataFrame, np.zeros)\n\n### 3. File System Organization\n\nWith `--rename-files`:\n\n- `myModule.py` ? `my_module.py`\n- `dataUtils/` ? `data_utils/`\n- `MyClass.py` ? `MyClass.py` (PascalCase preserved)\n\n## Installation\n\n```bash\npip install snake-shift\n```\n\nOr install from source:\n\n```bash\ngit clone https://github.com/simondoesstuff/snake_shift.git\npip install -e .\n```\n\n## Usage\n\n### Command Line Interface\n\n```bash\nsnake-shift [OPTIONS] PATH\n```\n\n**Options:**\n\n- `--dry-run, -n` - Show changes without writing to files\n- `--rename-files, -r` - Also rename files and directories\n- `--stdout` - Print refactored code to stdout (single files only)\n- `--verbose, -v` - Show detailed output during processing\n- `--help` - Show help message\n\n**Examples:**\n\n```bash\n# Preview all changes to a project\nsnake-shift my_project/ --rename-files --dry-run\n\n# Refactor a single file\nsnake-shift utils.py\n\n# Refactor directory with file renaming\nsnake-shift src/ --rename-files --verbose\n\n# Output refactored code to stdout\nsnake-shift my_script.py --stdout\n```\n\n### Python API\n\n```python\nfrom snake_shift import refactor_source, refactor_directory\n\n# Refactor source code string\ncode = \"\"\"\ndef myFunction(inputData):\n    return inputData.lower()\n\"\"\"\nrefactored = refactor_source(code)\nprint(refactored)\n# Output: def my_function(input_data):\\n    return input_data.lower()\n\n# Refactor entire directory\nfrom pathlib import Path\nrefactor_directory(\n    Path(\"my_project/\"),\n    rename_files=True,\n    dry_run=False\n)\n```\n\n## What Gets Refactored\n\n### Internal Code (Your Code)\n\n- Variable names: `myVar` $\\to$ `my_var`\n- Function names: `myFunction` $\\to$ `my_function`\n- Class names: `myClass` $\\to$ `MyClass`\n- Module imports: `from myPackage.myModule` $\\to$ `from my_package.my_module`\n- File names: `myModule.py` $\\to$ `my_module.py`\n- Directory names: `myPackage/` $\\to$ `my_package/`\n\n### External Code (Preserved)\n\n- Library calls: `pd.DataFrame()` stays `pd.DataFrame()`\n- Standard library: `os.path.join()` stays `os.path.join()`\n- PascalCase imports: `from typing import Dict` stays `Dict`\n- External attributes: `model.fit()` stays `model.fit()`\n\n## Contributing\n\nContributions are welcome!\n\n### Building\n\n```bash\n# run tests with,\nuv run pytest\n\n# or just set up the environment,\nuv sync\n\n# or if you don't have UV,\npip install -r requirements.txt\npytest  # tests\n```\n\n## License\n\nMIT Licence\n\n## Acknowledgments\n\n- Built with [LibCST](https://libcst.readthedocs.io/) for accurate Python code transformation\n- CLI powered by [Typer](https://typer.tiangolo.com/)\n- Inspired by the need for better Python refactoring tools that understand modern codebases\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Smart codebase refactor from camelCase to pythonic snake_case",
    "version": "1.0.2",
    "project_urls": {
        "Homepage": "https://github.com/simondoesstuff/snake_shift",
        "Issues": "https://github.com/simondoesstuff/snake_shift/issues",
        "Repository": "https://github.com/simondoesstuff/snake_shift"
    },
    "split_keywords": [
        "camelcase",
        " code-formatting",
        " python",
        " refactoring",
        " snake-case"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "45dd555f6a81493fa41daf4ea127b5b4d406bfbdac1d75d2f0b5314e03e882bd",
                "md5": "906ed1d1b9a848edff951d1667e56a01",
                "sha256": "77ad1dc51b12a4b7348bc969487c62f7a6aa088f1fbee1ddb561afdbaf19a08c"
            },
            "downloads": -1,
            "filename": "snake_shift-1.0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "906ed1d1b9a848edff951d1667e56a01",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 15621,
            "upload_time": "2025-09-02T00:22:51",
            "upload_time_iso_8601": "2025-09-02T00:22:51.404423Z",
            "url": "https://files.pythonhosted.org/packages/45/dd/555f6a81493fa41daf4ea127b5b4d406bfbdac1d75d2f0b5314e03e882bd/snake_shift-1.0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d0162be29a5671f626beb19c1a813d6e15341b1afb17750411ecb0ed9bcff349",
                "md5": "1a90c1afcb77eb0524efb8121003b386",
                "sha256": "ae94880cea64181d54a32cedb14ae7910160a126c39062ad3a641b9ec2de81dd"
            },
            "downloads": -1,
            "filename": "snake_shift-1.0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "1a90c1afcb77eb0524efb8121003b386",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 92462,
            "upload_time": "2025-09-02T00:22:52",
            "upload_time_iso_8601": "2025-09-02T00:22:52.867606Z",
            "url": "https://files.pythonhosted.org/packages/d0/16/2be29a5671f626beb19c1a813d6e15341b1afb17750411ecb0ed9bcff349/snake_shift-1.0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-02 00:22:52",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "simondoesstuff",
    "github_project": "snake_shift",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [],
    "lcname": "snake-shift"
}
        
Elapsed time: 0.82620s