Skip to content

Commit b2532ca

Browse files
Merge pull request #44 from IvanildoBarauna/feat-RetryStrategies
feat: Initial development of Retry Strategies
2 parents 84c0335 + 7011b6d commit b2532ca

File tree

12 files changed

+331
-163
lines changed

12 files changed

+331
-163
lines changed

.idea/api-to-dataframe.iml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,37 @@ To install the package using poetry, use the following command:
4545
poetry add api-to-dataframe
4646
```
4747

48-
## How to use it
48+
## User Guide
4949

5050
``` python
5151
## Importing library
5252
from api_to_dataframe import ClientBuilder, RetryStrategies
5353

54-
# Create a client for simple ingest data from API (timeout 5 seconds)
54+
# Create a client for simple ingest data from API (timeout 1 second)
5555
client = ClientBuilder(endpoint="https://api.example.com")
5656

57-
# if you can define timeout, use: (default is 5 seconds), with LinearStrategy (In development, actually don't nothing) and set headers:
57+
# if you can define timeout with LinearStrategy and set headers:
5858
headers = {
5959
"application_name": "api_to_dataframe"
6060
}
6161
client = ClientBuilder(endpoint="https://api.example.com"
6262
,retry_strategy=RetryStrategies.LinearStrategy
63-
,timeout=10
63+
,connection_timeout=2
6464
,headers=headers)
6565

66+
"""
67+
NOTE: by default the quantity of retries is 3 and the time between retries is 1 second, but you can define manually, like this:
68+
69+
"""
70+
71+
client = ClientBuilder(endpoint="https://api.example.com"
72+
,retry_strategy=RetryStrategies.LinearStrategy
73+
,connection_timeout=10
74+
,headers=headers
75+
,retries=5
76+
,delay=10)
77+
78+
6679
### timeout, retry_strategy and headers are opcionals parameters
6780

6881
# Get data from the API

notebooks/example.ipynb

Lines changed: 115 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,135 @@
11
{
22
"cells": [
33
{
4-
"cell_type": "code",
5-
"execution_count": 1,
64
"metadata": {},
7-
"outputs": [
8-
{
9-
"name": "stdout",
10-
"output_type": "stream",
11-
"text": [
12-
"Defaulting to user installation because normal site-packages is not writeable\n",
13-
"Collecting api-to-dataframe\n",
14-
" Downloading api_to_dataframe-0.0.3-py3-none-any.whl (4.0 kB)\n",
15-
"Collecting coverage<8.0.0,>=7.5.3\n",
16-
" Using cached coverage-7.5.3-cp39-cp39-macosx_10_9_x86_64.whl (204 kB)\n",
17-
"Collecting pytest<9.0.0,>=8.2.2\n",
18-
" Downloading pytest-8.2.2-py3-none-any.whl (339 kB)\n",
19-
"\u001b[K |████████████████████████████████| 339 kB 7.5 MB/s eta 0:00:01\n",
20-
"\u001b[?25hCollecting tomli>=1\n",
21-
" Using cached tomli-2.0.1-py3-none-any.whl (12 kB)\n",
22-
"Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /Users/ivsouza/Library/Python/3.9/lib/python/site-packages (from pytest<9.0.0,>=8.2.2->api-to-dataframe) (1.2.0)\n",
23-
"Requirement already satisfied: packaging in /Users/ivsouza/Library/Python/3.9/lib/python/site-packages (from pytest<9.0.0,>=8.2.2->api-to-dataframe) (23.2)\n",
24-
"Collecting iniconfig\n",
25-
" Using cached iniconfig-2.0.0-py3-none-any.whl (5.9 kB)\n",
26-
"Collecting pluggy<2.0,>=1.5\n",
27-
" Using cached pluggy-1.5.0-py3-none-any.whl (20 kB)\n",
28-
"Installing collected packages: tomli, pluggy, iniconfig, pytest, coverage, api-to-dataframe\n",
29-
"Successfully installed api-to-dataframe-0.0.3 coverage-7.5.3 iniconfig-2.0.0 pluggy-1.5.0 pytest-8.2.2 tomli-2.0.1\n",
30-
"\u001b[33mWARNING: You are using pip version 21.2.4; however, version 24.0 is available.\n",
31-
"You should consider upgrading via the '/Library/Developer/CommandLineTools/usr/bin/python3 -m pip install --upgrade pip' command.\u001b[0m\n",
32-
"Note: you may need to restart the kernel to use updated packages.\n"
33-
]
34-
}
35-
],
5+
"cell_type": "markdown",
366
"source": [
37-
"pip install api-to-dataframe"
7+
"## Case use - Using Linear Strategy\n",
8+
"For more examples see [User Guide on README](https://github.com/IvanildoBarauna/api-to-dataframe/blob/main/README.md#how-to-use-it)\n",
9+
"\n",
10+
"NOTE: Before ensure that api-to-dataframe is installed as a dependency, see how to do this [here](https://github.com/IvanildoBarauna/api-to-dataframe/blob/main/README.md#installation)"
3811
]
3912
},
4013
{
41-
"cell_type": "code",
42-
"execution_count": 2,
4314
"metadata": {},
44-
"outputs": [
45-
{
46-
"name": "stdout",
47-
"output_type": "stream",
48-
"text": [
49-
"Defaulting to user installation because normal site-packages is not writeable\n",
50-
"\u001b[31mERROR: You must give at least one requirement to install (see \"pip help install\")\u001b[0m\n",
51-
"\u001b[33mWARNING: You are using pip version 21.2.4; however, version 24.0 is available.\n",
52-
"You should consider upgrading via the '/Library/Developer/CommandLineTools/usr/bin/python3 -m pip install --upgrade pip' command.\u001b[0m\n",
53-
"Note: you may need to restart the kernel to use updated packages.\n"
54-
]
55-
}
56-
],
57-
"source": [
58-
"pip install --upgrade "
59-
]
15+
"cell_type": "markdown",
16+
"source": ""
6017
},
6118
{
62-
"cell_type": "code",
63-
"execution_count": 10,
64-
"metadata": {},
65-
"outputs": [
66-
{
67-
"ename": "AttributeError",
68-
"evalue": "'ApiToDataframe' object has no attribute 'name'",
69-
"output_type": "error",
70-
"traceback": [
71-
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
72-
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
73-
"Cell \u001b[0;32mIn[10], line 5\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mapi_to_dataframe\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m ApiToDataframe\n\u001b[1;32m 3\u001b[0m new \u001b[38;5;241m=\u001b[39m ApiToDataframe\u001b[38;5;241m.\u001b[39mApiToDataframe(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIvanildo\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m----> 5\u001b[0m \u001b[43mnew\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msay_hello\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
74-
"File \u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/api_to_dataframe/run.py:6\u001b[0m, in \u001b[0;36mApiToDataframe.say_hello\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21msay_hello\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mHello \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n",
75-
"\u001b[0;31mAttributeError\u001b[0m: 'ApiToDataframe' object has no attribute 'name'"
76-
]
19+
"metadata": {
20+
"ExecuteTime": {
21+
"end_time": "2024-06-21T04:14:54.199749Z",
22+
"start_time": "2024-06-21T04:14:54.124358Z"
7723
}
78-
],
24+
},
25+
"cell_type": "code",
7926
"source": [
80-
"from api_to_dataframe import ApiToDataframe\n",
27+
"from api_to_dataframe import ClientBuilder, RetryStrategies\n",
8128
"\n",
82-
"new = ApiToDataframe.ApiToDataframe(\"Ivanildo\")\n",
29+
"client = ClientBuilder(\n",
30+
" endpoint=\"https://brasilapi.com.br/api/banks/v1\",\n",
31+
" retry_strategy=RetryStrategies.LinearRetryStrategy,\n",
32+
" retries=3,\n",
33+
" connection_timeout=1,\n",
34+
" delay=1)\n",
8335
"\n",
84-
"new.say_hello()\n",
36+
"## Get response.json\n",
37+
"api_data = client.get_api_data()\n",
8538
"\n",
39+
"df = client.api_to_dataframe(api_data)\n",
8640
"\n",
87-
"\n"
88-
]
89-
},
90-
{
91-
"cell_type": "code",
92-
"execution_count": null,
93-
"metadata": {},
94-
"outputs": [],
95-
"source": []
41+
"df.head()"
42+
],
43+
"outputs": [
44+
{
45+
"data": {
46+
"text/plain": [
47+
" ispb name code \\\n",
48+
"0 00000000 BCO DO BRASIL S.A. 1.0 \n",
49+
"1 00000208 BRB - BCO DE BRASILIA S.A. 70.0 \n",
50+
"2 00038121 Selic NaN \n",
51+
"3 00038166 Bacen NaN \n",
52+
"4 00122327 SANTINVEST S.A. - CFI 539.0 \n",
53+
"\n",
54+
" fullName \n",
55+
"0 Banco do Brasil S.A. \n",
56+
"1 BRB - BANCO DE BRASILIA S.A. \n",
57+
"2 Banco Central do Brasil - Selic \n",
58+
"3 Banco Central do Brasil \n",
59+
"4 SANTINVEST S.A. - CREDITO, FINANCIAMENTO E INV... "
60+
],
61+
"text/html": [
62+
"<div>\n",
63+
"<style scoped>\n",
64+
" .dataframe tbody tr th:only-of-type {\n",
65+
" vertical-align: middle;\n",
66+
" }\n",
67+
"\n",
68+
" .dataframe tbody tr th {\n",
69+
" vertical-align: top;\n",
70+
" }\n",
71+
"\n",
72+
" .dataframe thead th {\n",
73+
" text-align: right;\n",
74+
" }\n",
75+
"</style>\n",
76+
"<table border=\"1\" class=\"dataframe\">\n",
77+
" <thead>\n",
78+
" <tr style=\"text-align: right;\">\n",
79+
" <th></th>\n",
80+
" <th>ispb</th>\n",
81+
" <th>name</th>\n",
82+
" <th>code</th>\n",
83+
" <th>fullName</th>\n",
84+
" </tr>\n",
85+
" </thead>\n",
86+
" <tbody>\n",
87+
" <tr>\n",
88+
" <th>0</th>\n",
89+
" <td>00000000</td>\n",
90+
" <td>BCO DO BRASIL S.A.</td>\n",
91+
" <td>1.0</td>\n",
92+
" <td>Banco do Brasil S.A.</td>\n",
93+
" </tr>\n",
94+
" <tr>\n",
95+
" <th>1</th>\n",
96+
" <td>00000208</td>\n",
97+
" <td>BRB - BCO DE BRASILIA S.A.</td>\n",
98+
" <td>70.0</td>\n",
99+
" <td>BRB - BANCO DE BRASILIA S.A.</td>\n",
100+
" </tr>\n",
101+
" <tr>\n",
102+
" <th>2</th>\n",
103+
" <td>00038121</td>\n",
104+
" <td>Selic</td>\n",
105+
" <td>NaN</td>\n",
106+
" <td>Banco Central do Brasil - Selic</td>\n",
107+
" </tr>\n",
108+
" <tr>\n",
109+
" <th>3</th>\n",
110+
" <td>00038166</td>\n",
111+
" <td>Bacen</td>\n",
112+
" <td>NaN</td>\n",
113+
" <td>Banco Central do Brasil</td>\n",
114+
" </tr>\n",
115+
" <tr>\n",
116+
" <th>4</th>\n",
117+
" <td>00122327</td>\n",
118+
" <td>SANTINVEST S.A. - CFI</td>\n",
119+
" <td>539.0</td>\n",
120+
" <td>SANTINVEST S.A. - CREDITO, FINANCIAMENTO E INV...</td>\n",
121+
" </tr>\n",
122+
" </tbody>\n",
123+
"</table>\n",
124+
"</div>"
125+
]
126+
},
127+
"execution_count": 21,
128+
"metadata": {},
129+
"output_type": "execute_result"
130+
}
131+
],
132+
"execution_count": 21
96133
}
97134
],
98135
"metadata": {

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[tool.poetry]
22
name = "api-to-dataframe"
3-
version = "1.1.0"
3+
version = "1.2.0"
44
description = "A package to convert API responses to pandas dataframe"
55
authors = ["IvanildoBarauna <ivanildo.jnr@outlook.com>"]
66
readme = "README.md"
77
license = "MIT"
88
classifiers=[
9-
"Development Status :: 2 - Pre-Alpha",
9+
"Development Status :: 3 - Alpha",
1010
"Intended Audience :: Developers",
1111
"License :: OSI Approved :: MIT License",
1212
"Programming Language :: Python :: 3",

src/api_to_dataframe/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
from .controller.client_builder import ClientBuilder
2-
from .common.utils.retry_strategies import RetryStrategies
2+
from .models.retainer import Strategies as RetryStrategies

src/api_to_dataframe/common/utils/retry_strategies.py

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,77 @@
1-
from api_to_dataframe.common.utils.retry_strategies import RetryStrategies
1+
from api_to_dataframe.models.retainer import RetryStrategies
2+
from api_to_dataframe.models.retainer import Strategies
23
from api_to_dataframe.models.get_data import GetData
34

45

56
class ClientBuilder:
67
def __init__(self,
78
endpoint: str,
8-
headers: dict = {},
9-
retry_strategy: RetryStrategies = RetryStrategies.NoRetryStrategy,
10-
timeout: int = 5):
9+
headers: dict = None,
10+
retry_strategy: Strategies = Strategies.NoRetryStrategy,
11+
retries: int = 3,
12+
delay: int = 1,
13+
connection_timeout: int = 1):
14+
1115
"""
12-
Initializes an instance of ClientBuilder.
16+
Initializes the ClientBuilder object.
1317
14-
Args:
15-
endpoint (str): The API endpoint to be accessed.
16-
retry_strategy (RetryStrategies, optional): The retry strategy for the request. Default is NoRetryStrategy.
17-
timeout (int, optional): The timeout for the request. Default is 5 seconds.
18+
Args:
19+
endpoint (str): The API endpoint to connect to.
20+
headers (dict, optional): The headers to use for the API request. Defaults to None.
21+
retry_strategy (Strategies, optional): The strategy to use for retrying failed requests. Defaults to Strategies.NoRetryStrategy.
22+
retries (int, optional): The number of times to retry a failed request. Defaults to 3.
23+
delay (int, optional): The delay between retries in seconds. Defaults to 1.
24+
connection_timeout (int, optional): The timeout for the connection in seconds. Defaults to 2.
1825
19-
Raises:
20-
ValueError: If the endpoint is empty.
26+
Raises:
27+
ValueError: If endpoint is an empty string.
28+
ValueError: If retries is not a non-negative integer.
29+
ValueError: If delay is not a non-negative integer.
30+
ValueError: If connection_timeout is not a non-negative integer.
2131
"""
32+
33+
if headers is None:
34+
headers = {}
2235
if endpoint == "":
2336
raise ValueError("::: endpoint param is mandatory :::")
24-
else:
25-
self.endpoint = endpoint
26-
self.retry_strategy = retry_strategy
27-
self.timeout = timeout
28-
self.headers = headers
37+
if not isinstance(retries, int) or retries < 0:
38+
raise ValueError("retries must be a non-negative integer")
39+
if not isinstance(delay, int) or delay < 0:
40+
raise ValueError("delay must be a non-negative integer")
41+
if not isinstance(connection_timeout, int) or connection_timeout < 0:
42+
raise ValueError("connection_timeout must be a non-negative integer")
43+
44+
self.endpoint = endpoint
45+
self.retry_strategy = retry_strategy
46+
self.connection_timeout = connection_timeout
47+
self.headers = headers
48+
self.retries = retries
49+
self.delay = delay
2950

51+
@RetryStrategies
3052
def get_api_data(self):
3153
"""
3254
Retrieves data from the API using the defined endpoint and retry strategy.
3355
3456
Returns:
3557
dict: The response from the API.
3658
"""
37-
response = GetData.get_response(self.endpoint, self.headers, self.retry_strategy, self.timeout)
59+
response = GetData.get_response(
60+
endpoint=self.endpoint,
61+
headers=self.headers,
62+
connection_timeout=self.connection_timeout
63+
)
64+
return response.json()
65+
66+
def _get_raw_api_data(self):
67+
response = GetData.get_response(
68+
endpoint=self.endpoint,
69+
headers=self.headers,
70+
connection_timeout=self.connection_timeout
71+
)
3872
return response
3973

4074
@staticmethod
4175
def api_to_dataframe(response: dict):
42-
"""
43-
Converts the API response into a DataFrame.
44-
45-
Args:
46-
response (dict): The response from the API.
47-
48-
Returns:
49-
DataFrame: The data converted into a DataFrame.
50-
"""
5176
df = GetData.to_dataframe(response)
5277
return df

0 commit comments

Comments
 (0)