diff --git a/claude-code-full-guide/cursor.md b/claude-code-full-guide/cursor.md new file mode 100644 index 0000000000..2a2bffec81 --- /dev/null +++ b/claude-code-full-guide/cursor.md @@ -0,0 +1,759 @@ +# CLAUDE.md + +This file provides comprehensive guidance to Claude Code when working with Python code in this repository. + +## Core Development Philosophy + +### KISS (Keep It Simple, Stupid) + +Simplicity should be a key goal in design. Choose straightforward solutions over complex ones whenever possible. Simple solutions are easier to understand, maintain, and debug. + +### YAGNI (You Aren't Gonna Need It) + +Avoid building functionality on speculation. Implement features only when they are needed, not when you anticipate they might be useful in the future. + +### Design Principles + +- **Dependency Inversion**: High-level modules should not depend on low-level modules. Both should depend on abstractions. +- **Open/Closed Principle**: Software entities should be open for extension but closed for modification. +- **Single Responsibility**: Each function, class, and module should have one clear purpose. +- **Fail Fast**: Check for potential errors early and raise exceptions immediately when issues occur. + +## 🧱 Code Structure & Modularity + +### File and Function Limits + +- **Never create a file longer than 500 lines of code**. If approaching this limit, refactor by splitting into modules. +- **Functions should be under 50 lines** with a single, clear responsibility. +- **Classes should be under 100 lines** and represent a single concept or entity. +- **Organize code into clearly separated modules**, grouped by feature or responsibility. +- **Line lenght should be max 100 characters** ruff rule in pyproject.toml +- **Use venv_linux** (the virtual environment) whenever executing Python commands, including for unit tests. + +### Project Architecture + +Follow strict vertical slice architecture with tests living next to the code they test: + +``` +src/project/ + __init__.py + main.py + tests/ + test_main.py + conftest.py + + # Core modules + database/ + __init__.py + connection.py + models.py + tests/ + test_connection.py + test_models.py + + auth/ + __init__.py + authentication.py + authorization.py + tests/ + test_authentication.py + test_authorization.py + + # Feature slices + features/ + user_management/ + __init__.py + handlers.py + validators.py + tests/ + test_handlers.py + test_validators.py + + payment_processing/ + __init__.py + processor.py + gateway.py + tests/ + test_processor.py + test_gateway.py +``` + +## πŸ› οΈ Development Environment + +### UV Package Management + +This project uses UV for blazing-fast Python package and environment management. + +```bash +# Install UV (if not already installed) +curl -LsSf https://astral.sh/uv/install.sh | sh + +# Create virtual environment +uv venv + +# Sync dependencies +uv sync + +# Add a package ***NEVER UPDATE A DEPENDENCY DIRECTLY IN PYPROJECT.toml*** +# ALWAYS USE UV ADD +uv add requests + +# Add development dependency +uv add --dev pytest ruff mypy + +# Remove a package +uv remove requests + +# Run commands in the environment +uv run python script.py +uv run pytest +uv run ruff check . + +# Install specific Python version +uv python install 3.12 +``` + +### Development Commands + +```bash +# Run all tests +uv run pytest + +# Run specific tests with verbose output +uv run pytest tests/test_module.py -v + +# Run tests with coverage +uv run pytest --cov=src --cov-report=html + +# Format code +uv run ruff format . + +# Check linting +uv run ruff check . + +# Fix linting issues automatically +uv run ruff check --fix . + +# Type checking +uv run mypy src/ + +# Run pre-commit hooks +uv run pre-commit run --all-files +``` + +## πŸ“‹ Style & Conventions + +### Python Style Guide + +- **Follow PEP8** with these specific choices: + - Line length: 100 characters (set by Ruff in pyproject.toml) + - Use double quotes for strings + - Use trailing commas in multi-line structures +- **Always use type hints** for function signatures and class attributes +- **Format with `ruff format`** (faster alternative to Black) +- **Use `pydantic` v2** for data validation and settings management + +### Docstring Standards + +Use Google-style docstrings for all public functions, classes, and modules: + +```python +def calculate_discount( + price: Decimal, + discount_percent: float, + min_amount: Decimal = Decimal("0.01") +) -> Decimal: + """ + Calculate the discounted price for a product. + + Args: + price: Original price of the product + discount_percent: Discount percentage (0-100) + min_amount: Minimum allowed final price + + Returns: + Final price after applying discount + + Raises: + ValueError: If discount_percent is not between 0 and 100 + ValueError: If final price would be below min_amount + + Example: + >>> calculate_discount(Decimal("100"), 20) + Decimal('80.00') + """ +``` + +### Naming Conventions + +- **Variables and functions**: `snake_case` +- **Classes**: `PascalCase` +- **Constants**: `UPPER_SNAKE_CASE` +- **Private attributes/methods**: `_leading_underscore` +- **Type aliases**: `PascalCase` +- **Enum values**: `UPPER_SNAKE_CASE` + +## πŸ§ͺ Testing Strategy + +### Test-Driven Development (TDD) + +1. **Write the test first** - Define expected behavior before implementation +2. **Watch it fail** - Ensure the test actually tests something +3. **Write minimal code** - Just enough to make the test pass +4. **Refactor** - Improve code while keeping tests green +5. **Repeat** - One test at a time + +### Testing Best Practices + +```python +# Always use pytest fixtures for setup +import pytest +from datetime import datetime + +@pytest.fixture +def sample_user(): + """Provide a sample user for testing.""" + return User( + id=123, + name="Test User", + email="test@example.com", + created_at=datetime.now() + ) + +# Use descriptive test names +def test_user_can_update_email_when_valid(sample_user): + """Test that users can update their email with valid input.""" + new_email = "newemail@example.com" + sample_user.update_email(new_email) + assert sample_user.email == new_email + +# Test edge cases and error conditions +def test_user_update_email_fails_with_invalid_format(sample_user): + """Test that invalid email formats are rejected.""" + with pytest.raises(ValidationError) as exc_info: + sample_user.update_email("not-an-email") + assert "Invalid email format" in str(exc_info.value) +``` + +### Test Organization + +- Unit tests: Test individual functions/methods in isolation +- Integration tests: Test component interactions +- End-to-end tests: Test complete user workflows +- Keep test files next to the code they test +- Use `conftest.py` for shared fixtures +- Aim for 80%+ code coverage, but focus on critical paths + +## 🚨 Error Handling + +### Exception Best Practices + +```python +# Create custom exceptions for your domain +class PaymentError(Exception): + """Base exception for payment-related errors.""" + pass + +class InsufficientFundsError(PaymentError): + """Raised when account has insufficient funds.""" + def __init__(self, required: Decimal, available: Decimal): + self.required = required + self.available = available + super().__init__( + f"Insufficient funds: required {required}, available {available}" + ) + +# Use specific exception handling +try: + process_payment(amount) +except InsufficientFundsError as e: + logger.warning(f"Payment failed: {e}") + return PaymentResult(success=False, reason="insufficient_funds") +except PaymentError as e: + logger.error(f"Payment error: {e}") + return PaymentResult(success=False, reason="payment_error") + +# Use context managers for resource management +from contextlib import contextmanager + +@contextmanager +def database_transaction(): + """Provide a transactional scope for database operations.""" + conn = get_connection() + trans = conn.begin_transaction() + try: + yield conn + trans.commit() + except Exception: + trans.rollback() + raise + finally: + conn.close() +``` + +### Logging Strategy + +```python +import logging +from functools import wraps + +# Configure structured logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' +) + +logger = logging.getLogger(__name__) + +# Log function entry/exit for debugging +def log_execution(func): + @wraps(func) + def wrapper(*args, **kwargs): + logger.debug(f"Entering {func.__name__}") + try: + result = func(*args, **kwargs) + logger.debug(f"Exiting {func.__name__} successfully") + return result + except Exception as e: + logger.exception(f"Error in {func.__name__}: {e}") + raise + return wrapper +``` + +## πŸ”§ Configuration Management + +### Environment Variables and Settings + +```python +from pydantic_settings import BaseSettings +from functools import lru_cache + +class Settings(BaseSettings): + """Application settings with validation.""" + app_name: str = "MyApp" + debug: bool = False + database_url: str + redis_url: str = "redis://localhost:6379" + api_key: str + max_connections: int = 100 + + class Config: + env_file = ".env" + env_file_encoding = "utf-8" + case_sensitive = False + +@lru_cache() +def get_settings() -> Settings: + """Get cached settings instance.""" + return Settings() + +# Usage +settings = get_settings() +``` + +## πŸ—οΈ Data Models and Validation + +### Example Pydantic Models strict with pydantic v2 + +```python +from pydantic import BaseModel, Field, validator, EmailStr +from datetime import datetime +from typing import Optional, List +from decimal import Decimal + +class ProductBase(BaseModel): + """Base product model with common fields.""" + name: str = Field(..., min_length=1, max_length=255) + description: Optional[str] = None + price: Decimal = Field(..., gt=0, decimal_places=2) + category: str + tags: List[str] = [] + + @validator('price') + def validate_price(cls, v): + if v > Decimal('1000000'): + raise ValueError('Price cannot exceed 1,000,000') + return v + + class Config: + json_encoders = { + Decimal: str, + datetime: lambda v: v.isoformat() + } + +class ProductCreate(ProductBase): + """Model for creating new products.""" + pass + +class ProductUpdate(BaseModel): + """Model for updating products - all fields optional.""" + name: Optional[str] = Field(None, min_length=1, max_length=255) + description: Optional[str] = None + price: Optional[Decimal] = Field(None, gt=0, decimal_places=2) + category: Optional[str] = None + tags: Optional[List[str]] = None + +class Product(ProductBase): + """Complete product model with database fields.""" + id: int + created_at: datetime + updated_at: datetime + is_active: bool = True + + class Config: + from_attributes = True # Enable ORM mode +``` + +## πŸ”„ Git Workflow + +### Branch Strategy + +- `main` - Production-ready code +- `develop` - Integration branch for features +- `feature/*` - New features +- `fix/*` - Bug fixes +- `docs/*` - Documentation updates +- `refactor/*` - Code refactoring +- `test/*` - Test additions or fixes + +### Commit Message Format + +Never include claude code, or written by claude code in commit messages + +``` +(): + + + +