def launch(root: str = None, host: str = None, port: int = None): host = host or environ.rpc_host port = port or environ.rpc_port if root: environ.root = root python_path = textwrap.indent("\n".join(filter(None, sys.path)), " " * 12) logger.info(f"Launching RPC: {host}:{port}") logger.info(f"KB Root Path : {environ.root}") logger.info(f"Python Path :\n{python_path}") serve({ServerKB: "kb"}, use_ns=False, host=host, port=port, verbose=False)
class SessionInstance(object): @expose def msg(self, message): print("[%s] %s.msg: %s" % (id(self), self.__class__.__name__, message)) return id(self), self.correlation_id @classmethod def create_instance(cls): obj = cls() obj.correlation_id = current_context.correlation_id return obj @behavior(instance_mode="percall") class PercallInstance(object): @expose def msg(self, message): print("[%s] %s.msg: %s" % (id(self), self.__class__.__name__, message)) return id(self) if __name__ == "__main__": # please make sure a name server is running somewhere first. serve( { SingleInstance: "instance.single", SessionInstance: "instance.session", PercallInstance: "instance.percall" }, verbose=True)
@expose class Streamer(object): def list(self): return [1, 2, 3, 4, 5, 6, 7, 8, 9] def iterator(self): return iter([1, 2, 3, 4, 5, 6, 7, 8, 9]) def generator(self): i = 1 while i < 10: yield i i += 1 def slow_generator(self): i = 1 while i < 10: time.sleep(0.5) yield i i += 1 def fibonacci(self): a, b = 0, 1 while True: yield a a, b = b, a + b serve({Streamer: "example.streamer"}, use_ns=False)
self.number = number self.callback = callback print("Worker %d created" % self.number) @expose @oneway def work(self, amount): print("Worker %d busy..." % self.number) time.sleep(amount) print("Worker %d done. Informing callback client." % self.number) self._pyroDaemon.unregister(self) self.callback._pyroClaimOwnership( ) # because this method may run in a different thread every time it's called self.callback.done(self.number) # invoke the callback object class CallbackServer(object): def __init__(self): self.number = 0 @expose def addworker(self, callback): self.number += 1 print("server: adding worker %d" % self.number) worker = Worker(self.number, callback) self._pyroDaemon.register(worker) # make it a Pyro object return worker serve({CallbackServer: "example.callback"})
from Pyro5.api import expose, serve from thingy import Thingy @expose class Factory(object): def createSomething(self, number): # create a new item thing = Thingy(number) # connect it to the Pyro daemon to make it a Pyro object self._pyroDaemon.register(thing) # Return it. Pyro's autoproxy feature turns it into a proxy automatically. # If that feature is disabled, the object itself (a copy) is returned, # and the client won't be able to interact with the actual Pyro object here. return thing serve({Factory: "example.autoproxy"}, use_ns=False)
return self.callcount # the number of completed calls def getconfig(self): return config.as_dict() def delay(self): threadname = threading.current_thread().getName() print("delay called in thread %s" % threadname) time.sleep(1) self.callcount += 1 return threadname @oneway def onewaydelay(self): threadname = threading.current_thread().getName() print("onewaydelay called in thread %s" % threadname) time.sleep(1) self.callcount += 1 # main program config.SERVERTYPE = "undefined" servertype = input("Servertype threaded or multiplex (t/m)?") if servertype == "t": config.SERVERTYPE = "thread" else: config.SERVERTYPE = "multiplex" serve({Server: "example.servertypes"})
self.resultqueue = queue.Queue() def putWork(self, item): self.workqueue.put(item) def getWork(self, timeout=5): try: return self.workqueue.get(block=True, timeout=timeout) except queue.Empty: raise ValueError("no items in queue") def putResult(self, item): self.resultqueue.put(item) def getResult(self, timeout=5): try: return self.resultqueue.get(block=True, timeout=timeout) except queue.Empty: raise ValueError("no result available") def workQueueSize(self): return self.workqueue.qsize() def resultQueueSize(self): return self.resultqueue.qsize() # main program serve({DispatcherQueue: "example.distributed.dispatcher"})
from Pyro5.api import expose, behavior, serve @expose @behavior(instance_mode="single") class Warehouse(object): def __init__(self): self.contents = ["chair", "bike", "flashlight", "laptop", "couch"] def list_contents(self): return self.contents def take(self, name, item): self.contents.remove(item) print("{0} took the {1}.".format(name, item)) def store(self, name, item): self.contents.append(item) print("{0} stored the {1}.".format(name, item)) serve({Warehouse: "example.warehouse"}, use_ns=False)
from Pyro5.api import behavior, expose, locate_ns, serve, config from diffiehellman import DiffieHellman config.SERVERTYPE = "multiplex" ns = locate_ns() @behavior(instance_mode="session") class KeyExchange(object): def __init__(self): print("New KeyExchange, initializing Diffie-Hellman") self.dh = DiffieHellman(group=14) @expose def exchange_key(self, other_public_key): print("received a public key, calculating shared secret...") self.dh.make_shared_secret_and_key(other_public_key) print("shared secret key = ", self.dh.key.hex()) return self.dh.public_key serve({KeyExchange: "example.dh.keyexchange"}, use_ns=True)
self.collection.discard(self) @expose @behavior(instance_mode="single") class Service(object): def __init__(self): self.resources = set() # the allocated resources def allocate(self, name): resource = Resource(name, self.resources) self.resources.add(resource) current_context.track_resource(resource) print("service: allocated resource", name, " for client", current_context.client_sock_addr) def free(self, name): resources = {r for r in self.resources if r.name == name} self.resources -= resources for r in resources: r.close() current_context.untrack_resource(r) def list(self): return [r.name for r in self.resources] with CustomDaemon() as daemon: serve({ Service: "service" }, use_ns=False, daemon=daemon)
self.sub = {"name": "value"} self.value = 42 self._value = 123 self.__value = 999 def __dunder__(self): return "yep" def __len__(self): return 200 def getValue(self): return self.value @property def prop_value(self): return self.value @prop_value.setter def prop_value(self, value): self.value = value @property def prop_sub(self): return self.sub serve({ Thingy: "example.attributes" }, use_ns=False)
fmt = '%Y-%m-%d %H:%M:%S %Z%z' @expose class Server(object): def echo(self, date): print("ECHO:") print(" [raw] ", repr(date)) if hasattr(date, "isoformat"): print(" [iso] ", date.isoformat()) return date def pytz(self): tz_nl = pytz.timezone("Europe/Amsterdam") return tz_nl.localize(datetime.datetime.now()) def dateutil(self): tz_nl = dateutil.tz.gettz("Europe/Amsterdam") return datetime.datetime.now(tz_nl) def pendulum(self): tz_nl = pendulum.now("Europe/Amsterdam") return tz_nl # main program serve({ Server: "example.timezones" }, use_ns=False)
pool.submit(self.count_chunk, next(roundrobin_counters), chunk)) # gather the results print("Collecting %d results (counted in parallel)..." % len(tasks)) totals = Counter() for task in futures.as_completed(tasks): try: totals.update(task.result()) except Pyro5.errors.CommunicationError as x: raise Pyro5.errors.PyroError( "Something went wrong in the server when collecting the responses: " + str(x)) return totals if __name__ == "__main__": print("Spinning up 5 word counters, and 1 dispatcher.") config.SERVERTYPE = "thread" serve( { WordCounter(): "example.dc2.wordcount.1", WordCounter(): "example.dc2.wordcount.2", WordCounter(): "example.dc2.wordcount.3", WordCounter(): "example.dc2.wordcount.4", WordCounter(): "example.dc2.wordcount.5", Dispatcher: "example.dc2.dispatcher" }, verbose=False)
file_content = f.read() return file_content def upload_file(self, username, file, data): #upload a file from client to server in user folder. outfile = os.path.join(username, file) # print(data) data = serpent.tobytes(data) # print(data) with open(outfile, "wb") as f: f.write(data) def iterator(self, size): chunksize = size//100 print("sending %d bytes via iterator, chunks of %d bytes" % (size, chunksize)) data = b"x" * size i = 0 while i < size: yield data[i:i+chunksize] i += chunksize serve( { Dropbox: "dropbox" }, use_ns=True)
return "A ação {0} foi adicionada a sua lista de cotações".format(code) def removeStockToQuoteList(self, code): stockToRemove = self.findStock(code) if(not stockToRemove): return "Ação não encontrada!" self.quoteList.remove(self.findStock(code)) return "A ação {0} foi removida a sua lista de cotações".format(code) def getQuoteList(self): return self.quoteList def findStock(self, code): for stock in self.stocks: if(stock['code'] == code): return stock def findOrderBuy(self, id): for order in self.bookBuy: if(order['id'] == id): return order def findOrderSell(self, id): for order in self.bookSell: if(order['id'] == id): return order serve({ CallbackServer: "home.broker.server" })
from collections import defaultdict from Pyro5.api import behavior, expose, serve # note: the dispatcher doesn't know anything about the CustomData class from the customdata module! @behavior(instance_mode="single") class Dispatcher(object): def __init__(self): self.listeners = defaultdict(list) @expose def register(self, topic, listener): self.listeners[topic].append(listener) print("New listener for topic {} registered: {}".format( topic, listener._pyroUri)) @expose def process_blob(self, blob): print("Dispatching blob with name:", blob.info) listeners = self.listeners.get(blob.info, []) for listener in listeners: listener._pyroClaimOwnership( ) # because this process_blob call may run in a different thread every time it is invoked listener.process_blob(blob) serve({Dispatcher: "example.blobdispatcher"})
def payCart(self, cart, name=None): receipt = [] if name: receipt.append("Receipt for %s." % name) receipt.append("Receipt Date: " + time.asctime()) total = 0.0 for item in cart.getContents(): price = self.inventory[item] total += price receipt.append("%13s %.2f" % (item, price)) receipt.append("") receipt.append("%13s %.2f" % ("total:", total)) cart.empty() return "\n".join(receipt) def leave(self, name): print("Customer %s leaves." % name) cart = self.customersInStore[name] print(" their shopping cart contains: %s" % cart.getContents()) if cart.getContents(): print(" it is not empty, they are trying to shoplift!") raise Exception("attempt to steal a full cart prevented") # delete the cart and unregister it with pyro del self.customersInStore[name] self._pyroDaemon.unregister(cart) # main program serve({Shop: "example.shop"})
from Pyro5.api import expose, behavior, serve @expose @behavior(instance_mode="single") class Warehouse(object): def __init__(self): self.contents = ["chair", "bike", "flashlight", "laptop", "couch"] def list_contents(self): return self.contents def take(self, name, item): self.contents.remove(item) print("{0} took the {1}.".format(name, item)) def store(self, name, item): self.contents.append(item) print("{0} stored the {1}.".format(name, item)) serve({Warehouse: "example.warehouse"}, use_ns=True)
import logging from Pyro5.api import expose, serve, config logging.basicConfig(level=logging.DEBUG) logging.getLogger("Pyro5").setLevel(logging.DEBUG) config.COMMTIMEOUT = 5.0 config.POLLTIMEOUT = 5.0 # only used for multiplexing server class TestDisconnect(object): @expose def echo(self, arg): print("echo: ", arg) return arg serve({TestDisconnect: "example.disconnect"}, use_ns=False)
import time import threading from Pyro5.api import expose, oneway, behavior, serve @expose @behavior("single") class Server(object): def __init__(self): self.counter = 0 @oneway def increment_oneway(self): print("oneway call executing in thread", threading.get_ident()) time.sleep(0.5) self.counter += 1 def increment(self): time.sleep(0.5) self.counter += 1 def getcount(self): return self.counter print("main thread:", threading.get_ident()) serve({Server: "example.oneway2"})
print('IGNORED UNKNOWN CHANNEL %s' % channel) return for (n, c) in self.channels[channel]: if n == nick: self.channels[channel].remove((n, c)) break self.publish(channel, 'SERVER', '** ' + nick + ' left **') if len(self.channels[channel]) < 1: del self.channels[channel] print('REMOVED CHANNEL %s' % channel) self.nicks.remove(nick) print("%s LEFT %s" % (nick, channel)) def publish(self, channel, nick, msg): if channel not in self.channels: print('IGNORED UNKNOWN CHANNEL %s' % channel) return for (n, c) in self.channels[channel][:]: # use a copy of the list c._pyroClaimOwnership() try: c.message(nick, msg) # oneway call except Pyro5.errors.ConnectionClosedError: # connection dropped, remove the listener if it's still there # check for existence because other thread may have killed it already if (n, c) in self.channels[channel]: self.channels[channel].remove((n, c)) print('Removed dead listener %s %s' % (n, c)) serve({ChatBox: "example.chatbox.server"})
from Pyro5.api import Daemon, serve import excep def my_error_handler(daemon, client_sock, method, vargs, kwargs, exception): print("\nERROR IN METHOD CALL USER CODE:") print(" client={} method={} exception={}".format(client_sock, method.__qualname__, repr(exception))) daemon = Daemon() daemon.methodcall_error_handler = my_error_handler serve({excep.TestClass: "example.exceptions"}, daemon=daemon, use_ns=True, verbose=True)
import time from Pyro5.api import expose, serve @expose class Thingy(object): def multiply(self, a, b): return a * b def add(self, a, b): return a + b def divide(self, a, b): return a // b def error(self): return 1 // 0 def delay(self, seconds): time.sleep(seconds) return seconds def printmessage(self, message): print(message) return 0 serve({ Thingy: "example.batched" }, use_ns=False)
import serpent from Pyro5.api import expose, serve, config import Pyro5.socketutil class Testclass(object): @expose def transfer(self, data): if config.SERIALIZER == "serpent" and type(data) is dict: data = serpent.tobytes(data) # in case of serpent encoded bytes print("received %d bytes" % len(data)) return len(data) @expose def download_chunks(self, size): print("client requests a 'streaming' download of %d bytes" % size) data = bytearray(size) i = 0 chunksize = 200000 print(" using chunks of size", chunksize) while i < size: yield data[i:i + chunksize] i += chunksize serve({Testclass: "example.hugetransfer"}, host=Pyro5.socketutil.get_ip_address("localhost", workaround127=True), use_ns=False, verbose=True)
from Pyro5.api import expose, serve, config @expose class CalcServer(object): def add(self, num1, num2): print("calling add: %d, %d" % (num1, num2)) return num1 + num2 config.COMMTIMEOUT = 0.5 # the server should time out easily now serve({CalcServer: "example.autoretry"})
def otherthingy_dict_to_class(classname, d): print("{deserializer hook, converting to class: %s}" % d) return mycustomclasses.OtherThingy(d["number"]) # for 'Thingy' we register both serialization and deserialization hooks register_dict_to_class("waheeee-custom-thingy", thingy_dict_to_class) register_class_to_dict(mycustomclasses.Thingy, thingy_class_to_dict) # for 'OtherThingy' we only register a deserialization hook (and for serialization depend on serpent's default behavior) register_dict_to_class("mycustomclasses.OtherThingy", otherthingy_dict_to_class) # regular Pyro server stuff @expose class Server(object): def method(self, arg): print("\nmethod called, arg=", arg) response = mycustomclasses.Thingy(999) return response def othermethod(self, arg): print("\nothermethod called, arg=", arg) response = mycustomclasses.OtherThingy(999) return response serve({Server: "example.customclasses"}, use_ns=False)
@behavior(instance_mode="session") @expose class SessionboundDatabase(object): """ This pyro object will work fine when used from multiple proxies at the same time because you'll get a new instance for every new session (proxy connection) """ def __init__(self): # get the user-token from the USER annotation user_annotation = current_context.annotations["USER"] user = bytes(user_annotation).decode("utf-8") self.connection = database.connect(user) print("[%s] new instance and connection for user: %s" % (self.__class__.__name__, user)) def store(self, key, value): self.connection.store(key, value) def retrieve(self, key): return self.connection.retrieve(key) def ping(self): return "hi" serve({ SingletonDatabase: "example.usersession.singletondb", SessionboundDatabase: "example.usersession.sessiondb" })