JSPyBridge
JSPyBridge copied to clipboard
Bridge either returns old state or times out
I'm managing Automerge documents through JSPyBridge.
from javascript import require
automerge = require('@automerge/automerge')
doc = automerge.init() # I also give it a key, "log", holding a list, using the separate automerge.load()
Updating a document requires sending the document and a change function into the .change()
call, which returns the changed document. This is my best attempt using the bridge:
def append_message(doc):
doc['log'].append("message")
return doc
new_doc = automerge.change(doc, append_message)
but the new_doc
always appears identical to doc
for some reason.
I tried a different approach using eval_js()
:
from javascript import eval_js
d = doc
new_doc = eval_js('''
return automerge.change(d, doc => {
doc['log'].push("message")
})
''')
which does update the new state into new_doc
, but this doesn't seem to be the intended way to use this library. Additionally, I start facing lots of bridge proxy timeout errors this way:
message = "foo"
new_doc = eval_js('''
let msg = await message.valueOf();
return automerge.change(d, doc => {
doc['log'].push(msg)
})
''')
this error throws when await
ing the valueOf()
when shuffling string data into eval_js()
with any reasonable frequency::
Exception in thread Thread-6 (process_queue):
Traceback (most recent call last):
File "/usr/local/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
self.run()
File "/usr/local/lib/python3.11/threading.py", line 975, in run
self._target(*self._args, **self._kwargs)
File "/home/jon/projects/project/file.py", line 80, in process_queue
new_doc = eval_js('''
^^^^^^^^^^^
File "/home/jon/.local/lib/python3.11/site-packages/javascript/__init__.py", line 53, in eval_js
rv = config.global_jsi.evaluateWithContext(js, local_vars, forceRefs=True)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jon/.local/lib/python3.11/site-packages/javascript/proxy.py", line 213, in __call__
else self._exe.callProp(
^^^^^^^^^^^^^^^^^^^
File "/home/jon/.local/lib/python3.11/site-packages/javascript/proxy.py", line 153, in callProp
resp = self.pcall(ffid, "call", method, args, timeout=timeout, forceRefs=forceRefs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jon/.local/lib/python3.11/site-packages/javascript/proxy.py", line 132, in pcall
raise Exception(
Exception: Call to 'evaluateWithContext' timed out. Increase the timeout by setting the `timeout` keyword argument.
I've ultimately found something that works well enough (so far):
message = query['message']
d = self.doc
js_code = f'''
let msg = {json.dumps(message)}; ''' + '''
const new_doc = automerge.change(d, doc => {
doc['log'].push(msg)
});
return new_doc;
'''
self.doc = eval_js(js_code)
This directly includes the data of the message as part of the code to run, instead of relying on async transfers.
The ''' + '''
avoids confusion around JS's curly braces while allowing direct variable assignment before the break with f''' ... '''
I somehow needed d = self.doc
since passing self.doc
directly to eval_js()
failed (can't handle periods? I'm missing some braces?).