mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-30 05:52:23 +00:00
* remove auto examples and split python from api * add missing exampels * rebuild * query params focstring * black * add scoped examples * group model imports in the router * unblock api * fix * classify examples * fix package identation * black sig * fix indentation without linter * fix python examples * remove doc * pylint * again * add model validators * commodity, crypto, currency * filter examples * fix python examples * fix filter and build * undo toml change * add comment * oop * comment * typing * lint * Update router.py * Update econometrics_router.py * fix to_python * to_python * to_python * black * fix multiple line field descriptions * remove circular import * add missing import * pass indent as object attr * doc * doc * this looks better * forgot this * fix: new examples adapted * fix prev commit * avoid future problems * Update ownership_router.py * rebuild + remove todo * make description mandatory for python examples * simple indent * append_examples func works for both website and docstring * Add example unit tests * Edit example unit tests * fix validator * this works * fix to_python * fix mandatory docstrings * typing * shorter error msgs * economy router * fix more examples * more examples * more examples * more examples * field desc * minor fix * fix etf examples * handling types better * lint * rename method * rename var * docstring + move method * typing * prompt * rebuild * prompt fix in PythonEx * fix examples without model * example mock data * add get_field_type func to get field data type * panel data * mock data * fix * fix * docstring * ohlcv * pylint * quantitaive router * simplify mock data * fix remaining quantitative routers * a bit more flexibility for examples * lint * mock dat from sample * docstring * assertion * bugfix * minor fix * technical * fix integration tests * fix docstring * econometrics examples * econometrics examples * remove warning * add technical examples * fix bad examples * fix more examples * update test rules * remoce old pydantic referenc * fix bug in treasury prices * fix quantitative examples * discovery router * equity shorts * equity shorts * fix currency pairs * fix sec_router example * fix panel data to support all funcs * black * more examples fixes * simplify test * rebuild * test doc * add provider to some ex * ^ * last * add provider * rebuild * working examples * noqa * pylint * pylint * clean * minor fix * fix test * lint * ruff --------- Co-authored-by: Pratyush Shukla <ps4534@nyu.edu> Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com>
142 lines
5.3 KiB
Python
142 lines
5.3 KiB
Python
"""Router testers."""
|
|
|
|
import ast
|
|
import os
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from openbb_core.app.provider_interface import ProviderInterface
|
|
|
|
from extensions.tests.utils.helpers import (
|
|
collect_router_functions,
|
|
collect_routers,
|
|
find_decorator,
|
|
find_missing_router_function_models,
|
|
get_decorator_details,
|
|
get_required_fields,
|
|
import_routers,
|
|
parse_example_string,
|
|
)
|
|
|
|
|
|
def check_router_function_models() -> List[str]:
|
|
"""Check if the models in the router functions exist in the provider interface map."""
|
|
pi = ProviderInterface()
|
|
pi_map = pi.map
|
|
routers = collect_routers("extensions")
|
|
loaded_routers = import_routers(routers)
|
|
router_functions = collect_router_functions(loaded_routers)
|
|
missing_models = find_missing_router_function_models(router_functions, pi_map)
|
|
|
|
return missing_models
|
|
|
|
|
|
def check_router_model_functions_signature() -> List[str]:
|
|
"""Check if the router model functions have the correct signature."""
|
|
expected_args = ["cc", "provider_choices", "standard_params", "extra_params"]
|
|
expected_return_type = "OBBject"
|
|
missing_args: List[str] = []
|
|
missing_return_type: List[str] = []
|
|
|
|
routers = collect_routers("extensions")
|
|
loaded_routers = import_routers(routers)
|
|
router_functions = collect_router_functions(loaded_routers)
|
|
|
|
for router_name, functions in router_functions.items():
|
|
for function in functions:
|
|
decorator = find_decorator(
|
|
os.path.join(*router_name.split(".")) + ".py",
|
|
function.__name__,
|
|
)
|
|
if decorator:
|
|
if "POST" in decorator or "GET" in decorator:
|
|
continue
|
|
args = list(function.__code__.co_varnames)
|
|
if args != expected_args and "model" in decorator:
|
|
missing_args.append(
|
|
f"{function.__name__} in {router_name} missing expected args: {expected_args}"
|
|
)
|
|
if expected_return_type not in str(function.__annotations__["return"]):
|
|
missing_return_type.append(
|
|
f"{function.__name__} in {router_name} "
|
|
f"doesn't have the expected return type: {expected_return_type}"
|
|
)
|
|
|
|
return missing_args + missing_return_type
|
|
|
|
|
|
def check_general(
|
|
keywords: Dict, examples: List, router_name: str, function: Any
|
|
) -> List[str]:
|
|
"""Check for general violations in the router command examples."""
|
|
general_violation: List[str] = []
|
|
|
|
# Check if the endpoint has examples
|
|
if "examples" not in keywords or not examples:
|
|
general_violation.append(
|
|
f"'{router_name}' > '{function.__name__}': missing examples"
|
|
)
|
|
return general_violation
|
|
|
|
return general_violation
|
|
|
|
|
|
def check_api(
|
|
examples: str, router_name: str, model: Optional[str], function: Any
|
|
) -> List[str]:
|
|
"""Check for API examples."""
|
|
# Check if the endpoint has at least 1 example with all required fields
|
|
api_example_violation: List[str] = []
|
|
parsed_examples = parse_example_string(examples)
|
|
if model and "APIEx" in parsed_examples:
|
|
required_fields = get_required_fields(model.strip("'"))
|
|
for api_example in parsed_examples["APIEx"]:
|
|
params = ast.literal_eval(api_example.get("params", "{}"))
|
|
if len(set(params.keys()) - set(required_fields) - {"provider"}) == 0:
|
|
break
|
|
else:
|
|
api_example_violation.append(
|
|
f"'{router_name}' > '{function.__name__}': missing example with required fields only > {required_fields}"
|
|
)
|
|
|
|
return api_example_violation
|
|
|
|
|
|
def check_router_command_examples() -> List[str]:
|
|
"""Check if the router command examples satisfy criteria."""
|
|
general_violation: List[str] = []
|
|
api_example_violation: List[str] = []
|
|
python_example_violation: List[str] = []
|
|
|
|
routers = collect_routers("extensions")
|
|
loaded_routers = import_routers(routers)
|
|
router_functions = collect_router_functions(loaded_routers)
|
|
|
|
for router_name, functions in router_functions.items():
|
|
for function in functions:
|
|
if (
|
|
"basemodel_to_df" in function.__name__
|
|
or "router" not in function.__module__
|
|
):
|
|
continue
|
|
decorator = find_decorator(
|
|
os.path.join(*router_name.split(".")) + ".py",
|
|
function.__name__,
|
|
)
|
|
if decorator:
|
|
decorator_details = get_decorator_details(function)
|
|
if decorator_details["decorator"] == "router.command":
|
|
keywords = decorator_details["keywords"]
|
|
examples = keywords.get("examples", [])
|
|
# General checks
|
|
general_violation += check_general(
|
|
keywords, examples, router_name, function
|
|
)
|
|
if examples:
|
|
# API example checks
|
|
model = keywords.get("model", None)
|
|
api_example_violation += check_api(
|
|
examples, router_name, model, function
|
|
)
|
|
|
|
return general_violation + api_example_violation + python_example_violation
|