# Code Style — grafeo-langchain

## Formatting

- **Line length:** 120 characters
- **Formatter:** ruff format (black-compatible)
- **Import sorting:** ruff (isort-compatible, rule `I`)
- **Target:** Python 3.12+

## Ruff Rules

```toml
select = ["E", "F", "W", "I", "UP", "B", "SIM", "RUF"]
```

- **E/W/F** — pycodestyle + pyflakes basics
- **I** — isort import ordering
- **UP** — pyupgrade (use modern Python syntax)
- **B** — bugbear (common pitfalls)
- **SIM** — simplify (reduce unnecessary complexity)
- **RUF** — ruff-specific rules

## Naming

- **Modules:** snake_case (`graph_store.py`, `embeddings.py`)
- **Functions:** snake_case (`upsert_node`, `mmr_select`)
- **Classes:** PascalCase (`GrafeoGraphStore`, `GrafeoVectorStore`)
- **Constants:** UPPER_SNAKE_CASE (`DEFAULT_COLLECTION`)
- **Private helpers:** prefix with `_` (e.g. `_upsert_node`, `_mmr_select`)
- **Type aliases:** PascalCase

## Imports

Standard ordering (enforced by ruff `I`):

```python
from __future__ import annotations          # 1. future (always)

import os                                    # 2. stdlib
from collections.abc import Sequence

import grafeo                                # 3. third-party
from langchain_core.vectorstores import VectorStore

from grafeo_langchain.graph_store import G   # 4. local
```

## Type Annotations

- `from __future__ import annotations` at the top of every module.
- Use modern syntax: `list[str]`, `dict[str, Any]`, `X | None` (not `Optional[X]`).
- Type hints on public APIs; skip for internal helpers.
- Keyword-only for optional parameters (use `*`).
- No `# type: ignore` — fix the actual types.
- Type checker: `ty` (Astral).

## Docstrings

- One-line summary, extended description if needed.
- Required on public classes and non-obvious public methods.
- Skip for internal helpers and trivial/obvious methods.
- Minimal comments — explain *why*, not *what*.
- Class docstring should include constructor parameters when non-obvious.

## Error Handling

- Let exceptions propagate naturally; don't catch-and-silence.
- Use specific exception types from grafeo/langchain where available.
- Validate at boundaries (public method inputs), trust internals.

## Tests

- Framework: pytest
- Test files mirror source: `test_graph_store.py` tests `graph_store.py`
- Use fixtures in `conftest.py` for shared setup (db instances, embeddings).
- Prefer in-memory databases for tests (no `db_path` argument).
- Test names: `test_<method>_<scenario>`
