backend.ai-cli 24.3.0.dev1__tar.gz → 24.3.0rc1__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.
Potentially problematic release.
This version of backend.ai-cli might be problematic. Click here for more details.
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/PKG-INFO +2 -2
- backend.ai-cli-24.3.0rc1/ai/backend/cli/VERSION +1 -0
- backend.ai-cli-24.3.0rc1/ai/backend/cli/params.py +210 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/ai/backend/cli/types.py +22 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/PKG-INFO +2 -2
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/SOURCES.txt +1 -0
- backend.ai-cli-24.3.0rc1/backend.ai_cli.egg-info/requires.txt +4 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/setup.py +6 -3
- backend.ai-cli-24.3.0.dev1/ai/backend/cli/VERSION +0 -1
- backend.ai-cli-24.3.0.dev1/backend.ai_cli.egg-info/requires.txt +0 -3
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/MANIFEST.in +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/ai/backend/cli/__init__.py +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/ai/backend/cli/__main__.py +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/ai/backend/cli/extensions.py +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/ai/backend/cli/interaction.py +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/ai/backend/cli/loader.py +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/ai/backend/cli/main.py +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/ai/backend/cli/py.typed +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/dependency_links.txt +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/entry_points.txt +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/namespace_packages.txt +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/not-zip-safe +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/top_level.txt +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend_shim.py +0 -0
- {backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: backend.ai-cli
|
|
3
|
-
Version: 24.3.
|
|
3
|
+
Version: 24.3.0rc1
|
|
4
4
|
Summary: Backend.AI Command Line Interface Helper
|
|
5
5
|
Home-page: https://github.com/lablup/backend.ai
|
|
6
6
|
Author: Lablup Inc. and contributors
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
15
15
|
Classifier: Environment :: No Input/Output (Daemon)
|
|
16
16
|
Classifier: Topic :: Scientific/Engineering
|
|
17
17
|
Classifier: Topic :: Software Development
|
|
18
|
-
Classifier: Development Status ::
|
|
18
|
+
Classifier: Development Status :: 4 - Beta
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
20
|
Classifier: License :: OSI Approved :: MIT License
|
|
21
21
|
Requires-Python: >=3.11,<3.12
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24.03.0rc1
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import re
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
from typing import Any, Generic, Mapping, Optional, Protocol, TypeVar, Union
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
import trafaret
|
|
8
|
+
|
|
9
|
+
from .types import Undefined, undefined
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BoolExprType(click.ParamType):
|
|
13
|
+
name = "boolean"
|
|
14
|
+
|
|
15
|
+
def convert(self, value, param, ctx):
|
|
16
|
+
if isinstance(value, bool):
|
|
17
|
+
return value
|
|
18
|
+
try:
|
|
19
|
+
return trafaret.ToBool().check(value)
|
|
20
|
+
except trafaret.DataError:
|
|
21
|
+
self.fail(f"Cannot parser/convert {value!r} as a boolean.", param, ctx)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ByteSizeParamType(click.ParamType):
|
|
25
|
+
name = "byte"
|
|
26
|
+
|
|
27
|
+
_rx_digits = re.compile(r"^(\d+(?:\.\d*)?)([kmgtpe]?)$", re.I)
|
|
28
|
+
_scales = {
|
|
29
|
+
"k": 2**10,
|
|
30
|
+
"m": 2**20,
|
|
31
|
+
"g": 2**30,
|
|
32
|
+
"t": 2**40,
|
|
33
|
+
"p": 2**50,
|
|
34
|
+
"e": 2**60,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def convert(self, value, param, ctx):
|
|
38
|
+
if isinstance(value, int):
|
|
39
|
+
return value
|
|
40
|
+
if not isinstance(value, str):
|
|
41
|
+
self.fail(
|
|
42
|
+
f"expected string, got {value!r} of type {type(value).__name__}",
|
|
43
|
+
param,
|
|
44
|
+
ctx,
|
|
45
|
+
)
|
|
46
|
+
m = self._rx_digits.search(value)
|
|
47
|
+
if m is None:
|
|
48
|
+
self.fail(f"{value!r} is not a valid byte-size expression", param, ctx)
|
|
49
|
+
size = float(m.group(1))
|
|
50
|
+
unit = m.group(2).lower()
|
|
51
|
+
return int(size * self._scales.get(unit, 1))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ByteSizeParamCheckType(ByteSizeParamType):
|
|
55
|
+
name = "byte-check"
|
|
56
|
+
|
|
57
|
+
def convert(self, value, param, ctx):
|
|
58
|
+
if isinstance(value, int):
|
|
59
|
+
return value
|
|
60
|
+
if not isinstance(value, str):
|
|
61
|
+
self.fail(
|
|
62
|
+
f"expected string, got {value!r} of type {type(value).__name__}",
|
|
63
|
+
param,
|
|
64
|
+
ctx,
|
|
65
|
+
)
|
|
66
|
+
m = self._rx_digits.search(value)
|
|
67
|
+
if m is None:
|
|
68
|
+
self.fail(f"{value!r} is not a valid byte-size expression", param, ctx)
|
|
69
|
+
return value
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class CommaSeparatedKVListParamType(click.ParamType):
|
|
73
|
+
name = "comma-seperated-KVList-check"
|
|
74
|
+
|
|
75
|
+
def convert(self, value: Union[str, Mapping[str, str]], param, ctx) -> Mapping[str, str]:
|
|
76
|
+
if isinstance(value, dict):
|
|
77
|
+
return value
|
|
78
|
+
if not isinstance(value, str):
|
|
79
|
+
self.fail(
|
|
80
|
+
f"expected string, got {value!r} of type {type(value).__name__}",
|
|
81
|
+
param,
|
|
82
|
+
ctx,
|
|
83
|
+
)
|
|
84
|
+
override_map = {}
|
|
85
|
+
for assignment in value.split(","):
|
|
86
|
+
try:
|
|
87
|
+
k, _, v = assignment.partition("=")
|
|
88
|
+
if k == "" or v == "":
|
|
89
|
+
raise ValueError(f"key or value is empty. key = {k}, value = {v}")
|
|
90
|
+
except ValueError:
|
|
91
|
+
self.fail(
|
|
92
|
+
f"{value!r} is not a valid mapping expression",
|
|
93
|
+
param,
|
|
94
|
+
ctx,
|
|
95
|
+
)
|
|
96
|
+
else:
|
|
97
|
+
override_map[k] = v
|
|
98
|
+
return override_map
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class JSONParamType(click.ParamType):
|
|
102
|
+
"""
|
|
103
|
+
A JSON string parameter type.
|
|
104
|
+
The default value must be given as a valid JSON-parsable string,
|
|
105
|
+
not the Python objects.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
name = "json-string"
|
|
109
|
+
|
|
110
|
+
def __init__(self) -> None:
|
|
111
|
+
super().__init__()
|
|
112
|
+
self._parsed = False
|
|
113
|
+
|
|
114
|
+
def convert(
|
|
115
|
+
self,
|
|
116
|
+
value: Optional[str],
|
|
117
|
+
param: Optional[click.Parameter],
|
|
118
|
+
ctx: Optional[click.Context],
|
|
119
|
+
) -> Any:
|
|
120
|
+
if self._parsed:
|
|
121
|
+
# Click invokes this method TWICE
|
|
122
|
+
# for a default value given as string.
|
|
123
|
+
return value
|
|
124
|
+
self._parsed = True
|
|
125
|
+
if value is None:
|
|
126
|
+
return None
|
|
127
|
+
try:
|
|
128
|
+
return json.loads(value)
|
|
129
|
+
except json.JSONDecodeError:
|
|
130
|
+
self.fail(f"cannot parse {value!r} as JSON", param, ctx)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def drange(start: Decimal, stop: Decimal, num: int):
|
|
134
|
+
"""
|
|
135
|
+
A simplified version of numpy.linspace with default options
|
|
136
|
+
"""
|
|
137
|
+
delta = stop - start
|
|
138
|
+
step = delta / (num - 1)
|
|
139
|
+
yield from (start + step * Decimal(tick) for tick in range(0, num))
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class RangeExprOptionType(click.ParamType):
|
|
143
|
+
"""
|
|
144
|
+
Accepts a range expression which generates a range of values for a variable.
|
|
145
|
+
|
|
146
|
+
Linear space range: "linspace:1,2,10" (start, stop, num) as in numpy.linspace
|
|
147
|
+
Pythonic range: "range:1,10,2" (start, stop[, step]) as in Python's range
|
|
148
|
+
Case range: "case:a,b,c" (comma-separated strings)
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
_rx_range_key = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")
|
|
152
|
+
name = "Range Expression"
|
|
153
|
+
|
|
154
|
+
def convert(self, arg, param, ctx):
|
|
155
|
+
key, value = arg.split("=", maxsplit=1)
|
|
156
|
+
assert self._rx_range_key.match(key), "The key must be a valid slug string."
|
|
157
|
+
try:
|
|
158
|
+
if value.startswith("case:"):
|
|
159
|
+
return key, value[5:].split(",")
|
|
160
|
+
elif value.startswith("linspace:"):
|
|
161
|
+
start, stop, num = value[9:].split(",")
|
|
162
|
+
return key, tuple(drange(Decimal(start), Decimal(stop), int(num)))
|
|
163
|
+
elif value.startswith("range:"):
|
|
164
|
+
range_args = map(int, value[6:].split(","))
|
|
165
|
+
return key, tuple(range(*range_args))
|
|
166
|
+
else:
|
|
167
|
+
self.fail("Unrecognized range expression type", param, ctx)
|
|
168
|
+
except ValueError as e:
|
|
169
|
+
self.fail(str(e), param, ctx)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class CommaSeparatedListType(click.ParamType):
|
|
173
|
+
name = "List Expression"
|
|
174
|
+
|
|
175
|
+
def convert(self, arg, param, ctx):
|
|
176
|
+
try:
|
|
177
|
+
if isinstance(arg, int):
|
|
178
|
+
return arg
|
|
179
|
+
elif isinstance(arg, str):
|
|
180
|
+
return arg.split(",")
|
|
181
|
+
except ValueError as e:
|
|
182
|
+
self.fail(repr(e), param, ctx)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
T = TypeVar("T")
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class SingleValueConstructorType(Protocol):
|
|
189
|
+
def __init__(self, value: Any) -> None: ...
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
TScalar = TypeVar("TScalar", bound=SingleValueConstructorType)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class OptionalType(click.ParamType, Generic[TScalar]):
|
|
196
|
+
name = "Optional Type Wrapper"
|
|
197
|
+
|
|
198
|
+
def __init__(self, type_: type[TScalar] | type[click.ParamType]) -> None:
|
|
199
|
+
super().__init__()
|
|
200
|
+
self.type_ = type_
|
|
201
|
+
|
|
202
|
+
def convert(self, value: Any, param, ctx) -> TScalar | Undefined:
|
|
203
|
+
try:
|
|
204
|
+
if value is undefined:
|
|
205
|
+
return undefined
|
|
206
|
+
if issubclass(self.type_, click.ParamType):
|
|
207
|
+
return self.type_()(value)
|
|
208
|
+
return self.type_(value)
|
|
209
|
+
except ValueError:
|
|
210
|
+
self.fail(f"{value!r} is not valid `{self.type_}` or `undefined`", param, ctx)
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import enum
|
|
2
4
|
from typing import Dict
|
|
3
5
|
|
|
4
6
|
import attr
|
|
5
7
|
|
|
8
|
+
__all__ = (
|
|
9
|
+
"Undefined",
|
|
10
|
+
"undefined",
|
|
11
|
+
)
|
|
12
|
+
|
|
6
13
|
|
|
7
14
|
@attr.define(slots=True)
|
|
8
15
|
class CliContextInfo:
|
|
@@ -15,3 +22,18 @@ class ExitCode(enum.IntEnum):
|
|
|
15
22
|
INVALID_USAGE = 2 # wraps Click's UsageError
|
|
16
23
|
OPERATION_TIMEOUT = 3 # timeout during operation
|
|
17
24
|
INVALID_ARGUMENT = 4 # invalid argument while it's not UsageError
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Undefined(enum.Enum):
|
|
28
|
+
"""
|
|
29
|
+
A special type to represent an undefined value.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
TOKEN = 0
|
|
33
|
+
|
|
34
|
+
def __bool__(self) -> bool:
|
|
35
|
+
# It should be evaluated as False when used as a boolean expr.
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
undefined = Undefined.TOKEN
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: backend.ai-cli
|
|
3
|
-
Version: 24.3.
|
|
3
|
+
Version: 24.3.0rc1
|
|
4
4
|
Summary: Backend.AI Command Line Interface Helper
|
|
5
5
|
Home-page: https://github.com/lablup/backend.ai
|
|
6
6
|
Author: Lablup Inc. and contributors
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
15
15
|
Classifier: Environment :: No Input/Output (Daemon)
|
|
16
16
|
Classifier: Topic :: Scientific/Engineering
|
|
17
17
|
Classifier: Topic :: Software Development
|
|
18
|
-
Classifier: Development Status ::
|
|
18
|
+
Classifier: Development Status :: 4 - Beta
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
20
|
Classifier: License :: OSI Approved :: MIT License
|
|
21
21
|
Requires-Python: >=3.11,<3.12
|
|
@@ -15,7 +15,7 @@ setup(**{
|
|
|
15
15
|
'Environment :: No Input/Output (Daemon)',
|
|
16
16
|
'Topic :: Scientific/Engineering',
|
|
17
17
|
'Topic :: Software Development',
|
|
18
|
-
'Development Status ::
|
|
18
|
+
'Development Status :: 4 - Beta',
|
|
19
19
|
'Programming Language :: Python :: 3.11',
|
|
20
20
|
'License :: OSI Approved :: MIT License',
|
|
21
21
|
],
|
|
@@ -27,8 +27,10 @@ setup(**{
|
|
|
27
27
|
},
|
|
28
28
|
'install_requires': (
|
|
29
29
|
'attrs>=20.3',
|
|
30
|
-
|
|
30
|
+
"""backend.ai-plugin==24.03.0rc1
|
|
31
|
+
""",
|
|
31
32
|
'click~=8.1.7',
|
|
33
|
+
'trafaret~=2.1',
|
|
32
34
|
),
|
|
33
35
|
'license': 'MIT',
|
|
34
36
|
'long_description': """# backend.ai-cli
|
|
@@ -74,6 +76,7 @@ You can do the same in `setup.py` as well.
|
|
|
74
76
|
},
|
|
75
77
|
'python_requires': '>=3.11,<3.12',
|
|
76
78
|
'url': 'https://github.com/lablup/backend.ai',
|
|
77
|
-
'version':
|
|
79
|
+
'version': """24.03.0rc1
|
|
80
|
+
""",
|
|
78
81
|
'zip_safe': False,
|
|
79
82
|
})
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
24.03.0dev1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{backend.ai-cli-24.3.0.dev1 → backend.ai-cli-24.3.0rc1}/backend.ai_cli.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|