Python protocols: How to compare against the TYPE of protocol attributes

Viewed 126

I find Protocols very useful to be able statically validate behavior expectations -- without the constraints of actual subclassing. For checking for attribute existence, they work like a charm:

from typing import Protocol, Callable, runtime_checkable
from collections import namedtuple

class HasItems(Protocol):
    items: Callable
        

assert isinstance(dict(), HasItems)
assert not isinstance(list(), HasItems) 

But the type of the attribute seems to be ignored. In some cases I'd like to actually have that level of comparison.

# @runtime_checkable  # doesn't make a difference in what I'm checking
class HasIntItems(Protocol):
    items: int


obj = namedtuple('IntItems', 'items')(3)
obj_with_no_items = namedtuple('IntItems', 'not_items')(3)
assert isinstance(obj.items, int)  # obj has items and is an int
assert isinstance(obj, HasIntItems)  # so this is true, and it's expected
assert not isinstance(obj_with_no_items, HasIntItems)  # also expected

obj_w_non_int_items = namedtuple('IntItems', 'items')('i am not an int')
assert not isinstance(obj_w_non_int_items.items, int) # items exists, but is not an int
assert isinstance(obj_w_non_int_items, HasIntItems)  # expected this to fail: items is a
assert isinstance(dict(), HasIntItems)  # expected this to fail:dict() considered to have items, but it's a callable, not an int!

But how?....

0 Answers
Related