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

Uploaded Python 3

File details

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

File metadata

  • Download URL: snake_shift-1.0.0.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.0.tar.gz
Algorithm Hash digest
SHA256 30a9f15b8e8ee04037b35e797bee5eeb47822769616bdbae68eaeac1e05bebb5
MD5 055a42a8a25392c11e453d5cf5e6c8e8
BLAKE2b-256 836f381a2d4db3bc287af936db9a4e5211bc6980a1701da995eaff546319b1dd

See more details on using hashes here.

File details

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

File metadata

  • Download URL: snake_shift-1.0.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f7848ceea5df87a4de6e18c7687ec83954ca69cf26e62f4eff8105e43b47aaaa
MD5 7ada417f3fbcce9dc1be0dc5a4a05c98
BLAKE2b-256 9d9441d8cc16819047193294bb766adf06986c89bbcbeaf5cd5f49a30df487b9

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