ui: add configoverride context manager
authorKostia Balytskyi <ikostia@fb.com>
Mon, 21 Nov 2016 16:22:26 -0800
changeset 30480 b0a8337ba9af
parent 30479 798bcb1274dd
child 30481 0a3b11a7489a
ui: add configoverride context manager I feel like this idea might've been discussed before, so please feel free to point me to the right mailing list entry to read about why it should not be done. We have a common pattern of the following code: backup = ui.backupconfig(section, name) try: ui.setconfig(section, name, temporaryvalue, source) do_something() finally: ui.restoreconfig(backup) IMO, this looks better: with ui.configoverride({(section, name): temporaryvalue}, source): do_something() Especially this becomes more convenient when one has to backup multiple config values before doing something. In such case, adding a new value to backup requires codemod in three places.
mercurial/ui.py
--- a/mercurial/ui.py	Mon Nov 21 18:17:02 2016 -0500
+++ b/mercurial/ui.py	Mon Nov 21 16:22:26 2016 -0800
@@ -7,6 +7,7 @@
 
 from __future__ import absolute_import
 
+import contextlib
 import errno
 import getpass
 import inspect
@@ -1193,6 +1194,23 @@
                 " update your code.)") % version
         self.develwarn(msg, stacklevel=2, config='deprec-warn')
 
+    @contextlib.contextmanager
+    def configoverride(self, overrides, source=""):
+        """Context manager for temporary config overrides
+        `overrides` must be a dict of the following structure:
+        {(section, name) : value}"""
+        backups = {}
+        for (section, name), value in overrides.items():
+            backups[(section, name)] = self.backupconfig(section, name)
+            self.setconfig(section, name, value, source)
+        yield
+        for __, backup in backups.items():
+            self.restoreconfig(backup)
+        # just restoring ui.quiet config to the previous value is not enough
+        # as it does not update ui.quiet class member
+        if ('ui', 'quiet') in overrides:
+            self.fixconfig(section='ui')
+
 class paths(dict):
     """Represents a collection of paths and their configs.