We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Interfaces with Protocols and ABCs step 17 of 26
Find Where Any Leaks into Function Signatures
You are about to put a teammate's module under mypy --strict. Strict mode
already rejects a parameter with no annotation and a bare list. It accepts
dict[str, Any] and Callable[..., int], and both let unchecked values in.
Any is a type that turns checking off. mypy accepts any operation on an
Any value and lets it go anywhere. Callable[..., int] accepts a function
that takes any arguments at all.
Say a signature leaks when it lets an unchecked value in. Write an auditor
that lists the public functions whose signatures leak. It reads the source
with Python's ast module, so it never imports or runs the code.
source = '''
from typing import Any
def load(path: str) -> dict[str, Any]: ...
def save(path, data: dict[str, str]) -> None: ...
def count(items: list) -> int: ...
def size(items: list[int]) -> int: ...
def _helper(x): ...
'''
solve(source) # ["count", "load", "save"]
What to write
Fill in the four functions in the starter.
tail_name(node)returnsnode.idfor anast.Name,node.attrfor anast.Attribute, andNonefor anything else.Anyandtyping.Anyboth give"Any".annotation_leaks(annotation)returnsTrueif any node inside the annotation, at any depth, matches one of the three rules below. Sodict[str, list[Any]]leaks anddict[str, list[int]]does not.function_leaks(fn)returnsTrueif a parameter or the return type has no annotation, or if any annotation leaks. Check positional-only, ordinary and keyword-only parameters, plus*argsand**kwargs. A parameter with a default still needs an annotation, and so does the return type of a function that returns nothing.solve(source)parses the source withast.parseand returns the names of the leaking functions insortedorder.
An annotation leaks when it contains any of these:
- A name whose
tail_nameisAny. - A
Callablesubscript whose first argument is the literal..., as inCallable[..., int]. Atuple[int, ...]does not count. - A name from
GENERIC_NAMESthat is not subscripted.listleaks andlist[int]does not. Inlist[list], the innerlistleaks.
Which functions to check
- Check only
defandasync defstatements directly in the module body. Skip methods, nested functions, and functions inside anifortry. - Skip names that start with an underscore.
- If two definitions share a name and both leak, list the name twice.
- An empty source gives
[]. Let aSyntaxErrorpropagate.
Match by name only
Treat every Any alike, whichever module it comes from, and keep
GENERIC_NAMES exactly as the starter gives it.
Leave string annotations alone. To ast, the "Any" in x: "Any" is a
string constant, so it does not leak.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.