Files
OpenBB/website/tests/test_platform_docs.py
Pratyush Shukla 577a42461d [Feature] - Platform V4 Markdown Generator V2 (#6094)
* add recent `openapi.json`

* fix data types in models

* removed `openapi.json`

* set default date value as None in PolygonCurrencyPairs class

* add function to generate reference.json file

* reworked function to improve readability

* reword function to add seo metadata

* add functions for creating markdown sections

* add code to extract data card markdown title

* add additional functions for generating index and data models file

* extract first sentence of the description for cards

* code cleanup and documentation

* linting

* linting polygon models

* add openbb import statement in create_reference_markdown_examples function

* add POST method functions

* cleanup; reworked generate_reference_index_files function

* moved development section to 7th position in the sidebar

* fix POST function params default value

add standard flag to QueryParams and Data fields

cleanup

* add type expansion from package_builder.MethodDefinition

* sort data models cards alphabetically

make printing less verbose

* make MAX_CARDS global

display less content in cards in Commannds section

* cleanup

* Remove '_' from the cards under Commands section

* " to ' in econometrics/causality

* replace ' with " in ReferenceCard for reference dir index files

* remove extra . from the quantile function description

* shoutout to @deeleeramone for finding POST method description bug!

* set correct value for standard field

* handle BaseModel types in provider data fields

* unit tests for the platform markdown generator v2

* yeet 'Default' and 'Optional' columns in the 'Data' section

* last minute bug fix

* add info for multiple symbols

* make multiple items info same as platform static

* organize sections properly

* sort reference sub-directories alphabetically

* extra space in 'OBBject extra' description

* add type expansion for fields with multiple items

POST method cleanup

---------

Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com>
Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com>
2024-02-27 11:20:28 +00:00

309 lines
8.6 KiB
Python

import datetime
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import List, Literal, Optional, Union
import pytest
from pydantic import BaseModel, Field
sys.path.append(str(Path(__file__).resolve().parent.parent))
# pylint: disable=unused-argument,redefined-outer-name,wrong-import-position
from generate_platform_v4_markdown import ( # noqa: E402
get_field_data_type,
get_function_params_default_value,
get_post_method_parameters_info,
get_post_method_returns_info,
get_provider_field_params,
get_provider_parameter_info,
)
# Mock Classes
class MockField:
def __init__(self, annotation):
self.annotation = annotation
class MockReturnType:
def __init__(self):
self.model_fields = {"results": MockField(annotation="List[str]")}
@dataclass
class MockProvider(BaseModel):
provider: Literal["provider1", "provider2"] = "provider1"
class MockModel(BaseModel):
provider: Optional[MockProvider] = Field(default=None)
# Mock Pydantic models to simulate your data structure
class OpenBBQueryParams(BaseModel):
field1: Optional[int] = Field(default=None, description="A sample integer field")
date: datetime.date = Field(
default=None, description="A datetime.date type field (expansion type)"
)
class OpenBBData(BaseModel):
field1: Literal["a", "b"] = Field(
default="a", description="A sample Union field with Literal['a', 'b']"
)
field2: Optional[int] = Field(
default=10,
description="A field with annotated type",
gt=0,
)
class Provider1QueryParams(BaseModel):
field1: Optional[List[str]] = Field(
default=None, description="A sample List[str] field"
)
class EmptyModel(BaseModel):
pass
@pytest.fixture
def mock_data():
return {
"openbb": {
"QueryParams": {"fields": OpenBBQueryParams().model_fields},
"Data": {"fields": OpenBBData().model_fields},
},
"provider1": {
"QueryParams": {"fields": Provider1QueryParams().model_fields},
"Data": {"fields": EmptyModel().model_fields},
},
}
@pytest.fixture
def mock_endpoint():
def endpoint(param1: int, param2: Optional[str] = "default"):
pass # Mock endpoint function
return endpoint
class MockEndpointSetup:
def __init__(self):
self.mock_endpoint = self._create_mock_endpoint()
def _create_mock_endpoint(self):
def mock_endpoint(provider_choices: Optional[MockProvider] = None):
return ["result1", "result2"]
# Simulate annotations with a dataclass model
mock_endpoint.__annotations__ = {
"provider_choices": Optional[MockProvider],
"return": List[str],
}
return mock_endpoint
@pytest.fixture
def mock_endpoint_setup():
return MockEndpointSetup()
# Test Classes
class TestFieldDataType:
@pytest.mark.parametrize(
"input_type,expected_output",
[
(int, "int"),
(str, "str"),
(Optional[int], "int"),
(Union[int, None], "int"),
],
)
def test_get_field_data_type(self, input_type, expected_output):
assert get_field_data_type(input_type) == expected_output
class TestProviderFieldParams:
def test_get_provider_field_params(self, mock_data, monkeypatch):
monkeypatch.setattr(
"generate_platform_v4_markdown.get_field_data_type",
get_field_data_type,
)
# Define expected_result based on mock_data and logic in get_provider_field_params
expected_result_1 = [
{
"name": "field1",
"type": "int",
"description": "A sample integer field",
"default": "None",
"optional": True,
"standard": True,
},
{
"name": "date",
"type": "Union[str, date]",
"description": "A datetime.date type field (expansion type)",
"default": "None",
"optional": True,
"standard": True,
},
]
expected_result_2 = [
{
"name": "field1",
"type": "List[str]",
"description": "A sample List[str] field",
"default": "None",
"optional": True,
"standard": False,
},
]
expected_result_3 = [
{
"name": "field1",
"type": "Literal['a', 'b']",
"description": "A sample Union field with Literal['a', 'b']",
"default": "a",
"optional": True,
"standard": True,
},
{
"name": "field2",
"type": "int",
"description": "A field with annotated type",
"default": "10",
"optional": True,
"standard": True,
},
]
result = get_provider_field_params(mock_data, "QueryParams")
assert result == expected_result_1
result = get_provider_field_params(mock_data, "QueryParams", "provider1")
assert result == expected_result_2
result = get_provider_field_params(mock_data, "Data")
assert result == expected_result_3
class TestProviderParameterInfo:
def test_get_provider_parameter_info(self, mock_endpoint_setup):
# Access the mock_endpoint from the fixture
mock_endpoint = mock_endpoint_setup.mock_endpoint
expected = {
"name": "provider",
"type": "Literal['provider1', 'provider2']",
"description": "The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'provider1' if there is no default.", # noqa: E501
"default": "provider1",
"optional": True,
"standard": True,
}
result = get_provider_parameter_info(mock_endpoint)
assert result == expected
class TestFunctionParamsDefaultValue:
def test_get_function_params_default_value(self, mock_endpoint):
expected_result = {
"param1": "",
"param2": "default",
}
result = get_function_params_default_value(mock_endpoint)
assert (
result == expected_result
), "Failed to correctly identify default parameter values."
class TestPostMethodParametersInfo:
def test_get_post_method_parameters_info(self, monkeypatch):
monkeypatch.setattr(
"generate_platform_v4_markdown.get_field_data_type",
get_field_data_type,
)
def mock_endpoint(param1: int, param2: Optional[str] = "default"):
"""
A mock endpoint function.
Parameters
----------
param1 : int
The first parameter.
param2 : Optional[str]
The second parameter, optional.
"""
return
expected_result = [
{
"name": "param1",
"type": "int",
"description": "The first parameter.",
"default": "",
"optional": False,
},
{
"name": "param2",
"type": "str",
"description": "The second parameter, optional.",
"default": "default",
"optional": True,
},
]
result = get_post_method_parameters_info(mock_endpoint)
assert (
result == expected_result
), "Failed to correctly extract POST method parameters info."
class TestPostMethodReturnsInfo:
def test_get_post_method_returns_info(self, monkeypatch):
monkeypatch.setattr(
"generate_platform_v4_markdown.get_field_data_type",
get_field_data_type,
)
class MockReturnModel(BaseModel):
results: List[str]
def mock_endpoint() -> MockReturnModel:
"""
A mock endpoint function.
Parameters
----------
None
Returns
-------
MockReturnModel
A list of strings as results.
"""
return
expected_result = [
{
"name": "results",
"type": "List[str]",
"description": "A list of strings as results.",
}
]
result = get_post_method_returns_info(mock_endpoint)
assert (
result == expected_result
), "Failed to correctly extract POST method returns info."