mirror of
https://github.com/zulip/zulip.git
synced 2025-11-16 03:41:58 +00:00
test_openapi: Clean up type ignores.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
This commit is contained in:
committed by
Tim Abbott
parent
9d33200fb2
commit
1ffbc0009d
@@ -5,7 +5,7 @@ import sys
|
|||||||
import mock
|
import mock
|
||||||
import inspect
|
import inspect
|
||||||
import typing
|
import typing
|
||||||
from typing import Dict, Any, Set, Union, List, Callable, Tuple, Optional, Iterable, Mapping
|
from typing import Dict, Any, Set, Union, List, Callable, Tuple, Optional, Iterable, Mapping, Sequence
|
||||||
from unittest.mock import patch, MagicMock
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@@ -35,7 +35,7 @@ VARMAP = {
|
|||||||
'array': list,
|
'array': list,
|
||||||
'Typing.List': list,
|
'Typing.List': list,
|
||||||
'object': dict,
|
'object': dict,
|
||||||
'NoneType': None,
|
'NoneType': type(None),
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenAPIToolsTest(ZulipTestCase):
|
class OpenAPIToolsTest(ZulipTestCase):
|
||||||
@@ -76,7 +76,7 @@ class OpenAPIToolsTest(ZulipTestCase):
|
|||||||
'msg': '',
|
'msg': '',
|
||||||
'result': 'success',
|
'result': 'success',
|
||||||
'foo': 'bar'
|
'foo': 'bar'
|
||||||
} # type: Dict[str, Any]
|
} # type: Dict[str, object]
|
||||||
validate_against_openapi_schema(bad_content,
|
validate_against_openapi_schema(bad_content,
|
||||||
TEST_ENDPOINT,
|
TEST_ENDPOINT,
|
||||||
TEST_METHOD,
|
TEST_METHOD,
|
||||||
@@ -292,26 +292,26 @@ so maybe we shouldn't mark it as intentionally undocumented in the urls.
|
|||||||
msg += "\n + {}".format(undocumented_path)
|
msg += "\n + {}".format(undocumented_path)
|
||||||
raise AssertionError(msg)
|
raise AssertionError(msg)
|
||||||
|
|
||||||
def get_type_by_priority(self, types: List[Union[type, Tuple[type, type]]]) -> Union[type, Tuple[type, type]]:
|
def get_type_by_priority(self, types: Sequence[Union[type, Tuple[type, object]]]) -> Union[type, Tuple[type, object]]:
|
||||||
priority = {list: 1, dict: 2, str: 3, int: 4, bool: 5}
|
priority = {list: 1, dict: 2, str: 3, int: 4, bool: 5}
|
||||||
tyiroirp = {1: list, 2: dict, 3: str, 4: int, 5: bool}
|
tyiroirp = {1: list, 2: dict, 3: str, 4: int, 5: bool}
|
||||||
val = 6
|
val = 6
|
||||||
for t in types:
|
for t in types:
|
||||||
if type(t) is tuple:
|
if isinstance(t, tuple):
|
||||||
return t # e.g. (list, dict) or (list ,str)
|
return t # e.g. (list, dict) or (list ,str)
|
||||||
v = priority.get(t, 6) # type: ignore # if t was a Tuple then we would have returned by this point
|
v = priority.get(t, 6)
|
||||||
if v < val:
|
if v < val:
|
||||||
val = v
|
val = v
|
||||||
return tyiroirp.get(val, types[0])
|
return tyiroirp.get(val, types[0])
|
||||||
|
|
||||||
def get_standardized_argument_type(self, t: Any) -> Union[type, Tuple[type, type]]:
|
def get_standardized_argument_type(self, t: Any) -> Union[type, Tuple[type, object]]:
|
||||||
""" Given a type from the typing module such as List[str] or Union[str, int],
|
""" Given a type from the typing module such as List[str] or Union[str, int],
|
||||||
convert it into a corresponding Python type. Unions are mapped to a canonical
|
convert it into a corresponding Python type. Unions are mapped to a canonical
|
||||||
choice among the options.
|
choice among the options.
|
||||||
E.g. typing.Union[typing.List[typing.Dict[str, typing.Any]], NoneType]
|
E.g. typing.Union[typing.List[typing.Dict[str, typing.Any]], NoneType]
|
||||||
needs to be mapped to list."""
|
needs to be mapped to list."""
|
||||||
|
|
||||||
if sys.version[:3] == "3.5" and type(t) == typing.UnionMeta: # nocoverage # in python3.6+
|
if sys.version_info < (3, 6) and type(t) == typing.UnionMeta: # nocoverage # in python3.6+
|
||||||
origin = Union
|
origin = Union
|
||||||
else: # nocoverage # in python3.5. I.E. this is used in python3.6+
|
else: # nocoverage # in python3.5. I.E. this is used in python3.6+
|
||||||
origin = getattr(t, "__origin__", None)
|
origin = getattr(t, "__origin__", None)
|
||||||
@@ -322,7 +322,7 @@ so maybe we shouldn't mark it as intentionally undocumented in the urls.
|
|||||||
return t
|
return t
|
||||||
elif origin == Union:
|
elif origin == Union:
|
||||||
subtypes = []
|
subtypes = []
|
||||||
if sys.version[:3] == "3.5": # nocoverage # in python3.6+
|
if sys.version_info < (3, 6): # nocoverage # in python3.6+
|
||||||
args = t.__union_params__
|
args = t.__union_params__
|
||||||
else: # nocoverage # in python3.5
|
else: # nocoverage # in python3.5
|
||||||
args = t.__args__
|
args = t.__args__
|
||||||
@@ -331,15 +331,15 @@ so maybe we shouldn't mark it as intentionally undocumented in the urls.
|
|||||||
return self.get_type_by_priority(subtypes)
|
return self.get_type_by_priority(subtypes)
|
||||||
elif origin in [List, Iterable]:
|
elif origin in [List, Iterable]:
|
||||||
subtypes = [self.get_standardized_argument_type(st) for st in t.__args__]
|
subtypes = [self.get_standardized_argument_type(st) for st in t.__args__]
|
||||||
return (list, self.get_type_by_priority(subtypes)) # type: ignore # this might be a Tuple[Type[List[Any]], Union[type, Tuple[type, type]]] but that means that it's a Tuple[type, Union[type, Tuple[type, type]]] too.
|
return (list, self.get_type_by_priority(subtypes))
|
||||||
elif origin in [Dict, Mapping]:
|
elif origin in [Dict, Mapping]:
|
||||||
return dict
|
return dict
|
||||||
return self.get_standardized_argument_type(t.__args__[0])
|
return self.get_standardized_argument_type(t.__args__[0])
|
||||||
|
|
||||||
def render_openapi_type_exception(self, function: Callable[..., HttpResponse],
|
def render_openapi_type_exception(self, function: Callable[..., HttpResponse],
|
||||||
openapi_params: Set[Tuple[str, Union[type, Tuple[type, type]]]],
|
openapi_params: Set[Tuple[str, Union[type, Tuple[type, object]]]],
|
||||||
function_params: Set[Tuple[str, Union[type, Tuple[type, type]]]],
|
function_params: Set[Tuple[str, Union[type, Tuple[type, object]]]],
|
||||||
diff: Set[Tuple[str, Union[type, Tuple[type, type]]]]) -> None: # nocoverage
|
diff: Set[Tuple[str, Union[type, Tuple[type, object]]]]) -> None: # nocoverage
|
||||||
""" Print a *VERY* clear and verbose error message for when the types
|
""" Print a *VERY* clear and verbose error message for when the types
|
||||||
(between the OpenAPI documentation and the function declaration) don't match. """
|
(between the OpenAPI documentation and the function declaration) don't match. """
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ do not match the types declared in the implementation of {}.\n""".format(functio
|
|||||||
OpenAPI data defines a different type than that actually accepted by the function.
|
OpenAPI data defines a different type than that actually accepted by the function.
|
||||||
Otherwise, we print out the exact differences for convenient debugging and raise an
|
Otherwise, we print out the exact differences for convenient debugging and raise an
|
||||||
AssertionError. """
|
AssertionError. """
|
||||||
openapi_params = set() # type: Set[Tuple[str, Union[type, Tuple[type, type]]]]
|
openapi_params = set() # type: Set[Tuple[str, Union[type, Tuple[type, object]]]]
|
||||||
for element in openapi_parameters:
|
for element in openapi_parameters:
|
||||||
name = element["name"] # type: str
|
name = element["name"] # type: str
|
||||||
_type = VARMAP[element["schema"]["type"]]
|
_type = VARMAP[element["schema"]["type"]]
|
||||||
@@ -384,15 +384,15 @@ do not match the types declared in the implementation of {}.\n""".format(functio
|
|||||||
st = st["type"]
|
st = st["type"]
|
||||||
subtypes.append(VARMAP[st])
|
subtypes.append(VARMAP[st])
|
||||||
self.assertTrue(len(subtypes) > 1)
|
self.assertTrue(len(subtypes) > 1)
|
||||||
sub_type = self.get_type_by_priority(subtypes) # type: ignore # sub_type is not List[Optional[type]], it's a List[type], handled in above step.
|
sub_type = self.get_type_by_priority(subtypes)
|
||||||
else:
|
else:
|
||||||
sub_type = VARMAP[element["schema"]["items"]["type"]] # type: ignore # we handle the case of None in the next step.
|
sub_type = VARMAP[element["schema"]["items"]["type"]]
|
||||||
self.assertIsNotNone(sub_type)
|
self.assertIsNotNone(sub_type)
|
||||||
openapi_params.add((name, (_type, sub_type))) # type: ignore # things are pretty dynamic at this point and we make some inferences so mypy gets confused.
|
openapi_params.add((name, (_type, sub_type)))
|
||||||
else:
|
else:
|
||||||
openapi_params.add((name, _type)) # type: ignore # in our given case, in this block, _type will always be a regular type.
|
openapi_params.add((name, _type))
|
||||||
|
|
||||||
function_params = set() # type: Set[Tuple[str, Union[type, Tuple[type, type]]]]
|
function_params = set() # type: Set[Tuple[str, Union[type, Tuple[type, object]]]]
|
||||||
|
|
||||||
# Iterate through the decorators to find the original
|
# Iterate through the decorators to find the original
|
||||||
# function, wrapped by has_request_variables, so we can parse
|
# function, wrapped by has_request_variables, so we can parse
|
||||||
@@ -626,7 +626,7 @@ class TestCurlExampleGeneration(ZulipTestCase):
|
|||||||
"brew": {} # the data is irrelevant as is should be rejected.
|
"brew": {} # the data is irrelevant as is should be rejected.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} # type: Dict[str, Any]
|
} # type: Dict[str, object]
|
||||||
|
|
||||||
spec_mock_using_object = {
|
spec_mock_using_object = {
|
||||||
"paths": {
|
"paths": {
|
||||||
|
|||||||
Reference in New Issue
Block a user