Merge branch 'develop' into feature/whisper

This commit is contained in:
martinb-bb
2023-02-23 20:45:31 -05:00
committed by GitHub
2060 changed files with 879641 additions and 1023280 deletions

1
.dockerignore vendored
View File

@@ -8,5 +8,4 @@ Dockerfile*
.idea
__pycache__
.python-version
jupyterlab/*/node_modules
logs/

View File

@@ -19,10 +19,11 @@
# Checklist:
- [ ] Update [our Hugo documentation](https://openbb-finance.github.io/OpenBBTerminal/) following [these guidelines](https://github.com/OpenBB-finance/OpenBBTerminal/tree/main/website).
- [ ] I have adhered to the GitFlow naming convention and my branch name is in the format of `feature/feature-name` or `hotfix/hotfix-name`.
- [ ] Update [our documentation](https://openbb-finance.github.io/OpenBBTerminal/) following [these guidelines](https://github.com/OpenBB-finance/OpenBBTerminal/tree/main/website). Update any user guides that are affected by the changes.
- [ ] Update our tests following [these guidelines](https://github.com/OpenBB-finance/OpenBBTerminal/tree/main/tests).
- [ ] Make sure you are following our [CONTRIBUTING guidelines](https://github.com/OpenBB-finance/OpenBBTerminal/blob/main/CONTRIBUTING.md).
- [ ] If a feature was added make sure to add it to the corresponding [scripts file](https://github.com/OpenBB-finance/OpenBBTerminal/tree/main/scripts).
- [ ] If a feature was added make sure to add it to the corresponding [integration test script](https://github.com/OpenBB-finance/OpenBBTerminal/tree/develop/openbb_terminal/miscellaneous/integration_tests_scripts).
# Others

View File

@@ -1,10 +1,28 @@
name-template: 'OpenBB Terminal v$NEXT_MINOR_VERSION'
tag-template: 'v$NEXT_MINOR_VERSION'
exclude-contributors:
- 'jmaslek'
- 'DidierRLopes'
- 'JerBouma'
- 'deeleeramone'
- 'hjoaquim'
- 'jose-donato'
- 'luqman-bello'
- 'martinb-bb'
- 'montezdesousa'
- 'tehcoderer'
- 'Chavithra'
- 'colin99d'
- 'northern-64bit'
- 'piiq'
- 'andrewkenreich'
template: |
## Thank you and welcome to our new contributors 🔥
$CONTRIBUTORS
## What's new 🎉
## What's changed 🚀
$CHANGES

244
.github/workflows/README.md vendored Normal file
View File

@@ -0,0 +1,244 @@
# OpenBB Workflows
This directory contains the workflows for the OpenBB 🦋 Project. The workflows are:
| Workflows | Summary
| :-------------------- |:---
| branch-name-check.yml | Checks if the branch name is valid and follows the naming convention.
| build-release.yml | Builds the project and runs the tests.
| docker.yml | Builds the docker image and pushes it to the docker hub.
| draft.yml | Creates a draft release when a new tag is pushed.
| gh-pages.yml | Builds the documentation and deploy to github pages.
| integration-test.yml | Runs the integration tests.
| intel_macos_build.yml | Builds the project on Intel Macs.
| issue.yml | Creates an issue when a new bug is reported.
| labels.yml | Adds labels to the issues and pull requests.
| linting.yml | Runs the linters.
| m1_macos_build.yml | Builds the project on M1 Macs.
| mac.yml | Builds the project on Mac OS X Full Clean Build with ML.
| nightly-build.yml | Builds the project and runs the integration tests every night on the `develop` branch.
| pypi.yml | Publishes the package to PyPI.
| unit-test.yml | Runs the unit tests.
| windows.yml | Builds the project on Windows 10 Full Clean Build with ML.
| windows10_build.yml | Builds the project on Windows 10.
## Branch Name Check Workflow
Objective: To check if pull request branch names follow the GitFlow naming convention before merging.
Triggered by: A pull request event where the target branch is either develop or main.
Branches checked: The source branch of a pull request and the target branch of a pull request.
Steps:
1. Extract branch names: Using the jq tool, the source and target branch names are extracted from the pull request event. The branch names are then stored in environment variables and printed as output.
2. Show Output result for source-branch and target-branch: The source and target branch names are printed to the console.
3. Check branch name for develop PRs: If the target branch is develop, then the source branch is checked against a regular expression to ensure that it follows the GitFlow naming convention. If the branch name is invalid, a message is printed to the console and the workflow exits with a status code of 1.
4. Check branch name for main PRs: If the target branch is main, then the source branch is checked against a regular expression to ensure that it is either a hotfix or a release branch. If the branch name is invalid, a message is printed to the console and the workflow exits with a status code of 1.
Note: The GitFlow naming convention for branches is as follows:
- Feature branches: feature/<feature-name>
- Hotfix branches: hotfix/<hotfix-name>
- Release branches: release/<major.minor.patch>(rc<number>)
## Build Release Workflow
This GitHub Actions workflow is responsible for building and releasing software for multiple platforms (Windows, M1 MacOS, Intel MacOS, and Docker).
The workflow has four jobs:
- `trigger-windows-build`
- `trigger-macos-build`
- `trigger-intel-build`
- `trigger-docker-build`
Each job uses the `aurelien-baudet/workflow-dispatch` action to trigger another workflow, respectively `windows10_build.yml`, `m1_macos_build.yml`, `intel_macos_build.yml`, and `docker.yml`. The `GITHUB_TOKEN` is passed as a secret so that the triggered workflows have access to the necessary permissions. The `wait-for-completion-timeout` is set to 2 hours, which is the maximum amount of time the job will wait for the triggered workflow to complete.
## Docker Workflow
This GitHub Actions workflow is responsible for building and pushing the docker image to the itHub Container Registry. This workflow is triggered when a new change is pushed to the main branch of the repository, and the Docker image is published to the GitHub Container Registry.
Steps
-----
1. Checkout Code: This step checks out the code from the GitHub repository.
2. Login to GitHub Container Registry: This step logs into the GitHub Container Registry using the GitHub Actions token.
3. Setup Commit Hash: This step sets the commit hash of the code that is being built.
4. Build Env File: This step builds the environment file for the Docker image.
5. Building the Docker Image: This step builds the Docker image using the scripts in the `build/docker` directory.
6. Publishing the Docker Image: This step publishes the Docker image to the GitHub Container Registry. The Docker image is only pushed to the registry if the branch being built is `main`.
## Draft Workflow
This GitHub Actions workflow is designed to automatically generate and update draft releases in a GitHub repository. The workflow is triggered when it is manually dispatched, allowing you to control when the draft releases are updated.
## GH Pages Workflow
This GitHub Actions workflow is responsible for building the documentation and deploying it to GitHub Pages. This workflow is triggered when a new change is pushed to the `main` or `release` branch of the repository, and the documentation is published to GitHub Pages.
## Integration Test Workflow
This GitHub Action is used to run integration tests on your code repository. It is triggered on pushes to the `release/*` or `main` branches, and it runs on the latest version of Ubuntu.
The workflow consists of the following steps:
1. Check out the code from the repository
2. Set up Python 3.9
3. Install Poetry, a package and dependency manager for Python
4. Load a cached virtual environment created by Poetry, to speed up the process if possible
5. Install dependencies specified in the `poetry.lock` file
6. Run the integration tests using the `terminal.py` script
7. Upload a summary of the test results to Slack
The results of the tests are captured in a file called `result.txt`. The summary of the tests, including information about failed tests, is then uploaded to Slack using the `adrey/slack-file-upload-action` GitHub Action.
## Intel MacOS Build Workflow
This GitHub Actions workflow is responsible for building and testing the project on Intel Macs. The workflow is triggered by the workflow_dispatch event, which means it can be manually triggered. The concurrency group for the job is defined based on the Github workflow and the Github ref, and it is set to cancel in-progress runs.
The job named `Build` has several steps:
1. Checkout the repository's main branch.
2. Git log to see the history of the repository.
3. Install `create-dmg` using Homebrew.
4. Clean up previous environment variables and set PATH to default.
5. Set up conda environment caching.
6. Set up Miniconda using the `build/conda/conda-3-9-env-full.yaml` file.
7. Use Poetry to install the necessary dependencies.
8. Install Pyinstaller.
9. Install Portfolio Optimization and Forecasting Toolkits.
10. Install a specific version of Papermill using pip.
11. Build the bundle using Pyinstaller and do some additional tasks such as setting up icons.
12. Create a keychain and decode a certificate using a password stored in Github secrets.
13. Code sign specific binaries using the certificate and password from the previous step.
This workflow builds the OpenBB Terminal application on MacOS and signs it with a certificate to allow it to run on the MacOS system.
## Linting Workflow
This GitHub Actions workflow is responsible for running linting checks on the codebase. This workflow is triggered on pull request events such as `opened`, `synchronize`, and `edited`, and push events on branches with names that start with `feature/`, `hotfix/`, or `release/`. The workflow also sets a number of environment variables and uses Github Actions caching to improve performance.
It consists of two jobs: `code-linting` and `markdown-link-check`.
The first job, `code-linting`, runs on an Ubuntu machine and performs several linting tasks on the code in the repository, including:
- Checking out the code from the repository
- Setting up Python 3.9
- Installing a number of Python packages necessary for the linting tasks
- Running `bandit` to check for security vulnerabilities
- Running `black` to check the code formatting
- Running `codespell` to check the spelling of comments, strings, and variable names
- Running `ruff` to check the use of Python
- Running `mypy` to check the type annotations
- Running `pyupgrade` to upgrade Python 2 code to Python 3
- Running `pylint` to perform static analysis of the code
The second job, `markdown-link-check`, runs on an Ubuntu machine and performs linting of the markdown files in the repository. It uses a Docker container `avtodev/markdown-lint` to perform the linting.
## MacOS Build Workflow
This GitHub Actions workflow is used to build a version of the OpenBB Terminal for M1 MacOS. The build process includes installing necessary dependencies, building the terminal application using PyInstaller, creating a DMG file for distribution, and running integration tests on the built application.
Jobs
----
The workflow consists of a single job named `Build` which runs on self-hosted MacOS systems with ARM64 architecture. The job performs the following steps:
1. Checkout: The main branch of the repository is checked out, allowing for the commit hashes to line up.
2. Git Log: The log of the Git repository is displayed.
3. Install create-dmg: The `create-dmg` tool is installed using Homebrew.
4. Clean Previous Path: The previous PATH environment variable is cleared and restored to its default values.
5. Setup Conda Caching: The miniconda environment is set up using a caching mechanism for faster workflow execution after the first run.
6. Setup Miniconda: Miniconda is set up using the `conda-3-9-env-full.yaml` environment file, with channels `conda-forge` and `defaults`, and with the `build_env` environment activated.
7. Run Poetry: Poetry is used to install the dependencies for the project.
8. Install PyInstaller: PyInstaller is installed using Poetry.
9. Poetry Install Portfolio Optimization and Forecasting Toolkits: The portfolio optimization and forecasting toolkits are installed using Poetry.
10. Install Specific Papermill: A specific version of Papermill is installed using pip.
11. Build Bundle: The terminal application is built using PyInstaller, with icons and assets copied to the DMG directory.
12. Create DMG: The DMG file is created using the `create-dmg` tool.
13. Clean up Build Artifacts: The build artifacts such as the terminal directory and DMG directory are removed.
14. Save Build Artifact DMG: The DMG file is saved as a build artifact.
15. Convert & Mount DMG: The DMG file is converted and mounted.
16. Directory Change: The current directory is changed to the mounted DMG file.
17. Unmount DMG: The mounted DMG file is unmounted.
18. Run Integration Tests: The built terminal application is run with integration tests, and the results are displayed.
Finally, the integration tests are run and the results are logged. The workflow is configured to run only when triggered by a workflow dispatch event and runs in a concurrent group, with the ability to cancel in-progress jobs.
## Nightly Build Workflow
This code is a GitHub Actions workflow configuration file that is used to trigger other workflows when certain events occur. The main purpose of this workflow is to trigger builds on different platforms when a release is made or a pull request is made to the main branch.
This workflow is triggered at UTC+0 daily by the GitHub Action schedule event.
The job includes the following steps:
1. Trigger Windows Build: This step uses the `aurelien-baudet/workflow-dispatch` action to trigger the windows10_build.yml workflow.
2. Trigger macOS Build: This step uses the `aurelien-baudet/workflow-dispatch` action to trigger the m1_macos_build.yml workflow
3. Trigger Intel Build: This step uses the `aurelien-baudet/workflow-dispatch` action to trigger the intel_macos_build.yml workflow
4. Trigger Docker Build: This step uses the `aurelien-baudet/workflow-dispatch` action to trigger the docker.yml workflow
This workflow also uses a concurrency setting that groups the jobs by the workflow and ref, and cancels any in-progress jobs.
## pypi-publish Workflow
The Github Action code `Deploy to PyPI` is used to deploy a Python project to PyPI (Python Package Index) and TestPyPI, which is a separate package index for testing purposes. The code is triggered on two events:
1. Push event: The code is triggered whenever there is a push to the `release/*` and `main` branches.
2. Workflow dispatch event: The code can be manually triggered by the workflow dispatch event.
The code sets the concurrency to the `group` and the option `cancel-in-progress` is set to `true` to ensure that the running jobs in the same `group` are cancelled in case another job is triggered.
The code contains two jobs, `deploy-test-pypi` and `deploy-pypi`, both of which have the same steps with slight variations.
The `deploy-test-pypi` job is triggered only if the pushed branch starts with `refs/heads/release/`. This job sets up the Python environment, installs the `build` package using `pip`, builds binary wheel and source tarball using `build`, and finally, publishes the distributions to TestPyPI using the `pypa/gh-action-pypi-publish@release/v1` Github Action. The `password` to access TestPyPI is stored as a secret named `TEST_PYPI_API_TOKEN`.
Similarly, the `deploy-pypi` job is triggered only if the pushed branch starts with `refs/heads/main`. This job follows the same steps as `deploy-test-pypi`, but the distributions are published to PyPI instead of TestPyPI. The `password` to access PyPI is stored as a secret named `PYPI_API_TOKEN`.
Note: The code uses the `pypa/build` package for building the binary wheel and source tarball, and the `pypa/gh-action-pypi-publish@release/v1` Github Action for publishing the distributions to PyPI and TestPyPI.
## Unit Tests Workflow
This workflow is used to run unit tests on the OpenBB Terminal. The workflow is triggered on the following events:
The events this workflow will respond to are:
1. Pull requests that are opened, synchronized, edited, or closed. The pull request must be made to the `develop` or `main` branches.
2. Pushes to the `release/*` branches.
Each job in the workflow specifies a set of steps that are executed in order.
The first job, `check-files-changed`, checks whether there are any changes to certain file types in the repository, such as Python files and lockfiles. If there are changes, then the `check-changes` output variable is set to `true`.
The next job, `base-test`, runs a series of tests if `check-changes` is `true` and the base branch of the pull request is `develop`. This job sets up a Python 3.9 environment, installs Poetry, and then runs tests using `pytest`. Finally, it starts the terminal and exits.
The next job, `tests-python`, runs tests for different versions of Python (3.8, 3.9, and 3.10) on the `ubuntu-latest` operating system. It sets up the specified Python version, installs Poetry and dependencies, and then runs tests using `pytest`.
The next job, `full-test`, uses the GitHub Actions `checkout` action to checkout the code, followed by the `setup-python` action to set up the specified version of Python. Then, the `install-poetry` action is used to install the package manager Poetry, and a cache is set up using the `actions/cache` action to avoid re-installing dependencies. After that, the dependencies are installed using Poetry, and a list of installed packages is displayed. Then, the tests are run using `pytest`, and finally, the `terminal.py` script is started and exited.
The last job, `tests-conda`, sets up a Miniconda environment using the `setup-miniconda` action. The environment is specified using a YAML file and is activated. Then, the tests are run.
## Windows 10 Build Workflow
This is a GitHub Actions workflow file that automates the build and testing process for the OpenBB Terminal on Windows 10. The workflow consists of two jobs:
1. Windows-Build
2. Build-Exe
- The Windows-Build job does the following:
- Sets up the Windows Git configuration for long file paths.
- Checks out the repository code.
- Sets up Python 3.9 and creates an OpenBB environment using poetry.
- Installs necessary packages and builds the terminal using PyInstaller.
- Uploads the built artifact to GitHub as an artifact.
- The Build-Exe job does the following:
- Sets up the Windows Git configuration for long file paths.
- Checks out the repository code.
- Downloads the built artifact from the previous Windows-Build job.
- Copies the files into an app folder for building the EXE file.
- Builds the EXE file using NSIS.
- Uploads the built EXE as an artifact to GitHub.
- Runs integration tests on the terminal and saves the results to a text file.
- Uploads the test results summary to Slack.
- Cleans up previous build files and artifacts.
This workflow is triggered by the `workflow_dispatch` event and runs in concurrency with other workflows in the same group, with the ability to cancel in-progress builds. The concurrency group is defined as `${{ github.workflow }}-${{ github.ref }}`.

View File

@@ -18,7 +18,6 @@ jobs:
source-branch: ${{ steps.branch-name-check.outputs.source-branch }}
target-branch: ${{ steps.branch-name-check.outputs.target-branch }}
steps:
# Extract the source and target branches for the PR
- name: Extract branch names
id: branch-name-check
run: |

62
.github/workflows/build-release.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: Build & Release
env:
OPENBB_ENABLE_QUICK_EXIT: true
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on:
push:
branches:
- release/*
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
actions: write
jobs:
trigger-windows-build:
runs-on: ubuntu-latest
steps:
- name: Trigger Windows Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: windows10_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-macos-build:
runs-on: ubuntu-latest
steps:
- name: Trigger M1 MacOs Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: m1_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-intel-build:
runs-on: ubuntu-latest
steps:
- name: Trigger Intel MacOs Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: intel_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-docker-build:
runs-on: ubuntu-latest
steps:
- name: Trigger docker Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: docker.yml
token: ${{ secrets.GITHUB_TOKEN }}

50
.github/workflows/code-coverage.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: Code Coverage Tests
on: workflow_dispatch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
code-coverage:
runs-on: ubuntu-latest
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
steps:
- name: Checkout code
if: github.event_name == 'push'
uses: actions/checkout@v3
- name: Checkout specific ref
if: github.event_name == 'pull_request'
run: git fetch origin ${{ github.event.pull_request.head.ref }} && git checkout FETCH_HEAD
- name: Setup Python 3.9
uses: actions/setup-python@v4
with:
python-version: "3.9"
architecture: x64
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.3.2
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-v1-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction -E optimization
- name: Run code coverage tests
run: |
source $VENV
pytest --cov --cov-fail-under=50

View File

@@ -40,3 +40,4 @@ jobs:
- name: Publishing the Docker image
run: |
docker push "${OPENBBTERMINAL_DOCKER_POETRY_IMAGE}"
if: startsWith(github.ref, 'refs/heads/main')

View File

@@ -1,16 +1,14 @@
name: Deploy to GitHub Pages
on:
pull_request:
push:
branches:
- main
types: [closed]
- release/*
jobs:
generate:
name: Generate and Deploy documentation
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Git checkout
@@ -25,7 +23,7 @@ jobs:
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.1.13
version: 1.3.2
virtualenvs-create: true
virtualenvs-in-project: true
@@ -41,7 +39,7 @@ jobs:
run: poetry install --no-interaction --no-root -E doc
- name: Install packages
run: poetry install --no-interaction -E prediction -E doc -E optimization
run: poetry install --no-interaction -E forecast -E doc -E optimization
- run: |
source $VENV
@@ -67,6 +65,7 @@ jobs:
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
if: startsWith(github.ref, 'refs/heads/main')
with:
github_token: ${{ secrets.DEPLOY_TOKEN }}
publish_dir: ./website/build

82
.github/workflows/integration-test.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: Integration Tests
on:
push:
branches:
- release/*
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
integration-tests:
runs-on: ubuntu-latest
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
steps:
- name: Slack Notification - Starting
uses: act10ns/slack@v1
with:
status: starting
channel: '#workflows'
message: Starting Integration Test...
if: always()
- name: Checkout code
if: github.event_name == 'push'
uses: actions/checkout@v3
- name: Checkout specific ref
if: github.event_name == 'pull_request'
run: git fetch origin ${{ github.event.pull_request.head.ref }} && git checkout FETCH_HEAD
- name: Setup Python 3.9
uses: actions/setup-python@v4
with:
python-version: "3.9"
architecture: x64
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.3.2
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-v1-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction -E optimization
- name: Run integration tests
id: integration-tests
run: |
source $VENV
python terminal.py -t > result.txt
cat result.txt
grep "================================ integration test summary ================================" result.txt -A100 | tail -c 2000 > failed_tests.txt
- name: Upload summary to Slack
uses: adrey/slack-file-upload-action@master
with:
token: ${{ secrets.SLACK_API_TOKEN }}
initial_comment: "Integration test summary"
title: "Integration test summary"
path: failed_tests.txt
channel: ${{ secrets.SLACK_CHANNEL_ID }}
- name: Slack Notification - Success/Failure
uses: act10ns/slack@v1
with:
status: ${{ job.status }}
steps: ${{ toJson(steps) }}
channel: '#workflows'
if: always()

View File

@@ -1,12 +1,20 @@
name: Intel MacOS Build
env:
OPENBB_ENABLE_QUICK_EXIT: true
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on: workflow_dispatch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Build:
name: Intel MacOS Build
@@ -14,7 +22,7 @@ jobs:
steps:
# Checkout repository main branch. this allows for the commit hashes to line up
- name: Checkout
uses: actions/checkout@v2.4.2
uses: actions/checkout@v3
- name: Git Log
run: git log
# Install create-dmg
@@ -28,7 +36,7 @@ jobs:
echo $PATH
# Set up caching for conda env so that the workflow runs quickly after the first time
- name: Setup Conda Caching
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/conda_pkgs_dir
key: conda-macos-3-9-${{ hashFiles('build/conda/conda-3-9-env-full.yaml') }}
@@ -45,19 +53,19 @@ jobs:
activate-environment: build_env
use-only-tar-bz2: true # Needed for caching some reason
- name: Run Poetry
run: poetry install
- name: Install Pyinstaller
run: poetry install -E installer
- name: Install Portfolio Optimization and Forecasting Toolkits
run: poetry install -E all
run: |
pip list
python -m pip install -r requirements-full.txt
- name: Install Specific Papermill
run: |
pip list
pip uninstall papermill -y
pip install git+https://github.com/nteract/papermill.git@main
# This is basically the same as build4mac.sh
- name: Build Bundle
run: |
pyinstaller build/pyinstaller/terminal.spec --clean
pip list
python -m PyInstaller build/pyinstaller/terminal.spec --clean
osascript build/pyinstaller/setup_icons.applescript
mkdir DMG
cp -r build/pyinstaller/macOS_package_assets/* DMG/
@@ -104,6 +112,8 @@ jobs:
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/cmdstan-2.26.1/stan/lib/stan_math/lib/tbb/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/torch/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/sklearn/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/scipy/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/xgboost/.dylibs/*.dylib
echo "Code Signing Other Files"
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/prophet_model.bin
@@ -139,7 +149,7 @@ jobs:
rm -rf build/terminal
rm -rf dist
rm -rf DMG
- name: Notorize DMG
- name: Notarize DMG
env:
NOTARIZE_APPLE_ID: ${{ secrets.NOTARIZE_APPLE_ID }}
NOTARIZE_APPLE_PWD: ${{ secrets.NOTARIZE_APPLE_PWD }}
@@ -167,8 +177,22 @@ jobs:
cp -R OpenBB\ Terminal ~/Desktop
- name: Unmount DMG
run: hdiutil detach /dev/disk2
- name: Run Integration Tests
run: /Users/openbb/Desktop/OpenBB\ Terminal/.OpenBB/OpenBBTerminal /Users/openbb/actions-runner/_work/OpenBBTerminal/OpenBBTerminal/openbb_terminal/miscellaneous/scripts -t
run: |
/Users/openbb/Desktop/OpenBB\ Terminal/.OpenBB/OpenBBTerminal -t -s forecast cryptocurrency reports alternative economy futures econometrics dashboards portfolio stocks/test_stocks_options_screen.openbb stocks/test_stocks_options.openbb forex etf stocks/test_stocks_fa.openbb > result.txt
cat result.txt
grep "================================ integration test summary ================================" result.txt -A100 | tail --bytes=2000 > failed_tests.txt
- name: Upload summary to Slack
uses: adrey/slack-file-upload-action@master
with:
token: ${{ secrets.SLACK_API_TOKEN }}
initial_comment: "Intel MacOs Build Integration test summary"
title: "Intel MacOs Build Integration test summary"
path: failed_tests.txt
channel: ${{ secrets.SLACK_CHANNEL_ID }}
- name: Remove OpenBB Folder
run: rm -rf /Users/openbb/Desktop/OpenBB\ Terminal
- name: Remove OpenBB Exports Folder

View File

@@ -10,7 +10,7 @@ jobs:
with:
mode: minimum
count: 1
labels: "guides, bug, build, do not merge, docker, docs, duplicate, enhancement, feat XS, feat S, feat M, feat L, feat XL, help wanted, refactor, tests, discord, dependencies, notebookreports, dashboards, analytics, portfolio, installer, SDK, HACKTOBERFEST, "
labels: "guides, bug, build, do not merge, docker, docs, duplicate, enhancement, feat XS, feat S, feat M, feat L, feat XL, help wanted, refactor, tests, discord, dependencies, notebookreports, dashboards, analytics, portfolio, installer, SDK, release "
- uses: mheap/github-action-required-labels@v1
with:
mode: exactly

View File

@@ -5,18 +5,23 @@ env:
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
on:
pull_request:
types: [opened, synchronize, edited]
push:
branches:
- 'feature/*'
- 'hotfix/*'
- 'release/[0-9]+\.[0-9]+\.[0-9]+(rc[0-9]+)?'
- 'release/*'
merge_group:
types: [checks_requested]
# Cancel previous runs that are not yet completed.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: ${{ github.event_name }}-${{ github.repository }}-${{ github.ref }}
cancel-in-progress: true
jobs:
@@ -40,17 +45,14 @@ jobs:
restore-keys: ${{ runner.os }}-linting-${{ hashFiles('**/poetry.lock') }}
- run: |
pip install bandit black codespell mypy==0.982 pyupgrade safety pylint==2.15.2 packaging==22 ruff==0.0.212
pip install bandit black codespell mypy==1.0.0 pylint==2.15.2 ruff==0.0.247
pip install types-pytz types-requests types-termcolor types-tabulate types-PyYAML types-python-dateutil types-setuptools types-six
- run: bandit -x ./tests -r . || true
- run: black --diff --check .
- run: codespell --ignore-words-list=commun,statics,ro,zar,zlot,jewl,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake,creat,vie,hel,ket,toke,certi,buidl,ot,te --quiet-level=2 --skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,./build/pyinstaller,./website/config.toml
- run: ruff .
- run: mypy --ignore-missing-imports openbb_terminal
- run: shopt -s globstar && pyupgrade --py38-plus **/*.py
- run: safety check
- run: |
pylint terminal.py openbb_terminal tests
- run: pylint terminal.py openbb_terminal tests
markdown-link-check:
name: Markdown Linting

View File

@@ -1,12 +1,20 @@
name: M1 MacOS Build
env:
OPENBB_ENABLE_QUICK_EXIT: true
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on: workflow_dispatch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Build:
name: M1 MacOS Build
@@ -14,7 +22,7 @@ jobs:
steps:
# Checkout repository main branch. this allows for the commit hashes to line up
- name: Checkout
uses: actions/checkout@v2.4.2
uses: actions/checkout@v3
- name: Git Log
run: git log
# Install create-dmg
@@ -28,7 +36,7 @@ jobs:
echo $PATH
# Set up caching for conda env so that the workflow runs quickly after the first time
- name: Setup Conda Caching
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/conda_pkgs_dir
key: conda-macos-3-9-${{ hashFiles('build/conda/conda-3-9-env-full.yaml') }}
@@ -45,26 +53,116 @@ jobs:
activate-environment: build_env
auto-activate-base: false
use-only-tar-bz2: true # Needed for caching some reason
- name: Run Poetry
run: poetry install
- name: Install Pyinstaller
run: poetry install -E installer
- name: Poetry Install Portfolio Optimization and Forecasting Toolkits
run: poetry install -E all
run: |
pip list
python -m pip install -r requirements-full.txt
- name: Install Specific Papermill
run: |
pip uninstall papermill -y
pip install git+https://github.com/nteract/papermill.git@main
# This is basically the same as build4mac.sh
- name: Build Bundle
run: |
pyinstaller build/pyinstaller/terminal.spec --clean
python -m PyInstaller build/pyinstaller/terminal.spec --clean
osascript build/pyinstaller/setup_icons.applescript
mkdir DMG
cp -r build/pyinstaller/macOS_package_assets/* DMG/
mv dist/OpenBBTerminal DMG/OpenBB\ Terminal/.OpenBB
- name: Creating Keychain
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
MACOS_KEYCHAIN_PWD: ${{ secrets.MACOS_KEYCHAIN_PWD }}
MACOS_CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
run: | # when pushing to main, make to generate new cert, and utilize secrets to store new password, and identity
echo "Ensuring Keychain with same name does not exist"
rm -rf /Users/openbb/Library/Keychains/build.keychain-db
echo "Decoding certificate"
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
echo "Creating Keychain"
security create-keychain -p $MACOS_KEYCHAIN_PWD build.keychain
echo "Setting Default Keychain"
security default-keychain -s build.keychain
echo "Unlocking Keychain"
security unlock-keychain -p $MACOS_KEYCHAIN_PWD build.keychain
echo "Importing Keychain"
security import certificate.p12 -k build.keychain -P $MACOS_CERTIFICATE_PWD -T /usr/bin/codesign
echo "Setting Partition List"
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $MACOS_KEYCHAIN_PWD build.keychain
- name: Codesign Specific Binaries
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
MACOS_KEYCHAIN_PWD: ${{ secrets.MACOS_KEYCHAIN_PWD }}
MACOS_CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
run: |
echo "Code Signing SO Files"
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*.so
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*/*.so
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*/*/*.so
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*/*/*/*.so
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*/*/*/*/*.so
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*/*/*/*/*/*.so
echo "Code Signing DYLIB Files"
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*/*/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/*/*/*/*/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/cmdstan-2.26.1/stan/lib/stan_math/lib/tbb/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/torch/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/sklearn/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/scipy/.dylibs/*.dylib
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/xgboost/.dylibs/*.dylib
echo "Code Signing Other Files"
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/prophet_model.bin
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/cmdstan-2.26.1/bin/diagnose
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/cmdstan-2.26.1/bin/print
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/cmdstan-2.26.1/bin/stanc
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/prophet/stan_model/cmdstan-2.26.1/bin/stansummary
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/pyarrow/plasma-store-server
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/torch/bin/protoc
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/torch/bin/protoc-3.13.0.0
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/torch/bin/torch_shm_manager
echo "Code Sign OpenBB Executable File"
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY DMG/OpenBB\ Terminal/.OpenBB/OpenBBTerminal
- name: Create DMG
run: create-dmg --volname "OpenBB Terminal" --volicon "images/dmg_volume.icns" --background "images/openbb_dmg_background.png" --icon "OpenBB Terminal" 190 250 --window-pos 190 120 --window-size 800 400 --icon-size 100 --text-size 14 --app-drop-link 600 250 --eula LICENSE --format UDZO --no-internet-enable "OpenBB Terminal".dmg DMG
- name: Code Sign DMG Installer
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERTIFICATE_PWD }}
MACOS_KEYCHAIN_PWD: ${{ secrets.MACOS_KEYCHAIN_PWD }}
MACOS_CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }}
run: |
echo "Code Signing DMG Installer"
/usr/bin/codesign --deep --force --verify --verbose --options runtime --entitlements "build/pyinstaller/entitlements.plist" -s $MACOS_CODESIGN_IDENTITY OpenBB\ Terminal.dmg
echo "Verify Signing"
codesign --verify --deep --strict --verbose=2 OpenBB\ Terminal.dmg
- name: Deleting Previous Keychain
run: |
echo "Deleting Previous Keychain to Clean Instance"
rm -rf /Users/openbb/Library/Keychains/build.keychain-db
- name: Clean up Build Artifacts
run: |
rm -rf build/terminal
rm -rf dist
rm -rf DMG
- name: Notorize DMG
env:
NOTARIZE_APPLE_ID: ${{ secrets.NOTARIZE_APPLE_ID }}
NOTARIZE_APPLE_PWD: ${{ secrets.NOTARIZE_APPLE_PWD }}
NOTARIZE_APPLE_TEAM_ID: ${{ secrets.NOTARIZE_APPLE_TEAM_ID }}
run: |
xcrun notarytool submit OpenBB\ Terminal.dmg --apple-id "$NOTARIZE_APPLE_ID" --password "$NOTARIZE_APPLE_PWD" --team-id "$NOTARIZE_APPLE_TEAM_ID" --wait
- name: Staple
run: |
xcrun stapler staple "OpenBB Terminal.dmg"
- name: Clean up Build Artifacts
run: |
rm -rf build/terminal
@@ -88,8 +186,22 @@ jobs:
cp -R OpenBB\ Terminal ~/Desktop
- name: Unmount DMG
run: hdiutil detach /dev/disk4
- name: Run Integration Tests
run: /Users/openbb/Desktop/OpenBB\ Terminal/.OpenBB/OpenBBTerminal /Users/openbb/actions-runner/_work/OpenBBTerminal/OpenBBTerminal/openbb_terminal/miscellaneous/scripts -t
run: |
/Users/openbb/Desktop/OpenBB\ Terminal/.OpenBB/OpenBBTerminal -t -s forecast cryptocurrency reports alternative economy futures econometrics dashboards portfolio stocks/test_stocks_options_screen.openbb stocks/test_stocks_options.openbb forex etf stocks/test_stocks_fa.openbb > result.txt
cat result.txt
grep "================================ integration test summary ================================" result.txt -A100 | tail --bytes=2000 > failed_tests.txt
- name: Upload summary to Slack
uses: adrey/slack-file-upload-action@master
with:
token: ${{ secrets.SLACK_API_TOKEN }}
initial_comment: "M1 MacOs Build Integration test summary"
title: "M1 MacOs Build Integration test summary"
path: failed_tests.txt
channel: ${{ secrets.SLACK_CHANNEL_ID }}
- name: Remove OpenBB Folder
run: rm -rf /Users/openbb/Desktop/OpenBB\ Terminal
- name: Remove OpenBB Exports Folder

View File

@@ -5,6 +5,7 @@ env:
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
PIP_DEFAULT_TIMEOUT: 100
OPENBB_FILE_OVERWRITE: true
PYTHONNOUSERSITE: 1
on:
push:

View File

@@ -1,4 +1,4 @@
name: Nightly Build on the develop branch
name: Nightly Build
env:
OPENBB_ENABLE_QUICK_EXIT: true
@@ -6,91 +6,61 @@ env:
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
PIP_DEFAULT_TIMEOUT: 100
OPENBB_FILE_OVERWRITE: true
PYTHONNOUSERSITE: 1
on:
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
actions: write
jobs:
Windows-Build:
name: Windows10 Build
runs-on: [self-hosted, Windows, x64]
# Configuring -------------
trigger-windows-build:
runs-on: ubuntu-latest
steps:
- name: Setup Windows Git Configuration # This is under the assumption that git is already installed on the system
run: |
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
git config --system core.longpaths true
- name: Checkout
uses: actions/checkout@v2.4.2
- name: Trigger Windows Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
ref: develop
workflow: windows10_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 3h
- name: Activate Base & Create OpenBB Environment
run: |
conda activate base
conda env create -n obb --file build/conda/conda-3-9-env-full.yaml
conda init
conda activate obb
conda env list
- name: Poetry Install
# Conda activate needs to be run every time because of the way that the workflow steps work
# on powershell where it creates a new shell every time for every step
run: |
conda activate obb
poetry install
- name: Poetry Install Portfolio Optimization and Forecasting Toolkits
run: |
conda activate obb
poetry install -E all
- name: Poetry Install Installer
run: |
conda activate obb
poetry install -E installer
- name: Install Specific Papermill
run: |
conda activate obb
pip uninstall papermill -y
pip install git+https://github.com/nteract/papermill.git@main
# Building ------------
- name: Build Terminal.spec file
run: |
conda activate obb
pyinstaller build/pyinstaller/terminal.spec --clean
- name: Move Files into App Folder
run: cp -r .\dist\OpenBBTerminal\ .\build\nsis\app\
# don't need this because log collection is turned off
# - name: Remove Log Data
# run: Remove-Item .\build\nsis\app\openbb_terminal\logs\ -Recurse
- name: Build Exe File
run: |
conda activate obb
C:\'.\Program Files (x86)\'\nsis\makensis.exe .\build\nsis\setup.nsi
- name: Save Build Artifact
uses: actions/upload-artifact@v3
trigger-macos-build:
runs-on: ubuntu-latest
steps:
- name: Trigger M1 MacOs Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
name: Windows EXE Artifact
path: '.\build\nsis\OpenBB Terminal Setup.exe'
- name: Run Integration Tests
run: |
dist\OpenBBTerminal\OpenBBTerminal.exe C:\Users\Administrator\actions-runner\_work\OpenBBTerminal\OpenBBTerminal\openbb_terminal\miscellaneous\scripts -t
# Cleaning ------------------------
# Make sure to add Remove-Item C:\Users\Administrator\Desktop\OPENBB-exports -Recurse whenever integration tests get fixed
- name: Remove Previous Build
run: |
Remove-Item '.\build\nsis\OpenBB Terminal Setup.exe' -Recurse
Remove-Item .\build\nsis\app\ -Recurse
Remove-Item .\dist\ -Recurse
Remove-Item .\build\terminal\ -Recurse
- name: Deactivate & Remove Conda Environment
run: |
conda deactivate obb
conda deactivate base
conda env remove -n obb
Remove-Item C:\Users\Administrator\miniconda3\envs\obb\ -Recurse
workflow: m1_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-intel-build:
runs-on: ubuntu-latest
steps:
- name: Trigger Intel MacOs Build
uses: aurelien-baudet/workflow-dispatch@v2
with:
workflow: intel_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-docker-build:
runs-on: ubuntu-latest
steps:
- name: Trigger docker Build
uses: aurelien-baudet/workflow-dispatch@v2
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 }}

48
.github/workflows/nightly-pypi.yml vendored Normal file
View File

@@ -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 }}

79
.github/workflows/pypi.yml vendored Normal file
View File

@@ -0,0 +1,79 @@
name: Deploy to PyPI
on:
push:
branches:
- release/*
- main
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
deploy-test-pypi:
name: Build and publish 📦 to TestPyPI
if: startsWith(github.ref, 'refs/heads/release/')
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: 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 Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository_url: https://test.pypi.org/legacy/
deploy-pypi:
name: Build and publish 📦 to PyPI
if: startsWith(github.ref, 'refs/heads/main')
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: 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.PYPI_API_TOKEN }}

View File

@@ -1,258 +0,0 @@
name: Tests
env:
OPENBB_ENABLE_QUICK_EXIT: true
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
PIP_DEFAULT_TIMEOUT: 100
on: [workflow_dispatch]
jobs:
linting:
name: General Linting
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
steps:
- name: Checkout Code
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # actions/checkout v3.0.2
- name: Setup Python 3.9
uses: actions/setup-python@v4
with:
python-version: "3.9"
architecture: x64
- uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-linting-${{ hashFiles('**/poetry.lock') }}
restore-keys: ${{ runner.os }}-linting-${{ hashFiles('**/poetry.lock') }}
- run: pip install bandit black codespell mypy==0.982 pyupgrade safety pylint==2.15.2 packaging==22 ruff==0.0.212
- run: pip install types-pytz types-requests types-termcolor types-tabulate types-PyYAML types-python-dateutil types-setuptools types-six
- run: bandit -x ./tests -r . || true
- run: black --diff --check .
- run: codespell --ignore-words-list=commun,statics,ro,zar,zlot,jewl,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake,creat,vie,hel,ket,toke,certi,buidl,ot,te --quiet-level=2 --skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,./build/pyinstaller,./website/config.toml
- run: ruff .
- run: mypy --ignore-missing-imports openbb_terminal
- run: shopt -s globstar && pyupgrade --py38-plus **/*.py
- run: safety check
- run: |
pylint terminal.py openbb_terminal tests
test:
name: Base Tests - Ubuntu-latest - Python 3.9
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup Python 3.9
uses: actions/setup-python@v4
with:
python-version: "3.9"
architecture: x64
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.1.13
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-v1-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction -E optimization
- name: Run tests
env:
MPLBACKEND: Agg
run: |
source $VENV
pytest tests/ --optimization
- name: Start Terminal and exit
run: |
source $VENV
python terminal.py
markdown-link-check:
name: Markdown Linting
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
steps:
- uses: actions/checkout@v3
name: Check out the code
- name: Lint Code Base
uses: docker://avtodev/markdown-lint:v1
with:
args: "./*.md ./changelogs/*.md ./openbb_terminal/**/*.md ./discordbot/**/*.md"
tests-python:
name: Vanilla Python Tests - (${{ matrix.python-version }}, ${{ matrix.os }})
needs: test
runs-on: ${{ matrix.os }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
strategy:
fail-fast: true
matrix:
python-version: ["3.8", "3.9", "3.10"]
os: [ubuntu-latest, macos-latest]
exclude:
- os: ubuntu-latest
python-version: "3.9"
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: x64
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.1.13
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v3
with:
path: .venv
key: venv-${{ runner.os }}-v1-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction -E optimization
- name: List installed packages
shell: bash -l {0}
run: |
source $VENV
pip list
- name: Run tests
env:
MPLBACKEND: Agg
run: |
source $VENV
pytest tests/ --optimization
- name: Start Terminal and exit
run: |
source $VENV
python terminal.py
tests-conda:
name: Anaconda Python Tests - (${{ matrix.python-version }}, ${{ matrix.os }})
needs: test
runs-on: ${{ matrix.os }}-latest
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
strategy:
fail-fast: false
matrix:
os: ["ubuntu", "windows"]
python-version: ["3.9"]
dependencies: [""]
include:
- os: ubuntu
python: 3.9
- os: windows
python: 3.9
env:
OS: ${{ matrix.os }}
PYTHON: ${{ matrix.python }}
PYTHONNOUSERSITE: 1
steps:
- name: Set git to use LF
if: runner.os == 'Windows'
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checkout
uses: actions/checkout@v3
with:
# Need to fetch more than the last commit so that setuptools-scm can
# create the correct version string. If the number of commits since
# the last release is greater than this, the version still be wrong.
# Increase if necessary.
fetch-depth: 100
# The GitHub token is preserved by default but this job doesn't need
# to be able to push to GitHub.
persist-credentials: false
- name: Setup caching for conda packages
uses: actions/cache@v3
with:
path: ~/conda_pkgs_dir
key: conda-${{ runner.os }}-v1-${{ matrix.python }}-${{ hashFiles('build/conda/conda-3-9-env-full.yaml') }}
- name: Setup Miniconda
uses: conda-incubator/setup-miniconda@v2
with:
python-version: ${{ matrix.python }}
miniconda-version: "latest"
auto-update-conda: true
channels: conda-forge,defaults
show-channel-urls: true
channel-priority: flexible
environment-file: build/conda/conda-3-9-env.yaml
activate-environment: testing
# Needed for caching
use-only-tar-bz2: true
- name: Update Temp permissions on windows
if: runner.os == 'Windows'
shell: cmd /C CALL {0}
run: >-
c:\windows\system32\icacls C:\Users\runneradmin\AppData\Local\Temp /grant "everyone":F /t
- name: Get pip cache dir
shell: bash -l {0}
id: pip-cache
run: |
echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT
- name: pip cache
uses: actions/cache@v3
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-v1-3-9-pip-${{ hashFiles('requirements-full.txt') }}
restore-keys: |
${{ runner.os }}-v1-pip-
- name: Uninstall Brotlipy
shell: bash -l {0}
run: |
conda remove brotlipy -y
- name: Install dependencies (Bash)
shell: bash -l {0}
run: |
pip install --requirement requirements-full.txt
- name: List installed packages (Bash)
shell: bash -l {0}
run: |
conda list
pip list
- name: Run tests (Bash)
env:
MPLBACKEND: Agg
shell: bash -l {0}
run: pytest tests/ -m "not linux" --optimization
- name: Start Terminal and exit
shell: bash -l {0}
run: python terminal.py

View File

@@ -5,6 +5,9 @@ env:
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
OPENBB_ENABLE_CHECK_API: false
OPENBB_PREVIOUS_USER: true
PIP_DEFAULT_TIMEOUT: 100
on:
@@ -13,7 +16,11 @@ on:
- develop
- main
types: [opened, synchronize, edited, closed]
push:
branches:
- release/*
merge_group:
types: [checks_requested]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
@@ -22,12 +29,13 @@ jobs:
check-files-changed:
name: Check for changes
runs-on: ubuntu-latest
if: github.event.pull_request.merged != true
# Run this job only if the PR is not merged and the event is not a push
if: github.event.pull_request.merged == false && github.event_name != 'push'
outputs:
check-changes: ${{ steps.check-changes.outputs.check-changes }}
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v1 # v1 is used to preserve the git history and works with the git diff command
with:
fetch-depth: 100
# The GitHub token is preserved by default but this job doesn't need
@@ -38,20 +46,16 @@ jobs:
- name: Check for changes to files to trigger unit test
id: check-changes
run: |
source_branch=$(jq -r .pull_request.head.ref "$GITHUB_EVENT_PATH")
target_branch=$(jq -r .pull_request.base.ref "$GITHUB_EVENT_PATH")
current_branch=$(jq -r .pull_request.base.ref "$GITHUB_EVENT_PATH")
if git diff --name-only origin/$target_branch HEAD | grep -E ".py$|openbb_terminal\/.*|pyproject.toml|poetry.lock|requirements.txt|requirements-full.txt"; then
if git diff --name-only origin/$current_branch HEAD | grep -E ".py$|openbb_terminal\/.*|pyproject.toml|poetry.lock|requirements.txt|requirements-full.txt"; then
echo "check-changes=true" >> $GITHUB_OUTPUT
else
echo "check-changes=false" >> $GITHUB_OUTPUT
fi
- name: Show output of previous step
run: |
# echo "python-changes=${{ steps.python-changes.outputs.python-changes }}"
# echo "folder-changes=${{ steps.folder-changes.outputs.folder-changes }}"
echo "check-changes=${{ steps.check-changes.outputs.check-changes }}"
run: echo "check-changes=${{ steps.check-changes.outputs.check-changes }}"
base-test:
name: Base Tests - Ubuntu-latest - Python 3.9
@@ -71,7 +75,7 @@ jobs:
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.1.13
version: 1.3.2
virtualenvs-create: true
virtualenvs-in-project: true
@@ -86,12 +90,12 @@ jobs:
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction -E optimization
- name: Run tests
- name: Run tests and coverage test
env:
MPLBACKEND: Agg
run: |
source $VENV
pytest tests/ --optimization --autodoc
pytest tests/ --optimization --cov --cov-fail-under=50 --autodoc -n auto --durations=10 --timeout=30
- name: Start Terminal and exit
run: |
@@ -100,7 +104,7 @@ jobs:
tests-python:
name: Vanilla Python Tests - ${{ matrix.python-version }}
needs: [check-files-changed, base-test]
needs: [base-test]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
@@ -123,7 +127,7 @@ jobs:
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.1.13
version: 1.3.2
virtualenvs-create: true
virtualenvs-in-project: true
@@ -149,7 +153,7 @@ jobs:
MPLBACKEND: Agg
run: |
source $VENV
pytest tests/ --optimization
pytest tests/ --optimization --autodoc -n auto --timeout=30
- name: Start Terminal and exit
run: |
@@ -159,9 +163,10 @@ jobs:
full-test:
name: Full Test Suite - (${{ matrix.python-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
if: github.event.pull_request.merged == true
# Run only when a PR is merged or a push to release/* branch
if: github.event_name == 'push' || github.event.pull_request.merged == true
strategy:
fail-fast: true
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10"]
os: [ubuntu-latest, macos-latest]
@@ -181,7 +186,7 @@ jobs:
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.1.13
version: 1.3.2
virtualenvs-create: true
virtualenvs-in-project: true
@@ -194,7 +199,8 @@ jobs:
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction -E optimization
run: |
poetry install --no-interaction -E optimization
- name: List installed packages
shell: bash -l {0}
@@ -202,26 +208,26 @@ jobs:
source $VENV
pip list
- name: Run tests
env:
MPLBACKEND: Agg
run: |
source $VENV
pytest tests/ --optimization --autodoc
- name: Start Terminal and exit
run: |
source $VENV
python terminal.py
- name: Run tests
env:
MPLBACKEND: Agg
run: |
source $VENV
pytest tests/ --optimization --autodoc -n auto --timeout=30
tests-conda:
name: Anaconda Python Tests - (${{ matrix.python-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}-latest
if: github.event.pull_request.merged == true
if: github.event_name == 'push' || github.event.pull_request.merged == true
strategy:
fail-fast: false
matrix:
os: ["ubuntu", "windows"]
os: ["ubuntu", "windows", "macos"]
python-version: ["3.9"]
dependencies: [""]
include:
@@ -293,11 +299,6 @@ jobs:
restore-keys: |
${{ runner.os }}-v1-pip-
- name: Uninstall Brotlipy
shell: bash -l {0}
run: |
conda remove brotlipy -y
- name: Install dependencies (Bash)
shell: bash -l {0}
run: |
@@ -313,8 +314,7 @@ jobs:
env:
MPLBACKEND: Agg
shell: bash -l {0}
run: pytest tests/ -m "not linux" --optimization
run: pytest tests/ -m "not linux" --optimization -n auto --timeout=30
- name: Start Terminal and exit
shell: bash -l {0}
run: python terminal.py

View File

@@ -4,6 +4,7 @@ env:
OPENBB_LOG_COLLECT: false
OPENBB_USE_ION: false
OPENBB_USE_PROMPT_TOOLKIT: false
OPENBB_FILE_OVERWRITE: true
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on:

View File

@@ -1,4 +1,5 @@
name: Windows10 Build
env:
OPENBB_ENABLE_QUICK_EXIT: true
OPENBB_LOG_COLLECT: false
@@ -6,50 +7,73 @@ env:
OPENBB_USE_PROMPT_TOOLKIT: false
PIP_DEFAULT_TIMEOUT: 100
PYTHONNOUSERSITE: 1
on: workflow_dispatch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Windows-Build:
name: Windows10 Build
runs-on: [self-hosted, Windows, x64]
name: Windows10 Build ENV
runs-on: windows-2019
# Configuring -------------
steps:
- name: Setup Windows Git Configuration # This is under the assumption that git is already installed on the system
run: |
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
git config --system core.longpaths true
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
git config --system core.longpaths true
- name: Checkout
uses: actions/checkout@v2.4.2
- name: Activate Base & Create OpenBB Environment
uses: actions/checkout@v3
- name: Set up Python & Create OpenBB Environment
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Create and start virtual environment
run: |
conda activate base
conda env create -n obb --file build/conda/conda-3-9-env-full.yaml
conda init
conda activate obb
conda env list
- name: Poetry Install
# Conda activate needs to be run every time because of the way that the workflow steps work
# on powershell where it creates a new shell every time for every step
python -m venv venv
source venv/Scripts/activate
python -m pip install --upgrade pip
python -m pip install setuptools==64.0.2 wheel
python -m pip install charset_normalizer==2.1.1
python -m pip install -r requirements-full.txt
python -m pip uninstall papermill -y
python -m pip install git+https://github.com/nteract/papermill.git@main
python -m PyInstaller build/pyinstaller/terminal.spec --clean
shell: bash
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: OpenBB-Windows10-ENV
path: dist
Build-Exe:
name: Windows10 Build-Exe
runs-on: [self-hosted, Windows, x64]
needs: Windows-Build
# Configuring -------------
steps:
- name: Setup Windows Git Configuration # This is under the assumption that git is already installed on the system
run: |
conda activate obb
poetry install
- name: Poetry Install Portfolio Optimization and Forecasting Toolkits
run: |
conda activate obb
poetry install -E all
- name: Poetry Install Installer
run: |
conda activate obb
poetry install -E installer
- name: Install Specific Papermill
run: |
conda activate obb
pip uninstall papermill -y
pip install git+https://github.com/nteract/papermill.git@main
# Building ------------
- name: Build Terminal.spec file
run: |
conda activate obb
pyinstaller build/pyinstaller/terminal.spec --clean
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -value 1
git config --system core.longpaths true
- name: Checkout
uses: actions/checkout@v3
- name: Download Artifact
uses: actions/download-artifact@v2
with:
name: OpenBB-Windows10-ENV
path: dist
- name: Move Files into App Folder
run: cp -r .\dist\OpenBBTerminal\ .\build\nsis\app\
# don't need this because log collection is turned off
@@ -57,16 +81,35 @@ jobs:
# run: Remove-Item .\build\nsis\app\openbb_terminal\logs\ -Recurse
- name: Build Exe File
run: |
conda activate obb
C:\'.\Program Files (x86)\'\nsis\makensis.exe .\build\nsis\setup.nsi
# This should autosign the installer now - We really need to only do this when needed though. ON RELEASE
- name: Sign Installer
if: startsWith(github.ref, 'refs/heads/main')
run: |
& 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86\signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /td sha256 /sha1 26a8e28dbe3b1db7407b92d7de97c290d4436a32 'C:\Users\Administrator\actions-runner\_work\OpenBBTerminal\OpenBBTerminal\build\nsis\OpenBB Terminal Setup.exe'
- name: Save Build Artifact
uses: actions/upload-artifact@v3
with:
name: Windows EXE Artifact
path: '.\build\nsis\OpenBB Terminal Setup.exe'
- name: Run Integration Tests
run: |
dist\OpenBBTerminal\OpenBBTerminal.exe C:\Users\Administrator\actions-runner\_work\OpenBBTerminal\OpenBBTerminal\openbb_terminal\miscellaneous\scripts -t
dist\OpenBBTerminal\OpenBBTerminal.exe -t -s forecast cryptocurrency reports alternative economy futures econometrics dashboards portfolio stocks/test_stocks_options_screen.openbb stocks/test_stocks_options.openbb forex etf stocks/test_stocks_fa.openbb > result.txt
cat result.txt
Select-String "================================ integration test summary ================================" result.txt -Context 0,100 | Select-Object -Last 2000 | Out-File failed_tests.txt
- name: Upload summary to Slack
uses: adrey/slack-file-upload-action@master
with:
token: ${{ secrets.SLACK_API_TOKEN }}
initial_comment: "Windows Build Integration test summary"
title: "Windows Build Integration test summary"
path: failed_tests.txt
channel: ${{ secrets.SLACK_CHANNEL_ID }}
# Cleaning ------------------------
# Make sure to add Remove-Item C:\Users\Administrator\Desktop\OPENBB-exports -Recurse whenever integration tests get fixed
- name: Remove Previous Build
@@ -74,10 +117,3 @@ jobs:
Remove-Item '.\build\nsis\OpenBB Terminal Setup.exe' -Recurse
Remove-Item .\build\nsis\app\ -Recurse
Remove-Item .\dist\ -Recurse
Remove-Item .\build\terminal\ -Recurse
- name: Deactivate & Remove Conda Environment
run: |
conda deactivate obb
conda deactivate base
conda env remove -n obb
Remove-Item C:\Users\Administrator\miniconda3\envs\obb\ -Recurse

18
.gitignore vendored
View File

@@ -39,6 +39,7 @@ website/functions
*_sdk_audit.csv
website/terminaltest
!build/docker/compose.env
.dccache
# pyinstaller artifacts
*.pyo
@@ -48,19 +49,6 @@ build/nsis/app
DMG/*
*.dmg
# Jupyter Lab Extension build files
jupyterlab/**/build
jupyterlab/*/*.bundle.*
jupyterlab/*/lib/
jupyterlab/*/*/labextension/
jupyterlab/*/node_modules/
jupyterlab/*/*/node_modules/
jupyterlab/*/*.egg-info/
jupyterlab/*/.ipynb_checkpoints
jupyterlab/*/*.tsbuildinfo
jupyterlab/*/ui-tests/test-results/
jupyterlab/*/ui-tests/tests/*.ts-snapshots/
# User stylesheets
styles/user
@@ -76,3 +64,7 @@ custom_imports/*/*.csv
# cache
cache/
# lightning logs
lightning_logs/

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.4.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
@@ -10,11 +10,11 @@ repos:
- id: check-merge-conflict
- id: detect-private-key
- repo: https://github.com/psf/black
rev: 22.10.0
rev: 23.1.0
hooks:
- id: black
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.0.212'
rev: 'v0.0.247'
hooks:
- id: ruff
- repo: https://github.com/codespell-project/codespell
@@ -64,11 +64,6 @@ repos:
"website/content/api/*",
]
exclude: package.lock.json
- repo: https://github.com/asottile/pyupgrade
rev: v3.2.2
hooks:
- id: pyupgrade
args: [--py38-plus]
- repo: local
hooks:
- id: reserved_args

223
CONTRIBUTING.md vendored
View File

@@ -13,7 +13,6 @@ Use your best judgment, and feel free to propose changes to this document in a p
- [View](#view)
- [Controller](#controller)
- [Add SDK endpoint](#add-sdk-endpoint)
- [Add Documentation](#add-documentation)
- [Open a Pull Request](#open-a-pull-request)
- [Review Process](#review-process)
- [Understand Code Structure](#understand-code-structure)
@@ -106,7 +105,7 @@ def get_most_shorted() -> pd.DataFrame:
url = "https://finance.yahoo.com/screener/predefined/most_shorted_stocks"
data = pd.read_html(
requests.get(url, headers={"User-Agent": get_user_agent()}).text
request(url, headers={"User-Agent": get_user_agent()}).text
)[0]
data = data.iloc[:, :-1]
return data
@@ -137,7 +136,7 @@ def get_economy_calendar_events() -> pd.DataFrame:
pd.DataFrame
Get dataframe with economic calendar events
"""
response = requests.get(
response = request(
f"https://finnhub.io/api/v1/calendar/economic?token={cfg.API_FINNHUB_KEY}"
)
@@ -310,160 +309,58 @@ In addition, note the `self.load_class` which allows to not create a new DarkPoo
In order to add a command to the SDK, follow these steps:
1. Go to the `sdk.py` file and scroll to the `functions` dictionary, it should look like this:
1. If you've created a new model or view file, add the import with an alias to `openbb_terminal/sdk_core/sdk_init.py` following this structure:
```python
functions = {
"stocks.get_news": {
"model": "openbb_terminal.common.newsapi_model.get_news",
},
"stocks.load": {
"model": "openbb_terminal.stocks.stocks_helper.load",
},
"stocks.candle": {
"model": "openbb_terminal.stocks.stocks_helper.load",
"view": "openbb_terminal.stocks.stocks_helper.display_candle",
},
...
# Stocks - Fundamental Analysis
from openbb_terminal.stocks.fundamental_analysis import (
finviz_model as stocks_fa_finviz_model,
finnhub_model as stocks_fa_finnhub_model,
finnhub_view as stocks_fa_finnhub_view,
)
```
2. Add a new key to the dictionary, which corresponds to the way the added command shall be accessed from the sdk.
This is called the `virtual path`. In this case it should be `stocks.dps.shorted`.
3. Now it is time to add the value to the key. This key shall be another dictionary with a `model` key and possibly a
`view` key.
1. The model keys value should be the path from project root to the new commands model function as a string. This
case it is `openbb_terminal.stocks.dark_pool_shorts.yahoofinance_model.get_most_shorted`.
2. If and **only if** the view function of the command **displays a chart**, then the `view` key and its value is
the view functions path from the project root as a string. In this example the view function of the only prints a
table and thus this step can be ignored.
4. Done!!! The final new dictionary looks like this after the added example:
2. Go to the `trail_map.csv` file located in `openbb_terminal/sdk_core`, which should look like this:
```python
functions = {
...
"stocks.dps.shorted": {
"model": "openbb_terminal.stocks.dark_pool_shorts.yahoofinance_model.get_most_shorted",
},
...
```csv
trail,model,view
stocks.fa.analyst,stocks_fa_finviz_model.get_analyst_data,
stocks.fa.rot,stocks_fa_finnhub_model.get_rating_over_time,stocks_fa_finnhub_view.rating_over_time
```
### Add Documentation
In this file, the trail represents the path to the function to be called. The model represents the import alias we gave to the `_model` file. The view represents the import alias we gave to the `_view` file.
To check whether documentation is added correctly follow [Hugo Server instructions](/website/README.md).
3. Add your new function to this structure. In our example of the `shorted` function, our trail would be `stocks.dps.shorted`.
The model is the import alias to the `_model` function that was written: `stocks_dps_yahoofinance_model.get_most_shorted`.
The view is the import alias to the `_view` function that was written: `stocks_dps_yahoofinance_view.display_most_shorted`.
The added line of the file should look like this:
This is the structure that the documentation follows:
```txt
website/content/_index.md
/stocks/_index.md
/load/_index.md
/candle/_index.md
/discovery/_index.md
/ipo/_index.md
/...
/...
/...
/cryptocurrency/_index.md
/chart/_index.md
/defi/_index.md
/borrow/_index.md
/...
/...
/...
/common/_index.md
/technical_analysis/_index.md
/ema/_index.md
/...
/...
```
Note that the `common` folder holds features that are common across contexts, e.g. `technical analysis` can be performed on both `stocks` or `crytpo`.
To add a new command, there are two main actions that need to be done:
1. Create a directory with the name of the command and a `_index.md` file within. Examples:
- When adding `ipo`, since this command belongs to context `stocks` and category `discovery`, we added a `ipo` folder with a `_index.md` file within to `website/content/stocks/discovery`.
- When adding `candle`, since this command belongs to context `stocks`, we added a `candle` folder with a `_index.md` file within to `website/content/stocks/`.
2. The `_index.md` file should have the output of the `command -h` followed by a screenshot example of what the user can expect. Note that you can now drag and drop the images while editing the readme file on the remote web version of your PR branch. Github will create a link for it with format (<https://user-images.githubusercontent.com/***/***.file_format>).
Example:
---
```shell
usage: ipo [--past PAST_DAYS] [--future FUTURE_DAYS]
```csv
stocks.dps.shorted,stocks_dps_yahoofinance_model.get_most_shorted,stocks_dps_yahoofinance_view.display_most_shorted
```
Past and future IPOs. [Source: <https://finnhub.io>]
4. Generate the SDK files by running `python generate_sdk.py` from the root of the project. This will automatically generate the SDK `openbb_terminal/sdk.py`, corresponding `openbb_terminal/sdk_core/controllers/` and `openbb_terminal/sdk_core/models/` class files.
- --past : Number of past days to look for IPOs. Default 0.
- --future : Number of future days to look for IPOs. Default 10.
To sort the `trail_map.csv` file and generate the SDK files, run the following command
<IMAGE HERE - Use drag and drop hint mentioned above>
---
3. Update the Navigation bar to match the content you've added. This is done by adding 2 lines of code to `website/data/menu/`, i.e. a `name` and a `ref`. Example:
```python
---
main:
- name: stocks
ref: "/stocks"
sub:
- name: load
ref: "/stocks/load"
- name: candle
ref: "/stocks/candle"
- name: discovery
ref: "/stocks/discovery"
sub:
- name: ipo
ref: "/stocks/discovery/ipo"
- name: map
ref: "/stocks/discovery/map"
```bash
python generate_sdk.py sort
```
### Open a Pull Request
Once you're happy with what you have, push your branch to remote. E.g. `git push origin feature/AmazingFeature`
Once you're happy with what you have, push your branch to remote. E.g. `git push origin feature/AmazingFeature`. Note that we follow gitflow naming convention, so your branch name should be prefixed with `feature/` or `hotfix/` depending on the type of work you are doing.
A user may create a **Draft Pull Request** when he/she wants to discuss implementation with the team.
The team will then assign your PR one of the following labels:
| Label name | Description | Example |
| -------------- | ----------------------------------- | ---------------------------------------------- |
| `feat XS` | Extra small feature | Add a preset |
| `feat S` | Small T-Shirt size Feature | New single command added |
| `feat M` | Medium T-Shirt size feature | Multiple commands added from same data source |
| `feat L` | Large T-Shirt size Feature | New category added under context |
| `feat XL` | Extra Large feature | New context added |
| `enhancement` | Enhancement | Add new parameter to existing command |
| `bug` | Fix a bug | Fixes terminal crashing or warning message |
| `build` | Build-related work | Fix a github action that is breaking the build |
| `tests` | Test-related work | Add/improve tests |
| `docs` | Improvements on documentation | Add/improve documentation |
| `refactor` | Refactor code | Changing argparse location |
| `docker` | Docker-related work | Add/improve docker |
| `help wanted` | Extra attention is needed | When a contributor needs help |
| `do not merge` | Label to prevent pull request merge | When PR is not ready to be merged just yet |
### Review Process
As soon as the Pull Request is opened, our repository has a specific set of github actions that will not only run
linters on the branch just pushed, but also run pytest on it. This allows for another layer of safety on the code developed.
In addition, our team is known for performing `diligent` code reviews. This not only allows us to reduce the amount of
iterations on that code and have it to be more future proof, but also allows the developer to learn/improve his coding skills.
In addition, our team is known for performing `diligent` code reviews. This not only allows us to reduce the amount of iterations on that code and have it to be more future proof, but also allows the developer to learn/improve his coding skills.
Often in the past the reviewers have suggested better coding practices, e.g. using `1_000_000` instead of `1000000` for
better visibility, or suggesting a speed optimization improvement.
Often in the past the reviewers have suggested better coding practices, e.g. using `1_000_000` instead of `1000000` forbetter visibility, or suggesting a speed optimization improvement.
## Understand Code Structure
@@ -1100,9 +997,8 @@ The following linters are used by our codebase:
| bandit | security analyzer |
| black | code formatter |
| codespell | spelling checker |
| flake8 | style guide enforcer |
| ruff | a fast python linter |
| mypy | static typing checker |
| pyupgrade | upgrade syntax for newer versions |
| safety | checks security vulnerabilities |
| pylint | bug and quality checker |
| markdownlint | markdown linter |
@@ -1146,39 +1042,46 @@ Note that a `OPENBB_` is added so that the user knows that that environment vari
One of the first steps once adding a new data source that requires an API key is to add that key to our [keys_controller.py](/openbb_terminal/keys_controller.py). This menu allows the user to set API keys and check their validity.
The following code allows to check the validity of the IEX Cloud API key.
The following code allows to check the validity of the Polygon API key.
```python
def check_iex_key(show_output: bool = False) -> str:
"""Check IEX Cloud key
def check_polygon_key(show_output: bool = False) -> str:
"""Check Polygon key
Parameters
----------
show_output: bool
Display status string or not.
show_output: bool
Display status string or not. By default, False.
Returns
-------
status: str
str
Status of key set
"""
if cfg.API_IEX_TOKEN == "REPLACE_ME": # nosec
logger.info("IEX Cloud key not defined")
if cfg.API_POLYGON_KEY == "REPLACE_ME":
logger.info("Polygon key not defined")
status = KeyStatus.NOT_DEFINED
else:
try:
pyEX.Client(api_token=cfg.API_IEX_TOKEN, version="v1").quote(symbol="AAPL")
logger.info("IEX Cloud key defined, test passed")
status = KeyStatus.DEFINED_TEST_PASSED
except Exception as _: # noqa: F841
logger.warning("IEX Cloud key defined, test failed")
r = request(
"https://api.polygon.io/v2/aggs/ticker/AAPL/range/1/day/2020-06-01/2020-06-17"
f"?apiKey={cfg.API_POLYGON_KEY}"
)
if r.status_code in [403, 401]:
logger.warning("Polygon key defined, test failed")
status = KeyStatus.DEFINED_TEST_FAILED
elif r.status_code == 200:
logger.info("Polygon key defined, test passed")
status = KeyStatus.DEFINED_TEST_PASSED
else:
logger.warning("Polygon key defined, test inconclusive")
status = KeyStatus.DEFINED_TEST_INCONCLUSIVE
if show_output:
console.print(status.colorize() + "\n")
console.print(status.colorize())
return status
return str(status)
```
Note that there are usually 3 states:
@@ -1193,13 +1096,13 @@ A function can then be created with the following format to allow the user to ch
```python
@log_start_end(log=logger)
def call_iex(self, other_args: List[str]):
"""Process iex command"""
def call_polygon(self, other_args: List[str]):
"""Process polygon command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="iex",
description="Set IEX Cloud API key.",
prog="polygon",
description="Set Polygon API key.",
)
parser.add_argument(
"-k",
@@ -1209,13 +1112,14 @@ def call_iex(self, other_args: List[str]):
help="key",
)
if not other_args:
console.print("For your API Key, visit: https://iexcloud.io\n")
console.print("For your API Key, visit: https://polygon.io\n")
return
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-k")
ns_parser = parse_simple_args(parser, other_args)
ns_parser = self.parse_simple_args(parser, other_args)
if ns_parser:
self.status_dict["iex"] = keys_model.set_iex_key(
self.status_dict["polygon"] = keys_model.set_polygon_key(
key=ns_parser.key, persist=True, show_output=True
)
```
@@ -1270,7 +1174,6 @@ The convention is as follows:
"candle": [],
"load": [
"YahooFinance",
"IEXCloud",
"AlphaVantage",
"Polygon",
"EODHD"
@@ -1300,7 +1203,7 @@ The way to interpret this file is by following the path to a data source, e.g.
- `stocks/search` relies on `FinanceDatabase`
- `stocks/candle` does not rely on any data source. This means that it relies on data that has been loaded before.
- `stocks/load` relies on `YahooFinance`, `IEXCloud`, `AlphaVantage`, `Polygon` or `EODHD`.
- `stocks/load` relies on `YahooFinance`, `AlphaVantage`, `Polygon` or `EODHD`.
- **The order is important as the first data source is the one utilized by default.**
- `stoks/options/unu` relies on `FDScanner`.
- `stocks/options/exp` relies on `YahooFinance` by default but `Tradier` and `Nasdaq` sources are allowed.

125
README.md vendored
View File

@@ -16,7 +16,6 @@
[![Bugs Open][bugs-open-shield]][bugs-open-url]
[![Bugs Closed][bugs-closed-shield]][bugs-closed-url]
[![Build Status](https://github.com/OpenBB-finance/OpenBBTerminal/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/OpenBB-finance/OpenBBTerminal/actions)
[![GitHub release](https://img.shields.io/github/release/OpenBB-finance/OpenBBTerminal.svg?maxAge=3600)](https://github.com/OpenBB-finance/OpenBBTerminal/releases)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/OpenBB-finance/OpenBBTerminal/main)](https://www.tickgit.com/browse?repo=github.com/OpenBB-finance/OpenBBTerminal&branch=main)
@@ -25,73 +24,48 @@
[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/openbb_finance.svg?style=social&label=Follow%20%40openbb_finance)](https://twitter.com/openbb_finance)
<!-- PROJECT LOGO -->
<br />
<p align="center">
<a href="https://openbb.co/">
<img src="images/openbb_gradient.png" alt="Logo" width="1000">
</a>
| OpenBB is committed to build the future of investment research by focusing on an open source infrastructure accessible to everyone, everywhere. |
|:--:|
| ![openbb.jpg](/images/openbb_gradient.png) |
| Check our website at [openbb.co](https://openbb.co) |
<br />
<p align="center">
<h3 align="center">OpenBB Terminal 🚀</h3>
<h4 align="center">Documentation can be found at: https://openbb.co/docs </h4>
<p align="center">Click on the GIF below for a DEMO of the terminal.</p>
<p align="center">
<a href="https://www.youtube.com/watch?v=fqGPK8OVHLk" rel="OpenBB Terminal Demo">
<img src="images/openbb_terminal_illustration.gif" alt="OpenBB Terminal Illustration" width="100%"/>
</a>
</p>
<p align="center">
<a href="https://www.youtube.com/watch?v=fqGPK8OVHLk" rel="OpenBB Terminal Demo">
<img src="images/openbb_terminal_illustration.gif" alt="OpenBB Terminal Illustration" width="100%"/>
</a>
</p>
<p align="center">
Investment research for everyone.
<br />
<a href="https://docs.openbb.co/terminal/quickstart/installation"><strong>≪ GETTING STARTED</strong></a>
&nbsp · &nbsp <a href="https://github.com/OpenBB-finance/OpenBBTerminal/tree/master/CONTRIBUTING.md"><strong>CONTRIBUTING</strong></a> &nbsp · &nbsp
<a href="https://docs.openbb.co/terminal">
<strong>SEE FEATURES »</strong></a>
<br />
<br />
<a href="https://github.com/OpenBB-finance/OpenBBTerminal/issues/new?assignees=&labels=bug&template=bug_report.md&title=%5BBug%5D">
Report Bug</a>
·
<a href="https://github.com/OpenBB-finance/OpenBBTerminal/issues/new?assignees=&labels=enhancement&template=enhancement.md&title=%5BIMPROVE%5D">
Suggest Improvement</a>
·
<a href="https://github.com/OpenBB-finance/OpenBBTerminal/issues/new?assignees=&labels=new+feature&template=feature_request.md&title=%5BFR%5D">
Request a Feature</a>
</p>
</p>
<!-- TABLE OF CONTENTS -->
<details open="open">
<details closed="closed">
<summary><h2 style="display: inline-block">Table of Contents</h2></summary>
<ol>
<li> <a href="#1-about-the-project">About The Project</a> </li>
<li><a href="#2-installation">Installation</a></li>
<li><a href="#3-contributing">Contributing</a></li>
<li><a href="#4-license">License</a></li>
<li><a href="#5-disclaimer">Disclaimer</a></li>
<li><a href="#6-contacts">Contacts</a></li>
<li><a href="#7-star-history">Star History</a></li>
<li><a href="#8-contributors">Contributors</a></li>
<li><a href="#1-installation">Installation</a></li>
<li><a href="#2-contributing">Contributing</a></li>
<li><a href="#3-license">License</a></li>
<li><a href="#4-disclaimer">Disclaimer</a></li>
<li><a href="#5-contacts">Contacts</a></li>
<li><a href="#6-star-history">Star History</a></li>
<li><a href="#7-contributors">Contributors</a></li>
</ol>
</details>
## 1. About The Project
**How it started:**
OpenBBTerminal is an awesome stock and crypto market terminal that has been developed for fun, while I saw my GME shares tanking. But hey, I like the stock 💎🙌.
**How it's going:**
OpenBBTerminal provides a Python-based integrated environment for investment research, that allows
an average joe retail trader to leverage state-of-the-art Data Science and Machine Learning technologies.
As a Python-based environment, OpenBBTerminal opens access to numerous Python data libraries in Data Science
(Pandas, Numpy, Scipy, Jupyter), Machine Learning (Pytorch, Sklearn, Flair), and Data Acquisition
(Beautiful Soup, and numerous third-party APIs).
## 2. Installation
## 1. Installation
If you wish to install the OpenBB Terminal or the OpenBB SDK, please use one of the following options:
@@ -107,42 +81,33 @@ If you wish to install the OpenBB Terminal or the OpenBB SDK, please use one of
|[PyPi](https://docs.openbb.co/sdk/quickstart/installation)|Recommended way if you just want to use the OpenBB SDK|
|[Python](https://docs.openbb.co/terminal/quickstart/installation?tab=python)|If you wish to contribute to the development of the OpenBB SDK &nbsp; &nbsp; &nbsp; &nbsp;|
## 3. Contributing
## 2. Contributing
There are three main ways of contributing to this project. (Hopefully you have starred the project by now ⭐️)
**BECOME A CONTRIBUTOR**
### Become a Contributor
1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Install the pre-commit hooks by running: `pre-commit install`
Any time you commit a change, linters will be run automatically. On changes, you will have to re-commit
4. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
5. Push to your Branch (`git push origin feature/AmazingFeature`)
6. Open a Pull Request
* More information on our [CONTRIBUTING GUIDELINES](/CONTRIBUTING.md).
You can read more details about adding a feature in our [CONTRIBUTING GUIDELINES](/CONTRIBUTING.md).
### Create a GitHub ticket
**RAISE AN ISSUE OR REQUEST A FEATURE**
Before creating a ticket make sure the one you are creating doesn't exist already [here](https://github.com/OpenBB-finance/OpenBBTerminal/issues)
- Raise an issue by opening a [bug ticket](https://github.com/OpenBB-finance/OpenBBTerminal/issues).
- Request a new feature through a [feature request ticket](https://github.com/OpenBB-finance/OpenBBTerminal/issues).
* [Report bug](https://github.com/OpenBB-finance/OpenBBTerminal/issues/new?assignees=&labels=bug&template=bug_report.md&title=%5BBug%5D)
* [Suggest improvement](https://github.com/OpenBB-finance/OpenBBTerminal/issues/new?assignees=&labels=enhancement&template=enhancement.md&title=%5BIMPROVE%5D)
* [Request a feature](https://github.com/OpenBB-finance/OpenBBTerminal/issues/new?assignees=&labels=new+feature&template=feature_request.md&title=%5BFR%5D)
**JOIN US**
### Provide feedback
Join [our Discord](https://openbb.co/discord) and provide us any feedback on The OpenBB Terminal.
We are most active on [our Discord](https://openbb.co/discord), but feel free to reach out to us in any of [our social media](https://openbb.co/links) for feedback.
## 4. License
## 3. License
Distributed under the MIT License. See
[LICENSE](https://github.com/OpenBB-finance/OpenBBTerminal/blob/main/LICENSE) for more information.
## 5. Disclaimer
## 4. Disclaimer
*"A few things I am not. I am not a cat. I am not an institutional investor, nor am I a hedge fund. I do not have
clients and I do not provide personalized investment advice for fees or commissions."* DFV
```text
Trading in financial instruments involves high risks including the risk of losing some, or all, of your investment
amount, and may not be suitable for all investors.
@@ -151,25 +116,27 @@ Before deciding to trade in a financial instrument you should be fully informed
The data contained in the OpenBBTerminal is not necessarily accurate.
OpenBB and any provider of the data contained in this website will not accept liability for any loss or damage as a result of your trading, or your reliance on the information displayed.
```
## 6. Contacts
All names, logos, and brands of third parties that may be referenced in our sites, products or documentation are trademarks of their respective owners. Unless otherwise specified, OpenBB and its products and services are not endorsed by, sponsored by, or affiliated with these third parties.
Our use of these names, logos, and brands is for identification purposes only, and does not imply any such endorsement, sponsorship, or affiliation.
If you have any questions about the terminal or anything OpenBB, feel free to email us at support@openbb.co
## 5. Contacts
If you want to say hi, or are interested in partnering with us, feel free to reach us at hello@openbb.co
If you have any questions about the terminal or anything OpenBB, feel free to email us at `support@openbb.co`
Feel free to share loss porn, memes or any questions at:
If you want to say hi, or are interested in partnering with us, feel free to reach us at `hello@openbb.co`
- Twitter: [@openbb_finance](https://twitter.com/openbb_finance)
- Discord: [openbb.co/discord](https://openbb.co/discord)
- Reddit: [openbb.co/reddit](https://openbb.co/reddit)
Any of our social media platforms: [openbb.co/links](https://openbb.co/links)
## 7. Star History
## 6. Star History
This is a proxy of our growth and that we are just getting started. But for more metrics important to us check [openbb.co/open](https://openbb.co/open).
[![Star History Chart](https://api.star-history.com/svg?repos=openbb-finance/OpenBBTerminal&type=Date)](https://star-history.com/#openbb-finance/OpenBBTerminal&Date)
## 8. Contributors
## 7. Contributors
OpenBB wouldn't be OpenBB without you. If we are going to disrupt financial industry, every contribution counts. Thank you for being part of this journey.
<a href="https://github.com/OpenBB-finance/OpenBBTerminal/graphs/contributors">
<img src="https://contributors-img.web.app/image?repo=OpenBB-finance/OpenBBTerminal" width="800"/>

2
TROUBLESHOOT.md vendored
View File

@@ -106,7 +106,7 @@ If you run into issues installing or `Cannot convert a symbolic Tensor...` at ru
```bash
poetry install
poetry install -E prediction
poetry install -E forecast
```
_Commands that may help you in case of an error:_

View File

@@ -4,5 +4,6 @@ channels:
dependencies:
- python=3.8
- pip
- poetry=1.1.13
- lightgbm=3.3.3
- conda-forge::lightgbm=3.3.3
- pip:
- poetry==1.3.2

View File

@@ -4,4 +4,5 @@ channels:
dependencies:
- python=3.8
- pip
- poetry=1.1.13
- pip:
- poetry==1.3.2

View File

@@ -2,7 +2,8 @@ channels:
- conda-forge
- defaults
dependencies:
- python=3.9.6
- python=3.9.13
- pip
- poetry=1.1.13
- lightgbm=3.3.3
- conda-forge::lightgbm=3.3.3
- pip:
- poetry==1.3.2

View File

@@ -2,6 +2,7 @@ channels:
- conda-forge
- defaults
dependencies:
- python=3.9
- python=3.9.13
- pip
- poetry=1.1.13
- pip:
- poetry==1.3.2

8
build/conda/conda-3-9-windows.yaml vendored Normal file
View File

@@ -0,0 +1,8 @@
channels:
- conda-forge
- defaults
dependencies:
- python=3.9
- poetry==1.3.2
- setuptools=64.0.2
- pip

View File

@@ -1,2 +1,2 @@
OPENBBTERMINAL_DOCKER_REGISTRY="ghcr.io"
OPENBBTERMINAL_DOCKER_RELEASE_VERSION="2.1.0"
OPENBBTERMINAL_DOCKER_RELEASE_VERSION="2.4.1"

View File

@@ -7,6 +7,6 @@ services:
- ~/OpenBBUserData:/home/python/OpenBBUserData
- ~/.openbb_terminal:/home/python/.openbb_terminal
platform: linux/amd64
image: ghcr.io/openbb-finance/openbbterminal/openbb:2.1.0
image: ghcr.io/openbb-finance/openbbterminal/openbb:2.4.1
stdin_open: true # docker run -i
tty: true # docker run -t

View File

@@ -40,7 +40,7 @@ FROM debian as poetry
ENV PATH="/home/python/.local/bin:${PATH}"
RUN pip install --upgrade pip wheel
RUN pip install poetry==1.1.15
RUN pip install poetry==1.3.2
# SETUP OPENBB IMAGE
FROM poetry as repository
@@ -62,9 +62,9 @@ RUN chown python:python .openbb_terminal
# SETUP OPENBB IMAGE
FROM repository as dependencies
RUN poetry install --no-root --no-dev --extras optimization --extras prediction
RUN poetry install --no-root --no-dev --extras optimization --extras forecast
# SETUP OPENBB IMAGE
FROM dependencies as openbb
CMD ["poetry", "run", "python", "terminal.py"]
CMD ["poetry", "run", "python", "terminal.py"]

139
build/nsis/setup.nsi vendored
View File

@@ -10,7 +10,7 @@
!define NAME "OpenBB Terminal"
!define COMPANY "OpenBB"
!define APPFILE "OpenBBTerminal.exe"
!define VERSION "2.1.0"
!define VERSION "2.4.1"
!define SLUG "${NAME} v${VERSION}"
;--------------------------------
@@ -30,6 +30,7 @@
!define MUI_HEADERIMAGE_BITMAP "assets\installer_horizontal.bmp"
!define MUI_ABORTWARNING
!define MUI_WELCOMEPAGE_TITLE "${SLUG} Setup"
!define UninstId "OpenBBTerminal" ; You might want to use a GUID here
;--------------------------------
; Pages
@@ -49,15 +50,145 @@
; Set UI language
!insertmacro MUI_LANGUAGE "English"
Var /GLOBAL installerPath
; StrContains
; This function does a case sensitive searches for an occurrence of a substring in a string.
; It returns the substring if it is found.
; Otherwise it returns null("").
; Written by kenglish_hi
; Adapted from StrReplace written by dandaman32
Var STR_HAYSTACK
Var STR_NEEDLE
Var STR_CONTAINS_VAR_1
Var STR_CONTAINS_VAR_2
Var STR_CONTAINS_VAR_3
Var STR_CONTAINS_VAR_4
Var STR_RETURN_VAR
Function StrContains
Exch $STR_NEEDLE
Exch 1
Exch $STR_HAYSTACK
; Uncomment to debug
;MessageBox MB_OK 'STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK '
StrCpy $STR_RETURN_VAR ""
StrCpy $STR_CONTAINS_VAR_1 -1
StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE
StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK
loop:
IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1
StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1
StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found
StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done
Goto loop
found:
StrCpy $STR_RETURN_VAR $STR_NEEDLE
Goto done
done:
Pop $STR_NEEDLE ;Prevent "invalid opcode" errors and keep the
Exch $STR_RETURN_VAR
FunctionEnd
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK
Push `${HAYSTACK}`
Push `${NEEDLE}`
Call StrContains
Pop `${OUT}`
!macroend
!define StrContains '!insertmacro "_StrContainsConstructor"'
;-------------------------------
; Uninstall Previous Version if exists
!macro UninstallExisting exitcode uninstcommand
Push `${uninstcommand}`
Call UninstallExisting
Pop ${exitcode}
!macroend
Function UninstallExisting
Exch $1 ; uninstcommand
Push $2 ; Uninstaller
Push $3 ; Len
StrCpy $3 ""
StrCpy $2 $1 1
StrCmp $2 '"' qloop sloop
sloop:
StrCpy $2 $1 1 $3
IntOp $3 $3 + 1
StrCmp $2 "" +2
StrCmp $2 ' ' 0 sloop
IntOp $3 $3 - 1
Goto run
qloop:
StrCmp $3 "" 0 +2
StrCpy $1 $1 "" 1 ; Remove initial quote
IntOp $3 $3 + 1
StrCpy $2 $1 1 $3
StrCmp $2 "" +2
StrCmp $2 '"' 0 qloop
run:
StrCpy $2 $1 $3 ; Path to uninstaller
StrCpy $1 161 ; ERROR_BAD_PATHNAME
GetFullPathName $3 "$2\.." ; $InstDir
IfFileExists "$2" 0 +4
ExecWait '"$2" /S _?=$3' $1 ; This assumes the existing uninstaller is a NSIS uninstaller, other uninstallers don't support /S nor _?=
IntCmp $1 0 "" +2 +2 ; Don't delete the installer if it was aborted
Delete "$2" ; Delete the uninstaller
RMDir "$3" ; Try to delete $InstDir
RMDir "$3\.." ; (Optional) Try to delete the parent of $InstDir
Pop $3
Pop $2
Exch $1 ; exitcode
FunctionEnd
Function .onInit
ReadRegStr $0 HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "UninstallString"
${If} $0 != ""
${AndIf} ${Cmd} `MessageBox MB_YESNO|MB_ICONQUESTION "It is highly recommended to uninstall the previous version of OpenBB Terminal - Please click Yes to proceed (Note - You will not lose your custom settings) - Or you can uninstall manually. " /SD IDYES IDYES`
!insertmacro UninstallExisting $0 $0
${If} $0 <> 0
MessageBox MB_YESNO|MB_ICONSTOP "Failed to uninstall, continue anyway?" /SD IDYES IDYES +2
Abort
${EndIf}
${EndIf}
FunctionEnd
;--------------------------------
; Section - Install App
Section "-hidden app"
SectionIn RO
SetOutPath "$INSTDIR"
${StrContains} $0 "\OpenBB" "$INSTDIR"
; Making sure here if user manually removes \openbb from their path that it still installs there
; so we dont have issues with uninstaller later.
StrCmp $0 "" notfound
; MessageBox MB_OK 'Found string $0 $INSTDIR'
SetOutPath "$INSTDIR"
Goto done
notfound:
; MessageBox MB_OK "$INSTDIR is 'bla'"
SetOutPath "$INSTDIR\OpenBB"
StrCpy $InstDir "$INSTDIR\OpenBB"
; MessageBox MB_OK 'Did not find string "$INSTDIR\OpenBB" "$installerPath"'
done:
File /r "app\*.*"
WriteRegStr HKCU "Software\${NAME}" "" $INSTDIR
WriteUninstaller "$INSTDIR\Uninstall.exe"
WriteRegStr HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "OpenBBTerminal" "OpenBB"
WriteRegStr HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "UninstallString" '"$InstDir\Uninstall.exe"'
WriteRegStr HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}" "QuietUninstallString" '"$InstDir\Uninstall.exe" /S'
SectionEnd
@@ -109,9 +240,13 @@ Section "Uninstall"
;Delete Directory
Delete '$SMPROGRAMS\${Company}\${NAME}'
;Delete Reg Key
DeleteRegKey HKCU "Software\Software\Microsoft\Windows\CurrentVersion\Uninstall\${UninstId}"
;Delete Uninstall
Delete "$INSTDIR\Uninstall.exe"
;Delete Folder
RMDir /r "$INSTDIR"
${RMDirUP} "$INSTDIR"

View File

@@ -1,5 +1,5 @@
OPENBB_LOGGING_APP_NAME=gst_packaged
OPENBB_LOGGING_COMMIT_HASH=sha:b0ef0ee6
OPENBB_LOGGING_COMMIT_HASH=sha:bbeaef4
OPENBB_ENABLE_PREDICT=false
OPENBB_ENABLE_CHECK_API=true
OPENBB_ENABLE_THOUGHTS_DAY=false

View File

@@ -0,0 +1,3 @@
from PyInstaller.utils.hooks import collect_all
datas, binaries, hiddenimports = collect_all("xgboost")

View File

@@ -1,17 +1,15 @@
# -*- mode: python ; coding: utf-8 -*-
import os
import pathlib
import subprocess
import sys
from pathlib import Path
import scipy
from dotenv import set_key
from PyInstaller.compat import is_darwin, is_win
from PyInstaller.building.api import PYZ, EXE, COLLECT
from PyInstaller.building.splash import Splash
from PyInstaller.building.api import COLLECT, EXE, PYZ
from PyInstaller.building.build_main import Analysis
# import subprocess
from PyInstaller.building.splash import Splash
from PyInstaller.compat import is_darwin, is_win
from openbb_terminal.loggers import get_commit_hash
@@ -22,21 +20,30 @@ build_type = (
)
# Local python environment packages folder
pathex = os.path.join(os.path.dirname(os.__file__), "site-packages")
venv_path = Path(sys.executable).parent.parent.resolve()
# Check if we are running in a conda environment
if is_darwin:
pathex = os.path.join(os.path.dirname(os.__file__), "site-packages")
else:
if "site-packages" in list(venv_path.iterdir()):
pathex = str(venv_path / "site-packages")
else:
pathex = str(venv_path / "lib" / "site-packages")
# Removing unused ARM64 binary
binary_to_remove = pathlib.Path(
os.path.join(pathex, "_scs_direct.cpython-39-darwin.so")
)
binary_to_remove = Path(os.path.join(pathex, "_scs_direct.cpython-39-darwin.so"))
print("Removing ARM64 Binary: _scs_direct.cpython-39-darwin.so")
binary_to_remove.unlink(missing_ok=True)
build_assets_folder = os.path.join(os.getcwd(), "build", "pyinstaller")
# Removing inspect hook
destination = pathlib.Path(
destination = Path(
os.path.join(pathex, "pyinstaller/hooks/rthooks", "pyi_rth_inspect.py")
)
print("Replacing Pyinstaller Hook: pyi_rth_inspect.py")
source = "build/pyinstaller/hooks/pyi_rth_inspect.py"
source = os.path.join(build_assets_folder, "hooks", "pyi_rth_inspect.py")
subprocess.run(["cp", source, str(destination)], check=True)
@@ -62,10 +69,6 @@ added_files = [
os.path.join(pathex, "statsmodels", "datasets"),
os.path.join("statsmodels", "datasets"),
),
(
os.path.join(pathex, "investpy", "resources"),
os.path.join("investpy", "resources"),
),
(
os.path.join(pathex, "debugpy", "_vendored"),
os.path.join("debugpy", "_vendored"),
@@ -74,6 +77,10 @@ added_files = [
(os.path.join(pathex, "blib2to3", "Grammar.txt"), "blib2to3"),
(os.path.join(pathex, "blib2to3", "PatternGrammar.txt"), "blib2to3"),
]
if is_win:
added_files.append(
(os.path.join(f"{os.path.dirname(scipy.__file__)}.libs"), "scipy.libs/"),
)
# Python libraries that are explicitly pulled into the bundle
hidden_imports = [
@@ -93,12 +100,12 @@ hidden_imports = [
"user_agent",
"vaderSentiment",
"frozendict",
"textwrap3",
"pyEX",
"feedparser",
"_sysconfigdata__darwin_darwin",
"prophet",
"debugpy",
"scipy.sparse.linalg._isolve._iterative",
]

View File

@@ -32,14 +32,8 @@ def main(ignore_files: Optional[str], ignore_commands: Optional[str]):
Commands that should not be checked
"""
if ignore_files:
ignore_file_list = ignore_files.split(",")
else:
ignore_file_list = []
if ignore_commands:
ignore_cmds_list = ignore_commands.split(",")
else:
ignore_cmds_list = []
ignore_file_list = ignore_files.split(",") if ignore_files else []
ignore_cmds_list = ignore_commands.split(",") if ignore_commands else []
path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
gst_path = os.path.join(path, "openbb_terminal/")
main_yaml_filename = os.path.join(path, "website/data/menu/main.yml")

View File

@@ -1,9 +1,9 @@
"""Check reserved command arguments in Controllers"""
import os
import sys
import glob
import os
import re
from typing import Optional, Any
import sys
from typing import Any, Optional
RESERVED_ARGS = {
"f": "file",

537
generate_sdk.py Normal file
View File

@@ -0,0 +1,537 @@
import os
import re
import subprocess
import sys
from pathlib import Path
from typing import Any, Dict, List, Optional, TextIO
from openbb_terminal.rich_config import console
from openbb_terminal.sdk_core.sdk_helpers import get_sdk_imports_text
from openbb_terminal.sdk_core.trailmap import Trailmap, get_trailmaps
REPO_ROOT = Path(__file__).parent.joinpath("openbb_terminal").resolve()
sub_names = {
"defi": "DeFi",
"disc": "Discovery",
"dd": "Due Diligence",
"onchain": "OnChain",
"ov": "Overview",
"keys": "Keys",
"forecast": "Forecasting",
"alt": "Alternative",
"crypto": "Cryptocurrency",
"ba": "Behavioral Analysis",
"ca": "Comparison Analysis",
"dps": "Darkpool Shorts",
"po": "Portfolio Optimization",
"qa": "Quantitative Analysis",
"screener": "Screener",
"sia": "Sector Industry Analysis",
"ta": "Technical Analysis",
"th": "Trading Hours",
"fa": "Fundamental Analysis",
"Oss": "Open Source Software",
"funds": "Mutual Funds",
"gov": "Government",
"ins": "Insiders",
"nft": "NFT",
}
sdk_openbb_var = """
class SDKLogger:
def __init__(self) -> None:
self.__check_initialize_logging()
def __check_initialize_logging(self):
if not cfg.LOGGING_SUPPRESS:
self.__initialize_logging()
@staticmethod
def __initialize_logging() -> None:
# pylint: disable=C0415
from openbb_terminal.core.log.generation.settings_logger import log_all_settings
from openbb_terminal.loggers import setup_logging
cfg.LOGGING_SUB_APP = "sdk"
setup_logging()
log_all_settings()
openbb = OpenBBSDK()\r\r
"""
disable_lines = "# flake8: noqa\r# pylint: disable=C0301,R0902,R0903\r"
class BuildCategoryModelClasses:
def __init__(self, trailmaps: List[Trailmap]) -> None:
self.trailmaps = trailmaps
self.categories: Dict[str, Any] = {}
self.import_modules: Dict[str, Any] = {}
self.root_modules: Dict[str, Any] = {}
self.import_cat_class = (
"from openbb_terminal.sdk_core.sdk_helpers import Category\r"
)
for tmap in self.trailmaps:
local = tmap.location_path
self.categories = self.add_todict(self.categories, local, tmap)
for folder in ["models", "controllers"]:
if not (REPO_ROOT / f"sdk_core/{folder}").exists():
(REPO_ROOT / f"sdk_core/{folder}").mkdir()
if not (REPO_ROOT / f"sdk_core/{folder}/__init__.py").exists():
with open(REPO_ROOT / f"sdk_core/{folder}/__init__.py", "w") as f:
f.write(
"# flake8: noqa\r# pylint: disable=unused-import,wrong-import-order\r\r"
)
if not (REPO_ROOT / "sdk_core/__init__.py").exists():
with open(REPO_ROOT / "sdk_core/__init__.py", "w") as f:
f.write("")
def add_todict(self, d: dict, location_path: list, tmap: Trailmap) -> dict:
"""Adds the trailmap to the dictionary. A trailmap is a path to a function
in the sdk. This function creates the dictionary paths to the function."""
if location_path[0] not in d:
d[location_path[0]] = {}
if len(location_path) > 1:
self.add_todict(d[location_path[0]], location_path[1:], tmap)
else:
d[location_path[0]][tmap.class_attr] = tmap
return d
def get_nested_dict(self, d: dict) -> dict:
"""Gets the nested dictionary of the category."""
nested_dict = {}
for k, v in d.items():
if isinstance(v, dict):
nested_dict[k] = self.get_nested_dict(v)
return nested_dict
def get_subcat_fullname(self, cat: str) -> str:
"""Gets the full category name from the shortened category name."""
if cat in sub_names:
return sub_names[cat]
return cat.title().replace(" ", "")
def check_submodules(self, category: str) -> bool:
"""Checks if a category has submodules."""
return any(isinstance(d, dict) for d in self.categories[category].values())
def write_init_imports(self, importstr: str, filestr: str) -> None:
"""Checks if a category has submodules and adds the imports to the init file."""
regex = re.compile(importstr)
with open(REPO_ROOT / filestr) as init_file:
check_init = bool(regex.search(init_file.read()))
if not check_init:
with open(REPO_ROOT / filestr, "a") as init_file:
init_file.write(f"{importstr}\r")
def write_sdk_class(
self, category: str, f: TextIO, cls_type: Optional[str] = ""
) -> None:
"""Writes the sdk class to the file.
Parameters
----------
category : str
The category name.
f : TextIO
The file to write to.
cls_type : Optional[str], optional
The class type, by default ""
"""
if category in self.root_modules:
class_name = f"{category.title()}{cls_type}(model.{category.title()}Root)"
else:
class_name = f"{category.title()}{cls_type}"
f.write(
f'class {class_name}:\r """{self.get_subcat_fullname(category)} Module.\r'
)
def write_class_property(
self, category: str, f: TextIO, subcat: Optional[str] = ""
) -> None:
"""Writes the class property to the file.
Parameters
----------
category : str
The category name.
f : TextIO
The file to write to.
subcat : Optional[str], optional
The subcategory name, by default None
"""
def_name = subcat if subcat else category
if subcat:
subcat = f" {self.get_subcat_fullname(subcat)}"
category = sub_names.get(category, category.title())
f.write(
f" @property\r def {def_name}(self):\r "
f'"""{category}{subcat} Submodule\r'
)
def write_class_attr_docs(
self,
d: dict,
f: TextIO,
module: bool = True,
sdk_root: bool = False,
trail: list = None,
) -> None:
"""Writes the class attribute docs to the category file.
Parameters
----------
d : dict
The dictionary of the category.
f : TextIO
The file to write to.
module : bool, optional
If the category is a module, by default True
sdk_root : bool, optional
If this is the sdk root file, by default False
trail : list, optional
The trail to the function, by default None
"""
add_indent = "" if module else " "
added_attributes = False
for v in d.values():
if isinstance(v, Trailmap):
if not added_attributes:
f.write(f"\r{add_indent} Attributes:\r")
added_attributes = True
for key in ["model", "view"]:
if v.func_attrs.get(key, None) and v.func_attrs[key].short_doc:
view = v.view_name if key == "view" else ""
f.write(
f"{add_indent} `{v.class_attr}{view}`: {v.func_attrs[key].short_doc}\\n\r"
)
f.write(f'{add_indent} """\r\r')
if trail:
f.write(f' _location_path = "{".".join(trail)}"\r')
if module:
f.write(" def __init__(self):\r super().__init__()\r")
elif sdk_root:
f.write(" __version__ = obbff.VERSION\r\r")
f.write(" def __init__(self):\r SDKLogger()\r")
def write_class_attributes(
self, d: dict, f: TextIO, cat: Optional[str] = None
) -> None:
"""Writes the class attributes to the category file.
Parameters
----------
d : dict
The dictionary of the category.
f : TextIO
The file to write to.
cat : Optional[str], optional
The category name, by default None
"""
add_indent = ""
missing_deps = {
"forecast": "FORECASTING_TOOLKIT",
"po": "OPTIMIZATION_TOOLKIT",
}
if cat in missing_deps:
f.write(
f"""
if not lib.{missing_deps[cat]}_ENABLED:\r
# pylint: disable=C0415
from openbb_terminal.rich_config import console
console.print(lib.{missing_deps[cat]}_WARNING)\r\r"""
)
add_indent = " "
f.write(f" if lib.{missing_deps[cat]}_ENABLED:\r")
for v in d.values():
if isinstance(v, Trailmap):
for attr, func in zip(["", v.view_name], [v.model_func, v.view_func]):
if func:
f.write(
f"{add_indent} self.{v.class_attr}{attr} = {func}\r"
)
f.write("\r\r")
def write_category(self, category: str, d: dict, f: TextIO) -> None:
"""Writes the category class to the file
Parameters
----------
category : str
The category name
d : dict
The category dictionary
f : TextIO
The file to write to
"""
subname = self.get_subcat_fullname(category)
# If this catergory has no attributes, then we don't write it to the file.
if not any(isinstance(v, Trailmap) for v in d.values()):
return
self.root_modules[category] = f"{category.title().replace(' ', '')}Root"
f.write(f"class {self.root_modules[category]}(Category):\r")
f.write(f' """{subname.title()} Module\r')
self.write_class_attr_docs(d, f, trail=[category])
self.write_class_attributes(d, f, category)
def write_nested_category(self, category: str, d: dict, f: TextIO) -> None:
"""Writes the nested category classes.
Parameters
----------
category : str
The category name
d : dict
The category dictionary
f : TextIO
The file to write to
"""
for nested_category, nested_dict in d.items():
if isinstance(nested_dict, Trailmap):
continue
subname = self.get_subcat_fullname(nested_category)
class_name = f"{category.title()}{subname.replace(' ', '')}(Category)"
f.write(f'class {class_name}:\r """{subname} Module.\r')
self.write_nested_submodule_docs(nested_dict, f)
if isinstance(nested_dict, dict):
self.write_class_attr_docs(
nested_dict, f, trail=[category, nested_category]
)
self.write_class_attributes(nested_dict, f, nested_category)
def write_submodule_doc(
self, k: str, f: TextIO, added: bool = False, indent: bool = False
) -> None:
"""Writes the submodules to the class docstring.
Parameters
----------
d : dict
The category dictionary
f : TextIO
The file to write to
added : bool, optional
Whether or not "Submodules:" have been added to the docstring, by default False
indent : bool, optional
Whether or not to add an indent to the docstring, by default False
"""
add_indent = " " if indent else ""
if not added:
f.write("\r Submodules:\r")
subcat_name = self.get_subcat_fullname(k)
f.write(f"{add_indent} `{k}`: {subcat_name} Module\r")
def write_nested_submodule_docs(
self, nested_dict: dict, f: TextIO, indent: bool = False
) -> None:
"""Writes the nested submodule docs to the class docstring.
Parameters
----------
nested_dict : dict
The nested dictionary
f : TextIO
The file to write to
indent : bool, optional
Whether or not to add an indent to the docstring, by default False
"""
added = False
nested_subcat = self.get_nested_dict(nested_dict)
if nested_subcat:
for k in nested_subcat:
if isinstance(nested_dict[k], Trailmap):
continue
self.write_submodule_doc(k, f, added, indent)
if not added:
added = True
def write_category_file(self, category: str, d: dict) -> None:
"""Writes the category file. This is the file that contains the categories
and subcategories of the sdk.
Parameters
----------
category : str
The category name
d : dict
The category dictionary
"""
with open(REPO_ROOT / f"sdk_core/models/{category}_sdk_model.py", "w") as f:
import_cat_class = self.import_cat_class
if category in self.root_modules:
import_cat_class = ""
category = self.root_modules[category]
f.write(
f"{disable_lines}{import_cat_class}import openbb_terminal.sdk_core.sdk_init as lib\r\r\r"
)
if category not in self.root_modules and any(
isinstance(v, Trailmap) for v in d.values()
):
self.write_init_imports(
f"from .{category}_sdk_model import {category.title()}Root",
"sdk_core/models/__init__.py",
)
self.write_category(category, d, f)
self.write_nested_category(category, d, f)
f.seek(f.tell() - 2, os.SEEK_SET)
f.truncate()
def write_sdk_controller_file(self, category: str, d: dict) -> None:
"""Writes the sdk controller file. This is the file that contains the
controller classes for the sdk.
Parameters
----------
category : str
The category name
d : dict
The category dictionary
"""
added_init_imports = []
with open(
REPO_ROOT / f"sdk_core/controllers/{category}_sdk_controller.py", "w"
) as f:
f.write(
f"{disable_lines}from openbb_terminal.sdk_core.models "
f"import {category}_sdk_model as model\r\r\r"
)
if category not in added_init_imports and any(
isinstance(v, dict) for v in d.values()
):
self.write_init_imports(
f"from .{category}_sdk_controller import {category.title()}Controller",
"sdk_core/controllers/__init__.py",
)
added_init_imports.append(category)
self.write_sdk_class(category, f, "Controller")
self.write_nested_submodule_docs(self.categories[category], f, True)
self.write_class_attr_docs(d, f, False)
for subcategory in self.categories[category]:
if isinstance(d[subcategory], Trailmap):
continue
self.write_class_property(category, f, subcategory)
self.write_nested_submodule_docs(d[subcategory], f, True)
self.write_class_attr_docs(d[subcategory], f, False)
f.write(
f" return model.{category.title()}"
f"{self.get_subcat_fullname(subcategory).replace(' ', '')}()\r\r"
)
f.seek(f.tell() - 1, os.SEEK_SET)
f.truncate()
def write_sdk_file(self) -> None:
"""Writes the main sdk file. This is the file that we initialize the SDK with openbb."""
with open(REPO_ROOT / "sdk.py", "w") as f:
f.write(
f'{get_sdk_imports_text()}class OpenBBSDK:\r """OpenBB SDK Class.\r'
)
root_attrs = self.categories.pop("root")
if root_attrs:
self.write_class_attr_docs(root_attrs, f, False, True)
self.write_class_attributes(root_attrs, f)
for category in self.categories:
self.write_class_property(category, f)
self.write_nested_submodule_docs(self.categories[category], f, True)
self.write_class_attr_docs(self.categories[category], f, False)
if self.check_submodules(category):
f.write(f" return ctrl.{category.title()}Controller()\r\r")
else:
f.write(f" return model.{self.root_modules[category]}()\r\r")
f.write("\r".join(sdk_openbb_var.splitlines()))
def build(self) -> None:
"""Builds the SDK."""
for path in ["sdk_core/models", "sdk_core/controllers"]:
for file in (REPO_ROOT / path).glob("*.py"):
if file.name == "__init__.py":
with open(file, "w") as f:
f.write(
"# flake8: noqa\r"
"# pylint: disable=unused-import,wrong-import-order\r\r"
)
continue
file.unlink()
for category, d in self.categories.items():
if isinstance(d, Trailmap) or category == "root":
continue
self.write_category_file(category, d)
if self.check_submodules(category):
self.write_sdk_controller_file(category, d)
self.write_sdk_file()
for path in ["sdk.py", "sdk_core", "sdk_core/models", "sdk_core/controllers"]:
for file in (REPO_ROOT / path).glob("*.py"):
with open(file, "rb") as f:
content = f.read()
with open(file, "wb") as f:
f.write(content.replace(b"\r", b"\n"))
# We run black to make sure the code is formatted correctly
subprocess.check_call(["black", "openbb_terminal"])
def generate_sdk(sort: bool = False) -> None:
"""Main function to generate the SDK.
Parameters
----------
sort : bool, optional
Whether to sort the CSVs, by default False
"""
trailmaps = get_trailmaps(sort)
console.print("[yellow]Generating SDK...[/]")
BuildCategoryModelClasses(trailmaps).build()
console.print("[green]SDK Generated Successfully.[/]")
return
if __name__ == "__main__":
sort_csv = False
if len(sys.argv) > 1:
if sys.argv[1] == "sort":
sort_csv = True
console.print("\n\n[bright_magenta]Sorting CSV...[/]\n")
else:
console.print("[red]Invalid argument.\n Accepted arguments: sort[/]")
generate_sdk(sort_csv)

55
jupyterlab/README.md vendored
View File

@@ -1,55 +0,0 @@
# Jupyter Ecosystem integration
The Jupyter ecosystem has created Open Source tools that have become the de-facto
standard for data related tasks.
This folder contains source code for a bunch of tools that help using the functionality
of the terminal in connection with Jupyter:
1. Jupyter Lab Extensions for using OpenBB Terminal
## 1. Jupyter Lab Extensions for using OpenBB Terminal
Documentation, OpenBB and GOpenBB-settings are 3 Jupyter Lab extensions that illustrate how
the terminal can be integrated with Jupyter Lab based IDEs.
_NOTE: The extensions should be considered prototypes and are not production-ready._
1. Only bash is supported (only macOS, Linux and WSL). No support for Windows powershell or command prompt.
2. The input values are not escaped
### Installation
To install the Terminal Launcher and the Settings Extensions run the following commands from the [root folder of the project](/):
```bash
pip install jupyterlab/openbb
pip install jupyterlab/openbb-settings
pip install jupyterlab/documentation
jupyter labextension install jupyterlab/openbb
jupyter labextension install jupyterlab/openbb-settings
jupyter labextension install jupyterlab/documentation
```
### Development setup
In this section `openbb` extension will be used as an example.
- In one terminal window `cd` into the launcher extension folder and build the extension:
```bash
cd openbb
jlpm
pip install -e .
jlpm run build
jupyter labextension develop . --overwrite
jlpm run watch
```
- In the second tab run jupyter lab
```bash
jupyter lab
```
---

View File

@@ -1,5 +0,0 @@
node_modules
dist
coverage
**/*.d.ts
ui-tests

View File

@@ -1,53 +0,0 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:jsdoc/recommended',
'plugin:prettier/recommended',
'plugin:react/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint', 'jsdoc'],
rules: {
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'interface',
format: ['PascalCase'],
custom: {
regex: '^I[A-Z]',
match: true,
},
},
],
'@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/quotes': [
'error',
'single',
{ avoidEscape: true, allowTemplateLiterals: false },
],
curly: ['error', 'all'],
eqeqeq: 'error',
'jsdoc/require-param-type': 'off',
'jsdoc/require-property-type': 'off',
'jsdoc/require-returns-type': 'off',
'jsdoc/no-types': 'warn',
'prefer-arrow-callback': 'error',
},
settings: {
jsdoc: {
mode: 'typescript',
},
react: {
version: 'detect',
},
},
};

View File

@@ -1,22 +0,0 @@
include LICENSE
include README.md
include pyproject.toml
include jupyter-config/openbb_terminal_documentation.json
include package.json
include ts*.json
graft openbb_terminal_documentation/labextension
# Javascript files
graft src
graft style
prune **/node_modules
prune lib
# Patterns to exclude from any directory
global-exclude *~
global-exclude *.pyc
global-exclude *.pyo
global-exclude .git
global-exclude .ipynb_checkpoints

View File

@@ -1,17 +0,0 @@
# OpenBB Terminal Documentation
This extensions adds a button into the OpenBB Terminal category of the Jupyter Lab launcher panel.
## Install, Use and Develop
```bash
pip install -e .
jlpm
jlpm run build:prod
jupyter labextension install .
# Rebuild Typescript source after making changes
jlpm build
# Rebuild JupyterLab after making any changes
jupyter lab build
```

View File

@@ -1,3 +0,0 @@
# Making a new release of gamestonk-settings
Check out the [workflow documentation](https://github.com/jupyter-server/jupyter_releaser#typical-workflow) for information.

View File

@@ -1,5 +0,0 @@
{
"packageManager": "python",
"packageName": "openbb_terminal_documentation",
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package openbb_terminal_documentation"
}

View File

@@ -1,87 +0,0 @@
{
"name": "@gamestonk/documentation",
"version": "0.1.0",
"description": "Gamestonk terminal documentation",
"keywords": [
"jupyter",
"jupyterlab",
"jupyterlab-extension"
],
"homepage": "https://github.com/OpenBB-finance/OpenBBTerminal",
"bugs": {
"url": "https://github.com/OpenBB-finance/OpenBBTerminal/issues"
},
"license": "MIT",
"author": {
"name": "Project Jupyter Contributors",
"email": "dro.lopes@campus.fct.unl.pt"
},
"files": [
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
"style/**/*.{css,eot,js,gif,html,jpg,json,png,svg,woff2,ttf}",
"schema/**/*.json"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
"style": "style/index.css",
"repository": {
"type": "git",
"url": "https://github.com/OpenBB-finance/OpenBBTerminal.git"
},
"scripts": {
"build": "jlpm run build:lib && jlpm run build:labextension:dev",
"build:all": "jlpm run build:lib && jlpm run build:labextension",
"build:labextension": "jupyter labextension build .",
"build:labextension:dev": "jupyter labextension build --development True .",
"build:lib": "tsc",
"build:prod": "jlpm run clean && jlpm run build:lib && jlpm run build:labextension",
"clean": "jlpm run clean:lib",
"clean:all": "jlpm run clean:lib && jlpm run clean:labextension",
"clean:labextension": "rimraf openbb_terminal_documentation/labextension",
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
"eslint": "eslint . --ext .ts,.tsx --fix",
"eslint:check": "eslint . --ext .ts,.tsx",
"install:extension": "jlpm run build",
"prepare": "jlpm run clean && jlpm run build:prod",
"watch": "run-p watch:src watch:labextension",
"watch:labextension": "jupyter labextension watch .",
"watch:src": "tsc -w"
},
"dependencies": {
"@jupyterlab/application": "^3.2.8",
"@jupyterlab/launcher": "^3.2.8",
"@jupyterlab/mainmenu": "^3.2.8",
"marked": "^4.0.10"
},
"devDependencies": {
"@jupyterlab/builder": "^3.2.8",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"eslint": "^8.7.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-jsdoc": "^37.6.3",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
"typescript": "<4.4"
},
"resolutions": {
"json-schema": "^0.4.0",
"marked": "^4.0.10",
"got": "^11.8.5",
"jpeg-js": "^0.4.4"
},
"sideEffects": [
"style/*.css",
"style/*.svg",
"style/index.js"
],
"jupyterlab": {
"extension": true,
"outputDir": "openbb_terminal_documentation/labextension",
"schemaDir": "schema"
},
"styleModule": "style/index.js"
}

View File

@@ -1,17 +0,0 @@
[build-system]
requires = ["jupyter_packaging~=0.10,<2", "jupyterlab~=3.1"]
build-backend = "jupyter_packaging.build_api"
[tool.jupyter-packaging.options]
skip-if-exists = ["openbb_terminal_documentation/labextension/static/style.js"]
ensured-targets = ["openbb_terminal_documentation/labextension/static/style.js", "openbb_terminal_documentation/labextension/package.json"]
[tool.jupyter-packaging.builder]
factory = "jupyter_packaging.npm_builder"
[tool.jupyter-packaging.build-args]
build_cmd = "build:prod"
npm = ["jlpm"]
[tool.check-manifest]
ignore = ["openbb_terminal_documentation/labextension/**", "yarn.lock", ".*", "package-lock.json"]

View File

@@ -1,25 +0,0 @@
{
"title": "OpenBB Terminal Documentation",
"description": "OpenBB Terminal Documentation.",
"jupyter.lab.menus": {
"main": [
{
"id": "jp-mainmenu-file",
"items": [
{
"type": "submenu",
"id": "jp-mainmenu-file-new",
"items": [
{
"command": "gamestonk:documentation",
"rank": 30
}
]
}
]
}
]
},
"additionalProperties": false,
"type": "object"
}

View File

@@ -1,86 +0,0 @@
"""
openbb_terminal_documentation setup
"""
import json
import sys
from pathlib import Path
import setuptools
HERE = Path(__file__).parent.resolve()
# The name of the project
name = "openbb_terminal_documentation"
lab_path = HERE / name.replace("-", "_") / "labextension"
# Representative files that should exist after a successful build
ensured_targets = [str(lab_path / "package.json"), str(lab_path / "static/style.js")]
labext_name = "@gamestonk/documentation"
data_files_spec = [
(
"share/jupyter/labextensions/%s" % labext_name,
str(lab_path.relative_to(HERE)),
"**",
),
("share/jupyter/labextensions/%s" % labext_name, ".", "install.json"),
]
long_description = (HERE / "README.md").read_text()
# Get the package info from package.json
pkg_json = json.loads((HERE / "package.json").read_bytes())
setup_args = dict(
name=name,
version=pkg_json["version"],
url=pkg_json["homepage"],
author=pkg_json["author"]["name"],
author_email=pkg_json["author"]["email"],
description=pkg_json["description"],
license=pkg_json["license"],
long_description=long_description,
long_description_content_type="text/markdown",
packages=setuptools.find_packages(),
install_requires=[],
zip_safe=False,
include_package_data=True,
python_requires=">=3.6",
platforms="Linux, Mac OS X, Windows",
keywords=["Jupyter", "JupyterLab", "JupyterLab3"],
classifiers=[
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Framework :: Jupyter",
],
)
try:
from jupyter_packaging import wrap_installers, npm_builder, get_data_files
post_develop = npm_builder(
build_cmd="install:extension", source_dir="src", build_dir=lab_path
)
setup_args["cmdclass"] = wrap_installers(
post_develop=post_develop, ensured_targets=ensured_targets
)
setup_args["data_files"] = get_data_files(data_files_spec)
except ImportError as e:
import logging
logging.basicConfig(format="%(levelname)s: %(message)s")
logging.warning(
"Build tool `jupyter-packaging` is missing. Install it with pip or conda."
)
if not ("--name" in sys.argv or "--version" in sys.argv):
raise e
if __name__ == "__main__":
setuptools.setup(**setup_args)

View File

@@ -1,77 +0,0 @@
import {
JupyterFrontEnd,
JupyterFrontEndPlugin,
} from '@jupyterlab/application';
import { ICommandPalette } from '@jupyterlab/apputils';
import { ILauncher } from '@jupyterlab/launcher';
import { IMainMenu } from "@jupyterlab/mainmenu";
import { LabIcon } from '@jupyterlab/ui-components';
import docsIconStr from '../style/docs.svg';
const CATEGORY = "OpenBB Terminal";
namespace CommandIDs {
export const createNew = 'jlab-examples:create-new-python-file';
}
const extension: JupyterFrontEndPlugin<void> = {
id: 'documentation',
autoStart: true,
optional: [ILauncher, ICommandPalette],
activate: (
app: JupyterFrontEnd,
launcher: ILauncher | null,
menu: IMainMenu | null,
palette: ICommandPalette | null
) => {
const { commands } = app;
const command = CommandIDs.createNew;
const icon = new LabIcon({
name: 'documentation:docs-icon',
svgstr: docsIconStr,
});
commands.addCommand(command, {
label: 'Gamestonk Documentation',
icon: icon,
execute: (args: any) => {
window.open(
'https://openbb-finance.github.io/OpenBBTerminal/',
'_blank'
);
},
});
// Add the command to the launcher
if (launcher) {
launcher.add({
command,
category: CATEGORY,
rank: 3,
});
}
// Add the command to the palette
if (palette) {
palette.addItem({
command,
args: { isPalette: true },
category: CATEGORY,
});
}
// Add the command to the menu
if (menu) {
menu.fileMenu.newMenu.addGroup([{ command }], 30);
}
console.log("Added Gamestonk Settings Extension.");
},
};
export default extension;

View File

@@ -1,4 +0,0 @@
declare module '*.svg' {
const value: string;
export default value;
}

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="256px" height="256px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>docs</title>
<g id="docs" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Rectangle" fill="#424242" x="15" y="18" width="225" height="220"></rect>
<path d="M128.5,67.5 C121.320298,67.5 115.5,73.3202983 115.5,80.5 C115.5,87.6797017 121.320298,93.5 128.5,93.5 C135.679702,93.5 141.5,87.6797017 141.5,80.5 C141.5,77.0521856 140.130361,73.7455848 137.692388,71.3076118 C135.254415,68.8696389 131.947814,67.5 128.5,67.5 Z" id="Path" stroke="#FFFFFF" stroke-width="10" fill-rule="nonzero"></path>
<rect id="Rectangle" fill="#FFFFFF" x="115.652174" y="108" width="25.7391304" height="74" rx="12"></rect>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 866 B

View File

@@ -1 +0,0 @@
@import url('base.css');

View File

@@ -1 +0,0 @@
import './base.css';

View File

@@ -1,24 +0,0 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"composite": true,
"declaration": true,
"esModuleInterop": true,
"incremental": true,
"jsx": "react",
"module": "esnext",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"preserveWatchOutput": true,
"resolveJsonModule": true,
"outDir": "lib",
"rootDir": "src",
"strict": true,
"strictNullChecks": false,
"target": "es2017",
"types": []
},
"include": ["src/*"]
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +0,0 @@
node_modules
dist
coverage
**/*.d.ts
ui-tests

View File

@@ -1,54 +0,0 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:jsdoc/recommended',
'plugin:prettier/recommended',
'plugin:react/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint', 'jsdoc'],
rules: {
"react/react-in-jsx-scope": "off",
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'interface',
format: ['PascalCase'],
custom: {
regex: '^I[A-Z]',
match: true,
},
},
],
'@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/quotes': [
'error',
'double',
{ avoidEscape: true, allowTemplateLiterals: false },
],
curly: ['error', 'all'],
eqeqeq: 'error',
'jsdoc/require-param-type': 'off',
'jsdoc/require-property-type': 'off',
'jsdoc/require-returns-type': 'off',
'jsdoc/no-types': 'warn',
'prefer-arrow-callback': 'error',
},
settings: {
jsdoc: {
mode: 'typescript',
},
react: {
version: 'detect',
},
},
};

View File

@@ -1,22 +0,0 @@
include LICENSE
include README.md
include pyproject.toml
include jupyter-config/openbb_terminal_settings.json
include package.json
include ts*.json
graft openbb_terminal_settings/labextension
# Javascript files
graft src
graft style
prune **/node_modules
prune lib
# Patterns to exclude from any directory
global-exclude *~
global-exclude *.pyc
global-exclude *.pyo
global-exclude .git
global-exclude .ipynb_checkpoints

View File

@@ -1,17 +0,0 @@
# OpenBB Terminal Settings Menu
This extensions allows the user to set API keys and feature flags for the OpenBB Terminal
## Install, Use and Develop
```bash
pip install -e .
jlpm
jlpm run build:prod
jupyter labextension install .
# Rebuild Typescript source after making changes
jlpm build
# Rebuild JupyterLab after making any changes
jupyter lab build
```

View File

@@ -1,3 +0,0 @@
# Making a new release of gamestonk-settings
Check out the [workflow documentation](https://github.com/jupyter-server/jupyter_releaser#typical-workflow) for information.

View File

@@ -1,5 +0,0 @@
{
"packageManager": "python",
"packageName": "openbb_terminal_settings",
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package openbb_terminal_settings"
}

View File

@@ -1,13 +0,0 @@
import json
import os.path as osp
from ._version import __version__ # noqa: F401
HERE = osp.abspath(osp.dirname(__file__))
with open(osp.join(HERE, "labextension", "package.json")) as fid:
data = json.load(fid)
def _jupyter_labextension_paths():
return [{"src": "labextension", "dest": data["name"]}]

View File

@@ -1,2 +0,0 @@
version_info = (0, 1, 0)
__version__ = ".".join(map(str, version_info))

View File

@@ -1,89 +0,0 @@
{
"name": "@gamestonk/settings",
"version": "0.1.0",
"description": "Gamestonk settings launcher",
"keywords": [
"jupyter",
"jupyterlab",
"jupyterlab-extension"
],
"homepage": "https://github.com/OpenBB-finance/OpenBBTerminal",
"bugs": {
"url": "https://github.com/OpenBB-finance/OpenBBTerminal/issues"
},
"license": "MIT",
"author": {
"name": "Gamestonk Contributors",
"email": "dro.lopes@campus.fct.unl.pt"
},
"files": [
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
"style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
"style/index.js",
"schema/**/*.json"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
"style": "style/index.css",
"repository": {
"type": "git",
"url": "https://github.com/jupyterlab/extension-examples.git"
},
"scripts": {
"build": "jlpm run build:lib && jlpm run build:labextension:dev",
"build:all": "jlpm run build:lib && jlpm run build:labextension",
"build:labextension": "jupyter labextension build .",
"build:labextension:dev": "jupyter labextension build --development True .",
"build:lib": "tsc",
"build:prod": "jlpm run clean && jlpm run build:lib && jlpm run build:labextension",
"clean": "jlpm run clean:lib",
"clean:all": "jlpm run clean:lib && jlpm run clean:labextension",
"clean:labextension": "rimraf openbb_terminal_settings/labextension",
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
"eslint": "eslint . --ext .ts,.tsx --fix",
"eslint:check": "eslint . --ext .ts,.tsx",
"install:extension": "jlpm run build",
"prepare": "jlpm run clean && jlpm run build:prod",
"watch": "run-p watch:src watch:labextension",
"watch:labextension": "jupyter labextension watch .",
"watch:src": "tsc -w"
},
"dependencies": {
"@jupyterlab/application": "^3.2.8",
"@jupyterlab/launcher": "^3.2.8",
"@jupyterlab/mainmenu": "^3.2.8",
"@jupyterlab/settingregistry": "^3.2.8",
"@jupyterlab/ui-components": "^3.2.8",
"marked": "^4.0.10"
},
"devDependencies": {
"@jupyterlab/builder": "^3.2.8",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"eslint": "^8.7.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-jsdoc": "^37.6.3",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
"typescript": "<4.4"
},
"resolutions": {
"json-schema": "^0.4.0",
"marked": "^4.0.10",
"got": "^11.8.5",
"jpeg-js": "^0.4.4"
},
"sideEffects": [
"style/*.css",
"style/index.js"
],
"jupyterlab": {
"extension": true,
"outputDir": "openbb_terminal_settings/labextension",
"schemaDir": "schema"
},
"styleModule": "style/index.js"
}

View File

@@ -1,17 +0,0 @@
[build-system]
requires = ["jupyter_packaging~=0.10,<2", "jupyterlab~=3.1"]
build-backend = "jupyter_packaging.build_api"
[tool.jupyter-packaging.options]
skip-if-exists = ["openbb_terminal_settings/labextension/static/style.js"]
ensured-targets = ["openbb_terminal_settings/labextension/static/style.js", "openbb_terminal_settings/labextension/package.json"]
[tool.jupyter-packaging.builder]
factory = "jupyter_packaging.npm_builder"
[tool.jupyter-packaging.build-args]
build_cmd = "build:prod"
npm = ["jlpm"]
[tool.check-manifest]
ignore = ["openbb_terminal_settings/labextension/**", "yarn.lock", ".*", "package-lock.json"]

View File

@@ -1,392 +0,0 @@
{
"title": "OpenBB settings",
"description": "Settings for OpenBB Terminal extension.",
"type": "object",
"properties":
{
"FEATURE_FLAGS":
{
"title": "Feature flags",
"description": "Feature flags for the OpenBB Terminal.",
"default":
{
"OPENBB_USE_CLEAR_AFTER_CMD":
{
"type": "bool",
"form": "checkbox",
"title": "Clear after command",
"description": "Use clear console after each command",
"default": false,
"value": ""
},
"OPENBB_USE_FLAIR":
{
"type": "string",
"form": "text",
"title": "Console flair",
"description": "Select console flair (choose from config_terminal.py list)",
"default": "openbb",
"value": ""
},
"OPENBB_USE_ION":
{
"type": "bool",
"form": "checkbox",
"title": "Interactive charts",
"description": "Enable interactive matplotlib",
"default": true,
"value": ""
},
"OPENBB_USE_PROMPT_TOOLKIT":
{
"type": "bool",
"form": "checkbox",
"title": "Autocomplete",
"description": "Enable Prompt Toolkit",
"default": true,
"value": ""
},
"OPENBB_ENABLE_PREDICT":
{
"type": "bool",
"form": "checkbox",
"title": "Prediction menu",
"description": "Enable Prediction features",
"default": true,
"value": ""
},
"OPENBB_USE_PLOT_AUTOSCALING":
{
"type": "bool",
"form": "checkbox",
"title": "Plot autoscaling",
"description": "Enable plot autoscaling",
"default": false,
"value": ""
},
"OPENBB_ENABLE_THOUGHTS_DAY":
{
"type": "bool",
"form": "checkbox",
"title": "Thoughts of the day",
"description": "Enable thoughts of the day",
"default": false,
"value": ""
},
"OPENBB_ENABLE_QUICK_EXIT":
{
"type": "bool",
"form": "checkbox",
"title": "Quick exit",
"description": "Quick exit for testing",
"default": false,
"value": ""
}
}
},
"APP_SETTINGS":
{
"title": "General",
"description": "Application settings for the OpenBB Terminal.",
"default":
{
"PAPERMILL_NOTEBOOK_REPORT_PORT":
{
"type": "number",
"form": "number",
"title": "Papermill port",
"description": "Papermill port",
"default": 8892,
"value": ""
},
"PYTHON_BINARY":
{
"type": "string",
"form": "text",
"title": "Python executable",
"description": "Path to the python in your custom environment",
"default": "python",
"value": ""
},
"TERMINAL_PATH":
{
"type": "string",
"form": "text",
"title": "Terminal path",
"description": "Path to the terminal.py",
"default": "terminal.py",
"value": ""
}
}
},
"API_KEYS":
{
"title": "API Keys",
"description": "Access credentials for data providers.",
"default":
{
"OPENBB_API_KEY_ALPHAVANTAGE":
{
"type": "string",
"form": "password",
"title": "Alphavantage",
"description": "https://www.alphavantage.co",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_KEY_FINANCIALMODELINGPREP":
{
"type": "string",
"form": "password",
"title": "financialmodelingprep",
"description": "https://financialmodelingprep.com/developer",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_KEY_QUANDL":
{
"type": "string",
"form": "password",
"title": "quandl",
"description": "https://www.quandl.com/tools/api",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_REDDIT_CLIENT_ID":
{
"type": "string",
"form": "password",
"title": "Reddit client ID",
"description": "https://www.reddit.com/prefs/apps",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_REDDIT_CLIENT_SECRET":
{
"type": "string",
"form": "password",
"title": "Reddit client secret",
"description": "https://www.reddit.com/prefs/apps",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_REDDIT_USERNAME":
{
"type": "string",
"form": "password",
"title": "Reddit username",
"description": "https://www.reddit.com/prefs/apps",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_REDDIT_USER_AGENT":
{
"type": "string",
"form": "password",
"title": "Reddit user agent",
"description": "https://www.reddit.com/prefs/apps",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_REDDIT_PASSWORD":
{
"type": "string",
"form": "password",
"title": "Reddit password",
"description": "https://www.reddit.com/prefs/apps",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_POLYGON_KEY":
{
"type": "string",
"form": "password",
"title": "Polygon",
"description": "https://polygon.io",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_TWITTER_KEY":
{
"type": "string",
"form": "password",
"title": "Twitter key",
"description": "https://developer.twitter.com",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_TWITTER_SECRET_KEY":
{
"type": "string",
"form": "password",
"title": "Twitter secret",
"description": "https://developer.twitter.com",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_TWITTER_BEARER_TOKEN":
{
"type": "string",
"form": "password",
"title": "Twitter token",
"description": "https://developer.twitter.com",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_FRED_KEY":
{
"type": "string",
"form": "password",
"title": "FRED",
"description": "https://fred.stlouisfed.org/docs/api/api_key.html",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_NEWS_TOKEN":
{
"type": "string",
"form": "password",
"title": "NewsAPI",
"description": "https://newsapi.org",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_RH_USERNAME":
{
"type": "string",
"form": "password",
"title": "Robinhood username",
"description": "Robinhood",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_RH_PASSWORD":
{
"type": "string",
"form": "password",
"title": "Robinhood password",
"description": "Robinhood",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_DG_USERNAME":
{
"type": "string",
"form": "password",
"title": "Degiro username",
"description": "Degiro",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_DG_PASSWORD":
{
"type": "string",
"form": "password",
"title": "Degiro password",
"description": "Degiro",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_DG_TOTP_SECRET":
{
"type": "string",
"form": "password",
"title": "Degiro secret",
"description": "Degiro",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_OANDA_ACCOUNT_TYPE":
{
"type": "string",
"form": "password",
"title": "Oanda account type",
"description": "https://developer.oanda.com",
"default": "practice",
"value": ""
},
"OPENBB_OANDA_ACCOUNT":
{
"type": "string",
"form": "password",
"title": "Oanda account",
"description": "https://developer.oanda.com",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_OANDA_TOKEN":
{
"type": "string",
"form": "password",
"title": "Oanda token",
"description": "https://developer.oanda.com",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_TRADIER_TOKEN":
{
"type": "string",
"form": "password",
"title": "Tradier token",
"description": "https://tradier.com/products/market-data-api",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_CMC_KEY":
{
"type": "string",
"form": "password",
"title": "Coinmarketcap key",
"description": "https://coinmarketcap.com/api/",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_BINANCE_KEY":
{
"type": "string",
"form": "password",
"title": "Binance key",
"description": "https://www.binance.com/en/",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_BINANCE_SECRET":
{
"type": "string",
"form": "password",
"title": "Binance secret",
"description": "Binance secret",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_FINNHUB_KEY":
{
"type": "string",
"form": "password",
"title": "Finnhub key",
"description": "https://finnhub.io",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_IEX_TOKEN":
{
"type": "string",
"form": "password",
"title": "IEX Cloud key",
"description": "https://iexcloud.io",
"default": "REPLACE_ME",
"value": ""
},
"OPENBB_API_SENTIMENTINVESTOR_TOKEN":
{
"type": "string",
"form": "password",
"title": "Sentimentinvestor token",
"description": "https://www.sentimentinvestor.com",
"default": "REPLACE_ME",
"value": ""
}
}
}
}
}

View File

@@ -1,86 +0,0 @@
"""
openbb_terminal_settings setup
"""
import json
import sys
from pathlib import Path
import setuptools
HERE = Path(__file__).parent.resolve()
# The name of the project
name = "openbb_terminal_settings"
lab_path = HERE / name.replace("-", "_") / "labextension"
# Representative files that should exist after a successful build
ensured_targets = [str(lab_path / "package.json"), str(lab_path / "static/style.js")]
labext_name = "@gamestonk/settings"
data_files_spec = [
(
"share/jupyter/labextensions/%s" % labext_name,
str(lab_path.relative_to(HERE)),
"**",
),
("share/jupyter/labextensions/%s" % labext_name, ".", "install.json"),
]
long_description = (HERE / "README.md").read_text()
# Get the package info from package.json
pkg_json = json.loads((HERE / "package.json").read_bytes())
setup_args = dict(
name=name,
version=pkg_json["version"],
url=pkg_json["homepage"],
author=pkg_json["author"]["name"],
author_email=pkg_json["author"]["email"],
description=pkg_json["description"],
license=pkg_json["license"],
long_description=long_description,
long_description_content_type="text/markdown",
packages=setuptools.find_packages(),
install_requires=[],
zip_safe=False,
include_package_data=True,
python_requires=">=3.6",
platforms="Linux, Mac OS X, Windows",
keywords=["Jupyter", "JupyterLab", "JupyterLab3"],
classifiers=[
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Framework :: Jupyter",
],
)
try:
from jupyter_packaging import wrap_installers, npm_builder, get_data_files
post_develop = npm_builder(
build_cmd="install:extension", source_dir="src", build_dir=lab_path
)
setup_args["cmdclass"] = wrap_installers(
post_develop=post_develop, ensured_targets=ensured_targets
)
setup_args["data_files"] = get_data_files(data_files_spec)
except ImportError as e:
import logging
logging.basicConfig(format="%(levelname)s: %(message)s")
logging.warning(
"Build tool `jupyter-packaging` is missing. Install it with pip or conda."
)
if not ("--name" in sys.argv or "--version" in sys.argv):
raise e
if __name__ == "__main__":
setuptools.setup(**setup_args)

View File

@@ -1,58 +0,0 @@
import { useState } from "react";
/**
* Generic input form
*
* @class FormInput (name)
* @param {} arg1 Arguments
* @param {} arg1.itemParent The item parent
* @param {} arg1.index The item index
* @param {} arg1.onChangeParent On change parent function
* @returns {} Gemeric input form
*/
export default function FormInput({
itemParent,
index,
onChangeParent,
}: {
itemParent: any;
index: number;
onChangeParent: any;
}): any {
const [item, setItem] = useState({
key: itemParent.key,
value: itemParent.value,
});
const onChange = (event: any) => {
const newValue =
event.target.type === "checkbox"
? event.target.checked
: event.target.value;
setItem((prevState) => {
const value = item.value;
value.value = newValue;
const newItem = { ...prevState, value: value };
onChangeParent(index, newItem);
return newItem;
});
};
return (
<>
<label className="inputFieldLabel">{item.value.title}</label>
<input
className={item.value.title}
type={item.value.form}
checked={
item.value.form === "checkbox"
? item.value.value === ""
? item.value.default
: item.value.value
: false
}
value={item.value.value === "" ? item.value.default : item.value.value}
onChange={onChange}
/>
</>
);
}

View File

@@ -1,90 +0,0 @@
import {
JupyterFrontEnd,
JupyterFrontEndPlugin,
} from "@jupyterlab/application";
import { ICommandPalette } from "@jupyterlab/apputils";
import { MainAreaWidget } from "@jupyterlab/apputils";
import { ILauncher } from "@jupyterlab/launcher";
import { ISettingRegistry } from "@jupyterlab/settingregistry";
import { IMainMenu } from "@jupyterlab/mainmenu";
import { LabIcon } from "@jupyterlab/ui-components";
import svgIconStr from "../style/settings-icon.svg";
import { TerminalSettingsWidget } from "./widget";
const CATEGORY = "OpenBB Terminal";
/**
* The command IDs used by the Gamestonk Settings plugin.
*/
namespace CommandIDs {
export const create = "gamestonk:settings";
}
/**
* Initialization data for the Gamestonk Settings extension.
*/
const extension: JupyterFrontEndPlugin<void> = {
id: "gst:settings",
autoStart: true,
optional: [ILauncher, IMainMenu, ICommandPalette, ISettingRegistry],
activate: async (
app: JupyterFrontEnd,
launcher: ILauncher | null,
menu: IMainMenu | null,
palette: ICommandPalette | null,
settings: ISettingRegistry
) => {
const { commands } = app;
const command = CommandIDs.create;
const icon = new LabIcon({
name: "launcher:gst-settings-icon",
svgstr: svgIconStr,
});
const s = await settings.load("@gamestonk/settings:settings");
commands.addCommand(command, {
caption: "Edit OpenBB Terminal Settings",
label: "Settings",
icon: (args) => (args["isPalette"] ? null : icon),
execute: () => {
const content = new TerminalSettingsWidget(s);
const widget = new MainAreaWidget<TerminalSettingsWidget>({ content });
widget.title.label = "Gamestonk Settings";
widget.title.icon = icon;
app.shell.add(widget, "main", { activate: true, mode: "split-right" });
},
});
if (launcher) {
launcher.add({
command,
category: CATEGORY,
rank: 2,
});
}
// Add the command to the palette
if (palette) {
palette.addItem({
command,
args: { isPalette: true },
category: CATEGORY,
});
}
// Add the command to the menu
if (menu) {
menu.fileMenu.newMenu.addGroup([{ command }], 30);
}
console.log("Added Gamestonk Settings Extension.");
},
};
export default extension;

View File

@@ -1,4 +0,0 @@
declare module '*.svg' {
const value: string;
export default value;
}

View File

@@ -1,189 +0,0 @@
import { ReactWidget } from "@jupyterlab/apputils";
import { ISettingRegistry } from "@jupyterlab/settingregistry";
import FormInput from "./components/FormInput";
/**
* OpenBB Terminal Settings Menu
*
* @class GamestonkTerminalSettingsComponent (name)
* @param {} root0 - s: Settings object
* @param {} root0.s - s: Accessible settings object
* @returns {} JSX.Element Settings form component
*/
export function GamestonkTerminalSettingsComponent({ s }: any): JSX.Element {
/**
* Get the section settings values.
*
* The section settings are taken from the user space (`s.user` if section keys
* exist there) or from the default values of the settings schema.
*
* @param section The section name
* @returns The state of the section settings.
*/
function getSectionState(section: string): Record<string, unknown>[] {
const values: Array<Record<string, unknown>> = [];
Object.keys(s.schema.properties[section].default).forEach((element) => {
const settingsValue =
typeof s.user[section] === "undefined"
? s.schema.properties[section].default[element]
: s.user[section][element];
values.push({
key: element,
value: settingsValue,
});
});
return values;
}
const featureFlags = getSectionState("FEATURE_FLAGS");
const appSettings = getSectionState("APP_SETTINGS");
const apiKeys = getSectionState("API_KEYS");
const onFeatureFlagsChange = (index: any, item: any) => {
featureFlags[index] = item;
};
const onAppSettingsChange = (index: any, item: any) => {
appSettings[index] = item;
};
const onApiKeysChange = (index: any, item: any) => {
apiKeys[index] = item;
};
/**
* @param event - Update button click event
*/
function handleSubmit(event: any) {
event.preventDefault();
const featureFlagsObject = {} as any;
featureFlags.forEach((flag: any) => {
featureFlagsObject[flag.key] = flag["value"];
});
s.set("FEATURE_FLAGS", featureFlagsObject);
const apiKeysObject = {} as any;
apiKeys.forEach((apiKey: any) => {
apiKeysObject[apiKey.key] = apiKey["value"];
});
s.set("API_KEYS", apiKeysObject);
const appSettingsObject = {} as any;
appSettings.forEach((appSetting: any) => {
appSettingsObject[appSetting.key] = appSetting["value"];
});
s.set("APP_SETTINGS", appSettingsObject);
alert("Settings updated.");
}
return (
<div className="gamestonkSettings">
<div className="settingsForm">
<form>
<fieldset id="featureFlags">
<p className="settingsSectionLabel">Feature Flags</p>
<div className="fieldSetData">
{featureFlags.map((item: any, index: any) => (
<FormInput
key={index}
itemParent={item}
index={index}
onChangeParent={onFeatureFlagsChange}
/>
))}
</div>
<div className="container">
<div className="center">
<button
className="settingsSectionButton"
onClick={handleSubmit}
>
Update Flags
</button>
</div>
</div>
</fieldset>
</form>
<br />
<br />
<form onSubmit={handleSubmit}>
<fieldset id="appSettings">
<p className="settingsSectionLabel">Configurations</p>
<div className="fieldSetData">
{appSettings.map((item: any, index: any) => (
<FormInput
key={index}
itemParent={item}
index={index}
onChangeParent={onAppSettingsChange}
/>
))}
</div>
<div className="container">
<div className="center">
<button
className="settingsSectionButton"
onClick={handleSubmit}
>
Update Configurations
</button>
</div>
</div>
</fieldset>
</form>
<br />
<br />
<form onSubmit={handleSubmit}>
<fieldset id="apiKeys">
<p className="settingsSectionLabel">API keys</p>
<div className="fieldSetData">
{apiKeys.map((item: any, index: any) => (
<FormInput
key={index}
itemParent={item}
index={index}
onChangeParent={onApiKeysChange}
/>
))}
</div>
<div className="container">
<div className="center">
<button
className="settingsSectionButton"
onClick={handleSubmit}
>
Update API keys
</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
);
}
/**
* A Lumino Widget that wraps a GamestonkTerminalSettingsComponent.
*
* @class TerminalSettingsWidget (name)
*/
export class TerminalSettingsWidget extends ReactWidget {
/**
* Constructs a new TerminalSettingsWidget.
*/
s: ISettingRegistry.ISettings;
constructor(s: ISettingRegistry.ISettings) {
super();
this.addClass("gamestonkSettingsWidget");
this.s = s;
}
render(): JSX.Element {
return <GamestonkTerminalSettingsComponent s={this.s} />;
}
}

View File

@@ -1,99 +0,0 @@
.gamestonkSettingsWidget {
color: var(--jp-ui-font-color1);
background: var(--jp-layout-color1);
font-size: 16px;
display: flex;
align-items: left;
justify-content: left;
text-align: left;
}
.gamestonkSettings {
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: auto;
display: inline;
justify-content: center;
}
.settingsForm {
min-width: 542px;
min-width: 542px;
width: 85%;
height: 100%;
padding-top: var(--jp-private-launcher-top-padding);
padding-left: var(--jp-private-launcher-side-padding);
padding-right: var(--jp-private-launcher-side-padding);
box-sizing: border-box;
}
.inputFieldLabel {
font-size: 16px;
}
form fieldset {
padding: 6%;
border: 1px solid var(--jp-border-color2);
}
form input[type="text" i],
form input[type="number" i] {
border: 1px solid var(--jp-border-color2);
}
.settingsSectionLabel {
font-size: var(--jp-ui-font-size2);
font-weight: normal;
color: var(--jp-ui-font-color1);
margin-bottom: 5%;
}
.settingsSectionButton {
display:inline-block;
height: 36px;
width: 13em;
margin:0.1em;
padding: 0.2em 1.45em;
border:0.05em solid #CCCCCC;
box-sizing: border-box;
text-decoration:none;
font-size: 16px;
font-weight: lighter;
color:#000000;
background-color:#CCCCCC;
text-align:center;
position:relative;
}
.settingsSectionButton:hover{
border-color:#7a7a7a;
}
.settingsSectionButton:active{
background-color:#999999;
}
.container {
height: 64px;
position: relative;
margin-top: 1em;
}
.center {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.settingsSectionUpdateButton {
}
div.fieldSetData {
display:grid;
grid-template-columns: 50% 50%;
grid-gap:5px;
}
div.fieldSetData label { text-align:right; }
div.fieldSetData label:after { content: ":"; }

View File

@@ -1 +0,0 @@
@import url('base.css');

View File

@@ -1 +0,0 @@
import './base.css';

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="256px" height="256px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>settings</title>
<g id="settings" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Rectangle" fill="#424242" x="15" y="18" width="225" height="220"></rect>
<path d="M116.854147,65.1962028 L125.954036,77.5895858 L128.098262,77.5895858 L137.198151,65.2223492 C139.271789,62.3318774 143.062502,61.2489295 146.350338,62.6077114 L161.019987,68.6475247 C164.3054,69.9974845 166.232064,73.4283204 165.674527,76.9359264 L163.347257,92.1008255 L164.890054,93.6434618 L180.056536,91.3164341 C183.564507,90.7589555 186.995701,92.6854186 188.345802,95.9704894 L194.412395,110.638607 C195.781546,113.925512 194.69663,117.722321 191.797484,119.789839 L179.428957,128.888779 L179.428957,131.032782 L191.797484,140.131721 C194.69663,142.19924 195.781546,145.996049 194.412395,149.282954 L188.345802,163.951071 C186.995701,167.236142 183.564507,169.162605 180.056536,168.605127 L164.890054,166.278099 L163.347257,167.820735 L165.674527,182.985634 C166.232064,186.49324 164.3054,189.924076 161.019987,191.274036 L146.350338,197.339996 C145.417331,197.741826 144.411352,197.946561 143.395489,197.941363 C140.941263,197.943952 138.635386,196.766813 137.198151,194.777651 L128.098262,182.410414 L125.954036,182.410414 L116.854147,194.803797 C114.78051,197.694269 110.989797,198.777217 107.70196,197.418435 L93.0323116,191.274036 C89.7468981,189.924076 87.820234,186.49324 88.3777708,182.985634 L90.7050412,167.820735 L89.162244,166.278099 L73.9957627,168.605127 C70.4877907,169.162605 67.0565969,167.236142 65.7064962,163.951071 L59.6399036,149.282954 C58.2707526,145.996049 59.3556682,142.19924 62.2548142,140.131721 L74.6233412,131.032782 L74.6233412,128.888779 L62.202516,119.789839 C59.30337,117.722321 58.2184544,113.925512 59.5876054,110.638607 L65.7064962,95.9704894 C67.0565969,92.6854186 70.4877907,90.7589555 73.9957627,91.3164341 L89.162244,93.6434618 L90.7050412,92.1008255 L88.3777708,76.9359264 C87.820234,73.4283204 89.7468981,69.9974845 93.0323116,68.6475247 L107.70196,62.581565 C110.989797,61.2227831 114.78051,62.305731 116.854147,65.1962028 Z M146.005273,68.5526316 L136.754354,81.1675213 C135.213998,83.2232711 132.818559,84.4622913 130.250677,84.5314919 L124.92439,84.5314919 C122.295546,84.5251197 119.82745,83.2650372 118.280549,81.1394882 L109.029629,68.5526316 L97.4239309,73.2902235 L99.8067434,88.7364551 C100.207815,91.3618086 99.3452187,94.022347 97.4799971,95.9129257 L93.8076625,99.5852603 C91.936076,101.424973 89.3129567,102.285522 86.7152912,101.912007 L71.1849603,99.5572272 L66.4473684,110.994727 L79.034225,120.245646 C81.159774,121.792548 82.4198565,124.260644 82.4262287,126.889488 L82.4262287,132.35594 C82.4198565,134.984785 81.159774,137.45288 79.034225,138.999782 L66.4473684,148.250701 L71.1849603,159.716235 L86.631192,157.333422 C89.231168,156.932646 91.8662632,157.797124 93.7235633,159.660168 L97.4799971,163.192337 C99.3430411,165.049638 100.207519,167.684733 99.8067434,170.284709 L97.3398317,185.81504 L108.805365,190.552632 L118.056284,177.965775 C119.603186,175.840226 122.071281,174.580143 124.700126,174.573771 L130.250677,174.573771 C132.868127,174.600046 135.324102,175.843578 136.894519,177.937742 L146.145438,190.552632 L157.610971,185.81504 L155.228159,170.368808 C154.783184,167.770558 155.582229,165.113994 157.386707,163.192337 L161.087074,159.520003 C162.958661,157.68029 165.58178,156.819741 168.179446,157.193257 L183.625677,159.576069 L188.363269,148.110536 L175.776413,138.859617 C173.721926,137.324487 172.499172,134.920429 172.468508,132.35594 L172.468508,127.029654 C172.47488,124.400809 173.734963,121.932714 175.860512,120.385812 L188.447368,111.134893 L183.709777,99.5572272 L168.263545,101.912007 C165.638191,102.313078 162.977653,101.450482 161.087074,99.5852603 L157.41474,95.9129257 C155.575027,94.0413392 154.714478,91.4182198 155.087993,88.8205544 L157.470806,73.3743228 L146.005273,68.5526316 Z" id="Combined-Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M127.5,106 C114.521308,106 104,116.521308 104,129.5 C104,142.478692 114.521308,153 127.5,153 C140.478692,153 151,142.478692 151,129.5 C151,123.267412 148.524114,117.290096 144.117009,112.882991 C139.709904,108.475886 133.732588,106 127.5,106 Z" id="Path" stroke="#FFFFFF" stroke-width="10" fill-rule="nonzero"></path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -1,24 +0,0 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"composite": true,
"declaration": true,
"esModuleInterop": true,
"incremental": true,
"jsx": "react-jsx",
"module": "esnext",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"preserveWatchOutput": true,
"resolveJsonModule": true,
"outDir": "lib",
"rootDir": "src",
"strict": true,
"strictNullChecks": false,
"target": "es2017",
"types": []
},
"include": ["src/*", "src/**/*"]
}

View File

@@ -1,91 +0,0 @@
# Test
The test will produce a video to help debugging and check what happened.
To execute integration tests, you have two options:
- use docker-compose (cons: needs to know and use docker) - this is a more reliable solution.
- run tests locally (cons: will interact with your JupyterLab user settings)
## Test locally
1. Compile the extension:
```
jlpm install
jlpm run build:prod
```
2. Start JupyterLab _with the extension installed_ without any token or password
```
jupyter lab --ServerApp.token= --ServerApp.password=
```
3. Execute in another console the [Playwright](https://playwright.dev/docs/intro) tests:
```
cd ui-tests
jlpm install
npx playwright install
npx playwright test
```
# Create tests
To create tests, the easiest way is to use the code generator tool of playwright:
1. Compile the extension:
```
jlpm install
jlpm run build:prod
```
2. Start JupyterLab _with the extension installed_ without any token or password:
**Using local installation**
```
jupyter lab --ServerApp.token= --ServerApp.password=
```
3. Launch the code generator tool:
```
cd ui-tests
jlpm install
npx playwright install
npx playwright codegen localhost:8888
```
# Debug tests
To debug tests, a good way is to use the inspector tool of playwright:
1. Compile the extension:
```
jlpm install
jlpm run build:prod
```
Note: When compiling the extension execute the commands in the extension root (`gst-settings`) folder and not the `gst-settings/ui-tests` folder.
2. Start JupyterLab _with the extension installed_ without any token or password:
**Using local installation**
```
jupyter lab --ServerApp.token= --ServerApp.password=
```
3. Launch the code generator tool:
```
cd ui-tests
jlpm install
npx playwright install
PWDEBUG=1 npx playwright test
```

View File

@@ -1,13 +0,0 @@
{
"name": "@gamestonk/settings-tests",
"version": "0.1.0",
"description": "Integration test for the gamestong Settings extension",
"repository": "https://github.com/OpenBB-finance/OpenBBTerminal",
"author": "OpenBB Terminal Contributors",
"license": "MIT",
"private": true,
"devDependencies": {
"@playwright/test": "1.16",
"typescript": "~4.1.3"
}
}

View File

@@ -1,18 +0,0 @@
import { PlaywrightTestConfig } from '@playwright/test';
const config: PlaywrightTestConfig = {
timeout: 60000,
use: {
// Browser options
// headless: false,
// slowMo: 500,
// Context options
viewport: { width: 1280, height: 720 },
// Artifacts
video: 'on',
},
};
export default config;

View File

@@ -1,77 +0,0 @@
/*
* E2E scenario for testing the Settings menu UI
*
* Steps:
* - Load the extension
* - Set a feature flag and save
* - Restore settings menu values from user settings
* - Unset the feature flag
*/
import { test, expect } from '@playwright/test';
const TARGET_URL = process.env.TARGET_URL ?? 'http://localhost:8888';
test('Test loading of the settings menu', async ({ page }) => {
// Open lab
await page.goto(`${TARGET_URL}/lab`);
await page.waitForSelector('#jupyterlab-splash', { state: 'detached' });
await page.waitForSelector('div[role="main"] >> text=Launcher');
// Click the Settings button in the Launcher panel
await page.click('text=settingsSettings >> div');
// Verify that the extension panel is visible on the same page
expect(page.url()).toBe('http://localhost:8888/lab');
expect(page.isVisible('#gamestonkSettings')).toBeTruthy();
// Click the "Clear.after.command" feature flag's checkbox
await page.check('#featureFlags > div.fieldSetData > input.Clear.after.command');
// Click "Update Flags" text and catch the dialog message
page.once('dialog', dialog => {
console.log(`Dialog message: ${dialog.message()}`);
dialog.dismiss().catch(() => {});
});
await page.click('text=Update Flags');
// Check the "Clear.after.command" feature flag's checkbox is checked
expect(await page.isChecked('#featureFlags > div.fieldSetData > input.Clear.after.command')).toBeTruthy();
// Reload the page
await page.goto(`${TARGET_URL}/lab`);
await page.waitForSelector('#jupyterlab-splash', { state: 'detached' });
await page.waitForSelector('div[role="main"] >> text=Launcher');
// Click the settings button in the Launcher panel
await page.click('text=settingsSettings >> div');
expect(page.url()).toBe('http://localhost:8888/lab');
// Check the "Clear.after.command" feature flag's checkbox is checked (populated from the user settings)
expect(await page.isChecked('#featureFlags > div.fieldSetData > input.Clear.after.command')).toBeTruthy();
// Uncheck the "Clear.after.command" feature flag's checkbox
await page.uncheck('#featureFlags > div.fieldSetData > input.Clear.after.command');
// Click "Update Flags" text and catch the dialog message
page.once('dialog', dialog => {
console.log(`Dialog message: ${dialog.message()}`);
dialog.dismiss().catch(() => {});
});
await page.click('text=Update Flags');
// Check the "Clear.after.command" feature flag's checkbox is not checked (user settings changed)
expect(await page.isChecked('#featureFlags > div.fieldSetData > input.Clear.after.command')).toBeFalsy();
// Reload the page
await page.goto(`${TARGET_URL}/lab`);
await page.waitForSelector('#jupyterlab-splash', { state: 'detached' });
await page.waitForSelector('div[role="main"] >> text=Launcher');
// Click the settings button in the Launcher panel
await page.click('text=settingsSettings >> div');
expect(page.url()).toBe('http://localhost:8888/lab');
// Check the "Clear.after.command" feature flag's checkbox is not checked (populated from the user settings)
expect(await page.isChecked('#featureFlags > div.fieldSetData > input.Clear.after.command')).toBeFalsy();
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +0,0 @@
node_modules
dist
coverage
**/*.d.ts
ui-tests

View File

@@ -1,53 +0,0 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:jsdoc/recommended',
'plugin:prettier/recommended',
'plugin:react/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint', 'jsdoc'],
rules: {
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'interface',
format: ['PascalCase'],
custom: {
regex: '^I[A-Z]',
match: true,
},
},
],
'@typescript-eslint/no-unused-vars': ['warn', { args: 'none' }],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/quotes': [
'error',
'double',
{ avoidEscape: true, allowTemplateLiterals: false },
],
curly: ['error', 'all'],
eqeqeq: 'error',
'jsdoc/require-param-type': 'off',
'jsdoc/require-property-type': 'off',
'jsdoc/require-returns-type': 'off',
'jsdoc/no-types': 'warn',
'prefer-arrow-callback': 'error',
},
settings: {
jsdoc: {
mode: 'typescript',
},
react: {
version: 'detect',
},
},
};

View File

@@ -1,22 +0,0 @@
include LICENSE
include README.md
include pyproject.toml
include jupyter-config/openbb_terminal_launcher.json
include package.json
include ts*.json
graft openbb_terminal_launcher/labextension
# Javascript files
graft src
graft style
prune **/node_modules
prune lib
# Patterns to exclude from any directory
global-exclude *~
global-exclude *.pyc
global-exclude *.pyo
global-exclude .git
global-exclude .ipynb_checkpoints

View File

@@ -1,17 +0,0 @@
# OpenBB Terminal Launcher
This extensions adds a button into the OpenBB Terminal category of the Jupyter Lab launcher panel.
## Install, Use and Develop
```bash
pip install -e .
jlpm
jlpm run build:prod
jupyter labextension install .
# Rebuild Typescript source after making changes
jlpm build
# Rebuild JupyterLab after making any changes
jupyter lab build
```

View File

@@ -1,3 +0,0 @@
# Making a new release of gamestonk-settings
Check out the [workflow documentation](https://github.com/jupyter-server/jupyter_releaser#typical-workflow) for information.

View File

@@ -1,5 +0,0 @@
{
"packageManager": "python",
"packageName": "openbb_terminal_launcher",
"uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package openbb_terminal_launcher"
}

View File

@@ -1,13 +0,0 @@
import json
import os.path as osp
from ._version import __version__ # noqa: F401
HERE = osp.abspath(osp.dirname(__file__))
with open(osp.join(HERE, "labextension", "package.json")) as fid:
data = json.load(fid)
def _jupyter_labextension_paths():
return [{"src": "labextension", "dest": data["name"]}]

View File

@@ -1,2 +0,0 @@
version_info = (0, 1, 0)
__version__ = ".".join(map(str, version_info))

View File

@@ -1,95 +0,0 @@
{
"name": "@gamestonk/terminal",
"version": "0.1.0",
"description": "Gamestonk terminal launcher",
"keywords": [
"jupyter",
"jupyterlab",
"jupyterlab-extension"
],
"homepage": "https://github.com/OpenBB-finance/OpenBBTerminal",
"bugs": {
"url": "https://github.com/OpenBB-finance/OpenBBTerminal/issues"
},
"license": "MIT",
"author": {
"name": "Gamestonk Contributors",
"email": "dro.lopes@campus.fct.unl.pt"
},
"files": [
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
"style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
"style/index.js"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
"style": "style/index.css",
"repository": {
"type": "git",
"url": "https://github.com/OpenBB-finance/OpenBBTerminal.git"
},
"scripts": {
"build": "jlpm run build:lib && jlpm run build:labextension:dev",
"build:all": "jlpm run build:lib && jlpm run build:labextension",
"build:labextension": "jupyter labextension build .",
"build:labextension:dev": "jupyter labextension build --development True .",
"build:lib": "tsc",
"build:prod": "jlpm run clean && jlpm run build:lib && jlpm run build:labextension",
"clean": "jlpm run clean:lib",
"clean:all": "jlpm run clean:lib && jlpm run clean:labextension",
"clean:labextension": "rimraf openbb_terminal_launcher/labextension",
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
"eslint": "eslint . --ext .ts,.tsx --fix",
"eslint:check": "eslint . --ext .ts,.tsx",
"install:extension": "jlpm run build",
"prepare": "jlpm run clean && jlpm run build:prod",
"watch": "run-p watch:src watch:labextension",
"watch:labextension": "jupyter labextension watch .",
"watch:src": "tsc -w"
},
"dependencies": {
"@jupyterlab/application": "^3.2.8",
"@jupyterlab/apputils": "^3.2.8",
"@jupyterlab/filebrowser": "^3.2.8",
"@jupyterlab/launcher": "^3.2.8",
"@jupyterlab/mainmenu": "^3.2.8",
"@jupyterlab/running": "^3.2.8",
"@jupyterlab/services": "^6.2.8",
"@jupyterlab/settingregistry": "^3.2.8",
"@jupyterlab/terminal": "^3.2.8",
"@jupyterlab/translation": "^3.2.8",
"@jupyterlab/ui-components": "^3.2.8",
"@lumino/algorithm": "^1.9.1",
"marked": "^4.0.10"
},
"devDependencies": {
"@jupyterlab/builder": "^3.2.8",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"eslint": "^8.7.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-jsdoc": "^37.6.3",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
"typescript": "<4.4"
},
"resolutions": {
"json-schema": "^0.4.0",
"marked": "^4.0.10",
"got": "^11.8.5",
"jpeg-js": "^0.4.4"
},
"sideEffects": [
"style/*.css",
"style/*.svg",
"style/index.js"
],
"jupyterlab": {
"extension": true,
"outputDir": "openbb_terminal_launcher/labextension"
},
"styleModule": "style/index.js"
}

View File

@@ -1,17 +0,0 @@
[build-system]
requires = ["jupyter_packaging~=0.10,<2", "jupyterlab~=3.1"]
build-backend = "jupyter_packaging.build_api"
[tool.jupyter-packaging.options]
skip-if-exists = ["openbb_terminal_launcher/labextension/static/style.js"]
ensured-targets = ["openbb_terminal_launcher/labextension/static/style.js", "openbb_terminal_launcher/labextension/package.json"]
[tool.jupyter-packaging.builder]
factory = "jupyter_packaging.npm_builder"
[tool.jupyter-packaging.build-args]
build_cmd = "build:prod"
npm = ["jlpm"]
[tool.check-manifest]
ignore = ["openbb_terminal_launcher/labextension/**", "yarn.lock", ".*", "package-lock.json"]

View File

@@ -1,84 +0,0 @@
"""
openbb_terminal_launcher setup
"""
import json
import sys
from pathlib import Path
import setuptools
HERE = Path(__file__).parent.resolve()
# The name of the project
name = "openbb_terminal_launcher"
lab_path = HERE / name.replace("-", "_") / "labextension"
# Representative files that should exist after a successful build
ensured_targets = [str(lab_path / "package.json"), str(lab_path / "static/style.js")]
labext_name = "@gamestonk/terminal_launcher"
data_files_spec = [
(
"share/jupyter/labextensions/%s" % labext_name,
str(lab_path.relative_to(HERE)),
"**",
),
("share/jupyter/labextensions/%s" % labext_name, ".", "install.json"),
]
long_description = (HERE / "README.md").read_text()
# Get the package info from package.json
pkg_json = json.loads((HERE / "package.json").read_bytes())
setup_args = dict(
name=name,
version=pkg_json["version"],
url=pkg_json["homepage"],
author=pkg_json["author"]["name"],
author_email=pkg_json["author"]["email"],
description=pkg_json["description"],
license=pkg_json["license"],
long_description=long_description,
long_description_content_type="text/markdown",
packages=setuptools.find_packages(),
install_requires=[],
zip_safe=False,
include_package_data=True,
python_requires=">=3.6",
platforms="Linux, Mac OS X, Windows",
keywords=["Jupyter", "JupyterLab", "JupyterLab3"],
classifiers=[
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Framework :: Jupyter",
],
)
try:
from jupyter_packaging import wrap_installers, npm_builder, get_data_files
post_develop = npm_builder(
build_cmd="install:extension", source_dir="src", build_dir=lab_path
)
setup_args["cmdclass"] = wrap_installers(
post_develop=post_develop, ensured_targets=ensured_targets
)
setup_args["data_files"] = get_data_files(data_files_spec)
except ImportError as e:
import logging
logging.basicConfig(format="%(levelname)s: %(message)s")
logging.warning(
"Build tool `jupyter-packaging` is missing. Install it with pip or conda."
)
if not ("--name" in sys.argv or "--version" in sys.argv):
raise e
if __name__ == "__main__":
setuptools.setup(**setup_args)

View File

@@ -1,170 +0,0 @@
import {
JupyterFrontEnd,
JupyterFrontEndPlugin,
} from "@jupyterlab/application";
import { ICommandPalette } from "@jupyterlab/apputils";
import { ILauncher } from "@jupyterlab/launcher";
import { IMainMenu } from "@jupyterlab/mainmenu";
import { ISettingRegistry } from "@jupyterlab/settingregistry";
import { LabIcon } from "@jupyterlab/ui-components";
import { TerminalManager } from "@jupyterlab/services";
import { Terminal } from "@jupyterlab/terminal";
import appStr from "../style/terminal.svg";
import { ITerminalSettingsInterface } from "./interfaces";
const CATEGORY = "OpenBB Terminal";
/**
* The command IDs used by the OpenBB Terminal Launcher plugin.
*/
namespace CommandIDs {
export const create = "gamestonk:terminal";
}
/**
* Get the section settings values.
*
* The section settings are taken from the user space (`s.user` if section keys
* exist there) or from the default values of the settings schema.
*
* @param section.section
* @param section The section name
* @param section.s
* @returns The state of the section settings.
*/
function getSettingsAsArray({ s }: { s: any }): any {
const values: Array<Record<string, unknown>> = [];
for (const section of ["APP_SETTINGS", "FEATURE_FLAGS", "API_KEYS"]) {
Object.keys(s.schema.properties[section].default).forEach(
(element: string) => {
const settingsValue =
typeof s.user[section] === "undefined"
? s.schema.properties[section].default[element]
: s.user[section][element];
values.push({
key: element,
value: settingsValue,
});
}
);
}
return values;
}
/**
* Initialization data for the OpenBB Terminal Launcher extension.
*/
const extension: JupyterFrontEndPlugin<void> = {
id: "gamestonk:terminal",
autoStart: true,
optional: [ILauncher, IMainMenu, ICommandPalette, ISettingRegistry],
activate: async (
app: JupyterFrontEnd,
launcher: ILauncher | null,
menu: IMainMenu | null,
palette: ICommandPalette | null,
settings: ISettingRegistry
) => {
const { commands } = app;
const command = CommandIDs.create;
const icon = new LabIcon({
name: "gamestonk:terminal",
svgstr: appStr,
});
const s = await settings.load("@gamestonk/settings:settings");
commands.addCommand(command, {
label: (args) =>
args["isPalette"] ? "New OpenBB Terminal" : "OpenBB Terminal",
caption: "New OpenBB Terminal",
icon: (args) => (args["isPalette"] ? null : icon),
execute: async () => {
const appSettings = getSettingsAsArray({ s: s });
let settingsAsBashVariablesString = "";
for (const appSetting of appSettings) {
settingsAsBashVariablesString = `${settingsAsBashVariablesString} && export ${
appSetting.key
}=${
appSetting.value.value === ""
? appSetting.value.default
: appSetting.value.value
}`;
}
const manager = new TerminalManager();
const session = await manager.startNew();
const terminal = new Terminal(session, { theme: "dark" });
terminal.title.closable = true;
session.send({
type: "stdin",
content: ["clear\n"],
});
await new Promise((f) => setTimeout(f, 1000));
session.send({
type: "stdin",
content: [`clear${settingsAsBashVariablesString}\nclear\n`],
});
const pythonBinarySetting: ITerminalSettingsInterface = appSettings.find(
(i: ITerminalSettingsInterface) => i.key === "PYTHON_BINARY"
);
const terminalPath: ITerminalSettingsInterface = appSettings.find(
(i: ITerminalSettingsInterface) => i.key === "TERMINAL_PATH"
);
const launchCommand = `${
pythonBinarySetting.value.value === ""
? pythonBinarySetting.value.default
: pythonBinarySetting.value.value
} ${
terminalPath.value.value === ""
? terminalPath.value.default
: terminalPath.value.value
}\n`;
session.send({
type: "stdin",
content: [launchCommand],
});
return terminal;
},
});
if (launcher) {
launcher.add({
command,
category: CATEGORY,
rank: 2,
});
}
// Add the command to the palette
if (palette) {
palette.addItem({
command,
args: { isPalette: true },
category: CATEGORY,
});
}
// Add the command to the menu
if (menu) {
menu.fileMenu.newMenu.addGroup([{ command }], 30);
}
console.log("Added OpenBB Terminal Launcher Exstension.");
},
};
export default extension;

Some files were not shown because too many files have changed in this diff Show More