Merge pull request #4237 from OpenBB-finance/release/2.4.0

Release 2.4.0
This commit is contained in:
James Maslek
2023-02-14 16:19:19 -05:00
committed by GitHub
1473 changed files with 674501 additions and 939495 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

@@ -23,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
@@ -76,4 +76,3 @@ jobs:
# You can swap them out with your own user credentials.
user_name: github-actions[bot]
user_email: 41898282+github-actions[bot]@users.noreply.github.com

View File

@@ -13,7 +13,17 @@ concurrency:
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
@@ -31,7 +41,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
@@ -47,6 +57,26 @@ jobs:
run: poetry install --no-interaction -E optimization
- name: Run integration tests
id: integration-tests
run: |
source $VENV
python terminal.py /home/runner/work/OpenBBTerminal/OpenBBTerminal/openbb_terminal/miscellaneous/integration_tests_scripts -t
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

@@ -22,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
@@ -36,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') }}
@@ -53,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/
@@ -149,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 }}
@@ -177,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/integration_tests_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

@@ -16,6 +16,8 @@ on:
- 'feature/*'
- 'hotfix/*'
- 'release/*'
merge_group:
types: [checks_requested]
# Cancel previous runs that are not yet completed.
concurrency:
@@ -43,16 +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.236
pip install bandit black codespell mypy==0.982 safety pylint==2.15.2 packaging==22 ruff==0.0.243
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: |
pylint terminal.py openbb_terminal tests
- run: pylint terminal.py openbb_terminal tests
markdown-link-check:
name: Markdown Linting

View File

@@ -22,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
@@ -36,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') }}
@@ -55,13 +55,9 @@ jobs:
use-only-tar-bz2: true # Needed for caching some reason
- name: Run Poetry
run: poetry install -vvv
- 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: |
@@ -71,13 +67,102 @@ jobs:
# 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
@@ -101,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/integration_tests_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

@@ -13,7 +13,7 @@ on:
schedule:
- cron: "0 0 * * *"
permissions:
permissions:
actions: write
jobs:
@@ -25,8 +25,8 @@ jobs:
with:
workflow: windows10_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
wait-for-completion-timeout: 3h
trigger-macos-build:
runs-on: ubuntu-latest
steps:
@@ -36,7 +36,7 @@ jobs:
workflow: m1_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-intel-build:
runs-on: ubuntu-latest
steps:
@@ -46,7 +46,7 @@ jobs:
workflow: intel_macos_build.yml
token: ${{ secrets.GITHUB_TOKEN }}
wait-for-completion-timeout: 2h
trigger-docker-build:
runs-on: ubuntu-latest
steps:

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 distributions 📦 to PyPI and 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 distributions 📦 to PyPI and TestPyPI
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,259 +0,0 @@
name: Tests
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
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

@@ -6,6 +6,8 @@ env:
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:
@@ -17,7 +19,8 @@ on:
push:
branches:
- release/*
merge_group:
types: [checks_requested]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
@@ -32,7 +35,7 @@ jobs:
check-changes: ${{ steps.check-changes.outputs.check-changes }}
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v3
with:
fetch-depth: 100
# The GitHub token is preserved by default but this job doesn't need
@@ -76,7 +79,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
@@ -128,7 +131,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
@@ -167,7 +170,7 @@ jobs:
# 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]
@@ -187,7 +190,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
@@ -200,7 +203,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}
@@ -208,6 +212,11 @@ jobs:
source $VENV
pip list
- name: Start Terminal and exit
run: |
source $VENV
python terminal.py
- name: Run tests
env:
MPLBACKEND: Agg
@@ -215,11 +224,6 @@ jobs:
source $VENV
pytest tests/ --optimization --autodoc
- name: Start Terminal and exit
run: |
source $VENV
python terminal.py
tests-conda:
name: Anaconda Python Tests - (${{ matrix.python-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}-latest
@@ -227,7 +231,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: ["ubuntu", "windows"]
os: ["ubuntu", "windows", "macos"]
python-version: ["3.9"]
dependencies: [""]
include:
@@ -299,11 +303,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: |

View File

@@ -17,7 +17,7 @@ concurrency:
jobs:
Windows-Build:
name: Windows10 Build ENV
runs-on: windows-latest
runs-on: windows-2019
# Configuring -------------
steps:
- name: Setup Windows Git Configuration # This is under the assumption that git is already installed on the system
@@ -26,7 +26,7 @@ jobs:
git config --system core.longpaths true
- name: Checkout
uses: actions/checkout@v2.4.2
uses: actions/checkout@v3
- name: Set up Python & Create OpenBB Environment
uses: actions/setup-python@v4
@@ -38,10 +38,9 @@ jobs:
python -m venv venv
source venv/Scripts/activate
python -m pip install --upgrade pip
python -m pip install poetry==1.1.13
python -m pip install setuptools==64.0.2 wheel
python -m pip install charset_normalizer==2.1.1
python -m poetry install -E installer -E all
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
@@ -67,7 +66,7 @@ jobs:
git config --system core.longpaths true
- name: Checkout
uses: actions/checkout@v2.4.2
uses: actions/checkout@v3
- name: Download Artifact
uses: actions/download-artifact@v2
@@ -84,6 +83,12 @@ jobs:
run: |
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:
@@ -92,7 +97,18 @@ jobs:
- name: Run Integration Tests
run: |
dist\OpenBBTerminal\OpenBBTerminal.exe -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

17
.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
@@ -73,3 +61,6 @@ darts_logs/
# User data
custom_imports/*.csv
custom_imports/*/*.csv
# lightning logs
lightning_logs/

View File

@@ -14,7 +14,7 @@ repos:
hooks:
- id: black
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.0.236'
rev: 'v0.0.243'
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.3.1
hooks:
- id: pyupgrade
args: [--py38-plus]
- repo: local
hooks:
- id: reserved_args

215
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)
@@ -310,160 +309,40 @@ 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. Go to the `trail_map.csv` file located in `openbb_terminal/miscellaneous/library`, which should look like this:
```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",
},
```csv
trail,model,view
...
stocks.fa.rot,openbb_terminal.stocks.fundamental_analysis.finnhub_model.get_rating_over_time,openbb_terminal.stocks.fundamental_analysis.finnhub_view.rating_over_time
stocks.fa.analyst,openbb_terminal.stocks.fundamental_analysis.finviz_model.get_analyst_data,
```
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:
In this file, the trail represents the path to the function to be called. The model represents the path to the model function and the view represents the path to the view function. Note that the second line does not have an associated view function, so we leave that column empty (the trailing comma is required to load).
```python
functions = {
...
2. 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 path to the `_model` function that was written, `openbb_terminal.stocks.dark_pool_shorts.yahoofinance_model.get_most_shorted`.
The view is the path to the `_view` function that was written: `openbb_terminal.stocks.dark_pool_shorts.yahoofinance_view.display_most_shorted`.
The added line of the file should look like this:
"stocks.dps.shorted": {
"model": "openbb_terminal.stocks.dark_pool_shorts.yahoofinance_model.get_most_shorted",
},
...
```
### Add Documentation
To check whether documentation is added correctly follow [Hugo Server instructions](/website/README.md).
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]
```
Past and future IPOs. [Source: <https://finnhub.io>]
- --past : Number of past days to look for IPOs. Default 0.
- --future : Number of future days to look for IPOs. Default 10.
<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"
```csv
stocks.dps.shorted,openbb_terminal.stocks.dark_pool_shorts.yahoofinance_model.get_most_shorted,openbb_terminal.stocks.dark_pool_shorts.yahoofinance_view.display_most_shorted
```
### 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 +979,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 +1024,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 +1078,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 +1094,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 +1156,6 @@ The convention is as follows:
"candle": [],
"load": [
"YahooFinance",
"IEXCloud",
"AlphaVantage",
"Polygon",
"EODHD"
@@ -1300,7 +1185,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.

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.3.1"
OPENBBTERMINAL_DOCKER_RELEASE_VERSION="2.4.0"

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.3.1
image: ghcr.io/openbb-finance/openbbterminal/openbb:2.4.0
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

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.3.1"
!define VERSION "2.4.0"
!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:dbd2097
OPENBB_LOGGING_COMMIT_HASH=sha:5705675
OPENBB_ENABLE_PREDICT=false
OPENBB_ENABLE_CHECK_API=true
OPENBB_ENABLE_THOUGHTS_DAY=false

View File

@@ -69,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"),
@@ -85,6 +81,7 @@ 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 = [
"sklearn.utils._cython_blas",
@@ -103,7 +100,6 @@ hidden_imports = [
"user_agent",
"vaderSentiment",
"frozendict",
"textwrap3",
"pyEX",
"feedparser",
"_sysconfigdata__darwin_darwin",

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",

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;

View File

@@ -1,13 +0,0 @@
interface ITerminalSettingsObject {
default?: string | number;
description?: string;
form?: string;
title?: string;
type?: string;
value?: string;
}
export interface ITerminalSettingsInterface {
key: string;
value: ITerminalSettingsObject;
}

View File

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

View File

@@ -1,16 +0,0 @@
.jp-example-view {
background-color: AliceBlue;
}
.jp-example-button {
background-color: red;
border-radius: 12px;
border: none;
color: white;
padding: 15px 32px;
margin: 30px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}

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

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 23 KiB

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/*"]
}

View File

@@ -1,92 +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`) folder and not the `gst/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 --headed
```

View File

@@ -1,13 +0,0 @@
{
"name": "@gamestonk/launcher-tests",
"version": "0.1.0",
"description": "Integration test for terminal launcher",
"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,37 +0,0 @@
/*
* Simple scenario placeholder for testing the Gamestonk Launcher
*
* Steps:
* - Wait for the launcher panel to load
* - Launch the terminal
* - Wait for the terminal to initialize
* - Press "return" three times
*
* This is a placeholder for the test.
* Depending on the future testing/QA decisions this test can be expanded.
*/
import { test, expect } from '@playwright/test';
const TARGET_URL = process.env.TARGET_URL ?? 'http://localhost:8888';
test('Should open a panel with the OpenBBTerminal and send "Enter" three times', async ({ page }) => {
await page.goto(`${TARGET_URL}/lab`);
await page.waitForSelector('#jupyterlab-splash', { state: 'detached' });
await page.waitForSelector('div[role="main"] >> text=Launcher');
await Promise.all([
page.waitForNavigation(/*{ url: 'http://localhost:8888/lab' }*/),
page.click('p:has-text("OpenBB Terminal")')
]);
expect(
await page.waitForSelector('[aria-label="Terminal input"]', { timeout: 1000 })
).toBeTruthy();
// Press Enter a couple of times
await page.waitForTimeout(3000)
await page.press('[aria-label="Terminal input"]', 'Enter');
await page.press('[aria-label="Terminal input"]', 'Enter');
await page.press('[aria-label="Terminal input"]', 'Enter');
await page.waitForTimeout(1000)
});

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