Created
November 7, 2020 09:52
-
-
Save podhmo/f025b1083c258bf4e1819f73ad004d1f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
handofcats | |
tinyrpc | |
zmq |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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