-
Notifications
You must be signed in to change notification settings - Fork 2
Adding Config and db query Support #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
a058e72
bd5c589
9c429b6
3d13dd2
f3a8fd8
6147396
af46876
ce69287
068dc34
bbf4db8
45e2397
406f0f7
bd31853
8d4ec34
f765031
f45a99e
55ac924
0beaf9f
470aead
bf8de96
62eab53
7513969
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,86 @@ | ||||
| # from ..utils.MessageUtils import * | ||||
| import logging | ||||
|
pateash marked this conversation as resolved.
Outdated
|
||||
|
|
||||
| import click | ||||
| import rich | ||||
| from cron_descriptor import get_description # type: ignore | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unused import. The Apply this diff to remove the unused import: -from cron_descriptor import get_description # type: ignoreCommittable suggestion
Suggested change
ToolsRuff
|
||||
| from rich.panel import Panel | ||||
|
|
||||
| from ..utils import ConfigUtils, MessageUtils | ||||
|
pateash marked this conversation as resolved.
Outdated
|
||||
| from ..utils.ConfigUtils import load_config, config_path, ensure_config_file, DEFAULT_CONFIG, configMessage | ||||
|
pateash marked this conversation as resolved.
Outdated
|
||||
|
|
||||
|
|
||||
| @click.group( | ||||
| help="Config commands", | ||||
| context_settings={"help_option_names": ["-h", "--help"]}, | ||||
| ) | ||||
| @click.pass_context | ||||
| def configure(ctx): | ||||
| """ | ||||
| Defines a command group for configuration-related commands. | ||||
| """ | ||||
| ensure_config_file() | ||||
|
|
||||
|
|
||||
| def common_config_options(func): | ||||
| func = click.option("-c", "--config", help="Config instance, default: DEFAULT", default=DEFAULT_CONFIG)(func) | ||||
| return func | ||||
|
|
||||
|
|
||||
| @configure.command() | ||||
| @common_config_options | ||||
| @click.argument('key') | ||||
| @click.argument('value') | ||||
| def set(config, key, value): | ||||
| """ | ||||
| Sets a configuration value. | ||||
|
|
||||
| Args: | ||||
| config (str): The configuration instance name. Default is defined by DEFAULT_CONFIG. | ||||
| key (str): The key of the config setting to change. | ||||
| value (str): The value to set for the specified key. | ||||
|
|
||||
| Example: | ||||
| $ cli_tool configure set database_host 127.0.0.1 | ||||
| """ | ||||
| configMessage(config) | ||||
| ConfigUtils.set_config_value(config, key, value) | ||||
| rich.print( | ||||
| Panel( | ||||
| f"[{config}] {key} <- {value}", | ||||
| expand=True, | ||||
| title="Success", | ||||
| ) | ||||
| ) | ||||
|
|
||||
| @configure.command() | ||||
| @common_config_options | ||||
| @click.argument('key') | ||||
| def get(config, key): | ||||
| """Get a configuration value.""" | ||||
| configMessage(config) | ||||
| try: | ||||
| value = ConfigUtils.get_config_value(config, key) | ||||
| rich.print( | ||||
| Panel( | ||||
| f"[{config}] {key} = {value}", | ||||
| expand=True, | ||||
| title="Success", | ||||
| ) | ||||
| ) | ||||
| except ValueError as e: | ||||
| rich.print( | ||||
| Panel( | ||||
| f"{e}", | ||||
| expand=True, | ||||
| title="Error", | ||||
| ) | ||||
| ) | ||||
|
|
||||
|
|
||||
| @configure.command() | ||||
| @common_config_options | ||||
| def show(config): | ||||
| """List configuration values.""" | ||||
| configMessage(config) | ||||
| ConfigUtils.list_config(config) | ||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| import configparser | ||
| import logging | ||
| from pathlib import Path | ||
|
|
||
| import click | ||
|
pateash marked this conversation as resolved.
Outdated
|
||
| import rich | ||
| from rich.panel import Panel | ||
|
|
||
| from . import MessageUtils | ||
| from ..__about__ import __version__ | ||
|
|
||
| # Define the default configuration file path, this can't be changed, although user can have multile instances using --config | ||
| config_path = Path.home() / ".hckrcfg" | ||
| DEFAULT_CONFIG = "HCKR" | ||
|
|
||
|
|
||
| def load_config(): | ||
| """Load the INI configuration file.""" | ||
| config = configparser.ConfigParser() | ||
| config.read(config_path) | ||
| return config | ||
|
|
||
|
|
||
| def ensure_config_file(): | ||
| """ | ||
| Ensures the existence of a configuration file at the specified path. | ||
|
|
||
| :param config_path: The path to the configuration file. | ||
| :return: None | ||
|
|
||
| This function creates a configuration file at the specified path if it does not already exist. It also creates any necessary parent directories. The configuration file is empty initially, but a default configuration is written to it using configparser. The default configuration includes a 'DEFAULT' section with a 'version' option that contains the value of the __version__ global variable. | ||
|
|
||
| Example Usage: | ||
| -------------- | ||
| ensure_config_file(Path('/path/to/config.ini')) | ||
| """ | ||
| if not config_path.exists(): | ||
| config_path.parent.mkdir(parents=True, exist_ok=True) | ||
| config_path.touch(exist_ok=True) | ||
| default_config = { | ||
| DEFAULT_CONFIG: { | ||
| 'version': f"{__version__}", | ||
| }, | ||
| } | ||
| config = configparser.ConfigParser() | ||
| config.read_dict(default_config) | ||
| with config_path.open('w') as config_file: | ||
| config.write(config_file) | ||
| MessageUtils.info(f"Creating default config file {config_path}") | ||
| else: | ||
| logging.debug(f"Config file {config_path} already exists ") | ||
|
|
||
|
|
||
| def set_config_value(section, key, value): | ||
| """ | ||
| Sets a configuration value in a configuration file. | ||
|
|
||
| :param section: The name of the configuration section. | ||
| :param key: The key of the configuration value. | ||
| :param value: The value to set. | ||
| :return: None | ||
|
|
||
| This function sets a configuration value in a configuration file. It first logs the action using the `logging.debug()` function. Then, it loads the configuration file using the `load_config()` function. If the configuration file does not have the specified section and the section is not the default section, it adds the section to the configuration file. Next, it sets the value for the key in the specified section. Finally, it writes the updated configuration file to disk. | ||
|
|
||
| After setting the configuration value, the function displays an information message using the `MessageUtils.info()` function. | ||
|
|
||
| Note: This function assumes that the `logging` and `MessageUtils` modules are imported and configured properly. | ||
|
|
||
| Example Usage: | ||
| set_config_value("database", "username", "admin") | ||
| """ | ||
| logging.debug(f"Setting [{section}] {key} = {value}") | ||
| config = load_config() | ||
| if not config.has_section(section) and section != DEFAULT_CONFIG: | ||
| logging.debug(f"Adding section {section}") | ||
| config.add_section(section) | ||
| config.set(section, key, value) | ||
| with config_path.open('w') as config_file: | ||
| config.write(config_file) | ||
|
|
||
|
|
||
| def get_config_value(section, key) -> str: | ||
| """ | ||
| :param section: The section of the configuration file where the desired value is located. | ||
| :param key: The key of the value within the specified section. | ||
| :return: The value corresponding to the specified key within the specified section of the configuration file. | ||
|
|
||
| """ | ||
| logging.debug(f"Getting [{section}] {key} ") | ||
| config = load_config() | ||
| if not config.has_section(section): | ||
| raise ValueError(f"Section '{section}' not found in the configuration.") | ||
| if not config.has_option(section, key): | ||
| raise ValueError(f"Key '{key}' not found in section '{section}'.") | ||
| return config.get(section, key) | ||
|
|
||
|
|
||
| def list_config(section): | ||
| """ | ||
| List Config | ||
|
|
||
| This function takes a section parameter and lists the configuration values for that section from the loaded configuration file. If the section is found in the configuration file, it will print the section name and all key-value pairs associated with that section. If the section is not found, it will display an error message. | ||
|
|
||
| :param section: The section name for which the configuration values should be listed. | ||
| :return: None | ||
| """ | ||
| config = load_config() | ||
| if config.has_section(section): | ||
| rich.print( | ||
| Panel( | ||
| "\n".join([f"{key} = {value}" for key, value in config.items(section)]) if config.items( | ||
| section) else "NOTHING FOUND", | ||
| expand=True, | ||
| title="HCKR", | ||
| ) | ||
| ) | ||
| else: | ||
| MessageUtils.warning(f"Config '{section}' not found.") | ||
|
|
||
|
|
||
| def configMessage(config): | ||
| if config == DEFAULT_CONFIG: | ||
| MessageUtils.info(f"Using default config: [magenta]{DEFAULT_CONFIG}") | ||
| else: | ||
| MessageUtils.info(f"Using config: [magenta]{config}") | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,28 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from distutils.command.config import config | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
pateash marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import random | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from click.testing import CliRunner | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from hckr.cli.configure import set, get | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _get_random_string(length): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| letters = string.ascii_lowercase | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result_str = ''.join(random.choice(letters) for i in range(length)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return result_str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # DEFAULT CONFIG GET AND SET | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_configure_get_set_default(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runner = CliRunner() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _key = f"key_{_get_random_string(5)}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _value = f"value_{_get_random_string(5)}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result = runner.invoke(set, [_key, _value]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert result.exit_code == 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print(result.output) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Set [DEFAULT] {_key} = {_value}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| in result.output | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result = runner.invoke(get, [_key, _value]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure the The Consider modifying the test to check if the result = runner.invoke(get, [_key])
assert result.exit_code == 0
assert (
f"[DEFAULT] {_key} = {_value}"
in result.output
)Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.