clarifai 11.2.2__py3-none-any.whl → 11.2.3rc1__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.
- clarifai/__init__.py +1 -1
- clarifai/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/__pycache__/errors.cpython-312.pyc +0 -0
- clarifai/__pycache__/versions.cpython-312.pyc +0 -0
- clarifai/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/cli/__pycache__/base.cpython-312.pyc +0 -0
- clarifai/cli/__pycache__/compute_cluster.cpython-312.pyc +0 -0
- clarifai/cli/__pycache__/deployment.cpython-312.pyc +0 -0
- clarifai/cli/__pycache__/model.cpython-312.pyc +0 -0
- clarifai/cli/__pycache__/nodepool.cpython-312.pyc +0 -0
- clarifai/cli/base.py +225 -89
- clarifai/cli/compute_cluster.py +21 -20
- clarifai/cli/deployment.py +63 -41
- clarifai/cli/model.py +1 -1
- clarifai/cli/nodepool.py +56 -40
- clarifai/client/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/app.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/base.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/compute_cluster.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/dataset.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/deployment.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/input.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/lister.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/model.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/model_client.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/module.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/nodepool.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/search.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/user.cpython-312.pyc +0 -0
- clarifai/client/__pycache__/workflow.cpython-312.pyc +0 -0
- clarifai/client/auth/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/client/auth/__pycache__/helper.cpython-312.pyc +0 -0
- clarifai/client/auth/__pycache__/register.cpython-312.pyc +0 -0
- clarifai/client/auth/__pycache__/stub.cpython-312.pyc +0 -0
- clarifai/constants/__pycache__/base.cpython-312.pyc +0 -0
- clarifai/constants/__pycache__/dataset.cpython-312.pyc +0 -0
- clarifai/constants/__pycache__/input.cpython-312.pyc +0 -0
- clarifai/constants/__pycache__/model.cpython-312.pyc +0 -0
- clarifai/constants/__pycache__/search.cpython-312.pyc +0 -0
- clarifai/constants/__pycache__/workflow.cpython-312.pyc +0 -0
- clarifai/datasets/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/datasets/export/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/datasets/export/__pycache__/inputs_annotations.cpython-312.pyc +0 -0
- clarifai/datasets/upload/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/datasets/upload/__pycache__/base.cpython-312.pyc +0 -0
- clarifai/datasets/upload/__pycache__/features.cpython-312.pyc +0 -0
- clarifai/datasets/upload/__pycache__/image.cpython-312.pyc +0 -0
- clarifai/datasets/upload/__pycache__/multimodal.cpython-312.pyc +0 -0
- clarifai/datasets/upload/__pycache__/text.cpython-312.pyc +0 -0
- clarifai/datasets/upload/__pycache__/utils.cpython-312.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/datasets/upload/loaders/__pycache__/coco_detection.cpython-312.pyc +0 -0
- clarifai/modules/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/modules/__pycache__/css.cpython-312.pyc +0 -0
- clarifai/runners/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/runners/__pycache__/server.cpython-312.pyc +0 -0
- clarifai/runners/models/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/runners/models/__pycache__/base_typed_model.cpython-312.pyc +0 -0
- clarifai/runners/models/__pycache__/model_builder.cpython-312.pyc +0 -0
- clarifai/runners/models/__pycache__/model_class.cpython-312.pyc +0 -0
- clarifai/runners/models/__pycache__/model_run_locally.cpython-312.pyc +0 -0
- clarifai/runners/models/__pycache__/model_runner.cpython-312.pyc +0 -0
- clarifai/runners/models/__pycache__/model_servicer.cpython-312.pyc +0 -0
- clarifai/runners/models/model_builder.py +17 -7
- clarifai/runners/models/model_run_locally.py +1 -0
- clarifai/runners/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/runners/utils/__pycache__/const.cpython-312.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_handler.cpython-312.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_types.cpython-312.pyc +0 -0
- clarifai/runners/utils/__pycache__/data_utils.cpython-312.pyc +0 -0
- clarifai/runners/utils/__pycache__/loader.cpython-312.pyc +0 -0
- clarifai/runners/utils/__pycache__/method_signatures.cpython-312.pyc +0 -0
- clarifai/runners/utils/__pycache__/serializers.cpython-312.pyc +0 -0
- clarifai/runners/utils/__pycache__/url_fetcher.cpython-312.pyc +0 -0
- clarifai/runners/utils/const.py +9 -8
- clarifai/schema/__pycache__/search.cpython-312.pyc +0 -0
- clarifai/urls/__pycache__/helper.cpython-312.pyc +0 -0
- clarifai/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/utils/__pycache__/cli.cpython-312.pyc +0 -0
- clarifai/utils/__pycache__/config.cpython-312.pyc +0 -0
- clarifai/utils/__pycache__/constants.cpython-312.pyc +0 -0
- clarifai/utils/__pycache__/logging.cpython-312.pyc +0 -0
- clarifai/utils/__pycache__/misc.cpython-312.pyc +0 -0
- clarifai/utils/__pycache__/model_train.cpython-312.pyc +0 -0
- clarifai/utils/cli.py +124 -34
- clarifai/utils/config.py +105 -0
- clarifai/utils/config.py~ +145 -0
- clarifai/utils/constants.py +4 -0
- clarifai/utils/evaluation/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/helpers.cpython-312.pyc +0 -0
- clarifai/utils/evaluation/__pycache__/main.cpython-312.pyc +0 -0
- clarifai/utils/misc.py +2 -0
- clarifai/workflows/__pycache__/__init__.cpython-312.pyc +0 -0
- clarifai/workflows/__pycache__/export.cpython-312.pyc +0 -0
- clarifai/workflows/__pycache__/utils.cpython-312.pyc +0 -0
- clarifai/workflows/__pycache__/validate.cpython-312.pyc +0 -0
- {clarifai-11.2.2.dist-info → clarifai-11.2.3rc1.dist-info}/METADATA +3 -15
- clarifai-11.2.3rc1.dist-info/RECORD +185 -0
- {clarifai-11.2.2.dist-info → clarifai-11.2.3rc1.dist-info}/WHEEL +1 -1
- clarifai-11.2.2.dist-info/RECORD +0 -101
- {clarifai-11.2.2.dist-info/licenses → clarifai-11.2.3rc1.dist-info}/LICENSE +0 -0
- {clarifai-11.2.2.dist-info → clarifai-11.2.3rc1.dist-info}/entry_points.txt +0 -0
- {clarifai-11.2.2.dist-info → clarifai-11.2.3rc1.dist-info}/top_level.txt +0 -0
clarifai/cli/nodepool.py
CHANGED
@@ -1,30 +1,27 @@
|
|
1
1
|
import click
|
2
|
+
|
2
3
|
from clarifai.cli.base import cli
|
3
4
|
from clarifai.client.compute_cluster import ComputeCluster
|
4
|
-
from clarifai.
|
5
|
+
from clarifai.client.user import User
|
6
|
+
from clarifai.utils.cli import (AliasedGroup, display_co_resources, dump_yaml, from_yaml,
|
7
|
+
validate_context)
|
5
8
|
|
6
9
|
|
7
|
-
@cli.group(['nodepool', 'np'])
|
10
|
+
@cli.group(['nodepool', 'np'], cls=AliasedGroup)
|
8
11
|
def nodepool():
|
9
12
|
"""Manage Nodepools: create, delete, list"""
|
10
|
-
pass
|
11
13
|
|
12
14
|
|
13
|
-
@nodepool.command()
|
14
|
-
@click.
|
15
|
-
|
16
|
-
'--compute_cluster_id',
|
17
|
-
required=False,
|
18
|
-
help='Compute Cluster ID for the compute cluster to interact with.')
|
15
|
+
@nodepool.command(['c'])
|
16
|
+
@click.argument('compute_cluster_id')
|
17
|
+
@click.argument('nodepool_id')
|
19
18
|
@click.option(
|
20
19
|
'--config',
|
21
20
|
type=click.Path(exists=True),
|
22
21
|
required=True,
|
23
22
|
help='Path to the nodepool config file.')
|
24
|
-
@click.option(
|
25
|
-
'-np_id', '--nodepool_id', required=False, help='New Nodepool ID for the nodepool to create.')
|
26
23
|
@click.pass_context
|
27
|
-
def create(ctx, compute_cluster_id,
|
24
|
+
def create(ctx, compute_cluster_id, nodepool_id, config):
|
28
25
|
"""Create a new Nodepool with the given config file."""
|
29
26
|
|
30
27
|
validate_context(ctx)
|
@@ -43,44 +40,63 @@ def create(ctx, compute_cluster_id, config, nodepool_id):
|
|
43
40
|
|
44
41
|
compute_cluster = ComputeCluster(
|
45
42
|
compute_cluster_id=compute_cluster_id,
|
46
|
-
user_id=ctx.obj
|
47
|
-
pat=ctx.obj
|
48
|
-
base_url=ctx.obj
|
43
|
+
user_id=ctx.obj.current.user_id,
|
44
|
+
pat=ctx.obj.current.pat,
|
45
|
+
base_url=ctx.obj.current.api_base)
|
49
46
|
if nodepool_id:
|
50
47
|
compute_cluster.create_nodepool(config, nodepool_id=nodepool_id)
|
51
48
|
else:
|
52
49
|
compute_cluster.create_nodepool(config)
|
53
50
|
|
54
51
|
|
55
|
-
@nodepool.command()
|
56
|
-
@click.
|
57
|
-
'-cc_id',
|
58
|
-
'--compute_cluster_id',
|
59
|
-
required=True,
|
60
|
-
help='Compute Cluster ID for the compute cluster to interact with.')
|
52
|
+
@nodepool.command(['ls'])
|
53
|
+
@click.argument('compute_cluster_id', default="")
|
61
54
|
@click.option('--page_no', required=False, help='Page number to list.', default=1)
|
62
|
-
@click.option('--per_page', required=False, help='Number of items per page.', default=
|
55
|
+
@click.option('--per_page', required=False, help='Number of items per page.', default=128)
|
63
56
|
@click.pass_context
|
64
57
|
def list(ctx, compute_cluster_id, page_no, per_page):
|
65
|
-
"""List all nodepools for the user.
|
58
|
+
"""List all nodepools for the user across all compute clusters. If compute_cluster_id is provided
|
59
|
+
it will list only within that compute cluster. """
|
66
60
|
|
67
61
|
validate_context(ctx)
|
68
|
-
compute_cluster = ComputeCluster(
|
69
|
-
compute_cluster_id=compute_cluster_id,
|
70
|
-
user_id=ctx.obj['user_id'],
|
71
|
-
pat=ctx.obj['pat'],
|
72
|
-
base_url=ctx.obj['base_url'])
|
73
|
-
response = compute_cluster.list_nodepools(page_no, per_page)
|
74
|
-
display_co_resources(response, "Nodepool")
|
75
62
|
|
63
|
+
cc_id = compute_cluster_id
|
76
64
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
65
|
+
if cc_id:
|
66
|
+
compute_cluster = ComputeCluster(
|
67
|
+
compute_cluster_id=cc_id,
|
68
|
+
user_id=ctx.obj.current.user_id,
|
69
|
+
pat=ctx.obj.current.pat,
|
70
|
+
base_url=ctx.obj.current.api_base)
|
71
|
+
response = compute_cluster.list_nodepools(page_no, per_page)
|
72
|
+
else:
|
73
|
+
user = User(
|
74
|
+
user_id=ctx.obj.current.user_id,
|
75
|
+
pat=ctx.obj.current.pat,
|
76
|
+
base_url=ctx.obj.current.api_base)
|
77
|
+
ccs = user.list_compute_clusters(page_no, per_page)
|
78
|
+
response = []
|
79
|
+
for cc in ccs:
|
80
|
+
compute_cluster = ComputeCluster(
|
81
|
+
compute_cluster_id=cc.id,
|
82
|
+
user_id=ctx.obj.current.user_id,
|
83
|
+
pat=ctx.obj.current.pat,
|
84
|
+
base_url=ctx.obj.current.api_base)
|
85
|
+
response.extend([i for i in compute_cluster.list_nodepools(page_no, per_page)])
|
86
|
+
|
87
|
+
display_co_resources(
|
88
|
+
response,
|
89
|
+
custom_columns={
|
90
|
+
'ID': lambda c: c.id,
|
91
|
+
'USER_ID': lambda c: c.compute_cluster.user_id,
|
92
|
+
'COMPUTE_CLUSTER_ID': lambda c: c.compute_cluster.id,
|
93
|
+
'DESCRIPTION': lambda c: c.description,
|
94
|
+
})
|
95
|
+
|
96
|
+
|
97
|
+
@nodepool.command(['rm'])
|
98
|
+
@click.argument('compute_cluster_id')
|
99
|
+
@click.argument('nodepool_id')
|
84
100
|
@click.pass_context
|
85
101
|
def delete(ctx, compute_cluster_id, nodepool_id):
|
86
102
|
"""Deletes a nodepool for the user."""
|
@@ -88,7 +104,7 @@ def delete(ctx, compute_cluster_id, nodepool_id):
|
|
88
104
|
validate_context(ctx)
|
89
105
|
compute_cluster = ComputeCluster(
|
90
106
|
compute_cluster_id=compute_cluster_id,
|
91
|
-
user_id=ctx.obj
|
92
|
-
pat=ctx.obj
|
93
|
-
base_url=ctx.obj
|
107
|
+
user_id=ctx.obj.current.user_id,
|
108
|
+
pat=ctx.obj.current.pat,
|
109
|
+
base_url=ctx.obj.current.api_base)
|
94
110
|
compute_cluster.delete_nodepools([nodepool_id])
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -142,17 +142,21 @@ class ModelBuilder:
|
|
142
142
|
def _validate_config_checkpoints(self):
|
143
143
|
"""
|
144
144
|
Validates the checkpoints section in the config file.
|
145
|
+
return loader_type, repo_id, hf_token, when, allowed_file_patterns, ignore_file_patterns
|
145
146
|
:return: loader_type the type of loader or None if no checkpoints.
|
146
147
|
:return: repo_id location of checkpoint.
|
147
148
|
:return: hf_token token to access checkpoint.
|
149
|
+
:return: when one of ['upload', 'build', 'runtime'] to download checkpoint
|
150
|
+
:return: allowed_file_patterns patterns to allow in downloaded checkpoint
|
151
|
+
:return: ignore_file_patterns patterns to ignore in downloaded checkpoint
|
148
152
|
"""
|
149
153
|
if "checkpoints" not in self.config:
|
150
|
-
return None, None, None, DEFAULT_DOWNLOAD_CHECKPOINT_WHEN
|
154
|
+
return None, None, None, DEFAULT_DOWNLOAD_CHECKPOINT_WHEN, None, None
|
151
155
|
assert "type" in self.config.get("checkpoints"), "No loader type specified in the config file"
|
152
156
|
loader_type = self.config.get("checkpoints").get("type")
|
153
157
|
if not loader_type:
|
154
158
|
logger.info("No loader type specified in the config file for checkpoints")
|
155
|
-
return None, None, None
|
159
|
+
return None, None, None, DEFAULT_DOWNLOAD_CHECKPOINT_WHEN, None, None
|
156
160
|
checkpoints = self.config.get("checkpoints")
|
157
161
|
if 'when' not in checkpoints:
|
158
162
|
logger.warn(
|
@@ -184,9 +188,17 @@ class ModelBuilder:
|
|
184
188
|
resp = self.client.STUB.GetApp(service_pb2.GetAppRequest(user_app_id=self.client.user_app_id))
|
185
189
|
if resp.status.code == status_code_pb2.SUCCESS:
|
186
190
|
return True
|
191
|
+
if resp.status.code == status_code_pb2.CONN_KEY_INVALID:
|
192
|
+
logger.error(
|
193
|
+
f"Invalid PAT provided for user {self.client.user_app_id.user_id}. Please check your PAT and try again."
|
194
|
+
)
|
195
|
+
return False
|
187
196
|
logger.error(
|
188
197
|
f"Error checking API {self._base_api} for user app {self.client.user_app_id.user_id}/{self.client.user_app_id.app_id}. Error code: {resp.status.code}"
|
189
198
|
)
|
199
|
+
logger.error(
|
200
|
+
f"App {self.client.user_app_id.app_id} not found for user {self.client.user_app_id.user_id}. Please create the app first and try again."
|
201
|
+
)
|
190
202
|
return False
|
191
203
|
|
192
204
|
def _validate_config_model(self):
|
@@ -207,9 +219,6 @@ class ModelBuilder:
|
|
207
219
|
assert model.get('id') != "", "model_id cannot be empty in the config file"
|
208
220
|
|
209
221
|
if not self._check_app_exists():
|
210
|
-
logger.error(
|
211
|
-
f"App {self.client.user_app_id.app_id} not found for user {self.client.user_app_id.user_id}"
|
212
|
-
)
|
213
222
|
sys.exit(1)
|
214
223
|
|
215
224
|
def _validate_config(self):
|
@@ -406,11 +415,12 @@ class ModelBuilder:
|
|
406
415
|
# Sort in reverse so that newer cuda versions come first and are preferred.
|
407
416
|
for image in sorted(AVAILABLE_TORCH_IMAGES, reverse=True):
|
408
417
|
if torch_version in image and f'py{python_version}' in image:
|
409
|
-
|
418
|
+
# like cu124, rocm6.3, etc.
|
419
|
+
gpu_version = image.split('-')[-1]
|
410
420
|
final_image = TORCH_BASE_IMAGE.format(
|
411
421
|
torch_version=torch_version,
|
412
422
|
python_version=python_version,
|
413
|
-
|
423
|
+
gpu_version=gpu_version,
|
414
424
|
)
|
415
425
|
logger.info(f"Using Torch version {torch_version} base image to build the Docker image")
|
416
426
|
break
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
clarifai/runners/utils/const.py
CHANGED
@@ -2,10 +2,10 @@ import os
|
|
2
2
|
|
3
3
|
registry = os.environ.get('CLARIFAI_BASE_IMAGE_REGISTRY', 'public.ecr.aws/clarifai-models')
|
4
4
|
|
5
|
-
GIT_SHA = "
|
5
|
+
GIT_SHA = "b8ae56bf3b7c95e686ca002b07ca83d259c716eb"
|
6
6
|
|
7
7
|
PYTHON_BASE_IMAGE = registry + '/python-base:{python_version}-' + GIT_SHA
|
8
|
-
TORCH_BASE_IMAGE = registry + '/torch:{torch_version}-py{python_version}-
|
8
|
+
TORCH_BASE_IMAGE = registry + '/torch:{torch_version}-py{python_version}-{gpu_version}-' + GIT_SHA
|
9
9
|
|
10
10
|
# List of available python base images
|
11
11
|
AVAILABLE_PYTHON_IMAGES = ['3.11', '3.12']
|
@@ -21,12 +21,13 @@ DEFAULT_RUNTIME_DOWNLOAD_PATH = os.path.join(os.sep, "tmp", ".cache")
|
|
21
21
|
# List of available torch images
|
22
22
|
# Keep sorted by most recent cuda version.
|
23
23
|
AVAILABLE_TORCH_IMAGES = [
|
24
|
-
'2.4.1-py3.11-
|
25
|
-
'2.5.1-py3.11-
|
26
|
-
'2.4.1-py3.12-
|
27
|
-
'2.5.1-py3.12-
|
28
|
-
|
29
|
-
|
24
|
+
'2.4.1-py3.11-cu124',
|
25
|
+
'2.5.1-py3.11-cu124',
|
26
|
+
'2.4.1-py3.12-cu124',
|
27
|
+
'2.5.1-py3.12-cu124',
|
28
|
+
'2.6.0-py3.12-cu126',
|
29
|
+
'2.7.0-py3.12-cu128',
|
30
|
+
'2.7.0-py3.12-rocm6.3',
|
30
31
|
]
|
31
32
|
CONCEPTS_REQUIRED_MODEL_TYPE = [
|
32
33
|
'visual-classifier', 'visual-detector', 'visual-segmenter', 'text-classifier'
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
clarifai/utils/cli.py
CHANGED
@@ -2,14 +2,13 @@ import importlib
|
|
2
2
|
import os
|
3
3
|
import pkgutil
|
4
4
|
import sys
|
5
|
+
import typing as t
|
6
|
+
from collections import defaultdict
|
7
|
+
from typing import OrderedDict
|
5
8
|
|
6
9
|
import click
|
7
10
|
import yaml
|
8
|
-
|
9
|
-
from rich.console import Console
|
10
|
-
from rich.panel import Panel
|
11
|
-
from rich.style import Style
|
12
|
-
from rich.text import Text
|
11
|
+
from tabulate import tabulate
|
13
12
|
|
14
13
|
from clarifai.utils.logging import logger
|
15
14
|
|
@@ -31,19 +30,6 @@ def dump_yaml(data, filename: str):
|
|
31
30
|
click.echo(f"Error writing YAML file: {e}", err=True)
|
32
31
|
|
33
32
|
|
34
|
-
def set_base_url(env):
|
35
|
-
environments = {
|
36
|
-
'prod': 'https://api.clarifai.com',
|
37
|
-
'staging': 'https://api-staging.clarifai.com',
|
38
|
-
'dev': 'https://api-dev.clarifai.com'
|
39
|
-
}
|
40
|
-
|
41
|
-
if env in environments:
|
42
|
-
return environments[env]
|
43
|
-
else:
|
44
|
-
raise ValueError("Invalid environment. Please choose from 'prod', 'staging', 'dev'.")
|
45
|
-
|
46
|
-
|
47
33
|
# Dynamically find and import all command modules from the cli directory
|
48
34
|
def load_command_modules():
|
49
35
|
package_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'cli')
|
@@ -53,24 +39,128 @@ def load_command_modules():
|
|
53
39
|
importlib.import_module(f'clarifai.cli.{module_name}')
|
54
40
|
|
55
41
|
|
56
|
-
def display_co_resources(response,
|
42
|
+
def display_co_resources(response,
|
43
|
+
custom_columns={
|
44
|
+
'ID': lambda c: c.id,
|
45
|
+
'USER_ID': lambda c: c.user_id,
|
46
|
+
'DESCRIPTION': lambda c: c.description,
|
47
|
+
}):
|
57
48
|
"""Display compute orchestration resources listing results using rich."""
|
58
49
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
50
|
+
formatter = TableFormatter(custom_columns)
|
51
|
+
print(formatter.format(list(response), fmt="plain"))
|
52
|
+
|
53
|
+
|
54
|
+
class TableFormatter:
|
55
|
+
|
56
|
+
def __init__(self, custom_columns: OrderedDict):
|
57
|
+
"""
|
58
|
+
Initializes the TableFormatter with column headers and custom column mappings.
|
59
|
+
|
60
|
+
:param headers: List of column headers for the table.
|
61
|
+
"""
|
62
|
+
self.custom_columns = custom_columns
|
63
|
+
|
64
|
+
def format(self, objects, fmt='plain'):
|
65
|
+
"""
|
66
|
+
Formats a list of objects into a table with custom columns.
|
67
|
+
|
68
|
+
:param objects: List of objects to format into a table.
|
69
|
+
:return: A string representing the table.
|
70
|
+
"""
|
71
|
+
# Prepare the rows by applying the custom column functions to each object
|
72
|
+
rows = []
|
73
|
+
for obj in objects:
|
74
|
+
# row = [self.custom_columns[header](obj) for header in self.headers]
|
75
|
+
row = [f(obj) for f in self.custom_columns.values()]
|
76
|
+
rows.append(row)
|
77
|
+
|
78
|
+
# Create the table
|
79
|
+
table = tabulate(rows, headers=self.custom_columns.keys(), tablefmt=fmt)
|
80
|
+
return table
|
81
|
+
|
82
|
+
|
83
|
+
class AliasedGroup(click.Group):
|
84
|
+
|
85
|
+
def __init__(self,
|
86
|
+
name: t.Optional[str] = None,
|
87
|
+
commands: t.Optional[t.Union[t.MutableMapping[str, click.Command], t.Sequence[
|
88
|
+
click.Command]]] = None,
|
89
|
+
**attrs: t.Any) -> None:
|
90
|
+
super().__init__(name, commands, **attrs)
|
91
|
+
self.alias_map = {}
|
92
|
+
self.command_to_aliases = defaultdict(list)
|
93
|
+
|
94
|
+
def add_alias(self, cmd: click.Command, alias: str) -> None:
|
95
|
+
self.alias_map[alias] = cmd
|
96
|
+
if alias != cmd.name:
|
97
|
+
self.command_to_aliases[cmd].append(alias)
|
98
|
+
|
99
|
+
def command(self, aliases=None, *args,
|
100
|
+
**kwargs) -> t.Callable[[t.Callable[..., t.Any]], click.Command]:
|
101
|
+
cmd_decorator = super().command(*args, **kwargs)
|
102
|
+
if aliases is None:
|
103
|
+
aliases = []
|
104
|
+
|
105
|
+
def aliased_decorator(f):
|
106
|
+
cmd = cmd_decorator(f)
|
107
|
+
if cmd.name:
|
108
|
+
self.add_alias(cmd, cmd.name)
|
109
|
+
for alias in aliases:
|
110
|
+
self.add_alias(cmd, alias)
|
111
|
+
return cmd
|
112
|
+
|
113
|
+
f = None
|
114
|
+
if args and callable(args[0]):
|
115
|
+
(f,) = args
|
116
|
+
if f is not None:
|
117
|
+
return aliased_decorator(f)
|
118
|
+
return aliased_decorator
|
119
|
+
|
120
|
+
def group(self, aliases=None, *args,
|
121
|
+
**kwargs) -> t.Callable[[t.Callable[..., t.Any]], click.Group]:
|
122
|
+
cmd_decorator = super().group(*args, **kwargs)
|
123
|
+
if aliases is None:
|
124
|
+
aliases = []
|
125
|
+
|
126
|
+
def aliased_decorator(f):
|
127
|
+
cmd = cmd_decorator(f)
|
128
|
+
if cmd.name:
|
129
|
+
self.add_alias(cmd, cmd.name)
|
130
|
+
for alias in aliases:
|
131
|
+
self.add_alias(cmd, alias)
|
132
|
+
return cmd
|
133
|
+
|
134
|
+
f = None
|
135
|
+
if args and callable(args[0]):
|
136
|
+
(f,) = args
|
137
|
+
if f is not None:
|
138
|
+
return aliased_decorator(f)
|
139
|
+
return aliased_decorator
|
140
|
+
|
141
|
+
def get_command(self, ctx: click.Context, cmd_name: str) -> t.Optional[click.Command]:
|
142
|
+
rv = click.Group.get_command(self, ctx, cmd_name)
|
143
|
+
if rv is not None:
|
144
|
+
return rv
|
145
|
+
return self.alias_map.get(cmd_name)
|
146
|
+
|
147
|
+
def format_commands(self, ctx, formatter):
|
148
|
+
sub_commands = self.list_commands(ctx)
|
149
|
+
|
150
|
+
rows = []
|
151
|
+
for sub_command in sub_commands:
|
152
|
+
cmd = self.get_command(ctx, sub_command)
|
153
|
+
if cmd is None or getattr(cmd, 'hidden', False):
|
154
|
+
continue
|
155
|
+
if cmd in self.command_to_aliases:
|
156
|
+
aliases = ', '.join(self.command_to_aliases[cmd])
|
157
|
+
sub_command = f'{sub_command} ({aliases})'
|
158
|
+
cmd_help = cmd.help
|
159
|
+
rows.append((sub_command, cmd_help))
|
160
|
+
|
161
|
+
if rows:
|
162
|
+
with formatter.section("Commands"):
|
163
|
+
formatter.write_dl(rows)
|
74
164
|
|
75
165
|
|
76
166
|
def validate_context(ctx):
|