• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.9.5/pyobjc-42/pyobjc/pyobjc-core/Examples/NonFunctional/RemotePyInterpreter/
1import types, itertools, exceptions
2
3def type_string(obj):
4    objType = type(obj)
5    if objType is types.InstanceType:
6        objType = obj.__class__
7    return getattr(objType, '__module__', '-') + '.' + objType.__name__
8
9class NetRepr(object):
10    def __init__(self, objectPool):
11        self.objectPool = objectPool
12        self.cache = {}
13        self._identfactory = itertools.count()
14
15    def clear(self):
16        self.cache.clear()
17        self._identfactory = itertools.count()
18
19    def netrepr_tuple(self, obj):
20        return repr(tuple(itertools.imap(self.netrepr, obj)))
21
22    def netrepr_list(self, obj):
23        return repr(map(self.netrepr, obj))
24
25    def netrepr_exception(self, e):
26        cls = e.__class__
27        if cls.__module__ == 'exceptions':
28            rval = cls.__name__ + self.netrepr_tuple(e.args)
29        else:
30            rval = 'Exception(%r)' % ('[Remote] %s.%s %s' % (cls.__module__, cls.__name__, e),)
31        return rval
32
33    def netrepr(self, obj):
34        if obj is None:
35            return 'None'
36        objtype = type(obj)
37        if objtype is int or objtype is long or objtype is float:
38            return repr(obj)
39        elif objtype is str or objtype is unicode:
40            if True:
41                return repr(obj)
42            else:
43                # "intern" these
44                obj_id = id(obj)
45                cached = self.get(cache, obj_id, None)
46                if cached is None:
47                    ident = self._identfactory.next()
48                    self.cache[obj_id] = '__cached__(%r)' % (obj_id,)
49                    cached = '__cache__(%r, %r)' % (obj_id, obj)
50                return cached
51        return self.netrepr_default(obj)
52
53    def netrepr_default(self, obj):
54        method = getattr(obj, '__netrepr__', None)
55        if method is None:
56            method = self.objectPool.referenceForObject(obj).__netrepr__
57        return method()
58
59
60class BaseObjectPool(object):
61    def __init__(self):
62        self.idents = {}
63        self.refs = {}
64        self.pools = []
65
66    def referenceForIdent(self, ident):
67        return self.idents[ident]
68
69    def base_alloc(self, ref, ident):
70        self.refs[ref] = ident
71        self.idents[ident] = ref
72
73    def base_dealloc(self, ref, ident):
74        del self.refs[ref]
75        del self.idents[ident]
76
77    def autorelease(self, ref):
78        if not self.pools:
79            raise RuntimeError, "no autoreleasepool for %r" % (ref,)
80        pool = self.pools[-1]
81        pool[ref] = pool.get(ref, 0) + 1
82
83    def push(self):
84        #print "pushed pool"
85        self.pools.append({})
86
87    def pop(self):
88        if not self.pools:
89            raise RuntimeError, "popped too many pools"
90        #print "popped pool"
91        pool = self.pools.pop()
92        for ref, count in pool.iteritems():
93            ref.release(count)
94
95    def referenceForObject(self, obj):
96        raise TypeError, "Can not create a reference to %r, the bridge is unidirectional" % (obj,)
97
98
99class RemoteObjectPool(BaseObjectPool):
100    def __init__(self, writecode):
101        BaseObjectPool.__init__(self)
102        self.writecode = writecode
103        self.namespace = {
104            'None': None,
105            '__ref__': self.referenceForRemoteIdent,
106        }
107
108    def referenceForRemoteIdent(self, ident, type_string):
109        rval = self.idents.get(ident)
110        if rval is None:
111            rval = RemoteObjectReference(self, ident, type_string)
112        return rval
113
114
115class ObjectPool(BaseObjectPool):
116    def __init__(self):
117        BaseObjectPool.__init__(self)
118        self._identfactory = itertools.count()
119        self.obj_ids = {}
120        self.namespace = {
121            '__obj__': self.objectForIdent,
122        }
123
124    def object_alloc(self, ref, obj_id):
125        self.obj_ids[obj_id] = ref
126
127    def object_dealloc(self, ref, obj_id):
128        del self.obj_ids[obj_id]
129
130    def objectForIdent(self, ident):
131        return self.referenceForIdent(ident).obj
132
133    def referenceForObject(self, obj):
134        obj_id = id(obj)
135        rval = self.obj_ids.get(obj_id)
136        if rval is None:
137            ident = self._identfactory.next()
138            rval = ObjectReference(self, ident, type_string(obj), obj, obj_id)
139            rval = rval.alloc().autorelease()
140        return rval
141
142
143class BaseObjectReference(object):
144    def __init__(self, objectPool, ident, type_string):
145        self.ident = ident
146        self.type_string = type_string
147        self.objectPool = objectPool
148        self.retainCount = 1
149
150    def retain(self, count=1):
151        #print "%r.retain(%d)" % (self, count)
152        self.retainCount += count
153        return self
154
155    def alloc(self):
156        self.objectPool.base_alloc(self, self.ident)
157        return self
158
159    def dealloc(self):
160        self.objectPool.base_dealloc(self, self.ident)
161        self.retainCount = -1
162
163    def release(self, count=1):
164        #print "%r.release(%d)" % (self, count)
165        newCount = self.retainCount - count
166        #print "  newCount = %d" % (newCount,)
167        if newCount == 0:
168            self.dealloc()
169        elif newCount < 0:
170            raise ValueError, "Reference %r over-released (%r -> %r)" % (self, self.retainCount, newCount)
171        self.retainCount = newCount
172        return self
173
174    def autorelease(self):
175        #print "%s.autorelease()" % (self,)
176        self.objectPool.autorelease(self)
177        return self
178
179    def __repr__(self):
180        return "%s(%r, %r)" % (type(self).__name__, self.ident, self.type_string)
181
182
183class RemoteObjectReference(BaseObjectReference):
184    def __netrepr__(self):
185        return "__obj__(%r)" % (self.ident,)
186
187
188class ObjectReference(BaseObjectReference):
189    def __init__(self, objectPool, ident, type_string, obj, obj_id):
190        BaseObjectReference.__init__(self, objectPool, ident, type_string)
191        self.obj = obj
192        self.obj_id = id(obj)
193
194    def alloc(self):
195        self = BaseObjectReference.alloc(self)
196        self.objectPool.object_alloc(self, self.obj_id)
197        return self
198
199    def dealloc(self):
200        self.objectPool.object_dealloc(self, self.obj_id)
201        self.obj = None
202        self.obj_id = -1
203        BaseObjectReference.dealloc(self)
204
205    def __netrepr__(self):
206        return "__ref__(%r, %r)" % (self.ident, self.type_string)
207
208
209def test_netrepr():
210    import compiler
211    pool = ObjectPool()
212    pool.push()
213    netrepr = NetRepr(pool).netrepr
214    assert netrepr("foo") == repr("foo")
215    ref = pool.referenceForObject(object)
216    assert ref.obj is object
217    assert ref is pool.referenceForObject(object)
218    assert ref.retainCount == 1
219    refrepr = netrepr(ref)
220    assert refrepr == netrepr(ref)
221    ref.retain()
222    assert ref.retainCount == 2
223    pool.pop()
224    pool.push()
225    assert ref.retainCount == 1
226    def __ref__(ident, type_string):
227        return pool.referenceForIdent(ident)
228    netref = eval(refrepr)
229    assert netref is ref
230    assert netref.obj is object
231    ref.release()
232    pool.pop()
233    assert ref.obj is None
234