Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to type Python mixin with superclass calls?

I'm trying to use the FieldMixin from this answer in my project, but I'm having trouble getting it to pass mypy checks. The current code:

class DynamicFieldsMixin(Serializer):
    context: Dict[str, Any]

    def get_field_names(
        self, declared_fields: OrderedDict, info: FieldInfo
    ) -> Set[str]:
        field_names: Set[str] = self.context.get(
            "fields",
            super().get_field_names(declared_fields, info)
        )
        return field_names

Inheriting from rest_framework.serializers.Serializer seems weird, and I wonder if there's a way to avoid that, since it's meant to be mixed into actual Serializer classes. Just removing the superclass results in this error:

error: "get_field_names" undefined in superclass

mypy configuration:

[mypy]
check_untyped_defs = true
disallow_untyped_defs = true
ignore_missing_imports = true
no_implicit_optional = true
warn_redundant_casts = true
warn_return_any = true
warn_unused_ignores = true
like image 549
l0b0 Avatar asked Jul 11 '19 00:07

l0b0


1 Answers

You can introduce the base class for the sake of type checking only:

import typing
from typing import Any, Dict, List, Mapping, TypeVar
from rest_framework.fields import Field
from rest_framework.serializers import ModelSerializer
from rest_framework.utils.model_meta import FieldInfo


if typing.TYPE_CHECKING:
    _Base = ModelSerializer
else:
    _Base = object


class DynamicFieldsMixin(_Base):
    context: Dict[str, Any]

    def get_field_names(self, declared_fields: Mapping[str, Field], info: FieldInfo) -> List[str]:
        field_names = super().get_field_names(declared_fields, info)
        # Revealed type is 'builtins.list[builtins.str]'
        reveal_type(field_names)
        return field_names
like image 117
hoefling Avatar answered Sep 20 '22 07:09

hoefling