langchain/tests/unit_tests/tools/openapi/test_api_models.py

76 lines
2.3 KiB
Python
Raw Normal View History

"""Test the APIOperation class."""
import json
import os
from pathlib import Path
from typing import Iterable, List, Tuple
import pytest
import yaml
from langchain.tools.openapi.utils.api_models import APIOperation
from langchain.tools.openapi.utils.openapi_utils import HTTPVerb, OpenAPISpec
_DIR = Path(__file__).parent
def _get_test_specs() -> Iterable[Path]:
"""Walk the test_specs directory and collect all files with the name 'apispec'
in them.
"""
test_specs_dir = _DIR / "test_specs"
return (
Path(root) / file
for root, _, files in os.walk(test_specs_dir)
for file in files
if file.startswith("apispec")
)
def _get_paths_and_methods_from_spec_dictionary(
spec: dict,
) -> Iterable[Tuple[str, str]]:
"""Return a tuple (paths, methods) for every path in spec."""
valid_methods = [verb.value for verb in HTTPVerb]
for path_name, path_item in spec["paths"].items():
for method in valid_methods:
if method in path_item:
yield (path_name, method)
def http_paths_and_methods() -> List[Tuple[str, OpenAPISpec, str, str]]:
"""Return a args for every method in cached OpenAPI spec in test_specs."""
http_paths_and_methods = []
for test_spec in _get_test_specs():
spec_name = test_spec.parent.name
if test_spec.suffix == ".json":
with test_spec.open("r") as f:
spec = json.load(f)
else:
with test_spec.open("r") as f:
spec = yaml.safe_load(f.read())
parsed_spec = OpenAPISpec.from_file(test_spec)
for path, method in _get_paths_and_methods_from_spec_dictionary(spec):
http_paths_and_methods.append(
(
spec_name,
parsed_spec,
path,
method,
)
)
return http_paths_and_methods
@pytest.mark.parametrize(
"spec_name, spec, path, method",
http_paths_and_methods(),
)
def test_parse_api_operations(
spec_name: str, spec: OpenAPISpec, path: str, method: str
) -> None:
"""Test the APIOperation class."""
try:
APIOperation.from_openapi_spec(spec, path, method)
except Exception as e:
raise AssertionError(f"Error processong {spec_name}: {e} ") from e