Files
mistral-vibe/AGENTS.md
Clément Drouin e1a25caa52 v2.7.5 (#589)
Co-authored-by: Bastien <bastien.baret@gmail.com>
Co-authored-by: Clément Sirieix <clement.sirieix@mistral.ai>
Co-authored-by: Julien Legrand <72564015+JulienLGRD@users.noreply.github.com>
Co-authored-by: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com>
Co-authored-by: Mathias Gesbert <mathias.gesbert@mistral.ai>
Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai>
Co-authored-by: Quentin <quentin.torroba@mistral.ai>
Co-authored-by: Vincent G <10739306+VinceOPS@users.noreply.github.com>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
2026-04-14 10:33:15 +02:00

9.4 KiB

python312.rule

Rule for enforcing modern Python 3.12+ best practices.

Applies to all Python files (*.py) in the project.

Guidelines covered:

- Use match-case syntax instead of if/elif/else for pattern matching.

- Use the walrus operator (:=) when it simplifies assignments and tests.

- Favor a "never nester" approach by avoiding deep nesting with early returns or guard clauses.

- Employ modern type hints using built-in generics (list, dict) and the union pipe (|) operator,

rather than deprecated types from the typing module (e.g., Optional, Union, Dict, List).

- Ensure code adheres to strong static typing practices compatible with static analyzers like pyright.

- Favor pathlib.Path methods for file system operations over older os.path functions.

- Write code in a declarative and minimalist style that clearly expresses its intent.

- Additional best practices including f-string formatting, comprehensions, context managers, and overall PEP 8 compliance.

description: "Modern Python 3.12+ best practices and style guidelines for coding." files: "**/*.py"

guidelines:

  • title: "Match-Case Syntax" description: > Prefer using the match-case construct over traditional if/elif/else chains when pattern matching is applicable. This leads to clearer, more concise, and more maintainable code.

  • title: "Walrus Operator" description: > Utilize the walrus operator (:=) to streamline code where assignment and conditional testing can be combined. Use it judiciously when it improves readability and reduces redundancy.

  • title: "Never Nester" description: > Aim to keep code flat by avoiding deep nesting. Use early returns, guard clauses, and refactoring to minimize nested structures, making your code more readable and maintainable.

  • title: "Modern Type Hints" description: > Adopt modern type hinting by using built-in generics like list and dict, along with the pipe (|) operator for union types (e.g., int | None). Avoid older, deprecated constructs such as Optional, Union, Dict, and List from the typing module.

  • title: "Strong Static Typing" description: > Write code with explicit and robust type annotations that are fully compatible with static type checkers like pyright. This ensures higher code reliability and easier maintenance.

  • title: "Pydantic-First Parsing" description: > Prefer Pydantic v2's native validation over ad-hoc parsing. Use model_validate, field_validator, from_attributes, and field aliases to coerce external SDK/DTO objects. Avoid manual getattr/hasattr flows and custom constructors like from_sdk unless they are thin wrappers over model_validate. Keep normalization logic inside model validators so call sites remain declarative and typed.

  • title: "Pathlib for File Operations" description: > Favor the use of pathlib.Path methods for file system operations. This approach offers a more readable, object-oriented way to handle file paths and enhances cross-platform compatibility, reducing reliance on legacy os.path functions.

  • title: "Declarative and Minimalist Code" description: > Write code that is declarative—clearly expressing its intentions rather than focusing on implementation details. Strive to keep your code minimalist by removing unnecessary complexity and boilerplate. This approach improves readability, maintainability, and aligns with modern Python practices.

  • title: "Additional Best Practices" description: > Embrace other modern Python idioms such as:

    • Using f-strings for string formatting.
    • Favoring comprehensions for building lists and dictionaries.
    • Employing context managers (with statements) for resource management.
    • Following PEP 8 guidelines to maintain overall code style consistency.
  • title: "Exception Documentation" description: > Document exceptions accurately and minimally in docstrings:

    • Only document exceptions that are explicitly raised in the function implementation
    • Remove Raises entries for exceptions that are not directly raised
    • Include all possible exceptions from explicit raise statements
    • For public APIs, document exceptions from called functions if they are allowed to propagate
    • Avoid documenting built-in exceptions that are obvious (like TypeError from type hints) This ensures documentation stays accurate and maintainable, avoiding the common pitfall of listing every possible exception that could theoretically occur.
  • title: "Modern Enum Usage" description: > Leverage Python's enum module effectively following modern practices:

    • Use StrEnum for string-based enums that need string comparison
    • Use IntEnum/IntFlag for performance-critical integer-based enums
    • Use auto() for automatic value assignment to maintain clean code
    • Always use UPPERCASE for enum members to avoid name clashes
    • Add methods to enums when behavior needs to be associated with values
    • Use @property for computed attributes rather than storing values
    • For type mixing, ensure mix-in types appear before Enum in base class sequence
    • Consider Flag/IntFlag for bit field operations
    • Use generate_next_value for custom value generation
    • Implement bool when enum boolean evaluation should depend on value This promotes type-safe constants, self-documenting code, and maintainable value sets.
  • title: "No Inline Ignores" description: > Do not use inline suppressions like # type: ignore[...] or # noqa[...] in production code. Instead, fix types and lint warnings at the source by:

    • Refining signatures with generics (TypeVar), Protocols, or precise return types
    • Guarding with isinstance checks before attribute access
    • Using typing.cast when control flow guarantees the type
    • Extracting small helpers to create clearer, typed boundaries If a suppression is truly unavoidable at an external boundary, prefer a narrow, well-typed wrapper over in-line ignores, and document the rationale in code comments.
  • title: "Pydantic Discriminated Unions" description: > When modeling variants with a discriminated union (e.g., on a transport field), do not narrow a field type in a subclass (e.g., overriding transport: Literal['http'] with Literal['streamable-http']). This violates Liskov substitution and triggers type checker errors due to invariance of class attributes. Prefer sibling classes plus a shared mixin for common fields and helpers, and compose the union with Annotated[Union[...], Field(discriminator='transport')]. Example pattern:

    • Create a base with shared non-discriminator fields (e.g., _MCPBase).
    • Create a mixin with protocol-specific fields/methods (e.g., _MCPHttpFields), without a transport.
    • Define sibling final classes per variant (e.g., MCPHttp, MCPStreamableHttp, MCPStdio) that set transport: Literal[...] once in each final class.
    • Use match on the discriminator to narrow types at call sites.
  • title: "Use uv for All Commands" description: > We use uv to manage our python environment. You should never try to run bare python commands. Always run commands using uv instead of invoking python or pip directly. For example, use uv add package and uv run script.py rather than pip install package or python script.py. This practice helps avoid environment drift and leverages modern Python packaging best practices. Useful uv commands are:

    • uv add/remove to manage dependencies
    • uv sync to install dependencies declared in pyproject.toml and uv.lock
    • uv run script.py to run a script within the uv environment
    • uv run pytest (or any other python tool) to run the tool within the uv environment
  • title: "Safe File Reading" description: > When reading files from disk, prefer the helpers in vibe.core.utils.io over raw Path.read_text(), Path.read_bytes().decode(), or open() calls:

    • read_safe(path) — synchronous read with automatic encoding detection.
    • read_safe_async(path) — async equivalent (anyio-based).
    • decode_safe(raw) — decode an already-read bytes object. These functions try UTF-8 first, then BOM detection, the locale encoding, and charset_normalizer (lazily, only when cheaper candidates fail). They return a ReadSafeResult(text, encoding) so callers always get valid str output without having to handle encoding errors manually. Use raise_on_error=True only when the caller must distinguish corrupt files from valid ones; the default (False) replaces undecodable bytes with U+FFFD.
  • title: "Imports in Cursor (no Pylance)" description: > Cursor's built-in Pyright does not offer the "Add import" quick fix (Ctrl+.). To add a missing import:

    • Use the workspace snippets: type the prefix (e.g. acpschema, acphelpers, vibetypes, vibeconfig) and accept the suggestion to insert the import line, then change the symbol name.
    • Or ask Cursor: select the undefined symbol, then Cmd+K and request "Add the missing import for ".
    • Or copy the import from an existing file in the repo (e.g. acp.schema, acp.helpers, vibe.core.*).