Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

monkey.py 2.2KB

1 year ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. # -*- test-case-name: twisted.test.test_monkey -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. class MonkeyPatcher:
  5. """
  6. Cover up attributes with new objects. Neat for monkey-patching things for
  7. unit-testing purposes.
  8. """
  9. def __init__(self, *patches):
  10. # List of patches to apply in (obj, name, value).
  11. self._patchesToApply = []
  12. # List of the original values for things that have been patched.
  13. # (obj, name, value) format.
  14. self._originals = []
  15. for patch in patches:
  16. self.addPatch(*patch)
  17. def addPatch(self, obj, name, value):
  18. """
  19. Add a patch so that the attribute C{name} on C{obj} will be assigned to
  20. C{value} when C{patch} is called or during C{runWithPatches}.
  21. You can restore the original values with a call to restore().
  22. """
  23. self._patchesToApply.append((obj, name, value))
  24. def _alreadyPatched(self, obj, name):
  25. """
  26. Has the C{name} attribute of C{obj} already been patched by this
  27. patcher?
  28. """
  29. for o, n, v in self._originals:
  30. if (o, n) == (obj, name):
  31. return True
  32. return False
  33. def patch(self):
  34. """
  35. Apply all of the patches that have been specified with L{addPatch}.
  36. Reverse this operation using L{restore}.
  37. """
  38. for obj, name, value in self._patchesToApply:
  39. if not self._alreadyPatched(obj, name):
  40. self._originals.append((obj, name, getattr(obj, name)))
  41. setattr(obj, name, value)
  42. __enter__ = patch
  43. def restore(self):
  44. """
  45. Restore all original values to any patched objects.
  46. """
  47. while self._originals:
  48. obj, name, value = self._originals.pop()
  49. setattr(obj, name, value)
  50. def __exit__(self, excType=None, excValue=None, excTraceback=None):
  51. self.restore()
  52. def runWithPatches(self, f, *args, **kw):
  53. """
  54. Apply each patch already specified. Then run the function f with the
  55. given args and kwargs. Restore everything when done.
  56. """
  57. self.patch()
  58. try:
  59. return f(*args, **kw)
  60. finally:
  61. self.restore()