From 18438c590bb997368210e0f908c6150d24bf8617 Mon Sep 17 00:00:00 2001 From: yuk1pedia <18627927506@163.com> Date: Wed, 27 Aug 2025 16:41:44 +0800 Subject: [PATCH] fix: [supervisord] environment section does not properly escape %% --- supervisor/options.py | 2 +- supervisor/tests/test_options.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/supervisor/options.py b/supervisor/options.py index 271735200..5f1bc5ae5 100644 --- a/supervisor/options.py +++ b/supervisor/options.py @@ -657,7 +657,7 @@ def get(opt, default, **kwargs): section.nocleanup = boolean(get('nocleanup', 'false')) section.strip_ansi = boolean(get('strip_ansi', 'false')) - environ_str = get('environment', '') + environ_str = get('environment', '', do_expand=False) environ_str = expand(environ_str, expansions, 'environment') section.environment = dict_of_key_value_pairs(environ_str) diff --git a/supervisor/tests/test_options.py b/supervisor/tests/test_options.py index 4f3ff71de..cc9e8366f 100644 --- a/supervisor/tests/test_options.py +++ b/supervisor/tests/test_options.py @@ -3409,6 +3409,18 @@ def test_daemonize_notifies_poller_before_and_after_fork(self): instance.poller.before_daemonize.assert_called_once_with() instance.poller.after_daemonize.assert_called_once_with() + def test_options_environment_of_supervisord_with_escaped_chars(self): + text = lstrip(""" + [supervisord] + environment=VAR_WITH_P="some_value_%%_end" + """) + + instance = self._makeOne() + instance.configfile = StringIO(text) + instance.realize(args=[]) + options = instance.configroot.supervisord + self.assertEqual(options.environment, dict(VAR_WITH_P="some_value_%_end")) + class ProcessConfigTests(unittest.TestCase): def _getTargetClass(self): from supervisor.options import ProcessConfig