How do you get AnyStr.join(Iterable[AnyStr]) to pass type checks?

165 Views Asked by At

The simplest example of what I'm trying to do is

from typing import AnyStr, Iterable

def joiner(delim: AnyStr, objs: Iterable[AnyStr]) -> AnyStr:
    return delim.join(objs)

MyPy doesn't have a problem with this by pyright flags it as an error

/tmp/type_demo.py
  /tmp/type_demo.py:7:27 - error: Argument of type "Iterable[AnyStr@joiner]" cannot be assigned to parameter "__iterable_of_bytes" of type "Iterable[ReadableBuffer]" in function "join"
    "Iterable[AnyStr@joiner]" is incompatible with "Iterable[ReadableBuffer]"
      TypeVar "_T_co@Iterable" is covariant
        Type "str* | bytes*" cannot be assigned to type "ReadableBuffer"
          "str*" is incompatible with protocol "ReadableBuffer"
            "__buffer__" is not present (reportGeneralTypeIssues)
  /tmp/type_demo.py:9:27 - error: Argument of type "Iterable[AnyStr@joiner]" cannot be assigned to parameter "__iterable" of type "Iterable[str]" in function "join"
    "Iterable[AnyStr@joiner]" is incompatible with "Iterable[str]"
      TypeVar "_T_co@Iterable" is covariant
        Type "str* | bytes*" cannot be assigned to type "str"
          "bytes*" is incompatible with "str" (reportGeneralTypeIssues)
2 errors, 0 warnings, 0 informations

As far as I can make out, the error comes from trying to pass Iterable[bytes] to something that expects Iterable[ReadableBuffer]. Is there any way to declare this function that doesn't get reported as an error?

(ReadableBuffer is defined as an alias of Buffer defined here)

1

There are 1 best solutions below

0
nischal sharma On

You can try using the following code instead:

from typing import AnyStr, Iterable
from io import BytesIO

def joiner(delim: AnyStr, objs: Iterable[AnyStr]) -> AnyStr:
    return delim.join(BytesIO(obj.encode()) for obj in objs).getvalue().decode()

This should work without any errors.