python typing + Literal with parameters

  python, python-typing, user-defined-types

I’m trying to build user defined types in python with Literal. The idea is to describe precisely the accepted arguments for a given function. Imagine I work with 2bits str and return an int

def foo(x: str)->int:
   assert len(x)==2
   assert all(map(lambda x:x in ['0', '1'], x))
   return 0

would be a way to enforce this. But I want my typechecker to do the job statically, so I can do something like :

from typing import Literal

ValidEntry = Literal["00", "01", "10", "11"]


def foo(x: ValidEntry)->int:
   return 0

foo("01")
foo("bar")
foo(01)

Calling mypy against the preceding code will raise errors on the last two calls to foo as expected.

My question now : how can I do if I want to define the Byte type. I tried to pass a list of all possible 8 bits words to Literal computed with itertools.product :

from itertools import product
from functools import reduce
from typing import Literal, List


def comb(n):
    tuple2str = lambda t: reduce(lambda x, y: x + y, t, "")
    return [tuple2str(t) for t in product("01", repeat=n)]


Bytes = List[Literal[c] for c in comb(8)]

mypy rejects this. pyright errs with the following messages : "c" is not defined and "Literal['00001001']" is incompatible with "Bytes".

Couldn’t figure a solution from the PEP586. Any hints welcome ! Maybe Literal is not the right way to do this…

Source: Python Questions

LEAVE A COMMENT