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.

crefutil.py 4.3KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. # -*- test-case-name: twisted.test.test_persisted -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. Utility classes for dealing with circular references.
  6. """
  7. from twisted.python import log, reflect
  8. from twisted.python.compat import _constructMethod
  9. class NotKnown:
  10. def __init__(self):
  11. self.dependants = []
  12. self.resolved = 0
  13. def addDependant(self, mutableObject, key):
  14. assert not self.resolved
  15. self.dependants.append((mutableObject, key))
  16. resolvedObject = None
  17. def resolveDependants(self, newObject):
  18. self.resolved = 1
  19. self.resolvedObject = newObject
  20. for mut, key in self.dependants:
  21. mut[key] = newObject
  22. def __hash__(self):
  23. assert 0, "I am not to be used as a dictionary key."
  24. class _Container(NotKnown):
  25. """
  26. Helper class to resolve circular references on container objects.
  27. """
  28. def __init__(self, l, containerType):
  29. """
  30. @param l: The list of object which may contain some not yet referenced
  31. objects.
  32. @param containerType: A type of container objects (e.g., C{tuple} or
  33. C{set}).
  34. """
  35. NotKnown.__init__(self)
  36. self.containerType = containerType
  37. self.l = l
  38. self.locs = list(range(len(l)))
  39. for idx in range(len(l)):
  40. if not isinstance(l[idx], NotKnown):
  41. self.locs.remove(idx)
  42. else:
  43. l[idx].addDependant(self, idx)
  44. if not self.locs:
  45. self.resolveDependants(self.containerType(self.l))
  46. def __setitem__(self, n, obj):
  47. """
  48. Change the value of one contained objects, and resolve references if
  49. all objects have been referenced.
  50. """
  51. self.l[n] = obj
  52. if not isinstance(obj, NotKnown):
  53. self.locs.remove(n)
  54. if not self.locs:
  55. self.resolveDependants(self.containerType(self.l))
  56. class _Tuple(_Container):
  57. """
  58. Manage tuple containing circular references. Deprecated: use C{_Container}
  59. instead.
  60. """
  61. def __init__(self, l):
  62. """
  63. @param l: The list of object which may contain some not yet referenced
  64. objects.
  65. """
  66. _Container.__init__(self, l, tuple)
  67. class _InstanceMethod(NotKnown):
  68. def __init__(self, im_name, im_self, im_class):
  69. NotKnown.__init__(self)
  70. self.my_class = im_class
  71. self.name = im_name
  72. # im_self _must_ be a NotKnown
  73. im_self.addDependant(self, 0)
  74. def __call__(self, *args, **kw):
  75. import traceback
  76. log.msg(f"instance method {reflect.qual(self.my_class)}.{self.name}")
  77. log.msg(f"being called with {args!r} {kw!r}")
  78. traceback.print_stack(file=log.logfile)
  79. assert 0
  80. def __setitem__(self, n, obj):
  81. assert n == 0, "only zero index allowed"
  82. if not isinstance(obj, NotKnown):
  83. method = _constructMethod(self.my_class, self.name, obj)
  84. self.resolveDependants(method)
  85. class _DictKeyAndValue:
  86. def __init__(self, dict):
  87. self.dict = dict
  88. def __setitem__(self, n, obj):
  89. if n not in (1, 0):
  90. raise RuntimeError("DictKeyAndValue should only ever be called with 0 or 1")
  91. if n: # value
  92. self.value = obj
  93. else:
  94. self.key = obj
  95. if hasattr(self, "key") and hasattr(self, "value"):
  96. self.dict[self.key] = self.value
  97. class _Dereference(NotKnown):
  98. def __init__(self, id):
  99. NotKnown.__init__(self)
  100. self.id = id
  101. from twisted.internet.defer import Deferred
  102. class _Defer(Deferred[object], NotKnown):
  103. def __init__(self):
  104. Deferred.__init__(self)
  105. NotKnown.__init__(self)
  106. self.pause()
  107. wasset = 0
  108. def __setitem__(self, n, obj):
  109. if self.wasset:
  110. raise RuntimeError(
  111. "setitem should only be called once, setting {!r} to {!r}".format(
  112. n, obj
  113. )
  114. )
  115. else:
  116. self.wasset = 1
  117. self.callback(obj)
  118. def addDependant(self, dep, key):
  119. # by the time I'm adding a dependant, I'm *not* adding any more
  120. # callbacks
  121. NotKnown.addDependant(self, dep, key)
  122. self.unpause()
  123. resovd = self.result
  124. self.resolveDependants(resovd)