qwak-core 0.4.265__py3-none-any.whl → 0.4.266__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.
- frogml_storage/__init__.py +0 -0
- frogml_storage/_artifactory_api.py +315 -0
- frogml_storage/_environment.py +22 -0
- frogml_storage/_log_config.py +45 -0
- frogml_storage/_storage_utils.py +15 -0
- frogml_storage/_utils.py +69 -0
- frogml_storage/authentication/_authentication_utils.py +259 -0
- frogml_storage/authentication/models/_auth_config.py +70 -0
- frogml_storage/cli/_frogml_cli.py +40 -0
- frogml_storage/cli/_login_cli.py +240 -0
- frogml_storage/cli/commands/_login_command.py +74 -0
- frogml_storage/cli/models/_cli_login_arguments.py +22 -0
- frogml_storage/cli/utils/_cli_utils.py +19 -0
- frogml_storage/cli/utils/_login_checks_utility.py +114 -0
- frogml_storage/constants.py +56 -0
- frogml_storage/dataset_manifest.py +13 -0
- frogml_storage/entity_manifest.py +93 -0
- frogml_storage/exceptions/checksum_verification_error.py +3 -0
- frogml_storage/exceptions/validation_error.py +4 -0
- frogml_storage/frog_ml.py +668 -0
- frogml_storage/frogml_entity_type_info.py +46 -0
- frogml_storage/http/__init__.py +0 -0
- frogml_storage/http/http_client.py +83 -0
- frogml_storage/model_manifest.py +60 -0
- frogml_storage/models/_download_context.py +54 -0
- frogml_storage/models/frogml_dataset_version.py +21 -0
- frogml_storage/models/frogml_entity_version.py +34 -0
- frogml_storage/models/frogml_model_version.py +21 -0
- frogml_storage/serialization_metadata.py +15 -0
- frogml_storage/storage.py +140 -0
- frogml_storage/utils/_input_checks_utility.py +104 -0
- qwak/__init__.py +1 -1
- qwak/clients/instance_template/client.py +6 -4
- qwak/clients/prompt_manager/model_descriptor_mapper.py +21 -19
- qwak/feature_store/_common/artifact_utils.py +3 -3
- qwak/feature_store/data_sources/base.py +4 -4
- qwak/feature_store/data_sources/batch/athena.py +3 -3
- qwak/feature_store/feature_sets/streaming.py +3 -3
- qwak/feature_store/feature_sets/streaming_backfill.py +1 -1
- qwak/feature_store/online/client.py +6 -6
- qwak/feature_store/sinks/streaming/factory.py +1 -1
- qwak/inner/build_logic/phases/phase_010_fetch_model/fetch_strategy_manager/strategy/git/git_strategy.py +3 -3
- qwak/llmops/provider/openai/provider.py +3 -3
- qwak/model/tools/adapters/output.py +1 -1
- qwak/model/utils/feature_utils.py +12 -8
- qwak/model_loggers/artifact_logger.py +7 -7
- qwak/tools/logger/logger.py +1 -1
- qwak_core-0.4.266.dist-info/METADATA +419 -0
- {qwak_core-0.4.265.dist-info → qwak_core-0.4.266.dist-info}/RECORD +51 -19
- qwak_core-0.4.266.dist-info/entry_points.txt +3 -0
- qwak_core-0.4.265.dist-info/METADATA +0 -53
- {qwak_core-0.4.265.dist-info → qwak_core-0.4.266.dist-info}/WHEEL +0 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
|
4
|
+
class LoginArguments(object):
|
5
|
+
isAnonymous: bool = False
|
6
|
+
server_id: Optional[str] = None
|
7
|
+
username: Optional[str] = None
|
8
|
+
password: Optional[str] = None
|
9
|
+
access_token: Optional[str] = None
|
10
|
+
artifactory_url: Optional[str] = None
|
11
|
+
|
12
|
+
def __eq__(self, other):
|
13
|
+
if not isinstance(other, LoginArguments):
|
14
|
+
return False
|
15
|
+
return (
|
16
|
+
self.isAnonymous == other.isAnonymous
|
17
|
+
and self.server_id == other.server_id
|
18
|
+
and self.username == other.username
|
19
|
+
and self.password == other.password
|
20
|
+
and self.access_token == other.access_token
|
21
|
+
and self.artifactory_url == other.artifactory_url
|
22
|
+
)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
|
4
|
+
def get_list_of_servers_from_config(jfrog_cli_config: dict) -> List[str]:
|
5
|
+
if jfrog_cli_config is not None:
|
6
|
+
servers = jfrog_cli_config.get("servers")
|
7
|
+
if servers is not None:
|
8
|
+
return list(map(__map_server_ids, servers))
|
9
|
+
|
10
|
+
return []
|
11
|
+
|
12
|
+
|
13
|
+
def __map_server_ids(server: dict) -> str:
|
14
|
+
server_id = ""
|
15
|
+
if server is not None:
|
16
|
+
server_id = str(server.get("serverId"))
|
17
|
+
if server.get("isDefault") is not None and bool(server.get("isDefault")):
|
18
|
+
server_id = server_id + " (Default)"
|
19
|
+
return server_id
|
@@ -0,0 +1,114 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
from frogml_storage.authentication.models._auth_config import AuthConfig
|
4
|
+
|
5
|
+
|
6
|
+
def login_input_checks(
|
7
|
+
url: Optional[str] = None,
|
8
|
+
username: Optional[str] = None,
|
9
|
+
password: Optional[str] = None,
|
10
|
+
token: Optional[str] = None,
|
11
|
+
anonymous: bool = False,
|
12
|
+
) -> bool:
|
13
|
+
return (
|
14
|
+
__is_user_name_password_command(url, username, password, token, anonymous)
|
15
|
+
or __is_access_token_command(url, username, password, token, anonymous)
|
16
|
+
or __is_anonymous_command(url, username, password, token, anonymous)
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
def is_login_command_without_params(
|
21
|
+
url: Optional[str] = None,
|
22
|
+
username: Optional[str] = None,
|
23
|
+
password: Optional[str] = None,
|
24
|
+
token: Optional[str] = None,
|
25
|
+
anonymous: bool = False,
|
26
|
+
) -> bool:
|
27
|
+
return (
|
28
|
+
all(params is None for params in [url, username, password, token])
|
29
|
+
and not anonymous
|
30
|
+
)
|
31
|
+
|
32
|
+
|
33
|
+
def is_username_password_login(
|
34
|
+
auth_config: AuthConfig, anonymous: Optional[bool] = False
|
35
|
+
) -> bool:
|
36
|
+
return __is_user_name_password_command(
|
37
|
+
url=auth_config.artifactory_url,
|
38
|
+
username=auth_config.user,
|
39
|
+
password=auth_config.password,
|
40
|
+
token=auth_config.access_token,
|
41
|
+
anonymous=anonymous,
|
42
|
+
)
|
43
|
+
|
44
|
+
|
45
|
+
def is_access_token_login(
|
46
|
+
auth_config: AuthConfig, anonymous: Optional[bool] = False
|
47
|
+
) -> bool:
|
48
|
+
if anonymous is None:
|
49
|
+
anonymous = False
|
50
|
+
return __is_access_token_command(
|
51
|
+
url=auth_config.artifactory_url,
|
52
|
+
username=auth_config.user,
|
53
|
+
password=auth_config.password,
|
54
|
+
token=auth_config.access_token,
|
55
|
+
anonymous=anonymous,
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
def is_anonymous_login(
|
60
|
+
auth_config: AuthConfig, anonymous: Optional[bool] = False
|
61
|
+
) -> bool:
|
62
|
+
if anonymous is None:
|
63
|
+
anonymous = False
|
64
|
+
return __is_anonymous_command(
|
65
|
+
url=auth_config.artifactory_url,
|
66
|
+
username=auth_config.user,
|
67
|
+
password=auth_config.password,
|
68
|
+
token=auth_config.access_token,
|
69
|
+
anonymous=anonymous,
|
70
|
+
)
|
71
|
+
|
72
|
+
|
73
|
+
def __is_anonymous_command(
|
74
|
+
url: Optional[str],
|
75
|
+
username: Optional[str],
|
76
|
+
password: Optional[str],
|
77
|
+
token: Optional[str],
|
78
|
+
anonymous: bool,
|
79
|
+
) -> bool:
|
80
|
+
return (
|
81
|
+
anonymous
|
82
|
+
and all(params is None for params in [username, password, token])
|
83
|
+
and url is not None
|
84
|
+
)
|
85
|
+
|
86
|
+
|
87
|
+
def __is_access_token_command(
|
88
|
+
url: Optional[str],
|
89
|
+
username: Optional[str],
|
90
|
+
password: Optional[str],
|
91
|
+
token: Optional[str],
|
92
|
+
anonymous: bool,
|
93
|
+
) -> bool:
|
94
|
+
if anonymous:
|
95
|
+
return False
|
96
|
+
return all(params is None for params in [username, password]) and all(
|
97
|
+
params is not None for params in [url, token]
|
98
|
+
)
|
99
|
+
|
100
|
+
|
101
|
+
def __is_user_name_password_command(
|
102
|
+
url: Optional[str],
|
103
|
+
username: Optional[str],
|
104
|
+
password: Optional[str],
|
105
|
+
token: Optional[str],
|
106
|
+
anonymous: Optional[bool] = False,
|
107
|
+
) -> bool:
|
108
|
+
return (
|
109
|
+
not anonymous
|
110
|
+
and url is not None
|
111
|
+
and username is not None
|
112
|
+
and password is not None
|
113
|
+
and token is None
|
114
|
+
)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
home_dir = os.path.expanduser("~")
|
4
|
+
|
5
|
+
JFROG_CLI_CONFIG_FILE_PATH = os.path.join(home_dir, ".jfrog", "jfrog-cli.conf.v6")
|
6
|
+
CONFIG_FILE_PATH = os.path.join(home_dir, ".frogml", "config.json")
|
7
|
+
|
8
|
+
FROG_ML_CONFIG_USER = "user"
|
9
|
+
FROG_ML_CONFIG_ARTIFACTORY_URL = "artifactory_url"
|
10
|
+
FROG_ML_CONFIG_PASSWORD = "password" # nosec B105
|
11
|
+
FROG_ML_CONFIG_ACCESS_TOKEN = "access_token" # nosec B105
|
12
|
+
FROG_ML_DEFAULT_HTTP_THREADS_COUNT = 5
|
13
|
+
FROG_ML_MAX_CHARS_FOR_NAME = 60
|
14
|
+
|
15
|
+
SERVER_ID = "server_id"
|
16
|
+
|
17
|
+
JFROG_CLI_CONFIG_ARTIFACTORY_URL = "artifactoryUrl"
|
18
|
+
JFROG_CLI_CONFIG_URL = "url"
|
19
|
+
JFROG_CLI_CONFIG_USER = "user"
|
20
|
+
JFROG_CLI_CONFIG_PASSWORD = "password" # nosec B105
|
21
|
+
JFROG_CLI_CONFIG_ACCESS_TOKEN = "accessToken" # nosec B105
|
22
|
+
|
23
|
+
MODEL = "model"
|
24
|
+
ROOT_FROGML_MODEL_UI_DIRECTORY = "models"
|
25
|
+
MODEL_UI_DIRECTORY = "model"
|
26
|
+
MODEL_METADATA_FILE_NAME = "model-manifest.json"
|
27
|
+
BODY_PART_MODEL_MANIFEST_STREAM = "modelManifest"
|
28
|
+
|
29
|
+
DATASET = "dataset"
|
30
|
+
ROOT_FROGML_DATASET_UI_DIRECTORY = "datasets"
|
31
|
+
DATASET_UI_DIRECTORY = "dataset"
|
32
|
+
DATASET_METADATA_FILE_NAME = "dataset-manifest.json"
|
33
|
+
BODY_PART_DATASET_MANIFEST_STREAM = "datasetManifest"
|
34
|
+
|
35
|
+
CHECKSUM_SHA2_HEADER = "X-Checksum-Sha256"
|
36
|
+
|
37
|
+
JFML_THREAD_COUNT = "JFML_THREAD_COUNT"
|
38
|
+
JF_URL = "JF_URL"
|
39
|
+
JF_ACCESS_TOKEN = "JF_ACCESS_TOKEN" # nosec B105
|
40
|
+
|
41
|
+
FROG_ML_IGNORED_FILES = [
|
42
|
+
".DS_Store",
|
43
|
+
"CVS",
|
44
|
+
".cvsignore",
|
45
|
+
"SCCS",
|
46
|
+
"vssver.scc",
|
47
|
+
".svn",
|
48
|
+
".git",
|
49
|
+
".gitignore",
|
50
|
+
".gitattributes",
|
51
|
+
".gitmodules",
|
52
|
+
".gitkeep",
|
53
|
+
".gitconfig",
|
54
|
+
MODEL_METADATA_FILE_NAME,
|
55
|
+
DATASET_METADATA_FILE_NAME,
|
56
|
+
]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from typing import List
|
2
|
+
|
3
|
+
from pydantic import Field
|
4
|
+
|
5
|
+
from frogml_storage.entity_manifest import Artifact, EntityManifest
|
6
|
+
|
7
|
+
|
8
|
+
class DatasetManifest(EntityManifest):
|
9
|
+
"""
|
10
|
+
Represent a dataset manifest file
|
11
|
+
"""
|
12
|
+
|
13
|
+
artifacts: List[Artifact] = Field(serialization_alias="dataset_artifacts")
|
@@ -0,0 +1,93 @@
|
|
1
|
+
import os
|
2
|
+
from abc import ABC
|
3
|
+
from typing import List, Optional
|
4
|
+
|
5
|
+
from pydantic import BaseModel
|
6
|
+
|
7
|
+
from frogml_storage._storage_utils import calc_content_sha2, calculate_sha2
|
8
|
+
|
9
|
+
|
10
|
+
class Checksums(BaseModel):
|
11
|
+
sha2: str
|
12
|
+
|
13
|
+
@classmethod
|
14
|
+
def calc_checksums(cls, file_path: str) -> "Checksums":
|
15
|
+
return cls(sha2=calculate_sha2(file_path))
|
16
|
+
|
17
|
+
@classmethod
|
18
|
+
def calc_content_checksums(cls, content: str) -> "Checksums":
|
19
|
+
return cls(sha2=calc_content_sha2(content))
|
20
|
+
|
21
|
+
|
22
|
+
class Artifact(BaseModel):
|
23
|
+
artifact_path: str
|
24
|
+
size: int
|
25
|
+
checksums: Checksums
|
26
|
+
|
27
|
+
def __eq__(self, other):
|
28
|
+
if not isinstance(other, Artifact):
|
29
|
+
return False
|
30
|
+
return (
|
31
|
+
self.artifact_path == other.artifact_path
|
32
|
+
and self.size == other.size
|
33
|
+
and self.checksums == other.checksums
|
34
|
+
)
|
35
|
+
|
36
|
+
|
37
|
+
class EntityManifest(BaseModel, ABC):
|
38
|
+
"""
|
39
|
+
Represent an entity manifest file
|
40
|
+
|
41
|
+
Attributes:
|
42
|
+
created_date: The date the model | dataset were uploaded to Artifactory
|
43
|
+
artifacts: A list of artifacts that belong to the model | dataset
|
44
|
+
id: <organization>/<entity_name> - exists only for downloaded EntityInfo
|
45
|
+
version: The entity version - exists only for downloaded EntityInfo
|
46
|
+
"""
|
47
|
+
|
48
|
+
created_date: str
|
49
|
+
artifacts: List[Artifact]
|
50
|
+
id: Optional[str] = None
|
51
|
+
version: Optional[str] = None
|
52
|
+
|
53
|
+
def add_file(self, file_path: str, checksums: Checksums, rel_path: str) -> None:
|
54
|
+
self.artifacts.append(
|
55
|
+
Artifact(
|
56
|
+
artifact_path=rel_path,
|
57
|
+
size=os.path.getsize(file_path),
|
58
|
+
checksums=checksums,
|
59
|
+
)
|
60
|
+
)
|
61
|
+
|
62
|
+
def add_content_file(self, rel_path: str, content: str) -> None:
|
63
|
+
checksums = Checksums.calc_content_checksums(content)
|
64
|
+
self.artifacts.append(
|
65
|
+
Artifact(
|
66
|
+
artifact_path=rel_path,
|
67
|
+
size=len((content, "utf-8")),
|
68
|
+
checksums=checksums,
|
69
|
+
)
|
70
|
+
)
|
71
|
+
|
72
|
+
@classmethod
|
73
|
+
def from_json(cls, json_str: str) -> "EntityManifest":
|
74
|
+
return cls.model_validate_json(json_str)
|
75
|
+
|
76
|
+
def to_json(self) -> str:
|
77
|
+
return self.model_dump_json(by_alias=True, exclude_none=True)
|
78
|
+
|
79
|
+
def __eq__(self, other):
|
80
|
+
if not isinstance(other, EntityManifest):
|
81
|
+
return False
|
82
|
+
if self.id != other.id:
|
83
|
+
return False
|
84
|
+
if self.version != other.version:
|
85
|
+
return False
|
86
|
+
if self.created_date != other.created_date:
|
87
|
+
return False
|
88
|
+
if len(self.artifacts) != len(other.artifacts):
|
89
|
+
return False
|
90
|
+
for self_artifact, other_artifact in zip(self.artifacts, other.artifacts):
|
91
|
+
if self_artifact != other_artifact:
|
92
|
+
return False
|
93
|
+
return True
|