1# encoding: utf-8
2"""Miscellaneous context managers."""
3
4import warnings
5
6# Copyright (c) IPython Development Team.
7# Distributed under the terms of the Modified BSD License.
8
9
10class preserve_keys:
11 """Preserve a set of keys in a dictionary.
12
13 Upon entering the context manager the current values of the keys
14 will be saved. Upon exiting, the dictionary will be updated to
15 restore the original value of the preserved keys. Preserved keys
16 which did not exist when entering the context manager will be
17 deleted.
18
19 Examples
20 --------
21
22 >>> d = {'a': 1, 'b': 2, 'c': 3}
23 >>> with preserve_keys(d, 'b', 'c', 'd'):
24 ... del d['a']
25 ... del d['b'] # will be reset to 2
26 ... d['c'] = None # will be reset to 3
27 ... d['d'] = 4 # will be deleted
28 ... d['e'] = 5
29 ... print(sorted(d.items()))
30 ...
31 [('c', None), ('d', 4), ('e', 5)]
32 >>> print(sorted(d.items()))
33 [('b', 2), ('c', 3), ('e', 5)]
34 """
35
36 def __init__(self, dictionary, *keys):
37 self.dictionary = dictionary
38 self.keys = keys
39
40 def __enter__(self):
41 # Actions to perform upon exiting.
42 to_delete = []
43 to_update = {}
44
45 d = self.dictionary
46 for k in self.keys:
47 if k in d:
48 to_update[k] = d[k]
49 else:
50 to_delete.append(k)
51
52 self.to_delete = to_delete
53 self.to_update = to_update
54
55 def __exit__(self, *exc_info):
56 d = self.dictionary
57
58 for k in self.to_delete:
59 d.pop(k, None)
60 d.update(self.to_update)