How to duplicate a master with Python?

What is the scripting equivalent of “Duplicate Selected” in the app Masters pane “+” menu?
When I access font.masters[0], there is no duplicate() function and copy() gets me a master with no layers.
Thanks!

Does this help?

Also check out the Method Reporter mekkablue script, you can search all available methods of the GSFontMaster class.

Thanks, but this seems to only get me partway there. The newly created master has a layer, but the new layer has no paths in it.

In the app’s UI, “Duplicate master” creates a new master with duplicated layers and duplicated paths within them. I can probably loop to copy existing paths into the new layer for each glyph, but wondering if I’m missing something here. Thanks again.

I seem to get copied shapes on my new layer by invoking the suggested copy expression from the scripting doc page:

def duplicateMaster(font, originalMaster):
	masterCopy = originalMaster.copy()
	font.masters.append(masterCopy)
	font.copyInfoFrom_sourceFontMasterID_targetFontMasterID_(font, master.id, masterCopy.id)
	
	for glyph in font.glyphs:
		layer = glyph.layers[master.id]
		layerCopy = glyph.layers[masterCopy.id]
		layerCopy.width = layer.width
		layerCopy.shapes = copy.copy(layer.shapes)
	
	return masterCopy

But I get strange behavior in the editing UI when I do this with respect to where the curve points are. I think something is still “linking” the paths between the layers despite them having been copied by the font.copyInfoFrom_sourceFontMasterID_targetFontMasterID_ function?

Note that I also have to set the new layer’s width to match the original layer width. But I still don’t know exactly what else I’m missing out on here.

It would be nice to have a documented/standard recipe that performs the same behavior that I get from using the app UI’s “duplicate” master feature. Thanks.

There is actually a better API:

font.addFontMasterAndContent_(originalMaster)
1 Like

this copies the shapes object (the list containing the shapes), but not the shapes. Use copy.deepcopy(layer.shapes).

2 Likes

Ah, thank you Georg! This works and avoids the weird UI glitching I was seeing (which I can now guess at the cause of). I recommend updating the Python doc page here to use deepcopy instead for these examples. I was using the suggestion shown:

# copy shapes from another layer
import copy
layer.shapes = copy.copy(anotherlayer.shapes)

Thanks.