Py type safety
Portable Python code-review skills for agentskills.io-compatible agents — router plus focused skills for type safety, error handling, anti-patterns, async, and code style
npx -y skills add CodeSigils/py-review-skill --skill py-type-safetyAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
3 things to look at
- 29 days oldThe repository was created 29 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Review Python code for type-safety issues including Any leaks, missing public annotations, unsafe Optional handling, unparameterized collections, imprecise generics, and type-checker configuration drift. Use when reviewing typed Python code, public APIs, dataclasses, protocols, generics, casts, or mypy/pyright configuration.
SKILL.md
4.8 KB, as published. Nobody here has run it
Python Type-Safety Review
Use these rules only after reading the changed code. Prefer findings that would be caught by a type checker or prevent a realistic runtime bug.
Review Rules
Rule: type-public-signatures
Impact: MEDIUM-HIGH Applies when: Public functions, methods, classes, or exported helpers are added or changed. Skip when: The code is private test scaffolding or a throwaway script with no typed boundary. Python: any Tools: mypy | pyright | project-configured Review signal: Public parameters or return values are unannotated, especially at package/API boundaries.
Incorrect:
def find_user(user_id):
return repository.get(user_id)
Correct:
def find_user(user_id: str) -> User | None:
return repository.get(user_id)
Reason: Public annotations make absence and data shape explicit. Without them, callers and type checkers lose the contract at the boundary.
Rule: type-any-leak
Impact: HIGH
Applies when: Any, dict[str, Any], raw JSON, or untyped third-party results cross into domain code.
Skip when: The value remains at a narrow dynamic boundary and is immediately validated or converted.
Python: any
Tools: mypy | pyright | project-configured
Review signal: Any appears in return types, domain objects, or widely reused helper signatures.
Incorrect:
def load_user(payload: dict[str, Any]) -> Any:
return payload["user"]
Correct:
def load_user(payload: Mapping[str, object]) -> User:
return User.model_validate(payload["user"])
Reason: Any disables checking wherever it flows. Convert dynamic data to domain types at boundaries so mistakes stay local.
Rule: type-none-narrowing
Impact: HIGH
Applies when: A value typed as optional is dereferenced, passed onward, or returned as non-optional.
Skip when: The code has an explicit guard, assertion, exception, or early return proving the value is present.
Python: >=3.10
Tools: mypy | pyright | project-configured
Review signal: A T | None value is used without an is None check or equivalent narrowing.
Incorrect:
user = find_user(user_id)
return user.email
Correct:
user = find_user(user_id)
if user is None:
raise UserNotFoundError(user_id)
return user.email
Reason: Optional return types encode a real missing-value path. Narrow before use so both runtime behavior and static analysis agree.
Rule: type-collection-parameters
Impact: MEDIUM
Applies when: Functions return or accept collections.
Skip when: The collection is intentionally heterogeneous and documented as such.
Python: >=3.9
Tools: mypy | pyright | project-configured
Review signal: Bare list, dict, set, tuple, or overly broad Iterable[Any] appears in changed signatures.
Incorrect:
def get_users() -> list:
...
Correct:
def get_users() -> list[User]:
...
Reason: Unparameterized collections hide element types and push errors to consumers.
Rule: type-preserve-generics
Impact: MEDIUM-HIGH
Applies when: A helper, container, decorator, or wrapper should preserve input/output types.
Skip when: The wrapper intentionally erases type information at a narrow dynamic boundary.
Python: any
Tools: mypy | pyright | project-configured
Review signal: A generic helper returns object, Any, or a base class when it can preserve T.
Incorrect:
def first(items: list[object]) -> object:
return items[0]
Correct:
def first[T](items: Sequence[T]) -> T:
return items[0]
Reason: Generic helpers should not throw away information callers already have. Preserving T keeps downstream code type-safe.
References: https://docs.python.org/3/library/typing.html
Checked: 2026-07-07
Expires: 2026-10-01
Sensitive Evidence Safety
If changed code or tool output reveals a suspected credential, token, private key, secret-bearing URL, or other sensitive value, do not quote or reproduce the value. Report only its existence and location. Treat filename and pattern checks as heuristic evidence, not proof that a repository is secret-free.
If the exposure appears credible, make it the first finding, stop lower-priority review, and recommend revocation or rotation. Never place sensitive values in reports, generated examples, or commit subjects or bodies.