summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanglewood <85772166+deeleeramone@users.noreply.github.com>2024-04-05 17:17:03 -0700
committerGitHub <noreply@github.com>2024-04-05 17:17:03 -0700
commitbf3e18bb79dbb53b21543ea096dcce877ae45823 (patch)
tree715b745f47caee63dde73762dde212286ed91c5e
parent4474022c5a26ab8ffa4cdd3bb3fcdc14a9aa1647 (diff)
parent3f4ab6edf6752eba9f8c3a3fccb6cb0137e19a33 (diff)
Merge branch 'develop' into feature/field-descriptionsfeature/field-descriptions
-rw-r--r--.github/workflows/platform-api-integration-test.yml3
-rw-r--r--examples/usdLiquidityIndex.ipynb24
-rw-r--r--openbb_platform/core/openbb_core/api/app_loader.py18
-rw-r--r--openbb_platform/core/openbb_core/api/rest_api.py2
-rw-r--r--openbb_platform/core/openbb_core/api/router/commands.py13
-rw-r--r--openbb_platform/core/openbb_core/app/model/obbject.py8
-rw-r--r--openbb_platform/core/openbb_core/app/model/system_settings.py3
-rw-r--r--openbb_platform/core/openbb_core/app/router.py51
-rw-r--r--openbb_platform/core/openbb_core/app/static/app_factory.py9
-rw-r--r--openbb_platform/core/openbb_core/app/static/coverage.py7
-rw-r--r--openbb_platform/core/openbb_core/app/static/package_builder.py257
-rw-r--r--openbb_platform/core/openbb_core/app/version.py5
-rw-r--r--openbb_platform/core/openbb_core/provider/abstract/annotated_result.py20
-rw-r--r--openbb_platform/core/openbb_core/provider/abstract/fetcher.py15
-rw-r--r--openbb_platform/core/openbb_core/provider/registry_map.py3
-rw-r--r--openbb_platform/core/openbb_core/provider/standard_models/forward_eps_estimates.py67
-rw-r--r--openbb_platform/core/openbb_core/provider/standard_models/forward_sales_estimates.py68
-rw-r--r--openbb_platform/core/openbb_core/provider/standard_models/price_target_consensus.py9
-rw-r--r--openbb_platform/core/tests/app/static/test_app_factory.py7
-rw-r--r--openbb_platform/core/tests/app/static/test_coverage.py7
-rw-r--r--openbb_platform/core/tests/app/static/test_package_builder.py25
-rw-r--r--openbb_platform/extensions/commodity/openbb_commodity/commodity_router.py2
-rw-r--r--openbb_platform/extensions/crypto/openbb_crypto/crypto_router.py2
-rw-r--r--openbb_platform/extensions/currency/openbb_currency/currency_router.py2
-rw-r--r--openbb_platform/extensions/derivatives/openbb_derivatives/derivatives_router.py2
-rw-r--r--openbb_platform/extensions/econometrics/openbb_econometrics/econometrics_router.py2
-rw-r--r--openbb_platform/extensions/economy/openbb_economy/economy_router.py2
-rw-r--r--openbb_platform/extensions/equity/integration/test_equity_api.py70
-rw-r--r--openbb_platform/extensions/equity/integration/test_equity_python.py64
-rw-r--r--openbb_platform/extensions/equity/openbb_equity/equity_router.py2
-rw-r--r--openbb_platform/extensions/equity/openbb_equity/estimates/estimates_router.py46
-rw-r--r--openbb_platform/extensions/etf/openbb_etf/etf_router.py2
-rw-r--r--openbb_platform/extensions/fixedincome/openbb_fixedincome/fixedincome_router.py2
-rw-r--r--openbb_platform/extensions/index/openbb_index/index_router.py2
-rw-r--r--openbb_platform/extensions/news/openbb_news/news_router.py2
-rw-r--r--openbb_platform/extensions/quantitative/README.md2
-rw-r--r--openbb_platform/extensions/quantitative/openbb_quantitative/quantitative_router.py2
-rw-r--r--openbb_platform/extensions/regulators/openbb_regulators/regulators_router.py2
-rw-r--r--openbb_platform/extensions/technical/openbb_technical/technical_router.py2
-rw-r--r--openbb_platform/openbb/assets/extension_map.json29
-rw-r--r--openbb_platform/openbb/assets/reference.json53755
-rw-r--r--openbb_platform/openbb/package/equity_estimates.py284
-rw-r--r--openbb_platform/providers/fmp/openbb_fmp/__init__.py2
-rw-r--r--openbb_platform/providers/fmp/openbb_fmp/models/forward_eps_estimates.py153
-rw-r--r--openbb_platform/providers/fmp/openbb_fmp/models/price_target_consensus.py15
-rw-r--r--openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_equity_forward_eps_fetcher.yaml269
-rw-r--r--openbb_platform/providers/fmp/tests/test_fmp_fetchers.py15
-rw-r--r--openbb_platform/providers/fred/openbb_fred/models/series.py41
-rw-r--r--openbb_platform/providers/intrinio/openbb_intrinio/__init__.py12
-rw-r--r--openbb_platform/providers/intrinio/openbb_intrinio/models/forward_eps_estimates.py230
-rw-r--r--openbb_platform/providers/intrinio/openbb_intrinio/models/forward_sales_estimates.py249
-rw-r--r--openbb_platform/providers/intrinio/openbb_intrinio/models/price_target_consensus.py183
-rw-r--r--openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_forward_eps_estimates_fetcher.yaml48
-rw-r--r--openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_forward_sales_estimates_fetcher.yaml52
-rw-r--r--openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_price_target_consensus_fetcher.yaml38
-rw-r--r--openbb_platform/providers/intrinio/tests/test_intrinio_fetchers.py36
-rw-r--r--openbb_platform/providers/tmx/openbb_tmx/models/price_target_consensus.py12
-rw-r--r--openbb_platform/providers/yfinance/openbb_yfinance/models/price_target_consensus.py12
-rw-r--r--openbb_platform/tests/test_extension_map.py14
-rw-r--r--website/content/pro/data-connectors/integrate-your-own-backend.md10
-rw-r--r--website/content/pro/data-connectors/native-integrations.md13
-rw-r--r--website/generate_platform_v4_markdown.py399
62 files changed, 29623 insertions, 27079 deletions
diff --git a/.github/workflows/platform-api-integration-test.yml b/.github/workflows/platform-api-integration-test.yml
index 92b7073045b..11b4c9c5d40 100644
--- a/.github/workflows/platform-api-integration-test.yml
+++ b/.github/workflows/platform-api-integration-test.yml
@@ -2,6 +2,9 @@ name: API Integration Tests
on:
workflow_dispatch:
+ pull_request:
+ branches:
+ - release/*
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
diff --git a/examples/usdLiquidityIndex.ipynb b/examples/usdLiquidityIndex.ipynb
index 7681e0c9488..4f177babebb 100644
--- a/examples/usdLiquidityIndex.ipynb
+++ b/examples/usdLiquidityIndex.ipynb
@@ -20,12 +20,10 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
- "import json\n",
- "\n",
"from openbb import obb\n",
"from pandas import DataFrame\n"
]
@@ -42,7 +40,7 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 2,
"metadata": {},
"outputs": [
{
@@ -50,15 +48,15 @@
"text/plain": [
"OBBject\n",
"\n",
- "id: 06580cab-5bdc-7e28-8000-632a5d8dc92f\n",
- "results: [{'date': datetime.date(2002, 12, 18), 'WALCL': 719542.0, 'WLRRAL': 21905....\n",
+ "id: 0660e135-3511-73d7-8000-b792f7e418bb\n",
+ "results: [{'date': datetime.date(2002, 12, 18), 'provider': 'fred', 'WALCL': 719542...\n",
"provider: fred\n",
- "warnings: [{'category': 'UserWarning', 'message': '{\"WALCL\": {\"title\": \"Assets: Tot...\n",
+ "warnings: None\n",
"chart: None\n",
- "extra: {'metadata': {'arguments': {'provider_choices': {'provider': None}, 'standar..."
+ "extra: {'results_metadata': {'WALCL': {'title': 'Assets: Total Assets: Total Assets..."
]
},
- "execution_count": 4,
+ "execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
@@ -78,7 +76,7 @@
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": 3,
"metadata": {},
"outputs": [
{
@@ -110,7 +108,7 @@
}
],
"source": [
- "metadata = json.loads(data.warnings[0].message)\n",
+ "metadata = data.extra[\"results_metadata\"]\n",
"\n",
"display(metadata.keys())\n",
"display(metadata[\"WALCL\"].get(\"title\"))\n",
@@ -573,7 +571,7 @@
},
{
"cell_type": "code",
- "execution_count": 33,
+ "execution_count": 5,
"metadata": {},
"outputs": [
{
@@ -10197,7 +10195,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.4"
+ "version": "3.11.7"
},
"orig_nbformat": 4
},
diff --git a/openbb_platform/core/openbb_core/api/app_loader.py b/openbb_platform/core/openbb_core/api/app_loader.py
index 9c8330af10b..d6ff19878ca 100644
--- a/openbb_platform/core/openbb_core/api/app_loader.py
+++ b/openbb_platform/core/openbb_core/api/app_loader.py
@@ -1,12 +1,30 @@
+"""App loader module."""
+
from typing import List, Optional
from fastapi import APIRouter, FastAPI
+from openbb_core.app.router import RouterLoader
class AppLoader:
"""App loader."""
@staticmethod
+ def get_openapi_tags() -> List[dict]:
+ """Get openapi tags."""
+ main_router = RouterLoader.from_extensions()
+ openapi_tags = []
+ # Add tag data for each router in the main router
+ for r in main_router.routers:
+ openapi_tags.append(
+ {
+ "name": r,
+ "description": main_router.get_attr(r, "description"),
+ }
+ )
+ return openapi_tags
+
+ @staticmethod
def from_routers(
app: FastAPI, routers: List[Optional[APIRouter]], prefix: str
) -> FastAPI:
diff --git a/openbb_platform/core/openbb_core/api/rest_api.py b/openbb_platform/core/openbb_core/api/rest_api.py
index f166a91be4e..0ad92f613b6 100644
--- a/openbb_platform/core/openbb_core/api/rest_api.py
+++ b/openbb_platform/core/openbb_core/api/rest_api.py
@@ -67,13 +67,13 @@ app = FastAPI(
],
lifespan=lifespan,
)
-
app.add_middleware(
CORSMiddleware,
allow_origins=system.api_settings.cors.allow_origins,
allow_methods=system.api_settings.cors.allow_methods,
allow_headers=system.api_settings.cors.allow_headers,
)
+app.openapi_tags = AppLoader.get_openapi_tags()
AppLoader.from_routers(
app=app,
routers=(
diff --git a/openbb_platform/core/openbb_core/api/router/commands.py b/openbb_platform/core/openbb_core/api/router/commands.py
index d524156ddbd..2d2ea3e6a11 100644
--- a/openbb_platform/core/openbb_core/api/router/commands.py
+++ b/openbb_platform/core/openbb_core/api/router/commands.py
@@ -117,7 +117,7 @@ def build_new_signature(path: str, func: Callable) -> Signature:
)
-def validate_output(c_out: OBBject) -> OBBject:
+def validate_output(c_out: OBBject) -> Dict:
"""
Validate OBBject object.
@@ -132,8 +132,8 @@ def validate_output(c_out: OBBject) -> OBBject:
Returns
-------
- OBBject
- Validated OBBject object.
+ Dict
+ Serialized OBBject.
"""
def is_model(type_):
@@ -170,7 +170,7 @@ def validate_output(c_out: OBBject) -> OBBject:
for k, v in c_out.model_copy():
exclude_fields_from_api(k, v)
- return c_out
+ return c_out.model_dump()
def build_api_wrapper(
@@ -188,7 +188,7 @@ def build_api_wrapper(
func.__annotations__ = new_annotations_map
@wraps(wrapped=func)
- async def wrapper(*args: Tuple[Any], **kwargs: Dict[str, Any]):
+ async def wrapper(*args: Tuple[Any], **kwargs: Dict[str, Any]) -> Dict:
user_settings: UserSettings = UserSettings.model_validate(
kwargs.pop(
"__authenticated_user_settings",
@@ -198,8 +198,7 @@ def build_api_wrapper(
execute = partial(command_runner.run, path, user_settings)
output: OBBject = await execute(*args, **kwargs)
- output = validate_output(output)
- return output
+ return validate_output(output)
return wrapper
diff --git a/openbb_platform/core/openbb_core/app/model/obbject.py b/openbb_platform/core/openbb_core/app/model/obbject.py
index 2a23286836e..da8ea5d4a4d 100644
--- a/openbb_platform/core/openbb_core/app/model/obbject.py
+++ b/openbb_platform/core/openbb_core/app/model/obbject.py
@@ -26,6 +26,7 @@ from openbb_core.app.model.abstract.tagged import Tagged
from openbb_core.app.model.abstract.warning import Warning_
from openbb_core.app.model.charts.chart import Chart
from openbb_core.app.utils import basemodel_to_df
+from openbb_core.provider.abstract.annotated_result import AnnotatedResult
from openbb_core.provider.abstract.data import Data
if TYPE_CHECKING:
@@ -330,4 +331,9 @@ class OBBject(Tagged, Generic[T]):
OBBject[ResultsType]
OBBject with results.
"""
- return cls(results=await query.execute())
+ results = await query.execute()
+ if isinstance(results, AnnotatedResult):
+ return cls(
+ results=results.result, extra={"results_metadata": results.metadata}
+ )
+ return cls(results=results)
diff --git a/openbb_platform/core/openbb_core/app/model/system_settings.py b/openbb_platform/core/openbb_core/app/model/system_settings.py
index 39ceebbc813..db30f6c20df 100644
--- a/openbb_platform/core/openbb_core/app/model/system_settings.py
+++ b/openbb_platform/core/openbb_core/app/model/system_settings.py
@@ -15,7 +15,7 @@ from openbb_core.app.constants import (
)
from openbb_core.app.model.abstract.tagged import Tagged
from openbb_core.app.model.fast_api_settings import FastAPISettings
-from openbb_core.app.version import VERSION
+from openbb_core.app.version import CORE_VERSION, VERSION
class SystemSettings(Tagged):
@@ -28,6 +28,7 @@ class SystemSettings(Tagged):
# OpenBB section
version: str = VERSION
+ core: str = CORE_VERSION
home_directory: str = str(HOME_DIRECTORY)
openbb_directory: str = str(OPENBB_DIRECTORY)
user_settings_path: str = str(USER_SETTINGS_PATH)
diff --git a/openbb_platform/core/openbb_core/app/router.py b/openbb_platform/core/openbb_core/app/router.py
index 218629be8ba..68ac8dec3ec 100644
--- a/openbb_platform/core/openbb_core/app/router.py
+++ b/openbb_platform/core/openbb_core/app/router.py
@@ -203,15 +203,33 @@ class Router:
"""API Router."""
return self._api_router
+ @property
+ def prefix(self) -> str:
+ """Prefix."""
+ return self._api_router.prefix
+
+ @property
+ def description(self) -> str:
+ """Description."""
+ return self._description
+
+ @property
+ def routers(self) -> Dict[str, "Router"]:
+ """Routers nested within the Router, i.e. sub-routers."""
+ return self._routers
+
def __init__(
self,
prefix: str = "",
+ description: str = "",
) -> None:
"""Initialize Router."""
self._api_router = APIRouter(
prefix=prefix,
responses={404: {"description": "Not found"}},
)
+ self._description = description
+ self._routers: Dict[str, Router] = {}
@overload
def command(self, func: Optional[Callable[P, OBBject]]) -> Callable[P, OBBject]:
@@ -290,10 +308,41 @@ class Router:
prefix: str = "",
):
"""Include router."""
- tags = [prefix[1:]] if prefix else None
+ tags = [prefix.strip("/")] if prefix else None
self._api_router.include_router(
router=router.api_router, prefix=prefix, tags=tags # type: ignore
)
+ name = prefix if prefix else router.prefix
+ self._routers[name.strip("/")] = router
+
+ def get_attr(self, path: str, attr: str) -> Any:
+ """Get router attribute from path.
+
+ Parameters
+ ----------
+ path : str
+ Path to the router or nested router.
+ E.g. "/equity" or "/equity/price".
+ attr : str
+ Attribute to get.
+
+ Returns
+ -------
+ Any
+ Attribute value.
+ """
+ return self._search_attr(self, path, attr)
+
+ @staticmethod
+ def _search_attr(router: "Router", path: str, attr: str) -> Any:
+ """Recursively search router attribute from path."""
+ path = path.strip("/")
+ first = path.split("/")[0]
+ if first in router.routers:
+ return Router._search_attr(