carbonarc 1.0.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Carbon Arc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,56 @@
1
+ Metadata-Version: 2.3
2
+ Name: carbonarc
3
+ Version: 1.0.0
4
+ Summary: Carbon Arc - Python Package
5
+ License: MIT
6
+ Author: Carbon Arc
7
+ Author-email: support@carbonarc.co
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 2
10
+ Classifier: Programming Language :: Python :: 2.7
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.4
13
+ Classifier: Programming Language :: Python :: 3.5
14
+ Classifier: Programming Language :: Python :: 3.6
15
+ Classifier: Programming Language :: Python :: 3.7
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Requires-Dist: Click (>=8.1.7,<9.0.0)
23
+ Requires-Dist: beautifulsoup4 (>=4.12.2,<5.0.0)
24
+ Requires-Dist: pandas (>=2.2.3,<3.0.0)
25
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
26
+ Project-URL: Repository, https://github.com/Carbon-Arc/carbonarc.git
27
+ Description-Content-Type: text/markdown
28
+
29
+ # Carbon Arc - Python Package
30
+
31
+ Client for [Carbon Arc](https://carbonarc.co/), an Insights Exchange Platform.
32
+
33
+ ## Usage
34
+
35
+ **Installation**
36
+
37
+ ```bash
38
+ pip install carbonarc
39
+ ```
40
+
41
+ **Quick Start**
42
+
43
+ Initialize the API client with authentication.
44
+
45
+ ```python
46
+ from carbonarc import CarbonArcClient
47
+
48
+ client = CarbonArcClient(token="<token>") # retrieve token from account
49
+ ```
50
+
51
+ ## Resources
52
+
53
+ - [Tutorials](https://github.com/Carbon-Arc/carbonarc-tutorials)
54
+ - [Docs](https://docs.carbonarc.co/)
55
+ - [App](https://app.carbonarc.co/)
56
+ - [API](https://api.carbonarc.co/)
@@ -0,0 +1,28 @@
1
+ # Carbon Arc - Python Package
2
+
3
+ Client for [Carbon Arc](https://carbonarc.co/), an Insights Exchange Platform.
4
+
5
+ ## Usage
6
+
7
+ **Installation**
8
+
9
+ ```bash
10
+ pip install carbonarc
11
+ ```
12
+
13
+ **Quick Start**
14
+
15
+ Initialize the API client with authentication.
16
+
17
+ ```python
18
+ from carbonarc import CarbonArcClient
19
+
20
+ client = CarbonArcClient(token="<token>") # retrieve token from account
21
+ ```
22
+
23
+ ## Resources
24
+
25
+ - [Tutorials](https://github.com/Carbon-Arc/carbonarc-tutorials)
26
+ - [Docs](https://docs.carbonarc.co/)
27
+ - [App](https://app.carbonarc.co/)
28
+ - [API](https://api.carbonarc.co/)
@@ -0,0 +1,35 @@
1
+ [tool.poetry]
2
+ name = "carbonarc"
3
+ version = "1.0.0"
4
+ description = "Carbon Arc - Python Package"
5
+ authors = ["Carbon Arc <support@carbonarc.co>"]
6
+ readme = "README.md"
7
+ packages = [{include = "carbonarc", from = "src"}, {include = "carbonarc_cli", from = "src"}]
8
+ license = "MIT License"
9
+ repository = "https://github.com/Carbon-Arc/carbonarc.git"
10
+ python = "^3.9"
11
+
12
+ [tool.poetry.dependencies]
13
+ requests = "^2.31.0"
14
+ pandas = "^2.2.3"
15
+ beautifulsoup4 = "^4.12.2"
16
+ Click = "^8.1.7"
17
+
18
+ [tool.poetry.scripts]
19
+ carbonarc = "carbonarc_cli.cli:cli"
20
+
21
+ [tool.setuptools.package-data]
22
+ carbonarc = ["carbonarc/*"]
23
+ carbonarc_cli = ["carbonarc_cli/*"]
24
+
25
+ [tool.poetry.group.dev.dependencies]
26
+ pytest = "^7.4.0"
27
+ pytest-mock = "^3.11.1"
28
+ black = "^23.7.0"
29
+ isort = "^5.12.0"
30
+ mypy = "^1.5.0"
31
+ types-requests = "^2.31.0"
32
+
33
+ [build-system]
34
+ requires = ["poetry-core"]
35
+ build-backend = "poetry.core.masonry.api"
@@ -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
@@ -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
@@ -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)