qwak-core 0.4.366__py3-none-any.whl → 0.4.392__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.
Files changed (66) hide show
  1. _qwak_proto/qwak/administration/runtime_configuration/v0/external/databricks/auth_pb2.py +6 -4
  2. _qwak_proto/qwak/administration/runtime_configuration/v0/external/databricks/auth_pb2.pyi +27 -4
  3. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting/azure/auth_pb2.py +5 -3
  4. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting/azure/auth_pb2.pyi +21 -1
  5. _qwak_proto/qwak/batch_job/v1/batch_job_service_pb2.pyi +1 -1
  6. _qwak_proto/qwak/builds/build_pb2.py +42 -41
  7. _qwak_proto/qwak/builds/build_pb2.pyi +8 -1
  8. _qwak_proto/qwak/builds/build_values_pb2.py +76 -0
  9. _qwak_proto/qwak/builds/build_values_pb2.pyi +533 -0
  10. _qwak_proto/qwak/builds/build_values_pb2_grpc.py +4 -0
  11. _qwak_proto/qwak/kube_deployment_captain/batch_job_pb2.pyi +1 -1
  12. _qwak_proto/qwak/projects/projects_pb2.py +17 -15
  13. qwak/__init__.py +1 -1
  14. qwak/clients/model_management/client.py +0 -5
  15. qwak/clients/project/client.py +0 -7
  16. qwak/feature_store/_common/packaging.py +11 -5
  17. qwak/inner/const.py +0 -2
  18. qwak/inner/di_configuration/account.py +6 -66
  19. qwak/inner/tool/auth.py +0 -86
  20. qwak/inner/tool/grpc/grpc_auth.py +0 -32
  21. qwak/inner/tool/grpc/grpc_tools.py +2 -8
  22. qwak/inner/tool/grpc/grpc_try_wrapping.py +3 -1
  23. qwak/qwak_client/client.py +2 -8
  24. qwak/vector_store/rest_helpers.py +4 -16
  25. qwak_core-0.4.392.dist-info/METADATA +50 -0
  26. {qwak_core-0.4.366.dist-info → qwak_core-0.4.392.dist-info}/RECORD +27 -62
  27. frogml_storage/__init__.py +0 -1
  28. frogml_storage/artifactory/__init__.py +0 -1
  29. frogml_storage/artifactory/_artifactory_api.py +0 -315
  30. frogml_storage/authentication/login/__init__.py +0 -1
  31. frogml_storage/authentication/login/_login_cli.py +0 -239
  32. frogml_storage/authentication/login/_login_command.py +0 -74
  33. frogml_storage/authentication/models/__init__.py +0 -3
  34. frogml_storage/authentication/models/_auth.py +0 -24
  35. frogml_storage/authentication/models/_auth_config.py +0 -70
  36. frogml_storage/authentication/models/_login.py +0 -22
  37. frogml_storage/authentication/utils/__init__.py +0 -17
  38. frogml_storage/authentication/utils/_authentication_utils.py +0 -281
  39. frogml_storage/authentication/utils/_login_checks_utils.py +0 -114
  40. frogml_storage/base_storage.py +0 -140
  41. frogml_storage/constants.py +0 -56
  42. frogml_storage/exceptions/checksum_verification_error.py +0 -3
  43. frogml_storage/exceptions/validation_error.py +0 -4
  44. frogml_storage/frog_ml.py +0 -668
  45. frogml_storage/http/__init__.py +0 -1
  46. frogml_storage/http/http_client.py +0 -83
  47. frogml_storage/logging/__init__.py +0 -1
  48. frogml_storage/logging/_log_config.py +0 -45
  49. frogml_storage/logging/log_utils.py +0 -21
  50. frogml_storage/models/__init__.py +0 -1
  51. frogml_storage/models/_download_context.py +0 -54
  52. frogml_storage/models/dataset_manifest.py +0 -13
  53. frogml_storage/models/entity_manifest.py +0 -93
  54. frogml_storage/models/frogml_dataset_version.py +0 -21
  55. frogml_storage/models/frogml_entity_type_info.py +0 -50
  56. frogml_storage/models/frogml_entity_version.py +0 -34
  57. frogml_storage/models/frogml_model_version.py +0 -21
  58. frogml_storage/models/model_manifest.py +0 -60
  59. frogml_storage/models/serialization_metadata.py +0 -15
  60. frogml_storage/utils/__init__.py +0 -12
  61. frogml_storage/utils/_environment.py +0 -21
  62. frogml_storage/utils/_input_checks_utility.py +0 -104
  63. frogml_storage/utils/_storage_utils.py +0 -15
  64. frogml_storage/utils/_url_utils.py +0 -27
  65. qwak_core-0.4.366.dist-info/METADATA +0 -414
  66. {qwak_core-0.4.366.dist-info → qwak_core-0.4.392.dist-info}/WHEEL +0 -0
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  import grpc
4
2
  from _qwak_proto.qwak.projects.projects_pb2 import (
5
3
  CreateProjectRequest,
@@ -8,7 +6,6 @@ from _qwak_proto.qwak.projects.projects_pb2 import (
8
6
  ListProjectsRequest,
9
7
  )
10
8
  from _qwak_proto.qwak.projects.projects_pb2_grpc import ProjectsManagementServiceStub
11
- from _qwak_proto.qwak.projects.jfrog_project_spec_pb2 import ModelRepositoryJFrogSpec
12
9
  from dependency_injector.wiring import Provide, inject
13
10
  from qwak.exceptions import QwakException
14
11
  from qwak.inner.di_configuration import QwakContainer
@@ -34,16 +31,12 @@ class ProjectsManagementClient:
34
31
  self,
35
32
  project_name,
36
33
  project_description,
37
- jfrog_project_key: Optional[str] = None,
38
34
  ):
39
35
  try:
40
36
  return self._projects_management_service.CreateProject(
41
37
  CreateProjectRequest(
42
38
  project_name=project_name,
43
39
  project_description=project_description,
44
- jfrog_spec=ModelRepositoryJFrogSpec(
45
- jfrog_project_key=jfrog_project_key
46
- ),
47
40
  )
48
41
  )
49
42
 
@@ -16,6 +16,7 @@ from qwak.feature_store._common.value import (
16
16
  UPDATE_QWAK_SDK_WITH_FEATURE_STORE_EXTRA_MSG,
17
17
  )
18
18
  from requests import HTTPError, Response
19
+ from urllib.parse import urlparse, ParseResult
19
20
 
20
21
  ZIP_FUNCTION_CONTENT_TYPE = "text/plain"
21
22
 
@@ -220,17 +221,22 @@ def put_files_content(
220
221
 
221
222
 
222
223
  def upload_to_s3(presign_url: str, in_memory_zip: bytes, content_type: str) -> str:
224
+ parsed_url: ParseResult = urlparse(presign_url)
225
+ extra_headers: Dict[str, str] = (
226
+ {"x-ms-blob-type": "BlockBlob"}
227
+ if parsed_url.hostname.endswith(".blob.core.windows.net")
228
+ else None
229
+ )
223
230
  put_files_content(
224
231
  url=presign_url,
225
232
  content=in_memory_zip,
226
233
  content_type=content_type,
234
+ extra_headers=extra_headers,
227
235
  )
228
- from urllib.parse import urlparse
229
236
 
230
- parsed_url = urlparse(presign_url)
231
- postfix = parsed_url.path
232
- bucket = parsed_url.hostname.split(".s3.")[0]
233
- s3_path = f"s3://{bucket}{postfix}" # noqa: E231
237
+ postfix: str = parsed_url.path
238
+ bucket: str = parsed_url.hostname.split(".s3.")[0]
239
+ s3_path: str = f"s3://{bucket}{postfix}" # noqa: E231
234
240
  return s3_path
235
241
 
236
242
 
qwak/inner/const.py CHANGED
@@ -39,6 +39,4 @@ class QwakConstants:
39
39
  "https://grpc.qwak.ai/api/v0/runtime/get-authenticated-user-context"
40
40
  )
41
41
 
42
- JFROG_TENANT_HEADER_KEY = "X-JFrog-Tenant-Id"
43
-
44
42
  QWAK_APP_URL: str = "https://app.qwak.ai"
@@ -2,13 +2,12 @@ import configparser
2
2
  import errno
3
3
  import os
4
4
  from dataclasses import dataclass
5
- from typing import Optional, Type, Union
5
+ from typing import Optional, Type
6
6
 
7
7
  from qwak.exceptions import QwakLoginException
8
8
  from qwak.inner.const import QwakConstants
9
9
  from qwak.inner.di_configuration.session import Session
10
- from qwak.inner.tool.auth import Auth0ClientBase, FrogMLAuthClient
11
- from frogml_storage.authentication.login import frogml_login
10
+ from qwak.inner.tool.auth import Auth0ClientBase
12
11
 
13
12
 
14
13
  @dataclass
@@ -23,18 +22,6 @@ class UserAccount:
23
22
  # Assigned username
24
23
  username: Optional[str] = None
25
24
 
26
- # Assigned password
27
- password: Optional[str] = None
28
-
29
- # Assigned URL
30
- url: Optional[str] = None
31
-
32
- # Anonymous login
33
- anonymous: bool = False
34
-
35
- # Interactive login
36
- is_interactive: bool = False
37
-
38
25
 
39
26
  class UserAccountConfiguration:
40
27
  USER_FIELD = "user"
@@ -43,9 +30,9 @@ class UserAccountConfiguration:
43
30
 
44
31
  def __init__(
45
32
  self,
46
- config_file=QwakConstants.QWAK_CONFIG_FILE,
47
- auth_file=QwakConstants.QWAK_AUTHORIZATION_FILE,
48
- auth_client: Union[Type[Auth0ClientBase], Type[FrogMLAuthClient]] = None,
33
+ config_file: str = QwakConstants.QWAK_CONFIG_FILE,
34
+ auth_file: str = QwakConstants.QWAK_AUTHORIZATION_FILE,
35
+ auth_client: Type[Auth0ClientBase] = Auth0ClientBase,
49
36
  ):
50
37
  self._config_file = config_file
51
38
  self._auth_file = auth_file
@@ -53,52 +40,12 @@ class UserAccountConfiguration:
53
40
  self._auth = configparser.ConfigParser()
54
41
  self._environment = Session().get_environment()
55
42
  self._auth_client = auth_client
56
- self._force_qwak_auth = os.getenv("FORCE_QWAK_AUTH", "False") == "True"
57
-
58
- if not self._auth_client:
59
- # Determine auth client based on FrogML configuration
60
- try:
61
- from frogml_storage.authentication.utils import (
62
- get_frogml_configuration,
63
- )
64
-
65
- if (
66
- get_frogml_configuration() or os.getenv("JF_URL")
67
- ) and not self._force_qwak_auth:
68
- self._auth_client = FrogMLAuthClient
69
- else:
70
- self._auth_client = Auth0ClientBase
71
- except (ImportError, Exception):
72
- self._auth_client = Auth0ClientBase
73
43
 
74
44
  def configure_user(self, user_account: UserAccount):
75
45
  """
76
46
  Configure user authentication based on the authentication client type
77
47
  """
78
- if issubclass(self._auth_client, Auth0ClientBase):
79
- # Existing Qwak authentication flow
80
- self.__qwak_login(user_account)
81
-
82
- elif issubclass(self._auth_client, FrogMLAuthClient):
83
- # Use FrogML's login flow
84
- success = frogml_login(
85
- url=user_account.url,
86
- username=user_account.username,
87
- password=user_account.password,
88
- token=user_account.api_key,
89
- anonymous=user_account.anonymous,
90
- is_interactive=user_account.is_interactive,
91
- )
92
-
93
- if not success:
94
- raise QwakLoginException("Failed to authenticate with JFrog")
95
- # Validate access token
96
- # TODO: Remove once we support reference token
97
- token = self._auth_client().get_token()
98
- if not token or len(token) <= 64:
99
- raise QwakLoginException(
100
- "Authentication with JFrog failed: Only Access Tokens are supported. Please ensure you are using a valid Access Token."
101
- )
48
+ self.__qwak_login(user_account)
102
49
 
103
50
  def __qwak_login(self, user_account: UserAccount):
104
51
  self._auth.read(self._auth_file)
@@ -139,8 +86,6 @@ class UserAccountConfiguration:
139
86
  :return:
140
87
  """
141
88
  try:
142
- if issubclass(self._auth_client, FrogMLAuthClient):
143
- return UserAccount()
144
89
  username = os.environ.get("QWAK_USERNAME")
145
90
  api_key = os.environ.get("QWAK_API_KEY")
146
91
  if not api_key and (
@@ -179,8 +124,6 @@ class UserAccountConfiguration:
179
124
  :return:
180
125
  """
181
126
  try:
182
- if issubclass(self._auth_client, FrogMLAuthClient):
183
- return ""
184
127
  api_key = os.environ.get("QWAK_API_KEY")
185
128
  if api_key:
186
129
  Session().set_environment(api_key)
@@ -213,7 +156,4 @@ class UserAccountConfiguration:
213
156
  auth_client_instance = self._auth_client()
214
157
  base_url = auth_client_instance.get_base_url()
215
158
 
216
- if issubclass(self._auth_client, FrogMLAuthClient):
217
- return f"{base_url}/ui/ml"
218
-
219
159
  return base_url
qwak/inner/tool/auth.py CHANGED
@@ -1,12 +1,9 @@
1
1
  import warnings
2
2
  from filelock import FileLock
3
- from typing_extensions import Self
4
3
 
5
4
  from qwak.inner.di_configuration.session import Session
6
5
  from abc import ABC, abstractmethod
7
6
  from typing import Optional
8
- from frogml_storage.authentication.utils import get_credentials
9
- from frogml_storage.authentication.models import AuthConfig
10
7
 
11
8
  warnings.filterwarnings(action="ignore", module=".*jose.*")
12
9
 
@@ -140,86 +137,3 @@ class Auth0ClientBase(BaseAuthClient):
140
137
  raise e
141
138
  except Exception:
142
139
  raise QwakLoginException()
143
-
144
-
145
- class FrogMLAuthClient(BaseAuthClient):
146
- __MIN_TOKEN_LENGTH: int = 64
147
-
148
- def __init__(self, auth_config: Optional[AuthConfig] = None):
149
- self.auth_config = auth_config
150
- self._token = None
151
- self._tenant_id = None
152
-
153
- def get_token(self) -> Optional[str]:
154
- if not self._token:
155
- self.login()
156
- return self._token
157
-
158
- def get_tenant_id(self) -> Optional[str]:
159
- if not self._tenant_id:
160
- self.login()
161
- return self._tenant_id
162
-
163
- def get_base_url(self) -> str:
164
- artifactory_url, _ = get_credentials(self.auth_config)
165
- return self.__format_artifactory_url(artifactory_url)
166
-
167
- def login(self) -> None:
168
- artifactory_url, auth = get_credentials(self.auth_config)
169
- # For now, we only support Bearer token authentication
170
- if not hasattr(auth, "token"):
171
- return
172
-
173
- # noinspection PyUnresolvedReferences
174
- self._token = auth.token
175
- self.__validate_token()
176
-
177
- base_url = self.__format_artifactory_url(artifactory_url)
178
- try:
179
- response = requests.get(
180
- f"{base_url}/ui/api/v1/system/auth/screen/footer",
181
- headers={"Authorization": f"Bearer {self._token}"},
182
- timeout=60,
183
- )
184
- response.raise_for_status() # Raises an HTTPError for bad responses
185
- response_data = response.json()
186
- if "serverId" not in response_data:
187
- response = requests.get(
188
- f"{base_url}/jfconnect/api/v1/system/jpd_id",
189
- headers={"Authorization": f"Bearer {self._token}"},
190
- timeout=60,
191
- )
192
- if response.status_code == 200:
193
- self._tenant_id = response.text
194
- elif response.status_code == 401:
195
- raise QwakLoginException(
196
- "Failed to authenticate with JFrog. Please check your credentials"
197
- )
198
- else:
199
- raise QwakLoginException(
200
- "Failed to authenticate with JFrog. Please check your artifactory configuration"
201
- )
202
- else:
203
- self._tenant_id = response_data["serverId"]
204
- except requests.exceptions.RequestException:
205
- raise QwakLoginException(
206
- "Failed to authenticate with JFrog. Please check your artifactory configuration"
207
- )
208
- except ValueError: # This catches JSON decode errors
209
- raise QwakLoginException(
210
- "Failed to authenticate with JFrog. Please check your artifactory configuration"
211
- )
212
-
213
- def __validate_token(self: Self):
214
- if self._token is None or len(self._token) <= self.__MIN_TOKEN_LENGTH:
215
- raise QwakLoginException(
216
- "Authentication with JFrog failed: Only JWT Access Tokens are supported. "
217
- "Please ensure you are using a valid JWT Access Token."
218
- )
219
-
220
- @staticmethod
221
- def __format_artifactory_url(artifactory_url: str) -> str:
222
- # Remove '/artifactory' from the URL
223
- base_url: str = artifactory_url.replace("/artifactory", "")
224
- # Remove trailing slash if exists
225
- return base_url.rstrip("/")
@@ -1,7 +1,6 @@
1
1
  from typing import Callable, Tuple
2
2
 
3
3
  import grpc
4
- from qwak.inner.const import QwakConstants
5
4
 
6
5
  _SIGNATURE_HEADER_KEY = "authorization"
7
6
 
@@ -35,34 +34,3 @@ class Auth0Client(grpc.AuthMetadataPlugin):
35
34
 
36
35
  self._auth_client = Auth0ClientBase()
37
36
  return self._auth_client.get_token()
38
-
39
-
40
- class FrogMLGrpcClient(grpc.AuthMetadataPlugin):
41
- def __init__(self):
42
- self._auth_client = None
43
-
44
- def __call__(
45
- self,
46
- context: grpc.AuthMetadataContext,
47
- callback: Callable[[Tuple[Tuple[str, str]], None], None],
48
- ):
49
- """Implements authentication by passing metadata to a callback.
50
-
51
- Args:
52
- context: An AuthMetadataContext providing information on the RPC that
53
- the plugin is being called to authenticate.
54
- callback: A callback that accepts a tuple of metadata key/value pairs and a None
55
- parameter.
56
- """
57
- # Get token from FrogML client
58
- if not self._auth_client:
59
- from qwak.inner.tool.auth import FrogMLAuthClient
60
-
61
- self._auth_client = FrogMLAuthClient()
62
- token = self._auth_client.get_token()
63
- jfrog_tenant_id = self._auth_client.get_tenant_id()
64
- metadata = (
65
- (_SIGNATURE_HEADER_KEY, f"Bearer {token}"),
66
- (QwakConstants.JFROG_TENANT_HEADER_KEY.lower(), jfrog_tenant_id),
67
- )
68
- callback(metadata, None)
@@ -6,10 +6,8 @@ from typing import Callable, Optional, Tuple
6
6
 
7
7
  import grpc
8
8
  from qwak.exceptions import QwakException
9
- from qwak.inner.di_configuration.account import UserAccountConfiguration
10
- from qwak.inner.tool.auth import Auth0ClientBase
11
9
 
12
- from .grpc_auth import Auth0Client, FrogMLGrpcClient
10
+ from .grpc_auth import Auth0Client
13
11
 
14
12
  logger = logging.getLogger()
15
13
 
@@ -49,11 +47,7 @@ def create_grpc_channel(
49
47
  credentials = grpc.ssl_channel_credentials()
50
48
  if enable_auth:
51
49
  if auth_metadata_plugin is None:
52
- user_config = UserAccountConfiguration()
53
- if issubclass(user_config._auth_client, Auth0ClientBase):
54
- auth_metadata_plugin = Auth0Client()
55
- else:
56
- auth_metadata_plugin = FrogMLGrpcClient()
50
+ auth_metadata_plugin = Auth0Client()
57
51
  credentials = grpc.composite_channel_credentials(
58
52
  credentials, grpc.metadata_call_credentials(auth_metadata_plugin)
59
53
  )
@@ -1,12 +1,14 @@
1
+ import logging
1
2
  import functools
2
3
  import inspect
3
4
  from inspect import BoundArguments, Signature
4
5
  from typing import Any, Callable, Optional
5
6
 
6
7
  import grpc
7
- from frogml_storage.logging import logger
8
8
  from qwak.exceptions import QwakException
9
9
 
10
+ logger = logging.getLogger()
11
+
10
12
 
11
13
  def grpc_try_catch_wrapper(
12
14
  exception_message: str,
@@ -238,8 +238,8 @@ class QwakClient:
238
238
  model = self._get_model_management().get_model(model_id=model_id)
239
239
  model_uuid = model.uuid
240
240
 
241
- metric_filters = list()
242
- parameter_filters = list()
241
+ metric_filters = []
242
+ parameter_filters = []
243
243
 
244
244
  for build_filter in filters:
245
245
  if isinstance(build_filter, MetricFilter):
@@ -356,7 +356,6 @@ class QwakClient:
356
356
  self,
357
357
  project_name: str,
358
358
  project_description: str,
359
- jfrog_project_key: Optional[str] = None,
360
359
  ) -> str:
361
360
  """
362
361
  Create project
@@ -364,7 +363,6 @@ class QwakClient:
364
363
  Args:
365
364
  project_name (str): The requested name
366
365
  project_description (str): The requested description
367
- jfrog_project_key (Optional[str]): The requested jfrog project key
368
366
 
369
367
  Returns:
370
368
  str: The project ID of the newly created project
@@ -373,7 +371,6 @@ class QwakClient:
373
371
  project = self._get_project_management().create_project(
374
372
  project_name=project_name,
375
373
  project_description=project_description,
376
- jfrog_project_key=jfrog_project_key,
377
374
  )
378
375
 
379
376
  return project.project.project_id
@@ -419,7 +416,6 @@ class QwakClient:
419
416
  project_id: str,
420
417
  model_name: str,
421
418
  model_description: str,
422
- jfrog_project_key: Optional[str] = None,
423
419
  ) -> str:
424
420
  """
425
421
  Create model
@@ -428,7 +424,6 @@ class QwakClient:
428
424
  project_id (str): The project ID to associate the model
429
425
  model_name (str): The requested name
430
426
  model_description (str): The requested description
431
- jfrog_project_key (Optional[str]): The jfrog project key
432
427
 
433
428
  Returns:
434
429
  str: The model ID of the newly created project
@@ -438,7 +433,6 @@ class QwakClient:
438
433
  project_id=project_id,
439
434
  model_name=model_name,
440
435
  model_description=model_description,
441
- jfrog_project_key=jfrog_project_key,
442
436
  )
443
437
 
444
438
  return model.model_id
@@ -4,25 +4,16 @@ import socket
4
4
  from datetime import datetime
5
5
 
6
6
  import requests
7
- from qwak.inner.di_configuration.account import UserAccountConfiguration
8
- from qwak.inner.tool.auth import Auth0ClientBase, FrogMLAuthClient
9
- from qwak.inner.const import QwakConstants
7
+ from qwak.inner.tool.auth import Auth0ClientBase
10
8
 
11
9
 
12
10
  def _get_authorization():
13
- user_account_configuration = UserAccountConfiguration()
14
- if issubclass(user_account_configuration._auth_client, Auth0ClientBase):
15
- auth_client = Auth0ClientBase()
16
- tenant_id = None
17
- else:
18
- auth_client = FrogMLAuthClient()
19
- tenant_id = auth_client.get_tenant_id()
20
-
11
+ auth_client = Auth0ClientBase()
21
12
  token = auth_client.get_token()
22
13
  token_split = token.split(".")
23
14
  decoded_token = json.loads(_base64url_decode(token_split[1]).decode("utf-8"))
24
15
  token_expiration = datetime.fromtimestamp(decoded_token["exp"])
25
- return f"Bearer {token}", token_expiration, tenant_id
16
+ return f"Bearer {token}", token_expiration
26
17
 
27
18
 
28
19
  def _base64url_decode(input):
@@ -77,8 +68,5 @@ class RestSession(requests.Session):
77
68
  return super().prepare_request(request)
78
69
 
79
70
  def prepare_request_token(self):
80
- auth_token, self.jwt_expiration, tenant_id = _get_authorization()
71
+ auth_token, self.jwt_expiration = _get_authorization()
81
72
  self.headers["Authorization"] = auth_token
82
-
83
- if tenant_id:
84
- self.headers[QwakConstants.JFROG_TENANT_HEADER_KEY] = tenant_id
@@ -0,0 +1,50 @@
1
+ Metadata-Version: 2.3
2
+ Name: qwak-core
3
+ Version: 0.4.392
4
+ Summary: Qwak Core contains the necessary objects and communication tools for using the Qwak Platform
5
+ License: Apache-2.0
6
+ Keywords: mlops,ml,deployment,serving,model
7
+ Author: Qwak
8
+ Author-email: info@qwak.com
9
+ Requires-Python: >=3.9,<3.12
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.7
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: Implementation :: CPython
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Provides-Extra: feature-store
21
+ Requires-Dist: PyYAML (>=6.0.2)
22
+ Requires-Dist: cachetools
23
+ Requires-Dist: chevron (==0.14.0)
24
+ Requires-Dist: cloudpickle (==2.2.1) ; extra == "feature-store"
25
+ Requires-Dist: dacite (==1.8.1)
26
+ Requires-Dist: dependency-injector (>=4.0)
27
+ Requires-Dist: filelock
28
+ Requires-Dist: grpcio (>=1.71.2)
29
+ Requires-Dist: joblib (>=1.3.2,<2.0.0)
30
+ Requires-Dist: marshmallow-dataclass (>=8.5.8,<9.0.0)
31
+ Requires-Dist: protobuf (>=4.25.8,<5)
32
+ Requires-Dist: pyarrow (>=20.0.0) ; extra == "feature-store"
33
+ Requires-Dist: pyathena (>=2.2.0,!=2.18.0) ; extra == "feature-store"
34
+ Requires-Dist: pydantic
35
+ Requires-Dist: pyspark (==3.4.2) ; extra == "feature-store"
36
+ Requires-Dist: python-jose[cryptography] (>=3.4.0)
37
+ Requires-Dist: python-json-logger (>=2.0.2)
38
+ Requires-Dist: requests
39
+ Requires-Dist: retrying (==1.3.4)
40
+ Requires-Dist: tqdm
41
+ Requires-Dist: typeguard (>=2,<3)
42
+ Requires-Dist: typer
43
+ Project-URL: Home page, https://www.qwak.com/
44
+ Description-Content-Type: text/markdown
45
+
46
+ # Qwak Core
47
+
48
+ Qwak is an end-to-end production ML platform designed to allow data scientists to build, deploy, and monitor their models in production with minimal engineering friction.
49
+ Qwak Core contains all the objects and tools necessary to use the Qwak Platform
50
+