autonomize-core 0.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.
@@ -0,0 +1,3 @@
1
+ Copyright (C) Autonomize AI - All Rights Reserved
2
+
3
+ The contents of this repository cannot be copied and/or distributed without the explicit permission from Autonomize.ai
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.1
2
+ Name: autonomize-core
3
+ Version: 0.1.0
4
+ Summary: Autonomize Core contains the unified authentication source to access platform.
5
+ Home-page: https://github.com/autonomize-ai/autonomize-core
6
+ License: Proprietary
7
+ Author: Varun Prakash
8
+ Author-email: varun.prakash@autonomize.ai
9
+ Requires-Python: >=3.12,<4.0
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: Other/Proprietary License
13
+ Classifier: Natural Language :: English
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Text Processing
22
+ Classifier: Typing :: Typed
23
+ Requires-Dist: httpx (>=0.28.1,<0.29.0)
24
+ Project-URL: Documentation, https://github.com/autonomize-ai/autonomize-core
25
+ Project-URL: Repository, https://github.com/autonomize-ai/autonomize-core
26
+ Description-Content-Type: text/markdown
27
+
28
+ # Autonomize Core
29
+
30
+ ![Python Version](https://img.shields.io/badge/Python-3.12+-blue?style=for-the-badge&logo=python)
31
+ ![PyPI Version](https://img.shields.io/pypi/v/autonomize-core?style=for-the-badge&logo=pypi)
32
+ ![Code Formatter](https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge)
33
+ ![Code Linter](https://img.shields.io/badge/linting-pylint-green.svg?style=for-the-badge)
34
+ ![Code Checker](https://img.shields.io/badge/mypy-checked-blue?style=for-the-badge)
35
+ ![Code Coverage](https://img.shields.io/badge/coverage-100%25-a4a523?style=for-the-badge&logo=codecov)
36
+
37
+ ## Overview
38
+
39
+ Autonomize Core houses the core functionality about authentication of our in-house platform.
40
+
41
+ ## Features
42
+
43
+ - **Authentication**: The SDK allows you to authenticate tokens for Modelhub.
44
+ - **High scalability**: Built to handle large-scale data retrieval and generation, enabling robust, production-ready applications.
45
+
46
+ ## Installation
47
+
48
+ 1. Create a virtual environment, we recommend [Miniconda](https://docs.anaconda.com/miniconda/) for environment management:
49
+ ```bash
50
+ conda create -n autocore python=3.12
51
+ conda activate autocore
52
+ ```
53
+ 2. Install the package:
54
+ ```bash
55
+ pip install autonomize-core
56
+ ```
57
+
58
+ To install with optional dependencies like Qdrant, Huggingface, OpenAI, Modelhub, etc., refer to the [Installation Guide](INSTALL.md).
59
+
60
+
61
+ ## Usage
62
+
63
+ ### Sync Usage
64
+
65
+ ```python
66
+ import os
67
+ from autonomize.core.credential import ModelhubCredential
68
+
69
+ cred = ModelhubCredential(
70
+ auth_url=MODELHUB_AUTH_ENDPOINT,
71
+ client_id=MODELHUB_AUTH_CLIENT_ID,
72
+ client_secret=MODELHUB_AUTH_CLIENT_SECRET,
73
+ )
74
+
75
+ r = cred.get_token()
76
+ ```
77
+
78
+ ### Async Usage
79
+
80
+ Simply use sync methods with `a` prefix and use `await` for each call. Example: `cred.get_token` becomes `await cred.aget_token` and everything else remains the same.
81
+
82
+ ```python
83
+ import os
84
+ from autonomize.core.credential import ModelhubCredential
85
+
86
+ cred = ModelhubCredential(
87
+ auth_url=MODELHUB_AUTH_ENDPOINT,
88
+ client_id=MODELHUB_AUTH_CLIENT_ID,
89
+ client_secret=MODELHUB_AUTH_CLIENT_SECRET,
90
+ )
91
+
92
+ r = await cred.aget_token()
93
+ ```
94
+
95
+ ## Contribution
96
+
97
+ To contribute in our Autonomize Core SDK, please refer to our [Contribution Guidelines](CONTRIBUTING.md).
98
+
99
+ ## License
100
+ Copyright (C) Autonomize AI - All Rights Reserved
101
+
102
+ The contents of this repository cannot be copied and/or distributed without the explicit permission from Autonomize.ai
103
+
@@ -0,0 +1,75 @@
1
+ # Autonomize Core
2
+
3
+ ![Python Version](https://img.shields.io/badge/Python-3.12+-blue?style=for-the-badge&logo=python)
4
+ ![PyPI Version](https://img.shields.io/pypi/v/autonomize-core?style=for-the-badge&logo=pypi)
5
+ ![Code Formatter](https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge)
6
+ ![Code Linter](https://img.shields.io/badge/linting-pylint-green.svg?style=for-the-badge)
7
+ ![Code Checker](https://img.shields.io/badge/mypy-checked-blue?style=for-the-badge)
8
+ ![Code Coverage](https://img.shields.io/badge/coverage-100%25-a4a523?style=for-the-badge&logo=codecov)
9
+
10
+ ## Overview
11
+
12
+ Autonomize Core houses the core functionality about authentication of our in-house platform.
13
+
14
+ ## Features
15
+
16
+ - **Authentication**: The SDK allows you to authenticate tokens for Modelhub.
17
+ - **High scalability**: Built to handle large-scale data retrieval and generation, enabling robust, production-ready applications.
18
+
19
+ ## Installation
20
+
21
+ 1. Create a virtual environment, we recommend [Miniconda](https://docs.anaconda.com/miniconda/) for environment management:
22
+ ```bash
23
+ conda create -n autocore python=3.12
24
+ conda activate autocore
25
+ ```
26
+ 2. Install the package:
27
+ ```bash
28
+ pip install autonomize-core
29
+ ```
30
+
31
+ To install with optional dependencies like Qdrant, Huggingface, OpenAI, Modelhub, etc., refer to the [Installation Guide](INSTALL.md).
32
+
33
+
34
+ ## Usage
35
+
36
+ ### Sync Usage
37
+
38
+ ```python
39
+ import os
40
+ from autonomize.core.credential import ModelhubCredential
41
+
42
+ cred = ModelhubCredential(
43
+ auth_url=MODELHUB_AUTH_ENDPOINT,
44
+ client_id=MODELHUB_AUTH_CLIENT_ID,
45
+ client_secret=MODELHUB_AUTH_CLIENT_SECRET,
46
+ )
47
+
48
+ r = cred.get_token()
49
+ ```
50
+
51
+ ### Async Usage
52
+
53
+ Simply use sync methods with `a` prefix and use `await` for each call. Example: `cred.get_token` becomes `await cred.aget_token` and everything else remains the same.
54
+
55
+ ```python
56
+ import os
57
+ from autonomize.core.credential import ModelhubCredential
58
+
59
+ cred = ModelhubCredential(
60
+ auth_url=MODELHUB_AUTH_ENDPOINT,
61
+ client_id=MODELHUB_AUTH_CLIENT_ID,
62
+ client_secret=MODELHUB_AUTH_CLIENT_SECRET,
63
+ )
64
+
65
+ r = await cred.aget_token()
66
+ ```
67
+
68
+ ## Contribution
69
+
70
+ To contribute in our Autonomize Core SDK, please refer to our [Contribution Guidelines](CONTRIBUTING.md).
71
+
72
+ ## License
73
+ Copyright (C) Autonomize AI - All Rights Reserved
74
+
75
+ The contents of this repository cannot be copied and/or distributed without the explicit permission from Autonomize.ai
File without changes
File without changes
@@ -0,0 +1,261 @@
1
+ """ModelhubCredential Implementation"""
2
+
3
+ # pylint: disable=line-too-long, invalid-name
4
+
5
+ import base64
6
+ import json
7
+ import os
8
+ import time
9
+ from typing import Optional
10
+
11
+ import httpx
12
+
13
+ from autonomize.exceptions.core import (
14
+ ModelhubInvalidTokenException,
15
+ ModelhubMissingCredentialsException,
16
+ ModelhubTokenRetrievalException,
17
+ ModelhubUnauthorizedException,
18
+ )
19
+ from autonomize.utils.logger import setup_logger
20
+
21
+ logger = setup_logger(__name__)
22
+
23
+
24
+ class ModelhubCredential:
25
+ """
26
+ ModelhubCredential Class.
27
+
28
+ This class instantiates a ModelhubCredential client to authenticate request to Modelhub.
29
+
30
+ Example:
31
+ .. code-block:: python
32
+
33
+ from autonomize.core import ModelhubCredential
34
+
35
+ # Using modelhub_url (recommended)
36
+ modelhub_credential = ModelhubCredential(
37
+ modelhub_url="https://example.com",
38
+ client_id="modelhub-client",
39
+ client_secret="xxx"
40
+ )
41
+
42
+ # Using token directly
43
+ modelhub_credential = ModelhubCredential(
44
+ token="xxx"
45
+ )
46
+ """
47
+
48
+ def __init__(
49
+ self,
50
+ modelhub_url: Optional[str] = None,
51
+ client_id: Optional[str] = None,
52
+ client_secret: Optional[str] = None,
53
+ token: Optional[str] = None,
54
+ auth_url: Optional[str] = None, # Kept for backward compatibility
55
+ ):
56
+ """
57
+ Initialize the ModelhubCredential instance.
58
+
59
+ Args:
60
+ modelhub_url (Optional[str]): The base URL for ModelHub services. Defaults to None.
61
+ client_id (Optional[str]): The client ID for authentication.
62
+ client_secret (Optional[str]): The client secret for authentication.
63
+ token (Optional[str]): An existing JWT token for authentication.
64
+ auth_url (Optional[str]): The direct authentication URL (legacy parameter).
65
+
66
+ Raises:
67
+ ModelhubMissingCredentialsException: If neither (client_id and client_secret) nor token is provided.
68
+ """
69
+ # Initialize base URL
70
+ self._modelhub_url = modelhub_url or (
71
+ os.getenv("MODELHUB_BASE_URL", "").strip() or None
72
+ )
73
+ self._client_id = client_id or (
74
+ os.getenv("MODELHUB_CLIENT_ID", "").strip() or None
75
+ )
76
+ self._client_secret = client_secret or (
77
+ os.getenv("MODELHUB_CLIENT_SECRET", "").strip() or None
78
+ )
79
+ self._token = token
80
+
81
+ # Derive auth_url from modelhub_url if available, otherwise use provided auth_url or default
82
+ if self._modelhub_url:
83
+ self._auth_url = f"{self._modelhub_url}/ums/api/v1/auth/get-token"
84
+ elif auth_url:
85
+ # Legacy support for direct auth_url
86
+ self._auth_url = auth_url
87
+ logger.warning(
88
+ "Using direct auth_url is deprecated. Please use modelhub_url instead."
89
+ )
90
+ else:
91
+ # Default URL as a fallback
92
+ self._auth_url = "https://auth.sprint.autonomize.dev/realms/autonomize/protocol/openid-connect/token"
93
+
94
+ # Validate credentials
95
+ if self._client_id is None or self._client_secret is None:
96
+ if self._token is None:
97
+ raise ModelhubMissingCredentialsException(
98
+ "Either (`client_id` and `client_secret`) or `token` must be provided."
99
+ )
100
+ logger.warning(
101
+ "It is recommended to provide `client_id` and `client_secret` over `token` "
102
+ "because token gets expired within 24 hours. "
103
+ "You can use `ModelhubCredential.is_token_expired(your_token)` to check if it has expired or not."
104
+ )
105
+
106
+ @property
107
+ def auth_url(self) -> str:
108
+ """Get the authentication URL."""
109
+ return self._auth_url
110
+
111
+ def reset_token(self) -> None:
112
+ """Reset the token to force a new token fetch on next request."""
113
+ self._token = None # pragma: no cover
114
+ logger.debug(
115
+ "Token reset, will fetch a new token on next request"
116
+ ) # pragma: no cover
117
+
118
+ @staticmethod
119
+ def is_token_expired(token: str) -> bool:
120
+ """
121
+ Checks whether the provided JWT token is expired or not.
122
+
123
+ Args:
124
+ token (str): The JWT token to check if its expired or not.
125
+
126
+ Returns:
127
+ bool: True if token has expired, otherwise False.
128
+
129
+ Raises:
130
+ ModelhubInvalidTokenException: When the token provided is ill-formatted.
131
+ """
132
+
133
+ # Split the token by `.` to get it in list
134
+ b64_components = token.split(".")
135
+
136
+ # The token should have three components: header, payload and signature.
137
+ if len(b64_components) != 3:
138
+ raise ModelhubInvalidTokenException(
139
+ "Ill-formatted token provided. Please recheck your token."
140
+ )
141
+
142
+ # Divide it into, header, payload and signature,
143
+ # but we don't need header and signature.
144
+ _, payload_b64, _ = b64_components
145
+
146
+ payload_json = base64.urlsafe_b64decode(payload_b64 + "==").decode("utf-8")
147
+ payload = json.loads(payload_json)
148
+
149
+ # Get expiry time in Unix-epoch time.
150
+ token_expiry_time = payload["exp"]
151
+
152
+ return token_expiry_time < int(time.time())
153
+
154
+ def get_token(self) -> str:
155
+ """
156
+ Obtains a JWT token for authorization if token is not provided or has expired.
157
+
158
+ Returns:
159
+ str: JWT token.
160
+ """
161
+ if not self._token or ModelhubCredential.is_token_expired(self._token):
162
+ if not self._client_id or not self._client_secret:
163
+ raise ModelhubMissingCredentialsException( # pragma: no cover
164
+ "client_id and client_secret must be provided to fetch JWT token."
165
+ )
166
+
167
+ # Setting verify=False, so our client doesn't check for SSL certificate.
168
+ with httpx.Client(verify=False, timeout=None) as client:
169
+ response = client.post(
170
+ self.auth_url,
171
+ headers={"Content-Type": "application/x-www-form-urlencoded"},
172
+ data={
173
+ "grant_type": "client_credentials",
174
+ "client_id": self._client_id,
175
+ "client_secret": self._client_secret,
176
+ "scope": "openid",
177
+ },
178
+ )
179
+
180
+ if response.status_code == 401:
181
+ raise ModelhubUnauthorizedException(
182
+ "Client Error `401 Unauthorized`: client_id or client_secret is invalid."
183
+ )
184
+ response.raise_for_status()
185
+
186
+ # Handle different response formats
187
+ json_response = response.json()
188
+ if "id_token" in json_response:
189
+ self._token = json_response["id_token"]
190
+ elif (
191
+ "token" in json_response
192
+ and "access_token" in json_response["token"]
193
+ ):
194
+ self._token = json_response["token"]["access_token"]
195
+ elif "access_token" in json_response:
196
+ self._token = json_response["access_token"]
197
+ else:
198
+ raise ModelhubTokenRetrievalException(
199
+ f"Could not find token in response: {json_response}"
200
+ )
201
+
202
+ # Ensure token is not None before returning
203
+ if not self._token:
204
+ raise ModelhubTokenRetrievalException( # pragma: no cover
205
+ "Token could not be retrieved."
206
+ )
207
+ return self._token
208
+
209
+ async def aget_token(self) -> str:
210
+ """
211
+ Asynchronously obtains a JWT token for authorization if token is not provided or has expired.
212
+
213
+ Returns:
214
+ str: JWT token.
215
+ """
216
+ if not self._token or ModelhubCredential.is_token_expired(self._token):
217
+ if not self._client_id or not self._client_secret:
218
+ raise ModelhubMissingCredentialsException(
219
+ "client_id and client_secret must be provided to fetch JWT token."
220
+ )
221
+
222
+ async with httpx.AsyncClient(verify=False, timeout=None) as client:
223
+ response = await client.post(
224
+ self.auth_url,
225
+ headers={"Content-Type": "application/x-www-form-urlencoded"},
226
+ data={
227
+ "grant_type": "client_credentials",
228
+ "client_id": self._client_id,
229
+ "client_secret": self._client_secret,
230
+ "scope": "openid",
231
+ },
232
+ )
233
+
234
+ if response.status_code == 401:
235
+ raise ModelhubUnauthorizedException(
236
+ "Client Error `401 Unauthorized`: client_id or client_secret is invalid."
237
+ )
238
+ response.raise_for_status()
239
+
240
+ # Handle different response formats
241
+ json_response = response.json()
242
+ if "id_token" in json_response:
243
+ self._token = json_response["id_token"]
244
+ elif (
245
+ "token" in json_response
246
+ and "access_token" in json_response["token"]
247
+ ):
248
+ self._token = json_response["token"]["access_token"]
249
+ elif "access_token" in json_response:
250
+ self._token = json_response["access_token"]
251
+ else:
252
+ raise ModelhubTokenRetrievalException(
253
+ f"Could not find token in response: {json_response}"
254
+ )
255
+
256
+ # Ensure token is not None before returning
257
+ if not self._token:
258
+ raise ModelhubTokenRetrievalException(
259
+ "Token could not be retrieved."
260
+ ) # pragma: no cover
261
+ return self._token
@@ -0,0 +1,15 @@
1
+ # pylint: disable=missing-module-docstring, duplicate-code
2
+
3
+ from .core import (
4
+ ModelhubInvalidTokenException,
5
+ ModelhubMissingCredentialsException,
6
+ ModelhubTokenRetrievalException,
7
+ ModelhubUnauthorizedException,
8
+ )
9
+
10
+ __all__ = [
11
+ "ModelhubInvalidTokenException",
12
+ "ModelhubMissingCredentialsException",
13
+ "ModelhubTokenRetrievalException",
14
+ "ModelhubUnauthorizedException",
15
+ ]
@@ -0,0 +1,15 @@
1
+ # pylint: disable=missing-module-docstring, duplicate-code
2
+
3
+ from .credentials import (
4
+ ModelhubInvalidTokenException,
5
+ ModelhubMissingCredentialsException,
6
+ ModelhubTokenRetrievalException,
7
+ ModelhubUnauthorizedException,
8
+ )
9
+
10
+ __all__ = [
11
+ "ModelhubInvalidTokenException",
12
+ "ModelhubMissingCredentialsException",
13
+ "ModelhubTokenRetrievalException",
14
+ "ModelhubUnauthorizedException",
15
+ ]
@@ -0,0 +1,21 @@
1
+ """Exceptions for the modelhub module."""
2
+
3
+
4
+ class ModelhubCredentialException(Exception):
5
+ """Base exception for ModelhubCredential exceptions."""
6
+
7
+
8
+ class ModelhubMissingCredentialsException(ModelhubCredentialException):
9
+ """Raised when modelhub credentials are not provided."""
10
+
11
+
12
+ class ModelhubInvalidTokenException(ModelhubCredentialException):
13
+ """Raised when an ill-formatted or invalid token is provided."""
14
+
15
+
16
+ class ModelhubTokenRetrievalException(ModelhubCredentialException):
17
+ """Raised when the token could not be retrieved."""
18
+
19
+
20
+ class ModelhubUnauthorizedException(ModelhubCredentialException):
21
+ """Raised when the modelhub credentials are invalid."""
File without changes
@@ -0,0 +1,71 @@
1
+ """ This module contains the logger setup function. """
2
+
3
+ import logging
4
+ import os
5
+ import sys
6
+ from datetime import datetime
7
+
8
+
9
+ class CustomFormatter(logging.Formatter):
10
+ """
11
+ A custom log formatter that adds detailed context information to log records.
12
+
13
+ This formatter extends the base `logging.Formatter` class and overrides the `format` method
14
+ to add timestamp, app label, file name, function name, and line number to each log record.
15
+
16
+ Attributes:
17
+ None
18
+
19
+ Methods:
20
+ format(record): Formats the log record with enhanced contextual information.
21
+
22
+ Usage:
23
+ formatter = CustomFormatter()
24
+ handler.setFormatter(formatter)
25
+ """
26
+
27
+ def format(self, record):
28
+ record.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
29
+ record.label = f"[{os.environ.get('APP_NAME', 'modelhub')}]"
30
+
31
+ # Add file location info
32
+ record.file_info = f"{record.pathname.split('/')[-1]}:{record.lineno}"
33
+
34
+ # Add function info if available
35
+ if record.funcName and record.funcName != "<module>":
36
+ record.file_info = f"{record.file_info} {record.funcName}()"
37
+
38
+ return super().format(record)
39
+
40
+
41
+ def setup_logger(name):
42
+ """
43
+ Set up a logger with the specified name and enhanced contextual information.
44
+
45
+ Args:
46
+ name (str): The name of the logger.
47
+
48
+ Returns:
49
+ logging.Logger: The configured logger object.
50
+ """
51
+ logger = logging.getLogger(name)
52
+
53
+ # Set log level from environment variable
54
+ log_level = os.getenv("LOG_LEVEL", "INFO").upper()
55
+ logger.setLevel(log_level)
56
+
57
+ if not logger.hasHandlers():
58
+ log_handler = logging.StreamHandler(sys.stdout) # pragma: no cover
59
+
60
+ # Enhanced format with file location and function information
61
+ formatter = CustomFormatter( # pragma: no cover
62
+ fmt="%(timestamp)s %(label)s %(levelname)s [%(name)s] [%(file_info)s]: %(message)s"
63
+ )
64
+
65
+ log_handler.setFormatter(formatter) # pragma: no cover
66
+ logger.addHandler(log_handler) # pragma: no cover
67
+
68
+ # Prevent propagation to avoid duplicate logs
69
+ logger.propagate = False
70
+
71
+ return logger
@@ -0,0 +1,49 @@
1
+ [tool.poetry]
2
+ name = "autonomize-core"
3
+ version = "0.1.0"
4
+ description = "Autonomize Core contains the unified authentication source to access platform."
5
+ authors = ["Varun Prakash <varun.prakash@autonomize.ai>"]
6
+ readme = "README.md"
7
+ license = "Proprietary"
8
+ classifiers = [
9
+ "Development Status :: 3 - Alpha",
10
+ "Intended Audience :: Developers",
11
+ "License :: Other/Proprietary License",
12
+ "Natural Language :: English",
13
+ "Operating System :: OS Independent",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.12",
16
+ "Programming Language :: Python :: 3.13",
17
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
18
+ "Topic :: Software Development :: Libraries :: Application Frameworks",
19
+ "Topic :: Software Development :: Libraries :: Python Modules",
20
+ "Topic :: Text Processing",
21
+ "Typing :: Typed"
22
+ ]
23
+ packages = [
24
+ { include = "autonomize" },
25
+ ]
26
+ homepage = "https://github.com/autonomize-ai/autonomize-core"
27
+ repository = "https://github.com/autonomize-ai/autonomize-core"
28
+ documentation = "https://github.com/autonomize-ai/autonomize-core"
29
+
30
+ [tool.poetry.dependencies]
31
+ python = "^3.12"
32
+ httpx = "^0.28.1"
33
+
34
+ [tool.poetry.group.dev]
35
+ optional = true
36
+
37
+ [tool.poetry.group.dev.dependencies]
38
+ pytest = "^8.3.2"
39
+ black = {version = "24.4.2", extras = ["jupyter"]}
40
+ pylint = "^3.2.6"
41
+ mypy = "^1.11.1"
42
+ pytest-asyncio = "^0.24.0"
43
+ pre-commit = "^3.8.0"
44
+ pytest-cov = "^5.0.0"
45
+
46
+
47
+ [build-system]
48
+ requires = ["poetry-core"]
49
+ build-backend = "poetry.core.masonry.api"