'Check if string is in string literal type

We use static type checking extensively, but we also need some simple runtime type checking. I'd love to use our static types for that runtime type checking. I've seen typeguard and the other libraries, but I'd prefer to have something simpler.

I've tried below, but assert value in expected_type doesn't make sense. How do I create a simple function that will check if a string is in a Python string literal?

from typing_extensions import Literal

def check_str_in_literal(value: str, expected_type: Literal):
    assert value in expected_type

Gender = Literal["Male", "Female", "Other"]
def print_gender(gender: Gender):
    print(gender)

# Unknown string as it's been retrieved from elsewhere
strRetrievedFromDB = "Male"  # type: ignore

check_str_in_literal(strRetrievedFromDB, Gender)
print_gender(strRetrievedFromDB)


Solution 1:[1]

Looking at the content of a Literal, we can see that the values are inside the private attribute __args__

>>> from typing_extensions import Literal
>>> literal = Literal["a", "b", "c"]
>>> literal.__dict__
{'_inst': True,
 '_name': None,
 '__origin__': typing.Literal,
 '__slots__': None,
 '__args__': ('a', 'b', 'c'),
 '__parameters__': (),
 '__module__': 'typing'}

Therefore, one way if really need to use Literal is to do as such:

def check_str_in_literal(value: str, expected_type: Literal):
    assert value in expected_type.__args__

However, it's usually not a good idea to use private attributes.

As mentioned in comments, you could also used Enum (or other type of enums from enum module), as such:

import enum
from typing import Optional

class Gender(enum.Enum):
    Male = enum.auto()
    Female = enum.auto()
    Other = enum.auto()

def get_gender(gender:str) -> Optional[Gender]:
    """Get an Enum Gender from its name (None if not valid)"""
    try:
        return Gender[gender]
    except KeyError:
        return None

def print_gender(gender:Gender) -> None:
    """Do something with a gender"""
    print(gender.name)


gender_from_db = "Male"
gender = get_gender(gender_from_db)
if gender:
    print_gender(gender)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jean-Francois T.