I’m trying to write a function that filters an input mapping to return a list of objects that implement a specific input protocol. The function looks like this:
from typing import TypeVar
from mypackage import ModelProtocol
P = TypeVar("P", bound=ModelProtocol)
def filter_models(
models: Mapping[str, ModelProtocol],
proto: type[P],
choices: Sequence[str] | None = None,
) -> list[P]:
"""Filter models by a specific protocol type.
Parameters
----------
models : ``Mapping[str, ModelProtocol]``
Mapping of model names to model instances.
proto : ``type[Any]``
The protocol type to filter for.
choices : ``Sequence[str]``, optional
If provided, return only models associated with names in this sequence.
Default is ``None`` (all ``proto`` models are returned).
Returns
-------
list[P]
List of model instances that implement the given protocol.
"""
if choices is not None:
return [
model
for name, model in models.items()
if isinstance(model, proto) and name in choices
]
return [model for model in models.values() if isinstance(model, proto)]
It’s usage should be:
myobjs = filter_models(models, CustomProtocol)
where models is of type Mapping[str, ModelProtocol]. It is always guaranteed that CustomProtocol inherits ModelProtocol.
mypy can correctly infer that myobjs is of type list[CustomProtocol] but then gives the following error:
Only concrete class can be given where "type[CustomProtocol]" is expected
Other than suppressing this error in the configuration, isn’t there any other way to express to mypy that this is fine?