cu-cli-core 0.1.0b1__tar.gz → 0.1.0b2__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.
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/PKG-INFO +1 -1
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/pyproject.toml +8 -1
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/analysis.py +113 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/command_spec.py +136 -8
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/contracts.py +25 -5
- cu_cli_core-0.1.0b2/src/cu_cli_core/doctor.py +253 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/infra.py +317 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/infra_models.py +220 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/input_planning.py +231 -15
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/operations/analysis.py +4 -2
- cu_cli_core-0.1.0b2/src/cu_cli_core/postprovision.py +262 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/reporting.py +65 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/resources/azd_template/README.md +196 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/resources/azd_template/azure.yaml +27 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/resources/azd_template/hooks/postprovision.ps1 +25 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/resources/azd_template/hooks/postprovision.sh +22 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/resources/azd_template/infra/main.bicep +115 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/resources/azd_template/infra/main.parameters.json +30 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/resources/azd_template/infra/models.json +1 -0
- cu_cli_core-0.1.0b2/src/cu_cli_core/resources/azd_template/infra/modules/foundry.bicep +122 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/service_options.py +19 -3
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core.egg-info/PKG-INFO +1 -1
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core.egg-info/SOURCES.txt +18 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_analysis.py +108 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_command_spec.py +36 -5
- cu_cli_core-0.1.0b2/tests/test_contracts.py +75 -0
- cu_cli_core-0.1.0b2/tests/test_doctor.py +149 -0
- cu_cli_core-0.1.0b2/tests/test_infra.py +116 -0
- cu_cli_core-0.1.0b2/tests/test_infra_models.py +97 -0
- cu_cli_core-0.1.0b2/tests/test_input_planning.py +795 -0
- cu_cli_core-0.1.0b2/tests/test_postprovision.py +201 -0
- cu_cli_core-0.1.0b2/tests/test_postprovision_launchers.py +117 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_service_options.py +4 -3
- cu_cli_core-0.1.0b1/tests/test_contracts.py +0 -36
- cu_cli_core-0.1.0b1/tests/test_input_planning.py +0 -348
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/README.md +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/setup.cfg +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/__init__.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/client.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/defaults.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/environment.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/errors.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/operations/__init__.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/operations/analyzer_copy.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/operations/analyzers.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/operations/profiles.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/operations/schema.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/operations/validation.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/profiles.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/py.typed +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/resources/openapi/2025-11-01/ContentUnderstanding.json +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/resources/openapi/2026-06-01-preview/ContentUnderstanding.json +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/schema.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/schema_validation.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/serialization.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core/spec_validation.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core.egg-info/dependency_links.txt +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core.egg-info/requires.txt +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/src/cu_cli_core.egg-info/top_level.txt +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_client.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_defaults.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_environment.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_errors.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_operations.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_package_metadata.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_profile_operations.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_profiles.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_schema.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_schema_validation.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_serialization.py +0 -0
- {cu_cli_core-0.1.0b1 → cu_cli_core-0.1.0b2}/tests/test_validation_operation.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cu-cli-core"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.0b2"
|
|
8
8
|
description = "Framework-neutral command contracts and operations for Azure Content Understanding CLIs."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -34,6 +34,13 @@ where = ["src"]
|
|
|
34
34
|
"cu_cli_core" = [
|
|
35
35
|
"py.typed",
|
|
36
36
|
"resources/openapi/*/*.json",
|
|
37
|
+
"resources/azd_template/*.md",
|
|
38
|
+
"resources/azd_template/*.yaml",
|
|
39
|
+
"resources/azd_template/hooks/*.ps1",
|
|
40
|
+
"resources/azd_template/hooks/*.sh",
|
|
41
|
+
"resources/azd_template/infra/*.bicep",
|
|
42
|
+
"resources/azd_template/infra/*.json",
|
|
43
|
+
"resources/azd_template/infra/modules/*.bicep",
|
|
37
44
|
]
|
|
38
45
|
|
|
39
46
|
[tool.pytest.ini_options]
|
|
@@ -45,6 +45,7 @@ class AnalyzeJob:
|
|
|
45
45
|
analyzer_id: str
|
|
46
46
|
out_path: Optional[Path] = None # None => caller streams to stdout
|
|
47
47
|
output_format: str = "markdown"
|
|
48
|
+
input_url: Optional[str] = None
|
|
48
49
|
|
|
49
50
|
|
|
50
51
|
@dataclass
|
|
@@ -249,6 +250,51 @@ def analyze_bytes_with_usage(
|
|
|
249
250
|
return AnalyzeResponse(result=result, usage=getattr(poller, "usage", None))
|
|
250
251
|
|
|
251
252
|
|
|
253
|
+
def _analysis_url_input(url: str) -> Any:
|
|
254
|
+
from azure.ai.contentunderstanding.models import AnalysisInput
|
|
255
|
+
|
|
256
|
+
return AnalysisInput(url=url)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def analyze_url(
|
|
260
|
+
client: Any,
|
|
261
|
+
analyzer_id: str,
|
|
262
|
+
url: str,
|
|
263
|
+
*,
|
|
264
|
+
raw_json: bool = False,
|
|
265
|
+
) -> Any:
|
|
266
|
+
"""Analyze an HTTPS input reference and return the completed result."""
|
|
267
|
+
return analyze_url_with_usage(
|
|
268
|
+
client,
|
|
269
|
+
analyzer_id,
|
|
270
|
+
url,
|
|
271
|
+
raw_json=raw_json,
|
|
272
|
+
).result
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def analyze_url_with_usage(
|
|
276
|
+
client: Any,
|
|
277
|
+
analyzer_id: str,
|
|
278
|
+
url: str,
|
|
279
|
+
*,
|
|
280
|
+
raw_json: bool = False,
|
|
281
|
+
) -> AnalyzeResponse:
|
|
282
|
+
"""Analyze an HTTPS input reference while retaining usage metadata."""
|
|
283
|
+
kwargs = {"cls": _capture_raw_response} if raw_json else {}
|
|
284
|
+
poller = client.begin_analyze(
|
|
285
|
+
analyzer_id=analyzer_id,
|
|
286
|
+
inputs=[_analysis_url_input(url)],
|
|
287
|
+
**kwargs,
|
|
288
|
+
)
|
|
289
|
+
completed = poller.result()
|
|
290
|
+
if raw_json:
|
|
291
|
+
_, raw_response = completed
|
|
292
|
+
result = raw_response.json()
|
|
293
|
+
else:
|
|
294
|
+
result = completed
|
|
295
|
+
return AnalyzeResponse(result=result, usage=getattr(poller, "usage", None))
|
|
296
|
+
|
|
297
|
+
|
|
252
298
|
def analyze_bytes_inline(
|
|
253
299
|
client: Any,
|
|
254
300
|
analyzer_id: str,
|
|
@@ -288,8 +334,54 @@ def analyze_bytes_inline_with_usage(
|
|
|
288
334
|
return AnalyzeResponse(result=result, usage=getattr(response, "usage", None))
|
|
289
335
|
|
|
290
336
|
|
|
337
|
+
def analyze_url_inline(
|
|
338
|
+
client: Any,
|
|
339
|
+
analyzer_id: str,
|
|
340
|
+
url: str,
|
|
341
|
+
*,
|
|
342
|
+
raw_json: bool = False,
|
|
343
|
+
) -> Any:
|
|
344
|
+
"""Analyze an HTTPS input reference synchronously."""
|
|
345
|
+
return analyze_url_inline_with_usage(
|
|
346
|
+
client,
|
|
347
|
+
analyzer_id,
|
|
348
|
+
url,
|
|
349
|
+
raw_json=raw_json,
|
|
350
|
+
).result
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def analyze_url_inline_with_usage(
|
|
354
|
+
client: Any,
|
|
355
|
+
analyzer_id: str,
|
|
356
|
+
url: str,
|
|
357
|
+
*,
|
|
358
|
+
raw_json: bool = False,
|
|
359
|
+
) -> AnalyzeResponse:
|
|
360
|
+
"""Analyze an HTTPS input reference synchronously with usage metadata."""
|
|
361
|
+
kwargs = {"cls": _capture_raw_response} if raw_json else {}
|
|
362
|
+
completed = client.analyze_inline(
|
|
363
|
+
analyzer_id=analyzer_id,
|
|
364
|
+
inputs=[_analysis_url_input(url)],
|
|
365
|
+
**kwargs,
|
|
366
|
+
)
|
|
367
|
+
if raw_json:
|
|
368
|
+
response, raw_response = completed
|
|
369
|
+
result = raw_response.json()
|
|
370
|
+
else:
|
|
371
|
+
response = completed
|
|
372
|
+
result = response.result
|
|
373
|
+
return AnalyzeResponse(result=result, usage=getattr(response, "usage", None))
|
|
374
|
+
|
|
375
|
+
|
|
291
376
|
def analyze_one(client: Any, job: AnalyzeJob) -> Any:
|
|
292
377
|
"""Run a single :class:`AnalyzeJob`, returning the completed SDK result."""
|
|
378
|
+
if job.input_url is not None:
|
|
379
|
+
return analyze_url(
|
|
380
|
+
client,
|
|
381
|
+
job.analyzer_id,
|
|
382
|
+
job.input_url,
|
|
383
|
+
raw_json=job.output_format == "json",
|
|
384
|
+
)
|
|
293
385
|
data = Path(job.input_ref).read_bytes()
|
|
294
386
|
return analyze_bytes(
|
|
295
387
|
client,
|
|
@@ -301,6 +393,13 @@ def analyze_one(client: Any, job: AnalyzeJob) -> Any:
|
|
|
301
393
|
|
|
302
394
|
def analyze_one_inline(client: Any, job: AnalyzeJob) -> Any:
|
|
303
395
|
"""Run a single job synchronously through the inline analyze API."""
|
|
396
|
+
if job.input_url is not None:
|
|
397
|
+
return analyze_url_inline(
|
|
398
|
+
client,
|
|
399
|
+
job.analyzer_id,
|
|
400
|
+
job.input_url,
|
|
401
|
+
raw_json=job.output_format == "json",
|
|
402
|
+
)
|
|
304
403
|
data = Path(job.input_ref).read_bytes()
|
|
305
404
|
return analyze_bytes_inline(
|
|
306
405
|
client,
|
|
@@ -312,6 +411,13 @@ def analyze_one_inline(client: Any, job: AnalyzeJob) -> Any:
|
|
|
312
411
|
|
|
313
412
|
def analyze_one_with_usage(client: Any, job: AnalyzeJob) -> AnalyzeResponse:
|
|
314
413
|
"""Run one long-running analysis and retain its usage metadata."""
|
|
414
|
+
if job.input_url is not None:
|
|
415
|
+
return analyze_url_with_usage(
|
|
416
|
+
client,
|
|
417
|
+
job.analyzer_id,
|
|
418
|
+
job.input_url,
|
|
419
|
+
raw_json=job.output_format == "json",
|
|
420
|
+
)
|
|
315
421
|
data = Path(job.input_ref).read_bytes()
|
|
316
422
|
return analyze_bytes_with_usage(
|
|
317
423
|
client,
|
|
@@ -323,6 +429,13 @@ def analyze_one_with_usage(client: Any, job: AnalyzeJob) -> AnalyzeResponse:
|
|
|
323
429
|
|
|
324
430
|
def analyze_one_inline_with_usage(client: Any, job: AnalyzeJob) -> AnalyzeResponse:
|
|
325
431
|
"""Run one inline analysis and retain its usage metadata."""
|
|
432
|
+
if job.input_url is not None:
|
|
433
|
+
return analyze_url_inline_with_usage(
|
|
434
|
+
client,
|
|
435
|
+
job.analyzer_id,
|
|
436
|
+
job.input_url,
|
|
437
|
+
raw_json=job.output_format == "json",
|
|
438
|
+
)
|
|
326
439
|
data = Path(job.input_ref).read_bytes()
|
|
327
440
|
return analyze_bytes_inline_with_usage(
|
|
328
441
|
client,
|
|
@@ -18,8 +18,11 @@ class SurfaceClassification(str, Enum):
|
|
|
18
18
|
COMMON = "common"
|
|
19
19
|
SHARED_ALIAS = "shared-alias"
|
|
20
20
|
STANDALONE_SHORTCUT = "standalone-shortcut"
|
|
21
|
+
STANDALONE_ONLY = "standalone-only"
|
|
22
|
+
AZURE_ONLY = "azure-only"
|
|
21
23
|
AZURE_HOST_GLOBAL = "azure-host-global"
|
|
22
24
|
FRONTEND_PRESENTATION = "frontend-presentation"
|
|
25
|
+
INTERNAL = "internal"
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
class ArgumentValueType(str, Enum):
|
|
@@ -27,6 +30,7 @@ class ArgumentValueType(str, Enum):
|
|
|
27
30
|
|
|
28
31
|
STRING = "string"
|
|
29
32
|
BOOLEAN = "boolean"
|
|
33
|
+
TRISTATE_BOOLEAN = "tristate-boolean"
|
|
30
34
|
INTEGER = "integer"
|
|
31
35
|
PATH = "path"
|
|
32
36
|
|
|
@@ -64,8 +68,8 @@ class CommandSpec:
|
|
|
64
68
|
|
|
65
69
|
path: tuple[str, ...]
|
|
66
70
|
help: str
|
|
67
|
-
operation: str
|
|
68
|
-
request_type: str
|
|
71
|
+
operation: str | None = None
|
|
72
|
+
request_type: str | None = None
|
|
69
73
|
arguments: tuple[ArgumentSpec, ...] = ()
|
|
70
74
|
service_options: tuple[str, ...] = ()
|
|
71
75
|
classification: SurfaceClassification = SurfaceClassification.COMMON
|
|
@@ -127,6 +131,8 @@ def bind_command_arguments(
|
|
|
127
131
|
def build_request(spec: CommandSpec, parsed: Mapping[str, Any]) -> Any:
|
|
128
132
|
"""Bind frontend values and instantiate the spec's lazy request type."""
|
|
129
133
|
|
|
134
|
+
if spec.request_type is None:
|
|
135
|
+
raise CommandBindingError(f"{' '.join(spec.path)} does not define a shared request type")
|
|
130
136
|
request_type = resolve_identifier(spec.request_type)
|
|
131
137
|
try:
|
|
132
138
|
return request_type(**bind_command_arguments(spec, parsed))
|
|
@@ -136,7 +142,11 @@ def build_request(spec: CommandSpec, parsed: Mapping[str, Any]) -> Any:
|
|
|
136
142
|
raise CommandBindingError(str(exc)) from exc
|
|
137
143
|
|
|
138
144
|
|
|
139
|
-
_SERVICE_OPTIONS = ("endpoint", "api-version", "auth-mode", "api-key")
|
|
145
|
+
_SERVICE_OPTIONS = ("endpoint", "api-version", "auth-mode", "api-key", "profile")
|
|
146
|
+
_API_VERSION_HELP = (
|
|
147
|
+
"Content Understanding API version. Known versions: 2025-11-01 (GA) and "
|
|
148
|
+
"2026-06-01-preview (preview); any YYYY-MM-DD-preview version is also accepted."
|
|
149
|
+
)
|
|
140
150
|
|
|
141
151
|
|
|
142
152
|
def _profile_name_arguments(option_help: str) -> tuple[ArgumentSpec, ...]:
|
|
@@ -223,14 +233,33 @@ _INPUT_ARGUMENTS = (
|
|
|
223
233
|
),
|
|
224
234
|
)
|
|
225
235
|
|
|
236
|
+
_ANALYZE_INPUT_ARGUMENTS = (
|
|
237
|
+
ArgumentSpec(
|
|
238
|
+
"INPUTS",
|
|
239
|
+
field="positional_inputs",
|
|
240
|
+
parser_name="inputs",
|
|
241
|
+
help="Standalone local file, directory, or HTTPS URL shortcuts.",
|
|
242
|
+
repeatable=True,
|
|
243
|
+
classification=SurfaceClassification.STANDALONE_SHORTCUT,
|
|
244
|
+
),
|
|
245
|
+
*_INPUT_ARGUMENTS[1:],
|
|
246
|
+
ArgumentSpec(
|
|
247
|
+
"--url",
|
|
248
|
+
field="urls",
|
|
249
|
+
parser_name="urls",
|
|
250
|
+
help="HTTPS or Azure Blob SAS URL. Repeat for multiple URLs.",
|
|
251
|
+
repeatable=True,
|
|
252
|
+
),
|
|
253
|
+
)
|
|
254
|
+
|
|
226
255
|
|
|
227
256
|
ANALYZE = CommandSpec(
|
|
228
257
|
path=("analyze",),
|
|
229
|
-
help="Process local files
|
|
258
|
+
help="Process local files or HTTPS URLs and return analyzer results.",
|
|
230
259
|
operation="cu_cli_core.operations.analysis#execute_analyze",
|
|
231
260
|
request_type="cu_cli_core.contracts#AnalyzeRequest",
|
|
232
261
|
arguments=(
|
|
233
|
-
*
|
|
262
|
+
*_ANALYZE_INPUT_ARGUMENTS,
|
|
234
263
|
ArgumentSpec(
|
|
235
264
|
"--analyzer",
|
|
236
265
|
aliases=("-a",),
|
|
@@ -317,7 +346,6 @@ ANALYZE = CommandSpec(
|
|
|
317
346
|
value_type=ArgumentValueType.PATH,
|
|
318
347
|
file_okay=True,
|
|
319
348
|
dir_okay=False,
|
|
320
|
-
classification=SurfaceClassification.FRONTEND_PRESENTATION,
|
|
321
349
|
),
|
|
322
350
|
ArgumentSpec(
|
|
323
351
|
"--concurrency",
|
|
@@ -824,7 +852,6 @@ PROFILE_SHOW = CommandSpec(
|
|
|
824
852
|
parser_name="deployments",
|
|
825
853
|
help="Also list live Foundry model deployments.",
|
|
826
854
|
value_type=ArgumentValueType.BOOLEAN,
|
|
827
|
-
classification=SurfaceClassification.FRONTEND_PRESENTATION,
|
|
828
855
|
),
|
|
829
856
|
),
|
|
830
857
|
)
|
|
@@ -935,7 +962,17 @@ PROFILE_DELETE = CommandSpec(
|
|
|
935
962
|
help="Delete an inactive named CU CLI profile.",
|
|
936
963
|
operation="cu_cli_core.operations.profiles#delete_profile",
|
|
937
964
|
request_type="cu_cli_core.contracts#ProfileDeleteRequest",
|
|
938
|
-
arguments=
|
|
965
|
+
arguments=(
|
|
966
|
+
*_profile_name_arguments("Existing inactive profile to delete."),
|
|
967
|
+
ArgumentSpec(
|
|
968
|
+
"--yes",
|
|
969
|
+
aliases=("-y",),
|
|
970
|
+
field="yes",
|
|
971
|
+
parser_name="yes",
|
|
972
|
+
help="Delete without prompting for confirmation.",
|
|
973
|
+
value_type=ArgumentValueType.BOOLEAN,
|
|
974
|
+
),
|
|
975
|
+
),
|
|
939
976
|
)
|
|
940
977
|
|
|
941
978
|
PROFILE_COPY = CommandSpec(
|
|
@@ -1061,6 +1098,93 @@ ENV_VAR_LIST = CommandSpec(
|
|
|
1061
1098
|
),
|
|
1062
1099
|
)
|
|
1063
1100
|
|
|
1101
|
+
DOCTOR = CommandSpec(
|
|
1102
|
+
path=("doctor",),
|
|
1103
|
+
help="Verify a Microsoft Foundry resource connection and Content Understanding defaults.",
|
|
1104
|
+
arguments=(
|
|
1105
|
+
ArgumentSpec(
|
|
1106
|
+
"--profile",
|
|
1107
|
+
aliases=("-p",),
|
|
1108
|
+
field="profile_name",
|
|
1109
|
+
parser_name="profile_name",
|
|
1110
|
+
help="Named CU CLI profile to use.",
|
|
1111
|
+
),
|
|
1112
|
+
ArgumentSpec(
|
|
1113
|
+
"--endpoint",
|
|
1114
|
+
field="endpoint",
|
|
1115
|
+
parser_name="endpoint",
|
|
1116
|
+
help="Override the configured Microsoft Foundry resource endpoint.",
|
|
1117
|
+
),
|
|
1118
|
+
ArgumentSpec(
|
|
1119
|
+
"--api-version",
|
|
1120
|
+
field="api_version",
|
|
1121
|
+
parser_name="api_version",
|
|
1122
|
+
help=_API_VERSION_HELP,
|
|
1123
|
+
),
|
|
1124
|
+
ArgumentSpec(
|
|
1125
|
+
"--fix-defaults",
|
|
1126
|
+
field="fix_defaults",
|
|
1127
|
+
parser_name="fix_defaults",
|
|
1128
|
+
help="Configure Content Understanding defaults from profile model mappings.",
|
|
1129
|
+
value_type=ArgumentValueType.BOOLEAN,
|
|
1130
|
+
),
|
|
1131
|
+
ArgumentSpec(
|
|
1132
|
+
"--auth-mode",
|
|
1133
|
+
field="auth_mode",
|
|
1134
|
+
parser_name="auth_mode",
|
|
1135
|
+
help="Authentication mode; defaults to the selected CU CLI profile.",
|
|
1136
|
+
choices=("login", "key"),
|
|
1137
|
+
),
|
|
1138
|
+
ArgumentSpec(
|
|
1139
|
+
"--api-key",
|
|
1140
|
+
field="api_key",
|
|
1141
|
+
parser_name="api_key",
|
|
1142
|
+
help="Override the configured API key.",
|
|
1143
|
+
),
|
|
1144
|
+
),
|
|
1145
|
+
)
|
|
1146
|
+
|
|
1147
|
+
INFRA_GENERATE = CommandSpec(
|
|
1148
|
+
path=("infra", "generate"),
|
|
1149
|
+
help="Generate an azd/Bicep project for Content Understanding.",
|
|
1150
|
+
arguments=(
|
|
1151
|
+
ArgumentSpec("--output-dir", aliases=("-d",), field="output_dir", parser_name="output_dir", help="Directory where the azd template is generated.", value_type=ArgumentValueType.PATH, default="provision", file_okay=False),
|
|
1152
|
+
ArgumentSpec("--environment", aliases=("-e",), field="environment", parser_name="environment", help="azd environment name."),
|
|
1153
|
+
ArgumentSpec("--location", aliases=("-l",), field="location", parser_name="location", help="Azure region."),
|
|
1154
|
+
ArgumentSpec("--subscription", field="subscription", parser_name="subscription", help="Azure subscription name or ID.", classification=SurfaceClassification.STANDALONE_ONLY),
|
|
1155
|
+
ArgumentSpec("--api-version", field="api_version", parser_name="api_version", help=_API_VERSION_HELP),
|
|
1156
|
+
ArgumentSpec("--models", field="models", parser_name="models", help="Comma-separated model names, 'recommended', or 'none'."),
|
|
1157
|
+
ArgumentSpec("--foundry-endpoint", field="foundry_endpoint", parser_name="foundry_endpoint", help="Existing Microsoft Foundry resource endpoint."),
|
|
1158
|
+
ArgumentSpec("--foundry-prefix", field="foundry_prefix", parser_name="foundry_prefix", help="Prefix for a new Microsoft Foundry resource name."),
|
|
1159
|
+
ArgumentSpec("--assign-roles", field="assign_roles", parser_name="assign_roles", help="Whether to configure RBAC role assignments; omit to use interactive or default behavior.", value_type=ArgumentValueType.TRISTATE_BOOLEAN),
|
|
1160
|
+
ArgumentSpec("--force", field="force", parser_name="force", help="Overwrite an existing generated template.", value_type=ArgumentValueType.BOOLEAN),
|
|
1161
|
+
),
|
|
1162
|
+
)
|
|
1163
|
+
|
|
1164
|
+
INFRA_MODELS = CommandSpec(
|
|
1165
|
+
path=("_infra-models",),
|
|
1166
|
+
help="Configure model deployments for a generated infrastructure project.",
|
|
1167
|
+
classification=SurfaceClassification.INTERNAL,
|
|
1168
|
+
arguments=(
|
|
1169
|
+
ArgumentSpec("--resource-group", field="resource_group", parser_name="resource_group", help="Resource group containing the Foundry account.", required=True),
|
|
1170
|
+
ArgumentSpec("--account", field="account_name", parser_name="account_name", help="Foundry account name.", required=True),
|
|
1171
|
+
ArgumentSpec("--subscription", field="subscription_id", parser_name="subscription_id", help="Azure subscription ID.", required=True, classification=SurfaceClassification.STANDALONE_ONLY),
|
|
1172
|
+
ArgumentSpec("--selection", field="selection", parser_name="selection", help="prompt, recommended, none, or comma-separated model selectors.", required=True),
|
|
1173
|
+
ArgumentSpec("--out", field="out_path", parser_name="out_path", help="Output Bicep model file.", value_type=ArgumentValueType.PATH, required=True),
|
|
1174
|
+
ArgumentSpec("--deploy/--no-deploy", field="deploy", parser_name="deploy", help="Deploy selected models before writing the model file.", value_type=ArgumentValueType.BOOLEAN, default=True, classification=SurfaceClassification.STANDALONE_ONLY),
|
|
1175
|
+
ArgumentSpec("--deploy", field="deploy", parser_name="deploy", help="Deploy selected models before writing the model file.", value_type=ArgumentValueType.BOOLEAN, default=True, classification=SurfaceClassification.AZURE_ONLY),
|
|
1176
|
+
ArgumentSpec("--endpoint", field="endpoint", parser_name="endpoint", help="Microsoft Foundry resource endpoint.", required=True, classification=SurfaceClassification.AZURE_ONLY),
|
|
1177
|
+
ArgumentSpec("--api-version", field="api_version", parser_name="api_version", help=_API_VERSION_HELP, classification=SurfaceClassification.AZURE_ONLY),
|
|
1178
|
+
ArgumentSpec("--use-key", field="use_key", parser_name="use_key", help="Use an account key for the data-plane request.", value_type=ArgumentValueType.BOOLEAN, classification=SurfaceClassification.AZURE_ONLY),
|
|
1179
|
+
),
|
|
1180
|
+
)
|
|
1181
|
+
|
|
1182
|
+
INFRA_POSTPROVISION_V1 = CommandSpec(
|
|
1183
|
+
path=("_infra-postprovision-v1",),
|
|
1184
|
+
help="Complete generated-project setup after azd provisioning.",
|
|
1185
|
+
classification=SurfaceClassification.INTERNAL,
|
|
1186
|
+
)
|
|
1187
|
+
|
|
1064
1188
|
|
|
1065
1189
|
COMMAND_SPECS: tuple[CommandSpec, ...] = (
|
|
1066
1190
|
ANALYZE,
|
|
@@ -1086,6 +1210,10 @@ COMMAND_SPECS: tuple[CommandSpec, ...] = (
|
|
|
1086
1210
|
PROFILE_SET_ACTIVE,
|
|
1087
1211
|
PROFILE_SYNC_DEFAULTS,
|
|
1088
1212
|
ENV_VAR_LIST,
|
|
1213
|
+
DOCTOR,
|
|
1214
|
+
INFRA_GENERATE,
|
|
1215
|
+
INFRA_MODELS,
|
|
1216
|
+
INFRA_POSTPROVISION_V1,
|
|
1089
1217
|
)
|
|
1090
1218
|
_COMMAND_SPECS_BY_PATH = {spec.path: spec for spec in COMMAND_SPECS}
|
|
1091
1219
|
|
|
@@ -20,13 +20,16 @@ class SelectionMode(str, Enum):
|
|
|
20
20
|
POSITIONAL = "positional"
|
|
21
21
|
NAMED_FILES = "named-files"
|
|
22
22
|
NAMED_SOURCES = "named-sources"
|
|
23
|
+
NAMED_URLS = "named-urls"
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class InputOrigin(str, Enum):
|
|
26
27
|
POSITIONAL_FILE = "positional-file"
|
|
27
28
|
POSITIONAL_SOURCE = "positional-source"
|
|
29
|
+
POSITIONAL_URL = "positional-url"
|
|
28
30
|
NAMED_FILE = "named-file"
|
|
29
31
|
NAMED_SOURCE = "named-source"
|
|
32
|
+
NAMED_URL = "named-url"
|
|
30
33
|
|
|
31
34
|
|
|
32
35
|
class ExistingResultPolicy(str, Enum):
|
|
@@ -49,6 +52,7 @@ class OutcomeStatus(str, Enum):
|
|
|
49
52
|
@dataclass(frozen=True)
|
|
50
53
|
class ProfileShowRequest:
|
|
51
54
|
name: str | None = None
|
|
55
|
+
deployments: bool = False
|
|
52
56
|
|
|
53
57
|
|
|
54
58
|
@dataclass(frozen=True)
|
|
@@ -83,6 +87,7 @@ class ProfileCreateRequest:
|
|
|
83
87
|
@dataclass(frozen=True)
|
|
84
88
|
class ProfileDeleteRequest:
|
|
85
89
|
name: str
|
|
90
|
+
yes: bool = False
|
|
86
91
|
|
|
87
92
|
|
|
88
93
|
@dataclass(frozen=True)
|
|
@@ -159,7 +164,7 @@ class AnalyzerDeleteRequest:
|
|
|
159
164
|
|
|
160
165
|
@dataclass(frozen=True)
|
|
161
166
|
class AnalyzeRequest:
|
|
162
|
-
positional_inputs: tuple[
|
|
167
|
+
positional_inputs: tuple[str, ...] = ()
|
|
163
168
|
files: tuple[Path, ...] = ()
|
|
164
169
|
sources: tuple[Path, ...] = ()
|
|
165
170
|
pattern: str | None = None
|
|
@@ -175,15 +180,17 @@ class AnalyzeRequest:
|
|
|
175
180
|
yes: bool = False
|
|
176
181
|
report_file: Path | None = None
|
|
177
182
|
concurrency: int = 4
|
|
183
|
+
urls: tuple[str, ...] = ()
|
|
178
184
|
|
|
179
185
|
def __post_init__(self) -> None:
|
|
180
186
|
object.__setattr__(
|
|
181
187
|
self,
|
|
182
188
|
"positional_inputs",
|
|
183
|
-
tuple(
|
|
189
|
+
tuple(str(value) for value in self.positional_inputs),
|
|
184
190
|
)
|
|
185
191
|
object.__setattr__(self, "files", tuple(Path(path) for path in self.files))
|
|
186
192
|
object.__setattr__(self, "sources", tuple(Path(path) for path in self.sources))
|
|
193
|
+
object.__setattr__(self, "urls", tuple(str(value) for value in self.urls))
|
|
187
194
|
if self.output_file is not None:
|
|
188
195
|
object.__setattr__(self, "output_file", Path(self.output_file))
|
|
189
196
|
if self.output_dir is not None:
|
|
@@ -329,11 +336,24 @@ class EnvironmentVariableListRequest:
|
|
|
329
336
|
|
|
330
337
|
@dataclass(frozen=True)
|
|
331
338
|
class PlannedInput:
|
|
332
|
-
path: Path
|
|
333
|
-
source_root: Path
|
|
339
|
+
path: Path | None
|
|
340
|
+
source_root: Path | None
|
|
334
341
|
relative_path: Path
|
|
335
342
|
origin: InputOrigin
|
|
336
|
-
size_bytes: int
|
|
343
|
+
size_bytes: int | None
|
|
344
|
+
url: str | None = None
|
|
345
|
+
|
|
346
|
+
@property
|
|
347
|
+
def reference(self) -> str:
|
|
348
|
+
if self.url is not None:
|
|
349
|
+
return self.url
|
|
350
|
+
if self.path is None:
|
|
351
|
+
raise ValueError("planned input must have either a local path or URL.")
|
|
352
|
+
return str(self.path)
|
|
353
|
+
|
|
354
|
+
@property
|
|
355
|
+
def is_remote(self) -> bool:
|
|
356
|
+
return self.url is not None
|
|
337
357
|
|
|
338
358
|
|
|
339
359
|
@dataclass(frozen=True)
|