Passing structs to python from the command

I recently needed to pass a struct from the command line through to a python function. I couldn’t see any documentation on this so I thought I would record what I did in case it helps anyone else.

By creating these three files a minimal working example can be made

struct.txt

input(value: {struct ($details) as foo})

structFunc.py

def function(details):
    for key in details:
        print(key + '=' + str(details[key]))

project.ini

[function struct]
description = 'Hello world' function example that takes a struct and prints the key/value pairs
location = structFunc.py
argument-types = [ details: anything ]
return-type = text

[model struct]
framework = pipeline
location = struct.txt

This can then be run with

riskscape model run struct -p "details = {greeting: 'Hello', name: 'Ronnie'}"

Which will print out

greeting=Hello
name=Ronnie

You can also use nested structs to create a ‘matrix’ of sorts

riskscape model run struct2 -p details="{a: {greeting: 'Kia ora', name: 'Ronnie', }, b: {greeting: 'Hi', name: 'Eve'}}"

This can be printed using

def function(details):
	print(details)
	for outerkey in details:
		print(outerkey)
		for key in details[outerkey]:
			print(key + '=' + str(details[outerkey][key]))

Which will print out

a
greeting=Kia ora
name=Ronnie
b
greeting=Hi
name=Eve

Just to add, you can also use the riskscape expression evaluate command to test out a function. It simplifies things a little, in that you no longer need the model, e.g.

riskscape expression evaluate "struct({greeting: 'Hello', name: 'Ronnie'})"

The return value from the function is displayed on the CLI (whereas riskscape model run will write the result to a file. Both approaches are simply evaluating an expression.