---
paths:
  - "*/src/**/*.py"
  - "*/tests/**/*.py"
---

# Code Conventions

Concrete patterns for imports, exports, docstrings, and code organization across codeflash packages.

## Import Conventions

Every file starts the same way:

```python
from __future__ import annotations

import logging
import sys

from collections.abc import Callable, Iterator, Sequence
from contextlib import suppress
from typing import Any, TypeVar, overload

import attrs

from ._core import Registry
from .exceptions import ServiceNotFoundError
```

**Order:**
1. `from __future__ import annotations` (always)
3. Blank line
4. Standard library imports (single names first, then `from` imports)
5. Blank line
6. Third-party imports
7. Blank line
8. Local imports (relative, using `.`)

**Rules:**
- One blank line between import groups (configured via `lines-between-types = 1`)
- Two blank lines after all imports (`lines-after-imports = 2`)
- Use `from collections.abc import ...` not `from typing import ...` for ABC types
- Use `typing.Any`, `typing.TypeVar`, `typing.overload` from typing
- Relative imports for intra-package (`from ._core import X`)
- Absolute imports for everything else

## The Sentinel Pattern

When `None` is a valid value and a "not set" marker is needed:

```python
class _Sentinel:
    def __init__(self, bool_: bool = True) -> None:
        self._bool = bool(bool_)

    def __bool__(self) -> bool:
        return self._bool

PREFIX_NOT_SET = _Sentinel(False)
```

## The Clean Re-export

```python
# __init__.py
from ._core import BoundLogger, get_logger, configure
from .exceptions import ServiceNotFoundError

__all__ = [
    "BoundLogger",
    "configure",
    "get_logger",
    "ServiceNotFoundError",
]
```

Explicit `__all__` in `__init__.py`. Users import from the package, never from submodules. The re-export is the public API contract.

## Docstring Format

```python
def bind(self, **new_values: Any) -> Self:
    """
    Return a new logger with *new_values* added to the existing ones.
    """
```

Three lines minimum. Opening `"""` on its own line. Summary is a complete sentence starting with a verb. Closing `"""` on its own line. Use `*arg_name*` (RST emphasis) to reference parameters inline.

## Writing Code Workflow

When writing new code, follow this order:

1. Start with the public API. What will users import? Write `__init__.py` first.
2. Define data types as frozen attrs classes. Think about what's immutable.
3. Put implementation in `_core.py`. The underscore is intentional.
4. Write focused exception classes in `exceptions.py`.
5. Add type annotations everywhere. Run mypy strict mentally — would this pass?
6. Write docstrings in the three-line format: opening `"""`, summary, closing `"""`.
7. Keep functions short. If it needs a comment explaining a block, extract a function.
8. Prefer returning new objects over mutating existing ones.

## Logging Setup

```python
import logging

log = logging.getLogger(__name__)
```

One line. Module-level. `__name__` for the logger name. No configuration in libraries — that's the application's job.

## TYPE_CHECKING Import Pattern

Ruff TC001/TC003 requires imports used only in annotations to live inside `if TYPE_CHECKING`:

```python
from __future__ import annotations

from typing import TYPE_CHECKING

import attrs

from ._model import FunctionToOptimize  # used at runtime → stays outside

if TYPE_CHECKING:
    from pathlib import Path  # only in annotations → goes here
```

This avoids circular imports and reduces import-time cost. Requires `from __future__ import annotations` to work (annotations become strings, not evaluated at runtime).
