diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 40153f66e0d1..5586ff6544eb 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -55,3 +55,12 @@ jobs: with: workflow: docker.yml token: ${{ secrets.GITHUB_TOKEN }} + + trigger-pypi-build: + runs-on: ubuntu-latest + steps: + - name: Trigger PyPI Build + uses: aurelien-baudet/workflow-dispatch@v2 + with: + workflow: nightly-pypi.yml + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/nightly-pypi.yml b/.github/workflows/nightly-pypi.yml new file mode 100644 index 000000000000..7035655e380d --- /dev/null +++ b/.github/workflows/nightly-pypi.yml @@ -0,0 +1,48 @@ +name: Deploy to PyPI - Nightly + +on: workflow_dispatch + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + deploy-nightly-pypi: + name: Build and publish nightly distributions 📦 to PyPI + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Setup Python 3.9 + uses: actions/setup-python@v4 + with: + python-version: "3.9" + + - name: Update version in pyproject.toml and Edit docs + run: | + sed -i 's/name = ".*"/name = "openbb-nightly"/' pyproject.toml + sed -i "3s/version = \"\(.*\)\"/version = \"\1.dev$(date +%Y%m%d)\"/" pyproject.toml + head pyproject.toml + sed -i 's/pip install openbb/pip install openbb-nightly/g; s/from openbb_terminal.sdk import openbb/from openbb_terminal.sdk import openbb-nightly/g' ./website/content/sdk/quickstart/pypi.md + + + - name: Install pypa/build + run: >- + python -m + pip install + build + --user + + - name: Build a binary wheel and a source tarball + run: >- + python -m + build + --sdist + --wheel + --outdir dist/ + . + + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.NIGHTLY_PYPI_API_TOKEN }} diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 59b61111acee..588a8dfeb962 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -14,7 +14,7 @@ concurrency: jobs: deploy-test-pypi: - name: Build and publish distributions 📦 to PyPI and TestPyPI + name: Build and publish 📦 to TestPyPI if: startsWith(github.ref, 'refs/heads/release/') runs-on: ubuntu-latest @@ -47,7 +47,7 @@ jobs: repository_url: https://test.pypi.org/legacy/ deploy-pypi: - name: Build and publish distributions 📦 to PyPI and TestPyPI + name: Build and publish 📦 to PyPI if: startsWith(github.ref, 'refs/heads/main') runs-on: ubuntu-latest diff --git a/openbb_terminal/core/config/paths.py b/openbb_terminal/core/config/paths.py index 6cbf00611d09..e5b44b65cfef 100644 --- a/openbb_terminal/core/config/paths.py +++ b/openbb_terminal/core/config/paths.py @@ -27,7 +27,7 @@ def get_user_data_directory(): USER_CUSTOM_IMPORTS_DIRECTORY = USER_DATA_DIRECTORY / "custom_imports" USER_PORTFOLIO_DATA_DIRECTORY = USER_DATA_DIRECTORY / "portfolio" USER_ROUTINES_DIRECTORY = USER_DATA_DIRECTORY / "routines" -USER_DATA_SOURCES_DEFAULT_FILE = USER_DATA_DIRECTORY / "data_sources_default.json" +USER_DATA_SOURCES_DEFAULT_FILE = MISCELLANEOUS_DIRECTORY / "data_sources_default.json" USER_PRESETS_DIRECTORY = USER_DATA_DIRECTORY / "presets" USER_REPORTS_DIRECTORY = USER_DATA_DIRECTORY / "reports" USER_CUSTOM_REPORTS_DIRECTORY = USER_DATA_DIRECTORY / "reports" / "custom reports" diff --git a/openbb_terminal/core/library/operation.py b/openbb_terminal/core/library/operation.py index 596a406e8f66..1483be1398cf 100644 --- a/openbb_terminal/core/library/operation.py +++ b/openbb_terminal/core/library/operation.py @@ -7,7 +7,6 @@ import openbb_terminal.config_terminal as cfg from openbb_terminal.core.library.metadata import Metadata from openbb_terminal.core.library.trail_map import TrailMap -from openbb_terminal.session.sdk_session import login # pylint: disable=import-outside-toplevel @@ -249,9 +248,6 @@ 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, @@ -275,17 +271,6 @@ 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( diff --git a/openbb_terminal/core/log/generation/custom_logger.py b/openbb_terminal/core/log/generation/custom_logger.py index e27a3dd7741a..483265adc25e 100644 --- a/openbb_terminal/core/log/generation/custom_logger.py +++ b/openbb_terminal/core/log/generation/custom_logger.py @@ -1,7 +1,7 @@ # IMPORTATION STANDARD import logging -from openbb_terminal.core.log.generation import settings_logger, user_logger +from openbb_terminal.core.log.generation import settings_logger from openbb_terminal.core.log.generation.common import do_rollover # IMPORTATION THIRDPARTY @@ -19,5 +19,4 @@ def log_terminal(test_mode: bool): logger.info("START") settings_logger.log_all_settings(with_rollover=False) - user_logger.log_user(with_rollover=False) do_rollover() diff --git a/openbb_terminal/core/log/generation/formatter_with_exceptions.py b/openbb_terminal/core/log/generation/formatter_with_exceptions.py index 8e7d4ed6857f..1b569af582f4 100644 --- a/openbb_terminal/core/log/generation/formatter_with_exceptions.py +++ b/openbb_terminal/core/log/generation/formatter_with_exceptions.py @@ -6,6 +6,7 @@ # IMPORTATION INTERNAL from openbb_terminal.core.config.paths import HOME_DIRECTORY from openbb_terminal.core.log.generation.settings import AppSettings +from openbb_terminal.core.log.generation.user_logger import get_user_uuid class FormatterWithExceptions(logging.Formatter): @@ -36,8 +37,6 @@ def extract_log_extra(record: logging.LogRecord): record.funcName = record.func_name_override # type: ignore record.lineno = 0 - log_extra["userId"] = getattr(record, "user_id", "NA") - if hasattr(record, "session_id"): log_extra["sessionId"] = record.session_id # type: ignore @@ -149,7 +148,9 @@ def format(self, record: logging.LogRecord) -> str: "appId": app_settings.identifier, "sessionId": app_settings.session_id, "commitHash": app_settings.commit_hash, + "userId": get_user_uuid(), } + log_extra = self.extract_log_extra(record=record) log_prefix_content = {**log_prefix_content, **log_extra} log_prefix = self.LOGPREFIXFORMAT % log_prefix_content diff --git a/openbb_terminal/core/log/generation/settings.py b/openbb_terminal/core/log/generation/settings.py index 2c4486746759..fd637ada0a38 100644 --- a/openbb_terminal/core/log/generation/settings.py +++ b/openbb_terminal/core/log/generation/settings.py @@ -42,12 +42,21 @@ def identifier(self) -> str: def session_id(self) -> str: return self.__session_id + @property + def user_id(self) -> str: + return self.__user_id + + @user_id.setter + def user_id(self, value: str): + self.__user_id = value + def __init__( self, name: str, commit_hash: str, session_id: str, identifier: str, + user_id: str, ): """ Args: @@ -55,12 +64,14 @@ def __init__( commit_hash (str): Commit hash of the current running code. identifier (str): Unique key identifying a particular installation. session_id (str): Key identifying a particular running session. + user_id (str): Hash identifying a particular user. """ self.__name = name self.__commit_hash = commit_hash self.__identifier = identifier self.__session_id = session_id + self.__user_id = user_id class LogSettings: diff --git a/openbb_terminal/core/log/generation/user_logger.py b/openbb_terminal/core/log/generation/user_logger.py index 635af0b83f94..d8f2c3049fa1 100644 --- a/openbb_terminal/core/log/generation/user_logger.py +++ b/openbb_terminal/core/log/generation/user_logger.py @@ -1,26 +1,19 @@ # IMPORTATION STANDARD -import json import logging -from openbb_terminal.core.log.generation.common import do_rollover - # IMPORTATION THIRDPARTY # IMPORTATION INTERNAL from openbb_terminal.session.user import User logger = logging.getLogger(__name__) +NO_USER_PLACEHOLDER = "NA" -def log_user(with_rollover: bool = True): - """Log user""" - if not User.is_guest(): - _log_user_info() - if with_rollover: - do_rollover() +def get_user_uuid() -> str: + """Get user UUID""" + if not User.is_guest(): + return User.get_uuid() -def _log_user_info(): - """Log user info""" - user_info = {"user_uuid": User.get_uuid()} - logger.info("USER: %s ", json.dumps(user_info)) + return NO_USER_PLACEHOLDER diff --git a/openbb_terminal/economy/economy_controller.py b/openbb_terminal/economy/economy_controller.py index db94b512aed4..aef5815a8be9 100644 --- a/openbb_terminal/economy/economy_controller.py +++ b/openbb_terminal/economy/economy_controller.py @@ -1591,6 +1591,7 @@ def call_eval(self, other_args): type=str, nargs="+", dest="query", + required="-h" not in other_args, help="Query to evaluate on loaded datasets", ) if other_args and "-" not in other_args[0][0]: diff --git a/openbb_terminal/loggers.py b/openbb_terminal/loggers.py index d4c0fe2a20bf..cdd09b0d4adf 100644 --- a/openbb_terminal/loggers.py +++ b/openbb_terminal/loggers.py @@ -40,6 +40,7 @@ LogSettings, Settings, ) +from openbb_terminal.core.log.generation.user_logger import get_user_uuid logging.getLogger("requests").setLevel(LOGGING_VERBOSITY) logging.getLogger("urllib3").setLevel(LOGGING_VERBOSITY) @@ -166,6 +167,7 @@ def setup_logging( name = app_name or LOGGING_APP_NAME identifier = get_app_id() session_id = session_id or str(START_TIMESTAMP) + user_id = get_user_uuid() # AWSSettings aws_access_key_id = LOGGING_AWS_ACCESS_KEY_ID @@ -184,6 +186,7 @@ def setup_logging( name=name, identifier=identifier, session_id=session_id, + user_id=user_id, ), aws_settings=AWSSettings( aws_access_key_id=aws_access_key_id, diff --git a/openbb_terminal/sdk.py b/openbb_terminal/sdk.py index 6e5b69548a8c..f9a9ed7d82a9 100644 --- a/openbb_terminal/sdk.py +++ b/openbb_terminal/sdk.py @@ -22,6 +22,7 @@ ) from openbb_terminal import feature_flags as obbff from openbb_terminal.session.user import User +from openbb_terminal.terminal_helper import is_auth_enabled if User.is_guest(): load_dotenv_and_reload_configs() @@ -48,6 +49,14 @@ def __init__(self): self.logout = lib.sdk_session.logout self.news = lib.common_feedparser_model.get_news self.whoami = lib.sdk_session.whoami + self._try_to_login() + + def _try_to_login(self): + if User.is_guest() and is_auth_enabled(): + try: + self.login() + except Exception: + pass @property def alt(self): diff --git a/openbb_terminal/sdk_core/sdk_helpers.py b/openbb_terminal/sdk_core/sdk_helpers.py index 0d86bbc2fd3e..42924069b5f4 100644 --- a/openbb_terminal/sdk_core/sdk_helpers.py +++ b/openbb_terminal/sdk_core/sdk_helpers.py @@ -16,7 +16,6 @@ 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 @@ -279,9 +278,6 @@ 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, @@ -305,17 +301,6 @@ 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( diff --git a/openbb_terminal/session/sdk_session.py b/openbb_terminal/session/sdk_session.py index 3606885662cc..13084c3fd9a3 100644 --- a/openbb_terminal/session/sdk_session.py +++ b/openbb_terminal/session/sdk_session.py @@ -1,3 +1,6 @@ +import logging + +from openbb_terminal.decorators import log_start_end from openbb_terminal.rich_config import console from openbb_terminal.session import ( local_model as Local, @@ -5,6 +8,8 @@ ) from openbb_terminal.session.user import User +logger = logging.getLogger(__name__) + def get_session(email: str, password: str, token: str, save: bool): session = "" @@ -13,7 +18,7 @@ def get_session(email: str, password: str, token: str, save: bool): console.print("Creating session from token.") session = session_model.create_session_from_token(token, save) # type: ignore - if not session: + if not session and email: console.print("Creating session from email and password.") session = session_model.create_session(email, password, save) # type: ignore @@ -23,6 +28,7 @@ def get_session(email: str, password: str, token: str, save: bool): return session +@log_start_end(log=logger) def login( email: str = "", password: str = "", token: str = "", keep_session: bool = False ): @@ -49,11 +55,10 @@ def login( >>> from openbb_terminal.sdk import openbb >>> openbb.login(email="your_email", password="your_password") """ - - session = Local.get_session() + if not (email or token): + session = Local.get_session() if not session: - console.print("No local session found. Creating new session.") session = get_session(email, password, token, keep_session) else: console.print("Using local session to login.") @@ -65,6 +70,7 @@ def login( console.print("[green]Login successful.[/green]") +@log_start_end(log=logger) def logout(): """ Logout and clear session. @@ -81,6 +87,7 @@ def logout(): ) +@log_start_end(log=logger) def whoami(): """ Display user info. diff --git a/tests/openbb_terminal/core/log/conftest.py b/tests/openbb_terminal/core/log/conftest.py index 705512921fa4..6069187d858b 100644 --- a/tests/openbb_terminal/core/log/conftest.py +++ b/tests/openbb_terminal/core/log/conftest.py @@ -16,6 +16,7 @@ def settings(tmp_path): name="MOCK_NAME", identifier="MOCK_IDENTIFIER", session_id="MOCK_SESSION_ID", + user_id="MOCK_USER_ID", ), aws_settings=AWSSettings( aws_access_key_id="MOCK_AWS_ACCESS_KEY_ID", diff --git a/tests/openbb_terminal/core/log/generation/json/test_formatter_with_exceptions/test_extract_log_extra.json b/tests/openbb_terminal/core/log/generation/json/test_formatter_with_exceptions/test_extract_log_extra.json index 75c63f4834cc..f8492ecf21e9 100644 --- a/tests/openbb_terminal/core/log/generation/json/test_formatter_with_exceptions/test_extract_log_extra.json +++ b/tests/openbb_terminal/core/log/generation/json/test_formatter_with_exceptions/test_extract_log_extra.json @@ -1 +1 @@ -{"userId": "MOCK_USER_ID", "sessionId": "MOCK_SESSION_ID"} \ No newline at end of file +{"sessionId": "MOCK_SESSION_ID"} \ No newline at end of file diff --git a/tests/openbb_terminal/core/log/generation/test_formatter_with_exceptions.py b/tests/openbb_terminal/core/log/generation/test_formatter_with_exceptions.py index dbfddc5539a8..0374f3b531d1 100644 --- a/tests/openbb_terminal/core/log/generation/test_formatter_with_exceptions.py +++ b/tests/openbb_terminal/core/log/generation/test_formatter_with_exceptions.py @@ -14,6 +14,7 @@ name="MOCK_COMMIT_HASH", identifier="MOCK_COMMIT_HASH", session_id="MOCK_SESSION_ID", + user_id="MOCK_USER_ID", ) formatter = FormatterWithExceptions(app_settings) diff --git a/tests/openbb_terminal/core/log/generation/test_settings.py b/tests/openbb_terminal/core/log/generation/test_settings.py index fb0916dde3e6..a02c06badf7b 100644 --- a/tests/openbb_terminal/core/log/generation/test_settings.py +++ b/tests/openbb_terminal/core/log/generation/test_settings.py @@ -24,12 +24,14 @@ def test_app_settings(): commit_hash = "MOCK_COMMIT_HASH" session_id = "MOCK_SESSION_ID" identifier = "MOCK_IDENTIFIER" + user_id = "MOCK_USER_ID" app_settings = AppSettings( name=name, commit_hash=commit_hash, session_id=session_id, identifier=identifier, + user_id=user_id, ) assert app_settings.name == name @@ -78,11 +80,13 @@ def test_settings(tmp_path): commit_hash = "MOCK_COMMIT_HASH" session_id = "MOCK_SESSION_ID" identifier = "MOCK_IDENTIFIER" + user_id = "MOCK_USER_ID" app_settings = AppSettings( name=name, commit_hash=commit_hash, session_id=session_id, identifier=identifier, + user_id=user_id, ) aws_access_key_id = "MOCK_AWS_ACCESS_KEY_ID" diff --git a/tests/openbb_terminal/test_loggers.py b/tests/openbb_terminal/test_loggers.py index f2739db88709..607dae3acf50 100644 --- a/tests/openbb_terminal/test_loggers.py +++ b/tests/openbb_terminal/test_loggers.py @@ -16,6 +16,7 @@ name="MOCK_COMMIT_HASH", identifier="MOCK_COMMIT_HASH", session_id="MOCK_SESSION_ID", + user_id="MOCK_USER_ID", ), aws_settings=AWSSettings( aws_access_key_id="MOCK_AWS_ACCESS_KEY_ID", diff --git a/tests/openbb_terminal/test_sources.py b/tests/openbb_terminal/test_sources.py new file mode 100644 index 000000000000..ee8142aebb79 --- /dev/null +++ b/tests/openbb_terminal/test_sources.py @@ -0,0 +1,10 @@ +import json + +from openbb_terminal.core.config.paths import USER_DATA_SOURCES_DEFAULT_FILE + + +def test_sources_load(): + with open(str(USER_DATA_SOURCES_DEFAULT_FILE)) as json_file: + json_doc = json.load(json_file) + assert isinstance(json_doc, dict) + assert "stocks" in json_doc diff --git a/website/content/terminal/reference/economy/eval.md b/website/content/terminal/reference/economy/eval.md index d9dce0b15baa..da96466aa7ab 100644 --- a/website/content/terminal/reference/economy/eval.md +++ b/website/content/terminal/reference/economy/eval.md @@ -19,6 +19,6 @@ eval [-q QUERY [QUERY ...]] | Name | Description | Default | Optional | Choices | | ---- | ----------- | ------- | -------- | ------- | -| query | Query to evaluate on loaded datasets | None | True | None | +| query | Query to evaluate on loaded datasets | None | False | None | ---