test.py 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. from contextlib import ContextDecorator, ExitStack, contextmanager
  2. from functools import wraps
  3. from unittest.mock import patch
  4. from .useracl import get_user_acl
  5. __all__ = ["patch_user_acl"]
  6. class patch_user_acl(ContextDecorator, ExitStack):
  7. """Testing utility that patches get_user_acl results
  8. Can be used as decorator or context manager.
  9. Accepts one or two arguments:
  10. - patch_user_acl(acl_patch)
  11. - patch_user_acl(user, acl_patch)
  12. Patch should be a dict or callable.
  13. """
  14. _acl_patches = []
  15. def __init__(self, acl_patch):
  16. super().__init__()
  17. self.acl_patch = acl_patch
  18. def patched_get_user_acl(self, user, cache_versions):
  19. user_acl = get_user_acl(user, cache_versions)
  20. self.apply_acl_patches(user, user_acl)
  21. return user_acl
  22. def apply_acl_patches(self, user, user_acl):
  23. for acl_patch in self._acl_patches:
  24. self.apply_acl_patch(user, user_acl, acl_patch)
  25. def apply_acl_patch(self, user, user_acl, acl_patch):
  26. if callable(acl_patch):
  27. acl_patch(user, user_acl)
  28. else:
  29. user_acl.update(acl_patch)
  30. def __enter__(self):
  31. super().__enter__()
  32. self.enter_context(self.enable_acl_patch())
  33. self.enter_context(self.patch_user_acl())
  34. @contextmanager
  35. def enable_acl_patch(self):
  36. try:
  37. self._acl_patches.append(self.acl_patch)
  38. yield
  39. finally:
  40. self._acl_patches.pop(-1)
  41. def patch_user_acl(self):
  42. return patch(
  43. "misago.acl.useracl.get_user_acl",
  44. side_effect=self.patched_get_user_acl,
  45. )