diff options
author | Danglewood <85772166+deeleeramone@users.noreply.github.com> | 2024-06-20 01:34:23 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-20 08:34:23 +0000 |
commit | 050b15696b65d059ff918622ac46b678efa73323 (patch) | |
tree | f74c340e88e2733a78468f244792882d21f4ebc0 | |
parent | 3e2d8b53d16cdf9c9f2552fd5e7598fb8b05c65d (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
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 |