Browse Source

fix(apidocs): __future__ compatibility (#31979)

Josh Ferge 3 years ago
parent
commit
8253e768e3

+ 6 - 4
src/sentry/apidocs/extensions.py

@@ -1,5 +1,4 @@
-import inspect
-from typing import Any, Dict, List, Optional, Union
+from typing import Any, Dict, List, Optional, Union, get_type_hints
 
 from drf_spectacular.extensions import OpenApiAuthenticationExtension, OpenApiSerializerExtension
 from drf_spectacular.openapi import AutoSchema
@@ -49,8 +48,11 @@ class SentryResponseSerializerExtension(OpenApiSerializerExtension):  # type: ig
         return name
 
     def map_serializer(self, auto_schema: AutoSchema, direction: Direction) -> Any:
-        serializer_signature = inspect.signature(self.target.serialize)
-        return resolve_type_hint(serializer_signature.return_annotation)
+        type_hints = get_type_hints(self.target.serialize)
+        if "return" not in type_hints:
+            raise TypeError("Please type the return value of the serializer with a TypedDict")
+
+        return resolve_type_hint(type_hints["return"])
 
 
 class SentryInlineResponseSerializerExtension(OpenApiSerializerExtension):  # type: ignore

+ 14 - 0
tests/apidocs/spectacular_extensions/unit_tests.py

@@ -1,5 +1,8 @@
+from __future__ import annotations
+
 from typing import List, Optional, Union
 
+import pytest
 from drf_spectacular.utils import extend_schema_serializer
 from typing_extensions import Literal, TypedDict
 
@@ -36,6 +39,11 @@ class BasicSerializer(Serializer):
         return {"a": 1, "b": "test", "c": True, "d": [1], "e": {"zz": "test"}}
 
 
+class FailSerializer(Serializer):
+    def serialize():
+        return {"a": 1, "b": "test", "c": True, "d": [1], "e": {"zz": "test"}}
+
+
 def test_sentry_response_serializer_extension():
     seralizer_extension = SentryResponseSerializerExtension(BasicSerializer)
     schema = seralizer_extension.map_serializer(None, None)
@@ -83,3 +91,9 @@ def test_sentry_inline_response_serializer_extension():
             "required": ["b", "c", "d", "e", "f", "g", "h"],
         },
     }
+
+
+def test_sentry_fails_when_serializer_not_typed():
+    seralizer_extension = SentryResponseSerializerExtension(FailSerializer)
+    with pytest.raises(TypeError):
+        seralizer_extension.map_serializer(None, None)