mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-05-07 06:23:26 +08:00
[BugFix] openbb-cli: Handle Pipe Union Types in argparse_translator (#7257)
* handle pipe union types in argparse_translator * lock file
This commit is contained in:
@@ -152,15 +152,93 @@ class ArgparseTranslator:
|
||||
@staticmethod
|
||||
def _build_description(func_doc: str) -> str:
|
||||
"""Build the description of the argparse program from the function docstring."""
|
||||
patterns = ["openbb\n ======", "Parameters\n ----------"]
|
||||
# Remove only the Examples section and the openbb header if present
|
||||
patterns_to_remove = [
|
||||
(r"openbb\n\s+={3,}\n", ""), # Remove openbb header
|
||||
(r"\n\s*Examples\n\s*-{3,}\n.*", ""), # Remove Examples section to end
|
||||
]
|
||||
|
||||
if func_doc:
|
||||
for pattern in patterns:
|
||||
if pattern in func_doc:
|
||||
func_doc = func_doc[: func_doc.index(pattern)].strip()
|
||||
break
|
||||
for pattern, replacement in patterns_to_remove:
|
||||
func_doc = re.sub(pattern, replacement, func_doc, flags=re.DOTALL)
|
||||
|
||||
return func_doc
|
||||
# Clean up type annotations in docstrings
|
||||
def clean_type_annotation(type_str: str) -> str:
|
||||
"""Clean up a single type annotation."""
|
||||
# First, handle the pipe union syntax: type1 | type2 -> type1 or type2
|
||||
# Do this FIRST before other transformations
|
||||
type_str = re.sub(r"\s*\|\s*", " or ", type_str)
|
||||
|
||||
# Handle Annotated[type, ...] -> type
|
||||
type_str = re.sub(r"Annotated\[([^,\]]+)(?:,\s*[^\]]+)?\]", r"\1", type_str)
|
||||
|
||||
# Handle Union[type1, type2, ...] -> type1 or type2 or ...
|
||||
type_str = re.sub(
|
||||
r"Union\[([^\]]+)\]",
|
||||
lambda m: " or ".join(m.group(1).split(", ")),
|
||||
type_str,
|
||||
)
|
||||
|
||||
# Handle Optional[type] -> type or None
|
||||
type_str = re.sub(r"Optional\[([^\]]+)\]", r"\1 or None", type_str)
|
||||
|
||||
# Deduplicate "or" separated types
|
||||
parts = [p.strip() for p in type_str.split(" or ")]
|
||||
|
||||
# Remove duplicates while preserving order (case-insensitive)
|
||||
seen = set()
|
||||
unique_parts = []
|
||||
for part in parts:
|
||||
part_lower = part.lower()
|
||||
if part_lower not in seen:
|
||||
seen.add(part_lower)
|
||||
unique_parts.append(part)
|
||||
|
||||
# If None is present, move it to the end
|
||||
if "None" in unique_parts:
|
||||
unique_parts.remove("None")
|
||||
unique_parts.append("None")
|
||||
|
||||
type_str = " or ".join(unique_parts)
|
||||
|
||||
return type_str
|
||||
|
||||
# Process each line that contains a type annotation (format: "name : type")
|
||||
lines = func_doc.split("\n")
|
||||
cleaned_lines = []
|
||||
|
||||
for line in lines:
|
||||
# Match lines with type annotations (parameter_name : type_annotation)
|
||||
if ":" in line and not line.strip().startswith("#"):
|
||||
# Split only on the first colon to preserve any colons in the description
|
||||
parts = line.split(":", 1)
|
||||
if len(parts) == 2:
|
||||
param_name = parts[0]
|
||||
rest = parts[1].strip()
|
||||
|
||||
# Extract the type part (everything before the first real description line)
|
||||
# Type annotations typically don't contain spaces at the start of continuation lines
|
||||
type_match = re.match(r"^([^\n]+?)(?:\n\s{4,}|\s{2,}|$)", rest)
|
||||
if type_match:
|
||||
type_part = type_match.group(1).strip()
|
||||
description_part = rest[len(type_match.group(1)) :]
|
||||
|
||||
# Clean the type annotation
|
||||
cleaned_type = clean_type_annotation(type_part)
|
||||
|
||||
# Reconstruct the line
|
||||
if description_part:
|
||||
cleaned_lines.append(
|
||||
f"{param_name}: {cleaned_type}{description_part}"
|
||||
)
|
||||
else:
|
||||
cleaned_lines.append(f"{param_name}: {cleaned_type}")
|
||||
continue
|
||||
|
||||
cleaned_lines.append(line)
|
||||
|
||||
func_doc = "\n".join(cleaned_lines)
|
||||
|
||||
return func_doc.strip()
|
||||
|
||||
@staticmethod
|
||||
def _param_is_default(param: inspect.Parameter) -> bool:
|
||||
@@ -192,7 +270,9 @@ class ArgparseTranslator:
|
||||
) -> tuple[type[Any], tuple[Any, ...]]:
|
||||
"""Return the type and choices for the given parameter."""
|
||||
|
||||
def get_base_type(t: Any) -> type:
|
||||
def get_base_type( # pylint: disable=R0911 # noqa:PLR0911
|
||||
t: Any,
|
||||
) -> type:
|
||||
"""Recursively find the base type for argparse."""
|
||||
origin = get_origin(t)
|
||||
args = get_args(t)
|
||||
@@ -201,9 +281,16 @@ class ArgparseTranslator:
|
||||
non_none_args = [a for a in args if a is not type(None)]
|
||||
if len(non_none_args) == 1:
|
||||
return get_base_type(non_none_args[0])
|
||||
# For Union[A, B], default to str, as argparse can't handle multiple types
|
||||
# For Union[A, B, C], check for bool first, then default to str
|
||||
if bool in non_none_args:
|
||||
return bool
|
||||
# If we have multiple types including str, prefer str as it's most flexible
|
||||
if str in non_none_args:
|
||||
return str
|
||||
# Otherwise, try to get the first concrete type
|
||||
for arg in non_none_args:
|
||||
if arg not in (type(None), Any):
|
||||
return get_base_type(arg)
|
||||
return str
|
||||
if origin is Literal:
|
||||
return type(args[0]) if args else str
|
||||
@@ -211,7 +298,10 @@ class ArgparseTranslator:
|
||||
return get_base_type(args[0]) if args else Any # type: ignore
|
||||
if t is Any:
|
||||
return str
|
||||
return t
|
||||
# Handle actual type objects (like datetime.date)
|
||||
if isinstance(t, type):
|
||||
return t
|
||||
return str
|
||||
|
||||
def get_choices(t: Any) -> tuple:
|
||||
"""Recursively find the choices for argparse."""
|
||||
|
||||
@@ -379,7 +379,7 @@ def print_rich_table( # noqa: PLR0912
|
||||
)
|
||||
|
||||
if columns_to_auto_color is None and rows_to_auto_color is None:
|
||||
df = df.applymap(lambda x: return_colored_value(str(x)))
|
||||
df = df.applymap(lambda x: return_colored_value(str(x))) # type: ignore
|
||||
|
||||
exceeds_allowed_columns = len(df.columns) > MAX_COLS
|
||||
exceeds_allowed_rows = len(df) > MAX_ROWS
|
||||
@@ -631,7 +631,7 @@ def remove_timezone_from_dataframe(df: pd.DataFrame) -> pd.DataFrame:
|
||||
if (
|
||||
df.index.dtype.kind == "M"
|
||||
and hasattr(df.index.dtype, "tz")
|
||||
and df.index.dtype.tz is not None
|
||||
and df.index.dtype.tz is not None # type: ignore
|
||||
):
|
||||
index_is_date = True
|
||||
|
||||
@@ -645,7 +645,7 @@ def remove_timezone_from_dataframe(df: pd.DataFrame) -> pd.DataFrame:
|
||||
|
||||
if index_is_date:
|
||||
index_name = df.index.name
|
||||
df.index = df.index.date
|
||||
df.index = df.index.date # type: ignore
|
||||
df.index.name = index_name
|
||||
|
||||
return df
|
||||
@@ -745,7 +745,7 @@ def save_to_excel(df, saved_path, sheet_name, start_row=0, index=True, header=Tr
|
||||
with pd.ExcelWriter(
|
||||
saved_path,
|
||||
mode="a",
|
||||
if_sheet_exists=overwrite_options[overwrite_option],
|
||||
if_sheet_exists=overwrite_options[overwrite_option], # type: ignore
|
||||
engine="openpyxl",
|
||||
) as writer:
|
||||
df.to_excel(
|
||||
|
||||
344
cli/poetry.lock
generated
vendored
344
cli/poetry.lock
generated
vendored
@@ -318,7 +318,7 @@ description = "Timeout context manager for asyncio programs"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version <= \"3.10\""
|
||||
markers = "python_version == \"3.10\""
|
||||
files = [
|
||||
{file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"},
|
||||
{file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"},
|
||||
@@ -343,7 +343,6 @@ description = "The ultimate Python library in building OAuth and OpenID Connect
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "authlib-1.6.5-py2.py3-none-any.whl", hash = "sha256:3e0e0507807f842b02175507bdee8957a1d5707fd4afb17c32fb43fee90b6e3a"},
|
||||
{file = "authlib-1.6.5.tar.gz", hash = "sha256:6aaf9c79b7cc96c900f0b284061691c5d4e61221640a948fe690b556a6d6d10b"},
|
||||
@@ -750,22 +749,6 @@ files = [
|
||||
{file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.8"
|
||||
description = "Composable command line interface toolkit"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.10\""
|
||||
files = [
|
||||
{file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
|
||||
{file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.3.0"
|
||||
@@ -773,7 +756,6 @@ description = "Composable command line interface toolkit"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc"},
|
||||
{file = "click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4"},
|
||||
@@ -822,7 +804,6 @@ description = "cryptography is a package which provides cryptographic recipes an
|
||||
optional = false
|
||||
python-versions = "!=3.9.0,!=3.9.1,>=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "cryptography-46.0.2-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:f3e32ab7dd1b1ef67b9232c4cf5e2ee4cd517d4316ea910acaaa9c5712a1c663"},
|
||||
{file = "cryptography-46.0.2-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1fd1a69086926b623ef8126b4c33d5399ce9e2f3fac07c9c734c2a4ec38b6d02"},
|
||||
@@ -952,7 +933,6 @@ description = "Intuitive, easy CLIs based on type hints."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "cyclopts-3.24.0-py3-none-any.whl", hash = "sha256:809d04cde9108617106091140c3964ee6fceb33cecdd537f7ffa360bde13ed71"},
|
||||
{file = "cyclopts-3.24.0.tar.gz", hash = "sha256:de6964a041dfb3c57bf043b41e68c43548227a17de1bad246e3a0bfc5c4b7417"},
|
||||
@@ -1118,7 +1098,6 @@ description = "DNS toolkit"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af"},
|
||||
{file = "dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f"},
|
||||
@@ -1140,7 +1119,6 @@ description = "Parse Python docstrings in reST, Google and Numpydoc format"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708"},
|
||||
{file = "docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912"},
|
||||
@@ -1158,7 +1136,6 @@ description = "Docutils -- Python Documentation Utilities"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "docutils-0.22.2-py3-none-any.whl", hash = "sha256:b0e98d679283fc3bb0ead8a5da7f501baa632654e7056e9c5846842213d674d8"},
|
||||
{file = "docutils-0.22.2.tar.gz", hash = "sha256:9fdb771707c8784c8f2728b67cb2c691305933d68137ef95a75db5f4dfbc213d"},
|
||||
@@ -1171,7 +1148,6 @@ description = "A robust email address syntax and deliverability validation libra
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4"},
|
||||
{file = "email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426"},
|
||||
@@ -1211,30 +1187,6 @@ typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""}
|
||||
[package.extras]
|
||||
test = ["pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "exchange-calendars"
|
||||
version = "4.5.6"
|
||||
description = "Calendars for securities exchanges"
|
||||
optional = false
|
||||
python-versions = "~=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.10\""
|
||||
files = [
|
||||
{file = "exchange_calendars-4.5.6-py3-none-any.whl", hash = "sha256:5abf5ebcb8ceef0ced36fe4e20071d42517091bf081e6c44354cb343009d672b"},
|
||||
{file = "exchange_calendars-4.5.6.tar.gz", hash = "sha256:5db77178cf849f81dd6dcc99995e2163b928c0f45dcd0a2c395958beb1dbb145"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
korean-lunar-calendar = "*"
|
||||
numpy = "*"
|
||||
pandas = ">=1.5"
|
||||
pyluach = "*"
|
||||
toolz = "*"
|
||||
tzdata = "*"
|
||||
|
||||
[package.extras]
|
||||
dev = ["flake8", "hypothesis", "pip-tools", "pytest", "pytest-benchmark", "pytest-xdist"]
|
||||
|
||||
[[package]]
|
||||
name = "exchange-calendars"
|
||||
version = "4.11.1"
|
||||
@@ -1242,7 +1194,6 @@ description = "Calendars for securities exchanges"
|
||||
optional = false
|
||||
python-versions = "~=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "exchange_calendars-4.11.1-py3-none-any.whl", hash = "sha256:40ec771589e5a9b96b9e09667cd0f3fde7c70444e3a7530b8989ebd0750ee478"},
|
||||
{file = "exchange_calendars-4.11.1.tar.gz", hash = "sha256:bdaf000c3c5a0087341e1fdfe063182d27585bdba3f1a3d0189a13bdb4afea5d"},
|
||||
@@ -1303,7 +1254,6 @@ description = "The fast, Pythonic way to build MCP servers and clients."
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "fastmcp-2.12.4-py3-none-any.whl", hash = "sha256:56188fbbc1a9df58c537063f25958c57b5c4d715f73e395c41b51550b247d140"},
|
||||
{file = "fastmcp-2.12.4.tar.gz", hash = "sha256:b55fe89537038f19d0f4476544f9ca5ac171033f61811cc8f12bdeadcbea5016"},
|
||||
@@ -1642,7 +1592,6 @@ description = "A minimal low-level HTTP client."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"},
|
||||
{file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"},
|
||||
@@ -1665,7 +1614,6 @@ description = "The next generation HTTP client."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"},
|
||||
{file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"},
|
||||
@@ -1691,7 +1639,6 @@ description = "Consume Server-Sent Event (SSE) messages with HTTPX."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "httpx_sse-0.4.2-py3-none-any.whl", hash = "sha256:a9fa4afacb293fa50ef9bacb6cae8287ba5fd1f4b1c2d10a35bb981c41da31ab"},
|
||||
{file = "httpx_sse-0.4.2.tar.gz", hash = "sha256:5bb6a2771a51e6c7a5f5c645e40b8a5f57d8de708f46cb5f3868043c3c18124e"},
|
||||
@@ -1798,7 +1745,6 @@ description = "An ISO 8601 date/time/duration parser and formatter"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "isodate-0.7.2-py3-none-any.whl", hash = "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15"},
|
||||
{file = "isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6"},
|
||||
@@ -1857,7 +1803,6 @@ description = "JSONSchema Spec with object-oriented paths"
|
||||
optional = false
|
||||
python-versions = "<4.0.0,>=3.8.0"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "jsonschema_path-0.3.4-py3-none-any.whl", hash = "sha256:f502191fdc2b22050f9a81c9237be9d27145b9001c55842bece5e94e382e52f8"},
|
||||
{file = "jsonschema_path-0.3.4.tar.gz", hash = "sha256:8365356039f16cc65fddffafda5f58766e34bebab7d6d105616ab52bc4297001"},
|
||||
@@ -1939,7 +1884,6 @@ description = "A fast and thorough lazy object proxy."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "lazy_object_proxy-1.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61d5e3310a4aa5792c2b599a7a78ccf8687292c8eb09cf187cca8f09cf6a7519"},
|
||||
{file = "lazy_object_proxy-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1ca33565f698ac1aece152a10f432415d1a2aa9a42dfe23e5ba2bc255ab91f6"},
|
||||
@@ -2038,38 +1982,6 @@ scipy = ">=1.8.0"
|
||||
setuptools-scm = {version = ">=8.0.0,<9.0.0", extras = ["toml"]}
|
||||
statsmodels = ">=0.13.0"
|
||||
|
||||
[[package]]
|
||||
name = "llvmlite"
|
||||
version = "0.43.0"
|
||||
description = "lightweight wrapper around basic LLVM functionality"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.10\""
|
||||
files = [
|
||||
{file = "llvmlite-0.43.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a289af9a1687c6cf463478f0fa8e8aa3b6fb813317b0d70bf1ed0759eab6f761"},
|
||||
{file = "llvmlite-0.43.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d4fd101f571a31acb1559ae1af30f30b1dc4b3186669f92ad780e17c81e91bc"},
|
||||
{file = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d434ec7e2ce3cc8f452d1cd9a28591745de022f931d67be688a737320dfcead"},
|
||||
{file = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6912a87782acdff6eb8bf01675ed01d60ca1f2551f8176a300a886f09e836a6a"},
|
||||
{file = "llvmlite-0.43.0-cp310-cp310-win_amd64.whl", hash = "sha256:14f0e4bf2fd2d9a75a3534111e8ebeb08eda2f33e9bdd6dfa13282afacdde0ed"},
|
||||
{file = "llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3e8d0618cb9bfe40ac38a9633f2493d4d4e9fcc2f438d39a4e854f39cc0f5f98"},
|
||||
{file = "llvmlite-0.43.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0a9a1a39d4bf3517f2af9d23d479b4175ead205c592ceeb8b89af48a327ea57"},
|
||||
{file = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2"},
|
||||
{file = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749"},
|
||||
{file = "llvmlite-0.43.0-cp311-cp311-win_amd64.whl", hash = "sha256:d5bd550001d26450bd90777736c69d68c487d17bf371438f975229b2b8241a91"},
|
||||
{file = "llvmlite-0.43.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f99b600aa7f65235a5a05d0b9a9f31150c390f31261f2a0ba678e26823ec38f7"},
|
||||
{file = "llvmlite-0.43.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:35d80d61d0cda2d767f72de99450766250560399edc309da16937b93d3b676e7"},
|
||||
{file = "llvmlite-0.43.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eccce86bba940bae0d8d48ed925f21dbb813519169246e2ab292b5092aba121f"},
|
||||
{file = "llvmlite-0.43.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df6509e1507ca0760787a199d19439cc887bfd82226f5af746d6977bd9f66844"},
|
||||
{file = "llvmlite-0.43.0-cp312-cp312-win_amd64.whl", hash = "sha256:7a2872ee80dcf6b5dbdc838763d26554c2a18aa833d31a2635bff16aafefb9c9"},
|
||||
{file = "llvmlite-0.43.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cd2a7376f7b3367019b664c21f0c61766219faa3b03731113ead75107f3b66c"},
|
||||
{file = "llvmlite-0.43.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18e9953c748b105668487b7c81a3e97b046d8abf95c4ddc0cd3c94f4e4651ae8"},
|
||||
{file = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74937acd22dc11b33946b67dca7680e6d103d6e90eeaaaf932603bec6fe7b03a"},
|
||||
{file = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9efc739cc6ed760f795806f67889923f7274276f0eb45092a1473e40d9b867"},
|
||||
{file = "llvmlite-0.43.0-cp39-cp39-win_amd64.whl", hash = "sha256:47e147cdda9037f94b399bf03bfd8a6b6b1f2f90be94a454e3386f006455a9b4"},
|
||||
{file = "llvmlite-0.43.0.tar.gz", hash = "sha256:ae2b5b5c3ef67354824fb75517c8db5fbe93bc02cd9671f3c62271626bc041d5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "llvmlite"
|
||||
version = "0.45.1"
|
||||
@@ -2077,7 +1989,6 @@ description = "lightweight wrapper around basic LLVM functionality"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "llvmlite-0.45.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:1b1af0c910af0978aa55fa4f60bbb3e9f39b41e97c2a6d94d199897be62ba07a"},
|
||||
{file = "llvmlite-0.45.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02a164db2d79088bbd6e0d9633b4fe4021d6379d7e4ac7cc85ed5f44b06a30c5"},
|
||||
@@ -2269,32 +2180,6 @@ files = [
|
||||
[package.dependencies]
|
||||
lxml = "*"
|
||||
|
||||
[[package]]
|
||||
name = "markdown-it-py"
|
||||
version = "3.0.0"
|
||||
description = "Python port of markdown-it. Markdown parsing, done right!"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.10\""
|
||||
files = [
|
||||
{file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
|
||||
{file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
mdurl = ">=0.1,<1.0"
|
||||
|
||||
[package.extras]
|
||||
benchmarking = ["psutil", "pytest", "pytest-benchmark"]
|
||||
code-style = ["pre-commit (>=3.0,<4.0)"]
|
||||
compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
|
||||
linkify = ["linkify-it-py (>=1,<3)"]
|
||||
plugins = ["mdit-py-plugins"]
|
||||
profiling = ["gprof2dot"]
|
||||
rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
|
||||
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-it-py"
|
||||
version = "4.0.0"
|
||||
@@ -2302,7 +2187,6 @@ description = "Python port of markdown-it. Markdown parsing, done right!"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147"},
|
||||
{file = "markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3"},
|
||||
@@ -2327,7 +2211,6 @@ description = "Safely add untrusted strings to HTML/XML markup."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"},
|
||||
{file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"},
|
||||
@@ -2427,7 +2310,6 @@ description = "Model Context Protocol SDK"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "mcp-1.16.0-py3-none-any.whl", hash = "sha256:ec917be9a5d31b09ba331e1768aa576e0af45470d657a0319996a20a57d7d633"},
|
||||
{file = "mcp-1.16.0.tar.gz", hash = "sha256:39b8ca25460c578ee2cdad33feeea122694cfdf73eef58bee76c42f6ef0589df"},
|
||||
@@ -2725,42 +2607,6 @@ traitlets = ">=5.1"
|
||||
docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"]
|
||||
test = ["pep440", "pre-commit", "pytest", "testpath"]
|
||||
|
||||
[[package]]
|
||||
name = "numba"
|
||||
version = "0.60.0"
|
||||
description = "compiling Python code using LLVM"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.10\""
|
||||
files = [
|
||||
{file = "numba-0.60.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d761de835cd38fb400d2c26bb103a2726f548dc30368853121d66201672e651"},
|
||||
{file = "numba-0.60.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:159e618ef213fba758837f9837fb402bbe65326e60ba0633dbe6c7f274d42c1b"},
|
||||
{file = "numba-0.60.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1527dc578b95c7c4ff248792ec33d097ba6bef9eda466c948b68dfc995c25781"},
|
||||
{file = "numba-0.60.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe0b28abb8d70f8160798f4de9d486143200f34458d34c4a214114e445d7124e"},
|
||||
{file = "numba-0.60.0-cp310-cp310-win_amd64.whl", hash = "sha256:19407ced081d7e2e4b8d8c36aa57b7452e0283871c296e12d798852bc7d7f198"},
|
||||
{file = "numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8"},
|
||||
{file = "numba-0.60.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3fb02b344a2a80efa6f677aa5c40cd5dd452e1b35f8d1c2af0dfd9ada9978e4b"},
|
||||
{file = "numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703"},
|
||||
{file = "numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8"},
|
||||
{file = "numba-0.60.0-cp311-cp311-win_amd64.whl", hash = "sha256:cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2"},
|
||||
{file = "numba-0.60.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7da4098db31182fc5ffe4bc42c6f24cd7d1cb8a14b59fd755bfee32e34b8404"},
|
||||
{file = "numba-0.60.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38d6ea4c1f56417076ecf8fc327c831ae793282e0ff51080c5094cb726507b1c"},
|
||||
{file = "numba-0.60.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:62908d29fb6a3229c242e981ca27e32a6e606cc253fc9e8faeb0e48760de241e"},
|
||||
{file = "numba-0.60.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0ebaa91538e996f708f1ab30ef4d3ddc344b64b5227b67a57aa74f401bb68b9d"},
|
||||
{file = "numba-0.60.0-cp312-cp312-win_amd64.whl", hash = "sha256:f75262e8fe7fa96db1dca93d53a194a38c46da28b112b8a4aca168f0df860347"},
|
||||
{file = "numba-0.60.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:01ef4cd7d83abe087d644eaa3d95831b777aa21d441a23703d649e06b8e06b74"},
|
||||
{file = "numba-0.60.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:819a3dfd4630d95fd574036f99e47212a1af41cbcb019bf8afac63ff56834449"},
|
||||
{file = "numba-0.60.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0b983bd6ad82fe868493012487f34eae8bf7dd94654951404114f23c3466d34b"},
|
||||
{file = "numba-0.60.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c151748cd269ddeab66334bd754817ffc0cabd9433acb0f551697e5151917d25"},
|
||||
{file = "numba-0.60.0-cp39-cp39-win_amd64.whl", hash = "sha256:3031547a015710140e8c87226b4cfe927cac199835e5bf7d4fe5cb64e814e3ab"},
|
||||
{file = "numba-0.60.0.tar.gz", hash = "sha256:5df6158e5584eece5fc83294b949fd30b9f1125df7708862205217e068aabf16"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
llvmlite = "==0.43.*"
|
||||
numpy = ">=1.22,<2.1"
|
||||
|
||||
[[package]]
|
||||
name = "numba"
|
||||
version = "0.62.1"
|
||||
@@ -2768,7 +2614,6 @@ description = "compiling Python code using LLVM"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "numba-0.62.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a323df9d36a0da1ca9c592a6baaddd0176d9f417ef49a65bb81951dce69d941a"},
|
||||
{file = "numba-0.62.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1e1f4781d3f9f7c23f16eb04e76ca10b5a3516e959634bd226fc48d5d8e7a0a"},
|
||||
@@ -2797,62 +2642,6 @@ files = [
|
||||
llvmlite = "==0.45.*"
|
||||
numpy = ">=1.22,<2.4"
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.0.2"
|
||||
description = "Fundamental package for array computing in Python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.10\""
|
||||
files = [
|
||||
{file = "numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece"},
|
||||
{file = "numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04"},
|
||||
{file = "numpy-2.0.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8c5713284ce4e282544c68d1c3b2c7161d38c256d2eefc93c1d683cf47683e66"},
|
||||
{file = "numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b"},
|
||||
{file = "numpy-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2da5960c3cf0df7eafefd806d4e612c5e19358de82cb3c343631188991566ccd"},
|
||||
{file = "numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318"},
|
||||
{file = "numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8"},
|
||||
{file = "numpy-2.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d731a1c6116ba289c1e9ee714b08a8ff882944d4ad631fd411106a30f083c326"},
|
||||
{file = "numpy-2.0.2-cp310-cp310-win32.whl", hash = "sha256:984d96121c9f9616cd33fbd0618b7f08e0cfc9600a7ee1d6fd9b239186d19d97"},
|
||||
{file = "numpy-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-win32.whl", hash = "sha256:a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4"},
|
||||
{file = "numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8df823f570d9adf0978347d1f926b2a867d5608f434a7cff7f7908c6570dcf5e"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9a92ae5c14811e390f3767053ff54eaee3bf84576d99a2456391401323f4ec2c"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05e238064fc0610c840d1cf6a13bf63d7e391717d247f1bf0318172e759e692"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec9852fb39354b5a45a80bdab5ac02dd02b15f44b3804e9f00c556bf24b4bded"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-win32.whl", hash = "sha256:671bec6496f83202ed2d3c8fdc486a8fc86942f2e69ff0e986140339a63bcbe5"},
|
||||
{file = "numpy-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:423e89b23490805d2a5a96fe40ec507407b8ee786d66f7328be214f9679df6dd"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:2b2955fa6f11907cf7a70dab0d0755159bca87755e831e47932367fc8f2f2d0b"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e795a8be3ddbac43274f18588329c72939870a16cae810c2b73461c40718ab1"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9189427407d88ff25ecf8f12469d4d39d35bee1db5d39fc5c168c6f088a6956d"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-win32.whl", hash = "sha256:905d16e0c60200656500c95b6b8dca5d109e23cb24abc701d41c02d74c6b3afa"},
|
||||
{file = "numpy-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73"},
|
||||
{file = "numpy-2.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8"},
|
||||
{file = "numpy-2.0.2-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4"},
|
||||
{file = "numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c"},
|
||||
{file = "numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385"},
|
||||
{file = "numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.2.6"
|
||||
@@ -3011,7 +2800,6 @@ description = "client-side and server-side support for the OpenAPI Specification
|
||||
optional = false
|
||||
python-versions = "<4.0.0,>=3.8.0"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "openapi_core-0.19.5-py3-none-any.whl", hash = "sha256:ef7210e83a59394f46ce282639d8d26ad6fc8094aa904c9c16eb1bac8908911f"},
|
||||
{file = "openapi_core-0.19.5.tar.gz", hash = "sha256:421e753da56c391704454e66afe4803a290108590ac8fa6f4a4487f4ec11f2d3"},
|
||||
@@ -3044,7 +2832,6 @@ description = "Pydantic OpenAPI schema implementation"
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146"},
|
||||
{file = "openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d"},
|
||||
@@ -3060,7 +2847,6 @@ description = "OpenAPI schema validation for Python"
|
||||
optional = false
|
||||
python-versions = "<4.0.0,>=3.8.0"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "openapi_schema_validator-0.6.3-py3-none-any.whl", hash = "sha256:f3b9870f4e556b5a62a1c39da72a6b4b16f3ad9c73dc80084b1b11e74ba148a3"},
|
||||
{file = "openapi_schema_validator-0.6.3.tar.gz", hash = "sha256:f37bace4fc2a5d96692f4f8b31dc0f8d7400fd04f3a937798eaf880d425de6ee"},
|
||||
@@ -3078,7 +2864,6 @@ description = "OpenAPI 2.0 (aka Swagger) and OpenAPI 3 spec validator"
|
||||
optional = false
|
||||
python-versions = "<4.0.0,>=3.8.0"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "openapi_spec_validator-0.7.2-py3-none-any.whl", hash = "sha256:4bbdc0894ec85f1d1bea1d6d9c8b2c3c8d7ccaa13577ef40da9c006c9fd0eb60"},
|
||||
{file = "openapi_spec_validator-0.7.2.tar.gz", hash = "sha256:cc029309b5c5dbc7859df0372d55e9d1ff43e96d678b9ba087f7c56fc586f734"},
|
||||
@@ -3684,7 +3469,6 @@ description = "OpenBB Platform MCP Server"
|
||||
optional = false
|
||||
python-versions = "<3.14,>=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "openbb_mcp_server-1.2.0-py3-none-any.whl", hash = "sha256:00a8d4c9ae76b5c3086b8b43799a3b50e48dc117eae93c5edfc4e3cb515a4f68"},
|
||||
{file = "openbb_mcp_server-1.2.0.tar.gz", hash = "sha256:ad465ee6f7e9ef38986322ece964d9dd4e5ad9824eb4ebfc26d1e69787b13053"},
|
||||
@@ -4165,10 +3949,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
numba = [
|
||||
{version = "<0.61.0", markers = "python_version < \"3.10\""},
|
||||
{version = ">=0.61.0", markers = "python_version >= \"3.10\""},
|
||||
]
|
||||
numba = {version = ">=0.61.0", markers = "python_version >= \"3.10\""}
|
||||
numpy = ">=1.26.4"
|
||||
pandas = ">=2.2.0"
|
||||
scipy = "<=1.15.3"
|
||||
@@ -4181,7 +3962,6 @@ description = "parse() is the opposite of format()"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "parse-1.20.2-py2.py3-none-any.whl", hash = "sha256:967095588cb802add9177d0c0b6133b5ba33b1ea9007ca800e526f42a85af558"},
|
||||
{file = "parse-1.20.2.tar.gz", hash = "sha256:b41d604d16503c79d81af5165155c0b20f6c8d6c559efa66b4b695c3e5a0a0ce"},
|
||||
@@ -4194,7 +3974,6 @@ description = "Object-oriented paths"
|
||||
optional = false
|
||||
python-versions = "<4.0.0,>=3.7.0"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "pathable-0.4.4-py3-none-any.whl", hash = "sha256:5ae9e94793b6ef5a4cbe0a7ce9dbbefc1eec38df253763fd0aeeacf2762dbbc2"},
|
||||
{file = "pathable-0.4.4.tar.gz", hash = "sha256:6905a3cd17804edfac7875b5f6c9142a218c7caef78693c2dbbbfbac186d88b2"},
|
||||
@@ -4631,7 +4410,6 @@ description = "Settings management using Pydantic"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "pydantic_settings-2.11.0-py3-none-any.whl", hash = "sha256:fe2cea3413b9530d10f3a5875adffb17ada5c1e1bab0b2885546d7310415207c"},
|
||||
{file = "pydantic_settings-2.11.0.tar.gz", hash = "sha256:d0e87a1c7d33593beb7194adb8470fc426e95ba02af83a0f23474a04c9a08180"},
|
||||
@@ -4725,7 +4503,6 @@ description = "A cross-platform clipboard module for Python. (Only handles plain
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273"},
|
||||
{file = "pyperclip-1.11.0.tar.gz", hash = "sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6"},
|
||||
@@ -4832,7 +4609,7 @@ description = "Python for Window Extensions"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["main"]
|
||||
markers = "sys_platform == \"win32\" and (platform_python_implementation != \"PyPy\" or python_version >= \"3.10\")"
|
||||
markers = "sys_platform == \"win32\""
|
||||
files = [
|
||||
{file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"},
|
||||
{file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"},
|
||||
@@ -4883,7 +4660,6 @@ description = "YAML parser and emitter for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"},
|
||||
{file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"},
|
||||
@@ -5174,7 +4950,6 @@ description = "A pure python RFC3339 validator"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"},
|
||||
{file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"},
|
||||
@@ -5209,7 +4984,6 @@ description = "A beautiful reStructuredText renderer for rich"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "rich_rst-1.3.1-py3-none-any.whl", hash = "sha256:498a74e3896507ab04492d326e794c3ef76e7cda078703aa592d1853d91098c1"},
|
||||
{file = "rich_rst-1.3.1.tar.gz", hash = "sha256:fad46e3ba42785ea8c1785e2ceaa56e0ffa32dbe5410dec432f37e4107c4f383"},
|
||||
@@ -5413,62 +5187,6 @@ files = [
|
||||
{file = "ruff-0.13.3.tar.gz", hash = "sha256:5b0ba0db740eefdfbcce4299f49e9eaefc643d4d007749d77d047c2bab19908e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scikit-learn"
|
||||
version = "1.6.1"
|
||||
description = "A set of python modules for machine learning and data mining"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.10\""
|
||||
files = [
|
||||
{file = "scikit_learn-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d056391530ccd1e501056160e3c9673b4da4805eb67eb2bdf4e983e1f9c9204e"},
|
||||
{file = "scikit_learn-1.6.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:0c8d036eb937dbb568c6242fa598d551d88fb4399c0344d95c001980ec1c7d36"},
|
||||
{file = "scikit_learn-1.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8634c4bd21a2a813e0a7e3900464e6d593162a29dd35d25bdf0103b3fce60ed5"},
|
||||
{file = "scikit_learn-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:775da975a471c4f6f467725dff0ced5c7ac7bda5e9316b260225b48475279a1b"},
|
||||
{file = "scikit_learn-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:8a600c31592bd7dab31e1c61b9bbd6dea1b3433e67d264d17ce1017dbdce8002"},
|
||||
{file = "scikit_learn-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:72abc587c75234935e97d09aa4913a82f7b03ee0b74111dcc2881cba3c5a7b33"},
|
||||
{file = "scikit_learn-1.6.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:b3b00cdc8f1317b5f33191df1386c0befd16625f49d979fe77a8d44cae82410d"},
|
||||
{file = "scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc4765af3386811c3ca21638f63b9cf5ecf66261cc4815c1db3f1e7dc7b79db2"},
|
||||
{file = "scikit_learn-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25fc636bdaf1cc2f4a124a116312d837148b5e10872147bdaf4887926b8c03d8"},
|
||||
{file = "scikit_learn-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:fa909b1a36e000a03c382aade0bd2063fd5680ff8b8e501660c0f59f021a6415"},
|
||||
{file = "scikit_learn-1.6.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:926f207c804104677af4857b2c609940b743d04c4c35ce0ddc8ff4f053cddc1b"},
|
||||
{file = "scikit_learn-1.6.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:2c2cae262064e6a9b77eee1c8e768fc46aa0b8338c6a8297b9b6759720ec0ff2"},
|
||||
{file = "scikit_learn-1.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1061b7c028a8663fb9a1a1baf9317b64a257fcb036dae5c8752b2abef31d136f"},
|
||||
{file = "scikit_learn-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e69fab4ebfc9c9b580a7a80111b43d214ab06250f8a7ef590a4edf72464dd86"},
|
||||
{file = "scikit_learn-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:70b1d7e85b1c96383f872a519b3375f92f14731e279a7b4c6cfd650cf5dffc52"},
|
||||
{file = "scikit_learn-1.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2ffa1e9e25b3d93990e74a4be2c2fc61ee5af85811562f1288d5d055880c4322"},
|
||||
{file = "scikit_learn-1.6.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:dc5cf3d68c5a20ad6d571584c0750ec641cc46aeef1c1507be51300e6003a7e1"},
|
||||
{file = "scikit_learn-1.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c06beb2e839ecc641366000ca84f3cf6fa9faa1777e29cf0c04be6e4d096a348"},
|
||||
{file = "scikit_learn-1.6.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8ca8cb270fee8f1f76fa9bfd5c3507d60c6438bbee5687f81042e2bb98e5a97"},
|
||||
{file = "scikit_learn-1.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:7a1c43c8ec9fde528d664d947dc4c0789be4077a3647f232869f41d9bf50e0fb"},
|
||||
{file = "scikit_learn-1.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a17c1dea1d56dcda2fac315712f3651a1fea86565b64b48fa1bc090249cbf236"},
|
||||
{file = "scikit_learn-1.6.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6a7aa5f9908f0f28f4edaa6963c0a6183f1911e63a69aa03782f0d924c830a35"},
|
||||
{file = "scikit_learn-1.6.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0650e730afb87402baa88afbf31c07b84c98272622aaba002559b614600ca691"},
|
||||
{file = "scikit_learn-1.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:3f59fe08dc03ea158605170eb52b22a105f238a5d512c4470ddeca71feae8e5f"},
|
||||
{file = "scikit_learn-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6849dd3234e87f55dce1db34c89a810b489ead832aaf4d4550b7ea85628be6c1"},
|
||||
{file = "scikit_learn-1.6.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e7be3fa5d2eb9be7d77c3734ff1d599151bb523674be9b834e8da6abe132f44e"},
|
||||
{file = "scikit_learn-1.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44a17798172df1d3c1065e8fcf9019183f06c87609b49a124ebdf57ae6cb0107"},
|
||||
{file = "scikit_learn-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b7a3b86e411e4bce21186e1c180d792f3d99223dcfa3b4f597ecc92fa1a422"},
|
||||
{file = "scikit_learn-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:7a73d457070e3318e32bdb3aa79a8d990474f19035464dfd8bede2883ab5dc3b"},
|
||||
{file = "scikit_learn-1.6.1.tar.gz", hash = "sha256:b4fc2525eca2c69a59260f583c56a7557c6ccdf8deafdba6e060f94c1c59738e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
joblib = ">=1.2.0"
|
||||
numpy = ">=1.19.5"
|
||||
scipy = ">=1.6.0"
|
||||
threadpoolctl = ">=3.1.0"
|
||||
|
||||
[package.extras]
|
||||
benchmark = ["matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "pandas (>=1.1.5)"]
|
||||
build = ["cython (>=3.0.10)", "meson-python (>=0.16.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)"]
|
||||
docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.3.4)", "memory_profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "polars (>=0.20.30)", "pooch (>=1.6.0)", "pydata-sphinx-theme (>=0.15.3)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)", "sphinx (>=7.3.7)", "sphinx-copybutton (>=0.5.2)", "sphinx-design (>=0.5.0)", "sphinx-design (>=0.6.0)", "sphinx-gallery (>=0.17.1)", "sphinx-prompt (>=1.4.0)", "sphinx-remove-toctrees (>=1.0.0.post1)", "sphinxcontrib-sass (>=0.3.4)", "sphinxext-opengraph (>=0.9.1)", "towncrier (>=24.8.0)"]
|
||||
examples = ["matplotlib (>=3.3.4)", "pandas (>=1.1.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.17.2)", "seaborn (>=0.9.0)"]
|
||||
install = ["joblib (>=1.2.0)", "numpy (>=1.19.5)", "scipy (>=1.6.0)", "threadpoolctl (>=3.1.0)"]
|
||||
maintenance = ["conda-lock (==2.5.6)"]
|
||||
tests = ["black (>=24.3.0)", "matplotlib (>=3.3.4)", "mypy (>=1.9)", "numpydoc (>=1.2.0)", "pandas (>=1.1.5)", "polars (>=0.20.30)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pyarrow (>=12.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.5.1)", "scikit-image (>=0.17.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "scikit-learn"
|
||||
version = "1.7.2"
|
||||
@@ -5476,7 +5194,6 @@ description = "A set of python modules for machine learning and data mining"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "scikit_learn-1.7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b33579c10a3081d076ab403df4a4190da4f4432d443521674637677dc91e61f"},
|
||||
{file = "scikit_learn-1.7.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:36749fb62b3d961b1ce4fedf08fa57a1986cd409eff2d783bca5d4b9b5fce51c"},
|
||||
@@ -5526,50 +5243,6 @@ install = ["joblib (>=1.2.0)", "numpy (>=1.22.0)", "scipy (>=1.8.0)", "threadpoo
|
||||
maintenance = ["conda-lock (==3.0.1)"]
|
||||
tests = ["matplotlib (>=3.5.0)", "mypy (>=1.15)", "numpydoc (>=1.2.0)", "pandas (>=1.4.0)", "polars (>=0.20.30)", "pooch (>=1.6.0)", "pyamg (>=4.2.1)", "pyarrow (>=12.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.11.7)", "scikit-image (>=0.19.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "scipy"
|
||||
version = "1.13.1"
|
||||
description = "Fundamental algorithms for scientific computing in Python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.10\""
|
||||
files = [
|
||||
{file = "scipy-1.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:20335853b85e9a49ff7572ab453794298bcf0354d8068c5f6775a0eabf350aca"},
|
||||
{file = "scipy-1.13.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d605e9c23906d1994f55ace80e0125c587f96c020037ea6aa98d01b4bd2e222f"},
|
||||
{file = "scipy-1.13.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfa31f1def5c819b19ecc3a8b52d28ffdcc7ed52bb20c9a7589669dd3c250989"},
|
||||
{file = "scipy-1.13.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26264b282b9da0952a024ae34710c2aff7d27480ee91a2e82b7b7073c24722f"},
|
||||
{file = "scipy-1.13.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:eccfa1906eacc02de42d70ef4aecea45415f5be17e72b61bafcfd329bdc52e94"},
|
||||
{file = "scipy-1.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:2831f0dc9c5ea9edd6e51e6e769b655f08ec6db6e2e10f86ef39bd32eb11da54"},
|
||||
{file = "scipy-1.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:27e52b09c0d3a1d5b63e1105f24177e544a222b43611aaf5bc44d4a0979e32f9"},
|
||||
{file = "scipy-1.13.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:54f430b00f0133e2224c3ba42b805bfd0086fe488835effa33fa291561932326"},
|
||||
{file = "scipy-1.13.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e89369d27f9e7b0884ae559a3a956e77c02114cc60a6058b4e5011572eea9299"},
|
||||
{file = "scipy-1.13.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a78b4b3345f1b6f68a763c6e25c0c9a23a9fd0f39f5f3d200efe8feda560a5fa"},
|
||||
{file = "scipy-1.13.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45484bee6d65633752c490404513b9ef02475b4284c4cfab0ef946def50b3f59"},
|
||||
{file = "scipy-1.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:5713f62f781eebd8d597eb3f88b8bf9274e79eeabf63afb4a737abc6c84ad37b"},
|
||||
{file = "scipy-1.13.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5d72782f39716b2b3509cd7c33cdc08c96f2f4d2b06d51e52fb45a19ca0c86a1"},
|
||||
{file = "scipy-1.13.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:017367484ce5498445aade74b1d5ab377acdc65e27095155e448c88497755a5d"},
|
||||
{file = "scipy-1.13.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:949ae67db5fa78a86e8fa644b9a6b07252f449dcf74247108c50e1d20d2b4627"},
|
||||
{file = "scipy-1.13.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de3ade0e53bc1f21358aa74ff4830235d716211d7d077e340c7349bc3542e884"},
|
||||
{file = "scipy-1.13.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2ac65fb503dad64218c228e2dc2d0a0193f7904747db43014645ae139c8fad16"},
|
||||
{file = "scipy-1.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:cdd7dacfb95fea358916410ec61bbc20440f7860333aee6d882bb8046264e949"},
|
||||
{file = "scipy-1.13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:436bbb42a94a8aeef855d755ce5a465479c721e9d684de76bf61a62e7c2b81d5"},
|
||||
{file = "scipy-1.13.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:8335549ebbca860c52bf3d02f80784e91a004b71b059e3eea9678ba994796a24"},
|
||||
{file = "scipy-1.13.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d533654b7d221a6a97304ab63c41c96473ff04459e404b83275b60aa8f4b7004"},
|
||||
{file = "scipy-1.13.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637e98dcf185ba7f8e663e122ebf908c4702420477ae52a04f9908707456ba4d"},
|
||||
{file = "scipy-1.13.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a014c2b3697bde71724244f63de2476925596c24285c7a637364761f8710891c"},
|
||||
{file = "scipy-1.13.1-cp39-cp39-win_amd64.whl", hash = "sha256:392e4ec766654852c25ebad4f64e4e584cf19820b980bc04960bca0b0cd6eaa2"},
|
||||
{file = "scipy-1.13.1.tar.gz", hash = "sha256:095a87a0312b08dfd6a6155cbbd310a8c51800fc931b8c0b84003014b874ed3c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
numpy = ">=1.22.4,<2.3"
|
||||
|
||||
[package.extras]
|
||||
dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy", "pycodestyle", "pydevtool", "rich-click", "ruff", "types-psutil", "typing_extensions"]
|
||||
doc = ["jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.12.0)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0)", "sphinx-design (>=0.4.0)"]
|
||||
test = ["array-api-strict", "asv", "gmpy2", "hypothesis (>=6.30)", "mpmath", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
|
||||
|
||||
[[package]]
|
||||
name = "scipy"
|
||||
version = "1.15.3"
|
||||
@@ -5577,7 +5250,6 @@ description = "Fundamental algorithms for scientific computing in Python"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c"},
|
||||
{file = "scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253"},
|
||||
@@ -5779,11 +5451,9 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""}
|
||||
packaging = ">=20"
|
||||
setuptools = "*"
|
||||
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
|
||||
typing-extensions = {version = "*", markers = "python_version < \"3.10\""}
|
||||
|
||||
[package.extras]
|
||||
docs = ["entangled-cli (>=2.0,<3.0)", "mkdocs", "mkdocs-entangled-plugin", "mkdocs-include-markdown-plugin", "mkdocs-material", "mkdocstrings[python]", "pygments"]
|
||||
@@ -5833,7 +5503,6 @@ description = "SSE plugin for Starlette"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "sse_starlette-3.0.2-py3-none-any.whl", hash = "sha256:16b7cbfddbcd4eaca11f7b586f3b8a080f1afe952c15813455b162edea619e5a"},
|
||||
{file = "sse_starlette-3.0.2.tar.gz", hash = "sha256:ccd60b5765ebb3584d0de2d7a6e4f745672581de4f5005ab31c3a25d10b52b3a"},
|
||||
@@ -5950,7 +5619,7 @@ description = "A lil' TOML parser"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version <= \"3.10\""
|
||||
markers = "python_version == \"3.10\""
|
||||
files = [
|
||||
{file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
|
||||
{file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
|
||||
@@ -6271,7 +5940,6 @@ description = "The comprehensive WSGI web application library."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
markers = "python_version >= \"3.10\""
|
||||
files = [
|
||||
{file = "werkzeug-3.1.1-py3-none-any.whl", hash = "sha256:a71124d1ef06008baafa3d266c02f56e1836a5984afd6dd6c9230669d60d9fb5"},
|
||||
{file = "werkzeug-3.1.1.tar.gz", hash = "sha256:8cd39dfbdfc1e051965f156163e2974e52c210f130810e9ad36858f0fd3edad4"},
|
||||
@@ -6598,5 +6266,5 @@ type = ["pytest-mypy"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = "^3.9.21,<3.14"
|
||||
content-hash = "14ee8d09bc4fb1bbbe43e35cb4612ed4d3e539bd224a8ff1a9e902663df8a189"
|
||||
python-versions = "^3.10,<3.14"
|
||||
content-hash = "5682dcc6dd227aeee333850434b0e6c2da6be9070245718d45d8f02524b53309"
|
||||
|
||||
2
cli/pyproject.toml
vendored
2
cli/pyproject.toml
vendored
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "openbb-cli"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
description = "Investment Research for Everyone, Anywhere."
|
||||
authors = ["OpenBB <hello@openbb.co>"]
|
||||
packages = [{ include = "openbb_cli" }]
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"""Test the Argparse Translator."""
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from datetime import date
|
||||
from typing import Literal
|
||||
|
||||
import pytest
|
||||
from openbb_cli.argparse_translator.argparse_argument import (
|
||||
@@ -10,10 +12,68 @@ from openbb_cli.argparse_translator.argparse_argument import (
|
||||
from openbb_cli.argparse_translator.argparse_translator import (
|
||||
ArgparseTranslator,
|
||||
)
|
||||
from openbb_cli.argparse_translator.reference_processor import (
|
||||
ReferenceToArgumentsProcessor,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
|
||||
# pylint: disable=protected-access
|
||||
# pylint: disable=protected-access,unused-argument
|
||||
|
||||
|
||||
# Test fixtures and helper functions
|
||||
def sample_function(
|
||||
symbol: str,
|
||||
start_date: date | None = None,
|
||||
limit: int = 100,
|
||||
provider: Literal["fmp", "yfinance"] = "fmp",
|
||||
) -> dict:
|
||||
"""Sample function for testing."""
|
||||
return {
|
||||
"symbol": symbol,
|
||||
"start_date": start_date,
|
||||
"limit": limit,
|
||||
"provider": provider,
|
||||
}
|
||||
|
||||
|
||||
def bool_function(
|
||||
symbol: str,
|
||||
adjusted: bool = False,
|
||||
extended_hours: bool | None = None,
|
||||
) -> dict:
|
||||
"""Function with boolean parameters."""
|
||||
return {"symbol": symbol, "adjusted": adjusted, "extended_hours": extended_hours}
|
||||
|
||||
|
||||
def union_function(
|
||||
param1: str | int = "default",
|
||||
param2: str | int | None = None,
|
||||
) -> dict:
|
||||
"""Function with union types."""
|
||||
return {"param1": param1, "param2": param2}
|
||||
|
||||
|
||||
def list_function(
|
||||
symbols: list[str],
|
||||
values: list[int] | None = None,
|
||||
) -> dict:
|
||||
"""Function with list parameters."""
|
||||
return {"symbols": symbols, "values": values}
|
||||
|
||||
|
||||
class CustomData(BaseModel):
|
||||
"""Custom data model for testing."""
|
||||
|
||||
field1: str
|
||||
field2: int = 10
|
||||
|
||||
|
||||
def custom_type_function(data: CustomData) -> dict:
|
||||
"""Function with custom type parameter."""
|
||||
return {"data": data}
|
||||
|
||||
|
||||
# ArgparseArgumentModel Tests
|
||||
def test_custom_argument_action_validation():
|
||||
"""Test that CustomArgument raises an error for invalid actions."""
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
@@ -70,6 +130,7 @@ def test_custom_argument_group():
|
||||
assert group.arguments[0].name == "test"
|
||||
|
||||
|
||||
# ArgparseTranslator Basic Tests
|
||||
def test_argparse_translator_setup():
|
||||
"""Test the ArgparseTranslator setup."""
|
||||
|
||||
@@ -94,3 +155,480 @@ def test_argparse_translator_execution():
|
||||
parsed_args = translator.parser.parse_args(["--test_arg", "3"])
|
||||
result = translator.execute_func(parsed_args)
|
||||
assert result == 6
|
||||
|
||||
|
||||
# ArgparseTranslator Comprehensive Tests
|
||||
def test_basic_translation():
|
||||
"""Test basic function translation."""
|
||||
translator = ArgparseTranslator(sample_function)
|
||||
parser = translator.parser
|
||||
|
||||
actions = {
|
||||
action.dest: action for action in parser._actions if action.dest != "help"
|
||||
}
|
||||
|
||||
assert "symbol" in actions
|
||||
assert "start_date" in actions
|
||||
assert "limit" in actions
|
||||
assert "provider" in actions
|
||||
|
||||
|
||||
def test_required_arguments():
|
||||
"""Test that required arguments are correctly identified."""
|
||||
translator = ArgparseTranslator(sample_function)
|
||||
|
||||
required_actions = [action for action in translator._required._group_actions]
|
||||
assert any(action.dest == "symbol" for action in required_actions)
|
||||
|
||||
|
||||
def test_optional_arguments():
|
||||
"""Test that optional arguments have defaults."""
|
||||
translator = ArgparseTranslator(sample_function)
|
||||
parser = translator.parser
|
||||
|
||||
actions = {action.dest: action for action in parser._actions}
|
||||
|
||||
assert actions["limit"].default == 100
|
||||
assert actions["provider"].default == "fmp"
|
||||
|
||||
|
||||
def test_literal_choices():
|
||||
"""Test that Literal types create choices."""
|
||||
translator = ArgparseTranslator(sample_function)
|
||||
parser = translator.parser
|
||||
|
||||
actions = {action.dest: action for action in parser._actions}
|
||||
assert set(actions["provider"].choices) == {"fmp", "yfinance"} # type: ignore
|
||||
|
||||
|
||||
def test_bool_store_true():
|
||||
"""Test that bool parameters use store_true action."""
|
||||
translator = ArgparseTranslator(bool_function)
|
||||
parser = translator.parser
|
||||
|
||||
actions = {action.dest: action for action in parser._actions}
|
||||
|
||||
# Check the action type by checking the class name
|
||||
assert actions["adjusted"].__class__.__name__ == "_StoreTrueAction"
|
||||
assert actions["extended_hours"].__class__.__name__ == "_StoreTrueAction"
|
||||
|
||||
|
||||
def test_union_type_handling():
|
||||
"""Test Union type handling."""
|
||||
translator = ArgparseTranslator(union_function)
|
||||
parser = translator.parser
|
||||
|
||||
actions = {action.dest: action for action in parser._actions}
|
||||
|
||||
# Should default to str for Union types
|
||||
assert actions["param1"].type is str
|
||||
assert actions["param2"].type is str
|
||||
|
||||
|
||||
def test_pipe_union_type_handling():
|
||||
"""Test pipe union (|) type handling."""
|
||||
translator = ArgparseTranslator(union_function)
|
||||
parser = translator.parser
|
||||
|
||||
actions = {action.dest: action for action in parser._actions}
|
||||
assert "param2" in actions
|
||||
|
||||
|
||||
def test_list_nargs():
|
||||
"""Test that list parameters get nargs='+'."""
|
||||
translator = ArgparseTranslator(list_function)
|
||||
parser = translator.parser
|
||||
|
||||
actions = {action.dest: action for action in parser._actions}
|
||||
|
||||
assert actions["symbols"].nargs == "+"
|
||||
# For Optional[list[int]], it should still have nargs="+" if it's a list type
|
||||
# but the implementation might handle Optional[list] differently
|
||||
# Let's check if it's at least recognized as a list parameter
|
||||
assert "values" in actions
|
||||
|
||||
|
||||
def test_custom_type_flattening():
|
||||
"""Test that custom BaseModel types are flattened."""
|
||||
translator = ArgparseTranslator(custom_type_function)
|
||||
parser = translator.parser
|
||||
|
||||
actions = {action.dest: action for action in parser._actions}
|
||||
|
||||
assert "data__field1" in actions
|
||||
assert "data__field2" in actions
|
||||
assert actions["data__field2"].default == 10
|
||||
|
||||
|
||||
def test_unflatten_args():
|
||||
"""Test unflattening of nested arguments."""
|
||||
args_dict = {
|
||||
"symbol": "AAPL",
|
||||
"data__field1": "value1",
|
||||
"data__field2": 20,
|
||||
}
|
||||
|
||||
result = ArgparseTranslator._unflatten_args(args_dict)
|
||||
|
||||
assert result["symbol"] == "AAPL"
|
||||
assert "data" in result
|
||||
assert result["data"]["field1"] == "value1"
|
||||
assert result["data"]["field2"] == 20
|
||||
|
||||
|
||||
def test_description_cleaning_union():
|
||||
"""Test that Union types are cleaned in descriptions."""
|
||||
|
||||
def func_with_union(param: str | int) -> None:
|
||||
"""Test function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
param : Union[str, int]
|
||||
A parameter description.
|
||||
"""
|
||||
|
||||
translator = ArgparseTranslator(func_with_union)
|
||||
description = translator._build_description(func_with_union.__doc__) # type: ignore
|
||||
|
||||
# The method removes the Parameters section, so we just check it processes without error
|
||||
assert "Union[" not in description
|
||||
|
||||
|
||||
def test_description_cleaning_optional():
|
||||
"""Test that Optional types are cleaned in descriptions."""
|
||||
|
||||
def func_with_optional(param: str | None) -> None:
|
||||
"""Test function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
param : Optional[str]
|
||||
A parameter description.
|
||||
"""
|
||||
|
||||
translator = ArgparseTranslator(func_with_optional)
|
||||
description = translator._build_description(func_with_optional.__doc__) # type: ignore
|
||||
|
||||
# The method removes the Parameters section, so we just check it processes without error
|
||||
assert "Optional[" not in description
|
||||
|
||||
|
||||
def test_description_cleaning_annotated():
|
||||
"""Test that Annotated types are cleaned in descriptions."""
|
||||
|
||||
def func_with_annotated(param: str) -> None:
|
||||
"""Test function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
param : Annotated[str, Field(...)]
|
||||
A parameter description.
|
||||
"""
|
||||
|
||||
translator = ArgparseTranslator(func_with_annotated)
|
||||
description = translator._build_description(func_with_annotated.__doc__) # type: ignore
|
||||
|
||||
assert "Annotated[" not in description
|
||||
assert "Field" not in description
|
||||
|
||||
|
||||
def test_description_cleaning_pipe_union():
|
||||
"""Test that pipe unions (|) are cleaned in descriptions."""
|
||||
|
||||
def func_with_pipe(param: str | int | None) -> None:
|
||||
"""Test function.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
param : str | int | None
|
||||
A parameter description.
|
||||
"""
|
||||
|
||||
translator = ArgparseTranslator(func_with_pipe)
|
||||
description = translator._build_description(func_with_pipe.__doc__) # type: ignore
|
||||
|
||||
# The method removes the Parameters section, so we just check it processes without error
|
||||
assert " | " not in description
|
||||
|
||||
|
||||
def test_custom_argument_groups():
|
||||
"""Test adding custom argument groups."""
|
||||
custom_groups = [
|
||||
ArgparseArgumentGroupModel(
|
||||
name="custom_provider",
|
||||
arguments=[
|
||||
ArgparseArgumentModel(
|
||||
name="custom_param",
|
||||
type=str,
|
||||
dest="custom_param",
|
||||
default="default",
|
||||
required=False,
|
||||
action="store",
|
||||
help="Custom parameter",
|
||||
nargs=None,
|
||||
choices=("a", "b", "c"),
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
translator = ArgparseTranslator(
|
||||
sample_function, custom_argument_groups=custom_groups
|
||||
)
|
||||
parser = translator.parser
|
||||
|
||||
actions = {action.dest: action for action in parser._actions}
|
||||
assert "custom_param" in actions
|
||||
assert set(actions["custom_param"].choices) == {"a", "b", "c"} # type: ignore
|
||||
|
||||
|
||||
def test_provider_parameters_tracking():
|
||||
"""Test that provider parameters are tracked."""
|
||||
custom_groups = [
|
||||
ArgparseArgumentGroupModel(
|
||||
name="provider1",
|
||||
arguments=[
|
||||
ArgparseArgumentModel(
|
||||
name="param1",
|
||||
type=str,
|
||||
dest="param1",
|
||||
default=None,
|
||||
required=False,
|
||||
action="store",
|
||||
help="Provider param",
|
||||
nargs=None,
|
||||
choices=None,
|
||||
)
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
translator = ArgparseTranslator(
|
||||
sample_function, custom_argument_groups=custom_groups
|
||||
)
|
||||
|
||||
assert "provider1" in translator.provider_parameters
|
||||
assert "param1" in translator.provider_parameters["provider1"]
|
||||
|
||||
|
||||
# ReferenceToArgumentsProcessor Tests
|
||||
class TestReferenceToArgumentsProcessor:
|
||||
"""Test the ReferenceToArgumentsProcessor class."""
|
||||
|
||||
def test_parse_type_simple(self):
|
||||
"""Test parsing simple types."""
|
||||
assert ReferenceToArgumentsProcessor._parse_type("str") is str
|
||||
assert ReferenceToArgumentsProcessor._parse_type("int") is int
|
||||
assert ReferenceToArgumentsProcessor._parse_type("float") is float
|
||||
assert ReferenceToArgumentsProcessor._parse_type("bool") is bool
|
||||
|
||||
def test_parse_type_optional(self):
|
||||
"""Test parsing Optional types."""
|
||||
assert ReferenceToArgumentsProcessor._parse_type("Optional[str]") is str
|
||||
assert ReferenceToArgumentsProcessor._parse_type("Optional[int]") is int
|
||||
assert ReferenceToArgumentsProcessor._parse_type("str | None") is str
|
||||
assert ReferenceToArgumentsProcessor._parse_type("int | None") is int
|
||||
|
||||
def test_parse_type_literal(self):
|
||||
"""Test parsing Literal types."""
|
||||
assert ReferenceToArgumentsProcessor._parse_type("Literal['a', 'b']") is str
|
||||
assert (
|
||||
ReferenceToArgumentsProcessor._parse_type("Literal['option1', 'option2']")
|
||||
is str
|
||||
)
|
||||
|
||||
def test_parse_type_annotated(self):
|
||||
"""Test parsing Annotated types."""
|
||||
assert (
|
||||
ReferenceToArgumentsProcessor._parse_type("Annotated[str, Field(...)]")
|
||||
is str
|
||||
)
|
||||
assert (
|
||||
ReferenceToArgumentsProcessor._parse_type("Annotated[int, Field(...)]")
|
||||
is int
|
||||
)
|
||||
|
||||
def test_parse_type_unknown(self):
|
||||
"""Test parsing unknown types defaults to str."""
|
||||
assert ReferenceToArgumentsProcessor._parse_type("UnknownType") is str
|
||||
assert ReferenceToArgumentsProcessor._parse_type("CustomClass") is str
|
||||
|
||||
def test_get_nargs_list(self):
|
||||
"""Test getting nargs for list types."""
|
||||
processor = ReferenceToArgumentsProcessor({})
|
||||
assert processor._get_nargs(list[str]) == "+"
|
||||
assert processor._get_nargs(list[int]) == "+"
|
||||
|
||||
def test_get_nargs_non_list(self):
|
||||
"""Test getting nargs for non-list types."""
|
||||
processor = ReferenceToArgumentsProcessor({})
|
||||
assert processor._get_nargs(str) is None
|
||||
assert processor._get_nargs(int) is None
|
||||
|
||||
def test_get_choices_literal(self):
|
||||
"""Test extracting choices from Literal types."""
|
||||
processor = ReferenceToArgumentsProcessor({})
|
||||
choices = processor._get_choices("Literal['a', 'b', 'c']", custom_choices=None)
|
||||
assert set(choices) == {"a", "b", "c"} # type: ignore
|
||||
|
||||
def test_get_choices_multiple_literals(self):
|
||||
"""Test extracting choices from multiple Literal types."""
|
||||
processor = ReferenceToArgumentsProcessor({})
|
||||
choices = processor._get_choices(
|
||||
"Union[Literal['a', 'b'], Literal['c', 'd']]", custom_choices=None
|
||||
)
|
||||
assert set(choices) == {"a", "b", "c", "d"} # type: ignore
|
||||
|
||||
def test_get_choices_custom(self):
|
||||
"""Test custom choices override Literal choices."""
|
||||
processor = ReferenceToArgumentsProcessor({})
|
||||
custom = ["x", "y", "z"]
|
||||
choices = processor._get_choices("Literal['a', 'b']", custom_choices=custom)
|
||||
assert choices == ("x", "y", "z")
|
||||
|
||||
def test_get_choices_none(self):
|
||||
"""Test no choices when not Literal and no custom."""
|
||||
processor = ReferenceToArgumentsProcessor({})
|
||||
assert processor._get_choices("str", custom_choices=None) is None
|
||||
assert processor._get_choices("int", custom_choices=None) is None
|
||||
|
||||
def test_build_custom_groups(self):
|
||||
"""Test building custom argument groups from reference."""
|
||||
reference = {
|
||||
"/equity/price/historical": {
|
||||
"parameters": {
|
||||
"standard": [],
|
||||
"fmp": [
|
||||
{
|
||||
"name": "interval",
|
||||
"type": "Literal['1min', '5min', '15min']",
|
||||
"description": "Time interval",
|
||||
"default": "1min",
|
||||
"optional": True,
|
||||
"standard": False,
|
||||
"choices": None,
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processor = ReferenceToArgumentsProcessor(reference)
|
||||
groups = processor.custom_groups
|
||||
|
||||
assert "/equity/price/historical" in groups
|
||||
assert len(groups["/equity/price/historical"]) == 1
|
||||
assert groups["/equity/price/historical"][0].name == "fmp"
|
||||
assert len(groups["/equity/price/historical"][0].arguments) == 1
|
||||
|
||||
arg = groups["/equity/price/historical"][0].arguments[0]
|
||||
assert arg.name == "interval"
|
||||
assert arg.type is str
|
||||
assert arg.default == "1min"
|
||||
assert not arg.required
|
||||
assert set(arg.choices) == {"1min", "5min", "15min"} # type: ignore
|
||||
|
||||
def test_build_custom_groups_skip_standard(self):
|
||||
"""Test that standard parameters are skipped."""
|
||||
reference = {
|
||||
"/test/route": {
|
||||
"parameters": {
|
||||
"standard": [],
|
||||
"provider1": [
|
||||
{
|
||||
"name": "param1",
|
||||
"type": "str",
|
||||
"description": "Standard param",
|
||||
"default": None,
|
||||
"optional": True,
|
||||
"standard": True,
|
||||
"choices": None,
|
||||
},
|
||||
{
|
||||
"name": "param2",
|
||||
"type": "int",
|
||||
"description": "Custom param",
|
||||
"default": 10,
|
||||
"optional": False,
|
||||
"standard": False,
|
||||
"choices": None,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processor = ReferenceToArgumentsProcessor(reference)
|
||||
groups = processor.custom_groups
|
||||
|
||||
# Only param2 should be included
|
||||
assert len(groups["/test/route"][0].arguments) == 1
|
||||
assert groups["/test/route"][0].arguments[0].name == "param2"
|
||||
|
||||
def test_build_custom_groups_multiple_providers(self):
|
||||
"""Test building groups for multiple providers."""
|
||||
reference = {
|
||||
"/test/route": {
|
||||
"parameters": {
|
||||
"standard": [],
|
||||
"provider1": [
|
||||
{
|
||||
"name": "param1",
|
||||
"type": "str",
|
||||
"description": "Provider 1 param",
|
||||
"default": None,
|
||||
"optional": True,
|
||||
"standard": False,
|
||||
"choices": None,
|
||||
}
|
||||
],
|
||||
"provider2": [
|
||||
{
|
||||
"name": "param2",
|
||||
"type": "int",
|
||||
"description": "Provider 2 param",
|
||||
"default": 5,
|
||||
"optional": False,
|
||||
"standard": False,
|
||||
"choices": None,
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processor = ReferenceToArgumentsProcessor(reference)
|
||||
groups = processor.custom_groups
|
||||
|
||||
assert len(groups["/test/route"]) == 2
|
||||
provider_names = {group.name for group in groups["/test/route"]}
|
||||
assert provider_names == {"provider1", "provider2"}
|
||||
|
||||
def test_bool_action(self):
|
||||
"""Test that bool types get store_true action."""
|
||||
reference = {
|
||||
"/test/route": {
|
||||
"parameters": {
|
||||
"standard": [],
|
||||
"provider1": [
|
||||
{
|
||||
"name": "flag",
|
||||
"type": "bool",
|
||||
"description": "A boolean flag",
|
||||
"default": False,
|
||||
"optional": True,
|
||||
"standard": False,
|
||||
"choices": None,
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processor = ReferenceToArgumentsProcessor(reference)
|
||||
groups = processor.custom_groups
|
||||
|
||||
arg = groups["/test/route"][0].arguments[0]
|
||||
assert arg.action == "store_true"
|
||||
assert arg.type is None # Should be None for store_true
|
||||
|
||||
Reference in New Issue
Block a user