root / trunk / twisted / persisted / crefutil.py

Revision 22687, 4.5 kB (checked in by therve, 1 year ago)

Merge kill-raise-string-2063-4

Authors: jerub, therve
Reviewers: dreid, exarkun
Fixes #2063

Remove string exceptions raised in the whole twisted codebase.

The first merge added an useless dependency on tk in tests, corrected since.

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