This PEP proposes changing function annotations and variable annotations so that they are no longer evaluated at function definition time. Instead, they are preserved in __annotations__ in string form.
This change is being introduced gradually, starting with a future import in Python 3.7.
It isn't yet activated by default, but gets activated on any file importing:
This will be completely broken once PEP 563 becomes the default.
Is this a regression?
Well, yes and no. It is a regression in the sense that the from __future__ import annotations is more and more often used, as it solves some problems such as forward references and cyclic imports.
Minimal Reproduction
Here is an example of the problem:
from __future__ import annotations
from rest_framework import serializers
class MySerializer(serializers.Serializer):
# This allows to return something that is not a direct
# attribute of a model, but a "computed" value
is_foo = serializers.SerializerMethodField()
# The type hint is important for drf-yasg to
# guess the proper type
def get_is_foo(self, obj) -> bool:
return obj.is_foo
In the above example, drf-yasg will wrongly assume {"is_foo": "STRING"} instead of {"is_foo": "BOOLEAN"}, because inspect.get_signature(is_foo) returns 'bool' (str) and not bool (type).
Possible fixes
In order to un-stringize the type, Python 3.10 introduced a new method, inspect.get_annotations(f, eval_str=True) and ported the eval_str parameter to inspect.signature. For Python 3.9 and older, this needs to be done manually.
The possible fixes are thus:
either change the logic so that both bool and 'bool' return String.BOOLEAN (same for other types)
or use the new methods if available, and clearly state the issue for older python versions in the docs.
Bug Report
Description
PEP 563 – Postponed Evaluation of Annotations is coming along, and breaks the inference of return types in
SerializerMethodField
. In short:It isn't yet activated by default, but gets activated on any file importing:
When this feature is on, https://github.com/axnsan12/drf-yasg/blob/1.21.7/src/drf_yasg/inspectors/field.py#L616 fails to guess the return type, since it assumes the type returned is actually a
Type
, but it is now astr
(see example below).This will be completely broken once PEP 563 becomes the default.
Is this a regression?
Well, yes and no. It is a regression in the sense that the
from __future__ import annotations
is more and more often used, as it solves some problems such as forward references and cyclic imports.Minimal Reproduction
Here is an example of the problem:
In the above example, drf-yasg will wrongly assume
{"is_foo": "STRING"}
instead of{"is_foo": "BOOLEAN"}
, becauseinspect.get_signature(is_foo)
returns'bool'
(str) and notbool
(type).Possible fixes
In order to un-stringize the type, Python 3.10 introduced a new method,
inspect.get_annotations(f, eval_str=True)
and ported theeval_str
parameter toinspect.signature
. For Python 3.9 and older, this needs to be done manually.The possible fixes are thus:
bool
and'bool'
returnString.BOOLEAN
(same for other types)