Files
gh-olino3-forge-forge-plugin/skills/python-code-review/templates/inline_comment_template.md
2025-11-30 08:45:11 +08:00

7.7 KiB

Inline Code Review Comments Template

This template provides examples of inline PR-style comments for different types of issues.


Critical Issues

Security Vulnerability

File: auth.py:45

# Current code
user = db.execute(f"SELECT * FROM users WHERE username = '{username}'")

Issue: SQL Injection Vulnerability

Severity: 🔴 Critical

Description: User input is directly interpolated into the SQL query, allowing attackers to execute arbitrary SQL commands.

Attack Vector:

username = "admin' OR '1'='1"
# Results in: SELECT * FROM users WHERE username = 'admin' OR '1'='1'

Fix:

# Use parameterized queries
user = db.execute("SELECT * FROM users WHERE username = %s", (username,))

# Or use ORM
user = User.query.filter_by(username=username).first()

Reference: OWASP A03:2021 - Injection


Data Corruption Risk

File: payment.py:123

# Current code
order.amount -= discount
order.save()
payment.process(order.amount)

Issue: Race Condition in Payment Processing

Severity: 🔴 Critical

Description: If two requests process the same order simultaneously, the discount could be applied twice, leading to incorrect payment amounts.

Fix:

from django.db import transaction

@transaction.atomic
def process_payment(order_id, discount):
    order = Order.objects.select_for_update().get(id=order_id)
    order.amount -= discount
    order.save()
    payment.process(order.amount)

Important Issues

Performance Bottleneck

File: views.py:67

# Current code
posts = Post.objects.all()
for post in posts:
    print(post.author.name)  # N+1 query problem

Issue: N+1 Query Problem

Severity: 🟡 Important

Impact: For 100 posts, this executes 101 database queries instead of 1.

Performance: ~1000ms → ~10ms (100x improvement)

Fix:

posts = Post.objects.select_related('author').all()
for post in posts:
    print(post.author.name)  # No additional queries

Type Safety Issue

File: utils.py:234

def calculate_total(prices):
    return sum(prices) * 1.1

Issue: Missing Type Hints

Severity: 🟡 Important

Description: Function lacks type hints, making it unclear what types are expected and returned. Could lead to runtime errors.

Fix:

def calculate_total(prices: list[float]) -> float:
    """Calculate total with 10% tax.

    Args:
        prices: List of item prices

    Returns:
        Total amount including tax
    """
    return sum(prices) * 1.1

Architectural Concern

File: api.py:89

@app.route('/process')
def process_data():
    # 150 lines of business logic mixed with HTTP handling
    data = request.get_json()
    # ... lots of processing ...
    return jsonify(result)

Issue: Fat Controller / Missing Service Layer

Severity: 🟡 Important

Impact:

  • Hard to test business logic
  • Violates Single Responsibility Principle
  • Difficult to reuse logic elsewhere

Recommendation:

# services/data_processor.py
class DataProcessor:
    def process(self, data: dict) -> dict:
        # Business logic here
        return result

# api.py
@app.route('/process')
def process_data():
    data = request.get_json()
    processor = DataProcessor()
    result = processor.process(data)
    return jsonify(result)

Minor Issues

Code Smell

File: helpers.py:45

def append_to_list(item, items=[]):  # Mutable default argument!
    items.append(item)
    return items

Issue: Mutable Default Argument

Severity: 🔵 Minor

Bug: Default list is shared between all function calls, causing unexpected behavior.

Example:

list1 = append_to_list('a')  # ['a']
list2 = append_to_list('b')  # ['a', 'b'] - UNEXPECTED!

Fix:

def append_to_list(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

Dead Code

File: old_utils.py:123

def legacy_function():
    # This function is never called
    pass

Issue: Unused Code

Severity: 🔵 Minor

Recommendation: Remove to improve code maintainability and reduce cognitive load.


Complexity

File: calculator.py:56

def complex_calculation(x, y, z, mode, options):
    # 50 lines with nested if/else
    # Cyclomatic complexity: 23 (Rank D)
    ...

Issue: High Cyclomatic Complexity

Severity: 🔵 Minor

Impact: Hard to understand, test, and maintain.

Recommendation: Refactor into smaller, focused functions:

def complex_calculation(x, y, z, mode, options):
    if mode == 'simple':
        return _simple_calc(x, y, z)
    elif mode == 'advanced':
        return _advanced_calc(x, y, z, options)
    else:
        return _default_calc(x, y)

def _simple_calc(x, y, z):
    ...

def _advanced_calc(x, y, z, options):
    ...

Testing Issues

Missing Test Coverage

File: payment.py:200

def process_refund(order_id, amount):
    # Critical business logic with no tests!
    order = Order.objects.get(id=order_id)
    order.refund(amount)
    send_notification(order.user, f"Refunded ${amount}")

Issue: Missing Tests for Critical Path

Severity: 🟡 Important

Recommendation: Add comprehensive tests:

# tests/test_payment.py
def test_process_refund_success():
    order = create_test_order(amount=100)
    process_refund(order.id, 50)
    assert order.amount == 50
    assert_notification_sent(order.user)

def test_process_refund_exceeds_amount():
    order = create_test_order(amount=100)
    with pytest.raises(ValueError):
        process_refund(order.id, 150)

def test_process_refund_invalid_order():
    with pytest.raises(Order.DoesNotExist):
        process_refund(99999, 50)

Information / Suggestions

Opportunity for Optimization

File: data_processor.py:78

results = []
for item in large_dataset:
    results.append(transform(item))

Suggestion: Use list comprehension or generator for better performance

# List comprehension (if all results needed in memory)
results = [transform(item) for item in large_dataset]

# Generator (if processing one at a time)
results = (transform(item) for item in large_dataset)

Modern Python Pattern

File: file_handler.py:34

f = open('data.txt', 'r')
data = f.read()
f.close()  # May not execute if read() raises exception

Suggestion: Use context manager

with open('data.txt', 'r') as f:
    data = f.read()
# File automatically closed, even if exception occurs

# Or use pathlib
from pathlib import Path
data = Path('data.txt').read_text()

Comment Format Guidelines

Structure

**File**: path/to/file.py:line_number

[Code snippet if helpful]

**Issue**: Brief title

**Severity**: 🔴 Critical | 🟡 Important | 🔵 Minor | ⚪ Info

**Description**: Detailed explanation

**Impact/Why it matters**: Consequences

**Fix/Recommendation**: Concrete solution with code example

**Reference**: Links to docs, CVEs, etc. (if applicable)

Severity Levels

  • 🔴 Critical: Security vulnerabilities, data corruption, production failures
  • 🟡 Important: Performance issues, type safety, architectural problems, missing tests
  • 🔵 Minor: Code smells, complexity, dead code, minor bugs
  • Info: Suggestions, optimizations, style (only if blocking automation)

Tone

  • Be specific and actionable
  • Explain the "why" not just the "what"
  • Provide code examples
  • Reference authoritative sources
  • Acknowledge good code when present
  • Be constructive, not critical