[shpy-commit] r2840 - in shpy/trunk/dist/shpy: . net net/test
arigo@codespeak.net
arigo@codespeak.net
Mon, 19 Jan 2004 20:02:10 +0100 (MET)
Author: arigo
Date: Mon Jan 19 20:02:07 2004
New Revision: 2840
Added:
shpy/trunk/dist/shpy/net/structure.py
shpy/trunk/dist/shpy/net/test/test_structure.py
Modified:
shpy/trunk/dist/shpy/net/gateway.py
shpy/trunk/dist/shpy/net/register.py
shpy/trunk/dist/shpy/net/shared.py
shpy/trunk/dist/shpy/net/test/test_basic.py
shpy/trunk/dist/shpy/ui_pygame.py
Log:
Intermediate check-in. The basic object distribution is working nicely.
The next thing to do is use it in ui_pygame to exchange the cursor(s)
position(s) among clients.
Note that we finally dropped the idea of using pickle or marshal for
exchanging structures: just like with source code, which we send around
in text format and execute remotely, we send data representations in a
text format that you can just execute to rebuild the objects in the
other process.
Modified: shpy/trunk/dist/shpy/net/gateway.py
==============================================================================
--- shpy/trunk/dist/shpy/net/gateway.py (original)
+++ shpy/trunk/dist/shpy/net/gateway.py Mon Jan 19 20:02:07 2004
@@ -1,12 +1,12 @@
import autopath
-import threading, pickle, Queue, select
+import threading, pickle, Queue, select, StringIO
from unittest2.tool import dyncode
from shpy.net import common
class SocketGateway:
- def __init__(self, sock, ns = None):
+ def __init__(self, sock, ns = None):
if ns is None:
ns = {}
ns['gateway'] = self
Modified: shpy/trunk/dist/shpy/net/register.py
==============================================================================
--- shpy/trunk/dist/shpy/net/register.py (original)
+++ shpy/trunk/dist/shpy/net/register.py Mon Jan 19 20:02:07 2004
@@ -1,7 +1,7 @@
import autopath, os
-import inspect, socket, pickle
-from shpy.net import gateway
+import inspect, socket, pickle, thread
+from shpy.net import gateway, structure
class ServerGateway(gateway.SocketGateway):
@@ -45,6 +45,25 @@
""")
self.exec_remote("".join(l) % locals())
- def registerclient(self):
- self.import_remote('shared.py', 'shared')
+ def registerclient(self, reload=False):
+ self.import_remote('shared.py', 'shared', reload)
self.exec_remote("shared.registerclient(gateway)")
+ # import the root
+ self.waiting_for_root = thread.allocate_lock()
+ self.waiting_for_root.acquire()
+ self.exec_remote(inspect.getsource(structure))
+ self.exec_remote('''
+ lines = representeverything(shared.root)
+ lines.append('root = getstructure(%r)' % getstructureid(shared.root))
+ gateway.exec_remote('gateway.setstructure(%r)' % (lines,))
+ ''')
+ self.waiting_for_root.acquire()
+ del self.waiting_for_root
+ return self.root
+
+ def setstructure(self, lines):
+ l = {}
+ exec '\n'.join(lines) in vars(structure), l
+ if 'root' in l:
+ self.root = l['root']
+ self.waiting_for_root.release()
Modified: shpy/trunk/dist/shpy/net/shared.py
==============================================================================
--- shpy/trunk/dist/shpy/net/shared.py (original)
+++ shpy/trunk/dist/shpy/net/shared.py Mon Jan 19 20:02:07 2004
@@ -1,6 +1,8 @@
# This module is sent by the first connecting client to the server.
# It is not reloaded if it changes later!
+import pickle
+
clientlist = []
def getclientlist():
@@ -9,3 +11,16 @@
def registerclient(gw):
clientlist.append(gw)
+
+
+class Structure:
+ def __init__(self, **attributes):
+ self.__dict__.update(attributes)
+
+root = Structure()
+
+root.cells = Structure()
+cell = Structure(lines=open('/etc/passwd', 'r').read().split('\n'))
+root.cells.list = [cell]
+
+root.users = Structure()
Added: shpy/trunk/dist/shpy/net/structure.py
==============================================================================
--- (empty file)
+++ shpy/trunk/dist/shpy/net/structure.py Mon Jan 19 20:02:07 2004
@@ -0,0 +1,83 @@
+import socket, thread, time
+
+class Structure:
+
+ def __init__(self, **attributes):
+ self.__dict__.update(attributes)
+
+
+
+def represent(obj, ref):
+ if isinstance(obj, (int, float, str, unicode)):
+ return repr(obj)
+ elif isinstance(obj, dict):
+ items = ['%s: %s' % (represent(key,ref), represent(value,ref))
+ for key, value in obj.items()]
+ return '{%s}' % (', '.join(items))
+ elif isinstance(obj, tuple):
+ items = [represent(item,ref)+',' for item in obj]
+ return '(%s)' % (''.join(items))
+ elif isinstance(obj, list):
+ items = [represent(item,ref) for item in obj]
+ return '[%s]' % (','.join(items))
+ elif obj.__class__.__name__ == 'Structure': # ahem
+ ref[obj] = True
+ return 'getstructure(%r)' % getstructureid(obj)
+ else:
+ raise TypeError, 'cannot represent %r' % (obj,)
+
+
+structure2id = {}
+id2structure = {}
+maplock = thread.allocate_lock()
+hostname = socket.getfqdn()
+
+def getstructureid(structure):
+ maplock.acquire()
+ try:
+ try:
+ return structure2id[structure]
+ except KeyError:
+ structid = '%d@%s@%s' % (len(structure2id), hostname, time.time())
+ structure2id[structure] = structid
+ id2structure[structid] = structure
+ return structid
+ finally:
+ maplock.release()
+
+def getstructure(structid):
+ print "hello, i'm getstructure changing the dict id", id(id2structure)
+ maplock.acquire()
+ try:
+ try:
+ return id2structure[structid]
+ except KeyError:
+ structure = Structure()
+ structure2id[structure] = structid
+ id2structure[structid] = structure
+ return structure
+ finally:
+ maplock.release()
+
+def representstructure(structure, ref=None):
+ data = {}
+ for key, value in structure.__dict__.items():
+ if not key.startswith('_'):
+ data[key] = value
+ if ref is None:
+ ref = {}
+ return 'getstructure(%r).__dict__ = %s' % (
+ getstructureid(structure), represent(data, ref))
+
+def representeverything(root):
+ lines = []
+ pending = [root]
+ seen = {root: True}
+ for structure in pending:
+ ref = {}
+ lines.append(representstructure(structure, ref))
+ for referenced in ref:
+ if referenced not in seen:
+ pending.append(referenced)
+ seen[referenced] = True
+ return lines
Modified: shpy/trunk/dist/shpy/net/test/test_basic.py
==============================================================================
--- shpy/trunk/dist/shpy/net/test/test_basic.py (original)
+++ shpy/trunk/dist/shpy/net/test/test_basic.py Mon Jan 19 20:02:07 2004
@@ -30,7 +30,9 @@
def test_1_server_initialization():
gw = getservergateway()
- gw.exec_remote('fromgateway.exec_remote( ')
+ gw.exec_remote('gateway.exec_remote("test_1_back = 42")')
+ time.sleep(1)
+ check.equal(gw.ns['test_1_back'], 42)
#res = gw.call_synchronous(functest.f)
#check.equal(res, 42)
Added: shpy/trunk/dist/shpy/net/test/test_structure.py
==============================================================================
--- (empty file)
+++ shpy/trunk/dist/shpy/net/test/test_structure.py Mon Jan 19 20:02:07 2004
@@ -0,0 +1,17 @@
+import autopath, os, time, sys
+
+from unittest2 import check, main
+
+
+from shpy.net import shared
+from shpy.net.structure import representeverything, getstructure
+
+def test_everything():
+ lines = representeverything(shared.root)
+ shared.root.funnythings = 42
+ exec '\n'.join(lines)
+ check.false(hasattr(shared.root, 'funnythings'))
+
+
+if __name__=='__main__':
+ main()
Modified: shpy/trunk/dist/shpy/ui_pygame.py
==============================================================================
--- shpy/trunk/dist/shpy/ui_pygame.py (original)
+++ shpy/trunk/dist/shpy/ui_pygame.py Mon Jan 19 20:02:07 2004
@@ -111,7 +111,8 @@
self.cell = InputCell()
self.cursor = Cursor()
self.cursor.entercell(self.cell, (10, 10))
- self.servergateway.registerclient()
+ self.root = self.servergateway.registerclient()
+ import pdb; pdb.set_trace()
def repaint(self):
self.screen.fill((255,255,255))