api-to-dataframe 1.1.0__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {api_to_dataframe-1.1.0 → api_to_dataframe-1.2.0}/PKG-INFO +19 -6
- {api_to_dataframe-1.1.0 → api_to_dataframe-1.2.0}/README.md +17 -4
- {api_to_dataframe-1.1.0 → api_to_dataframe-1.2.0}/pyproject.toml +2 -2
- api_to_dataframe-1.2.0/src/api_to_dataframe/__init__.py +2 -0
- api_to_dataframe-1.2.0/src/api_to_dataframe/controller/client_builder.py +77 -0
- api_to_dataframe-1.2.0/src/api_to_dataframe/models/get_data.py +30 -0
- api_to_dataframe-1.2.0/src/api_to_dataframe/models/retainer.py +30 -0
- api_to_dataframe-1.1.0/src/api_to_dataframe/__init__.py +0 -2
- api_to_dataframe-1.1.0/src/api_to_dataframe/common/utils/retry_strategies.py +0 -9
- api_to_dataframe-1.1.0/src/api_to_dataframe/controller/client_builder.py +0 -52
- api_to_dataframe-1.1.0/src/api_to_dataframe/models/get_data.py +0 -36
- api_to_dataframe-1.1.0/src/api_to_dataframe/models/retainer.py +0 -15
- {api_to_dataframe-1.1.0 → api_to_dataframe-1.2.0}/LICENSE +0 -0
- {api_to_dataframe-1.1.0 → api_to_dataframe-1.2.0}/src/api_to_dataframe/config/config.py +0 -0
- {api_to_dataframe-1.1.0 → api_to_dataframe-1.2.0}/src/api_to_dataframe/views/dataframe_metrics.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: api-to-dataframe
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: A package to convert API responses to pandas dataframe
|
|
5
5
|
Home-page: https://github.com/IvanildoBarauna/api-to-dataframe
|
|
6
6
|
License: MIT
|
|
7
7
|
Author: IvanildoBarauna
|
|
8
8
|
Author-email: ivanildo.jnr@outlook.com
|
|
9
9
|
Requires-Python: >=3.9,<4.0
|
|
10
|
-
Classifier: Development Status ::
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -70,24 +70,37 @@ To install the package using poetry, use the following command:
|
|
|
70
70
|
poetry add api-to-dataframe
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
##
|
|
73
|
+
## User Guide
|
|
74
74
|
|
|
75
75
|
``` python
|
|
76
76
|
## Importing library
|
|
77
77
|
from api_to_dataframe import ClientBuilder, RetryStrategies
|
|
78
78
|
|
|
79
|
-
# Create a client for simple ingest data from API (timeout
|
|
79
|
+
# Create a client for simple ingest data from API (timeout 1 second)
|
|
80
80
|
client = ClientBuilder(endpoint="https://api.example.com")
|
|
81
81
|
|
|
82
|
-
# if you can define timeout
|
|
82
|
+
# if you can define timeout with LinearStrategy and set headers:
|
|
83
83
|
headers = {
|
|
84
84
|
"application_name": "api_to_dataframe"
|
|
85
85
|
}
|
|
86
86
|
client = ClientBuilder(endpoint="https://api.example.com"
|
|
87
87
|
,retry_strategy=RetryStrategies.LinearStrategy
|
|
88
|
-
,
|
|
88
|
+
,connection_timeout=2
|
|
89
89
|
,headers=headers)
|
|
90
90
|
|
|
91
|
+
"""
|
|
92
|
+
NOTE: by default the quantity of retries is 3 and the time between retries is 1 second, but you can define manually, like this:
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
client = ClientBuilder(endpoint="https://api.example.com"
|
|
97
|
+
,retry_strategy=RetryStrategies.LinearStrategy
|
|
98
|
+
,connection_timeout=10
|
|
99
|
+
,headers=headers
|
|
100
|
+
,retries=5
|
|
101
|
+
,delay=10)
|
|
102
|
+
|
|
103
|
+
|
|
91
104
|
### timeout, retry_strategy and headers are opcionals parameters
|
|
92
105
|
|
|
93
106
|
# Get data from the API
|
|
@@ -45,24 +45,37 @@ To install the package using poetry, use the following command:
|
|
|
45
45
|
poetry add api-to-dataframe
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
##
|
|
48
|
+
## User Guide
|
|
49
49
|
|
|
50
50
|
``` python
|
|
51
51
|
## Importing library
|
|
52
52
|
from api_to_dataframe import ClientBuilder, RetryStrategies
|
|
53
53
|
|
|
54
|
-
# Create a client for simple ingest data from API (timeout
|
|
54
|
+
# Create a client for simple ingest data from API (timeout 1 second)
|
|
55
55
|
client = ClientBuilder(endpoint="https://api.example.com")
|
|
56
56
|
|
|
57
|
-
# if you can define timeout
|
|
57
|
+
# if you can define timeout with LinearStrategy and set headers:
|
|
58
58
|
headers = {
|
|
59
59
|
"application_name": "api_to_dataframe"
|
|
60
60
|
}
|
|
61
61
|
client = ClientBuilder(endpoint="https://api.example.com"
|
|
62
62
|
,retry_strategy=RetryStrategies.LinearStrategy
|
|
63
|
-
,
|
|
63
|
+
,connection_timeout=2
|
|
64
64
|
,headers=headers)
|
|
65
65
|
|
|
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
|
+
|
|
66
79
|
### timeout, retry_strategy and headers are opcionals parameters
|
|
67
80
|
|
|
68
81
|
# Get data from the API
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "api-to-dataframe"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.2.0"
|
|
4
4
|
description = "A package to convert API responses to pandas dataframe"
|
|
5
5
|
authors = ["IvanildoBarauna <ivanildo.jnr@outlook.com>"]
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
license = "MIT"
|
|
8
8
|
classifiers=[
|
|
9
|
-
"Development Status ::
|
|
9
|
+
"Development Status :: 3 - Alpha",
|
|
10
10
|
"Intended Audience :: Developers",
|
|
11
11
|
"License :: OSI Approved :: MIT License",
|
|
12
12
|
"Programming Language :: Python :: 3",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from api_to_dataframe.models.retainer import RetryStrategies
|
|
2
|
+
from api_to_dataframe.models.retainer import Strategies
|
|
3
|
+
from api_to_dataframe.models.get_data import GetData
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ClientBuilder:
|
|
7
|
+
def __init__(self,
|
|
8
|
+
endpoint: str,
|
|
9
|
+
headers: dict = None,
|
|
10
|
+
retry_strategy: Strategies = Strategies.NoRetryStrategy,
|
|
11
|
+
retries: int = 3,
|
|
12
|
+
delay: int = 1,
|
|
13
|
+
connection_timeout: int = 1):
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
Initializes the ClientBuilder object.
|
|
17
|
+
|
|
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.
|
|
25
|
+
|
|
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.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
if headers is None:
|
|
34
|
+
headers = {}
|
|
35
|
+
if endpoint == "":
|
|
36
|
+
raise ValueError("::: endpoint param is mandatory :::")
|
|
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
|
|
50
|
+
|
|
51
|
+
@RetryStrategies
|
|
52
|
+
def get_api_data(self):
|
|
53
|
+
"""
|
|
54
|
+
Retrieves data from the API using the defined endpoint and retry strategy.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
dict: The response from the API.
|
|
58
|
+
"""
|
|
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
|
+
)
|
|
72
|
+
return response
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def api_to_dataframe(response: dict):
|
|
76
|
+
df = GetData.to_dataframe(response)
|
|
77
|
+
return df
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from requests.exceptions import HTTPError, Timeout
|
|
3
|
+
import pandas as pd
|
|
4
|
+
|
|
5
|
+
# from api_to_dataframe.common.utils.retry_strategies import RetryStrategies
|
|
6
|
+
from api_to_dataframe.models.retainer import RetryStrategies
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class GetData:
|
|
10
|
+
@staticmethod
|
|
11
|
+
def get_response(endpoint: str,
|
|
12
|
+
headers: dict,
|
|
13
|
+
connection_timeout: int):
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
response = requests.get(endpoint, timeout=connection_timeout, headers=headers)
|
|
18
|
+
response.raise_for_status()
|
|
19
|
+
return response
|
|
20
|
+
@staticmethod
|
|
21
|
+
def to_dataframe(response):
|
|
22
|
+
try:
|
|
23
|
+
df = pd.DataFrame(response)
|
|
24
|
+
except Exception as err:
|
|
25
|
+
raise TypeError(f"Invalid response for transform in dataframe: {err}")
|
|
26
|
+
|
|
27
|
+
if df.empty:
|
|
28
|
+
raise ValueError("::: DataFrame is empty :::")
|
|
29
|
+
else:
|
|
30
|
+
return df
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from enum import Enum
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Strategies(Enum):
|
|
6
|
+
NoRetryStrategy = 0
|
|
7
|
+
LinearRetryStrategy = 1
|
|
8
|
+
ExponentialRetryStrategy = 2
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def RetryStrategies(func):
|
|
12
|
+
def wrapper(*args, **kwargs):
|
|
13
|
+
retry_number = 0
|
|
14
|
+
while retry_number < args[0].retries:
|
|
15
|
+
try:
|
|
16
|
+
return func(*args, **kwargs)
|
|
17
|
+
except Exception as e:
|
|
18
|
+
retry_number += 1
|
|
19
|
+
|
|
20
|
+
if args[0].retry_strategy == Strategies.NoRetryStrategy:
|
|
21
|
+
raise e
|
|
22
|
+
elif args[0].retry_strategy == Strategies.LinearRetryStrategy:
|
|
23
|
+
time.sleep(args[0].delay)
|
|
24
|
+
elif args[0].retry_strategy == Strategies.ExponentialRetryStrategy:
|
|
25
|
+
time.sleep(args[0].delay * 2 ** retry_number)
|
|
26
|
+
|
|
27
|
+
if retry_number == args[0].retries:
|
|
28
|
+
print(f"Failed after {retry_number} retries using {args[0].retry_strategy}")
|
|
29
|
+
raise e
|
|
30
|
+
return wrapper
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
from api_to_dataframe.common.utils.retry_strategies import RetryStrategies
|
|
2
|
-
from api_to_dataframe.models.get_data import GetData
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class ClientBuilder:
|
|
6
|
-
def __init__(self,
|
|
7
|
-
endpoint: str,
|
|
8
|
-
headers: dict = {},
|
|
9
|
-
retry_strategy: RetryStrategies = RetryStrategies.NoRetryStrategy,
|
|
10
|
-
timeout: int = 5):
|
|
11
|
-
"""
|
|
12
|
-
Initializes an instance of ClientBuilder.
|
|
13
|
-
|
|
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
|
-
|
|
19
|
-
Raises:
|
|
20
|
-
ValueError: If the endpoint is empty.
|
|
21
|
-
"""
|
|
22
|
-
if endpoint == "":
|
|
23
|
-
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
|
|
29
|
-
|
|
30
|
-
def get_api_data(self):
|
|
31
|
-
"""
|
|
32
|
-
Retrieves data from the API using the defined endpoint and retry strategy.
|
|
33
|
-
|
|
34
|
-
Returns:
|
|
35
|
-
dict: The response from the API.
|
|
36
|
-
"""
|
|
37
|
-
response = GetData.get_response(self.endpoint, self.headers, self.retry_strategy, self.timeout)
|
|
38
|
-
return response
|
|
39
|
-
|
|
40
|
-
@staticmethod
|
|
41
|
-
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
|
-
"""
|
|
51
|
-
df = GetData.to_dataframe(response)
|
|
52
|
-
return df
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
from requests.exceptions import HTTPError, Timeout, RequestException
|
|
3
|
-
import pandas as pd
|
|
4
|
-
|
|
5
|
-
from api_to_dataframe.common.utils.retry_strategies import RetryStrategies
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class GetData:
|
|
9
|
-
@staticmethod
|
|
10
|
-
def get_response(endpoint: str,
|
|
11
|
-
headers: dict,
|
|
12
|
-
retry_strategies: RetryStrategies,
|
|
13
|
-
timeout: int):
|
|
14
|
-
try:
|
|
15
|
-
response = requests.get(endpoint, timeout=timeout, headers=headers)
|
|
16
|
-
response.raise_for_status()
|
|
17
|
-
except HTTPError as http_err:
|
|
18
|
-
print(f'HTTP error occurred: {http_err}')
|
|
19
|
-
raise http_err
|
|
20
|
-
except Timeout as timeout_err:
|
|
21
|
-
print(f'Timeout error occurred: {timeout_err}')
|
|
22
|
-
raise timeout_err
|
|
23
|
-
else:
|
|
24
|
-
return response
|
|
25
|
-
|
|
26
|
-
@staticmethod
|
|
27
|
-
def to_dataframe(response):
|
|
28
|
-
try:
|
|
29
|
-
df = pd.DataFrame(response.json())
|
|
30
|
-
except Exception as err:
|
|
31
|
-
raise TypeError(f"Invalid response for transform in dataframe: {err}")
|
|
32
|
-
|
|
33
|
-
if df.empty:
|
|
34
|
-
raise ValueError("::: DataFrame is empty :::")
|
|
35
|
-
else:
|
|
36
|
-
return df
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
from api_to_dataframe.common.utils.retry_strategies import RetryStrategies
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Retainer:
|
|
5
|
-
@staticmethod
|
|
6
|
-
def strategy(retry_strategy: RetryStrategies = RetryStrategies.NoRetryStrategy):
|
|
7
|
-
if retry_strategy == RetryStrategies.NoRetryStrategy:
|
|
8
|
-
print("::: NoRetryStrategy :::")
|
|
9
|
-
elif retry_strategy == RetryStrategies.LinearStrategy:
|
|
10
|
-
print("::: LinearStrategy :::")
|
|
11
|
-
elif retry_strategy == RetryStrategies.ExponentialStrategy:
|
|
12
|
-
print("::: ExponentialStrategy :::")
|
|
13
|
-
elif retry_strategy == RetryStrategies.CustomStrategy:
|
|
14
|
-
print("::: CustomStrategy :::")
|
|
15
|
-
|
|
File without changes
|
|
File without changes
|
{api_to_dataframe-1.1.0 → api_to_dataframe-1.2.0}/src/api_to_dataframe/views/dataframe_metrics.py
RENAMED
|
File without changes
|