Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDK Added about() for methods and class, fixed pypi.md #4273

Merged
merged 5 commits into from
Feb 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion openbb_terminal/account/account_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def update_runtime_choices(self):
"""Update runtime choices"""
self.ROUTINE_FILES = self.get_routines()
if session and obbff.USE_PROMPT_TOOLKIT:
choices: dict = {c: {} for c in self.controller_choices}
choices: dict = {c: {} for c in self.controller_choices} # type: ignore
choices["sync"] = {"--on": {}, "--off": {}}
choices["upload"]["--file"] = {c: {} for c in self.ROUTINE_FILES}
choices["upload"]["-f"] = choices["upload"]["--file"]
Expand Down
2 changes: 1 addition & 1 deletion openbb_terminal/core/log/collection/log_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def run(self):
identifier = app_settings.identifier

while True:
item: QueueItem = queue.get()
item: QueueItem = queue.get() # type: ignore
file = item.path
last = item.last

Expand Down
2 changes: 1 addition & 1 deletion openbb_terminal/economy/economy_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -1666,7 +1666,7 @@ def call_qa(self, _):
QaController,
)

data: Dict = {}
data: Dict = {} # type: ignore
for source, _ in self.DATASETS.items():
if not self.DATASETS[source].empty:
if len(self.DATASETS[source].columns) == 1:
Expand Down
2 changes: 1 addition & 1 deletion openbb_terminal/forecast/forecast_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def update_runtime_choices(self):
# Load in any newly exported files
self.DATA_FILES = forecast_model.get_default_files()
if session and obbff.USE_PROMPT_TOOLKIT:
choices: dict = self.choices_default
choices: dict = self.choices_default # type: ignore

self.choices = choices
self.completer = NestedCompleter.from_nested_dict(choices)
Expand Down
2 changes: 1 addition & 1 deletion openbb_terminal/reports/reports_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def update_choices(self):
)

if session and obbff.USE_PROMPT_TOOLKIT:
self.choices: dict = {c: {} for c in self.controller_choices}
self.choices: dict = {c: {} for c in self.controller_choices} # type: ignore
self.choices["run"] = {
"--file": {c: None for c in reports_model.USER_REPORTS},
"-f": "--file",
Expand Down
94 changes: 65 additions & 29 deletions openbb_terminal/sdk_core/sdk_helpers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""OpenBB Terminal SDK Helpers."""
import json
from inspect import signature
from logging import Logger, getLogger
from typing import Any, Callable, Dict, Optional

Expand All @@ -15,6 +16,7 @@
OPTIMIZATION_TOOLKIT_ENABLED,
OPTIMIZATION_TOOLKIT_WARNING,
)
from openbb_terminal.session.sdk_session import login

if not FORECASTING_TOOLKIT_ENABLED and not load_env_vars(
"OPENBB_DISABLE_FORECASTING_WARNING", strtobool, False
Expand Down Expand Up @@ -51,23 +53,49 @@ def class_repr(cls_dict: Dict[str, Any]) -> list:
]


def helptext(func: Callable) -> Callable:
"""Wrapper to preserve the help text of the function."""
class Operation:
def __init__(self, name: str, trail: str, func: Callable) -> None:
self._trail = trail
self._method = func
self._name = name

def decorator(f: Callable) -> Callable:
for attr in [
"__doc__",
"__name__",
"__annotations__",
"__module__",
"__defaults__",
"__kwdefaults__",
"__dict__",
"__module__",
]:
setattr(f, attr, getattr(func, attr))
return f
setattr(self.__class__, attr, getattr(func, attr))
setattr(self, attr, getattr(func, attr))

self.__signature__ = signature(func)
self.__class__.__signature__ = signature(func)

def __call__(self, *args: Any, **kwargs: Any) -> Any:
method = self._method

# We make a copy of the kwargs to avoid modifying the original
log_kwargs = kwargs.copy()
log_kwargs["chart"] = "chart" in self._name

operation_logger = OperationLogger(
trail=self._trail, method_chosen=method, args=args, kwargs=log_kwargs
)
operation_logger.log_before_call()
method_result = method(*args, **kwargs)
operation_logger.log_after_call(method_result=method_result)

return method_result

def about(self):
# pylint: disable=C0415
import webbrowser

return decorator
trail = "/".join(self._trail.split("."))
url = f"https://docs.openbb.co/sdk/reference/{trail}"
webbrowser.open(url)


class Category:
Expand All @@ -93,33 +121,27 @@ def __getattribute__(self, name: str):
"""We override the __getattribute__ method and wrap all callable
attributes with a wrapper that logs the call and the result.
"""
if name.startswith("_"):
return super().__getattribute__(name)

attr = super().__getattribute__(name)
trail = f"{self.__class__._location_path}.{name}"

if callable(attr):
if isinstance(attr, Operation) or name.startswith("__"):
return attr

@helptext(attr)
def wrapper(*args, **kwargs):
method = attr
trail = f"{self.__class__._location_path}.{name}"

# We make a copy of the kwargs to avoid modifying the original
log_kwargs = kwargs.copy()
log_kwargs["chart"] = "chart" in name
if callable(attr) and not isinstance(attr, Operation):
# We set the attribute to the wrapped function so that we don't
# have to wrap it when called again.
setattr(self, name, Operation(name=name, trail=trail, func=attr))
return getattr(self, name)

operation_logger = OperationLogger(
trail=trail, method_chosen=method, args=args, kwargs=log_kwargs
)
operation_logger.log_before_call()
method_result = method(*args, **kwargs)
operation_logger.log_after_call(method_result=method_result)
return attr

return method_result
def about(self):
# pylint: disable=C0415
import webbrowser

return wrapper
return attr
trail = "/".join(self._location_path.split("."))
url = f"https://docs.openbb.co/sdk/reference/{trail}"
webbrowser.open(url)


class OperationLogger:
Expand Down Expand Up @@ -257,6 +279,9 @@ def log_after_call(
method_result=method_result,
method_chosen=self.__method_chosen,
)
self.__log_if_login(
method_chosen=self.__method_chosen,
)
self.__log_end(
logger=logger,
method_chosen=self.__method_chosen,
Expand All @@ -280,6 +305,17 @@ def __log_exception_if_any(
extra={"func_name_override": method_chosen.__name__},
)

@staticmethod
def __log_if_login(
method_chosen: Callable,
):
if method_chosen.__name__ == login.__name__:
from openbb_terminal.core.log.generation.user_logger import ( # pylint: disable=import-outside-toplevel
log_user,
)

log_user(with_rollover=False)

@staticmethod
def __log_end(logger: Logger, method_chosen: Callable):
logger.info(
Expand Down
2 changes: 1 addition & 1 deletion openbb_terminal/stocks/options/hedge/hedge_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ def call_sop(self, other_args):

for _, value in self.options.items():
if value:
option_side: str = "Long" if value["sign"] == 1 else "Short"
option_side: str = "Long" if value["sign"] == 1 else "Short" # type: ignore
positions = positions.append(
[
[
Expand Down
2 changes: 1 addition & 1 deletion openbb_terminal/terminal_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def update_runtime_choices(self):
self.ROUTINE_CHOICES["--h"] = None

if session and obbff.USE_PROMPT_TOOLKIT:
choices: dict = {c: {} for c in self.controller_choices}
choices: dict = {c: {} for c in self.controller_choices} # type: ignore
choices["support"] = self.SUPPORT_CHOICES
choices["exe"] = self.ROUTINE_CHOICES
choices["news"] = self.NEWS_CHOICES
Expand Down
6 changes: 3 additions & 3 deletions website/content/sdk/quickstart/pypi.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

| OpenBB is committed to build the future of investment research by focusing on an open source infrastructure accessible to everyone, everywhere. |
|:--:|
| <img width="1000" alt="Screenshot 2023-02-14 at 5 12 08 PM" src="https://user-images.githubusercontent.com/25267873/218899768-1f0964b8-326c-4f35-af6f-ea0946ac970b.png"> |
| ![OpenBBLogo](https://user-images.githubusercontent.com/25267873/218899768-1f0964b8-326c-4f35-af6f-ea0946ac970b.png) |
| Check our website at [openbb.co](www.openbb.co) |


Expand Down Expand Up @@ -41,10 +41,10 @@ ___

Access raw financial data from any data source that you are interested. The open source nature of this SDK makes it so that this is an ever-growing project and that everyone can contribute to.

![image-20221025-092439 2](https://user-images.githubusercontent.com/25267873/218906336-cebd1fc8-7e7a-45bc-a5fc-641eb19c3e8c.png)
![Stocks Load](https://user-images.githubusercontent.com/25267873/218906336-cebd1fc8-7e7a-45bc-a5fc-641eb19c3e8c.png)

#### GENERATE INSIGHTS 10X FASTER

For most of the functionalities, adding `_chart` to the function will allow you to visualize the output directly from a Jupyter Notebook. Not only speeding up the time it takes to create a plot for the data you are interested in, but making building custom reports much faster.

<img width="992" alt="Group 550" src="https://user-images.githubusercontent.com/25267873/218906112-b2272d43-11fc-4ec1-9a8f-b2d8e2ed7dc1.png">
![Economy Treasury Chart](https://user-images.githubusercontent.com/25267873/218906112-b2272d43-11fc-4ec1-9a8f-b2d8e2ed7dc1.png)