From 53aa434d77d52931ef08a48a15b8ceb34d9665d4 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Wed, 18 Nov 2020 13:01:08 -0500 Subject: [PATCH] Add a helper to make a deep copy of a ConfigParser This will help avoid unintentional side-effects --- src/allmydata/test/test_configutil.py | 13 +++++++++++++ src/allmydata/util/configutil.py | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/allmydata/test/test_configutil.py b/src/allmydata/test/test_configutil.py index ea7759fec..1b8fb5029 100644 --- a/src/allmydata/test/test_configutil.py +++ b/src/allmydata/test/test_configutil.py @@ -280,3 +280,16 @@ enabled = false ), None, ) + + @given(arbitrary_config_dicts()) + def test_copy_config(self, cfgdict): + """ + ``copy_config`` creates a new ``ConfigParser`` object containing the same + values as its input. + """ + cfg = to_configparser(cfgdict) + copied = configutil.copy_config(cfg) + # Should be equal + self.assertEqual(cfg, copied) + # But not because they're the same object. + self.assertIsNot(cfg, copied) diff --git a/src/allmydata/util/configutil.py b/src/allmydata/util/configutil.py index c85f58af3..8063ba449 100644 --- a/src/allmydata/util/configutil.py +++ b/src/allmydata/util/configutil.py @@ -173,6 +173,23 @@ class ValidConfiguration(object): ) +def copy_config(old): + """ + Return a brand new ``ConfigParser`` containing the same values as + the given object. + + :param ConfigParser old: The configuration to copy. + + :return ConfigParser: The new object containing the same configuration. + """ + new = ConfigParser() + for section_name in old.sections(): + new.add_section(section_name) + for k, v in old.items(section_name): + new.set(section_name, k, v.replace("%", "%%")) + return new + + def _either(f, g): """ :return: A function which returns True if either f or g returns True.