Skip to main content

Smart codebase refactor from camelCase to pythonic snake_case

Project description

Snake Shift

Tests Python 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

# 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:

# 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:

# 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

pip install snake-shift

Or install from source:

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

Usage

Command Line Interface

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:

# 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

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

# 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 for accurate Python code transformation
  • CLI powered by Typer
  • Inspired by the need for better Python refactoring tools that understand modern codebases

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

snake_shift-1.0.1.tar.gz (92.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

snake_shift-1.0.1-py3-none-any.whl (15.6 kB view details)

Uploaded Python 3

File details

Details for the file snake_shift-1.0.1.tar.gz.

File metadata

  • Download URL: snake_shift-1.0.1.tar.gz
  • Upload date:
  • Size: 92.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.23

File hashes

Hashes for snake_shift-1.0.1.tar.gz
Algorithm Hash digest
SHA256 af2ce6c2ead65849f01255feda26273360e60fc962b8555b32359d63f23cc5aa
MD5 2fd722d6af08605ada12c4a3ea1e3877
BLAKE2b-256 57fb0190fecab0102d58dea31974b1efccbf048b15e671ece8bbc7bdc02e31b7

See more details on using hashes here.

File details

Details for the file snake_shift-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: snake_shift-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 15.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.23

File hashes

Hashes for snake_shift-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 06ad50e85db70807a96b7db7fc1bcf4eda8948abc232b447b5f5b404902714e7
MD5 afabe5f02ebf211b461ad4e8b285e9c1
BLAKE2b-256 b08ca9a7d2402ab5a0a4963d0285b5f13409ae4ec25827ee4714d630619d2e2f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page