mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
[Feature] Remove Python 3.9 (#7235)
* remove python 3.9 support and code * black * more cli lint * more linting * more lint * fix for tests * docstring grammar police * add lock to to build function to avoid async import race conditions * grammar police * lots more linting * relock
This commit is contained in:
@@ -8,7 +8,7 @@ import shlex
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
|
||||
from typing import Any, Literal
|
||||
|
||||
import pandas as pd
|
||||
from openbb_cli.config.completer import NestedCompleter
|
||||
@@ -20,7 +20,6 @@ from openbb_cli.controllers.utils import (
|
||||
check_positive,
|
||||
get_flair_and_username,
|
||||
handle_obbject_display,
|
||||
parse_and_split_input,
|
||||
parse_unknown_args_to_dict,
|
||||
print_guest_block_msg,
|
||||
print_rich_table,
|
||||
@@ -35,7 +34,7 @@ from prompt_toolkit.styles import Style
|
||||
# pylint: disable=C0301,C0302,R0902,global-statement,too-many-boolean-expressions
|
||||
# pylint: disable=R0912
|
||||
|
||||
controllers: Dict[str, Any] = {}
|
||||
controllers: dict[str, Any] = {}
|
||||
session = Session()
|
||||
|
||||
|
||||
@@ -70,8 +69,8 @@ class BaseController(metaclass=ABCMeta):
|
||||
"results",
|
||||
]
|
||||
|
||||
CHOICES_COMMANDS: List[str] = []
|
||||
CHOICES_MENUS: List[str] = []
|
||||
CHOICES_COMMANDS: list[str] = []
|
||||
CHOICES_MENUS: list[str] = []
|
||||
NEWS_CHOICES: dict = {}
|
||||
COMMAND_SEPARATOR = "/"
|
||||
KEYS_MENU = "keys" + COMMAND_SEPARATOR
|
||||
@@ -90,7 +89,7 @@ class BaseController(metaclass=ABCMeta):
|
||||
|
||||
return choices
|
||||
|
||||
def __init__(self, queue: Optional[List[str]] = None) -> None:
|
||||
def __init__(self, queue: list[str] | None = None) -> None:
|
||||
"""Create the base class for any controller in the codebase.
|
||||
|
||||
Used to simplify the creation of menus.
|
||||
@@ -113,7 +112,7 @@ class BaseController(metaclass=ABCMeta):
|
||||
else:
|
||||
self.controller_choices = self.CHOICES_COMMON
|
||||
|
||||
self.completer: Union[None, NestedCompleter] = None
|
||||
self.completer: None | NestedCompleter = None
|
||||
|
||||
self.parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
@@ -154,7 +153,7 @@ class BaseController(metaclass=ABCMeta):
|
||||
"""Save the current instance of the class to be loaded later."""
|
||||
controllers[self.PATH] = self
|
||||
|
||||
def custom_reset(self) -> List[str]:
|
||||
def custom_reset(self) -> list[str]:
|
||||
"""Implement custom reset.
|
||||
|
||||
This will be replaced by any children with custom_reset functions.
|
||||
@@ -167,34 +166,16 @@ class BaseController(metaclass=ABCMeta):
|
||||
raise NotImplementedError("Must override print_help.")
|
||||
|
||||
def parse_input(self, an_input: str) -> list:
|
||||
"""Parse controller input.
|
||||
"""Parse controller input."""
|
||||
# The original regex has been improved to handle quoted strings.
|
||||
# It now splits by '/' only when it's not enclosed in single or double quotes.
|
||||
# This allows commands like: exe --file "folder with spaces/file.openbb"
|
||||
# or exe --file 'folder with spaces/file.openbb'
|
||||
commands = re.split(r"/(?=(?:[^\"']*[\"'][^\"']*[\"'])*[^\"']*$)", an_input)
|
||||
# Remove empty strings from the list of commands
|
||||
return [cmd.strip() for cmd in commands if cmd.strip()]
|
||||
|
||||
Splits the command chain from user input into a list of individual commands
|
||||
while respecting the forward slash in the command arguments.
|
||||
|
||||
In the default scenario only unix-like paths are handles by the parser.
|
||||
Override this function in the controller classes that inherit from this one to
|
||||
resolve edge cases specific to command arguments on those controllers.
|
||||
|
||||
When handling edge cases add additional regular expressions to the list.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
an_input : str
|
||||
User input string
|
||||
|
||||
Returns
|
||||
----------
|
||||
list
|
||||
Command queue as list
|
||||
"""
|
||||
custom_filters: list = []
|
||||
commands = parse_and_split_input(
|
||||
an_input=an_input, custom_filters=custom_filters
|
||||
)
|
||||
return commands
|
||||
|
||||
def switch(self, an_input: str) -> List[str]:
|
||||
def switch(self, an_input: str) -> list[str]:
|
||||
"""Process and dispatch input.
|
||||
|
||||
Returns
|
||||
@@ -507,8 +488,7 @@ class BaseController(metaclass=ABCMeta):
|
||||
# If file already exists, add a timestamp to the name
|
||||
if os.path.isfile(routine_file):
|
||||
i = session.console.input(
|
||||
"A local routine with the same name already exists, "
|
||||
"do you want to override it? (y/n): "
|
||||
"A local routine with the same name already exists, do you want to override it? (y/n): "
|
||||
)
|
||||
session.console.print("")
|
||||
while i.lower() not in ["y", "yes", "n", "no"]:
|
||||
@@ -583,8 +563,7 @@ class BaseController(metaclass=ABCMeta):
|
||||
response = upload_routine(**kwargs) # type: ignore
|
||||
if response is not None and response.status_code == 409:
|
||||
i = session.console.input(
|
||||
"A routine with the same name already exists, "
|
||||
"do you want to replace it? (y/n): "
|
||||
"A routine with the same name already exists, do you want to replace it? (y/n): "
|
||||
)
|
||||
session.console.print("")
|
||||
if i.lower() in ["y", "yes"]:
|
||||
@@ -597,7 +576,7 @@ class BaseController(metaclass=ABCMeta):
|
||||
RECORD_SESSION = False
|
||||
SESSION_RECORDED = list()
|
||||
|
||||
def call_whoami(self, other_args: List[str]) -> None:
|
||||
def call_whoami(self, other_args: list[str]) -> None:
|
||||
"""Process whoami command."""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
@@ -621,7 +600,7 @@ class BaseController(metaclass=ABCMeta):
|
||||
else:
|
||||
print_guest_block_msg()
|
||||
|
||||
def call_results(self, other_args: List[str]):
|
||||
def call_results(self, other_args: list[str]):
|
||||
"""Process results command."""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
@@ -708,9 +687,9 @@ class BaseController(metaclass=ABCMeta):
|
||||
@staticmethod
|
||||
def parse_simple_args(
|
||||
parser: argparse.ArgumentParser,
|
||||
other_args: List[str],
|
||||
other_args: list[str],
|
||||
unknown_args: bool = False,
|
||||
) -> Tuple[Optional[argparse.Namespace], Optional[List[str]]]:
|
||||
) -> tuple[argparse.Namespace | None, list[str] | None]:
|
||||
"""Parse list of arguments into the supplied parser.
|
||||
|
||||
Parameters
|
||||
@@ -755,10 +734,10 @@ class BaseController(metaclass=ABCMeta):
|
||||
return ns_parser, l_unknown_args
|
||||
|
||||
@classmethod
|
||||
def parse_known_args_and_warn(
|
||||
def parse_known_args_and_warn( # pylint: disable=R0917
|
||||
cls,
|
||||
parser: argparse.ArgumentParser,
|
||||
other_args: List[str],
|
||||
other_args: list[str],
|
||||
export_allowed: Literal[
|
||||
"no_export", "raw_data_only", "figures_only", "raw_data_and_figures"
|
||||
] = "no_export",
|
||||
@@ -892,7 +871,7 @@ class BaseController(metaclass=ABCMeta):
|
||||
|
||||
# Check if the action has optional choices, if yes, remove them
|
||||
for action in parser._actions: # pylint: disable=protected-access
|
||||
if hasattr(action, "optional_choices") and action.optional_choices:
|
||||
if getattr(action, "optional_choices", None):
|
||||
action.choices = None
|
||||
|
||||
(ns_parser, l_unknown_args) = parser.parse_known_args(other_args)
|
||||
@@ -945,8 +924,7 @@ class BaseController(metaclass=ABCMeta):
|
||||
# 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 not in ("home", "help")
|
||||
and an_input.split(" ")[0] in self.controller_choices
|
||||
):
|
||||
session.console.print(
|
||||
|
||||
Reference in New Issue
Block a user