From 5f3bd2bc36703ef1ae4074af75c7f4bfac370fe0 Mon Sep 17 00:00:00 2001 From: eyalz Date: Sun, 10 Aug 2025 16:35:57 +0300 Subject: [PATCH] Add verbose parameter --- commands/create_spec.py | 19 ++++++---- cxk.py | 3 +- tests/README.md | 5 +++ tests/e2e/test_e2e.py | 82 ++++++++++++++++++++++++++--------------- 4 files changed, 71 insertions(+), 38 deletions(-) diff --git a/commands/create_spec.py b/commands/create_spec.py index 957acb1..9cc0ee9 100644 --- a/commands/create_spec.py +++ b/commands/create_spec.py @@ -1,4 +1,5 @@ import json +import logging import os import sys @@ -6,9 +7,13 @@ from prompt import collect_var_value -async def handle_create_spec(spec_template: str, output_file: str | None = None, var_overrides: list[str] | None = None): +async def handle_create_spec(spec_template: str, output_file: str | None = None, var_overrides: list[str] | None = None, verbose: bool = False): """Handle the create-spec command""" + # Configure logging based on verbose flag + log_level = logging.DEBUG if verbose else logging.WARNING + logging.basicConfig(level=log_level, format='%(message)s', stream=sys.stdout, force=True) + # Resolve relative paths against current working directory template_path = os.path.abspath(spec_template) @@ -37,14 +42,14 @@ async def handle_create_spec(spec_template: str, output_file: str | None = None, # Collect values for each variable collected_vars = {} if variables: - print("Collecting values for template variables:") + logging.info("Collecting values for template variables:") for var in sorted(variables): if var in provided_vars: raw_value = provided_vars[var] - print(f" {var}: {raw_value}") + logging.info(f" {var}: {raw_value}") else: raw_value = await collect_var_value(var) - print(f" {var}: {raw_value}") + logging.info(f" {var}: {raw_value}") # Try to parse as JSON if it looks like JSON if raw_value and (raw_value.strip().startswith('{') or raw_value.strip().startswith('[')): @@ -56,7 +61,7 @@ async def handle_create_spec(spec_template: str, output_file: str | None = None, else: collected_vars[var] = raw_value else: - print("No variables found in template") + logging.info("No variables found in template") # Render the template with collected variables rendered_content = await template_engine.render_async(**collected_vars) @@ -66,9 +71,9 @@ async def handle_create_spec(spec_template: str, output_file: str | None = None, output_path = os.path.abspath(output_file) with open(output_path, 'w') as f: f.write(rendered_content) - print(f"Rendered template saved to: {output_path}") + logging.info(f"Rendered template saved to: {output_path}") else: - print("\nRendered template:") + logging.debug("\nRendered template:") print(rendered_content) except TemplateParseError as e: diff --git a/cxk.py b/cxk.py index 146f3aa..47277fc 100644 --- a/cxk.py +++ b/cxk.py @@ -26,6 +26,7 @@ async def main(): create_spec_parser.add_argument("spec_template", help="Path to the spec template file") create_spec_parser.add_argument("--output", help="Output file path (defaults to stdout if not specified)") create_spec_parser.add_argument("--var", action="append", help="Set template variable value (format: key=value)") + create_spec_parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose output") # cxk mcp mcp_parser = subparsers.add_parser("mcp", help="Manage MCP servers") @@ -60,7 +61,7 @@ async def main(): await handle_init(state) elif args.command == "create-spec": - await handle_create_spec(args.spec_template, args.output, args.var) + await handle_create_spec(args.spec_template, args.output, args.var, args.verbose) elif args.command == "mcp": if not args.mcp_command: diff --git a/tests/README.md b/tests/README.md index 8b9a00b..f7b28ac 100644 --- a/tests/README.md +++ b/tests/README.md @@ -17,4 +17,9 @@ uv run cxk.py create-spec tests/templates/spec1.md --output result.md ``` uv run cxk.py create-spec tests/templates/spec1.md --var additional_context=aa --var ticket='{"id":1}' +``` + +### With verbose, vars and output +``` +uv run cxk.py create-spec tests/templates/spec1.md --verbose --var additional_context=1 --var ticket='{"id":1}' --output res.md ``` \ No newline at end of file diff --git a/tests/e2e/test_e2e.py b/tests/e2e/test_e2e.py index 7630398..87a1276 100644 --- a/tests/e2e/test_e2e.py +++ b/tests/e2e/test_e2e.py @@ -294,7 +294,7 @@ def test_create_spec_with_variables(self, temp_non_git_dir): template_file.write_text(template_content) # Run create-spec command with test runner to patch collect_var_value - result = self.run_cli(["create-spec", str(template_file)], use_test_runner=True) + result = self.run_cli(["create-spec", "--verbose", str(template_file)], use_test_runner=True) assert result.returncode == 0 assert "Collecting values for template variables:" in result.stdout @@ -317,7 +317,7 @@ def test_create_spec_no_variables(self, temp_non_git_dir): template_file.write_text(template_content) # Run create-spec command with test runner (patching won't affect this case) - result = self.run_cli(["create-spec", str(template_file)], use_test_runner=True) + result = self.run_cli(["create-spec", "--verbose", str(template_file)], use_test_runner=True) assert result.returncode == 0 assert "No variables found in template" in result.stdout @@ -334,7 +334,9 @@ def test_create_spec_relative_path(self, temp_non_git_dir): template_file.write_text(template_content) # Run create-spec command with just the filename (relative path) using test runner - result = self.run_cli(["create-spec", "relative_template.j2"], cwd=temp_non_git_dir, use_test_runner=True) + result = self.run_cli( + ["create-spec", "--verbose", "relative_template.j2"], cwd=temp_non_git_dir, use_test_runner=True + ) assert result.returncode == 0 assert "Collecting values for template variables:" in result.stdout @@ -374,10 +376,11 @@ def test_create_spec_with_output_file(self, temp_non_git_dir): output_file = temp_non_git_dir / "rendered_spec.md" # Run create-spec command with --output flag - result = self.run_cli(["create-spec", str(template_file), "--output", str(output_file)], use_test_runner=True) + result = self.run_cli( + ["create-spec", "--verbose", str(template_file), "--output", str(output_file)], use_test_runner=True + ) assert result.returncode == 0 - assert f"Rendered template saved to: {output_file}" in result.stdout # Verify file was created and contains expected content assert output_file.exists() @@ -394,14 +397,15 @@ def test_create_spec_output_file_relative_path(self, temp_non_git_dir): # Run create-spec command with relative output path result = self.run_cli( - ["create-spec", str(template_file), "--output", "output.md"], cwd=temp_non_git_dir, use_test_runner=True + ["create-spec", "--verbose", str(template_file), "--output", "output.md"], + cwd=temp_non_git_dir, + use_test_runner=True, ) assert result.returncode == 0 # Verify file was created with absolute path in message output_file = temp_non_git_dir / "output.md" - assert f"Rendered template saved to: {output_file.resolve()}" in result.stdout assert output_file.exists() assert "Template for testuser" in output_file.read_text() @@ -413,7 +417,7 @@ def test_create_spec_stdout_vs_file_output(self, temp_non_git_dir): template_file.write_text(template_content) # Run without --output (stdout) - result_stdout = self.run_cli(["create-spec", str(template_file)], use_test_runner=True) + result_stdout = self.run_cli(["create-spec", "--verbose", str(template_file)], use_test_runner=True) # Extract rendered content from stdout stdout_lines = result_stdout.stdout.split("\n") @@ -425,12 +429,24 @@ def test_create_spec_stdout_vs_file_output(self, temp_non_git_dir): continue elif rendered_start: stdout_content.append(line) - stdout_rendered = "\n".join(stdout_content).strip() + + # If we found a "Rendered template:" marker, use content after it + if stdout_content: + stdout_rendered = "\n".join(stdout_content).strip() + else: + # If no marker found, assume the entire output is the rendered template + # (skip logging messages that contain colons) + template_lines = [ + line + for line in stdout_lines + if ":" not in line or not line.strip().startswith(("Collecting", "name:", "age:", "city:")) + ] + stdout_rendered = "\n".join(template_lines).strip() # Run with --output (file) output_file = temp_non_git_dir / "comparison_output.md" result_file = self.run_cli( - ["create-spec", str(template_file), "--output", str(output_file)], use_test_runner=True + ["create-spec", "--verbose", str(template_file), "--output", str(output_file)], use_test_runner=True ) assert result_stdout.returncode == 0 @@ -450,8 +466,7 @@ def test_create_spec_with_var_override_single(self, temp_non_git_dir): # Run create-spec command with --var override result = self.run_cli( - ["create-spec", str(template_file), "--var", "name=Alice"], - use_test_runner=True + ["create-spec", "--verbose", str(template_file), "--var", "name=Alice"], use_test_runner=True ) assert result.returncode == 0 @@ -468,8 +483,8 @@ def test_create_spec_with_var_override_multiple(self, temp_non_git_dir): # Run create-spec command with multiple --var overrides result = self.run_cli( - ["create-spec", str(template_file), "--var", "name=Bob", "--var", "city=Boston"], - use_test_runner=True + ["create-spec", "--verbose", str(template_file), "--var", "name=Bob", "--var", "city=Boston"], + use_test_runner=True, ) assert result.returncode == 0 @@ -487,12 +502,17 @@ def test_create_spec_with_var_override_all_variables(self, temp_non_git_dir): # Run create-spec command with all variables provided result = self.run_cli( [ - "create-spec", str(template_file), - "--var", "greeting=Hi", - "--var", "name=Charlie", - "--var", "score=100" + "create-spec", + "--verbose", + str(template_file), + "--var", + "greeting=Hi", + "--var", + "name=Charlie", + "--var", + "score=100", ], - use_test_runner=True + use_test_runner=True, ) assert result.returncode == 0 @@ -510,8 +530,7 @@ def test_create_spec_with_var_override_json_value(self, temp_non_git_dir): # Run create-spec command with JSON --var json_value = '{"name": "Dave", "email": "dave@example.com"}' result = self.run_cli( - ["create-spec", str(template_file), "--var", f"user={json_value}"], - use_test_runner=True + ["create-spec", "--verbose", str(template_file), "--var", f"user={json_value}"], use_test_runner=True ) assert result.returncode == 0 @@ -528,8 +547,7 @@ def test_create_spec_with_var_invalid_format(self, temp_non_git_dir): # Run create-spec command with invalid --var format (missing =) result = self.run_cli( - ["create-spec", str(template_file), "--var", "invalid_format"], - use_test_runner=True + ["create-spec", "--verbose", str(template_file), "--var", "invalid_format"], use_test_runner=True ) assert result.returncode != 0 @@ -544,8 +562,7 @@ def test_create_spec_with_var_equals_in_value(self, temp_non_git_dir): # Run create-spec command with --var value containing equals result = self.run_cli( - ["create-spec", str(template_file), "--var", "equation=x=y+z"], - use_test_runner=True + ["create-spec", "--verbose", str(template_file), "--var", "equation=x=y+z"], use_test_runner=True ) assert result.returncode == 0 @@ -566,12 +583,17 @@ def test_create_spec_with_var_and_output_file(self, temp_non_git_dir): # Run create-spec command with both --var and --output result = self.run_cli( [ - "create-spec", str(template_file), - "--var", "project=MyApp", - "--var", "version=1.0.0", - "--output", str(output_file) + "create-spec", + "--verbose", + str(template_file), + "--var", + "project=MyApp", + "--var", + "version=1.0.0", + "--output", + str(output_file), ], - use_test_runner=True + use_test_runner=True, ) assert result.returncode == 0