Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 395dda1

Browse files
committed
first step toward opensource
0 parents  commit 395dda1

17 files changed

+2652
-0
lines changed

CREDITS

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
initial protocol
2+
- Sébastien Pahl <sebastien.pahl/\gmail.com>
3+
- Solomon Hykes <solomon/\dotcloud.com>
4+
5+
initial implementation
6+
- Sébastien Pahl <sebastien.pahl/\gmail.com>
7+
8+
gevent implementation
9+
- François-Xavier Bourlet <fx/\dotcloud.com>

__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# -*- coding: utf-8 -*-
2+
# Started by François-Xavier Bourlet <[email protected]>, Nov 2011.
3+
4+
from gevent_zerorpc import *

bin/zerorpc-client

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
# Started by François-Xavier Bourlet <[email protected]>, Jan 2012.
4+
5+
import argparse
6+
import json
7+
import sys
8+
import inspect
9+
from pprint import pprint
10+
11+
import zerorpc
12+
13+
14+
parser = argparse.ArgumentParser(
15+
description='Make a zerorpc call to a remote service.'
16+
)
17+
18+
client_or_server = parser.add_mutually_exclusive_group()
19+
client_or_server.add_argument('--client', action='store_true', default=True,
20+
help='remote procedure call mode (default)')
21+
client_or_server.add_argument('--server', action='store_false', dest='client',
22+
help='turn a given python module into a server')
23+
24+
parser.add_argument('--connect', action='append', metavar='address',
25+
help='specify address to connect to. Can be specified \
26+
multiple times and in conjunction with --bind')
27+
parser.add_argument('--bind', action='append', metavar='address',
28+
help='specify address to listen to. Can be specified \
29+
multiple times and in conjunction with --connect')
30+
parser.add_argument('--timeout', default=30, metavar='seconds', type=int,
31+
help='abort request after X seconds. \
32+
(default: 30s, --client only)')
33+
parser.add_argument('--heartbeat', default=5, metavar='seconds', type=int,
34+
help='heartbeat frequency. You should always use \
35+
the same frequency as the server. (default: 5s)')
36+
parser.add_argument('-j', '--json', default=False, action='store_true',
37+
help='arguments are in JSON format and will be be parsed \
38+
before being sent to the remote')
39+
parser.add_argument('-pj', '--print-json', default=False, action='store_true',
40+
help='print result in JSON format.')
41+
parser.add_argument('-?', '--inspect', default=False, action='store_true',
42+
help='retrieve detailed informations for the given \
43+
remote (cf: command) method. If not method, display \
44+
a list of remote methods signature. (only for --client).')
45+
parser.add_argument('--active-hb', default=False, action='store_true',
46+
help='enable active heartbeat. The default is to \
47+
wait for the server to send the first heartbeat')
48+
parser.add_argument('address', nargs='?', help='address to connect to. Skip \
49+
this if you specified --connect or --bind at least once')
50+
parser.add_argument('command', nargs='?',
51+
help='remote procedure to call if --client (default) or \
52+
python module/class to load if --server. If no command is \
53+
specified, a list of remote methods are displayed.')
54+
parser.add_argument('params', nargs='*',
55+
help='parameters for the remote call if --client (default)')
56+
57+
58+
def setup_links(args, socket):
59+
if args.bind:
60+
for endpoint in args.bind:
61+
print 'binding to "{0}"'.format(endpoint)
62+
socket.bind(endpoint)
63+
addresses = []
64+
if args.address:
65+
addresses.append(args.address)
66+
if args.connect:
67+
addresses.extend(args.connect)
68+
for endpoint in addresses:
69+
print 'connecting to "{0}"'.format(endpoint)
70+
socket.connect(endpoint)
71+
72+
def run_server(args):
73+
server_obj_path = args.command
74+
75+
if '.' in server_obj_path:
76+
modulepath, objname = server_obj_path.rsplit('.', 1)
77+
module = __import__(modulepath, fromlist=[objname])
78+
server_obj = getattr(module, objname)
79+
else:
80+
server_obj = __import__(server_obj_path)
81+
82+
if callable(server_obj):
83+
server_obj = server_obj()
84+
85+
server = zerorpc.Server(server_obj, heartbeat=args.heartbeat)
86+
setup_links(args, server)
87+
print 'serving "{0}"'.format(server_obj_path)
88+
return server.run()
89+
90+
# this function does a really intricate job to keep backward compatibility
91+
# with a previous version of zerorpc, and lazily retrieving results if possible...
92+
def zerorpc_inspect(client, method=None, long_doc=True, include_argspec=True):
93+
try:
94+
remote_detailled_methods = client._zerorpc_inspect(method,
95+
long_doc)['methods']
96+
97+
if include_argspec:
98+
r = [(name + (inspect.formatargspec(*argspec) if argspec else
99+
'(...)'), doc if doc else '<undocumented>') for name, argspec, doc
100+
in remote_detailled_methods]
101+
else:
102+
r = [(name, doc if doc else '<undocumented>')
103+
for name, argspec, doc in remote_detailled_methods]
104+
105+
longest_name_len = max(len(name) for name, doc in r)
106+
return (longest_name_len, r)
107+
except zerorpc.RemoteError:
108+
pass
109+
110+
if method is None:
111+
remote_methods = client._zerorpc_list()
112+
else:
113+
remote_methods = [method]
114+
115+
def remote_detailled_methods():
116+
for name in remote_methods:
117+
if include_argspec:
118+
argspec = client._zerorpc_args(name)
119+
else:
120+
argspec = None
121+
docstring = client._zerorpc_help(name)
122+
if docstring and not long_doc:
123+
docstring = docstring.split('\n', 1)[0]
124+
yield (name, argspec, docstring if docstring else '<undocumented>')
125+
126+
if not include_argspec:
127+
longest_name_len = max(len(name) for name in remote_methods)
128+
return (longest_name_len, ((name, doc) for name, argspec, doc in
129+
remote_detailled_methods()))
130+
131+
r = [(name + (inspect.formatargspec(*argspec) if argspec else '(...)'), doc)
132+
for name, argspec, doc in remote_detailled_methods()]
133+
longest_name_len = max(len(name) for name, doc in r)
134+
return (longest_name_len, r)
135+
136+
def run_client(args):
137+
client = zerorpc.Client(timeout=args.timeout, heartbeat=args.heartbeat,
138+
passive_heartbeat=not args.active_hb)
139+
setup_links(args, client)
140+
if not args.command:
141+
(longest_name_len, detailled_methods) = zerorpc_inspect(client,
142+
long_doc=False, include_argspec=args.inspect)
143+
if args.inspect:
144+
for (name, doc) in detailled_methods:
145+
print name
146+
else:
147+
for (name, doc) in detailled_methods:
148+
print '{0} {1}'.format(name.ljust(longest_name_len), doc)
149+
return
150+
if args.inspect:
151+
(longest_name_len, detailled_methods) = zerorpc_inspect(client,
152+
method=args.command)
153+
(name, doc) = detailled_methods[0]
154+
print '\n{0}\n\n{1}\n'.format(name, doc)
155+
return
156+
if args.json:
157+
call_args = [json.loads(x) for x in args.params]
158+
else:
159+
call_args = args.params
160+
results = client(args.command, *call_args)
161+
if getattr(results, 'next', None) is None:
162+
if args.print_json:
163+
json.dump(results, sys.stdout)
164+
else:
165+
pprint(results)
166+
else:
167+
# streaming responses
168+
if args.print_json:
169+
first = True
170+
sys.stdout.write('[')
171+
for result in results:
172+
if first:
173+
first = False
174+
else:
175+
sys.stdout.write(',')
176+
json.dump(result, sys.stdout)
177+
sys.stdout.write(']')
178+
else:
179+
for result in results:
180+
pprint(result)
181+
182+
def main():
183+
args = parser.parse_args()
184+
if args.bind or args.connect:
185+
if args.command:
186+
args.arguments.prepend(args.command)
187+
args.command = args.address
188+
args.address = None
189+
if args.client:
190+
return run_client(args)
191+
return run_server(args)
192+
193+
if __name__ == '__main__':
194+
exit(main())

0 commit comments

Comments
 (0)