From 46fee7802235ec412a832e94f9d448d3a8279541 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 24 Jul 2025 14:30:10 +0000 Subject: [PATCH 1/2] Initial plan From c88e7c2dfcac80ecfa5f8c99753cec36ece2136b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 24 Jul 2025 14:43:48 +0000 Subject: [PATCH 2/2] Add comprehensive tests for KVP splitting to prevent issue #35 regression Co-authored-by: smurawski <4006985+smurawski@users.noreply.github.com> --- src/tests/service/test_service_environment.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/tests/service/test_service_environment.py b/src/tests/service/test_service_environment.py index fad4eb2..96c9b24 100644 --- a/src/tests/service/test_service_environment.py +++ b/src/tests/service/test_service_environment.py @@ -1,6 +1,7 @@ from unittest import TestCase from pycomposefile import compose_file +from pycomposefile.compose_element.compose_list_or_map import ComposeListOrMapElement from ..compose_generator import ComposeGenerator @@ -19,3 +20,38 @@ def test_service_with_environment_list(self): self.assertEqual(compose_file.services["frontend"].environment["RACK_ENV"], "development") self.assertEqual(compose_file.services["frontend"].environment["SHOW"], "true") self.assertIsNone(compose_file.services["frontend"].environment["USER_INPUT"]) + + def test_kvp_with_multiple_equals_issue_35(self): + """Test for issue #35: KVP strings with multiple '=' should split on first '=' only""" + # Test the exact scenario from the issue + element = ComposeListOrMapElement("JAVA_OPTS=foo=bar&&baz=buzz") + self.assertEqual(element["JAVA_OPTS"], "foo=bar&&baz=buzz") + + def test_kvp_splitting_edge_cases(self): + """Test various edge cases for KVP splitting to prevent regression""" + test_cases = [ + # (input_string, expected_key, expected_value) + ("KEY=value", "KEY", "value"), + ("KEY=value=extra", "KEY", "value=extra"), + ("KEY=a=b=c=d", "KEY", "a=b=c=d"), + ("URL=http://example.com:8080/path?param=value", "URL", "http://example.com:8080/path?param=value"), + ("CONFIG=key1=val1,key2=val2", "CONFIG", "key1=val1,key2=val2"), + ("COMPLEX=a=b&c=d&e=f", "COMPLEX", "a=b&c=d&e=f"), + ("NO_VALUE", "NO_VALUE", None), + ] + + for input_string, expected_key, expected_value in test_cases: + with self.subTest(input=input_string): + element = ComposeListOrMapElement(input_string) + self.assertEqual(element[expected_key], expected_value) + + def test_empty_value_handling(self): + """Test handling of empty values - this is existing behavior that should be preserved""" + # EMPTY= should result in None (existing behavior) + element = ComposeListOrMapElement("EMPTY=") + self.assertIsNone(element["EMPTY"]) + + # Test the isValueEmpty method directly + element_test = ComposeListOrMapElement(None) + self.assertTrue(element_test.isValueEmpty("KEY=")) + self.assertFalse(element_test.isValueEmpty("KEY=value"))