diff options
author | Frantisek Tobias <frantisek.tobias@nic.cz> | 2024-10-15 12:40:23 +0200 |
---|---|---|
committer | Aleš Mrázek <ales.mrazek@nic.cz> | 2024-12-20 22:24:22 +0100 |
commit | f984af0096ebe50d866a94ff66aadfe926f18d20 (patch) | |
tree | 184b69310b7a1f114544228b9f1764c1eea8f621 | |
parent | kresctl: tab-completion: auto-complete for all commands except config (diff) | |
download | knot-resolver-f984af0096ebe50d866a94ff66aadfe926f18d20.tar.xz knot-resolver-f984af0096ebe50d866a94ff66aadfe926f18d20.zip |
kresctl: tab-completion: enable config completion
-rw-r--r-- | python/knot_resolver/client/commands/config.py | 109 |
1 files changed, 58 insertions, 51 deletions
diff --git a/python/knot_resolver/client/commands/config.py b/python/knot_resolver/client/commands/config.py index 52df39c4..dbf6ccaa 100644 --- a/python/knot_resolver/client/commands/config.py +++ b/python/knot_resolver/client/commands/config.py @@ -1,9 +1,10 @@ import argparse import sys from enum import Enum -from typing import List, Literal, Optional, Tuple, Type +from typing import Any, Dict, List, Literal, Optional, Tuple, Type -from knot_resolver.client.command import Command, CommandArgs, CompWords, register_command +from knot_resolver.client.command import Command, CommandArgs, CompWords, get_subparsers_words, register_command +from knot_resolver.datamodel import KresConfig from knot_resolver.utils.modeling.parsing import DataFormat, parse_json, try_to_parse from knot_resolver.utils.requests import request @@ -22,54 +23,53 @@ def operation_to_method(operation: Operations) -> Literal["PUT", "GET", "DELETE" return "GET" -# def _properties_words(props: Dict[str, Any]) -> CompWords: -# words: CompWords = {} -# for name, prop in props.items(): -# words[name] = prop["description"] if "description" in prop else None -# return words - - -# def _path_comp_words(node: str, nodes: List[str], props: Dict[str, Any]) -> CompWords: -# i = nodes.index(node) -# ln = len(nodes[i:]) - -# # if node is last in path, return all possible words on thi level -# if ln == 1: -# return _properties_words(props) -# # if node is valid -# elif node in props: -# node_schema = props[node] - -# if "anyOf" in node_schema: -# for item in node_schema["anyOf"]: -# print(item) - -# elif "type" not in node_schema: -# pass - -# elif node_schema["type"] == "array": -# if ln > 2: -# # skip index for item in array -# return _path_comp_words(nodes[i + 2], nodes, node_schema["items"]["properties"]) -# if "enum" in node_schema["items"]: -# print(node_schema["items"]["enum"]) -# return {"0": "first array item", "-": "last array item"} -# elif node_schema["type"] == "object": -# if "additionalProperties" in node_schema: -# print(node_schema) -# return _path_comp_words(nodes[i + 1], nodes, node_schema["properties"]) -# return {} - -# # arrays/lists must be handled sparately -# if node_schema["type"] == "array": -# if ln > 2: -# # skip index for item in array -# return _path_comp_words(nodes[i + 2], nodes, node_schema["items"]["properties"]) -# return {"0": "first array item", "-": "last array item"} -# return _path_comp_words(nodes[i + 1], nodes, node_schema["properties"]) -# else: -# # if node is not last or valid, value error -# raise ValueError(f"unknown config path node: {node}") +def _properties_words(props: Dict[str, Any]) -> CompWords: + words: CompWords = {} + for name, prop in props.items(): + words[name] = prop["description"] if "description" in prop else None + return words + + +def _path_comp_words(node: str, nodes: List[str], props: Dict[str, Any]) -> CompWords: # noqa: PLR0911, PLR0912 + i = nodes.index(node) + ln = len(nodes[i:]) + + # if node is last in path, return all possible words on thi level + if ln == 1: + return _properties_words(props) + # if node is valid + if node in props: + node_schema = props[node] + + if "anyOf" in node_schema: + for item in node_schema["anyOf"]: + print(item) + + elif "type" not in node_schema: + pass + + elif node_schema["type"] == "array": + if ln > 2: + # skip index for item in array + return _path_comp_words(nodes[i + 2], nodes, node_schema["items"]["properties"]) + if "enum" in node_schema["items"]: + print(node_schema["items"]["enum"]) + return {"0": "first array item", "-": "last array item"} + elif node_schema["type"] == "object": + if "additionalProperties" in node_schema: + print(node_schema) + return _path_comp_words(nodes[i + 1], nodes, node_schema["properties"]) + # return {} + + # arrays/lists must be handled sparately + if node_schema["type"] == "array": + if ln > 2: + # skip index for item in array + return _path_comp_words(nodes[i + 2], nodes, node_schema["items"]["properties"]) + return {"0": "first array item", "-": "last array item"} + return _path_comp_words(nodes[i + 1], nodes, node_schema["properties"]) + # if node is not last or valid, value error + raise ValueError(f"unknown config path node: {node}") @register_command @@ -170,7 +170,14 @@ class ConfigCommand(Command): @staticmethod def completion(args: List[str], parser: argparse.ArgumentParser) -> CompWords: - # words = parser_words(parser._actions) # pylint: disable=W0212 + words = get_subparsers_words(parser._actions) # noqa: SLF001 + if args is None: + return words + + arg = args[-1] + config_path = arg[1:].split("/") if arg.startswith("/") else arg.split("/") + schema_props: Dict[str, Any] = KresConfig.json_schema()["properties"] + return _path_comp_words(config_path[0], config_path, schema_props) # for arg in args: # if arg in words: |