Skip to content

Commit 5be0765

Browse files
docs(python): document import block blank-line conventions
Specify single blank lines between __future__, stdlib, third-party, local, relative, and TYPE_CHECKING blocks, plus two blank lines after imports before module body content. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 8340463 commit 5be0765

1 file changed

Lines changed: 30 additions & 6 deletions

File tree

.ai/rules/code/Python/0-general-Python-code-guidance.md

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -602,8 +602,10 @@ def _get_point_role_and_aspect_type_caches(
602602
1. **Future imports** (if needed): `from __future__ import annotations`
603603
2. **Standard library imports**: `import argparse`, `import json`, `from pathlib import Path`
604604
3. **Third-party imports**: `import pandas as pd`, `from tqdm import tqdm`
605-
4. **Internal/local imports**: `from autonomous_building import ...`
606-
5. **Within each group**: **MANDATORY** - Alphabetical ordering (unless explicitly instructed/overridden otherwise)
605+
4. **Internal/local imports**: absolute imports from the current project/package (e.g. `from autonomous_building import ...`, `from agent_neo.graph import ...`)
606+
5. **Relative local imports** (when used): same-package relative imports (e.g. `from .enum import GraphEdgeKind`, `from .._django import Agent`)
607+
6. **`TYPE_CHECKING` imports** (when used): the `if TYPE_CHECKING:` block and its indented imports — always **last** in the import section
608+
7. **Within each group**: **MANDATORY** - Alphabetical ordering (unless explicitly instructed/overridden otherwise)
607609

608610
**Example of good practice**:
609611
```python
@@ -643,11 +645,12 @@ import argparse
643645
- **Maintainability**: Clear separation between stdlib, third-party, and internal code
644646

645647
### Import Grouping Rules
646-
- **Group by source**: Standard library, third-party, internal
647-
- **Separate groups**: Use blank lines between groups (one blank line is sufficient)
648+
- **Group by source**: `__future__` → standard library → third-party → internal/local (absolute) → relative local → `TYPE_CHECKING`
649+
- **Separate groups with single blank lines**: Put **exactly one blank line** between each import block listed above. Do not run adjacent groups together (e.g. never place `from typing import ...` immediately above `from django...` without a blank line between them).
650+
- **Two blank lines after imports**: After the final import block (including a trailing `if TYPE_CHECKING:` block when present), put **two blank lines** before the next module content (`__all__`, module-level constants, type aliases, or class/function definitions).
648651
- **Group comments**: **RECOMMENDED** - Add comments identifying each import group for clarity (e.g., `# Standard library imports (alphabetical)`, `# Third-party imports (alphabetical)`, `# Internal imports (alphabetical)`)
649652
- **Within groups**: **MANDATORY** - Alphabetical ordering (unless explicitly instructed/overridden otherwise)
650-
- **Relative vs absolute**: Use absolute imports for cross-package imports, relative imports for same-package modules. **Within internal imports group**: Absolute imports come first, then relative imports (both alphabetically ordered within their respective subgroups)
653+
- **Relative vs absolute**: Use absolute imports for cross-package imports; use relative imports for same-package modules. **Order**: absolute internal/local imports first, then relative local imports (each subgroup alphabetically ordered). Do not mix third-party imports into the local/relative groups.
651654
- **Organize large import lists**: For large import lists (e.g., many query constants), use comments to group related imports for readability
652655
- **Pattern**: `# Group name` comment before related imports
653656
- **When to use**: When importing 10+ items from a single module, especially when they can be logically grouped
@@ -674,7 +677,7 @@ import inspect
674677
import json
675678
import os
676679
from pathlib import Path
677-
from typing import Any, Literal, LiteralString
680+
from typing import TYPE_CHECKING, Any, Literal, LiteralString
678681
from uuid import UUID
679682

680683
# Third-party imports (alphabetical)
@@ -684,7 +687,28 @@ from dana.core.agent.star_agent import STARAgent
684687
from ORION.ontology.physical._django.models import AssetName, PointName, SpatialElementName
685688
from ORION.util.llm import DEFAULT_LLM_PROVIDER, DEFAULT_LLM, DEFAULT_MAX_CONTEXT_TOKENS
686689

690+
# Relative local imports (alphabetical)
687691
from .._django import Agent as AgentInDb, ProblemSolvingSession
692+
693+
if TYPE_CHECKING:
694+
from rest_framework.viewsets import ReadOnlyModelViewSet
695+
696+
697+
__all__ = [
698+
"DEFAULT_LLM",
699+
"STARAgent",
700+
]
701+
```
702+
703+
**Example of bad practice** (DO NOT USE):
704+
```python
705+
from __future__ import annotations
706+
from typing import Any
707+
from django.db import models
708+
from agent_neo.graph.queries import GraphDbQueryAndReturnHeaderList
709+
if TYPE_CHECKING:
710+
from rest_framework.viewsets import ReadOnlyModelViewSet
711+
type Row = list[Any]
688712
```
689713

690714
**Benefits of Group Comments:**

0 commit comments

Comments
 (0)