diff --git a/pkgs/clan-cli/clan_cli/config/__init__.py b/pkgs/clan-cli/clan_cli/config/__init__.py index 79824c5..3dcbc93 100644 --- a/pkgs/clan-cli/clan_cli/config/__init__.py +++ b/pkgs/clan-cli/clan_cli/config/__init__.py @@ -92,7 +92,7 @@ def cast(value: Any, type: Type, opt_description: str) -> Any: def process_args( - option: str, value: Any, options: dict, option_description: str = "" + option: str, value: Any, options: dict, out_file: Path, option_description: str = "" ) -> None: option_path = option.split(".") @@ -107,6 +107,7 @@ def process_args( option=".".join(option_parent), value={attr: value}, options=options, + out_file=out_file, option_description=option, ) @@ -125,14 +126,14 @@ def process_args( current[option_path[-1]] = casted # check if there is an existing config file - if os.path.exists("clan-settings.json"): - with open("clan-settings.json") as f: + if os.path.exists(out_file): + with open(out_file) as f: current_config = json.load(f) else: current_config = {} # merge and save the new config file new_config = merge(current_config, result) - with open("clan-settings.json", "w") as f: + with open(out_file, "w") as f: json.dump(new_config, f, indent=2) print("New config:") print(json.dumps(new_config, indent=2)) @@ -178,10 +179,22 @@ def _register_parser( # inject callback function to process the input later parser.set_defaults( func=lambda args: process_args( - option=args.option, value=args.value, options=options + option=args.option, + value=args.value, + options=options, + out_file=args.out_file, ) ) + # add argument to pass output file + parser.add_argument( + "--out-file", + "-o", + help="Output file", + type=Path, + default=Path("clan-settings.json"), + ) + # add single positional argument for the option (e.g. "foo.bar") parser.add_argument( "option", diff --git a/pkgs/clan-cli/default.nix b/pkgs/clan-cli/default.nix index 93f7b53..9939d1b 100644 --- a/pkgs/clan-cli/default.nix +++ b/pkgs/clan-cli/default.nix @@ -21,6 +21,10 @@ , rsync }: let + # This provides dummy options for testing clan config and prevents it from + # evaluating the flake .# + CLAN_OPTIONS_FILE = ./clan_cli/config/jsonschema/options.json; + dependencies = [ argcomplete ]; testDependencies = [ @@ -48,7 +52,7 @@ python3.pkgs.buildPythonPackage { src = source; format = "pyproject"; - CLAN_OPTIONS_FILE = ./clan_cli/config/jsonschema/options.json; + inherit CLAN_OPTIONS_FILE; nativeBuildInputs = [ setuptools @@ -58,6 +62,7 @@ python3.pkgs.buildPythonPackage { passthru.tests = { clan-mypy = runCommand "clan-mypy" { } '' + export CLAN_OPTIONS_FILE="${CLAN_OPTIONS_FILE}" cp -r ${source} ./src chmod +w -R ./src cd ./src @@ -68,6 +73,7 @@ python3.pkgs.buildPythonPackage { { nativeBuildInputs = [ age zerotierone bubblewrap sops nix openssh rsync stdenv.cc ]; } '' + export CLAN_OPTIONS_FILE="${CLAN_OPTIONS_FILE}" cp -r ${source} ./src chmod +w -R ./src cd ./src diff --git a/pkgs/clan-cli/shell.nix b/pkgs/clan-cli/shell.nix index 61a98ff..1a17315 100644 --- a/pkgs/clan-cli/shell.nix +++ b/pkgs/clan-cli/shell.nix @@ -20,6 +20,9 @@ pkgs.mkShell { ]; # sets up an editable install and add enty points to $PATH CLAN_FLAKE = self; + # This provides dummy options for testing clan config and prevents it from + # evaluating the flake .# + CLAN_OPTIONS_FILE = ./clan_cli/config/jsonschema/options.json; shellHook = '' tmp_path=$(realpath ./.pythonenv) repo_root=$(realpath .) diff --git a/pkgs/clan-cli/tests/test_config.py b/pkgs/clan-cli/tests/test_config.py index 165626d..effba09 100644 --- a/pkgs/clan-cli/tests/test_config.py +++ b/pkgs/clan-cli/tests/test_config.py @@ -1,6 +1,7 @@ import argparse import json import sys +import tempfile from pathlib import Path from typing import Any @@ -32,15 +33,20 @@ def test_set_some_option( monkeypatch: pytest.MonkeyPatch, ) -> None: # monkeypatch sys.argv - monkeypatch.setattr(sys, "argv", [""] + argv) - parser = argparse.ArgumentParser() - config.register_parser(parser=parser, optionsFile=Path(example_options)) - args = parser.parse_args() - args.func(args) - captured = capsys.readouterr() - print(captured.out) - json_out = json.loads(captured.out) - assert json_out == expected + # create temporary file for out_file + with tempfile.NamedTemporaryFile() as out_file: + with open(out_file.name, "w") as f: + json.dump({}, f) + monkeypatch.setattr(sys, "argv", ["", "--out-file", out_file.name] + argv) + parser = argparse.ArgumentParser() + config._register_parser( + parser=parser, + options=json.loads(Path(example_options).read_text()), + ) + args = parser.parse_args() + args.func(args) + json_out = json.loads(open(out_file.name).read()) + assert json_out == expected def test_walk_jsonschema_all_types() -> None: