api-to-dataframe 2.0.6__tar.gz → 2.1.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.
@@ -1,22 +1,20 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: api-to-dataframe
3
- Version: 2.0.6
3
+ Version: 2.1.0
4
4
  Summary: A package to convert API responses to pandas dataframe
5
5
  License: MIT
6
6
  Author: IvanildoBarauna
7
7
  Author-email: ivanildo.jnr@outlook.com
8
- Requires-Python: >=3.9,<4.0
8
+ Requires-Python: >=3.10,<4.0
9
9
  Classifier: Development Status :: 5 - Production/Stable
10
10
  Classifier: Intended Audience :: Developers
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.9
14
13
  Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
16
15
  Classifier: Programming Language :: Python :: 3.8
17
- Requires-Dist: logging (>=0.4.9.6,<0.5.0.0)
18
16
  Requires-Dist: pandas (>=2.2.3,<3.0.0)
19
- Requires-Dist: requests (>=2.32.3,<3.0.0)
17
+ Requires-Dist: requests (>=2.33.0,<3.0.0)
20
18
  Project-URL: Documentation, https://github.com/IvanildoBarauna/api-to-dataframe/blob/main/README.md
21
19
  Project-URL: Homepage, https://pypi.org/project/api-to-dataframe
22
20
  Project-URL: ImplementationCase, https://github.com/IvanildoBarauna/ETL-awesome-api
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "api-to-dataframe"
3
- version = "2.0.6"
3
+ version = "2.1.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"
@@ -23,18 +23,17 @@ Issues = "https://github.com/IvanildoBarauna/api-to-dataframe/issues"
23
23
  Repository = "https://github.com/IvanildoBarauna/api-to-dataframe"
24
24
 
25
25
  [tool.poetry.dependencies]
26
- python = "^3.9"
26
+ python = "^3.10"
27
27
  pandas = "^2.2.3"
28
- requests = "^2.32.3"
29
- logging = "^0.4.9.6"
28
+ requests = "^2.33.0"
30
29
 
31
30
  [tool.poetry.group.dev.dependencies]
32
31
  poetry-dynamic-versioning = "^1.3.0"
33
- pytest = "^8.2.2"
32
+ pytest = "^9.0.3"
34
33
  coverage = "^7.5.3"
35
34
  responses = ">=0.25.3,<0.27.0"
36
35
  pylint = "^3.2.5"
37
- black = "^24.4.2"
36
+ black = "^26.3.1"
38
37
  pytest-cov = "^7.0.0"
39
38
 
40
39
 
@@ -7,11 +7,11 @@ class ClientBuilder:
7
7
  def __init__( # pylint: disable=too-many-positional-arguments,too-many-arguments
8
8
  self,
9
9
  endpoint: str,
10
- headers: dict = None,
10
+ headers: dict | None = None,
11
11
  retry_strategy: Strategies = Strategies.NO_RETRY_STRATEGY,
12
12
  retries: int = 3,
13
13
  initial_delay: int = 1,
14
- connection_timeout: int = 1,
14
+ connection_timeout: int = 10,
15
15
  ):
16
16
  """
17
17
  Initializes the ClientBuilder object.
@@ -20,14 +20,14 @@ class ClientBuilder:
20
20
  endpoint (str): The API endpoint to connect to.
21
21
  headers (dict, optional): The headers to use for the API request. Defaults to None.
22
22
  retry_strategy (Strategies, optional): Defaults to Strategies.NO_RETRY_STRATEGY.
23
- retries (int): The number of times to retry a failed request. Defaults to 3.
23
+ retries (int): The number of attempts to make. Must be >= 1. Defaults to 3.
24
24
  initial_delay (int): The delay between retries in seconds. Defaults to 1.
25
- connection_timeout (int): The timeout for the connection in seconds. Defaults to 1.
25
+ connection_timeout (int): The timeout for the connection in seconds. Defaults to 10.
26
26
 
27
27
  Raises:
28
28
  ValueError: If endpoint is an empty string.
29
- ValueError: If retries is not a non-negative integer.
30
- ValueError: If delay is not a non-negative integer.
29
+ ValueError: If retries is not a positive integer (>= 1).
30
+ ValueError: If initial_delay is not a non-negative integer.
31
31
  ValueError: If connection_timeout is not a non-negative integer.
32
32
  """
33
33
 
@@ -36,19 +36,19 @@ class ClientBuilder:
36
36
  if endpoint == "":
37
37
  error_msg = "endpoint cannot be an empty string"
38
38
  logger.error(error_msg)
39
- raise ValueError
40
- if not isinstance(retries, int) or retries < 0:
41
- error_msg = "retries must be a non-negative integer"
39
+ raise ValueError(error_msg)
40
+ if not isinstance(retries, int) or isinstance(retries, bool) or retries < 1:
41
+ error_msg = "retries must be a positive integer (>= 1)"
42
42
  logger.error(error_msg)
43
- raise ValueError
44
- if not isinstance(initial_delay, int) or initial_delay < 0:
43
+ raise ValueError(error_msg)
44
+ if not isinstance(initial_delay, int) or isinstance(initial_delay, bool) or initial_delay < 0:
45
45
  error_msg = "initial_delay must be a non-negative integer"
46
46
  logger.error(error_msg)
47
- raise ValueError
48
- if not isinstance(connection_timeout, int) or connection_timeout < 0:
47
+ raise ValueError(error_msg)
48
+ if not isinstance(connection_timeout, int) or isinstance(connection_timeout, bool) or connection_timeout < 0:
49
49
  error_msg = "connection_timeout must be a non-negative integer"
50
50
  logger.error(error_msg)
51
- raise ValueError
51
+ raise ValueError(error_msg)
52
52
 
53
53
  self.endpoint = endpoint
54
54
  self.retry_strategy = retry_strategy
@@ -58,14 +58,10 @@ class ClientBuilder:
58
58
  self.delay = initial_delay
59
59
 
60
60
  @retry_strategies
61
- def get_api_data(self):
61
+ def get_api_data(self) -> dict:
62
62
  """
63
63
  Retrieves data from the API using the defined endpoint and retry strategy.
64
64
 
65
- This function sends a request to the API using the endpoint, headers, and
66
- connection timeout specified in the instance attributes. It uses the
67
- defined retry strategy to handle potential failures and retries.
68
-
69
65
  Returns:
70
66
  dict: The JSON response from the API as a dictionary.
71
67
  """
@@ -82,10 +78,6 @@ class ClientBuilder:
82
78
  """
83
79
  Converts an API response to a DataFrame.
84
80
 
85
- This function takes a dictionary response from an API,
86
- uses the `to_dataframe` function from the `GetData` class
87
- to convert it into a DataFrame, and logs the operation as successful.
88
-
89
81
  Args:
90
82
  response (dict): The dictionary containing the API response.
91
83
 
@@ -13,13 +13,13 @@ class Strategies(Enum):
13
13
 
14
14
 
15
15
  def retry_strategies(func):
16
- def wrapper(*args, **kwargs): # pylint: disable=inconsistent-return-statements
16
+ def wrapper(*args, **kwargs):
17
17
  retry_number = 0
18
18
  while retry_number < args[0].retries:
19
19
  try:
20
20
  if retry_number > 0:
21
21
  logger.info(
22
- f"Trying for the {retry_number} of {Constants.MAX_OF_RETRIES} retries. Using {args[0].retry_strategy}"
22
+ f"Attempt {retry_number} of {min(args[0].retries, Constants.MAX_OF_RETRIES)}. Strategy: {args[0].retry_strategy}"
23
23
  )
24
24
  return func(*args, **kwargs)
25
25
  except RequestException as e:
@@ -27,13 +27,13 @@ def retry_strategies(func):
27
27
 
28
28
  if args[0].retry_strategy == Strategies.NO_RETRY_STRATEGY:
29
29
  raise e
30
- if args[0].retry_strategy == Strategies.LINEAR_RETRY_STRATEGY:
30
+ elif args[0].retry_strategy == Strategies.LINEAR_RETRY_STRATEGY:
31
31
  time.sleep(args[0].delay)
32
32
  elif args[0].retry_strategy == Strategies.EXPONENTIAL_RETRY_STRATEGY:
33
33
  time.sleep(args[0].delay * retry_number)
34
34
 
35
35
  if retry_number in (args[0].retries, Constants.MAX_OF_RETRIES):
36
- logger.error(f"Failed after {retry_number} retries")
36
+ logger.error(f"Failed after {retry_number} attempts")
37
37
  raise e
38
38
 
39
39
  return wrapper
@@ -0,0 +1,4 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger("api-to-dataframe")
4
+ logger.addHandler(logging.NullHandler())
@@ -1,11 +0,0 @@
1
- import logging
2
-
3
- logging.basicConfig(
4
- encoding="utf-8",
5
- format="%(asctime)s :: api-to-dataframe[%(levelname)s] :: %(message)s",
6
- datefmt="%Y-%m-%d %H:%M:%S %Z",
7
- level=logging.INFO,
8
- )
9
-
10
- # Initialize traditional logger
11
- logger = logging.getLogger("api-to-dataframe")