-
-
Save mara004/c1ad00953cf9f4946f45b6dcc9d4778e to your computer and use it in GitHub Desktop.
Reset global state
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import enum | |
| import functools | |
| class _VoidClass (enum.Enum): | |
| # enum attributes are actually transformed to instances of the enum class, so the methods below apply to the attribute. | |
| VOID = enum.auto() | |
| def __str__(self): | |
| return "VOID" | |
| __repr__ = __str__ | |
| def __bool__(self): | |
| return False | |
| # Placeholder to indicate absence of a value where None is ambiguous. | |
| # In this case, we need to be able to either reset a variable to None or delete it, so we need another unambiguous indicator for deletion. To avoid new ambiguity, this instance should not be used by the caller except in @reset_globals(). | |
| VOID = _VoidClass.VOID | |
| class reset_globals: | |
| def __init__(self, **kwargs): | |
| self._deletes = tuple(k for k, v in kwargs.items() if v is VOID) | |
| for k in self._deletes: | |
| del kwargs[k] | |
| self._resets = kwargs | |
| def _resethook(self): | |
| for d in self._deletes: | |
| del globals()[d] | |
| globals().update(self._resets) | |
| def __call__(self, func): | |
| @functools.wraps(func) | |
| def wrapped(*args, **kwargs): | |
| try: | |
| return func(*args, **kwargs) | |
| finally: | |
| self._resethook() | |
| return wrapped | |
| if __name__ == "__main__": | |
| @reset_globals(A=0, B="", C=VOID) | |
| def test(): | |
| global A, B, C | |
| A = 1 | |
| B = "test" | |
| C = None | |
| print(f"A, B, C = {A, B, C}") | |
| test() | |
| print(f"A, B = {A, B}") | |
| try: | |
| print(C) | |
| except NameError: | |
| print("C is unset") | |
| else: | |
| assert False, "C is not unset" |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Alternatively, take
reset: dict, delete: tupledirectly. Would avoid theVOIDsingleton and may be cleaner internally.However, I tend to prefer the flat syntax.