summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanglewood <85772166+deeleeramone@users.noreply.github.com>2024-06-20 01:34:23 -0700
committerGitHub <noreply@github.com>2024-06-20 08:34:23 +0000
commit050b15696b65d059ff918622ac46b678efa73323 (patch)
treef74c340e88e2733a78468f244792882d21f4ebc0
parent3e2d8b53d16cdf9c9f2552fd5e7598fb8b05c65d (diff)
[Feature] Add Nasdaq To Equity Screener (#6521)
* nasdaq equity screener * commit the limit param * missing test params * the other missing param * sector mapping * fix biztoc
-rw-r--r--openbb_platform/extensions/equity/integration/test_equity_api.py13
-rw-r--r--openbb_platform/extensions/equity/integration/test_equity_python.py13
-rw-r--r--openbb_platform/extensions/news/integration/test_news_api.py6
-rw-r--r--openbb_platform/extensions/news/integration/test_news_python.py6
-rw-r--r--openbb_platform/providers/biztoc/openbb_biztoc/models/world_news.py112
-rw-r--r--openbb_platform/providers/biztoc/openbb_biztoc/utils/helpers.py144
-rw-r--r--openbb_platform/providers/biztoc/poetry.lock326
-rw-r--r--openbb_platform/providers/biztoc/pyproject.toml1
-rw-r--r--openbb_platform/providers/biztoc/tests/record/http/test_biztoc_fetchers/test_biztoc_world_news_fetcher.yaml993
-rw-r--r--openbb_platform/providers/biztoc/tests/test_biztoc_fetchers.py8
-rw-r--r--openbb_platform/providers/nasdaq/openbb_nasdaq/__init__.py2
-rw-r--r--openbb_platform/providers/nasdaq/openbb_nasdaq/models/equity_screener.py490
-rw-r--r--openbb_platform/providers/nasdaq/tests/record/http/test_nasdaq_fetchers/test_nasdaq_equity_screener_fetcher.yaml101
-rw-r--r--openbb_platform/providers/nasdaq/tests/test_nasdaq_fetchers.py11
14 files changed, 1011 insertions, 1215 deletions
diff --git a/openbb_platform/extensions/equity/integration/test_equity_api.py b/openbb_platform/extensions/equity/integration/test_equity_api.py
index 544bb8052b1..fc36d561d4f 100644
--- a/openbb_platform/extensions/equity/integration/test_equity_api.py
+++ b/openbb_platform/extensions/equity/integration/test_equity_api.py
@@ -1462,6 +1462,19 @@ def test_equity_search(params, headers):
"provider": "fmp",
}
),
+ (
+ {
+ "sector": "consumer_staples,consumer_discretionary",
+ "exchange": "all",
+ "exsubcategory": "all",
+ "region": "all",
+ "country": "all",
+ "mktcap": "large",
+ "recommendation": "all",
+ "limit": None,
+ "provider": "nasdaq",
+ }
+ ),
],
)
@pytest.mark.integration
diff --git a/openbb_platform/extensions/equity/integration/test_equity_python.py b/openbb_platform/extensions/equity/integration/test_equity_python.py
index cb836f59019..115d3631700 100644
--- a/openbb_platform/extensions/equity/integration/test_equity_python.py
+++ b/openbb_platform/extensions/equity/integration/test_equity_python.py
@@ -1396,6 +1396,19 @@ def test_equity_search(params, obb):
"provider": "fmp",
}
),
+ (
+ {
+ "sector": "consumer_staples,consumer_discretionary",
+ "exchange": "all",
+ "exsubcategory": "all",
+ "region": "all",
+ "country": "all",
+ "mktcap": "large",
+ "recommendation": "all",
+ "limit": None,
+ "provider": "nasdaq",
+ }
+ ),
],
)
@pytest.mark.integration
diff --git a/openbb_platform/extensions/news/integration/test_news_api.py b/openbb_platform/extensions/news/integration/test_news_api.py
index b54a1f38320..d0e1f5a2fa2 100644
--- a/openbb_platform/extensions/news/integration/test_news_api.py
+++ b/openbb_platform/extensions/news/integration/test_news_api.py
@@ -73,10 +73,8 @@ def headers():
(
{
"provider": "biztoc",
- "filter": "tag",
- "tag": "federalreserve",
- "source": "bloomberg",
- "term": "MSFT",
+ "source": None,
+ "term": "microsoft",
"start_date": None,
"end_date": None,
}
diff --git a/openbb_platform/extensions/news/integration/test_news_python.py b/openbb_platform/extensions/news/integration/test_news_python.py
index 2e9b49b1eeb..f1492d02404 100644
--- a/openbb_platform/extensions/news/integration/test_news_python.py
+++ b/openbb_platform/extensions/news/integration/test_news_python.py
@@ -69,10 +69,8 @@ def obb(pytestconfig): # pylint: disable=inconsistent-return-statements
(
{
"provider": "biztoc",
- "filter": "tag",
- "tag": "federalreserve",
- "source": "bloomberg",
- "term": "MSFT",
+ "source": None,
+ "term": "microsoft",
"start_date": None,
"end_date": None,
}
diff --git a/openbb_platform/providers/biztoc/openbb_biztoc/models/world_news.py b/openbb_platform/providers/biztoc/openbb_biztoc/models/world_news.py
index 8d6d3ae2ea9..43267d77970 100644
--- a/openbb_platform/providers/biztoc/openbb_biztoc/models/world_news.py
+++ b/openbb_platform/providers/biztoc/openbb_biztoc/models/world_news.py
@@ -1,59 +1,47 @@
"""Biztoc World News Model."""
-import warnings
-from datetime import datetime, timedelta
-from typing import Any, Dict, List, Literal, Optional
+# pylint: disable=unused-argument
-from openbb_biztoc.utils.helpers import get_news
+from typing import Any, Dict, List, Optional
+from warnings import warn
+
+from openbb_core.app.model.abstract.error import OpenBBError
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.world_news import (
WorldNewsData,
WorldNewsQueryParams,
)
+from openbb_core.provider.utils.helpers import make_request
from pandas import to_datetime
from pydantic import Field, field_validator
-_warn = warnings.warn
-
class BiztocWorldNewsQueryParams(WorldNewsQueryParams):
"""Biztoc World News Query."""
- filter: Literal["crypto", "hot", "latest", "main", "media", "source", "tag"] = (
- Field(default="latest", description="Filter by type of news.")
- )
- source: str = Field(
- description="Filter by a specific publisher. Only valid when filter is set to source.",
- default="bloomberg",
- )
- tag: Optional[str] = Field(
- description="Tag, topic, to filter articles by. Only valid when filter is set to tag.",
- default=None,
- )
term: Optional[str] = Field(
description="Search term to filter articles by. This overrides all other filters.",
default=None,
)
+ source: Optional[str] = Field(
+ description="Filter by a specific publisher. Only valid when filter is set to source.",
+ default=None,
+ )
class BiztocWorldNewsData(WorldNewsData):
"""Biztoc World News Data."""
__alias_dict__ = {
- "date": "created",
+ "date": "published",
"text": "body",
- "site": "domain",
"images": "img",
}
images: Optional[Dict[str, str]] = Field(
description="Images for the article.", alias="images", default=None
)
- favicon: Optional[str] = Field(
- description="Icon image for the source of the article.", default=None
- )
tags: Optional[List[str]] = Field(description="Tags for the article.", default=None)
- id: Optional[str] = Field(description="Unique Article ID.", default=None)
score: Optional[float] = Field(
description="Search relevance score for the article.", default=None
)
@@ -64,6 +52,12 @@ class BiztocWorldNewsData(WorldNewsData):
"""Return formatted datetime."""
return to_datetime(v).strftime("%Y-%m-%d %H:%M:%S")
+ @field_validator("title")
+ @classmethod
+ def title_validate(cls, v):
+ """Strip empty title text."""
+ return v.strip() if v else None
+
class BiztocWorldNewsFetcher(
Fetcher[
@@ -77,7 +71,7 @@ class BiztocWorldNewsFetcher(
def transform_query(params: Dict[str, Any]) -> BiztocWorldNewsQueryParams:
"""Transform the query."""
if params.get("start_date") or params.get("end_date"):
- _warn("start_date and end_date are not supported for this endpoint.")
+ warn("start_date and end_date are not supported for this endpoint.")
return BiztocWorldNewsQueryParams(**params)
@staticmethod
@@ -88,29 +82,61 @@ class BiztocWorldNewsFetcher(
) -> List[Dict]:
"""Extract the data from the Biztoc endpoint."""
api_key = credentials.get("biztoc_api_key") if credentials else ""
-
- data = get_news(
- api_key=api_key, filter_=query.filter, source=query.source, tag=query.tag, term=query.term # type: ignore
- )
- if query.filter == "hot":
- data = [post for sublist in data for post in sublist["posts"]]
-
- times = {"2 Hours Ago": 2, "4 Hours Ago": 4}
- # Drop 'body_preview' because it is always nan, empty string, or empty string with space.
- for _, item in enumerate(data):
- item.pop("body_preview", None) # Removes 'body_preview' if it exists
- # Adjust 'created' time if necessary
- if item.get("created") in times:
- item["created"] = datetime.now() - timedelta(
- hours=times[item["created"]]
+ headers = {
+ "X-RapidAPI-Key": f"{api_key}",
+ "X-RapidAPI-Host": "biztoc.p.rapidapi.com",
+ "Accept": "application/json",
+ "Accept-Encoding": "gzip",
+ }
+ base_url = "https://biztoc.p.rapidapi.com/"
+ url = ""
+ response: List = []
+ if query.term:
+ query.term = query.term.replace(" ", "%20")
+ url = base_url + f"search?q={query.term}"
+ response = make_request(url, headers=headers).json()
+ if query.source is not None:
+ sources_response = make_request(
+ "https://biztoc.p.rapidapi.com/sources",
+ headers=headers,
+ ).json()
+ sources = [source["id"] for source in sources_response]
+ if query.source.lower() not in sources:
+ raise OpenBBError(
+ f"{query.source} not a valid source. Valid sources: {sources}"
)
+ url = base_url + f"news/source/{query.source.lower()}"
+ response = make_request(url, headers=headers).json()
+ else:
+ url1 = base_url + "news/latest"
+ url2 = base_url + "news/topics"
+ response = make_request(url1, headers=headers).json()
+ response2 = make_request(url2, headers=headers).json()
+ if response2:
+ for topic in response2:
+ stories = topic.get("stories", [])
+ if stories:
+ response.extend(
+ {
+ "text" if k == "body_preview" else k: v
+ for k, v in story.items()
+ }
+ for story in stories
+ )
+
+ return response
- return sorted(data, key=lambda x: x["created"], reverse=True)
-
- # pylint: disable=unused-argument
@staticmethod
def transform_data(
query: BiztocWorldNewsQueryParams, data: List[Dict], **kwargs: Any
) -> List[BiztocWorldNewsData]:
"""Transform the data to the standard format."""
- return [BiztocWorldNewsData.model_validate(d) for d in data[: query.limit]]
+ results: List[BiztocWorldNewsData] = []
+ for item in data:
+ item.pop("id", None)
+ item.pop("uid", None)
+ item.pop("body_preview", None)
+ item.pop("site", None)
+ item.pop("domain", None)
+ results.append(BiztocWorldNewsData.model_validate(item))
+ return results
diff --git a/openbb_platform/providers/biztoc/openbb_biztoc/utils/helpers.py b/openbb_platform/providers/biztoc/openbb_biztoc/utils/helpers.py
deleted file mode 100644
index bfef88972d4..00000000000
--- a/openbb_platform/providers/biztoc/openbb_biztoc/utils/helpers.py
+++ /dev/null
@@ -1,144 +0,0 @@
-"""Biztoc Helpers."""
-
-from datetime import timedelta
-from typing import Dict, List, Literal
-
-import requests
-import requests_cache
-from openbb_core.app.model.abstract.error import OpenBBError
-from openbb_core.app.utils import get_user_cache_directory
-
-# pylint: disable=C0325
-
-cache_dir = get_user_cache_directory()
-
-biztoc_session_tags = requests_cache.CachedSession(
- f"{cache_dir}/http/biztoc_tags", expire_after=timedelta(days=1)
-)
-biztoc_session_sources = requests_cache.CachedSession(
- f"{cache_dir}/http/biztoc_sources", expire_after=timedelta(days=3)
-)
-
-
-def get_sources(api_key: str) -> List[Dict]:
- """Get valid sources for Biztoc queries."""
- headers = {
- "X-RapidAPI-Key": f"{api_key}",
- "X-RapidAPI-Host": "biztoc.p.rapidapi.com",
- "Accept": "application/json",
- "Accept-Encoding": "gzip",
- }
- sources = biztoc_session_sources.get(
- "https://biztoc.p.rapidapi.com/sources", headers=headers, timeout=10
- )
-
- return sources.json()
-
-
-def get_pages(api_key: str) -> List[str]:
- """Get valid pages for Biztoc queries."""
- headers = {
- "X-RapidAPI-Key": f"{api_key}",
- "X-RapidAPI-Host": "biztoc.p.rapidapi.com",
- "Accept": "application/json",
- "Accept-Encoding": "gzip",
- }
- pages = biztoc_session_sources.get(
- "https://biztoc.p.rapidapi.com/pages", headers=headers, timeout=10
- )
- if pages.status_code != 200:
- msg = pages.json().get("message") or pages.text
- raise OpenBBError(f"HTTP error - > {msg}")
-
- return pages.json()
-
-
-def get_tags_by_page(page_id: str, api_key: str) -> List[str]:
- """Get valid tags required for Biztoc queries."""
- headers = {
- "X-RapidAPI-Key": f"{api_key}",
- "X-RapidAPI-Host": "biztoc.p.rapidapi.com",
- "Accept": "application/json",
- "Accept-Encoding": "gzip",
- }
- tags = biztoc_session_tags.get(
- f"https://biztoc.p.rapidapi.com/tags/{page_id}", headers=headers, timeout=10
- )
- if tags.status_code != 200:
- msg = tags.json().get("message") or tags.text
- raise OpenBBError(f"HTTP error - > {msg}")
-
- return tags.json()
-
-
-def get_all_tags(api_key) -> Dict[str, List[str]]:
- """Get all tags for all pages."""
- tags: Dict[str, List[str]] = {}
-
- pages = get_pages(api_key)
- for page in pages:
- page_tags = get_tags_by_page(page, api_key)
- tags.update({page: [x["tag"] for x in page_tags]}) # type: ignore
-
- return tags
-
-
-def get_news(
- api_key: str,
- filter_: Literal[
- "crypto", "hot", "latest", "main", "media", "source", "tag"
- ] = "latest",
- source: str = "bloomberg",
- tag: str = "",
- term: str = "",
-) -> List[Dict]:
- """Call the BizToc API and returns the data."""
- results = []
- term = term.replace(" ", "%20") if term else ""
- _tags = get_all_tags(api_key)
- pages = get_pages(api_key)
- tags = []
- tag = tag.lower() if tag else ""
- for page in pages:
- tags.extend(_tags[page][:])
-
- _sources = get_sources(api_key)
- sources = sorted([i["id"] for i in _sources])
-
- headers = {
- "X-RapidAPI-Key": f"{api_key}",
- "X-RapidAPI-Host": "biztoc.p.rapidapi.com",
- "Accept": "application/json",
- "Accept-Encoding": "gzip",
- }
-
- filter_dict = {
- "hot": "news/hot",
- "latest": "news/latest",
- "crypto": "news/latest/crypto",
- "main": "news/latest/main",
- "media": "news/latest/media",
- "source": f"news/source/{source.lower()}",
- "tag": f"tag/{tag}",
- }
- if filter_ == "source" and source.lower() not in sources:
- raise OpenBBError(f"{source} not a valid source. Valid sources: {sources}")
-
- if filter_ == "tag" and tag.lower().replace(" ", "") not in tags:
- raise OpenBBError(f"{tag} not a valid tag. Valid tags: {tags}")
-
- url = (
- f"https://biztoc.p.rapidapi.com/search?q={term}"
- if term
- else f"https://biztoc.p.rapidapi.com/{filter_dict[filter_]}"
- )
- r = requests.get(url, headers=headers, timeout=5)
- if r.status_code != 200:
- raise OpenBBError(f"HTTP error - > {r.text}")
-
- try:
- results = r.json()
- except Exception as e:
- raise (e)
-
- return results
diff --git a/openbb_platform/providers/biztoc/poetry.lock b/openbb_platform/providers/biztoc/poetry.lock
index 0f2ad166822..1f3f34b20ba 100644
--- a/openbb_platform/providers/biztoc/poetry.lock
+++ b/openbb_platform/providers/biztoc/poetry.lock
@@ -188,31 +188,6 @@ files = [
]
[[package]]
-name = "cattrs"
-version = "23.2.3"
-description = "Composable complex class support for attrs and dataclasses."
-optional = false
-python-versions = ">=3.8"
-files = [
- {file = "cattrs-23.2.3-py3-none-any.whl", hash = "sha256:0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108"},
- {file = "cattrs-23.2.3.tar.gz", hash = "sha256:a934090d95abaa9e911dac357e3a8699e0b4b14f8529bcc7d2b1ad9d51672b9f"},
-]
-
-[package.dependencies]
-attrs = ">=23.1.0"
-exceptiongroup = {version = ">=1.1.1", markers = "python_version < \"3.11\""}
-typing-extensions = {version = ">=4.1.0,<4.6.3 || >4.6.3", markers = "python_version < \"3.11\""}
-
-[package.extras]
-bson = ["pymongo (>=4.4.0)"]
-cbor2 = ["cbor2 (>=5.4.6)"]
-msgpack = ["msgpack (>=1.0.5)"]
-orjson = ["orjson (>=3.9.2)"]
-pyyaml = ["pyyaml (>=6.0)"]
-tomlkit = ["tomlkit (>=0.11.8)"]
-ujson = ["ujson (>=5.7.0)"]
-
-[[package]]
name = "certifi"
version = "2024.6.2"
description = "Python package for providing Mozilla's CA Bundle."
@@ -369,13 +344,13 @@ wmi = ["wmi (>=1.5.1)"]
[[package]]
name = "email-validator"
-version = "2.1.1"
+version = "2.1.2"
description = "A robust email address syntax and deliverability validation library."
optional = false
python-versions = ">=3.8"
files = [
- {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"},
- {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"},
+ {file = "email_validator-2.1.2-py3-none-any.whl", hash = "sha256:d89f6324e13b1e39889eab7f9ca2f91dc9aebb6fa50a6d8bd4329ab50f251115"},
+ {file = "email_validator-2.1.2.tar.gz", hash = "sha256:14c0f3d343c4beda37400421b39fa411bbe33a75df20825df73ad53e06a9f04c"},
]
[package.dependencies]
@@ -951,47 +926,56 @@ files = [
[[package]]
name = "numpy"
-version = "1.26.4"
+version = "2.0.0"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.9"
files = [
- {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"},
- {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"},
- {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"},
- {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"},
- {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"},
- {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"},
- {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"},
- {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"},
- {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"},
- {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"},
- {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"},
- {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"},
- {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"},
- {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"},
- {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"},
- {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"},
- {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"},
- {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"},
- {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"},
- {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"},
- {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"},
- {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"},
- {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"},
- {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"},
- {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"},
- {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"},
- {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"},
- {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"},
- {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"},
- {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"},
- {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"},
- {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"},
- {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"},
- {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"},
- {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"},
- {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"},
+ {file = "numpy-2.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:04494f6ec467ccb5369d1808570ae55f6ed9b5809d7f035059000a37b8d7e86f"},
+ {file = "numpy-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2635dbd200c2d6faf2ef9a0d04f0ecc6b13b3cad54f7c67c61155138835515d2"},
+ {file = "numpy-2.0.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:0a43f0974d501842866cc83471bdb0116ba0dffdbaac33ec05e6afed5b615238"},
+ {file = "numpy-2.0.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:8d83bb187fb647643bd56e1ae43f273c7f4dbcdf94550d7938cfc32566756514"},
+ {file = "numpy-2.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79e843d186c8fb1b102bef3e2bc35ef81160ffef3194646a7fdd6a73c6b97196"},
+ {file = "numpy-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d7696c615765091cc5093f76fd1fa069870304beaccfd58b5dcc69e55ef49c1"},
+ {file = "numpy-2.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b4c76e3d4c56f145d41b7b6751255feefae92edbc9a61e1758a98204200f30fc"},
+ {file = "numpy-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acd3a644e4807e73b4e1867b769fbf1ce8c5d80e7caaef0d90dcdc640dfc9787"},
+ {file = "numpy-2.0.0-cp310-cp310-win32.whl", hash = "sha256:cee6cc0584f71adefe2c908856ccc98702baf95ff80092e4ca46061538a2ba98"},
+ {file = "numpy-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:ed08d2703b5972ec736451b818c2eb9da80d66c3e84aed1deeb0c345fefe461b"},
+ {file = "numpy-2.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad0c86f3455fbd0de6c31a3056eb822fc939f81b1618f10ff3406971893b62a5"},
+ {file = "numpy-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7f387600d424f91576af20518334df3d97bc76a300a755f9a8d6e4f5cadd289"},
+ {file = "numpy-2.0.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:34f003cb88b1ba38cb9a9a4a3161c1604973d7f9d5552c38bc2f04f829536609"},
+ {file = "numpy-2.0.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:b6f6a8f45d0313db07d6d1d37bd0b112f887e1369758a5419c0370ba915b3871"},
+ {file = "numpy-2.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f64641b42b2429f56ee08b4f427a4d2daf916ec59686061de751a55aafa22e4"},
+ {file = "numpy-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7039a136017eaa92c1848152827e1424701532ca8e8967fe480fe1569dae581"},
+ {file = "numpy-2.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:46e161722e0f619749d1cd892167039015b2c2817296104487cd03ed4a955995"},
+ {file = "numpy-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0e50842b2295ba8414c8c1d9d957083d5dfe9e16828b37de883f51fc53c4016f"},
+ {file = "numpy-2.0.0-cp311-cp311-win32.whl", hash = "sha256:2ce46fd0b8a0c947ae047d222f7136fc4d55538741373107574271bc00e20e8f"},
+ {file = "numpy-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd6acc766814ea6443628f4e6751d0da6593dae29c08c0b2606164db026970c"},
+ {file = "numpy-2.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:354f373279768fa5a584bac997de6a6c9bc535c482592d7a813bb0c09be6c76f"},
+ {file = "numpy-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d2f62e55a4cd9c58c1d9a1c9edaedcd857a73cb6fda875bf79093f9d9086f85"},
+ {file = "numpy-2.0.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:1e72728e7501a450288fc8e1f9ebc73d90cfd4671ebbd631f3e7857c39bd16f2"},
+ {file = "numpy-2.0.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:84554fc53daa8f6abf8e8a66e076aff6ece62de68523d9f665f32d2fc50fd66e"},
+ {file = "numpy-2.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c73aafd1afca80afecb22718f8700b40ac7cab927b8abab3c3e337d70e10e5a2"},
+ {file = "numpy-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49d9f7d256fbc804391a7f72d4a617302b1afac1112fac19b6c6cec63fe7fe8a"},
+ {file = "numpy-2.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0ec84b9ba0654f3b962802edc91424331f423dcf5d5f926676e0150789cb3d95"},
+ {file = "numpy-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:feff59f27338135776f6d4e2ec7aeeac5d5f7a08a83e80869121ef8164b74af9"},
+ {file = "numpy-2.0.0-cp312-cp312-win32.whl", hash = "sha256:c5a59996dc618351