pal-found-cli 0.1.2__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 (89) hide show
  1. pal_found_cli/__init__.py +1 -0
  2. pal_found_cli/_version.py +24 -0
  3. pal_found_cli/admin/__init__.py +2 -0
  4. pal_found_cli/admin/scripts/__init__.py +2 -0
  5. pal_found_cli/admin/scripts/pal_found_admin_cli.py +600 -0
  6. pal_found_cli/aip_agents/__init__.py +1 -0
  7. pal_found_cli/aip_agents/metadata-allow-list.md +20 -0
  8. pal_found_cli/aip_agents/scripts/__init__.py +1 -0
  9. pal_found_cli/aip_agents/scripts/pal_found_aip_agents_cli.py +704 -0
  10. pal_found_cli/audit/__init__.py +1 -0
  11. pal_found_cli/audit/metadata-allow-list.md +4 -0
  12. pal_found_cli/audit/scripts/__init__.py +1 -0
  13. pal_found_cli/audit/scripts/pal_found_audit_cli.py +387 -0
  14. pal_found_cli/checkpoints/__init__.py +9 -0
  15. pal_found_cli/checkpoints/metadata-allow-list.md +7 -0
  16. pal_found_cli/checkpoints/scripts/__init__.py +1 -0
  17. pal_found_cli/checkpoints/scripts/pal_found_checkpoints_cli.py +527 -0
  18. pal_found_cli/common/__init__.py +56 -0
  19. pal_found_cli/common/access_control_guard.py +591 -0
  20. pal_found_cli/common/async_client_factory.py +161 -0
  21. pal_found_cli/common/auth_provider.py +82 -0
  22. pal_found_cli/common/binary_download_handler.py +288 -0
  23. pal_found_cli/common/config_loader.py +388 -0
  24. pal_found_cli/common/error_serializer.py +412 -0
  25. pal_found_cli/common/log_setup.py +241 -0
  26. pal_found_cli/common/metadata-allow-list.md +169 -0
  27. pal_found_cli/common/output_formatter.py +267 -0
  28. pal_found_cli/common/pagination_helper.py +212 -0
  29. pal_found_cli/common/retry.py +617 -0
  30. pal_found_cli/common/sdk_error_utils.py +112 -0
  31. pal_found_cli/common/session_manager.py +461 -0
  32. pal_found_cli/common/tracing_provider.py +107 -0
  33. pal_found_cli/connectivity/__init__.py +9 -0
  34. pal_found_cli/connectivity/metadata-allow-list.md +24 -0
  35. pal_found_cli/connectivity/scripts/__init__.py +1 -0
  36. pal_found_cli/connectivity/scripts/pal_found_connectivity_cli.py +720 -0
  37. pal_found_cli/data_health/__init__.py +9 -0
  38. pal_found_cli/data_health/metadata-allow-list.md +10 -0
  39. pal_found_cli/data_health/scripts/__init__.py +1 -0
  40. pal_found_cli/data_health/scripts/pal_found_data_health_cli.py +458 -0
  41. pal_found_cli/datasets/__init__.py +1 -0
  42. pal_found_cli/datasets/scripts/__init__.py +1 -0
  43. pal_found_cli/datasets/scripts/pal_found_datasets_cli.py +732 -0
  44. pal_found_cli/filesystem/__init__.py +2 -0
  45. pal_found_cli/filesystem/scripts/__init__.py +2 -0
  46. pal_found_cli/filesystem/scripts/pal_found_filesystem_cli.py +659 -0
  47. pal_found_cli/functions/__init__.py +2 -0
  48. pal_found_cli/functions/scripts/__init__.py +2 -0
  49. pal_found_cli/functions/scripts/pal_found_functions_cli.py +389 -0
  50. pal_found_cli/language_models/__init__.py +1 -0
  51. pal_found_cli/language_models/metadata-allow-list.md +6 -0
  52. pal_found_cli/language_models/scripts/__init__.py +1 -0
  53. pal_found_cli/language_models/scripts/pal_found_language_models_cli.py +342 -0
  54. pal_found_cli/media_sets/__init__.py +9 -0
  55. pal_found_cli/media_sets/metadata-allow-list.md +23 -0
  56. pal_found_cli/media_sets/scripts/__init__.py +1 -0
  57. pal_found_cli/media_sets/scripts/pal_found_media_sets_cli.py +642 -0
  58. pal_found_cli/models/__init__.py +5 -0
  59. pal_found_cli/models/metadata-allow-list.md +27 -0
  60. pal_found_cli/models/scripts/__init__.py +1 -0
  61. pal_found_cli/models/scripts/pal_found_models_cli.py +714 -0
  62. pal_found_cli/ontologies/__init__.py +1 -0
  63. pal_found_cli/ontologies/scripts/__init__.py +1 -0
  64. pal_found_cli/ontologies/scripts/pal_found_ontologies_cli.py +1225 -0
  65. pal_found_cli/orchestration/__init__.py +9 -0
  66. pal_found_cli/orchestration/metadata-allow-list.md +24 -0
  67. pal_found_cli/orchestration/scripts/__init__.py +1 -0
  68. pal_found_cli/orchestration/scripts/pal_found_orchestration_cli.py +640 -0
  69. pal_found_cli/sql_queries/__init__.py +9 -0
  70. pal_found_cli/sql_queries/metadata-allow-list.md +9 -0
  71. pal_found_cli/sql_queries/scripts/__init__.py +1 -0
  72. pal_found_cli/sql_queries/scripts/pal_found_sql_queries_cli.py +514 -0
  73. pal_found_cli/streams/__init__.py +9 -0
  74. pal_found_cli/streams/metadata-allow-list.md +19 -0
  75. pal_found_cli/streams/scripts/__init__.py +1 -0
  76. pal_found_cli/streams/scripts/pal_found_streams_cli.py +615 -0
  77. pal_found_cli/third_party_applications/__init__.py +9 -0
  78. pal_found_cli/third_party_applications/metadata-allow-list.md +13 -0
  79. pal_found_cli/third_party_applications/scripts/__init__.py +1 -0
  80. pal_found_cli/third_party_applications/scripts/pal_found_third_party_applications_cli.py +547 -0
  81. pal_found_cli/widgets/__init__.py +9 -0
  82. pal_found_cli/widgets/metadata-allow-list.md +12 -0
  83. pal_found_cli/widgets/scripts/__init__.py +1 -0
  84. pal_found_cli/widgets/scripts/pal_found_widgets_cli.py +571 -0
  85. pal_found_cli-0.1.2.dist-info/METADATA +74 -0
  86. pal_found_cli-0.1.2.dist-info/RECORD +89 -0
  87. pal_found_cli-0.1.2.dist-info/WHEEL +5 -0
  88. pal_found_cli-0.1.2.dist-info/entry_points.txt +19 -0
  89. pal_found_cli-0.1.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,389 @@
1
+ #!/usr/bin/env python3
2
+ """Foundry Functions CLI - 7 canonical API v2 operations."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import asyncio
8
+ import inspect
9
+ import json
10
+ import logging
11
+ import sys
12
+ from collections.abc import Iterable
13
+ from pathlib import Path
14
+ from typing import Any
15
+
16
+ _SCRIPT_DIR = Path(__file__).resolve().parent
17
+ _PROJECT_ROOT: str | None = None
18
+ _candidate = _SCRIPT_DIR
19
+ for _depth in range(8):
20
+ if (_candidate / "src" / "pal_found_cli" / "__init__.py").exists():
21
+ _PROJECT_ROOT = str(_candidate)
22
+ break
23
+ if _candidate.parent == _candidate:
24
+ break
25
+ _candidate = _candidate.parent
26
+ if _PROJECT_ROOT is None:
27
+ _PROJECT_ROOT = str(_SCRIPT_DIR.parents[4])
28
+ if _PROJECT_ROOT not in sys.path:
29
+ sys.path.insert(0, _PROJECT_ROOT)
30
+
31
+ from pal_found_cli.common.access_control_guard import ( # noqa: E402
32
+ AccessControlError,
33
+ AccessControlGuard,
34
+ )
35
+ from pal_found_cli.common.async_client_factory import AsyncClientFactory # noqa: E402
36
+ from pal_found_cli.common.config_loader import ConfigLoader # noqa: E402
37
+ from pal_found_cli.common.error_serializer import ( # noqa: E402
38
+ EXIT_ACCESS_CONTROL,
39
+ EXIT_NOT_FOUND,
40
+ EXIT_PERMISSION_DENIED,
41
+ EXIT_RATE_LIMIT,
42
+ EXIT_SERVER_ERROR,
43
+ EXIT_SUCCESS,
44
+ EXIT_TIMEOUT,
45
+ EXIT_USER_INPUT,
46
+ ErrorSerializer,
47
+ )
48
+ from pal_found_cli.common.log_setup import LogSetup # noqa: E402
49
+ from pal_found_cli.common.output_formatter import OutputFormatter # noqa: E402
50
+ from pal_found_cli.common.retry import RetryHandler # noqa: E402
51
+
52
+ logger = logging.getLogger(__name__)
53
+
54
+ OperationSpec = dict[str, Any]
55
+
56
+
57
+ def _op(
58
+ resource: str,
59
+ operation: str,
60
+ client_path: str,
61
+ method: str,
62
+ positional: Iterable[str] = (),
63
+ required: Iterable[str] = (),
64
+ optional: Iterable[str] = (),
65
+ *,
66
+ json_args: Iterable[str] = (),
67
+ ) -> OperationSpec:
68
+ """Build an operation specification entry."""
69
+ return {
70
+ "resource": resource,
71
+ "operation": operation,
72
+ "client_path": client_path,
73
+ "method": method,
74
+ "positional": tuple(positional),
75
+ "required": tuple(required),
76
+ "optional": tuple(optional),
77
+ "json_args": frozenset(json_args),
78
+ }
79
+
80
+
81
+ OP_SPECS: tuple[OperationSpec, ...] = (
82
+ _op(
83
+ "query",
84
+ "execute",
85
+ "Query",
86
+ "execute",
87
+ ("query_api_name",),
88
+ required=("parameters",),
89
+ optional=(
90
+ "attribution",
91
+ "branch",
92
+ "preview",
93
+ "trace_parent",
94
+ "trace_state",
95
+ "transaction_id",
96
+ "version",
97
+ ),
98
+ json_args=("parameters", "attribution"),
99
+ ),
100
+ _op(
101
+ "query",
102
+ "get",
103
+ "Query",
104
+ "get",
105
+ ("query_api_name",),
106
+ optional=("preview", "version"),
107
+ ),
108
+ _op(
109
+ "query",
110
+ "get_by_rid",
111
+ "Query",
112
+ "get_by_rid",
113
+ required=("rid",),
114
+ optional=("include_prerelease", "preview", "version"),
115
+ ),
116
+ _op(
117
+ "query",
118
+ "get_by_rid_batch",
119
+ "Query",
120
+ "get_by_rid_batch",
121
+ ("body",),
122
+ optional=("preview",),
123
+ json_args=("body",),
124
+ ),
125
+ _op(
126
+ "query",
127
+ "streaming_execute",
128
+ "Query",
129
+ "streaming_execute",
130
+ ("query_api_name",),
131
+ required=("parameters",),
132
+ optional=(
133
+ "attribution",
134
+ "branch",
135
+ "ontology",
136
+ "preview",
137
+ "trace_parent",
138
+ "trace_state",
139
+ "transaction_id",
140
+ "version",
141
+ ),
142
+ json_args=("parameters", "attribution"),
143
+ ),
144
+ _op("value_type", "get", "ValueType", "get", ("value_type_rid",), optional=("preview",)),
145
+ _op(
146
+ "version_id",
147
+ "get",
148
+ "ValueType.VersionId",
149
+ "get",
150
+ ("value_type_rid", "version_id_version_id"),
151
+ optional=("preview",),
152
+ ),
153
+ )
154
+
155
+ OPERATION_BY_RESOURCE: dict[str, dict[str, OperationSpec]] = {}
156
+ for _spec in OP_SPECS:
157
+ OPERATION_BY_RESOURCE.setdefault(_spec["resource"], {})[_spec["operation"]] = _spec
158
+
159
+ PAGINATED_OPS: frozenset[tuple[str, str]] = frozenset()
160
+
161
+
162
+ def _model_to_dict(obj: Any) -> Any:
163
+ """Convert SDK/Pydantic objects into JSON-serializable values."""
164
+ if obj is None:
165
+ return None
166
+ if isinstance(obj, (bytes, bytearray)):
167
+ return {"bytes": len(obj)}
168
+ if isinstance(obj, list):
169
+ return [_model_to_dict(item) for item in obj]
170
+ if isinstance(obj, dict):
171
+ return {key: _model_to_dict(value) for key, value in obj.items()}
172
+ try:
173
+ result = obj.to_dict()
174
+ if isinstance(result, dict):
175
+ return result
176
+ except (AttributeError, TypeError):
177
+ pass
178
+ try:
179
+ result = obj.model_dump()
180
+ if isinstance(result, dict):
181
+ return result
182
+ except (AttributeError, TypeError):
183
+ pass
184
+ try:
185
+ result = obj.dict()
186
+ if isinstance(result, dict):
187
+ return result
188
+ except (AttributeError, TypeError):
189
+ pass
190
+ return obj
191
+
192
+
193
+ def _resolve(resource: str, op: str) -> str:
194
+ """Resolve CLI kebab-case operation name to SDK snake_case."""
195
+ return op.replace("-", "_")
196
+
197
+
198
+ def _kebab(name: str) -> str:
199
+ """Convert snake_case names to CLI kebab-case."""
200
+ return name.replace("_", "-")
201
+
202
+
203
+ def _common_parser() -> argparse.ArgumentParser:
204
+ """Build shared parser for operation-level common options."""
205
+ common = argparse.ArgumentParser(add_help=False)
206
+ common.add_argument("--timeout", type=int, default=None)
207
+ common.add_argument("--format", choices=["json", "toon", "auto"], default="auto")
208
+ common.add_argument("--pretty", action="store_true")
209
+ return common
210
+
211
+
212
+ def _add_kwarg(
213
+ parser: argparse.ArgumentParser, arg_name: str, *, required: bool
214
+ ) -> None:
215
+ flag = "--" + _kebab(arg_name)
216
+ if arg_name in {"include_prerelease", "preview"}:
217
+ parser.add_argument(flag, action="store_true", default=None, dest=arg_name)
218
+ return
219
+ parser.add_argument(flag, required=required, default=None, dest=arg_name)
220
+
221
+
222
+ def build_parser() -> argparse.ArgumentParser:
223
+ """Build argparse parser with all 7 functions operations."""
224
+ parser = argparse.ArgumentParser(
225
+ prog="pal_found_functions_cli",
226
+ description="Foundry Functions CLI - 7 operations",
227
+ )
228
+ subparsers = parser.add_subparsers(dest="resource", help="Resource type")
229
+
230
+ for resource in sorted(OPERATION_BY_RESOURCE):
231
+ res_parser = subparsers.add_parser(_kebab(resource))
232
+ op_sub = res_parser.add_subparsers(dest="operation")
233
+ for operation, spec in sorted(OPERATION_BY_RESOURCE[resource].items()):
234
+ op_parser = op_sub.add_parser(_kebab(operation), parents=[_common_parser()])
235
+ for arg_name in spec["positional"]:
236
+ op_parser.add_argument(arg_name)
237
+ for arg_name in spec["required"]:
238
+ _add_kwarg(op_parser, arg_name, required=True)
239
+ for arg_name in spec["optional"]:
240
+ _add_kwarg(op_parser, arg_name, required=False)
241
+
242
+ return parser
243
+
244
+
245
+ def _spec_for(resource: str, operation: str) -> OperationSpec:
246
+ """Return the operation spec for a resource and operation."""
247
+ try:
248
+ return OPERATION_BY_RESOURCE[resource][operation]
249
+ except KeyError as exc:
250
+ raise ValueError(f"Unknown operation: {resource}.{operation}") from exc
251
+
252
+
253
+ def _get_client(
254
+ cfg: ConfigLoader, resource: str, factory: AsyncClientFactory | None = None
255
+ ) -> Any:
256
+ """Get SDK client for a functions resource."""
257
+ root = (factory or AsyncClientFactory()).create(cfg).functions
258
+ spec = next(iter(OPERATION_BY_RESOURCE[resource].values()))
259
+ client = root
260
+ for attr in spec["client_path"].split("."):
261
+ client = getattr(client, attr)
262
+ return client
263
+
264
+
265
+ def _coerce_arg(value: Any, *, json_arg: bool) -> Any:
266
+ """Parse JSON CLI values for structured SDK arguments."""
267
+ if value is None:
268
+ return None
269
+ if json_arg and isinstance(value, str):
270
+ return json.loads(value)
271
+ return value
272
+
273
+
274
+ async def _resolve_result(value: Any) -> Any:
275
+ """Await SDK calls that return awaitables."""
276
+ if asyncio.isfuture(value) or inspect.isawaitable(value):
277
+ return await value
278
+ return value
279
+
280
+
281
+ async def _invoke(
282
+ resource: str,
283
+ operation: str,
284
+ client: Any,
285
+ args: argparse.Namespace,
286
+ timeout: int | None,
287
+ ) -> Any:
288
+ """Invoke a functions SDK operation."""
289
+ spec = _spec_for(resource, operation)
290
+ method = getattr(client, spec["method"])
291
+ positional = [
292
+ _coerce_arg(getattr(args, name), json_arg=name in spec["json_args"])
293
+ for name in spec["positional"]
294
+ ]
295
+ kwargs: dict[str, Any] = {}
296
+
297
+ for name in (*spec["required"], *spec["optional"]):
298
+ value = getattr(args, name, None)
299
+ if value is not None:
300
+ kwargs[name] = _coerce_arg(value, json_arg=name in spec["json_args"])
301
+
302
+ kwargs["request_timeout"] = timeout
303
+ return await _resolve_result(method(*positional, **kwargs))
304
+
305
+
306
+ async def main() -> int:
307
+ """Run the Foundry Functions CLI."""
308
+ parser = build_parser()
309
+ args = parser.parse_args()
310
+ if not args.resource:
311
+ parser.print_help()
312
+ return EXIT_USER_INPUT
313
+ if not getattr(args, "operation", None):
314
+ parser.print_help()
315
+ return EXIT_USER_INPUT
316
+
317
+ cfg = ConfigLoader()
318
+ cfg.load()
319
+ LogSetup.configure(log_level=cfg.log_level)
320
+
321
+ resource = args.resource.replace("-", "_")
322
+ operation = _resolve(resource, args.operation)
323
+ logger.info(
324
+ "Executing operation", extra={"resource": resource, "operation": operation}
325
+ )
326
+
327
+ try:
328
+ _spec_for(resource, operation)
329
+ except ValueError as exc:
330
+ ErrorSerializer().serialize(exc)
331
+ return EXIT_USER_INPUT
332
+
333
+ try:
334
+ AccessControlGuard(cfg, "FUNCTIONS").check(resource, operation)
335
+ except AccessControlError as exc:
336
+ ErrorSerializer().serialize(exc)
337
+ return EXIT_ACCESS_CONTROL
338
+
339
+ factory = AsyncClientFactory()
340
+ try:
341
+ with factory.invocation_scope(cfg):
342
+ client = _get_client(cfg, resource, factory)
343
+ timeout = getattr(args, "timeout", None) or getattr(cfg, "timeout_s", None)
344
+ retry_handler = RetryHandler()
345
+ result = await retry_handler.execute(
346
+ _invoke,
347
+ resource,
348
+ operation,
349
+ client,
350
+ args,
351
+ timeout,
352
+ )
353
+ formatter = OutputFormatter(
354
+ format_setting=getattr(args, "format", "auto"),
355
+ pretty=getattr(args, "pretty", False),
356
+ )
357
+ print(formatter.format(_model_to_dict(result)))
358
+ return EXIT_SUCCESS
359
+ except PermissionError as exc:
360
+ ErrorSerializer().serialize(exc)
361
+ return EXIT_PERMISSION_DENIED
362
+ except FileNotFoundError as exc:
363
+ ErrorSerializer().serialize(exc)
364
+ return EXIT_NOT_FOUND
365
+ except TimeoutError as exc:
366
+ ErrorSerializer().serialize(exc)
367
+ return EXIT_TIMEOUT
368
+ except ValueError as exc:
369
+ ErrorSerializer().serialize(exc)
370
+ return EXIT_USER_INPUT
371
+ except OSError as exc:
372
+ exit_code = ErrorSerializer().serialize(exc)
373
+ if getattr(exc, "errno", None) in (11, 115):
374
+ return EXIT_RATE_LIMIT
375
+ return exit_code
376
+ except Exception as exc:
377
+ exit_code = ErrorSerializer().serialize(exc)
378
+ if exit_code != EXIT_USER_INPUT:
379
+ return exit_code
380
+ return EXIT_SERVER_ERROR
381
+
382
+
383
+ def console_main() -> int:
384
+ """Run the async CLI from the console script entry point."""
385
+ return asyncio.run(main())
386
+
387
+
388
+ if __name__ == "__main__":
389
+ sys.exit(console_main())
@@ -0,0 +1 @@
1
+ """Foundry Language Models command-line namespace."""
@@ -0,0 +1,6 @@
1
+ # Language Models metadata allow-list
2
+
3
+ | SDK Path | Status | Rationale |
4
+ |---|---|---|
5
+ | `language_models.anthropic_model.messages` | BLOCKED | Executes model inference |
6
+ | `language_models.open_ai_model.embeddings` | BLOCKED | Executes model inference |
@@ -0,0 +1 @@
1
+ """Executable modules for Foundry Language Models."""