Skip to content

Commit 958516f

Browse files
author
Ysf
committed
fixed kwarg parsing
1 parent f4d9d46 commit 958516f

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

azpype/commands/base_command.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ def build_flags(self, options: dict):
3434
config = {k: v for k, v in config.items() if v not in ['NULL', None]}
3535

3636
if options is not None:
37-
# Also filter None values from runtime options
38-
filtered_options = {k: v for k, v in options.items() if v is not None}
37+
# Convert underscores to hyphens for CLI compatibility and filter None values
38+
filtered_options = {
39+
k.replace('_', '-'): v
40+
for k, v in options.items()
41+
if v is not None
42+
}
3943
config.update(filtered_options)
4044

4145
# Log detailed config to file only (suppress console output since we have Rich table)

tests/test_basecommand.py

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import sys
22
sys.path.append('../')
33
import unittest
4-
from unittest.mock import patch, Mock
4+
from unittest.mock import patch, Mock, mock_open
55
from azpype.commands.base_command import BaseCommand
66
from azpype.resource_paths import get_azcopy_path
77
import subprocess
8+
import yaml
9+
10+
11+
# Create a concrete implementation for testing
12+
class ConcreteCommand(BaseCommand):
13+
def __init__(self, command_name):
14+
super().__init__(command_name)
815

916

1017
class TestBaseCommand(unittest.TestCase):
1118
def setUp(self):
12-
self.command = BaseCommand("test_command")
19+
self.command = ConcreteCommand("test_command")
1320

1421
def test_build_command(self):
1522
args = ["arg1", "arg2"]
@@ -21,18 +28,72 @@ def test_build_command(self):
2128
def test_execute_success(self, mock_run):
2229
args = ["arg1", "arg2"]
2330
options = {"option1": "value1", "option2": True}
24-
mock_run.return_value = Mock(returncode=0, stdout="Success")
31+
mock_run.return_value = Mock(returncode=0, stdout="Success", stderr="")
2532
expected_output = (0, "Success")
2633
self.assertEqual(self.command.execute(args, options), expected_output)
2734

2835
@patch("subprocess.run")
2936
def test_execute_failure(self, mock_run):
3037
args = ["arg1", "arg2"]
3138
options = {"option1": "value1", "option2": True}
32-
mock_run.side_effect = subprocess.CalledProcessError(1, "test_command", "Error")
39+
error = subprocess.CalledProcessError(1, "test_command", "Error")
40+
error.stdout = "Error"
41+
error.stderr = ""
42+
mock_run.side_effect = error
3343
expected_output = (1, "Error")
3444
self.assertEqual(self.command.execute(args, options), expected_output)
3545

46+
def test_build_command_with_underscores(self):
47+
"""Test that underscores in option names are preserved in build_command"""
48+
args = ["source", "dest"]
49+
options = {"put_md5": True, "check_length": True, "dry_run": False}
50+
# Note: build_command expects options already converted to hyphens
51+
# The conversion happens in build_flags
52+
options_with_hyphens = {"put-md5": True, "check-length": True, "dry-run": False}
53+
expected_command = [
54+
get_azcopy_path(),
55+
"test_command",
56+
"source",
57+
"dest",
58+
"--put-md5=true",
59+
"--check-length=true"
60+
]
61+
actual_command = self.command.build_command(args, options_with_hyphens)
62+
# Check that the hyphenated options are in the command
63+
self.assertIn("--put-md5=true", actual_command)
64+
self.assertIn("--check-length=true", actual_command)
65+
self.assertNotIn("--dry-run", actual_command) # False values should not be included
66+
67+
@patch("builtins.open", new_callable=mock_open, read_data="key1: value1\nkey2: value2")
68+
@patch("azpype.resource_paths.ensure_user_config")
69+
def test_build_flags_underscore_to_hyphen(self, mock_ensure_config, mock_file):
70+
"""Test that build_flags converts underscores to hyphens in option keys"""
71+
mock_ensure_config.return_value = "/fake/path/config.yaml"
72+
73+
# Test with underscores in option names
74+
options = {
75+
"put_md5": True,
76+
"check_length": True,
77+
"as_subdir": False,
78+
"dry_run": None # Should be filtered out
79+
}
80+
81+
result = self.command.build_flags(options)
82+
83+
# Check that underscores were converted to hyphens
84+
self.assertIn("put-md5", result)
85+
self.assertIn("check-length", result)
86+
self.assertIn("as-subdir", result)
87+
88+
# Check that None values were filtered out
89+
self.assertNotIn("dry-run", result)
90+
self.assertNotIn("dry_run", result)
91+
92+
# Check that values are preserved
93+
self.assertEqual(result["put-md5"], True)
94+
self.assertEqual(result["check-length"], True)
95+
self.assertEqual(result["as-subdir"], False)
96+
3697

3798
if __name__ == "__main__":
3899
unittest.main()

0 commit comments

Comments
 (0)