-
Notifications
You must be signed in to change notification settings - Fork 183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[udf] Unlock Lua for user-defined functions #669
base: amo/javascript
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--[[ | ||
Forward OwnTracks low-battery warnings to ntfy. | ||
https://mqttwarn.readthedocs.io/en/latest/examples/owntracks-battery/readme.html | ||
--]] | ||
|
||
-- mqttwarn filter function, returning true if the message should be ignored. | ||
-- In this case, ignore all battery level telemetry values above a certain threshold. | ||
function owntracks_batteryfilter(topic, message) | ||
local ignore = true | ||
|
||
-- Decode inbound message. | ||
local data = json.decode(message) | ||
|
||
-- Evaluate filtering rule. | ||
if data ~= nil and data.batt ~= nil then | ||
ignore = tonumber(data.batt) > 20 | ||
end | ||
|
||
return ignore | ||
end | ||
|
||
-- Status message. | ||
print("Loaded Lua module.") | ||
|
||
-- Export symbols. | ||
return { | ||
owntracks_batteryfilter = owntracks_batteryfilter, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
import os | ||
import re | ||
import string | ||
import sys | ||
import threading | ||
import types | ||
import typing as t | ||
|
@@ -150,6 +151,8 @@ | |
loader = importlib.machinery.SourcelessFileLoader(fullname=name, path=str(path)) | ||
elif path.suffix in [".js", ".javascript"]: | ||
return load_source_js(name, str(path)) | ||
elif path.suffix == ".lua": | ||
return load_source_lua(name, str(path)) | ||
else: | ||
raise ImportError(f"Loading file type failed (only .py, .pyc, .js, .javascript): {path}") | ||
spec = importlib.util.spec_from_loader(loader.name, loader) | ||
|
@@ -317,3 +320,41 @@ | |
javascript.eval_js(js_code) | ||
threading.Event().wait(0.01) | ||
return module_factory(mod_name, module["exports"]) | ||
|
||
|
||
class LuaJsonAdapter: | ||
""" | ||
Support Lua as if it had its `json` module. | ||
|
||
Wasn't able to make Lua's `json` module work, so this provides minimal functionality | ||
instead. It will be injected into the Lua context's global `json` symbol. | ||
""" | ||
|
||
@staticmethod | ||
def decode(data): | ||
if data is None: | ||
return None | ||
return json.loads(data) | ||
Comment on lines
+325
to
+337
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not quite the same, but I've discovered another monkey-patching around the JSON library at -- https://github.com/extremeheat/JSPyBridge/blob/1.0.1/src/pythonia/json_patch.py |
||
|
||
|
||
def load_source_lua(mod_name, filepath): | ||
""" | ||
Load a Lua module, and import its exported symbols into a synthetic Python module. | ||
""" | ||
import lupa | ||
|
||
lua = lupa.LuaRuntime(unpack_returned_tuples=True) | ||
|
||
# Lua modules want to be loaded without suffix, but the interpreter would like to know about their path. | ||
modfile = Path(filepath).with_suffix("").name | ||
modpath = Path(filepath).parent | ||
# Yeah, Windows. | ||
if sys.platform == "win32": | ||
modpath = str(modpath).replace("\\", "\\\\") | ||
lua.execute(rf'package.path = package.path .. ";{str(modpath)}/?.lua"') | ||
|
||
logger.info(f"Loading Lua module {modfile} from path {modpath}") | ||
module, filepath = lua.require(modfile) | ||
# FIXME: Add support for common modules, as long as they are not available natively. | ||
lua.globals()["json"] = LuaJsonAdapter | ||
return module_factory(mod_name, module) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,9 @@ | |
"javascript": [ | ||
"javascript==1!1.0.1; python_version>='3.7'", | ||
], | ||
"lua": [ | ||
"lupa<3", | ||
], | ||
"mysql": [ | ||
"mysql", | ||
], | ||
|
@@ -205,6 +208,9 @@ | |
"Operating System :: MacOS", | ||
"Operating System :: Microsoft :: Windows", | ||
"Programming Language :: JavaScript", | ||
"Programming Language :: Lua", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is connected to a corresponding request to add it as a new Trove classifier. |
||
"Programming Language :: Other", | ||
"Programming Language :: Other Scripting Engines", | ||
"Programming Language :: Python", | ||
"Programming Language :: Python :: 3.6", | ||
"Programming Language :: Python :: 3.7", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copy/paste error. Apologies.