type-safety
MANVENDRA-github/agentry/.cursor/rules/python/type-safety.mdc
Python static typing discipline — annotate every signature, run a strict type checker, treat escape hatches as code smells. Apply when working in any Python file. Skip for throwaway scripts and notebooks where the code will not outlive the session.
Cursor rule0 starsChanged 3 months ago
What's in it
- Python type safety
- What strict checking enforces
- When you may be tempted to skip typing
- What to do when the checker catches something
- What you do not do
--- name: type-safety description: Python static typing discipline — annotate every signature, run a strict type checker, treat escape hatches as code smells. Apply when working in any Python file. Skip for throwaway scripts and notebooks where the code will not outlive the session. language: python globs: **/*.py alwaysApply: false --- # Python type safety Python's runtime is dynamic; your development loop does not have to be. A strict type checker catches the class of bug that unit tests miss and refactors introduce. Annotate every function signature and every non-trivial local, then run mypy (`--strict`) or pyright in strict mode in CI. Type safety is not a stretch goal — skip the checker and you give up the one tool that verifies your data actually flows the way you think it does. ## What strict checking enforces - `disallow_untyped_defs` — every function must annotate its parameters and return type. - `disallow_any_generics` — no bare `list`, `dict`, `Callable`; parameterize them (`list[str]`, `dict[str, int]`). - `warn_return_any` — a function annotated to return a concrete type may not silently return `Any`. - `no_implicit_optional` — a parameter defaulting to `None` must be typed `Optional[T]` explicitly, not inferred. - `check_untyped_defs` — the bodies of unannotated functions are still type-checked, not skipped. Treat each one as load-bearing. None of them is a luxury. ## When you may be tempted to skip typing - **"I will annotate it later."** Later does not come. Unannotated code has to be retroactively verified line by line. Type from the first draft. - **"The third-party library has no stubs."** Install its `types-*` package, add a stub from typeshed, or write a thin typed wrapper at the boundary. Not a project-wide `ignore_missing_imports`. - **"It is just glue code."** Glue code is where the shapes disagree and the `KeyError` hides. That is exactly where annotations pay off. - **"CI is failing and the release is due."** The type error is real. Add `# type: ignore[error-code]` with a TODO and a ticket number — never a bare ignore, never a config flag flip. The TODO is the ratchet that brings strictness back. ## What to do when the checker catches something - **`Any` flagged on a value of unknown shape.** `Any` is the hole in the type system — it disables checking on everything it touches. Prefer `object` and narrow with `isinstance`, a `typing.Protocol` for structural typing, or a `TypedDict`/dataclass for a shaped dict. `object` is the strict cousin of `Any`: flexible for the producer, safe for the consumer. - **`None` possible.** Narrow explicitly (`if x is not None:`, an early return, pattern matching). Returning a silent default is rarely correct. - **A generic passed through as `Any`.** Introduce a `TypeVar` so the type flows in and out instead of being erased. - **An untyped third-party call.** Add its stubs or wrap it; use `typing.reveal_type` to confirm the inferred type before you trust it. ## What you do not do - **`Any` to silence an error.** This is type erasure with a hat on. If you must coerce, `cast(T, value)` *after* a runtime `isinstance` check that proves the shape. - **Bare `# type: ignore`.** Use `# type: ignore[error-code]` with a reason comment. It stays scoped to the one error and fails loudly if a different one appears. - **`# type: ignore` on a whole file, or `# mypy: ignore-errors`.** No file is too big to type one expression at a time. - **Relaxing strict flags for a package in `pyproject.toml`/`mypy.ini`.** The most common "temporary" loosening and the hardest to reverse — every value in that module silently degrades to `Any`. - **`cast()` without a runtime check.** A cast is an assertion the checker trusts blindly; if it is wrong, the bug survives to production. Narrow, then cast.
More agent context in MANVENDRA-github/agentry
82 other files this repository gives its agents, the first 60 shown.
CLAUDE.md
Cursor rule
- accessibility.cursor/rules/accessibility.mdc
- api-design.cursor/rules/api-design.mdc
- background-jobs.cursor/rules/background-jobs.mdc
- strict-mode.cursor/rules/bash/strict-mode.mdc
- caching.cursor/rules/caching.mdc
- ci-pipeline-authoring.cursor/rules/ci-pipeline-authoring.mdc
- memory-safety.cursor/rules/c/memory-safety.mdc
- code-review.cursor/rules/code-review.mdc
- concurrency-safety.cursor/rules/concurrency-safety.mdc
- containerization.cursor/rules/containerization.mdc
- continuous-learning.cursor/rules/continuous-learning.mdc
- resource-safety.cursor/rules/cpp/resource-safety.mdc
- nullable-reference-types.cursor/rules/csharp/nullable-reference-types.mdc
- database-transactions.cursor/rules/database-transactions.mdc
- data-modeling.cursor/rules/data-modeling.mdc
- datetime-handling.cursor/rules/datetime-handling.mdc
- error-debugging.cursor/rules/error-debugging.mdc
- eval-harness.cursor/rules/eval-harness.mdc
- feature-flags.cursor/rules/feature-flags.mdc
- git-commit-craft.cursor/rules/git-commit-craft.mdc
- error-handling.cursor/rules/go/error-handling.mdc
- incident-response.cursor/rules/incident-response.mdc
- null-safety.cursor/rules/java/null-safety.mdc
- vanilla-safety.cursor/rules/javascript/vanilla-safety.mdc
- null-safety.cursor/rules/kotlin/null-safety.mdc
- mcp-authoring.cursor/rules/mcp-authoring.mdc
- observability.cursor/rules/observability.mdc
- perf-profiling.cursor/rules/perf-profiling.mdc
- security-essentials.cursor/rules/php/security-essentials.mdc
- powershell-strict-mode.cursor/rules/powershell/powershell-strict-mode.mdc
- rate-limiting.cursor/rules/rate-limiting.mdc
- release-notes.cursor/rules/release-notes.mdc
- resilience.cursor/rules/resilience.mdc
- nil-and-exception-safety.cursor/rules/ruby/nil-and-exception-safety.mdc
- error-handling.cursor/rules/rust/error-handling.mdc
- search-first.cursor/rules/search-first.mdc
- secrets-management.cursor/rules/secrets-management.mdc
- security-review.cursor/rules/security-review.mdc
- session-handoff.cursor/rules/session-handoff.mdc
- injection-safety.cursor/rules/sql/injection-safety.mdc
- strategic-compact.cursor/rules/strategic-compact.mdc
- supply-chain-security.cursor/rules/supply-chain-security.mdc
- optionals-and-memory.cursor/rules/swift/optionals-and-memory.mdc
- tdd-workflow.cursor/rules/tdd-workflow.mdc
- state-and-plan-safety.cursor/rules/terraform/state-and-plan-safety.mdc
- test-writing.cursor/rules/test-writing.mdc
- strict-mode.cursor/rules/typescript/strict-mode.mdc
- verification-loop.cursor/rules/verification-loop.mdc
- config-safety.cursor/rules/yaml/config-safety.mdc
Skill
- accessibility.claude/skills/accessibility/SKILL.md
- api-design.claude/skills/api-design/SKILL.md
- background-jobs.claude/skills/background-jobs/SKILL.md
- caching.claude/skills/caching/SKILL.md
- ci-pipeline-authoring.claude/skills/ci-pipeline-authoring/SKILL.md
- code-review.claude/skills/code-review/SKILL.md
- concurrency-safety.claude/skills/concurrency-safety/SKILL.md
- containerization.claude/skills/containerization/SKILL.md
- continuous-learning.claude/skills/continuous-learning/SKILL.md
- database-transactions.claude/skills/database-transactions/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
No reports yet. Be the first to say whether it worked.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool public_context_discussion, action report. How to connect one.

