Expanded type coverage to benchmarks, samples and tests. (#566)
* Renamed json samples to fix duplicate module name. Signed-off-by: dblock <[email protected]> * Enabled mypy on all source files. Signed-off-by: dblock <[email protected]> * Added missing types. Signed-off-by: dblock <[email protected]> * Added CHANGELOG. Signed-off-by: dblock <[email protected]> * Move type: ignore to fix untyped decorator makes function untyped. Signed-off-by: dblock <[email protected]> * Fix nox -rs lint-3.7. Signed-off-by: dblock <[email protected]> * Fixed incorrect import. Signed-off-by: dblock <[email protected]> * Fix broken test. Signed-off-by: dblock <[email protected]> * Fixed TestBulk::test_bulk_works_with_bytestring_body. Signed-off-by: dblock <[email protected]> --------- Signed-off-by: dblock <[email protected]>
This commit is contained in:
@@ -36,6 +36,7 @@ import os
|
||||
import re
|
||||
import warnings
|
||||
import zipfile
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
import urllib3
|
||||
@@ -142,23 +143,23 @@ FALSEY_VALUES = ("", None, False, 0, 0.0)
|
||||
|
||||
|
||||
class YamlRunner:
|
||||
def __init__(self, client) -> None:
|
||||
def __init__(self, client: Any) -> None:
|
||||
self.client = client
|
||||
self.last_response = None
|
||||
self.last_response: Any = None
|
||||
|
||||
self._run_code = None
|
||||
self._setup_code = None
|
||||
self._teardown_code = None
|
||||
self._state = {}
|
||||
self._run_code: Any = None
|
||||
self._setup_code: Any = None
|
||||
self._teardown_code: Any = None
|
||||
self._state: Any = {}
|
||||
|
||||
def use_spec(self, test_spec) -> None:
|
||||
def use_spec(self, test_spec: Any) -> None:
|
||||
self._setup_code = test_spec.pop("setup", None)
|
||||
self._run_code = test_spec.pop("run", None)
|
||||
self._teardown_code = test_spec.pop("teardown", None)
|
||||
|
||||
def setup(self):
|
||||
def setup(self) -> Any:
|
||||
# Pull skips from individual tests to not do unnecessary setup.
|
||||
skip_code = []
|
||||
skip_code: Any = []
|
||||
for action in self._run_code:
|
||||
assert len(action) == 1
|
||||
action_type, _ = list(action.items())[0]
|
||||
@@ -174,12 +175,12 @@ class YamlRunner:
|
||||
if self._setup_code:
|
||||
self.run_code(self._setup_code)
|
||||
|
||||
def teardown(self) -> None:
|
||||
def teardown(self) -> Any:
|
||||
if self._teardown_code:
|
||||
self.section("teardown")
|
||||
self.run_code(self._teardown_code)
|
||||
|
||||
def opensearch_version(self):
|
||||
def opensearch_version(self) -> Any:
|
||||
global OPENSEARCH_VERSION
|
||||
if OPENSEARCH_VERSION is None:
|
||||
version_string = (self.client.info())["version"]["number"]
|
||||
@@ -189,10 +190,10 @@ class YamlRunner:
|
||||
OPENSEARCH_VERSION = tuple(int(v) if v.isdigit() else 99 for v in version)
|
||||
return OPENSEARCH_VERSION
|
||||
|
||||
def section(self, name) -> None:
|
||||
def section(self, name: str) -> None:
|
||||
print(("=" * 10) + " " + name + " " + ("=" * 10))
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self) -> Any:
|
||||
try:
|
||||
self.setup()
|
||||
self.section("test")
|
||||
@@ -203,7 +204,7 @@ class YamlRunner:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def run_code(self, test) -> None:
|
||||
def run_code(self, test: Any) -> Any:
|
||||
"""Execute an instruction based on its type."""
|
||||
for action in test:
|
||||
assert len(action) == 1
|
||||
@@ -215,7 +216,7 @@ class YamlRunner:
|
||||
else:
|
||||
raise RuntimeError("Invalid action type %r" % (action_type,))
|
||||
|
||||
def run_do(self, action) -> None:
|
||||
def run_do(self, action: Any) -> Any:
|
||||
api = self.client
|
||||
headers = action.pop("headers", None)
|
||||
catch = action.pop("catch", None)
|
||||
@@ -267,7 +268,7 @@ class YamlRunner:
|
||||
|
||||
# Filter out warnings raised by other components.
|
||||
caught_warnings = [
|
||||
str(w.message)
|
||||
str(w.message) # type: ignore
|
||||
for w in caught_warnings
|
||||
if w.category == OpenSearchWarning
|
||||
and str(w.message) not in allowed_warnings
|
||||
@@ -275,13 +276,13 @@ class YamlRunner:
|
||||
|
||||
# Sorting removes the issue with order raised. We only care about
|
||||
# if all warnings are raised in the single API call.
|
||||
if warn and sorted(warn) != sorted(caught_warnings):
|
||||
if warn and sorted(warn) != sorted(caught_warnings): # type: ignore
|
||||
raise AssertionError(
|
||||
"Expected warnings not equal to actual warnings: expected=%r actual=%r"
|
||||
% (warn, caught_warnings)
|
||||
)
|
||||
|
||||
def run_catch(self, catch, exception) -> None:
|
||||
def run_catch(self, catch: Any, exception: Any) -> None:
|
||||
if catch == "param":
|
||||
assert isinstance(exception, TypeError)
|
||||
return
|
||||
@@ -296,7 +297,7 @@ class YamlRunner:
|
||||
) is not None
|
||||
self.last_response = exception.info
|
||||
|
||||
def run_skip(self, skip) -> None:
|
||||
def run_skip(self, skip: Any) -> Any:
|
||||
global IMPLEMENTED_FEATURES
|
||||
|
||||
if "features" in skip:
|
||||
@@ -318,32 +319,32 @@ class YamlRunner:
|
||||
if min_version <= (self.opensearch_version()) <= max_version:
|
||||
pytest.skip(reason)
|
||||
|
||||
def run_gt(self, action) -> None:
|
||||
def run_gt(self, action: Any) -> None:
|
||||
for key, value in action.items():
|
||||
value = self._resolve(value)
|
||||
assert self._lookup(key) > value
|
||||
|
||||
def run_gte(self, action) -> None:
|
||||
def run_gte(self, action: Any) -> None:
|
||||
for key, value in action.items():
|
||||
value = self._resolve(value)
|
||||
assert self._lookup(key) >= value
|
||||
|
||||
def run_lt(self, action) -> None:
|
||||
def run_lt(self, action: Any) -> None:
|
||||
for key, value in action.items():
|
||||
value = self._resolve(value)
|
||||
assert self._lookup(key) < value
|
||||
|
||||
def run_lte(self, action) -> None:
|
||||
def run_lte(self, action: Any) -> None:
|
||||
for key, value in action.items():
|
||||
value = self._resolve(value)
|
||||
assert self._lookup(key) <= value
|
||||
|
||||
def run_set(self, action) -> None:
|
||||
def run_set(self, action: Any) -> None:
|
||||
for key, value in action.items():
|
||||
value = self._resolve(value)
|
||||
self._state[value] = self._lookup(key)
|
||||
|
||||
def run_is_false(self, action) -> None:
|
||||
def run_is_false(self, action: Any) -> None:
|
||||
try:
|
||||
value = self._lookup(action)
|
||||
except AssertionError:
|
||||
@@ -351,23 +352,23 @@ class YamlRunner:
|
||||
else:
|
||||
assert value in FALSEY_VALUES
|
||||
|
||||
def run_is_true(self, action) -> None:
|
||||
def run_is_true(self, action: Any) -> None:
|
||||
value = self._lookup(action)
|
||||
assert value not in FALSEY_VALUES
|
||||
|
||||
def run_length(self, action) -> None:
|
||||
def run_length(self, action: Any) -> None:
|
||||
for path, expected in action.items():
|
||||
value = self._lookup(path)
|
||||
expected = self._resolve(expected)
|
||||
assert expected == len(value)
|
||||
|
||||
def run_match(self, action) -> None:
|
||||
def run_match(self, action: Any) -> None:
|
||||
for path, expected in action.items():
|
||||
value = self._lookup(path)
|
||||
expected = self._resolve(expected)
|
||||
|
||||
if (
|
||||
isinstance(expected, string_types)
|
||||
isinstance(expected, str)
|
||||
and expected.startswith("/")
|
||||
and expected.endswith("/")
|
||||
):
|
||||
@@ -379,7 +380,7 @@ class YamlRunner:
|
||||
else:
|
||||
self._assert_match_equals(value, expected)
|
||||
|
||||
def run_contains(self, action) -> None:
|
||||
def run_contains(self, action: Any) -> None:
|
||||
for path, expected in action.items():
|
||||
value = self._lookup(path) # list[dict[str,str]] is returned
|
||||
expected = self._resolve(expected) # dict[str, str]
|
||||
@@ -387,7 +388,7 @@ class YamlRunner:
|
||||
if expected not in value:
|
||||
raise AssertionError("%s is not contained by %s" % (expected, value))
|
||||
|
||||
def run_transform_and_set(self, action) -> None:
|
||||
def run_transform_and_set(self, action: Any) -> None:
|
||||
for key, value in action.items():
|
||||
# Convert #base64EncodeCredentials(id,api_key) to ["id", "api_key"]
|
||||
if "#base64EncodeCredentials" in value:
|
||||
@@ -397,7 +398,7 @@ class YamlRunner:
|
||||
(self._lookup(value[0]), self._lookup(value[1]))
|
||||
)
|
||||
|
||||
def _resolve(self, value):
|
||||
def _resolve(self, value: Any) -> Any:
|
||||
# resolve variables
|
||||
if isinstance(value, string_types) and "$" in value:
|
||||
for k, v in self._state.items():
|
||||
@@ -422,12 +423,13 @@ class YamlRunner:
|
||||
value = list(map(self._resolve, value))
|
||||
return value
|
||||
|
||||
def _lookup(self, path):
|
||||
def _lookup(self, path: str) -> Any:
|
||||
# fetch the possibly nested value from last_response
|
||||
value = self.last_response
|
||||
value: Any = self.last_response
|
||||
if path == "$body":
|
||||
return value
|
||||
path = path.replace(r"\.", "\1")
|
||||
step: Any
|
||||
for step in path.split("."):
|
||||
if not step:
|
||||
continue
|
||||
@@ -449,10 +451,10 @@ class YamlRunner:
|
||||
value = value[step]
|
||||
return value
|
||||
|
||||
def _feature_enabled(self, name) -> bool:
|
||||
def _feature_enabled(self, name: str) -> Any:
|
||||
return False
|
||||
|
||||
def _assert_match_equals(self, a, b) -> None:
|
||||
def _assert_match_equals(self, a: Any, b: Any) -> None:
|
||||
# Handle for large floating points with 'E'
|
||||
if isinstance(b, string_types) and isinstance(a, float) and "e" in repr(a):
|
||||
a = repr(a).replace("e+", "E")
|
||||
@@ -460,8 +462,8 @@ class YamlRunner:
|
||||
assert a == b, "%r does not match %r" % (a, b)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def sync_runner(sync_client):
|
||||
@pytest.fixture(scope="function") # type: ignore
|
||||
def sync_runner(sync_client: Any) -> Any:
|
||||
return YamlRunner(sync_client)
|
||||
|
||||
|
||||
@@ -532,8 +534,8 @@ except Exception as e:
|
||||
|
||||
if not RUN_ASYNC_REST_API_TESTS:
|
||||
|
||||
@pytest.mark.parametrize("test_spec", YAML_TEST_SPECS)
|
||||
def test_rest_api_spec(test_spec, sync_runner) -> None:
|
||||
@pytest.mark.parametrize("test_spec", YAML_TEST_SPECS) # type: ignore
|
||||
def test_rest_api_spec(test_spec: Any, sync_runner: Any) -> None:
|
||||
if test_spec.get("skip", False):
|
||||
pytest.skip("Manually skipped in 'SKIP_TESTS'")
|
||||
sync_runner.use_spec(test_spec)
|
||||
|
||||
Reference in New Issue
Block a user