validio-cli 10.0.6__tar.gz → 10.1.0__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.
Files changed (29) hide show
  1. {validio_cli-10.0.6 → validio_cli-10.1.0}/PKG-INFO +3 -3
  2. validio_cli-10.1.0/pyproject.toml +111 -0
  3. validio_cli-10.0.6/pyproject.toml → validio_cli-10.1.0/pyproject.toml.orig +7 -6
  4. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/__init__.py +2 -2
  5. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/code.py +58 -2
  6. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/namespaces.py +3 -18
  7. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/resources.py +1 -1
  8. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/sources.py +3 -5
  9. validio_cli-10.1.0/validio_cli/bin/entities/validator_debug_queries.py +130 -0
  10. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/main.py +6 -0
  11. {validio_cli-10.0.6 → validio_cli-10.1.0}/README_PUBLIC.md +0 -0
  12. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/channels.py +0 -0
  13. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/config.py +0 -0
  14. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/credentials.py +0 -0
  15. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/dbt.py +0 -0
  16. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/filters.py +0 -0
  17. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/incidents.py +0 -0
  18. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/integrations.py +0 -0
  19. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/metrics.py +0 -0
  20. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/notification_rules.py +0 -0
  21. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/segmentations.py +0 -0
  22. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/segments.py +0 -0
  23. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/users.py +0 -0
  24. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/validators.py +0 -0
  25. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/bin/entities/windows.py +0 -0
  26. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/components.py +0 -0
  27. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/metadata.py +0 -0
  28. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/namespace.py +0 -0
  29. {validio_cli-10.0.6 → validio_cli-10.1.0}/validio_cli/schema.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: validio-cli
3
- Version: 10.0.6
3
+ Version: 10.1.0
4
4
  Summary: CLI tool to interact with the Validio platform
5
5
  Author: Validio
6
6
  Author-email: Validio <support@validio.io>
@@ -11,9 +11,9 @@ Classifier: Programming Language :: Python :: 3.11
11
11
  Classifier: Programming Language :: Python :: 3.12
12
12
  Classifier: Programming Language :: Python :: 3.13
13
13
  Classifier: Programming Language :: Python :: 3.14
14
- Requires-Dist: camel-converter>=3.0.0,<4
14
+ Requires-Dist: camel-converter>=5.1.0,<6
15
15
  Requires-Dist: classdiff>=0.5.2,<0.6
16
- Requires-Dist: typer[all]>=0.8.0,<0.16.0
16
+ Requires-Dist: typer>=0.27.0,<0.28.0
17
17
  Requires-Dist: prompt-toolkit>=3.0.38,<4
18
18
  Requires-Dist: tabulate>=0.9.0,<0.11
19
19
  Requires-Dist: types-tabulate>=0.9.0.2,<0.11
@@ -0,0 +1,111 @@
1
+ [project]
2
+ name = "validio-cli"
3
+ version = "10.1.0"
4
+ description = "CLI tool to interact with the Validio platform"
5
+ requires-python = ">=3.10,<4"
6
+ readme = "README_PUBLIC.md"
7
+ license = "Apache-2.0"
8
+ classifiers = [
9
+ "Programming Language :: Python :: 3",
10
+ "Programming Language :: Python :: 3.10",
11
+ "Programming Language :: Python :: 3.11",
12
+ "Programming Language :: Python :: 3.12",
13
+ "Programming Language :: Python :: 3.13",
14
+ "Programming Language :: Python :: 3.14",
15
+ ]
16
+ dependencies = [
17
+ "camel-converter>=5.1.0,<6",
18
+ "classdiff>=0.5.2,<0.6",
19
+ "typer>=0.27.0,<0.28.0",
20
+ "prompt-toolkit>=3.0.38,<4",
21
+ "tabulate>=0.9.0,<0.11",
22
+ "types-tabulate>=0.9.0.2,<0.11",
23
+ "validio-sdk",
24
+ ]
25
+
26
+ [[project.authors]]
27
+ name = "Validio"
28
+ email = "support@validio.io"
29
+
30
+ [project.urls]
31
+ Homepage = "https://validio.io/"
32
+ Documentation = "https://docs.validio.io/"
33
+
34
+ [project.scripts]
35
+ validio = "validio_cli.bin.main:main"
36
+
37
+ [dependency-groups]
38
+ dev = [
39
+ "ruff==0.16.1",
40
+ "mypy>=1.2.0,<2",
41
+ "licensecheck>=2025.1.0,<2026",
42
+ "pytest>=9.0.3,<10",
43
+ "flameprof>=0.4,<0.5",
44
+ "validio-sdk",
45
+ ]
46
+
47
+ [tool.uv]
48
+ default-groups = "all"
49
+
50
+ [tool.uv.sources.validio-sdk]
51
+ workspace = true
52
+
53
+ [tool.uv.build-backend]
54
+ module-name = ["validio_cli"]
55
+ module-root = ""
56
+
57
+ [tool.ruff]
58
+ fix = true
59
+
60
+ [tool.ruff.lint]
61
+ select = [
62
+ "ARG",
63
+ "C4",
64
+ "D",
65
+ "E",
66
+ "F",
67
+ "I",
68
+ "N",
69
+ "PIE",
70
+ "PL",
71
+ "PT",
72
+ "PTH",
73
+ "RET",
74
+ "RUF",
75
+ "SIM",
76
+ "UP",
77
+ "W",
78
+ ]
79
+ ignore = [
80
+ "D203",
81
+ "D212",
82
+ "PLR0913",
83
+ "PLR0917",
84
+ "PLC0415",
85
+ ]
86
+
87
+ [tool.ruff.lint.per-file-ignores]
88
+ "__init__.py" = ["D"]
89
+ "*/bin/*.py" = [
90
+ "D",
91
+ "UP007",
92
+ "UP045",
93
+ ]
94
+ "examples/*.py" = ["D"]
95
+
96
+ [tool.mypy]
97
+ ignore_missing_imports = true
98
+ disallow_untyped_calls = true
99
+ disallow_untyped_defs = true
100
+ disallow_incomplete_defs = true
101
+ check_untyped_defs = true
102
+ disallow_untyped_decorators = true
103
+
104
+ [tool.licensecheck]
105
+ license = "Apache-2.0"
106
+ ignore_packages = ["MYPY-EXTENSIONS"]
107
+ zero = true
108
+
109
+ [build-system]
110
+ requires = ["uv_build>=0.12.3,<0.13.0"]
111
+ build-backend = "uv_build"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "validio-cli"
3
- version = "10.0.6"
3
+ version = "10.1.0"
4
4
  description = "CLI tool to interact with the Validio platform"
5
5
  authors = [{ name = "Validio", email = "support@validio.io" }]
6
6
  requires-python = ">=3.10,<4"
@@ -15,9 +15,9 @@ classifiers = [
15
15
  "Programming Language :: Python :: 3.14",
16
16
  ]
17
17
  dependencies = [
18
- "camel-converter>=3.0.0,<4",
18
+ "camel-converter>=5.1.0,<6",
19
19
  "classdiff>=0.5.2,<0.6",
20
- "typer[all]>=0.8.0,<0.16.0",
20
+ "typer>=0.27.0,<0.28.0",
21
21
  "prompt-toolkit>=3.0.38,<4",
22
22
  "tabulate>=0.9.0,<0.11",
23
23
  "types-tabulate>=0.9.0.2,<0.11",
@@ -33,10 +33,10 @@ validio = "validio_cli.bin.main:main"
33
33
 
34
34
  [dependency-groups]
35
35
  dev = [
36
- "ruff==0.15.22",
36
+ "ruff==0.16.1",
37
37
  "mypy>=1.2.0,<2",
38
38
  "licensecheck>=2025.1.0,<2026",
39
- "pytest>=7.4.3,<8",
39
+ "pytest>=9.0.3,<10",
40
40
  "flameprof>=0.4,<0.5",
41
41
  "validio-sdk",
42
42
  ]
@@ -52,7 +52,7 @@ module-name = ["validio_cli"]
52
52
  module-root = ""
53
53
 
54
54
  [build-system]
55
- requires = ["uv_build>=0.9.5,<0.10.0"]
55
+ requires = ["uv_build>=0.12.3,<0.13.0"]
56
56
  build-backend = "uv_build"
57
57
 
58
58
  [tool.ruff]
@@ -82,6 +82,7 @@ ignore = [
82
82
  "D203", # `one-blank-line-before-class` Incompatible with D211
83
83
  "D212", # `multi-line-summary-first-line` Incompatible with D213
84
84
  "PLR0913", # `too-many-arguments` - Not relevant with only 6
85
+ "PLR0917", # `too-many-positional-arguments` - Same as PLR0913
85
86
  "PLC0415", # Imports are intentionally lazy (circular dependencies / startup perf)
86
87
  ]
87
88
 
@@ -11,10 +11,10 @@ from pathlib import Path
11
11
  from types import EllipsisType
12
12
  from typing import Any, TypeVar
13
13
 
14
- import click
15
14
  import typer
16
15
  from camel_converter import to_snake
17
16
  from tabulate import tabulate
17
+ from typer._click.globals import get_current_context
18
18
  from validio_sdk import config
19
19
  from validio_sdk._api.api import APIClient
20
20
  from validio_sdk.client import USER_AGENT as SDK_USER_AGENT
@@ -108,7 +108,7 @@ def _cli_headers(iac: bool = False) -> dict[str, str]:
108
108
  """
109
109
  headers: dict[str, str] = {}
110
110
 
111
- ctx = click.get_current_context(silent=True)
111
+ ctx = get_current_context(silent=True)
112
112
  if ctx is not None:
113
113
  # `command_path` is e.g. "validio channels get",
114
114
  # drop the program name to get the command itself.
@@ -20,7 +20,10 @@ from validio_sdk.resource._resource import (
20
20
  ResourceDeprecation,
21
21
  ResourceFeatureNotice,
22
22
  )
23
- from validio_sdk.resource._util import SourceSchemaReinference
23
+ from validio_sdk.resource._util import (
24
+ SourceSchemaInferenceSkip,
25
+ SourceSchemaReinference,
26
+ )
24
27
  from validio_sdk.resource.replacement import (
25
28
  ImmutableFieldReplacementReason,
26
29
  RecreateOnChangeReplacementReason,
@@ -130,6 +133,26 @@ update_all_schemas_option = typer.Option(
130
133
  ),
131
134
  )
132
135
 
136
+ skip_schema_inference_option = typer.Option(
137
+ [],
138
+ help=(
139
+ f"{BETA_BANNER} "
140
+ "Specify a Source name to create without inferring its schema. This will"
141
+ " fallback to the corresponding schema in the Validio catalog. You can use"
142
+ " --skip-schema-inference src1 --skip-schema-inference src2 to specify"
143
+ " multiple Sources."
144
+ ),
145
+ )
146
+
147
+ skip_all_schema_inference_option = typer.Option(
148
+ False,
149
+ help=(
150
+ f"{BETA_BANNER} "
151
+ "Similar to --skip-schema-inference. Skips schema inference for all Sources"
152
+ " being created"
153
+ ),
154
+ )
155
+
133
156
  show_progress_option = typer.Option(
134
157
  sys.stdout.isatty(),
135
158
  help=(
@@ -172,6 +195,8 @@ async def plan(
172
195
  config_dir: str = ConfigDir,
173
196
  update_schema: list[str] = update_schema_option,
174
197
  update_all_schemas: bool = update_all_schemas_option,
198
+ skip_schema_inference: list[str] = skip_schema_inference_option,
199
+ skip_all_schema_inference: bool = skip_all_schema_inference_option,
175
200
  show_schema: bool = show_schema_option,
176
201
  diff_output: DiffOutput = diff_option,
177
202
  destroy: bool = destroy_option,
@@ -184,6 +209,7 @@ async def plan(
184
209
  segmentation: list[str] = target_option("segmentation"),
185
210
  source: list[str] = target_option("source"),
186
211
  validator: list[str] = target_option("validator"),
212
+ validator_debug_query: list[str] = target_option("validator-debug-query"),
187
213
  window: list[str] = target_option("window"),
188
214
  progress: bool = show_progress_option,
189
215
  ) -> None:
@@ -193,6 +219,9 @@ async def plan(
193
219
  schema_reinference = create_source_schema_reinference(
194
220
  update_schema, update_all_schemas
195
221
  )
222
+ schema_inference_skip = create_source_schema_inference_skip(
223
+ skip_schema_inference, skip_all_schema_inference
224
+ )
196
225
 
197
226
  namespace = get_namespace(dir_path)
198
227
  await _plan(
@@ -200,6 +229,7 @@ async def plan(
200
229
  client=client,
201
230
  directory=dir_path,
202
231
  schema_reinference=schema_reinference,
232
+ schema_inference_skip=schema_inference_skip,
203
233
  destroy=destroy,
204
234
  no_capture=no_capture,
205
235
  color=color,
@@ -214,6 +244,7 @@ async def plan(
214
244
  segmentations=set(segmentation),
215
245
  sources=set(source),
216
246
  validators=set(validator),
247
+ validator_debug_queries=set(validator_debug_query),
217
248
  windows=set(window),
218
249
  ),
219
250
  show_progress=progress,
@@ -230,6 +261,8 @@ async def apply(
230
261
  config_dir: str = ConfigDir,
231
262
  update_schema: list[str] = update_schema_option,
232
263
  update_all_schemas: bool = update_all_schemas_option,
264
+ skip_schema_inference: list[str] = skip_schema_inference_option,
265
+ skip_all_schema_inference: bool = skip_all_schema_inference_option,
233
266
  show_schema: bool = show_schema_option,
234
267
  diff_output: DiffOutput = diff_option,
235
268
  destroy: bool = destroy_option,
@@ -242,6 +275,7 @@ async def apply(
242
275
  segmentation: list[str] = target_option("segmentation"),
243
276
  source: list[str] = target_option("source"),
244
277
  validator: list[str] = target_option("validator"),
278
+ validator_debug_query: list[str] = target_option("validator-debug-query"),
245
279
  window: list[str] = target_option("window"),
246
280
  progress: bool = show_progress_option,
247
281
  test_credentials: bool = typer.Option(
@@ -263,6 +297,9 @@ async def apply(
263
297
  schema_reinference = create_source_schema_reinference(
264
298
  update_schema, update_all_schemas
265
299
  )
300
+ schema_inference_skip = create_source_schema_inference_skip(
301
+ skip_schema_inference, skip_all_schema_inference
302
+ )
266
303
 
267
304
  namespace = get_namespace(dir_path)
268
305
  plan_result = await _plan(
@@ -270,6 +307,7 @@ async def apply(
270
307
  client=client,
271
308
  directory=dir_path,
272
309
  schema_reinference=schema_reinference,
310
+ schema_inference_skip=schema_inference_skip,
273
311
  destroy=destroy,
274
312
  no_capture=no_capture,
275
313
  color=color,
@@ -284,6 +322,7 @@ async def apply(
284
322
  segmentations=set(segmentation),
285
323
  sources=set(source),
286
324
  validators=set(validator),
325
+ validator_debug_queries=set(validator_debug_query),
287
326
  windows=set(window),
288
327
  ),
289
328
  show_progress=progress,
@@ -308,6 +347,7 @@ async def apply(
308
347
  show_progress=progress,
309
348
  dry_run_sql=dry_run_sql,
310
349
  test_credentials=test_credentials,
350
+ schema_inference_skip=schema_inference_skip,
311
351
  )
312
352
 
313
353
  print(
@@ -414,7 +454,7 @@ async def _import(
414
454
  tags_ctx=plan_result.tags_context,
415
455
  include_schema=include_schema,
416
456
  )
417
- output.write_text(s)
457
+ output.write_text(s, encoding="utf-8")
418
458
  print(f"Generated file {output.absolute()}")
419
459
 
420
460
 
@@ -435,6 +475,7 @@ async def _plan(
435
475
  destroy: bool,
436
476
  no_capture: bool,
437
477
  color: bool,
478
+ schema_inference_skip: SourceSchemaInferenceSkip = SourceSchemaInferenceSkip(),
438
479
  show_schema: bool = False,
439
480
  diff_output: DiffOutput = DiffOutput.FULL,
440
481
  show_secrets: bool = False,
@@ -447,6 +488,7 @@ async def _plan(
447
488
  client=client,
448
489
  directory=directory,
449
490
  schema_reinference=schema_reinference,
491
+ schema_inference_skip=schema_inference_skip,
450
492
  destroy=destroy,
451
493
  no_capture=no_capture,
452
494
  show_secrets=show_secrets,
@@ -741,6 +783,20 @@ def create_source_schema_reinference(
741
783
  )
742
784
 
743
785
 
786
+ def create_source_schema_inference_skip(
787
+ sources_to_skip: list[str], skip_all: bool
788
+ ) -> SourceSchemaInferenceSkip:
789
+ source_names = None
790
+ if skip_all:
791
+ source_names = []
792
+ elif len(sources_to_skip) > 0:
793
+ source_names = sources_to_skip
794
+
795
+ return SourceSchemaInferenceSkip(
796
+ set(source_names) if source_names is not None else None
797
+ )
798
+
799
+
744
800
  def _print_no_changes() -> None:
745
801
  print("No changes. The configuration is up-to-date!")
746
802
 
@@ -1,6 +1,5 @@
1
1
  from typing import Any, Optional
2
2
 
3
- import click
4
3
  import typer
5
4
  from validio_sdk import ValidioError
6
5
 
@@ -15,21 +14,7 @@ from validio_cli import (
15
14
  output_text,
16
15
  )
17
16
 
18
-
19
- class RoleSuggestion(click.ParamType):
20
- name = "role"
21
-
22
- def get_metavar(self, _: click.Parameter) -> str | None:
23
- return "[Admin|Editor|Viewer|<Custom>]"
24
-
25
- def convert(
26
- self,
27
- value: Any,
28
- _param: click.Parameter | None,
29
- _ctx: click.Context | None,
30
- ) -> Any:
31
- return value
32
-
17
+ ROLE_METAVAR = "[Admin|Editor|Viewer|<Custom>]"
33
18
 
34
19
  app = AsyncTyper(help="Namespaces used to separate resources")
35
20
 
@@ -63,7 +48,7 @@ async def create(
63
48
  identifier: str = typer.Argument(..., help="Namespace name"),
64
49
  role: str = typer.Option(
65
50
  None,
66
- click_type=RoleSuggestion(),
51
+ metavar=ROLE_METAVAR,
67
52
  help="The role (name or id) to assign --api-key and --member",
68
53
  ),
69
54
  api_key: list[str] = typer.Option(
@@ -134,7 +119,7 @@ async def update(
134
119
  identifier: str = typer.Argument(..., help="Namespace name"),
135
120
  role: str = typer.Option(
136
121
  None,
137
- click_type=RoleSuggestion(),
122
+ metavar=ROLE_METAVAR,
138
123
  help="The role (name or id) to assign --api-key and --member",
139
124
  ),
140
125
  api_key: list[str] = typer.Option(
@@ -113,7 +113,7 @@ def _read_resource_file(file: pathlib.Path) -> dict:
113
113
  if not file.is_file():
114
114
  raise ValidioError(f"'{file.absolute()}' is not a file")
115
115
 
116
- obj = json.loads(file.read_text())
116
+ obj = json.loads(file.read_text(encoding="utf-8"))
117
117
  if not isinstance(obj, dict):
118
118
  raise ValidioError(f"expected json object in resource file: got {type(obj)}")
119
119
 
@@ -4,7 +4,6 @@ import uuid
4
4
  from pathlib import Path
5
5
  from typing import Any, Optional, cast
6
6
 
7
- import click
8
7
  import typer
9
8
  from prompt_toolkit import PromptSession
10
9
  from prompt_toolkit.completion import WordCompleter
@@ -283,6 +282,7 @@ async def reset(
283
282
 
284
283
  @infer_schema_app.callback(invoke_without_command=True)
285
284
  def main(
285
+ ctx: typer.Context,
286
286
  interactive: bool = typer.Option(
287
287
  False, "--interactive", "-i", help="Infer schema with an interactive prompt"
288
288
  ),
@@ -290,8 +290,6 @@ def main(
290
290
  filename: Path = schema_filename_option("schema"),
291
291
  namespace: str = Namespace(),
292
292
  ) -> None:
293
- ctx = click.get_current_context()
294
-
295
293
  # A subcommand was run prior to this, nothing todo
296
294
  if ctx.invoked_subcommand is not None:
297
295
  return None
@@ -302,7 +300,7 @@ def main(
302
300
 
303
301
  # A flag for this command was used but not interactive, print the help as if
304
302
  # no command was given
305
- click.echo(ctx.get_help())
303
+ typer.echo(ctx.get_help())
306
304
 
307
305
  return None
308
306
 
@@ -955,7 +953,7 @@ async def _infer_schema_bigquery(
955
953
 
956
954
 
957
955
  def _write_schema(filename: Path, schema: Any) -> None:
958
- filename.write_text(json.dumps(schema, indent=2))
956
+ filename.write_text(json.dumps(schema, indent=2), encoding="utf-8")
959
957
 
960
958
  print(f"Schema written to {filename}")
961
959
 
@@ -0,0 +1,130 @@
1
+ import typer
2
+ from validio_sdk._api.api import APIClient
3
+ from validio_sdk.config import ValidioConfig
4
+ from validio_sdk.exception import ValidioError
5
+
6
+ from validio_cli import (
7
+ AsyncTyper,
8
+ ConfigDir,
9
+ Identifier,
10
+ Identifiers,
11
+ Namespace,
12
+ OutputFormat,
13
+ OutputFormatOption,
14
+ OutputSettings,
15
+ get_client,
16
+ output_json,
17
+ output_ok_or_error,
18
+ output_text,
19
+ )
20
+ from validio_cli.bin.entities.validators import get_validator_id
21
+ from validio_cli.namespace import get_namespace
22
+
23
+ app = AsyncTyper(help="Debug queries saved on validators")
24
+
25
+
26
+ @app.async_command(help="List validator debug queries")
27
+ async def get(
28
+ config_dir: str = ConfigDir,
29
+ output_format: OutputFormat = OutputFormatOption,
30
+ namespace: str = Namespace(),
31
+ identifier: str = Identifier,
32
+ validator: str = typer.Option(
33
+ None, help="List debug queries for this Validator (name or ID)"
34
+ ),
35
+ ) -> None:
36
+ if identifier and validator:
37
+ raise ValidioError("--validator can't be used together with an identifier")
38
+
39
+ vc, cfg = get_client(config_dir)
40
+
41
+ validator_id = (
42
+ await get_validator_id(vc, cfg, validator, namespace) if validator else None
43
+ )
44
+
45
+ debug_queries = await vc.get_validator_debug_queries(
46
+ validator_debug_query_id=identifier,
47
+ validator_id=validator_id,
48
+ namespace_id=get_namespace(namespace, cfg),
49
+ )
50
+
51
+ if output_format == OutputFormat.JSON:
52
+ return output_json(debug_queries, identifier)
53
+
54
+ return output_text(
55
+ debug_queries,
56
+ fields={
57
+ "name": OutputSettings(attribute_name="resourceName"),
58
+ "validator": OutputSettings(
59
+ reformat=lambda validator: validator["resourceName"]
60
+ ),
61
+ "default": OutputSettings(attribute_name="defaultQuery"),
62
+ "age": OutputSettings.string_as_datetime(attribute_name="createdAt"),
63
+ },
64
+ )
65
+
66
+
67
+ @app.async_command(help="Delete validator debug query")
68
+ async def delete(
69
+ config_dir: str = ConfigDir,
70
+ output_format: OutputFormat = OutputFormatOption,
71
+ namespace: str = Namespace(),
72
+ identifiers: list[str] = Identifiers,
73
+ ) -> None:
74
+ if not identifiers:
75
+ raise ValidioError("no identifiers are provided")
76
+
77
+ vc, cfg = get_client(config_dir)
78
+
79
+ debug_query_ids = [
80
+ debug_query_id
81
+ for debug_query_id in [
82
+ await get_validator_debug_query_id(vc, cfg, identifier, namespace)
83
+ for identifier in identifiers
84
+ ]
85
+ if debug_query_id
86
+ ]
87
+
88
+ result = await vc.delete_validator_debug_queries(debug_query_ids)
89
+
90
+ if output_format == OutputFormat.JSON:
91
+ return output_json(result)
92
+
93
+ return output_ok_or_error(result)
94
+
95
+
96
+ async def get_validator_debug_query_id(
97
+ vc: APIClient, cfg: ValidioConfig, identifier: str, namespace: str
98
+ ) -> str | None:
99
+ """
100
+ Ensure the identifier is a resource id.
101
+
102
+ If it doesn't have the expected prefix, do a resource lookup by name.
103
+ """
104
+ identifier_type = "validator debug query"
105
+ prefix = "VDQ_"
106
+
107
+ if not identifier:
108
+ print(f"Missing {identifier_type} id or name")
109
+ return None
110
+
111
+ if identifier.startswith(prefix):
112
+ return identifier
113
+
114
+ resource = await vc.get_validator_debug_queries(
115
+ validator_debug_query_id=identifier,
116
+ namespace_id=get_namespace(namespace, cfg),
117
+ )
118
+
119
+ if resource is None:
120
+ print(f"No {identifier_type} with name or id {identifier} found")
121
+ return None
122
+
123
+ if not isinstance(resource, dict):
124
+ raise ValidioError("failed to get validator debug query id")
125
+
126
+ return resource["id"]
127
+
128
+
129
+ if __name__ == "__main__":
130
+ app()
@@ -30,6 +30,7 @@ from validio_cli.bin.entities import (
30
30
  segments,
31
31
  sources,
32
32
  users,
33
+ validator_debug_queries,
33
34
  validators,
34
35
  windows,
35
36
  )
@@ -78,6 +79,11 @@ app.add_typer(segments.app, no_args_is_help=True, name="segments")
78
79
  app.add_typer(sources.app, no_args_is_help=True, name="sources")
79
80
  app.add_typer(users.app, no_args_is_help=True, name="users")
80
81
  app.add_typer(validators.app, no_args_is_help=True, name="validators")
82
+ app.add_typer(
83
+ validator_debug_queries.app,
84
+ no_args_is_help=True,
85
+ name="validator-debug-queries",
86
+ )
81
87
  app.add_typer(windows.app, no_args_is_help=True, name="windows")
82
88
 
83
89