Package: singyeong.py
신경.pyAn asynchronous client library for신경, a dynamic metadata-oriented service mesh.WARNINGIf 신경 is alpha quality software, then Singyeong.py is pre-alpha quality software. Expect things to break spectacularly.InstallingYou can get the library directly from PyPI:python3-mpipinstall-Usingyeong.pyIf you are using Windows, then the following should be used instead:py-3-mpipinstall-Usingyeong.pyInstall with faster json supportpipinstallsingyeong.py[ujson]Install with msgpack supportpipinstallsingyeong.py[msgpack]Event ReferenceThis section outlines the different types of events listened by Client.How to register event?There are two ways to register an event, the first way is through the use of Client.event().importsingyeongclient=singyeong.Client("singyeong://receiver@localhost:4567")@client.eventasyncdefon_ready():print('Ready!')The second way is through subclassing Client and overriding the specific events. For example:importsingyeongclassSingyeongClient(singyeong.Client):asyncdefon_raw_packet(self,message):print(message.payload)client=SingyeongClient("singyeong://receiver@localhost:4567")If an event handler raises an exception, on_error() will be called to handle it, which defaults to print a traceback and ignoring the exception.List of available eventsClient.on_ready()Called when the 신경 has accepted you, and will send you packets. Usually after login is successful.Client.on_raw_packet(message)Called when the 신경 has sent to you BROADCAST or SEND event. Example below shows how to get all data from the packet:importsingyeongclient=...@client.eventasyncdefon_raw_packet(message:singyeong.Message):nonce=message.nonce# Optional nonce, used by clients for req-res queriespayload=message.payload# Whatever data you want to passtimestamp=message.timestamp# Timestamp of the packet when it was sent on the server. Can be used for ex. latency calculationsevent_name=message.event_name# May be "BROADCAST" or "SEND"Client.on_error()Usually when an event raises an uncaught exception, a traceback is printed to stderr and the exception is ignored.importtracebackdefon_error(exc):traceback.print_exc()If you want to change this behaviour and handle the exception for whatever reason yourself, this event can be overridden. Which, when done, will suppress the default action of printing the traceback.Sending dataimportsingyeongclient=...asyncdeffunc():target=singyeong.Target(application="application id here",restricted=True,key="1234567890",droppable=True,optional=True,selector=singyeong.Minimum("key"),operators=[singyeong.Equal("/key","value"),singyeong.LessThanEqual("/key2",1234),singyeong.And(singyeong.GreaterThan("/key3",10),singyeong.LessThan("/key3",20),),singyeong.In("/key4",["123","456"])],)payload={"foo":"bar"}awaitclient.send(target,payload)# or await client.broadcast(...)Keyword arguments for singyeong.Target():application: ID of the application to query againstrestricted: Whether or not to allow restricted-mode clients in the query resultskey: The key used for consistent-hashing when choosing a client from the outputdroppable: Whether or not this payload can be dropped if it isn't routableoptional: Whether or not this query is optional, ie. will be ignored and a client
will be chosen randomly if it matches nothing.selector: The selector used. May be None.operators: The ops used for querying.Available operatorsComparisonOperator(path, to)singyeong.Equal(...)singyeong.NotEqual(...)singyeong.GreaterThan(...)singyeong.GreaterThanEqual(...)singyeong.LessThan(...)singyeong.LessThanEqual(...)singyeong.In(...)singyeong.Contains(...)singyeong.NotContains(...)LogicalOperator(comparison_op1, comparison_op2, comparison_op3, ... )singyeong.And(...)singyeong.Or(...)singyeong.Nor(...)Available selectorssingyeong.Minimum(name)singyeong.Maximum(name)singyeong.Average(name)Run 신경 clientYou can run 신경 client in the main loop or in the separate task (if you have e.g. discord.py running).Running 신경 in the loop (recommended)importsingyeongclient=singyeong.Client("dsn")...client.run()Running 신경 in the backgroundimportsingyeongimportasyncioloop=asyncio.get_event_loop()client=singyeong.Client("dsn")...singyeong_task=loop.create_task(client.connect())try:loop.run_until_complete(main())# <- Your async function herefinally:singyeong_task.cancel()loop.run_until_complete(asyncio.gather(singyeong_task,return_exceptions=True))Running 신경 along with discord.pyIn some cases, it is not required to manually close the task. E.g. discord.py automatically closes all tasks gracefully on the shutdown.importdiscordimportsingyeongimportasyncioloop=asyncio.get_event_loop()bot=discord.Client()client=singyeong.Client("dsn")...loop.create_task(client.connect())bot.run("token")Logging신경.py logs errors and debug information via theloggingpython
module. It is strongly recommended that the logging module is
configured, as no errors or warnings will be output if it is not set up.
Configuration of theloggingmodule can be as simple as:importlogginglogging.basicConfig(level=logging.INFO)Placed at the start of the application. This will output the logs from
discord as well as other libraries that use theloggingmodule
directly to the console.The optionallevelargument specifies what level of events to log
out and can be any ofCRITICAL,ERROR,WARNING,INFO, andDEBUGand if not specified defaults toWARNING.More advanced setups are possible with theloggingmodule. For
example to write the logs to a file callederror.loginstead of
outputting them to the console the following snippet can be used:importlogginglogger=logging.getLogger("singyeong")logger.setLevel(logging.ERROR)handler=logging.FileHandler(filename="error.log",encoding="utf-8",mode="w")handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s:%(message)s"))logger.addHandler(handler)This is recommended, especially at verbose levels such asINFOandDEBUG, as there are a lot of events logged and it would clog the
stdout of your program.For more information, check the documentation and tutorial of theloggingmodule.To-DoMetadata support :)QueuesUnit tests