I successfully ran an Elm worker from Python

For the past hour or so I have been working on a Python module that can run a compiled Elm 0.19 module that runs on Platform.worker. It’s actually very easy to do and it uses less than 40 lines of Python code. I’m using this dukpy library to run the javascript (it’s not available on PyPI and there is a completely different package with the same name on PyPI).

This is the Python code:

import dukpy
import time


GLOBALS = '''
var console = {
	warn: function(str) {},
	log: function(str) {},
};
'''

def set_timeout(f, milliseconds):
	time.sleep(milliseconds)
	f()


class Elm:

	def __init__(self, jscode, main_module, flags=''):
		self.ctx = dukpy.Context()
		self.ctx.eval(GLOBALS)
		self.ctx.g.setTimeout = set_timeout

		self.ctx.eval(jscode)
		self.ctx.eval(f'var elm = Elm.{main_module}.init({flags});')


	def subscribe(self, port_name):
		def decor(f):
			self.ctx.g.tempfunc = f
			self.ctx.eval(f'elm.ports.{port_name}.subscribe(tempfunc);')
			return f

		return decor


	def send(self, port_name, arg='null'):
		self.ctx.eval(f'elm.ports.{port_name}.send({arg});')

As an example, I wrote a counter app that runs on Platform.worker. It defines these ports:

port getNum : ( () -> msg ) -> Sub msg -- Immediately triggers gotNum
port increment : ( () -> msg ) -> Sub msg
port decrement : ( () -> msg ) -> Sub msg

port gotNum : Int -> Cmd msg -- Sends the current counter state to JavaScript

And this is how I run this from Python (after running elm make --output=counter.js):

with open('counter.js', 'r') as f:
	elm = Elm(f.read(), 'Main')


@elm.subscribe('gotNum')
def when_num_received(num):
	print(f'Got current number: {num}')


elm.send('getNum')
elm.send('increment')
elm.send('getNum')
elm.send('increment')
elm.send('increment')
elm.send('getNum')
elm.send('decrement')
elm.send('getNum')

Output:

Got current number: 0
Got current number: 1
Got current number: 3
Got current number: 2
7 Likes

Nice solution to fix the dependencies on console! It looks like this is simpler than trying to remove the dependencies in the javascript.

1 Like

Python’s mojo: “If it quacks like it’s a duck”. It makes sense that a pythonish solution comes from a python developer :wink:

Maybe I could use this to create a framework for making command line applications with Elm

Probably the easiest way of doing this is with NodeJS - a little bit of JS wrapper code around an Elm program. You can also publish them to npm this way, which gives you a way of publishing command line tools that web developers are already familiar with.

or maybe this could be used to use elm as a way to extend your aoplication

Yes, if you had an existing Python application and wanted to render some HTML from it, server side, it could be a useful way of doing that and getting the data more directly from the Python part into the Elm part. An alternative way might be to add a REST API to the Python bit and then build a UI in Elm on top of that.

I have an equivalent project for Elm in Java (not updated for 0.19 though). Was doing server side Elm rendering with it:

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.