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.2.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.2-py3-none-any.whl (15.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: snake_shift-1.0.2.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.2.tar.gz
Algorithm Hash digest
SHA256 ae94880cea64181d54a32cedb14ae7910160a126c39062ad3a641b9ec2de81dd
MD5 1a90c1afcb77eb0524efb8121003b386
BLAKE2b-256 d0162be29a5671f626beb19c1a813d6e15341b1afb17750411ecb0ed9bcff349

See more details on using hashes here.

File details

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

File metadata

  • Download URL: snake_shift-1.0.2-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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 77ad1dc51b12a4b7348bc969487c62f7a6aa088f1fbee1ddb561afdbaf19a08c
MD5 906ed1d1b9a848edff951d1667e56a01
BLAKE2b-256 45dd555f6a81493fa41daf4ea127b5b4d406bfbdac1d75d2f0b5314e03e882bd

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