Skip to content

Instantly share code, notes, and snippets.

@podhmo
Created November 7, 2020 09:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save podhmo/f025b1083c258bf4e1819f73ad004d1f to your computer and use it in GitHub Desktop.
Save podhmo/f025b1083c258bf4e1819f73ad004d1f to your computer and use it in GitHub Desktop.
import sys
from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.server import SimpleXMLRPCRequestHandler
from handofcats import as_command
# Restrict to a particular path.
class RequestHandler(SimpleXMLRPCRequestHandler):
rpc_paths = ("/RPC2",)
# Create server
@as_command
def run(port: int = 8888) -> None:
print(f"listen ... {port}", file=sys.stderr)
with SimpleXMLRPCServer(
("localhost", port), requestHandler=RequestHandler
) as server:
server.register_introspection_functions()
# Register pow() function; this will use the value of
# pow.__name__ as the name, which is just 'pow'.
server.register_function(pow)
# Register a function under a different name
def adder_function(x, y):
return x + y
server.register_function(adder_function, "add")
# Register an instance; all the methods of the instance are
# published as XML-RPC methods (in this case, just 'mul').
class MyFuncs:
def mul(self, x, y):
return x * y
server.register_instance(MyFuncs())
# Run the server's main loop
server.serve_forever()
import sys
import pathlib
import time
from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.server import SimpleXMLRPCRequestHandler
from handofcats import as_command
# Restrict to a particular path.
class RequestHandler(SimpleXMLRPCRequestHandler):
rpc_paths = ("/RPC2",)
# Create server
@as_command
def run(*, port: int = 8888, sentinel: str = "") -> None:
if sentinel:
p = pathlib.Path(sentinel)
ok = False
for wait_time in [0.1, 0.2, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4]:
if not p.exists():
print(f" wait ... {wait_time}", file=sys.stderr)
time.sleep(wait_time)
continue
print(f"ack {sentinel}", file=sys.stderr)
p.unlink()
ok = True
break
if not ok:
raise RuntimeError(f"timeout, f{sentinel}, {time.time()-st}")
print(f"listen ... {port}", file=sys.stderr)
with SimpleXMLRPCServer(
("localhost", port), requestHandler=RequestHandler
) as server:
server.register_introspection_functions()
# Register pow() function; this will use the value of
# pow.__name__ as the name, which is just 'pow'.
server.register_function(pow)
# Register a function under a different name
def adder_function(x, y):
return x + y
server.register_function(adder_function, "add")
# Register an instance; all the methods of the instance are
# published as XML-RPC methods (in this case, just 'mul').
class MyFuncs:
def mul(self, x, y):
return x * y
server.register_instance(MyFuncs())
# Run the server's main loop
server.serve_forever()
import sys
import tempfile
import pathlib
import time
import subprocess
import logging
import xmlrpc.client
import contextlib
from handofcats import as_command
logger = logging.getLogger(__name__)
def _find_free_port(host: str = "0.0.0.0") -> int:
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind((host, 0))
sock.listen(1)
name, port = sock.getsockname() # type: t.Tuple[str, int]
return port
@contextlib.contextmanager
def connect_server(*, sentinel: str, port: int):
cmd = [sys.executable, "01server.py", "--port", str(port), "--sentinel", sentinel]
server_process = subprocess.Popen(cmd)
try:
p = pathlib.Path(sentinel)
with p.open("w"):
pass
ok = False
st = time.time()
for wait_time in [0.1, 0.2, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4]:
if p.exists():
print(f" wait ... {wait_time}", file=sys.stderr)
time.sleep(wait_time)
continue
ok = True
break
if not ok:
raise RuntimeError(f"timeout, f{sentinel}, {time.time()-st}")
yield server_process
finally:
try:
server_process.terminate()
server_process.wait()
except Exception as e:
logger.info(str(e), exc_info=True)
@as_command
def run() -> None:
sentinel = tempfile.mktemp()
port = _find_free_port()
with connect_server(sentinel=sentinel, port=port):
print(f"connect ... {port}", file=sys.stderr)
s = xmlrpc.client.ServerProxy(f"http://localhost:{port}")
print(s.pow(2, 3)) # Returns 2**3 = 8
print(s.add(2, 3)) # Returns 5
print(s.mul(5, 2)) # Returns 5*2 = 10
# Print list of available methods
print(s.system.listMethods())
import sys
import pathlib
import time
import zmq
from tinyrpc.server import RPCServer
from tinyrpc.dispatch import RPCDispatcher
from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
from tinyrpc.transports.zmq import ZmqServerTransport
from handofcats import as_command
ctx = zmq.Context()
dispatcher = RPCDispatcher()
@dispatcher.public(name="add")
def adder_function(x, y):
return x + y
dispatcher.public(pow)
@dispatcher.public
def mul(x, y):
return x * y
@dispatcher.public
def list_methods():
return list(dispatcher.method_map.keys())
@as_command
def run(*, port: int = 8888, sentinel: str = "") -> None:
if sentinel:
p = pathlib.Path(sentinel)
ok = False
for wait_time in [0.1, 0.2, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4]:
if not p.exists():
print(f" wait ... {wait_time}", file=sys.stderr)
time.sleep(wait_time)
continue
print(f"ack {sentinel}", file=sys.stderr)
p.unlink()
ok = True
break
if not ok:
raise RuntimeError(f"timeout, f{sentinel}, {time.time()-st}")
print(f"listen ... {port}", file=sys.stderr)
transport = ZmqServerTransport.create(ctx, f"tcp://127.0.0.1:{port}")
rpc_server = RPCServer(transport, JSONRPCProtocol(), dispatcher)
rpc_server.serve_forever()
PORT ?= 8888
export DEBUG = 1
SENTINEL ?= xxx
00:
python $(shell echo $@*.py) --port $(PORT)
x00:
python $(shell echo $@*.py) --port $(PORT)
01:
python $(shell echo $@*.py) --port $(PORT) --sentinel=$(SENTINEL)
x01:
python $(shell echo $@*.py) --port $(PORT) --sentinel=$(SENTINEL)
# use
02:
python $(shell echo $@*.py)
03:
python $(shell echo $@*.py) --port $(PORT) --sentinel=$(SENTINEL)
x03:
python $(shell echo $@*.py)
# echo python $(shell echo $(shell echo $@ | gsed 's/^x//')*.py)
handofcats
tinyrpc
zmq
import sys
import xmlrpc.client
from handofcats import as_command
@as_command
def run(port: int = 8888) -> None:
print(f"connect ... {port}", file=sys.stderr)
s = xmlrpc.client.ServerProxy(f"http://localhost:{port}")
print(s.pow(2, 3)) # Returns 2**3 = 8
print(s.add(2, 3)) # Returns 5
print(s.mul(5, 2)) # Returns 5*2 = 10
# Print list of available methods
print(s.system.listMethods())
import sys
import time
import pathlib
import xmlrpc.client
from handofcats import as_command
@as_command
def run(port: int = 8888, sentinel: str = "") -> None:
if sentinel:
p = pathlib.Path(sentinel)
with p.open("w"):
pass
ok = False
st = time.time()
for wait_time in [0.1, 0.2, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4]:
if p.exists():
print(f" wait ... {wait_time}", file=sys.stderr)
time.sleep(wait_time)
continue
ok = True
break
if not ok:
raise RuntimeError(f"timeout, f{sentinel}, {time.time()-st}")
print(f"connect ... {port}", file=sys.stderr)
s = xmlrpc.client.ServerProxy(f"http://localhost:{port}")
print(s.pow(2, 3)) # Returns 2**3 = 8
print(s.add(2, 3)) # Returns 5
print(s.mul(5, 2)) # Returns 5*2 = 10
# Print list of available methods
print(s.system.listMethods())
from __future__ import annotations
import typing as t
import sys
import tempfile
import pathlib
import time
import subprocess
import logging
import contextlib
import zmq
from tinyrpc import RPCClient
from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
from tinyrpc.transports.zmq import ZmqClientTransport
from handofcats import as_command
logger = logging.getLogger(__name__)
def _find_free_port(host: str = "0.0.0.0") -> int:
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind((host, 0))
sock.listen(1)
name, port = sock.getsockname() # type: t.Tuple[str, int]
return port
@contextlib.contextmanager
def connect_server(
cmd: t.List[str], *, sentinel: str, port: int
) -> t.Iterator[t.subprocess.Popen]:
assert sentinel in cmd
assert str(port) in cmd
server_process = subprocess.Popen(cmd)
try:
p = pathlib.Path(sentinel)
with p.open("w"):
pass
ok = False
st = time.time()
for wait_time in [0.1, 0.2, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4]:
if p.exists():
print(f" wait ... {wait_time}", file=sys.stderr)
time.sleep(wait_time)
continue
ok = True
break
if not ok:
raise RuntimeError(f"timeout, f{sentinel}, {time.time()-st}")
yield server_process
finally:
try:
server_process.terminate()
server_process.wait()
except Exception as e:
logger.info(str(e), exc_info=True)
@as_command
def run() -> None:
ctx = zmq.Context()
port = _find_free_port()
sentinel = tempfile.mktemp()
cmd = [sys.executable, "03server.py", "--port", str(port), "--sentinel", sentinel]
with connect_server(cmd, sentinel=sentinel, port=port):
print(f"connect ... {port}", file=sys.stderr)
rpc_client = RPCClient(
JSONRPCProtocol(), ZmqClientTransport.create(ctx, f"tcp://127.0.0.1:{port}")
)
s = rpc_client.get_proxy()
print("Returns 2**3 = 8", "->", s.pow(2, 3))
print("Returns 5", "->", s.add(2, 3))
print("Returns 5*2 = 10", "->", s.mul(5, 2))
# Print list of available methods
print(s.list_methods())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment