carbonarc 1.0.0__py2.py3-none-any.whl

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.
carbonarc/__init__.py ADDED
@@ -0,0 +1,13 @@
1
+ try:
2
+ from importlib.metadata import version, PackageNotFoundError
3
+ try:
4
+ __version__ = version("carbonarc")
5
+ except PackageNotFoundError:
6
+ __version__ = "unkown"
7
+ except ImportError:
8
+ __version__ = "unkown"
9
+
10
+ from carbonarc.client import CarbonArcClient
11
+
12
+
13
+ __all__ = ["CarbonArcClient"]
File without changes
carbonarc/base/auth.py ADDED
@@ -0,0 +1,22 @@
1
+ from requests.auth import AuthBase
2
+
3
+
4
+ class TokenAuth(AuthBase):
5
+ """
6
+ Class for authenticating requests by user supplied token.
7
+ """
8
+
9
+ def __init__(self, token: str):
10
+ assert token, "Token must be a non-empty string."
11
+ self.auth_token = token
12
+
13
+ def __call__(self, r):
14
+ """
15
+ Override the default __call__ method for the AuthBase base class
16
+
17
+ More more info, see:
18
+ https://docs.python-requests.org/en/master/user/advanced/
19
+ """
20
+ auth_token = self.auth_token
21
+ r.headers["Authorization"] = "Bearer " + auth_token
22
+ return r
@@ -0,0 +1,44 @@
1
+ import logging
2
+ from typing import Literal
3
+
4
+ from carbonarc.base.auth import TokenAuth
5
+ from carbonarc.base.manager import HttpRequestManager
6
+
7
+
8
+ class BaseAPIClient:
9
+ """
10
+ A client for interacting with the Carbon Arc API.
11
+ """
12
+
13
+ def __init__(
14
+ self,
15
+ token: str,
16
+ host: str = "https://platform.carbonarc.co",
17
+ version: str = "v2"
18
+ ):
19
+ """
20
+ Initialize APIClient with an authentication token and user agent.
21
+ :param auth_token: The authentication token to be used for requests.
22
+ :param host: The base URL of the Carbon Arc API.
23
+ :param version: The API version to use.
24
+ """
25
+
26
+ self.host = host
27
+ self.version = version
28
+
29
+ self._logger = logging.getLogger(__name__)
30
+
31
+ self.auth_token = TokenAuth(token)
32
+ self.request_manager = HttpRequestManager(auth_token=self.auth_token)
33
+
34
+ def _build_base_url(
35
+ self,
36
+ product: Literal["clients", "framework", "library", "ontology", "hub"],
37
+ ) -> str:
38
+ return self.host + f"/api/{self.version}/" + product
39
+
40
+ def _get(self, url: str, **kwargs) -> dict:
41
+ return self.request_manager.get(url, **kwargs).json()
42
+
43
+ def _post(self, url: str, **kwargs) -> dict:
44
+ return self.request_manager.post(url, **kwargs).json()
@@ -0,0 +1,32 @@
1
+ class CarbonArcException(Exception):
2
+ """Base exception for all errors."""
3
+
4
+ def __init__(self, message, status_code=None, response=None):
5
+ self.message = message
6
+ self.status_code = status_code
7
+ self.response = response
8
+ super().__init__(self.message)
9
+
10
+
11
+ class AuthenticationError(CarbonArcException):
12
+ """Raised when authentication fails."""
13
+ pass
14
+
15
+
16
+ class NotFoundError(CarbonArcException):
17
+ """Raised when a resource is not found."""
18
+ pass
19
+
20
+
21
+ class ValidationError(CarbonArcException):
22
+ """Raised when request validation fails."""
23
+ pass
24
+
25
+
26
+ class RateLimitError(CarbonArcException):
27
+ """Raised when API rate limit is exceeded."""
28
+ pass
29
+
30
+ class InvalidConfigurationError(CarbonArcException):
31
+ """Raised when the configuration is invalid."""
32
+ pass
@@ -0,0 +1,85 @@
1
+ import logging
2
+ from http import HTTPStatus
3
+
4
+ import requests
5
+ from bs4 import BeautifulSoup
6
+ from requests.auth import AuthBase
7
+
8
+ from carbonarc import __version__
9
+ from carbonarc.base.exceptions import AuthenticationError
10
+
11
+
12
+ class HttpRequestManager:
13
+ """
14
+ This class is responsible for
15
+ making Http request calls
16
+ """
17
+
18
+ def __init__(
19
+ self, auth_token: AuthBase, user_agent: str = f"Python-APIClient/{__version__}"
20
+ ):
21
+ """
22
+ Initialize the HttpRequestManager with an authentication token and user agent.
23
+ :param auth_token: The authentication token to be used for requests.
24
+ :param user_agent: The user agent string to be used for requests.
25
+ """
26
+ if not isinstance(auth_token, AuthBase):
27
+ raise ValueError("auth_token must be an instance of requests.auth.AuthBase")
28
+
29
+ self.auth_token = auth_token
30
+ self._logger = logging.getLogger(__name__)
31
+ self.request_session = requests.Session()
32
+ self.request_session.headers.update(
33
+ {
34
+ "User-Agent": user_agent,
35
+ "Accept": "application/json",
36
+ }
37
+ )
38
+
39
+ def post(self, url, data=None, json=None, **kwargs) -> requests.Response:
40
+ return self._raise_for_status(
41
+ self.request_session.post(
42
+ url, auth=self.auth_token, data=data, json=json, **kwargs
43
+ )
44
+ )
45
+
46
+ def patch(self, url, data=None, json=None, **kwargs) -> requests.Response:
47
+ return self._raise_for_status(
48
+ self.request_session.patch(
49
+ url, auth=self.auth_token, data=data, json=json, **kwargs
50
+ )
51
+ )
52
+
53
+ def get(self, url, **kwargs) -> requests.Response:
54
+ return self._raise_for_status(
55
+ self.request_session.get(url, auth=self.auth_token, **kwargs)
56
+ )
57
+
58
+ def put(self, url, data=None, **kwargs) -> requests.Response:
59
+ return self._raise_for_status(
60
+ self.request_session.put(url, auth=self.auth_token, data=data, **kwargs)
61
+ )
62
+
63
+ def delete(self, url, **kwargs) -> requests.Response:
64
+ return self._raise_for_status(
65
+ self.request_session.delete(url, auth=self.auth_token, **kwargs)
66
+ )
67
+
68
+ def get_stream(self, url, **kwargs) -> requests.Response:
69
+ self.request_session.headers.update({"Accept": "application/octet-stream"})
70
+ return self._raise_for_status(
71
+ self.request_session.get(url, auth=self.auth_token, stream=True, **kwargs)
72
+ )
73
+
74
+ def _raise_for_status(self, response: requests.Response) -> requests.Response:
75
+ try:
76
+ response.raise_for_status()
77
+ except requests.exceptions.HTTPError as e:
78
+ if e.response.status_code == HTTPStatus.CONFLICT:
79
+ raise AuthenticationError("Conflict error")
80
+ if not bool(BeautifulSoup(e.response.text, "html.parser").find()):
81
+ self._logger.error(e.response.text)
82
+ else:
83
+ self._logger.debug(e.response.text)
84
+ raise
85
+ return response
@@ -0,0 +1,36 @@
1
+ import pandas as pd
2
+ import datetime
3
+ from typing import Union
4
+
5
+ def timeseries_response_to_pandas(response: Union[dict, pd.DataFrame]) -> pd.DataFrame:
6
+ """
7
+ Convert a timeseries response to a pandas DataFrame.
8
+ :param response: The response object from the API.
9
+ :return: A pandas DataFrame containing the timeseries data.
10
+ """
11
+ if isinstance(response, pd.DataFrame):
12
+ response["date"] = pd.to_datetime(response["date"])
13
+ return response
14
+ elif isinstance(response, dict):
15
+ current_page_data = response["data"]
16
+ df = pd.DataFrame(current_page_data)
17
+ df["date"] = pd.to_datetime(df["date"])
18
+ return df
19
+ else:
20
+ raise ValueError("Response must be a dictionary or a pandas DataFrame")
21
+
22
+
23
+ def is_valid_date(date_string: str) -> bool:
24
+ """
25
+ Checks if a string is a valid date in YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS format.
26
+ :param date_string: The date string to check.
27
+ :return: True if the date string is valid, False otherwise.
28
+ """
29
+ formats = ['%Y-%m-%d', '%Y-%m-%dT%H:%M:%S']
30
+ for fmt in formats:
31
+ try:
32
+ datetime.datetime.strptime(date_string, fmt)
33
+ return True
34
+ except ValueError:
35
+ continue
36
+ return False
carbonarc/client.py ADDED
@@ -0,0 +1,31 @@
1
+ from carbonarc.data import DataAPIClient
2
+ from carbonarc.explorer import ExplorerAPIClient
3
+ from carbonarc.hub import HubAPIClient
4
+ from carbonarc.platform import PlatformAPIClient
5
+ from carbonarc.ontology import OntologyAPIClient
6
+
7
+
8
+ class CarbonArcClient:
9
+ """
10
+ A client for interacting with the Carbon Arc API.
11
+ """
12
+
13
+ def __init__(
14
+ self,
15
+ token: str,
16
+ host: str = "https://platform.carbonarc.co",
17
+ version: str = "v2",
18
+ ):
19
+ """
20
+ Initialize CarbonArcClient with an authentication token and user agent.
21
+
22
+ Args:
23
+ token (str): The authentication token to be used for requests.
24
+ host (str): The base URL of the Carbon Arc API.
25
+ version (str): The API version to use.
26
+ """
27
+ self.data = DataAPIClient(token=token, host=host, version=version)
28
+ self.explorer = ExplorerAPIClient(token=token, host=host, version=version)
29
+ self.hub = HubAPIClient(token=token, host=host, version=version)
30
+ self.platform = PlatformAPIClient(token=token, host=host, version=version)
31
+ self.ontology = OntologyAPIClient(token=token, host=host, version=version)