From 1bb3df85db9995ab009a2ae5536cf9347cc4ac62 Mon Sep 17 00:00:00 2001 From: colin99d Date: Mon, 21 Aug 2023 15:04:19 -0400 Subject: [PATCH 01/20] Began the fax --- .../core/models/preferences_model.py | 4 +- openbb_terminal/core/session/env_handler.py | 6 +- openbb_terminal/settings_controller.py | 96 ++++++++----------- 3 files changed, 40 insertions(+), 66 deletions(-) diff --git a/openbb_terminal/core/models/preferences_model.py b/openbb_terminal/core/models/preferences_model.py index 016299be1983..e92e855eb353 100644 --- a/openbb_terminal/core/models/preferences_model.py +++ b/openbb_terminal/core/models/preferences_model.py @@ -4,9 +4,7 @@ from pydantic import NonNegativeInt, PositiveFloat, PositiveInt from pydantic.dataclasses import dataclass -from openbb_terminal.core.config.paths import ( - HOME_DIRECTORY, -) +from openbb_terminal.core.config.paths import HOME_DIRECTORY from openbb_terminal.core.models import BaseModel # pylint: disable=too-many-instance-attributes, disable=no-member, useless-parent-delegation diff --git a/openbb_terminal/core/session/env_handler.py b/openbb_terminal/core/session/env_handler.py index 424c665434b5..66213eca38de 100644 --- a/openbb_terminal/core/session/env_handler.py +++ b/openbb_terminal/core/session/env_handler.py @@ -12,11 +12,7 @@ SETTINGS_ENV_FILE, ) -DEFAULT_ORDER = [ - SETTINGS_ENV_FILE, - PACKAGE_ENV_FILE, - REPOSITORY_ENV_FILE, -] +DEFAULT_ORDER = [SETTINGS_ENV_FILE, PACKAGE_ENV_FILE, REPOSITORY_ENV_FILE] def get_reading_order() -> list: diff --git a/openbb_terminal/settings_controller.py b/openbb_terminal/settings_controller.py index d1aa82d41326..88d9bffdc077 100644 --- a/openbb_terminal/settings_controller.py +++ b/openbb_terminal/settings_controller.py @@ -483,6 +483,11 @@ def call_flair(self, other_args: List[str]): @log_start_end(log=logger) def call_userdata(self, other_args: List[str]): """Process userdata command""" + + def save_file(file_path: Path): + console.print(f"User data to be saved in the default folder: '{file_path}'") + self.set_and_save_preference("USER_DATA_DIRECTORY", file_path) + parser = argparse.ArgumentParser( add_help=False, formatter_class=argparse.ArgumentDefaultsHelpFormatter, @@ -496,69 +501,44 @@ def call_userdata(self, other_args: List[str]): help="Folder where to store user data. ", default=f"{str(Path.home() / 'OpenBBUserData')}", ) + parser.add_argument( + "--default", + action="store", + dest="default", + default=False, + type=bool, + help="Revert to the default path.", + ) if other_args and "-" not in other_args[0][0]: other_args.insert(0, "--folder") ns_parser = self.parse_simple_args(parser, other_args) - if ns_parser and (other_args or self.queue): - userdata_path = "" if other_args else "/" + if not (ns_parser and (other_args or self.queue)): + return - userdata_path += "/".join([ns_parser.folder] + self.queue) - self.queue = [] + if ns_parser.default: + save_file(Path.home() / "OpenBBUserData") - userdata_path = userdata_path.replace("'", "").replace('"', "") + userdata_path = "" if other_args else "/" + userdata_path += "/".join([ns_parser.folder] + self.queue) + userdata_path = userdata_path.replace("'", "").replace('"', "") + # If the path selected does not start from the user root, give relative location from root + if userdata_path[0] == "~": + userdata_path = userdata_path.replace("~", os.path.expanduser("~")) - default_path = Path.home() / "OpenBBUserData" + self.queue = [] + # Check if the directory exists + if os.path.isdir(userdata_path): + save_file(userdata_path) + return - success_userdata = False - while not success_userdata: - if userdata_path.upper() == "DEFAULT": - console.print( - f"User data to be saved in the default folder: '{default_path}'" - ) - self.set_and_save_preference("USER_DATA_DIRECTORY", default_path) - success_userdata = True - else: - # If the path selected does not start from the user root, give relative location from root - if userdata_path[0] == "~": - userdata_path = userdata_path.replace( - "~", os.path.expanduser("~") - ) - - # Check if the directory exists - if os.path.isdir(userdata_path): - console.print( - f"User data to be saved in the selected folder: '{userdata_path}'" - ) - self.set_and_save_preference( - "USER_DATA_DIRECTORY", userdata_path - ) - success_userdata = True - else: - console.print( - "[red]The path selected to user data does not exist![/red]\n" - ) - user_opt = "None" - while user_opt not in ("Y", "N"): - user_opt = input( - f"Do you wish to create folder: `{userdata_path}` ? [Y/N]\n" - ).upper() - - if user_opt == "Y": - os.makedirs(userdata_path) - console.print( - f"[green]Folder '{userdata_path}' successfully created.[/green]" - ) - self.set_and_save_preference( - "USER_DATA_DIRECTORY", userdata_path - ) - else: - # Do not update userdata_folder path since we will keep the same as before - console.print( - "[yellow]User data to keep being saved in " - + "the selected folder: " - + f"{str(get_current_user().preferences.USER_DATA_DIRECTORY)}[/yellow]" - ) - success_userdata = True - - console.print() + user_opt = input( + f"Path `{userdata_path}` does not exist, do you wish to create it? [Y/N]\n" + ) + + if user_opt.upper() == "Y": + os.makedirs(userdata_path) + console.print( + f"[green]Folder '{userdata_path}' successfully created.[/green]" + ) + save_file(userdata_path) From d6604a2975b4d295e2714029bcd22b82d06f09d7 Mon Sep 17 00:00:00 2001 From: colin99d Date: Mon, 21 Aug 2023 15:52:41 -0400 Subject: [PATCH 02/20] Bumped ruff --- .../behavioural_analysis/reddit_helpers.py | 2 +- openbb_terminal/core/plots/backend.py | 6 +- openbb_terminal/core/sdk/sdk_init.py | 207 +------ .../dashboards/stream/pages/Indicators.py | 1 - .../dashboards/stream/pages/Options.py | 18 +- .../econometrics/econometrics_controller.py | 5 +- openbb_terminal/etf/fmp_model.py | 2 +- openbb_terminal/forex/forex_helper.py | 2 +- openbb_terminal/forex/polygon_model.py | 2 +- .../portfolio_optimization/optimizer_model.py | 12 +- .../portfolio_optimization/optimizer_view.py | 7 +- .../portfolio_optimization/po_view.py | 10 +- .../yahoo_finance_model.py | 6 +- .../stocks/dark_pool_shorts/ibkr_model.py | 2 +- .../stocks/fundamental_analysis/dcf_model.py | 2 +- .../yahoo_finance_model.py | 2 +- .../quantitative_analysis/factors_model.py | 2 +- openbb_terminal/stocks/stocks_helper.py | 4 +- openbb_terminal/stocks/stocks_model.py | 2 +- poetry.lock | 536 ++++++++++++++++-- pyproject.toml | 5 +- .../covid/test_covid_controller.py | 1 - .../alternative/oss/test_oss_controller.py | 1 - .../alternative/test_alt_controller.py | 1 - .../test_formatter_with_exceptions.py | 2 +- .../defi/test_defi_controller.py | 1 - .../discovery/test_discovery_controller.py | 1 - .../cryptocurrency/nft/test_nft_controller.py | 1 - .../onchain/test_onchain_controller.py | 1 - .../tools/test_tools_controller.py | 1 - .../futures/test_futures_controller.py | 1 - .../test_mutual_fund_controller.py | 1 - .../brokers/degiro/test_degiro_controller.py | 1 - .../portfolio/test_portfolio_controller.py | 1 - .../reports/test_reports_controller.py | 1 - .../stocks/discovery/test_disc_controller.py | 1 - .../test_fa_controller.py | 1 - .../stocks/insider/test_openinsider_view.py | 1 - website/controller_doc_classes.py | 9 +- 39 files changed, 564 insertions(+), 298 deletions(-) diff --git a/openbb_terminal/common/behavioural_analysis/reddit_helpers.py b/openbb_terminal/common/behavioural_analysis/reddit_helpers.py index 01491496bc89..4c75478464f5 100644 --- a/openbb_terminal/common/behavioural_analysis/reddit_helpers.py +++ b/openbb_terminal/common/behavioural_analysis/reddit_helpers.py @@ -157,7 +157,7 @@ def validate( ) -> None: """Validate tickers.""" valids = [] - with urllib.request.urlopen(url) as file: + with urllib.request.urlopen(url) as file: # noqa: S310 for line in file: new_item = line.decode("utf-8").replace("\n", "").strip() valids.append(new_item) diff --git a/openbb_terminal/core/plots/backend.py b/openbb_terminal/core/plots/backend.py index af6a29e29473..97a337bf800a 100644 --- a/openbb_terminal/core/plots/backend.py +++ b/openbb_terminal/core/plots/backend.py @@ -242,10 +242,12 @@ async def process_image(self, export_image: Path): if get_current_user().preferences.PLOT_OPEN_EXPORT: if sys.platform == "win32": - os.startfile(export_image) # nosec: B606 + os.startfile(export_image) # noqa: S606 # nosec: B606 else: opener = "open" if sys.platform == "darwin" else "xdg-open" - subprocess.check_call([opener, export_image]) # nosec: B603 + subprocess.check_call( + [opener, export_image] + ) # nosec: B603 # noqa: S603 def send_table( self, diff --git a/openbb_terminal/core/sdk/sdk_init.py b/openbb_terminal/core/sdk/sdk_init.py index 660500334239..1375236e1896 100644 --- a/openbb_terminal/core/sdk/sdk_init.py +++ b/openbb_terminal/core/sdk/sdk_init.py @@ -7,111 +7,52 @@ # Session -from openbb_terminal.core.session import sdk_session - - # Alternative - - import openbb_terminal.alternative.hackernews_model as alt_hackernews_model - - import openbb_terminal.alternative.hackernews_view as alt_hackernews_view - - import openbb_terminal.alternative.oss.github_model as alt_oss_github_model - - import openbb_terminal.alternative.oss.github_view as alt_oss_github_view - - import openbb_terminal.alternative.oss.runa_model as alt_oss_runa_model - - import openbb_terminal.alternative.oss.runa_view as alt_oss_runa_view - - import openbb_terminal.alternative.realestate.landRegistry_model as alt_realestate_landRegistry_model - # Crypto Helpers - - import openbb_terminal.cryptocurrency.cryptocurrency_helpers as crypto_helpers - # ETF - - import openbb_terminal.etf.discovery.wsj_model as etf_disc_wsj_model - - import openbb_terminal.etf.discovery.wsj_view as etf_disc_wsj_view - - -# Forex Helpers - - -import openbb_terminal.forex.forex_helper as forex_helper - - import openbb_terminal.forex.oanda.oanda_model as forex_oanda_model - - import openbb_terminal.forex.oanda.oanda_view as forex_oanda_view - - -# Keys - - -import openbb_terminal.keys_model as keys_model - - import openbb_terminal.stocks.options.hedge.hedge_model as stocks_options_hedge_model - - import openbb_terminal.stocks.options.hedge.hedge_view as stocks_options_hedge_view - - import openbb_terminal.stocks.quantitative_analysis.beta_model as stocks_qa_beta_model - - import openbb_terminal.stocks.quantitative_analysis.beta_view as stocks_qa_beta_view - # Stocks - Quantitative Analysis - - import openbb_terminal.stocks.quantitative_analysis.factors_model as stocks_qa_factors_model - - import openbb_terminal.stocks.quantitative_analysis.factors_view as stocks_qa_factors_view - +# Keys +from openbb_terminal import keys_model from openbb_terminal.alternative.covid import ( covid_model as alt_covid_model, covid_view as alt_covid_view, ) - # Common - - from openbb_terminal.common import ( common_model, feedparser_model as common_feedparser_model, feedparser_view as common_feedparser_view, - ultima_newsmonitor_model as common_ultima_newsmonitor_model, - ultima_newsmonitor_view as common_ultima_newsmonitor_view, + news_sdk_helper as common_news_sdk_helper, newsapi_model as common_newsapi_model, newsapi_view as common_newsapi_view, - news_sdk_helper as common_news_sdk_helper, + ultima_newsmonitor_model as common_ultima_newsmonitor_model, + ultima_newsmonitor_view as common_ultima_newsmonitor_view, ) - # Common Behavioural Analysis - - from openbb_terminal.common.behavioural_analysis import ( finbrain_model as stocks_ba_finbrain_model, finbrain_view as stocks_ba_finbrain_view, @@ -123,10 +64,7 @@ stocktwits_view as stocks_ba_stocktwits_view, ) - # Common Quantitative Analysis - - from openbb_terminal.common.quantitative_analysis import ( qa_model as common_qa_model, qa_view as common_qa_view, @@ -134,10 +72,7 @@ rolling_view as common_qa_rolling_view, ) - # Common Technical Analysis - - from openbb_terminal.common.technical_analysis import ( custom_indicators_model as common_ta_custom_indicators_model, custom_indicators_view as common_ta_custom_indicators_view, @@ -152,17 +87,13 @@ volume_model as common_ta_volume_model, volume_view as common_ta_volume_view, ) - - +from openbb_terminal.core.session import sdk_session from openbb_terminal.cryptocurrency import ( crypto_models, pyth_view as crypto_pyth_view, ) - # Cryptocurrency Defi - - from openbb_terminal.cryptocurrency.defi import ( coindix_model as crypto_defi_coindix_model, coindix_view as crypto_defi_coindix_view, @@ -180,28 +111,22 @@ terramoney_fcd_view as crypto_defi_terramoney_fcd_view, ) - # Cryptocurrency Discovery - - from openbb_terminal.cryptocurrency.discovery import ( coinmarketcap_model as crypto_disc_coinmarketcap_model, coinmarketcap_view as crypto_disc_coinmarketcap_view, coinpaprika_model as crypto_disc_coinpaprika_model, coinpaprika_view as crypto_disc_coinpaprika_view, + cryptostats_model as crypto_disc_cryptostats_model, + cryptostats_view as crypto_disc_cryptostats_view, dappradar_model as crypto_disc_dappradar_model, dappradar_view as crypto_disc_dappradar_view, pycoingecko_model as crypto_disc_pycoingecko_model, pycoingecko_view as crypto_disc_pycoingecko_view, - cryptostats_model as crypto_disc_cryptostats_model, - cryptostats_view as crypto_disc_cryptostats_view, sdk_helpers as crypto_disc_sdk_helpers, ) - # Cryptocurrency Due Diligence - - from openbb_terminal.cryptocurrency.due_diligence import ( binance_model as crypto_dd_binance_model, binance_view as crypto_dd_binance_view, @@ -226,10 +151,7 @@ sdk_helper as crypto_dd_sdk_helper, ) - # Cryptocurrency NFT - - from openbb_terminal.cryptocurrency.nft import ( nftpricefloor_model as crypto_nft_pricefloor_model, nftpricefloor_view as crypto_nft_pricefloor_view, @@ -237,10 +159,7 @@ opensea_view as crypto_nft_opensea_view, ) - # Cryptocurrency Onchain - - from openbb_terminal.cryptocurrency.onchain import ( bitquery_model as crypto_onchain_bitquery_model, bitquery_view as crypto_onchain_bitquery_view, @@ -250,18 +169,15 @@ ethgasstation_view as crypto_onchain_ethgasstation_view, ethplorer_model as crypto_onchain_ethplorer_model, ethplorer_view as crypto_onchain_ethplorer_view, - whale_alert_model as crypto_onchain_whale_alert_model, - whale_alert_view as crypto_onchain_whale_alert_view, shroom_model as crypto_onchain_shroom_model, shroom_view as crypto_onchain_shroom_view, topledger_model as crypto_onchain_topledger_model, topledger_view as crypto_onchain_topledger_view, + whale_alert_model as crypto_onchain_whale_alert_model, + whale_alert_view as crypto_onchain_whale_alert_view, ) - # Cryptocurrency Overview - - from openbb_terminal.cryptocurrency.overview import ( blockchaincenter_model as crypto_ov_blockchaincenter_model, blockchaincenter_view as crypto_ov_blockchaincenter_view, @@ -284,19 +200,13 @@ withdrawalfees_view as crypto_ov_withdrawalfees_view, ) - # Cryptocurrency Tools - - from openbb_terminal.cryptocurrency.tools import ( tools_model as crypto_tools_model, tools_view as crypto_tools_view, ) - # Econometrics - - from openbb_terminal.econometrics import ( econometrics_model, econometrics_view, @@ -304,88 +214,69 @@ regression_view as econometrics_regression_view, ) - -# Fixedincome - - -from openbb_terminal.fixedincome import ( - fred_model as fixedincome_fred_model, - ecb_model as fixedincome_ecb_model, - oecd_model as fixedincome_oecd_model, - fred_view as fixedincome_fred_view, -) - - # Economy - - from openbb_terminal.economy import ( econdb_model as economy_econdb_model, econdb_view as economy_econdb_view, + fedreserve_model as economy_fedreserve_model, + fedreserve_view as economy_fedreserve_view, finviz_model as economy_finviz_model, finviz_view as economy_finviz_view, fred_model as economy_fred_model, fred_view as economy_fred_view, nasdaq_model as economy_nasdaq_model, nasdaq_view as economy_nasdaq_view, + oecd_model as economy_oecd_model, + oecd_view as economy_oecd_view, sdk_helpers as economy_sdk_helpers, wsj_model as economy_wsj_model, yfinance_model as economy_yfinance_model, yfinance_view as economy_yfinance_view, - oecd_model as economy_oecd_model, - oecd_view as economy_oecd_view, - fedreserve_model as economy_fedreserve_model, - fedreserve_view as economy_fedreserve_view, ) - # ETF's - - from openbb_terminal.etf import ( financedatabase_model as etf_financedatabase_model, financedatabase_view as etf_financedatabase_view, - stockanalysis_model as etf_stockanalysis_model, - stockanalysis_view as etf_stockanalysis_view, fmp_model as etf_fmp_model, fmp_view as etf_fmp_view, + stockanalysis_model as etf_stockanalysis_model, + stockanalysis_view as etf_stockanalysis_view, ) +# Fixedincome +from openbb_terminal.fixedincome import ( + ecb_model as fixedincome_ecb_model, + fred_model as fixedincome_fred_model, + fred_view as fixedincome_fred_view, + oecd_model as fixedincome_oecd_model, +) +# Forex Helpers # Forex - - from openbb_terminal.forex import ( av_model as forex_av_model, av_view as forex_av_view, + forex_helper, fxempire_model as forex_fxempire_model, fxempire_view as forex_fxempire_view, sdk_helpers as forex_sdk_helpers, ) - -# Funds - - -from openbb_terminal.mutual_funds import ( - mstarpy_model as funds_mstarpy_model, - mstarpy_view as funds_mstarpy_view, -) - - # Futures - - from openbb_terminal.futures import ( + sdk_helper as futures_sdk_model, yfinance_model as futures_yfinance_model, yfinance_view as futures_yfinance_view, - sdk_helper as futures_sdk_model, ) +# Funds +from openbb_terminal.mutual_funds import ( + mstarpy_model as funds_mstarpy_model, + mstarpy_view as funds_mstarpy_view, +) # Stocks Helpers - - from openbb_terminal.stocks import ( cboe_model as stocks_cboe_model, cboe_view as stocks_cboe_view, @@ -394,10 +285,7 @@ stocks_view, ) - # Stocks -Behavioral Analysis - - from openbb_terminal.stocks.behavioural_analysis import ( finnhub_model as stocks_ba_finnhub_model, finnhub_view as stocks_ba_finnhub_view, @@ -405,10 +293,7 @@ news_sentiment_view as stocks_ba_news_sentiment_view, ) - # Stocks - Comparison Analysis - - from openbb_terminal.stocks.comparison_analysis import ( finbrain_model as stocks_ca_finbrain_model, finbrain_view as stocks_ca_finbrain_view, @@ -422,10 +307,7 @@ yahoo_finance_view as stocks_ca_yahoo_finance_view, ) - # Stocks - Dark Pool Shorts - - from openbb_terminal.stocks.dark_pool_shorts import ( finra_model as stocks_dps_finra_model, finra_view as stocks_dps_finra_view, @@ -442,10 +324,7 @@ yahoofinance_model as stocks_dps_yahoofinance_model, ) - # Stocks - Fundamental Discovery - - from openbb_terminal.stocks.discovery import ( ark_model as stocks_disc_ark_model, finnhub_model as stocks_disc_finnhub_model, @@ -456,10 +335,7 @@ yahoofinance_model as stocks_disc_yahoofinance_model, ) - # Stocks - Fundamental Analysis - - from openbb_terminal.stocks.fundamental_analysis import ( av_model as stocks_fa_av_model, av_view as stocks_fa_av_view, @@ -487,19 +363,13 @@ yahoo_finance_view as stocks_fa_yahoo_finance_view, ) - # Government - - from openbb_terminal.stocks.government import ( quiverquant_model as stocks_gov_quiverquant_model, quiverquant_view as stocks_gov_quiverquant_view, ) - # Stocks - Insider Trading - - from openbb_terminal.stocks.insider import ( businessinsider_model as stocks_insider_businessinsider_model, businessinsider_view as stocks_insider_businessinsider_view, @@ -510,10 +380,7 @@ sdk_helper as stocks_insider_sdk_helper, ) - # Stocks - Options - - from openbb_terminal.stocks.options import ( alphaquery_model as stocks_options_alphaquery_model, alphaquery_view as stocks_options_alphaquery_view, @@ -536,17 +403,12 @@ yfinance_model as stocks_options_yfinance_model, yfinance_view as stocks_options_yfinance_view, ) - - from openbb_terminal.stocks.screener import ( finviz_model as stocks_screener_finviz_model, finviz_view as stocks_screener_finviz_view, ) - # Stocks - Technical Analysis - - from openbb_terminal.stocks.technical_analysis import ( finbrain_model as stocks_ta_finbrain_model, finbrain_view as stocks_ta_finbrain_view, @@ -554,16 +416,12 @@ tradingview_view as stocks_ta_tradingview_view, ) - # Stocks - Trading Hours - - from openbb_terminal.stocks.tradinghours import ( bursa_model as stocks_th_bursa_model, bursa_view as stocks_th_bursa_view, ) - # Forecast Extras @@ -571,9 +429,7 @@ import darts # pyright: reportMissingImports=false # If you just import darts this will pass during pip install, this creates - # Failures later on, also importing utils ensures that darts is installed correctly - from darts import utils FORECASTING_TOOLKIT_ENABLED = True @@ -632,7 +488,6 @@ from openbb_terminal.portfolio import portfolio_model, portfolio_view - try: # pylint: disable=W0611 # noqa: F401 # pyright: reportMissingImports=false diff --git a/openbb_terminal/dashboards/stream/pages/Indicators.py b/openbb_terminal/dashboards/stream/pages/Indicators.py index 43b723e989f5..46fa14e9f075 100644 --- a/openbb_terminal/dashboards/stream/pages/Indicators.py +++ b/openbb_terminal/dashboards/stream/pages/Indicators.py @@ -109,7 +109,6 @@ async def plot_indicators( rows = fig.subplots_kwargs["rows"] for ticker in tickers: - ticker = ticker df_ticker = st.session_state["indicators_dfs"][ticker] df_ticker["% Change"] = df_ticker["Close"].apply( lambda x: (x - df_ticker["Close"].iloc[0]) / df_ticker["Close"].iloc[0] diff --git a/openbb_terminal/dashboards/stream/pages/Options.py b/openbb_terminal/dashboards/stream/pages/Options.py index 6c1195be4d24..a089b8cdeb7a 100644 --- a/openbb_terminal/dashboards/stream/pages/Options.py +++ b/openbb_terminal/dashboards/stream/pages/Options.py @@ -325,7 +325,7 @@ def get_highest_volume(df: OptionsChains) -> pd.DataFrame: options=["Open Interest", "Volume", "Ratios"], key="stats_type", ) - if stats_type == "Open Interest" or stats_type == "Volume": + if stats_type in ("Open Interest", "Volume"): is_percent = st.checkbox( "Percent of Total", value=False, key="is_percent" ) @@ -437,10 +437,7 @@ def get_highest_volume(df: OptionsChains) -> pd.DataFrame: index=default_strike, key="straddle_strike", ) - if ( - strategy_choice == "Synthetic Long" - or strategy_choice == "Synthetic Short" - ): + if strategy_choice in ("Synthetic Long", "Synthetic Short"): default_strike_price = get_nearest_call_strike( df, strike_price=df.last_price ) @@ -453,10 +450,7 @@ def get_highest_volume(df: OptionsChains) -> pd.DataFrame: index=default_strike, key="synthetic_strike", ) - if ( - strategy_choice == "Vertical Call" - or strategy_choice == "Vertical Put" - ): + if strategy_choice in ("Vertical Call", "Vertical Put"): default_strike_price1 = get_nearest_call_strike( df, strike_price=df.last_price + 5 @@ -499,7 +493,7 @@ def get_highest_volume(df: OptionsChains) -> pd.DataFrame: vol_choice = st.selectbox( "Volatility Type", options=vol_choices, index=0, key="vol_choice" ) - if vol_choice == "Smile" or vol_choice == "Skew": + if vol_choice in ("Smile", "Skew"): if vol_choice == "Smile": col1, col2 = st.columns(2) with col1: @@ -658,7 +652,7 @@ def get_highest_volume(df: OptionsChains) -> pd.DataFrame: use_container_width=True, ) - elif stats_type == "Open Interest" or stats_type == "Volume": + elif stats_type in ("Open Interest", "Volume"): tab1, tab2 = st.tabs(["By Expiration", "By Strike"]) with tab1: if stats_type == "Open Interest": @@ -737,7 +731,7 @@ def get_highest_volume(df: OptionsChains) -> pd.DataFrame: ) price_data["Call"] = call_price_data[target_column[strike_data_point]] price_data["Put"] = put_price_data[target_column[strike_data_point]] - if strike_choice == "Separate Calls and Puts" or strike_choice == "% OTM": + if strike_choice in ("Separate Calls and Puts", "% OTM"): call_price_data = ( df.chains[df.chains["strike"] == _strikes["call"]] .query("`optionType` == 'call'") diff --git a/openbb_terminal/econometrics/econometrics_controller.py b/openbb_terminal/econometrics/econometrics_controller.py index 5229e030e5ac..550c617b5601 100644 --- a/openbb_terminal/econometrics/econometrics_controller.py +++ b/openbb_terminal/econometrics/econometrics_controller.py @@ -409,10 +409,7 @@ def call_load(self, other_args: List[str]): if ns_parser.alias: alias = ns_parser.alias else: - if "." in ns_parser.file: - alias = ".".join(ns_parser.file.split(".")[:-1]) - else: - alias = ns_parser.file + alias = ".".join(ns_parser.file.split(".")[:-1]) if "." in ns_parser.file else ns_parser.file # check if this dataset has been added already if alias in self.files: diff --git a/openbb_terminal/etf/fmp_model.py b/openbb_terminal/etf/fmp_model.py index 303367dac6c7..26b8cfc99db8 100644 --- a/openbb_terminal/etf/fmp_model.py +++ b/openbb_terminal/etf/fmp_model.py @@ -31,7 +31,7 @@ def get_etf_sector_weightings(name: str) -> Dict: Dictionary with sector weightings allocation """ try: - response = urlopen( + response = urlopen( # noqa: S310 "https://financialmodelingprep.com/api/v3/etf-sector-weightings/" f"{name}?apikey={get_current_user().credentials.API_KEY_FINANCIALMODELINGPREP}" ) diff --git a/openbb_terminal/forex/forex_helper.py b/openbb_terminal/forex/forex_helper.py index 636bcda32822..c07a725fa8a2 100644 --- a/openbb_terminal/forex/forex_helper.py +++ b/openbb_terminal/forex/forex_helper.py @@ -134,7 +134,7 @@ def load( if source in ["YahooFinance", "AlphaVantage"]: interval_map = INTERVAL_MAPS[source] - if interval not in interval_map.keys() and resolution != "d": + if interval not in interval_map and resolution != "d": if verbose: console.print( f"Interval not supported by {FOREX_SOURCES[source]}." diff --git a/openbb_terminal/forex/polygon_model.py b/openbb_terminal/forex/polygon_model.py index 07791f30e661..99029c9f7450 100644 --- a/openbb_terminal/forex/polygon_model.py +++ b/openbb_terminal/forex/polygon_model.py @@ -59,7 +59,7 @@ def get_historical( console.print(f"[red]{json_response['error']}[/red]\n") return pd.DataFrame() - if "results" not in json_response.keys(): + if "results" not in json_response: console.print("[red]Error in polygon request[/red]\n") return pd.DataFrame() diff --git a/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py b/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py index d31d27a6fd42..219556a1e65c 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py +++ b/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py @@ -17,13 +17,13 @@ from scipy.interpolate import interp1d from openbb_terminal.decorators import log_start_end -from openbb_terminal.stocks.fundamental_analysis import fmp_model from openbb_terminal.portfolio.portfolio_optimization import yahoo_finance_model from openbb_terminal.portfolio.portfolio_optimization.optimizer_helper import ( get_kwarg, validate_risk_measure, ) from openbb_terminal.rich_config import console +from openbb_terminal.stocks.fundamental_analysis import fmp_model logger = logging.getLogger(__name__) @@ -1271,10 +1271,7 @@ def get_max_decorrelation_portfolio( if weights is not None: weights = weights.round(5) - if len(weights) > 1: - weights = weights.squeeze().to_dict() - else: - weights = weights.to_dict() + weights = weights.squeeze().to_dict() if len(weights) > 1 else weights.to_dict() return weights, stock_returns @@ -2876,10 +2873,7 @@ def black_litterman( delta = (a - risk_free_rate) / (benchmark.T @ S @ benchmark) delta = delta.item() - if equilibrium: - PI_eq = delta * (S @ benchmark) - else: - PI_eq = mu - risk_free_rate + PI_eq = delta * (S @ benchmark) if equilibrium else mu - risk_free_rate flag = False if p_views is None or q_views is None: diff --git a/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py b/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py index bc919ee926f8..1ee58e23d991 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py +++ b/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py @@ -21,10 +21,10 @@ from matplotlib.gridspec import GridSpec from matplotlib.lines import Line2D +from openbb_terminal.config_terminal import theme # IMPORTS INTERNAL from openbb_terminal.core.session.current_user import get_current_user -from openbb_terminal.config_terminal import theme from openbb_terminal.decorators import log_start_end from openbb_terminal.helper_funcs import plot_autoscale, print_rich_table from openbb_terminal.portfolio.portfolio_optimization import ( @@ -3975,10 +3975,7 @@ def additional_plots( figsize=plot_autoscale(), dpi=get_current_user().preferences.PLOT_DPI ) - if len(weights) <= 3: - number_of_clusters = len(weights) - else: - number_of_clusters = None + number_of_clusters = len(weights) if len(weights) <= 3 else None ax = rp.plot_clusters( returns=data, diff --git a/openbb_terminal/portfolio/portfolio_optimization/po_view.py b/openbb_terminal/portfolio/portfolio_optimization/po_view.py index 37a1aa466b57..fdeea1f30a77 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/po_view.py +++ b/openbb_terminal/portfolio/portfolio_optimization/po_view.py @@ -6,9 +6,9 @@ # IMPORTS STANDARD import logging -from typing import Optional import math import warnings +from typing import Optional # IMPORTATION THIRDPARTY import matplotlib @@ -19,9 +19,10 @@ from matplotlib.gridspec import GridSpec from matplotlib.lines import Line2D +from openbb_terminal.config_terminal import theme + # IMPORTATION INTERNAL from openbb_terminal.core.session.current_user import get_current_user -from openbb_terminal.config_terminal import theme from openbb_terminal.decorators import log_start_end from openbb_terminal.helper_funcs import plot_autoscale from openbb_terminal.portfolio.portfolio_optimization.optimizer_helper import get_kwarg @@ -418,10 +419,7 @@ def display_heat(**kwargs): figsize=plot_autoscale(), dpi=get_current_user().preferences.PLOT_DPI ) - if len(weights) <= 3: - number_of_clusters = len(weights) - else: - number_of_clusters = None + number_of_clusters = len(weights) if len(weights) <= 3 else None ax = rp.plot_clusters( returns=data, diff --git a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py index 76865af38564..ac358eb4ba1a 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py +++ b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py @@ -191,7 +191,7 @@ def process_stocks( # Checking if exist if os.path.exists(name): - stock_closes_0 = pd.read_pickle(name) + stock_closes_0 = pd.read_pickle(name) # noqa: S301 list_of_stocks_0 = list(set(symbols) - set(stock_closes_0.columns)) else: stock_closes_0 = None @@ -219,7 +219,7 @@ def process_stocks( # Creating if exist if os.path.exists(name): - stock_closes_0 = pd.read_pickle(name) + stock_closes_0 = pd.read_pickle(name) # noqa: S301 list_of_stocks_0 = list(set(symbols) - set(stock_closes_0.columns)) else: stock_closes_0 = None @@ -265,7 +265,7 @@ def process_stocks( # Checking if temporal file exists if os.path.exists(name): - stock_closes_0 = pd.read_pickle(name) + stock_closes_0 = pd.read_pickle(name) # noqa: S301 list_of_stocks_0 = list(set(symbols) - set(stock_closes_0.columns)) else: stock_closes_0 = None diff --git a/openbb_terminal/stocks/dark_pool_shorts/ibkr_model.py b/openbb_terminal/stocks/dark_pool_shorts/ibkr_model.py index f3602d4d97c4..add7c2f1cf3c 100644 --- a/openbb_terminal/stocks/dark_pool_shorts/ibkr_model.py +++ b/openbb_terminal/stocks/dark_pool_shorts/ibkr_model.py @@ -21,7 +21,7 @@ def get_cost_to_borrow() -> pd.DataFrame: pd.DataFrame Cost to borrow """ - ftp = ftplib.FTP("ftp3.interactivebrokers.com", "shortstock") + ftp = ftplib.FTP("ftp3.interactivebrokers.com", "shortstock") # noqa: S321 flo = BytesIO() ftp.retrbinary("RETR usa.txt", flo.write) diff --git a/openbb_terminal/stocks/fundamental_analysis/dcf_model.py b/openbb_terminal/stocks/fundamental_analysis/dcf_model.py index 23b25ced19a1..801fc1d8abce 100644 --- a/openbb_terminal/stocks/fundamental_analysis/dcf_model.py +++ b/openbb_terminal/stocks/fundamental_analysis/dcf_model.py @@ -243,7 +243,7 @@ def get_fama_raw() -> pd.DataFrame: df : pd.DataFrame Fama French data """ - with urlopen( # noqa: SIM117 + with urlopen( # noqa: SIM117,S310 "https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip" ) as url: # Download Zipfile and create pandas DataFrame diff --git a/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py b/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py index 72f0fc7d533e..537db6f1ffa8 100644 --- a/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py +++ b/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py @@ -294,7 +294,7 @@ def get_financials(symbol: str, statement: str, ratios: bool = False) -> pd.Data # Making the website believe that you are accessing it using a Mozilla browser req = Request(url, headers={"User-Agent": "Mozilla/5.0"}) - webpage = urlopen(req).read() # pylint: disable= R1732 + webpage = urlopen(req).read() # pylint: disable= R1732 # noqa: S310 soup = BeautifulSoup(webpage, "html.parser") features = soup.find_all("div", class_="D(tbr)") diff --git a/openbb_terminal/stocks/quantitative_analysis/factors_model.py b/openbb_terminal/stocks/quantitative_analysis/factors_model.py index 2fd0e124d1af..c04e517350aa 100644 --- a/openbb_terminal/stocks/quantitative_analysis/factors_model.py +++ b/openbb_terminal/stocks/quantitative_analysis/factors_model.py @@ -25,7 +25,7 @@ def get_fama_raw() -> pd.DataFrame: fama : pd.DataFrame A data with fama french model information """ - with urlopen( + with urlopen( # noqa: S310 "http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip" ) as url: # Download Zipfile and create pandas DataFrame diff --git a/openbb_terminal/stocks/stocks_helper.py b/openbb_terminal/stocks/stocks_helper.py index 28f4a722798c..2a955caef05a 100644 --- a/openbb_terminal/stocks/stocks_helper.py +++ b/openbb_terminal/stocks/stocks_helper.py @@ -450,7 +450,7 @@ def load( # pylint: disable=too-many-return-statements return pd.DataFrame() r_json = r.json() - if "results" not in r_json.keys(): + if "results" not in r_json: console.print("[red]No results found in polygon reply.[/red]") return pd.DataFrame() @@ -940,7 +940,7 @@ def show_codes_polygon(ticker: str): console.print("[red]Error in polygon request[/red]\n") return r_json = r.json() - if "results" not in r_json.keys(): + if "results" not in r_json: console.print("[red]Results not found in polygon request[/red]") return r_json = r_json["results"] diff --git a/openbb_terminal/stocks/stocks_model.py b/openbb_terminal/stocks/stocks_model.py index b4c1d72c72ac..56bdde3f8129 100644 --- a/openbb_terminal/stocks/stocks_model.py +++ b/openbb_terminal/stocks/stocks_model.py @@ -290,7 +290,7 @@ def load_stock_polygon( return pd.DataFrame() r_json = r.json() - if "results" not in r_json.keys(): + if "results" not in r_json: console.print("[red]No results found in polygon reply.[/red]") return pd.DataFrame() diff --git a/poetry.lock b/poetry.lock index 26737938fd50..78029168582a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand. [[package]] name = "absl-py" version = "1.4.0" description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -15,6 +16,7 @@ files = [ name = "adagio" version = "0.2.4" description = "The Dag IO Framework for Fugue projects" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -29,6 +31,7 @@ triad = ">=0.6.1" name = "aiodns" version = "3.0.0" description = "Simple DNS resolver for asyncio" +category = "main" optional = false python-versions = "*" files = [ @@ -43,6 +46,7 @@ pycares = ">=4.0.0" name = "aiofiles" version = "22.1.0" description = "File support for asyncio." +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -54,6 +58,7 @@ files = [ name = "aiohttp" version = "3.8.5" description = "Async http client/server framework (asyncio)" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -162,6 +167,7 @@ speedups = ["Brotli", "aiodns", "cchardet"] name = "aiosignal" version = "1.3.1" description = "aiosignal: a list of registered asynchronous callbacks" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -176,6 +182,7 @@ frozenlist = ">=1.1.0" name = "aiosqlite" version = "0.19.0" description = "asyncio bridge to the standard sqlite3 module" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -191,6 +198,7 @@ docs = ["sphinx (==6.1.3)", "sphinx-mdinclude (==0.5.3)"] name = "alabaster" version = "0.7.13" description = "A configurable sidebar-enabled Sphinx theme" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -202,6 +210,7 @@ files = [ name = "alpha-vantage" version = "2.3.1" description = "Python module to get stock data from the Alpha Vantage Api" +category = "main" optional = false python-versions = "*" files = [ @@ -217,6 +226,7 @@ requests = "*" name = "altair" version = "5.0.1" description = "Vega-Altair: A declarative statistical visualization library for Python." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -240,6 +250,7 @@ doc = ["docutils", "geopandas", "jinja2", "myst-parser", "numpydoc", "pillow", " name = "altgraph" version = "0.17.3" description = "Python graph (network) package" +category = "main" optional = true python-versions = "*" files = [ @@ -251,6 +262,7 @@ files = [ name = "ansi2html" version = "1.8.0" description = "" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -266,6 +278,7 @@ test = ["pytest", "pytest-cov"] name = "ansiwrap" version = "0.8.4" description = "textwrap, but savvy to ANSI colors and styles" +category = "main" optional = false python-versions = "*" files = [ @@ -280,6 +293,7 @@ textwrap3 = ">=0.9.2" name = "antlr4-python3-runtime" version = "4.11.1" description = "ANTLR 4.11.1 runtime for Python 3" +category = "main" optional = true python-versions = "*" files = [ @@ -291,6 +305,7 @@ files = [ name = "anyio" version = "3.7.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -312,6 +327,7 @@ trio = ["trio (<0.22)"] name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" optional = false python-versions = "*" files = [ @@ -323,6 +339,7 @@ files = [ name = "appnope" version = "0.1.3" description = "Disable App Nap on macOS >= 10.9" +category = "main" optional = false python-versions = "*" files = [ @@ -334,6 +351,7 @@ files = [ name = "arch" version = "5.6.0" description = "ARCH for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -373,6 +391,7 @@ statsmodels = ">=0.11" name = "argon2-cffi" version = "21.3.0" description = "The secure Argon2 password hashing algorithm." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -392,6 +411,7 @@ tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"] name = "argon2-cffi-bindings" version = "21.2.0" description = "Low-level CFFI bindings for Argon2" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -429,6 +449,7 @@ tests = ["pytest"] name = "arrow" version = "1.2.3" description = "Better dates & times for Python" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -443,6 +464,7 @@ python-dateutil = ">=2.7.0" name = "ascii-magic" version = "1.6" description = "Converts pictures into ASCII art" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -458,6 +480,7 @@ Pillow = "*" name = "astor" version = "0.8.1" description = "Read/rewrite/write Python ASTs" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" files = [ @@ -469,6 +492,7 @@ files = [ name = "astroid" version = "2.15.6" description = "An abstract syntax tree for Python with inference support." +category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -485,6 +509,7 @@ wrapt = {version = ">=1.11,<2", markers = "python_version < \"3.11\""} name = "astropy" version = "5.2.2" description = "Astronomy and astrophysics core library" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -538,6 +563,7 @@ test-all = ["coverage[toml]", "ipython (>=4.2)", "objgraph", "pytest (>=7.0)", " name = "asttokens" version = "2.2.1" description = "Annotate AST trees with source code positions" +category = "main" optional = false python-versions = "*" files = [ @@ -555,6 +581,7 @@ test = ["astroid", "pytest"] name = "async-timeout" version = "4.0.2" description = "Timeout context manager for asyncio programs" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -566,6 +593,7 @@ files = [ name = "atomicwrites" version = "1.4.1" description = "Atomic file writes." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -576,6 +604,7 @@ files = [ name = "attrs" version = "21.4.0" description = "Classes Without Boilerplate" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -593,6 +622,7 @@ tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy" name = "babel" version = "2.12.1" description = "Internationalization utilities" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -607,6 +637,7 @@ pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} name = "backcall" version = "0.2.0" description = "Specifications for callback functions passed in to an API" +category = "main" optional = false python-versions = "*" files = [ @@ -618,6 +649,7 @@ files = [ name = "backoff" version = "2.2.1" description = "Function decoration for backoff and retry" +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -629,6 +661,7 @@ files = [ name = "backports-zoneinfo" version = "0.2.1" description = "Backport of the standard library zoneinfo module" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -657,6 +690,7 @@ tzdata = ["tzdata"] name = "bandit" version = "1.7.5" description = "Security oriented static analyser for python code." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -680,6 +714,7 @@ yaml = ["PyYAML"] name = "base58" version = "2.1.1" description = "Base58 and Base58Check implementation." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -694,6 +729,7 @@ tests = ["PyHamcrest (>=2.0.2)", "mypy", "pytest (>=4.6)", "pytest-benchmark", " name = "beautifulsoup4" version = "4.12.2" description = "Screen-scraping library" +category = "main" optional = false python-versions = ">=3.6.0" files = [ @@ -712,6 +748,7 @@ lxml = ["lxml"] name = "black" version = "23.7.0" description = "The uncompromising code formatter." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -758,6 +795,7 @@ uvloop = ["uvloop (>=0.15.2)"] name = "bleach" version = "6.0.0" description = "An easy safelist-based HTML-sanitizing tool." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -776,6 +814,7 @@ css = ["tinycss2 (>=1.1.0,<1.2)"] name = "blinker" version = "1.6.2" description = "Fast, simple object-to-object and broadcast signaling" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -787,6 +826,7 @@ files = [ name = "brotli" version = "1.0.9" description = "Python bindings for the Brotli compression library" +category = "main" optional = true python-versions = "*" files = [ @@ -878,6 +918,7 @@ files = [ name = "brotlicffi" version = "1.0.9.2" description = "Python CFFI bindings to the Brotli library" +category = "main" optional = true python-versions = "*" files = [ @@ -920,6 +961,7 @@ cffi = ">=1.0.0" name = "bs4" version = "0.0.1" description = "Dummy package for Beautiful Soup" +category = "main" optional = false python-versions = "*" files = [ @@ -933,6 +975,7 @@ beautifulsoup4 = "*" name = "bt" version = "0.2.9" description = "A flexible backtesting framework for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -958,6 +1001,7 @@ dev = ["black (>=20.8b1)", "codecov", "coverage", "cython (>=0.25)", "ffn (>=0.3 name = "cachetools" version = "5.3.1" description = "Extensible memoizing collections and decorators" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -969,6 +1013,7 @@ files = [ name = "catboost" version = "1.2" description = "CatBoost Python Package" +category = "main" optional = true python-versions = "*" files = [ @@ -1011,6 +1056,7 @@ widget = ["ipython", "ipywidgets (>=7.0,<9.0)", "traitlets"] name = "cattrs" version = "23.1.2" description = "Composable complex class support for attrs and dataclasses." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -1036,6 +1082,7 @@ ujson = ["ujson (>=5.4.0,<6.0.0)"] name = "ccxt" version = "4.0.33" description = "A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 130+ exchanges" +category = "main" optional = false python-versions = "*" files = [ @@ -1059,6 +1106,7 @@ qa = ["flake8 (==3.7.9)"] name = "certifi" version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1070,6 +1118,7 @@ files = [ name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = "*" files = [ @@ -1146,6 +1195,7 @@ pycparser = "*" name = "cfgv" version = "3.3.1" description = "Validate configuration and produce human readable error messages." +category = "dev" optional = false python-versions = ">=3.6.1" files = [ @@ -1157,6 +1207,7 @@ files = [ name = "charset-normalizer" version = "3.2.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -1241,6 +1292,7 @@ files = [ name = "click" version = "8.1.6" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1255,6 +1307,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "cloudpickle" version = "2.2.1" description = "Extended pickling support for Python objects" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -1266,6 +1319,7 @@ files = [ name = "cmdstanpy" version = "1.1.0" description = "Python interface to CmdStan" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -1287,6 +1341,7 @@ tests = ["flake8", "mypy", "pylint", "pytest", "pytest-cov", "pytest-order", "tq name = "codespell" version = "2.2.5" description = "Codespell" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1304,6 +1359,7 @@ types = ["chardet (>=5.1.0)", "mypy", "pytest", "pytest-cov", "pytest-dependency name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -1315,6 +1371,7 @@ files = [ name = "comm" version = "0.1.3" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1334,6 +1391,7 @@ typing = ["mypy (>=0.990)"] name = "commonmark" version = "0.9.1" description = "Python parser for the CommonMark Markdown spec" +category = "main" optional = false python-versions = "*" files = [ @@ -1348,6 +1406,7 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"] name = "contourpy" version = "1.1.0" description = "Python library for calculating contours of 2D quadrilateral grids" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1406,6 +1465,7 @@ test-no-images = ["pytest", "pytest-cov", "wurlitzer"] name = "convertdate" version = "2.4.0" description = "Converts between Gregorian dates and other calendar systems" +category = "main" optional = false python-versions = "<4,>=3.7" files = [ @@ -1425,6 +1485,7 @@ tests = ["coverage"] name = "coverage" version = "7.2.7" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1500,6 +1561,7 @@ toml = ["tomli"] name = "cryptography" version = "41.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1545,6 +1607,7 @@ test-randomorder = ["pytest-randomly"] name = "cssselect" version = "1.2.0" description = "cssselect parses CSS3 Selectors and translates them to XPath 1.0" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1556,6 +1619,7 @@ files = [ name = "cssselect2" version = "0.7.0" description = "CSS selectors for Python ElementTree" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1575,6 +1639,7 @@ test = ["flake8", "isort", "pytest"] name = "cvxpy" version = "1.2.2" description = "A domain-specific language for modeling convex optimization problems in Python." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -1607,6 +1672,7 @@ scs = ">=1.1.6" name = "cycler" version = "0.11.0" description = "Composable style cycles" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1618,6 +1684,7 @@ files = [ name = "cython" version = "3.0.0" description = "The Cython compiler for writing C extensions in the Python language." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1685,6 +1752,7 @@ files = [ name = "dash" version = "2.9.3" description = "A Python framework for building reactive web-apps. Developed by Plotly." +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -1711,6 +1779,7 @@ testing = ["beautifulsoup4 (>=4.8.2)", "cryptography (<3.4)", "dash-testing-stub name = "dash-core-components" version = "2.0.0" description = "Core component suite for Dash" +category = "main" optional = true python-versions = "*" files = [ @@ -1722,6 +1791,7 @@ files = [ name = "dash-html-components" version = "2.0.0" description = "Vanilla HTML components for Dash" +category = "main" optional = true python-versions = "*" files = [ @@ -1733,6 +1803,7 @@ files = [ name = "dash-table" version = "5.0.0" description = "Dash table" +category = "main" optional = true python-versions = "*" files = [ @@ -1744,6 +1815,7 @@ files = [ name = "dataclasses-json" version = "0.5.12" description = "Easily serialize dataclasses to and from JSON." +category = "main" optional = false python-versions = ">=3.7,<3.12" files = [ @@ -1759,6 +1831,7 @@ typing-inspect = ">=0.4.0,<1" name = "dateparser" version = "1.1.8" description = "Date parsing library designed to parse dates from HTML pages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1781,6 +1854,7 @@ langdetect = ["langdetect"] name = "datetime" version = "5.2" description = "This package provides a DateTime data type, as known from Zope. Unless you need to communicate with Zope APIs, you're probably better off using Python's built-in datetime module." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1796,6 +1870,7 @@ pytz = "*" name = "debugpy" version = "1.6.7" description = "An implementation of the Debug Adapter Protocol for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1823,6 +1898,7 @@ files = [ name = "decorator" version = "5.1.1" description = "Decorators for Humans" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1834,6 +1910,7 @@ files = [ name = "defusedxml" version = "0.7.1" description = "XML bomb protection for Python stdlib modules" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1845,6 +1922,7 @@ files = [ name = "degiro-connector" version = "2.0.21" description = "This is yet another library to access Degiro's API." +category = "main" optional = false python-versions = ">=3.7.1,<4.0.0" files = [ @@ -1864,6 +1942,7 @@ wrapt = ">=1.12.1,<2.0.0" name = "detecta" version = "0.0.5" description = "Detect events in data" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1875,6 +1954,7 @@ files = [ name = "dill" version = "0.3.6" description = "serialize all of python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1889,6 +1969,7 @@ graph = ["objgraph (>=1.7.2)"] name = "distlib" version = "0.3.7" description = "Distribution utilities" +category = "dev" optional = false python-versions = "*" files = [ @@ -1900,6 +1981,7 @@ files = [ name = "dnspython" version = "2.4.0" description = "DNS toolkit" +category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -1923,6 +2005,7 @@ wmi = ["wmi (>=1.5.1,<2.0.0)"] name = "docstring-parser" version = "0.15" description = "Parse Python docstrings in reST, Google and Numpydoc format" +category = "main" optional = true python-versions = ">=3.6,<4.0" files = [ @@ -1934,6 +2017,7 @@ files = [ name = "docstring-to-markdown" version = "0.12" description = "On the fly conversion of Python docstrings to markdown" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -1945,6 +2029,7 @@ files = [ name = "docutils" version = "0.17.1" description = "Docutils -- Python Documentation Utilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1956,6 +2041,7 @@ files = [ name = "ecdsa" version = "0.18.0" description = "ECDSA cryptographic signature library (pure python)" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1974,6 +2060,7 @@ gmpy2 = ["gmpy2"] name = "ecos" version = "2.0.12" description = "This is the Python package for ECOS: Embedded Cone Solver. See Github page for more information." +category = "main" optional = true python-versions = "*" files = [ @@ -2003,6 +2090,7 @@ scipy = ">=0.9" name = "entrypoints" version = "0.4" description = "Discover and load entry points from installed packages." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2014,6 +2102,7 @@ files = [ name = "ephem" version = "4.1.4" description = "Compute positions of the planets and stars" +category = "main" optional = true python-versions = "*" files = [ @@ -2028,17 +2117,6 @@ files = [ {file = "ephem-4.1.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4039aa2f0b8c204283fc478551d8b29c9473137ad8a910a5ff60ae3be6593c7b"}, {file = "ephem-4.1.4-cp310-cp310-win32.whl", hash = "sha256:8979429643ac4e29a5496321c9c41a20cd7a6a530aee9865c7fab0008450ef28"}, {file = "ephem-4.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:589a2235f49232b92ee0247923360a264086a57b2c39d4191348f95ba5ce0c3d"}, - {file = "ephem-4.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:feab5f68ae9fa622d6316790c9cfc399e8b78f7958a61da4edf2cb5e0e675d44"}, - {file = "ephem-4.1.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df9c482c8d25e69271311606b4de0e177e44ceb11781c7ebacf17cc5b391f832"}, - {file = "ephem-4.1.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cceea883856817f3ea3f73442e3be3a4a56558cdb77cc85d02db4429ce5ab16"}, - {file = "ephem-4.1.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f3e9ea626bc522fd4dd1ff795f0922fcb4c4eb57effe91b6284411166ddd1fd7"}, - {file = "ephem-4.1.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad22e769bd35415cad8f2ef6d4d875190d9bdad4fed2842fd19dac6f1ccb9dd"}, - {file = "ephem-4.1.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e3327218495235ec215ffe43253c0bf3fa982f59504b351c53b024f1c7b63752"}, - {file = "ephem-4.1.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d2c56238a1aec72a78ad7061f5c531df97a66ea0cca45204b6b8141c3bb1540e"}, - {file = "ephem-4.1.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fffe176bd94f4f61be5a54b54a966988cceb6ba69a6ed729aab166020fdb37c3"}, - {file = "ephem-4.1.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8f9b27117e7a82f7f70db9cb23b5cc36d37b166a2f73c55e14d7225d0ab95afa"}, - {file = "ephem-4.1.4-cp311-cp311-win32.whl", hash = "sha256:9bb21c0b117c9122c0141b0a71ee6fbbb087ed2aab4a7ab60f009e95e9f4a521"}, - {file = "ephem-4.1.4-cp311-cp311-win_amd64.whl", hash = "sha256:55d7fb5c34b2e453e01fa4ca7ee375b19b438c9401ae8c4099ae4a3a37656972"}, {file = "ephem-4.1.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:40067fc050c946c8d4c2d779805b61f063471a091e6124cbabcf61ac538011b2"}, {file = "ephem-4.1.4-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e2abe97aa2b091090012768b4d94793213cc01f0bf040dcc311a380ab08df69"}, {file = "ephem-4.1.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2677d3a5b42aedc578de10b0eecdba6a50731f159cb28f7ad38c5f62143494"}, @@ -2090,6 +2168,7 @@ files = [ name = "et-xmlfile" version = "1.1.0" description = "An implementation of lxml.xmlfile for the standard library" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2101,6 +2180,7 @@ files = [ name = "exceptiongroup" version = "1.1.2" description = "Backport of PEP 654 (exception groups)" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2115,6 +2195,7 @@ test = ["pytest (>=6)"] name = "exchange-calendars" version = "4.2.8" description = "Calendars for securities exchanges" +category = "main" optional = false python-versions = "~=3.8" files = [ @@ -2138,6 +2219,7 @@ dev = ["flake8", "hypothesis", "pip-tools", "pytest", "pytest-benchmark", "pytes name = "execnet" version = "2.0.2" description = "execnet: rapid multi-Python deployment" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2152,6 +2234,7 @@ testing = ["hatch", "pre-commit", "pytest", "tox"] name = "executing" version = "1.2.0" description = "Get the currently executing AST node of a frame, and other information" +category = "main" optional = false python-versions = "*" files = [ @@ -2166,6 +2249,7 @@ tests = ["asttokens", "littleutils", "pytest", "rich"] name = "fastjsonschema" version = "2.17.1" description = "Fastest Python implementation of JSON schema" +category = "main" optional = false python-versions = "*" files = [ @@ -2180,6 +2264,7 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc name = "feedparser" version = "6.0.10" description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2194,6 +2279,7 @@ sgmllib3k = "*" name = "ffmpeg-python" version = "0.2.0" description = "Python bindings for FFmpeg - with complex filtering support" +category = "main" optional = true python-versions = "*" files = [ @@ -2211,6 +2297,7 @@ dev = ["Sphinx (==2.1.0)", "future (==0.17.1)", "numpy (==1.16.4)", "pytest (==4 name = "ffn" version = "0.3.6" description = "Financial functions for Python" +category = "main" optional = false python-versions = "*" files = [ @@ -2236,6 +2323,7 @@ dev = ["black (>=20.8b1)", "codecov", "coverage", "flake8", "flake8-black", "fut name = "filelock" version = "3.12.2" description = "A platform independent file lock." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2251,6 +2339,7 @@ testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "p name = "financedatabase" version = "2.1.0" description = "This is a database of 300.000+ symbols containing Equities, ETFs, Funds, Indices, Currencies, Cryptocurrencies and Money Markets." +category = "main" optional = false python-versions = "*" files = [ @@ -2265,6 +2354,7 @@ pandas = "*" name = "finnhub-python" version = "2.4.18" description = "Finnhub API" +category = "main" optional = false python-versions = "*" files = [ @@ -2279,6 +2369,7 @@ requests = ">=2.22.0" name = "finviz" version = "1.4.6" description = "Unofficial API for FinViz.com" +category = "main" optional = false python-versions = "*" files = [ @@ -2300,6 +2391,7 @@ user_agent = "*" name = "finvizfinance" version = "0.14.6rc2" description = "Finviz Finance. Information downloader." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -2318,6 +2410,7 @@ requests = "*" name = "flake8" version = "6.0.0" description = "the modular source code checker: pep8 pyflakes and co" +category = "main" optional = false python-versions = ">=3.8.1" files = [ @@ -2334,6 +2427,7 @@ pyflakes = ">=3.0.0,<3.1.0" name = "flask" version = "2.3.2" description = "A simple framework for building complex web applications." +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -2357,6 +2451,7 @@ dotenv = ["python-dotenv"] name = "fonttools" version = "4.41.0" description = "Tools to manipulate font files" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2414,6 +2509,7 @@ woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] name = "formulaic" version = "0.6.4" description = "An implementation of Wilkinson formulas." +category = "main" optional = false python-versions = ">=3.7.2" files = [ @@ -2439,6 +2535,7 @@ calculus = ["sympy (>=1.3,!=1.10)"] name = "fqdn" version = "1.5.1" description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" +category = "main" optional = false python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" files = [ @@ -2450,6 +2547,7 @@ files = [ name = "fred" version = "3.1" description = "St. Louis Federal Reserve FRED API" +category = "main" optional = false python-versions = "*" files = [ @@ -2463,6 +2561,7 @@ requests = "*" name = "fredapi" version = "0.4.3" description = "Python API for Federal Reserve Economic Data (FRED) from St. Louis Fed" +category = "main" optional = false python-versions = "*" files = [ @@ -2477,6 +2576,7 @@ pandas = "*" name = "freezegun" version = "1.2.2" description = "Let your Python tests travel through time" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2491,6 +2591,7 @@ python-dateutil = ">=2.7" name = "frozendict" version = "2.3.8" description = "A simple immutable dictionary" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2537,6 +2638,7 @@ files = [ name = "frozenlist" version = "1.4.0" description = "A list-like structure which implements collections.abc.MutableSequence" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2607,6 +2709,7 @@ files = [ name = "fs" version = "2.4.16" description = "Python's filesystem abstraction layer" +category = "main" optional = true python-versions = "*" files = [ @@ -2626,6 +2729,7 @@ scandir = ["scandir (>=1.5,<2.0)"] name = "fsspec" version = "2023.6.0" description = "File-system specification" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2665,6 +2769,7 @@ tqdm = ["tqdm"] name = "fugue" version = "0.8.5" description = "An abstraction layer for distributed computation" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -2698,6 +2803,7 @@ sql = ["fugue-sql-antlr (>=0.1.6)", "jinja2", "qpd (>=0.4.3)", "sqlglot"] name = "fugue-sql-antlr" version = "0.1.6" description = "Fugue SQL Antlr Parser" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -2717,6 +2823,7 @@ test = ["speedy_antlr_tool"] name = "fundamentalanalysis" version = "0.2.14" description = "Fully-fledged Fundamental Analysis package capable of collecting 20 years of Company Profiles, Financial Statements, Ratios and Stock Data of 20.000+ companies." +category = "main" optional = false python-versions = "*" files = [ @@ -2728,6 +2835,7 @@ files = [ name = "future" version = "0.18.3" description = "Clean single-source support for Python 3 and 2" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2738,6 +2846,7 @@ files = [ name = "gitdb" version = "4.0.10" description = "Git Object Database" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2752,6 +2861,7 @@ smmap = ">=3.0.1,<6" name = "gitpython" version = "3.1.32" description = "GitPython is a Python library used to interact with Git repositories" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2766,6 +2876,7 @@ gitdb = ">=4.0.1,<5" name = "google-auth" version = "2.22.0" description = "Google Authentication Library" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -2791,6 +2902,7 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"] name = "google-auth-oauthlib" version = "1.0.0" description = "Google Authentication Library" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -2809,6 +2921,7 @@ tool = ["click (>=6.0.0)"] name = "graphlib-backport" version = "1.0.3" description = "Backport of the Python 3.9 graphlib module for Python 3.6+" +category = "main" optional = false python-versions = ">=3.6,<4.0" files = [ @@ -2820,6 +2933,7 @@ files = [ name = "graphviz" version = "0.20.1" description = "Simple Python interface for Graphviz" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -2836,6 +2950,7 @@ test = ["coverage", "mock (>=4)", "pytest (>=7)", "pytest-cov", "pytest-mock (>= name = "greenlet" version = "2.0.2" description = "Lightweight in-process concurrent programming" +category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" files = [ @@ -2909,6 +3024,7 @@ test = ["objgraph", "psutil"] name = "grpcio" version = "1.56.2" description = "HTTP/2-based RPC framework" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2966,6 +3082,7 @@ protobuf = ["grpcio-tools (>=1.56.2)"] name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2977,6 +3094,7 @@ files = [ name = "hijri-converter" version = "2.3.1" description = "Accurate Hijri-Gregorian dates converter based on the Umm al-Qura calendar" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2988,6 +3106,7 @@ files = [ name = "holidays" version = "0.14.2" description = "Generate and work with holidays in Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3005,6 +3124,7 @@ python-dateutil = "*" name = "html5lib" version = "1.1" description = "HTML parser based on the WHATWG HTML specification" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -3026,6 +3146,7 @@ lxml = ["lxml"] name = "httpcore" version = "0.17.3" description = "A minimal low-level HTTP client." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3037,16 +3158,17 @@ files = [ anyio = ">=3.0,<5.0" certifi = "*" h11 = ">=0.13,<0.15" -sniffio = "==1.*" +sniffio = ">=1.0.0,<2.0.0" [package.extras] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "huggingface-hub" version = "0.16.4" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" +category = "main" optional = true python-versions = ">=3.7.0" files = [ @@ -3079,6 +3201,7 @@ typing = ["pydantic", "types-PyYAML", "types-requests", "types-simplejson", "typ name = "identify" version = "2.5.25" description = "File identification library for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -3093,6 +3216,7 @@ license = ["ukkonen"] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -3104,6 +3228,7 @@ files = [ name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3115,6 +3240,7 @@ files = [ name = "importlib-metadata" version = "6.8.0" description = "Read metadata from Python packages" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3134,6 +3260,7 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs name = "importlib-resources" version = "6.0.0" description = "Read resources from Python packages" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3152,6 +3279,7 @@ testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", name = "inflection" version = "0.5.1" description = "A port of Ruby on Rails inflector to Python" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -3163,6 +3291,7 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3174,6 +3303,7 @@ files = [ name = "interface-meta" version = "1.3.0" description = "`interface_meta` provides a convenient way to expose an extensible API with enforced method signatures and consistent documentation." +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -3185,6 +3315,7 @@ files = [ name = "intrinio-sdk" version = "6.24.1" description = "Intrinio API" +category = "main" optional = false python-versions = "*" files = [ @@ -3203,6 +3334,7 @@ urllib3 = ">=1.15" name = "ipykernel" version = "6.24.0" description = "IPython Kernel for Jupyter" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3216,7 +3348,7 @@ comm = ">=0.1.1" debugpy = ">=1.6.5" ipython = ">=7.23.1" jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" matplotlib-inline = ">=0.1" nest-asyncio = "*" packaging = "*" @@ -3236,6 +3368,7 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio" name = "ipympl" version = "0.8.4" description = "Matplotlib Jupyter Extension" +category = "main" optional = false python-versions = "*" files = [ @@ -3252,6 +3385,7 @@ matplotlib = ">=2.0.0" name = "ipython" version = "8.11.0" description = "IPython: Productive Interactive Computing" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3290,6 +3424,7 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pa name = "ipython-genutils" version = "0.2.0" description = "Vestigial utilities from IPython" +category = "main" optional = false python-versions = "*" files = [ @@ -3301,6 +3436,7 @@ files = [ name = "ipywidgets" version = "8.0.7" description = "Jupyter interactive widgets" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3322,6 +3458,7 @@ test = ["ipykernel", "jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] name = "iso8601" version = "0.1.16" description = "Simple module to parse ISO 8601 dates" +category = "main" optional = false python-versions = "*" files = [ @@ -3333,6 +3470,7 @@ files = [ name = "isodate" version = "0.6.1" description = "An ISO 8601 date/time/duration parser and formatter" +category = "main" optional = false python-versions = "*" files = [ @@ -3347,6 +3485,7 @@ six = "*" name = "isoduration" version = "20.11.0" description = "Operations with ISO 8601 durations" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3361,6 +3500,7 @@ arrow = ">=0.15.0" name = "isort" version = "5.12.0" description = "A Python utility / library to sort Python imports." +category = "dev" optional = false python-versions = ">=3.8.0" files = [ @@ -3378,6 +3518,7 @@ requirements-deprecated-finder = ["pip-api", "pipreqs"] name = "itsdangerous" version = "2.1.2" description = "Safely pass data to untrusted environments and back." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -3389,6 +3530,7 @@ files = [ name = "jedi" version = "0.18.2" description = "An autocompletion tool for Python that can be used for text editors." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -3408,6 +3550,7 @@ testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] name = "jedi-language-server" version = "0.40.0" description = "A language server for Jedi!" +category = "main" optional = true python-versions = ">=3.7,<3.12" files = [ @@ -3426,6 +3569,7 @@ pygls = ">=1.0.0,<2.0.0" name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3443,6 +3587,7 @@ i18n = ["Babel (>=2.7)"] name = "joblib" version = "1.3.1" description = "Lightweight pipelining with Python functions" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3454,6 +3599,7 @@ files = [ name = "json5" version = "0.9.14" description = "A Python implementation of the JSON5 data format." +category = "main" optional = false python-versions = "*" files = [ @@ -3468,6 +3614,7 @@ dev = ["hypothesis"] name = "jsonpointer" version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ @@ -3479,6 +3626,7 @@ files = [ name = "jsonschema" version = "4.17.3" description = "An implementation of JSON Schema validation for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3508,6 +3656,7 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "jupyter-client" version = "7.4.1" description = "Jupyter protocol implementation and client libraries" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3532,6 +3681,7 @@ test = ["codecov", "coverage", "ipykernel (>=6.5)", "ipython", "mypy", "pre-comm name = "jupyter-core" version = "5.3.1" description = "Jupyter core package. A base package on which Jupyter projects rely." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3552,6 +3702,7 @@ test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] name = "jupyter-dash" version = "0.4.2" description = "Dash support for the Jupyter notebook interface" +category = "main" optional = true python-versions = ">=3.5" files = [ @@ -3576,6 +3727,7 @@ dev = ["jupyter-server-proxy", "jupyterlab (>=2.0)", "notebook (>=6.0)"] name = "jupyter-events" version = "0.6.3" description = "Jupyter Event System library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3600,6 +3752,7 @@ test = ["click", "coverage", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>= name = "jupyter-lsp" version = "2.2.0" description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -3615,6 +3768,7 @@ jupyter-server = ">=1.1.2" name = "jupyter-server" version = "1.23.6" description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3627,7 +3781,7 @@ anyio = ">=3.1.0,<4" argon2-cffi = "*" jinja2 = "*" jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" nbconvert = ">=6.4.4" nbformat = ">=5.2.0" packaging = "*" @@ -3647,6 +3801,7 @@ test = ["coverage", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console name = "jupyter-server-fileid" version = "0.9.0" description = "" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3666,6 +3821,7 @@ test = ["jupyter-server[test] (>=1.15,<3)", "pytest", "pytest-cov"] name = "jupyter-server-ydoc" version = "0.8.0" description = "A Jupyter Server Extension Providing Y Documents." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3685,6 +3841,7 @@ test = ["coverage", "jupyter-server[test] (>=2.0.0a0)", "pytest (>=7.0)", "pytes name = "jupyter-ydoc" version = "0.2.5" description = "Document structures for collaborative editing using Ypy" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3704,6 +3861,7 @@ test = ["pre-commit", "pytest", "pytest-asyncio", "websockets (>=10.0)", "ypy-we name = "jupyterlab" version = "3.6.5" description = "JupyterLab computational environment" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3732,6 +3890,7 @@ test = ["check-manifest", "coverage", "jupyterlab-server[test]", "pre-commit", " name = "jupyterlab-code-formatter" version = "1.6.1" description = "Code formatter for JupyterLab" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -3746,6 +3905,7 @@ jupyterlab = ">=3.0,<4.0" name = "jupyterlab-lsp" version = "3.10.2" description = "Coding assistance for JupyterLab with Language Server Protocol" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -3761,6 +3921,7 @@ jupyterlab = ">=3.1.0,<4.0.0a0" name = "jupyterlab-pygments" version = "0.2.2" description = "Pygments theme using JupyterLab CSS variables" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3772,6 +3933,7 @@ files = [ name = "jupyterlab-server" version = "2.23.0" description = "A set of server components for JupyterLab and JupyterLab like applications." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3798,6 +3960,7 @@ test = ["hatch", "ipykernel", "jupyterlab-server[openapi]", "openapi-spec-valida name = "jupyterlab-widgets" version = "3.0.8" description = "Jupyter interactive widgets for JupyterLab" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3809,6 +3972,7 @@ files = [ name = "kiwisolver" version = "1.4.4" description = "A fast implementation of the Cassowary constraint solver" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3886,6 +4050,7 @@ files = [ name = "korean-lunar-calendar" version = "0.3.1" description = "Korean Lunar Calendar" +category = "main" optional = false python-versions = "*" files = [ @@ -3897,6 +4062,7 @@ files = [ name = "langchain" version = "0.0.237" description = "Building applications with LLMs through composability" +category = "main" optional = false python-versions = ">=3.8.1,<4.0" files = [ @@ -3936,6 +4102,7 @@ text-helpers = ["chardet (>=5.1.0,<6.0.0)"] name = "langsmith" version = "0.0.10" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." +category = "main" optional = false python-versions = ">=3.8.1,<4.0" files = [ @@ -3951,6 +4118,7 @@ requests = ">=2,<3" name = "lazy-object-proxy" version = "1.9.0" description = "A fast and thorough lazy object proxy." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3996,6 +4164,7 @@ files = [ name = "lightgbm" version = "3.3.5" description = "LightGBM Python Package" +category = "main" optional = true python-versions = "*" files = [ @@ -4019,6 +4188,7 @@ dask = ["dask[array] (>=2.0.0)", "dask[dataframe] (>=2.0.0)", "dask[distributed] name = "lightning-utilities" version = "0.9.0" description = "PyTorch Lightning Sample project." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -4039,6 +4209,7 @@ typing = ["mypy (>=1.0.0)"] name = "linearmodels" version = "4.31" description = "Linear Panel, Instrumental Variable, Asset Pricing, and System Regression models for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4083,6 +4254,7 @@ statsmodels = ">=0.11" name = "llama-index" version = "0.7.11" description = "Interface between LLMs and your data" +category = "main" optional = false python-versions = "*" files = [ @@ -4110,6 +4282,7 @@ urllib3 = "<2" name = "llvmlite" version = "0.40.1" description = "lightweight wrapper around basic LLVM functionality" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -4143,6 +4316,7 @@ files = [ name = "loguru" version = "0.7.0" description = "Python logging made (stupidly) simple" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -4161,6 +4335,7 @@ dev = ["Sphinx (==5.3.0)", "colorama (==0.4.5)", "colorama (==0.4.6)", "freezegu name = "lsprotocol" version = "2023.0.0a2" description = "Python implementation of the Language Server Protocol." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -4176,6 +4351,7 @@ cattrs = "*" name = "lunarcalendar" version = "0.0.9" description = "A lunar calendar converter, including a number of lunar and solar holidays, mainly from China." +category = "main" optional = true python-versions = ">=2.7, <4" files = [ @@ -4192,6 +4368,7 @@ pytz = "*" name = "lxml" version = "4.9.3" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" files = [ @@ -4299,6 +4476,7 @@ source = ["Cython (>=0.29.35)"] name = "macholib" version = "1.16.2" description = "Mach-O header analysis and editing" +category = "main" optional = true python-versions = "*" files = [ @@ -4313,6 +4491,7 @@ altgraph = ">=0.17" name = "markdown" version = "3.4.3" description = "Python implementation of John Gruber's Markdown." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -4330,6 +4509,7 @@ testing = ["coverage", "pyyaml"] name = "markdown-it-py" version = "1.1.0" description = "Python port of markdown-it. Markdown parsing, done right!" +category = "dev" optional = false python-versions = "~=3.6" files = [ @@ -4352,6 +4532,7 @@ testing = ["coverage", "psutil", "pytest (>=3.6,<4)", "pytest-benchmark (>=3.2,< name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4411,6 +4592,7 @@ files = [ name = "marshmallow" version = "3.19.0" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4431,6 +4613,7 @@ tests = ["pytest", "pytz", "simplejson"] name = "matplotlib" version = "3.7.2" description = "Python plotting package" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4493,6 +4676,7 @@ python-dateutil = ">=2.7" name = "matplotlib-inline" version = "0.1.6" description = "Inline Matplotlib backend for Jupyter" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -4507,6 +4691,7 @@ traitlets = "*" name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -4518,6 +4703,7 @@ files = [ name = "mdit-py-plugins" version = "0.2.8" description = "Collection of plugins for markdown-it-py" +category = "dev" optional = false python-versions = "~=3.6" files = [ @@ -4537,6 +4723,7 @@ testing = ["coverage", "pytest (>=3.6,<4)", "pytest-cov", "pytest-regressions"] name = "mistune" version = "3.0.1" description = "A sane and fast Markdown parser with useful plugins and renderers" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4548,6 +4735,7 @@ files = [ name = "mock" version = "4.0.3" description = "Rolling backport of unittest.mock for all Pythons" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -4564,6 +4752,7 @@ test = ["pytest (<5.4)", "pytest-cov"] name = "monotonic" version = "1.6" description = "An implementation of time.monotonic() for Python 2 & < 3.3" +category = "main" optional = false python-versions = "*" files = [ @@ -4575,6 +4764,7 @@ files = [ name = "more-itertools" version = "9.1.0" description = "More routines for operating on iterables, beyond itertools" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4586,6 +4776,7 @@ files = [ name = "mplfinance" version = "0.12.9b7" description = "Utilities for the visualization, and visual analysis, of financial data" +category = "main" optional = false python-versions = "*" files = [ @@ -4601,6 +4792,7 @@ pandas = "*" name = "mstarpy" version = "0.0.4" description = "Mutual funds data extraction from MorningStar with Python" +category = "main" optional = false python-versions = "*" files = [ @@ -4617,6 +4809,7 @@ requests = ">=2.28.1" name = "multidict" version = "6.0.4" description = "multidict implementation" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4700,6 +4893,7 @@ files = [ name = "multitasking" version = "0.0.11" description = "Non-blocking Python methods using decorators" +category = "main" optional = false python-versions = "*" files = [ @@ -4711,6 +4905,7 @@ files = [ name = "mutagen" version = "1.46.0" description = "read and write audio tags for many formats" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -4722,6 +4917,7 @@ files = [ name = "mypy" version = "1.4.1" description = "Optional static typing for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4768,6 +4964,7 @@ reports = ["lxml"] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -4779,6 +4976,7 @@ files = [ name = "myst-parser" version = "0.15.2" description = "An extended commonmark compliant parser, with bridges to docutils & sphinx." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -4804,6 +5002,7 @@ testing = ["beautifulsoup4", "coverage", "docutils (>=0.17.0,<0.18.0)", "pytest name = "nbclassic" version = "1.0.0" description = "Jupyter Notebook as a Jupyter Server extension." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4839,6 +5038,7 @@ test = ["coverage", "nbval", "pytest", "pytest-cov", "pytest-jupyter", "pytest-p name = "nbclient" version = "0.6.8" description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -4860,6 +5060,7 @@ test = ["black", "check-manifest", "flake8", "ipykernel", "ipython", "ipywidgets name = "nbconvert" version = "7.7.2" description = "Converting Jupyter Notebooks" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4898,6 +5099,7 @@ webpdf = ["playwright"] name = "nbformat" version = "5.9.1" description = "The Jupyter Notebook format" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4919,6 +5121,7 @@ test = ["pep440", "pre-commit", "pytest", "testpath"] name = "nbmake" version = "1.4.1" description = "Pytest plugin for testing notebooks" +category = "dev" optional = false python-versions = ">=3.7.0,<4.0.0" files = [ @@ -4938,6 +5141,7 @@ pytest = ">=6.1.0" name = "nest-asyncio" version = "1.5.6" description = "Patch asyncio to allow nested event loops" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -4949,6 +5153,7 @@ files = [ name = "networkx" version = "3.1" description = "Python package for creating and manipulating graphs and networks" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -4967,6 +5172,7 @@ test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] name = "nfoursid" version = "1.0.1" description = "Implementation of N4SID, Kalman filtering and state-space models" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -4983,6 +5189,7 @@ pandas = ">=1.1" name = "nodeenv" version = "1.8.0" description = "Node.js virtual environment builder" +category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ @@ -4997,6 +5204,7 @@ setuptools = "*" name = "notebook" version = "6.5.4" description = "A web-based notebook environment for interactive computing" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5031,6 +5239,7 @@ test = ["coverage", "nbval", "pytest", "pytest-cov", "requests", "requests-unixs name = "notebook-shim" version = "0.2.3" description = "A shim layer for notebook traits and config" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5048,6 +5257,7 @@ test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync" name = "numba" version = "0.57.1" description = "compiling Python code using LLVM" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -5079,13 +5289,14 @@ files = [ [package.dependencies] importlib-metadata = {version = "*", markers = "python_version < \"3.9\""} -llvmlite = "==0.40.*" +llvmlite = ">=0.40.0dev0,<0.41" numpy = ">=1.21,<1.25" [[package]] name = "numexpr" version = "2.8.4" description = "Fast numerical expression evaluator for NumPy" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5128,6 +5339,7 @@ numpy = ">=1.13.3" name = "numpy" version = "1.23.4" description = "NumPy is the fundamental package for array computing with Python." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -5165,6 +5377,7 @@ files = [ name = "oandapyv20" version = "0.6.3" description = "Python wrapper for the OANDA REST-V20 API" +category = "main" optional = false python-versions = "*" files = [ @@ -5175,6 +5388,7 @@ files = [ name = "oauthlib" version = "3.2.2" description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -5191,6 +5405,7 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] name = "onetimepass" version = "1.0.1" description = "Module for generating and validating HOTP and TOTP tokens" +category = "main" optional = false python-versions = "*" files = [ @@ -5204,6 +5419,7 @@ six = "*" name = "openai" version = "0.27.8" description = "Python client library for the OpenAI API" +category = "main" optional = false python-versions = ">=3.7.1" files = [ @@ -5218,7 +5434,7 @@ tqdm = "*" [package.extras] datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -dev = ["black (>=21.6b0,<22.0)", "pytest (==6.*)", "pytest-asyncio", "pytest-mock"] +dev = ["black (>=21.6b0,<22.0)", "pytest (>=6.0.0,<7.0.0)", "pytest-asyncio", "pytest-mock"] embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"] wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"] @@ -5226,6 +5442,7 @@ wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1 name = "openai-whisper" version = "20230124" description = "Robust Speech Recognition via Large-Scale Weak Supervision" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -5247,6 +5464,7 @@ dev = ["pytest"] name = "openapi-schema-pydantic" version = "1.2.4" description = "OpenAPI (v3) specification schema as pydantic class" +category = "main" optional = false python-versions = ">=3.6.1" files = [ @@ -5261,6 +5479,7 @@ pydantic = ">=1.8.2" name = "openpyxl" version = "3.1.2" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -5275,6 +5494,7 @@ et-xmlfile = "*" name = "orjson" version = "3.9.2" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -5286,6 +5506,7 @@ files = [ {file = "orjson-3.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a39c2529d75373b7167bf84c814ef9b8f3737a339c225ed6c0df40736df8748"}, {file = "orjson-3.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:84ebd6fdf138eb0eb4280045442331ee71c0aab5e16397ba6645f32f911bfb37"}, {file = "orjson-3.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a60a1cfcfe310547a1946506dd4f1ed0a7d5bd5b02c8697d9d5dcd8d2e9245e"}, + {file = "orjson-3.9.2-cp310-none-win32.whl", hash = "sha256:2ae61f5d544030a6379dbc23405df66fea0777c48a0216d2d83d3e08b69eb676"}, {file = "orjson-3.9.2-cp310-none-win_amd64.whl", hash = "sha256:c290c4f81e8fd0c1683638802c11610b2f722b540f8e5e858b6914b495cf90c8"}, {file = "orjson-3.9.2-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:02ef014f9a605e84b675060785e37ec9c0d2347a04f1307a9d6840ab8ecd6f55"}, {file = "orjson-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:992af54265ada1c1579500d6594ed73fe333e726de70d64919cf37f93defdd06"}, @@ -5295,6 +5516,7 @@ files = [ {file = "orjson-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:275b5a18fd9ed60b2720543d3ddac170051c43d680e47d04ff5203d2c6d8ebf1"}, {file = "orjson-3.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b9aea6dcb99fcbc9f6d1dd84fca92322fda261da7fb014514bb4689c7c2097a8"}, {file = "orjson-3.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7d74ae0e101d17c22ef67b741ba356ab896fc0fa64b301c2bf2bb0a4d874b190"}, + {file = "orjson-3.9.2-cp311-none-win32.whl", hash = "sha256:a9a7d618f99b2d67365f2b3a588686195cb6e16666cd5471da603a01315c17cc"}, {file = "orjson-3.9.2-cp311-none-win_amd64.whl", hash = "sha256:6320b28e7bdb58c3a3a5efffe04b9edad3318d82409e84670a9b24e8035a249d"}, {file = "orjson-3.9.2-cp37-cp37m-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:368e9cc91ecb7ac21f2aa475e1901204110cf3e714e98649c2502227d248f947"}, {file = "orjson-3.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58e9e70f0dcd6a802c35887f306b555ff7a214840aad7de24901fc8bd9cf5dde"}, @@ -5304,6 +5526,7 @@ files = [ {file = "orjson-3.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e46e9c5b404bb9e41d5555762fd410d5466b7eb1ec170ad1b1609cbebe71df21"}, {file = "orjson-3.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8170157288714678ffd64f5de33039e1164a73fd8b6be40a8a273f80093f5c4f"}, {file = "orjson-3.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e3e2f087161947dafe8319ea2cfcb9cea4bb9d2172ecc60ac3c9738f72ef2909"}, + {file = "orjson-3.9.2-cp37-none-win32.whl", hash = "sha256:373b7b2ad11975d143556fdbd2c27e1150b535d2c07e0b48dc434211ce557fe6"}, {file = "orjson-3.9.2-cp37-none-win_amd64.whl", hash = "sha256:d7de3dbbe74109ae598692113cec327fd30c5a30ebca819b21dfa4052f7b08ef"}, {file = "orjson-3.9.2-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8cd4385c59bbc1433cad4a80aca65d2d9039646a9c57f8084897549b55913b17"}, {file = "orjson-3.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a74036aab1a80c361039290cdbc51aa7adc7ea13f56e5ef94e9be536abd227bd"}, @@ -5313,6 +5536,7 @@ files = [ {file = "orjson-3.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1882a70bb69595b9ec5aac0040a819e94d2833fe54901e2b32f5e734bc259a8b"}, {file = "orjson-3.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fc05e060d452145ab3c0b5420769e7356050ea311fc03cb9d79c481982917cca"}, {file = "orjson-3.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f8bc2c40d9bb26efefb10949d261a47ca196772c308babc538dd9f4b73e8d386"}, + {file = "orjson-3.9.2-cp38-none-win32.whl", hash = "sha256:302d80198d8d5b658065627da3a356cbe5efa082b89b303f162f030c622e0a17"}, {file = "orjson-3.9.2-cp38-none-win_amd64.whl", hash = "sha256:3164fc20a585ec30a9aff33ad5de3b20ce85702b2b2a456852c413e3f0d7ab09"}, {file = "orjson-3.9.2-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7a6ccadf788531595ed4728aa746bc271955448d2460ff0ef8e21eb3f2a281ba"}, {file = "orjson-3.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3245d230370f571c945f69aab823c279a868dc877352817e22e551de155cb06c"}, @@ -5322,6 +5546,7 @@ files = [ {file = "orjson-3.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03fb36f187a0c19ff38f6289418863df8b9b7880cdbe279e920bef3a09d8dab1"}, {file = "orjson-3.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:20925d07a97c49c6305bff1635318d9fc1804aa4ccacb5fb0deb8a910e57d97a"}, {file = "orjson-3.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:eebfed53bec5674e981ebe8ed2cf00b3f7bcda62d634733ff779c264307ea505"}, + {file = "orjson-3.9.2-cp39-none-win32.whl", hash = "sha256:ba60f09d735f16593950c6adf033fbb526faa94d776925579a87b777db7d0838"}, {file = "orjson-3.9.2-cp39-none-win_amd64.whl", hash = "sha256:869b961df5fcedf6c79f4096119b35679b63272362e9b745e668f0391a892d39"}, {file = "orjson-3.9.2.tar.gz", hash = "sha256:24257c8f641979bf25ecd3e27251b5cc194cdd3a6e96004aac8446f5e63d9664"}, ] @@ -5330,6 +5555,7 @@ files = [ name = "osqp" version = "0.6.3" description = "OSQP: The Operator Splitting QP Solver" +category = "main" optional = true python-versions = "*" files = [ @@ -5369,6 +5595,7 @@ scipy = ">=0.13.2" name = "packaging" version = "23.1" description = "Core utilities for Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5380,6 +5607,7 @@ files = [ name = "pandas" version = "1.5.3" description = "Powerful data structures for data analysis, time series, and statistics" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -5427,6 +5655,7 @@ test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] name = "pandas-datareader" version = "0.10.0" description = "Data readers extracted from the pandas codebase,should be compatible with recent pandas versions" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -5443,6 +5672,7 @@ requests = ">=2.19.0" name = "pandas-market-calendars" version = "3.2" description = "Market and exchange trading calendars for pandas" +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -5460,6 +5690,7 @@ pytz = "*" name = "pandas-ta" version = "0.3.14b" description = "An easy to use Python 3 Pandas Extension with 130+ Technical Analysis Indicators. Can be called from a Pandas DataFrame or standalone like TA-Lib. Correlation tested with TA-Lib." +category = "main" optional = false python-versions = "*" files = [ @@ -5477,6 +5708,7 @@ test = ["ta-lib"] name = "pandocfilters" version = "1.5.0" description = "Utilities for writing pandoc filters in python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -5488,6 +5720,7 @@ files = [ name = "papermill" version = "2.4.0" description = "Parametrize and run Jupyter and nteract Notebooks" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5521,6 +5754,7 @@ test = ["attrs (>=17.4.0)", "azure-datalake-store (>=0.0.30)", "azure-storage-bl name = "parso" version = "0.8.3" description = "A Python Parser" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -5536,6 +5770,7 @@ testing = ["docopt", "pytest (<6.0.0)"] name = "pathspec" version = "0.11.1" description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -5547,6 +5782,7 @@ files = [ name = "patsy" version = "0.5.3" description = "A Python package for describing statistical models and for building design matrices." +category = "main" optional = false python-versions = "*" files = [ @@ -5565,6 +5801,7 @@ test = ["pytest", "pytest-cov", "scipy"] name = "pbr" version = "5.11.1" description = "Python Build Reasonableness" +category = "dev" optional = false python-versions = ">=2.6" files = [ @@ -5576,6 +5813,7 @@ files = [ name = "pefile" version = "2023.2.7" description = "Python PE parsing module" +category = "main" optional = true python-versions = ">=3.6.0" files = [ @@ -5587,6 +5825,7 @@ files = [ name = "pexpect" version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." +category = "main" optional = false python-versions = "*" files = [ @@ -5601,6 +5840,7 @@ ptyprocess = ">=0.5" name = "pickleshare" version = "0.7.5" description = "Tiny 'shelve'-like database with concurrency support" +category = "main" optional = false python-versions = "*" files = [ @@ -5612,6 +5852,7 @@ files = [ name = "pillow" version = "9.5.0" description = "Python Imaging Library (Fork)" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5691,6 +5932,7 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa name = "pkgutil-resolve-name" version = "1.3.10" description = "Resolve a name to an object." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -5702,6 +5944,7 @@ files = [ name = "platformdirs" version = "3.9.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5717,6 +5960,7 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest- name = "plotly" version = "5.15.0" description = "An open-source, interactive data visualization library for Python" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -5732,6 +5976,7 @@ tenacity = ">=6.2.0" name = "plotly-resampler" version = "0.8.3.2" description = "Visualizing large time series with plotly" +category = "main" optional = true python-versions = ">=3.7.1,<4.0.0" files = [ @@ -5755,6 +6000,7 @@ inline-persistent = ["Flask-Cors (>=3.0.10,<4.0.0)", "kaleido (==0.2.1)"] name = "pluggy" version = "1.2.0" description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -5770,6 +6016,7 @@ testing = ["pytest", "pytest-benchmark"] name = "pmaw" version = "3.0.0" description = "A multithread Pushshift.io API Wrapper for reddit.com comment and submission searches." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -5785,6 +6032,7 @@ requests = "*" name = "pmdarima" version = "2.0.3" description = "Python's forecast::auto.arima equivalent" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -5830,6 +6078,7 @@ urllib3 = "*" name = "posthog" version = "3.0.1" description = "Integrate PostHog into any python application." +category = "main" optional = false python-versions = "*" files = [ @@ -5853,6 +6102,7 @@ test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint" name = "praw" version = "7.7.1" description = "PRAW, an acronym for \"Python Reddit API Wrapper\", is a Python package that allows for simple access to Reddit's API." +category = "main" optional = false python-versions = "~=3.7" files = [ @@ -5867,15 +6117,16 @@ websocket-client = ">=0.54.0" [package.extras] ci = ["coveralls"] -dev = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "furo", "packaging", "pre-commit", "pytest (>=2.7.3)", "requests (>=2.20.1,<3)", "sphinx", "urllib3 (==1.26.*)"] +dev = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "furo", "packaging", "pre-commit", "pytest (>=2.7.3)", "requests (>=2.20.1,<3)", "sphinx", "urllib3 (>=1.26.0,<1.27.0)"] lint = ["furo", "pre-commit", "sphinx"] readthedocs = ["furo", "sphinx"] -test = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "pytest (>=2.7.3)", "requests (>=2.20.1,<3)", "urllib3 (==1.26.*)"] +test = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "pytest (>=2.7.3)", "requests (>=2.20.1,<3)", "urllib3 (>=1.26.0,<1.27.0)"] [[package]] name = "prawcore" version = "2.3.0" description = "Low-level communication layer for PRAW 4+." +category = "main" optional = false python-versions = "~=3.6" files = [ @@ -5896,6 +6147,7 @@ test = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.4.0,<0.5)", "betamax-seri name = "pre-commit" version = "2.21.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -5914,6 +6166,7 @@ virtualenv = ">=20.10.0" name = "prometheus-client" version = "0.17.1" description = "Python client for the Prometheus monitoring system." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -5928,6 +6181,7 @@ twisted = ["twisted"] name = "prompt-toolkit" version = "3.0.39" description = "Library for building powerful interactive command lines in Python" +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -5942,6 +6196,7 @@ wcwidth = "*" name = "property-cached" version = "1.6.4" description = "A decorator for caching properties in classes (forked from cached-property)." +category = "main" optional = false python-versions = ">= 3.5" files = [ @@ -5953,6 +6208,7 @@ files = [ name = "prophet" version = "1.1.3" description = "Automatic Forecasting Procedure" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -5983,6 +6239,7 @@ parallel = ["dask[dataframe]", "distributed"] name = "protobuf" version = "3.20.1" description = "Protocol Buffers" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6016,6 +6273,7 @@ files = [ name = "psutil" version = "5.9.5" description = "Cross-platform lib for process and system monitoring in Python." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -6042,6 +6300,7 @@ test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" +category = "main" optional = false python-versions = "*" files = [ @@ -6053,6 +6312,7 @@ files = [ name = "pure-eval" version = "0.2.2" description = "Safely evaluate AST nodes without side effects" +category = "main" optional = false python-versions = "*" files = [ @@ -6067,6 +6327,7 @@ tests = ["pytest"] name = "py" version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -6078,6 +6339,7 @@ files = [ name = "pyarrow" version = "12.0.1" description = "Python library for Apache Arrow" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6115,6 +6377,7 @@ numpy = ">=1.16.6" name = "pyasn1" version = "0.5.0" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -6126,6 +6389,7 @@ files = [ name = "pyasn1-modules" version = "0.3.0" description = "A collection of ASN.1-based protocols modules" +category = "main" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -6140,6 +6404,7 @@ pyasn1 = ">=0.4.6,<0.6.0" name = "pycares" version = "4.3.0" description = "Python interface for c-ares" +category = "main" optional = false python-versions = "*" files = [ @@ -6207,6 +6472,7 @@ idna = ["idna (>=2.1)"] name = "pycodestyle" version = "2.10.0" description = "Python style guide checker" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -6218,6 +6484,7 @@ files = [ name = "pycoingecko" version = "3.1.0" description = "Python wrapper around the CoinGecko API" +category = "main" optional = false python-versions = "*" files = [ @@ -6232,6 +6499,7 @@ requests = "*" name = "pycparser" version = "2.21" description = "C parser in Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -6243,6 +6511,7 @@ files = [ name = "pycryptodome" version = "3.18.0" description = "Cryptographic library for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -6284,6 +6553,7 @@ files = [ name = "pycryptodomex" version = "3.18.0" description = "Cryptographic library for Python" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -6325,6 +6595,7 @@ files = [ name = "pydantic" version = "1.10.11" description = "Data validation and settings management using python type hints" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6377,6 +6648,7 @@ email = ["email-validator (>=1.0.3)"] name = "pydeck" version = "0.8.0" description = "Widget for deck.gl maps" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6396,6 +6668,7 @@ jupyter = ["ipykernel (>=5.1.2)", "ipython (>=5.8.0)", "ipywidgets (>=7,<8)", "t name = "pydeprecate" version = "0.3.2" description = "Deprecation tooling" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -6407,6 +6680,7 @@ files = [ name = "pydocstyle" version = "6.3.0" description = "Python docstring style checker" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -6424,6 +6698,7 @@ toml = ["tomli (>=1.2.3)"] name = "pyerfa" version = "2.0.0.3" description = "Python bindings for ERFA" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -6480,6 +6755,7 @@ test = ["pytest", "pytest-doctestplus (>=0.7)"] name = "pyflakes" version = "3.0.1" description = "passive checker of Python programs" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -6491,6 +6767,7 @@ files = [ name = "pygls" version = "1.0.2" description = "a pythonic generic language server (pronounced like \"pie glass\")." +category = "main" optional = true python-versions = "<4,>=3.7" files = [ @@ -6506,12 +6783,13 @@ typeguard = ">=3,<4" dev = ["bandit (==1.7.4)", "flake8 (==4.0.1)", "mypy (==0.961)"] docs = ["sphinx (==5.0.1)", "sphinx-rtd-theme (==1.0.0)"] test = ["pytest (==7.1.2)", "pytest-asyncio (==0.18.3)"] -ws = ["websockets (==10.*)"] +ws = ["websockets (>=10.0.0,<11.0.0)"] [[package]] name = "pygments" version = "2.15.1" description = "Pygments is a syntax highlighting package written in Python." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6526,6 +6804,7 @@ plugins = ["importlib-metadata"] name = "pyhdfe" version = "0.1.2" description = "High dimensional fixed effect absorption with Python 3" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -6545,6 +6824,7 @@ tests = ["pytest", "pytest-xdist"] name = "pyinstaller" version = "4.10" description = "PyInstaller bundles a Python application and all its dependencies into a single package." +category = "main" optional = true python-versions = "<3.11,>=3.6" files = [ @@ -6577,6 +6857,7 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] name = "pyinstaller-hooks-contrib" version = "2023.6" description = "Community maintained hooks for PyInstaller" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -6588,6 +6869,7 @@ files = [ name = "pylint" version = "2.17.0" description = "python code static checker" +category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -6614,6 +6896,7 @@ testutils = ["gitpython (>3)"] name = "pyluach" version = "2.2.0" description = "A Python package for dealing with Hebrew (Jewish) calendar dates." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6629,6 +6912,7 @@ test = ["beautifulsoup4", "flake8", "pytest", "pytest-cov"] name = "pymeeus" version = "0.5.12" description = "Python implementation of Jean Meeus astronomical routines" +category = "main" optional = false python-versions = "*" files = [ @@ -6639,6 +6923,7 @@ files = [ name = "pympler" version = "1.0.1" description = "A development tool to measure, monitor and analyze the memory behavior of Python objects." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -6650,6 +6935,7 @@ files = [ name = "pyobjc-core" version = "9.2" description = "Python<->ObjC Interoperability Module" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6667,6 +6953,7 @@ files = [ name = "pyobjc-framework-cocoa" version = "9.2" description = "Wrappers for the Cocoa frameworks on macOS" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6687,6 +6974,7 @@ pyobjc-core = ">=9.2" name = "pyod" version = "1.1.0" description = "A Comprehensive and Scalable Python Library for Outlier Detection (Anomaly Detection)" +category = "main" optional = true python-versions = "*" files = [ @@ -6706,6 +6994,7 @@ six = "*" name = "pyotp" version = "2.8.0" description = "Python One Time Password Library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6717,6 +7006,7 @@ files = [ name = "pyparsing" version = "3.0.9" description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "main" optional = false python-versions = ">=3.6.8" files = [ @@ -6731,6 +7021,7 @@ diagrams = ["jinja2", "railroad-diagrams"] name = "pyprind" version = "2.11.3" description = "Python Progress Bar and Percent Indicator Utility" +category = "main" optional = false python-versions = "*" files = [ @@ -6742,6 +7033,7 @@ files = [ name = "pyrsistent" version = "0.19.3" description = "Persistent/Functional/Immutable data structures" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -6778,6 +7070,7 @@ files = [ name = "pytest" version = "6.2.5" description = "pytest: simple powerful testing with Python" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -6802,6 +7095,7 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm name = "pytest-cov" version = "3.0.0" description = "Pytest plugin for measuring coverage." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -6820,6 +7114,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-mock" version = "3.11.1" description = "Thin-wrapper around the mock package for easier use with pytest" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -6837,6 +7132,7 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] name = "pytest-recorder" version = "0.2.3" description = "Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs." +category = "dev" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -6852,6 +7148,7 @@ vcrpy = ">=4.2.1,<5.0.0" name = "pytest-recording" version = "0.12.2" description = "A pytest plugin that allows you recording of network interactions via VCR.py" +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -6868,6 +7165,7 @@ vcrpy = ">=2.0.1" name = "pytest-timeout" version = "2.1.0" description = "pytest plugin to abort hanging tests" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -6882,6 +7180,7 @@ pytest = ">=5.0.0" name = "pytest-xdist" version = "3.3.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -6902,6 +7201,7 @@ testing = ["filelock"] name = "pythclient" version = "0.1.6" description = "A library to retrieve Pyth account structures off the Solana blockchain." +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -6927,6 +7227,7 @@ testing = ["aiodns", "aiohttp (>=3.7.4)", "backoff", "base58", "dnspython", "fla name = "python-binance" version = "1.0.17" description = "Binance REST API python implementation" +category = "main" optional = false python-versions = "*" files = [ @@ -6947,6 +7248,7 @@ websockets = "*" name = "python-coinmarketcap" version = "0.2" description = "CoinMarketCap Python API Wrapper" +category = "main" optional = false python-versions = "*" files = [ @@ -6959,6 +7261,7 @@ files = [ name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -6973,6 +7276,7 @@ six = ">=1.5" name = "python-dotenv" version = "1.0.0" description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -6987,6 +7291,7 @@ cli = ["click (>=5.0)"] name = "python-i18n" version = "0.3.9" description = "Translation library for Python" +category = "main" optional = false python-versions = "*" files = [ @@ -7001,6 +7306,7 @@ yaml = ["pyyaml (>=3.10)"] name = "python-jose" version = "3.3.0" description = "JOSE implementation in Python" +category = "main" optional = false python-versions = "*" files = [ @@ -7022,6 +7328,7 @@ pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"] name = "python-json-logger" version = "2.0.7" description = "A python library adding a json log formatter" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -7033,6 +7340,7 @@ files = [ name = "pytorch-lightning" version = "1.6.5" description = "PyTorch Lightning is the lightweight PyTorch wrapper for ML researchers. Scale your models. Write less boilerplate." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -7070,6 +7378,7 @@ test = ["cloudpickle (>=1.3)", "codecov (>=2.1)", "coverage (>=6.4)", "flake8 (> name = "pytrends" version = "4.9.2" description = "Pseudo API for Google Trends" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -7086,6 +7395,7 @@ requests = ">=2.0" name = "pytz" version = "2023.3" description = "World timezone definitions, modern and historical" +category = "main" optional = false python-versions = "*" files = [ @@ -7097,6 +7407,7 @@ files = [ name = "pytz-deprecation-shim" version = "0.1.0.post0" description = "Shims to make deprecation of pytz easier" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -7112,6 +7423,7 @@ tzdata = {version = "*", markers = "python_version >= \"3.6\""} name = "pywin32" version = "306" description = "Python for Window Extensions" +category = "main" optional = false python-versions = "*" files = [ @@ -7135,6 +7447,7 @@ files = [ name = "pywin32-ctypes" version = "0.2.2" description = "A (partial) reimplementation of pywin32 using ctypes/cffi" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -7146,6 +7459,7 @@ files = [ name = "pywinpty" version = "2.0.11" description = "Pseudo terminal support for Windows from Python." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -7160,6 +7474,7 @@ files = [ name = "pywry" version = "0.5.13" description = "" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -7188,6 +7503,7 @@ dev = ["auditwheel", "wheel"] name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -7237,6 +7553,7 @@ files = [ name = "pyzmq" version = "25.1.0" description = "Python bindings for 0MQ" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -7326,6 +7643,7 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} name = "qdldl" version = "0.1.7.post0" description = "QDLDL, a free LDL factorization routine." +category = "main" optional = true python-versions = "*" files = [ @@ -7358,6 +7676,7 @@ scipy = ">=0.13.2" name = "qpd" version = "0.4.4" description = "Query Pandas Using SQL" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -7379,6 +7698,7 @@ dask = ["cloudpickle (>=1.4.0)", "dask[dataframe,distributed]"] name = "quandl" version = "3.7.0" description = "Package for quandl API access" +category = "main" optional = false python-versions = ">= 3.6" files = [ @@ -7399,6 +7719,7 @@ six = "*" name = "rdflib" version = "6.3.2" description = "RDFLib is a Python library for working with RDF, a simple yet powerful language for representing information." +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -7420,6 +7741,7 @@ networkx = ["networkx (>=2.0.0,<3.0.0)"] name = "regex" version = "2023.6.3" description = "Alternative regular expression module, to replace re." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -7517,6 +7839,7 @@ files = [ name = "reportlab" version = "3.6.13" description = "The Reportlab Toolkit" +category = "main" optional = false python-versions = ">=3.7,<4" files = [ @@ -7578,6 +7901,7 @@ rlpycairo = ["rlPyCairo (>=0.1.0)"] name = "requests" version = "2.31.0" description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -7599,6 +7923,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-futures" version = "1.0.1" description = "Asynchronous Python HTTP for Humans." +category = "main" optional = false python-versions = "*" files = [ @@ -7616,6 +7941,7 @@ dev = ["black (>=22.3.0)", "build (>=0.7.0)", "isort (>=5.11.4)", "pyflakes (>=2 name = "requests-oauthlib" version = "1.3.1" description = "OAuthlib authentication support for Requests." +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -7634,6 +7960,7 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"] name = "retrying" version = "1.3.4" description = "Retrying" +category = "main" optional = false python-versions = "*" files = [ @@ -7648,6 +7975,7 @@ six = ">=1.7.0" name = "rfc3339-validator" version = "0.1.4" description = "A pure python RFC3339 validator" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -7662,6 +7990,7 @@ six = "*" name = "rfc3986-validator" version = "0.1.1" description = "Pure python rfc3986 validator" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -7673,6 +8002,7 @@ files = [ name = "rich" version = "12.6.0" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "main" optional = false python-versions = ">=3.6.3,<4.0.0" files = [ @@ -7692,6 +8022,7 @@ jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] name = "riskfolio-lib" version = "3.3.0" description = "Portfolio Optimization and Quantitative Strategic Asset Allocation in Python" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -7716,6 +8047,7 @@ xlsxwriter = ">=1.3.7" name = "robin-stocks" version = "2.1.0" description = "A Python wrapper around the Robinhood API" +category = "main" optional = false python-versions = ">=3" files = [ @@ -7733,6 +8065,7 @@ requests = "*" name = "rsa" version = "4.9" description = "Pure-Python RSA implementation" +category = "main" optional = false python-versions = ">=3.6,<4" files = [ @@ -7747,6 +8080,7 @@ pyasn1 = ">=0.1.3" name = "ruamel-yaml" version = "0.17.32" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +category = "main" optional = false python-versions = ">=3" files = [ @@ -7765,6 +8099,7 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] name = "ruamel-yaml-clib" version = "0.2.7" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -7775,8 +8110,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, @@ -7809,34 +8143,36 @@ files = [ [[package]] name = "ruff" -version = "0.0.256" +version = "0.0.285" description = "An extremely fast Python linter, written in Rust." +category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.0.256-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:eb8e949f6e7fb16f9aa163fcc13318e2b7910577513468417e5b003b984410a1"}, - {file = "ruff-0.0.256-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:48a42f0ec4c5a3c3b062e947b2a5f8f7a4264761653fb0ee656a9b535ae6d8d7"}, - {file = "ruff-0.0.256-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36ca633cfc335869643a13e2006f13a63bc4cb94073aa9508ceb08a1e3afe3af"}, - {file = "ruff-0.0.256-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:80fa5d3a40dd0b65c6d6adea4f825984d5d3a215a25d90cc6139978cb22ea1cd"}, - {file = "ruff-0.0.256-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0f88839b886db3577136375865bd080b9ed6f9b85bb990d897780e5a30ca3c2"}, - {file = "ruff-0.0.256-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fe6d77a43b2d52f45ee42f6f682198ed1c34cd0165812e276648981dfd50ad36"}, - {file = "ruff-0.0.256-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3878593507b281b2615702ece06426e8b27076e8fedf658bf0c5e1e5e2ad1b40"}, - {file = "ruff-0.0.256-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e052ec4d5c92663caa662b68fe1902ec10eddac2783229b1c5f20f3df62a865"}, - {file = "ruff-0.0.256-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2116bd67e52ade9f90e5a3a3aa511a9b179c699690221bdd5bb267dbf7e94b22"}, - {file = "ruff-0.0.256-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3c6e93d7818a75669328e49a0f7070c40e18676ca8e56ca9c566633bef4d8d05"}, - {file = "ruff-0.0.256-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7ebb7de4e62d751b65bb15418a83ac5d555afb3eaa3ad549dea21744da34ae86"}, - {file = "ruff-0.0.256-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f310bfc76c0404a487759c8904f57bf51653c46e686c800efc1ff1d165a59a04"}, - {file = "ruff-0.0.256-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:93a0cfec812b2ba57bff22b176901e0ddf44e4d42a9bd7da7ffb5e53df13fd6e"}, - {file = "ruff-0.0.256-py3-none-win32.whl", hash = "sha256:d63e5320bc2d91e94925cd1863e381a48edf087041035967faf2614bb36a6a0d"}, - {file = "ruff-0.0.256-py3-none-win_amd64.whl", hash = "sha256:859c8ffb1801895fe043a2b85a45cd0ff35667ddea4b465ba2a29d275550814a"}, - {file = "ruff-0.0.256-py3-none-win_arm64.whl", hash = "sha256:64b276149e86c3d234608d3fe1da77535865e03debd3a1d5d04576f7f5031bbb"}, - {file = "ruff-0.0.256.tar.gz", hash = "sha256:f9a96b34a4870ee8cf2f3779cd7854620d1788a83b52374771266cf800541bb7"}, + {file = "ruff-0.0.285-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:72a3a0936369b986b0e959f9090206ed3c18f9e5e439ea5b8e6867c6707aded5"}, + {file = "ruff-0.0.285-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:0d9ab6ad16742eb78919e0fba09f914f042409df40ad63423c34bb20d350162a"}, + {file = "ruff-0.0.285-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c48926156288b8ac005eb1db5e77c15e8a37309ae49d9fb6771d5cf5f777590"}, + {file = "ruff-0.0.285-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d2a60c102e7a5e147b58fc2cbea12a563c565383effc527c987ea2086a05742"}, + {file = "ruff-0.0.285-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b02aae62f922d088bb01943e1dbd861688ada13d735b78b8348a7d90121fd292"}, + {file = "ruff-0.0.285-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f572c4296d8c7ddd22c3204de4031965be524fdd1fdaaef273945932912b28c5"}, + {file = "ruff-0.0.285-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80effdf4fe69763d69eb4ab9443e186fd09e668b59fe70ba4b49f4c077d15a1b"}, + {file = "ruff-0.0.285-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5977ce304da35c263f5e082901bd7ac0bd2be845a8fcfd1a29e4d6680cddb307"}, + {file = "ruff-0.0.285-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a087712d474fa17b915d7cb9ef807e1256182b12ddfafb105eb00aeee48d1a"}, + {file = "ruff-0.0.285-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7ce67736cd8dfe97162d1e7adfc2d9a1bac0efb9aaaff32e4042c7cde079f54b"}, + {file = "ruff-0.0.285-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5473a4c6cac34f583bff08c5f63b8def5599a0ea4dc96c0302fbd2cc0b3ecbad"}, + {file = "ruff-0.0.285-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e6b1c961d608d373a032f047a20bf3c55ad05f56c32e7b96dcca0830a2a72348"}, + {file = "ruff-0.0.285-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2933cc9631f453305399c7b8fb72b113ad76b49ae1d7103cc4afd3a423bed164"}, + {file = "ruff-0.0.285-py3-none-win32.whl", hash = "sha256:770c5eb6376de024111443022cda534fb28980a9dd3b4abc83992a8770167ba6"}, + {file = "ruff-0.0.285-py3-none-win_amd64.whl", hash = "sha256:a8c6ad6b9cd77489bf6d1510950cbbe47a843aa234adff0960bae64bd06c3b6d"}, + {file = "ruff-0.0.285-py3-none-win_arm64.whl", hash = "sha256:de44fbc6c3b25fccee473ddf851416fd4e246fc6027b2197c395b1b3b3897921"}, + {file = "ruff-0.0.285.tar.gz", hash = "sha256:45866048d1dcdcc80855998cb26c4b2b05881f9e043d2e3bfe1aa36d9a2e8f28"}, ] [[package]] name = "scikit-learn" version = "1.3.0" description = "A set of python modules for machine learning and data mining" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -7879,6 +8215,7 @@ tests = ["black (>=23.3.0)", "matplotlib (>=3.1.3)", "mypy (>=1.3)", "numpydoc ( name = "scipy" version = "1.10.1" description = "Fundamental algorithms for scientific computing in Python" +category = "main" optional = false python-versions = "<3.12,>=3.8" files = [ @@ -7917,6 +8254,7 @@ test = ["asv", "gmpy2", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeo name = "screeninfo" version = "0.6.7" description = "Fetch location and size of physical screens." +category = "main" optional = false python-versions = "*" files = [ @@ -7931,6 +8269,7 @@ pyobjc-framework-Cocoa = {version = "*", markers = "sys_platform == \"darwin\""} name = "scs" version = "3.2.3" description = "scs: splitting conic solver" +category = "main" optional = true python-versions = "*" files = [ @@ -7960,6 +8299,7 @@ scipy = ">=0.13.2" name = "seaborn" version = "0.11.2" description = "seaborn: statistical data visualization" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -7977,6 +8317,7 @@ scipy = ">=1.0" name = "semantic-version" version = "2.10.0" description = "A library implementing the 'SemVer' scheme." +category = "main" optional = true python-versions = ">=2.7" files = [ @@ -7992,6 +8333,7 @@ doc = ["Sphinx", "sphinx-rtd-theme"] name = "send2trash" version = "1.8.2" description = "Send file to trash natively under Mac OS X, Windows and Linux" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -8008,6 +8350,7 @@ win32 = ["pywin32"] name = "setproctitle" version = "1.3.2" description = "A Python module to customize the process title" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8092,6 +8435,7 @@ test = ["pytest"] name = "setuptools" version = "65.4.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8108,6 +8452,7 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs ( name = "setuptools-rust" version = "1.6.0" description = "Setuptools Rust extension plugin" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -8124,6 +8469,7 @@ typing-extensions = ">=3.7.4.3" name = "setuptools-scm" version = "7.1.0" description = "the blessed package to manage your versions by scm tags" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8148,6 +8494,7 @@ toml = ["setuptools (>=42)"] name = "sgmllib3k" version = "1.0.0" description = "Py3k port of sgmllib." +category = "main" optional = false python-versions = "*" files = [ @@ -8158,6 +8505,7 @@ files = [ name = "shap" version = "0.42.1" description = "A unified approach to explain the output of any machine learning model." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -8210,6 +8558,7 @@ test-core = ["pytest", "pytest-cov", "pytest-mpl"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -8221,6 +8570,7 @@ files = [ name = "slicer" version = "0.0.7" description = "A small package for big slicing." +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -8232,6 +8582,7 @@ files = [ name = "smmap" version = "5.0.0" description = "A pure Python implementation of a sliding window memory map manager" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -8243,6 +8594,7 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8254,6 +8606,7 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "dev" optional = false python-versions = "*" files = [ @@ -8265,6 +8618,7 @@ files = [ name = "soupsieve" version = "2.4.1" description = "A modern CSS selector implementation for Beautiful Soup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8276,6 +8630,7 @@ files = [ name = "sparqlwrapper" version = "2.0.0" description = "SPARQL Endpoint interface to Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8296,6 +8651,7 @@ pandas = ["pandas (>=1.3.5)"] name = "sphinx" version = "4.5.0" description = "Python documentation generator" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -8331,6 +8687,7 @@ test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] name = "sphinxcontrib-applehelp" version = "1.0.4" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -8346,6 +8703,7 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -8361,6 +8719,7 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.0.1" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -8376,6 +8735,7 @@ test = ["html5lib", "pytest"] name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -8390,6 +8750,7 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -8405,6 +8766,7 @@ test = ["pytest"] name = "sphinxcontrib-serializinghtml" version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -8420,6 +8782,7 @@ test = ["pytest"] name = "sqlalchemy" version = "2.0.19" description = "Database Abstraction Library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8467,7 +8830,7 @@ files = [ ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} typing-extensions = ">=4.2.0" [package.extras] @@ -8498,6 +8861,7 @@ sqlcipher = ["sqlcipher3-binary"] name = "sqlglot" version = "17.6.0" description = "An easily customizable SQL parser and transpiler" +category = "main" optional = true python-versions = "*" files = [ @@ -8512,6 +8876,7 @@ dev = ["autoflake", "black", "duckdb (>=0.6)", "isort", "mypy (>=0.990)", "panda name = "squarify" version = "0.4.3" description = "Pure Python implementation of the squarify treemap layout algorithm" +category = "main" optional = false python-versions = "*" files = [ @@ -8523,6 +8888,7 @@ files = [ name = "stack-data" version = "0.6.2" description = "Extract data from python stack frames and tracebacks for informative displays" +category = "main" optional = false python-versions = "*" files = [ @@ -8542,6 +8908,7 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] name = "statsforecast" version = "1.5.0" description = "Time series forecasting suite using statistical models" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -8569,6 +8936,7 @@ ray = ["fugue[ray] (>=0.8.1)", "protobuf (>=3.15.3,<4.0.0)"] name = "statsmodels" version = "0.13.2" description = "Statistical computations and models for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8613,6 +8981,7 @@ docs = ["ipykernel", "jupyter-client", "matplotlib", "nbconvert", "nbformat", "n name = "statsmodels" version = "0.13.3" description = "Statistical computations and models for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8648,7 +9017,7 @@ numpy = {version = ">=1.17", markers = "python_version != \"3.10\" or platform_s packaging = ">=21.3" pandas = ">=0.25" patsy = ">=0.5.2" -scipy = {version = ">=1.3", markers = "(python_version > \"3.7\" or platform_system != \"Windows\" or platform_machine != \"x86\") and python_version < \"3.12\""} +scipy = {version = ">=1.3", markers = "python_version > \"3.7\" and python_version < \"3.12\" or platform_system != \"Windows\" and python_version < \"3.12\" or platform_machine != \"x86\" and python_version < \"3.12\""} [package.extras] build = ["cython (>=0.29.32)"] @@ -8659,6 +9028,7 @@ docs = ["ipykernel", "jupyter-client", "matplotlib", "nbconvert", "nbformat", "n name = "statsmodels" version = "0.13.5" description = "Statistical computations and models for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8697,7 +9067,7 @@ numpy = [ packaging = ">=21.3" pandas = ">=0.25" patsy = ">=0.5.2" -scipy = {version = ">=1.3", markers = "(python_version > \"3.9\" or platform_system != \"Windows\" or platform_machine != \"x86\") and python_version < \"3.12\""} +scipy = {version = ">=1.3", markers = "python_version > \"3.9\" and python_version < \"3.12\" or platform_system != \"Windows\" and python_version < \"3.12\" or platform_machine != \"x86\" and python_version < \"3.12\""} [package.extras] build = ["cython (>=0.29.32)"] @@ -8708,6 +9078,7 @@ docs = ["ipykernel", "jupyter-client", "matplotlib", "nbconvert", "nbformat", "n name = "stevedore" version = "5.1.0" description = "Manage dynamic plugins for Python applications" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -8722,6 +9093,7 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0" name = "stocksera" version = "0.1.21" description = "Official Stocksera API" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -8737,6 +9109,7 @@ requests = "*" name = "streamlit" version = "1.24.1" description = "A faster way to build and share data apps" +category = "main" optional = false python-versions = ">=3.8, !=3.9.7" files = [ @@ -8777,6 +9150,7 @@ snowflake = ["snowflake-snowpark-python"] name = "svglib" version = "1.5.1" description = "A pure-Python library for reading and converting SVG" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8793,6 +9167,7 @@ tinycss2 = ">=0.6.0" name = "tabulate" version = "0.9.0" description = "Pretty-print tabular data" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8807,6 +9182,7 @@ widechars = ["wcwidth"] name = "tbats" version = "1.1.3" description = "BATS and TBATS for time series forecasting" +category = "main" optional = true python-versions = "*" files = [ @@ -8827,6 +9203,7 @@ dev = ["pip-tools", "pytest", "rpy2"] name = "tenacity" version = "8.2.2" description = "Retry code until it succeeds" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -8841,6 +9218,7 @@ doc = ["reno", "sphinx", "tornado (>=4.5)"] name = "tensorboard" version = "2.13.0" description = "TensorBoard lets you watch Tensors Flow" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -8865,6 +9243,7 @@ wheel = ">=0.26" name = "tensorboard-data-server" version = "0.7.1" description = "Fast data loading for TensorBoard" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -8877,6 +9256,7 @@ files = [ name = "terminado" version = "0.17.1" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -8897,6 +9277,7 @@ test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] name = "textwrap3" version = "0.9.2" description = "textwrap from Python 3.6 backport (plus a few tweaks)" +category = "main" optional = false python-versions = "*" files = [ @@ -8908,6 +9289,7 @@ files = [ name = "thepassiveinvestor" version = "1.2.1" description = "Passive Investing for the Average Joe." +category = "main" optional = false python-versions = "*" files = [ @@ -8924,6 +9306,7 @@ yahooquery = "*" name = "threadpoolctl" version = "3.2.0" description = "threadpoolctl" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -8935,6 +9318,7 @@ files = [ name = "tiktoken" version = "0.4.0" description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -8980,6 +9364,7 @@ blobfile = ["blobfile (>=2)"] name = "time-machine" version = "2.11.0" description = "Travel through time in your tests." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -9037,6 +9422,7 @@ python-dateutil = "*" name = "tinycss2" version = "1.2.1" description = "A tiny CSS parser" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9055,6 +9441,7 @@ test = ["flake8", "isort", "pytest"] name = "tokenizers" version = "0.13.3" description = "Fast and Customizable Tokenizers" +category = "main" optional = true python-versions = "*" files = [ @@ -9109,6 +9496,7 @@ testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] name = "tokenterminal" version = "1.0.1" description = "Unofficial Token Terminal API client." +category = "main" optional = false python-versions = "*" files = [ @@ -9123,6 +9511,7 @@ requests = ">=2.18.4" name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -9134,6 +9523,7 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9145,6 +9535,7 @@ files = [ name = "tomlkit" version = "0.11.8" description = "Style preserving TOML library" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -9156,6 +9547,7 @@ files = [ name = "toolz" version = "0.12.0" description = "List processing tools and functional utilities" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -9167,6 +9559,7 @@ files = [ name = "torch" version = "1.11.0" description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" +category = "main" optional = true python-versions = ">=3.7.0" files = [ @@ -9198,6 +9591,7 @@ typing-extensions = "*" name = "torchmetrics" version = "1.0.1" description = "PyTorch native Metrics" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -9227,6 +9621,7 @@ visual = ["SciencePlots (>=2.0.0)", "matplotlib (>=3.2.0)"] name = "tornado" version = "6.3.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "main" optional = false python-versions = ">= 3.8" files = [ @@ -9247,6 +9642,7 @@ files = [ name = "tqdm" version = "4.65.0" description = "Fast, Extensible Progress Meter" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9267,6 +9663,7 @@ telegram = ["requests"] name = "trace-updater" version = "0.0.9.1" description = "Dash component which allows to update a dcc.Graph its traces. This component is data efficient as it (1) only sends the to-be-updated traces (and not the whole) from the back-end to the client-side and (2) only updates the traces that have changed (and does not redraw the whole figure)." +category = "main" optional = true python-versions = "*" files = [ @@ -9278,6 +9675,7 @@ files = [ name = "tradingview-ta" version = "3.3.0" description = "Unofficial TradingView technical analysis API wrapper." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -9292,6 +9690,7 @@ requests = "*" name = "traitlets" version = "5.9.0" description = "Traitlets Python configuration system" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9307,6 +9706,7 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] name = "transformers" version = "4.27.1" description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow" +category = "main" optional = true python-versions = ">=3.7.0" files = [ @@ -9374,6 +9774,7 @@ vision = ["Pillow"] name = "triad" version = "0.9.1" description = "A collection of python utils for Fugue projects" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -9396,6 +9797,7 @@ ciso8601 = ["ciso8601"] name = "typeguard" version = "3.0.2" description = "Run-time type checker for Python" +category = "main" optional = true python-versions = ">=3.7.4" files = [ @@ -9415,6 +9817,7 @@ test = ["mypy (>=0.991)", "pytest (>=7)"] name = "types-python-dateutil" version = "2.8.19.14" description = "Typing stubs for python-dateutil" +category = "dev" optional = false python-versions = "*" files = [ @@ -9426,6 +9829,7 @@ files = [ name = "types-pytz" version = "2021.3.8" description = "Typing stubs for pytz" +category = "dev" optional = false python-versions = "*" files = [ @@ -9437,6 +9841,7 @@ files = [ name = "types-pyyaml" version = "6.0.12.11" description = "Typing stubs for PyYAML" +category = "dev" optional = false python-versions = "*" files = [ @@ -9448,6 +9853,7 @@ files = [ name = "types-requests" version = "2.31.0.2" description = "Typing stubs for requests" +category = "dev" optional = false python-versions = "*" files = [ @@ -9462,6 +9868,7 @@ types-urllib3 = "*" name = "types-setuptools" version = "57.4.18" description = "Typing stubs for setuptools" +category = "dev" optional = false python-versions = "*" files = [ @@ -9473,6 +9880,7 @@ files = [ name = "types-six" version = "1.16.21.9" description = "Typing stubs for six" +category = "dev" optional = false python-versions = "*" files = [ @@ -9484,6 +9892,7 @@ files = [ name = "types-urllib3" version = "1.26.25.14" description = "Typing stubs for urllib3" +category = "dev" optional = false python-versions = "*" files = [ @@ -9495,6 +9904,7 @@ files = [ name = "typing-extensions" version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9506,6 +9916,7 @@ files = [ name = "typing-inspect" version = "0.9.0" description = "Runtime inspection utilities for typing module." +category = "main" optional = false python-versions = "*" files = [ @@ -9521,6 +9932,7 @@ typing-extensions = ">=3.7.4" name = "tzdata" version = "2023.3" description = "Provider of IANA time zone data" +category = "main" optional = false python-versions = ">=2" files = [ @@ -9532,6 +9944,7 @@ files = [ name = "tzlocal" version = "4.3.1" description = "tzinfo object for the local timezone" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9551,6 +9964,7 @@ devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pyte name = "u8darts" version = "0.23.0" description = "A python library for easy manipulation and forecasting of time series." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -9591,6 +10005,7 @@ torch = ["pytorch-lightning (>=1.5.0)", "torch (>=1.8.0)"] name = "ujson" version = "5.8.0" description = "Ultra fast JSON encoder and decoder for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -9661,6 +10076,7 @@ files = [ name = "update-checker" version = "0.18.0" description = "A python module that will check for package updates." +category = "main" optional = false python-versions = "*" files = [ @@ -9680,6 +10096,7 @@ test = ["pytest (>=2.7.3)"] name = "uri-template" version = "1.3.0" description = "RFC 6570 URI Template Processor" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9694,6 +10111,7 @@ dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake name = "urllib3" version = "1.26.16" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -9710,6 +10128,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "user-agent" version = "0.1.10" description = "User-Agent generator" +category = "main" optional = false python-versions = "*" files = [ @@ -9723,6 +10142,7 @@ six = "*" name = "vadersentiment" version = "3.3.2" description = "VADER Sentiment Analysis. VADER (Valence Aware Dictionary and sEntiment Reasoner) is a lexicon and rule-based sentiment analysis tool that is specifically attuned to sentiments expressed in social media, and works well on texts from other domains." +category = "main" optional = false python-versions = "*" files = [ @@ -9737,6 +10157,7 @@ requests = "*" name = "validators" version = "0.20.0" description = "Python Data Validation for Humans™." +category = "main" optional = false python-versions = ">=3.4" files = [ @@ -9753,6 +10174,7 @@ test = ["flake8 (>=2.4.0)", "isort (>=4.2.2)", "pytest (>=2.2.3)"] name = "valinvest" version = "0.0.2" description = "A value investing tool based on Warren Buffett, Joseph Piotroski and Benjamin Graham thoughts" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -9764,6 +10186,7 @@ files = [ name = "vcrpy" version = "4.4.0" description = "Automatically mock your HTTP interactions to simplify and speed up testing" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -9782,6 +10205,7 @@ yarl = "*" name = "virtualenv" version = "20.24.1" description = "Virtual Python Environment builder" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -9802,6 +10226,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "watchdog" version = "2.3.1" description = "Filesystem events monitoring" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -9842,6 +10267,7 @@ watchmedo = ["PyYAML (>=3.10)"] name = "wcwidth" version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" +category = "main" optional = false python-versions = "*" files = [ @@ -9853,6 +10279,7 @@ files = [ name = "webcolors" version = "1.13" description = "A library for working with the color formats defined by HTML and CSS." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9868,6 +10295,7 @@ tests = ["pytest", "pytest-cov"] name = "webencodings" version = "0.5.1" description = "Character encoding aliases for legacy web content" +category = "main" optional = false python-versions = "*" files = [ @@ -9879,6 +10307,7 @@ files = [ name = "websocket-client" version = "1.6.1" description = "WebSocket client for Python with low level API options" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9895,6 +10324,7 @@ test = ["websockets"] name = "websockets" version = "11.0.3" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -9974,6 +10404,7 @@ files = [ name = "werkzeug" version = "2.3.6" description = "The comprehensive WSGI web application library." +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -9991,6 +10422,7 @@ watchdog = ["watchdog (>=2.3)"] name = "wheel" version = "0.40.0" description = "A built-package format for Python" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -10005,6 +10437,7 @@ test = ["pytest (>=6.0.0)"] name = "widgetsnbextension" version = "4.0.8" description = "Jupyter interactive widgets for Jupyter Notebook" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -10016,6 +10449,7 @@ files = [ name = "win32-setctime" version = "1.1.0" description = "A small Python utility to set file creation time on Windows" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -10030,6 +10464,7 @@ dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] name = "wrapt" version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -10114,6 +10549,7 @@ files = [ name = "xarray" version = "2023.1.0" description = "N-D labeled arrays and datasets in Python" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -10138,6 +10574,7 @@ viz = ["matplotlib", "nc-time-axis", "seaborn"] name = "xgboost" version = "1.7.6" description = "XGBoost Python Package" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -10165,6 +10602,7 @@ scikit-learn = ["scikit-learn"] name = "xlsxwriter" version = "3.1.2" description = "A Python module for creating Excel XLSX files." +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -10176,6 +10614,7 @@ files = [ name = "y-py" version = "0.6.0" description = "Python bindings for the Y-CRDT built from yrs (Rust)" +category = "main" optional = false python-versions = "*" files = [ @@ -10251,6 +10690,7 @@ files = [ name = "yahooquery" version = "2.3.2" description = "Python interface to unofficial Yahoo Finance API endpoints" +category = "main" optional = false python-versions = "*" files = [ @@ -10273,6 +10713,7 @@ test = ["coverage (==5.2.1)", "pytest (==6.0.2)", "pytest-cov (==2.10.1)", "sele name = "yarl" version = "1.9.2" description = "Yet another URL library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -10360,6 +10801,7 @@ multidict = ">=4.0" name = "yfinance" version = "0.2.25" description = "Download market data from Yahoo! Finance API" +category = "main" optional = false python-versions = "*" files = [ @@ -10383,6 +10825,7 @@ requests = ">=2.26" name = "ypy-websocket" version = "0.8.4" description = "WebSocket connector for Ypy" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -10402,6 +10845,7 @@ test = ["mypy", "pre-commit", "pytest", "pytest-asyncio", "websockets (>=10.0)"] name = "yt-dlp" version = "2023.7.6" description = "A youtube-dl fork with additional features and patches" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -10421,6 +10865,7 @@ websockets = "*" name = "zipp" version = "3.16.2" description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -10436,6 +10881,7 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p name = "zope-interface" version = "6.0" description = "Interfaces for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -10490,4 +10936,4 @@ optimization = ["Riskfolio-Lib"] [metadata] lock-version = "2.0" python-versions = "^3.8.1,<3.11, !=3.9.7" -content-hash = "cf28c86b1360b436443a486b5ed8b33101e35d3a6c02f81c7dc85515e520c634" +content-hash = "3758e48ae4cb9a6e0b8230c499e52258247407589475577994761c1141fea600" diff --git a/pyproject.toml b/pyproject.toml index 504d83c49a3c..b5ff20871c9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -122,6 +122,7 @@ ffn = "0.3.6" jupyter-client = "7.4.1" jupyter-server = "1.23.6" python-jose = "^3.3.0" +ruff = "0.0.285" @@ -158,7 +159,6 @@ pre-commit = "^2.16.0" pytest-cov = "^3.0.0" types-six = "^1.16.12" nbmake = ">0.5.0" -ruff = "^0.0.256" pytest-timeout = "^2.1.0" pytest-recorder = "^0.2.1" freezegun = "^1.2.2" @@ -181,10 +181,11 @@ target-version = "py38" # All options here: https://github.com/charliermarsh/ruff#supported-rules select = ["E", "W", "F", "Q", "S", "UP", "I", "PLC", "PLE", "PLR", "PLW", "SIM"] # These ignores should be seen as temporary solutions to problems that will NEED fixed -ignore = ["S105", "S106", "S107", "S110", "PLR2004", "PLR0911", "PLR0913", "PLR0912", "PLR0915", "SIM114", "SIM105", "SIM117", "PLC1901", "PLR5501","PLW2901","PLW0603"] +ignore = ["S105", "S106", "S107", "S110", "PLR2004", "PLR0911", "PLR0913", "PLR0912", "PLR0915", "SIM114", "SIM105", "SIM117", "PLC1901", "PLR5501","PLW2901","PLW0603", "E741", "S311", "S602", "S603", "S605", "S607", "S307"] [tool.ruff.per-file-ignores] "tests/*" = ["S101"] +"*init*.py" = ["F401"] [tool.ruff.flake8-import-conventions.aliases] "matplotlib.pyplot" = "plt" diff --git a/tests/openbb_terminal/alternative/covid/test_covid_controller.py b/tests/openbb_terminal/alternative/covid/test_covid_controller.py index ff1a51b4ff81..010e72a52e99 100644 --- a/tests/openbb_terminal/alternative/covid/test_covid_controller.py +++ b/tests/openbb_terminal/alternative/covid/test_covid_controller.py @@ -9,7 +9,6 @@ from openbb_terminal.alternative.covid import covid_controller from openbb_terminal.core.session.current_user import PreferencesModel, copy_user - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/alternative/oss/test_oss_controller.py b/tests/openbb_terminal/alternative/oss/test_oss_controller.py index 0d31ebe4b07d..d78fc0771b29 100644 --- a/tests/openbb_terminal/alternative/oss/test_oss_controller.py +++ b/tests/openbb_terminal/alternative/oss/test_oss_controller.py @@ -9,7 +9,6 @@ from openbb_terminal.alternative.oss import oss_controller from openbb_terminal.core.session.current_user import PreferencesModel, copy_user - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/alternative/test_alt_controller.py b/tests/openbb_terminal/alternative/test_alt_controller.py index e8cdabd69e2a..f57b376b0dd5 100644 --- a/tests/openbb_terminal/alternative/test_alt_controller.py +++ b/tests/openbb_terminal/alternative/test_alt_controller.py @@ -12,7 +12,6 @@ copy_user, ) - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/core/log/generation/test_formatter_with_exceptions.py b/tests/openbb_terminal/core/log/generation/test_formatter_with_exceptions.py index 0374f3b531d1..7c9247141811 100644 --- a/tests/openbb_terminal/core/log/generation/test_formatter_with_exceptions.py +++ b/tests/openbb_terminal/core/log/generation/test_formatter_with_exceptions.py @@ -63,7 +63,7 @@ def test_format(mocker): mock.levelname = "" mock.created = 6 mock.name = "Hello" - mock.getMessage = lambda: "aeffew" or "3232432423" + mock.getMessage = lambda: "aeffew" mock.stack_info = "info" value = formatter.format(mock) assert value diff --git a/tests/openbb_terminal/cryptocurrency/defi/test_defi_controller.py b/tests/openbb_terminal/cryptocurrency/defi/test_defi_controller.py index a5a1263266c5..680de88be72d 100644 --- a/tests/openbb_terminal/cryptocurrency/defi/test_defi_controller.py +++ b/tests/openbb_terminal/cryptocurrency/defi/test_defi_controller.py @@ -12,7 +12,6 @@ ) from openbb_terminal.cryptocurrency.defi import defi_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/cryptocurrency/discovery/test_discovery_controller.py b/tests/openbb_terminal/cryptocurrency/discovery/test_discovery_controller.py index 0991d598dc26..2ae21e16fa0b 100644 --- a/tests/openbb_terminal/cryptocurrency/discovery/test_discovery_controller.py +++ b/tests/openbb_terminal/cryptocurrency/discovery/test_discovery_controller.py @@ -9,7 +9,6 @@ from openbb_terminal.core.session.current_user import PreferencesModel, copy_user from openbb_terminal.cryptocurrency.discovery import discovery_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/cryptocurrency/nft/test_nft_controller.py b/tests/openbb_terminal/cryptocurrency/nft/test_nft_controller.py index 5c166c894d41..7ff5a4f83ccc 100644 --- a/tests/openbb_terminal/cryptocurrency/nft/test_nft_controller.py +++ b/tests/openbb_terminal/cryptocurrency/nft/test_nft_controller.py @@ -12,7 +12,6 @@ ) from openbb_terminal.cryptocurrency.nft import nft_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/cryptocurrency/onchain/test_onchain_controller.py b/tests/openbb_terminal/cryptocurrency/onchain/test_onchain_controller.py index debbcaad5ebd..4fe08ffb5f10 100644 --- a/tests/openbb_terminal/cryptocurrency/onchain/test_onchain_controller.py +++ b/tests/openbb_terminal/cryptocurrency/onchain/test_onchain_controller.py @@ -12,7 +12,6 @@ ) from openbb_terminal.cryptocurrency.onchain import onchain_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/cryptocurrency/tools/test_tools_controller.py b/tests/openbb_terminal/cryptocurrency/tools/test_tools_controller.py index 58f6dd39efa6..38c224e0c1a7 100644 --- a/tests/openbb_terminal/cryptocurrency/tools/test_tools_controller.py +++ b/tests/openbb_terminal/cryptocurrency/tools/test_tools_controller.py @@ -12,7 +12,6 @@ ) from openbb_terminal.cryptocurrency.tools import tools_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/futures/test_futures_controller.py b/tests/openbb_terminal/futures/test_futures_controller.py index 22bde7dbd0b3..657858d6fd84 100644 --- a/tests/openbb_terminal/futures/test_futures_controller.py +++ b/tests/openbb_terminal/futures/test_futures_controller.py @@ -12,7 +12,6 @@ ) from openbb_terminal.futures import futures_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/mutual_funds/test_mutual_fund_controller.py b/tests/openbb_terminal/mutual_funds/test_mutual_fund_controller.py index b133ab602dfb..b5a5499b8030 100644 --- a/tests/openbb_terminal/mutual_funds/test_mutual_fund_controller.py +++ b/tests/openbb_terminal/mutual_funds/test_mutual_fund_controller.py @@ -10,7 +10,6 @@ # IMPORTATION INTERNAL from openbb_terminal.mutual_funds import mutual_fund_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/portfolio/brokers/degiro/test_degiro_controller.py b/tests/openbb_terminal/portfolio/brokers/degiro/test_degiro_controller.py index a56fbfea26a1..ab72c94fbc5c 100644 --- a/tests/openbb_terminal/portfolio/brokers/degiro/test_degiro_controller.py +++ b/tests/openbb_terminal/portfolio/brokers/degiro/test_degiro_controller.py @@ -12,7 +12,6 @@ ) from openbb_terminal.portfolio.brokers.degiro import degiro_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/portfolio/test_portfolio_controller.py b/tests/openbb_terminal/portfolio/test_portfolio_controller.py index 34d623a7c6aa..9973589e0b33 100644 --- a/tests/openbb_terminal/portfolio/test_portfolio_controller.py +++ b/tests/openbb_terminal/portfolio/test_portfolio_controller.py @@ -12,7 +12,6 @@ ) from openbb_terminal.portfolio import portfolio_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/reports/test_reports_controller.py b/tests/openbb_terminal/reports/test_reports_controller.py index 32f268c658e4..49b717148418 100644 --- a/tests/openbb_terminal/reports/test_reports_controller.py +++ b/tests/openbb_terminal/reports/test_reports_controller.py @@ -12,7 +12,6 @@ ) from openbb_terminal.reports import reports_controller, reports_model - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/stocks/discovery/test_disc_controller.py b/tests/openbb_terminal/stocks/discovery/test_disc_controller.py index 24ce8f952171..faabdeedb9f8 100644 --- a/tests/openbb_terminal/stocks/discovery/test_disc_controller.py +++ b/tests/openbb_terminal/stocks/discovery/test_disc_controller.py @@ -10,7 +10,6 @@ from openbb_terminal.core.session.current_user import PreferencesModel, copy_user from openbb_terminal.stocks.discovery import disc_controller - # pylint: disable=E1101,W0603,E1111 diff --git a/tests/openbb_terminal/stocks/fundamental_analysis/test_fa_controller.py b/tests/openbb_terminal/stocks/fundamental_analysis/test_fa_controller.py index ca4fccfd322b..c0c6d7c15b1f 100644 --- a/tests/openbb_terminal/stocks/fundamental_analysis/test_fa_controller.py +++ b/tests/openbb_terminal/stocks/fundamental_analysis/test_fa_controller.py @@ -11,7 +11,6 @@ from openbb_terminal.core.session.current_user import PreferencesModel, copy_user from openbb_terminal.stocks.fundamental_analysis import fa_controller - # pylint: disable=E1101 # pylint: disable=W0603 # pylint: disable=E1111 diff --git a/tests/openbb_terminal/stocks/insider/test_openinsider_view.py b/tests/openbb_terminal/stocks/insider/test_openinsider_view.py index 4fcbd1680654..cb26afddfd03 100644 --- a/tests/openbb_terminal/stocks/insider/test_openinsider_view.py +++ b/tests/openbb_terminal/stocks/insider/test_openinsider_view.py @@ -7,7 +7,6 @@ # IMPORTATION INTERNAL from openbb_terminal.stocks.insider import openinsider_view - # pylint: disable=E1101 diff --git a/website/controller_doc_classes.py b/website/controller_doc_classes.py index 39efdc45970f..93b99c6191e5 100644 --- a/website/controller_doc_classes.py +++ b/website/controller_doc_classes.py @@ -460,11 +460,10 @@ def get_controllers(self) -> None: if ( # noqa: SIM102 name != "TerminalController" and "BaseController" not in name ): # noqa: SIM102 - if isclass(obj) and issubclass(obj, BaseController): - if trailmap not in self.controller_docs: - ctrl = ControllerDoc(obj, trailmap) # type: ignore - if ctrl.has_commands(): - self.controller_docs[trailmap] = ctrl + if isclass(obj) and issubclass(obj, BaseController) and trailmap not in self.controller_docs: + ctrl = ControllerDoc(obj, trailmap) # type: ignore + if ctrl.has_commands(): + self.controller_docs[trailmap] = ctrl def _get_modules(self) -> Dict[str, ModuleType]: """Gets all controllers modules""" From ac6a270573eb3969126eb4a616aef69b22b480fa Mon Sep 17 00:00:00 2001 From: colin99d Date: Mon, 21 Aug 2023 16:47:17 -0400 Subject: [PATCH 03/20] Fixed a BUNCH of ruff errors --- .../generation/path_tracking_file_handler.py | 4 +- openbb_terminal/core/plots/backend.py | 17 ++- .../cryptocurrency/cryptocurrency_helpers.py | 4 +- .../dashboards/stream/Forecasting.py | 9 +- .../dashboards/stream/pages/Indicators.py | 133 +++++++++--------- .../dashboards/stream/pages/Stocks.py | 4 +- openbb_terminal/fixedincome/ecb_model.py | 13 +- openbb_terminal/loggers.py | 4 +- openbb_terminal/portfolio/portfolio_helper.py | 22 ++- openbb_terminal/routine_functions.py | 43 ++---- .../stocks/dark_pool_shorts/finra_model.py | 2 +- .../fundamental_analysis/finviz_model.py | 2 +- .../stocks/options/options_chains_model.py | 14 +- .../quantitative_analysis/factors_model.py | 23 ++- openbb_terminal/stocks/stocks_helper.py | 2 +- pyproject.toml | 3 +- .../session/test_local_model.py | 16 +-- 17 files changed, 142 insertions(+), 173 deletions(-) diff --git a/openbb_terminal/core/log/generation/path_tracking_file_handler.py b/openbb_terminal/core/log/generation/path_tracking_file_handler.py index bd97c8a57ed6..5cdf91556041 100644 --- a/openbb_terminal/core/log/generation/path_tracking_file_handler.py +++ b/openbb_terminal/core/log/generation/path_tracking_file_handler.py @@ -186,8 +186,8 @@ def close(self): log_sender.send_path(path=closed_log_path, last=True) try: log_sender.join(timeout=3) - except Exception: - pass # noqa + except Exception: # noqa: S110 + pass super().close() diff --git a/openbb_terminal/core/plots/backend.py b/openbb_terminal/core/plots/backend.py index 97a337bf800a..1cfb1b7845eb 100644 --- a/openbb_terminal/core/plots/backend.py +++ b/openbb_terminal/core/plots/backend.py @@ -424,7 +424,7 @@ async def get_results(self, description: str) -> dict: data: dict = self.recv.get(block=False) or {} if data.get("result", False): return json.loads(data["result"]) - except Exception: # pylint: disable=W0703 + except Exception: # pylint: disable=W0703 # noqa: S110 pass await asyncio.sleep(1) @@ -482,14 +482,13 @@ async def download_plotly_js(): # this is so we don't have to block the main thread async with aiohttp.ClientSession( connector=aiohttp.TCPConnector(verify_ssl=False) - ) as session: - async with session.get(f"https://cdn.plot.ly/{js_filename}") as resp: - with open(str(PLOTLYJS_PATH), "wb") as f: - while True: - chunk = await resp.content.read(1024) - if not chunk: - break - f.write(chunk) + ) as session, session.get(f"https://cdn.plot.ly/{js_filename}") as resp: + with open(str(PLOTLYJS_PATH), "wb") as f: + while True: + chunk = await resp.content.read(1024) + if not chunk: + break + f.write(chunk) # We delete the old version of plotly.js for file in (PLOTS_CORE_PATH / "assets").glob("plotly*.js"): diff --git a/openbb_terminal/cryptocurrency/cryptocurrency_helpers.py b/openbb_terminal/cryptocurrency/cryptocurrency_helpers.py index 9f88d23a739f..f5c33751d850 100644 --- a/openbb_terminal/cryptocurrency/cryptocurrency_helpers.py +++ b/openbb_terminal/cryptocurrency/cryptocurrency_helpers.py @@ -629,8 +629,8 @@ def show_quick_performance( ) ), ) - except Exception: - pass # noqa + except Exception: # noqa: S110 + pass exchange_str = f"in {exchange.capitalize()}" if source == "ccxt" else "" print_rich_table( diff --git a/openbb_terminal/dashboards/stream/Forecasting.py b/openbb_terminal/dashboards/stream/Forecasting.py index b05fd29a3783..3dbe6b22549a 100644 --- a/openbb_terminal/dashboards/stream/Forecasting.py +++ b/openbb_terminal/dashboards/stream/Forecasting.py @@ -163,11 +163,10 @@ def handle_changes( external_axes=True, ) - with st.spinner("Running model..."): - with patch.object(OpenBBFigure, "show", mock_show): - fig: OpenBBFigure = getattr( - common_vars.openbb.forecast, f"{model}_chart" - )(**kwargs) + with st.spinner("Running model..."), patch.object(OpenBBFigure, "show", mock_show): + fig: OpenBBFigure = getattr( + common_vars.openbb.forecast, f"{model}_chart" + )(**kwargs) with plotly_chart: dt_now = datetime.now().strftime("%Y%m%d_%H%M%S") diff --git a/openbb_terminal/dashboards/stream/pages/Indicators.py b/openbb_terminal/dashboards/stream/pages/Indicators.py index 46fa14e9f075..5dfa2d8b223a 100644 --- a/openbb_terminal/dashboards/stream/pages/Indicators.py +++ b/openbb_terminal/dashboards/stream/pages/Indicators.py @@ -243,81 +243,80 @@ async def handle_changes( ] result: pd.DataFrame = st.session_state["indicators_dfs"][main_ticker] - with st.spinner("Calculating indicators..."): - with patch.object(console, "print", special_st): - if result.empty: - with logger.container(): - logger.error("There was an error with the data", icon="🔥") - await asyncio.sleep(2) - return None + with st.spinner("Calculating indicators..."), patch.object(console, "print", special_st): + if result.empty: + with logger.container(): + logger.error("There was an error with the data", icon="🔥") + await asyncio.sleep(2) + return None - data = pd.DataFrame(result) - data.index.name = "date" + data = pd.DataFrame(result) + data.index.name = "date" - if ta_helpers.check_columns(data) is None: - return None + if ta_helpers.check_columns(data) is None: + return None - fig = await plot_indicators(data, tickers_l, indicators) + fig = await plot_indicators(data, tickers_l, indicators) - with plotly_chart.container(): - dt_now = datetime.now().strftime("%Y%m%d_%H%M%S") - filename = f"{dt_now}_{main_ticker}_technical_analysis" - fig.show(external=True, bar_width=0.00001) + with plotly_chart.container(): + dt_now = datetime.now().strftime("%Y%m%d_%H%M%S") + filename = f"{dt_now}_{main_ticker}_technical_analysis" + fig.show(external=True, bar_width=0.00001) - if list( - set(indicators).intersection( - set(TA_CLASS.ma_mode + TA_CLASS.inchart) - ) - ): - margin = fig.layout.margin - margin.l += 30 - fig.update_layout(margin=margin) - - st.plotly_chart( - fig, - use_container_width=True, - config=dict( - scrollZoom=True, - displaylogo=False, - toImageButtonOptions=dict( - format="png", - filename=filename, - ), - **common_vars.PLOTLY_CONFIG, + if list( + set(indicators).intersection( + set(TA_CLASS.ma_mode + TA_CLASS.inchart) + ) + ): + margin = fig.layout.margin + margin.l += 30 + fig.update_layout(margin=margin) + + st.plotly_chart( + fig, + use_container_width=True, + config=dict( + scrollZoom=True, + displaylogo=False, + toImageButtonOptions=dict( + format="png", + filename=filename, ), + **common_vars.PLOTLY_CONFIG, + ), + ) + components.html(common_vars.PLOTLY_MODEBAR) + + with table_container: + last_day = data.loc[data.index.date == data.index.date[-1]] + + if not last_day.empty: + last_day.index = pd.to_datetime(last_day.index).date + weeks52 = data.loc[ + data.index.date >= data.index.date[-1] - timedelta(weeks=52) + ] + stats_df = pd.DataFrame( + { + "Open": last_day["Open"].head(1).values[0], + "High": last_day["High"].max(), + "Low": last_day["Low"].min(), + "Close": last_day["Close"].tail(1).values[0], + "Volume": last_day["Volume"].sum(), + "52w high": weeks52["High"].values.max(), + "52w low": weeks52["Low"].values.min(), + }, + index=[ + last_day.tail(1).index.values[0].strftime("%Y-%m-%d") + ], ) - components.html(common_vars.PLOTLY_MODEBAR) - - with table_container: - last_day = data.loc[data.index.date == data.index.date[-1]] - - if not last_day.empty: - last_day.index = pd.to_datetime(last_day.index).date - weeks52 = data.loc[ - data.index.date >= data.index.date[-1] - timedelta(weeks=52) - ] - stats_df = pd.DataFrame( - { - "Open": last_day["Open"].head(1).values[0], - "High": last_day["High"].max(), - "Low": last_day["Low"].min(), - "Close": last_day["Close"].tail(1).values[0], - "Volume": last_day["Volume"].sum(), - "52w high": weeks52["High"].values.max(), - "52w low": weeks52["Low"].values.min(), - }, - index=[ - last_day.tail(1).index.values[0].strftime("%Y-%m-%d") - ], - ) - stats_df["Volume"] = stats_df["Volume"].apply( - lambda x: f"{x:,.0f}" - ) - st.table( - stats_df.transpose().style.format( - precision=2, thousands="," - ) + stats_df["Volume"] = stats_df["Volume"].apply( + lambda x: f"{x:,.0f}" + ) + st.table( + stats_df.transpose().style.format( + precision=2, thousands="," ) + ) async def load_ticker_data( self, ticker: str, interval: str, start: date, end: date, source: str diff --git a/openbb_terminal/dashboards/stream/pages/Stocks.py b/openbb_terminal/dashboards/stream/pages/Stocks.py index a647732295b7..839af97778b8 100644 --- a/openbb_terminal/dashboards/stream/pages/Stocks.py +++ b/openbb_terminal/dashboards/stream/pages/Stocks.py @@ -188,7 +188,7 @@ def stock_data( if not df.empty: df.index = pd.to_datetime(df.index).tz_localize(None) return df - except Exception: + except Exception: # noqa: S110 pass return pd.DataFrame() @@ -203,7 +203,7 @@ def volume_data(infos: dict, start: datetime, end: datetime, interval: str) -> d df = df[["Volume"]] df = df.rename(columns={"Volume": ticker}) result[ticker] = df - except Exception: + except Exception: # noqa: S110 pass return result diff --git a/openbb_terminal/fixedincome/ecb_model.py b/openbb_terminal/fixedincome/ecb_model.py index 4ab051a528ac..32a0d391df25 100644 --- a/openbb_terminal/fixedincome/ecb_model.py +++ b/openbb_terminal/fixedincome/ecb_model.py @@ -115,6 +115,7 @@ def get_ecb_yield_curve( Since there is a delay with the data, the most recent date is returned and can be accessed with return_date=True >>> ycrv_df, ycrv_date = openbb.fixedincome.ycrv(return_date=True) """ + base_return = pd.DataFrame(), date if return_date else pd.DataFrame() if yield_type == "spot_rate": yield_type = f"YC.B.U2.EUR.4F.G_N_{'A' if any_rating else 'C'}.SV_C_YM.SR_" elif yield_type == "instantaneous_forward": @@ -123,9 +124,7 @@ def get_ecb_yield_curve( yield_type = f"YC.B.U2.EUR.4F.G_N_{'A' if any_rating else 'C'}.SV_C_YM.PY" else: console.print("[red]Incorrect input for parameter yield_type[/red]") - if return_date: - return pd.DataFrame(), date - return pd.DataFrame() + return base_return if detailed: console.print( @@ -161,9 +160,7 @@ def get_ecb_yield_curve( today = datetime.now().strftime("%Y-%m-%d") if date and date >= today: console.print("[red]Date cannot be today or in the future[/red]") - if return_date: - return pd.DataFrame(), date - return pd.DataFrame() + return base_return # Add in logic that will get the most recent date. @@ -207,9 +204,7 @@ def get_ecb_yield_curve( return pd.DataFrame(), date if df.empty: - if return_date: - return pd.DataFrame(), date - return pd.DataFrame() + return base_return # Drop rows with NaN -- corresponding to weekends typically df = df.dropna() diff --git a/openbb_terminal/loggers.py b/openbb_terminal/loggers.py index ee228eedc604..c48ebb5c886e 100644 --- a/openbb_terminal/loggers.py +++ b/openbb_terminal/loggers.py @@ -112,7 +112,7 @@ def get_branch_commit_hash(branch: str) -> str: try: if get_branch_commit_hash(branch) == current_commit_hash: return branch - except Exception: + except Exception: # noqa: S110 pass git_dir = Path(__file__).parent.parent.joinpath(".git") @@ -121,7 +121,7 @@ def get_branch_commit_hash(branch: str) -> str: repo = git.Repo(path=git_dir) branch = repo.active_branch.name return branch - except Exception: + except Exception: # noqa: S110 pass return "unknown-branch" diff --git a/openbb_terminal/portfolio/portfolio_helper.py b/openbb_terminal/portfolio/portfolio_helper.py index ed5ddcc7e3d4..be79a63ab91f 100644 --- a/openbb_terminal/portfolio/portfolio_helper.py +++ b/openbb_terminal/portfolio/portfolio_helper.py @@ -144,18 +144,16 @@ def filter_df_by_period(df: pd.DataFrame, period: str = "all") -> pd.DataFrame: return df[df.index.strftime("%Y-%m") >= f"{datetime.now().strftime('%Y')}-10"] if period == "ytd": return df[df.index.strftime("%Y") == datetime.now().strftime("%Y")] - if period == "3m": - return df[df.index >= (datetime.now() - relativedelta(months=3))] - if period == "6m": - return df[df.index >= (datetime.now() - relativedelta(months=6))] - if period == "1y": - return df[df.index >= (datetime.now() - relativedelta(years=1))] - if period == "3y": - return df[df.index >= (datetime.now() - relativedelta(years=3))] - if period == "5y": - return df[df.index >= (datetime.now() - relativedelta(years=5))] - if period == "10y": - return df[df.index >= (datetime.now() - relativedelta(years=10))] + period_dict = { + "3m": relativedelta(months=3), + "6m": relativedelta(months=6), + "1y": relativedelta(years=1), + "3y": relativedelta(years=3), + "5y": relativedelta(years=5), + "10y": relativedelta(years=10), + } + if period in period_dict: + return df[df.index >= (datetime.now() - period_dict[period])] return df diff --git a/openbb_terminal/routine_functions.py b/openbb_terminal/routine_functions.py index 327ce81292bf..ac12de47fb93 100644 --- a/openbb_terminal/routine_functions.py +++ b/openbb_terminal/routine_functions.py @@ -70,44 +70,27 @@ def match_and_return_openbb_keyword_date(keyword: str) -> str: ---------- str: Date with format YYYY-MM-DD """ - match = re.match(r"^\$(\d+)([A-Z]+)AGO$", keyword) now = datetime.now() - if match: - integer_value = int(match.group(1)) - time_unit = match.group(2) - if time_unit == "DAYS": - return (now - timedelta(days=integer_value)).strftime("%Y-%m-%d") - if time_unit == "MONTHS": - return (now - relativedelta(months=integer_value)).strftime("%Y-%m-%d") - if time_unit == "YEARS": - return (now - relativedelta(years=integer_value)).strftime("%Y-%m-%d") - - match = re.match(r"^\$(\d+)([A-Z]+)FROMNOW$", keyword) - if match: - integer_value = int(match.group(1)) - time_unit = match.group(2) - if time_unit == "DAYS": - return (now + timedelta(days=integer_value)).strftime("%Y-%m-%d") - if time_unit == "MONTHS": - return (now + relativedelta(months=integer_value)).strftime("%Y-%m-%d") - if time_unit == "YEARS": - return (now + relativedelta(years=integer_value)).strftime("%Y-%m-%d") + for regex in [r"^\$(\d+)([A-Z]+)AGO$", r"^\$(\d+)([A-Z]+)FROMNOW$"]: + match = re.match(regex, keyword) + if match: + integer_value = int(match.group(1)) + time_unit = match.group(2) + if time_unit.upper() in ("DAYS", "MONTHS", "YEARS"): + kwargs = {time_unit.lower(): integer_value} + return (now - relativedelta(**kwargs)).strftime("%Y-%m-%d") match = re.search(r"\$LAST(\w+)", keyword) if match: time_unit = match.group(1) # Check if it corresponds to a month if time_unit in list(MONTHS_VALUE.keys()): + the_year = now.year # Calculate the year and month for last month date - if now.month > MONTHS_VALUE[time_unit]: + if now.month <= MONTHS_VALUE[time_unit]: # If the current month is greater than the last date month, it means it is this year - return datetime(now.year, MONTHS_VALUE[time_unit], 1).strftime( - "%Y-%m-%d" - ) - - return datetime(now.year - 1, MONTHS_VALUE[time_unit], 1).strftime( - "%Y-%m-%d" - ) + the_year = now.year - 1 + return datetime(the_year, MONTHS_VALUE[time_unit], 1).strftime("%Y-%m-%d") # Check if it corresponds to a week day if time_unit in list(WEEKDAY_VALUE.keys()): @@ -158,7 +141,7 @@ def match_and_return_openbb_keyword_date(keyword: str) -> str: return "" -def parse_openbb_script( +def parse_openbb_script( # noqa: PLR0911 raw_lines: List[str], script_inputs: Optional[List[str]] = None, ) -> Tuple[str, str]: diff --git a/openbb_terminal/stocks/dark_pool_shorts/finra_model.py b/openbb_terminal/stocks/dark_pool_shorts/finra_model.py index 9074088dfc4a..dc8b8c3e6acf 100644 --- a/openbb_terminal/stocks/dark_pool_shorts/finra_model.py +++ b/openbb_terminal/stocks/dark_pool_shorts/finra_model.py @@ -283,7 +283,7 @@ def getATSdata(limit: int = 1000, tier_ats: str = "T1") -> Tuple[pd.DataFrame, D ].values, )[0] d_ats_reg[symbol] = slope - except Exception: # nosec B110 + except Exception: # nosec B110 # noqa: S110 pass return df_ats, d_ats_reg diff --git a/openbb_terminal/stocks/fundamental_analysis/finviz_model.py b/openbb_terminal/stocks/fundamental_analysis/finviz_model.py index 8e36c853e5af..826200a30e57 100644 --- a/openbb_terminal/stocks/fundamental_analysis/finviz_model.py +++ b/openbb_terminal/stocks/fundamental_analysis/finviz_model.py @@ -111,7 +111,7 @@ def get_analyst_price_targets_workaround( data["target"] = float(rating[4]) analyst_price_targets.append(data) - except Exception: + except Exception: # noqa: S110 pass # noqa return analyst_price_targets[:last_ratings] diff --git a/openbb_terminal/stocks/options/options_chains_model.py b/openbb_terminal/stocks/options/options_chains_model.py index 32144e4c6c90..53c40f1d0554 100644 --- a/openbb_terminal/stocks/options/options_chains_model.py +++ b/openbb_terminal/stocks/options/options_chains_model.py @@ -132,7 +132,7 @@ def load_options_chains( return load_cboe(symbol, pydantic) -def validate_object( +def validate_object( # noqa: PLR0911 options: Options, scope: Optional[str] = "object", days: Optional[int] = None ) -> Any: """This is an internal helper function for validating the Options data object passed @@ -178,8 +178,6 @@ def validate_object( scopes = ["chains", "object", "strategies", "nonZeroPrices"] - valid: bool = True - if scope == "": scope = "chains" @@ -194,24 +192,24 @@ def validate_object( and isinstance(options.expirations, list) and hasattr(options, "last_price") ): - return valid + return True except AttributeError: print( "Error: Invalid data type supplied. The Options data object is required. " "Use load_options_chains() first." ) - return not valid + return False if scope == "strategies": try: if isinstance(options.last_price, float): - return valid + return True except AttributeError: print( "`last_price` was not found in the OptionsChainsData object and is required for this operation." ) - return not valid + return False if scope == "chains": try: @@ -295,7 +293,7 @@ def validate_object( "Error: No valid data supplied. Check the input to ensure it is not empty or None." ) - return not valid + return False def get_nearest_expiration(options: Options, expiration: Optional[str] = "") -> str: diff --git a/openbb_terminal/stocks/quantitative_analysis/factors_model.py b/openbb_terminal/stocks/quantitative_analysis/factors_model.py index c04e517350aa..e1ab5e2e780d 100644 --- a/openbb_terminal/stocks/quantitative_analysis/factors_model.py +++ b/openbb_terminal/stocks/quantitative_analysis/factors_model.py @@ -25,18 +25,17 @@ def get_fama_raw() -> pd.DataFrame: fama : pd.DataFrame A data with fama french model information """ - with urlopen( # noqa: S310 - "http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip" - ) as url: - # Download Zipfile and create pandas DataFrame - with ZipFile(BytesIO(url.read())) as zipfile: - with zipfile.open("F-F_Research_Data_Factors.CSV") as zip_open: - df = pd.read_csv( - zip_open, - header=0, - names=["Date", "MKT-RF", "SMB", "HML", "RF"], - skiprows=3, - ) + url = "http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip" + file = "F-F_Research_Data_Factors.CSV" + with urlopen(url) as url, ZipFile( # noqa: S310 + BytesIO(url.read()) + ) as zipfile, zipfile.open(file) as zip_open: + df = pd.read_csv( + zip_open, + header=0, + names=["Date", "MKT-RF", "SMB", "HML", "RF"], + skiprows=3, + ) df = df[df["Date"].apply(lambda x: len(str(x).strip()) == 6)] df["Date"] = df["Date"].astype(str) + "01" diff --git a/openbb_terminal/stocks/stocks_helper.py b/openbb_terminal/stocks/stocks_helper.py index 2a955caef05a..eaf83e79169c 100644 --- a/openbb_terminal/stocks/stocks_helper.py +++ b/openbb_terminal/stocks/stocks_helper.py @@ -232,7 +232,7 @@ def search( return df.reset_index() -def load( # pylint: disable=too-many-return-statements +def load( # pylint: disable=too-many-return-statements # noqa: PLR0911 symbol: str, start_date: Optional[Union[datetime, str]] = None, interval: int = 1440, diff --git a/pyproject.toml b/pyproject.toml index b5ff20871c9c..832e7907834d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -181,7 +181,8 @@ target-version = "py38" # All options here: https://github.com/charliermarsh/ruff#supported-rules select = ["E", "W", "F", "Q", "S", "UP", "I", "PLC", "PLE", "PLR", "PLW", "SIM"] # These ignores should be seen as temporary solutions to problems that will NEED fixed -ignore = ["S105", "S106", "S107", "S110", "PLR2004", "PLR0911", "PLR0913", "PLR0912", "PLR0915", "SIM114", "SIM105", "SIM117", "PLC1901", "PLR5501","PLW2901","PLW0603", "E741", "S311", "S602", "S603", "S605", "S607", "S307"] +# Ignores that can be removed easily: PLR0912,SIM114,PLR5501,PLW2901,PLW0603 +ignore = ["S105", "S106", "PLR2004", "PLR0913", "PLR0912", "PLR0915", "SIM105", "SIM114", "PLR5501","PLW2901","PLW0603"] [tool.ruff.per-file-ignores] "tests/*" = ["S101"] diff --git a/tests/openbb_terminal/session/test_local_model.py b/tests/openbb_terminal/session/test_local_model.py index 6f8c0cfda8b7..47eef8404b11 100644 --- a/tests/openbb_terminal/session/test_local_model.py +++ b/tests/openbb_terminal/session/test_local_model.py @@ -65,11 +65,10 @@ def test_save_session_exception(): def test_get_session(): open_mock = mock_open(read_data=json.dumps(TEST_SESSION)) - with patch("openbb_terminal.core.session.local_model.os.path") as path_mock: - with patch( - "openbb_terminal.core.session.local_model.open", open_mock, create=True - ): - assert local_model.get_session() == TEST_SESSION + with patch("openbb_terminal.core.session.local_model.os.path") as path_mock, patch( + "openbb_terminal.core.session.local_model.open", open_mock, create=True + ): + assert local_model.get_session() == TEST_SESSION path_mock.isfile.assert_called_with(SESSION_FILE_PATH) open_mock.assert_called_with(SESSION_FILE_PATH) @@ -94,10 +93,9 @@ def test_get_session_not_exist(): def test_get_session_exception(): open_mock = mock_open() path = "openbb_terminal.core.session.local_model" - with patch(f"{path}.os.path") as path_mock: - with patch(f"{path}.open", open_mock, create=True): - open_mock.side_effect = Exception - assert local_model.get_session() == {} + with patch(f"{path}.os.path") as path_mock, patch(f"{path}.open", open_mock, create=True): + open_mock.side_effect = Exception + assert local_model.get_session() == {} path_mock.isfile.assert_called_with(SESSION_FILE_PATH) open_mock.assert_called_with(SESSION_FILE_PATH) From d13276379cc41781144d17429f8489cde392aee0 Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 07:32:20 -0400 Subject: [PATCH 04/20] Fixed a lot of ruff errors --- generate_sdk.py | 4 +- openbb_terminal/account/show_prompt.py | 2 +- openbb_terminal/core/plots/backend.py | 2 +- openbb_terminal/core/plots/plotly_helper.py | 6 +- openbb_terminal/core/plots/plotly_ta/base.py | 2 +- openbb_terminal/core/sdk/trailmap.py | 4 +- .../core/session/current_system.py | 2 +- .../discovery/pycoingecko_model.py | 4 +- openbb_terminal/custom_prompt_toolkit.py | 2 +- .../dashboards/stream/pages/Indicators.py | 26 +-- openbb_terminal/economy/economy_controller.py | 190 +++--------------- openbb_terminal/economy/economy_helpers.py | 56 ++++++ openbb_terminal/etf/etf_controller.py | 6 +- openbb_terminal/forecast/helpers.py | 8 +- openbb_terminal/forecast/whisper_utils.py | 14 +- openbb_terminal/forex/forex_controller.py | 6 +- openbb_terminal/helper_funcs.py | 6 +- openbb_terminal/keys_controller.py | 4 +- openbb_terminal/parent_classes.py | 74 +++---- .../portfolio_optimization/optimizer_view.py | 40 ++-- .../parameters/params_controller.py | 8 +- .../parameters/params_view.py | 12 +- .../portfolio_optimization/po_view.py | 40 ++-- openbb_terminal/routine_functions.py | 18 +- openbb_terminal/settings_controller.py | 4 +- openbb_terminal/sources_controller.py | 4 +- .../stocks/discovery/nasdaq_view.py | 6 +- .../stocks/options/options_chains_model.py | 2 +- .../stocks/options/options_chains_view.py | 8 +- .../stocks/screener/finviz_model.py | 22 +- openbb_terminal/stocks/stocks_controller.py | 6 +- openbb_terminal/terminal_helper.py | 8 +- pyproject.toml | 4 +- 33 files changed, 267 insertions(+), 333 deletions(-) diff --git a/generate_sdk.py b/generate_sdk.py index 60d1f9533487..28fb5c7059f7 100644 --- a/generate_sdk.py +++ b/generate_sdk.py @@ -536,7 +536,9 @@ def build(self) -> None: f.write(content.replace(b"\r", b"\n")) # We run black to make sure the code is formatted correctly - subprocess.check_call(["black", "openbb_terminal"]) # nosec: B603, B607 + subprocess.check_call( # noqa: S603 # nosec: B603, B607 + ["black", "openbb_terminal"] # noqa: S603,S607 + ) def generate_sdk(sort: bool = False) -> bool: diff --git a/openbb_terminal/account/show_prompt.py b/openbb_terminal/account/show_prompt.py index d481b041fde5..77e555a67ffd 100644 --- a/openbb_terminal/account/show_prompt.py +++ b/openbb_terminal/account/show_prompt.py @@ -20,5 +20,5 @@ def set_show_prompt(value: bool): value : bool The show_prompt flag. """ - global __show_prompt # pylint: disable=global-statement + global __show_prompt # pylint: disable=global-statement # noqa: PLW0603 __show_prompt = value diff --git a/openbb_terminal/core/plots/backend.py b/openbb_terminal/core/plots/backend.py index 1cfb1b7845eb..2a8e02c5b4d3 100644 --- a/openbb_terminal/core/plots/backend.py +++ b/openbb_terminal/core/plots/backend.py @@ -246,7 +246,7 @@ async def process_image(self, export_image: Path): else: opener = "open" if sys.platform == "darwin" else "xdg-open" subprocess.check_call( - [opener, export_image] + [opener, export_image] # nosec: B603 # noqa: S603 ) # nosec: B603 # noqa: S603 def send_table( diff --git a/openbb_terminal/core/plots/plotly_helper.py b/openbb_terminal/core/plots/plotly_helper.py index dfa7f92aef0d..993a6dcff6a0 100644 --- a/openbb_terminal/core/plots/plotly_helper.py +++ b/openbb_terminal/core/plots/plotly_helper.py @@ -600,7 +600,9 @@ def _validate_x(data: Union[np.ndarray, pd.Series, type[TimeSeriesT]]): max_y = 0 for i0, (x_i, name_i, color_i) in enumerate(zip(valid_x, name, colors)): if not color_i: - color_i = theme.up_color if i0 % 2 == 0 else theme.down_color + color_i = ( # noqa: PLW2901 + theme.up_color if i0 % 2 == 0 else theme.down_color + ) res_mean, res_std = np.mean(x_i), np.std(x_i) res_min, res_max = min(x_i), max(x_i) @@ -1054,7 +1056,7 @@ def add_legend_label( [trace, trace_.mode, trace_.marker, trace_.line_dash], ): if not arg and default: - arg = default + arg = default # noqa: PLW2901 kwargs.update(dict(yaxis=trace_.yaxis)) break diff --git a/openbb_terminal/core/plots/plotly_ta/base.py b/openbb_terminal/core/plots/plotly_ta/base.py index df9574dabf7c..0a4019d83773 100644 --- a/openbb_terminal/core/plots/plotly_ta/base.py +++ b/openbb_terminal/core/plots/plotly_ta/base.py @@ -54,7 +54,7 @@ def __new__(mcs: Type["PluginMeta"], *args: Any, **kwargs: Any) -> "PluginMeta": is_static_method = isinstance(value, staticmethod) if is_static_method: - value = value.__func__ + value = value.__func__ # noqa: PLW2901 if isinstance(value, Indicator): if is_static_method: raise TypeError( diff --git a/openbb_terminal/core/sdk/trailmap.py b/openbb_terminal/core/sdk/trailmap.py index 663c105276b2..4da09ca0b1ad 100644 --- a/openbb_terminal/core/sdk/trailmap.py +++ b/openbb_terminal/core/sdk/trailmap.py @@ -41,7 +41,9 @@ def get_signature_parameters( annotation = annotation.__forward_arg__ if isinstance(annotation, str): - annotation = eval(annotation, globalns, cache) # pylint: disable=W0123 + annotation = eval( # pylint: disable=W0123 # noqa: S307 + annotation, globalns, cache + ) params[name] = parameter.replace(annotation=annotation) diff --git a/openbb_terminal/core/session/current_system.py b/openbb_terminal/core/session/current_system.py index f6afec6704a2..f4396455f4fd 100644 --- a/openbb_terminal/core/session/current_system.py +++ b/openbb_terminal/core/session/current_system.py @@ -16,7 +16,7 @@ def get_current_system() -> SystemModel: def set_current_system(system: SystemModel): """Set current system.""" - global __system # pylint: disable=global-statement + global __system # pylint: disable=global-statement# noqa: PLW0603 __system = system diff --git a/openbb_terminal/cryptocurrency/discovery/pycoingecko_model.py b/openbb_terminal/cryptocurrency/discovery/pycoingecko_model.py index c66c8aad9801..4ec94cb63731 100644 --- a/openbb_terminal/cryptocurrency/discovery/pycoingecko_model.py +++ b/openbb_terminal/cryptocurrency/discovery/pycoingecko_model.py @@ -348,8 +348,8 @@ def get_trending_coins() -> pd.DataFrame: coins = data["coins"] df = pd.DataFrame(columns=["Symbol", "Name", "market_cap Cap Rank"]) for i, coin in enumerate(coins): - coin = coin["item"] - df.loc[i] = [coin["id"], coin["name"], coin["market_cap_rank"]] + coin_data = coin["item"] + df.loc[i] = [coin_data["id"], coin_data["name"], coin_data["market_cap_rank"]] return df diff --git a/openbb_terminal/custom_prompt_toolkit.py b/openbb_terminal/custom_prompt_toolkit.py index b02cab31cb06..1caac91c0b88 100644 --- a/openbb_terminal/custom_prompt_toolkit.py +++ b/openbb_terminal/custom_prompt_toolkit.py @@ -186,7 +186,7 @@ def from_nested_dict(cls, data: dict) -> "NestedCompleter": return cls(options) - def get_completions( + def get_completions( # noqa: PLR0912 self, document: Document, complete_event: CompleteEvent ) -> Iterable[Completion]: # Split document. diff --git a/openbb_terminal/dashboards/stream/pages/Indicators.py b/openbb_terminal/dashboards/stream/pages/Indicators.py index 5dfa2d8b223a..99c3992eeb46 100644 --- a/openbb_terminal/dashboards/stream/pages/Indicators.py +++ b/openbb_terminal/dashboards/stream/pages/Indicators.py @@ -234,16 +234,18 @@ async def handle_changes( end_n = datetime(end.year, end.month, end.day).date() for ticker in tickers_l: - ticker = ticker.upper().strip() - st.session_state["indicators_dfs"][ticker] = st.session_state[ + clean_ticker = ticker.upper().strip() + st.session_state["indicators_dfs"][clean_ticker] = st.session_state[ "indicators_dfs" - ][ticker].loc[ - (st.session_state["indicators_dfs"][ticker].index.date >= start_n) - & (st.session_state["indicators_dfs"][ticker].index.date <= end_n) + ][clean_ticker].loc[ + (st.session_state["indicators_dfs"][clean_ticker].index.date >= start_n) + & (st.session_state["indicators_dfs"][clean_ticker].index.date <= end_n) ] result: pd.DataFrame = st.session_state["indicators_dfs"][main_ticker] - with st.spinner("Calculating indicators..."), patch.object(console, "print", special_st): + with st.spinner("Calculating indicators..."), patch.object( + console, "print", special_st + ): if result.empty: with logger.container(): logger.error("There was an error with the data", icon="🔥") @@ -305,17 +307,11 @@ async def handle_changes( "52w high": weeks52["High"].values.max(), "52w low": weeks52["Low"].values.min(), }, - index=[ - last_day.tail(1).index.values[0].strftime("%Y-%m-%d") - ], - ) - stats_df["Volume"] = stats_df["Volume"].apply( - lambda x: f"{x:,.0f}" + index=[last_day.tail(1).index.values[0].strftime("%Y-%m-%d")], ) + stats_df["Volume"] = stats_df["Volume"].apply(lambda x: f"{x:,.0f}") st.table( - stats_df.transpose().style.format( - precision=2, thousands="," - ) + stats_df.transpose().style.format(precision=2, thousands=",") ) async def load_ticker_data( diff --git a/openbb_terminal/economy/economy_controller.py b/openbb_terminal/economy/economy_controller.py index 8db660098314..6e48496a7ceb 100644 --- a/openbb_terminal/economy/economy_controller.py +++ b/openbb_terminal/economy/economy_controller.py @@ -2021,172 +2021,34 @@ def call_plot(self, other_args: List[str]): "There is no data stored yet. Please use either the 'macro', 'fred', 'index' and/or " "'treasury' command." ) - else: - dataset_yaxis1 = pd.DataFrame() - dataset_yaxis2 = pd.DataFrame() - - if y1s: - for variable in y1s: - for key, data in self.DATASETS.items(): - if variable in data.columns: - if key == "macro": - split = variable.split("_") - transform = "" - if ( - len(split) == 3 - and split[1] in econdb_model.TRANSFORM - ): - ( - country, - transform, - parameter_abbreviation, - ) = split - elif ( - len(split) == 4 - and split[2] in econdb_model.TRANSFORM - ): - country = f"{split[0]} {split[1]}" - transform = split[2] - parameter_abbreviation = split[3] - elif len(split) == 2: - country, parameter_abbreviation = split - else: - country = f"{split[0]} {split[1]}" - parameter_abbreviation = split[2] - - parameter = econdb_model.PARAMETERS[ - parameter_abbreviation - ]["name"] - - units = self.UNITS[country.replace(" ", "_")][ - parameter_abbreviation - ] - transformtype = ( - f" ({econdb_model.TRANSFORM[transform]}) " - if transform - else " " - ) - dataset_yaxis1[ - f"{country}{transformtype}[{parameter}, Units: {units}]" - ] = data[variable] - elif key == "fred": - compound_detail = self.FRED_TITLES[variable] - detail = { - "units": compound_detail.split("(")[-1].split( - ")" - )[0], - "title": compound_detail.split("(")[0].strip(), - } - data_to_plot, title = fred_view.format_data_to_plot( - data[variable], detail - ) - dataset_yaxis1[title] = data_to_plot - elif ( - key == "index" - and variable in yfinance_model.INDICES - ): - dataset_yaxis1[ - yfinance_model.INDICES[variable]["name"] - ] = data[variable] - elif key == "treasury": - parameter, maturity = variable.split("_") - dataset_yaxis1[f"{parameter} [{maturity}]"] = data[ - variable - ] - else: - dataset_yaxis1[variable] = data[variable] - break - if dataset_yaxis1.empty: - console.print( - f"[red]Not able to find any data for the --y1 argument. The currently available " - f"options are: {', '.join(self.choices['plot']['--y1'])}[/red]\n" - ) + return + dataset_yaxis1 = economy_helpers.get_yaxis_data( + self.DATASETS, self.UNITS, self.FRED_TITLES, y1s + ) + if dataset_yaxis1.empty: + console.print( + f"[red]Not able to find any data for the --y1 argument. The currently available " + f"options are: {', '.join(self.choices['plot']['--y1'])}[/red]\n" + ) - if y2s: - for variable in y2s: - for key, data in self.DATASETS.items(): - if variable in data.columns: - if key == "macro": - split = variable.split("_") - transform = "" - if ( - len(split) == 3 - and split[1] in econdb_model.TRANSFORM - ): - ( - country, - transform, - parameter_abbreviation, - ) = split - elif ( - len(split) == 4 - and split[2] in econdb_model.TRANSFORM - ): - country = f"{split[0]} {split[1]}" - transform = split[2] - parameter_abbreviation = split[3] - elif len(split) == 2: - country, parameter_abbreviation = split - else: - country = f"{split[0]} {split[1]}" - parameter_abbreviation = split[2] - - parameter = econdb_model.PARAMETERS[ - parameter_abbreviation - ]["name"] - units = self.UNITS[country.replace(" ", "_")][ - parameter_abbreviation - ] - transformtype = ( - f" ({econdb_model.TRANSFORM[transform]}) " - if transform - else " " - ) - dataset_yaxis2[ - f"{country}{transformtype}[{parameter}, Units: {units}]" - ] = data[variable] - elif key == "fred": - compound_detail = self.FRED_TITLES[variable] - detail = { - "units": compound_detail.split("(")[-1].split( - ")" - )[0], - "title": compound_detail.split("(")[0].strip(), - } - data_to_plot, title = fred_view.format_data_to_plot( - data[variable], detail - ) - dataset_yaxis2[title] = data_to_plot - elif ( - key == "index" - and variable in yfinance_model.INDICES - ): - dataset_yaxis2[ - yfinance_model.INDICES[variable]["name"] - ] = data[variable] - elif key == "treasury": - parameter, maturity = variable.split("_") - dataset_yaxis2[f"{parameter} [{maturity}]"] = data[ - variable - ] - else: - dataset_yaxis2[variable] = data[variable] - break - if dataset_yaxis2.empty: - console.print( - f"[red]Not able to find any data for the --y2 argument. The currently available " - f"options are: {', '.join(self.choices['plot']['--y2'])}[/red]\n" - ) + dataset_yaxis2 = economy_helpers.get_yaxis_data( + self.DATASETS, self.UNITS, self.FRED_TITLES, y2s + ) + if dataset_yaxis2.empty: + console.print( + f"[red]Not able to find any data for the --y2 argument. The currently available " + f"options are: {', '.join(self.choices['plot']['--y2'])}[/red]\n" + ) - if y1s or y2s: - plot_view.show_plot( - dataset_yaxis_1=dataset_yaxis1, - dataset_yaxis_2=dataset_yaxis2, - export=ns_parser.export, - sheet_name=" ".join(ns_parser.sheet_name) - if ns_parser.sheet_name - else None, - ) + if y1s or y2s: + plot_view.show_plot( + dataset_yaxis_1=dataset_yaxis1, + dataset_yaxis_2=dataset_yaxis2, + export=ns_parser.export, + sheet_name=" ".join(ns_parser.sheet_name) + if ns_parser.sheet_name + else None, + ) @log_start_end(log=logger) def call_valuation(self, other_args: List[str]): diff --git a/openbb_terminal/economy/economy_helpers.py b/openbb_terminal/economy/economy_helpers.py index 813edf3e8f8f..e100c43992d5 100644 --- a/openbb_terminal/economy/economy_helpers.py +++ b/openbb_terminal/economy/economy_helpers.py @@ -5,6 +5,7 @@ import pandas as pd +from openbb_terminal.economy import econdb_model, fred_view, yfinance_model from openbb_terminal.rich_config import console @@ -100,3 +101,58 @@ def update_stored_datasets_string(datasets) -> str: stored_datasets_string += ", " + col return stored_datasets_string + + +def get_plot_macro(dataset, variable: str, units, data): + split = variable.split("_") + transform = "" + if len(split) == 3 and split[1] in econdb_model.TRANSFORM: + country, transform, parameter_abbreviation = split + elif len(split) == 4 and split[2] in econdb_model.TRANSFORM: + country = f"{split[0]} {split[1]}" + transform = split[2] + parameter_abbreviation = split[3] + elif len(split) == 2: + country, parameter_abbreviation = split + else: + country = f"{split[0]} {split[1]}" + parameter_abbreviation = split[2] + + parameter = econdb_model.PARAMETERS[parameter_abbreviation]["name"] + + units = units[country.replace(" ", "_")][parameter_abbreviation] + transformtype = f" ({econdb_model.TRANSFORM[transform]}) " if transform else " " + dataset[f"{country}{transformtype}[{parameter}, Units: {units}]"] = data[variable] + return dataset + + +def get_yaxis_data(datasets, units, titles, ys): + dataset_yaxis = pd.DataFrame() + if not ys: + return dataset_yaxis + for variable in ys: + for key, data in datasets.items(): + if variable in data.columns: + if key == "macro": + dataset_yaxis = get_plot_macro(dataset_yaxis, variable, units, data) + elif key == "fred": + compound_detail = titles[variable] + detail = { + "units": compound_detail.split("(")[-1].split(")")[0], + "title": compound_detail.split("(")[0].strip(), + } + data_to_plot, title = fred_view.format_data_to_plot( + data[variable], detail + ) + dataset_yaxis[title] = data_to_plot + elif key == "index" and variable in yfinance_model.INDICES: + dataset_yaxis[yfinance_model.INDICES[variable]["name"]] = data[ + variable + ] + elif key == "treasury": + parameter, maturity = variable.split("_") + dataset_yaxis[f"{parameter} [{maturity}]"] = data[variable] + else: + dataset_yaxis[variable] = data[variable] + break + return dataset_yaxis diff --git a/openbb_terminal/etf/etf_controller.py b/openbb_terminal/etf/etf_controller.py index 6262bdcb9111..26a4311208e2 100644 --- a/openbb_terminal/etf/etf_controller.py +++ b/openbb_terminal/etf/etf_controller.py @@ -491,12 +491,12 @@ def call_candle(self, other_args: List[str]): for num in mov_list: try: - num = int(num) + clean_num = int(num) - if num <= 1: + if clean_num <= 1: raise ValueError - mov_avgs.append(num) + mov_avgs.append(clean_num) except ValueError: console.print( f"[red]{num} is not a valid moving average, must be an integer " diff --git a/openbb_terminal/forecast/helpers.py b/openbb_terminal/forecast/helpers.py index 7c5d41939637..0a3063a0eddc 100644 --- a/openbb_terminal/forecast/helpers.py +++ b/openbb_terminal/forecast/helpers.py @@ -782,7 +782,7 @@ def plotly_shap_scatter_plot( fig.set_xaxis_title("SHAP value (impact on model output)") for pos, i in enumerate(feature_order): - pos += 2 + new_pos = pos + 2 shaps = shap_values[:, i] values = None if features is None else features[:, i] inds = np.arange(len(shaps)) @@ -838,7 +838,7 @@ def plotly_shap_scatter_plot( nan_mask = np.isnan(values) fig.add_scattergl( x=shaps[nan_mask], - y=pos + ys[nan_mask], + y=new_pos + ys[nan_mask], mode="markers", marker=dict( color="#777777", @@ -860,12 +860,12 @@ def plotly_shap_scatter_plot( fig.add_scattergl( x=shaps[np.invert(nan_mask)], - y=pos + ys[np.invert(nan_mask)], + y=new_pos + ys[np.invert(nan_mask)], mode="markers", marker=dict( color=cvals, colorscale="Bluered", - showscale=bool(pos == 2), + showscale=bool(new_pos == 2), colorbar=dict( x=-0.05, thickness=10, diff --git a/openbb_terminal/forecast/whisper_utils.py b/openbb_terminal/forecast/whisper_utils.py index a969487d95fa..4f62ceeece2a 100644 --- a/openbb_terminal/forecast/whisper_utils.py +++ b/openbb_terminal/forecast/whisper_utils.py @@ -58,11 +58,11 @@ def process_segment(segment: dict, line_length: int = 0): def write_vtt(transcript: Iterator[dict], file: TextIO, line_length: int = 0): print("WEBVTT\n", file=file) for segment in transcript: - segment = process_segment(segment, line_length=line_length) + clean_segment = process_segment(segment, line_length=line_length) print( - f"{format_timestamp(segment['start'])} --> {format_timestamp(segment['end'])}\n" - f"{segment['text'].strip().replace('-->', '->')}\n", + f"{format_timestamp(clean_segment['start'])} --> {format_timestamp(clean_segment['end'])}\n" + f"{clean_segment['text'].strip().replace('-->', '->')}\n", file=file, flush=True, ) @@ -70,13 +70,13 @@ def write_vtt(transcript: Iterator[dict], file: TextIO, line_length: int = 0): def write_srt(transcript: Iterator[dict], file: TextIO, line_length: int = 0): for i, segment in enumerate(transcript, start=1): - segment = process_segment(segment, line_length=line_length) + clean_segment = process_segment(segment, line_length=line_length) print( f"{i}\n" - f"{format_timestamp(segment['start'], always_include_hours=True, decimal_marker=',')} --> " - f"{format_timestamp(segment['end'], always_include_hours=True, decimal_marker=',')}\n" - f"{segment['text'].strip().replace('-->', '->')}\n", + f"{format_timestamp(clean_segment['start'], always_include_hours=True, decimal_marker=',')} --> " + f"{format_timestamp(clean_segment['end'], always_include_hours=True, decimal_marker=',')}\n" + f"{clean_segment['text'].strip().replace('-->', '->')}\n", file=file, flush=True, ) diff --git a/openbb_terminal/forex/forex_controller.py b/openbb_terminal/forex/forex_controller.py index 756cf52cb02d..5136460a80e9 100644 --- a/openbb_terminal/forex/forex_controller.py +++ b/openbb_terminal/forex/forex_controller.py @@ -307,12 +307,12 @@ def call_candle(self, other_args: List[str]): for num in mov_list: try: - num = int(num) + clean_num = int(num) - if num <= 1: + if clean_num <= 1: raise ValueError - mov_avgs.append(num) + mov_avgs.append(clean_num) except ValueError: console.print( f"[red]{num} is not a valid moving average, must be an integer greater than 1." diff --git a/openbb_terminal/helper_funcs.py b/openbb_terminal/helper_funcs.py index 615e7fb40d0e..ab1b83457e3b 100644 --- a/openbb_terminal/helper_funcs.py +++ b/openbb_terminal/helper_funcs.py @@ -263,7 +263,7 @@ def return_colored_value(value: str): # pylint: disable=too-many-arguments -def print_rich_table( +def print_rich_table( # noqa: PLR0912 df: pd.DataFrame, show_index: bool = False, title: str = "", @@ -1120,7 +1120,7 @@ def get_user_agent() -> str: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:84.0) Gecko/20100101 Firefox/84.0", ] - return random.choice(user_agent_strings) # nosec + return random.choice(user_agent_strings) # nosec # noqa: S311 def text_adjustment_init(self): @@ -1641,7 +1641,7 @@ def get_rf() -> float: def system_clear(): """Clear screen.""" - os.system("cls||clear") # nosec + os.system("cls||clear") # nosec # noqa: S605,S607 def excel_columns() -> List[str]: diff --git a/openbb_terminal/keys_controller.py b/openbb_terminal/keys_controller.py index 976475b934a0..13d49e71cf9b 100644 --- a/openbb_terminal/keys_controller.py +++ b/openbb_terminal/keys_controller.py @@ -110,11 +110,11 @@ def print_help(self, update_status: bool = True, reevaluate: bool = True): api_name = self.API_DICT[cmd_name] c = status_color_map.get(status_msg, "grey30") - status_msg = status_msg or keys_model.KeyStatus.NOT_DEFINED.value + clean_status_msg = status_msg or keys_model.KeyStatus.NOT_DEFINED.value mt.add_raw( f" [cmds]{cmd_name}[/cmds] {(20 - len(cmd_name)) * ' '}" - f" [{c}] {api_name} {(25 - len(api_name)) * ' '} {translate(status_msg)} [/{c}]\n" + f" [{c}] {api_name} {(25 - len(api_name)) * ' '} {translate(clean_status_msg)} [/{c}]\n" ) self.help_status_text = mt.menu_text diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index 11d31d2a52f0..ac8e028058c6 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -1011,12 +1011,12 @@ def call_record(self, other_args) -> None: ) return - global RECORD_SESSION - global RECORD_SESSION_LOCAL_ONLY - global SESSION_RECORDED_NAME - global SESSION_RECORDED_DESCRIPTION - global SESSION_RECORDED_TAGS - global SESSION_RECORDED_PUBLIC + global RECORD_SESSION # noqa: PLW0603 + global RECORD_SESSION_LOCAL_ONLY # noqa: PLW0603 + global SESSION_RECORDED_NAME # noqa: PLW0603 + global SESSION_RECORDED_DESCRIPTION # noqa: PLW0603 + global SESSION_RECORDED_TAGS # noqa: PLW0603 + global SESSION_RECORDED_PUBLIC # noqa: PLW0603 RECORD_SESSION = True RECORD_SESSION_LOCAL_ONLY = ns_parser.local @@ -1042,8 +1042,8 @@ def call_record(self, other_args) -> None: @log_start_end(log=logger) def call_stop(self, _) -> None: """Process stop command.""" - global RECORD_SESSION - global SESSION_RECORDED + global RECORD_SESSION # noqa: PLW0603 + global SESSION_RECORDED # noqa: PLW0603 if not RECORD_SESSION: console.print( @@ -1377,6 +1377,35 @@ def parse_known_args_and_warn( ) return ns_parser + def handle_command_in_queue(self, current_user, custom_path_menu_above: str): + # If the command is quitting the menu we want to return in here + if self.queue[0] in ("q", "..", "quit"): + self.save_class() + # Go back to the root in order to go to the right directory because + # there was a jump between indirect menus + if custom_path_menu_above: + self.queue.insert(1, custom_path_menu_above) + + if len(self.queue) > 1: + return self.queue[1:] + + if current_user.preferences.ENABLE_EXIT_AUTO_HELP: + return ["help"] + return [] + + # Consume 1 element from the queue + an_input = self.queue[0] + self.queue = self.queue[1:] + + # Print location because this was an instruction and we want user to know the action + if ( + an_input + and an_input != "home" + and an_input != "help" + and an_input.split(" ")[0] in self.controller_choices + ): + console.print(f"{get_flair()} {self.PATH} $ {an_input}") + def menu(self, custom_path_menu_above: str = ""): """Enter controller menu.""" @@ -1386,34 +1415,7 @@ def menu(self, custom_path_menu_above: str = ""): while True: # There is a command in the queue if self.queue and len(self.queue) > 0: - # If the command is quitting the menu we want to return in here - if self.queue[0] in ("q", "..", "quit"): - self.save_class() - # Go back to the root in order to go to the right directory because - # there was a jump between indirect menus - if custom_path_menu_above: - self.queue.insert(1, custom_path_menu_above) - - if len(self.queue) > 1: - return self.queue[1:] - - if current_user.preferences.ENABLE_EXIT_AUTO_HELP: - return ["help"] - return [] - - # Consume 1 element from the queue - an_input = self.queue[0] - self.queue = self.queue[1:] - - # Print location because this was an instruction and we want user to know the action - if ( - an_input - and an_input != "home" - and an_input != "help" - and an_input.split(" ")[0] in self.controller_choices - ): - console.print(f"{get_flair()} {self.PATH} $ {an_input}") - + self.handle_command_in_queue(current_user, custom_path_menu_above) # Get input command from user else: # Display help menu when entering on this menu from a level above diff --git a/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py b/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py index 1ee58e23d991..5d3e74a86119 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py +++ b/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py @@ -2269,8 +2269,8 @@ def display_ef( ax.set_title(f"Efficient Frontier simulating {n_portfolios} portfolios") ax.legend(loc="best", scatterpoints=1) theme.style_primary_axis(ax) - l, b, w, h = ax.get_position().bounds - ax.set_position([l, b, w * 0.9, h]) + L, b, w, h = ax.get_position().bounds + ax.set_position([L, b, w * 0.9, h]) ax1 = ax.get_figure().axes ll, bb, ww, hh = ax1[-1].get_position().bounds ax1[-1].set_position([ll * 1.02, bb, ww, hh]) @@ -3996,38 +3996,38 @@ def additional_plots( if category_dict is None: # Vertical dendrogram - l, b, w, h = ax[4].get_position().bounds - l1 = l * 0.5 + L, b, w, h = ax[4].get_position().bounds + l1 = L * 0.5 w1 = w * 0.2 b1 = h * 0.05 - ax[4].set_position([l - l1, b + b1, w * 0.8, h * 0.95]) + ax[4].set_position([L - l1, b + b1, w * 0.8, h * 0.95]) # Heatmap - l, b, w, h = ax[1].get_position().bounds - ax[1].set_position([l - l1 - w1, b + b1, w * 0.8, h * 0.95]) + L, b, w, h = ax[1].get_position().bounds + ax[1].set_position([L - l1 - w1, b + b1, w * 0.8, h * 0.95]) w2 = w * 0.2 # colorbar - l, b, w, h = ax[2].get_position().bounds - ax[2].set_position([l - l1 - w1 - w2, b, w, h]) + L, b, w, h = ax[2].get_position().bounds + ax[2].set_position([L - l1 - w1 - w2, b, w, h]) # Horizontal dendrogram - l, b, w, h = ax[3].get_position().bounds - ax[3].set_position([l - l1 - w1, b, w * 0.8, h]) + L, b, w, h = ax[3].get_position().bounds + ax[3].set_position([L - l1 - w1, b, w * 0.8, h]) else: # Vertical dendrogram - l, b, w, h = ax[4].get_position().bounds - l1 = l * 0.5 + L, b, w, h = ax[4].get_position().bounds + l1 = L * 0.5 w1 = w * 0.4 b1 = h * 0.2 - ax[4].set_position([l - l1, b + b1, w * 0.6, h * 0.8]) + ax[4].set_position([L - l1, b + b1, w * 0.6, h * 0.8]) # Heatmap - l, b, w, h = ax[1].get_position().bounds - ax[1].set_position([l - l1 - w1, b + b1, w * 0.6, h * 0.8]) + L, b, w, h = ax[1].get_position().bounds + ax[1].set_position([L - l1 - w1, b + b1, w * 0.6, h * 0.8]) w2 = w * 0.05 # colorbar - l, b, w, h = ax[2].get_position().bounds - ax[2].set_position([l - l1 - w1 - w2, b, w, h]) + L, b, w, h = ax[2].get_position().bounds + ax[2].set_position([L - l1 - w1 - w2, b, w, h]) # Horizontal dendrogram - l, b, w, h = ax[3].get_position().bounds - ax[3].set_position([l - l1 - w1, b, w * 0.6, h]) + L, b, w, h = ax[3].get_position().bounds + ax[3].set_position([L - l1 - w1, b, w * 0.6, h]) title = "Portfolio - " + title_opt + "\n" title += ax[3].get_title(loc="left") diff --git a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py index 8d92c0188ab1..9d3d7059d8b5 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py +++ b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py @@ -122,18 +122,18 @@ def print_help(self): if self.current_model: max_len = max(len(k) for k in self.params) for k, v in self.params.items(): - v = params_helpers.booltostr(v) + clean_v = params_helpers.booltostr(v) all_params = DEFAULT_PARAMETERS + MODEL_PARAMS[self.current_model] if k in all_params: mt.add_raw( - f" [param]{k}{' ' * (max_len - len(k))} :[/param] {v}\n" + f" [param]{k}{' ' * (max_len - len(k))} :[/param] {clean_v}\n" ) else: max_len = max(len(k) for k in self.params) for k, v in self.params.items(): - v = params_helpers.booltostr(v) + clean_v = params_helpers.booltostr(v) mt.add_raw( - f" [param]{k}{' ' * (max_len - len(k))} :[/param] {v}\n" + f" [param]{k}{' ' * (max_len - len(k))} :[/param] {clean_v}\n" ) console.print( text=mt.menu_text, menu="Portfolio - Portfolio Optimization - Parameters" diff --git a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_view.py b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_view.py index 2673bac4e7de..aead731d9332 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_view.py +++ b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_view.py @@ -57,12 +57,16 @@ def load_file(path: str = "") -> Tuple[dict, str]: + params_statics.MODEL_PARAMS[current_model] ) if k in all_params: - v = booltostr(v) - help_text += f" [param]{k}{' ' * (max_len - len(k))} :[/param] {v}\n" + clean_v = booltostr(v) + help_text += ( + f" [param]{k}{' ' * (max_len - len(k))} :[/param] {clean_v}\n" + ) else: for k, v in converted_parameters.items(): - v = booltostr(v) - help_text += f" [param]{k}{' ' * (max_len - len(k))} :[/param] {v}\n" + clean_v = booltostr(v) + help_text += ( + f" [param]{k}{' ' * (max_len - len(k))} :[/param] {clean_v}\n" + ) console.print(help_text) diff --git a/openbb_terminal/portfolio/portfolio_optimization/po_view.py b/openbb_terminal/portfolio/portfolio_optimization/po_view.py index fdeea1f30a77..df172597b8bb 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/po_view.py +++ b/openbb_terminal/portfolio/portfolio_optimization/po_view.py @@ -239,8 +239,8 @@ def display_ef(portfolio_engine: Optional[PoEngine] = None, **kwargs): ax.set_title(f"Efficient Frontier simulating {n_portfolios} portfolios") ax.legend(loc="best", scatterpoints=1) theme.style_primary_axis(ax) - l, b, w, h = ax.get_position().bounds - ax.set_position([l, b, w * 0.9, h]) + L, b, w, h = ax.get_position().bounds + ax.set_position([L, b, w * 0.9, h]) ax1 = ax.get_figure().axes ll, bb, ww, hh = ax1[-1].get_position().bounds ax1[-1].set_position([ll * 1.02, bb, ww, hh]) @@ -440,38 +440,38 @@ def display_heat(**kwargs): if category is None: # Vertical dendrogram - l, b, w, h = ax[4].get_position().bounds - l1 = l * 0.5 + L, b, w, h = ax[4].get_position().bounds + l1 = L * 0.5 w1 = w * 0.2 b1 = h * 0.05 - ax[4].set_position([l - l1, b + b1, w * 0.8, h * 0.95]) + ax[4].set_position([L - l1, b + b1, w * 0.8, h * 0.95]) # Heatmap - l, b, w, h = ax[1].get_position().bounds - ax[1].set_position([l - l1 - w1, b + b1, w * 0.8, h * 0.95]) + L, b, w, h = ax[1].get_position().bounds + ax[1].set_position([L - l1 - w1, b + b1, w * 0.8, h * 0.95]) w2 = w * 0.2 # colorbar - l, b, w, h = ax[2].get_position().bounds - ax[2].set_position([l - l1 - w1 - w2, b, w, h]) + L, b, w, h = ax[2].get_position().bounds + ax[2].set_position([L - l1 - w1 - w2, b, w, h]) # Horizontal dendrogram - l, b, w, h = ax[3].get_position().bounds - ax[3].set_position([l - l1 - w1, b, w * 0.8, h]) + L, b, w, h = ax[3].get_position().bounds + ax[3].set_position([L - l1 - w1, b, w * 0.8, h]) else: # Vertical dendrogram - l, b, w, h = ax[4].get_position().bounds - l1 = l * 0.5 + L, b, w, h = ax[4].get_position().bounds + l1 = L * 0.5 w1 = w * 0.4 b1 = h * 0.2 - ax[4].set_position([l - l1, b + b1, w * 0.6, h * 0.8]) + ax[4].set_position([L - l1, b + b1, w * 0.6, h * 0.8]) # Heatmap - l, b, w, h = ax[1].get_position().bounds - ax[1].set_position([l - l1 - w1, b + b1, w * 0.6, h * 0.8]) + L, b, w, h = ax[1].get_position().bounds + ax[1].set_position([L - l1 - w1, b + b1, w * 0.6, h * 0.8]) w2 = w * 0.05 # colorbar - l, b, w, h = ax[2].get_position().bounds - ax[2].set_position([l - l1 - w1 - w2, b, w, h]) + L, b, w, h = ax[2].get_position().bounds + ax[2].set_position([L - l1 - w1 - w2, b, w, h]) # Horizontal dendrogram - l, b, w, h = ax[3].get_position().bounds - ax[3].set_position([l - l1 - w1, b, w * 0.6, h]) + L, b, w, h = ax[3].get_position().bounds + ax[3].set_position([L - l1 - w1, b, w * 0.6, h]) title = "Portfolio - " + title + "\n" title += ax[3].get_title(loc="left") diff --git a/openbb_terminal/routine_functions.py b/openbb_terminal/routine_functions.py index ac12de47fb93..434e5f8c6b70 100644 --- a/openbb_terminal/routine_functions.py +++ b/openbb_terminal/routine_functions.py @@ -247,11 +247,13 @@ def parse_openbb_script( # noqa: PLR0911 # in python will only take the first '2' if VAR_SLICE == "0": if VAR_NAME in ROUTINE_VARS: - values = eval(f'ROUTINE_VARS["{VAR_NAME}"]') + values = eval( # noqa: S307 + f'ROUTINE_VARS["{VAR_NAME}"]' + ) if isinstance(values, list): templine = templine.replace( match[0], - eval(f"values[{VAR_SLICE}]"), + eval(f"values[{VAR_SLICE}]"), # noqa: S307 ) else: templine = templine.replace(match[0], values) @@ -265,7 +267,9 @@ def parse_openbb_script( # noqa: PLR0911 # Only enters here when any other index from 0 is used else: if VAR_NAME in ROUTINE_VARS: - variable = eval(f'ROUTINE_VARS["{VAR_NAME}"]') + variable = eval( # noqa: S307 + f'ROUTINE_VARS["{VAR_NAME}"]' + ) length_variable = ( len(variable) if isinstance(variable, list) @@ -317,7 +321,9 @@ def parse_openbb_script( # noqa: PLR0911 templine = templine.replace( match[0], ",".join( - eval(f'ROUTINE_VARS["{VAR_NAME}"][{slicing_tuple}]') + eval( # noqa: S307 + f'ROUTINE_VARS["{VAR_NAME}"][{slicing_tuple}]' + ) ), ) @@ -343,7 +349,9 @@ def parse_openbb_script( # noqa: PLR0911 ) if VAR_NAME in ROUTINE_VARS: - value = eval(f'ROUTINE_VARS["{VAR_NAME}"]') + value = eval( # noqa: S307 + f'ROUTINE_VARS["{VAR_NAME}"]' + ) # If the value is a list, we want to replace it with the whole list if isinstance(value, list): diff --git a/openbb_terminal/settings_controller.py b/openbb_terminal/settings_controller.py index 88d9bffdc077..834c44c045d1 100644 --- a/openbb_terminal/settings_controller.py +++ b/openbb_terminal/settings_controller.py @@ -91,8 +91,8 @@ def __init__( self.sort_filter = r"((tz\ -t |tz ).*?(" for tz in pytz.all_timezones: - tz = tz.replace("/", r"\/") - self.sort_filter += f"{tz}|" + clean_tz = tz.replace("/", r"\/") + self.sort_filter += f"{clean_tz}|" self.sort_filter += ")*)" self.PREVIEW = ", ".join( diff --git a/openbb_terminal/sources_controller.py b/openbb_terminal/sources_controller.py index d6483057bbf3..689035a9a04b 100644 --- a/openbb_terminal/sources_controller.py +++ b/openbb_terminal/sources_controller.py @@ -64,8 +64,8 @@ def parse_input(self, an_input: str) -> List: """ cmd_filter = r"((set\s+--cmd\s+|set\s+-c\s+|set\s+|get\s+--cmd\s+|get\s+-c\s+|get\s+).*?(" for cmd in get_current_user().sources.choices: - cmd = cmd.replace("/", r"\/") - cmd_filter += f"{cmd}|" + clean_cmd = cmd.replace("/", r"\/") + cmd_filter += f"{clean_cmd}|" cmd_filter += ")*)" commands = parse_and_split_input(an_input=an_input, custom_filters=[cmd_filter]) diff --git a/openbb_terminal/stocks/discovery/nasdaq_view.py b/openbb_terminal/stocks/discovery/nasdaq_view.py index b29a9da76cf6..140586317cb9 100644 --- a/openbb_terminal/stocks/discovery/nasdaq_view.py +++ b/openbb_terminal/stocks/discovery/nasdaq_view.py @@ -37,10 +37,10 @@ def display_top_retail( return for date, df in retails.head(limit * 10).groupby("Date"): - df = df.drop(columns=["Date"]) - df = df.reset_index(drop=True) + clean_df = df.drop(columns=["Date"]) + clean_df = clean_df.reset_index(drop=True) print_rich_table( - df, + clean_df, headers=[x.title() for x in df.columns], show_index=False, title=f"[bold]{date} Top Retail:[/bold]", diff --git a/openbb_terminal/stocks/options/options_chains_model.py b/openbb_terminal/stocks/options/options_chains_model.py index 53c40f1d0554..8549776ab4ea 100644 --- a/openbb_terminal/stocks/options/options_chains_model.py +++ b/openbb_terminal/stocks/options/options_chains_model.py @@ -1530,7 +1530,7 @@ def get_strategies( for day in days: if day == 0: - day = -1 + day = -1 # noqa: PLW2901 days_list.append(get_nearest_dte(options, day)) days = list(set(days_list)) days.sort() diff --git a/openbb_terminal/stocks/options/options_chains_view.py b/openbb_terminal/stocks/options/options_chains_view.py index 5fefc7b5a6b7..08d03616ef04 100644 --- a/openbb_terminal/stocks/options/options_chains_view.py +++ b/openbb_terminal/stocks/options/options_chains_view.py @@ -581,10 +581,10 @@ def display_skew( color = -1 for expiration in expirations: # type: ignore [union-attr] if expiration == "": - expiration = options.expirations[1] + expiration = options.expirations[1] # noqa: PLW2901 if expiration not in options.expirations: - expiration = options_chains_model.get_nearest_expiration( - options, expiration + expiration = ( # noqa: PLW2901 + options_chains_model.get_nearest_expiration(options, expiration) ) color = color + 1 skew = options_chains_model.calculate_skew(options, expiration, moneyness)[ @@ -903,7 +903,7 @@ def display_volatility( if volume is True: iv_df = iv_df[iv_df["volume"] > 0] for expiration in expirations: - expiration = options_chains_model.get_nearest_expiration( + expiration = options_chains_model.get_nearest_expiration( # noqa: PLW2901 options, expiration ) data = iv_df[iv_df["expiration"] == expiration] diff --git a/openbb_terminal/stocks/screener/finviz_model.py b/openbb_terminal/stocks/screener/finviz_model.py index ae9880067f8a..afc786da3a44 100644 --- a/openbb_terminal/stocks/screener/finviz_model.py +++ b/openbb_terminal/stocks/screener/finviz_model.py @@ -109,18 +109,16 @@ def get_screener_data( Dataframe with loaded filtered stocks """ df_screen = pd.DataFrame() - if data_type == "overview": - screen = overview.Overview() - elif data_type == "valuation": - screen = valuation.Valuation() - elif data_type == "financial": - screen = financial.Financial() - elif data_type == "ownership": - screen = ownership.Ownership() - elif data_type == "performance": - screen = performance.Performance() - elif data_type == "technical": - screen = technical.Technical() + screen_type = { + "overview": overview.Overview, + "valuation": valuation.Valuation, + "financial": financial.Financial, + "ownership": ownership.Ownership, + "performance": performance.Performance, + "technical": technical.Technical, + } + if data_type in screen_type: + screen = screen_type[data_type]() else: console.print("Invalid selected screener type") return pd.DataFrame() diff --git a/openbb_terminal/stocks/stocks_controller.py b/openbb_terminal/stocks/stocks_controller.py index 06b4ea0e254a..84706039ed9d 100644 --- a/openbb_terminal/stocks/stocks_controller.py +++ b/openbb_terminal/stocks/stocks_controller.py @@ -503,12 +503,12 @@ def call_candle(self, other_args: List[str]): for num in mov_list: try: - num = int(num) + clean_num = int(num) - if num <= 1: + if clean_num <= 1: raise ValueError - mov_avgs.append(num) + mov_avgs.append(clean_num) except ValueError: console.print( f"[red]{num} is not a valid moving average, must be an integer greater than 1." diff --git a/openbb_terminal/terminal_helper.py b/openbb_terminal/terminal_helper.py index 63458b34186e..1b2cc2705895 100644 --- a/openbb_terminal/terminal_helper.py +++ b/openbb_terminal/terminal_helper.py @@ -107,7 +107,9 @@ def update_terminal(): poetry_hash = sha256sum("poetry.lock") - completed_process = subprocess.run("git pull", shell=True, check=False) # nosec + completed_process = subprocess.run( # nosec + "git pull", shell=True, check=False # noqa: S607,S602 + ) if completed_process.returncode != 0: return completed_process.returncode @@ -121,7 +123,7 @@ def update_terminal(): ) completed_process = subprocess.run( # nosec - "poetry install", shell=True, check=False + "poetry install", shell=True, check=False # noqa: S607,S602 ) if completed_process.returncode != 0: return completed_process.returncode @@ -270,7 +272,7 @@ def is_installer() -> bool: def bootup(): if sys.platform == "win32": # Enable VT100 Escape Sequence for WINDOWS 10 Ver. 1607 - os.system("") # nosec + os.system("") # nosec # noqa: S605,S607 # Hide splashscreen loader of the packaged app if is_installer(): hide_splashscreen() diff --git a/pyproject.toml b/pyproject.toml index 832e7907834d..0219939523d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -181,8 +181,8 @@ target-version = "py38" # All options here: https://github.com/charliermarsh/ruff#supported-rules select = ["E", "W", "F", "Q", "S", "UP", "I", "PLC", "PLE", "PLR", "PLW", "SIM"] # These ignores should be seen as temporary solutions to problems that will NEED fixed -# Ignores that can be removed easily: PLR0912,SIM114,PLR5501,PLW2901,PLW0603 -ignore = ["S105", "S106", "PLR2004", "PLR0913", "PLR0912", "PLR0915", "SIM105", "SIM114", "PLR5501","PLW2901","PLW0603"] +# Ignores that can be removed easily: SIM114 +ignore = ["S105", "S106", "PLR2004", "PLR0913", "PLR0915", "SIM105", "SIM114", "PLR0912", "S311"] [tool.ruff.per-file-ignores] "tests/*" = ["S101"] From 0c242a8eb4f0144fb8c69406ad3a91ab4a73db49 Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 08:22:07 -0400 Subject: [PATCH 05/20] Simplify if statements --- openbb_terminal/account/account_controller.py | 410 +++++++++--------- openbb_terminal/base_helpers.py | 7 +- openbb_terminal/core/completer/choices.py | 11 +- .../integration_controller.py | 7 +- openbb_terminal/core/session/local_model.py | 4 +- .../cryptocurrency/cryptocurrency_helpers.py | 69 ++- .../due_diligence/coinglass_model.py | 21 +- .../due_diligence/glassnode_model.py | 5 +- openbb_terminal/custom_prompt_toolkit.py | 11 +- openbb_terminal/economy/nasdaq_model.py | 9 +- openbb_terminal/forecast/helpers.py | 11 +- openbb_terminal/forex/av_model.py | 73 ++-- openbb_terminal/keys_model.py | 7 +- openbb_terminal/parent_classes.py | 69 ++- .../portfolio/portfolio_controller.py | 17 +- .../portfolio_optimization/optimizer_model.py | 17 +- .../portfolio_optimization/optimizer_view.py | 17 +- .../parameters/params_helpers.py | 7 +- .../yahoo_finance_model.py | 133 +++--- openbb_terminal/rich_config.py | 7 +- openbb_terminal/routine_functions.py | 46 +- .../stocks/discovery/nasdaq_model.py | 18 +- .../stocks/fundamental_analysis/av_model.py | 246 +++++------ .../yahoo_finance_model.py | 10 +- openbb_terminal/stocks/options/cboe_model.py | 37 +- .../stocks/screener/finviz_model.py | 7 +- .../stocks/screener/finviz_view.py | 44 +- openbb_terminal/terminal_controller.py | 32 +- openbb_terminal/terminal_helper.py | 43 +- pyproject.toml | 4 +- tests/conftest.py | 15 +- .../stocks/government/test_gov_controller.py | 4 +- website/generate_sdk_markdown.py | 5 +- 33 files changed, 643 insertions(+), 780 deletions(-) diff --git a/openbb_terminal/account/account_controller.py b/openbb_terminal/account/account_controller.py index 8db4d421c25c..d16be3a05da1 100644 --- a/openbb_terminal/account/account_controller.py +++ b/openbb_terminal/account/account_controller.py @@ -155,9 +155,8 @@ def call_login(self, other_args: List[str]) -> None: ns_parser = self.parse_known_args_and_warn(parser, other_args) if not is_local() and "-h" not in other_args and "--help" not in other_args: console.print("[info]You are already logged in.[/info]") - else: - if ns_parser: - set_show_prompt(True) + elif ns_parser: + set_show_prompt(True) @log_start_end(log=logger) def call_logout(self, other_args: List[str]) -> None: @@ -171,18 +170,17 @@ def call_logout(self, other_args: List[str]) -> None: ns_parser = self.parse_known_args_and_warn(parser, other_args) if is_local() and "-h" not in other_args and "--help" not in other_args: print_guest_block_msg() - else: - if ns_parser: - current_user = get_current_user() - logout( - auth_header=current_user.profile.get_auth_header(), - token=current_user.profile.get_token(), - cls=True, - ) - if is_installer(): - set_show_prompt(True) - else: - self.print_help() + elif ns_parser: + current_user = get_current_user() + logout( + auth_header=current_user.profile.get_auth_header(), + token=current_user.profile.get_token(), + cls=True, + ) + if is_installer(): + set_show_prompt(True) + else: + self.print_help() @log_start_end(log=logger) def call_clear(self, other_args: List[str]): @@ -196,20 +194,19 @@ def call_clear(self, other_args: List[str]): ns_parser = self.parse_known_args_and_warn(parser, other_args) if is_local() and "-h" not in other_args and "--help" not in other_args: print_guest_block_msg() - else: - if ns_parser: - i = console.input( - "[bold red]This action is irreversible![/bold red]\n" - "Are you sure you want to permanently delete your keys from OpenBB hub? (y/n): " + elif ns_parser: + i = console.input( + "[bold red]This action is irreversible![/bold red]\n" + "Are you sure you want to permanently delete your keys from OpenBB hub? (y/n): " + ) + console.print("") + if i.lower() in ["y", "yes"]: + Hub.clear_user_configs( + config="features_keys", + auth_header=get_current_user().profile.get_auth_header(), ) - console.print("") - if i.lower() in ["y", "yes"]: - Hub.clear_user_configs( - config="features_keys", - auth_header=get_current_user().profile.get_auth_header(), - ) - else: - console.print("[info]Aborted.[/info]") + else: + console.print("[info]Aborted.[/info]") @log_start_end(log=logger) def call_list(self, other_args: List[str]): @@ -248,31 +245,30 @@ def call_list(self, other_args: List[str]): ns_parser = self.parse_known_args_and_warn(parser, other_args) if is_local() and "-h" not in other_args and "--help" not in other_args: print_guest_block_msg() - else: - if ns_parser: - if ns_parser.type == "personal": - response = Hub.list_routines( - auth_header=get_current_user().profile.get_auth_header(), - page=ns_parser.page, - size=ns_parser.size, - base_url=Hub.BackendEnvironment.BASE_URL, - ) - df, page, pages = get_personal_routines_info(response) - if not df.empty: - temp_dict = dict(zip(df["name"], df["uuid"])) - self.REMOTE_CHOICES = {**self.REMOTE_CHOICES, **temp_dict} - self.update_runtime_choices() - display_personal_routines(df, page, pages) - else: - console.print("[red]No personal routines found.[/red]") - elif ns_parser.type == "default": - df = get_default_routines_info(self.DEFAULT_ROUTINES) - if not df.empty: - display_default_routines(df) - else: - console.print("[red]No default routines found.[/red]") + elif ns_parser: + if ns_parser.type == "personal": + response = Hub.list_routines( + auth_header=get_current_user().profile.get_auth_header(), + page=ns_parser.page, + size=ns_parser.size, + base_url=Hub.BackendEnvironment.BASE_URL, + ) + df, page, pages = get_personal_routines_info(response) + if not df.empty: + temp_dict = dict(zip(df["name"], df["uuid"])) + self.REMOTE_CHOICES = {**self.REMOTE_CHOICES, **temp_dict} + self.update_runtime_choices() + display_personal_routines(df, page, pages) + else: + console.print("[red]No personal routines found.[/red]") + elif ns_parser.type == "default": + df = get_default_routines_info(self.DEFAULT_ROUTINES) + if not df.empty: + display_default_routines(df) + else: + console.print("[red]No default routines found.[/red]") - console.print("") + console.print("") @log_start_end(log=logger) def call_upload(self, other_args: List[str]): @@ -332,51 +328,48 @@ def call_upload(self, other_args: List[str]): ns_parser = self.parse_known_args_and_warn(parser, other_args) if is_local() and "-h" not in other_args and "--help" not in other_args: print_guest_block_msg() - else: - if ns_parser: - routine = read_routine(file_name=" ".join(ns_parser.file)) - if routine is not None: - description = " ".join(ns_parser.description) - - name = ( - " ".join(ns_parser.name) - if ns_parser.name - else " ".join(ns_parser.file).split(sep=".openbb", maxsplit=-1)[ - 0 - ] - ) + elif ns_parser: + routine = read_routine(file_name=" ".join(ns_parser.file)) + if routine is not None: + description = " ".join(ns_parser.description) + + name = ( + " ".join(ns_parser.name) + if ns_parser.name + else " ".join(ns_parser.file).split(sep=".openbb", maxsplit=-1)[0] + ) - tags = " ".join(ns_parser.tags) if ns_parser.tags else "" + tags = " ".join(ns_parser.tags) if ns_parser.tags else "" - current_user = get_current_user() + current_user = get_current_user() - kwargs = { - "auth_header": current_user.profile.get_auth_header(), - "name": name, - "description": description, - "routine": routine, - "tags": tags, - "public": ns_parser.public, - "base_url": Hub.BackendEnvironment.BASE_URL, - } - response = Hub.upload_routine(**kwargs) # type: ignore + kwargs = { + "auth_header": current_user.profile.get_auth_header(), + "name": name, + "description": description, + "routine": routine, + "tags": tags, + "public": ns_parser.public, + "base_url": Hub.BackendEnvironment.BASE_URL, + } + response = Hub.upload_routine(**kwargs) # type: ignore - if response is not None and response.status_code == 409: - i = console.input( - "A routine with the same name already exists, " - "do you want to replace it? (y/n): " - ) - console.print("") - if i.lower() in ["y", "yes"]: - kwargs["override"] = True # type: ignore - response = Hub.upload_routine(**kwargs) # type: ignore - else: - console.print("[info]Aborted.[/info]") + if response is not None and response.status_code == 409: + i = console.input( + "A routine with the same name already exists, " + "do you want to replace it? (y/n): " + ) + console.print("") + if i.lower() in ["y", "yes"]: + kwargs["override"] = True # type: ignore + response = Hub.upload_routine(**kwargs) # type: ignore + else: + console.print("[info]Aborted.[/info]") - if response and response.status_code == 200: - the_uuid = response.json()["uuid"] - self.REMOTE_CHOICES[name] = the_uuid - self.update_runtime_choices() + if response and response.status_code == 200: + the_uuid = response.json()["uuid"] + self.REMOTE_CHOICES[name] = the_uuid + self.update_runtime_choices() # store data in list with "personal/default" to identify data's routine type # and for save_routine @@ -405,64 +398,63 @@ def call_download(self, other_args: List[str]): ns_parser = self.parse_known_args_and_warn(parser, other_args) if is_local() and "-h" not in other_args and "--help" not in other_args: print_guest_block_msg() - else: - if ns_parser: - data = [] - name = " ".join(ns_parser.name) - # Personal routines - if name in self.REMOTE_CHOICES: - response = Hub.download_routine( - auth_header=get_current_user().profile.get_auth_header(), - uuid=self.REMOTE_CHOICES[name], - base_url=Hub.BackendEnvironment.BASE_URL, + elif ns_parser: + data = [] + name = " ".join(ns_parser.name) + # Personal routines + if name in self.REMOTE_CHOICES: + response = Hub.download_routine( + auth_header=get_current_user().profile.get_auth_header(), + uuid=self.REMOTE_CHOICES[name], + base_url=Hub.BackendEnvironment.BASE_URL, + ) + if response and response.status_code == 200: + data = [response.json(), "personal"] + # Default routine + elif name in self.DEFAULT_CHOICES: + data = [ + next( + (r for r in self.DEFAULT_ROUTINES if r["name"] == name), + None, + ), + "default", + ] + + # Save routine + if data[0]: + name = data[0].get("name", "") + if name: + console.print(f"[info]Name:[/info] {name}") + + description = data[0].get("description", "") + if description: + console.print(f"[info]Description:[/info] {description}") + + script = [data[0].get("script", ""), data[1]] + if script: + file_name = f"{name}.openbb" + file_path = save_routine( + file_name=file_name, + routine=script, ) - if response and response.status_code == 200: - data = [response.json(), "personal"] - # Default routine - elif name in self.DEFAULT_CHOICES: - data = [ - next( - (r for r in self.DEFAULT_ROUTINES if r["name"] == name), - None, - ), - "default", - ] - - # Save routine - if data[0]: - name = data[0].get("name", "") - if name: - console.print(f"[info]Name:[/info] {name}") - - description = data[0].get("description", "") - if description: - console.print(f"[info]Description:[/info] {description}") - - script = [data[0].get("script", ""), data[1]] - if script: - file_name = f"{name}.openbb" - file_path = save_routine( - file_name=file_name, - routine=script, + if file_path == "File already exists": + i = console.input( + "\nA file with the same name already exists, " + "do you want to replace it? (y/n): " ) - if file_path == "File already exists": - i = console.input( - "\nA file with the same name already exists, " - "do you want to replace it? (y/n): " + console.print("") + if i.lower() in ["y", "yes"]: + file_path = save_routine( + file_name=file_name, + routine=script, + force=True, ) - console.print("") - if i.lower() in ["y", "yes"]: - file_path = save_routine( - file_name=file_name, - routine=script, - force=True, - ) - if file_path: - console.print(f"[info]Location:[/info] {file_path}") - else: - console.print("[info]Aborted.[/info]") - elif file_path: - console.print(f"[info]Location:[/info] {file_path}") + if file_path: + console.print(f"[info]Location:[/info] {file_path}") + else: + console.print("[info]Aborted.[/info]") + elif file_path: + console.print(f"[info]Location:[/info] {file_path}") @log_start_end(log=logger) def call_delete(self, other_args: List[str]): @@ -489,30 +481,29 @@ def call_delete(self, other_args: List[str]): ns_parser = self.parse_known_args_and_warn(parser, other_args) if is_local() and "-h" not in other_args and "--help" not in other_args: print_guest_block_msg() - else: - if ns_parser: - name = " ".join(ns_parser.name) + elif ns_parser: + name = " ".join(ns_parser.name) - i = console.input( - "[bold red]This action is irreversible![/bold red]\n" - "Are you sure you want to delete this routine? (y/n): " + i = console.input( + "[bold red]This action is irreversible![/bold red]\n" + "Are you sure you want to delete this routine? (y/n): " + ) + console.print("") + if i.lower() in ["y", "yes"]: + response = Hub.delete_routine( + auth_header=get_current_user().profile.get_auth_header(), + uuid=self.REMOTE_CHOICES[name], + base_url=Hub.BackendEnvironment.BASE_URL, ) - console.print("") - if i.lower() in ["y", "yes"]: - response = Hub.delete_routine( - auth_header=get_current_user().profile.get_auth_header(), - uuid=self.REMOTE_CHOICES[name], - base_url=Hub.BackendEnvironment.BASE_URL, - ) - if ( - response - and response.status_code == 200 - and name in self.REMOTE_CHOICES - ): - self.REMOTE_CHOICES.pop(name) - self.update_runtime_choices() - else: - console.print("[info]Aborted.[/info]") + if ( + response + and response.status_code == 200 + and name in self.REMOTE_CHOICES + ): + self.REMOTE_CHOICES.pop(name) + self.update_runtime_choices() + else: + console.print("[info]Aborted.[/info]") @log_start_end(log=logger) def call_generate(self, other_args: List[str]) -> None: @@ -542,26 +533,25 @@ def call_generate(self, other_args: List[str]) -> None: ns_parser = self.parse_known_args_and_warn(parser, other_args) if is_local() and "-h" not in other_args and "--help" not in other_args: print_guest_block_msg() - else: - if ns_parser: - i = console.input( - "[bold yellow]This will revoke any token that was previously generated." - "\nThis action is irreversible.[/bold yellow]" - "\nAre you sure you want to generate a new token? (y/n): " - ) - if i.lower() not in ["y", "yes"]: - console.print("\n[info]Aborted.[/info]") - return - - response = Hub.generate_personal_access_token( - auth_header=get_current_user().profile.get_auth_header(), - base_url=Hub.BackendEnvironment.BASE_URL, - days=ns_parser.days, - ) - if response and response.status_code == 200: - token = response.json().get("token", "") - if token: - console.print(f"\n[info]Token:[/info] {token}\n") + elif ns_parser: + i = console.input( + "[bold yellow]This will revoke any token that was previously generated." + "\nThis action is irreversible.[/bold yellow]" + "\nAre you sure you want to generate a new token? (y/n): " + ) + if i.lower() not in ["y", "yes"]: + console.print("\n[info]Aborted.[/info]") + return + + response = Hub.generate_personal_access_token( + auth_header=get_current_user().profile.get_auth_header(), + base_url=Hub.BackendEnvironment.BASE_URL, + days=ns_parser.days, + ) + if response and response.status_code == 200: + token = response.json().get("token", "") + if token: + console.print(f"\n[info]Token:[/info] {token}\n") @log_start_end(log=logger) def call_show(self, other_args: List[str]) -> None: @@ -575,15 +565,14 @@ def call_show(self, other_args: List[str]) -> None: ns_parser = self.parse_known_args_and_warn(parser, other_args) if is_local() and "-h" not in other_args and "--help" not in other_args: print_guest_block_msg() - else: - if ns_parser: - response = Hub.get_personal_access_token( - auth_header=get_current_user().profile.get_auth_header() - ) - if response and response.status_code == 200: - token = response.json().get("token", "") - if token: - console.print(f"[info]Token:[/info] {token}") + elif ns_parser: + response = Hub.get_personal_access_token( + auth_header=get_current_user().profile.get_auth_header() + ) + if response and response.status_code == 200: + token = response.json().get("token", "") + if token: + console.print(f"[info]Token:[/info] {token}") @log_start_end(log=logger) def call_revoke(self, other_args: List[str]) -> None: @@ -597,17 +586,16 @@ def call_revoke(self, other_args: List[str]) -> None: ns_parser = self.parse_known_args_and_warn(parser, other_args) if is_local() and "-h" not in other_args and "--help" not in other_args: print_guest_block_msg() - else: - if ns_parser: - i = console.input( - "[bold red]This action is irreversible![/bold red]\n" - "Are you sure you want to revoke your token? (y/n): " + elif ns_parser: + i = console.input( + "[bold red]This action is irreversible![/bold red]\n" + "Are you sure you want to revoke your token? (y/n): " + ) + if i.lower() in ["y", "yes"]: + response = Hub.revoke_personal_access_token( + auth_header=get_current_user().profile.get_auth_header() ) - if i.lower() in ["y", "yes"]: - response = Hub.revoke_personal_access_token( - auth_header=get_current_user().profile.get_auth_header() - ) - if response and response.status_code in [200, 202]: - console.print("[info]Token revoked.[/info]") - else: - console.print("[info]Aborted.[/info]") + if response and response.status_code in [200, 202]: + console.print("[info]Token revoked.[/info]") + else: + console.print("[info]Aborted.[/info]") diff --git a/openbb_terminal/base_helpers.py b/openbb_terminal/base_helpers.py index a8ae42ce3a08..e4c4c4136e8d 100644 --- a/openbb_terminal/base_helpers.py +++ b/openbb_terminal/base_helpers.py @@ -95,8 +95,5 @@ def remove_log_handlers(): def clear_openbb_env_vars(exceptions: Optional[List[str]] = None): """Clear openbb environment variables.""" for v in os.environ: - if v.startswith("OPENBB"): - if not exceptions: - os.environ.pop(v) - elif v not in exceptions: - os.environ.pop(v) + if v.startswith("OPENBB") and (not exceptions or v not in exceptions): + os.environ.pop(v) diff --git a/openbb_terminal/core/completer/choices.py b/openbb_terminal/core/completer/choices.py index fabfb46c384d..595620991993 100644 --- a/openbb_terminal/core/completer/choices.py +++ b/openbb_terminal/core/completer/choices.py @@ -157,14 +157,9 @@ def contains_functions_to_patch(command_func: Callable) -> bool: co_names = command_func.__code__.co_names - if "parse_simple_args" in co_names: - in_command = True - elif "parse_known_args_and_warn" in co_names: - in_command = True - else: - in_command = False - - return in_command + return bool( + "parse_simple_args" in co_names or "parse_known_args_and_warn" in co_names + ) @contextmanager diff --git a/openbb_terminal/core/integration_tests/integration_controller.py b/openbb_terminal/core/integration_tests/integration_controller.py index 431e67121064..eab820a05203 100644 --- a/openbb_terminal/core/integration_tests/integration_controller.py +++ b/openbb_terminal/core/integration_tests/integration_controller.py @@ -472,9 +472,10 @@ def display_failures(fails: Dict[str, Dict[str, Any]]): for i, line in enumerate(formatted_tb): if "openbb_terminal" not in line: style = "rgb(128,128,128)" - elif i == len(formatted_tb) - 1: - style = "yellow" - elif "openbb_terminal" not in formatted_tb[i + 1]: + elif ( + i == len(formatted_tb) - 1 + or "openbb_terminal" not in formatted_tb[i + 1] + ): style = "yellow" console.print(line, end="", style=style) diff --git a/openbb_terminal/core/session/local_model.py b/openbb_terminal/core/session/local_model.py index 8bd78653125a..64d9e868b366 100644 --- a/openbb_terminal/core/session/local_model.py +++ b/openbb_terminal/core/session/local_model.py @@ -145,9 +145,7 @@ def set_preferences_from_hub(configs: dict, fields: Optional[List[str]] = None): if configs: preferences = configs.get("features_settings", {}) or {} for k, v in preferences.items(): - if not fields: - set_preference(k, v) - elif k in fields: + if not fields or k in fields: set_preference(k, v) diff --git a/openbb_terminal/cryptocurrency/cryptocurrency_helpers.py b/openbb_terminal/cryptocurrency/cryptocurrency_helpers.py index f5c33751d850..4c109e11bdaf 100644 --- a/openbb_terminal/cryptocurrency/cryptocurrency_helpers.py +++ b/openbb_terminal/cryptocurrency/cryptocurrency_helpers.py @@ -717,42 +717,41 @@ def display_all_coins( df = df.merge(df_matched, on="CoinGecko") df.drop("index", axis=1, inplace=True) - else: - if source == "CoinGecko": - coins_df = pycoingecko_model.get_coin_list().drop("index", axis=1) - df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff) - df = df[["index", "id", "name"]] - - elif source == "CoinPaprika": - coins_df = coinpaprika_model.get_coin_list() - df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff) - df = df[["index", "id", "name"]] - - elif source == "Binance": - coins_df_gecko = pycoingecko_model.get_coin_list() - coins_df_bin = load_binance_map() - coins_df_bin.columns = ["symbol", "id"] - coins_df = pd.merge( - coins_df_bin, coins_df_gecko[["id", "name"]], how="left", on="id" - ) - df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff) - df = df[["index", "symbol", "name"]] - df.columns = ["index", "id", "name"] - - elif source == "Coinbase": - coins_df_gecko = pycoingecko_model.get_coin_list() - coins_df_cb = load_coinbase_map() - coins_df_cb.columns = ["symbol", "id"] - coins_df = pd.merge( - coins_df_cb, coins_df_gecko[["id", "name"]], how="left", on="id" - ) - df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff) - df = df[["index", "symbol", "name"]] - df.columns = ["index", "id", "name"] + elif source == "CoinGecko": + coins_df = pycoingecko_model.get_coin_list().drop("index", axis=1) + df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff) + df = df[["index", "id", "name"]] + + elif source == "CoinPaprika": + coins_df = coinpaprika_model.get_coin_list() + df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff) + df = df[["index", "id", "name"]] + + elif source == "Binance": + coins_df_gecko = pycoingecko_model.get_coin_list() + coins_df_bin = load_binance_map() + coins_df_bin.columns = ["symbol", "id"] + coins_df = pd.merge( + coins_df_bin, coins_df_gecko[["id", "name"]], how="left", on="id" + ) + df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff) + df = df[["index", "symbol", "name"]] + df.columns = ["index", "id", "name"] + + elif source == "Coinbase": + coins_df_gecko = pycoingecko_model.get_coin_list() + coins_df_cb = load_coinbase_map() + coins_df_cb.columns = ["symbol", "id"] + coins_df = pd.merge( + coins_df_cb, coins_df_gecko[["id", "name"]], how="left", on="id" + ) + df = _create_closest_match_df(symbol.lower(), coins_df, limit, cutoff) + df = df[["index", "symbol", "name"]] + df.columns = ["index", "id", "name"] - else: - df = pd.DataFrame(columns=["index", "id", "symbol"]) - console.print("Couldn't find any coins") + else: + df = pd.DataFrame(columns=["index", "id", "symbol"]) + console.print("Couldn't find any coins") try: df = df[skip : skip + limit] # noqa diff --git a/openbb_terminal/cryptocurrency/due_diligence/coinglass_model.py b/openbb_terminal/cryptocurrency/due_diligence/coinglass_model.py index 76a4bd588fd6..8a7c0baff576 100644 --- a/openbb_terminal/cryptocurrency/due_diligence/coinglass_model.py +++ b/openbb_terminal/cryptocurrency/due_diligence/coinglass_model.py @@ -65,11 +65,10 @@ def get_liquidations(symbol: str) -> pd.DataFrame: df = df.set_index("date") else: console.print(f"No data found for {symbol}.\n") + elif "secret invalid" in res_json["msg"]: + console.print("[red]Invalid API Key[/red]\n") else: - if "secret invalid" in res_json["msg"]: - console.print("[red]Invalid API Key[/red]\n") - else: - console.print(res_json["msg"]) + console.print(res_json["msg"]) elif response.status_code == 429: console.print("[red]Exceeded number of calls per minute[/red]\n") @@ -128,11 +127,10 @@ def get_funding_rate(symbol: str) -> pd.DataFrame: df = df.set_index("date") else: console.print(f"No data found for {symbol}.\n") + elif "secret invalid" in res_json["msg"]: + console.print("[red]Invalid API Key[/red]\n") else: - if "secret invalid" in res_json["msg"]: - console.print("[red]Invalid API Key[/red]\n") - else: - console.print(res_json["msg"]) + console.print(res_json["msg"]) elif response.status_code == 429: console.print("[red]Exceeded number of calls per minute[/red]\n") @@ -195,11 +193,10 @@ def get_open_interest_per_exchange(symbol: str, interval: int = 0) -> pd.DataFra df = df.set_index("date") else: console.print(f"No data found for {symbol}.\n") + elif "secret invalid" in res_json["msg"]: + console.print("[red]Invalid API Key[/red]\n") else: - if "secret invalid" in res_json["msg"]: - console.print("[red]Invalid API Key[/red]\n") - else: - console.print(res_json["msg"]) + console.print(res_json["msg"]) elif response.status_code == 429: console.print("[red]Exceeded number of calls per minute[/red]\n") diff --git a/openbb_terminal/cryptocurrency/due_diligence/glassnode_model.py b/openbb_terminal/cryptocurrency/due_diligence/glassnode_model.py index bd3774d9a1ac..856fdba49a0b 100644 --- a/openbb_terminal/cryptocurrency/due_diligence/glassnode_model.py +++ b/openbb_terminal/cryptocurrency/due_diligence/glassnode_model.py @@ -237,9 +237,8 @@ def get_close_price( elif r.status_code == 401: if print_errors: console.print("[red]Invalid API Key[/red]\n") - else: - if print_errors: - console.print(r.text) + elif print_errors: + console.print(r.text) return df diff --git a/openbb_terminal/custom_prompt_toolkit.py b/openbb_terminal/custom_prompt_toolkit.py index 1caac91c0b88..1406aba26414 100644 --- a/openbb_terminal/custom_prompt_toolkit.py +++ b/openbb_terminal/custom_prompt_toolkit.py @@ -195,9 +195,7 @@ def get_completions( # noqa: PLR0912 if " " in text: cmd = text.split(" ")[0] if "-" in text: - if text.rfind("--") == -1: - unprocessed_text = "-" + text.split("-")[-1] - elif text.rfind("-") - 1 > text.rfind("--"): + if text.rfind("--") == -1 or text.rfind("-") - 1 > text.rfind("--"): unprocessed_text = "-" + text.split("-")[-1] else: unprocessed_text = "--" + text.split("--")[-1] @@ -268,11 +266,10 @@ def get_completions( # noqa: PLR0912 if "-" not in text: completer = self.options.get(first_term) + elif cmd in self.options and self.options.get(cmd): + completer = self.options.get(cmd).options.get(first_term) # type: ignore else: - if cmd in self.options and self.options.get(cmd): - completer = self.options.get(cmd).options.get(first_term) # type: ignore - else: - completer = self.options.get(first_term) + completer = self.options.get(first_term) # If we have a sub completer, use this for the completions. if completer is not None: diff --git a/openbb_terminal/economy/nasdaq_model.py b/openbb_terminal/economy/nasdaq_model.py index e9bf702ac197..2a0a6e4691f3 100644 --- a/openbb_terminal/economy/nasdaq_model.py +++ b/openbb_terminal/economy/nasdaq_model.py @@ -192,14 +192,7 @@ def get_big_mac_index(country_code: str = "USA") -> pd.DataFrame: df.columns = response_json["dataset"]["column_names"] df["Date"] = pd.to_datetime(df["Date"]) - # Wrong API Key - elif r.status_code == 400: - console.print(r.text) - # Premium Feature - elif r.status_code == 403: - console.print(r.text) - # Catching other exception - elif r.status_code != 200: + else: console.print(r.text) return df diff --git a/openbb_terminal/forecast/helpers.py b/openbb_terminal/forecast/helpers.py index 0a3063a0eddc..0e6dbcb8d6c1 100644 --- a/openbb_terminal/forecast/helpers.py +++ b/openbb_terminal/forecast/helpers.py @@ -1119,13 +1119,12 @@ def get_prediction( past_covariates=past_covariate_whole, n=n_predict, ) + elif probabilistic: + prediction = best_model.predict( + series=ticker_series, n=n_predict, num_samples=500 + ) else: - if probabilistic: - prediction = best_model.predict( - series=ticker_series, n=n_predict, num_samples=500 - ) - else: - prediction = best_model.predict(series=ticker_series, n=n_predict) + prediction = best_model.predict(series=ticker_series, n=n_predict) # calculate precision based on metric (rmse, mse, mape) if metric == "rmse": diff --git a/openbb_terminal/forex/av_model.py b/openbb_terminal/forex/av_model.py index ad4fc66937aa..bf34651f78f7 100644 --- a/openbb_terminal/forex/av_model.py +++ b/openbb_terminal/forex/av_model.py @@ -82,12 +82,11 @@ def get_quote(to_symbol: str = "USD", from_symbol: str = "EUR") -> Dict[str, Any if "Error Message" in response_json: console.print(response_json["Error Message"]) logger.error(response_json["Error Message"]) - else: # check if json is empty - if not response_json: - console.print("No data found.\n") - else: - result = response_json + elif not response_json: + console.print("No data found.\n") + else: + result = response_json return result @@ -143,39 +142,37 @@ def get_historical( console.print(response_json["Error Message"]) elif "Note" in response_json: console.print(response_json["Note"]) + elif not response_json: + console.print("No data found.\n") else: - # check if json is empty - if not response_json: - console.print("No data found.\n") - else: - if "Meta Data" not in response_json and "Information" in response_json: - console.print(response_json["Information"]) - return pd.DataFrame() - - key = list(response_json.keys())[1] - - df = pd.DataFrame.from_dict(response_json[key], orient="index") - df.index = pd.to_datetime(df.index) - - if start_date and resolution != "i": - df = df[df.index > start_date] - - if end_date and resolution != "i": - df = df[df.index < end_date] - - if (df.index.hour != 0).any(): - # if intraday data, convert to local timezone - df.index = df.index.tz_localize("UTC").tz_convert(get_user_timezone()) - - df = df.rename( - columns={ - "1. open": "Open", - "2. high": "High", - "3. low": "Low", - "4. close": "Close", - } - ) - df.index = pd.DatetimeIndex(df.index) - df = df[::-1] + if "Meta Data" not in response_json and "Information" in response_json: + console.print(response_json["Information"]) + return pd.DataFrame() + + key = list(response_json.keys())[1] + + df = pd.DataFrame.from_dict(response_json[key], orient="index") + df.index = pd.to_datetime(df.index) + + if start_date and resolution != "i": + df = df[df.index > start_date] + + if end_date and resolution != "i": + df = df[df.index < end_date] + + if (df.index.hour != 0).any(): + # if intraday data, convert to local timezone + df.index = df.index.tz_localize("UTC").tz_convert(get_user_timezone()) + + df = df.rename( + columns={ + "1. open": "Open", + "2. high": "High", + "3. low": "Low", + "4. close": "Close", + } + ) + df.index = pd.DatetimeIndex(df.index) + df = df[::-1] return df.astype(float) diff --git a/openbb_terminal/keys_model.py b/openbb_terminal/keys_model.py index 5582e0aea3a1..6c94599f00fc 100644 --- a/openbb_terminal/keys_model.py +++ b/openbb_terminal/keys_model.py @@ -111,9 +111,10 @@ def colorize(self): c = "grey30" elif self.name == self.DEFINED_TEST_PASSED.name: c = "green" - elif self.name == self.DEFINED_TEST_INCONCLUSIVE.name: - c = "yellow" - elif self.name == self.DEFINED_NOT_TESTED.name: + elif self.name in [ + self.DEFINED_TEST_INCONCLUSIVE.name, + self.DEFINED_NOT_TESTED.name, + ]: c = "yellow" return f"[{c}]{self.value}[/{c}]" diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index ac8e028058c6..1208398b7f93 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -1115,34 +1115,33 @@ def call_stop(self, _) -> None: ) # If user doesn't specify they want to store routine locally - else: - # Confirm that the user is logged in - if not is_local(): - # routine = read_routine(file_name=routine_file) - routine = "\n".join(SESSION_RECORDED[:-1]) - - if routine is not None: - kwargs = { - "auth_header": current_user.profile.get_auth_header(), - "name": SESSION_RECORDED_NAME, - "description": SESSION_RECORDED_DESCRIPTION, - "routine": routine, - "tags": SESSION_RECORDED_TAGS, - "public": SESSION_RECORDED_PUBLIC, - "base_url": Hub.BackendEnvironment.BASE_URL, - } - response = Hub.upload_routine(**kwargs) # type: ignore - if response is not None and response.status_code == 409: - i = console.input( - "A routine with the same name already exists, " - "do you want to replace it? (y/n): " - ) - console.print("") - if i.lower() in ["y", "yes"]: - kwargs["override"] = True # type: ignore - response = Hub.upload_routine(**kwargs) # type: ignore - else: - console.print("[info]Aborted.[/info]") + # Confirm that the user is logged in + elif not is_local(): + # routine = read_routine(file_name=routine_file) + routine = "\n".join(SESSION_RECORDED[:-1]) + + if routine is not None: + kwargs = { + "auth_header": current_user.profile.get_auth_header(), + "name": SESSION_RECORDED_NAME, + "description": SESSION_RECORDED_DESCRIPTION, + "routine": routine, + "tags": SESSION_RECORDED_TAGS, + "public": SESSION_RECORDED_PUBLIC, + "base_url": Hub.BackendEnvironment.BASE_URL, + } + response = Hub.upload_routine(**kwargs) # type: ignore + if response is not None and response.status_code == 409: + i = console.input( + "A routine with the same name already exists, " + "do you want to replace it? (y/n): " + ) + console.print("") + if i.lower() in ["y", "yes"]: + kwargs["override"] = True # type: ignore + response = Hub.upload_routine(**kwargs) # type: ignore + else: + console.print("[info]Aborted.[/info]") # Clear session to be recorded again RECORD_SESSION = False @@ -1509,13 +1508,9 @@ def menu(self, custom_path_menu_above: str = ""): logger.warning("Replacing by %s", an_input) console.print(f"[green]Replacing by '{an_input}'.[/green]\n") self.queue.insert(0, an_input) - else: - if ( - self.TRY_RELOAD - and get_current_user().preferences.RETRY_WITH_LOAD - ): - console.print(f"\nTrying `load {an_input}`\n") - self.queue.insert(0, "load " + an_input) + elif self.TRY_RELOAD and get_current_user().preferences.RETRY_WITH_LOAD: + console.print(f"\nTrying `load {an_input}`\n") + self.queue.insert(0, "load " + an_input) class StockBaseController(BaseController, metaclass=ABCMeta): @@ -1690,9 +1685,7 @@ def call_load(self, other_args: List[str]): self.ticker = ns_parser.ticker.upper() self.suffix = "" - if ns_parser.source == "EODHD": - self.start = self.stock.index[0].to_pydatetime() - elif ns_parser.source == "eodhd": + if ns_parser.source.lower() == "EODHD": self.start = self.stock.index[0].to_pydatetime() else: self.start = ns_parser.start diff --git a/openbb_terminal/portfolio/portfolio_controller.py b/openbb_terminal/portfolio/portfolio_controller.py index 7281af1b60c6..2677a0e62573 100644 --- a/openbb_terminal/portfolio/portfolio_controller.py +++ b/openbb_terminal/portfolio/portfolio_controller.py @@ -428,15 +428,14 @@ def call_bench(self, other_args: List[str]): console.print( "[red]Please first load transactions file using 'load'[/red]" ) - else: - if self.portfolio.set_benchmark( - ns_parser.benchmark, ns_parser.full_shares - ): - self.benchmark_name = statics.BENCHMARK_CHOICES.get( - ns_parser.benchmark, ns_parser.benchmark - ) - self.original_benchmark_ticker = ns_parser.benchmark - self.recalculate_alloc = True + elif self.portfolio.set_benchmark( + ns_parser.benchmark, ns_parser.full_shares + ): + self.benchmark_name = statics.BENCHMARK_CHOICES.get( + ns_parser.benchmark, ns_parser.benchmark + ) + self.original_benchmark_ticker = ns_parser.benchmark + self.recalculate_alloc = True @log_start_end(log=logger) def call_alloc(self, other_args: List[str]): diff --git a/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py b/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py index 219556a1e65c..ac24ef14dde2 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py +++ b/openbb_terminal/portfolio/portfolio_optimization/optimizer_model.py @@ -141,15 +141,14 @@ def d_period(interval: str = "1y", start_date: str = "", end_date: str = ""): if start_date == "": if interval in extra_choices: p = extra_choices[interval] - else: - if interval[-1] == "d": - p = "[" + interval[:-1] + " Days]" - elif interval[-1] == "w": - p = "[" + interval[:-1] + " Weeks]" - elif interval[-1] == "o": - p = "[" + interval[:-2] + " Months]" - elif interval[-1] == "y": - p = "[" + interval[:-1] + " Years]" + elif interval[-1] == "d": + p = "[" + interval[:-1] + " Days]" + elif interval[-1] == "w": + p = "[" + interval[:-1] + " Weeks]" + elif interval[-1] == "o": + p = "[" + interval[:-2] + " Months]" + elif interval[-1] == "y": + p = "[" + interval[:-1] + " Years]" if p[1:3] == "1 ": p = p.replace("s", "") else: diff --git a/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py b/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py index 5d3e74a86119..255df4e12d06 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py +++ b/openbb_terminal/portfolio/portfolio_optimization/optimizer_view.py @@ -135,15 +135,14 @@ def d_period(interval: str = "1y", start_date: str = "", end_date: str = ""): if start_date == "": if interval in extra_choices: p = extra_choices[interval] - else: - if interval[-1] == "d": - p = "[" + interval[:-1] + " Days]" - elif interval[-1] == "w": - p = "[" + interval[:-1] + " Weeks]" - elif interval[-1] == "o": - p = "[" + interval[:-2] + " Months]" - elif interval[-1] == "y": - p = "[" + interval[:-1] + " Years]" + elif interval[-1] == "d": + p = "[" + interval[:-1] + " Days]" + elif interval[-1] == "w": + p = "[" + interval[:-1] + " Weeks]" + elif interval[-1] == "o": + p = "[" + interval[:-2] + " Months]" + elif interval[-1] == "y": + p = "[" + interval[:-1] + " Years]" if p[1:3] == "1 ": p = p.replace("s", "") else: diff --git a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_helpers.py b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_helpers.py index b71c07caf216..7fce5d259fea 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_helpers.py +++ b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_helpers.py @@ -21,11 +21,8 @@ def check_save_file(file: str) -> str: "Cannot overwrite defaults.ini file, please save with a different name" ) ) - else: - if not file.endswith(".ini"): - log_and_raise( - argparse.ArgumentTypeError("File to be saved needs to be .ini") - ) + elif not file.endswith(".ini"): + log_and_raise(argparse.ArgumentTypeError("File to be saved needs to be .ini")) return file diff --git a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py index ac358eb4ba1a..e1abd5aaf919 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py +++ b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py @@ -209,79 +209,76 @@ def process_stocks( group_by="ticker", ) - else: - if interval in period_choices: - # Setting temporal file name - name = os.path.join( - path, - "Stocks " + interval + " " + date.today().strftime("%Y-%m-%d") + ".pkl", - ) + elif interval in period_choices: + # Setting temporal file name + name = os.path.join( + path, + "Stocks " + interval + " " + date.today().strftime("%Y-%m-%d") + ".pkl", + ) - # Creating if exist - if os.path.exists(name): - stock_closes_0 = pd.read_pickle(name) # noqa: S301 - list_of_stocks_0 = list(set(symbols) - set(stock_closes_0.columns)) - else: - stock_closes_0 = None - list_of_stocks_0 = symbols - - # Download assets that are not in temporal file - if list_of_stocks_0 == []: - stock_closes = stock_closes_0.copy() - else: - stock_prices = yf.download( - list_of_stocks_0, period=interval, progress=False, group_by="ticker" - ) + # Creating if exist + if os.path.exists(name): + stock_closes_0 = pd.read_pickle(name) # noqa: S301 + list_of_stocks_0 = list(set(symbols) - set(stock_closes_0.columns)) + else: + stock_closes_0 = None + list_of_stocks_0 = symbols + # Download assets that are not in temporal file + if list_of_stocks_0 == []: + stock_closes = stock_closes_0.copy() else: - end_ = date.today() - if end_.weekday() >= 5: - end_ = end_ + relativedelta(weekday=FR(-1)) - if interval.find("d") >= 1: - days = int(interval[:-1]) - start_ = end_ - relativedelta(days=days) - elif interval.find("w") >= 1: - weeks = int(interval[:-1]) - start_ = end_ - relativedelta(weeks=weeks) - elif interval.find("mo") >= 1: - months = int(interval[:-2]) - start_ = end_ - relativedelta(months=months) - elif interval.find("y") >= 1: - years = int(interval[:-1]) - start_ = end_ - relativedelta(years=years) - else: - # console.print( - # "Please use an adequate interval." - # ) - return None - - start_date = start_.strftime("%Y-%m-%d") - end_date = end_.strftime("%Y-%m-%d") - - # Creating temporal file name - name = os.path.join( - path, "Stocks " + start_date + " to " + end_date + ".pkl" + stock_prices = yf.download( + list_of_stocks_0, period=interval, progress=False, group_by="ticker" ) - # Checking if temporal file exists - if os.path.exists(name): - stock_closes_0 = pd.read_pickle(name) # noqa: S301 - list_of_stocks_0 = list(set(symbols) - set(stock_closes_0.columns)) - else: - stock_closes_0 = None - list_of_stocks_0 = symbols - - # Download assets that are not in temporal file - if list_of_stocks_0 == []: - stock_closes = stock_closes_0.copy() - else: - stock_prices = yf.download( - list_of_stocks_0, - start=start_date, - end=end_date, - progress=False, - group_by="ticker", - ) + else: + end_ = date.today() + if end_.weekday() >= 5: + end_ = end_ + relativedelta(weekday=FR(-1)) + if interval.find("d") >= 1: + days = int(interval[:-1]) + start_ = end_ - relativedelta(days=days) + elif interval.find("w") >= 1: + weeks = int(interval[:-1]) + start_ = end_ - relativedelta(weeks=weeks) + elif interval.find("mo") >= 1: + months = int(interval[:-2]) + start_ = end_ - relativedelta(months=months) + elif interval.find("y") >= 1: + years = int(interval[:-1]) + start_ = end_ - relativedelta(years=years) + else: + # console.print( + # "Please use an adequate interval." + # ) + return None + + start_date = start_.strftime("%Y-%m-%d") + end_date = end_.strftime("%Y-%m-%d") + + # Creating temporal file name + name = os.path.join(path, "Stocks " + start_date + " to " + end_date + ".pkl") + + # Checking if temporal file exists + if os.path.exists(name): + stock_closes_0 = pd.read_pickle(name) # noqa: S301 + list_of_stocks_0 = list(set(symbols) - set(stock_closes_0.columns)) + else: + stock_closes_0 = None + list_of_stocks_0 = symbols + + # Download assets that are not in temporal file + if list_of_stocks_0 == []: + stock_closes = stock_closes_0.copy() + else: + stock_prices = yf.download( + list_of_stocks_0, + start=start_date, + end=end_date, + progress=False, + group_by="ticker", + ) if stock_closes is None: if len(list_of_stocks_0) == 1: diff --git a/openbb_terminal/rich_config.py b/openbb_terminal/rich_config.py index 34acae8d7273..444151abb14a 100644 --- a/openbb_terminal/rich_config.py +++ b/openbb_terminal/rich_config.py @@ -264,11 +264,10 @@ def print(self, *args, **kwargs): self.__console.print(kwargs["text"]) else: print(self.filter_rich_tags(kwargs["text"])) + elif not get_current_system().TEST_MODE: + self.__console.print(*args, **kwargs) else: - if not get_current_system().TEST_MODE: - self.__console.print(*args, **kwargs) - else: - print(*args, **kwargs) + print(*args, **kwargs) def input(self, *args, **kwargs): self.print(*args, **kwargs, end="") diff --git a/openbb_terminal/routine_functions.py b/openbb_terminal/routine_functions.py index 434e5f8c6b70..ea1c50e4a92a 100644 --- a/openbb_terminal/routine_functions.py +++ b/openbb_terminal/routine_functions.py @@ -261,39 +261,33 @@ def parse_openbb_script( # noqa: PLR0911 return ( f"[red]Variable {VAR_NAME} not given " "for current routine script.[/red]", - "", ) # Only enters here when any other index from 0 is used - else: - if VAR_NAME in ROUTINE_VARS: - variable = eval( # noqa: S307 - f'ROUTINE_VARS["{VAR_NAME}"]' - ) - length_variable = ( - len(variable) - if isinstance(variable, list) - else 1 - ) + elif VAR_NAME in ROUTINE_VARS: + variable = eval( # noqa: S307 + f'ROUTINE_VARS["{VAR_NAME}"]' + ) + length_variable = ( + len(variable) if isinstance(variable, list) else 1 + ) - # We use <= because we are using 0 index based lists - if length_variable <= int(VAR_SLICE): - return ( - f"[red]Variable {VAR_NAME} only has " - f"{length_variable} elements and there " - f"was an attempt to access it with index {VAR_SLICE}.[/red]", - "", - ) - templine = templine.replace( - match[0], - variable[int(VAR_SLICE)], - ) - else: + # We use <= because we are using 0 index based lists + if length_variable <= int(VAR_SLICE): return ( - f"[red]Variable {VAR_NAME} not given " - "for current routine script.[/red]", + f"[red]Variable {VAR_NAME} only has " + f"{length_variable} elements and there " + f"was an attempt to access it with index {VAR_SLICE}.[/red]", "", ) + templine = templine.replace( + match[0], + variable[int(VAR_SLICE)], + ) + else: + return ( + f"[red]Variable {VAR_NAME} not given for current routine script.[/red]", + ) # Involves slicing which is a bit more tricky to use eval on elif ( diff --git a/openbb_terminal/stocks/discovery/nasdaq_model.py b/openbb_terminal/stocks/discovery/nasdaq_model.py index dc63e7852fba..c405f7eed4c9 100644 --- a/openbb_terminal/stocks/discovery/nasdaq_model.py +++ b/openbb_terminal/stocks/discovery/nasdaq_model.py @@ -35,14 +35,7 @@ def get_retail_tickers() -> pd.DataFrame: if r.status_code == 200: df = pd.DataFrame(r.json()["datatable"]["data"]) df.columns = ["Date", "Ticker", "Activity", "Sentiment"] - # Wrong API Key - elif r.status_code == 400: - console.print(r.text) - # Premium Feature - elif r.status_code == 403: - console.print(r.text) - # Catching other exception - elif r.status_code != 200: + else: console.print(r.text) return df @@ -89,14 +82,7 @@ def get_dividend_cal(date: Optional[str] = None) -> pd.DataFrame: if r.status_code == 200: df = pd.DataFrame(r.json()["data"]["calendar"]["rows"]) - # Wrong API Key - elif r.status_code == 400: - console.print(r.text) - # Premium Feature - elif r.status_code == 403: - console.print(r.text) - # Catching other exception - elif r.status_code != 200: + else: console.print(r.text) except requests.exceptions.ReadTimeout: diff --git a/openbb_terminal/stocks/fundamental_analysis/av_model.py b/openbb_terminal/stocks/fundamental_analysis/av_model.py index 4632daaed1fc..3f9dccc1b5a3 100644 --- a/openbb_terminal/stocks/fundamental_analysis/av_model.py +++ b/openbb_terminal/stocks/fundamental_analysis/av_model.py @@ -59,22 +59,19 @@ def get_overview(symbol: str) -> pd.DataFrame: # If the returned data was unsuccessful if "Error Message" in result_json: console.print(result_json["Error Message"]) + # check if json is empty + elif not result_json: + console.print("No data found from Alpha Vantage\n") + # Parse json data to dataframe + elif "Note" in result_json: + console.print(result_json["Note"], "\n") else: - # check if json is empty - if not result_json: - console.print("No data found from Alpha Vantage\n") - # Parse json data to dataframe - elif "Note" in result_json: - console.print(result_json["Note"], "\n") - else: - df_fa = pd.json_normalize(result_json) + df_fa = pd.json_normalize(result_json) - # Keep json data sorting in dataframe - df_fa = df_fa[list(result_json.keys())].T - df_fa.iloc[5:] = df_fa.iloc[5:].applymap( - lambda x: lambda_long_number_format(x) - ) - df_fa.columns = [" "] + # Keep json data sorting in dataframe + df_fa = df_fa[list(result_json.keys())].T + df_fa.iloc[5:] = df_fa.iloc[5:].applymap(lambda x: lambda_long_number_format(x)) + df_fa.columns = [" "] return df_fa @@ -185,54 +182,48 @@ def get_income_statements( # If the returned data was unsuccessful if "Error Message" in response_json: console.print(response_json["Error Message"]) + # check if json is empty + elif not response_json: + console.print("No data found from Alpha Vantage, looking in Yahoo Finance\n") + if ( + yahoo_finance_model.get_financials(symbol, statement="financials") + is not None + ): + return yahoo_finance_model.get_financials(symbol, statement="financials") else: - # check if json is empty - if not response_json: - console.print( - "No data found from Alpha Vantage, looking in Yahoo Finance\n" - ) - if ( - yahoo_finance_model.get_financials(symbol, statement="financials") - is not None - ): - return yahoo_finance_model.get_financials( - symbol, statement="financials" - ) - else: - statements = response_json - df_fa = pd.DataFrame() + statements = response_json + df_fa = pd.DataFrame() - if quarterly: - if "quarterlyReports" in statements: - df_fa = pd.DataFrame(statements["quarterlyReports"]) - else: - if "annualReports" in statements: - df_fa = pd.DataFrame(statements["annualReports"]) + if quarterly: + if "quarterlyReports" in statements: + df_fa = pd.DataFrame(statements["quarterlyReports"]) + elif "annualReports" in statements: + df_fa = pd.DataFrame(statements["annualReports"]) - if df_fa.empty: - console.print("No data found from Alpha Vantage\n") - return pd.DataFrame() + if df_fa.empty: + console.print("No data found from Alpha Vantage\n") + return pd.DataFrame() - df_fa = df_fa.set_index("fiscalDateEnding") - df_fa = df_fa[::-1].T + df_fa = df_fa.set_index("fiscalDateEnding") + df_fa = df_fa[::-1].T - df_fa = df_fa.replace("None", "0") - df_fa.iloc[1:] = df_fa.iloc[1:].astype("float") + df_fa = df_fa.replace("None", "0") + df_fa.iloc[1:] = df_fa.iloc[1:].astype("float") - df_fa_c = df_fa.iloc[:, -limit:].applymap( - lambda x: lambda_long_number_format(x) - ) + df_fa_c = df_fa.iloc[:, -limit:].applymap( + lambda x: lambda_long_number_format(x) + ) - if ratios: - df_fa_pc = df_fa.iloc[1:].pct_change(axis="columns").fillna(0) - j = 0 - for i in list(range(1, 25)): - df_fa.iloc[i] = df_fa_pc.iloc[j] - j += 1 + if ratios: + df_fa_pc = df_fa.iloc[1:].pct_change(axis="columns").fillna(0) + j = 0 + for i in list(range(1, 25)): + df_fa.iloc[i] = df_fa_pc.iloc[j] + j += 1 - df_fa = df_fa.iloc[:, 0:limit] + df_fa = df_fa.iloc[:, 0:limit] - return df_fa_c if not plot else df_fa + return df_fa_c if not plot else df_fa return pd.DataFrame() @@ -292,9 +283,8 @@ def get_balance_sheet( if quarterly: if "quarterlyReports" in statements: df_fa = pd.DataFrame(statements["quarterlyReports"]) - else: - if "annualReports" in statements: - df_fa = pd.DataFrame(statements["annualReports"]) + elif "annualReports" in statements: + df_fa = pd.DataFrame(statements["annualReports"]) if df_fa.empty: console.print("No data found from Alpha Vantage\n") @@ -366,57 +356,52 @@ def get_cash_flow( # If the returned data was unsuccessful if "Error Message" in response_json: console.print(response_json["Error Message"]) + elif not response_json: + console.print("No data found from Alpha Vantage, looking in Yahoo Finance\n") + + if ( + yahoo_finance_model.get_financials(symbol, statement="cash-flow") + is not None + ): + return yahoo_finance_model.get_financials(symbol, statement="cash-flow") else: - # check if json is empty - if not response_json: - console.print( - "No data found from Alpha Vantage, looking in Yahoo Finance\n" - ) + statements = response_json + df_fa = pd.DataFrame() - if ( - yahoo_finance_model.get_financials(symbol, statement="cash-flow") - is not None - ): - return yahoo_finance_model.get_financials(symbol, statement="cash-flow") - else: - statements = response_json - df_fa = pd.DataFrame() + if quarterly: + if "quarterlyReports" in statements: + df_fa = pd.DataFrame(statements["quarterlyReports"]) + elif "annualReports" in statements: + df_fa = pd.DataFrame(statements["annualReports"]) - if quarterly: - if "quarterlyReports" in statements: - df_fa = pd.DataFrame(statements["quarterlyReports"]) - else: - if "annualReports" in statements: - df_fa = pd.DataFrame(statements["annualReports"]) + if df_fa.empty: + console.print("No data found from Alpha Vantage\n") + return pd.DataFrame() - if df_fa.empty: - console.print("No data found from Alpha Vantage\n") - return pd.DataFrame() + df_fa = df_fa.set_index("fiscalDateEnding") + df_fa = df_fa[::-1].T - df_fa = df_fa.set_index("fiscalDateEnding") - df_fa = df_fa[::-1].T + df_fa = df_fa.replace("None", "0") + df_fa.iloc[1:] = df_fa.iloc[1:].astype("float") + + df_fa_c = df_fa.iloc[:, -limit:].applymap( + lambda x: lambda_long_number_format(x) + ) - df_fa = df_fa.replace("None", "0") - df_fa.iloc[1:] = df_fa.iloc[1:].astype("float") + if ratios: + df_fa_pc = df_fa.iloc[1:].pct_change(axis="columns").fillna(0) + j = 0 + for i in list(range(1, 37)): + df_fa.iloc[i] = df_fa_pc.iloc[j] + j += 1 - df_fa_c = df_fa.iloc[:, -limit:].applymap( + df_fa_c = df_fa.iloc[:, 0:limit].applymap( lambda x: lambda_long_number_format(x) ) - if ratios: - df_fa_pc = df_fa.iloc[1:].pct_change(axis="columns").fillna(0) - j = 0 - for i in list(range(1, 37)): - df_fa.iloc[i] = df_fa_pc.iloc[j] - j += 1 - - df_fa_c = df_fa.iloc[:, 0:limit].applymap( - lambda x: lambda_long_number_format(x) - ) - - df_fa = df_fa.iloc[:, 0:limit] + df_fa = df_fa.iloc[:, 0:limit] - return df_fa_c if not plot else df_fa + return df_fa_c if not plot else df_fa return pd.DataFrame() @@ -448,43 +433,42 @@ def get_earnings(symbol: str, quarterly: bool = False) -> pd.DataFrame: # If the returned data was unsuccessful if "Error Message" in result_json: console.print(result_json["Error Message"]) + # check if json is empty + elif not result_json or len(result_json) < 2: + console.print("No data found from Alpha Vantage\n") else: - # check if json is empty - if not result_json or len(result_json) < 2: - console.print("No data found from Alpha Vantage\n") - else: - df_fa = pd.json_normalize(result_json) - - if quarterly: - df_fa = pd.DataFrame(df_fa["quarterlyEarnings"][0]) - df_fa = df_fa[ - [ - "fiscalDateEnding", - "reportedDate", - "reportedEPS", - "estimatedEPS", - "surprise", - "surprisePercentage", - ] + df_fa = pd.json_normalize(result_json) + + if quarterly: + df_fa = pd.DataFrame(df_fa["quarterlyEarnings"][0]) + df_fa = df_fa[ + [ + "fiscalDateEnding", + "reportedDate", + "reportedEPS", + "estimatedEPS", + "surprise", + "surprisePercentage", ] - df_fa = df_fa.rename( - columns={ - "fiscalDateEnding": "Fiscal Date Ending", - "reportedEPS": "Reported EPS", - "estimatedEPS": "Estimated EPS", - "reportedDate": "Reported Date", - "surprise": "Surprise", - "surprisePercentage": "Surprise Percentage", - } - ) - else: - df_fa = pd.DataFrame(df_fa["annualEarnings"][0]) - df_fa = df_fa.rename( - columns={ - "fiscalDateEnding": "Fiscal Date Ending", - "reportedEPS": "Reported EPS", - } - ) + ] + df_fa = df_fa.rename( + columns={ + "fiscalDateEnding": "Fiscal Date Ending", + "reportedEPS": "Reported EPS", + "estimatedEPS": "Estimated EPS", + "reportedDate": "Reported Date", + "surprise": "Surprise", + "surprisePercentage": "Surprise Percentage", + } + ) + else: + df_fa = pd.DataFrame(df_fa["annualEarnings"][0]) + df_fa = df_fa.rename( + columns={ + "fiscalDateEnding": "Fiscal Date Ending", + "reportedEPS": "Reported EPS", + } + ) return df_fa diff --git a/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py b/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py index 537db6f1ffa8..fb3eb06ec547 100644 --- a/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py +++ b/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py @@ -332,15 +332,7 @@ def get_financials(symbol: str, statement: str, ratios: bool = False) -> pd.Data new_headers[:0] = ["Breakdown"] df.columns = new_headers df.set_index("Breakdown", inplace=True) - elif statement == "financials": - for dates in headers[2:]: - read = datetime.strptime(dates, "%d/%m/%Y") - write = read.strftime("%Y-%m-%d") - new_headers.append(write) - new_headers[:0] = ["Breakdown", "ttm"] - df.columns = new_headers - df.set_index("Breakdown", inplace=True) - elif statement == "cash-flow": + elif statement == ("financials", "cash-flow"): for dates in headers[2:]: read = datetime.strptime(dates, "%d/%m/%Y") write = read.strftime("%Y-%m-%d") diff --git a/openbb_terminal/stocks/options/cboe_model.py b/openbb_terminal/stocks/options/cboe_model.py index 8aa534ec4433..f3cbd73c7b23 100644 --- a/openbb_terminal/stocks/options/cboe_model.py +++ b/openbb_terminal/stocks/options/cboe_model.py @@ -143,14 +143,13 @@ def get_ticker_info(symbol: str) -> Tuple[pd.DataFrame, list[str]]: try: if symbol in TICKER_EXCEPTIONS: new_ticker = "^" + symbol - else: - if symbol not in INDEXES: - new_ticker = symbol + elif symbol not in INDEXES: + new_ticker = symbol - elif symbol in INDEXES: - new_ticker = "^" + symbol + elif symbol in INDEXES: + new_ticker = "^" + symbol - # Gets the data to return, and if none returns empty Tuple # + # Gets the data to return, and if none returns empty Tuple # symbol_info_url = ( "https://www.cboe.com/education/tools/trade-optimizer/symbol-info/?symbol=" @@ -298,23 +297,19 @@ def get_ticker_iv(symbol: str) -> pd.DataFrame: if symbol in TICKER_EXCEPTIONS: quotes_iv_url = ( "https://cdn.cboe.com/api/global/delayed_quotes/historical_data/_" - f"{symbol}" - ".json" + f"{symbol}.json" + ) + elif symbol not in INDEXES: + quotes_iv_url = ( + "https://cdn.cboe.com/api/global/delayed_quotes/historical_data/" + f"{symbol}.json" ) - else: - if symbol not in INDEXES: - quotes_iv_url = ( - "https://cdn.cboe.com/api/global/delayed_quotes/historical_data/" - f"{symbol}" - ".json" - ) - elif symbol in INDEXES: - quotes_iv_url = ( - "https://cdn.cboe.com/api/global/delayed_quotes/historical_data/_" - f"{symbol}" - ".json" - ) + elif symbol in INDEXES: + quotes_iv_url = ( + "https://cdn.cboe.com/api/global/delayed_quotes/historical_data/_" + f"{symbol}.json" + ) h_iv = request(quotes_iv_url) if h_iv.status_code != 200: diff --git a/openbb_terminal/stocks/screener/finviz_model.py b/openbb_terminal/stocks/screener/finviz_model.py index afc786da3a44..ff9eb0060a85 100644 --- a/openbb_terminal/stocks/screener/finviz_model.py +++ b/openbb_terminal/stocks/screener/finviz_model.py @@ -181,11 +181,10 @@ def get_screener_data( order=d_general["Order"], ascend=ascend ) + elif limit > 0: + df_screen = screen.screener_view(limit=limit, ascend=ascend) else: - if limit > 0: - df_screen = screen.screener_view(limit=limit, ascend=ascend) - else: - df_screen = screen.screener_view(ascend=ascend) + df_screen = screen.screener_view(ascend=ascend) df_screen.columns = [val.strip("\n") for val in df_screen.columns] if "Company" in df_screen.columns: diff --git a/openbb_terminal/stocks/screener/finviz_view.py b/openbb_terminal/stocks/screener/finviz_view.py index fdc8f786aa85..7b8014f6d7c8 100644 --- a/openbb_terminal/stocks/screener/finviz_view.py +++ b/openbb_terminal/stocks/screener/finviz_view.py @@ -200,38 +200,18 @@ def screener( df_original = df_screen.copy() df_screen = df_screen.fillna("") - if data_type == "ownership": - cols = ["Market Cap", "Outstanding", "Float", "Avg Volume", "Volume"] - df_screen[cols] = df_screen[cols].applymap( - lambda x: lambda_long_number_format(x, 1) - ) - elif data_type == "overview": - cols = ["Market Cap", "Volume"] - df_screen[cols] = df_screen[cols].applymap( - lambda x: lambda_long_number_format(x, 1) - ) - elif data_type == "technical": - cols = ["Volume"] - df_screen[cols] = df_screen[cols].applymap( - lambda x: lambda_long_number_format(x, 1) - ) - elif data_type == "valuation": - cols = ["Market Cap", "Volume"] - df_screen[cols] = df_screen[cols].applymap( - lambda x: lambda_long_number_format(x, 1) - ) - elif data_type == "financial": - cols = ["Market Cap", "Volume"] - df_screen[cols] = df_screen[cols].applymap( - lambda x: lambda_long_number_format(x, 1) - ) - elif data_type == "performance": - cols = ["Avg Volume", "Volume"] - df_screen[cols] = df_screen[cols].applymap( - lambda x: lambda_long_number_format(x, 1) - ) - elif data_type == "technical": - cols = ["Volume"] + cols = [] + data_type_cols = { + "ownership": ["Market Cap", "Outstanding", "Float", "Avg Volume", "Volume"], + "overview": ["Market Cap", "Volume"], + "technical": ["Volume"], + "valuation": ["Market Cap", "Volume"], + "financial": ["Market Cap", "Volume"], + "performance": ["Avg Volume", "Volume"], + } + cols = data_type_cols.get(data_type) + + if cols: df_screen[cols] = df_screen[cols].applymap( lambda x: lambda_long_number_format(x, 1) ) diff --git a/openbb_terminal/terminal_controller.py b/openbb_terminal/terminal_controller.py index c92261eaed67..ef722e6f8bda 100644 --- a/openbb_terminal/terminal_controller.py +++ b/openbb_terminal/terminal_controller.py @@ -425,20 +425,19 @@ def call_guess(self, other_args: List[str]) -> None: ) # When there is a single path to the solution + elif an_input.lower() == solution.lower(): + self.queue = an_input.split("/") + ["home"] + console.print( + f"\n[green]You guessed correctly in {round(time_dif, 2)} seconds![green]\n" + ) + # If we are already counting successes + if self.GUESS_TOTAL_TRIES > 0: + self.GUESS_CORRECTLY += 1 + self.GUESS_SUM_SCORE += time_dif else: - if an_input.lower() == solution.lower(): - self.queue = an_input.split("/") + ["home"] - console.print( - f"\n[green]You guessed correctly in {round(time_dif, 2)} seconds![green]\n" - ) - # If we are already counting successes - if self.GUESS_TOTAL_TRIES > 0: - self.GUESS_CORRECTLY += 1 - self.GUESS_SUM_SCORE += time_dif - else: - console.print( - f"\n[red]You guessed wrong! The correct path would have been:\n{solution}[/red]\n" - ) + console.print( + f"\n[red]You guessed wrong! The correct path would have been:\n{solution}[/red]\n" + ) # Compute average score and provide a result if it's the last try if self.GUESS_TOTAL_TRIES > 0: @@ -683,11 +682,10 @@ def call_exe(self, other_args: List[str]): "https" ) and not ns_parser.url.startswith("http:"): url = "https://" + ns_parser.url + elif ns_parser.url.startswith("http://"): + url = ns_parser.url.replace("http://", "https://") else: - if ns_parser.url.startswith("http://"): - url = ns_parser.url.replace("http://", "https://") - else: - url = ns_parser.url + url = ns_parser.url username = url.split("/")[-3] script_name = url.split("/")[-1] file_name = f"{username}_{script_name}.openbb" diff --git a/openbb_terminal/terminal_helper.py b/openbb_terminal/terminal_helper.py index 1b2cc2705895..08fea1ac836d 100644 --- a/openbb_terminal/terminal_helper.py +++ b/openbb_terminal/terminal_helper.py @@ -157,29 +157,28 @@ def open_openbb_documentation( elif "account" in path: path = "/usage?path=/usage/guides/basics" command = "" - else: - if arg_type == "command": # user passed a command name - if command in ["settings", "featflags"]: - path = "/usage?path=/usage/guides/customizing-the-terminal" - command = "" - else: - path = f"/commands?path={path}" - elif arg_type == "menu": # user passed a menu name - if command in ["ta", "ba", "qa"]: - menu = path.split("/")[-2] - path = f"/usage?path=/usage/intros/common/{menu}" - elif command == "forecast": - command = "" - path = "/usage?path=/usage/intros/forecast" - else: - path = f"/usage?path=/usage/intros/{path}" - else: # user didn't pass argument and is in a menu + elif arg_type == "command": # user passed a command name + if command in ["settings", "featflags"]: + path = "/usage?path=/usage/guides/customizing-the-terminal" + command = "" + else: + path = f"/commands?path={path}" + elif arg_type == "menu": # user passed a menu name + if command in ["ta", "ba", "qa"]: menu = path.split("/")[-2] - path = ( - f"/usage?path=/usage/intros/common/{menu}" - if menu in ["ta", "ba", "qa"] - else f"/usage?path=/usage/intros/{path}" - ) + path = f"/usage?path=/usage/intros/common/{menu}" + elif command == "forecast": + command = "" + path = "/usage?path=/usage/intros/forecast" + else: + path = f"/usage?path=/usage/intros/{path}" + else: # user didn't pass argument and is in a menu + menu = path.split("/")[-2] + path = ( + f"/usage?path=/usage/intros/common/{menu}" + if menu in ["ta", "ba", "qa"] + else f"/usage?path=/usage/intros/{path}" + ) if command: if command == "keys": diff --git a/pyproject.toml b/pyproject.toml index 0219939523d7..970b91090a5f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -181,8 +181,8 @@ target-version = "py38" # All options here: https://github.com/charliermarsh/ruff#supported-rules select = ["E", "W", "F", "Q", "S", "UP", "I", "PLC", "PLE", "PLR", "PLW", "SIM"] # These ignores should be seen as temporary solutions to problems that will NEED fixed -# Ignores that can be removed easily: SIM114 -ignore = ["S105", "S106", "PLR2004", "PLR0913", "PLR0915", "SIM105", "SIM114", "PLR0912", "S311"] +# Ignores that can be removed easily: PLR0912 +ignore = ["S105", "S106", "PLR2004", "PLR0913", "PLR0915", "SIM105", "PLR0912", "S311"] [tool.ruff.per-file-ignores] "tests/*" = ["S101"] diff --git a/tests/conftest.py b/tests/conftest.py index 55910c87e51a..e33852d6f5de 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -83,16 +83,11 @@ def strip(self) -> bool: @property def record_changed(self) -> bool: - if self.__recorded is None: - changed = True - elif self.__strip and self.__recorded.strip() != self.__captured.strip(): - changed = True - elif not self.__strip and self.__recorded != self.__captured: - changed = True - else: - changed = False - - return changed + return ( + self.__recorded is None + or (self.__strip and self.__recorded.strip() != self.__captured.strip()) + or (not self.__strip and self.__recorded != self.__captured) + ) @property def record_exists(self) -> bool: diff --git a/tests/openbb_terminal/stocks/government/test_gov_controller.py b/tests/openbb_terminal/stocks/government/test_gov_controller.py index a7d5464e6a6c..5370f0faddab 100644 --- a/tests/openbb_terminal/stocks/government/test_gov_controller.py +++ b/tests/openbb_terminal/stocks/government/test_gov_controller.py @@ -372,9 +372,7 @@ def test_call_func(tested_func, mocked_func, other_args, called_with, mocker): controller = gov_controller.GovController(ticker="MOCK_TICKER") getattr(controller, tested_func)(other_args=other_args) - if isinstance(called_with, dict): - mock.assert_called_once_with(**called_with) - elif isinstance(called_with, list): + if isinstance(called_with, (dict, list)): mock.assert_called_once_with(**called_with) else: mock.assert_called_once() diff --git a/website/generate_sdk_markdown.py b/website/generate_sdk_markdown.py index 537dcc0e41a4..b4595d594b14 100644 --- a/website/generate_sdk_markdown.py +++ b/website/generate_sdk_markdown.py @@ -155,9 +155,8 @@ def generate_markdown_section(meta: Dict[str, Any]): if example["description"] and prev_snippet != "": markdown += f"```\n{example['description']}\n```\n" prev_snippet = snippet.strip() - else: - if example["description"]: - markdown += f"\n{example['description']}\n\n" + elif example["description"]: + markdown += f"\n{example['description']}\n\n" else: if example["description"]: markdown += f"\n{example['description']}\n\n" From 6d8c8b5096c220f6b1452b7e73ddbe02365e95f5 Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 08:29:01 -0400 Subject: [PATCH 06/20] Fixed black --- openbb_terminal/dashboards/stream/Forecasting.py | 4 +++- openbb_terminal/econometrics/econometrics_controller.py | 6 +++++- tests/openbb_terminal/session/test_local_model.py | 4 +++- website/controller_doc_classes.py | 6 +++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/openbb_terminal/dashboards/stream/Forecasting.py b/openbb_terminal/dashboards/stream/Forecasting.py index 3dbe6b22549a..6c9383bf92f8 100644 --- a/openbb_terminal/dashboards/stream/Forecasting.py +++ b/openbb_terminal/dashboards/stream/Forecasting.py @@ -163,7 +163,9 @@ def handle_changes( external_axes=True, ) - with st.spinner("Running model..."), patch.object(OpenBBFigure, "show", mock_show): + with st.spinner("Running model..."), patch.object( + OpenBBFigure, "show", mock_show + ): fig: OpenBBFigure = getattr( common_vars.openbb.forecast, f"{model}_chart" )(**kwargs) diff --git a/openbb_terminal/econometrics/econometrics_controller.py b/openbb_terminal/econometrics/econometrics_controller.py index 550c617b5601..317b92902e96 100644 --- a/openbb_terminal/econometrics/econometrics_controller.py +++ b/openbb_terminal/econometrics/econometrics_controller.py @@ -409,7 +409,11 @@ def call_load(self, other_args: List[str]): if ns_parser.alias: alias = ns_parser.alias else: - alias = ".".join(ns_parser.file.split(".")[:-1]) if "." in ns_parser.file else ns_parser.file + alias = ( + ".".join(ns_parser.file.split(".")[:-1]) + if "." in ns_parser.file + else ns_parser.file + ) # check if this dataset has been added already if alias in self.files: diff --git a/tests/openbb_terminal/session/test_local_model.py b/tests/openbb_terminal/session/test_local_model.py index 47eef8404b11..6ce36afbc479 100644 --- a/tests/openbb_terminal/session/test_local_model.py +++ b/tests/openbb_terminal/session/test_local_model.py @@ -93,7 +93,9 @@ def test_get_session_not_exist(): def test_get_session_exception(): open_mock = mock_open() path = "openbb_terminal.core.session.local_model" - with patch(f"{path}.os.path") as path_mock, patch(f"{path}.open", open_mock, create=True): + with patch(f"{path}.os.path") as path_mock, patch( + f"{path}.open", open_mock, create=True + ): open_mock.side_effect = Exception assert local_model.get_session() == {} diff --git a/website/controller_doc_classes.py b/website/controller_doc_classes.py index 93b99c6191e5..db5efb037d2e 100644 --- a/website/controller_doc_classes.py +++ b/website/controller_doc_classes.py @@ -460,7 +460,11 @@ def get_controllers(self) -> None: if ( # noqa: SIM102 name != "TerminalController" and "BaseController" not in name ): # noqa: SIM102 - if isclass(obj) and issubclass(obj, BaseController) and trailmap not in self.controller_docs: + if ( + isclass(obj) + and issubclass(obj, BaseController) + and trailmap not in self.controller_docs + ): ctrl = ControllerDoc(obj, trailmap) # type: ignore if ctrl.has_commands(): self.controller_docs[trailmap] = ctrl From 0cc35d5a486152eade4daa40ad076d84b85bc87f Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 09:19:37 -0400 Subject: [PATCH 07/20] Updated some stuff --- .github/workflows/branch-name-check.yml | 6 +-- .github/workflows/docker-build.yml | 4 +- .github/workflows/gh-pages.yml | 2 +- .github/workflows/linting.yml | 4 +- .pre-commit-config.yaml | 2 +- poetry.lock | 62 ++++++++++++------------- pyproject.toml | 5 +- 7 files changed, 42 insertions(+), 43 deletions(-) diff --git a/.github/workflows/branch-name-check.yml b/.github/workflows/branch-name-check.yml index 2f47dd5da5da..f14494487d24 100644 --- a/.github/workflows/branch-name-check.yml +++ b/.github/workflows/branch-name-check.yml @@ -26,12 +26,12 @@ jobs: echo "Source-branch=$source_branch" >> $GITHUB_OUTPUT echo "target-branch=$target_branch" >> $GITHUB_OUTPUT - + - name: Show Output result for source-branch and target-branch run: | echo "source-branch=${{ steps.branch-name-check.outputs.source-branch }}" echo "target-branch=${{ steps.branch-name-check.outputs.target-branch }}" - + - name: Check branch name for develop PRs if: ${{ steps.branch-name-check.outputs.target-branch == 'develop' }} run: | @@ -50,4 +50,4 @@ jobs: else echo "PR is not from a hotfix or release branch. Pull requests must be from a hotfix or release branch and target the main branch" exit 1 - fi \ No newline at end of file + fi diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 12e2ad1826de..6e69b5d9a6c4 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -5,7 +5,7 @@ on: workflow_dispatch jobs: publish-image: runs-on: ubuntu-latest - env: + env: OPENBBTERMINAL_DOCKER_GITHUB_REPOSITORY: ${{ github.repository }} OPENBB_LOGGING_APP_NAME: "gst_docker" @@ -45,4 +45,4 @@ jobs: - name: Publishing the latest Docker image run: | docker push "${OPENBBTERMINAL_DOCKER_POETRY_IMAGE_LATEST}" - if: startsWith(github.ref, 'refs/heads/main') \ No newline at end of file + if: startsWith(github.ref, 'refs/heads/main') diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index ac1e4c292f5b..a0c8bb86b990 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -90,7 +90,7 @@ jobs: (github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop' && - startsWith(github.head_ref, 'docs/')) + startsWith(github.head_ref, 'docs/')) with: github_token: ${{ secrets.DEPLOY_TOKEN }} publish_dir: ./website/build diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 4c1dae15afef..c131fdf5294b 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -44,7 +44,7 @@ jobs: restore-keys: ${{ runner.os }}-linting-${{ hashFiles('**/poetry.lock') }} - run: | - pip install bandit black codespell mypy==1.1.1 pylint==2.17.0 ruff==0.0.256 + pip install bandit black codespell mypy==1.5.1 pylint==2.17.0 ruff==0.0.285 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 . @@ -74,4 +74,4 @@ jobs: id: json-yaml-validate uses: GrantBirki/json-yaml-validate@v2.0.0 with: - exclude_file: json_validate_exclude.txt \ No newline at end of file + exclude_file: json_validate_exclude.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0e1684b2263e..3400c92429a7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: hooks: - id: black - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: "v0.0.256" + rev: "v0.0.285" hooks: - id: ruff - repo: https://github.com/codespell-project/codespell diff --git a/poetry.lock b/poetry.lock index 78029168582a..8cfa2cd90752 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4915,38 +4915,39 @@ files = [ [[package]] name = "mypy" -version = "1.4.1" +version = "1.5.1" description = "Optional static typing for Python" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "mypy-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8"}, - {file = "mypy-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878"}, - {file = "mypy-1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd"}, - {file = "mypy-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc"}, - {file = "mypy-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1"}, - {file = "mypy-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462"}, - {file = "mypy-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258"}, - {file = "mypy-1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2"}, - {file = "mypy-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7"}, - {file = "mypy-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01"}, - {file = "mypy-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b"}, - {file = "mypy-1.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b"}, - {file = "mypy-1.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7"}, - {file = "mypy-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9"}, - {file = "mypy-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042"}, - {file = "mypy-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3"}, - {file = "mypy-1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6"}, - {file = "mypy-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f"}, - {file = "mypy-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc"}, - {file = "mypy-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828"}, - {file = "mypy-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3"}, - {file = "mypy-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816"}, - {file = "mypy-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c"}, - {file = "mypy-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f"}, - {file = "mypy-1.4.1-py3-none-any.whl", hash = "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4"}, - {file = "mypy-1.4.1.tar.gz", hash = "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b"}, + {file = "mypy-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f33592ddf9655a4894aef22d134de7393e95fcbdc2d15c1ab65828eee5c66c70"}, + {file = "mypy-1.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:258b22210a4a258ccd077426c7a181d789d1121aca6db73a83f79372f5569ae0"}, + {file = "mypy-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9ec1f695f0c25986e6f7f8778e5ce61659063268836a38c951200c57479cc12"}, + {file = "mypy-1.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:abed92d9c8f08643c7d831300b739562b0a6c9fcb028d211134fc9ab20ccad5d"}, + {file = "mypy-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:a156e6390944c265eb56afa67c74c0636f10283429171018446b732f1a05af25"}, + {file = "mypy-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ac9c21bfe7bc9f7f1b6fae441746e6a106e48fc9de530dea29e8cd37a2c0cc4"}, + {file = "mypy-1.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51cb1323064b1099e177098cb939eab2da42fea5d818d40113957ec954fc85f4"}, + {file = "mypy-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:596fae69f2bfcb7305808c75c00f81fe2829b6236eadda536f00610ac5ec2243"}, + {file = "mypy-1.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:32cb59609b0534f0bd67faebb6e022fe534bdb0e2ecab4290d683d248be1b275"}, + {file = "mypy-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:159aa9acb16086b79bbb0016145034a1a05360626046a929f84579ce1666b315"}, + {file = "mypy-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f6b0e77db9ff4fda74de7df13f30016a0a663928d669c9f2c057048ba44f09bb"}, + {file = "mypy-1.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26f71b535dfc158a71264e6dc805a9f8d2e60b67215ca0bfa26e2e1aa4d4d373"}, + {file = "mypy-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc3a600f749b1008cc75e02b6fb3d4db8dbcca2d733030fe7a3b3502902f161"}, + {file = "mypy-1.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:26fb32e4d4afa205b24bf645eddfbb36a1e17e995c5c99d6d00edb24b693406a"}, + {file = "mypy-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:82cb6193de9bbb3844bab4c7cf80e6227d5225cc7625b068a06d005d861ad5f1"}, + {file = "mypy-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4a465ea2ca12804d5b34bb056be3a29dc47aea5973b892d0417c6a10a40b2d65"}, + {file = "mypy-1.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9fece120dbb041771a63eb95e4896791386fe287fefb2837258925b8326d6160"}, + {file = "mypy-1.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d28ddc3e3dfeab553e743e532fb95b4e6afad51d4706dd22f28e1e5e664828d2"}, + {file = "mypy-1.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:57b10c56016adce71fba6bc6e9fd45d8083f74361f629390c556738565af8eeb"}, + {file = "mypy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff0cedc84184115202475bbb46dd99f8dcb87fe24d5d0ddfc0fe6b8575c88d2f"}, + {file = "mypy-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8f772942d372c8cbac575be99f9cc9d9fb3bd95c8bc2de6c01411e2c84ebca8a"}, + {file = "mypy-1.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5d627124700b92b6bbaa99f27cbe615c8ea7b3402960f6372ea7d65faf376c14"}, + {file = "mypy-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:361da43c4f5a96173220eb53340ace68cda81845cd88218f8862dfb0adc8cddb"}, + {file = "mypy-1.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:330857f9507c24de5c5724235e66858f8364a0693894342485e543f5b07c8693"}, + {file = "mypy-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:c543214ffdd422623e9fedd0869166c2f16affe4ba37463975043ef7d2ea8770"}, + {file = "mypy-1.5.1-py3-none-any.whl", hash = "sha256:f757063a83970d67c444f6e01d9550a7402322af3557ce7630d3c957386fa8f5"}, + {file = "mypy-1.5.1.tar.gz", hash = "sha256:b031b9601f1060bf1281feab89697324726ba0c0bae9d7cd7ab4b690940f0b92"}, ] [package.dependencies] @@ -4957,7 +4958,6 @@ typing-extensions = ">=4.1.0" [package.extras] dmypy = ["psutil (>=4.0)"] install-types = ["pip"] -python2 = ["typed-ast (>=1.4.0,<2)"] reports = ["lxml"] [[package]] @@ -8145,7 +8145,7 @@ files = [ name = "ruff" version = "0.0.285" description = "An extremely fast Python linter, written in Rust." -category = "main" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -10936,4 +10936,4 @@ optimization = ["Riskfolio-Lib"] [metadata] lock-version = "2.0" python-versions = "^3.8.1,<3.11, !=3.9.7" -content-hash = "3758e48ae4cb9a6e0b8230c499e52258247407589475577994761c1141fea600" +content-hash = "bfe9e3f9163a60635a3d4e1b100992d34f0c50de66b2bc2c6e47ff79376aa207" diff --git a/pyproject.toml b/pyproject.toml index 970b91090a5f..8d4a939f29cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -122,8 +122,6 @@ ffn = "0.3.6" jupyter-client = "7.4.1" jupyter-server = "1.23.6" python-jose = "^3.3.0" -ruff = "0.0.285" - [tool.poetry.extras] @@ -138,7 +136,6 @@ doc = ["docstring-parser"] pytest-xdist = "^3.2.0" pytest = "^6.2.2" pylint = "2.17.0" -mypy = "^1.1.1" mock = "^4.0.3" codespell = "^2.2.4" pydocstyle = "^6.3.0" @@ -162,6 +159,8 @@ nbmake = ">0.5.0" pytest-timeout = "^2.1.0" pytest-recorder = "^0.2.1" freezegun = "^1.2.2" +ruff = "^0.0.285" +mypy = "^1.5.1" [build-system] requires = ["setuptools<65.5.0", "poetry-core>=1.0.0"] From e814a15820d262427d730a0a3e18d8f8cd9631ec Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 09:23:52 -0400 Subject: [PATCH 08/20] Updated some stuff --- openbb_terminal/core/sdk/sdk_init.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/openbb_terminal/core/sdk/sdk_init.py b/openbb_terminal/core/sdk/sdk_init.py index 546a674331bf..e075c597bb22 100644 --- a/openbb_terminal/core/sdk/sdk_init.py +++ b/openbb_terminal/core/sdk/sdk_init.py @@ -1,12 +1,6 @@ -# flake8: noqa pylint: disable=R0402,C0412,unused-import - - +# flake8: pylint: disable=R0402,C0412,unused-import # noqa: F401 - -# Session - - # Alternative import openbb_terminal.alternative.hackernews_model as alt_hackernews_model import openbb_terminal.alternative.hackernews_view as alt_hackernews_view @@ -169,8 +163,6 @@ ethgasstation_view as crypto_onchain_ethgasstation_view, ethplorer_model as crypto_onchain_ethplorer_model, ethplorer_view as crypto_onchain_ethplorer_view, - whale_alert_model as crypto_onchain_whale_alert_model, - whale_alert_view as crypto_onchain_whale_alert_view, topledger_model as crypto_onchain_topledger_model, topledger_view as crypto_onchain_topledger_view, whale_alert_model as crypto_onchain_whale_alert_model, From fefb3e63d7a069949bcf214022b35b0cd11056af Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 10:04:24 -0400 Subject: [PATCH 09/20] A lot more ruff fixes --- openbb_terminal/common/news_sdk_helper.py | 3 ++- .../integration_test_coverage.py | 11 +++++------ .../core/log/collection/s3_sender.py | 4 ++-- openbb_terminal/core/log/generation/common.py | 7 ++----- .../core/log/generation/expired_files.py | 6 +++--- .../generation/path_tracking_file_handler.py | 6 +++--- openbb_terminal/core/plots/plotly_helper.py | 9 ++++----- .../core/session/session_controller.py | 2 +- .../onchain/onchain_controller.py | 2 +- .../overview/pycoingecko_model.py | 6 +++--- openbb_terminal/forecast/whisper_model.py | 19 +++++++++---------- openbb_terminal/keys_model.py | 8 ++++---- .../gpt_index/generate_gpt_index.py | 10 +++++----- .../portfolio/brokers/degiro/degiro_model.py | 7 ++----- .../parameters/params_controller.py | 6 +++--- openbb_terminal/terminal_controller.py | 9 +++------ openbb_terminal/thought_of_the_day.py | 4 +++- pyproject.toml | 3 +-- .../account/test_account_controller.py | 10 +++++----- .../core/log/collection/test_s3_sender.py | 10 +++++----- tests/openbb_terminal/core/log/conftest.py | 2 +- .../test_path_tracking_file_handler.py | 2 +- .../core/log/generation/test_settings.py | 4 ++-- .../session/test_session_model.py | 2 +- tests/openbb_terminal/session/test_user.py | 4 ++-- tests/openbb_terminal/test_loggers.py | 2 +- website/controller_doc_classes.py | 9 ++++----- 27 files changed, 78 insertions(+), 89 deletions(-) diff --git a/openbb_terminal/common/news_sdk_helper.py b/openbb_terminal/common/news_sdk_helper.py index 512c5edc5a86..8e1346e2029f 100644 --- a/openbb_terminal/common/news_sdk_helper.py +++ b/openbb_terminal/common/news_sdk_helper.py @@ -30,7 +30,8 @@ def news(term: str = "", sources: str = "", tag="", source="") -> pd.DataFrame: else: # Use biztoc if token is provided provider = "feedparser" - if get_current_user().credentials.API_BIZTOC_TOKEN != "REPLACE_ME": + biztoc_token = get_current_user().credentials.API_BIZTOC_TOKEN + if biztoc_token != "REPLACE_ME": # noqa: S105 provider = "biztoc" if provider == "feedparser": diff --git a/openbb_terminal/core/integration_tests/integration_test_coverage.py b/openbb_terminal/core/integration_tests/integration_test_coverage.py index ef9dcffd7c66..43970a708593 100644 --- a/openbb_terminal/core/integration_tests/integration_test_coverage.py +++ b/openbb_terminal/core/integration_tests/integration_test_coverage.py @@ -1,6 +1,7 @@ """Obtain the integration test coverage for the OpenBB Terminal.""" # IMPORT STANDARD +import contextlib import importlib import json import os @@ -170,10 +171,9 @@ def get_commands_and_params( for command in commands: params[command] = [] - try: + with contextlib.suppress(AttributeError): params[command] = list(module_data[command].keys()) - except AttributeError: - pass + if get_commands and get_params: return commands, params @@ -277,10 +277,9 @@ def get_missing_params( for param in value: for param2 in value: if param != param2 and param2.startswith(param): - try: + with contextlib.suppress(ValueError): missing_params[key].remove(param) - except ValueError: - pass + missing_params = {k: v for k, v in missing_params.items() if v} diff --git a/openbb_terminal/core/log/collection/s3_sender.py b/openbb_terminal/core/log/collection/s3_sender.py index b3c1e2c51057..4809dfcbd83a 100644 --- a/openbb_terminal/core/log/collection/s3_sender.py +++ b/openbb_terminal/core/log/collection/s3_sender.py @@ -119,8 +119,8 @@ def send_to_s3( if ( not last - and aws_settings.aws_access_key_id != "REPLACE_ME" - and aws_settings.aws_secret_access_key != "REPLACE_ME" + and aws_settings.aws_access_key_id != "REPLACE_ME" # noqa: S105 + and aws_settings.aws_secret_access_key != "REPLACE_ME" # noqa: S105 ): send_to_s3_directly( aws_access_key_id=aws_settings.aws_access_key_id, diff --git a/openbb_terminal/core/log/generation/common.py b/openbb_terminal/core/log/generation/common.py index d67c9b5df646..cdfde6f8c1b7 100644 --- a/openbb_terminal/core/log/generation/common.py +++ b/openbb_terminal/core/log/generation/common.py @@ -1,4 +1,5 @@ # IMPORTATION STANDARD +import contextlib import logging # IMPORTATION THIRDPARTY @@ -10,11 +11,7 @@ def do_rollover(): """RollOver the log file.""" - for handler in logging.getLogger().handlers: if isinstance(handler, PathTrackingFileHandler): - try: + with contextlib.suppress(PermissionError): handler.doRollover() - # IGNORE PermissionError : WINDOWS FILE OPEN - except PermissionError: - pass diff --git a/openbb_terminal/core/log/generation/expired_files.py b/openbb_terminal/core/log/generation/expired_files.py index c32620c0ee2c..a214f4b17aca 100644 --- a/openbb_terminal/core/log/generation/expired_files.py +++ b/openbb_terminal/core/log/generation/expired_files.py @@ -1,4 +1,5 @@ # IMPORTATION STANDARD +import contextlib from datetime import datetime from pathlib import Path from typing import List @@ -25,7 +26,6 @@ def get_expired_file_list(directory: Path, before_timestamp: float) -> List[Path def remove_file_list(file_list: List[Path]): for file in file_list: - try: + with contextlib.suppress(PermissionError): file.unlink(missing_ok=True) - except PermissionError: - pass + diff --git a/openbb_terminal/core/log/generation/path_tracking_file_handler.py b/openbb_terminal/core/log/generation/path_tracking_file_handler.py index 5cdf91556041..478b2df54a3c 100644 --- a/openbb_terminal/core/log/generation/path_tracking_file_handler.py +++ b/openbb_terminal/core/log/generation/path_tracking_file_handler.py @@ -1,4 +1,5 @@ # IMPORTATION STANDARD +import contextlib from copy import deepcopy from logging.handlers import TimedRotatingFileHandler from pathlib import Path @@ -184,10 +185,9 @@ def close(self): if log_sender.check_sending_conditions(file=closed_log_path): log_sender.send_path(path=closed_log_path, last=True) - try: + with contextlib.suppress(Exception): log_sender.join(timeout=3) - except Exception: # noqa: S110 - pass + super().close() diff --git a/openbb_terminal/core/plots/plotly_helper.py b/openbb_terminal/core/plots/plotly_helper.py index 993a6dcff6a0..2546a75f6b3f 100644 --- a/openbb_terminal/core/plots/plotly_helper.py +++ b/openbb_terminal/core/plots/plotly_helper.py @@ -1,5 +1,6 @@ """Chart and style helpers for Plotly.""" # pylint: disable=C0302,R0902,W3301 +import contextlib import json import sys import textwrap @@ -42,11 +43,9 @@ from openbb_terminal.core.session.current_user import get_current_user if TYPE_CHECKING: - try: - # pylint: disable=W0611 # noqa: F401 - from darts import TimeSeries - except ImportError: - pass + with contextlib.suppress(ImportError): + from darts import TimeSeries # pylint: disable=W0611 # noqa: F401 + TimeSeriesT = TypeVar("TimeSeriesT", bound="TimeSeries") diff --git a/openbb_terminal/core/session/session_controller.py b/openbb_terminal/core/session/session_controller.py index 6d26fb297849..ecc4118cc09b 100644 --- a/openbb_terminal/core/session/session_controller.py +++ b/openbb_terminal/core/session/session_controller.py @@ -94,7 +94,7 @@ def pywry_login(welcome: bool = True): if isinstance(response, dict) and response: console.print("\n[info]Logging in... Please wait.[/info]\n") - response["token_type"] = "bearer" + response["token_type"] = "bearer" # noqa: S105 for r_key, new_key in zip( ["status", "accessToken", "primaryUsage"], diff --git a/openbb_terminal/cryptocurrency/onchain/onchain_controller.py b/openbb_terminal/cryptocurrency/onchain/onchain_controller.py index 083fed888d7e..94eb9d6b330f 100644 --- a/openbb_terminal/cryptocurrency/onchain/onchain_controller.py +++ b/openbb_terminal/cryptocurrency/onchain/onchain_controller.py @@ -1460,7 +1460,7 @@ def call_baas(self, other_args: List[str]): else: console.print(f"Coin '{ns_parser.coin}' does not exist.") if ns_parser.coin.upper() == "BTC": - token = "WBTC" + token = "WBTC" # noqa: S105 else: similar_cmd = difflib.get_close_matches( ns_parser.coin, diff --git a/openbb_terminal/cryptocurrency/overview/pycoingecko_model.py b/openbb_terminal/cryptocurrency/overview/pycoingecko_model.py index 0c240a8fd1a8..db31c7ae7541 100644 --- a/openbb_terminal/cryptocurrency/overview/pycoingecko_model.py +++ b/openbb_terminal/cryptocurrency/overview/pycoingecko_model.py @@ -4,6 +4,7 @@ # pylint: disable=C0301, E1101 # pylint: disable=unsupported-assignment-operation +import contextlib import logging import re from typing import List, Union @@ -516,10 +517,9 @@ def get_global_defi_info() -> pd.DataFrame: client = CoinGeckoAPI() results = client.get_global_decentralized_finance_defi() for key, value in results.items(): - try: + with contextlib.suppress(ValueError, TypeError): results[key] = round(float(value), 4) - except (ValueError, TypeError): - pass + df = pd.Series(results).reset_index() df.columns = ["Metric", "Value"] diff --git a/openbb_terminal/forecast/whisper_model.py b/openbb_terminal/forecast/whisper_model.py index 2820eead25cf..302287719eca 100644 --- a/openbb_terminal/forecast/whisper_model.py +++ b/openbb_terminal/forecast/whisper_model.py @@ -165,16 +165,15 @@ def transcribe_and_summarize( os.makedirs(whisper_cache_dir, exist_ok=True) - if model_name in ["small", "small.en"]: - model_size = "483.6 MB" - elif model_name in ["tiny", "tiny.en"]: - model_size = "75.6 MB" - elif model_name in ["base", "base.en"]: - model_size = "145.3 MB" - elif model_name in ["medium", "medium.en"]: - model_size = "1.53 GB" - elif model_name in ["large", "large-v2", "large-v1"]: - model_size = "2.87 GB" + sizes = { + "small": "483.6 MB", + "tiny": "75.6 MB", + "base": "145.3 MB", + "medium": "1.53 GB", + "large": "2.87 GB", + } + clean_key = model_name.replace(".en", "").replace("-v2", "").replace("-v1", "") + model_size = sizes[clean_key] full_model_name = model_name + ".en.pt" if language == "en" else model_name + ".pt" if full_model_name not in os.listdir(whisper_cache_dir): diff --git a/openbb_terminal/keys_model.py b/openbb_terminal/keys_model.py index 5fca523ba789..a3f40a9c8469 100644 --- a/openbb_terminal/keys_model.py +++ b/openbb_terminal/keys_model.py @@ -658,7 +658,7 @@ def check_news_key(show_output: bool = False) -> str: current_user = get_current_user() - if current_user.credentials.API_NEWS_TOKEN == "REPLACE_ME": # nosec + if current_user.credentials.API_NEWS_TOKEN == "REPLACE_ME": # nosec# noqa: S105 status = KeyStatus.NOT_DEFINED else: r = request( @@ -727,7 +727,7 @@ def check_biztoc_key(show_output: bool = False) -> str: current_user = get_current_user() - if current_user.credentials.API_BIZTOC_TOKEN == "REPLACE_ME": # nosec + if current_user.credentials.API_BIZTOC_TOKEN == "REPLACE_ME": # nosec# noqa: S105 status = KeyStatus.NOT_DEFINED else: r = request( @@ -800,7 +800,7 @@ def check_tradier_key(show_output: bool = False) -> str: current_user = get_current_user() - if current_user.credentials.API_TRADIER_TOKEN == "REPLACE_ME": # nosec + if current_user.credentials.API_TRADIER_TOKEN == "REPLACE_ME": # nosec# noqa: S105 status = KeyStatus.NOT_DEFINED else: r = request( @@ -2386,7 +2386,7 @@ def check_tokenterminal_key(show_output: bool = False) -> str: current_user = get_current_user() - if current_user.credentials.API_TOKEN_TERMINAL_KEY == "REPLACE_ME": + if current_user.credentials.API_TOKEN_TERMINAL_KEY == "REPLACE_ME": # noqa: S105 status = KeyStatus.NOT_DEFINED else: token_terminal = TokenTerminal( diff --git a/openbb_terminal/miscellaneous/gpt_index/generate_gpt_index.py b/openbb_terminal/miscellaneous/gpt_index/generate_gpt_index.py index d48d72460f56..0da4c651afbe 100644 --- a/openbb_terminal/miscellaneous/gpt_index/generate_gpt_index.py +++ b/openbb_terminal/miscellaneous/gpt_index/generate_gpt_index.py @@ -82,7 +82,7 @@ def process_cmd_parsers(ctrl: ControllerDoc) -> List[Dict[str, str]]: elif isinstance(default, datetime): if "start" in action.dest: - random_int = random.randint(1, 365) + random_int = random.randint(1, 365) # noqa: S311 default = ( datetime.now() - timedelta(days=random_int) ).strftime("%Y-%m-%d") @@ -133,9 +133,9 @@ def process_cmd_parsers(ctrl: ControllerDoc) -> List[Dict[str, str]]: if action.type is bool: default = "" elif action.type is int: - default = random.randint(1, 100) + default = random.randint(1, 100) # noqa: S311 elif action.type is float: - default = random.uniform(1, 100) + default = random.uniform(1, 100) # noqa: S311 else: default = "None" @@ -211,7 +211,7 @@ def get_examples( example += f" {flag}" break if param["choices"]: # type: ignore - example += f" {random.choice(choices_type(param['choices']))}" # type: ignore + example += f" {random.choice(choices_type(param['choices']))}" # type: ignore # noqa: S311 elif param["default"]: # type: ignore default = param["default"] # type: ignore if default in ["False", "True"]: @@ -225,7 +225,7 @@ def get_examples( example += f" {flag}" break if param["choices"]: # type: ignore - example += f" {random.choice(choices_type(param['choices']))}" # type: ignore + example += f" {random.choice(choices_type(param['choices']))}" # type: ignore # noqa: S311 elif param["default"]: # type: ignore default = param["default"] # type: ignore if default in ["False", "True"]: diff --git a/openbb_terminal/portfolio/brokers/degiro/degiro_model.py b/openbb_terminal/portfolio/brokers/degiro/degiro_model.py index 8af26c2040b7..11d736742c03 100644 --- a/openbb_terminal/portfolio/brokers/degiro/degiro_model.py +++ b/openbb_terminal/portfolio/brokers/degiro/degiro_model.py @@ -48,11 +48,8 @@ def get_default_credentials(self): Credentials: credentials object with default settings """ current_user = get_current_user() - totp_secret_key = ( - None - if current_user.credentials.DG_TOTP_SECRET == "REPLACE_ME" - else current_user.credentials.DG_TOTP_SECRET - ) + topt_key = current_user.credentials.DG_TOTP_SECRET + totp_secret_key = None if topt_key == "REPLACE_ME" else topt_key return Credentials( int_account=None, diff --git a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py index 9d3d7059d8b5..b7f0723541a3 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py +++ b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py @@ -4,6 +4,7 @@ # pylint: disable=C0302, no-else-return import argparse +import contextlib import logging from typing import List, Optional @@ -311,10 +312,9 @@ def call_arg(self, other_args: List[str]): "[red]The parameter you are trying to access is unused in this model.[/red]\n" ) - try: + with contextlib.suppress(ValueError): value = float(value) - except ValueError: - pass + if argument == "historic_period": for option in AVAILABLE_OPTIONS[argument]: diff --git a/openbb_terminal/terminal_controller.py b/openbb_terminal/terminal_controller.py index ef722e6f8bda..5c9c5972da71 100644 --- a/openbb_terminal/terminal_controller.py +++ b/openbb_terminal/terminal_controller.py @@ -395,7 +395,7 @@ def call_guess(self, other_args: List[str]) -> None: # Load the file as a JSON document json_doc = json.load(f) - task = random.choice(list(json_doc.keys())) # nosec + task = random.choice(list(json_doc.keys())) # nosec # noqa: S311 solution = json_doc[task] start = time.time() @@ -827,12 +827,9 @@ def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): welcome_message() if first_time_user(): - try: - # t_controller.call_intro(None) + with contextlib.suppress(EOFError): webbrowser.open("https://docs.openbb.co/terminal/usage/basics") - # TDDO: Fix the CI - except EOFError: - pass + t_controller.print_help() check_for_updates() diff --git a/openbb_terminal/thought_of_the_day.py b/openbb_terminal/thought_of_the_day.py index 66361cf3f413..54b81fd0ceeb 100644 --- a/openbb_terminal/thought_of_the_day.py +++ b/openbb_terminal/thought_of_the_day.py @@ -134,7 +134,9 @@ def get_thought_of_the_day(): console.print("Thought of the day:") console.print( - totd.quote_to_str(quotes[random.randint(0, len(quotes) - 1)]) # nosec + totd.quote_to_str( + quotes[random.randint(0, len(quotes) - 1)] # nosec # noqa: S311 + ) ) console.print("\n") diff --git a/pyproject.toml b/pyproject.toml index 8d4a939f29cd..30e8abaa4990 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -180,8 +180,7 @@ target-version = "py38" # All options here: https://github.com/charliermarsh/ruff#supported-rules select = ["E", "W", "F", "Q", "S", "UP", "I", "PLC", "PLE", "PLR", "PLW", "SIM"] # These ignores should be seen as temporary solutions to problems that will NEED fixed -# Ignores that can be removed easily: PLR0912 -ignore = ["S105", "S106", "PLR2004", "PLR0913", "PLR0915", "SIM105", "PLR0912", "S311"] +ignore = ["PLR2004", "PLR0913", "PLR0915"] [tool.ruff.per-file-ignores] "tests/*" = ["S101"] diff --git a/tests/openbb_terminal/account/test_account_controller.py b/tests/openbb_terminal/account/test_account_controller.py index 5dbbaa7ba5c4..59bd181ed58d 100644 --- a/tests/openbb_terminal/account/test_account_controller.py +++ b/tests/openbb_terminal/account/test_account_controller.py @@ -106,7 +106,10 @@ def fixture_test_user(mocker): credentials=CredentialsModel(), preferences=PreferencesModel(), profile=ProfileModel( - token_type="Bearer", token="123", uuid="00001", email="test@email.com" + token_type="Bearer", # noqa: S106 + token="123", # noqa: S106 + uuid="00001", + email="test@email.com", ), sources=SourcesModel(), ) @@ -502,10 +505,7 @@ def test_call_delete(mocker, monkeypatch, test_user): controller = account_controller.AccountController(queue=None) path_controller = "openbb_terminal.account.account_controller" - profile = ProfileModel( - token_type="Bearer", - token="123", - ) + profile = ProfileModel(token_type="Bearer", token="123") # noqa: S106 mock_current_user = copy_user(user=test_user, profile=profile) mocker.patch( target="openbb_terminal.core.session.current_user.__current_user", diff --git a/tests/openbb_terminal/core/log/collection/test_s3_sender.py b/tests/openbb_terminal/core/log/collection/test_s3_sender.py index e9a8cc00cf2e..63786500196c 100644 --- a/tests/openbb_terminal/core/log/collection/test_s3_sender.py +++ b/tests/openbb_terminal/core/log/collection/test_s3_sender.py @@ -23,7 +23,7 @@ def test_send_to_s3_directly(mocker): ) aws_access_key_id = "MOCK_ACCESS_KEY_ID" - aws_secret_access_key = "MOCK_ACCESS_SECRET_KEY" + aws_secret_access_key = "MOCK_ACCESS_SECRET_KEY" # noqa: S105 bucket = "MOCK_BUCKET" file = Path(__file__) object_key = "MOCK_S3/OBJECT_KEY" @@ -47,7 +47,7 @@ def test_send_to_s3_directly_exception(mocker): ) aws_access_key_id = "MOCK_ACCESS_KEY_ID" - aws_secret_access_key = "MOCK_ACCESS_SECRET_KEY" + aws_secret_access_key = "MOCK_ACCESS_SECRET_KEY" # noqa: S105 bucket = "MOCK_BUCKET" file = Path(__file__) object_key = "MOCK_S3/OBJECT_KEY" @@ -97,14 +97,14 @@ def test_send_to_s3_using_presigned_url(mocker, tmp_path): ( AWSSettings( aws_access_key_id="MOCK_AWS_ACCESS_KEY_ID", - aws_secret_access_key="MOCK_AWS_ACCESS_KEY", + aws_secret_access_key="MOCK_AWS_ACCESS_KEY", # noqa: S106 ), False, ), ( AWSSettings( aws_access_key_id="REPLACE_ME", - aws_secret_access_key="REPLACE_ME", + aws_secret_access_key="REPLACE_ME", # noqa: S106 ), True, ), @@ -160,7 +160,7 @@ def test_send_to_s3_exception(mocker, tmp_path): archives_file=archives_file, aws_settings=AWSSettings( aws_access_key_id="REPLACE_ME", - aws_secret_access_key="REPLACE_ME", + aws_secret_access_key="REPLACE_ME", # noqa: S106 ), file=file, object_key=object_key, diff --git a/tests/openbb_terminal/core/log/conftest.py b/tests/openbb_terminal/core/log/conftest.py index f79043b59af7..c5fd6cc3d01b 100644 --- a/tests/openbb_terminal/core/log/conftest.py +++ b/tests/openbb_terminal/core/log/conftest.py @@ -20,7 +20,7 @@ def settings(tmp_path): ), aws_settings=AWSSettings( aws_access_key_id="MOCK_AWS_ACCESS_KEY_ID", - aws_secret_access_key="MOCK_AWS_ACCESS_KEY", # pragma: allowlist secret + aws_secret_access_key="MOCK_AWS_ACCESS_KEY", # pragma: allowlist secret # noqa: S106 ), log_settings=LogSettings( directory=tmp_path, diff --git a/tests/openbb_terminal/core/log/generation/test_path_tracking_file_handler.py b/tests/openbb_terminal/core/log/generation/test_path_tracking_file_handler.py index fc3da4653a78..91bf94b9c3f8 100644 --- a/tests/openbb_terminal/core/log/generation/test_path_tracking_file_handler.py +++ b/tests/openbb_terminal/core/log/generation/test_path_tracking_file_handler.py @@ -8,7 +8,7 @@ PathTrackingFileHandler, ) -randint = random.randint(0, 999999999) +randint = random.randint(0, 999999999) # noqa: S311 def return_list(**_): diff --git a/tests/openbb_terminal/core/log/generation/test_settings.py b/tests/openbb_terminal/core/log/generation/test_settings.py index 0c5ae369c292..89eca43eb190 100644 --- a/tests/openbb_terminal/core/log/generation/test_settings.py +++ b/tests/openbb_terminal/core/log/generation/test_settings.py @@ -8,7 +8,7 @@ def test_aws_settings(): aws_access_key_id = "MOCK_AWS_ACCESS_KEY_ID" - aws_secret_access_key = "MOCK_AWS_SECRET_ACCESS_KEY" + aws_secret_access_key = "MOCK_AWS_SECRET_ACCESS_KEY" # noqa: S105 aws_settings = AWSSettings( aws_access_key_id=aws_access_key_id, @@ -90,7 +90,7 @@ def test_settings(tmp_path): ) aws_access_key_id = "MOCK_AWS_ACCESS_KEY_ID" - aws_secret_access_key = "MOCK_AWS_SECRET_ACCESS_KEY" + aws_secret_access_key = "MOCK_AWS_SECRET_ACCESS_KEY" # noqa: S105 aws_settings = AWSSettings( aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, diff --git a/tests/openbb_terminal/session/test_session_model.py b/tests/openbb_terminal/session/test_session_model.py index 138c9af8a6ff..a54263958dc4 100644 --- a/tests/openbb_terminal/session/test_session_model.py +++ b/tests/openbb_terminal/session/test_session_model.py @@ -147,7 +147,7 @@ def test_logout_user(mocker, guest): mock_plt_close = mocker.patch(path + "plt.close") auth_header = "Bearer test_token" - token = "test_token" + token = "test_token" # noqa: S105 base_url = "https://payments.openbb.co/" session_model.logout(auth_header, token) diff --git a/tests/openbb_terminal/session/test_user.py b/tests/openbb_terminal/session/test_user.py index 656d17c28385..abd9b5325e09 100644 --- a/tests/openbb_terminal/session/test_user.py +++ b/tests/openbb_terminal/session/test_user.py @@ -35,8 +35,8 @@ def fixture_test_user(): def test_load_user_info(test_user): """Test load user info.""" - assert test_user.profile.token == "test_token" - assert test_user.profile.token_type == "bearer" + assert test_user.profile.token == "test_token" # noqa: S105 + assert test_user.profile.token_type == "bearer" # noqa: S105 assert test_user.profile.uuid == "test_uuid" assert test_user.profile.email == "test@email.com" assert test_user.profile.remember is False diff --git a/tests/openbb_terminal/test_loggers.py b/tests/openbb_terminal/test_loggers.py index 05d6643c5ab5..cb514673dacd 100644 --- a/tests/openbb_terminal/test_loggers.py +++ b/tests/openbb_terminal/test_loggers.py @@ -20,7 +20,7 @@ ), aws_settings=AWSSettings( aws_access_key_id="MOCK_AWS_ACCESS_KEY_ID", - aws_secret_access_key="MOCK_AWS", # pragma: allowlist secret + aws_secret_access_key="MOCK_AWS", # pragma: allowlist secret # noqa: S106 ), log_settings=LogSettings( directory=Path("."), diff --git a/website/controller_doc_classes.py b/website/controller_doc_classes.py index db5efb037d2e..b0d4894af029 100644 --- a/website/controller_doc_classes.py +++ b/website/controller_doc_classes.py @@ -1,5 +1,6 @@ # pylint: disable=unused-argument import argparse +import contextlib import inspect import sys from datetime import datetime, timedelta @@ -370,11 +371,9 @@ def mock_func(fparser: argparse.ArgumentParser, *args, **kwargs): if len(fullspec.args) > 2: args.update({arg: ["1234"] for arg in fullspec.args[2:]}) - with patch("openbb_terminal.rich_config.console.print"): - try: - _ = getattr(self.controller, command)(["--help"], **args) - except (SystemExit, AttributeError): - pass + with patch("openbb_terminal.rich_config.console.print"), contextlib.suppress(SystemExit, AttributeError): + _ = getattr(self.controller, command)(["--help"], **args) + except Exception as e: print(e) From 10e9cc3389d2dcf9ed0690a09df6d7d4e147cd6d Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 11:12:16 -0400 Subject: [PATCH 10/20] Added a fix --- openbb_terminal/forecast/whisper_model.py | 31 +++--- .../yahoo_finance_model.py | 20 +--- openbb_terminal/routine_functions.py | 2 +- .../stocks/options/options_chains_model.py | 75 ++++---------- openbb_terminal/stocks/stocks_helper.py | 98 ++++++++----------- openbb_terminal/terminal_controller.py | 67 +++++++------ 6 files changed, 119 insertions(+), 174 deletions(-) diff --git a/openbb_terminal/forecast/whisper_model.py b/openbb_terminal/forecast/whisper_model.py index 302287719eca..0f9fe4297de8 100644 --- a/openbb_terminal/forecast/whisper_model.py +++ b/openbb_terminal/forecast/whisper_model.py @@ -278,22 +278,9 @@ def transcribe_and_summarize( negative_score += chunk_sentiment_score * len(chunk) total_length += len(chunk) - # calculate overall sentiment score - if total_length > 0: - positive_percent = positive_score / total_length * 100 - negative_percent = negative_score / total_length * 100 - if positive_percent > 70: - overall_sentiment_label = "POSITIVE" - overall_sentiment_score = positive_percent - elif negative_percent > 70: - overall_sentiment_label = "NEGATIVE" - overall_sentiment_score = negative_percent - else: - overall_sentiment_label = "NEUTRAL" - overall_sentiment_score = (positive_percent + negative_percent) / 2 - else: - overall_sentiment_label = "NEUTRAL" - overall_sentiment_score = 0.0 + overall_sentiment_label, overall_sentiment_score = get_sentiment_score( + total_length, positive_score, negative_score + ) # Write summary and get reduction summary_text_length = len(summary_text) @@ -338,3 +325,15 @@ def transcribe_and_summarize( summary_path = os.path.join(output_dir, f"{slugify(title)}_summary.txt") with open(summary_path, "w") as f: f.write(summary_text) + + +def get_sentiment_score(total_length, positive_score, negative_score): + if total_length > 0: + positive_percent = positive_score / total_length * 100 + negative_percent = negative_score / total_length * 100 + if positive_percent > 70: + return "POSITIVE", positive_percent + elif negative_percent > 70: + return "NEGATIVE", negative_percent + return "NEUTRAL", (positive_percent + negative_percent) / 2 + return "NEUTRAL", 0.0 diff --git a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py index e1abd5aaf919..42ddc99f8963 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py +++ b/openbb_terminal/portfolio/portfolio_optimization/yahoo_finance_model.py @@ -236,22 +236,12 @@ def process_stocks( end_ = date.today() if end_.weekday() >= 5: end_ = end_ + relativedelta(weekday=FR(-1)) - if interval.find("d") >= 1: - days = int(interval[:-1]) - start_ = end_ - relativedelta(days=days) - elif interval.find("w") >= 1: - weeks = int(interval[:-1]) - start_ = end_ - relativedelta(weeks=weeks) - elif interval.find("mo") >= 1: - months = int(interval[:-2]) - start_ = end_ - relativedelta(months=months) - elif interval.find("y") >= 1: - years = int(interval[:-1]) - start_ = end_ - relativedelta(years=years) + for item in ["d", "w", "mo", "y"]: + if interval.find(item) >= 1: + n = int(interval[: -len(item)]) + start_ = end_ - relativedelta(days=n) + break else: - # console.print( - # "Please use an adequate interval." - # ) return None start_date = start_.strftime("%Y-%m-%d") diff --git a/openbb_terminal/routine_functions.py b/openbb_terminal/routine_functions.py index ea1c50e4a92a..a05b0e126629 100644 --- a/openbb_terminal/routine_functions.py +++ b/openbb_terminal/routine_functions.py @@ -141,7 +141,7 @@ def match_and_return_openbb_keyword_date(keyword: str) -> str: return "" -def parse_openbb_script( # noqa: PLR0911 +def parse_openbb_script( # noqa: PLR0911,PLR0912 raw_lines: List[str], script_inputs: Optional[List[str]] = None, ) -> Tuple[str, str]: diff --git a/openbb_terminal/stocks/options/options_chains_model.py b/openbb_terminal/stocks/options/options_chains_model.py index 8549776ab4ea..a0299cf1b435 100644 --- a/openbb_terminal/stocks/options/options_chains_model.py +++ b/openbb_terminal/stocks/options/options_chains_model.py @@ -178,8 +178,7 @@ def validate_object( # noqa: PLR0911 scopes = ["chains", "object", "strategies", "nonZeroPrices"] - if scope == "": - scope = "chains" + scope = scope or "chains" if scope not in scopes: print("Invalid choice. The supported methods are:", scopes) @@ -1463,6 +1462,10 @@ def get_strategies( ) """ + def to_clean_list(x): + if x is not None: + return [x] if not isinstance(x, list) else x + options = deepcopy(options) if validate_object(options, scope="object") is False: @@ -1472,14 +1475,14 @@ def get_strategies( print("`last_price` was not found in the Options data object.") return pd.DataFrame() - if isinstance(options.chains, dict): - options.chains = pd.DataFrame(options.chains) - - if strangle_moneyness is None: - strangle_moneyness = [0.0] + options.chains = ( + pd.DataFrame(options.chains) + if isinstance(options.chains, dict) + else options.chains + ) - if days is None: - days = options.chains["dte"].unique().tolist() + strangle_moneyness = strangle_moneyness or [0.0] + days = days or options.chains["dte"].unique().tolist() # Allows a single input to be passed instead of a list. days = [days] if isinstance(days, int) else days # type: ignore[list-item] @@ -1495,26 +1498,9 @@ def get_strategies( ) return pd.DataFrame() - if strangle_moneyness is not None: - strangle_moneyness = ( - [strangle_moneyness] # type: ignore[list-item] - if not isinstance(strangle_moneyness, list) - else strangle_moneyness - ) - - if synthetic_longs is not None: - synthetic_longs = ( - [synthetic_longs] # type: ignore[list-item] - if not isinstance(synthetic_longs, list) - else synthetic_longs - ) - - if synthetic_shorts is not None: - synthetic_shorts = ( - [synthetic_shorts] # type: ignore[list-item] - if not isinstance(synthetic_shorts, list) - else synthetic_shorts - ) + strangle_moneyness = to_clean_list(strangle_moneyness) + synthetic_longs = to_clean_list(synthetic_longs) + synthetic_shorts = to_clean_list(synthetic_shorts) days_list = [] strategies = pd.DataFrame() @@ -1529,8 +1515,7 @@ def get_strategies( put_spreads = pd.DataFrame() for day in days: - if day == 0: - day = -1 # noqa: PLW2901 + day = day or -1 # noqa: PLW2901 days_list.append(get_nearest_dte(options, day)) days = list(set(days_list)) days.sort() @@ -1560,24 +1545,14 @@ def get_strategies( for day in days: straddle = calculate_straddle(options, day, straddle_strike).transpose() if straddle.iloc[0]["Cost"] != 0: - straddles = pd.concat( - [ - straddles, - straddle, - ] - ) + straddles = pd.concat([straddles, straddle]) if strangle_moneyness and strangle_moneyness[0] != 0: for day in days: for moneyness in strangle_moneyness: strangle = calculate_strangle(options, day, moneyness).transpose() if strangle.iloc[0]["Cost"] != 0: - strangles_ = pd.concat( - [ - strangles_, - strangle, - ] - ) + strangles_ = pd.concat([strangles_, strangle]) strangles = pd.concat([strangles, strangles_]) strangles = strangles.query("`Strike 1` != `Strike 2`").drop_duplicates() @@ -1590,12 +1565,7 @@ def get_strategies( options, day, strike ).transpose() if _synthetic_long.iloc[0]["Strike 1 Premium"] != 0: - _synthetic_longs = pd.concat( - [ - _synthetic_longs, - _synthetic_long, - ] - ) + _synthetic_longs = pd.concat([_synthetic_longs, _synthetic_long]) synthetic_longs_df = pd.concat([synthetic_longs_df, _synthetic_longs]) @@ -1607,12 +1577,7 @@ def get_strategies( options, day, strike ).transpose() if _synthetic_short.iloc[0]["Strike 1 Premium"] != 0: - _synthetic_shorts = pd.concat( - [ - _synthetic_shorts, - _synthetic_short, - ] - ) + _synthetic_shorts = pd.concat([_synthetic_shorts, _synthetic_short]) synthetic_shorts_df = pd.concat([synthetic_shorts_df, _synthetic_shorts]) diff --git a/openbb_terminal/stocks/stocks_helper.py b/openbb_terminal/stocks/stocks_helper.py index eaf83e79169c..b8aa62044fc7 100644 --- a/openbb_terminal/stocks/stocks_helper.py +++ b/openbb_terminal/stocks/stocks_helper.py @@ -232,7 +232,40 @@ def search( return df.reset_index() -def load( # pylint: disable=too-many-return-statements # noqa: PLR0911 +def get_daily_stock_candidate( + source: str, symbol: str, int_string: str, start_date, end_date, monthly, weekly +) -> pd.DataFrame: + if source == "AlphaVantage": + return load_stock_av(symbol, int_string, start_date, end_date) + + if source == "YahooFinance": + return load_stock_yf(symbol, start_date, end_date, weekly, monthly) + + if source == "EODHD": + try: + return load_stock_eodhd(symbol, start_date, end_date, weekly, monthly) + except KeyError: + console.print( + "[red]Invalid symbol for EODHD. Please check your subscription.[/red]\n" + ) + return pd.DataFrame() + + if source == "Polygon": + return load_stock_polygon(symbol, start_date, end_date, weekly, monthly) + + if source == "Intrinio": + return load_stock_intrinio(symbol, start_date, end_date, weekly, monthly) + + if source == "DataBento": + return databento_model.get_historical_stock( + symbol, start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d") + ) + + console.print("[red]Invalid source for stock[/red]\n") + return pd.DataFrame() + + +def load( symbol: str, start_date: Optional[Union[datetime, str]] = None, interval: int = 1440, @@ -298,65 +331,20 @@ def load( # pylint: disable=too-many-return-statements # noqa: PLR0911 df_stock_candidate: pd.DataFrame Dataframe of data """ - if start_date is None: - start_date = (datetime.now() - timedelta(days=1100)).strftime("%Y-%m-%d") - - if end_date is None: - end_date = datetime.now().strftime("%Y-%m-%d") - + start_date = start_date or (datetime.now() - timedelta(days=1100)).strftime( + "%Y-%m-%d" + ) + end_date = end_date or datetime.now().strftime("%Y-%m-%d") start_date = check_datetime(start_date) end_date = check_datetime(end_date, start=False) - int_string = "Daily" - if weekly: - int_string = "Weekly" - if monthly: - int_string = "Monthly" + + int_string = "Weekly" if weekly else "Monthly" if monthly else "Daily" # Daily if int(interval) == 1440: - if source == "AlphaVantage": - df_stock_candidate: pd.DataFrame = load_stock_av( - symbol, int_string, start_date, end_date - ) - - elif source == "YahooFinance": - df_stock_candidate = load_stock_yf( - symbol, start_date, end_date, weekly, monthly - ) - - elif source == "EODHD": - try: - df_stock_candidate = load_stock_eodhd( - symbol, - start_date, - end_date, - weekly, - monthly, - ) - except KeyError: - console.print( - "[red]Invalid symbol for EODHD. Please check your subscription.[/red]\n" - ) - return pd.DataFrame() - - elif source == "Polygon": - df_stock_candidate = load_stock_polygon( - symbol, start_date, end_date, weekly, monthly - ) - - elif source == "Intrinio": - df_stock_candidate = load_stock_intrinio( - symbol, start_date, end_date, weekly, monthly - ) - - elif source == "DataBento": - df_stock_candidate = databento_model.get_historical_stock( - symbol, start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d") - ) - - else: - console.print("[red]Invalid source for stock[/red]\n") - return + df_stock_candidate = get_daily_stock_candidate( + source, symbol, int_string, start_date, end_date, monthly, weekly + ) is_df = isinstance(df_stock_candidate, pd.DataFrame) if (is_df and df_stock_candidate.empty) or ( not is_df and not df_stock_candidate diff --git a/openbb_terminal/terminal_controller.py b/openbb_terminal/terminal_controller.py index 5c9c5972da71..121f819768f9 100644 --- a/openbb_terminal/terminal_controller.py +++ b/openbb_terminal/terminal_controller.py @@ -14,7 +14,7 @@ import webbrowser from datetime import datetime from pathlib import Path -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Tuple import certifi import pandas as pd @@ -777,14 +777,11 @@ def call_exe(self, other_args: List[str]): self.queue = self.queue[1:] -# pylint: disable=global-statement -def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): - """Terminal Menu.""" - - current_user = get_current_user() - - log_terminal(test_mode=test_mode) - +def handle_export_and_cmds( + jobs_cmds: Optional[List[str]], +) -> Tuple[Optional[str], Optional[List[str]]]: + # If the path selected does not start from the user root, + # give relative location from terminal root if jobs_cmds is not None and jobs_cmds: logger.info("INPUT: %s", "/".join(jobs_cmds)) @@ -795,32 +792,39 @@ def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): if len(first_split) > 1: export_path = first_split[1] jobs_cmds = ["/".join(commands[1:])] + if not export_path: + return export_path, jobs_cmds + if export_path[0] == "~": + export_path = export_path.replace("~", HOME_DIRECTORY.as_posix()) + elif export_path[0] != "/": + export_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), export_path + ) + + # Check if the directory exists + if os.path.isdir(export_path): + console.print( + f"Export data to be saved in the selected folder: '{export_path}'" + ) + else: + os.makedirs(export_path) + console.print(f"[green]Folder '{export_path}' successfully created.[/green]") + set_preference("USER_EXPORTS_DIRECTORY", Path(export_path)) + return export_path, jobs_cmds + + +def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): + """Terminal Menu.""" + + current_user = get_current_user() + + log_terminal(test_mode=test_mode) ret_code = 1 t_controller = TerminalController(jobs_cmds) an_input = "" - if export_path: - # If the path selected does not start from the user root, - # give relative location from terminal root - if export_path[0] == "~": - export_path = export_path.replace("~", HOME_DIRECTORY.as_posix()) - elif export_path[0] != "/": - export_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), export_path - ) - - # Check if the directory exists - if os.path.isdir(export_path): - console.print( - f"Export data to be saved in the selected folder: '{export_path}'" - ) - else: - os.makedirs(export_path) - console.print( - f"[green]Folder '{export_path}' successfully created.[/green]" - ) - set_preference("USER_EXPORTS_DIRECTORY", Path(export_path)) + export_path, jobs_cmds = handle_export_and_cmds() bootup() if not jobs_cmds: @@ -931,6 +935,7 @@ def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): cutoff=0.7, ) if similar_cmd: + an_input = similar_cmd[0] if " " in an_input: candidate_input = ( f"{similar_cmd[0]} {' '.join(an_input.split(' ')[1:])}" @@ -941,8 +946,6 @@ def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): console.print("\n") continue an_input = candidate_input - else: - an_input = similar_cmd[0] console.print(f"[green]Replacing by '{an_input}'.[/green]") t_controller.queue.insert(0, an_input) From 855fd26256ba48490237f9d89d305cfbc67475c6 Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 11:20:44 -0400 Subject: [PATCH 11/20] Added a fix --- .../core/integration_tests/integration_test_coverage.py | 2 -- openbb_terminal/core/log/generation/expired_files.py | 1 - .../core/log/generation/path_tracking_file_handler.py | 1 - openbb_terminal/cryptocurrency/overview/pycoingecko_model.py | 1 - .../portfolio_optimization/parameters/params_controller.py | 1 - website/controller_doc_classes.py | 5 +++-- 6 files changed, 3 insertions(+), 8 deletions(-) diff --git a/openbb_terminal/core/integration_tests/integration_test_coverage.py b/openbb_terminal/core/integration_tests/integration_test_coverage.py index 43970a708593..4664ee6d24b1 100644 --- a/openbb_terminal/core/integration_tests/integration_test_coverage.py +++ b/openbb_terminal/core/integration_tests/integration_test_coverage.py @@ -174,7 +174,6 @@ def get_commands_and_params( with contextlib.suppress(AttributeError): params[command] = list(module_data[command].keys()) - if get_commands and get_params: return commands, params if get_commands and not get_params: @@ -280,7 +279,6 @@ def get_missing_params( with contextlib.suppress(ValueError): missing_params[key].remove(param) - missing_params = {k: v for k, v in missing_params.items() if v} return missing_params diff --git a/openbb_terminal/core/log/generation/expired_files.py b/openbb_terminal/core/log/generation/expired_files.py index a214f4b17aca..0e4bcb0c523b 100644 --- a/openbb_terminal/core/log/generation/expired_files.py +++ b/openbb_terminal/core/log/generation/expired_files.py @@ -28,4 +28,3 @@ def remove_file_list(file_list: List[Path]): for file in file_list: with contextlib.suppress(PermissionError): file.unlink(missing_ok=True) - diff --git a/openbb_terminal/core/log/generation/path_tracking_file_handler.py b/openbb_terminal/core/log/generation/path_tracking_file_handler.py index 478b2df54a3c..0289441196a7 100644 --- a/openbb_terminal/core/log/generation/path_tracking_file_handler.py +++ b/openbb_terminal/core/log/generation/path_tracking_file_handler.py @@ -188,7 +188,6 @@ def close(self): with contextlib.suppress(Exception): log_sender.join(timeout=3) - super().close() if log_sender.check_sending_conditions(file=closed_log_path): diff --git a/openbb_terminal/cryptocurrency/overview/pycoingecko_model.py b/openbb_terminal/cryptocurrency/overview/pycoingecko_model.py index db31c7ae7541..476e2e2db6a6 100644 --- a/openbb_terminal/cryptocurrency/overview/pycoingecko_model.py +++ b/openbb_terminal/cryptocurrency/overview/pycoingecko_model.py @@ -520,7 +520,6 @@ def get_global_defi_info() -> pd.DataFrame: with contextlib.suppress(ValueError, TypeError): results[key] = round(float(value), 4) - df = pd.Series(results).reset_index() df.columns = ["Metric", "Value"] df["Metric"] = df["Metric"].apply( diff --git a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py index b7f0723541a3..b4debb8ee344 100644 --- a/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py +++ b/openbb_terminal/portfolio/portfolio_optimization/parameters/params_controller.py @@ -315,7 +315,6 @@ def call_arg(self, other_args: List[str]): with contextlib.suppress(ValueError): value = float(value) - if argument == "historic_period": for option in AVAILABLE_OPTIONS[argument]: if option in str(value): diff --git a/website/controller_doc_classes.py b/website/controller_doc_classes.py index b0d4894af029..22b31459d76c 100644 --- a/website/controller_doc_classes.py +++ b/website/controller_doc_classes.py @@ -371,10 +371,11 @@ def mock_func(fparser: argparse.ArgumentParser, *args, **kwargs): if len(fullspec.args) > 2: args.update({arg: ["1234"] for arg in fullspec.args[2:]}) - with patch("openbb_terminal.rich_config.console.print"), contextlib.suppress(SystemExit, AttributeError): + with patch( + "openbb_terminal.rich_config.console.print" + ), contextlib.suppress(SystemExit, AttributeError): _ = getattr(self.controller, command)(["--help"], **args) - except Exception as e: print(e) From e5d6c9c4b44991679029d760253d382e6b974bfc Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 11:30:21 -0400 Subject: [PATCH 12/20] Fixed mypy --- openbb_terminal/routine_functions.py | 4 +++- openbb_terminal/settings_controller.py | 2 +- openbb_terminal/stocks/quantitative_analysis/factors_model.py | 4 ++-- openbb_terminal/stocks/screener/finviz_view.py | 4 ++-- openbb_terminal/terminal_controller.py | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/openbb_terminal/routine_functions.py b/openbb_terminal/routine_functions.py index a05b0e126629..c54b293793bd 100644 --- a/openbb_terminal/routine_functions.py +++ b/openbb_terminal/routine_functions.py @@ -78,7 +78,7 @@ def match_and_return_openbb_keyword_date(keyword: str) -> str: time_unit = match.group(2) if time_unit.upper() in ("DAYS", "MONTHS", "YEARS"): kwargs = {time_unit.lower(): integer_value} - return (now - relativedelta(**kwargs)).strftime("%Y-%m-%d") + return (now - relativedelta(**kwargs)).strftime("%Y-%m-%d") # type: ignore match = re.search(r"\$LAST(\w+)", keyword) if match: @@ -261,6 +261,7 @@ def parse_openbb_script( # noqa: PLR0911,PLR0912 return ( f"[red]Variable {VAR_NAME} not given " "for current routine script.[/red]", + "", ) # Only enters here when any other index from 0 is used @@ -287,6 +288,7 @@ def parse_openbb_script( # noqa: PLR0911,PLR0912 else: return ( f"[red]Variable {VAR_NAME} not given for current routine script.[/red]", + "", ) # Involves slicing which is a bit more tricky to use eval on diff --git a/openbb_terminal/settings_controller.py b/openbb_terminal/settings_controller.py index 834c44c045d1..844192329eec 100644 --- a/openbb_terminal/settings_controller.py +++ b/openbb_terminal/settings_controller.py @@ -484,7 +484,7 @@ def call_flair(self, other_args: List[str]): def call_userdata(self, other_args: List[str]): """Process userdata command""" - def save_file(file_path: Path): + def save_file(file_path: Union[str, Path]): console.print(f"User data to be saved in the default folder: '{file_path}'") self.set_and_save_preference("USER_DATA_DIRECTORY", file_path) diff --git a/openbb_terminal/stocks/quantitative_analysis/factors_model.py b/openbb_terminal/stocks/quantitative_analysis/factors_model.py index e1ab5e2e780d..98afbb824f45 100644 --- a/openbb_terminal/stocks/quantitative_analysis/factors_model.py +++ b/openbb_terminal/stocks/quantitative_analysis/factors_model.py @@ -27,8 +27,8 @@ def get_fama_raw() -> pd.DataFrame: """ url = "http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip" file = "F-F_Research_Data_Factors.CSV" - with urlopen(url) as url, ZipFile( # noqa: S310 - BytesIO(url.read()) + with urlopen(url) as data, ZipFile( # noqa: S310 + BytesIO(data.read()) ) as zipfile, zipfile.open(file) as zip_open: df = pd.read_csv( zip_open, diff --git a/openbb_terminal/stocks/screener/finviz_view.py b/openbb_terminal/stocks/screener/finviz_view.py index 7b8014f6d7c8..ed7446c7e620 100644 --- a/openbb_terminal/stocks/screener/finviz_view.py +++ b/openbb_terminal/stocks/screener/finviz_view.py @@ -200,7 +200,7 @@ def screener( df_original = df_screen.copy() df_screen = df_screen.fillna("") - cols = [] + cols: List[str] = [] data_type_cols = { "ownership": ["Market Cap", "Outstanding", "Float", "Avg Volume", "Volume"], "overview": ["Market Cap", "Volume"], @@ -209,7 +209,7 @@ def screener( "financial": ["Market Cap", "Volume"], "performance": ["Avg Volume", "Volume"], } - cols = data_type_cols.get(data_type) + cols = data_type_cols.get(data_type, []) if cols: df_screen[cols] = df_screen[cols].applymap( diff --git a/openbb_terminal/terminal_controller.py b/openbb_terminal/terminal_controller.py index 121f819768f9..80315d2c32ab 100644 --- a/openbb_terminal/terminal_controller.py +++ b/openbb_terminal/terminal_controller.py @@ -824,7 +824,7 @@ def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): t_controller = TerminalController(jobs_cmds) an_input = "" - export_path, jobs_cmds = handle_export_and_cmds() + export_path, jobs_cmds = handle_export_and_cmds(jobs_cmds) bootup() if not jobs_cmds: From 2031e4e9e7e3339df299cd35b81ff1dee857fac2 Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 11:40:57 -0400 Subject: [PATCH 13/20] Fixed some stuff --- openbb_terminal/forecast/whisper_model.py | 2 +- openbb_terminal/parent_classes.py | 9 +++++++-- .../stocks/options/options_chains_model.py | 5 +++-- openbb_terminal/terminal_controller.py | 12 +++++------- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/openbb_terminal/forecast/whisper_model.py b/openbb_terminal/forecast/whisper_model.py index 0f9fe4297de8..674b1c56c768 100644 --- a/openbb_terminal/forecast/whisper_model.py +++ b/openbb_terminal/forecast/whisper_model.py @@ -333,7 +333,7 @@ def get_sentiment_score(total_length, positive_score, negative_score): negative_percent = negative_score / total_length * 100 if positive_percent > 70: return "POSITIVE", positive_percent - elif negative_percent > 70: + if negative_percent > 70: return "NEGATIVE", negative_percent return "NEUTRAL", (positive_percent + negative_percent) / 2 return "NEUTRAL", 0.0 diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index 1208398b7f93..72b43a41c0de 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -1376,7 +1376,7 @@ def parse_known_args_and_warn( ) return ns_parser - def handle_command_in_queue(self, current_user, custom_path_menu_above: str): + def __handle_command_in_queue(self, current_user, custom_path_menu_above: str): # If the command is quitting the menu we want to return in here if self.queue[0] in ("q", "..", "quit"): self.save_class() @@ -1404,6 +1404,7 @@ def handle_command_in_queue(self, current_user, custom_path_menu_above: str): and an_input.split(" ")[0] in self.controller_choices ): console.print(f"{get_flair()} {self.PATH} $ {an_input}") + return None def menu(self, custom_path_menu_above: str = ""): """Enter controller menu.""" @@ -1414,7 +1415,11 @@ def menu(self, custom_path_menu_above: str = ""): while True: # There is a command in the queue if self.queue and len(self.queue) > 0: - self.handle_command_in_queue(current_user, custom_path_menu_above) + result = self.__handle_command_in_queue( + current_user, custom_path_menu_above + ) + if result is not None: + return result # Get input command from user else: # Display help menu when entering on this menu from a level above diff --git a/openbb_terminal/stocks/options/options_chains_model.py b/openbb_terminal/stocks/options/options_chains_model.py index a0299cf1b435..b7b89f97e99a 100644 --- a/openbb_terminal/stocks/options/options_chains_model.py +++ b/openbb_terminal/stocks/options/options_chains_model.py @@ -1463,8 +1463,9 @@ def get_strategies( """ def to_clean_list(x): - if x is not None: - return [x] if not isinstance(x, list) else x + if x is None: + return None + return [x] if not isinstance(x, list) else x options = deepcopy(options) diff --git a/openbb_terminal/terminal_controller.py b/openbb_terminal/terminal_controller.py index 80315d2c32ab..e273d6a76f27 100644 --- a/openbb_terminal/terminal_controller.py +++ b/openbb_terminal/terminal_controller.py @@ -14,7 +14,7 @@ import webbrowser from datetime import datetime from pathlib import Path -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional import certifi import pandas as pd @@ -777,9 +777,7 @@ def call_exe(self, other_args: List[str]): self.queue = self.queue[1:] -def handle_export_and_cmds( - jobs_cmds: Optional[List[str]], -) -> Tuple[Optional[str], Optional[List[str]]]: +def handle_job_cmds(jobs_cmds: Optional[List[str]]) -> Optional[List[str]]: # If the path selected does not start from the user root, # give relative location from terminal root if jobs_cmds is not None and jobs_cmds: @@ -793,7 +791,7 @@ def handle_export_and_cmds( export_path = first_split[1] jobs_cmds = ["/".join(commands[1:])] if not export_path: - return export_path, jobs_cmds + return jobs_cmds if export_path[0] == "~": export_path = export_path.replace("~", HOME_DIRECTORY.as_posix()) elif export_path[0] != "/": @@ -810,7 +808,7 @@ def handle_export_and_cmds( os.makedirs(export_path) console.print(f"[green]Folder '{export_path}' successfully created.[/green]") set_preference("USER_EXPORTS_DIRECTORY", Path(export_path)) - return export_path, jobs_cmds + return jobs_cmds def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): @@ -824,7 +822,7 @@ def terminal(jobs_cmds: Optional[List[str]] = None, test_mode=False): t_controller = TerminalController(jobs_cmds) an_input = "" - export_path, jobs_cmds = handle_export_and_cmds(jobs_cmds) + jobs_cmds = handle_job_cmds(jobs_cmds) bootup() if not jobs_cmds: From 0db203320719006e5dc4cf5e4ee582000dd88e0f Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 12:02:50 -0400 Subject: [PATCH 14/20] Reverted one thing --- openbb_terminal/parent_classes.py | 65 +++++++++++++------------------ 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index 72b43a41c0de..fa723aeec2c6 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -1376,36 +1376,6 @@ def parse_known_args_and_warn( ) return ns_parser - def __handle_command_in_queue(self, current_user, custom_path_menu_above: str): - # If the command is quitting the menu we want to return in here - if self.queue[0] in ("q", "..", "quit"): - self.save_class() - # Go back to the root in order to go to the right directory because - # there was a jump between indirect menus - if custom_path_menu_above: - self.queue.insert(1, custom_path_menu_above) - - if len(self.queue) > 1: - return self.queue[1:] - - if current_user.preferences.ENABLE_EXIT_AUTO_HELP: - return ["help"] - return [] - - # Consume 1 element from the queue - an_input = self.queue[0] - self.queue = self.queue[1:] - - # Print location because this was an instruction and we want user to know the action - if ( - an_input - and an_input != "home" - and an_input != "help" - and an_input.split(" ")[0] in self.controller_choices - ): - console.print(f"{get_flair()} {self.PATH} $ {an_input}") - return None - def menu(self, custom_path_menu_above: str = ""): """Enter controller menu.""" @@ -1415,11 +1385,33 @@ def menu(self, custom_path_menu_above: str = ""): while True: # There is a command in the queue if self.queue and len(self.queue) > 0: - result = self.__handle_command_in_queue( - current_user, custom_path_menu_above - ) - if result is not None: - return result + if self.queue[0] in ("q", "..", "quit"): + self.save_class() + # Go back to the root in order to go to the right directory because + # there was a jump between indirect menus + if custom_path_menu_above: + self.queue.insert(1, custom_path_menu_above) + + if len(self.queue) > 1: + return self.queue[1:] + + if current_user.preferences.ENABLE_EXIT_AUTO_HELP: + return ["help"] + return [] + + # Consume 1 element from the queue + an_input = self.queue[0] + self.queue = self.queue[1:] + + # Print location because this was an instruction and we want user to know the action + if ( + an_input + and an_input != "home" + and an_input != "help" + and an_input.split(" ")[0] in self.controller_choices + ): + console.print(f"{get_flair()} {self.PATH} $ {an_input}") + # Get input command from user else: # Display help menu when entering on this menu from a level above @@ -1466,8 +1458,7 @@ def menu(self, custom_path_menu_above: str = ""): try: # Allow user to go back to root - if an_input == "/": - an_input = "home" + an_input = "home" if an_input == "/" else an_input # Process the input command self.queue = self.switch(an_input) From c39c56d4041933fd6af93889b93b3c1621bda2ff Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 12:08:47 -0400 Subject: [PATCH 15/20] Small fix --- openbb_terminal/parent_classes.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openbb_terminal/parent_classes.py b/openbb_terminal/parent_classes.py index fa723aeec2c6..77d14c28b9c3 100644 --- a/openbb_terminal/parent_classes.py +++ b/openbb_terminal/parent_classes.py @@ -1437,9 +1437,7 @@ def menu(self, custom_path_menu_above: str = ""): f"{self.path[-1].capitalize()} (cmd/menu) Documentation" ), style=Style.from_dict( - { - "bottom-toolbar": "#ffffff bg:#333333", - } + {"bottom-toolbar": "#ffffff bg:#333333"} ), ) else: From 1ac549070bda62d9d9d192e08e9633adef08e30a Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 12:38:41 -0400 Subject: [PATCH 16/20] Small fix --- openbb_terminal/routine_functions.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openbb_terminal/routine_functions.py b/openbb_terminal/routine_functions.py index c54b293793bd..449f7d70b9f6 100644 --- a/openbb_terminal/routine_functions.py +++ b/openbb_terminal/routine_functions.py @@ -71,14 +71,18 @@ def match_and_return_openbb_keyword_date(keyword: str) -> str: str: Date with format YYYY-MM-DD """ now = datetime.now() - for regex in [r"^\$(\d+)([A-Z]+)AGO$", r"^\$(\d+)([A-Z]+)FROMNOW$"]: + for i, regex in enumerate([r"^\$(\d+)([A-Z]+)AGO$", r"^\$(\d+)([A-Z]+)FROMNOW$"]): match = re.match(regex, keyword) if match: integer_value = int(match.group(1)) time_unit = match.group(2) - if time_unit.upper() in ("DAYS", "MONTHS", "YEARS"): + clean_time = time_unit.upper() + if "DAYS" in clean_time or "MONTHS" in clean_time or "YEARS" in clean_time: + print("HELLO") kwargs = {time_unit.lower(): integer_value} - return (now - relativedelta(**kwargs)).strftime("%Y-%m-%d") # type: ignore + if i == 0: + return (now - relativedelta(**kwargs)).strftime("%Y-%m-%d") # type: ignore + return (now + relativedelta(**kwargs)).strftime("%Y-%m-%d") # type: ignore match = re.search(r"\$LAST(\w+)", keyword) if match: From 47e6b571627825e43f746d400c713d3c35aebef3 Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 12:47:08 -0400 Subject: [PATCH 17/20] Small fix --- openbb_terminal/routine_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbb_terminal/routine_functions.py b/openbb_terminal/routine_functions.py index 449f7d70b9f6..baac84511997 100644 --- a/openbb_terminal/routine_functions.py +++ b/openbb_terminal/routine_functions.py @@ -58,7 +58,7 @@ def is_reset(command: str) -> bool: return False -def match_and_return_openbb_keyword_date(keyword: str) -> str: +def match_and_return_openbb_keyword_date(keyword: str) -> str: # noqa: PLR0911 """Return OpenBB keyword into date Parameters From a5a024555d34e56fd6a5b7d7e09655e4de450e23 Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 12:51:49 -0400 Subject: [PATCH 18/20] Added fix --- openbb_terminal/routine_functions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openbb_terminal/routine_functions.py b/openbb_terminal/routine_functions.py index baac84511997..b68b10feab07 100644 --- a/openbb_terminal/routine_functions.py +++ b/openbb_terminal/routine_functions.py @@ -78,7 +78,6 @@ def match_and_return_openbb_keyword_date(keyword: str) -> str: # noqa: PLR0911 time_unit = match.group(2) clean_time = time_unit.upper() if "DAYS" in clean_time or "MONTHS" in clean_time or "YEARS" in clean_time: - print("HELLO") kwargs = {time_unit.lower(): integer_value} if i == 0: return (now - relativedelta(**kwargs)).strftime("%Y-%m-%d") # type: ignore From 9cf1adef36f43336ca7ff5126b443e59ee27bda5 Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 14:34:57 -0400 Subject: [PATCH 19/20] Added fix --- .../stocks/fundamental_analysis/yahoo_finance_model.py | 2 +- openbb_terminal/stocks/stocks_helper.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py b/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py index fb3eb06ec547..9a32d7f6c371 100644 --- a/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py +++ b/openbb_terminal/stocks/fundamental_analysis/yahoo_finance_model.py @@ -332,7 +332,7 @@ def get_financials(symbol: str, statement: str, ratios: bool = False) -> pd.Data new_headers[:0] = ["Breakdown"] df.columns = new_headers df.set_index("Breakdown", inplace=True) - elif statement == ("financials", "cash-flow"): + elif statement in ("financials", "cash-flow"): for dates in headers[2:]: read = datetime.strptime(dates, "%d/%m/%Y") write = read.strftime("%Y-%m-%d") diff --git a/openbb_terminal/stocks/stocks_helper.py b/openbb_terminal/stocks/stocks_helper.py index b8aa62044fc7..5fc9425b0bc3 100644 --- a/openbb_terminal/stocks/stocks_helper.py +++ b/openbb_terminal/stocks/stocks_helper.py @@ -233,7 +233,13 @@ def search( def get_daily_stock_candidate( - source: str, symbol: str, int_string: str, start_date, end_date, monthly, weekly + source: str, + symbol: str, + int_string: str, + start_date, + end_date, + monthly: bool, + weekly: bool, ) -> pd.DataFrame: if source == "AlphaVantage": return load_stock_av(symbol, int_string, start_date, end_date) @@ -338,7 +344,7 @@ def load( start_date = check_datetime(start_date) end_date = check_datetime(end_date, start=False) - int_string = "Weekly" if weekly else "Monthly" if monthly else "Daily" + int_string = "Monthly" if monthly else "Weekly" if weekly else "Daily" # Daily if int(interval) == 1440: From d724a60625746b689aff3ec3ce9ee77b3bc62db9 Mon Sep 17 00:00:00 2001 From: colin99d Date: Tue, 22 Aug 2023 14:42:14 -0400 Subject: [PATCH 20/20] Update requirements --- requirements-full.txt | 10 +++++----- requirements.txt | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/requirements-full.txt b/requirements-full.txt index 7fea20f12111..2832901d4710 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -14,7 +14,7 @@ ansiwrap==0.8.4 ; python_full_version >= "3.8.1" and python_full_version != "3.9 antlr4-python3-runtime==4.11.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" anyio==3.7.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" appdirs==1.4.4 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" -appnope==0.1.3 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (sys_platform == "darwin" or platform_system == "Darwin") +appnope==0.1.3 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and sys_platform == "darwin" or python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and platform_system == "Darwin" arch==5.6.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" argon2-cffi-bindings==21.2.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" argon2-cffi==21.3.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" @@ -122,7 +122,7 @@ google-auth-oauthlib==1.0.0 ; python_full_version >= "3.8.1" and python_full_ver google-auth==2.22.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" graphlib-backport==1.0.3 ; python_full_version >= "3.8.1" and python_version < "3.9" graphviz==0.20.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" -greenlet==2.0.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (platform_machine == "win32" or platform_machine == "WIN32" or platform_machine == "AMD64" or platform_machine == "amd64" or platform_machine == "x86_64" or platform_machine == "ppc64le" or platform_machine == "aarch64") +greenlet==2.0.2 ; python_full_version >= "3.8.1" and platform_machine == "aarch64" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "ppc64le" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "x86_64" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "amd64" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "AMD64" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "win32" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "WIN32" and python_full_version != "3.9.7" and python_version < "3.11" grpcio==1.56.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" h11==0.14.0 ; python_full_version >= "3.8.1" and python_version < "3.11" and python_full_version != "3.9.7" hijri-converter==2.3.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" @@ -200,7 +200,7 @@ multidict==6.0.4 ; python_full_version >= "3.8.1" and python_full_version != "3. multitasking==0.0.11 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" mutagen==1.46.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" mypy-extensions==1.0.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" -mypy==1.4.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" +mypy==1.5.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" myst-parser==0.15.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" nbclassic==1.0.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" nbclient==0.6.8 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" @@ -257,7 +257,7 @@ property-cached==1.6.4 ; python_full_version >= "3.8.1" and python_full_version prophet==1.1.3 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" protobuf==3.20.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" psutil==5.9.5 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" -ptyprocess==0.7.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (sys_platform != "win32" or os_name != "nt") +ptyprocess==0.7.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and sys_platform != "win32" or python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and os_name != "nt" pure-eval==0.2.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" py==1.11.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pyarrow==12.0.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" @@ -333,7 +333,7 @@ robin-stocks==2.1.0 ; python_full_version >= "3.8.1" and python_full_version != rsa==4.9 ; python_full_version >= "3.8.1" and python_version < "3.11" and python_full_version != "3.9.7" ruamel-yaml-clib==0.2.7 ; platform_python_implementation == "CPython" and python_version < "3.11" and python_full_version >= "3.8.1" and python_full_version != "3.9.7" ruamel-yaml==0.17.32 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" -ruff==0.0.256 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" +ruff==0.0.285 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" scikit-learn==1.3.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" scipy==1.10.1 ; python_full_version >= "3.8.1" and python_version < "3.11" and python_full_version != "3.9.7" screeninfo==0.6.7 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" diff --git a/requirements.txt b/requirements.txt index 507bae43beaf..2f2c8ed090bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ altair==5.0.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7 ansiwrap==0.8.4 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" anyio==3.7.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" appdirs==1.4.4 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" -appnope==0.1.3 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (sys_platform == "darwin" or platform_system == "Darwin") +appnope==0.1.3 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and sys_platform == "darwin" or python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and platform_system == "Darwin" arch==5.6.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" argon2-cffi-bindings==21.2.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" argon2-cffi==21.3.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" @@ -80,7 +80,7 @@ future==0.18.3 ; python_full_version >= "3.8.1" and python_full_version != "3.9. gitdb==4.0.10 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" gitpython==3.1.32 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" graphlib-backport==1.0.3 ; python_full_version >= "3.8.1" and python_version < "3.9" -greenlet==2.0.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (platform_machine == "win32" or platform_machine == "WIN32" or platform_machine == "AMD64" or platform_machine == "amd64" or platform_machine == "x86_64" or platform_machine == "ppc64le" or platform_machine == "aarch64") +greenlet==2.0.2 ; python_full_version >= "3.8.1" and platform_machine == "aarch64" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "ppc64le" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "x86_64" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "amd64" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "AMD64" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "win32" and python_full_version != "3.9.7" and python_version < "3.11" or python_full_version >= "3.8.1" and platform_machine == "WIN32" and python_full_version != "3.9.7" and python_version < "3.11" grpcio==1.56.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" h11==0.14.0 ; python_full_version >= "3.8.1" and python_version < "3.11" and python_full_version != "3.9.7" hijri-converter==2.3.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" @@ -178,7 +178,7 @@ prompt-toolkit==3.0.39 ; python_full_version >= "3.8.1" and python_full_version property-cached==1.6.4 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" protobuf==3.20.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" psutil==5.9.5 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" -ptyprocess==0.7.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (sys_platform != "win32" or os_name != "nt") +ptyprocess==0.7.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and sys_platform != "win32" or python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and os_name != "nt" pure-eval==0.2.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pyarrow==12.0.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pyasn1==0.5.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11"