contexts.py 1.9 KB

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