> ## Documentation Index
> Fetch the complete documentation index at: https://docs.muna.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Python Style Guide

> How we author Python code.

This document outlines the Python coding standards and conventions used across Muna.

## General Principles

* **Readability**: Code should be clear and self-documenting.
* **Consistency**: Follow established patterns throughout the codebase.
* **Type Safety**: Use comprehensive type annotations.
* **Modularity**: Keep functions and classes focused on single responsibilities.
* **Performance**: Consider efficiency in compiler-related code.

## File Structure and Organization

This section covers how to structure Python files, organize imports, and arrange code within modules to maintain clarity and consistency.

<AccordionGroup>
  <Accordion title="File Headers">
    All Python files must start with the standard copyright header:

    ```python icon="python" theme={null}
    #
    #   Muna
    #   Copyright © 2025 NatML Inc. All Rights Reserved.
    #
    ```
  </Accordion>

  <Accordion title="Import Organization">
    Imports should be organized in the following order:

    ```python icon="python" theme={null}
    # 1. Future imports
    from __future__ import annotations

    # 2. Standard library imports (alphabetical)
    from abc import ABC, abstractmethod
    from collections.abc import Callable
    from pathlib import Path

    # 3. Third-party imports (alphabetical)
    from pydantic import BaseModel
    from yaml import safe_load

    # 4. Local/project imports (alphabetical, relative imports last)
    from .schema import Operator
    ```
  </Accordion>

  <Accordion title="Module Structure">
    Prefer structuring modules sequentially:

    ```python icon="python" theme={null}
    # 1. Copyright header
    # 2. Future imports
    # 3. Other imports
    # 4. Module-level constants
    # 5. Exception classes
    # 6. Data classes/models
    # 7. Function definitions
    # 8. Class definitions
    # 9. Main execution block (if applicable)
    ```
  </Accordion>
</AccordionGroup>

## Imports

We use specific imports rather than wildcards, always include `from __future__ import annotations` when needed, and organize imports in four distinct groups with alphabetical ordering within each group. Related imports are grouped together, and we prefer absolute imports for clarity.

<AccordionGroup>
  <Accordion title="Import Style">
    * Use `from __future__ import annotations` at the top of files that use forward references
    * Prefer specific imports over wildcard imports
    * Group related imports together
    * Use absolute imports for clarity

    Example:

    ```python icon="python" theme={null}
    # Good: Absolute imports
    from __future__ import annotations
    from pathlib import Path
    from typing import Iterator

    # Good: Relative imports
    from ..foo import SomeType, AnotherType
    from .schema import SomeModel

    # Bad
    from pathlib import *
    from ..foo import *
    ```
  </Accordion>
</AccordionGroup>

## Naming Conventions

We use `snake_case` for variables and functions, `PascalCase` for classes, `UPPER_SNAKE_CASE` for constants, and single leading underscores for private members. Names should be descriptive and avoid abbreviations unless they're well-known in the domain.

<AccordionGroup>
  <Accordion title="Variables and Functions">
    * Use `snake_case` for variables, functions, and module names
    * Use descriptive names that clearly indicate purpose
    * Avoid abbreviations unless they're well-known

    ```python icon="python" theme={null}
    # Good
    def get_function_signature(func: Callable[..., object]) -> Signature:
        ...

    # Avoid
    def get_func_sig(f):
        ...
    ```
  </Accordion>

  <Accordion title="Classes">
    * Use `PascalCase` for class names
    * Use descriptive names that indicate the class purpose

    ```python icon="python" theme={null}
    class CompileError(Exception):
        pass
    ```
  </Accordion>

  <Accordion title="Constants">
    * Use `UPPER_SNAKE_CASE` for module-level constants
    * Group related constants together

    ```python icon="python" theme={null}
    SDK_VERSION = "2.34.0.250424"
    GOOGLE_URL = f"https://www.google.com"
    ```
  </Accordion>

  <Accordion title="Private Members">
    * Use single leading underscore for internal functions/methods
    * Use double leading underscore for name mangling when necessary

    ```python icon="python" theme={null}
    def _generate_sample_data(count: int) -> list[SampleItem]:
        pass

    class _TensorSpec(BaseModel):
        pass
    ```
  </Accordion>
</AccordionGroup>

## Function and Class Definitions

We requrie comprehensive type annotations on functions and classes. We use keyword-only arguments for optional parameters, and
group logically.

<AccordionGroup>
  <Accordion title="Function Signatures">
    * Always include type annotations for parameters and return values
    * Use keyword-only arguments for optional parameters when appropriate
    * Group related parameters together

    ```python icon="python" theme={null}
    # Good: Fully annotate parameter and return types
    def process_data(items: list[str]) -> list[str]:
        return items

    # Good: Use keyword-only arguments for optional parameters when appropriate
    def compile(
        source: SourceCode,
        *,
        src_dir: Path=Path("src"),
        build_dir: Path=Path("build"),
        config: BuildConfig="MinSizeRel",
    ) -> CompiledCode | None:
    ```
  </Accordion>

  <Accordion title="Class Definitions">
    * Inherit from appropriate base classes (`ABC`, `BaseModel`, etc.)
    * Use abstract methods when defining interfaces
    * Include type annotations for class attributes

    ```python icon="python" theme={null}
    # Good: Inherit from an appropriate base class
    class Database(ABC):

        # Good: Use abstract methods when defining interfaces
        @abstractmethod
        def search(
            self,
            query: str,
            *,
            limit: int = 10
        ) -> list[Item]:
            """
            Search for items given a query
            """
            pass
    ```
  </Accordion>
</AccordionGroup>

## Type Annotations

We use comprehensive type annotations throughout the codebase.
All function parameters, return types, and class attributes must be annotated.

<AccordionGroup>
  <Accordion title="Basic Types">
    Use built-in types and typing module for annotations:

    ```python icon="python" theme={null}
    from typing import Iterator, Literal
    from collections.abc import Callable

    def process_items(items: list[str]) -> Iterator[str]:
        pass

    def create_model(backend: Literal["cpu", "gpu", "htp"]) -> Model:
        pass
    ```
  </Accordion>

  <Accordion title="Union Types">
    Use the pipe `|` syntax for union types (Python 3.10+):

    ```python icon="python" theme={null}
    def get_result() -> str | None:
        pass

    def process_value(value: int | float) -> float:
        pass
    ```
  </Accordion>

  <Accordion title="Generic Types">
    Make sure to specify type arguments for generic types:

    ```python icon="python" theme={null}
    # Good: Specify generic type arguments
    def sum(value: list[int]) -> int:
        return value

    # Bad: No generic type arguments for generic type
    def sum(value: list) -> int:
        return value
    ```
  </Accordion>

  <Accordion title="Forward References">
    Prefer using `from __future__ import annotations` for forward references over string annotations:

    ```python icon="python" theme={null}
    from __future__ import annotations

    class Node:

        # Good: Use type annotation
        def __init__(self, parent: Node | None = None):
            self.parent = parent

        # Bad: Using string annotations
        def __init__(self, parent: "Node" | None = None):
            self.parent = parent
    ```
  </Accordion>
</AccordionGroup>

## Comments and Docstrings

We encourage the use of comments and docstrings to provide context around code.

<AccordionGroup>
  <Accordion title="Docstrings">
    Use triple-quoted strings for docstrings. Follow Google-style format:

    ```python icon="python" theme={null}
    def detect_objects(
        image: Image.Image
        *,
        min_score: float=0.3,
        max_iou: float=0.5
    ) -> list[Detection]:
        """
        Detect objects in an image.

        Parameters:
            image (PIL.Image): Input image
            min_score (float): Minimum detection score.
            max_iou (float): Maximum IoU.

        Returns:
            list: Detected objects.
        """
    ```
  </Accordion>

  <Accordion title="Inline Comments">
    * Use comments sparingly for complex logic
    * Prefer self-documenting code over comments
    * Use `# CHECK` for areas that need review
    * Use `# INCOMPLETE` for unfinished functionality

    ```python icon="python" theme={null}
    # CHECK # This might have issues with complex nested structures
    if isinstance(value, dict):
        process_dict(value)

    # INCOMPLETE # Add support for additional tensor types
    tensor_type = get_basic_tensor_type(input_tensor)
    ```
  </Accordion>
</AccordionGroup>

## Code Formatting

We write highly ergonomic code that is easy to both look at and reason about:

<AccordionGroup>
  <Accordion title="Line Length">
    * Maximum line length: 120 characters
    * Break long lines using parentheses for natural grouping

    ```python icon="python" theme={null}
    # Good: Long list declarations over multiple lines
    shell_args = [
        f"echo",
        f"'Hello world'",
    ]

    # Good: Long function calls over multiple lines
    result = some_long_function_name(
        first_argument,
        second_argument,
        third_argument
    )
    ```
  </Accordion>

  <Accordion title="Spacing">
    * Use 4 spaces for indentation
    * No trailing whitespace
    * Single blank line between function and class definitions
    * No spaces around `=` in keyword arguments

    ```python icon="python" theme={null}
    def function_one():
        pass

    def function_two():
        pass

    class FirstClass:
        pass

    class SecondClass:
        pass
    ```
  </Accordion>

  <Accordion title="Block Comments">
    * Use comments to separate logical blocks within functions or methods instead of empty lines:

    ```python icon="python" theme={null}
    def process_model(model_path: Path) -> ProcessedModel:
        # Load and validate model
        model = load_model(model_path)
        validate_model_format(model)
        # Process model layers
        layers = extract_layers(model)
        optimized_layers = optimize_layers(layers)
        # Generate output
        processed_model = create_processed_model(optimized_layers)
        return processed_model
    ```
  </Accordion>

  <Accordion title="String Formatting">
    * Use f-strings for string interpolation
    * Use double quotes for strings consistently
    * Use triple double quotes for multiline strings

    ```python icon="python" theme={null}
    # Use double quotes for string literals
    greeting = "Hello and have a nice day!"

    # Use F-strings for string interpolation
    sql_query = f"SELECT * FROM {table_name} WHERE id = {item_id}"

    # Use triple double quotes for multiline strings
    template = """
    This is a multiline
    string template with {variable}.
    """
    ```
  </Accordion>
</AccordionGroup>

## Error Handling

We encourage defining a small set of custom exception types that can be explicitly handled:

<AccordionGroup>
  <Accordion title="Exception Classes">
    * Create specific exception classes for different error types:

    ```python icon="python" theme={null}
    class CompileError(Exception):
        """
        Compile error.
        """
    ```
  </Accordion>

  <Accordion title="Error Messages">
    * Provide clear, actionable error messages
    * Include context about what failed and why

    ```python icon="python" theme={null}
    if param_type is None:
        raise CompileError(
            f"Missing type annotation for parameter `{name}` in "
            f"function [hot_pink]{func.__name__}[/hot_pink]."
        )
    ```
  </Accordion>

  <Accordion title="Exception Handling">
    * Catch specific errors when it makes sense to do so.
    * When propagating errors from an exception handler, chain exceptions with `raise ... from ex` to preserve context.

    ```python icon="python" theme={null}
    try:
        result = risky_operation()
    except SpecificError as ex:
        logger.error(f"Operation failed: {ex}")
        raise CompileError(f"Failed to process: {ex}") from ex
    except Exception as ex:
        logger.exception("Unexpected error")
        raise
    ```
  </Accordion>
</AccordionGroup>

## Testing

Tests follow the Arrange-Act-Assert pattern with comments, and are
organized in a `test/` directory that mirrors the source code structure.

<AccordionGroup>
  <Accordion title="Test Structure">
    * Use descriptive test function names with `test_` prefix
    * Group related tests in classes
    * Use clear assertions

    ```python icon="python" theme={null}
    def test_add_two_numbers():
        # Arrange
        num_a = 9
        num_b = 10
        # Act
        result = num_a + num_b
        # Assert
        assert result == 21
    ```
  </Accordion>

  <Accordion title="Test Files">
    * Test files should end with `_test.py`
    * Place tests in a `test/` directory
    * Mirror the source code structure in test organization
  </Accordion>
</AccordionGroup>

## Dependencies

We prefer well-maintained packages with pinned versions for critical dependencies, use optional import patterns with try/except blocks for non-critical features, and favor relative imports for internal modules.

<AccordionGroup>
  <Accordion title="External Dependencies">
    * Prefer well-maintained, widely-used packages
    * Pin versions for critical dependencies
    * Use optional imports for non-critical features

    ```python icon="python" theme={null}
    # Optional import pattern
    try:
        from onnxruntime import InferenceSession
    except ImportError:
        InferenceSession = None

    def onnx_model_inference(model):
        if InferenceSession and isinstance(model, InferenceSession):
            # Handle ONNX model
            pass
    ```
  </Accordion>

  <Accordion title="Internal Dependencies">
    * Use relative imports for internal modules
    * Keep dependencies between modules minimal
    * Avoid circular imports
  </Accordion>
</AccordionGroup>
