Skip to content
Advertisement

How do you type hint an additional attribute on an object?

I have a custom test runner that uses inspect to find all the functions starting with with test_. At one point I add an attribute to the function object. This is done so the test runner has access to the docstring information later.

I’d really like to create a type hint for the list of functions so that my IDE (pycharm) knows that tdi is indeed an attribute of the function object.

How do you build such a type hint?

for m, fn in module.__dict__.items():
        if m.startswith(prefix):
            if callable(fn):
                tdi = getTestDocInfo(fn) # reads the docstring for tags and puts the info in a dataclass
                fn.tdi = tdi
                tests.append(fn)

edit: In this case, the type hint should convey the object is a function AND that it has the attribute tdi.

As @chepner pointed out the Protocol building block for a type hint is what was needed here.

This is what worked.

@runtime_checkable
class TestFunc(Protocol):
    tdi: TestDocInfo
    def __call__(self, testresult: TestResult, shareditems: SharedItems): pass

tests: List[TestFunc]. #type hint I am looking for.

Advertisement

Answer

This seems like a job for typing.Protocol and typing.runtime_checkable:

from typing import Protocol, runtime_checkable

@runtime_checkable
class HasTDI(Protocol):
    tdi: int  # Or whatever type is appropriate.

Then

isinstance(fn, HasTDI)

should be true if fn.tdi exists and is an int.

I’m afraid I don’t know if PyCharm will make use of this information, though.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement