Friday 17 February 2012

Scripting and Automating Maestro

Know some Python?

Want to build or customize functionality?

Included with the next release of Maestro, is the IronPython scripting engine, allowing you to script and automate the Maestro application.



A new IronPython Console tab appears the bottom. This is an interactive REPL console that lets you try and experiment with assorted pieces of python code. The whole .net framework libraries (and the Maestro API) are available for use from within the IronPython console.

Unfortunately, there are some .net concepts that do not translate cleanly or at all to Python. One major case is generics. A fair bit of the Maestro Application Services API (the internal API that's built on top of SharpDevelop Core) which drives most of the Maestro application and its addins uses generics. So trying to expose this API in its current form to IronPython would be clunky.

So to rectify this problem, a new Host Application class is being introduced which is accessible via the "app" global variable from the IronPython console. This class provides common functions for interacting with the application itself. For example, this code gets the names of the currently open connections:

connNames = app.GetConnectionNames()

Which we can then use to get the matching connection

conn = app.GetConnection(connNames[0])

"app" is the Host Application object I already mentioned. "conn" is the IServerConnection from the Maestro API. Given that this interface is the root interface of the Maestro API, you can now do any of the things you can do in the Maestro API as you would from a normal .net language.

So fetching a resource is now simply

resXml = app.GetResourceXml(conn, "Library://Samples/Sheboygan/Maps/Sheboygan.MapDefinition")

Or the long way

import clr
clr.AddReference("OSGeo.MapGuide.MaestroAPI")
from OSGeo.MapGuide.MaestroAPI import ResourceTypeRegistry
res = conn.ResourceService.GetResource("Library://Samples/Sheboygan/Maps/Sheboygan.MapDefinition")
resXml = ResourceTypeRegistry.SerializeAsString(res)

You can inspect these variables in two ways:

  1. Reflecting on the variable via the refl command (or reflw to display the result in a new window)
  2. Printing the actual variable value via the print command (or printw to display the result in a new window)
So reflecting the "resXml" variable (reflw resXml) looks like this:



While printing the "resXml" variable (printw resXml) looks like this:




So here's a taste of what you can do with the new scripting capabilities. I'm sure there's some scenarios where scripting would prove to be invaluable for automation and improving productivity.

Many thanks to Joe Socoloski's MIT-licensed IronTextBox for the backbone of this new feature.

2 comments:

MikeDub said...

Hi Jackie:

I would like to report a minor bug with Maestro.

It has to do with symbols, and after I created a simple symbol definition, and when I try to update a point feature to use that symbol, it won't even let me select the definition because the default and ONLY type of resources allowed is Symbol Library, the dropdown box to select different types of resources is disable.

I don't know if you guys are aware of this. Hopefully this is being resolved, or better yet, there is a solution already!

Thank you!

Jackie Ng said...

This is by design.

Point/Line/Polygon styles use basic stylization, so they cannot consume Symbol Definitions.

You can only consume Symbol Definitions through composite styles.