Python Style Guide

Principles (so far)

  1. Clean > Clever - Readability first

  2. Document Why - Explain reasoning, not implementation

Naming

# snake_case for modules, functions
continuity/core/mailbox.py
def read_mailbox_messages() -> List[Dict]:

# PascalCase for classes  
class MailboxManager:

# UPPER_CASE for constants
DEFAULT_MAILBOX_PATH = "~/.continuity"

# _underscore for private
def _parse_metadata() -> Dict:

Import Style

All imports MUST be at the top of the file:

# Standard library imports first
import json
import os
import sys
from pathlib import Path
from typing import Optional, Dict, List

# Third-party imports
import click
from rich.console import Console

# Local imports
from ...core.role import Role
from ...core.mailbox import Message

Rules:

  • All imports at file top (never inside functions)

  • Group: stdlib, third-party, local

  • Use absolute imports for clarity

Type Hints

Required for all functions:

def process_message(
    message_path: Path,
    validate: bool = True
) -> Optional[Dict[str, str]]:
    """Process and return message data."""
    pass

Documentation

Document public APIs:

def move_to_read(message_path: str) -> bool:
    """Move message to read folder.
    
    Args:
        message_path: Path to message file
        
    Returns:
        True if successful
    """

Error Handling

# Specific exceptions
class MailboxError(Exception):
    """Base exception for mailbox operations."""

# Log and handle gracefully
try:
    result = process_message(path)
except FileNotFoundError:
    logger.warning(f"Message not found: {path}")
    return None

Key Patterns

Files:

from pathlib import Path

with file_path.open('r', encoding='utf-8') as f:
    content = f.read()

Logging:

import logging
logger = logging.getLogger(__name__)

logger.info(f"Processing {len(messages)} messages")

Testing:

import unittest

class TestMailboxManager(unittest.TestCase):
    def test_read_empty_mailbox(self):
        messages = self.manager.read_messages()
        self.assertEqual(messages, [])

Rules

Do:

  • All imports at top of file

  • Type hints on all functions

  • pathlib.Path for files

  • Context managers for resources

  • Specific exception types

  • Log important operations

  • Test all functionality

Don’t:

  • Imports inside functions

  • Bare except clauses

  • Functions > 50 lines

  • Global variables

  • Hardcoded paths

  • print() instead of logging