import py

class remotefile(object):
    """ remotely control a file pointer using py.execnet
    """
    code = py.code.Source('''\
        fp = file(%r, %r, %r)
        try:
            while True:
                data = channel.receive()
                if data == 'close':
                    break
                elif isinstance(data, tuple):
                    callable = getattr(fp, data[0])
                    channel.send(callable(*data[1], **data[2]))
                else:
                    channel.send(getattr(fp, data))
        finally:
            fp.close()
            channel.close()
    ''')


    initcmd = 'import os; os.__fp = file(%r, %r, %r)'
    attrcmd = 'import os; channel.send(os.__fp.%s)'
    callablecmd = 'import os; channel.send(os.__fp.%s(%s))'
    closecmd = 'import os; os.__fp.close()'

    def __init__(self, address, mode='r', buffering=0,
                 gatewayclass=py.execnet.SshGateway):
        self.address = address
        self.mode = mode
        self.buffering = buffering
        self.gatewayclass = gatewayclass
        self._gateway = None
        self._channel = None

    def __getattr__(self, name):
        attr = getattr(file, name)
        c = self._initialize()
        if callable(attr):
            def handler(*args, **kwargs):
                c.send((name, args, kwargs))
                return c.receive()
            return handler
        c.send(name)
        return c.receive()

    def _initialize(self):
        c = self._channel
        if c is None:
            address, path = self.address.split(':', 1)
            self._gateway = gw = self.gatewayclass(address)
            self._channel = c = gw.remote_exec(
                str(self.code) % (path, self.mode, self.buffering))
        return c

if __name__ == '__main__':
    fp = remotefile('localhost:/tmp/foo')
    try:
        print fp.read()
    finally:
        fp.close()

