mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-02 23:41:27 +00:00
* Rename SDK folder * Fixing all the tests I hope * Depreciate the sia menu * Fix routine script * Update SDK generation scripts * This needed fixing anyways * Regenerate SDK files * Update paths in sdk helpers * Regenerate the remains of the SDK * Fix candle not working with symbol via the sdk * Fix pydocstyle errors * deps * Add in Docstrings * Push to website since I need to upload images * typos * Add in Fixed Income Guide * Tests : fix cassette * changes to layout and adding more content * trailmap * poetry * updates to requirements files * add `_try_to_login` to sdk generation, fix `_chart` in `about()` url * sentiment analysis * refactor * changing to base model default * rounding * renewing poetry * fixed poetry * spacing * black * adds selectable models for realized volatility calculations * fixes line too long * Add intro guides to Fixed Income * Fix some missing docstrings * Fix website not working * missed a few * fix /economy/test_yfinance_view tests * fix etf/test_stockanalysis_model.py * fix etf/test_stockanalysis_view.py * fix test_stocks_controller * deprecating non used function * update financedatabase to 2.0.4 * Delete SIA from OpenBB Docs and SDK * Searching was not done properly for short name and index * changes the default data source for crypto.load * Fix tests I broke * Little fixy fix to remove duplicates * Fix tests * typo * adds check for empty dataframe * Patch Equity Report * Update so that image links to website * linting v2 * silly imports * adding tempfile * add imap unordered * reordering imports * Adding databento as a source (#4293) * First commit * Baby steps * Keys and sdk * Fix import for api key * Add SDK endpoints * Test + api checks * tests * roque print of api key * Changes * minor * custom timeout * improve timeouts --------- Co-authored-by: hjoaquim <h.joaquim@campus.fct.unl.pt> * Tests * Integration test * frozendict remove * update spec * rename sdk faq to troubleshooting * add hidden import * add hidden imports * imports again * valid url check * new lines and prompt * split imports * more spec * adds cones to the crypto-ta menu * Fix tests * Update code to reflect new changes to FinanceDatabase * Small bugfix for DCF if you have no ticker loaded * remove yfinance from news * add reverse fx choices * black * ruff * Add options greeks to the SDK * Linting * Delete rogue file and update test and add fixedincome to en.yml * fix for options screener * ruff * updates tests for options screener * reqs * updates more test files * rewrite for test_github_model * rewrite test for test_syncretism_view * removes test_view_available_presets[] * black * coverage * adds option screener preset * Update directories.py * len & set * set all list * adds unit testing for cones * ruff * pylint * adds options screener endpoint to SDK * test markers * Testing draft PR mode * Update package to v2.0.7 * Remove etf/screener and tests * Updated * Merge reqs * Updated readme * hook test for pyinstaller * Little fixy fix * Remove etf/scr from SDK * Update tests * Update hook-whisper.py * oops lol * Update sdk * update * Etf * removed old trailmap csv's * Update fixedincome text * add greeks to trail * rouge file * merge killed it * fix test * fix build failure * catch for error message * fix for frozendict * caching search and prompting on hub * whisper model prompts * Fix long/short issue and fix transform issue * separates volatility models from cones function * Introduce CPI functionality * improves error handling for volatility models when window length is too small * ur welcome <3 * additional sanity check for volatility_view * updates volatility_model test * black * Fix linting * Make cpi a little bit more robust * Add in missing value * sdk updates * update dep files * Update trail_map_forecasting.csv * import ordering pylint? * fix trailing comma * sorted trailmaps * remove one test artifact * rewrite test * Adds the missing pieces. * adds clickable URL in keys + Databento * adds databento images * adds images for Databento * update deps * req files * swap order in databento * ruff * mypy * lint * sdk * makes requested changes * ruff v2.. * replaces screenshot. * Removed because it shouldn't have been in this PR. * ruff v3 * Minor edit, move installation to position 2 instead of last * util linting changes * linting for controller * fix test * test * Revert some tests * Guess not * see if this sticks * fixes * Fix linters. Add --video if not provided * Checkout develop tests for keys * Release time * Revert papermill and update gh pages action * Fix shortname (#4356) * uninstall brotli on conda test * Fix issue 4316 (#4357) * Fix issue 4316 * Updating polygon_model + options_controller * Tests : FRED * ruff --------- Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com> Co-authored-by: Jeroen Bouma <jer.bouma@gmail.com> Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com> Co-authored-by: hjoaquim <h.joaquim@campus.fct.unl.pt> Co-authored-by: Chavithra PARANA <chavithra@gmail.com> Co-authored-by: teh_coderer <me@tehcoderer.com> Co-authored-by: martinb-bb <105685594+martinb-bb@users.noreply.github.com> Co-authored-by: Diogo Sousa <montezdesousa@gmail.com> Co-authored-by: northern-64bit <75195383+northern-64bit@users.noreply.github.com> Co-authored-by: luqazino@gmail.com <luqazino@gmail.com> Co-authored-by: colin99d <colin99delahunty@gmail.com> Co-authored-by: montezdesousa <79287829+montezdesousa@users.noreply.github.com> Co-authored-by: andrewkenreich <andrew.kenreich@gmail.com>
227 lines
7.6 KiB
Python
227 lines
7.6 KiB
Python
import importlib.util
|
|
import os
|
|
from datetime import datetime
|
|
from inspect import getmembers, isfunction
|
|
from pathlib import Path
|
|
from typing import Callable, List, Tuple
|
|
|
|
import pandas as pd
|
|
|
|
try:
|
|
import darts # pylint: disable=W0611 # noqa: F401
|
|
|
|
# If you just import darts this will pass during pip install, this creates
|
|
# Failures later on, also importing utils ensures that darts is installed correctly
|
|
from darts import utils # pylint: disable=W0611 # noqa: F401
|
|
|
|
FORECASTING = True
|
|
except ImportError:
|
|
FORECASTING = False
|
|
|
|
base_path = Path(__file__).parent.parent.parent.parent / "openbb_terminal"
|
|
|
|
|
|
def load_modules(full_path: Path):
|
|
"""Loads a module from a given Path.
|
|
|
|
Parameter:
|
|
----------
|
|
full_path: Path
|
|
The path to the module
|
|
|
|
Returns:
|
|
----------
|
|
The python module
|
|
"""
|
|
mod_path = str(full_path).split("OpenBBTerminal" + os.sep)[1].replace(os.sep, ".")
|
|
spec = importlib.util.spec_from_file_location(mod_path, full_path)
|
|
if not spec:
|
|
raise ValueError(f"Could not import path: {full_path}")
|
|
mod = importlib.util.module_from_spec(spec)
|
|
if not mod:
|
|
raise ValueError(f"Could not import path: {full_path}")
|
|
if not spec.loader:
|
|
raise ValueError(f"Could not import path: {full_path}")
|
|
spec.loader.exec_module(mod)
|
|
return mod
|
|
|
|
|
|
def all_view_models() -> List[Path]:
|
|
"""Geta all files with 'view' or 'model' in the name.
|
|
|
|
Returns:
|
|
----------
|
|
List[Path]
|
|
All paths in openbb_terminal with 'view' or 'model' in the name
|
|
"""
|
|
|
|
file_list = []
|
|
all_files = os.walk(base_path)
|
|
for root, _, files in all_files:
|
|
for filename in files:
|
|
if filename.endswith(".py") and ("view" in filename or "model" in filename):
|
|
file_list.append(f"{root}/{filename}")
|
|
clean_list = set(file_list)
|
|
return [Path(x) for x in clean_list]
|
|
|
|
|
|
def get_sdk(file_path: str = "miscellaneous/library/trail_map.csv") -> pd.DataFrame:
|
|
"""Reads the CSV that generates the sdk and converts it to a dataframe
|
|
|
|
Parameters
|
|
----------
|
|
file_path: str
|
|
The path to the sdk csv
|
|
|
|
Returns:
|
|
----------
|
|
pd.DataFrame
|
|
A dataframe with columns for sdk endpoint functiom and trail. Trails will be duplicated
|
|
because there is a model and view function
|
|
"""
|
|
df = pd.read_csv(base_path / file_path)
|
|
df_dups = len(df["trail"]) - len(df["trail"].drop_duplicates())
|
|
if df_dups > 0:
|
|
print(f"Number of duplicate sdk paths: {df_dups}")
|
|
print("This indicates that the same SDK trail is being used multiple times\n")
|
|
views = list(df[["view", "trail"]].itertuples(index=False, name=None))
|
|
models = list(df[["model", "trail"]].itertuples(index=False, name=None))
|
|
# Add in whether it is a view or a model in pandas
|
|
combined = [x + ("view",) for x in views] + [x + ("model",) for x in models]
|
|
final_df = pd.DataFrame()
|
|
final_df["name"] = [x[0] for x in combined]
|
|
final_df["trail"] = [x[1] for x in combined]
|
|
final_df["type"] = [x[2] for x in combined]
|
|
final_df = final_df.dropna()
|
|
final_df = final_df.set_index("name")
|
|
return final_df
|
|
|
|
|
|
def format_function(function: Callable) -> Tuple[str, str]:
|
|
"""Gives a function a pretty name
|
|
|
|
Parameters
|
|
----------
|
|
function: Callable
|
|
The function to get a pretty string for
|
|
|
|
Returns:
|
|
----------
|
|
Tuple[str, str]
|
|
The functions pretty name and docstring
|
|
"""
|
|
mod = str(function.__module__)[:-2].replace("/", ".")
|
|
name = function.__name__
|
|
if mod[-1] != ".":
|
|
mod = f"{mod}."
|
|
return f"{mod}{name}", str(function.__doc__)
|
|
|
|
|
|
def functions_df() -> pd.DataFrame:
|
|
"""Creates a dataframe for all functions in 'models' and 'views'.
|
|
|
|
Returns:
|
|
----------
|
|
pd.DataFrame
|
|
Information for all view and model functions
|
|
"""
|
|
modules = all_view_models()
|
|
all_formatted = []
|
|
for module in modules:
|
|
if not FORECASTING and "forecast" in str(module):
|
|
continue
|
|
loaded = load_modules(module)
|
|
# Gets all of a module's functions, but ignores imported functions
|
|
func_list = [
|
|
x[1]
|
|
for x in getmembers(loaded, isfunction)
|
|
if x[1].__module__ == loaded.__name__
|
|
]
|
|
formatted_list = [format_function(x) for x in func_list]
|
|
all_formatted.extend(formatted_list)
|
|
func_df = pd.DataFrame()
|
|
func_df["name"] = [x[0] for x in all_formatted]
|
|
func_df["docstring"] = [x[1] for x in all_formatted]
|
|
func_dups = len(func_df["name"]) - len(func_df["name"].drop_duplicates())
|
|
if func_dups > 0:
|
|
print(f"Number of duplicate functions found: {func_dups}")
|
|
print(
|
|
"This may indicate that functions are defined several times in the terminal.\n"
|
|
)
|
|
func_df = func_df.set_index("name")
|
|
return func_df
|
|
|
|
|
|
def save_df(data: pd.DataFrame) -> None:
|
|
timestamp = datetime.now().timestamp()
|
|
time_str = (str(timestamp)).replace(".", "")
|
|
output_path = f"{time_str}_sdk_audit.csv"
|
|
data.to_csv(output_path)
|
|
print(f"File saved to {output_path}")
|
|
|
|
|
|
def get_nonconforming_functions(data: pd.DataFrame) -> pd.DataFrame:
|
|
"""When we first check all functions we only look in model and view files. This means that any
|
|
function in the helpers will be ignored. This function checks any helper funcs in the sdk
|
|
treemap, so that we can get a clearer picture of whether or not functions exist
|
|
|
|
Parameters
|
|
----------
|
|
data: pd.DataFrame
|
|
The dataframe of all values, this will be searched
|
|
|
|
Returns
|
|
----------
|
|
pd.DataFrame
|
|
The dataframe with any functions that could not be found
|
|
"""
|
|
df = data[data["docstring"].isnull()]
|
|
names = df.index.tolist()
|
|
for name in names:
|
|
path_list = name.split(".")
|
|
file = "/".join(path_list[:-1])
|
|
mod_path = Path(__file__).parent.parent.parent.parent / f"{file}.py"
|
|
module = load_modules(mod_path)
|
|
command = path_list[-1]
|
|
function = getattr(module, command)
|
|
if function:
|
|
data.loc[name, "docstring"] = function.__doc__
|
|
return data
|
|
|
|
|
|
def main():
|
|
print(
|
|
"This tool checks all functions in a file with a name including 'view' or 'model'against\n"
|
|
"all functions in the sdk, which is gathered from 'trail_map.csv'. If the generated csv\n"
|
|
"has an entry for 'trail' that means it is in the SDK, and if it has an entry for\n"
|
|
"'docstring' it is in a model or view.\n"
|
|
)
|
|
funcs_df = functions_df()
|
|
sdk_df = get_sdk()
|
|
|
|
final_df = funcs_df.merge(sdk_df, how="outer", left_index=True, right_index=True)
|
|
final_df = final_df.sort_values("name")
|
|
final_df = get_nonconforming_functions(final_df)
|
|
# Do this so that the duplicated method also checks the name column
|
|
final_df = final_df.reset_index()
|
|
# Get further stats on bad data
|
|
no_doc_count = len(final_df[final_df["docstring"].isnull()].index)
|
|
if no_doc_count > 0:
|
|
print(f"The number of rows with blank docstrings is: {no_doc_count}")
|
|
print(
|
|
"This indicates a matching function does not exist, is not in a 'model' or 'view'\n"
|
|
"file, or that the trailmap does not import it from the place it is defined.\n"
|
|
)
|
|
dup_name_count = len(final_df[final_df.duplicated(keep=False)].index)
|
|
if dup_name_count > 0:
|
|
print(f"The number of duplicate functions after merge is: {dup_name_count}")
|
|
print(
|
|
"This most likely indicates that the same function is being used at "
|
|
"different SDK endpoints.\n"
|
|
)
|
|
save_df(final_df)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|