Python asynchronous I/O package for LDMud
Project description
Python asynchronous I/O package for LDMud
This is a python module that enables the use of the Python asyncio module with LDMud 3.6.2 and later. The module doesn't export any names, it just extends the Python asyncio module to work with LDMud.
Usage
Install from the python package index
The efun package can be downloaded from the python package index:
pip3 install --user ldmud-asyncio
Build & install the package yourself
You can build the package yourself.
First clone the repository
git clone https://github.com/ldmud/python-asyncio.git
Install the package
cd python-asyncio
python3 setup.py install --user
Automatically load the module at startup
In your Python startup script for LDMud add the following line:
import ldmud_asyncio
Examples
call_out() replacement
import ldmud, ldmud_asyncio, asyncio
async def do_call_out(cb, sec):
await asyncio.sleep(sec)
cb()
def efun_call_out(cb: ldmud.Closure, sec: int) -> None:
asyncio.run(do_call_out(cb, sec))
ldmud.register_efun("py_call_out", efun_call_out)
Call a program and return the lines
import ldmud, ldmud_asyncio, asyncio
async def do_exec(prog, cb):
proc = await asyncio.create_subprocess_exec(prog, stdout=asyncio.subprocess.PIPE)
async for line in proc.stdout:
cb(line.decode())
await proc.wait()
cb(0)
def efun_exec(prog: str, cb: ldmud.Closure) -> None:
asyncio.run(do_exec(prog, cb))
ldmud.register_efun("py_exec", efun_exec)
Start a websockets server
This is the synchronization example from the websockets package. Here we only added an efun to influence the value as well.
This is the Python code:
import ldmud, ldmud_asyncio, asyncio, websockets, json
STATE = {"value": 0}
USERS = set()
def state_event():
return json.dumps({"type": "state", **STATE})
def users_event():
return json.dumps({"type": "users", "count": len(USERS)})
async def notify_state():
if USERS: # asyncio.wait doesn't accept an empty list
message = state_event()
await asyncio.wait([user.send(message) for user in USERS])
async def notify_users():
if USERS: # asyncio.wait doesn't accept an empty list
message = users_event()
await asyncio.wait([user.send(message) for user in USERS])
async def register(websocket):
USERS.add(websocket)
await notify_users()
async def unregister(websocket):
USERS.remove(websocket)
await notify_users()
async def counter(websocket, path):
# register(websocket) sends user_event() to websocket
await register(websocket)
try:
await websocket.send(state_event())
async for message in websocket:
data = json.loads(message)
if data["action"] == "minus":
STATE["value"] -= 1
await notify_state()
elif data["action"] == "plus":
STATE["value"] += 1
await notify_state()
finally:
await unregister(websocket)
asyncio.run(websockets.serve(counter, "localhost", 6789))
async def do_ws_set_value(val):
STATE["value"] = val
await notify_state()
def efun_ws_set_value(val: int) -> None:
asyncio.run(do_ws_set_value(val))
ldmud.register_efun("py_ws_set_value", efun_ws_set_value)
And here the HTML code to run in the browser:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket demo</title>
<style type="text/css">
body {
font-family: "Courier New", sans-serif;
text-align: center;
}
.buttons {
font-size: 4em;
display: flex;
justify-content: center;
}
.button, .value {
line-height: 1;
padding: 2rem;
margin: 2rem;
border: medium solid;
min-height: 1em;
min-width: 1em;
}
.button {
cursor: pointer;
user-select: none;
}
.minus {
color: red;
}
.plus {
color: green;
}
.value {
min-width: 2em;
}
.state {
font-size: 2em;
}
</style>
</head>
<body>
<div class="buttons">
<div class="minus button">-</div>
<div class="value">?</div>
<div class="plus button">+</div>
</div>
<div class="state">
<span class="users">?</span> online
</div>
<script>
var minus = document.querySelector('.minus'),
plus = document.querySelector('.plus'),
value = document.querySelector('.value'),
users = document.querySelector('.users'),
websocket = new WebSocket("ws://127.0.0.1:6789/");
minus.onclick = function (event) {
websocket.send(JSON.stringify({action: 'minus'}));
}
plus.onclick = function (event) {
websocket.send(JSON.stringify({action: 'plus'}));
}
websocket.onmessage = function (event) {
data = JSON.parse(event.data);
switch (data.type) {
case 'state':
value.textContent = data.value;
break;
case 'users':
users.textContent = (
data.count.toString() + " user" +
(data.count == 1 ? "" : "s"));
break;
default:
console.error(
"unsupported event", data);
}
};
</script>
</body>
</html>
Have fun!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file ldmud-asyncio-0.0.4.tar.gz
.
File metadata
- Download URL: ldmud-asyncio-0.0.4.tar.gz
- Upload date:
- Size: 6.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | db64f9be44217a6c49448a57ca845db26cf6e90267476e01751bac39599d25bc |
|
MD5 | b80f682b701273fb1c51c6e3fce5ee80 |
|
BLAKE2b-256 | e856fc7fbfcb270407383c040a15cb3fbde3f4e2417ca8458b45d88bdabe74be |
File details
Details for the file ldmud_asyncio-0.0.4-py3-none-any.whl
.
File metadata
- Download URL: ldmud_asyncio-0.0.4-py3-none-any.whl
- Upload date:
- Size: 6.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.4.2 requests/2.25.1 setuptools/52.0.0 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.9.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d08bfc9298639a7ffd4dcc7ab448662c0c6d35965d638e6e2cce8d7955c9ad63 |
|
MD5 | e5f6d828655d6eb212d9af0234da60a3 |
|
BLAKE2b-256 | 4e4183a4160f76f66dbd5825735eb0cd4fefa13c521336555772e4975df5caba |