Remoting - the Python way
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.
Paweł Płazieński 48a2629260 Merge branch 'master' of git@github.com:nivertius/remoteable.git 8 years ago
.coveragerc more tests; coveragerc 8 years ago
LICENSE initial commit 8 years ago
README.rst attach and browse documentation 8 years ago
__init__.py pylint suggested changes 8 years ago
capsule.py Merge branch 'master' of git@github.com:nivertius/remoteable.git 8 years ago
client.py Merge branch 'master' of git@github.com:nivertius/remoteable.git 8 years ago
command.py datetime and timedelta handled in capsules; some comparition operators; test fixes 8 years ago
response.py unicode evaluation 8 years ago
serializable.py some YAGNI principle application; __all__ defined 8 years ago
server.py pylint suggested changes 8 years ago
tests.py Merge branch 'master' of git@github.com:nivertius/remoteable.git 8 years ago

README.rst

============
remoteable
============

This library provides remoting in python-friendly way. It allows user to create a server, which holds and manages objects, and a client, which can remotely act upon these objects.

**Warning** this is still work-in-progress, but no API changes are foreseen.

How to use it?
--------------

Consider following simple tree-building class::

class Node(object):
def __init__(self, value, parent = None):
self.value = value
self.parent = parent
self._children = []

def child(self, index):
return self._children[index]

def add_child(self, node):
if node.parent is not None:
node.parent.remove_child(node)
node.parent = self
self._children.append(node)

def remove_node(self, node):
self._children.remove(node)

First, we need to setup a *server*, a remoting provider, where all the objects will exist::

>>> from remoteable.server import RemotingServer
>>> server = RemotingServer(('localhost', 3000))

Server will immediately bind and listen on specified host/port pair, but it won't accept connections. It needs to be started::

>>> server.run()

This call will block. Other threads can stop the server by calling ``server.stop``. If you want a background server, use ThreadedRemotingServer, which inherits Thread.

Let us create some class instances::

>>> root = Node(1)
>>> child = Node(2)
>>> root.add_child(child)

We can export those instances with ``server.export``. Remote name is arbitrary, this is a string that clients will send to gain access to exported object::

>>> server.export(root, remote_name = 'root')
>>> server.export(child, remote_name = 'child')

Any kind of object can be exported::

>>> server.export(Node, remote_name = 'Node')
>>> server.export(5, remote_name = 'five')

You can see exported remotes by executing ``server.browse``::

>>> server.browse()
set('root', 'child', 'Node', 'five') # order may vary

Next step to use these objects is to setup client::

>>> from remoteable.client import RemotingClient
>>> client = RemotingClient(('localhost', 3000))

Client will immediately connect and will be ready to fetch handles::

>>> client_root = client.fetch('root')
>>> client_root
<RemoteHandle (d0d7177e-22f6-4476-9ed9-cec060fc7c79)> # may vary

Clients can also browse for handles, but besides existing name, no further information can be obtained about the exported objects::

>>> client.browse()
set('root', 'child', 'Node', 'five') # order may vary

Fetched handle is a simple, pythonic object which delegates all operations to a remote instance. There is a lot of implemented operations which can be simply done like:

- dereferencing an attribute
>>> client_value = client_root.value
>>> client_value
<RemoteHandle (bd8c80ab-b183-401a-b7c2-9e3ee5c82d9a)> # may vary

- casting to simple types
>>> int(client_value)
1
>>> str(client_value)
'1'

- setting attribute
>>> client_root.value = 4
>>> int(client_root.value)
4

- calling function (method)
>>> child = client_root.child(0)
>>> child
<RemoteHandle (3ba4ba04-a6ec-41d7-818d-60d8a5388c74)> # may vary
>>> int(child.value)
2

- basic two argument operations
>>> int(child.value + 4)
6

- comparation
>>> result = (child == client_root.child(0))
>>> result
<RemoteHandle (2a33e675-a18e-4acb-b360-dcad69858638)>
>>> bool(result)
True

...and more.

Remember, that remote object always stays remote, beside simple evaluation, it can never be transmitted over to the client.

Client can also store values on server::

>>> reference = client.store(5)
>>> reference
<RemoteHandle (ded685b6-3d3f-4fd9-96be-7d72b09a9a22)>
>>> int(reference)
5

And also clients can attach objects, that is, client can request that handle he has should be exported with some name:

>>> client.attach(reference, 'exported_by_client')
>>> second_reference = client.fetch('exported_by_client')
>>> bool(second_reference == reference)
True
>>> client.browse()
set('root', 'child', 'node', 'five', 'exported_by_client') # order may vary

Handles can be provided as an argument for operations with other handles::

>>> client_root.value = reference
>>> int(client_root.value)
5