Pre-commit hooks for Frappe Framework coding standards
Project description
🎯 Frappe Pre-commit
Comprehensive pre-commit hooks for Frappe Framework projects to enforce coding standards, security practices, and best practices automatically.
✨ Features
- 🛡️ SQL Injection Prevention - Detect and prevent SQL injection vulnerabilities
- 📏 Coding Standards - Enforce Frappe-specific coding conventions and best practices
- 📝 DocType Naming - Validate DocType and field naming conventions
- ⚡ Fast Execution - Lightweight checks with minimal dependencies
- 🎯 Customizable - Pick and choose hooks based on your project needs
🚀 Quick Start
System Requirements
- Python: 3.8 or higher
- pip: Latest version
- pre-commit: Will be installed automatically
- Git: For version control
Python Path Setup
If you encounter "Executable python not found" errors, ensure Python is properly configured:
# Check Python installation
python3 --version
# Create python symlink if needed (Linux/macOS)
sudo ln -s /usr/bin/python3 /usr/bin/python
# Or add alias to your shell profile (~/.bashrc, ~/.zshrc)
echo 'alias python=python3' >> ~/.bashrc
source ~/.bashrc
For New Frappe Projects
# 1. Initialize new Frappe app
bench new-app my_custom_app
cd apps/my_custom_app
# 2. Create .pre-commit-config.yaml
curl -o .pre-commit-config.yaml https://raw.githubusercontent.com/dhwani-ris/frappe-pre-commit/main/examples/.pre-commit-config.yaml
# 3. Install and run
pip install pre-commit
pre-commit install
pre-commit run --all-files
For Existing Frappe Projects
# 1. Navigate to your app directory
cd apps/your_app
# 2. Add .pre-commit-config.yaml (see configuration below)
# 3. Install pre-commit
pip install pre-commit
pre-commit install
# 4. Run on existing code
pre-commit run --all-files
📋 Available Hooks
| Hook ID | Description | Files | Dependencies |
|---|---|---|---|
frappe-coding-standards |
General coding standards and best practices | *.py |
None |
frappe-sql-security |
SQL injection and security checks | *.py |
None |
frappe-doctype-naming |
DocType and field naming conventions | *.py, *.js, *.json |
pyyaml |
⚙️ Configuration
Basic Configuration
Create .pre-commit-config.yaml in your project root:
repos:
# Frappe-specific hooks
- repo: https://github.com/dhwani-ris/frappe-pre-commit
rev: v1.0.0 # Use latest tag
hooks:
- id: frappe-translation-check
- id: frappe-sql-security
- id: frappe-coding-standards
# Code formatting (recommended)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.1
hooks:
- id: ruff
args: ["--select=I", "--fix"] # Import sorting
- id: ruff-format # Code formatting
# Additional quality checks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
Complete Configuration
repos:
# Python formatting and linting
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.1
hooks:
- id: ruff
name: "Ruff import sorter"
args: ["--select=I", "--fix"]
- id: ruff
name: "Ruff linter"
args: ["--extend-ignore=E501"]
- id: ruff-format
name: "Ruff formatter"
# JavaScript/CSS/JSON formatting
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v4.0.0-alpha.8
hooks:
- id: prettier
files: \.(js|jsx|ts|tsx|css|scss|json|md|yml|yaml)$
exclude: |
(?x)^(
.*\.min\.(js|css)$|
node_modules/.*|
.*/static/.*
)$
# Basic file checks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
exclude: \.(md|rst)$
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-merge-conflict
- id: debug-statements
# Frappe-specific coding standards
- repo: https://github.com/dhwani-ris/frappe-pre-commit
rev: v1.0.0
hooks:
- id: frappe-coding-standards
# Exclude patterns
exclude: |
(?x)^(
.*/migrations/.*|
.*/patches/.*|
.*\.min\.(js|css)$|
node_modules/.*|
__pycache__/.*
)$
Selective Hook Usage
# Use only specific hooks you need
repos:
- repo: https://github.com/dhwani-ris/frappe-pre-commit
rev: v1.0.0
hooks:
- id: frappe-sql-security # Only SQL security checks
- id: frappe-translation-check # Only translation checks
🔍 What Gets Checked
🛡️ SQL Security Checks
Detects:
- SQL injection vulnerabilities using
.format()or f-strings - String concatenation in SQL queries
- Unencrypted storage of sensitive data (passwords, API keys)
# ❌ Will be flagged
frappe.db.sql("SELECT * FROM tabUser WHERE name = '{}'".format(user_name))
frappe.db.set_value("User", user, "password", plain_password)
# ✅ Correct approach
frappe.db.sql("SELECT * FROM tabUser WHERE name = %s", user_name)
frappe.db.set_value("User", user, "password", frappe.utils.password.encrypt(plain_password))
📏 Coding Standards
Enforces:
- Function length (≤20 lines recommended)
- Proper indentation (tabs, not spaces)
- Naming conventions (snake_case for functions, PascalCase for classes)
- Import organization
- Complexity limits (max nesting depth)
📝 DocType Naming Conventions
Validates:
- DocType names: Title Case with spaces (
"Sales Order") - Field names: snake_case (
"customer_name") - Field labels: Title Case (
"Customer Name")
🏗️ Integration Examples
Integration with Bench
# For bench-managed projects
cd frappe-bench/apps/your_app
# Add pre-commit config
curl -o .pre-commit-config.yaml https://raw.githubusercontent.com/dhwani-ris/frappe-pre-commit/main/examples/.pre-commit-config.yaml
# Install globally in bench environment
~/frappe-bench/env/bin/pip install pre-commit
~/frappe-bench/env/bin/pre-commit install
Integration with GitHub Actions
Create .github/workflows/code-quality.yml:
name: Code Quality
on: [push, pull_request]
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install pre-commit
run: pip install pre-commit
- name: Run pre-commit
run: pre-commit run --all-files
Integration with VS Code
Add to .vscode/settings.json:
{
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.formatting.provider": "black",
"editor.formatOnSave": true,
"python.sortImports.args": ["--profile", "black"],
"[python]": {
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
}
}
🧪 Development and Testing
Setting Up Development Environment
# Clone the repository
git clone https://github.com/dhwani-ris/frappe-pre-commit.git
cd frappe-pre-commit
# Create virtual environment
python -m venv dev_env
source dev_env/bin/activate # On Windows: dev_env\Scripts\activate
# Install development dependencies
pip install -r requirements-dev.txt
pip install pre-commit
# Install pre-commit hooks for this repository
pre-commit install
Running Tests
# Test individual scripts
python scripts/check_coding_standards.py test_files/sample.py
python scripts/check_sql_security.py test_files/sample.py
python scripts/check_translations.py test_files/sample.py
# Test all hooks
python test_scripts/test_all_hooks.py
# Test with pre-commit
pre-commit run --all-files
Creating Test Files
# Create test files with issues
mkdir test_project && cd test_project
# Create Python file with intentional issues
cat > bad_example.py << 'EOF'
import frappe
def very_long_function_that_violates_standards():
frappe.msgprint("Missing translation wrapper")
result = frappe.db.sql("SELECT * FROM tabUser WHERE name = '{}'".format("test"))
return result
EOF
# Test your hooks
cd ../
python scripts/check_translations.py test_project/bad_example.py
python scripts/check_sql_security.py test_project/bad_example.py
Testing with Different Frappe Projects
# Test with ERPNext
cd path/to/erpnext
git clone https://github.com/dhwani-ris/frappe-pre-commit.git .pre-commit-hooks
cp .pre-commit-hooks/examples/.pre-commit-config.yaml .
pre-commit install
pre-commit run --all-files
# Test with custom app
cd path/to/your_custom_app
# Same process as above
Contributing
- Fork the repository
- Create feature branch:
git checkout -b feature/new-check - Add your hook script in
scripts/ - Update
.pre-commit-hooks.yaml - Add tests in
test_scripts/ - Update documentation
- Submit pull request
📚 Examples
Example 1: Basic Frappe App Setup
# Create new app
cd frappe-bench
bench new-app inventory_management
cd apps/inventory_management
# Add pre-commit
cat > .pre-commit-config.yaml << 'EOF'
repos:
- repo: https://github.com/dhwani-ris/frappe-pre-commit
rev: v1.0.0
hooks:
- id: frappe-quick-check
EOF
# Install and test
pip install pre-commit
pre-commit install
pre-commit run --all-files
Example 2: ERPNext Customization
# For ERPNext customizations
cd frappe-bench/apps/erpnext
# Use comprehensive config
curl -o .pre-commit-config.yaml https://raw.githubusercontent.com/dhwani-ris/frappe-pre-commit/main/examples/erpnext-config.yaml
pre-commit install
pre-commit run --all-files
Example 3: CI/CD Integration
# .github/workflows/quality-check.yml
name: Quality Check
on:
pull_request:
branches: [main, develop]
jobs:
code-quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip install pre-commit
pip install -r requirements.txt
- name: Run pre-commit
run: pre-commit run --all-files
- name: Comment PR
if: failure()
uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '❌ Code quality checks failed. Please run `pre-commit run --all-files` locally and fix the issues.'
})
🔧 Troubleshooting
Common Issues
Pre-commit hooks not running:
pre-commit uninstall
pre-commit install
pre-commit run --all-files
Python executable not found error:
# Error: Executable `python` not found
# Solution: Create a python symlink or alias
# Option 1: Create symlink (Linux/macOS)
sudo ln -s /usr/bin/python3 /usr/bin/python
# Option 2: Create alias (add to ~/.bashrc or ~/.zshrc)
alias python=python3
# Option 3: Use python3 explicitly in PATH
export PATH="/usr/bin:$PATH"
# Option 4: Install python-is-python3 package (Ubuntu/Debian)
sudo apt install python-is-python3
# After fixing, reinstall pre-commit hooks
pre-commit uninstall
pre-commit install
Hooks failing on large files:
# Skip hooks for specific commit
git commit -m "Large file update" --no-verify
# Or exclude large files in config
# Add to .pre-commit-config.yaml:
exclude: |
(?x)^(
large_files/.*|
.*\.min\.js$
)$
Import errors in scripts:
# Make sure Python can find the scripts
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
Package installation issues:
# If frappe-pre-commit package fails to install automatically
pip install frappe-pre-commit
# Clear pre-commit cache and reinstall
pre-commit clean
pre-commit install
Performance Tips
# Cache pre-commit environments
export PRE_COMMIT_HOME=~/.cache/pre-commit
# Run only on changed files
pre-commit run
# Skip slow hooks during development
PRE_COMMIT_SKIP=frappe-all-checks git commit -m "Quick fix"
🤝 Contributing
We welcome contributions!
Quick Contribution Steps
- Fork the repository
- Clone your fork:
git clone https://github.com/yourusername/frappe-pre-commit.git - Create branch:
git checkout -b feature/improvement - Make changes and test thoroughly
- Submit pull request
For Developers
If you want to contribute to the package development, testing, or publishing, see DEVELOPER.md for detailed instructions on:
- Setting up the development environment
- Testing changes locally
- Publishing updates to PyPI
- Version management
- Troubleshooting
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🏢 About
Maintained by Dhwani RIS
- 🌐 Website: dhwaniris.com
- 🐙 GitHub: @dhwani-ris
Ready to improve your Frappe code quality? Get started with Frappe-Pre-commit today! 🚀
# Install pre-commit
pip install pre-commit
# Download the pre-commit configuration
curl -o .pre-commit-config.yaml https://raw.githubusercontent.com/dhwani-ris/frappe-pre-commit/main/examples/.pre-commit-config.yaml
# Install the pre-commit hooks (frappe-pre-commit package will be installed automatically)
pre-commit install
# Run all checks
pre-commit run --all-files
Note: If you encounter "Executable
pythonnot found" errors, see the Python Path Setup section above.
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
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 frappe_pre_commit-1.0.4.tar.gz.
File metadata
- Download URL: frappe_pre_commit-1.0.4.tar.gz
- Upload date:
- Size: 12.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e05e6241c1bb5fcf9da4461f6778133cf888562be339b99960e044365eafdc6
|
|
| MD5 |
44fc3079980269389daf31337826e0fe
|
|
| BLAKE2b-256 |
27b2ecd3131b0756fabf1034ff82c14ead09837c49dcd0efdedbad54951ce4d8
|
File details
Details for the file frappe_pre_commit-1.0.4-py3-none-any.whl.
File metadata
- Download URL: frappe_pre_commit-1.0.4-py3-none-any.whl
- Upload date:
- Size: 13.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e4163ce0b545fd4f49cb67c44a5f9cfc10aaa60d996a4f1d24d8c918be675425
|
|
| MD5 |
45c697881cd54863ac7863dc93948ab4
|
|
| BLAKE2b-256 |
e494fc5e255bdc7052b76c6b76fb1dd5b6255cdb6d9efef77055cd12d7e66a49
|