Skip to content
Advertisement

How do I annotate a function that takes AnyStr with a str default value?

I wish to type-annotate a function that takes an AnyStr argument that defaults to a str and also returns an AnyStr of the same type. However, if I write this:

from typing import AnyStr

def func(s: AnyStr = ".") -> AnyStr:
    return s

then mypy fails with “Incompatible default for argument "s" (default has type "str", argument has type "bytes")“.

I also tried splitting the code into a .py and .pyi file like so:

.py file:

def func(s = "."):
    return s

.pyi file:

from typing import AnyStr

def func(s: AnyStr = ...) -> AnyStr:
    ...

… but I must be invoking mypy wrong, because it fails to type-check the invocations of func; e.g., if I add func(42) to the .py file, mypy doesn’t complain.

What is the correct way to annotate my function and get the code to be completely type-checked?

Advertisement

Answer

Use None as the default value, then inside the function use two casts: one to replace None with “.” cast as an Optional[AnyStr], and one to cast the return value as an AnyStr.

def func(s : AnyStr = None) -> AnyStr:
    if s is None:
        s = cast(Optional[AnyStr], ".")
    return cast(AnyStr, s)

EDIT: My original answer fails, as the type check ignores the concrete implementation:

One possibility is to use overload to enumerate the two cases covered by AnyStr:

from typing import overload


@overload
def func(s: str = ".") -> str:
    pass


@overload
def func(s: bytes) -> bytes:
    pass


def func(s):
    return s 
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement