summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanglewood <85772166+deeleeramone@users.noreply.github.com>2024-01-20 08:46:25 -0800
committerGitHub <noreply@github.com>2024-01-20 16:46:25 +0000
commit2428d3efe27a56681ff606a0ccf8aaddfeacb516 (patch)
tree5c3e16183a3f8e9853a86a1661f3b8c1212f897d
parentcf5a6417a0476d6aa96086545abbafac10adc31b (diff)
docs/http-requests: Contributor Guide For Building HTTP Requests (#5973)
* contributor guide for http requests * add a docstring * add section on get_querystring * extra space * add note for people installing PyPI in a zsh terminal shell --------- Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com>
-rw-r--r--website/content/platform/development/contributor-guidelines/http_requests.md226
-rw-r--r--website/content/platform/installation.md6
2 files changed, 232 insertions, 0 deletions
diff --git a/website/content/platform/development/contributor-guidelines/http_requests.md b/website/content/platform/development/contributor-guidelines/http_requests.md
new file mode 100644
index 00000000000..d9b14414270
--- /dev/null
+++ b/website/content/platform/development/contributor-guidelines/http_requests.md
@@ -0,0 +1,226 @@
+---
+title: HTTP Requests
+sidebar_position: 2
+description: This guide outlines OpenBB processes for making HTTP requests synchronously and asynchronously. Using the helpers will keep the codebase leaner and easier to maintain by eliminating duplicate processes. Anyone can build effective and efficient data fetchers, this guide outlines how to import and implement either type of request into any fetcher.
+keywords:
+- OpenBB Platform
+- Open source
+- Python interface
+- REST API
+- Code contribution
+- Requests
+- HTTP
+- Async
+- Synchronous
+- provider
+- extension
+- data
+- fetch
+---
+
+import HeadTitle from '@site/src/components/General/HeadTitle.tsx';
+
+<HeadTitle title="HTTP Requests - Contributor Guidelines - Development | OpenBB Platform Docs" />
+
+## Overview
+
+Any function fetching data requires making an outbound HTTP request. Utility functions within the `openbb-core` simplify the procedure for making both asynchronous and synchronous requests. These cover the majority of typical requests and should be imported for use instead of creating a new client from scratch.
+
+Using the helpers will keep the codebase leaner and easier to maintain by eliminating duplicate processes. Anyone can build effective and efficient data fetchers, this guide outlines how to import and implement either type of request into any fetcher.
+
+## Generate Query String
+
+To pass parameters to a URL, they need to be formatted as a query string. The helper function, `get_querystring()`, converts a dictionary of parameters to a standard query URL string.
+
+```python
+from openbb_core.provider.utils.helpers import get_querystring
+```
+
+```python
+ Parameters
+ ----------
+ items: dict
+ The dictionary to be turned into a querystring.
+
+ exclude: List[str]
+ The keys to be excluded from the querystring.
+
+ Returns
+ -------
+ str
+ The querystring.
+```
+
+Within the context of the Fetcher, the "query" object is a Pydantic model. To pass the query parameters to the helper function, apply `model_dump()` to the query object. This removes any key:values where the value is `None`.
+
+There may be parameters that are not intended to be included in the parameters portion of the URL string. Pass those as a `List` to the `exclude` parameter of `get_querystring()`.
+
+```python
+query_string = get_querystring(query.model_dump(), ["interval"])
+```
+
+In the example above, the "base url" is dedicated to the "interval" of the OHLC data. We want to exclude `&interval=1d` from the parameters portion of the final URL. Or, daily/monthly/intraday levels are all different end points from the provider's API.
+
+## Asynchronous vs Synchronous
+
+Every function in the router is asynchronous. This is the only place an asynchronous function *must* be used. Data-fetching router functions all follow the same format.
+
+```python
+@router.command(model="MarketSnapshots")
+async def market_snapshots(
+ cc: CommandContext,
+ provider_choices: ProviderChoices,
+ standard_params: StandardParams,
+ extra_params: ExtraParams,
+) -> OBBject[BaseModel]:
+ """Get a current, complete, market snapshot."""
+ return await OBBject.from_query(Query(**locals()))
+```
+
+The code above executes the endpoint consumed by the user. Each data provider model mapped to the model name in the router decorator could be asynchronous or synchronous.
+
+### Why Async?
+
+An asynchronous fetcher is suitable for data sources demanding multiple queries per command. Options chains, for example, could be served as only a single expiration date, but others will provide the complete chain as a single request.
+
+In the case of the former, dozens of requests, an asynchronous fetcher will dramatically improve performance. The latter is only one request and the code can be simplified as a synchronous process.
+
+Some data providers allow for bulk downloading from a list of symbols, while many do not. It might be desirable to enhance a data source by adding support for bulk downloading. Wrapping it as list of asynchronous tasks makes it an efficient process. The time to download one item should be the same as two because the tasks are carried out concurrently.
+
+Ultimately, the choice is at the discretion of the developer. OpenBB has made the implementation of both methods easy and fast, the next sections will elaborate.
+
+### Synchronous - Requests
+
+```python
+from openbb_core.provider.utils import make_request
+```
+
+This function is an abstract helper to make requests from a URL with potential headers and parameters. It accepts `**kwargs` and returns a `requests.Response` object. If no headers are supplied, it will attempt to use a generic user-agent. Add headers as a dictionary to the `headers` parameter of the query.
+
+All parameters of `requests.get` or `requests.post`are accessible and passed through as `**kwargs`.
+
+```python
+
+ Parameters
+ ----------
+ url : str
+ Url to make the request to
+ method : str, optional
+ HTTP method to use. Can be "GET" or "POST", by default "GET"
+ timeout : int, optional
+ Timeout in seconds, by default 10. Can be overwritten by user setting, request_timeout
+
+ Returns
+ -------
+ requests.Response
+ Request response object
+
+ Raises
+ ------
+ ValueError
+ If invalid method is passed
+```
+
+### Asynchronous - AIOHTTP
+
+Single-URL requests can be made asynchronously. The name of the function now starts with, `a`.
+
+```python
+from openbb_core.provider.utils.helpers import amake_request
+```
+
+This function uses the `aiohttp` client and accepts `kwargs`. It has a default callback function that assumes the content is `json`. No post-request object parsing is required, but this behaviour is overridden with the `response_callback` parameter.
+
+```python
+ Parameters
+ ----------
+ url : str
+ Url to make the request to
+ method : str, optional
+ HTTP method to use. Can be "GET" or "POST", by default "GET"
+ timeout : int, optional
+ Timeout in seconds, by default 10. Can be overwritten by user setting, request_timeout
+ response_callback : Callable[[ClientResponse, ClientSession], Awaitable[Union[dict, List[dict]]]], optional
+ Async callback with response and session as arguments that returns the json, by default None
+ session : ClientSession, optional
+ Custom session to use for requests, by default None
+
+
+ Returns
+ -------
+ Union[dict, List[dict]]
+ Response json
+```
+
+:::tip
+Don't forget to `await`!
+
+```python
+url = "https://someurlwithdata.profit"
+response_json = await amake_requests(url)
+```
+
+Absent `await`, the response is a coroutine - a task waiting to be executed.
+
+:::
+
+### Multi-URL Requests
+
+The helper function becomes plural, `amake_requests`, when fetching for a list of URLs. Under the hood, it is using `asyncio.gather` to perform the tasks concurrently. The same default callback function from `amake_request` exists, only here it appends the expected `json` output to a `List[Dict]`.
+
+```python
+from openbb_core.provider.utils.helpers import amake_requests
+```
+
+```python
+ Parameters
+ ----------
+ urls : Union[str, List[str]]
+ List of urls to make requests to
+ method : Literal["GET", "POST"], optional
+ HTTP method to use. Can be "GET" or "POST", by default "GET"
+ timeout : int, optional
+ Timeout in seconds, by default 10. Can be overwritten by user setting, request_timeout
+ response_callback : Callable[[ClientResponse, ClientSession], Awaitable[Union[dict, List[dict]]]], optional
+ Async callback with response and session as arguments that returns the json, by default None
+ session : ClientSession, optional
+ Custom session to use for requests, by default None
+
+ Returns
+ -------
+ Union[dict, List[dict]]
+ Response json
+```
+
+### Custom Callback
+
+Customize the response parsing by creating a specific callback function. The example below is a method for converting CSV data to a dictionary and appending it to a list.
+
+```python
+from io import StringIO
+from typing import Any
+from pandas import DataFrame
+
+results = []
+
+async def response_callback(response, _: Any):
+ """Callback for HTTP Client Response."""
+ response = await response.text()
+ data = DataFrame(StringIO(response), skiprows=2)
+ results.append(data.to_dict("records"))
+```
+
+### Asynchronous Fetchers
+
+When a Fetcher is asynchronous, the `extract_data` static method needs to be defined accordingly - `aextract_data` instead of `extract_data`.
+
+```python
+ @staticmethod
+ async def aextract_data(
+ query: SourceModelQueryParams,
+ credentials: Optional[Dict[str, str]],
+ **kwargs: Any,
+ ) -> List[Dict]:
+```
+
+These helper functions simplify and standardize the majority of HTTP requests. These helper functions are starting points for building or modifying data provider extensions, and they can also be imported as a standalone utility within any Python session.
diff --git a/website/content/platform/installation.md b/website/content/platform/installation.md
index b7c737a3679..20a1cc2c6ec 100644
--- a/website/content/platform/installation.md
+++ b/website/content/platform/installation.md
@@ -89,6 +89,12 @@ To install all extensions and providers (both officially supported and community
pip install openbb[all]
```
+:::tip
+In a macOS `zsh` Terminal shell, add quotation marks around the library name.
+
+`"openbb[all]"`
+:::
+
To install a single extension:
```console